diff --git a/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form.xml b/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form.xml new file mode 100644 index 0000000000000000000000000000000000000000..cdba2281157c898f089a61e3a93bbcef66e11e78 --- /dev/null +++ b/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form.xml @@ -0,0 +1,26 @@ + + + + + + + + + + _objects + + + + + + id + erp5_json_form + + + title + + + + + + diff --git a/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/json-schema.xml b/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/json-schema.xml new file mode 100644 index 0000000000000000000000000000000000000000..cbafac43b5a1793f55e24fbf511e1bbc351fb212 --- /dev/null +++ b/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/json-schema.xml @@ -0,0 +1,26 @@ + + + + + + + + + + _objects + + + + + + id + json-schema + + + title + + + + + + diff --git a/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/json-schema/schema4.json.json b/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/json-schema/schema4.json.json new file mode 100644 index 0000000000000000000000000000000000000000..bcbb84743e3838fab7cbec5f0a5bcbafcfc99136 --- /dev/null +++ b/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/json-schema/schema4.json.json @@ -0,0 +1,149 @@ +{ + "id": "http://json-schema.org/draft-04/schema#", + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "Core schema meta-schema", + "definitions": { + "schemaArray": { + "type": "array", + "minItems": 1, + "items": { "$ref": "#" } + }, + "positiveInteger": { + "type": "integer", + "minimum": 0 + }, + "positiveIntegerDefault0": { + "allOf": [ { "$ref": "#/definitions/positiveInteger" }, { "default": 0 } ] + }, + "simpleTypes": { + "enum": [ "array", "boolean", "integer", "null", "number", "object", "string" ] + }, + "stringArray": { + "type": "array", + "items": { "type": "string" }, + "minItems": 1, + "uniqueItems": true + } + }, + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "$schema": { + "type": "string" + }, + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "default": {}, + "multipleOf": { + "type": "number", + "minimum": 0, + "exclusiveMinimum": true + }, + "maximum": { + "type": "number" + }, + "exclusiveMaximum": { + "type": "boolean", + "default": false + }, + "minimum": { + "type": "number" + }, + "exclusiveMinimum": { + "type": "boolean", + "default": false + }, + "maxLength": { "$ref": "#/definitions/positiveInteger" }, + "minLength": { "$ref": "#/definitions/positiveIntegerDefault0" }, + "pattern": { + "type": "string", + "format": "regex" + }, + "additionalItems": { + "anyOf": [ + { "type": "boolean" }, + { "$ref": "#" } + ], + "default": {} + }, + "items": { + "anyOf": [ + { "$ref": "#" }, + { "$ref": "#/definitions/schemaArray" } + ], + "default": {} + }, + "maxItems": { "$ref": "#/definitions/positiveInteger" }, + "minItems": { "$ref": "#/definitions/positiveIntegerDefault0" }, + "uniqueItems": { + "type": "boolean", + "default": false + }, + "maxProperties": { "$ref": "#/definitions/positiveInteger" }, + "minProperties": { "$ref": "#/definitions/positiveIntegerDefault0" }, + "required": { "$ref": "#/definitions/stringArray" }, + "additionalProperties": { + "anyOf": [ + { "type": "boolean" }, + { "$ref": "#" } + ], + "default": {} + }, + "definitions": { + "type": "object", + "additionalProperties": { "$ref": "#" }, + "default": {} + }, + "properties": { + "type": "object", + "additionalProperties": { "$ref": "#" }, + "default": {} + }, + "patternProperties": { + "type": "object", + "additionalProperties": { "$ref": "#" }, + "default": {} + }, + "dependencies": { + "type": "object", + "additionalProperties": { + "anyOf": [ + { "$ref": "#" }, + { "$ref": "#/definitions/stringArray" } + ] + } + }, + "enum": { + "type": "array", + "minItems": 1, + "uniqueItems": true + }, + "type": { + "anyOf": [ + { "$ref": "#/definitions/simpleTypes" }, + { + "type": "array", + "items": { "$ref": "#/definitions/simpleTypes" }, + "minItems": 1, + "uniqueItems": true + } + ] + }, + "format": { "type": "string" }, + "allOf": { "$ref": "#/definitions/schemaArray" }, + "anyOf": { "$ref": "#/definitions/schemaArray" }, + "oneOf": { "$ref": "#/definitions/schemaArray" }, + "not": { "$ref": "#" } + }, + "dependencies": { + "exclusiveMaximum": [ "maximum" ], + "exclusiveMinimum": [ "minimum" ] + }, + "default": {} +} diff --git a/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/json-schema/schema4.json.xml b/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/json-schema/schema4.json.xml new file mode 100644 index 0000000000000000000000000000000000000000..e70369b20d7ebdb546f980b260106517c4e73949 --- /dev/null +++ b/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/json-schema/schema4.json.xml @@ -0,0 +1,28 @@ + + + + + + + + + + __name__ + schema4.json + + + content_type + application/json + + + precondition + + + + title + schema4.json + + + + + diff --git a/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/json-schema/schema6.json.json b/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/json-schema/schema6.json.json new file mode 100644 index 0000000000000000000000000000000000000000..5656240b94724091487c1c3c9cdce68c10352598 --- /dev/null +++ b/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/json-schema/schema6.json.json @@ -0,0 +1,154 @@ +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "$id": "http://json-schema.org/draft-06/schema#", + "title": "Core schema meta-schema", + "definitions": { + "schemaArray": { + "type": "array", + "minItems": 1, + "items": { "$ref": "#" } + }, + "nonNegativeInteger": { + "type": "integer", + "minimum": 0 + }, + "nonNegativeIntegerDefault0": { + "allOf": [ + { "$ref": "#/definitions/nonNegativeInteger" }, + { "default": 0 } + ] + }, + "simpleTypes": { + "enum": [ + "array", + "boolean", + "integer", + "null", + "number", + "object", + "string" + ] + }, + "stringArray": { + "type": "array", + "items": { "type": "string" }, + "uniqueItems": true, + "default": [] + } + }, + "type": ["object", "boolean"], + "properties": { + "$id": { + "type": "string", + "format": "uri-reference" + }, + "$schema": { + "type": "string", + "format": "uri" + }, + "$ref": { + "type": "string", + "format": "uri-reference" + }, + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "default": {}, + "examples": { + "type": "array", + "items": {} + }, + "multipleOf": { + "type": "number", + "exclusiveMinimum": 0 + }, + "maximum": { + "type": "number" + }, + "exclusiveMaximum": { + "type": "number" + }, + "minimum": { + "type": "number" + }, + "exclusiveMinimum": { + "type": "number" + }, + "maxLength": { "$ref": "#/definitions/nonNegativeInteger" }, + "minLength": { "$ref": "#/definitions/nonNegativeIntegerDefault0" }, + "pattern": { + "type": "string", + "format": "regex" + }, + "additionalItems": { "$ref": "#" }, + "items": { + "anyOf": [ + { "$ref": "#" }, + { "$ref": "#/definitions/schemaArray" } + ], + "default": {} + }, + "maxItems": { "$ref": "#/definitions/nonNegativeInteger" }, + "minItems": { "$ref": "#/definitions/nonNegativeIntegerDefault0" }, + "uniqueItems": { + "type": "boolean", + "default": false + }, + "contains": { "$ref": "#" }, + "maxProperties": { "$ref": "#/definitions/nonNegativeInteger" }, + "minProperties": { "$ref": "#/definitions/nonNegativeIntegerDefault0" }, + "required": { "$ref": "#/definitions/stringArray" }, + "additionalProperties": { "$ref": "#" }, + "definitions": { + "type": "object", + "additionalProperties": { "$ref": "#" }, + "default": {} + }, + "properties": { + "type": "object", + "additionalProperties": { "$ref": "#" }, + "default": {} + }, + "patternProperties": { + "type": "object", + "additionalProperties": { "$ref": "#" }, + "default": {} + }, + "dependencies": { + "type": "object", + "additionalProperties": { + "anyOf": [ + { "$ref": "#" }, + { "$ref": "#/definitions/stringArray" } + ] + } + }, + "propertyNames": { "$ref": "#" }, + "const": {}, + "enum": { + "type": "array", + "minItems": 1, + "uniqueItems": true + }, + "type": { + "anyOf": [ + { "$ref": "#/definitions/simpleTypes" }, + { + "type": "array", + "items": { "$ref": "#/definitions/simpleTypes" }, + "minItems": 1, + "uniqueItems": true + } + ] + }, + "format": { "type": "string" }, + "allOf": { "$ref": "#/definitions/schemaArray" }, + "anyOf": { "$ref": "#/definitions/schemaArray" }, + "oneOf": { "$ref": "#/definitions/schemaArray" }, + "not": { "$ref": "#" } + }, + "default": {} +} diff --git a/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/json-schema/schema6.json.xml b/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/json-schema/schema6.json.xml new file mode 100644 index 0000000000000000000000000000000000000000..00ece57f36b2158b4e11378672fefe5c2c895554 --- /dev/null +++ b/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/json-schema/schema6.json.xml @@ -0,0 +1,28 @@ + + + + + + + + + + __name__ + schema6.json + + + content_type + application/json + + + precondition + + + + title + schema6.json + + + + + diff --git a/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/json-schema/schema7.json.json b/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/json-schema/schema7.json.json new file mode 100644 index 0000000000000000000000000000000000000000..5bee90ec141cc3c3fb369aee979027c6453c49e9 --- /dev/null +++ b/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/json-schema/schema7.json.json @@ -0,0 +1,168 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "http://json-schema.org/draft-07/schema#", + "title": "Core schema meta-schema", + "definitions": { + "schemaArray": { + "type": "array", + "minItems": 1, + "items": { "$ref": "#" } + }, + "nonNegativeInteger": { + "type": "integer", + "minimum": 0 + }, + "nonNegativeIntegerDefault0": { + "allOf": [ + { "$ref": "#/definitions/nonNegativeInteger" }, + { "default": 0 } + ] + }, + "simpleTypes": { + "enum": [ + "array", + "boolean", + "integer", + "null", + "number", + "object", + "string" + ] + }, + "stringArray": { + "type": "array", + "items": { "type": "string" }, + "uniqueItems": true, + "default": [] + } + }, + "type": ["object", "boolean"], + "properties": { + "$id": { + "type": "string", + "format": "uri-reference" + }, + "$schema": { + "type": "string", + "format": "uri" + }, + "$ref": { + "type": "string", + "format": "uri-reference" + }, + "$comment": { + "type": "string" + }, + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "default": true, + "readOnly": { + "type": "boolean", + "default": false + }, + "examples": { + "type": "array", + "items": true + }, + "multipleOf": { + "type": "number", + "exclusiveMinimum": 0 + }, + "maximum": { + "type": "number" + }, + "exclusiveMaximum": { + "type": "number" + }, + "minimum": { + "type": "number" + }, + "exclusiveMinimum": { + "type": "number" + }, + "maxLength": { "$ref": "#/definitions/nonNegativeInteger" }, + "minLength": { "$ref": "#/definitions/nonNegativeIntegerDefault0" }, + "pattern": { + "type": "string", + "format": "regex" + }, + "additionalItems": { "$ref": "#" }, + "items": { + "anyOf": [ + { "$ref": "#" }, + { "$ref": "#/definitions/schemaArray" } + ], + "default": true + }, + "maxItems": { "$ref": "#/definitions/nonNegativeInteger" }, + "minItems": { "$ref": "#/definitions/nonNegativeIntegerDefault0" }, + "uniqueItems": { + "type": "boolean", + "default": false + }, + "contains": { "$ref": "#" }, + "maxProperties": { "$ref": "#/definitions/nonNegativeInteger" }, + "minProperties": { "$ref": "#/definitions/nonNegativeIntegerDefault0" }, + "required": { "$ref": "#/definitions/stringArray" }, + "additionalProperties": { "$ref": "#" }, + "definitions": { + "type": "object", + "additionalProperties": { "$ref": "#" }, + "default": {} + }, + "properties": { + "type": "object", + "additionalProperties": { "$ref": "#" }, + "default": {} + }, + "patternProperties": { + "type": "object", + "additionalProperties": { "$ref": "#" }, + "propertyNames": { "format": "regex" }, + "default": {} + }, + "dependencies": { + "type": "object", + "additionalProperties": { + "anyOf": [ + { "$ref": "#" }, + { "$ref": "#/definitions/stringArray" } + ] + } + }, + "propertyNames": { "$ref": "#" }, + "const": true, + "enum": { + "type": "array", + "items": true, + "minItems": 1, + "uniqueItems": true + }, + "type": { + "anyOf": [ + { "$ref": "#/definitions/simpleTypes" }, + { + "type": "array", + "items": { "$ref": "#/definitions/simpleTypes" }, + "minItems": 1, + "uniqueItems": true + } + ] + }, + "format": { "type": "string" }, + "contentMediaType": { "type": "string" }, + "contentEncoding": { "type": "string" }, + "if": {"$ref": "#"}, + "then": {"$ref": "#"}, + "else": {"$ref": "#"}, + "allOf": { "$ref": "#/definitions/schemaArray" }, + "anyOf": { "$ref": "#/definitions/schemaArray" }, + "oneOf": { "$ref": "#/definitions/schemaArray" }, + "not": { "$ref": "#" } + }, + "default": true +} diff --git a/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/json-schema/schema7.json.xml b/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/json-schema/schema7.json.xml new file mode 100644 index 0000000000000000000000000000000000000000..4bad30d30d2bf1e519a503124d34b461166b9df1 --- /dev/null +++ b/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/json-schema/schema7.json.xml @@ -0,0 +1,28 @@ + + + + + + + + + + __name__ + schema7.json + + + content_type + application/json + + + precondition + + + + title + schema7.json + + + + + diff --git a/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/jsonform.gadget.appcache.appcache b/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/jsonform.gadget.appcache.appcache new file mode 100644 index 0000000000000000000000000000000000000000..fd6fcdb868c0733201f1552618ce2bfd860dc01f --- /dev/null +++ b/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/jsonform.gadget.appcache.appcache @@ -0,0 +1,22 @@ +#shared +rsvp.js +renderjs.js +handlebars.js +gadget_erp5_nojqm.css + +gadget_erp5_global.js +gadget_html5_select.html +gadget_html5_select.js + +#jsonform +jio.js +gadget_html5_select.html +gadget_html5_select.js +json-schema/schema4.json +json-schema/schema6.json +json-schema/schema7.json +jsonform.gadget.html +jsonform.gadget.js +jsonform/gadget_json_generated_form_child.html +jsonform/gadget_json_generated_form_child.js +jsonform/tv4.js diff --git a/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/jsonform.gadget.appcache.xml b/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/jsonform.gadget.appcache.xml new file mode 100644 index 0000000000000000000000000000000000000000..63b3403ef8fd492c6869d531b9215cdd4758c203 --- /dev/null +++ b/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/jsonform.gadget.appcache.xml @@ -0,0 +1,28 @@ + + + + + + + + + + __name__ + jsonform.gadget.appcache + + + content_type + text/cache-manifest + + + precondition + + + + title + jsonform.gadget.appcache + + + + + diff --git a/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/jsonform.gadget.html.html b/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/jsonform.gadget.html.html new file mode 100644 index 0000000000000000000000000000000000000000..8f38c203d1f73c5fe8f17c02583e3fe4cde59450 --- /dev/null +++ b/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/jsonform.gadget.html.html @@ -0,0 +1,16 @@ + + + + + + ERP5 + + + + + + + + + + diff --git a/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/jsonform.gadget.html.xml b/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/jsonform.gadget.html.xml new file mode 100644 index 0000000000000000000000000000000000000000..d63d0617dccf2a8e7735de5d8601680b68751870 --- /dev/null +++ b/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/jsonform.gadget.html.xml @@ -0,0 +1,28 @@ + + + + + + + + + + __name__ + jsonform.gadget.html + + + content_type + text/html + + + precondition + + + + title + schema.gadget.html + + + + + diff --git a/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/jsonform.gadget.js.js b/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/jsonform.gadget.js.js new file mode 100644 index 0000000000000000000000000000000000000000..01a14d41ac02965af25cc85fc5d0e33a1c4b0b28 --- /dev/null +++ b/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/jsonform.gadget.js.js @@ -0,0 +1,936 @@ +/*jslint nomen: true, maxlen: 200, indent: 2, maxerr: 100*/ +/*global window, document, URL, rJS, RSVP, jIO, tv4, location */ + +(function (window, document, location, rJS, RSVP, jIO, tv4) { + "use strict"; + var expandSchema; + + function arrayIntersect(x, y) { + return x.filter(function (value) { + return y.indexOf(value) >= 0; + }); + } + + function URLwithJio(url, base_url) { + var urn_prefix, + pathname, + fake_prefix = "https://jio_urn_prefix/"; + // XXX urn: can any case + if (url.startsWith("urn:jio:reference?")) { + urn_prefix = url.indexOf("?") + 1; + urn_prefix = url.slice(0, urn_prefix); + url = fake_prefix + decodeURIComponent(url.replace(urn_prefix, "")); + } + if (typeof base_url === "string" && + !(url.startsWith("http://") || url.startsWith("https://") || url.startsWith("//")) && + base_url.startsWith("urn:jio:reference?")) { + if (!urn_prefix) { + urn_prefix = base_url.indexOf("?") + 1; + urn_prefix = base_url.slice(0, urn_prefix); + } + base_url = fake_prefix + decodeURIComponent(base_url.replace(urn_prefix, "")); + } + url = new URL(url, base_url); + if (urn_prefix) { + pathname = url.pathname.slice(1); + this.href = urn_prefix + encodeURIComponent(pathname + url.search + url.hash); + this.origin = urn_prefix; + this.pathname = encodeURIComponent(pathname); + this.hash = url.hash; + this.search = ""; + return this; + } + return url; + } + + function decodeJsonPointer(_str) { + // https://tools.ietf.org/html/rfc6901#section-5 + return _str.replace(/~1/g, '/').replace(/~0/g, '~'); + } + + function encodeJsonPointer(_str) { + // https://tools.ietf.org/html/rfc6901#section-5 + return _str.replace(/~/g, '~0').replace(/\//g, '~1'); + } + + function getMaxPathInDict(dict, path) { + var target, + key, + max_len = 0; + if (!path) { + return ""; + } + for (key in dict) { + if (dict.hasOwnProperty(key) && + path.startsWith(key) && + key.length > max_len) { + target = key; + max_len = key.length; + } + } + return target; + } + + function checkCircular(urls, path, url) { + var stack, + idx, + prev_field_path = getMaxPathInDict(urls, path); + stack = urls[prev_field_path] || []; + idx = stack.indexOf(url); + if (idx >= 0) { + if (path === prev_field_path && idx === 0) { + return; + } + return true; + } + // copy and add url as first element + urls[path] = [url].concat(stack); + } + + function checkHardCircular(g, path, url) { + return checkCircular(g.props.schema_required_urls, path, url); + } + + function checkAndMarkSoftCircular(g, schema_arr, path, url) { + var ret = true; + // if schema_arr.length > 1 selection rendered in any case + // so we not need checkCircular and have small optimisation + if (schema_arr.length === 1) { + ret = checkCircular(g.props.schema_urls, path, url); + schema_arr[0].circular = ret; + } + if (ret) { + // if schema_arr.length > 1 selection rendered and loop break + // if circular found selection rendered and loop break + // so we can begin from start + g.props.schema_urls[path] = []; + } + } + + function convertToRealWorldSchemaPath(g, path) { + var url, + hash, + map = g.props.schema_map, + prev_downl_path, + max_len = 0; + if (!path) { + return ""; + } + // previous downloaded path + prev_downl_path = getMaxPathInDict(map, path); + if (prev_downl_path === undefined) { + url = ""; + max_len = 0; + } else { + url = map[prev_downl_path]; + if (prev_downl_path === "/") { + max_len = 0; + } else { + max_len = prev_downl_path.length; + } + } + hash = path.substr(max_len); + if (hash) { + // XXX urlencode for hash + if (url.indexOf("#") >= 0) { + url = url + hash; + } else { + url = url + "#" + hash; + } + } + return url; + } + + function convertUrlToAbsolute(g, path, url, base_url_failback) { + var // previous downloaded path + base_url = convertToRealWorldSchemaPath(g, path), + absolute_url; + if (base_url === "" || base_url.indexOf("#") === 0) { + absolute_url = new URLwithJio(url, base_url_failback); + } else { + absolute_url = new URLwithJio(url, base_url); + } + return absolute_url; + } + + function downloadJSON(url) { + return RSVP.Queue() + .push(function () { + return jIO.util.ajax({ + url: url, + dataType: "json" + }); + }) + .push(function (evt) { + return evt.target.response; + }); + } + + function resolveLocalReference(schema, ref) { + // 2 here is for #/ + var i, ref_path = ref.substr(2, ref.length), + parts = ref_path.split("/"); + if (parts.length === 1 && parts[0] === "") { + // It was uses #/ to reference the entire json so just return it. + return schema; + } + for (i = 0; i < parts.length; i += 1) { + if (schema === undefined) { + throw new Error("local ref `" + ref + "` does not exist in:"); + } + schema = schema[decodeJsonPointer(parts[i])]; + } + return schema; + } + + function schemaPushSchemaPart(schema, schema_path, schema_part) { + var i, + k, + key_list; + if (schema_path === "/") { + schema_path = ""; + } + key_list = schema_path.split("/"); + for (i = 0; i < key_list.length; i += 1) { + k = decodeJsonPointer(key_list[i]); + if (i === key_list.length - 1) { + if (schema_part !== undefined) { + schema[k] = schema_part; + } else { + return schema[k]; + } + } else { + if (!schema.hasOwnProperty(k)) { + schema[k] = {}; + } + schema = schema[k]; + } + } + } + + function map_url(g, download_url) { + var mapped_url = download_url, + hash = mapped_url.hash, + i, + schemas = g.props.schemas, + next_mapped_url; + // simple defence forever loop + for (i = 0; i < Object.keys(schemas).length; i += 1) { + next_mapped_url = g.props.schemas[mapped_url.origin + mapped_url.pathname + mapped_url.search]; + if (next_mapped_url === undefined) { + break; + } + mapped_url = next_mapped_url; + if (typeof mapped_url !== "string") { + mapped_url = resolveLocalReference(mapped_url, hash); + break; + } + mapped_url = new URL(mapped_url, g.__path); + if (hash[0] === '#') { + hash = hash.slice(1); + } + if (hash === '/') { + hash = ''; + } + hash = mapped_url.hash + hash; + } + return mapped_url; + } + + function loadJSONSchema(g, $ref, path) { + var protocol, + url, + download_url, + hash, + mapped_url, + queue; + // XXX need use `id` property + if (!path) { + path = "/"; + } + url = convertUrlToAbsolute(g, path, decodeURI($ref), window.location); + mapped_url = map_url(g, url); + if (mapped_url instanceof URL || mapped_url instanceof URLwithJio) { + url = mapped_url; + } + protocol = url.protocol; + if (protocol === "http:" || protocol === "https:") { + if (window.location.protocol !== protocol) { + url = new URL(decodeURI($ref).replace(protocol + "//", window.location.protocol + "//")); + // throw new Error("You cannot mixed http and https calls"); + } + } + download_url = url.origin + url.pathname + url.search; + hash = url.hash; + url = url.href; + if (!(mapped_url instanceof URL || mapped_url instanceof URLwithJio)) { + queue = RSVP.Queue() + .push(function () { + return mapped_url; + }); + } else { + if (download_url.startsWith("urn:jio:")) { + queue = RSVP.Queue() + .push(function () { + return g.resolveExternalReference(download_url); + }); + } else { + queue = RSVP.Queue() + .push(function () { + return downloadJSON(download_url); + }); + } + queue + .push(function (json) { + if (checkHardCircular(g, path, url)) { + throw new Error("Circular reference detected"); + } + return resolveLocalReference(json, hash); + }); + } + return queue + .push(undefined, function (err) { + // XXX it will be great to have ability convert json_pointers(hash) + // in line numbers for pointed to line in rich editors. + // we can use https://github.com/vtrushin/json-to-ast for it + var url_from_pointed = convertToRealWorldSchemaPath(g, path), + schema_a = document.createElement("a"), + pointed_a = document.createElement("a"); + schema_a.setAttribute("href", download_url); + schema_a.text = (new URLwithJio(download_url)).pathname; + pointed_a.setAttribute("href", url_from_pointed); + pointed_a.text = (new URLwithJio(url_from_pointed)).pathname; + g.props.schema_resolve_errors[url_from_pointed] = { + schemaPath: path, + message: [ + document.createTextNode("schema error: "), + document.createTextNode(err.message), + schema_a, + document.createTextNode(" pointed from schema: "), + pointed_a + ] + }; + return null; // schema part can't be null + }) + .push(function (schema_part) { + // console.log(path); + if (schema_part === null) { + // if resolving schema part contain errors + // use {} as failback + schema_part = {}; + } else { + // save map url only for correctly resolved schema + // otherwise we have issue in convertToRealWorldSchemaPath + g.props.schema_map[path] = url; + } + schemaPushSchemaPart(g.props.schema, path, JSON.parse(JSON.stringify(schema_part))); + // console.log(g.props.schema[""]); + return expandSchema(g, schema_part, path, $ref); + }) + .push(function (schema_arr) { + checkAndMarkSoftCircular(g, schema_arr, path, url); + return schema_arr; + }); + } + + function mergeSchemas(x, y, doesntcopy) { + if (x === true && y === true) { + return true; + } + if (x === false || y === false) { + return false; + } + var key, + p; + if (x.hasOwnProperty("$ref") || + y.hasOwnProperty("$ref")) { + if (doesntcopy) { + // we need reference resolve before merging + // so allOf schema returned and array item or object field + // run merging on next iteration. + return { + allOf: [ + x, + y + ] + }; + } else { + throw new Error("all reference must be resolved before merge run on first recursion level"); + } + } + if (x === true) { + x = {}; + } else if (!doesntcopy) { + x = JSON.parse(JSON.stringify(x)); + // cleanup already walked schema variations + if (x.anyOf) { + delete x.anyOf; + } + if (x.oneOf) { + delete x.oneOf; + } + if (x.allOf) { + delete x.allOf; + } + } + if (y === true) { + y = {}; + } + for (key in y) { + if (y.hasOwnProperty(key)) { + if (x.hasOwnProperty(key)) { + switch (key) { + case "maxProperties": + case "maxLength": + case "maxItems": + case "maximum": + case "exclusiveMaximum": + if (y[key] < x[key]) { + x[key] = y[key]; + } + break; + case "minProperties": + case "minItems": + case "minLength": + case "minimum": + case "exclusiveMinimum": + if (x[key] < y[key]) { + x[key] = y[key]; + } + break; + case "additionalProperties": + case "additionalItems": + case "contains": + case "propertyNames": + x[key] = mergeSchemas(x[key], y[key], true); + break; + case "items": + // XXX items can be array + x[key] = mergeSchemas(x[key], y[key], true); + break; + case "contentEncoding": + case "contentMediaType": + if (x[key] !== y[key]) { + return false; + } + break; + case "multipleOf": + x[key] = x[key] * y[key]; + break; + case "type": + if (typeof x.type === "string") { + if (typeof y.type === "string") { + if (x.type !== y.type) { + return false; + } + } else if (y.type.indexOf(x.type) === -1) { + return false; + } + } else { + if (typeof y.type === "string") { + if (x.type.indexOf(y.type) === -1) { + return false; + } + } else { + x.type = arrayIntersect(x.type, y.type); + if (x.type.length === 0) { + return false; + } + } + } + break; + case "properties": + case "patternProperties": + for (p in y[key]) { + if (y[key].hasOwnProperty(p)) { + if (x[key].hasOwnProperty(p)) { + x[key][p] = mergeSchemas(x[key][p], y[key][p], true); + } else { + x[key][p] = y[key][p]; + } + } + } + break; + case "pattern": + // XXX regex string merge + case "dependencies": + // XXX find solution how merge + x[key] = y[key]; + break; + case "required": + for (p = 0; p < y.required.length; p += 1) { + if (x.required.indexOf(y.required[p]) < 0) { + x.required.push(y.required[p]); + } + } + break; + case "uniqueItems": + x[key] = y[key]; + break; + case "allOf": + case "anyOf": + case "oneOf": + case "$ref": + case "id": + case "$id": + // XXX + break; + default: + // XXX + x[key] = y[key]; + } + } else { + switch (key) { + case "allOf": + case "anyOf": + case "oneOf": + case "$ref": + break; + default: + x[key] = y[key]; + } + } + } + } + return x; + } + + function allOf(g, schema_array, schema_path, base_schema) { + return RSVP.Queue() + .push(function () { + var i, + arr = []; + for (i = 0; i < schema_array.length; i += 1) { + arr.push(expandSchema(g, schema_array[i], schema_path + '/' + i.toString())); + } + return RSVP.all(arr); + }) + .push(function (arr) { + var i, + x, + y, + next_schema, + schema, + summ_arr; + for (i = 0; i < arr.length - 1; i += 1) { + summ_arr = []; + for (x = 0; x < arr[i].length; x += 1) { + for (y = 0; y < arr[i + 1].length; y += 1) { + schema = arr[i][x].schema; + next_schema = arr[i + 1][y].schema; + schema = mergeSchemas(schema, next_schema); + summ_arr.push({ + schema: schema, + // XXX we loss path arr[i + 1][y].schema_path + schema_path: arr[i][x].schema_path + }); + } + } + arr[i + 1] = summ_arr; + } + for (x = 0; x < summ_arr.length; x += 1) { + summ_arr[x].schema = mergeSchemas(summ_arr[x].schema, base_schema); + } + return summ_arr; + }); + } + + function anyOf(g, schema_array, schema_path, base_schema) { + return RSVP.Queue() + .push(function () { + var i, + arr = []; + for (i = 0; i < schema_array.length; i += 1) { + arr.push(expandSchema(g, schema_array[i], schema_path + '/' + i.toString())); + } + return RSVP.all(arr); + }) + .push(function (arr) { + var i, + z, + schema_arr = []; + for (i = 0; i < arr.length; i += 1) { + for (z = 0; z < arr[i].length; z += 1) { + if (arr[i][z].schema === true) { + // or(any, restricted, restricted, .. ) simplify to any + return [arr[i][z]]; + } + if (base_schema.title) { + arr[i][z].title = base_schema.title; + } + if (base_schema.description) { + arr[i][z].description = base_schema.description; + } + arr[i][z].schema = mergeSchemas(base_schema, arr[i][z].schema); + schema_arr.push(arr[i][z]); + } + } + return schema_arr; + }); + } + + expandSchema = function (g, schema, schema_path, ref) { + // XXX `if then else` construction can be simplify to + // anyOf(allOf(if_schema, then_schema), else_schema) + // and realized by existed rails + if (schema === undefined || + Object.keys(schema).length === 0) { + schema = true; + } + if (schema.anyOf !== undefined) { + return anyOf(g, schema.anyOf, schema_path + '/anyOf', schema); + } + if (schema.oneOf !== undefined) { + return anyOf(g, schema.oneOf, schema_path + '/oneOf', schema); + } + if (schema.allOf !== undefined) { + return allOf(g, schema.allOf, schema_path + '/allOf', schema); + } + if (schema.$ref) { + return loadJSONSchema(g, schema.$ref, schema_path); + } + if (schema.definitions) { + var key, + d, + url, + mapped_url; + for (key in schema.definitions) { + if (schema.definitions.hasOwnProperty(key)) { + d = schema.definitions[key]; + url = d.$id || d.id; + if (url) { + mapped_url = convertUrlToAbsolute(g, schema_path, '#' + schema_path, window.location); + // XXX /? + mapped_url = mapped_url + 'definitions/' + key; + g.props.schemas[url] = mapped_url; + } + } + } + } + return RSVP.Queue() + .push(function () { + return [{ + title: schema.title, + ref: ref, + schema: schema, + schema_path: schema_path + }]; + }); + }; + + function schema_arr_marker(schema_arr) { + var i; + // XXX need cleanup false schema before + for (i = 0; i < schema_arr.length; i += 1) { + if (!schema_arr[i].schema.hasOwnProperty('const')) { + schema_arr[0].is_arr_of_const = false; + break; + } + if (i === schema_arr.length - 1) { + schema_arr[0].is_arr_of_const = true; + } + } + return schema_arr; + } + + function expandSchemaForField(g, schema, schema_path, for_required) { + var required_stack, + prev_field_path; + if (for_required) { + prev_field_path = getMaxPathInDict(g.props.schema_required_urls, schema_path); + required_stack = g.props.schema_required_urls[prev_field_path]; + } else { + required_stack = []; + } + g.props.schema_required_urls[schema_path] = required_stack; + return expandSchema(g, schema, schema_path) + .push(schema_arr_marker); + } + + rJS(window) + .ready(function () { + var g = this; + g.props = {}; + g.options = {}; + }) + .declareAcquiredMethod("resolveExternalReference", "resolveExternalReference") + .declareAcquiredMethod("notifyChange", "notifyChange") + .allowPublicAcquisition("rootNotifyChange", function () { + this.props.changed = true; + return this.notifyChange(); + }) + .declareAcquiredMethod("notifyValid", "notifyValid") + .declareAcquiredMethod("notifyInvalid", "notifyInvalid") + .allowPublicAcquisition("checkValidity", function (arr) { + return this.checkValidity(arr[0]); + }) + .declareMethod('checkValidity', function (json_document) { + // XXX need use local schema and local json document + // in every subgadget to take into account user anyOf choice + // and so more precisely point to issue + var g = this.props.form_gadget, + gadget = this; + return RSVP.Queue() + .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, + error_id, + error, + span, + tasks = [], + errors = [], + schema_resolve_errors = gadget.props.schema_resolve_errors, + errors_block = g.element.querySelector("div.error-block"); + + if (errors_block) { + errors_block.parentNode.removeChild(errors_block); + } + g.element.querySelectorAll(".error").forEach(function (error_message) { + error_message.textContent = ""; + error_message.removeAttribute("id"); + error_message.hidden = true; + }); + + g.element.querySelectorAll("div.error-input").forEach(function (div) { + div.setAttribute("class", ""); + }); + + for (i in schema_resolve_errors) { + if (schema_resolve_errors.hasOwnProperty(i)) { + errors.push(schema_resolve_errors[i]); + } + } + + errors = errors.concat(validation.errors); + errors = errors.concat(validation.missing); + + if (errors.length === 0) { + return gadget.notifyValid() + .push(function () { + return false; + }); + } + span = document.createElement("span"); + span.setAttribute("class", "error"); + span.textContent = "errors: "; + errors_block = document.createElement("div"); + errors_block.setAttribute("class", "subfield error-block"); + errors_block.appendChild(span); + + function print_error(error, errorUid, errorId) { + return function (element) { + var id = element.id, + error_message, + createTextNode = document.createTextNode.bind(document), + a = document.createElement("a"); + a.setAttribute("href", "#" + errorUid); + a.text = errorId; + element.setAttribute("class", "error-input"); + error_message = document.getElementById(id).querySelector(".error"); + error_message.appendChild(a); + error_message.setAttribute("id", errorUid); + if (error.message instanceof Array) { + error.message.forEach(function (x) { + error_message.appendChild(x); + }); + } else { + error_message.appendChild(createTextNode(error.message)); + } + error_message.appendChild(document.createElement("br")); + error_message.hidden = false; + + a = document.createElement("a"); + a.text = errorId; + a.setAttribute("data-error-link", "#" + errorUid); + a.setAttribute("class", "error-link"); + if (errorId !== "1") { + errors_block.appendChild(createTextNode(",")); + } + errors_block.appendChild(a); + }; + } + for (i = 0; i < errors.length; i += 1) { + error = errors[i]; + error_id = (i + 1).toString(); + tasks.push( + g.getElementByPath(error.dataPath || "/") + .push(print_error(error, "error" + error_id, error_id)) + ); + } + + return RSVP.Queue() + .push(function () { + return RSVP.all(tasks); + }) + .push(function () { + g.element.insertBefore(errors_block, g.element.firstChild); + }) + .push(gadget.notifyInvalid.bind(gadget)) + .push(function () { + return false; + }); + }); + }) + + .declareMethod('render', function (options) { + var z = { + key: options.key, + schema: JSON.stringify(options.schema), + saveOrigValue: options.saveOrigValue, + schema_url: options.schema_url, + editable: options.editable === undefined ? true : options.editable + }; + if (options.value !== undefined) { + z.value = JSON.stringify(options.value); + } + return this.changeState(z); + }) + .onStateChange(function () { + var g = this, + json_document = g.state.value, + schema; + if (json_document !== undefined) { + json_document = JSON.parse(json_document); + } + if (g.state.schema !== undefined) { + schema = JSON.parse(g.state.schema); + } + g.props.toplevel = true; + // contain map of current normalized schema + // json pointer and corresponding url + // it's need for schema uri computation + g.props.schema = {}; + g.props.schema_map = {}; + g.props.schemas = { + "http://json-schema.org/draft-04/schema": "json-schema/schema4.json", + "http://json-schema.org/draft-06/schema": "json-schema/schema6.json", + "http://json-schema.org/draft-07/schema": "json-schema/schema7.json", + "http://json-schema.org/schema": "json-schema/schema7.json" + }; + // schema_urls[path] = [ + // stack urls + // "url1", + // "url2" + // ] + // used for break soft circular relation of schemas + g.props.schema_urls = {}; + // schema_required_urls[path] = [ + // stack required urls, on every unrequired field stack begining from [] + // "url1", + // "url2" + // ] + // used for break hard circular relation of schemas + g.props.schema_required_urls = {}; + // schema_resolve_errors[schema_url] = { + // schemaPath: local_schema_path, + // message: error_message can be array containing dom elements + // } + g.props.schema_resolve_errors = {}; + return RSVP.Queue() + .push(function () { + if (!g.props.form_gadget) { + return g.declareGadget('jsonform/gadget_json_generated_form_child.html', + {scope: "j" + Math.random().toString(36).substr(2, 9)}) + .push(function (json_form_child) { + g.props.form_gadget = json_form_child; + g.element.appendChild(json_form_child.element); + }); + } + }) + .push(function () { + var schema_url, + queue; + if (schema !== undefined) { + schema_url = g.state.schema_url || + schema.$id || + schema.id || + window.location.toString(); + g.props.schema[""] = schema; + g.props.schema_map["/"] = schema_url; + g.props.schemas[schema_url] = schema; + queue = expandSchemaForField(g, schema, "/", true); + } else { + schema_url = g.state.schema_url || + (json_document && json_document.$schema); + if (schema_url) { + queue = loadJSONSchema(g, schema_url) + .push(schema_arr_marker); + } + } + if (queue) { + return queue; + } + return [{ + schema: true, + schema_path: "" + }]; + }) + .push(function (schema_arr) { + return g.props.form_gadget.renderForm({ + schema_arr: schema_arr, + document: json_document, + saveOrigValue: g.state.saveOrigValue, + required: true, + top: true + }); + }) + .push(function () { + return g.checkValidity(); + }) + .push(function () { + if (g.props.form_gadget.props.changed) { + g.notifyChange(); + } + }) + .push(function () { + return g; + }) + .push(undefined, function (err) { + console.log(err); + }); + }) + .allowPublicAcquisition("expandSchema", function (arr) { + return expandSchemaForField(this, arr[0], arr[1], arr[2]); + }) + .onLoop(function () { + var gadget = this; + if (this.props.changed) { + return this.checkValidity() + .push(function () { + gadget.props.changed = false; + }); + } + }, 500) + + .declareMethod('getContent', function () { + var g = this; + if (g.state.editable) { + return g.props.form_gadget.getContent() + .push(function (value) { + // Change the value state in place + // This will prevent the gadget to be changed if + // its parent call render with the same value + // (as ERP5 does in case of formulator error) + g.state.value = JSON.stringify(value); + if (g.state.key) { + var form_data = {}; + value = JSON.stringify(value); + form_data[g.state.key] = value; + return form_data; + } + return value; + }); + } + return {}; + }, {mutex: 'changestate'}); + +}(window, document, location, rJS, RSVP, jIO, tv4)); \ No newline at end of file diff --git a/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/jsonform.gadget.js.xml b/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/jsonform.gadget.js.xml new file mode 100644 index 0000000000000000000000000000000000000000..e74857f8664c0c0725dcf4aef13883b5bec60d70 --- /dev/null +++ b/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/jsonform.gadget.js.xml @@ -0,0 +1,28 @@ + + + + + + + + + + __name__ + jsonform.gadget.js + + + content_type + application/javascript + + + precondition + + + + title + jsonform.gadget.js + + + + + diff --git a/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/jsonform.xml b/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/jsonform.xml new file mode 100644 index 0000000000000000000000000000000000000000..e95a62ff6f96e2da59a2c32ec67923ea2f1e3c0a --- /dev/null +++ b/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/jsonform.xml @@ -0,0 +1,26 @@ + + + + + + + + + + _objects + + + + + + id + jsonform + + + title + + + + + + diff --git a/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/jsonform/gadget_json_generated_form_child.html.html b/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/jsonform/gadget_json_generated_form_child.html.html new file mode 100644 index 0000000000000000000000000000000000000000..6afe69360257c76d9cec43b6176517e555f48f8d --- /dev/null +++ b/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/jsonform/gadget_json_generated_form_child.html.html @@ -0,0 +1,17 @@ + + + + + + ERP5 + + + + + + + +
+
+ + diff --git a/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/jsonform/gadget_json_generated_form_child.html.xml b/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/jsonform/gadget_json_generated_form_child.html.xml new file mode 100644 index 0000000000000000000000000000000000000000..64890d6898d6c2fa153aabc23607e9d70a6d3c25 --- /dev/null +++ b/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/jsonform/gadget_json_generated_form_child.html.xml @@ -0,0 +1,28 @@ + + + + + + + + + + __name__ + gadget_json_generated_form_child.html + + + content_type + text/html + + + precondition + + + + title + gadget_json_generated_form_child.html + + + + + diff --git a/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/jsonform/gadget_json_generated_form_child.js.js b/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/jsonform/gadget_json_generated_form_child.js.js new file mode 100644 index 0000000000000000000000000000000000000000..15e21cd9f2c8f96be7a2ad6ca34840276d1b22bb --- /dev/null +++ b/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/jsonform/gadget_json_generated_form_child.js.js @@ -0,0 +1,2004 @@ +/*jslint nomen: true, maxlen: 200, indent: 2, maxerr: 100*/ +/*global window, document, URL, rJS, RSVP, jIO, tv4, location */ + +(function (window, document, location, rJS, RSVP, tv4) { + "use strict"; + var render_object; + + function deepEqual(x, y) { + if (x === y) { + return true; + } + if ((typeof x === "object" && x !== null) && (typeof y === "object" && y !== null)) { + if (Object.keys(x).length !== Object.keys(y).length) { + return false; + } + var prop; + for (prop in x) { + if (x.hasOwnProperty(prop)) { + if (y.hasOwnProperty(prop)) { + if (!deepEqual(x[prop], y[prop])) { + return false; + } + } else { + return false; + } + } + } + return true; + } + return false; + } + + function decodeJsonPointer(_str) { + // https://tools.ietf.org/html/rfc6901#section-5 + return _str.replace(/~1/g, '/').replace(/~0/g, '~'); + } + + function encodeJsonPointer(_str) { + // https://tools.ietf.org/html/rfc6901#section-5 + return _str.replace(/~/g, '~0').replace(/\//g, '~1'); + } + + function getDocumentType(doc) { + if (doc === undefined) { + return; + } + if (doc === null) { + return "null"; + } + if (doc instanceof Array) { + return "array"; + } + return typeof doc; + } + + function guessSchemaType(schema) { + var property_name; + for (property_name in schema) { + if (schema.hasOwnProperty(property_name)) { + switch (property_name) { + // case "allOf": + // case "anyOf": + // case "oneOf": + // return false; + case "required": + case "maxProperties": + case "minProperties": + case "additionalProperties": + case "properties": + case "patternProperties": + case "dependencies": + case "propertyNames": + return "object"; + case "additionalItems": + case "items": + case "maxItems": + case "minItems": + case "uniqueItems": + case "contains": + return "array"; + case "maxLength": + case "minLength": + case "pattern": + case "contentEncoding": + case "contentMediaType": + return "string"; + case "multipleOf": + case "maximum": + case "exclusiveMaximum": + case "minimum": + case "exclusiveMinimum": + return "number"; + } + } + } + } + + function createElement(type, props) { + var element = document.createElement(type), + key; + for (key in props) { + if (props.hasOwnProperty(key)) { + element.setAttribute(key, props[key]); + } + } + return element; + } + + function getDocumentSchema(doc) { + var type = getDocumentType(doc), + schema = { + type: type + }; + if (type === "array") { + schema.maxItems = 0; + } else if (type === "object") { + schema.additionalProperties = false; + } else { + schema.readOnly = true; + } + return schema; + } + + function render_enum(schema, json_document) { + var input = document.createElement("select"), + option, + i, + ser_value, + selected = false, + enum_arr = schema['enum']; + input.size = 1; + option = document.createElement("option"); + option.value = ""; + if (json_document === undefined) { + option.selected = true; + } + input.appendChild(option); + for (i = 0; i < enum_arr.length; i += 1) { + if (enum_arr.hasOwnProperty(i)) { + option = document.createElement("option"); + // XXX use number id for speedup + ser_value = JSON.stringify(enum_arr[i]); + option.value = ser_value; + if (typeof enum_arr[i] === "string") { + option.textContent = enum_arr[i]; + } else { + option.textContent = ser_value; + } + if (deepEqual(enum_arr[i], json_document)) { + option.selected = true; + selected = true; + } + input.appendChild(option); + } + } + if (json_document !== undefined && !selected) { + // save original json_document even if it + // not support with schema + // XXX element should be removed on first user interact + option = document.createElement("option"); + ser_value = JSON.stringify(json_document); + option.value = ser_value; + if (typeof json_document === "string") { + option.textContent = json_document; + } else { + option.textContent = ser_value; + } + option.selected = true; + input.appendChild(option); + } + return input; + } + + function render_enum_with_title(schema_arr, json_document, selected_schema) { + var input = document.createElement("select"), + option, + i, + ser_value, + selected = false; + input.size = 1; + if (json_document === undefined && selected_schema !== undefined) { + json_document = selected_schema.schema.const; + } + option = document.createElement("option"); + option.value = ""; + if (json_document === undefined) { + option.selected = true; + } + input.appendChild(option); + for (i = 0; i < schema_arr.length; i += 1) { + option = document.createElement("option"); + // XXX use number id for speedup + ser_value = JSON.stringify(schema_arr[i].schema.const); + option.value = ser_value; + if (schema_arr[i].schema.title) { + option.textContent = schema_arr[i].schema.title; + } else if (typeof schema_arr[i].schema.const === "string") { + option.textContent = schema_arr[i].schema.const; + } else { + option.textContent = ser_value; + } + if (deepEqual(schema_arr[i].schema.const, json_document)) { + option.selected = true; + selected = true; + } + input.appendChild(option); + } + if (json_document !== undefined && !selected) { + // save original json_document even if it + // not support with schema + // XXX element should be removed on first user interact + option = document.createElement("option"); + ser_value = JSON.stringify(json_document); + option.value = ser_value; + if (typeof json_document === "string") { + option.textContent = json_document; + } else { + option.textContent = ser_value; + } + option.selected = true; + input.appendChild(option); + } + return input; + } + + function render_boolean(json_document) { + var input, + schema_for_selection = { + type: "boolean", + enum: [true, false] + }; + // XXX change json_document on open is not correct @bk + if (json_document === "true") { + json_document = true; + } + if (json_document === "false") { + json_document = false; + } + input = render_enum(schema_for_selection, json_document); + input.setAttribute('data-json-type', "boolean"); + return input; + } + + function render_const(g, schema, json_document) { + var input = document.createElement("input"), + ser_doc = JSON.stringify(json_document), + ser_const = JSON.stringify(schema.const); + input.setAttribute('readonly', true); + if (json_document === undefined || deepEqual(json_document, schema.const)) { + if (json_document === undefined) { + g.props.changed = true; + } + input.setAttribute('data-origin-value', ser_const); + if (schema.title) { + input.value = schema.title; + } else { + input.value = ser_const; + } + } else { + input.value = ser_doc + ' ≠ ' + ser_const; + input.setAttribute('data-origin-value', ser_doc); + input.setAttribute('data-const-value', ser_const); + } + return input; + } + + function render_textarea(json_document, data_format) { + var input = document.createElement("textarea"); + if (json_document !== undefined) { + if (typeof json_document === "object") { + input.value = JSON.stringify(json_document, null, 2); + } else { + input.value = json_document; + } + } + input["data-format"] = data_format; + return input; + } + + function addSubForm(options) { + var input_element = options.element, + g = options.gadget, + property_name, + parent_path, + scope; + + scope = "j" + Math.random().toString(36).substr(2, 9); + if (options.parent_type !== "array") { + parent_path = options.path; + property_name = options.property_name; + if (!property_name) { + property_name = input_element.value; + } + if (!property_name) { + // XXX notify user + // you can't create property without property_name + return RSVP.Queue(); + } + if (g.props.objects[parent_path].hasOwnProperty(property_name) && g.props.objects[parent_path][property_name] !== "") { + // XXX notify user + // you can't create property with existed property_name + return RSVP.Queue(); + } + if (input_element) { + input_element.value = ""; + } + } + + return g.declareGadget('gadget_json_generated_form_child.html', {scope: scope}) + .push(function (form_gadget) { + form_gadget.element.setAttribute("data-gadget-parent-scope", + g.element.getAttribute("data-gadget-scope")); + if (options.parent_type !== "array") { + g.props.objects[parent_path][property_name] = scope; + form_gadget.element.setAttribute("data-json-parent", parent_path); + form_gadget.element.setAttribute("data-json-property-name", property_name); + } + return form_gadget.renderForm({ + type: options.type, + required: options.required, + delete_button: options.delete_button, + selected_schema: options.selected_schema, + schema_arr: options.schema_arr, + document: options.json_document, + display_label: options.parent_type !== "array", + saveOrigValue: g.props.saveOrigValue, + scope: scope + }) + .push(function () { + if (form_gadget.props.changed) { + g.props.changed = true; + } + return form_gadget.element; + }); + }); + } + + function expandItems(g, items, schema_path, minItems) { + if (!(items instanceof Array)) { + return g.expandSchema(items, schema_path, minItems !== 0); + } + var i, + tasks = []; + for (i = 0; i < items.length; i += 1) { + tasks.push(g.expandSchema(items[i], schema_path + '/' + i, i < minItems)); + } + return RSVP.Queue() + .push(function () { + return RSVP.all(tasks); + }); + } + + function expandProperties(g, properties, schema_path, required) { + var ret_obj = {}; + return RSVP.Queue() + .push(function () { + var property_name, + arr = []; + function addPropertyName(p_name) { + return function (schema_array) { + ret_obj[p_name] = schema_array; + }; + } + for (property_name in properties) { + if (properties.hasOwnProperty(property_name)) { + arr.push( + g.expandSchema( + properties[property_name], + schema_path + encodeJsonPointer(property_name), + required.indexOf(property_name) >= 0 + ) + .push(addPropertyName(property_name)) + ); + } + } + return RSVP.all(arr); + }) + .push(function () { + return ret_obj; + }); + } + + function checkSchemaArrOneChoise(schema_arr) { + if (schema_arr.length === 1) { + if (schema_arr[0].schema === true || + !(schema_arr[0].schema.hasOwnProperty('type') || + schema_arr[0].schema.hasOwnProperty('enum') || + schema_arr[0].schema.hasOwnProperty('const') + )) { + return false; + } + if (schema_arr[0].schema.type instanceof Array) { + return schema_arr[0].schema.type.length <= 1; + } + return true; + } + if (schema_arr[0].is_arr_of_const) { + return true; + } + return false; + } + + function checkSchemaSimpleType(schema_arr) { + // return true if rendering are not recursive + var schema = schema_arr[0].schema; + return schema_arr[0].is_arr_of_const || + schema.hasOwnProperty('const') || + [ + 'string', + 'integer', + 'number', + 'boolean', + 'null' + ].indexOf(schema.type) >= 0; + } + + function convertExpandedProperties2array(properties) { + var property_name, + arr = [], + i, + schema_array; + for (property_name in properties) { + if (properties.hasOwnProperty(property_name)) { + schema_array = properties[property_name]; + for (i = 0; i < schema_array.length; i += 1) { + // add propertyName to title + if (schema_array[i].title && schema_array.length > 1) { + schema_array[i].title = property_name + ' /' + schema_array[i].title; + } else if (schema_array[i].ref && schema_array.length > 1) { + schema_array[i].title = property_name + ' /' + schema_array[i].ref; + } else { + schema_array[i].title = property_name; + } + // add propertyName to schemaItem + schema_array[i].property_name = property_name; + arr.push(schema_array[i]); + } + } + } + return arr; + } + + function schemaArrFilteredByDocument(schema_arr, json_document) { + var x, + i, + errors, + error, + flag, + circular = schema_arr[0].circular, + ret_arr = [], + validation, + schema; + if (schema_arr.length === 1 || + schema_arr[0].is_arr_of_const) { + return schema_arr; + } + if (json_document !== undefined) { + for (x = 0; x < schema_arr.length; x += 1) { + schema = schema_arr[x].schema; + if (schema === true) { + flag = true; + } else if (schema === false) { + flag = false; + } else { + flag = tv4.validate(json_document, schema); + } + if (flag) { + ret_arr.push(schema_arr[x]); + } + } + if (ret_arr.length === 0) { + // currently try to find + // more compatible schema for current document + // XXX it may be need be more smart in future + // (every error has weigh, weigh depend from level...), + // may be not. + for (x = 0; x < schema_arr.length; x += 1) { + schema = schema_arr[x].schema; + if (schema !== false) { + validation = tv4.validateMultiple(json_document, schema); + errors = validation.errors; + flag = true; + for (i = 0; i < errors.length; i += 1) { + error = errors[i]; + if (error.code === 0 || // INVALID_TYPE + error.code === 13 || // NOT_PASSED + error.code === 14 // BOOLEAN_SCHEMA_FALSE + ) { + if (error.dataPath.split('/').length === 1) { + flag = false; + break; + } + } + if (error.code === 15 // CONST_NOT_EQUAL + ) { + // take in account errors only on fist level + if (error.dataPath.split('/').length <= 2) { + flag = false; + break; + } + } + } + if (flag) { + ret_arr = [schema_arr[x]]; + break; + } + } + } + } + if (ret_arr.length === 0) { + return schema_arr; + } + ret_arr[0].circular = circular; + return ret_arr; + } + return schema_arr; + } + + function render_schema_selector(gadget, title, schema_arr, event, rerender) { + return RSVP.Queue() + .push(function () { + var schema_alternatives = [], + schema_item, + description, + i, + z, + type; + function generateItemsForAny(property_name, schema_path) { + var desc, + types = [ + "string", + "number", + "boolean", + "array", + "object", + "null" + ], + ii; + if (property_name) { + desc = property_name + " # "; + } else { + desc = ""; + } + for (ii = 0; ii < types.length; ii += 1) { + schema_alternatives.push({ + title: desc + types[ii], + value: { + property_name: property_name, + schema: { type: types[ii] }, + schema_path: schema_path + } + }); + } + } + for (i = 0; i < schema_arr.length; i += 1) { + schema_item = schema_arr[i]; + description = schema_item.title; + if (schema_item.schema === true || + !(schema_item.schema.hasOwnProperty('type') || + schema_item.schema.hasOwnProperty('enum') || + schema_item.schema.hasOwnProperty('const'))) { + generateItemsForAny(schema_item.property_name, schema_item.schema_path); + } else if (getDocumentType(schema_item.schema.type) === "array") { + description = description || schema_item.schema.description; + for (z = 0; z < schema_item.schema.type.length; z += 1) { + type = schema_item.schema.type[z]; + schema_alternatives.push({ + title: description + ' # ' + type, + value: { + type: type, + property_name: schema_item.property_name, + schema_path: schema_item.schema_path, + schema: schema_item.schema + } + }); + } + } else { + description = description || + schema_item.schema.type || + schema_item.schema.description; + schema_alternatives.push({ + title: description, + value: { + property_name: schema_item.property_name, + schema_path: schema_item.schema_path, + schema: schema_item.schema + } + }); + } + } + return schema_alternatives; + }) + .push(function (schema_alternatives) { + var scope = 's' + Math.random().toString(36).substr(2, 9); + if (schema_alternatives.length > 1) { + return gadget.declareGadget("../gadget_html5_select.html", {scope: scope}) + .push(function (g) { + return RSVP.Queue() + .push(function () { + var x, + item_list = [[title, title]], + item; + if (rerender) { + return rerender(g, schema_alternatives); + } + for (x = 0; x < schema_alternatives.length; x += 1) { + item = schema_alternatives[x]; + item_list.push([item.title, x]); + } + return { + name: scope, + editable: true, + hidden: item_list.length === 0, + value: item_list[0][1], + item_list: item_list + }; + }) + .push(function (render_options) { + gadget.props.add_custom_data[scope] = { + element: g.element, + event: function () { + return g.getContent() + .push(function (value) { + return event(schema_alternatives[value[scope]].value); + }) + .push(function () { + if (rerender) { + return rerender(g, schema_alternatives); + } + return render_options; + }) + .push(function (render_options) { + return g.render(render_options); + }) + .push(function () { + return gadget.rootNotifyChange(); + }); + }, + rerender: function () { + return RSVP.Queue() + .push(function () { + if (rerender) { + return rerender(g, schema_alternatives); + } + return render_options; + }) + .push(function (render_options) { + return g.render(render_options); + }); + } + }; + return g.render(render_options); + }) + //not need if gadget_html5_select.render return element + .push(function () { + return g.element; + }); + }); + } + if (schema_alternatives.length === 1) { + return RSVP.Queue() + .push(function () { + if (rerender) { + return rerender(undefined, schema_alternatives); + } + return true; + }) + .push(function (ret) { + var input = document.createElement("button"); + input.setAttribute("class", "ui-btn-icon-notext ui-icon-plus"); + input.type = "button"; + input.title = title; + if (!ret) { + input.setAttribute("style", "display: none;"); + } + gadget.props.add_buttons.push({ + element: input, + event: function () { + return event(schema_alternatives[0].value) + .push(function () { + if (rerender) { + return rerender(undefined, schema_alternatives); + } + return true; + }) + .push(function (r) { + if (!r) { + input.setAttribute("style", "display: none;"); + } else { + input.removeAttribute("style"); + } + return gadget.rootNotifyChange(); + }); + }, + rerender: function () { + return RSVP.Queue() + .push(function () { + if (rerender) { + return rerender(undefined, schema_alternatives); + } + return true; + }) + .push(function (r) { + if (!r) { + input.setAttribute("style", "display: none;"); + } else { + input.removeAttribute("style"); + } + }); + } + }); + return input; + }); + } + return RSVP.Queue() + .push(function () { + return document.createElement("div"); + }); + }); + } + + function render_array(gadget, schema, json_document, div_input, path, schema_path) { + var input, + is_items_arr = schema.items instanceof Array, + minItems = schema.minItems || 0; + if (json_document instanceof Array && + json_document.length === 0) { + div_input.setAttribute("data-json-empty-array", "true"); + } + + function element_append(child) { + if (child) { + input.parentNode.insertBefore(child, input); + div_input.removeAttribute("data-json-empty-array"); + } + } + + function div_append(child) { + if (child) { + div_input.appendChild(child); + div_input.removeAttribute("data-json-empty-array"); + } + } + + // XXX add failback rendering if json_document not array + // input = render_textarea(schema, default_value, "array"); + return RSVP.Queue() + .push(function () { + return RSVP.all([ + expandItems(gadget, schema.items, schema_path + '/items', minItems), + gadget.expandSchema(schema.additionalItems, schema_path + '/additionalItems', false) + ]); + }) + .push(function (arr) { + var queue = RSVP.Queue(), + i, + schema_arr_arr = arr[0], + additionalItems = arr[1], + schema_arr = schema_arr_arr, + len = 0; + // XXX rewrite loading document for anyOf schema + if (json_document) { + for (i = 0; i < json_document.length; i = i + 1) { + if (is_items_arr) { + if (i < schema_arr_arr.length) { + schema_arr = schema_arr_arr[i]; + } else { + schema_arr = additionalItems; + } + } + queue + .push( + addSubForm.bind(gadget, { + gadget: gadget, + parent_type: 'array', + schema_arr: schema_arr, + json_document: json_document[i], + required: i < minItems + }) + ) + .push(div_append); + } + len = json_document.length; + } + + if (is_items_arr) { + if (minItems > len) { + for (i; i < (minItems - len); i += 1) { + if (i < schema_arr_arr.length) { + schema_arr = schema_arr_arr[i]; + } else { + schema_arr = additionalItems; + } + if (!checkSchemaArrOneChoise(schema_arr)) { + break; + } + queue + .push( + addSubForm.bind(gadget, { + gadget: gadget, + parent_type: 'array', + schema_arr: schema_arr, + required: true + }) + ) + .push(div_append); + } + } + if (i < schema_arr_arr.length) { + schema_arr = schema_arr_arr[i]; + } else { + schema_arr = additionalItems; + } + // XXX rerender on next item in schema.items + queue.push(render_schema_selector.bind(gadget, + gadget, "add item to array", + schema_arr, function (value) { + return addSubForm({ + gadget: gadget, + parent_type: 'array', + type: value.type, + selected_schema: value, + schema_arr: schema_arr + }) + .push(element_append); + })); + } else { + if (minItems > len && checkSchemaArrOneChoise(schema_arr)) { + for (i = 0; i < (minItems - len); i += 1) { + queue + .push( + addSubForm.bind(gadget, { + gadget: gadget, + parent_type: 'array', + schema_arr: schema_arr, + required: true + }) + ) + .push(div_append); + } + } + + queue.push(render_schema_selector.bind(gadget, + gadget, "add item to array", + schema_arr, function (value) { + return addSubForm({ + gadget: gadget, + parent_type: 'array', + type: value.type, + selected_schema: value, + schema_arr: schema_arr + }) + .push(element_append); + })); + } + return queue; + }) + .push(function (element) { + // var maxItems = schema.maxItems; + input = element; + // XXX update on every add/delete item + // input.hidden = maxItems !== undefined && json_document.length >= maxItems; + div_input.appendChild(input); + gadget.props.arrays[path] = div_input; + }); + } + + function render_field(gadget, property_name, path, schema_arr, json_document, root, options) { + var type, + div, + delete_button, + label, + label_text, + div_input, + span_info, + error_message, + input, + schema, + schema_path, + schema_ob, + first_path, + type_changed, + queue = RSVP.Queue(); + + if (options.selected_schema) { + schema_ob = options.selected_schema; + } else { + // XXX if (ret_arr.length > 1) notify user + schema_ob = schemaArrFilteredByDocument(schema_arr, json_document)[0]; + } + schema = schema_ob.schema; + schema_path = schema_ob.schema_path; + + if (schema_path === '/') { + schema_path = ''; + } + + options = options || {}; + type = options.type; + + if (path && property_name) { + first_path = path + encodeJsonPointer(property_name); + } else { + first_path = ""; + } + + if (schema === undefined) { + schema = getDocumentSchema(json_document); + } + + if (getDocumentType(schema.type) === "string") { + type = schema.type; + } else if (type === undefined && + json_document === undefined && + getDocumentType(schema.type) === "array") { + type = schema.type[0]; + } + if (["object", "array"].indexOf(type) >= 0 && + !(path !== "" && json_document === undefined) && + getDocumentType(json_document) !== type) { + if (gadget.props.saveOrigValue) { + // XXX is not useful for user + // only for tests + schema = { + const: json_document + }; + } else { + gadget.props.changed = true; + } + } + if (type === undefined && json_document !== undefined) { + type = getDocumentType(json_document); + } + + if (typeof type === "string") { + // it's only for simple types so we not use + // complex type detection + type_changed = json_document !== undefined && + typeof json_document !== type; + } + + // render input begin + if (!input && schema_arr[0].is_arr_of_const && schema_arr.length > 1) { + input = render_enum_with_title(schema_arr, json_document, options.selected_schema); + } + if (!input && schema.const !== undefined) { + input = render_const(gadget, schema, json_document); + } + if (!input && schema.enum !== undefined) { + input = render_enum(schema, json_document); + // XXX take in account existing type with enum + type_changed = false; + } + + if (!input && type === "null") { + input = render_const(gadget, {const: null}, json_document); + } + + if (!input && type === "boolean") { + input = render_boolean(json_document); + } + + if (!input && ["string", "integer", "number", "null"].indexOf(type) >= 0) { + if (schema.contentMediaType === "text/plain") { + input = render_textarea(json_document, "string"); + } else { + input = document.createElement("input"); + if (json_document !== undefined) { + if (typeof json_document === "object") { + input.value = JSON.stringify(json_document); + } else { + input.value = json_document; + } + } + + if (type === "integer" || type === "number") { + input.setAttribute("data-json-type", type); + if (json_document === undefined || json_document === null || + typeof json_document === "number") { + input.type = "number"; + } + if (type === "integer") { + input.setAttribute("step", "1"); + if (typeof json_document === "number" && + parseInt(json_document, 10) !== json_document) { + // original json_document contain float schema + // limit integer we can save original document + type_changed = true; + } + } + if (type === "number") { + input.setAttribute("step", "any"); + } + if (schema.multipleOf && schema.multipleOf >= 0) { + input.step = schema.multipleOf; + } + if (schema.minimum && + // step work from min value so we can't + // use min if min not multipleOf step + !(schema.multipleOf && + (schema.minimum % schema.multipleOf) !== 0)) { + input.min = schema.minimum; + } + if (schema.maximum) { + input.max = schema.maximum; + } + } else { + input.type = "text"; + if (schema.pattern) { + input.pattern = schema.pattern; + } else if (schema.minLength) { + // minLength absent in html5 so + // use pattern for this task + input.pattern = ".{" + schema.minLength + ",}"; + } + if (schema.maxLength) { + input.maxLength = schema.maxLength; + } + if (schema.format === 'uri') { + input.type = "url"; + input.spellcheck = false; + } + } + } + } + // render input end + + // html layout render begin + div = document.createElement("div"); + div.setAttribute("class", "jsonformfield ui-field-contain"); + if (schema.description) { + div.title = schema.description; + } + // if (property_name && !first_path) { + if (options.delete_button === true) { + delete_button = createElement("span", + {"class": "ui-btn-icon-top ui-icon-trash-o"} + ); + gadget.props.delete_button = delete_button; + div.appendChild(delete_button); + } else if (options.top !== true) { + if (options.required) { + delete_button = createElement("span", + {"class": "ui-btn-icon-top ui-icon-circle"} + ); + div.appendChild(delete_button); + } else { + delete_button = createElement("span"); + delete_button.innerHTML = " "; + div.appendChild(delete_button); + } + } + + label_text = [property_name, schema_ob.title] + .filter(function (v) { return v; }) + .join(" ") + // use non-breaking hyphen + .replace(/-/g, "‑"); + if (property_name || options.top) { + if (options.top) { + label = document.createElement("span"); + label.textContent = label_text; + root.appendChild(label); + } else { + label = document.createElement("label"); + label.textContent = label_text; + div.appendChild(label); + } + } + + div_input = document.createElement("div"); + div_input.setAttribute("id", gadget.element.getAttribute("data-gadget-scope") + first_path + '/'); + div_input.setAttribute("class", "input"); + + if (!input && type === "array") { + queue = render_array( + gadget, + schema, + json_document, + div_input, + first_path + '/', + schema_path + ); + } + + if (!input && type === "object") { + queue + .push(function () { + return render_object( + gadget, + schema, + json_document, + div_input, + first_path + '/', + schema_path + ); + }); + } + + if (input) { + // object and array excluded from + // gadget.props.inputs not contain values + gadget.props.inputs.push(input); + input.name = first_path; + input.required = options.required; + if (type_changed) { + input.setAttribute('data-origin-value', JSON.stringify(json_document)); + } + // XXX for gui + //input.setAttribute("class", "slapos-parameter"); + div_input.appendChild(input); + } else { + div.setAttribute("data-parent-scope", gadget.element.getAttribute("data-gadget-scope")); + div.setAttribute("data-json-path", first_path + '/'); + div.setAttribute("data-json-type", type); + if (options.required) { + div.setAttribute("data-json-required", "true"); + } + } + + if (schema.info !== undefined) { + span_info = document.createElement("span"); + span_info.textContent = schema.info; + div_input.appendChild(span_info); + } + error_message = document.createElement("span"); + error_message.setAttribute("class", "error"); + error_message.hidden = true; + div_input.appendChild(error_message); + div.appendChild(div_input); + // html layout render end + + return queue + .push(function () { + root.appendChild(div); + return div; + }); + } + + function render_object_additionalProperty(g, title, json_document, path, schema, schema_path, used, element_append) { + var div, + div_input, + input; + + div = document.createElement("div"); + div.setAttribute("class", "jsonformfield"); + // div.title = schema.description; + + div_input = document.createElement("div"); + div_input.setAttribute("class", "input"); + + input = document.createElement("input"); + input.type = "text"; + input.placeholder = "name of " + title; + div_input.appendChild(input); + + return g.expandSchema(schema, schema_path) + .push(function (schema_arr) { + var queue = RSVP.Queue(), + property_name; + for (property_name in json_document) { + if (json_document.hasOwnProperty(property_name) && !used.hasOwnProperty(property_name)) { + used[property_name] = ""; + queue + .push( + addSubForm.bind(g, { + gadget: g, + property_name: property_name, + path: path, + schema_arr: schema_arr, + json_document: json_document[property_name] + }) + ) + .push(element_append); + } + } + queue.push(function () { + return render_schema_selector(g, "add " + title, schema_arr, function (value) { + return addSubForm({ + gadget: g, + element: input, + path: path, + type: value.type, + schema_arr: [value] + }) + .push(element_append); + }); + }); + return queue; + }) + .push(function (input) { + div_input.appendChild(input); + div.appendChild(div_input); + return div; + }); + } + + function checkSchemaIsMetaSchema(schema) { + if (!schema) { + return false; + } + if (schema instanceof Array) { + var i, + sch; + for (i = 0; i < schema.length; i += 1) { + sch = schema[i].schema; + if (sch.hasOwnProperty("properties") && + sch.properties.hasOwnProperty("$schema")) { + return true; + } + } + return false; + } + return schema.hasOwnProperty("properties") && + schema.properties.hasOwnProperty("$schema"); + } + + function checkSchemaType(type, check) { + if (type instanceof Array) { + return type.indexOf(check) >= 0; + } + return type === check; + } + + // filter property for schema editor mode + function filterPropery(property_name, current_document) { + if (current_document.hasOwnProperty("type")) { + switch (property_name) { + case "allOf": + case "anyOf": + case "oneOf": + return false; + case "additionalItems": + case "items": + case "maxItems": + case "minItems": + case "uniqueItems": + case "contains": + if (!checkSchemaType(current_document.type, "array")) { + return false; + } + break; + case "required": + case "maxProperties": + case "minProperties": + case "additionalProperties": + case "properties": + case "patternProperties": + case "dependencies": + case "propertyNames": + if (!checkSchemaType(current_document.type, "object")) { + return false; + } + break; + case "maxLength": + case "minLength": + case "pattern": + case "contentEncoding": + case "contentMediaType": + if (!checkSchemaType(current_document.type, "string")) { + return false; + } + break; + case "multipleOf": + case "maximum": + case "exclusiveMaximum": + case "minimum": + case "exclusiveMinimum": + if (!(checkSchemaType(current_document.type, "number") || + checkSchemaType(current_document.type, "integer"))) { + return false; + } + break; + } + } else { + if (current_document.hasOwnProperty("allOf") || + current_document.hasOwnProperty("anyOf") || + current_document.hasOwnProperty("oneOf")) { + switch (property_name) { + case "type": + case "allOf": + case "anyOf": + case "oneOf": + return false; + } + } + switch (property_name) { + case "additionalItems": + case "items": + case "maxItems": + case "minItems": + case "uniqueItems": + case "required": + case "maxProperties": + case "minProperties": + case "additionalProperties": + case "properties": + case "patternProperties": + case "propertyNames": + case "maxLength": + case "minLength": + case "pattern": + case "multipleOf": + case "maximum": + case "exclusiveMaximum": + case "minimum": + case "exclusiveMinimum": + case "contains": + case "dependencies": + case "contentEncoding": + case "contentMediaType": + return false; + } + } + return true; + } + + render_object = function (g, schema, json_document, root, path, schema_path) { + var required = schema.required || [], + schema_editor = checkSchemaIsMetaSchema(schema), + used_properties = {}, + properties, + selector = {}; + + g.props.objects[path] = used_properties; + + function element_append(child) { + if (child) { + // insert additionalProperty before selector + selector.element.parentNode.insertBefore(child, selector.element); + } + } + + function root_append(child) { + root.appendChild(child); + } + + if (json_document === undefined) { + json_document = {}; + } + + return expandProperties(g, schema.properties, schema_path + '/properties/', required) + .push(function (ret) { + var schema_arr, + q = RSVP.Queue(), + filtered_schema_arr, + key; + properties = ret; + for (key in properties) { + if (properties.hasOwnProperty(key)) { + schema_arr = properties[key]; + filtered_schema_arr = schemaArrFilteredByDocument(schema_arr, json_document[key]); + // XXX need schema merge with patternProperties passed key + if (checkSchemaArrOneChoise(schema_arr)) { + if (required.indexOf(key) >= 0) { + used_properties[key] = false; + q.push(render_field.bind(g, g, key, path, + filtered_schema_arr, json_document[key], root, {required: true}) + ); + } + if (!used_properties.hasOwnProperty(key) && + !schema_editor && + (checkSchemaSimpleType(filtered_schema_arr) || !filtered_schema_arr[0].circular) + ) { + used_properties[key] = false; + q.push(render_field.bind(g, g, key, path, + filtered_schema_arr, json_document[key], root, { + required: false, + delete_button: false + })); + } + } + if (!used_properties.hasOwnProperty(key) && + json_document.hasOwnProperty(key)) { + used_properties[key] = ""; + q.push( + addSubForm.bind(g, { + gadget: g, + property_name: key, + path: path, + schema_arr: filtered_schema_arr, + json_document: json_document[key] + }) + ) + .push(root_append); + } + } + } + return q; + }) + .push(function () { + var schema_arr = convertExpandedProperties2array(properties); + return render_schema_selector(g, "add property", schema_arr, function (value) { + used_properties[value.property_name] = ""; + return addSubForm({ + gadget: g, + property_name: value.property_name, + path: path, + type: value.type, + schema_arr: [value] + }) + .push(function (element) { + var s_e = selector.element; + if (s_e) { + s_e.parentNode.insertBefore(element, s_e); + } + }); + }, + function (gadget_s, schema_alternatives) { + var x, + item_list = [["add property", "add property"]], + item, + current_document = g.props.current_document; + if (schema_alternatives) { + for (x = 0; x < schema_alternatives.length; x += 1) { + item = schema_alternatives[x]; + if (!used_properties.hasOwnProperty(item.value.property_name) && + !(schema_editor && current_document && + !filterPropery(item.value.property_name, current_document))) { + item_list.push([item.title, x]); + } + } + if (gadget_s) { + return { + name: gadget_s.element.getAttribute('data-gadget-scope'), + editable: true, + hidden: item_list.length === 1, + value: item_list[0][1], + item_list: item_list + }; + } + return item_list.length > 1; + } + }); + }) + .push(function (element) { + selector.element = element; + return root_append(element); + }) + .push(function () { + var queue = RSVP.Queue(), + key, + additionalProperties; + + // XXX for pattern properties needs schemas merge for + // all passed patterns + if (schema.patternProperties !== undefined) { + for (key in schema.patternProperties) { + if (schema.patternProperties.hasOwnProperty(key)) { + if (key === ".*" || + key === "^.*$" || + key === ".*$" || + key === "^.*" + ) { + // additionalProperties nether used in this case + additionalProperties = false; + } + queue + .push(render_object_additionalProperty.bind(g, + g, + key + " property", + json_document, + path, + schema.patternProperties[key], + schema_path + '/patternProperties/' + key, + used_properties, + element_append + )) + .push(root_append); + } + } + } + + if (additionalProperties === undefined) { + if (schema.additionalProperties === undefined) { + additionalProperties = true; + } else { + additionalProperties = schema.additionalProperties; + } + } + if (additionalProperties !== false) { + queue + .push(render_object_additionalProperty.bind(g, + g, + "additional property", + json_document, + path, + additionalProperties, + schema_path + '/additionalProperties', + used_properties, + element_append + )) + .push(root_append); + } + + return queue; + }) + .push(function () { + var key, + queue = RSVP.Queue(); + for (key in json_document) { + if (json_document.hasOwnProperty(key)) { + if (!used_properties.hasOwnProperty(key)) { + queue + .push( + addSubForm.bind(g, { + gadget: g, + property_name: key, + path: path, + schema_arr: [{ + schema: undefined, + schema_path: "" + }], + json_document: json_document[key] + }) + ) + .push(root_append); + } + } + } + return queue; + }); + }; + + function getFormValuesAsJSONDict(g) { + var multi_level_dict = {"": {}}, + is_empty = true, + scope, + options = g.props, + array, + path, + key, + i, + len, + json_dict = {}, + queue = RSVP.Queue(); + + function convertOnMultiLevel(d, key, value) { + var ii, + kk, + key_list = key.split("/"); + for (ii = 0; ii < key_list.length; ii += 1) { + kk = decodeJsonPointer(key_list[ii]); + if (ii === key_list.length - 1) { + if (value !== undefined) { + d[kk] = value; + is_empty = false; + } else { + return d[kk]; + } + } else { + if (!d.hasOwnProperty(kk)) { + if (value !== undefined) { + d[kk] = {}; + } else { + return; + } + } + d = d[kk]; + } + } + } + + function check_parent_path_not_empty(path) { + var key_list = path.split("/"), + parent_path = key_list.slice(0, key_list.length - 1).join("/"); + return convertOnMultiLevel(multi_level_dict, parent_path) !== undefined; + } + + function recursiveGetContent(scope, path) { + queue + .push(function () { + return g.getDeclaredGadget(scope); + }) + .push(function (gadget) { + return gadget.getContent(); + }) + .push(function (jdict) { + if (jdict === undefined) { + return; + } + convertOnMultiLevel(multi_level_dict, path, jdict); + }); + } + + function getContentAndPushArray(scope, parent_path) { + queue + .push(function () { + return g.getDeclaredGadget(scope); + }) + .push(function (gadget) { + return gadget.getContent(); + }) + .push(function (jdict) { + if (jdict === undefined) { + return; + } + var arr = convertOnMultiLevel(multi_level_dict, parent_path); + if (!(arr instanceof Array)) { + arr = []; + convertOnMultiLevel(multi_level_dict, parent_path, arr); + } + arr.push(jdict); + }); + } + + g.props.inputs.forEach(function (input) { + if (input.hasAttribute('data-origin-value')) { + json_dict[input.name] = JSON.parse(input.getAttribute('data-origin-value')); + } else { + if (input.value !== "") { + var type = input.getAttribute('data-json-type'); + if (input.tagName === "SELECT" && input.value) { + // selection used for enums + json_dict[input.name] = JSON.parse(input.value); + } else if (type === 'number') { + json_dict[input.name] = parseFloat(input.value); + } else if (type === "integer") { + json_dict[input.name] = parseInt(input.value, 10); + } else if (type === "boolean") { + if (input.value === "true") { + json_dict[input.name] = true; + } else if (input.value === "false") { + json_dict[input.name] = false; + } + } else if (input.tagName === "TEXTAREA") { + if (input["data-format"] === "string") { + json_dict[input.name] = input.value; + } else { + json_dict[input.name] = input.value.split('\n'); + } + } else { + json_dict[input.name] = input.value; + } + } + } + }); + for (path in json_dict) { + if (json_dict.hasOwnProperty(path)) { + convertOnMultiLevel(multi_level_dict, path, json_dict[path]); + } + } + + + for (path in options.arrays) { + if (options.arrays.hasOwnProperty(path)) { + array = options.arrays[path] + .querySelectorAll("div[data-gadget-parent-scope='" + g.element.getAttribute("data-gadget-scope") + "']"); + len = array.length; + if (len === 0 && + options.arrays[path].hasAttribute('data-json-empty-array')) { + convertOnMultiLevel(multi_level_dict, path.slice(0, -1), []); + } + for (i = 0; i < len; i = i + 1) { + getContentAndPushArray( + array[i].getAttribute('data-gadget-scope'), + // slice remove concluding '/' + path.slice(0, -1) + ); + } + } + } + + for (path in options.objects) { + if (options.objects.hasOwnProperty(path)) { + for (key in options.objects[path]) { + if (options.objects[path].hasOwnProperty(key)) { + scope = options.objects[path][key]; + if (scope) { + recursiveGetContent(scope, path + encodeJsonPointer(key)); + } + } + } + } + } + + return queue + .push(function () { + // set empty object/array for required properties/items + // if parent object/array existed + array = g.element + .querySelectorAll("div[data-parent-scope='" + + g.element.getAttribute("data-gadget-scope") + "']"); + for (i = 0; i < array.length; i += 1) { + path = array[i].getAttribute("data-json-path").slice(0, -1); + if (check_parent_path_not_empty(path) && + convertOnMultiLevel(multi_level_dict, path) === undefined) { + if (array[i].hasAttribute("data-json-required")) { + if (array[i].getAttribute("data-json-type") === "object") { + convertOnMultiLevel(multi_level_dict, path, {}); + } else { + convertOnMultiLevel(multi_level_dict, path, []); + } + } + } + } + + if (is_empty) { + switch (g.props.type) { + case "string": + return ""; + case "number": + return null; + case "boolean": + return null; + case "array": + return []; + case "object": + return {}; + default: + return; + } + } + return multi_level_dict[""]; + }); + } + + function getSubGadgetElement(g, scope) { + return g.element.querySelector("div[data-gadget-scope='" + scope + "']"); + } + + rJS(window) + .ready(function () { + var g = this; + g.props = {}; + g.options = {}; + }) + .declareAcquiredMethod("rootNotifyChange", "rootNotifyChange") + .declareAcquiredMethod("selfRemove", "deleteChildren") + .allowPublicAcquisition("deleteChildren", function (arr, scope) { + var g = this, + key, + i, + button_list = this.props.add_buttons, + objects = this.props.objects, + element = getSubGadgetElement(g, scope), + parent = element.getAttribute("data-json-parent"), + tasks = []; + if (objects.hasOwnProperty(parent)) { + parent = objects[parent]; + for (key in parent) { + if (parent.hasOwnProperty(key) && parent[key] === scope) { + delete parent[key]; + } + } + } + element.parentNode.removeChild(element); + for (key in g.props.add_custom_data) { + if (g.props.add_custom_data.hasOwnProperty(key)) { + tasks.push(g.props.add_custom_data[key].rerender()); + } + } + for (i = 0; i < button_list.length; i = i + 1) { + tasks.push(button_list[i].rerender()); + } + tasks.push(g.rootNotifyChange()); + return RSVP.Queue() + .push(function () { + return RSVP.all(tasks); + }); + }) + + .declareMethod('getElementByPath', function (data_path) { + var g = this, + array, + path, + scope, + key, + next_data_path, + slash_count = 0, + slash_count_next, + bingo, + idx, + options = g.props; + if (data_path !== "/") { + for (path in options.arrays) { + if (options.arrays.hasOwnProperty(path) && data_path.startsWith(path)) { + slash_count_next = path.split("/").length - 1; + if (slash_count_next > slash_count) { + bingo = path; + slash_count = slash_count_next; + } + } + } + if (bingo) { + array = options.arrays[bingo] + .querySelectorAll("div[data-gadget-parent-scope='" + g.element.getAttribute("data-gadget-scope") + "']"); + next_data_path = data_path.slice(bingo.length).split("/"); + idx = next_data_path[0]; + next_data_path = "/" + next_data_path.slice(1).join("/"); + return g.getDeclaredGadget(array[idx].getAttribute('data-gadget-scope')) + .push(function (gadget) { + return gadget.getElementByPath(next_data_path); + }); + } + + slash_count = 0; + for (path in options.objects) { + if (options.objects.hasOwnProperty(path) && data_path.startsWith(path)) { + slash_count_next = path.split("/").length - 1; + if (slash_count_next > slash_count) { + bingo = path; + slash_count = slash_count_next; + } + } + } + if (bingo) { + path = options.objects[bingo]; + key = decodeJsonPointer(data_path.slice(bingo.length).split('/')[0]); + if (path.hasOwnProperty(key)) { + next_data_path = data_path.slice(bingo.length + encodeJsonPointer(key).length); + if (!next_data_path) { + next_data_path = "/"; + } + scope = path[key]; + } + } + if (scope === false) { + // gadget for this element absent + // so find element in current gadget + return document.getElementById( + g.element.getAttribute("data-gadget-scope") + bingo + key + '/' + ); + } + if (scope) { + // get gadget by scope and use relative path for find element in gadget + return g.getDeclaredGadget(scope) + .push(function (gadget) { + return gadget.getElementByPath(next_data_path); + }); + } + } + return RSVP.Queue() + .push(function () { + return document.getElementById( + g.element.getAttribute("data-gadget-scope") + data_path + ); + }); + }) + .declareAcquiredMethod("notifyValid", "notifyValid") + .declareAcquiredMethod("notifyInvalid", "notifyInvalid") + .declareAcquiredMethod("checkValidity", "checkValidity") + + .allowPublicAcquisition("notifyValid", function () { + return true; + }) + .allowPublicAcquisition("notifyChange", function (arr, sub_scope) { + var g = this, + opt = arr[0], + event_object; + event_object = g.props.add_custom_data[sub_scope]; + if (event_object && opt.type === "change") { + return event_object.event(); + } + return g.rootNotifyChange(); + }) + .declareMethod('renderForm', function (options) { + var g = this, + property_name = g.element.getAttribute('data-json-property-name'), + schema = options.schema_arr !== undefined && options.schema_arr[0].schema, + root; + g.props.changed = false; + g.props.saveOrigValue = options.saveOrigValue; + g.props.inputs = []; + g.props.add_buttons = []; + g.props.add_custom_data = {}; + g.props.arrays = {}; + g.props.objects = {}; + g.props.path = options.path; // self gadget scope + if (!property_name || !options.display_label) { + property_name = ""; + } + root = g.element.querySelector('[data-json-path="/"]'); + if (!root) { + root = g.element; + } + if (options.delete_button === undefined) { + if (options.top) { + options.delete_button = false; + } else { + options.delete_button = !options.required; + } + } + if (!options.type && schema && !schema.type) { + options.type = guessSchemaType(schema); + } + // used for empty document generation + g.props.type = (schema && typeof schema.type === "string" && schema.type) || + options.type || getDocumentType(options.document); + while (root.firstChild) { + root.removeChild(root.firstChild); + } + if (checkSchemaIsMetaSchema(schema)) { + g.props.updatePropertySelectors = true; + g.props.current_document = options.document; + } + return render_field(g, property_name, "", options.schema_arr, + options.document, root, + { + type: options.type, + selected_schema: options.selected_schema, + required: options.required, + delete_button: options.delete_button, + top: options.top + }) + .push(function () { + return g.element; + }); + }) + + .declareAcquiredMethod("expandSchema", "expandSchema") + .onEvent('click', function (evt) { + if (evt.target === this.props.delete_button) { + return this.selfRemove(evt); + } + + var link = evt.target.getAttribute("data-error-link"), + button_list = this.props.add_buttons, + field_list = this.props.inputs, + input, + changed = false, + i; + if (link) { + location.href = link; + return; + } + + for (i = 0; i < button_list.length; i = i + 1) { + if (evt.target === button_list[i].element) { + return button_list[i].event(evt); + } + } + + for (i = 0; i < field_list.length; i = i + 1) { + if (evt.target === field_list[i]) { + input = evt.target; + if (input.hasAttribute('data-const-value')) { + input.value = input.getAttribute('data-const-value'); + input.setAttribute('data-origin-value', input.value); + input.removeAttribute('data-const-value'); + changed = true; + } + } + } + if (changed) { + return this.rootNotifyChange(); + } + }) + + .onEvent('input', function (evt) { + var gadget = this, + field_list = this.props.inputs, + i, + input, + changed = false; + // on form data field + for (i = 0; i < field_list.length; i = i + 1) { + if (evt.target === field_list[i]) { + input = evt.target; + if (input.hasAttribute('data-origin-value')) { + input.removeAttribute('data-origin-value'); + } + if (!input.hasAttribute("type")) { + if (["integer", "number"] + .indexOf(input.getAttribute('data-json-type')) >= 0) { + input.type = "number"; + } + } + changed = true; + } + } + if (changed) { + return gadget.rootNotifyChange(); + } + }) + + .declareMethod('getContent', function () { + var g = this; + return getFormValuesAsJSONDict(g) + .push(function (data) { + if (g.props.updatePropertySelectors) { + g.props.current_document = data; + var key, + tasks = []; + for (key in g.props.add_custom_data) { + if (g.props.add_custom_data.hasOwnProperty(key)) { + tasks.push(g.props.add_custom_data[key].rerender()); + } + } + if (tasks.length > 0) { + return RSVP.Queue() + .push(function () { + return RSVP.all(tasks); + }) + .push(function () { + return data; + }); + } + } + return data; + }); + }); + +}(window, document, location, rJS, RSVP, tv4)); \ No newline at end of file diff --git a/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/jsonform/gadget_json_generated_form_child.js.xml b/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/jsonform/gadget_json_generated_form_child.js.xml new file mode 100644 index 0000000000000000000000000000000000000000..00514ccee83e70a05fd60d7c9b6f7df00c2b4241 --- /dev/null +++ b/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/jsonform/gadget_json_generated_form_child.js.xml @@ -0,0 +1,28 @@ + + + + + + + + + + __name__ + gadget_json_generated_form_child.js + + + content_type + application/javascript + + + precondition + + + + title + gadget_json_generated_form_child.js + + + + + diff --git a/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/jsonform/tv4.js.js b/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/jsonform/tv4.js.js new file mode 100644 index 0000000000000000000000000000000000000000..820b4ab6fee5ba4ff2d7ca56d03a1e5242e7cb95 --- /dev/null +++ b/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/jsonform/tv4.js.js @@ -0,0 +1,1754 @@ +/* +Author: Geraint Luff and others +Year: 2013 + +This code is released into the "public domain" by its author(s). Anybody may use, alter and distribute the code without restriction. The author makes no guarantees, and takes no liability of any kind for use of this code. + +If you find a bug or make an improvement, it would be courteous to let the author know, but it is not compulsory. +*/ +/*global module, define*/ +/*jslint indent: 2, white: true*/ +/*jshint -W014: true, -W089: true, -W084: true, -W069: true*/ +(function (global, factory) { + "use strict"; + if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define([], factory); + } else if (typeof module !== 'undefined' && module.exports){ + // CommonJS. Define export. + module.exports = factory(); + } else { + // Browser globals + global.tv4 = factory(); + } +}(this, function () { +"use strict"; + +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys?redirectlocale=en-US&redirectslug=JavaScript%2FReference%2FGlobal_Objects%2FObject%2Fkeys +if (!Object.keys) { + Object.keys = (function () { + var hasOwnProperty = Object.prototype.hasOwnProperty, + hasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'), + dontEnums = [ + 'toString', + 'toLocaleString', + 'valueOf', + 'hasOwnProperty', + 'isPrototypeOf', + 'propertyIsEnumerable', + 'constructor' + ], + dontEnumsLength = dontEnums.length; + + return function (obj) { + if (typeof obj !== 'object' && typeof obj !== 'function' || obj === null) { + throw new TypeError('Object.keys called on non-object'); + } + + var result = []; + + for (var prop in obj) { + if (hasOwnProperty.call(obj, prop)) { + result.push(prop); + } + } + + if (hasDontEnumBug) { + for (var i=0; i < dontEnumsLength; i++) { + if (hasOwnProperty.call(obj, dontEnums[i])) { + result.push(dontEnums[i]); + } + } + } + return result; + }; + })(); +} +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create +if (!Object.create) { + Object.create = (function(){ + function F(){} + + return function(o){ + if (arguments.length !== 1) { + throw new Error('Object.create implementation only accepts one parameter.'); + } + F.prototype = o; + return new F(); + }; + })(); +} +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray?redirectlocale=en-US&redirectslug=JavaScript%2FReference%2FGlobal_Objects%2FArray%2FisArray +if(!Array.isArray) { + Array.isArray = function (vArg) { + return Object.prototype.toString.call(vArg) === "[object Array]"; + }; +} +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf?redirectlocale=en-US&redirectslug=JavaScript%2FReference%2FGlobal_Objects%2FArray%2FindexOf +if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) { + /*jslint bitwise: true */ + if (this === null) { + throw new TypeError(); + } + var t = Object(this); + var len = t.length >>> 0; + + if (len === 0) { + return -1; + } + var n = 0; + if (arguments.length > 1) { + n = Number(arguments[1]); + if (n !== n) { // shortcut for verifying if it's NaN + n = 0; + } else if (n !== 0 && n !== Infinity && n !== -Infinity) { + n = (n > 0 || -1) * Math.floor(Math.abs(n)); + } + } + if (n >= len) { + return -1; + } + var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0); + for (; k < len; k++) { + if (k in t && t[k] === searchElement) { + return k; + } + } + return -1; + }; +} + +// Grungey Object.isFrozen hack +if (!Object.isFrozen) { + Object.isFrozen = function (obj) { + var key = "tv4_test_frozen_key"; + while (obj.hasOwnProperty(key)) { + key += Math.random(); + } + try { + obj[key] = true; + delete obj[key]; + return false; + } catch (e) { + return true; + } + }; +} +// Based on: https://github.com/geraintluff/uri-templates, but with all the de-substitution stuff removed + +var uriTemplateGlobalModifiers = { + "+": true, + "#": true, + ".": true, + "/": true, + ";": true, + "?": true, + "&": true +}; +var uriTemplateSuffices = { + "*": true +}; + +function notReallyPercentEncode(string) { + return encodeURI(string).replace(/%25[0-9][0-9]/g, function (doubleEncoded) { + return "%" + doubleEncoded.substring(3); + }); +} + +function uriTemplateSubstitution(spec) { + var modifier = ""; + if (uriTemplateGlobalModifiers[spec.charAt(0)]) { + modifier = spec.charAt(0); + spec = spec.substring(1); + } + var separator = ""; + var prefix = ""; + var shouldEscape = true; + var showVariables = false; + var trimEmptyString = false; + if (modifier === '+') { + shouldEscape = false; + } else if (modifier === ".") { + prefix = "."; + separator = "."; + } else if (modifier === "/") { + prefix = "/"; + separator = "/"; + } else if (modifier === '#') { + prefix = "#"; + shouldEscape = false; + } else if (modifier === ';') { + prefix = ";"; + separator = ";"; + showVariables = true; + trimEmptyString = true; + } else if (modifier === '?') { + prefix = "?"; + separator = "&"; + showVariables = true; + } else if (modifier === '&') { + prefix = "&"; + separator = "&"; + showVariables = true; + } + + var varNames = []; + var varList = spec.split(","); + var varSpecs = []; + var varSpecMap = {}; + for (var i = 0; i < varList.length; i++) { + var varName = varList[i]; + var truncate = null; + if (varName.indexOf(":") !== -1) { + var parts = varName.split(":"); + varName = parts[0]; + truncate = parseInt(parts[1], 10); + } + var suffices = {}; + while (uriTemplateSuffices[varName.charAt(varName.length - 1)]) { + suffices[varName.charAt(varName.length - 1)] = true; + varName = varName.substring(0, varName.length - 1); + } + var varSpec = { + truncate: truncate, + name: varName, + suffices: suffices + }; + varSpecs.push(varSpec); + varSpecMap[varName] = varSpec; + varNames.push(varName); + } + var subFunction = function (valueFunction) { + var result = ""; + var startIndex = 0; + for (var i = 0; i < varSpecs.length; i++) { + var varSpec = varSpecs[i]; + var value = valueFunction(varSpec.name); + if (value === null || value === undefined || (Array.isArray(value) && value.length === 0) || (typeof value === 'object' && Object.keys(value).length === 0)) { + startIndex++; + continue; + } + if (i === startIndex) { + result += prefix; + } else { + result += (separator || ","); + } + if (Array.isArray(value)) { + if (showVariables) { + result += varSpec.name + "="; + } + for (var j = 0; j < value.length; j++) { + if (j > 0) { + result += varSpec.suffices['*'] ? (separator || ",") : ","; + if (varSpec.suffices['*'] && showVariables) { + result += varSpec.name + "="; + } + } + result += shouldEscape ? encodeURIComponent(value[j]).replace(/!/g, "%21") : notReallyPercentEncode(value[j]); + } + } else if (typeof value === "object") { + if (showVariables && !varSpec.suffices['*']) { + result += varSpec.name + "="; + } + var first = true; + for (var key in value) { + if (!first) { + result += varSpec.suffices['*'] ? (separator || ",") : ","; + } + first = false; + result += shouldEscape ? encodeURIComponent(key).replace(/!/g, "%21") : notReallyPercentEncode(key); + result += varSpec.suffices['*'] ? '=' : ","; + result += shouldEscape ? encodeURIComponent(value[key]).replace(/!/g, "%21") : notReallyPercentEncode(value[key]); + } + } else { + if (showVariables) { + result += varSpec.name; + if (!trimEmptyString || value !== "") { + result += "="; + } + } + if (varSpec.truncate !== null) { + value = value.substring(0, varSpec.truncate); + } + result += shouldEscape ? encodeURIComponent(value).replace(/!/g, "%21"): notReallyPercentEncode(value); + } + } + return result; + }; + subFunction.varNames = varNames; + return { + prefix: prefix, + substitution: subFunction + }; +} + +function UriTemplate(template) { + if (!(this instanceof UriTemplate)) { + return new UriTemplate(template); + } + var parts = template.split("{"); + var textParts = [parts.shift()]; + var prefixes = []; + var substitutions = []; + var varNames = []; + while (parts.length > 0) { + var part = parts.shift(); + var spec = part.split("}")[0]; + var remainder = part.substring(spec.length + 1); + var funcs = uriTemplateSubstitution(spec); + substitutions.push(funcs.substitution); + prefixes.push(funcs.prefix); + textParts.push(remainder); + varNames = varNames.concat(funcs.substitution.varNames); + } + this.fill = function (valueFunction) { + var result = textParts[0]; + for (var i = 0; i < substitutions.length; i++) { + var substitution = substitutions[i]; + result += substitution(valueFunction); + result += textParts[i + 1]; + } + return result; + }; + this.varNames = varNames; + this.template = template; +} +UriTemplate.prototype = { + toString: function () { + return this.template; + }, + fillFromObject: function (obj) { + return this.fill(function (varName) { + return obj[varName]; + }); + } +}; +var ValidatorContext = function ValidatorContext(parent, collectMultiple, errorReporter, checkRecursive, trackUnknownProperties) { + this.missing = []; + this.missingMap = {}; + this.formatValidators = parent ? Object.create(parent.formatValidators) : {}; + this.schemas = parent ? Object.create(parent.schemas) : {}; + this.collectMultiple = collectMultiple; + this.errors = []; + this.handleError = collectMultiple ? this.collectError : this.returnError; + if (checkRecursive) { + this.checkRecursive = true; + this.scanned = []; + this.scannedFrozen = []; + this.scannedFrozenSchemas = []; + this.scannedFrozenValidationErrors = []; + this.validatedSchemasKey = 'tv4_validation_id'; + this.validationErrorsKey = 'tv4_validation_errors_id'; + } + if (trackUnknownProperties) { + this.trackUnknownProperties = true; + this.knownPropertyPaths = {}; + this.unknownPropertyPaths = {}; + } + this.errorReporter = errorReporter || defaultErrorReporter('en'); + if (typeof this.errorReporter === 'string') { + throw new Error('debug'); + } + this.definedKeywords = {}; + if (parent) { + for (var key in parent.definedKeywords) { + this.definedKeywords[key] = parent.definedKeywords[key].slice(0); + } + } +}; +ValidatorContext.prototype.defineKeyword = function (keyword, keywordFunction) { + this.definedKeywords[keyword] = this.definedKeywords[keyword] || []; + this.definedKeywords[keyword].push(keywordFunction); +}; +ValidatorContext.prototype.createError = function (code, messageParams, dataPath, schemaPath, subErrors, data, schema) { + var error = new ValidationError(code, messageParams, dataPath, schemaPath, subErrors); + error.message = this.errorReporter(error, data, schema); + return error; +}; +ValidatorContext.prototype.returnError = function (error) { + return error; +}; +ValidatorContext.prototype.collectError = function (error) { + if (error) { + this.errors.push(error); + } + return null; +}; +ValidatorContext.prototype.prefixErrors = function (startIndex, dataPath, schemaPath) { + for (var i = startIndex; i < this.errors.length; i++) { + this.errors[i] = this.errors[i].prefixWith(dataPath, schemaPath); + } + return this; +}; +ValidatorContext.prototype.banUnknownProperties = function (data, schema) { + for (var unknownPath in this.unknownPropertyPaths) { + var error = this.createError(ErrorCodes.UNKNOWN_PROPERTY, {path: unknownPath}, unknownPath, "", null, data, schema); + var result = this.handleError(error); + if (result) { + return result; + } + } + return null; +}; + +ValidatorContext.prototype.addFormat = function (format, validator) { + if (typeof format === 'object') { + for (var key in format) { + this.addFormat(key, format[key]); + } + return this; + } + this.formatValidators[format] = validator; +}; +ValidatorContext.prototype.resolveRefs = function (schema, urlHistory) { + if (schema['$ref'] !== undefined) { + urlHistory = urlHistory || {}; + if (urlHistory[schema['$ref']]) { + return this.createError(ErrorCodes.CIRCULAR_REFERENCE, {urls: Object.keys(urlHistory).join(', ')}, '', '', null, undefined, schema); + } + urlHistory[schema['$ref']] = true; + schema = this.getSchema(schema['$ref'], urlHistory); + } + return schema; +}; +ValidatorContext.prototype.getSchema = function (url, urlHistory) { + var schema; + if (this.schemas[url] !== undefined) { + schema = this.schemas[url]; + return this.resolveRefs(schema, urlHistory); + } + var baseUrl = url; + var fragment = ""; + if (url.indexOf('#') !== -1) { + fragment = url.substring(url.indexOf("#") + 1); + baseUrl = url.substring(0, url.indexOf("#")); + } + if (typeof this.schemas[baseUrl] === 'object') { + schema = this.schemas[baseUrl]; + var pointerPath = decodeURIComponent(fragment); + if (pointerPath === "") { + return this.resolveRefs(schema, urlHistory); + } else if (pointerPath.charAt(0) !== "/") { + return undefined; + } + var parts = pointerPath.split("/").slice(1); + for (var i = 0; i < parts.length; i++) { + var component = parts[i].replace(/~1/g, "/").replace(/~0/g, "~"); + if (schema[component] === undefined) { + schema = undefined; + break; + } + schema = schema[component]; + } + if (schema !== undefined) { + return this.resolveRefs(schema, urlHistory); + } + } + if (this.missing[baseUrl] === undefined) { + this.missing.push(baseUrl); + this.missing[baseUrl] = baseUrl; + this.missingMap[baseUrl] = baseUrl; + } +}; +ValidatorContext.prototype.searchSchemas = function (schema, url) { + if (Array.isArray(schema)) { + for (var i = 0; i < schema.length; i++) { + this.searchSchemas(schema[i], url); + } + } else if (schema && typeof schema === "object") { + if (typeof schema.id === "string") { + if (isTrustedUrl(url, schema.id)) { + if (this.schemas[schema.id] === undefined) { + this.schemas[schema.id] = schema; + } + } + } + for (var key in schema) { + if (key !== "enum") { + if (typeof schema[key] === "object") { + this.searchSchemas(schema[key], url); + } else if (key === "$ref") { + var uri = getDocumentUri(schema[key]); + if (uri && this.schemas[uri] === undefined && this.missingMap[uri] === undefined) { + this.missingMap[uri] = uri; + } + } + } + } + } +}; +ValidatorContext.prototype.addSchema = function (url, schema) { + //overload + if (typeof url !== 'string' || typeof schema === 'undefined') { + if (typeof url === 'object' && typeof url.id === 'string') { + schema = url; + url = schema.id; + } + else { + return; + } + } + if (url === getDocumentUri(url) + "#") { + // Remove empty fragment + url = getDocumentUri(url); + } + this.schemas[url] = schema; + delete this.missingMap[url]; + // schema normalisation and downloading are disabled because already done by us. + // and current realisation not support CIRCULAR_REFERENCE + // normSchema(schema, url); + // this.searchSchemas(schema, url); +}; + +ValidatorContext.prototype.getSchemaMap = function () { + var map = {}; + for (var key in this.schemas) { + map[key] = this.schemas[key]; + } + return map; +}; + +ValidatorContext.prototype.getSchemaUris = function (filterRegExp) { + var list = []; + for (var key in this.schemas) { + if (!filterRegExp || filterRegExp.test(key)) { + list.push(key); + } + } + return list; +}; + +ValidatorContext.prototype.getMissingUris = function (filterRegExp) { + var list = []; + for (var key in this.missingMap) { + if (!filterRegExp || filterRegExp.test(key)) { + list.push(key); + } + } + return list; +}; + +ValidatorContext.prototype.dropSchemas = function () { + this.schemas = {}; + this.reset(); +}; +ValidatorContext.prototype.reset = function () { + this.missing = []; + this.missingMap = {}; + this.errors = []; +}; + +ValidatorContext.prototype.validateAllValidators = function validateAllValidators(data, schema, dataPointerPath) { + return this.validateBasic(data, schema, dataPointerPath) + || this.validateNumeric(data, schema, dataPointerPath) + || this.validateString(data, schema, dataPointerPath) + || this.validateArray(data, schema, dataPointerPath) + || this.validateObject(data, schema, dataPointerPath) + || this.validateCombinations(data, schema, dataPointerPath) + || this.validateHypermedia(data, schema, dataPointerPath) + || this.validateFormat(data, schema, dataPointerPath) + || this.validateDefinedKeywords(data, schema, dataPointerPath) + || null; +}; + +ValidatorContext.prototype.validateAll = function (data, schema, dataPathParts, schemaPathParts, dataPointerPath) { + var topLevel; + if (schema === undefined || schema === true) { + return null; + } else if (schema instanceof ValidationError) { + this.errors.push(schema); + return schema; + } + + var startErrorCount = this.errors.length; + var frozenIndex, scannedFrozenSchemaIndex = null, scannedSchemasIndex = null; + if (this.checkRecursive && data && typeof data === 'object') { + topLevel = !this.scanned.length; + if (data[this.validatedSchemasKey]) { + var schemaIndex = data[this.validatedSchemasKey].indexOf(schema); + if (schemaIndex !== -1) { + this.errors = this.errors.concat(data[this.validationErrorsKey][schemaIndex]); + return null; + } + } + if (Object.isFrozen(data)) { + frozenIndex = this.scannedFrozen.indexOf(data); + if (frozenIndex !== -1) { + var frozenSchemaIndex = this.scannedFrozenSchemas[frozenIndex].indexOf(schema); + if (frozenSchemaIndex !== -1) { + this.errors = this.errors.concat(this.scannedFrozenValidationErrors[frozenIndex][frozenSchemaIndex]); + return null; + } + } + } + this.scanned.push(data); + if (Object.isFrozen(data)) { + if (frozenIndex === -1) { + frozenIndex = this.scannedFrozen.length; + this.scannedFrozen.push(data); + this.scannedFrozenSchemas.push([]); + } + scannedFrozenSchemaIndex = this.scannedFrozenSchemas[frozenIndex].length; + this.scannedFrozenSchemas[frozenIndex][scannedFrozenSchemaIndex] = schema; + this.scannedFrozenValidationErrors[frozenIndex][scannedFrozenSchemaIndex] = []; + } else { + if (!data[this.validatedSchemasKey]) { + try { + Object.defineProperty(data, this.validatedSchemasKey, { + value: [], + configurable: true + }); + Object.defineProperty(data, this.validationErrorsKey, { + value: [], + configurable: true + }); + } catch (e) { + //IE 7/8 workaround + data[this.validatedSchemasKey] = []; + data[this.validationErrorsKey] = []; + } + } + scannedSchemasIndex = data[this.validatedSchemasKey].length; + data[this.validatedSchemasKey][scannedSchemasIndex] = schema; + data[this.validationErrorsKey][scannedSchemasIndex] = []; + } + } + + var errorCount = this.errors.length; + var error = this.validateAllValidators(data, schema, dataPointerPath); + + if (topLevel) { + while (this.scanned.length) { + var item = this.scanned.pop(); + delete item[this.validatedSchemasKey]; + } + this.scannedFrozen = []; + this.scannedFrozenSchemas = []; + } + + if (error || errorCount !== this.errors.length) { + while ((dataPathParts && dataPathParts.length) || (schemaPathParts && schemaPathParts.length)) { + var dataPart = (dataPathParts && dataPathParts.length) ? "" + dataPathParts.pop() : null; + var schemaPart = (schemaPathParts && schemaPathParts.length) ? "" + schemaPathParts.pop() : null; + if (error) { + error = error.prefixWith(dataPart, schemaPart); + } + this.prefixErrors(errorCount, dataPart, schemaPart); + } + } + + if (scannedFrozenSchemaIndex !== null) { + this.scannedFrozenValidationErrors[frozenIndex][scannedFrozenSchemaIndex] = this.errors.slice(startErrorCount); + } else if (scannedSchemasIndex !== null) { + data[this.validationErrorsKey][scannedSchemasIndex] = this.errors.slice(startErrorCount); + } + + return this.handleError(error); +}; +ValidatorContext.prototype.validateFormat = function (data, schema) { + if (typeof schema.format !== 'string' || !this.formatValidators[schema.format]) { + return null; + } + var errorMessage = this.formatValidators[schema.format].call(null, data, schema); + if (typeof errorMessage === 'string' || typeof errorMessage === 'number') { + return this.createError(ErrorCodes.FORMAT_CUSTOM, {message: errorMessage}, '', '/format', null, data, schema); + } else if (errorMessage && typeof errorMessage === 'object') { + return this.createError(ErrorCodes.FORMAT_CUSTOM, {message: errorMessage.message || "?"}, errorMessage.dataPath || '', errorMessage.schemaPath || "/format", null, data, schema); + } + return null; +}; +ValidatorContext.prototype.validateDefinedKeywords = function (data, schema, dataPointerPath) { + for (var key in this.definedKeywords) { + if (typeof schema[key] === 'undefined') { + continue; + } + var validationFunctions = this.definedKeywords[key]; + for (var i = 0; i < validationFunctions.length; i++) { + var func = validationFunctions[i]; + var result = func(data, schema[key], schema, dataPointerPath); + if (typeof result === 'string' || typeof result === 'number') { + return this.createError(ErrorCodes.KEYWORD_CUSTOM, {key: key, message: result}, '', '', null, data, schema).prefixWith(null, key); + } else if (result && typeof result === 'object') { + var code = result.code; + if (typeof code === 'string') { + if (!ErrorCodes[code]) { + throw new Error('Undefined error code (use defineError): ' + code); + } + code = ErrorCodes[code]; + } else if (typeof code !== 'number') { + code = ErrorCodes.KEYWORD_CUSTOM; + } + var messageParams = (typeof result.message === 'object') ? result.message : {key: key, message: result.message || "?"}; + var schemaPath = result.schemaPath || ("/" + key.replace(/~/g, '~0').replace(/\//g, '~1')); + return this.createError(code, messageParams, result.dataPath || null, schemaPath, null, data, schema); + } + } + } + return null; +}; + +function recursiveCompare(A, B) { + if (A === B) { + return true; + } + if (A && B && typeof A === "object" && typeof B === "object") { + if (Array.isArray(A) !== Array.isArray(B)) { + return false; + } else if (Array.isArray(A)) { + if (A.length !== B.length) { + return false; + } + for (var i = 0; i < A.length; i++) { + if (!recursiveCompare(A[i], B[i])) { + return false; + } + } + } else { + var key; + for (key in A) { + if (B[key] === undefined && A[key] !== undefined) { + return false; + } + } + for (key in B) { + if (A[key] === undefined && B[key] !== undefined) { + return false; + } + } + for (key in A) { + if (!recursiveCompare(A[key], B[key])) { + return false; + } + } + } + return true; + } + return false; +} + +ValidatorContext.prototype.validateBasic = function validateBasic(data, schema, dataPointerPath) { + if (schema === false && data !== undefined) { + return this.createError(ErrorCodes.BOOLEAN_SCHEMA_FALSE, {}, '', '', null, data, schema); + } + var error; + if (error = this.validateType(data, schema, dataPointerPath)) { + return error.prefixWith(null, "type"); + } + if (error = this.validateConst(data, schema, dataPointerPath)) { + return error.prefixWith(null, "const"); + } + if (error = this.validateEnum(data, schema, dataPointerPath)) { + return error.prefixWith(null, "type"); + } + return null; +}; + +ValidatorContext.prototype.validateType = function validateType(data, schema) { + if (schema.type === undefined) { + return null; + } + var dataType = typeof data; + if (data === null) { + dataType = "null"; + } else if (Array.isArray(data)) { + dataType = "array"; + } + var allowedTypes = schema.type; + if (!Array.isArray(allowedTypes)) { + allowedTypes = [allowedTypes]; + } + + for (var i = 0; i < allowedTypes.length; i++) { + var type = allowedTypes[i]; + if (type === dataType || (type === "integer" && dataType === "number" && (data % 1 === 0))) { + return null; + } + } + return this.createError(ErrorCodes.INVALID_TYPE, {type: dataType, expected: allowedTypes.join("/")}, '', '', null, data, schema); +}; + +ValidatorContext.prototype.validateConst = function validateConst(data, schema) { + if (schema.const === undefined || + recursiveCompare(data, schema.const)) { + return null; + } + return this.createError(ErrorCodes.CONST_NOT_EQUAL, {}, '', '', null, data, schema); +}; + +ValidatorContext.prototype.validateEnum = function validateEnum(data, schema) { + if (schema["enum"] === undefined) { + return null; + } + for (var i = 0; i < schema["enum"].length; i++) { + var enumVal = schema["enum"][i]; + if (recursiveCompare(data, enumVal)) { + return null; + } + } + return this.createError(ErrorCodes.ENUM_MISMATCH, {value: (typeof JSON !== 'undefined') ? JSON.stringify(data) : data}, '', '', null, data, schema); +}; + +ValidatorContext.prototype.validateNumeric = function validateNumeric(data, schema, dataPointerPath) { + return this.validateMultipleOf(data, schema, dataPointerPath) + || this.validateMinMax(data, schema, dataPointerPath) + || this.validateNaN(data, schema, dataPointerPath) + || null; +}; + +var CLOSE_ENOUGH_LOW = Math.pow(2, -51); +var CLOSE_ENOUGH_HIGH = 1 - CLOSE_ENOUGH_LOW; +ValidatorContext.prototype.validateMultipleOf = function validateMultipleOf(data, schema) { + var multipleOf = schema.multipleOf || schema.divisibleBy; + if (multipleOf === undefined) { + return null; + } + if (typeof data === "number") { + var remainder = (data/multipleOf)%1; + if (remainder >= CLOSE_ENOUGH_LOW && remainder < CLOSE_ENOUGH_HIGH) { + return this.createError(ErrorCodes.NUMBER_MULTIPLE_OF, {value: data, multipleOf: multipleOf}, '', '', null, data, schema); + } + } + return null; +}; + +ValidatorContext.prototype.validateMinMax = function validateMinMax(data, schema) { + if (typeof data !== "number") { + return null; + } + if (schema.minimum !== undefined) { + if (data < schema.minimum) { + return this.createError(ErrorCodes.NUMBER_MINIMUM, {value: data, minimum: schema.minimum}, '', '/minimum', null, data, schema); + } + if (schema.exclusiveMinimum === true && data === schema.minimum) { + return this.createError(ErrorCodes.NUMBER_MINIMUM_EXCLUSIVE, {value: data, minimum: schema.minimum}, '', '/exclusiveMinimum', null, data, schema); + } + } + if ((typeof schema.exclusiveMinimum === "number") && data <= schema.exclusiveMinimum) { + return this.createError(ErrorCodes.NUMBER_MINIMUM_EXCLUSIVE, {value: data, minimum: schema.exclusiveMinimum}, '', '/exclusiveMinimum', null, data, schema); + } + if (schema.maximum !== undefined) { + if (data > schema.maximum) { + return this.createError(ErrorCodes.NUMBER_MAXIMUM, {value: data, maximum: schema.maximum}, '', '/maximum', null, data, schema); + } + if (schema.exclusiveMaximum === true && data === schema.maximum) { + return this.createError(ErrorCodes.NUMBER_MAXIMUM_EXCLUSIVE, {value: data, maximum: schema.maximum}, '', '/exclusiveMaximum', null, data, schema); + } + } + if ((typeof schema.exclusiveMaximum === "number") && data >= schema.exclusiveMaximum) { + return this.createError(ErrorCodes.NUMBER_MAXIMUM_EXCLUSIVE, {value: data, maximum: schema.exclusiveMaximum}, '', '/exclusiveMaximum', null, data, schema); + } + return null; +}; + +ValidatorContext.prototype.validateNaN = function validateNaN(data, schema) { + if (typeof data !== "number") { + return null; + } + if (isNaN(data) === true || data === Infinity || data === -Infinity) { + return this.createError(ErrorCodes.NUMBER_NOT_A_NUMBER, {value: data}, '', '/type', null, data, schema); + } + return null; +}; + +ValidatorContext.prototype.validateString = function validateString(data, schema, dataPointerPath) { + return this.validateStringLength(data, schema, dataPointerPath) + || this.validateStringPattern(data, schema, dataPointerPath) + || null; +}; + +ValidatorContext.prototype.validateStringLength = function validateStringLength(data, schema) { + if (typeof data !== "string") { + return null; + } + if (schema.minLength !== undefined) { + if (data.length < schema.minLength) { + return this.createError(ErrorCodes.STRING_LENGTH_SHORT, {length: data.length, minimum: schema.minLength}, '', '/minLength', null, data, schema); + } + } + if (schema.maxLength !== undefined) { + if (data.length > schema.maxLength) { + return this.createError(ErrorCodes.STRING_LENGTH_LONG, {length: data.length, maximum: schema.maxLength}, '', '/maxLength', null, data, schema); + } + } + return null; +}; + +ValidatorContext.prototype.validateStringPattern = function validateStringPattern(data, schema) { + if (typeof data !== "string" || (typeof schema.pattern !== "string" && !(schema.pattern instanceof RegExp))) { + return null; + } + var regexp; + if (schema.pattern instanceof RegExp) { + regexp = schema.pattern; + } + else { + var body, flags = ''; + // Check for regular expression literals + // @see http://www.ecma-international.org/ecma-262/5.1/#sec-7.8.5 + var literal = schema.pattern.match(/^\/(.+)\/([img]*)$/); + if (literal) { + body = literal[1]; + flags = literal[2]; + } + else { + body = schema.pattern; + } + regexp = new RegExp(body, flags); + } + if (!regexp.test(data)) { + return this.createError(ErrorCodes.STRING_PATTERN, {pattern: schema.pattern}, '', '/pattern', null, data, schema); + } + return null; +}; + +ValidatorContext.prototype.validateArray = function validateArray(data, schema, dataPointerPath) { + if (!Array.isArray(data)) { + return null; + } + return this.validateArrayLength(data, schema, dataPointerPath) + || this.validateArrayUniqueItems(data, schema, dataPointerPath) + || this.validateArrayContains(data, schema, dataPointerPath) + || this.validateArrayItems(data, schema, dataPointerPath) + || null; +}; + +ValidatorContext.prototype.validateArrayLength = function validateArrayLength(data, schema) { + var error; + if (schema.minItems !== undefined) { + if (data.length < schema.minItems) { + error = this.createError(ErrorCodes.ARRAY_LENGTH_SHORT, {length: data.length, minimum: schema.minItems}, '', '/minItems', null, data, schema); + if (this.handleError(error)) { + return error; + } + } + } + if (schema.maxItems !== undefined) { + if (data.length > schema.maxItems) { + error = this.createError(ErrorCodes.ARRAY_LENGTH_LONG, {length: data.length, maximum: schema.maxItems}, '', '/maxItems', null, data, schema); + if (this.handleError(error)) { + return error; + } + } + } + return null; +}; + +ValidatorContext.prototype.validateArrayContains = function validateArrayContains(data, schema, dataPointerPath) { + if ((schema.contains === true && data.length > 0) || schema.contains === undefined) { + return null; + } + var error; + if (data.length === 0 || schema.contains === false) { + error = true; + } else { + for (var i = 0; i < data.length; i++) { + error = this.validateAllValidators(data[i], schema.contains, dataPointerPath + "/" + i); + if (!error) { + return null; + } + } + error = true; + } + if (error) { + return this.createError(ErrorCodes.ARRAY_CONTAINS, {}, '', '/contains', null, data, schema); + } + return null; +}; + +ValidatorContext.prototype.validateArrayUniqueItems = function validateArrayUniqueItems(data, schema) { + if (schema.uniqueItems) { + for (var i = 0; i < data.length; i++) { + for (var j = i + 1; j < data.length; j++) { + if (recursiveCompare(data[i], data[j])) { + var error = this.createError(ErrorCodes.ARRAY_UNIQUE, {match1: i, match2: j}, '', '/uniqueItems', null, data, schema); + if (this.handleError(error)) { + return error; + } + } + } + } + } + return null; +}; + +ValidatorContext.prototype.validateArrayItems = function validateArrayItems(data, schema, dataPointerPath) { + if (schema.items === undefined) { + return null; + } + var error, i; + if (Array.isArray(schema.items)) { + for (i = 0; i < data.length; i++) { + if (i < schema.items.length) { + if (error = this.validateAll(data[i], schema.items[i], [i], ["items", i], dataPointerPath + "/" + i)) { + return error; + } + } else if (schema.additionalItems !== undefined) { + if (typeof schema.additionalItems === "boolean") { + if (!schema.additionalItems) { + error = (this.createError(ErrorCodes.ARRAY_ADDITIONAL_ITEMS, {}, '/' + i, '/additionalItems', null, data, schema)); + if (this.handleError(error)) { + return error; + } + } + } else if (error = this.validateAll(data[i], schema.additionalItems, [i], ["additionalItems"], dataPointerPath + "/" + i)) { + return error; + } + } + } + } else { + for (i = 0; i < data.length; i++) { + if (error = this.validateAll(data[i], schema.items, [i], ["items"], dataPointerPath + "/" + i)) { + return error; + } + } + } + return null; +}; + +ValidatorContext.prototype.validateObject = function validateObject(data, schema, dataPointerPath) { + if (typeof data !== "object" || data === null || Array.isArray(data)) { + return null; + } + return this.validateObjectMinMaxProperties(data, schema, dataPointerPath) + || this.validateObjectRequiredProperties(data, schema, dataPointerPath) + || this.validateObjectProperties(data, schema, dataPointerPath) + || this.validateObjectDependencies(data, schema, dataPointerPath) + || null; +}; + +ValidatorContext.prototype.validateObjectMinMaxProperties = function validateObjectMinMaxProperties(data, schema) { + var keys = Object.keys(data); + var error; + if (schema.minProperties !== undefined) { + if (keys.length < schema.minProperties) { + error = this.createError(ErrorCodes.OBJECT_PROPERTIES_MINIMUM, {propertyCount: keys.length, minimum: schema.minProperties}, '', '/minProperties', null, data, schema); + if (this.handleError(error)) { + return error; + } + } + } + if (schema.maxProperties !== undefined) { + if (keys.length > schema.maxProperties) { + error = this.createError(ErrorCodes.OBJECT_PROPERTIES_MAXIMUM, {propertyCount: keys.length, maximum: schema.maxProperties}, '', '/maxProperties', null, data, schema); + if (this.handleError(error)) { + return error; + } + } + } + return null; +}; + +ValidatorContext.prototype.validateObjectRequiredProperties = function validateObjectRequiredProperties(data, schema) { + if (schema.required !== undefined) { + for (var i = 0; i < schema.required.length; i++) { + var key = schema.required[i]; + if (data[key] === undefined) { + var error = this.createError(ErrorCodes.OBJECT_REQUIRED, {key: key}, '', '/required/' + i, null, data, schema); + if (this.handleError(error)) { + return error; + } + } + } + } + return null; +}; + +ValidatorContext.prototype.validateObjectProperties = function validateObjectProperties(data, schema, dataPointerPath) { + var error; + for (var key in data) { + var keyPointerPath = dataPointerPath + "/" + key.replace(/~/g, '~0').replace(/\//g, '~1'); + var foundMatch = false; + if (schema.propertyNames !== undefined && schema.propertyNames !== true) { + if (error = this.validateAllValidators(key, schema.propertyNames, keyPointerPath)) { + return this.createError(ErrorCodes.OBJECT_PROPERTY_NAMES, {key: key, error: error.message}, '', '/propertyNames', null, data, schema).prefixWith(key, null); + } + } + if (schema.properties !== undefined && schema.properties[key] !== undefined) { + foundMatch = true; + if (error = this.validateAll(data[key], schema.properties[key], [key], ["properties", key], keyPointerPath)) { + return error; + } + } + if (schema.patternProperties !== undefined) { + for (var patternKey in schema.patternProperties) { + var regexp = new RegExp(patternKey); + if (regexp.test(key)) { + foundMatch = true; + if (error = this.validateAll(data[key], schema.patternProperties[patternKey], [key], ["patternProperties", patternKey], keyPointerPath)) { + return error; + } + } + } + } + if (!foundMatch) { + if (schema.additionalProperties !== undefined) { + if (this.trackUnknownProperties) { + this.knownPropertyPaths[keyPointerPath] = true; + delete this.unknownPropertyPaths[keyPointerPath]; + } + if (typeof schema.additionalProperties === "boolean") { + if (!schema.additionalProperties) { + error = this.createError(ErrorCodes.OBJECT_ADDITIONAL_PROPERTIES, {key: key}, '', '/additionalProperties', null, data, schema).prefixWith(key, null); + if (this.handleError(error)) { + return error; + } + } + } else { + if (error = this.validateAll(data[key], schema.additionalProperties, [key], ["additionalProperties"], keyPointerPath)) { + return error; + } + } + } else if (this.trackUnknownProperties && !this.knownPropertyPaths[keyPointerPath]) { + this.unknownPropertyPaths[keyPointerPath] = true; + } + } else if (this.trackUnknownProperties) { + this.knownPropertyPaths[keyPointerPath] = true; + delete this.unknownPropertyPaths[keyPointerPath]; + } + } + return null; +}; + +ValidatorContext.prototype.validateObjectDependencies = function validateObjectDependencies(data, schema, dataPointerPath) { + var error; + if (schema.dependencies !== undefined) { + for (var depKey in schema.dependencies) { + if (data[depKey] !== undefined) { + var dep = schema.dependencies[depKey]; + if (typeof dep === "string") { + if (data[dep] === undefined) { + error = this.createError(ErrorCodes.OBJECT_DEPENDENCY_KEY, {key: depKey, missing: dep}, '', '', null, data, schema).prefixWith(null, depKey).prefixWith(null, "dependencies"); + if (this.handleError(error)) { + return error; + } + } + } else if (Array.isArray(dep)) { + for (var i = 0; i < dep.length; i++) { + var requiredKey = dep[i]; + if (data[requiredKey] === undefined) { + error = this.createError(ErrorCodes.OBJECT_DEPENDENCY_KEY, {key: depKey, missing: requiredKey}, '', '/' + i, null, data, schema).prefixWith(null, depKey).prefixWith(null, "dependencies"); + if (this.handleError(error)) { + return error; + } + } + } + } else { + if (error = this.validateAll(data, dep, [], ["dependencies", depKey], dataPointerPath)) { + return error; + } + } + } + } + } + return null; +}; + +ValidatorContext.prototype.validateCombinations = function validateCombinations(data, schema, dataPointerPath) { + return this.validateAllOf(data, schema, dataPointerPath) + || this.validateAnyOf(data, schema, dataPointerPath) + || this.validateOneOf(data, schema, dataPointerPath) + || this.validateNot(data, schema, dataPointerPath) + || null; +}; + +ValidatorContext.prototype.validateAllOf = function validateAllOf(data, schema, dataPointerPath) { + if (schema.allOf === undefined) { + return null; + } + var error; + for (var i = 0; i < schema.allOf.length; i++) { + var subSchema = schema.allOf[i]; + if (error = this.validateAll(data, subSchema, [], ["allOf", i], dataPointerPath)) { + return error; + } + } + return null; +}; + +ValidatorContext.prototype.validateAnyOf = function validateAnyOf(data, schema, dataPointerPath) { + if (schema.anyOf === undefined) { + return null; + } + var errors = []; + var startErrorCount = this.errors.length; + var oldUnknownPropertyPaths, oldKnownPropertyPaths; + if (this.trackUnknownProperties) { + oldUnknownPropertyPaths = this.unknownPropertyPaths; + oldKnownPropertyPaths = this.knownPropertyPaths; + } + var errorAtEnd = true; + for (var i = 0; i < schema.anyOf.length; i++) { + if (this.trackUnknownProperties) { + this.unknownPropertyPaths = {}; + this.knownPropertyPaths = {}; + } + var subSchema = schema.anyOf[i]; + + var errorCount = this.errors.length; + var error = this.validateAll(data, subSchema, [], ["anyOf", i], dataPointerPath); + + if (error === null && errorCount === this.errors.length) { + this.errors = this.errors.slice(0, startErrorCount); + + if (this.trackUnknownProperties) { + for (var knownKey in this.knownPropertyPaths) { + oldKnownPropertyPaths[knownKey] = true; + delete oldUnknownPropertyPaths[knownKey]; + } + for (var unknownKey in this.unknownPropertyPaths) { + if (!oldKnownPropertyPaths[unknownKey]) { + oldUnknownPropertyPaths[unknownKey] = true; + } + } + // We need to continue looping so we catch all the property definitions, but we don't want to return an error + errorAtEnd = false; + continue; + } + + return null; + } + if (error) { + errors.push(error.prefixWith(null, "" + i).prefixWith(null, "anyOf")); + } + } + if (this.trackUnknownProperties) { + this.unknownPropertyPaths = oldUnknownPropertyPaths; + this.knownPropertyPaths = oldKnownPropertyPaths; + } + if (errorAtEnd) { + errors = errors.concat(this.errors.slice(startErrorCount)); + this.errors = this.errors.slice(0, startErrorCount); + return this.createError(ErrorCodes.ANY_OF_MISSING, {}, "", "/anyOf", errors, data, schema); + } +}; + +ValidatorContext.prototype.validateOneOf = function validateOneOf(data, schema, dataPointerPath) { + if (schema.oneOf === undefined) { + return null; + } + var validIndex = null; + var errors = []; + var startErrorCount = this.errors.length; + var oldUnknownPropertyPaths, oldKnownPropertyPaths; + if (this.trackUnknownProperties) { + oldUnknownPropertyPaths = this.unknownPropertyPaths; + oldKnownPropertyPaths = this.knownPropertyPaths; + } + for (var i = 0; i < schema.oneOf.length; i++) { + if (this.trackUnknownProperties) { + this.unknownPropertyPaths = {}; + this.knownPropertyPaths = {}; + } + var subSchema = schema.oneOf[i]; + + var errorCount = this.errors.length; + var error = this.validateAll(data, subSchema, [], ["oneOf", i], dataPointerPath); + + if (error === null && errorCount === this.errors.length) { + if (validIndex === null) { + validIndex = i; + } else { + this.errors = this.errors.slice(0, startErrorCount); + return this.createError(ErrorCodes.ONE_OF_MULTIPLE, {index1: validIndex, index2: i}, "", "/oneOf", null, data, schema); + } + if (this.trackUnknownProperties) { + for (var knownKey in this.knownPropertyPaths) { + oldKnownPropertyPaths[knownKey] = true; + delete oldUnknownPropertyPaths[knownKey]; + } + for (var unknownKey in this.unknownPropertyPaths) { + if (!oldKnownPropertyPaths[unknownKey]) { + oldUnknownPropertyPaths[unknownKey] = true; + } + } + } + } else if (error) { + errors.push(error); + } + } + if (this.trackUnknownProperties) { + this.unknownPropertyPaths = oldUnknownPropertyPaths; + this.knownPropertyPaths = oldKnownPropertyPaths; + } + if (validIndex === null) { + errors = errors.concat(this.errors.slice(startErrorCount)); + this.errors = this.errors.slice(0, startErrorCount); + return this.createError(ErrorCodes.ONE_OF_MISSING, {}, "", "/oneOf", errors, data, schema); + } else { + this.errors = this.errors.slice(0, startErrorCount); + } + return null; +}; + +ValidatorContext.prototype.validateNot = function validateNot(data, schema, dataPointerPath) { + if (schema.not === undefined) { + return null; + } + var oldErrorCount = this.errors.length; + var oldUnknownPropertyPaths, oldKnownPropertyPaths; + if (this.trackUnknownProperties) { + oldUnknownPropertyPaths = this.unknownPropertyPaths; + oldKnownPropertyPaths = this.knownPropertyPaths; + this.unknownPropertyPaths = {}; + this.knownPropertyPaths = {}; + } + var error = this.validateAll(data, schema.not, null, null, dataPointerPath); + var notErrors = this.errors.slice(oldErrorCount); + this.errors = this.errors.slice(0, oldErrorCount); + if (this.trackUnknownProperties) { + this.unknownPropertyPaths = oldUnknownPropertyPaths; + this.knownPropertyPaths = oldKnownPropertyPaths; + } + if (error === null && notErrors.length === 0) { + return this.createError(ErrorCodes.NOT_PASSED, {}, "", "/not", null, data, schema); + } + return null; +}; + +ValidatorContext.prototype.validateHypermedia = function validateCombinations(data, schema, dataPointerPath) { + if (!schema.links) { + return null; + } + var error; + for (var i = 0; i < schema.links.length; i++) { + var ldo = schema.links[i]; + if (ldo.rel === "describedby") { + var template = new UriTemplate(ldo.href); + var allPresent = true; + for (var j = 0; j < template.varNames.length; j++) { + if (!(template.varNames[j] in data)) { + allPresent = false; + break; + } + } + if (allPresent) { + var schemaUrl = template.fillFromObject(data); + var subSchema = {"$ref": schemaUrl}; + if (error = this.validateAll(data, subSchema, [], ["links", i], dataPointerPath)) { + return error; + } + } + } + } +}; + +// parseURI() and resolveUrl() are from https://gist.github.com/1088850 +// - released as public domain by author ("Yaffle") - see comments on gist + +function parseURI(url) { + var m = String(url).replace(/^\s+|\s+$/g, '').match(/^([^:\/?#]+:)?(\/\/(?:[^:@]*(?::[^:@]*)?@)?(([^:\/?#]*)(?::(\d*))?))?([^?#]*)(\?[^#]*)?(#[\s\S]*)?/); + // authority = '//' + user + ':' + pass '@' + hostname + ':' port + return (m ? { + href : m[0] || '', + protocol : m[1] || '', + authority: m[2] || '', + host : m[3] || '', + hostname : m[4] || '', + port : m[5] || '', + pathname : m[6] || '', + search : m[7] || '', + hash : m[8] || '' + } : null); +} + +function resolveUrl(base, href) {// RFC 3986 + + function removeDotSegments(input) { + var output = []; + input.replace(/^(\.\.?(\/|$))+/, '') + .replace(/\/(\.(\/|$))+/g, '/') + .replace(/\/\.\.$/, '/../') + .replace(/\/?[^\/]*/g, function (p) { + if (p === '/..') { + output.pop(); + } else { + output.push(p); + } + }); + return output.join('').replace(/^\//, input.charAt(0) === '/' ? '/' : ''); + } + + href = parseURI(href || ''); + base = parseURI(base || ''); + + return !href || !base ? null : (href.protocol || base.protocol) + + (href.protocol || href.authority ? href.authority : base.authority) + + removeDotSegments(href.protocol || href.authority || href.pathname.charAt(0) === '/' ? href.pathname : (href.pathname ? ((base.authority && !base.pathname ? '/' : '') + base.pathname.slice(0, base.pathname.lastIndexOf('/') + 1) + href.pathname) : base.pathname)) + + (href.protocol || href.authority || href.pathname ? href.search : (href.search || base.search)) + + href.hash; +} + +function getDocumentUri(uri) { + return uri.split('#')[0]; +} +function normSchema(schema, baseUri) { + if (schema && typeof schema === "object") { + if (baseUri === undefined) { + baseUri = schema.id; + } else if (typeof schema.id === "string") { + baseUri = resolveUrl(baseUri, schema.id); + schema.id = baseUri; + } + if (Array.isArray(schema)) { + for (var i = 0; i < schema.length; i++) { + normSchema(schema[i], baseUri); + } + } else { + if (typeof schema['$ref'] === "string") { + schema['$ref'] = resolveUrl(baseUri, schema['$ref']); + } + for (var key in schema) { + if (key !== "enum") { + normSchema(schema[key], baseUri); + } + } + } + } +} + +function defaultErrorReporter(language) { + language = language || 'en'; + + var errorMessages = languages[language]; + + return function (error) { + var messageTemplate = errorMessages[error.code] || ErrorMessagesDefault[error.code]; + if (typeof messageTemplate !== 'string') { + return "Unknown error code " + error.code + ": " + JSON.stringify(error.messageParams); + } + var messageParams = error.params; + // Adapted from Crockford's supplant() + return messageTemplate.replace(/\{([^{}]*)\}/g, function (whole, varName) { + var subValue = messageParams[varName]; + return typeof subValue === 'string' || typeof subValue === 'number' ? subValue : whole; + }); + }; +} + +var ErrorCodes = { + INVALID_TYPE: 0, + ENUM_MISMATCH: 1, + ANY_OF_MISSING: 10, + ONE_OF_MISSING: 11, + ONE_OF_MULTIPLE: 12, + NOT_PASSED: 13, + BOOLEAN_SCHEMA_FALSE: 14, + CONST_NOT_EQUAL: 15, + // Numeric errors + NUMBER_MULTIPLE_OF: 100, + NUMBER_MINIMUM: 101, + NUMBER_MINIMUM_EXCLUSIVE: 102, + NUMBER_MAXIMUM: 103, + NUMBER_MAXIMUM_EXCLUSIVE: 104, + NUMBER_NOT_A_NUMBER: 105, + // String errors + STRING_LENGTH_SHORT: 200, + STRING_LENGTH_LONG: 201, + STRING_PATTERN: 202, + // Object errors + OBJECT_PROPERTIES_MINIMUM: 300, + OBJECT_PROPERTIES_MAXIMUM: 301, + OBJECT_REQUIRED: 302, + OBJECT_ADDITIONAL_PROPERTIES: 303, + OBJECT_DEPENDENCY_KEY: 304, + OBJECT_PROPERTY_NAMES: 305, + // Array errors + ARRAY_LENGTH_SHORT: 400, + ARRAY_LENGTH_LONG: 401, + ARRAY_UNIQUE: 402, + ARRAY_ADDITIONAL_ITEMS: 403, + ARRAY_CONTAINS: 404, + // Custom/user-defined errors + FORMAT_CUSTOM: 500, + KEYWORD_CUSTOM: 501, + // Schema structure + CIRCULAR_REFERENCE: 600, + // Non-standard validation options + UNKNOWN_PROPERTY: 1000 +}; +var ErrorCodeLookup = {}; +for (var key in ErrorCodes) { + ErrorCodeLookup[ErrorCodes[key]] = key; +} +var ErrorMessagesDefault = { + INVALID_TYPE: "Invalid type: {type} (expected {expected})", + ENUM_MISMATCH: "No enum match for: {value}", + ANY_OF_MISSING: "Data does not match any schemas from \"anyOf\"", + ONE_OF_MISSING: "Data does not match any schemas from \"oneOf\"", + ONE_OF_MULTIPLE: "Data is valid against more than one schema from \"oneOf\": indices {index1} and {index2}", + NOT_PASSED: "Data matches schema from \"not\"", + BOOLEAN_SCHEMA_FALSE: "Schema does not allow any data", + CONST_NOT_EQUAL: "Data does not match schema.const", + // Numeric errors + NUMBER_MULTIPLE_OF: "Value {value} is not a multiple of {multipleOf}", + NUMBER_MINIMUM: "Value {value} is less than minimum {minimum}", + NUMBER_MINIMUM_EXCLUSIVE: "Value {value} is equal to exclusive minimum {minimum}", + NUMBER_MAXIMUM: "Value {value} is greater than maximum {maximum}", + NUMBER_MAXIMUM_EXCLUSIVE: "Value {value} is equal to exclusive maximum {maximum}", + NUMBER_NOT_A_NUMBER: "Value {value} is not a valid number", + // String errors + STRING_LENGTH_SHORT: "String is too short ({length} chars), minimum {minimum}", + STRING_LENGTH_LONG: "String is too long ({length} chars), maximum {maximum}", + STRING_PATTERN: "String does not match pattern: {pattern}", + // Object errors + OBJECT_PROPERTIES_MINIMUM: "Too few properties defined ({propertyCount}), minimum {minimum}", + OBJECT_PROPERTIES_MAXIMUM: "Too many properties defined ({propertyCount}), maximum {maximum}", + OBJECT_REQUIRED: "Missing required property: {key}", + OBJECT_ADDITIONAL_PROPERTIES: "Additional properties not allowed", + OBJECT_DEPENDENCY_KEY: "Dependency failed - key must exist: {missing} (due to key: {key})", + OBJECT_PROPERTY_NAMES: "Property name \"{key}\" does not match schema with error: {error}", + // Array errors + ARRAY_LENGTH_SHORT: "Array is too short ({length}), minimum {minimum}", + ARRAY_LENGTH_LONG: "Array is too long ({length}), maximum {maximum}", + ARRAY_UNIQUE: "Array items are not unique (indices {match1} and {match2})", + ARRAY_ADDITIONAL_ITEMS: "Additional items not allowed", + ARRAY_CONTAINS: "Array are not contain item matching schema.contains", + // Format errors + FORMAT_CUSTOM: "Format validation failed ({message})", + KEYWORD_CUSTOM: "Keyword failed: {key} ({message})", + // Schema structure + CIRCULAR_REFERENCE: "Circular $refs: {urls}", + // Non-standard validation options + UNKNOWN_PROPERTY: "Unknown property (not in schema)" +}; + +function ValidationError(code, params, dataPath, schemaPath, subErrors) { + Error.call(this); + if (code === undefined) { + throw new Error ("No error code supplied: " + schemaPath); + } + this.message = ''; + this.params = params; + this.code = code; + this.dataPath = dataPath || ""; + this.schemaPath = schemaPath || ""; + this.subErrors = subErrors || null; + + var err = new Error(this.message); + this.stack = err.stack || err.stacktrace; + if (!this.stack) { + /*jshint -W002: true*/ + try { + throw err; + } + catch(err) { + this.stack = err.stack || err.stacktrace; + } + } +} +ValidationError.prototype = Object.create(Error.prototype); +ValidationError.prototype.constructor = ValidationError; +ValidationError.prototype.name = 'ValidationError'; + +ValidationError.prototype.prefixWith = function (dataPrefix, schemaPrefix) { + if (dataPrefix !== null) { + dataPrefix = dataPrefix.replace(/~/g, "~0").replace(/\//g, "~1"); + this.dataPath = "/" + dataPrefix + this.dataPath; + } + if (schemaPrefix !== null) { + schemaPrefix = schemaPrefix.replace(/~/g, "~0").replace(/\//g, "~1"); + this.schemaPath = "/" + schemaPrefix + this.schemaPath; + } + if (this.subErrors !== null) { + for (var i = 0; i < this.subErrors.length; i++) { + this.subErrors[i].prefixWith(dataPrefix, schemaPrefix); + } + } + return this; +}; + +function isTrustedUrl(baseUrl, testUrl) { + if(testUrl.substring(0, baseUrl.length) === baseUrl){ + var remainder = testUrl.substring(baseUrl.length); + if ((testUrl.length > 0 && testUrl.charAt(baseUrl.length - 1) === "/") + || remainder.charAt(0) === "#" + || remainder.charAt(0) === "?") { + return true; + } + } + return false; +} + +var languages = {}; +function createApi(language) { + var globalContext = new ValidatorContext(); + var currentLanguage; + var customErrorReporter; + var api = { + setErrorReporter: function (reporter) { + if (typeof reporter === 'string') { + return this.language(reporter); + } + customErrorReporter = reporter; + return true; + }, + addFormat: function () { + globalContext.addFormat.apply(globalContext, arguments); + }, + language: function (code) { + if (!code) { + return currentLanguage; + } + if (!languages[code]) { + code = code.split('-')[0]; // fall back to base language + } + if (languages[code]) { + currentLanguage = code; + return code; // so you can tell if fall-back has happened + } + return false; + }, + addLanguage: function (code, messageMap) { + var key; + for (key in ErrorCodes) { + if (messageMap[key] && !messageMap[ErrorCodes[key]]) { + messageMap[ErrorCodes[key]] = messageMap[key]; + } + } + var rootCode = code.split('-')[0]; + if (!languages[rootCode]) { // use for base language if not yet defined + languages[code] = messageMap; + languages[rootCode] = messageMap; + } else { + languages[code] = Object.create(languages[rootCode]); + for (key in messageMap) { + if (typeof languages[rootCode][key] === 'undefined') { + languages[rootCode][key] = messageMap[key]; + } + languages[code][key] = messageMap[key]; + } + } + return this; + }, + freshApi: function (language) { + var result = createApi(); + if (language) { + result.language(language); + } + return result; + }, + validate: function (data, schema, checkRecursive, banUnknownProperties) { + var def = defaultErrorReporter(currentLanguage); + var errorReporter = customErrorReporter ? function (error, data, schema) { + return customErrorReporter(error, data, schema) || def(error, data, schema); + } : def; + var context = new ValidatorContext(globalContext, false, errorReporter, checkRecursive, banUnknownProperties); + if (typeof schema === "string") { + schema = {"$ref": schema}; + } + context.addSchema("", schema); + var error = context.validateAll(data, schema, null, null, ""); + if (!error && banUnknownProperties) { + error = context.banUnknownProperties(data, schema); + } + this.error = error; + this.missing = context.missing; + this.valid = (error === null); + + this.toString = function () { + if (this.error) { + return this.error.message; + } else { + return 'Object passed schema validation'; + } + }; + + return this.valid; + }, + validateResult: function () { + var result = {}; + this.validate.apply(result, arguments); + return result; + }, + validateMultiple: function (data, schema, checkRecursive, banUnknownProperties) { + var def = defaultErrorReporter(currentLanguage); + var errorReporter = customErrorReporter ? function (error, data, schema) { + return customErrorReporter(error, data, schema) || def(error, data, schema); + } : def; + var context = new ValidatorContext(globalContext, true, errorReporter, checkRecursive, banUnknownProperties); + if (typeof schema === "string") { + schema = {"$ref": schema}; + } + context.addSchema("", schema); + context.validateAll(data, schema, null, null, ""); + if (banUnknownProperties) { + context.banUnknownProperties(data, schema); + } + var result = {}; + result.errors = context.errors; + result.missing = context.missing; + result.valid = (result.errors.length === 0); + return result; + }, + addSchema: function () { + return globalContext.addSchema.apply(globalContext, arguments); + }, + getSchema: function () { + return globalContext.getSchema.apply(globalContext, arguments); + }, + getSchemaMap: function () { + return globalContext.getSchemaMap.apply(globalContext, arguments); + }, + getSchemaUris: function () { + return globalContext.getSchemaUris.apply(globalContext, arguments); + }, + getMissingUris: function () { + return globalContext.getMissingUris.apply(globalContext, arguments); + }, + dropSchemas: function () { + globalContext.dropSchemas.apply(globalContext, arguments); + }, + defineKeyword: function () { + globalContext.defineKeyword.apply(globalContext, arguments); + }, + defineError: function (codeName, codeNumber, defaultMessage) { + if (typeof codeName !== 'string' || !/^[A-Z]+(_[A-Z]+)*$/.test(codeName)) { + throw new Error('Code name must be a string in UPPER_CASE_WITH_UNDERSCORES'); + } + if (typeof codeNumber !== 'number' || codeNumber%1 !== 0 || codeNumber < 10000) { + throw new Error('Code number must be an integer > 10000'); + } + if (typeof ErrorCodes[codeName] !== 'undefined') { + throw new Error('Error already defined: ' + codeName + ' as ' + ErrorCodes[codeName]); + } + if (typeof ErrorCodeLookup[codeNumber] !== 'undefined') { + throw new Error('Error code already used: ' + ErrorCodeLookup[codeNumber] + ' as ' + codeNumber); + } + ErrorCodes[codeName] = codeNumber; + ErrorCodeLookup[codeNumber] = codeName; + ErrorMessagesDefault[codeName] = ErrorMessagesDefault[codeNumber] = defaultMessage; + for (var langCode in languages) { + var language = languages[langCode]; + if (language[codeName]) { + language[codeNumber] = language[codeNumber] || language[codeName]; + } + } + }, + reset: function () { + globalContext.reset(); + this.error = null; + this.missing = []; + this.valid = true; + }, + missing: [], + error: null, + valid: true, + normSchema: normSchema, + resolveUrl: resolveUrl, + getDocumentUri: getDocumentUri, + errorCodes: ErrorCodes + }; + api.language(language || 'en'); + return api; +} + +var tv4 = createApi(); +tv4.addLanguage('en-gb', ErrorMessagesDefault); + +//legacy property +tv4.tv4 = tv4; + +return tv4; // used by _header.js to globalise. + +})); diff --git a/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/jsonform/tv4.js.xml b/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/jsonform/tv4.js.xml new file mode 100644 index 0000000000000000000000000000000000000000..af0ecfd7f377f7057ef68765096c4c18edb93ebc --- /dev/null +++ b/bt5/erp5_json_form/SkinTemplateItem/portal_skins/erp5_json_form/jsonform/tv4.js.xml @@ -0,0 +1,28 @@ + + + + + + + + + + __name__ + tv4.js + + + content_type + application/javascript + + + precondition + + + + title + tv4.js + + + + + diff --git a/bt5/erp5_json_form/bt/comment b/bt5/erp5_json_form/bt/comment new file mode 100644 index 0000000000000000000000000000000000000000..58718d3dc1d73abb27a8c3784039598c75d61dc4 --- /dev/null +++ b/bt5/erp5_json_form/bt/comment @@ -0,0 +1,2 @@ +jsonform is available at: +https://lab.nexedi.com/bk/rjs_json_form \ No newline at end of file diff --git a/bt5/erp5_json_form/bt/dependency_list b/bt5/erp5_json_form/bt/dependency_list new file mode 100644 index 0000000000000000000000000000000000000000..db80eea7f74d654663adfb80d3bbfc5671366893 --- /dev/null +++ b/bt5/erp5_json_form/bt/dependency_list @@ -0,0 +1 @@ +erp5_view_style \ No newline at end of file diff --git a/bt5/erp5_json_form/bt/description b/bt5/erp5_json_form/bt/description new file mode 100644 index 0000000000000000000000000000000000000000..26febe9f6948c2eba71c398299b59e0bd8507dfb --- /dev/null +++ b/bt5/erp5_json_form/bt/description @@ -0,0 +1 @@ +Form generation based on http://json-schema.org/ \ No newline at end of file diff --git a/bt5/erp5_json_form/bt/maintainer_list b/bt5/erp5_json_form/bt/maintainer_list new file mode 100644 index 0000000000000000000000000000000000000000..452d733bbaba8b9500bef8451d20525ed4bfe18d --- /dev/null +++ b/bt5/erp5_json_form/bt/maintainer_list @@ -0,0 +1 @@ +bk \ No newline at end of file diff --git a/bt5/erp5_json_form/bt/template_format_version b/bt5/erp5_json_form/bt/template_format_version new file mode 100644 index 0000000000000000000000000000000000000000..56a6051ca2b02b04ef92d5150c9ef600403cb1de --- /dev/null +++ b/bt5/erp5_json_form/bt/template_format_version @@ -0,0 +1 @@ +1 \ No newline at end of file diff --git a/bt5/erp5_json_form/bt/template_skin_id_list b/bt5/erp5_json_form/bt/template_skin_id_list new file mode 100644 index 0000000000000000000000000000000000000000..d1e8bf126ce11a70b64e293c5314971a83a1288f --- /dev/null +++ b/bt5/erp5_json_form/bt/template_skin_id_list @@ -0,0 +1 @@ +erp5_json_form \ No newline at end of file diff --git a/bt5/erp5_json_form/bt/title b/bt5/erp5_json_form/bt/title new file mode 100644 index 0000000000000000000000000000000000000000..d1e8bf126ce11a70b64e293c5314971a83a1288f --- /dev/null +++ b/bt5/erp5_json_form/bt/title @@ -0,0 +1 @@ +erp5_json_form \ No newline at end of file diff --git a/bt5/erp5_json_form/bt/version b/bt5/erp5_json_form/bt/version new file mode 100644 index 0000000000000000000000000000000000000000..48360de846a2e022a0b981d250895f20d3480d34 --- /dev/null +++ b/bt5/erp5_json_form/bt/version @@ -0,0 +1 @@ +5.4.7 \ No newline at end of file diff --git a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_ojs_schema_panel.html.html b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_ojs_schema_panel.html.html new file mode 100644 index 0000000000000000000000000000000000000000..3861edf9913866a811d84f4dfcfda378c026c8be --- /dev/null +++ b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_ojs_schema_panel.html.html @@ -0,0 +1,73 @@ + + + + + + ERP5 Schema Panel + + + + + + + + + + + + + + + + + + + + + + +
+ + \ No newline at end of file diff --git a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_ojs_schema_panel.html.xml b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_ojs_schema_panel.html.xml new file mode 100644 index 0000000000000000000000000000000000000000..15273ceac57b1904cfe02a1ce22478abcbeffe9e --- /dev/null +++ b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_ojs_schema_panel.html.xml @@ -0,0 +1,321 @@ + + + + + + + + + + _Access_contents_information_Permission + + + Anonymous + Assignee + Assignor + Associate + Auditor + Manager + + + + + _Add_portal_content_Permission + + + Assignor + Manager + + + + + _Change_local_roles_Permission + + + Assignor + Manager + + + + + _Modify_portal_content_Permission + + + Manager + + + + + _View_Permission + + + Anonymous + Assignee + Assignor + Associate + Auditor + Manager + + + + + content_md5 + + + + + + content_type + text/html + + + default_reference + gadget_erp5_ojs_schema_panel.html + + + description + + + + + + id + gadget_erp5_ojs_schema_panel.html + + + language + + + + + + portal_type + Web Page + + + short_title + + + + + + version + + + + + + workflow_history + + AAAAAAAAAAI= + + + + + + + + + + + + + data + + + + document_publication_workflow + + AAAAAAAAAAM= + + + + edit_workflow + + AAAAAAAAAAQ= + + + + processing_status_workflow + + AAAAAAAAAAU= + + + + + + + + + + + + + + + + + + + action + publish + + + actor + zope + + + comment + + + + error_message + + + + time + + + + + + + + + + + 1528361035.49 + UTC + + + + + + + validation_state + published + + + + + + + + + + + + + + + + + action + edit + + + actor + zope + + + comment + + + + + + error_message + + + + serial + 968.3755.60725.37512 + + + state + current + + + time + + + + + + + + + + + 1528473429.83 + UTC + + + + + + + + + + + + + + + + + + + + + action + + + + + + actor + zope + + + comment + + + + error_message + + + + external_processing_state + empty + + + serial + 0.0.0.0 + + + time + + + + + + + + + + + 1528309343.96 + UTC + + + + + + + + + + + diff --git a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_ojs_schema_panel.js.js b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_ojs_schema_panel.js.js new file mode 100644 index 0000000000000000000000000000000000000000..f06cc1c595330c2c10f47540285477a03747376a --- /dev/null +++ b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_ojs_schema_panel.js.js @@ -0,0 +1,411 @@ +/*jslint nomen: true, indent: 2, maxerr: 3, unparam: true */ +/*global window, document, rJS, Handlebars, RSVP, Node, loopEventListener */ +(function (window, document, rJS, Handlebars, RSVP, Node, loopEventListener) { + "use strict"; + + ///////////////////////////////////////////////////////////////// + // temlates + ///////////////////////////////////////////////////////////////// + // Precompile templates while loading the first gadget instance + var gadget_klass = rJS(window), + template_element = gadget_klass.__template_element, + panel_template_header = Handlebars.compile(template_element + .getElementById("panel-template-header") + .innerHTML), + panel_template_body = Handlebars.compile(template_element + .getElementById("panel-template-body") + .innerHTML), + panel_template_body_list = Handlebars.compile(template_element + .getElementById("panel-template-body-list") + .innerHTML), + panel_template_body_desktop = Handlebars.compile(template_element + .getElementById("panel-template-body-desktop") + .innerHTML); + + gadget_klass + .setState({ + visible: false, + desktop: false + }) + ////////////////////////////////////////////// + // acquired method + ////////////////////////////////////////////// + .declareAcquiredMethod("getUrlFor", "getUrlFor") + .declareAcquiredMethod("translateHtml", "translateHtml") + .declareAcquiredMethod("translate", "translate") + .declareAcquiredMethod("redirect", "redirect") + .declareAcquiredMethod("updatePanel", "updatePanel") + .declareAcquiredMethod("getSetting", "getSetting") + .declareAcquiredMethod("setSetting", "setSetting") + .declareAcquiredMethod("getUrlParameter", "getUrlParameter") + .declareAcquiredMethod("jio_allDocs", "jio_allDocs") + + ///////////////////////////////////////////////////////////////// + // declared methods + ///////////////////////////////////////////////////////////////// + .declareMethod('toggle', function () { + return this.changeState({ + visible: !this.state.visible + }); + }) + .declareMethod('close', function () { + return this.changeState({ + visible: false + }); + }) + + .declareMethod('render', function (options) { + var erp5_document = options.erp5_document, + workflow_list, + view_list, + context = this; + if (erp5_document !== undefined) { + workflow_list = erp5_document._links.action_workflow || []; + view_list = erp5_document._links.action_object_view || []; + if (workflow_list.constructor !== Array) { + workflow_list = [workflow_list]; + } + if (view_list.constructor !== Array) { + view_list = [view_list]; + } + // Prevent has much as possible to modify the DOM panel + // stateChange prefer to compare strings + workflow_list = JSON.stringify(workflow_list); + view_list = JSON.stringify(view_list); + } + return RSVP.Queue() + .push(function () { + return RSVP.all([ + context.getSetting('jio_storage_name'), + context.getSetting('sync_reload', false) + ]); + }) + .push(function (result) { + var storage_name = result[0], + sync_reload = result[1]; + if (!storage_name || sync_reload) { + return ["[]", true]; + } + return RSVP.all([ + context.jio_allDocs({ + "query": '(portal_type:"JSON Schema") AND (NOT (title:""))', + "limit": [0, 31], + "select_list": ["title", "reference"], + "sort_on": [["title", "descending"]] + }) + .push(function (result) { + return JSON.stringify(result.data.rows); + }), + context.getSetting('developer_mode') + ]); + }) + .push(function (ret) { + var schema_list = ret[0], + developer_mode = ret[1]; + if (developer_mode === undefined) { + developer_mode = true; + } + if (developer_mode === "false") { + developer_mode = false; + } + return context.changeState({ + workflow_list: workflow_list, + view_list: view_list, + schema_list: schema_list, + global: true, + developer_mode: developer_mode + }); + }); + }) + + .onStateChange(function (modification_dict) { + var context = this, + gadget = this, + queue = new RSVP.Queue(), + tmp_element; + + if (modification_dict.hasOwnProperty("visible")) { + if (this.state.visible) { + if (!this.element.classList.contains('visible')) { + this.element.classList.toggle('visible'); + } + } else { + if (this.element.classList.contains('visible')) { + this.element.classList.remove('visible'); + } + } + } + + if (modification_dict.hasOwnProperty("global")) { + queue + .push(function () { + // XXX: Customize panel header! + return context.translateHtml( + panel_template_header() + + panel_template_body() + ); + }) + .push(function (my_translated_or_plain_html) { + tmp_element = document.createElement('div'); + tmp_element.innerHTML = my_translated_or_plain_html; + + return context.declareGadget('gadget_erp5_searchfield.html', { + scope: "erp5_searchfield", + element: tmp_element.querySelector('[data-gadget-scope="erp5_searchfield"]') + }); + }) + .push(function (search_gadget) { + return search_gadget.render({ + focus: false + }); + }) + .push(function () { + return context.declareGadget('gadget_erp5_field_multicheckbox.html', { + scope: "developer_mode", + element: tmp_element.querySelector('[data-gadget-scope="developer_mode"]') + }); + }) + .push(function () { + context.element.querySelector("div").appendChild(tmp_element); + return context.listenResize(); + }); + } + + if (modification_dict.hasOwnProperty("schema_list") || + modification_dict.hasOwnProperty("developer_mode")) { + queue + .push(function () { + function gen_element(element, title, css, accesskey) { + return context.getUrlFor(element) + .push(function (url) { + return { + title: title, + href: url, + icon_class: css, + accesskey: accesskey + }; + }); + } + var i, + row, + tasks = [], + schema_list = JSON.parse(context.state.schema_list); + if (context.state.developer_mode) { + tasks.push(gen_element({command: 'display', options: {page: "ojs_schema_document_list"}}, + "Schemas", "search", "s")); + } + for (i = 0; i < schema_list.length; i += 1) { + row = schema_list[i]; + tasks.push(gen_element({command: 'display', options: { + page: "ojs_schema_document_list", + portal_type: "JSON Document", + schema: row.id, + schema_title: row.value.title + }}, row.value.title, "search")); + } + tasks.push(gen_element({command: 'display', options: {page: "ojs_sync", 'auto_repair': true}}, + "Synchronize", "refresh")); + tasks.push(gen_element({command: 'display', options: {page: "ojs_configurator"}}, + "Storages", "dropbox")); + if (context.state.developer_mode) { + tasks.push(gen_element({command: 'index', options: {page: "ojs_zip_upload"}}, + "Upload", "upload")); + } + return RSVP.all(tasks); + }) + .push(function (result_list) { + return context.translateHtml( + panel_template_body_list(result_list) + ); + }) + + .push(function (result) { + context.element.querySelector("ul").innerHTML = result; + + // Update the checkbox field value + return RSVP.all([ + context.getDeclaredGadget("developer_mode"), + context.translate("Developer Mode") + ]); + }) + .push(function (result_list) { + var value = [], + developer_mode_gadget = result_list[0], + title = result_list[1]; + if (context.state.developer_mode) { + value = ['developer']; + } + return developer_mode_gadget.render({field_json: { + editable: true, + name: 'developer', + key: 'developer', + hidden: false, + items: [[title, 'developer']], + default: value + }}); + }); + } + + if ((this.state.global === true) && + (modification_dict.hasOwnProperty("desktop") || + modification_dict.hasOwnProperty("editable") || + modification_dict.hasOwnProperty("workflow_list") || + modification_dict.hasOwnProperty("view_list"))) { + if (!(this.state.desktop && (this.state.view_list !== undefined))) { + queue + .push(function () { + gadget.element.querySelector("dl").textContent = ''; + }); + } else { + queue + .push(function () { + var i = 0, + promise_list = [], + workflow_list = JSON.parse(gadget.state.workflow_list), + view_list = JSON.parse(gadget.state.view_list); + + for (i = 0; i < workflow_list.length; i += 1) { + promise_list.push( + gadget.getUrlFor({ + command: 'change', + options: { + view: workflow_list[i].href, + page: undefined + } + }) + ); + } + for (i = 0; i < view_list.length; i += 1) { + promise_list.push( + gadget.getUrlFor({ + command: 'change', + options: { + view: view_list[i].href, + page: undefined + } + }) + ); + } + return RSVP.all(promise_list); + }) + .push(function (result_list) { + var i, + result_workflow_list = [], + result_view_list = [], + workflow_list = JSON.parse(gadget.state.workflow_list), + view_list = JSON.parse(gadget.state.view_list); + + for (i = 0; i < workflow_list.length; i += 1) { + result_workflow_list.push({ + title: workflow_list[i].title, + href: result_list[i] + }); + } + for (i = 0; i < view_list.length; i += 1) { + result_view_list.push({ + title: view_list[i].title, + href: result_list[i + workflow_list.length] + }); + } + gadget.element.querySelector("dl").innerHTML = panel_template_body_desktop({ + workflow_list: result_workflow_list, + view_list: result_view_list + }); + }); + } + } + + return queue; + }) + + ///////////////////////////////////////////////////////////////// + // declared services + ///////////////////////////////////////////////////////////////// + .onEvent('click', function (evt) { + if ((evt.target.nodeType === Node.ELEMENT_NODE) && + (evt.target.tagName === 'BUTTON')) { + return this.toggle(); + } + }, false, false) + + .declareJob('listenResize', function () { + // resize should be only trigger after the render method + // as displaying the panel rely on external gadget (for translation for example) + var result, + event, + context = this; + function extractSizeAndDispatch() { + if (window.matchMedia("(min-width: 85em)").matches) { + return context.changeState({ + desktop: true + }); + } + return context.changeState({ + desktop: false + }); + } + result = loopEventListener(window, 'resize', false, + extractSizeAndDispatch); + event = document.createEvent("Event"); + event.initEvent('resize', true, true); + window.dispatchEvent(event); + return result; + }) + + .allowPublicAcquisition('notifyChange', function (argument_list, scope) { + if (scope === 'developer_mode' && argument_list[0] === "change") { + var context = this; + return context.getDeclaredGadget('developer_mode') + .push(function (gadget) { + return gadget.getContent(); + }) + .push(function (result) { + var value = "false"; + if (result.developer.length === 1) { + value = true; + } + return context.setSetting("developer_mode", value); + }) + .push(function () { + return context.updatePanel({}); + }); + } + // Typing a search query should not modify the header status + return; + }, {mutex: 'changestate'}) + .allowPublicAcquisition('notifyValid', function () { + // Typing a search query should not modify the header status + return; + }) + + .onEvent('submit', function () { + var gadget = this; + + return gadget.getDeclaredGadget("erp5_searchfield") + .push(function (search_gadget) { + return search_gadget.getContent(); + }) + .push(function (data) { + var options = { + page: "ojs_schema_document_list" + }; + if (data.search) { + options.extended_search = data.search; + } + // Remove focus from the search field + document.activeElement.blur(); + return gadget.redirect({command: 'display', options: options}); + }); + + }, false, true) + + .onEvent('blur', function (evt) { + // XXX Horrible hack to clear the search when focus is lost + // This does not follow renderJS design, as a gadget should not touch + // another gadget content + if (evt.target.type === 'search') { + evt.target.value = ""; + } + }, true, false); + +}(window, document, rJS, Handlebars, RSVP, Node, loopEventListener)); diff --git a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_ojs_schema_panel.js.xml b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_ojs_schema_panel.js.xml new file mode 100644 index 0000000000000000000000000000000000000000..9082b81ed85f85e47355819479bbf9429ea28cc0 --- /dev/null +++ b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_ojs_schema_panel.js.xml @@ -0,0 +1,321 @@ + + + + + + + + + + _Access_contents_information_Permission + + + Anonymous + Assignee + Assignor + Associate + Auditor + Manager + + + + + _Add_portal_content_Permission + + + Assignor + Manager + + + + + _Change_local_roles_Permission + + + Assignor + Manager + + + + + _Modify_portal_content_Permission + + + Manager + + + + + _View_Permission + + + Anonymous + Assignee + Assignor + Associate + Auditor + Manager + + + + + content_md5 + + + + + + content_type + text/javascript + + + default_reference + gadget_erp5_ojs_schema_panel.js + + + description + + + + + + id + gadget_erp5_ojs_schema_panel.js + + + language + + + + + + portal_type + Web Script + + + short_title + + + + + + version + + + + + + workflow_history + + AAAAAAAAAAI= + + + + + + + + + + + + + data + + + + document_publication_workflow + + AAAAAAAAAAM= + + + + edit_workflow + + AAAAAAAAAAQ= + + + + processing_status_workflow + + AAAAAAAAAAU= + + + + + + + + + + + + + + + + + + + action + publish + + + actor + zope + + + comment + + + + error_message + + + + time + + + + + + + + + + + 1528361027.63 + UTC + + + + + + + validation_state + published + + + + + + + + + + + + + + + + + action + edit + + + actor + zope + + + comment + + + + + + error_message + + + + serial + 968.5915.6298.25190 + + + state + current + + + time + + + + + + + + + + + 1528741133.22 + UTC + + + + + + + + + + + + + + + + + + + + + action + + + + + + actor + zope + + + comment + + + + error_message + + + + external_processing_state + empty + + + serial + 0.0.0.0 + + + time + + + + + + + + + + + 1528310368.01 + UTC + + + + + + + + + + + diff --git a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_ojs_schema_router.html.html b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_ojs_schema_router.html.html new file mode 100644 index 0000000000000000000000000000000000000000..e9e8820e0649ed4ba8b151fd6bc716633695c50d --- /dev/null +++ b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_ojs_schema_router.html.html @@ -0,0 +1,26 @@ + + + + + + OfficeJS Schema Router Gadget + + + + + + + + + + + + + + + + + +
+ + \ No newline at end of file diff --git a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_ojs_schema_router.html.xml b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_ojs_schema_router.html.xml new file mode 100644 index 0000000000000000000000000000000000000000..fcfa3b653244801661a63586fd53149843df11df --- /dev/null +++ b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_ojs_schema_router.html.xml @@ -0,0 +1,325 @@ + + + + + + + + + + _Access_contents_information_Permission + + + Anonymous + Assignee + Assignor + Associate + Auditor + Manager + + + + + _Add_portal_content_Permission + + + Assignor + Manager + + + + + _Change_local_roles_Permission + + + Assignor + Manager + + + + + _Modify_portal_content_Permission + + + Manager + + + + + _View_Permission + + + Anonymous + Assignee + Assignor + Associate + Auditor + Manager + + + + + content_md5 + + + + + + content_type + text/html + + + default_reference + gadget_erp5_ojs_schema_router.html + + + description + + + + + + id + gadget_erp5_ojs_schema_router.html + + + language + + + + + + portal_type + Web Page + + + short_title + + + + + + title + gadget_erp5_ojs_schema_router.html + + + version + + + + + + workflow_history + + AAAAAAAAAAI= + + + + + + + + + + + + + data + + + + document_publication_workflow + + AAAAAAAAAAM= + + + + edit_workflow + + AAAAAAAAAAQ= + + + + processing_status_workflow + + AAAAAAAAAAU= + + + + + + + + + + + + + + + + + + + action + publish + + + actor + zope + + + comment + + + + error_message + + + + time + + + + + + + + + + + 1528361019.52 + UTC + + + + + + + validation_state + published + + + + + + + + + + + + + + + + + action + edit + + + actor + zope + + + comment + + + + + + error_message + + + + serial + 968.3755.43319.6656 + + + state + current + + + time + + + + + + + + + + + 1528473447.8 + UTC + + + + + + + + + + + + + + + + + + + + + action + + + + + + actor + zope + + + comment + + + + error_message + + + + external_processing_state + empty + + + serial + 0.0.0.0 + + + time + + + + + + + + + + + 1528311094.78 + UTC + + + + + + + + + + + diff --git a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_page_ojs_add_json_document.html.html b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_page_ojs_add_json_document.html.html new file mode 100644 index 0000000000000000000000000000000000000000..f9b05339e3428f78da1f47eaa69312a7eab45dcd --- /dev/null +++ b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_page_ojs_add_json_document.html.html @@ -0,0 +1,18 @@ + + + + + + + + OfficeJS Add Json Document + + + + + + + + + + diff --git a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_page_ojs_add_json_document.html.xml b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_page_ojs_add_json_document.html.xml new file mode 100644 index 0000000000000000000000000000000000000000..37ccd668aa30916d78c6d133acb23ca85e54998e --- /dev/null +++ b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_page_ojs_add_json_document.html.xml @@ -0,0 +1,319 @@ + + + + + + + + + + _Access_contents_information_Permission + + + Anonymous + Assignee + Assignor + Associate + Auditor + Manager + + + + + _Add_portal_content_Permission + + + Assignor + Manager + + + + + _Change_local_roles_Permission + + + Assignor + Manager + + + + + _Modify_portal_content_Permission + + + Manager + + + + + _View_Permission + + + Anonymous + Assignee + Assignor + Associate + Auditor + Manager + + + + + content_md5 + + + + + + content_type + text/html + + + default_reference + gadget_erp5_page_ojs_add_json_document.html + + + description + + + + + + id + gadget_erp5_page_ojs_add_json_document.html + + + language + + + + + + portal_type + Web Page + + + short_title + + + + + + version + + + + + + workflow_history + + AAAAAAAAAAI= + + + + + + + + + + + + + data + + + + document_publication_workflow + + AAAAAAAAAAM= + + + + edit_workflow + + AAAAAAAAAAQ= + + + + processing_status_workflow + + AAAAAAAAAAU= + + + + + + + + + + + + + + + + + + + action + publish + + + actor + zope + + + comment + + + + error_message + + + + time + + + + + + + + + + + 1529312559.88 + UTC + + + + + + + validation_state + published + + + + + + + + + + + + + + + + + action + edit + + + actor + zope + + + comment + + + + + + error_message + + + + serial + 968.19604.62909.57139 + + + state + current + + + time + + + + + + + + + + + 1529311989.6 + UTC + + + + + + + + + + + + + + + + + + + + + action + detect_converted_file + + + actor + zope + + + comment + + + + error_message + + + + external_processing_state + converted + + + serial + 0.0.0.0 + + + time + + + + + + + + + + + 1529311949.17 + UTC + + + + + + + + + + + diff --git a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_page_ojs_add_json_document.js.js b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_page_ojs_add_json_document.js.js new file mode 100644 index 0000000000000000000000000000000000000000..7845afedb56eaf33dbe17d2a18b73b8f680a40c7 --- /dev/null +++ b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_page_ojs_add_json_document.js.js @@ -0,0 +1,41 @@ +/*global window, rJS, RSVP */ +/*jslint nomen: true, indent: 2, maxerr: 3 */ +(function (window, rJS, RSVP) { + "use strict"; + + rJS(window) + ///////////////////////////////////////////////////////////////// + // Acquired methods + ///////////////////////////////////////////////////////////////// + .declareAcquiredMethod("updateHeader", "updateHeader") + .declareAcquiredMethod("getSetting", "getSetting") + .declareAcquiredMethod("jio_putAttachment", "jio_putAttachment") + .declareAcquiredMethod("redirect", "redirect") + .declareAcquiredMethod("jio_post", "jio_post") + + ///////////////////////////////////////////////////////////////// + // declared methods + ///////////////////////////////////////////////////////////////// + .declareMethod("render", function (options) { + var gadget = this; + return RSVP.Queue() + .push(function () { + var ret = { + title: "Untitled Document", + portal_type: "JSON Document", + schema: options.schema, + parent_relative_url: "document_module" + }; + return gadget.jio_post(ret); + }) + .push(function (id) { + return gadget.redirect({ + command: 'display', + options: { + jio_key: id, + editable: true + } + }); + }); + }); +}(window, rJS, RSVP)); diff --git a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_page_ojs_add_json_document.js.xml b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_page_ojs_add_json_document.js.xml new file mode 100644 index 0000000000000000000000000000000000000000..2bd7c36571cb895fe01d0dfa98be4af7c242010a --- /dev/null +++ b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_page_ojs_add_json_document.js.xml @@ -0,0 +1,319 @@ + + + + + + + + + + _Access_contents_information_Permission + + + Anonymous + Assignee + Assignor + Associate + Auditor + Manager + + + + + _Add_portal_content_Permission + + + Assignor + Manager + + + + + _Change_local_roles_Permission + + + Assignor + Manager + + + + + _Modify_portal_content_Permission + + + Manager + + + + + _View_Permission + + + Anonymous + Assignee + Assignor + Associate + Auditor + Manager + + + + + content_md5 + + + + + + content_type + text/javascript + + + default_reference + gadget_erp5_page_ojs_add_json_document.js + + + description + + + + + + id + gadget_erp5_page_ojs_add_json_document.js + + + language + + + + + + portal_type + Web Script + + + short_title + + + + + + version + + + + + + workflow_history + + AAAAAAAAAAI= + + + + + + + + + + + + + data + + + + document_publication_workflow + + AAAAAAAAAAM= + + + + edit_workflow + + AAAAAAAAAAQ= + + + + processing_status_workflow + + AAAAAAAAAAU= + + + + + + + + + + + + + + + + + + + action + publish + + + actor + zope + + + comment + + + + error_message + + + + time + + + + + + + + + + + 1529312550.04 + UTC + + + + + + + validation_state + published + + + + + + + + + + + + + + + + + action + edit + + + actor + zope + + + comment + + + + + + error_message + + + + serial + 968.19606.36848.59733 + + + state + current + + + time + + + + + + + + + + + 1529312523.59 + UTC + + + + + + + + + + + + + + + + + + + + + action + detect_converted_file + + + actor + zope + + + comment + + + + error_message + + + + external_processing_state + converted + + + serial + 0.0.0.0 + + + time + + + + + + + + + + + 1529312001.47 + UTC + + + + + + + + + + + diff --git a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_page_ojs_add_json_schema.html.html b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_page_ojs_add_json_schema.html.html new file mode 100644 index 0000000000000000000000000000000000000000..83f6adab2f46bda04740a2e9c5484af9e62aa038 --- /dev/null +++ b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_page_ojs_add_json_schema.html.html @@ -0,0 +1,18 @@ + + + + + + + + OfficeJS Add JSON Schema + + + + + + + + + + diff --git a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_page_ojs_add_json_schema.html.xml b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_page_ojs_add_json_schema.html.xml new file mode 100644 index 0000000000000000000000000000000000000000..620331a1602d5cdf28ba1979ba9fd519a1f5f37c --- /dev/null +++ b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_page_ojs_add_json_schema.html.xml @@ -0,0 +1,319 @@ + + + + + + + + + + _Access_contents_information_Permission + + + Anonymous + Assignee + Assignor + Associate + Auditor + Manager + + + + + _Add_portal_content_Permission + + + Assignor + Manager + + + + + _Change_local_roles_Permission + + + Assignor + Manager + + + + + _Modify_portal_content_Permission + + + Manager + + + + + _View_Permission + + + Anonymous + Assignee + Assignor + Associate + Auditor + Manager + + + + + content_md5 + + + + + + content_type + text/html + + + default_reference + gadget_erp5_page_ojs_add_json_schema.html + + + description + + + + + + id + gadget_erp5_page_ojs_add_json_schema.html + + + language + + + + + + portal_type + Web Page + + + short_title + + + + + + version + + + + + + workflow_history + + AAAAAAAAAAI= + + + + + + + + + + + + + data + + + + document_publication_workflow + + AAAAAAAAAAM= + + + + edit_workflow + + AAAAAAAAAAQ= + + + + processing_status_workflow + + AAAAAAAAAAU= + + + + + + + + + + + + + + + + + + + action + publish + + + actor + zope + + + comment + + + + error_message + + + + time + + + + + + + + + + + 1529423472.58 + UTC + + + + + + + validation_state + published + + + + + + + + + + + + + + + + + action + edit + + + actor + zope + + + comment + + + + + + error_message + + + + serial + 968.21463.13805.56115 + + + state + current + + + time + + + + + + + + + + + 1529423544.97 + UTC + + + + + + + + + + + + + + + + + + + + + action + detect_converted_file + + + actor + zope + + + comment + + + + error_message + + + + external_processing_state + converted + + + serial + 0.0.0.0 + + + time + + + + + + + + + + + 1529422971.29 + UTC + + + + + + + + + + + diff --git a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_page_ojs_add_json_schema.js.js b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_page_ojs_add_json_schema.js.js new file mode 100644 index 0000000000000000000000000000000000000000..a6c882846ee6c46f521b670f5f4004257d0d53f0 --- /dev/null +++ b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_page_ojs_add_json_schema.js.js @@ -0,0 +1,53 @@ +/*global window, rJS, RSVP */ +/*jslint nomen: true, indent: 2, maxerr: 3 */ +(function (window, rJS, RSVP, Blob) { + "use strict"; + + rJS(window) + ///////////////////////////////////////////////////////////////// + // Acquired methods + ///////////////////////////////////////////////////////////////// + .declareAcquiredMethod("updateHeader", "updateHeader") + .declareAcquiredMethod("updatePanel", "updatePanel") + .declareAcquiredMethod("getSetting", "getSetting") + .declareAcquiredMethod("jio_putAttachment", "jio_putAttachment") + .declareAcquiredMethod("redirect", "redirect") + .declareAcquiredMethod("jio_post", "jio_post") + .declareAcquiredMethod("jio_put", "jio_put") + + ///////////////////////////////////////////////////////////////// + // declared methods + ///////////////////////////////////////////////////////////////// + .declareMethod("render", function () { + var gadget = this, + ret = { + title: "Untitled Schema", + portal_type: "JSON Schema", + parent_relative_url: "schema_module" + }; + return RSVP.Queue() + .push(function () { + return gadget.jio_post(ret); + }) + .push(function (id) { + ret.reference = id; + return gadget.jio_put(id, ret) + .push(function () { + return gadget.jio_putAttachment(id, 'data', + new Blob(['{"$schema": "http://json-schema.org/draft-07/schema#" }'])); + }) + .push(function () { + return gadget.updatePanel({editable: true}); + }) + .push(function () { + return gadget.redirect({ + command: 'display', + options: { + jio_key: id, + editable: true + } + }); + }); + }); + }); +}(window, rJS, RSVP, Blob)); diff --git a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_page_ojs_add_json_schema.js.xml b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_page_ojs_add_json_schema.js.xml new file mode 100644 index 0000000000000000000000000000000000000000..e3d3f901f1e67029c7fc2908a4f996ae1da8abdf --- /dev/null +++ b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_page_ojs_add_json_schema.js.xml @@ -0,0 +1,319 @@ + + + + + + + + + + _Access_contents_information_Permission + + + Anonymous + Assignee + Assignor + Associate + Auditor + Manager + + + + + _Add_portal_content_Permission + + + Assignor + Manager + + + + + _Change_local_roles_Permission + + + Assignor + Manager + + + + + _Modify_portal_content_Permission + + + Manager + + + + + _View_Permission + + + Anonymous + Assignee + Assignor + Associate + Auditor + Manager + + + + + content_md5 + + + + + + content_type + text/javascript + + + default_reference + gadget_erp5_page_ojs_add_json_schema.js + + + description + + + + + + id + gadget_erp5_page_ojs_add_json_schema.js + + + language + + + + + + portal_type + Web Script + + + short_title + + + + + + version + + + + + + workflow_history + + AAAAAAAAAAI= + + + + + + + + + + + + + data + + + + document_publication_workflow + + AAAAAAAAAAM= + + + + edit_workflow + + AAAAAAAAAAQ= + + + + processing_status_workflow + + AAAAAAAAAAU= + + + + + + + + + + + + + + + + + + + action + publish + + + actor + zope + + + comment + + + + error_message + + + + time + + + + + + + + + + + 1529422852.29 + UTC + + + + + + + validation_state + published + + + + + + + + + + + + + + + + + action + edit + + + actor + zope + + + comment + + + + + + error_message + + + + serial + 968.21427.35485.43758 + + + state + current + + + time + + + + + + + + + + + 1529422814.82 + UTC + + + + + + + + + + + + + + + + + + + + + action + detect_converted_file + + + actor + zope + + + comment + + + + error_message + + + + external_processing_state + converted + + + serial + 0.0.0.0 + + + time + + + + + + + + + + + 1529421291.26 + UTC + + + + + + + + + + + diff --git a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_page_ojs_schema_document_list.html.html b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_page_ojs_schema_document_list.html.html new file mode 100644 index 0000000000000000000000000000000000000000..484477c7374ebaed275c0730d56367a95761da12 --- /dev/null +++ b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_page_ojs_schema_document_list.html.html @@ -0,0 +1,19 @@ + + + + + + + + OfficeJS Jio Schema Document List + + + + + + + + +
+ + diff --git a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_page_ojs_schema_document_list.html.xml b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_page_ojs_schema_document_list.html.xml new file mode 100644 index 0000000000000000000000000000000000000000..327ea3428bb23573d025e25436ea4a266188b7de --- /dev/null +++ b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_page_ojs_schema_document_list.html.xml @@ -0,0 +1,321 @@ + + + + + + + + + + _Access_contents_information_Permission + + + Anonymous + Assignee + Assignor + Associate + Auditor + Manager + + + + + _Add_portal_content_Permission + + + Assignor + Manager + + + + + _Change_local_roles_Permission + + + Assignor + Manager + + + + + _Modify_portal_content_Permission + + + Manager + + + + + _View_Permission + + + Anonymous + Assignee + Assignor + Associate + Auditor + Manager + + + + + content_md5 + + + + + + content_type + text/html + + + default_reference + gadget_erp5_page_ojs_schema_document_list.html + + + description + + + + + + id + gadget_erp5_page_ojs_schema_document_list.html + + + language + + + + + + portal_type + Web Page + + + short_title + + + + + + version + + + + + + workflow_history + + AAAAAAAAAAI= + + + + + + + + + + + + + data + + + + document_publication_workflow + + AAAAAAAAAAM= + + + + edit_workflow + + AAAAAAAAAAQ= + + + + processing_status_workflow + + AAAAAAAAAAU= + + + + + + + + + + + + + + + + + + + action + publish + + + actor + zope + + + comment + + + + error_message + + + + time + + + + + + + + + + + 1528361012.65 + UTC + + + + + + + validation_state + published + + + + + + + + + + + + + + + + + action + edit + + + actor + zope + + + comment + + + + + + error_message + + + + serial + 968.3755.35782.24098 + + + state + current + + + time + + + + + + + + + + + 1528473464.7 + UTC + + + + + + + + + + + + + + + + + + + + + action + + + + + + actor + zope + + + comment + + + + error_message + + + + external_processing_state + empty + + + serial + 0.0.0.0 + + + time + + + + + + + + + + + 1528311178.97 + UTC + + + + + + + + + + + diff --git a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_page_ojs_schema_document_list.js.js b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_page_ojs_schema_document_list.js.js new file mode 100644 index 0000000000000000000000000000000000000000..4b3dbcfb6e73e0277264eed436a8cacc645ad8c2 --- /dev/null +++ b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_page_ojs_schema_document_list.js.js @@ -0,0 +1,156 @@ +/*global window, rJS, RSVP */ +/*jslint nomen: true, indent: 2, maxerr: 3 */ +(function (window, rJS, RSVP) { + "use strict"; + + rJS(window) + ///////////////////////////////////////////////////////////////// + // Acquired methods + ///////////////////////////////////////////////////////////////// + .declareAcquiredMethod("updateHeader", "updateHeader") + .declareAcquiredMethod("getUrlParameter", "getUrlParameter") + .declareAcquiredMethod("getUrlFor", "getUrlFor") + .declareAcquiredMethod("jio_allDocs", "jio_allDocs") + .declareAcquiredMethod("getSetting", "getSetting") + + ///////////////////////////////////////////////////////////////// + // declared methods + ///////////////////////////////////////////////////////////////// + + .allowPublicAcquisition("jio_allDocs", function (param_list) { + var gadget = this; + return gadget.jio_allDocs(param_list[0]) + .push(function (result) { + var i, date, len = result.data.total_rows; + for (i = 0; i < len; i += 1) { + if (result.data.rows[i].value.hasOwnProperty("modification_date")) { + date = new Date(result.data.rows[i].value.modification_date); + result.data.rows[i].value.modification_date = { + field_gadget_param: { + allow_empty_time: 0, + ampm_time_style: 0, + css_class: "date_field", + date_only: 0, + description: "The Date", + editable: 0, + hidden: 0, + hidden_day_is_last_day: 0, + "default": date.toUTCString(), + key: "modification_date", + required: 0, + timezone_style: 0, + title: "Modification Date", + type: "DateTimeField" + } + }; + result.data.rows[i].value["listbox_uid:list"] = { + key: "listbox_uid:list", + value: 2713 + }; + } + } + return result; + }); + }) + + .allowPublicAcquisition('notifySubmit', function () { + return this.triggerSubmit(); + }) + + .declareMethod("triggerSubmit", function () { + var argument_list = arguments; + return this.getDeclaredGadget('form_list') + .push(function (gadget) { + return gadget.triggerSubmit.apply(gadget, argument_list); + }); + }) + + .declareMethod("render", function (options) { + var gadget = this; + return new RSVP.Queue() + .push(function () { + var portal_type = options.portal_type || gadget.getSetting("portal_type"); + return RSVP.all([ + gadget.getDeclaredGadget('form_list'), + portal_type + ]); + }) + .push(function (result) { + var column_list = [ + ['title', 'Title'], + ['reference', 'Reference'], + ['language', 'Language'], + ['description', 'Description'], + ['version', 'Version'], + ['modification_date', 'Modification Date'] + ], + query = 'portal_type:"' + result[1] + '"'; + if (options.schema) { + query += ' AND schema:"' + options.schema + '"'; + } + query = encodeURIComponent(query); + return result[0].render({ + erp5_document: { + "_embedded": {"_view": { + "listbox": { + "column_list": column_list, + "show_anchor": 0, + "default_params": {}, + "editable": 1, + "editable_column_list": [], + "key": "field_listbox", + "lines": 30, + "list_method": "portal_catalog", + "query": "urn:jio:allDocs?query=" + query, + "portal_type": [], + "search_column_list": column_list, + "sort_column_list": column_list, + "sort": [['modification_date', 'descending']], + "title": options.schema_title || "Schemas", + "type": "ListBox" + } + }}, + "_links": { + "type": { + // form_list display portal_type in header + name: "" + } + } + }, + form_definition: { + group_list: [[ + "bottom", + [["listbox"]] + ]] + } + }); + }) + .push(function () { + var tasks; + if (options.portal_type === "JSON Document") { + tasks = [ + gadget.getUrlFor({command: "index", options: { + page: "ojs_add_json_document", + schema: options.schema + }}), + gadget.getSetting('document_title_plural') + ]; + } else { + tasks = [ + gadget.getUrlFor({command: "index", options: { + page: "ojs_add_json_schema" + }}), + gadget.getSetting('document_title_plural') + ]; + } + return RSVP.all(tasks); + }) + .push(function (result) { + return gadget.updateHeader({ + page_title: options.schema_title || result[1], + filter_action: true, + add_url: result[0] + }); + }); + }); +}(window, rJS, RSVP)); \ No newline at end of file diff --git a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_page_ojs_schema_document_list.js.xml b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_page_ojs_schema_document_list.js.xml new file mode 100644 index 0000000000000000000000000000000000000000..70818e1e67d84e79acc41249e95e65730bd2b93b --- /dev/null +++ b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_page_ojs_schema_document_list.js.xml @@ -0,0 +1,321 @@ + + + + + + + + + + _Access_contents_information_Permission + + + Anonymous + Assignee + Assignor + Associate + Auditor + Manager + + + + + _Add_portal_content_Permission + + + Assignor + Manager + + + + + _Change_local_roles_Permission + + + Assignor + Manager + + + + + _Modify_portal_content_Permission + + + Manager + + + + + _View_Permission + + + Anonymous + Assignee + Assignor + Associate + Auditor + Manager + + + + + content_md5 + + + + + + content_type + text/javascript + + + default_reference + gadget_erp5_page_ojs_schema_document_list.js + + + description + + + + + + id + gadget_erp5_page_ojs_schema_document_list.js + + + language + + + + + + portal_type + Web Script + + + short_title + + + + + + version + + + + + + workflow_history + + AAAAAAAAAAI= + + + + + + + + + + + + + data + + + + document_publication_workflow + + AAAAAAAAAAM= + + + + edit_workflow + + AAAAAAAAAAQ= + + + + processing_status_workflow + + AAAAAAAAAAU= + + + + + + + + + + + + + + + + + + + action + publish + + + actor + zope + + + comment + + + + error_message + + + + time + + + + + + + + + + + 1528361005.14 + UTC + + + + + + + validation_state + published + + + + + + + + + + + + + + + + + action + edit + + + actor + zope + + + comment + + + + + + error_message + + + + serial + 968.2945.55875.51438 + + + state + current + + + time + + + + + + + + + + + 1528312444.69 + UTC + + + + + + + + + + + + + + + + + + + + + action + + + + + + actor + zope + + + comment + + + + error_message + + + + external_processing_state + empty + + + serial + 0.0.0.0 + + + time + + + + + + + + + + + 1528312422.54 + UTC + + + + + + + + + + + diff --git a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_page_ojs_zip_upload.html.html b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_page_ojs_zip_upload.html.html new file mode 100644 index 0000000000000000000000000000000000000000..9c11deff4faabb4facef91f8593447ee50979f83 --- /dev/null +++ b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_page_ojs_zip_upload.html.html @@ -0,0 +1,24 @@ + + + + + + + + OfficeJS Jio Upload Zip File Containing files or files as is + + + + + + + + + + +
+
+ + diff --git a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_page_ojs_zip_upload.html.xml b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_page_ojs_zip_upload.html.xml new file mode 100644 index 0000000000000000000000000000000000000000..f80b260782719d2d0f32cdc12b66021a30cc59db --- /dev/null +++ b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_page_ojs_zip_upload.html.xml @@ -0,0 +1,319 @@ + + + + + + + + + + _Access_contents_information_Permission + + + Anonymous + Assignee + Assignor + Associate + Auditor + Manager + + + + + _Add_portal_content_Permission + + + Assignor + Manager + + + + + _Change_local_roles_Permission + + + Assignor + Manager + + + + + _Modify_portal_content_Permission + + + Manager + + + + + _View_Permission + + + Anonymous + Assignee + Assignor + Associate + Auditor + Manager + + + + + content_md5 + + + + + + content_type + text/html + + + default_reference + gadget_erp5_page_ojs_zip_upload.html + + + description + + + + + + id + gadget_erp5_page_ojs_zip_upload.html + + + language + + + + + + portal_type + Web Page + + + short_title + + + + + + version + + + + + + workflow_history + + AAAAAAAAAAI= + + + + + + + + + + + + + data + + + + document_publication_workflow + + AAAAAAAAAAM= + + + + edit_workflow + + AAAAAAAAAAQ= + + + + processing_status_workflow + + AAAAAAAAAAU= + + + + + + + + + + + + + + + + + + + action + publish + + + actor + zope + + + comment + + + + error_message + + + + time + + + + + + + + + + + 1531858269.29 + UTC + + + + + + + validation_state + published + + + + + + + + + + + + + + + + + action + edit + + + actor + zope + + + comment + + + + + + error_message + + + + serial + 968.63483.10177.13550 + + + state + current + + + time + + + + + + + + + + + 1531858473.45 + UTC + + + + + + + + + + + + + + + + + + + + + action + detect_converted_file + + + actor + zope + + + comment + + + + error_message + + + + external_processing_state + converted + + + serial + 0.0.0.0 + + + time + + + + + + + + + + + 1531848195.02 + UTC + + + + + + + + + + + diff --git a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_page_ojs_zip_upload.js.js b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_page_ojs_zip_upload.js.js new file mode 100644 index 0000000000000000000000000000000000000000..27544602332135f112b5e36fed6169fef73a1bd1 --- /dev/null +++ b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_page_ojs_zip_upload.js.js @@ -0,0 +1,309 @@ +/*global window, rJS, RSVP, loopEventListener, + jIO, document, URL */ +/*jslint nomen: true, indent: 2, maxerr: 3 */ +(function (window, rJS, jIO, RSVP) { + "use strict"; + + var content_type = { + Spreadsheet: 'application/x-asc-spreadsheet', + Presentation: 'application/x-asc-presentation', + Text: 'application/x-asc-text' + }; + + function displayError(g, text) { + return g.notifySubmitted({ + message: text, + status: 'fail' + }) + .push(function () { + // return undefined for fail detection + return; + }); + } + + function endsWith(str, suffix) { + return str.indexOf(suffix, str.length - suffix.length) !== -1; + } + + function generateMetadata(id, filename, path, body) { + // it's core of upload of zip gadget + // in this function can be added support another formats + var ret; + if (endsWith(filename, ".json")) { + ret = { + id: id, + content_type: "application/json", + reference: path + }; + if (body) { + if (body.$schema && body.$schema !== "") { + ret.portal_type = "JSON Schema"; + ret.parent_relative_url = "schema_module"; + ret.title = body.title || ""; + } else { + // XXX need schema relation property + ret.portal_type = "JSON Document"; + ret.parent_relative_url = "document_module"; + ret.title = body.filename || ""; + } + } else { + ret.format = "json"; + } + // used for detect supported extension + return ret; + } + } + + rJS(window) + ///////////////////////////////////////////////////////////////// + // Acquired methods + ///////////////////////////////////////////////////////////////// + .declareAcquiredMethod("updateHeader", "updateHeader") + .declareAcquiredMethod("getUrlFor", "getUrlFor") + .declareAcquiredMethod("getSetting", "getSetting") + .declareAcquiredMethod("notifySubmitting", "notifySubmitting") + .declareAcquiredMethod("notifySubmitted", "notifySubmitted") + .declareAcquiredMethod("jio_putAttachment", "jio_putAttachment") + .declareAcquiredMethod("redirect", "redirect") + .declareAcquiredMethod("jio_post", "jio_post") + .declareAcquiredMethod("jio_put", "jio_put") + .declareAcquiredMethod("jio_putAttachment", "jio_putAttachment") + + ///////////////////////////////////////////////////////////////// + // declared methods + ///////////////////////////////////////////////////////////////// + .declareMethod("render", function () { + var gadget = this; + return gadget.changeState({ + title: 'Untitled Document' + }); + }) + + .declareMethod('putIntoDB', function (id, file_name, path, blob) { + var gadget = this, + queue = RSVP.Queue(), + // first run generateMetadata for check file support + // and detect document format + file_supported = generateMetadata(id, file_name, path); + if (file_supported) { + if (file_supported.format === "json") { + queue + .push(function () { + return jIO.util.readBlobAsText(blob); + }) + .push(function (evt) { + return JSON.parse(evt.target.result); + }); + } else { + queue.push(function () { + return blob; + }); + } + queue + .push(function (data) { + return gadget.jio_post(generateMetadata(id, file_name, path, data)) + .push(function (added_id) { + return gadget.jio_putAttachment(added_id, 'data', blob); + }); + }); + } + return queue; + }) + + .declareMethod('triggerSubmit', function () { + var gadget = this; + return gadget.notifySubmitting() + .push(function () { + return gadget.getDeclaredGadget('form_view'); + }) + .push(function (form_gadget) { + return form_gadget.getContent(); + }) + .push(function (content) { + var data_array, + protocol, + i; + if (!content.data) { + content.data = []; + } + data_array = content.data; + for (i = 0; i < data_array.length; i += 1) { + data_array[i].blob = jIO.util.dataURItoBlob(data_array[i].url); + data_array[i].url = undefined; + } + if (content.data_url) { + protocol = (new URL(content.data_url, gadget.__path)).protocol; + if (protocol === "http:") { + if (window.location.protocol !== protocol) { + return displayError(gadget, "You cannot mixed http and https calls"); + } + } + return RSVP.Queue() + .push(function () { + return jIO.util.ajax({ + dataType: "blob", + url: content.data_url + }); + }) + .push(function (evt) { + content.data.push({ + blob: evt.target.response, + file_name: content.data_url + }); + return content; + }, function () { + return displayError(gadget, 'Download ' + content.data_url + ' Failed'); + }); + } + return content; + }) + .push(function (content) { + if (!content) { + // fail while downloading + return; + } + if (content.data.length === 0) { + return gadget.notifySubmitted({message: 'You need enter data', status: 'fail'}); + } + return new RSVP.Queue() + .push(function () { + + return RSVP.all([ + gadget.getSetting('jio_storage_name'), + gadget.getSetting('jio_storage_description') + ]); + }) + .push(function (result) { + var promiseArray = [], + data_array = content.data, + i, + blob, + storage_name = result[0], + storage_description = result[1], + storage, + local_database, + configuration; + + // XXX support other type of storage + if (storage_name === "LOCAL") { + local_database = storage_description.sub_storage.sub_storage.database; + } + + for (i = 0; i < data_array.length; i += 1) { + blob = data_array[i].blob; + if (endsWith(data_array[i].file_name, ".zip")) { + configuration = { + type: "replicate", + conflict_handling: 2, + check_local_attachment_creation: false, + check_local_creation: false, + check_local_modification: false, + check_local_deletion: false, + check_remote_attachment_creation: true, + check_remote_creation: true, + check_remote_modification: true, + check_remote_deletion: true, + local_sub_storage: { + type: "indexeddb", + database: local_database + }, + signature_sub_storage: { + type: "query", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "ziptodocuments", + generateMetadata: generateMetadata, + sub_storage: { + type: "zipfile", + file: blob + } + } + }; + storage = jIO.createJIO(configuration); + promiseArray.push(storage.repair()); + } else { + promiseArray.push(gadget.putIntoDB("", data_array[i].file_name, data_array[i].file_name, blob)); + } + } + return RSVP.all(promiseArray); + }) + .push(function () { + return RSVP.all([ + gadget.notifySubmitted({message: 'Data Updated', status: 'success'}), + gadget.redirect({command: 'history_previous'}) + ]); + }); + }); + }) + + .onStateChange(function () { + var gadget = this; + return RSVP.Queue() + .push(function () { + return RSVP.all([ + gadget.getDeclaredGadget('form_view'), + gadget.getSetting('upload_content_type') + ]); + }) + .push(function (result) { + return result[0].render({ + erp5_document: { + "_embedded": { + "_view": { + "my_file": { + "description": "", + "title": "Upload files and Zip archive containing files", + "default": "", + "css_class": "", + "required": 0, + "editable": 1, + "key": "data", + "hidden": 0, + "multiple": "true", + "accept": "application/zip," + result[1], + "type": "FileField" + }, + "my_url": { + "description": "", + "title": "Fetch and Upload files and Zip archive containing files", + "default": "", + "css_class": "", + "required": 0, + "editable": 1, + "key": "data_url", + "hidden": 0, + "type": "StringField" + } + } + }, + "_links": { + "type": { + // form_list display portal_type in header + name: "" + } + } + }, + form_definition: { + group_list: [[ + "left", + [["my_file"], ["my_url"]] + ]] + } + }); + }) + .push(function () { + return gadget.getUrlFor({command: 'history_previous'}); + }) + .push(function (result) { + return gadget.updateHeader({ + page_title: 'Document(s)', + back_field: true, + selection_url: result, + save_action: true + }); + }); + }); +}(window, rJS, jIO, RSVP)); diff --git a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_page_ojs_zip_upload.js.xml b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_page_ojs_zip_upload.js.xml new file mode 100644 index 0000000000000000000000000000000000000000..5b2150969b7042ea0839ce5b2d25c0771de6540f --- /dev/null +++ b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_erp5_page_ojs_zip_upload.js.xml @@ -0,0 +1,319 @@ + + + + + + + + + + _Access_contents_information_Permission + + + Anonymous + Assignee + Assignor + Associate + Auditor + Manager + + + + + _Add_portal_content_Permission + + + Assignor + Manager + + + + + _Change_local_roles_Permission + + + Assignor + Manager + + + + + _Modify_portal_content_Permission + + + Manager + + + + + _View_Permission + + + Anonymous + Assignee + Assignor + Associate + Auditor + Manager + + + + + content_md5 + + + + + + content_type + text/javascript + + + default_reference + gadget_erp5_page_ojs_zip_upload.js + + + description + + + + + + id + gadget_erp5_page_ojs_zip_upload.js + + + language + + + + + + portal_type + Web Script + + + short_title + + + + + + version + + + + + + workflow_history + + AAAAAAAAAAI= + + + + + + + + + + + + + data + + + + document_publication_workflow + + AAAAAAAAAAM= + + + + edit_workflow + + AAAAAAAAAAQ= + + + + processing_status_workflow + + AAAAAAAAAAU= + + + + + + + + + + + + + + + + + + + action + publish + + + actor + zope + + + comment + + + + error_message + + + + time + + + + + + + + + + + 1531858278.36 + UTC + + + + + + + validation_state + published + + + + + + + + + + + + + + + + + action + edit + + + actor + zope + + + comment + + + + + + error_message + + + + serial + 968.63287.21360.10154 + + + state + current + + + time + + + + + + + + + + + 1531846571.54 + UTC + + + + + + + + + + + + + + + + + + + + + action + detect_converted_file + + + actor + zope + + + comment + + + + error_message + + + + external_processing_state + converted + + + serial + 0.0.0.0 + + + time + + + + + + + + + + + 1531846497.56 + UTC + + + + + + + + + + + diff --git a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_jio_json_document_view.html.html b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_jio_json_document_view.html.html new file mode 100644 index 0000000000000000000000000000000000000000..c10b856a6aa24297bde901b5304ee96a5968fba0 --- /dev/null +++ b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_jio_json_document_view.html.html @@ -0,0 +1,26 @@ + + + + + + + OfficeJS Jio Document View + + + + + + + + + +
+ +
+
+
+ + diff --git a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_jio_json_document_view.html.xml b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_jio_json_document_view.html.xml new file mode 100644 index 0000000000000000000000000000000000000000..dc5b73ec5f7f390d13bfd2ba7cdca62607b4c531 --- /dev/null +++ b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_jio_json_document_view.html.xml @@ -0,0 +1,319 @@ + + + + + + + + + + _Access_contents_information_Permission + + + Anonymous + Assignee + Assignor + Associate + Auditor + Manager + + + + + _Add_portal_content_Permission + + + Assignor + Manager + + + + + _Change_local_roles_Permission + + + Assignor + Manager + + + + + _Modify_portal_content_Permission + + + Manager + + + + + _View_Permission + + + Anonymous + Assignee + Assignor + Associate + Auditor + Manager + + + + + content_md5 + + + + + + content_type + text/html + + + default_reference + gadget_officejs_jio_json_document_view.html + + + description + + + + + + id + gadget_officejs_jio_json_document_view.html + + + language + + + + + + portal_type + Web Page + + + short_title + + + + + + version + + + + + + workflow_history + + AAAAAAAAAAI= + + + + + + + + + + + + + data + + + + document_publication_workflow + + AAAAAAAAAAM= + + + + edit_workflow + + AAAAAAAAAAQ= + + + + processing_status_workflow + + AAAAAAAAAAU= + + + + + + + + + + + + + + + + + + + action + publish + + + actor + zope + + + comment + + + + error_message + + + + time + + + + + + + + + + + 1529312245.83 + UTC + + + + + + + validation_state + published + + + + + + + + + + + + + + + + + action + edit + + + actor + zope + + + comment + + + + + + error_message + + + + serial + 968.19572.63845.39133 + + + state + current + + + time + + + + + + + + + + + 1529310065.14 + UTC + + + + + + + + + + + + + + + + + + + + + action + detect_converted_file + + + actor + zope + + + comment + + + + error_message + + + + external_processing_state + converted + + + serial + 0.0.0.0 + + + time + + + + + + + + + + + 1529309725.59 + UTC + + + + + + + + + + + diff --git a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_jio_json_document_view.js.js b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_jio_json_document_view.js.js new file mode 100644 index 0000000000000000000000000000000000000000..614490ddd546f88662bb31823f073888727500b5 --- /dev/null +++ b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_jio_json_document_view.js.js @@ -0,0 +1,219 @@ +/*global window, rJS, RSVP, jIO, URL, Query, + promiseEventListener, document*/ +/*jslint nomen: true, indent: 2, maxerr: 3 */ +(function (window, jIO, rJS, RSVP, Query) { + "use strict"; + + rJS(window) + ///////////////////////////////////////////////////////////////// + // Acquired methods + ///////////////////////////////////////////////////////////////// + .declareAcquiredMethod("updateHeader", "updateHeader") + .declareAcquiredMethod("getUrlParameter", "getUrlParameter") + .declareAcquiredMethod("getUrlFor", "getUrlFor") + .declareAcquiredMethod("updateDocument", "updateDocument") + .declareAcquiredMethod("notifySubmitting", "notifySubmitting") + .declareAcquiredMethod("notifySubmitted", 'notifySubmitted') + .declareAcquiredMethod("redirect", "redirect") + .declareAcquiredMethod("jio_get", "jio_get") + .declareAcquiredMethod("jio_put", "jio_put") + .declareAcquiredMethod("jio_allDocs", "jio_allDocs") + .declareAcquiredMethod("jio_getAttachment", "jio_getAttachment") + .declareAcquiredMethod("jio_putAttachment", "jio_putAttachment") + + ///////////////////////////////////////////////////////////////// + // declared methods + ///////////////////////////////////////////////////////////////// + .declareMethod("render", function (options) { + var gadget = this; + return gadget.changeState({ + jio_key: options.jio_key, + doc: options.doc + }); + }) + + .onEvent('submit', function () { + var gadget = this; + return gadget.notifySubmitting() + .push(function () { + return gadget.getDeclaredGadget('form_view'); + }) + .push(function (form_gadget) { + return form_gadget.getContent(); + }) + .push(function (content) { + var list = [], + blob; + if (content.file) { + blob = jIO.util.dataURItoBlob(content.file.url); + content.title = content.file.file_name; + delete content.file; + list = [ + gadget.updateDocument(content), + gadget.jio_putAttachment(gadget.state.jio_key, 'data', blob) + ]; + } else if (content.data) { + blob = new Blob([content.data]); + delete content.data; + list = [ + gadget.updateDocument(content), + gadget.jio_putAttachment(gadget.state.jio_key, 'data', blob) + ]; + } else { + list = [gadget.updateDocument(content)]; + } + return RSVP.all(list); + }) + .push(function () { + return gadget.notifySubmitted({message: 'Data Updated', status: 'success'}); + }, function (error) { + if (error.target && error.target.error.name === 'NotReadableError') { + return gadget.notifySubmitted({message: error.target.error.message, status: 'fail'}); + } + throw error; + }).push(function () { + // debugger; + return gadget.redirect({ + command: 'reload' + }); + }); + }) + + .declareMethod("triggerSubmit", function () { + return this.element.querySelector('button[type="submit"]').click(); + }) + + .allowPublicAcquisition("resolveExternalReference", function (arr) { + var g = this, + url = arr[0], + reference, + args; + if (url.startsWith("urn:jio:reference?")) { + reference = decodeURIComponent(url.replace("urn:jio:reference?", "")); + args = { + query: Query.objectToSearchText({ + type: "complex", + operator: "AND", + query_list: [ + { + key: "portal_type", + type: "simple", + value: "JSON Schema" + }, + { + key: "reference", + type: "simple", + value: reference + } + ] + }), + limit: [0, 1], + select_list: [], + sort_on: [["modification_date", "descending"]] + }; + return g.jio_allDocs(args) + .push(function (result) { + return g.jio_getAttachment(result.data.rows[0].id, "data", {format: "json"}); + }); + } + }) + + .onStateChange(function () { + var gadget = this, + schema_obj; + return RSVP.Queue() + .push(function () { + return RSVP.all([ + gadget.getDeclaredGadget('form_view'), + gadget.jio_getAttachment(gadget.state.jio_key, 'data', {format: "json"}) + .push(undefined, function () { + return; + }), + gadget.jio_get(gadget.state.doc.schema) + ]); + }) + .push(function (result) { + schema_obj = result[2]; + return result[0].render({ + erp5_document: { + "_embedded": { + "_view": { + "my_title": { + "description": "", + "title": "Title", + "default": gadget.state.doc.title, + "css_class": "", + "required": 1, + "editable": 1, + "key": "title", + "hidden": 0, + "type": "StringField" + }, + "my_file": { + "description": "", + "title": "Upload and rewrite this document", + "default": "", + "css_class": "", + "required": 0, + "editable": 1, + "key": "file", + "hidden": 0, + "accept": "application/json", + "type": "FileField" + }, + "my_content": { + "default": result[1], + "css_class": "", + "required": 0, + "editable": 1, + "key": "data", + "hidden": 0, + "type": "GadgetField", + "renderjs_extra": '{"name": "data",' + + ' "schema_url": "urn:jio:reference?' + schema_obj.reference + '"}', + "url": "jsonform.gadget.html", + "sandbox": "public" + } + } + }, + "_links": { + "type": { + // form_list display portal_type in header + name: "" + } + } + }, + form_definition: { + group_list: [[ + "left", + [["my_title"], ["my_reference"]] + ], [ + "bottom", + [["my_content"]] + ]] + } + }); + }) + .push(function () { + return RSVP.all([ + gadget.getUrlFor({command: 'display', options: { + page: "ojs_schema_document_list", + portal_type: "JSON Document", + schema: gadget.state.doc.schema, + schema_title: schema_obj.title + }}), + gadget.getUrlFor({command: 'selection_previous'}), + gadget.getUrlFor({command: 'selection_next'}) + ]); + }) + .push(function (url_list) { + return gadget.updateHeader({ + page_title: gadget.state.doc.title, + save_action: true, + selection_url: url_list[0], + previous_url: url_list[1], + next_url: url_list[2] + }); + }); + }); +}(window, jIO, rJS, RSVP, Query)); diff --git a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_jio_json_document_view.js.xml b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_jio_json_document_view.js.xml new file mode 100644 index 0000000000000000000000000000000000000000..7defc5d4ad9b706c71803d23fc0e34f1fa8bfdd2 --- /dev/null +++ b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_jio_json_document_view.js.xml @@ -0,0 +1,319 @@ + + + + + + + + + + _Access_contents_information_Permission + + + Anonymous + Assignee + Assignor + Associate + Auditor + Manager + + + + + _Add_portal_content_Permission + + + Assignor + Manager + + + + + _Change_local_roles_Permission + + + Assignor + Manager + + + + + _Modify_portal_content_Permission + + + Manager + + + + + _View_Permission + + + Anonymous + Assignee + Assignor + Associate + Auditor + Manager + + + + + content_md5 + + + + + + content_type + text/javascript + + + default_reference + gadget_officejs_jio_json_document_view.js + + + description + + + + + + id + gadget_officejs_jio_json_document_view.js + + + language + + + + + + portal_type + Web Script + + + short_title + + + + + + version + + + + + + workflow_history + + AAAAAAAAAAI= + + + + + + + + + + + + + data + + + + document_publication_workflow + + AAAAAAAAAAM= + + + + edit_workflow + + AAAAAAAAAAQ= + + + + processing_status_workflow + + AAAAAAAAAAU= + + + + + + + + + + + + + + + + + + + action + publish + + + actor + zope + + + comment + + + + error_message + + + + time + + + + + + + + + + + 1529312206.16 + UTC + + + + + + + validation_state + published + + + + + + + + + + + + + + + + + action + edit + + + actor + zope + + + comment + + + + + + error_message + + + + serial + 968.19585.54009.7782 + + + state + current + + + time + + + + + + + + + + + 1529310839.13 + UTC + + + + + + + + + + + + + + + + + + + + + action + detect_converted_file + + + actor + zope + + + comment + + + + error_message + + + + external_processing_state + converted + + + serial + 0.0.0.0 + + + time + + + + + + + + + + + 1529310542.24 + UTC + + + + + + + + + + + diff --git a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_jio_json_schema_view.html.html b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_jio_json_schema_view.html.html new file mode 100644 index 0000000000000000000000000000000000000000..4145b1a952d09f160454f0ea98164484aaaeb235 --- /dev/null +++ b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_jio_json_schema_view.html.html @@ -0,0 +1,26 @@ + + + + + + + OfficeJS Jio Schema View + + + + + + + + + +
+ +
+
+
+ + diff --git a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_jio_json_schema_view.html.xml b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_jio_json_schema_view.html.xml new file mode 100644 index 0000000000000000000000000000000000000000..a6ddf7c2395f985ffbcf642b87c54257376e8b0c --- /dev/null +++ b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_jio_json_schema_view.html.xml @@ -0,0 +1,321 @@ + + + + + + + + + + _Access_contents_information_Permission + + + Anonymous + Assignee + Assignor + Associate + Auditor + Manager + + + + + _Add_portal_content_Permission + + + Assignor + Manager + + + + + _Change_local_roles_Permission + + + Assignor + Manager + + + + + _Modify_portal_content_Permission + + + Manager + + + + + _View_Permission + + + Anonymous + Assignee + Assignor + Associate + Auditor + Manager + + + + + content_md5 + + + + + + content_type + text/html + + + default_reference + gadget_officejs_jio_json_schema_view.html + + + description + + + + + + id + gadget_officejs_jio_json_schema_view.html + + + language + + + + + + portal_type + Web Page + + + short_title + + + + + + version + + + + + + workflow_history + + AAAAAAAAAAI= + + + + + + + + + + + + + data + + + + document_publication_workflow + + AAAAAAAAAAM= + + + + edit_workflow + + AAAAAAAAAAQ= + + + + processing_status_workflow + + AAAAAAAAAAU= + + + + + + + + + + + + + + + + + + + action + publish + + + actor + zope + + + comment + + + + error_message + + + + time + + + + + + + + + + + 1528360995.81 + UTC + + + + + + + validation_state + published + + + + + + + + + + + + + + + + + action + edit + + + actor + zope + + + comment + + + + + + error_message + + + + serial + 968.3755.17326.23210 + + + state + current + + + time + + + + + + + + + + + 1528473480.92 + UTC + + + + + + + + + + + + + + + + + + + + + action + + + + + + actor + zope + + + comment + + + + error_message + + + + external_processing_state + empty + + + serial + 0.0.0.0 + + + time + + + + + + + + + + + 1528312462.14 + UTC + + + + + + + + + + + diff --git a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_jio_json_schema_view.js.js b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_jio_json_schema_view.js.js new file mode 100644 index 0000000000000000000000000000000000000000..bfc656c207f13f791b14ab3fffb091a3b868e98a --- /dev/null +++ b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_jio_json_schema_view.js.js @@ -0,0 +1,182 @@ +/*global window, rJS, RSVP, jIO, URL, + promiseEventListener, document*/ +/*jslint nomen: true, indent: 2, maxerr: 3 */ +(function (window, jIO, rJS, RSVP) { + "use strict"; + + rJS(window) + ///////////////////////////////////////////////////////////////// + // Acquired methods + ///////////////////////////////////////////////////////////////// + .declareAcquiredMethod("updateHeader", "updateHeader") + .declareAcquiredMethod("getUrlParameter", "getUrlParameter") + .declareAcquiredMethod("getUrlFor", "getUrlFor") + .declareAcquiredMethod("updateDocument", "updateDocument") + .declareAcquiredMethod("notifySubmitting", "notifySubmitting") + .declareAcquiredMethod("notifySubmitted", 'notifySubmitted') + .declareAcquiredMethod("redirect", "redirect") + .declareAcquiredMethod("jio_get", "jio_get") + .declareAcquiredMethod("jio_put", "jio_put") + .declareAcquiredMethod("jio_getAttachment", "jio_getAttachment") + .declareAcquiredMethod("jio_putAttachment", "jio_putAttachment") + + ///////////////////////////////////////////////////////////////// + // declared methods + ///////////////////////////////////////////////////////////////// + .declareMethod("render", function (options) { + var gadget = this; + return gadget.changeState({ + jio_key: options.jio_key, + doc: options.doc + }); + }) + + .onEvent('submit', function () { + var gadget = this; + return gadget.notifySubmitting() + .push(function () { + return gadget.getDeclaredGadget('form_view'); + }) + .push(function (form_gadget) { + return form_gadget.getContent(); + }) + .push(function (content) { + var list = [], + blob; + if (content.file) { + blob = jIO.util.dataURItoBlob(content.file.url); + content.title = content.title || content.file.file_name; + content.reference = content.reference || content.file.file_name; + delete content.file; + list = [ + gadget.updateDocument(content), + gadget.jio_putAttachment(gadget.state.jio_key, 'data', blob) + ]; + } else if (content.data) { + blob = new Blob([content.data]); + delete content.data; + list = [ + gadget.updateDocument(content), + gadget.jio_putAttachment(gadget.state.jio_key, 'data', blob) + ]; + } else { + list = [gadget.updateDocument(content)]; + } + return RSVP.all(list); + }) + .push(function () { + return gadget.notifySubmitted({message: 'Data Updated', status: 'success'}); + }, function (error) { + if (error.target && error.target.error.name === 'NotReadableError') { + return gadget.notifySubmitted({message: error.target.error.message, status: 'fail'}); + } + throw error; + }).push(function () { + return gadget.redirect({ + command: 'reload' + }); + }); + }) + + .declareMethod("triggerSubmit", function () { + return this.element.querySelector('button[type="submit"]').click(); + }) + + .onStateChange(function () { + var gadget = this; + return RSVP.Queue() + .push(function () { + return RSVP.all([ + gadget.getDeclaredGadget('form_view'), + gadget.jio_getAttachment(gadget.state.jio_key, 'data', {format: "json"}) + ]); + }) + .push(function (result) { + return result[0].render({ + erp5_document: { + "_embedded": { + "_view": { + "my_title": { + "description": "", + "title": "Title", + "default": gadget.state.doc.title, + "css_class": "", + "required": 1, + "editable": 1, + "key": "title", + "hidden": 0, + "type": "StringField" + }, + "my_reference": { + "description": "", + "title": "Reference", + "default": gadget.state.doc.reference, + "css_class": "", + "required": 1, + "editable": 1, + "key": "reference", + "hidden": 0, + "type": "StringField" + }, + "my_file": { + "description": "", + "title": "Upload and rewrite this document", + "default": "", + "css_class": "", + "required": 0, + "editable": 1, + "key": "file", + "hidden": 0, + "accept": "application/json", + "type": "FileField" + }, + "my_content": { + "default": result[1], + "css_class": "", + "required": 0, + "editable": 1, + "key": "data", + "hidden": 0, + "type": "GadgetField", + "renderjs_extra": '{"name": "data"}', + "url": "jsonform.gadget.html", + "sandbox": "public" + } + } + }, + "_links": { + "type": { + // form_list display portal_type in header + name: "" + } + } + }, + form_definition: { + group_list: [[ + "left", + [["my_title"], ["my_reference"], ["my_file"]] + ], [ + "bottom", + [["my_content"]] + ]] + } + }); + }) + .push(function () { + return RSVP.all([ + gadget.getUrlFor({command: 'history_previous'}), + gadget.getUrlFor({command: 'selection_previous'}), + gadget.getUrlFor({command: 'selection_next'}) + ]); + }) + .push(function (url_list) { + return gadget.updateHeader({ + page_title: gadget.state.doc.title, + save_action: true, + selection_url: url_list[0], + previous_url: url_list[1], + next_url: url_list[2] + }); + }); + }); +}(window, jIO, rJS, RSVP)); \ No newline at end of file diff --git a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_jio_json_schema_view.js.xml b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_jio_json_schema_view.js.xml new file mode 100644 index 0000000000000000000000000000000000000000..4ec720277f4c588cb50b7b820f1fddb1f00f4c24 --- /dev/null +++ b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_jio_json_schema_view.js.xml @@ -0,0 +1,321 @@ + + + + + + + + + + _Access_contents_information_Permission + + + Anonymous + Assignee + Assignor + Associate + Auditor + Manager + + + + + _Add_portal_content_Permission + + + Assignor + Manager + + + + + _Change_local_roles_Permission + + + Assignor + Manager + + + + + _Modify_portal_content_Permission + + + Manager + + + + + _View_Permission + + + Anonymous + Assignee + Assignor + Associate + Auditor + Manager + + + + + content_md5 + + + + + + content_type + text/javascript + + + default_reference + gadget_officejs_jio_json_schema_view.js + + + description + + + + + + id + gadget_officejs_jio_json_schema_view.js + + + language + + + + + + portal_type + Web Script + + + short_title + + + + + + version + + + + + + workflow_history + + AAAAAAAAAAI= + + + + + + + + + + + + + data + + + + document_publication_workflow + + AAAAAAAAAAM= + + + + edit_workflow + + AAAAAAAAAAQ= + + + + processing_status_workflow + + AAAAAAAAAAU= + + + + + + + + + + + + + + + + + + + action + publish + + + actor + zope + + + comment + + + + error_message + + + + time + + + + + + + + + + + 1528360876.11 + UTC + + + + + + + validation_state + published + + + + + + + + + + + + + + + + + action + edit + + + actor + zope + + + comment + + + + + + error_message + + + + serial + 968.4203.52459.13892 + + + state + current + + + time + + + + + + + + + + + 1528478452.62 + UTC + + + + + + + + + + + + + + + + + + + + + action + + + + + + actor + zope + + + comment + + + + error_message + + + + external_processing_state + empty + + + serial + 0.0.0.0 + + + time + + + + + + + + + + + 1528312499.11 + UTC + + + + + + + + + + + diff --git a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_jio_multi_upload_js.js b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_jio_multi_upload_js.js index 4bcf4b3a66ba171e70cab6409539eb2f412992cd..c9f8206a8050a0d26f78efe9836bcfb70ed9a9c0 100644 --- a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_jio_multi_upload_js.js +++ b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_jio_multi_upload_js.js @@ -46,6 +46,9 @@ }; post_variables.title = data.file_name || post_variables.title; + if (data.file_name) { + post_variables.reference = data.file_name; + } return gadget.jio_post(post_variables) .push(function (id) { return gadget.jio_putAttachment(id, 'data', blob); diff --git a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_schema.appcache.xml b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_schema.appcache.xml new file mode 100644 index 0000000000000000000000000000000000000000..2bc2311dfdbf4bfd1669ef2e924ab022d6ee3de0 --- /dev/null +++ b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_schema.appcache.xml @@ -0,0 +1,478 @@ + + + + + + + + + + _Access_contents_information_Permission + + + Anonymous + Assignee + Assignor + Associate + Auditor + Manager + + + + + _Add_portal_content_Permission + + + Assignor + Manager + + + + + _Change_local_roles_Permission + + + Assignor + Manager + + + + + _Modify_portal_content_Permission + + + Manager + + + + + _View_Permission + + + Anonymous + Assignee + Assignor + Associate + Auditor + Manager + + + + + categories + + + contributor/person_module/1 + + + + + content_md5 + + + + + + content_type + text/html + + + default_reference + gadget_officejs_schema.appcache + + + description + + + + + + id + gadget_officejs_schema.appcache + + + language + en + + + portal_type + Web Manifest + + + short_title + + + + + + text_content + CACHE MANIFEST\n +# generated on Fri, 25 Jun 2016 11:45:33 +0000\n +# XXX + fonts\n +# images/ajax-loader.gif\n +CACHE:\n +#officejs\n +app/\n +font-awesome/font-awesome.css\n +font-awesome/font-awesome-webfont.eot\n +font-awesome/font-awesome-webfont.woff\n +font-awesome/font-awesome-webfont.woff2\n +font-awesome/font-awesome-webfont.ttf\n +font-awesome/font-awesome-webfont.svg\n +gadget_erp5_nojqm.css\n +jio_ojs_storage.js\n +gadget_erp5_global.js\n +URI.js\n +dygraph.js\n +handlebars.js\n +jiodev.js\n +jio_ziptodocuments.js\n +zipfilestorage-with-jszip.js\n +renderjs.js\n +rsvp.js\n +gadget_global.js\n +erp5_launcher_nojqm.js\n +gadget_officejs_router.js\n +gadget_erp5_router.html\n +gadget_erp5_router.js\n +gadget_jio.html\n +gadget_jio.js\n +gadget_translate.html\n +gadget_translate.js\n +gadget_translation.html\n +gadget_translation.js\n +gadget_translation_data.js\n +gadget_erp5_editor_panel.html\n +gadget_erp5_editor_panel.js\n +gadget_erp5_ojs_panel.html\n +gadget_erp5_ojs_panel.js\n +gadget_erp5_header.html\n +gadget_erp5_header.js\n +gadget_ojs_jio.html\n +gadget_ojs_jio.js\n +gadget_erp5_page_ojs_controller.html\n +gadget_erp5_page_ojs_controller.js\n +gadget_erp5_page_ojs_add_json_schema.html\n +gadget_erp5_page_ojs_add_json_schema.js\n +gadget_erp5_page_ojs_add_json_document.html\n +gadget_erp5_page_ojs_add_json_document.js\n +gadget_erp5_page_ojs_configurator.html\n +gadget_erp5_page_ojs_configurator.js\n +gadget_erp5_page_ojs_dav_configurator.html\n +gadget_erp5_page_ojs_dav_configurator.js\n +gadget_erp5_page_ojs_erp5_configurator.html\n +gadget_erp5_page_ojs_erp5_configurator.js\n +gadget_erp5_page_ojs_dropbox_configurator.html\n +gadget_erp5_page_ojs_dropbox_configurator.js\n +gadget_erp5_page_ojs_sync.html\n +gadget_erp5_page_ojs_sync.js\n +gadget_erp5_page_ojs_document_list.html\n +gadget_erp5_page_ojs_document_list.js\n +gadget_ojs_configurator_access.html\n +gadget_ojs_configurator_access.js\n +gadget_html5_input.html\n +gadget_html5_input.js\n +gadget_erp5_field_multicheckbox.html\n +gadget_erp5_field_multicheckbox.js\n +gadget_erp5_searchfield.html\n +gadget_erp5_searchfield.js\n +gadget_erp5_pt_form_list.html\n +gadget_erp5_pt_form_list.js\n +gadget_erp5_form.html\n +gadget_erp5_form.js\n +gadget_erp5_label_field.html\n +gadget_erp5_label_field.js\n +gadget_erp5_field_listbox.html\n +gadget_erp5_field_listbox.js\n +gadget_erp5_field_datetime.html\n +gadget_erp5_field_datetime.js\n +gadget_html5_element.html\n +gadget_html5_element.js\n +gadget_erp5_notification.html\n +gadget_erp5_notification.js\n +gadget_erp5_field_string.html\n +gadget_erp5_field_string.js\n +gadget_erp5_field_editor.html\n +gadget_erp5_field_editor.js\n +gadget_erp5_field_gadget.html\n +gadget_erp5_field_gadget.js\n +gadget_erp5_field_file.html\n +gadget_erp5_field_file.js\n +gadget_erp5_search_editor.html\n +gadget_erp5_search_editor.js\n +gadget_erp5_sort_editor.html\n +gadget_erp5_sort_editor.js\n +gadget_erp5_field_password.html\n +gadget_erp5_field_password.js\n +gadget_erp5_field_textarea.html\n +gadget_erp5_field_textarea.js\n +gadget_html5_textarea.html\n +gadget_html5_textarea.js\n +gadget_editor.html\n +gadget_editor.js\n +gadget_button_maximize.html\n +gadget_button_maximize.js\n +gadget_erp5_configure_editor.html\n +gadget_erp5_configure_editor.js\n +gadget_erp5_ojs_schema_router.html\n +gadget_erp5_ojs_schema_panel.html\n +gadget_erp5_ojs_schema_panel.js\n +gadget_officejs_jio_json_schema_view.html\n +gadget_officejs_jio_json_schema_view.js\n +gadget_officejs_jio_json_document_view.html\n +gadget_officejs_jio_json_document_view.js\n +gadget_erp5_page_ojs_multi_upload.html\n +gadget_erp5_page_ojs_multi_upload.js\n +gadget_erp5_page_ojs_zip_upload.html\n +gadget_erp5_page_ojs_zip_upload.js\n +gadget_erp5_page_ojs_schema_document_list.html\n +gadget_erp5_page_ojs_schema_document_list.js\n +\n +#jsonform\n +jio.js\n +gadget_html5_select.html\n +gadget_html5_select.js\n +json-schema/schema4.json\n +json-schema/schema6.json\n +json-schema/schema7.json\n +jsonform.gadget.html\n +jsonform.gadget.js\n +jsonform/gadget_json_generated_form_child.html\n +jsonform/gadget_json_generated_form_child.js\n +jsonform/tv4.js\n +\n +#setting\n +gadget_officejs_setting.js\n +gadget_officejs_setting.html\n +\n +\n +NETWORK:\n +* + + + title + gadget_officejs_schema.appcache + + + url_string + + + + + + version + 001 + + + workflow_history + + AAAAAAAAAAI= + + + + + + + + + + + + + data + + + + document_publication_workflow + + AAAAAAAAAAM= + + + + edit_workflow + + AAAAAAAAAAQ= + + + + processing_status_workflow + + AAAAAAAAAAU= + + + + + + + + + + + + + + + + + + + action + publish + + + actor + zope + + + comment + + + + error_message + + + + time + + + + + + + + + + + 1528361044.61 + UTC + + + + + + + validation_state + published + + + + + + + + + + + + + + + + + action + edit + + + actor + zope + + + comment + + + + + + error_message + + + + serial + 968.64277.23410.35857 + + + state + current + + + time + + + + + + + + + + + 1531936654.32 + UTC + + + + + + + + + + + + + + + + + + + + + action + detect_converted_file + + + actor + zope + + + comment + + + + error_message + + + + external_processing_state + converted + + + serial + 0.0.0.0 + + + time + + + + + + + + + + + 1528316831.84 + UTC + + + + + + + + + + + diff --git a/bt5/erp5_officejs/PathTemplateItem/web_page_module/jio_zipfilestorage-with-jszip_js.js b/bt5/erp5_officejs/PathTemplateItem/web_page_module/jio_zipfilestorage-with-jszip_js.js index 8ffc5c143b06542932895f83883835f220d63a5c..9c6c7062b9da6a3dc66749f4ece71ab07f606847 100644 --- a/bt5/erp5_officejs/PathTemplateItem/web_page_module/jio_zipfilestorage-with-jszip_js.js +++ b/bt5/erp5_officejs/PathTemplateItem/web_page_module/jio_zipfilestorage-with-jszip_js.js @@ -139,6 +139,26 @@ for(d=1;d<=W;d++)f[d]=g=g+c[d-1]<<1;for(e=0;e<=b;e++){var h=a[2*e+1];0!==h&&(a[2 }); }; + ZipFileStorage.prototype.hasCapacity = function (name) { + return (name === "list"); + }; + + ZipFileStorage.prototype.buildQuery = function () { + return loadZip(this) + .push(function (zip) { + var dirname, + dir_list = [{id: '/', value: {}}]; + for (dirname in zip.files) { + if (zip.files.hasOwnProperty(dirname)) { + if (zip.files[dirname].dir) { + dir_list.push({id: '/' + dirname, value: {}}); + } + } + } + return dir_list; + }); + }; + ZipFileStorage.prototype.allAttachments = function (id) { id = restrictDocumentId(id); return loadZip(this) @@ -204,8 +224,8 @@ for(d=1;d<=W;d++)f[d]=g=g+c[d-1]<<1;for(e=0;e<=b;e++){var h=a[2*e+1];0!==h&&(a[2 throw new jIO.util.jIOError("Cannot find document", 404); } if (!(zip.files.hasOwnProperty(attachId) && !zip.files[attachId].dir)) { - throw new jIO.util.jIOError("Cannot find attachment: " - + '/' + id + " , " + name, + throw new jIO.util.jIOError("Cannot find attachment: " + + '/' + id + " , " + name, 404); } return zip.file(attachId).async('blob'); @@ -222,8 +242,8 @@ for(d=1;d<=W;d++)f[d]=g=g+c[d-1]<<1;for(e=0;e<=b;e++){var h=a[2*e+1];0!==h&&(a[2 throw new jIO.util.jIOError("Cannot find document", 404); } if (!(zip.files.hasOwnProperty(attachId) && !zip.files[attachId].dir)) { - throw new jIO.util.jIOError("Cannot find attachment: " - + '/' + id + " , " + name, + throw new jIO.util.jIOError("Cannot find attachment: " + + '/' + id + " , " + name, 404); } zip.remove(attachId); diff --git a/bt5/erp5_officejs/PathTemplateItem/web_page_module/jio_zipfilestorage-with-jszip_js.xml b/bt5/erp5_officejs/PathTemplateItem/web_page_module/jio_zipfilestorage-with-jszip_js.xml index b82ca2e5434471acec87a15e725a410aeb476999..d134623609357dd6bdbe60a92bb78dcdfcc0563e 100644 --- a/bt5/erp5_officejs/PathTemplateItem/web_page_module/jio_zipfilestorage-with-jszip_js.xml +++ b/bt5/erp5_officejs/PathTemplateItem/web_page_module/jio_zipfilestorage-with-jszip_js.xml @@ -242,7 +242,7 @@ serial - 960.14254.57744.3293 + 968.64417.14775.57582 state @@ -260,7 +260,7 @@ - 1498139912.86 + 1531915725.03 UTC diff --git a/bt5/erp5_officejs/PathTemplateItem/web_page_module/jio_ziptodocuments.js.js b/bt5/erp5_officejs/PathTemplateItem/web_page_module/jio_ziptodocuments.js.js new file mode 100644 index 0000000000000000000000000000000000000000..1ef04cccdc5c10d2f0f33146dc80ce85742f7a92 --- /dev/null +++ b/bt5/erp5_officejs/PathTemplateItem/web_page_module/jio_ziptodocuments.js.js @@ -0,0 +1,268 @@ +/*jslint nomen: true*/ +/*global jIO, RSVP*/ +(function (jIO, RSVP) { + "use strict"; + + function decodeJsonPointer(_str) { + // https://tools.ietf.org/html/rfc6901#section-5 + return _str.replace(/~1/g, '/').replace(/~0/g, '~'); + } + + function encodeJsonPointer(_str) { + // https://tools.ietf.org/html/rfc6901#section-5 + return _str.replace(/~/g, '~0').replace(/\//g, '~1'); + } + + /** + * The jIO ZipToDocumentsBridgeStorage extension + * + * convert set of files provided zip container as + * documents contains metadata for files + * with attachment 'body' as file content + * + * @class ZipToDocumentsBridgeStorage + * @constructor + */ + function ZipToDocumentsBridgeStorage(spec) { + this._sub_storage = jIO.createJIO(spec.sub_storage); + if (spec.generateMetadata) { + this._generateMetadata = spec.generateMetadata; + } else { + throw new jIO.util.jIOError("Need specify generateMetadata function", + 400); + /** + * used for generate metadata for files + * based on extension and file content. + * used for determine supported or not + * supported file by return undefined. + * + * @function generateMetadata + */ + // example generateMetadata function + // function generateMetadata(id, filename, path, body) { + // var ret; + // if (endsWith(filename, ".json")) { + // ret = { + // id: id, + // content_type: "application/json", + // reference: path + // }; + // if (body) { + // if (body.$schema && body.$schema !== "") { + // ret.portal_type = "JSON Schema"; + // ret.parent_relative_url = "schema_module"; + // ret.title = body.title; + // } else { + // // XXX need schema relation property + // ret.portal_type = "JSON Document"; + // ret.parent_relative_url = "document_module"; + // ret.title = body.filename; + // } + // } else { + // ret.format = "json"; + // } + // // used for detect supported extension + // return ret; + // } + // } + } + } + + + ZipToDocumentsBridgeStorage.prototype.get = function (id) { + var context = this, + path = "/" + decodeJsonPointer(id), + idx = path.lastIndexOf('/') + 1, + filename = path.substring(idx), + dirname = path.substring(0, idx), + file_supported; + path = path.substring(1); + file_supported = context._generateMetadata(id, filename, path); + if (!file_supported) { + return new RSVP.Queue() + .push(function () { + throw new jIO.util.jIOError("Cannot find document " + id, + 404); + }); + } + return context._sub_storage.getAttachment(dirname, filename, + {format: file_supported.format} + ) + .push(undefined, function (error) { + if ((error instanceof jIO.util.jIOError) && + (error.status_code === 404)) { + throw new jIO.util.jIOError("Cannot find document " + id, + 404); + + } + throw error; + }) + .push(function (attachment) { + return context._generateMetadata(id, filename, path, attachment); + }); + }; + + ZipToDocumentsBridgeStorage.prototype.allAttachments = function (id) { + var context = this, + path = "/" + decodeJsonPointer(id), + idx = path.lastIndexOf('/') + 1, + filename = path.substring(idx), + dirname = path.substring(0, idx); + return context._sub_storage.getAttachment(dirname, filename) + .push(function () { + return {"data": {}}; + }, function (error) { + if ((error instanceof jIO.util.jIOError) && + (error.status_code === 404)) { + throw new jIO.util.jIOError("Cannot find document " + id, + 404); + } + throw error; + }); + }; + + ZipToDocumentsBridgeStorage.prototype.put = function (doc_id) { + // we can not save file metadata(document in upper storage) + // in zip so do nothing + return RSVP.Queue() + .push(function () { + return doc_id; + }); + }; + + ZipToDocumentsBridgeStorage.prototype.remove = function (id) { + var context = this, + path = "/" + decodeJsonPointer(id), + idx = path.lastIndexOf('/') + 1, + filename = path.substring(idx), + dirname = path.substring(0, idx); + return context._sub_storage.removeAttachment(dirname, filename) + .push(undefined, function (error) { + if ((error instanceof jIO.util.jIOError) && + (error.status_code === 404)) { + throw new jIO.util.jIOError("Cannot find document " + id, + 404); + } + throw error; + }); + + }; + + ZipToDocumentsBridgeStorage.prototype.hasCapacity = function (capacity) { + return ((capacity === "list") || (capacity === "include")); + }; + + ZipToDocumentsBridgeStorage.prototype.buildQuery = function (options) { + var result_dict = {}, + context = this; + return context._sub_storage.allDocs() + .push(function (result) { + var i, + id, + tasks = []; + + function push_doc(k, filename, path) { + return function (json) { + result_dict[k].doc = context._generateMetadata(k, filename, path, json); + }; + } + + function f(dirname) { + return function (dir) { + var k, + path, + filename, + attachment_tasks = []; + + for (filename in dir) { + if (dir.hasOwnProperty(filename)) { + path = dirname.substring(1) + filename; + k = encodeJsonPointer(dirname.substring(1) + filename); + // check file with extension supported + if (context._generateMetadata(k, filename, path)) { + result_dict[k] = { + id: k, + value: {} + }; + if (options.include_docs) { + attachment_tasks.push( + context._sub_storage.getAttachment(id, filename) + .push(push_doc(k, filename, path)) + ); + } + } + } + } + if (attachment_tasks.length > 0) { + return RSVP.all(attachment_tasks); + } + }; + } + + for (i = 0; i < result.data.rows.length; i += 1) { + id = result.data.rows[i].id; + tasks.push(context._sub_storage.allAttachments(id) + .push(f(id))); + } + return RSVP.all(tasks); + }) + .push(function () { + var result = [], + key; + for (key in result_dict) { + if (result_dict.hasOwnProperty(key)) { + result.push(result_dict[key]); + } + } + return result; + }); + }; + + ZipToDocumentsBridgeStorage.prototype.getAttachment = function (id, + name, + options) { + if (name !== "data") { + throw new jIO.util.jIOError("Only support 'data' attachment", + 400); + } + var path = "/" + decodeJsonPointer(id), + idx = path.lastIndexOf('/') + 1, + filename = path.substring(idx), + dirname = path.substring(0, idx); + + return this._sub_storage.getAttachment(dirname, filename, options); + }; + + ZipToDocumentsBridgeStorage.prototype.putAttachment = function (id, + name, + blob) { + if (name !== "data") { + throw new jIO.util.jIOError("Only support 'data' attachment", + 400); + } + + var path = "/" + decodeJsonPointer(id), + idx = path.lastIndexOf('/') + 1, + filename = path.substring(idx), + dirname = path.substring(0, idx); + return this._sub_storage.putAttachment(dirname, filename, blob); + }; + + ZipToDocumentsBridgeStorage.prototype.removeAttachment = function (id, + name) { + if (name !== "data") { + throw new jIO.util.jIOError("Only support 'data' attachment" + + " in document:" + id, + 400); + } + // document(metadata) with attachment === attachment in zip + // so we can do nothing + }; + + ZipToDocumentsBridgeStorage.prototype.repair = function () { + return this._sub_storage.repair.apply(this._sub_storage, arguments); + }; + + jIO.addStorage('ziptodocuments', ZipToDocumentsBridgeStorage); + +}(jIO, RSVP)); diff --git a/bt5/erp5_officejs/PathTemplateItem/web_page_module/jio_ziptodocuments.js.xml b/bt5/erp5_officejs/PathTemplateItem/web_page_module/jio_ziptodocuments.js.xml new file mode 100644 index 0000000000000000000000000000000000000000..c560d6a23c13898d96c5124194f6d029893312a1 --- /dev/null +++ b/bt5/erp5_officejs/PathTemplateItem/web_page_module/jio_ziptodocuments.js.xml @@ -0,0 +1,319 @@ + + + + + + + + + + _Access_contents_information_Permission + + + Anonymous + Assignee + Assignor + Associate + Auditor + Manager + + + + + _Add_portal_content_Permission + + + Assignor + Manager + + + + + _Change_local_roles_Permission + + + Assignor + Manager + + + + + _Modify_portal_content_Permission + + + Manager + + + + + _View_Permission + + + Anonymous + Assignee + Assignor + Associate + Auditor + Manager + + + + + content_md5 + + + + + + content_type + text/javascript + + + default_reference + jio_ziptodocuments.js + + + description + + + + + + id + jio_ziptodocuments.js + + + language + + + + + + portal_type + Web Script + + + short_title + + + + + + version + + + + + + workflow_history + + AAAAAAAAAAI= + + + + + + + + + + + + + data + + + + document_publication_workflow + + AAAAAAAAAAM= + + + + edit_workflow + + AAAAAAAAAAQ= + + + + processing_status_workflow + + AAAAAAAAAAU= + + + + + + + + + + + + + + + + + + + action + publish + + + actor + zope + + + comment + + + + error_message + + + + time + + + + + + + + + + + 1531857837.73 + UTC + + + + + + + validation_state + published + + + + + + + + + + + + + + + + + action + edit + + + actor + zope + + + comment + + + + + + error_message + + + + serial + 968.63397.4495.43707 + + + state + current + + + time + + + + + + + + + + + 1531857455.0 + UTC + + + + + + + + + + + + + + + + + + + + + action + detect_converted_file + + + actor + zope + + + comment + + + + error_message + + + + external_processing_state + converted + + + serial + 0.0.0.0 + + + time + + + + + + + + + + + 1531853065.16 + UTC + + + + + + + + + + + diff --git a/bt5/erp5_officejs/PathTemplateItem/web_site_module/officejs_schema.xml b/bt5/erp5_officejs/PathTemplateItem/web_site_module/officejs_schema.xml new file mode 100644 index 0000000000000000000000000000000000000000..f95bd9c23dfd72adf0c2847e1423a175b0059eff --- /dev/null +++ b/bt5/erp5_officejs/PathTemplateItem/web_site_module/officejs_schema.xml @@ -0,0 +1,751 @@ + + + + + + + + + + _Access_contents_information_Permission + + + Anonymous + Assignee + Assignor + Associate + Auditor + Authenticated + Author + Manager + Member + Owner + Reviewer + + + + + _Add_portal_content_Permission + + + Assignor + Manager + + + + + _Add_portal_folders_Permission + + + Assignor + Manager + + + + + _Copy_or_Move_Permission + + + Assignor + Manager + + + + + _Delete_objects_Permission + + + Assignor + Manager + + + + + _Modify_portal_content_Permission + + + Assignee + Assignor + Manager + + + + + _View_Permission + + + Anonymous + Assignee + Assignor + Associate + Auditor + Authenticated + Author + Manager + Member + Owner + Reviewer + + + + + __before_publishing_traverse__ + + + + + + + + + + _defined_in_class + 1 + + + _hookname + __before_publishing_traverse__ + + + _list + + + AAAAAAAAAAI= + + + + + _prior + + + + + + + + + + + __before_traverse__ + + + + + + 99 + ERP5 Web Site/officejs_schema + + + + AAAAAAAAAAI= + + + + + + + _count + + AAAAAAAAAAM= + + + + _identity_criterion + + AAAAAAAAAAQ= + + + + _local_properties + + + + + id + frontpage_gadget_url + + + type + string + + + + + id + configuration_frontpage_gadget_url + + + type + string + + + + + id + configuration_application_title + + + type + string + + + + + id + configuration_hateoas_url + + + type + string + + + + + id + configuration_view_action_category + + + type + string + + + + + id + configuration_default_view_action_reference + + + type + string + + + + + id + configuration_panel_gadget_url + + + type + string + + + + + id + configuration_router_gadget_url + + + type + string + + + + + id + configuration_jio_gadget_url + + + type + string + + + + + id + configuration_translation_gadget_url + + + type + string + + + + + id + configuration_manifest_url + + + type + string + + + + + id + configuration_header_gadget_url + + + type + string + + + + + id + configuration_content_security_policy + + + type + string + + + + + id + configuration_x_frame_options + + + type + string + + + + + id + configuration_latest_document_version + + + type + string + + + + + id + configuration_latest_version + + + type + string + + + + + id + configuration_cache_file + + + type + string + + + + + id + configuration_redirect_url + + + type + string + + + + + id + configuration_landing_page + + + type + string + + + + + id + configuration_sub_gadget_installer + + + type + string + + + + + + + _mt_index + + AAAAAAAAAAU= + + + + _range_criterion + + AAAAAAAAAAY= + + + + _tree + + AAAAAAAAAAc= + + + + available_language + + + en + + + + + categories + + + caching_policy/must-revalidate + aggregate/web_page_module/gadget_officejs_bootloader.html + + + + + configuration_application_title + Text Editor + + + configuration_cache_file + gadget_officejs_schema.appcache + + + configuration_content_security_policy + default-src \'self\'; img-src \'self\' data:; media-src \'self\' blob:; connect-src \'self\' https://content.dropboxapi.com https://api.dropboxapi.com mail.tiolive.com data: *.host.vifib.net *.node.vifib.com *.erp5.net https://netdna.bootstrapcdn.com; script-src \'self\' \'unsafe-eval\' \'unsafe-inline\'; font-src \'self\' netdna.bootstrapcdn.com; style-src \'self\' netdna.bootstrapcdn.com \'unsafe-inline\' data:; frame-src \'self\' data: + + + configuration_default_view_action_reference + + + + + + configuration_frontpage_gadget_url + + + + + + configuration_hateoas_url + hateoas/ + + + configuration_header_gadget_url + gadget_officejs_header.html + + + configuration_jio_gadget_url + gadget_officejs_jio.html + + + configuration_landing_page + + + + + + configuration_latest_document_version + 001 + + + configuration_latest_version + app + + + configuration_manifest_url + gadget_officejs.appcache + + + configuration_panel_gadget_url + gadget_officejs_application_panel.html + + + configuration_redirect_url + app + + + configuration_router_gadget_url + gadget_officejs_text_editor_router.html + + + configuration_sub_gadget_installer + + + + + + configuration_translation_gadget_url + gadget_translation.html + + + configuration_view_action_category + + + + + + configuration_x_frame_options + SAMEORIGIN + + + container_layout + WebSection_renderOfficeJSApplicationPage + + + content_layout + WebSection_renderOfficeJSApplicationPage + + + custom_render_method_id + WebSection_renderOfficeJSApplicationPage + + + description + + + + + + frontpage_gadget_url + gadget_woelfel_pt_frontpage.html + + + id + officejs_schema + + + layout_configuration_form_id + WebSection_viewOfficeJSApplicationPreference + + + portal_type + Web Site + + + short_title + + + + + + skin_selection_name + RJS + + + static_language_selection + 0 + + + title + OfficeJS Schema Editor + + + visible + 1 + + + workflow_history + + AAAAAAAAAAg= + + + + + + + + + + + + + + + + + + 0 + + + + + + + + + data + + + + + + + + + + + + + + + + + + + + + + + data + + + + + + + + + + + + + + + + + + + + + + + data + + + + category_publication_workflow + + AAAAAAAAAAk= + + + + edit_workflow + + AAAAAAAAAAo= + + + + + + + + + + + + + + + + + + + action + publish + + + actor + zope + + + comment + + + + error_message + + + + time + + + + + + + + + + + 1532439048.88 + UTC + + + + + + + validation_state + published + + + + + + + + + + + + + + + + + action + edit + + + actor + zope + + + comment + + + + + + error_message + + + + serial + 968.21791.29852.58675 + + + state + current + + + time + + + + + + + + + + + 1529569812.75 + UTC + + + + + + + + + + + diff --git a/bt5/erp5_officejs/PathTemplateItem/web_site_module/officejs_schema/app.xml b/bt5/erp5_officejs/PathTemplateItem/web_site_module/officejs_schema/app.xml new file mode 100644 index 0000000000000000000000000000000000000000..2026866a5253b5dd1c143dd6058183ce35de106f --- /dev/null +++ b/bt5/erp5_officejs/PathTemplateItem/web_site_module/officejs_schema/app.xml @@ -0,0 +1,664 @@ + + + + + + + + + + _Add_portal_content_Permission + + + Assignor + Manager + + + + + _Add_portal_folders_Permission + + + Assignor + Manager + + + + + _Copy_or_Move_Permission + + + Assignor + Manager + + + + + _Delete_objects_Permission + + + Assignor + Manager + + + + + _Modify_portal_content_Permission + + + Assignee + Assignor + Manager + Owner + + + + + __before_publishing_traverse__ + + + + + + + + + + _defined_in_class + 1 + + + _hookname + __before_publishing_traverse__ + + + _list + + + AAAAAAAAAAI= + + + + + _prior + + + + + + + + + + + __before_traverse__ + + + + + + 99 + ERP5 Web Section/app + + + + AAAAAAAAAAI= + + + + + + + __translation_dict + + + + + + _count + + AAAAAAAAAAM= + + + + _identity_criterion + + AAAAAAAAAAQ= + + + + _local_properties + + + + + id + configuration_router_gadget_url + + + type + string + + + + + id + configuration_application_title + + + type + string + + + + + id + configuration_jio_gadget_url + + + type + string + + + + + id + configuration_content_security_policy + + + type + string + + + + + id + configuration_panel_gadget_url + + + type + string + + + + + id + configuration_translation_gadget_url + + + type + string + + + + + id + configuration_header_gadget_url + + + type + string + + + + + id + configuration_hateoas_url + + + type + string + + + + + id + configuration_manifest_url + + + type + string + + + + + id + configuration_x_frame_options + + + type + string + + + + + id + configuration_default_jio_document_page_gadget_url + + + type + string + + + + + id + configuration_default_view_action_reference + + + type + string + + + + + id + configuration_frontpage_gadget_url + + + type + string + + + + + id + configuration_view_action_category + + + type + string + + + + + id + configuration_stylesheet_url + + + type + string + + + + + + + _mt_index + + AAAAAAAAAAU= + + + + _range_criterion + + AAAAAAAAAAY= + + + + _tree + + AAAAAAAAAAc= + + + + categories + + + caching_policy/must-revalidate + aggregate/web_page_module/rjs_gadget_erp5_launcher_html + + + + + configuration_application_title + Schema Editor + + + configuration_content_security_policy + default-src \'self\'; img-src \'self\' data:; media-src \'self\' blob:; connect-src \'self\' https://content.dropboxapi.com https://api.dropboxapi.com mail.tiolive.com data: *.host.vifib.net *.node.vifib.com *.erp5.net https://netdna.bootstrapcdn.com; script-src \'self\' \'unsafe-eval\' \'unsafe-inline\'; font-src \'self\' netdna.bootstrapcdn.com; style-src \'self\' netdna.bootstrapcdn.com \'unsafe-inline\' data:; frame-src \'self\' data: + + + configuration_default_jio_document_page_gadget_url + ojs_controller + + + configuration_default_view_action_reference + jio_view + + + configuration_frontpage_gadget_url + ojs_schema_document_list + + + configuration_hateoas_url + ../hateoas/ + + + configuration_header_gadget_url + gadget_erp5_header.html + + + configuration_jio_gadget_url + gadget_ojs_jio.html + + + configuration_manifest_url + gadget_officejs_schema.appcache + + + configuration_panel_gadget_url + gadget_erp5_ojs_schema_panel.html + + + configuration_router_gadget_url + gadget_erp5_ojs_schema_router.html + + + configuration_stylesheet_url + + + + + + configuration_translation_gadget_url + + + + + + configuration_view_action_category + + + + + + configuration_x_frame_options + SAMEORIGIN + + + container_layout + WebSection_renderDefaultPageAsGadget + + + content_layout + WebSection_renderDefaultPageAsGadget + + + custom_render_method_id + WebSection_renderDefaultPageAsGadget + + + description + + + + + + empty_criterion_valid + 1 + + + id + app + + + int_index + + + + + + layout_configuration_form_id + WebSection_viewRenderJSPreference + + + membership_criterion_category + + + + + + portal_type + Web Section + + + short_title + + + + + + skin_selection_name + RJS + + + string_index + + + + + + test_method_id + + + + + + title + app + + + visible + 0 + + + workflow_history + + AAAAAAAAAAg= + + + + + + + + + + + + + + + + + + 0 + + + + + + + + + data + + + + + + + + + + + + + + + + + + + + + + + data + + + + + + + + + + + + + + + + + + + + + + + data + + + + category_publication_workflow + + AAAAAAAAAAk= + + + + edit_workflow + + AAAAAAAAAAo= + + + + + + + + + + + + + + + + + + + action + publish + + + actor + zope + + + comment + + + + error_message + + + + time + + + + + + + + + + + 1528355166.8 + UTC + + + + + + + validation_state + published + + + + + + + + + + + + + + + + + action + edit + + + actor + zope + + + comment + + + + + + error_message + + + + serial + 968.21792.18763.37393 + + + state + current + + + time + + + + + + + + + + + 1529569802.7 + UTC + + + + + + + + + + + diff --git a/bt5/erp5_officejs/bt/dependency_list b/bt5/erp5_officejs/bt/dependency_list index 21d3ddb98a51761c250f183b7badfec0cda9f6dc..acdf8b6ac1e54c008548931535f14fb104faaf0d 100644 --- a/bt5/erp5_officejs/bt/dependency_list +++ b/bt5/erp5_officejs/bt/dependency_list @@ -1,5 +1,6 @@ erp5_web_renderjs_ui erp5_code_mirror +erp5_json_form erp5_multimedia erp5_notebook erp5_smart_assistant \ No newline at end of file diff --git a/bt5/erp5_officejs/bt/template_keep_last_workflow_history_only_path_list b/bt5/erp5_officejs/bt/template_keep_last_workflow_history_only_path_list index 1e07a43d03ccfdccc1a6ccc8a62b216e58576ca2..9f759160bc95e1a9159db04e636a3aacadbfa10b 100644 --- a/bt5/erp5_officejs/bt/template_keep_last_workflow_history_only_path_list +++ b/bt5/erp5_officejs/bt/template_keep_last_workflow_history_only_path_list @@ -7,6 +7,8 @@ image_module/officejs_todomvc_* image_module/wallsearch_icon_svg web_page_module/dhtmlx_gantt_* web_page_module/fb_sdk_js +web_page_module/gadget_erp5_ojs_* +web_page_module/gadget_erp5_page_ojs_* web_page_module/gadget_field_* web_page_module/gadget_officejs_* web_page_module/jio_* @@ -32,6 +34,8 @@ web_site_module/officejs_notebook web_site_module/officejs_notebook/** web_site_module/officejs_pdf_viewer web_site_module/officejs_pdf_viewer/** +web_site_module/officejs_schema +web_site_module/officejs_schema/** web_site_module/officejs_svg_editor web_site_module/officejs_svg_editor/** web_site_module/officejs_text_editor diff --git a/bt5/erp5_officejs/bt/template_keep_workflow_path_list b/bt5/erp5_officejs/bt/template_keep_workflow_path_list index d595038c4cf2f453c9bcc7bda0ab3f28ab06cfa1..5f86f468c970be9a8a97f64ce9082a890487349b 100644 --- a/bt5/erp5_officejs/bt/template_keep_workflow_path_list +++ b/bt5/erp5_officejs/bt/template_keep_workflow_path_list @@ -7,6 +7,8 @@ image_module/officejs_todomvc_* image_module/wallsearch_icon_svg web_page_module/dhtmlx_gantt_* web_page_module/fb_sdk_js +web_page_module/gadget_erp5_ojs_* +web_page_module/gadget_erp5_page_ojs_* web_page_module/gadget_field_* web_site_module/officejs_media_player web_page_module/gadget_officejs_* @@ -32,6 +34,8 @@ web_site_module/officejs_notebook web_site_module/officejs_notebook/** web_site_module/officejs_pdf_viewer web_site_module/officejs_pdf_viewer/** +web_site_module/officejs_schema +web_site_module/officejs_schema/** web_site_module/officejs_svg_editor web_site_module/officejs_svg_editor/** web_site_module/officejs_text_editor diff --git a/bt5/erp5_officejs/bt/template_path_list b/bt5/erp5_officejs/bt/template_path_list index cd9a8ebdcfa66adbac26db33077fdde505c93ddc..95a92147f018062dad6bcb534b6ecf3089a315c9 100644 --- a/bt5/erp5_officejs/bt/template_path_list +++ b/bt5/erp5_officejs/bt/template_path_list @@ -7,6 +7,8 @@ image_module/officejs_todomvc_* image_module/wallsearch_icon_svg web_page_module/dhtmlx_gantt_* web_page_module/fb_sdk_js +web_page_module/gadget_erp5_ojs_* +web_page_module/gadget_erp5_page_ojs_* web_page_module/gadget_field_* web_page_module/gadget_officejs_* web_page_module/jio_* @@ -33,6 +35,8 @@ web_site_module/officejs_notebook web_site_module/officejs_notebook/** web_site_module/officejs_pdf_viewer web_site_module/officejs_pdf_viewer/** +web_site_module/officejs_schema +web_site_module/officejs_schema/** web_site_module/officejs_smart_assistant web_site_module/officejs_smart_assistant/** web_site_module/officejs_svg_editor diff --git a/bt5/erp5_officejs_ui_test/PathTemplateItem/portal_tests/officejs_ui_schema_editor_zuite.xml b/bt5/erp5_officejs_ui_test/PathTemplateItem/portal_tests/officejs_ui_schema_editor_zuite.xml new file mode 100644 index 0000000000000000000000000000000000000000..42dc26d3a4be8b5d57d941736d4a06ded196cd4c --- /dev/null +++ b/bt5/erp5_officejs_ui_test/PathTemplateItem/portal_tests/officejs_ui_schema_editor_zuite.xml @@ -0,0 +1,26 @@ + + + + + + + + + + _objects + + + + + + id + officejs_ui_schema_editor_zuite + + + title + + + + + + diff --git a/bt5/erp5_officejs_ui_test/PathTemplateItem/portal_tests/officejs_ui_schema_editor_zuite/testOfficeJSchemaEditor.xml b/bt5/erp5_officejs_ui_test/PathTemplateItem/portal_tests/officejs_ui_schema_editor_zuite/testOfficeJSchemaEditor.xml new file mode 100644 index 0000000000000000000000000000000000000000..19f794ed4d2104cab6669bae938e68d80da135e4 --- /dev/null +++ b/bt5/erp5_officejs_ui_test/PathTemplateItem/portal_tests/officejs_ui_schema_editor_zuite/testOfficeJSchemaEditor.xml @@ -0,0 +1,58 @@ + + + + + + + + + + _bind_names + + + + + + + + + + _asgns + + + + name_subpath + traverse_subpath + + + + + + + + + + + content_type + text/html + + + expand + 0 + + + id + testOfficeJSchemaEditor + + + output_encoding + utf-8 + + + title + + + + + + diff --git a/bt5/erp5_officejs_ui_test/PathTemplateItem/portal_tests/officejs_ui_schema_editor_zuite/testOfficeJSchemaEditor.zpt b/bt5/erp5_officejs_ui_test/PathTemplateItem/portal_tests/officejs_ui_schema_editor_zuite/testOfficeJSchemaEditor.zpt new file mode 100644 index 0000000000000000000000000000000000000000..1fb5ab045b4c9fe6ab85207c39d63536ad968866 --- /dev/null +++ b/bt5/erp5_officejs_ui_test/PathTemplateItem/portal_tests/officejs_ui_schema_editor_zuite/testOfficeJSchemaEditor.zpt @@ -0,0 +1,104 @@ + + + + Test Media Player UI + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test OfficeJS UI
waitForElementPresent//a[@data-i18n='Storages']
click//a[@data-i18n='Storages']
waitForElementPresentlink=Local is Enough
clicklink=Local is Enough
waitForElementPresent//a[@data-i18n='Add']
verifyTextPresentSchemas
verifyTextPresentAdd
click//a[@data-i18n='Add']
waitForElementPresent//button[@data-i18n='Save']
verifyTextPresentUpload
verifyTextPresentSave
click//a[@data-i18n='Schemas']
verifyElementPresent//a[text()='Untitled Schema']
verifyTextPresentSchemas
verifyTextPresentFilter
verifyTextPresentAdd
+ + \ No newline at end of file diff --git a/bt5/erp5_officejs_ui_test/TestTemplateItem/portal_components/test.erp5.testFunctionalOfficeJSSchemaEditor.py b/bt5/erp5_officejs_ui_test/TestTemplateItem/portal_components/test.erp5.testFunctionalOfficeJSSchemaEditor.py new file mode 100644 index 0000000000000000000000000000000000000000..0f730cdede4fc9046e8aa7422435ac032b5994f6 --- /dev/null +++ b/bt5/erp5_officejs_ui_test/TestTemplateItem/portal_components/test.erp5.testFunctionalOfficeJSSchemaEditor.py @@ -0,0 +1,47 @@ +############################################################################## +# +# Copyright (c) 2011 Nexedi SARL and Contributors. All Rights Reserved. +# Kazuhiko +# Rafael Monnerat +# +# WARNING: This program as such is intended to be used by professional +# programmers who take the whole responsability of assessing all potential +# consequences resulting from its eventual inadequacies and bugs +# End users who are looking for a ready-to-use solution with commercial +# garantees and support are strongly adviced to contract a Free Software +# Service Company +# +# This program is Free Software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################## +import unittest + +from Products.ERP5Type.tests.ERP5TypeFunctionalTestCase import ERP5TypeFunctionalTestCase + +class TestOfficejSUISchemaEditor(ERP5TypeFunctionalTestCase): + foreground = 0 + run_only = "officejs_ui_schema_editor_zuite" + + def getBusinessTemplateList(self): + return ( + 'erp5_officejs', + 'erp5_officejs_ui_test', + 'erp5_ui_test_core', + ) + +def test_suite(): + suite = unittest.TestSuite() + suite.addTest(unittest.makeSuite(TestOfficejSUISchemaEditor)) + return suite diff --git a/bt5/erp5_officejs_ui_test/TestTemplateItem/portal_components/test.erp5.testFunctionalOfficeJSSchemaEditor.xml b/bt5/erp5_officejs_ui_test/TestTemplateItem/portal_components/test.erp5.testFunctionalOfficeJSSchemaEditor.xml new file mode 100644 index 0000000000000000000000000000000000000000..57e6aa0a088b3a601e77eb790eedacc4ec2afb13 --- /dev/null +++ b/bt5/erp5_officejs_ui_test/TestTemplateItem/portal_components/test.erp5.testFunctionalOfficeJSSchemaEditor.xml @@ -0,0 +1,102 @@ + + + + + + + + + + default_reference + testFunctionalOfficeJSSchemaEditor + + + description + + + + + + id + test.erp5.testFunctionalOfficeJSSchemaEditor + + + portal_type + Test Component + + + sid + + + + + + text_content_error_message + + + + + + text_content_warning_message + + + + + + version + erp5 + + + workflow_history + + AAAAAAAAAAI= + + + + + + + + + + + + + data + + + + component_validation_workflow + + AAAAAAAAAAM= + + + + + + + + + + + + + + + + + + + action + validate + + + validation_state + validated + + + + + + + diff --git a/bt5/erp5_officejs_ui_test/bt/template_test_id_list b/bt5/erp5_officejs_ui_test/bt/template_test_id_list index d99e0ec7233dd3e00fad42a93ed774981c3dd93e..81c8efeb44801e0160860722f59b72869457d849 100644 --- a/bt5/erp5_officejs_ui_test/bt/template_test_id_list +++ b/bt5/erp5_officejs_ui_test/bt/template_test_id_list @@ -1,4 +1,5 @@ test.erp5.testFunctionalOfficeJSSmartAssistant +test.erp5.testFunctionalOfficeJSSchemaEditor test.erp5.testFunctionalOfficeJSTextEditor test.erp5.testFunctionalOfficeJSCodeMirror test.erp5.testFunctionalOfficeJSMediaPlayer diff --git a/bt5/erp5_only_office/SkinTemplateItem/portal_skins/erp5_only_office/zipfilestorage-with-jszip.js.js b/bt5/erp5_only_office/SkinTemplateItem/portal_skins/erp5_only_office/zipfilestorage-with-jszip.js.js index 8ffc5c143b06542932895f83883835f220d63a5c..9c6c7062b9da6a3dc66749f4ece71ab07f606847 100644 --- a/bt5/erp5_only_office/SkinTemplateItem/portal_skins/erp5_only_office/zipfilestorage-with-jszip.js.js +++ b/bt5/erp5_only_office/SkinTemplateItem/portal_skins/erp5_only_office/zipfilestorage-with-jszip.js.js @@ -139,6 +139,26 @@ for(d=1;d<=W;d++)f[d]=g=g+c[d-1]<<1;for(e=0;e<=b;e++){var h=a[2*e+1];0!==h&&(a[2 }); }; + ZipFileStorage.prototype.hasCapacity = function (name) { + return (name === "list"); + }; + + ZipFileStorage.prototype.buildQuery = function () { + return loadZip(this) + .push(function (zip) { + var dirname, + dir_list = [{id: '/', value: {}}]; + for (dirname in zip.files) { + if (zip.files.hasOwnProperty(dirname)) { + if (zip.files[dirname].dir) { + dir_list.push({id: '/' + dirname, value: {}}); + } + } + } + return dir_list; + }); + }; + ZipFileStorage.prototype.allAttachments = function (id) { id = restrictDocumentId(id); return loadZip(this) @@ -204,8 +224,8 @@ for(d=1;d<=W;d++)f[d]=g=g+c[d-1]<<1;for(e=0;e<=b;e++){var h=a[2*e+1];0!==h&&(a[2 throw new jIO.util.jIOError("Cannot find document", 404); } if (!(zip.files.hasOwnProperty(attachId) && !zip.files[attachId].dir)) { - throw new jIO.util.jIOError("Cannot find attachment: " - + '/' + id + " , " + name, + throw new jIO.util.jIOError("Cannot find attachment: " + + '/' + id + " , " + name, 404); } return zip.file(attachId).async('blob'); @@ -222,8 +242,8 @@ for(d=1;d<=W;d++)f[d]=g=g+c[d-1]<<1;for(e=0;e<=b;e++){var h=a[2*e+1];0!==h&&(a[2 throw new jIO.util.jIOError("Cannot find document", 404); } if (!(zip.files.hasOwnProperty(attachId) && !zip.files[attachId].dir)) { - throw new jIO.util.jIOError("Cannot find attachment: " - + '/' + id + " , " + name, + throw new jIO.util.jIOError("Cannot find attachment: " + + '/' + id + " , " + name, 404); } zip.remove(attachId); diff --git a/bt5/erp5_only_office/SkinTemplateItem/portal_skins/erp5_only_office/zipfilestorage-with-jszip.js.xml b/bt5/erp5_only_office/SkinTemplateItem/portal_skins/erp5_only_office/zipfilestorage-with-jszip.js.xml index 396dab6e6d1c5a85a86fafb7eb847d6278bb0e83..0013f9fc2e5e453784f079d1f56a09e5b8affeeb 100644 --- a/bt5/erp5_only_office/SkinTemplateItem/portal_skins/erp5_only_office/zipfilestorage-with-jszip.js.xml +++ b/bt5/erp5_only_office/SkinTemplateItem/portal_skins/erp5_only_office/zipfilestorage-with-jszip.js.xml @@ -6,13 +6,17 @@ + + _Cacheable__manager_id + http_cache + __name__ zipfilestorage-with-jszip.js content_type - application/javascript + text/javascript precondition @@ -20,7 +24,7 @@ title - zipfilestorage-with-jszip.js + diff --git a/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_label_field_js.js b/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_label_field_js.js index 29a23fe1c65e7f6c64bfbeaa0b0d9772a7730c66..61e310aba850afdbc9fbdfbf53ce216cc2c2d815 100644 --- a/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_label_field_js.js +++ b/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_label_field_js.js @@ -141,6 +141,7 @@ if (this.state.error_text) { if (span === null) { span = document.createElement('span'); + span.setAttribute('class', 'error'); span.textContent = this.state.error_text; this.props.container_element.appendChild(span); } else { diff --git a/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_launcher_js.js b/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_launcher_js.js index 04a77484b1108de75066ecbde2c6b5dc6d31da46..648da6ed7cf7bc530556d44a352c51941d05bf2b 100644 --- a/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_launcher_js.js +++ b/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_launcher_js.js @@ -31,10 +31,6 @@ }; } - function initPanelOptions(gadget) { - gadget.props.panel_argument_list = {}; - } - function route(my_root_gadget, my_scope, my_method, argument_list) { return my_root_gadget.getDeclaredGadget(my_scope) .push(function (my_gadget) { @@ -45,7 +41,7 @@ }); } - function updateHeader(gadget) { + function lUpdateHeader(gadget) { var header_gadget; return gadget.getDeclaredGadget("header") .push(function (result) { @@ -57,10 +53,10 @@ }); } - function updatePanel(gadget) { + function lUpdatePanel(gadget, panel_state) { return gadget.getDeclaredGadget("panel") .push(function (panel_gadget) { - return panel_gadget.render(gadget.props.panel_argument_list); + return panel_gadget.render(panel_state || {}); }); } @@ -473,9 +469,7 @@ }) .allowPublicAcquisition("updatePanel", function updatePanel(param_list) { - var gadget = this; - initPanelOptions(gadget); - gadget.props.panel_argument_list = param_list[0]; + return lUpdatePanel(this, param_list[0]); }) .allowPublicAcquisition('hidePanel', function hidePanel(param_list) { @@ -593,8 +587,8 @@ element.appendChild(content_container); return RSVP.all([ - updateHeader(gadget), - updatePanel(gadget) + lUpdateHeader(gadget), + lUpdatePanel(gadget) ]); // XXX Drop notification // return header_gadget.notifyLoaded(); @@ -609,8 +603,8 @@ }) .push(function () { return RSVP.all([ - updateHeader(gadget), - updatePanel(gadget) + lUpdateHeader(gadget), + lUpdatePanel(gadget) ]); }); }) @@ -623,7 +617,6 @@ // By default, init the header options to be empty // (ERP5 title by default + sidebar) initHeaderOptions(gadget); - initPanelOptions(gadget); return increaseLoadingCounter(gadget) .push(function () { var promise_list = [ @@ -670,4 +663,4 @@ }); }(window, document, RSVP, rJS, - XMLHttpRequest, location, console, navigator, ProgressEvent)); \ No newline at end of file + XMLHttpRequest, location, console, navigator, ProgressEvent)); diff --git a/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_nojqm_css.css b/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_nojqm_css.css index 57a10bb18fdef7832b2f6ebb0df9947621964e91..cabde9d709789ba51330d861ff798219f564ee7e 100644 --- a/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_nojqm_css.css +++ b/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_nojqm_css.css @@ -1190,11 +1190,11 @@ div[data-gadget-scope='header'] .ui-header ul { .gadget-content form .ui-field-contain { position: relative; } -.gadget-content form .ui-field-contain > span { +.gadget-content form .ui-field-contain > span.error { animation: fadein 0.2s ease-out; } @media not screen and (max-width: 85em), only screen and (min-width: 45em) and (max-width: 85em) { - .gadget-content form .ui-field-contain > span { + .gadget-content form .ui-field-contain > span.error { background-color: #FF6600; color: #f8fff3; left: 25%; @@ -1206,7 +1206,7 @@ div[data-gadget-scope='header'] .ui-header ul { width: auto; z-index: 1001; } - .gadget-content form .ui-field-contain > span:before { + .gadget-content form .ui-field-contain > span.error:before { position: absolute; top: 100%; left: 2em; @@ -1218,7 +1218,7 @@ div[data-gadget-scope='header'] .ui-header ul { } } @media not screen and (min-width: 45em) { - .gadget-content form .ui-field-contain > span { + .gadget-content form .ui-field-contain > span.error { margin-left: 6pt; color: #FF6600; } @@ -1802,6 +1802,39 @@ div[data-gadget-url$="gadget_erp5_page_front.html"] > ul > li li { padding: 3pt 6pt; } /********************************************** +* JSONForm +**********************************************/ +fieldset > .jsonformfield { + padding-left: 0; +} +.jsonformfield { + display: flex; + /*padding-left: 20px;*/ + padding-top: 3px; + /*margin-left: 15px;*/ +} +.jsonformfield button { + display: block; + vertical-align: top; +} +.jsonformfield .ui-btn-icon-top::before { + vertical-align: top; +} +.jsonformfield label { + word-break: keep-all; + hyphens: none; +} +.jsonformfield span { + color: #5e7f8d; +} +.jsonformfield .error { + color: #E82525; + font-weight: 600; +} +.jsonformfield input[type=number] { + text-align: right; +} +/********************************************** * Icons **********************************************/ .ui-btn-icon-top::before, diff --git a/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_html5_select_js.js b/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_html5_select_js.js index def1b3120e5001bf59aea942e98a9a1420b42eb2..76f2718b0fd63981373eaaeed21cd85597e44eab 100644 --- a/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_html5_select_js.js +++ b/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_html5_select_js.js @@ -136,16 +136,16 @@ }) .declareAcquiredMethod("notifyChange", "notifyChange") - .onEvent('change', function change() { + .onEvent('change', function change(e) { return RSVP.all([ this.checkValidity(), - this.notifyChange() + this.notifyChange(e) ]); }, false, false) - .onEvent('input', function input() { + .onEvent('input', function input(e) { return RSVP.all([ this.checkValidity(), - this.notifyChange() + this.notifyChange(e) ]); }, false, false) diff --git a/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs_ui/erp5css.less.txt b/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs_ui/erp5css.less.txt index bb41eb4038018652ea750c335089d8bb82d985d3..fcd6358b7fe54a81069daab94dd6aaf005f052b3 100644 --- a/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs_ui/erp5css.less.txt +++ b/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs_ui/erp5css.less.txt @@ -1403,7 +1403,7 @@ div[data-gadget-scope='header'] .ui-header { // relative for displaying popups with errors position: relative; - & > span { + & > span.error { animation: fadein @transition-timing; @media @desktop, @tablet { @@ -2045,6 +2045,42 @@ div[data-gadget-url$="gadget_erp5_page_front.html"] { } } +/********************************************** +* JSONForm +**********************************************/ + +fieldset > .jsonformfield { + padding-left: 0 +} + +.jsonformfield { + display: flex; + /*padding-left: 20px;*/ + padding-top: 3px; + /*margin-left: 15px;*/ + button { + display: block; + vertical-align: top; + } + .ui-btn-icon-top::before { + vertical-align: top; + } + label { + word-break: keep-all; + hyphens: none; + } + span { + color: rgb(94, 127, 141) + } + .error { + color: #E82525; + font-weight: 600; + } + input[type=number] { + text-align:right; + } +} + /********************************************** * Icons **********************************************/ diff --git a/tests/__init__.py b/tests/__init__.py index 571fd45fd71bd8e86bed19df248d1eb6fd858cc3..c2f559dd20ad956e2145b4d9eef16db4fa0f4a21 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -35,9 +35,20 @@ class _ERP5(ERP5TypeTestSuite): component_re = re.compile(".*/([^/]+)/TestTemplateItem/portal_components" "/test\.[^.]+\.([^.]+).py$") for test_path in ( - glob('%s/product/*/tests/test*.py' % path) + - glob('%s/bt5/*/TestTemplateItem/test*.py' % path) + - glob('%s/bt5/*/TestTemplateItem/portal_components/test.*.test*.py' % path)): + # glob('%s/product/Formulator/tests/test*.py' % path) + + # glob('%s/product/ERP5Form/tests/test*.py' % path) + + # ['%s/product/ERP5/tests/testXHTML.py' % path] + + # ['%s/product/ERP5Type/tests/testFunctionalCore.py' % path] + + # ['%s/product/ERP5Type/tests/testFunctionalAnonymousSelection.py' % path] + + # glob('%s/bt5/erp5_hal_json_style/TestTemplateItem/portal_components/test.*.test*.py' % path) + + # glob('%s/bt5/erp5_ui_test/TestTemplateItem/portal_components/test.*.test*.py' % path) + + # glob('%s/bt5/erp5_token_login/TestTemplateItem/portal_components/test.*.test*.py' % path) + + # glob('%s/bt5/erp5_pdm_renderjs_ui_test/TestTemplateItem/portal_components/test.*.test*.py' % path) + + # glob('%s/bt5/erp5_crm_renderjs_ui_test/TestTemplateItem/portal_components/test.*.test*.py' % path) + + # glob('%s/bt5/erp5_accounting_renderjs_ui_test/TestTemplateItem/portal_components/test.*.test*.py' % path) + + # glob('%s/bt5/erp5_gadget_interface_validator_ui_test/TestTemplateItem/portal_components/test.*.test*.py' % path) + + # glob('%s/bt5/erp5_web_renderjs_ui_test/TestTemplateItem/portal_components/test.*.test*.py' % path)): + glob('%s/bt5/erp5_officejs_ui_test/TestTemplateItem/portal_components/test.erp5.testFunctionalOfficeJSSchemaEditor.py' % path)): component_re_match = component_re.match(test_path) if component_re_match is not None: test_case = "%s:%s" % (component_re_match.group(1),