Commit 410ba47a authored by Boris Kocherov's avatar Boris Kocherov Committed by Romain Courteaud

[erp5_json_form] update from https://lab.nexedi.com/bk/rjs_json_form

parent 28c4c875
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
<title>ERP5</title> <title>ERP5</title>
<link rel="stylesheet" href="gadget_erp5_nojqm.css"> <link rel="stylesheet" href="gadget_erp5_nojqm.css">
<script src="rsvp.js" type="text/javascript"></script> <script src="rsvp.js" type="text/javascript"></script>
<script src="jsonform/tv4.js" type="text/javascript"></script>
<script src="renderjs.js" type="text/javascript"></script> <script src="renderjs.js" type="text/javascript"></script>
<script src="jio.js" type="text/javascript"></script> <script src="jio.js" type="text/javascript"></script>
<script src="jsonform.gadget.js" type="text/javascript"></script> <script src="jsonform.gadget.js" type="text/javascript"></script>
......
/*jslint nomen: true, maxlen: 200, indent: 2, maxerr: 100*/ /*jslint nomen: true, maxlen: 200, indent: 2, maxerr: 100*/
/*global window, document, URL, rJS, RSVP, jIO, tv4, Blob */ /*global window, document, URL, rJS, RSVP, jIO, tv4, Blob */
(function (window, document, Blob, rJS, RSVP, jIO, tv4) { (function (window, document, Blob, rJS, RSVP, jIO) {
"use strict"; "use strict";
var expandSchema; var expandSchema;
...@@ -575,18 +575,32 @@ ...@@ -575,18 +575,32 @@
// XXX `if then else` construction can be simplify to // XXX `if then else` construction can be simplify to
// anyOf(allOf(if_schema, then_schema), else_schema) // anyOf(allOf(if_schema, then_schema), else_schema)
// and realized by existed rails // and realized by existed rails
var schema_p;
if (schema === undefined || if (schema === undefined ||
Object.keys(schema).length === 0) { Object.keys(schema).length === 0) {
schema = true; schema = true;
} }
if (schema_path === "/") {
schema_p = "";
} else {
schema_p = schema_path;
}
if (schema.anyOf !== undefined) { if (schema.anyOf !== undefined) {
return anyOf(g, schema.anyOf, schema_path + '/anyOf', path, schema); return anyOf(g, schema.anyOf, schema_p + '/anyOf', path, schema);
} }
if (schema.oneOf !== undefined) { if (schema.oneOf !== undefined) {
return anyOf(g, schema.oneOf, schema_path + '/oneOf', path, schema); return anyOf(g, schema.oneOf, schema_p + '/oneOf', path, schema)
.push(function (ret) {
ret.schema_path = schema_path;
return ret;
});
} }
if (schema.allOf !== undefined) { if (schema.allOf !== undefined) {
return allOf(g, schema.allOf, schema_path + '/allOf', path, schema); return allOf(g, schema.allOf, schema_p + '/allOf', path, schema)
.push(function (ret) {
ret.schema_path = schema_path;
return ret;
});
} }
if (schema.$ref) { if (schema.$ref) {
return loadJSONSchema(g, schema.$ref, schema_path, path); return loadJSONSchema(g, schema.$ref, schema_path, path);
...@@ -655,6 +669,9 @@ ...@@ -655,6 +669,9 @@
var ii, var ii,
kk, kk,
key_list = key.split("/"); key_list = key.split("/");
if (key === "/") {
return d;
}
for (ii = 1; ii < key_list.length; ii += 1) { for (ii = 1; ii < key_list.length; ii += 1) {
kk = decodeJsonPointer(key_list[ii]); kk = decodeJsonPointer(key_list[ii]);
if (ii === key_list.length - 1) { if (ii === key_list.length - 1) {
...@@ -671,41 +688,43 @@ ...@@ -671,41 +688,43 @@
rJS(window) rJS(window)
.ready(function () { .ready(function () {
var g = this; var g = this;
g.props = {}; g.props = {
errors: {}
};
g.options = {}; g.options = {};
}) })
.declareAcquiredMethod("resolveExternalReference", "resolveExternalReference") .declareAcquiredMethod("resolveExternalReference", "resolveExternalReference")
.declareAcquiredMethod("notifyChange", "notifyChange") .declareAcquiredMethod("notifyChange", "notifyChange")
.allowPublicAcquisition("rootNotifyChange", function (arr, scope) { .allowPublicAcquisition("rootNotifyChange", function (arr, scope) {
this.props.changed = true;
return this.notifyChange(arr[0], scope); return this.notifyChange(arr[0], scope);
}) })
.declareAcquiredMethod("notifyValid", "notifyValid") .declareAcquiredMethod("notifyValid", "notifyValid")
.declareAcquiredMethod("notifyInvalid", "notifyInvalid") .declareAcquiredMethod("notifyInvalid", "notifyInvalid")
.allowPublicAcquisition("checkValidity", function (arr) { .allowPublicAcquisition("notifyInvalid", function (arr) {
return this.checkValidity(arr[0]); if (arr[0].length === 0) {
delete this.props.errors[arr[1]];
} else {
this.props.errors[arr[1]] = arr[0];
}
}) })
.declareMethod('getGadgetByPath', function (path) { .declareMethod('getGadgetByPath', function (path) {
return this.props.form_gadget.getGadgetByPath(path || "/"); return this.props.form_gadget.getGadgetByPath(path || "/");
}) })
.declareMethod('checkValidity', function (json_document) { .allowPublicAcquisition("getSchema", function (arr) {
// XXX need use local schema and local json document var schema_path = arr[0];
// in every subgadget to take into account user anyOf choice return convertOnMultiLevel(this.props.schema[""], schema_path);
// and so more precisely point to issue })
.declareJob('jobPrintErrors', function () {
return this.printErrors();
})
.allowPublicAcquisition("printErrors", function () {
return this.jobPrintErrors();
})
.declareMethod("printErrors", function () {
var g = this.props.form_gadget, var g = this.props.form_gadget,
gadget = this; gadget = this;
return RSVP.Queue() return RSVP.Queue()
.push(function () { .push(function () {
if (json_document === undefined) {
return g.getContent();
}
return json_document;
})
.push(function (json_d) {
gadget.state.value = JSON.stringify(json_d);
return tv4.validateMultiple(json_d, gadget.props.schema[""]);
})
.push(function (validation) {
var i, var i,
error_id, error_id,
error, error,
...@@ -728,15 +747,18 @@ ...@@ -728,15 +747,18 @@
div.setAttribute("class", ""); div.setAttribute("class", "");
}); });
for (i in gadget.props.errors) {
if (gadget.props.errors.hasOwnProperty(i)) {
errors = errors.concat(gadget.props.errors[i]);
}
}
for (i in schema_resolve_errors) { for (i in schema_resolve_errors) {
if (schema_resolve_errors.hasOwnProperty(i)) { if (schema_resolve_errors.hasOwnProperty(i)) {
errors.push(schema_resolve_errors[i]); errors.push(schema_resolve_errors[i]);
} }
} }
errors = errors.concat(validation.errors);
errors = errors.concat(validation.missing);
if (errors.length === 0) { if (errors.length === 0) {
return gadget.notifyValid() return gadget.notifyValid()
.push(function () { .push(function () {
...@@ -752,14 +774,14 @@ ...@@ -752,14 +774,14 @@
function print_error(error, errorUid, errorId) { function print_error(error, errorUid, errorId) {
return function (element) { return function (element) {
var id = element.id, var error_message,
error_message,
createTextNode = document.createTextNode.bind(document), createTextNode = document.createTextNode.bind(document),
a = document.createElement("a"); a = document.createElement("a");
element = element || error.element;
a.setAttribute("href", "#" + errorUid); a.setAttribute("href", "#" + errorUid);
a.text = errorId; a.text = errorId;
element.setAttribute("class", "error-input"); element.setAttribute("class", "error-input");
error_message = document.getElementById(id).querySelector(".error"); error_message = element.querySelector(".error");
error_message.appendChild(a); error_message.appendChild(a);
error_message.setAttribute("id", errorUid); error_message.setAttribute("id", errorUid);
if (error.message instanceof Array) { if (error.message instanceof Array) {
...@@ -785,10 +807,17 @@ ...@@ -785,10 +807,17 @@
for (i = 0; i < errors.length; i += 1) { for (i = 0; i < errors.length; i += 1) {
error = errors[i]; error = errors[i];
error_id = (i + 1).toString(); error_id = (i + 1).toString();
tasks.push( if (error.element) {
g.getElementByPath(error.dataPath || "/") tasks.push(
.push(print_error(error, "error" + error_id, error_id)) new RSVP.Queue()
); .push(print_error(error, "error" + error_id, error_id))
);
} else {
tasks.push(
g.getElementByPath(error.dataPath || "/")
.push(print_error(error, "error" + error_id, error_id))
);
}
} }
return RSVP.Queue() return RSVP.Queue()
...@@ -824,7 +853,7 @@ ...@@ -824,7 +853,7 @@
z.schema = JSON.stringify(options.schema); z.schema = JSON.stringify(options.schema);
} }
} }
if (options.hasOwnProperty("schema_url")) { if (options.schema_url) {
z.schema_url = (new URL(options.schema_url, window.location)) z.schema_url = (new URL(options.schema_url, window.location))
.toString(); .toString();
} }
...@@ -897,7 +926,7 @@ ...@@ -897,7 +926,7 @@
g.props.schema_map["/"] = schema_url; g.props.schema_map["/"] = schema_url;
g.props.schemas[schema_url] = URL g.props.schemas[schema_url] = URL
.createObjectURL(new Blob([g.state.schema], {type : 'application/json'})); .createObjectURL(new Blob([g.state.schema], {type : 'application/json'}));
queue = expandSchemaForField(g, schema, "/", "/". true); queue = expandSchemaForField(g, schema, "/", "/", true);
} else { } else {
schema_url = g.state.schema_url || schema_url = g.state.schema_url ||
(json_document && json_document.$schema); (json_document && json_document.$schema);
...@@ -924,7 +953,7 @@ ...@@ -924,7 +953,7 @@
}); });
}) })
.push(function () { .push(function () {
return g.checkValidity(); return g.printErrors();
}) })
.push(function () { .push(function () {
if (g.props.form_gadget.props.changed) { if (g.props.form_gadget.props.changed) {
...@@ -935,21 +964,33 @@ ...@@ -935,21 +964,33 @@
return g; return g;
}) })
.push(undefined, function (err) { .push(undefined, function (err) {
console.log(err); console.error(err);
}); });
}) })
.declareMethod('rerender', function (path, schema) {
var g = this,
gadget;
if (path) {
return g.props.form_gadget.getGadgetByPath(path)
.push(function (ret) {
gadget = ret.gadget;
return gadget.getContent();
})
.push(function (value) {
return gadget.rerender({
schema: schema,
value: value
})
.push(function () {
return gadget.reValidate(value, schema);
});
});
}
})
.allowPublicAcquisition("expandSchema", function (arr) { .allowPublicAcquisition("expandSchema", function (arr) {
return expandSchemaForField(this, arr[0], arr[1], arr[2], arr[3]); return expandSchemaForField(this, arr[0], arr[1], arr[2], arr[3]);
}) })
.onLoop(function () {
var gadget = this;
if (this.props.changed) {
return this.checkValidity()
.push(function () {
gadget.props.changed = false;
});
}
}, 500)
.declareMethod('getContent', function (sub_path) { .declareMethod('getContent', function (sub_path) {
var g = this; var g = this;
...@@ -976,4 +1017,4 @@ ...@@ -976,4 +1017,4 @@
return {}; return {};
}, {mutex: 'changestate'}); }, {mutex: 'changestate'});
}(window, document, Blob, rJS, RSVP, jIO, tv4)); }(window, document, Blob, rJS, RSVP, jIO));
\ No newline at end of file \ No newline at end of file
...@@ -40,6 +40,10 @@ ...@@ -40,6 +40,10 @@
return _str.replace(/~/g, '~0').replace(/\//g, '~1'); return _str.replace(/~/g, '~0').replace(/\//g, '~1');
} }
function escapeId(s) {
return s.replace(/[!"#$%&'()*+,.\/:;<=>?@[\\\]^`{|}~]/g, "\\$&");
}
function getDocumentType(doc) { function getDocumentType(doc) {
if (doc === undefined) { if (doc === undefined) {
return; return;
...@@ -1398,7 +1402,7 @@ ...@@ -1398,7 +1402,7 @@
gadget: g, gadget: g,
property_name: key, property_name: key,
parent_path: path, parent_path: path,
delete_button: false, delete_button: !schema_arr.external_reference,
schema_arr: filtered_schema_arr, schema_arr: filtered_schema_arr,
json_document: json_document[key] json_document: json_document[key]
}) })
...@@ -1743,18 +1747,44 @@ ...@@ -1743,18 +1747,44 @@
rJS(window) rJS(window)
.ready(function () { .ready(function () {
var g = this; var g = this;
g.props = {}; g.props = {
needValidate: false
};
g.options = {}; g.options = {};
}) })
.declareAcquiredMethod("rNotifyChange", "rootNotifyChange") .declareAcquiredMethod("rNotifyChange", "rootNotifyChange")
.declareMethod("rootNotifyChange", function (path) { .declareMethod("rootNotifyChange", function (path) {
var g = this; var g = this;
return this.getJsonPath(path) this.props.needValidate = true;
return g.getJsonPath(path)
.push(function (p) { .push(function (p) {
return g.rNotifyChange(p); return g.rNotifyChange({
scope: g.element.getAttribute("data-gadget-scope"),
rel_path: path,
path: p
});
});
})
.declareMethod("selfRemove", function () {
var g = this,
sub_gadets = g.element.querySelectorAll("div[data-gadget-scope]"),
i,
tasks = [];
for (i = 0; i < sub_gadets.length; i += 1) {
tasks.push(
g.notifyInvalid([], sub_gadets[i].getAttribute("data-gadget-scope"))
);
}
tasks.push(g.notifyInvalid([], g.element.getAttribute("data-gadget-scope")));
return new RSVP.Queue()
.push(function () {
return RSVP.all(tasks);
})
.push(function () {
return g.deleteChildren();
}); });
}) })
.declareAcquiredMethod("selfRemove", "deleteChildren") .declareAcquiredMethod("deleteChildren", "deleteChildren")
.allowPublicAcquisition("deleteChildren", function (arr, scope) { .allowPublicAcquisition("deleteChildren", function (arr, scope) {
var g = this, var g = this,
key, key,
...@@ -1929,14 +1959,13 @@ ...@@ -1929,14 +1959,13 @@
.declareMethod('getElementByPath', function (data_path) { .declareMethod('getElementByPath', function (data_path) {
return this.getGadgetByPath(data_path) return this.getGadgetByPath(data_path)
.push(function (ret) { .push(function (ret) {
return document.getElementById( return ret.gadget.element.querySelector("#" +
ret.gadget.element.getAttribute("data-gadget-scope") + ret.path ret.gadget.element.getAttribute("data-gadget-scope") +
); escapeId(ret.path));
}); });
}) })
.declareAcquiredMethod("notifyValid", "notifyValid") .declareAcquiredMethod("notifyValid", "notifyValid")
.declareAcquiredMethod("notifyInvalid", "notifyInvalid") .declareAcquiredMethod("notifyInvalid", "notifyInvalid")
.declareAcquiredMethod("checkValidity", "checkValidity")
.allowPublicAcquisition("notifyValid", function () { .allowPublicAcquisition("notifyValid", function () {
return true; return true;
...@@ -2004,14 +2033,25 @@ ...@@ -2004,14 +2033,25 @@
} }
for_delete = Array.from(root.childNodes); for_delete = Array.from(root.childNodes);
if (opt.schema) { if (opt.schema) {
if (g.props.render_opt.selected_schema) {
g.props.render_opt.selected_schema.schema = opt.schema;
}
g.props.schema_arr[0].schema = opt.schema; g.props.schema_arr[0].schema = opt.schema;
} }
return render_field(g, g.props.property_name, "", g.props.schema_arr, return render_field(g, g.props.property_name, "", g.props.schema_arr,
opt.value, root, g.props.render_opt) opt.value, root, g.props.render_opt)
.push(function () { .push(function () {
for (var i = 0; i < for_delete.length; i += 1) { var value = opt.value,
i;
for (i = 0; i < for_delete.length; i += 1) {
root.removeChild(for_delete[i]); root.removeChild(for_delete[i]);
} }
if (g.props.changed) {
value = undefined;
}
return g.checkValidity(value);
})
.push(function () {
return g.element; return g.element;
}); });
}) })
...@@ -2055,6 +2095,120 @@ ...@@ -2055,6 +2095,120 @@
} }
}) })
.declareAcquiredMethod("rootGetSchema", "getSchema")
.declareMethod('getSchema', function (json_document) {
var g = this,
schema_arr = g.props.schema_arr,
schema_path;
if (g.props.render_opt.selected_schema) {
schema_path = g.props.render_opt.selected_schema.schema_path;
} else {
if (json_document !== undefined && !g.props.render_opt.top) {
schema_path = schemaArrFilteredByDocument(schema_arr, json_document)[0].schema_path;
} else if (schema_arr.schema_path) {
schema_path = schema_arr.schema_path;
} else if (json_document !== undefined) {
schema_path = schemaArrFilteredByDocument(schema_arr, json_document)[0].schema_path;
} else {
schema_path = schema_arr[0].schema_path;
}
}
return g.rootGetSchema(schema_path);
})
.declareMethod('checkValidity', function (json_document, schema) {
var g = this;
return RSVP.Queue()
.push(function () {
if (json_document === undefined) {
return g.getContent();
}
return json_document;
})
.push(function (json_d) {
json_document = json_d;
if (schema === undefined) {
return g.getSchema(json_document);
}
return schema;
})
.push(function (s) {
schema = s;
return tv4.validateMultiple(json_document, schema);
})
.push(function (validation) {
var i,
error,
tasks = [],
errors = [],
self_scope = g.element.getAttribute("data-gadget-scope"),
ret_errors = [];
errors = errors.concat(validation.errors);
errors = errors.concat(validation.missing);
if (errors.length === 0) {
return g.notifyInvalid(
errors,
self_scope
);
}
function print_error(error) {
return function (ret) {
var scope = ret.gadget.element.getAttribute("data-gadget-scope"),
parent_scope = ret.gadget.element.getAttribute("data-gadget-parent-scope");
if ((scope === self_scope && (g.props.render_opt.top || ret.path !== "/")) ||
(parent_scope === self_scope && ret.path === "/")) {
error.element = ret.gadget.element.querySelector("#" +
scope +
escapeId(ret.path));
ret_errors.push(error);
}
};
}
for (i = 0; i < errors.length; i += 1) {
error = errors[i];
tasks.push(
g.getGadgetByPath(error.dataPath || "/")
.push(print_error(error))
);
}
return RSVP.Queue()
.push(function () {
return RSVP.all(tasks);
})
.push(function () {
return g.notifyInvalid(
ret_errors,
self_scope
);
});
});
})
.allowPublicAcquisition("printErrors", function () {
this.props.needValidate = true;
})
.declareAcquiredMethod("parentPrintErrors", "printErrors")
.declareJob("reValidate", function (json_document, schema) {
var gadget = this;
return this.checkValidity(json_document, schema)
.push(function () {
return gadget.parentPrintErrors();
})
.push(function () {
gadget.props.needValidate = false;
});
})
.onLoop(function () {
if (this.props.needValidate) {
return this.reValidate();
}
}, 500)
.onEvent('input', function (evt) { .onEvent('input', function (evt) {
var gadget = this, var gadget = this,
field_list = this.props.inputs, field_list = this.props.inputs,
......
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