Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

attempt to add reactjsonschemaform #93

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from .react_jsonschema_form_widget import ReactJsonSchemaFormWidget

__all__ = ["ReactJsonSchemaFormWidget"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
"""Implements a widget based on react jsonschema form."""
import json
from typing import Any, Dict, List, Tuple, Union
from uuid import uuid4

import colander
from deform.field import Field
from deform.widget import DateTimeInputWidget, ResourceRegistry
from deform.widget import Select2Widget
from deform.widget import SelectWidget
from deform.widget import Widget
from pkg_resources import resource_filename


from pathlib import Path

here = Path(__file__).parent
fname = here / 'test.txt'


class JsonWidget(Widget):
"""Json editor with schema validation.

Based on https://github.com/josdejong/jsoneditor/
"""

template: str = "templates/json"
readonly_template: str = "templates/json_readonly"
style: str = "font-family: monospace;"
requirements: Tuple[Tuple[str, None], ...] = (("jsoneditor", None),)
jsonschema = "{}"

def __init__(self, jsonschema={}, **kw):
"""Initialize instance."""
self.jsonschema = json.dumps(jsonschema)
self.title = (jsonschema.get("title", None),)
self.description = jsonschema.get("description", None)

def serialize(self, field: Field, cstruct, **kw: Any) -> str:
"""Serialize."""
try:
cstruct = json.dumps(cstruct, indent=4)
except TypeError:
jsonschema = json.loads(
kw.get("jsonschema", field.widget.jsonschema)
)
if jsonschema.get("type") == "array":
cstruct = "[]"
elif jsonschema.get("type") == "object":
cstruct = "{}"
else:
cstruct = "undefined"
readonly = kw.get("readonly", self.readonly)
template = readonly and self.readonly_template or self.template
values = self.get_template_values(field, cstruct, kw)
return field.renderer(template, uuid=uuid4(), **values)

def deserialize(
self, field: Field, pstruct: str
) -> Union[Dict[str, Any], List[Dict[str, Any]], colander._null]:
"""Deserialize."""
try:
return json.loads(pstruct)
except (TypeError, json.JSONDecodeError):
return colander.null


class ReactJsonSchemaFormWidget(JsonWidget):
"""Use react-jsonschema-form widget."""

template = "templates/react_jsonschema_form"
requirements = (
("rjsf-react", None),
("rjsf-react-dom", None),
("rjsf", None),
)

@classmethod
def register_resources(cls, resource_registry):
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ugliness to extend a particular resource registry with entries for this widget

resource_registry.set_js_resources(
"rjsf-react",
None,
"deformdemo:custom_widgets/react_jsonschema_form_widget/static/react.js",
)
resource_registry.set_js_resources(
"rjsf-react-dom",
None,
"deformdemo:custom_widgets/react_jsonschema_form_widget/static/react-dom.js",
)
resource_registry.set_js_resources(
"rjsf",
None,
"deformdemo:custom_widgets/react_jsonschema_form_widget/static/react-jsonschema-form.js",
)
return resource_registry
# resource_filename("deformdemo", "templates")

def serialize(self, field: Field, cstruct, **kw: Any) -> str:
"""Serialize with conversion for rjsf."""
self.get_template_values(field, cstruct, kw)
kw["jsonschema"] = json.dumps(
json.loads(kw.get("jsonschema", field.widget.jsonschema)),
indent=2,
)
return super().serialize(field, cstruct, **kw)
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
This artefact was created by:

git clone https://github.com/tdamsma/react-jsonschema-form.git@select-by-index
cd react-jsonschema-form/packages/core
npm install
npm run build

Then copy the react jsonschema form files from react-jsonschema-form/packages/core/dist

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<tal:def tal:define="oid oid|field.oid;
uuid uuid|field.uuid;
name name|field.name;
errormsg errormsg|field.errormsg;
jsonschema jsonschema|field.widget.jsonschema;" i18n:domain="deform">



<input id="${oid}-${uuid}" name="${name}" value="${cstruct}" hidden></input>
<div id="${oid}-${uuid}-editor"></div>
<div tal:condition="errormsg" class="clearfix alert alert-danger">
<p>${errormsg}</p>
</div>
<script>
(function(){
const container = document.getElementById("${oid}-${uuid}-editor");
const field = document.getElementById("${oid}-${uuid}");
const formData = ${cstruct}
const properties = {
schema: ${jsonschema},
onChange: (change) => {
document.getElementById("${oid}-${uuid}").setAttribute("value",JSON.stringify(change.formData))
},
children: [],
omitExtraData: true,
liveValidate: true,
liveOmit: true,
formData: formData
}

ReactDOM.render(
React.createElement(JSONSchemaForm.default, properties),
document.getElementById("${oid}-${uuid}-editor")
);
})()
</script>

<style>
form.rjsf div.panel.panel-danger.errors {
display: none
}
</style>
</tal:def>
Loading