Commit b523fbfe authored by Jérome Perrin's avatar Jérome Perrin

json_form: proto with react jsonschema form

note: to use with ERP5JS, change CSP on the web site to something including
lab.nexedi.com:

    default-src 'self'; img-src 'self' data: blob:; media-src 'self' blob:; connect-src 'self' lab.nexedi.com data:; script-src 'self'; font-src 'self'; style-src 'self' data:; frame-src 'self' data:
parent bb34768a
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Folder" module="OFS.Folder"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_objects</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>erp5_react_jsonschema_form</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
This source diff could not be displayed because it is too large. You can view the blob instead.
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>__name__</string> </key>
<value> <string>react-dom.production.min.js</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>text/javascript</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>react-dom.production.min.js</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
.rjsf button.array-item-move-down::before {
font-family: "FontAwesome";
content: "\f0d7"
}
.rjsf button.array-item-move-up::before {
font-family: "FontAwesome";
content: "\f0d8"
}
.rjsf button.array-item-remove::before {
font-family: "FontAwesome";
content: "\f1f8"
}
.rjsf button.btn-add::before {
font-family: "FontAwesome";
content: "\f067"
}
.rjsf legend {
color: hsl(0, 0%, 42%)
}
.rjsf label {
color: hsl(0, 0%, 42%)
}
.rjsf fieldset {
display: block;
margin-inline-start: 2px;
margin-inline-end: 2px;
padding-block-start: 0.35em;
padding-inline-start: 0.75em;
padding-inline-end: 0.75em;
padding-block-end: 0.625em;
min-inline-size: min-content;
border-width: 2px;
border-style: groove;
border-color: threedface;
border-image: initial;
}
/** XXX hide submit button ... */
.rjsf button[type="submit"] {
display: none;
}
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>__name__</string> </key>
<value> <string>react-jsonschema-form-gadget.css</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>text/css</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>JSON schema form editor</title>
<script src="./react.production.min.js" type="text/javascript"></script>
<script src="./react-dom.production.min.js" type="text/javascript"></script>
<script src="./react-jsonschema-form.js" type="text/javascript"></script>
<script src="./ref-parser.min.js" type="text/javascript"></script>
<script src="rsvp.js" type="text/javascript"></script>
<script src="renderjs.js" type="text/javascript"></script>
<script src="./react-jsonschema-form-gadget.js" type="text/javascript"></script>
<link rel="stylesheet" href="react-jsonschema-form-gadget.css">
</head>
<body>
<div id="app"></div>
</body>
</html>
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>__name__</string> </key>
<value> <string>react-jsonschema-form-gadget.html</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>text/html</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
/*jslint nomen: true, indent: 2 */
/*global window, rJS, RSVP, document*/
(function (window, rJS, RSVP, document) {
'use strict';
const e = React.createElement;;
const ERP5Theme = {}
/*
ArrayFieldTemplatex: (props) => {
return React.createElement(
'div',
{
className: props.className,
},
props.items &&
props.items.map((element) =>
React.createElement(
'div',
{
key: element.key,
className: element.className,
},
React.createElement('div', null, element.children),
React.createElement(
'button',
{
onClick: element.onDropIndexClick(element.index),
},
'Delete'
),
React.createElement('hr', null)
)
),
props.canAdd &&
React.createElement(
'div',
{
className: 'row',
},
React.createElement(
'p',
{
className: 'col-xs-3 col-xs-offset-9 array-item-add text-right',
},
React.createElement(
'button',
{
onClick: props.onAddClick,
type: 'button',
},
'Add'
)
)
)
);
},
};
*/
/**
* Prepare a ui-schema from the conventions of SlapOS instance parameters schema.
* This does the following:
* - remove `default` from schema. In SlapOS schemas we use `default` as a documentation
* and we don't expect to pre-fill the form data with default.
* TODO: we don't always want to remove default (maybe we never want ?)
* - TODO something with textarea
*
* TODO: if this is really needed - if we use a theme this is probably not, don't mutate
* arguments like this but return new copies instead.
*/
function makeUiSchema(schema, uiSchema) {
if (schema.properties) {
for (const [key, value] of Object.entries(schema.properties)) {
uiSchema[key] = {};
if (value.default) {
/** XXX value.const ... isn't it a bug in ERP5 SR schema ? */
if (value?.type === 'string' && value.const === undefined) {
uiSchema[key]['ui:placeholder'] = value.default;
} else {
// XXX seems ugly
// uiSchema[key]['ui:help'] = `Default value: ${value.default}`
}
if (value.const === undefined) {
value.default = undefined;
}
}
if (value?.type === 'object') {
makeUiSchema(value, uiSchema[key]);
}
for (const oneOf of value.oneOf || []) {
makeUiSchema(oneOf, uiSchema[key]);
}
for (const allOf of value.allOf || []) {
makeUiSchema(allOf, uiSchema[key]);
}
for (const anyOf of value.anyOf || []) {
makeUiSchema(anyOf, uiSchema[key]);
}
}
}
}
rJS(window)
.declareMethod('render', function (options) {
return this.changeState({
data: {},
value: options.value,
key: options.key,
schema_url: options.schema,
});
})
.onStateChange(function (modification_dict) {
var gadget = this;
if (modification_dict.schema_url) {
return $RefParser
.dereference(modification_dict.schema_url)
.then(function (schema) {
let uiSchema = {};
makeUiSchema(schema, uiSchema);
console.log('after simplification', schema, uiSchema);
const log = (type) => console.log.bind(console, type);
ReactDOM.render(
React.createElement(JSONSchemaForm.withTheme(ERP5Theme), {
schema: schema,
uiSchema: uiSchema,
// XXX don't make a <form> by default
tagName: 'div',
// TODO: handle malformed json
formData: JSON.parse(modification_dict.value),
// TODO: keep promise chain
onChange: (state) =>
gadget.changeState({
data: state.formData,
errors: state.errors,
}),
// onSubmit: log('submitted'),
onError: log('errors'),
}),
gadget.element
);
});
}
console.log(this.element, modification_dict);
if (!this.initialized) {
}
if (modification_dict.schema) {
console.log(modification_dict);
}
})
.declareMethod(
'getContent',
function () {
var result = {};
result[this.state.key] = JSON.stringify(this.state.data, null, ' ');
return result;
},
{ mutex: 'changestate' }
)
.declareMethod('checkValidity', function () {
return true;
});
})(window, rJS, RSVP, document);
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>__name__</string> </key>
<value> <string>react-jsonschema-form-gadget.js</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>application/javascript</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
This source diff could not be displayed because it is too large. You can view the blob instead.
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>__name__</string> </key>
<value> <string>react-jsonschema-form.js</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>text/javascript</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>react-jsonschema-form.js</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>__name__</string> </key>
<value> <string>react.production.min.js</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>text/javascript</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>react.production.min.js</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
This source diff could not be displayed because it is too large. You can view the blob instead.
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>__name__</string> </key>
<value> <string>ref-parser.min.js</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>text/javascript</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>ref-parser.min.js</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
erp5_react_jsonschema_form
\ No newline at end of file
erp5_json_form
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment