Commit 7df80c9d authored by Boris Kocherov's avatar Boris Kocherov

support anyOf in object.additionalProperties and array.items

parent 1cca3113
...@@ -160,6 +160,7 @@ ...@@ -160,6 +160,7 @@
form_gadget.element.setAttribute("data-json-property-name", property_name); form_gadget.element.setAttribute("data-json-property-name", property_name);
} }
return form_gadget.renderForm({ return form_gadget.renderForm({
type: options.type,
schema: options.schema_part, schema: options.schema_part,
schema_path: options.schema_path, schema_path: options.schema_path,
document: options.default_dict, document: options.default_dict,
...@@ -169,26 +170,100 @@ ...@@ -169,26 +170,100 @@
}); });
} }
function render_select_type(gadget, title, type_arr, event) { function anyOf(g, schema_array, schema_path) {
var scope = Math.random().toString(36).substr(2, 9); return RSVP.Queue()
if (!type_arr || type_arr === true) { .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][z].length; z += 1) {
if (arr[i][z].schema === true) {
// or(any, restricted, restricted) simplify to any
return [arr[i][z]];
}
}
schema_arr.concat(arr[i]);
}
return schema_arr;
});
}
function render_select_type(gadget, title, schema_arr, event) {
var scope = Math.random().toString(36).substr(2, 9),
type_arr = [],
schema_item,
description,
i,
z,
type,
schema_path;
if (schema_arr.length === 1 && schema_arr[0].schema === true) {
type_arr = [
"string",
"number",
"boolean",
"array",
"object",
"null"
];
schema_path = schema_arr[0].schema_path;
} else {
for (i = 0; i < schema_arr.length; i += 1) {
schema_item = schema_arr[i];
description = schema_item.schema.$ref || schema_item.schema.title;
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];
type_arr.push({
title: description + ' # ' + type,
value: {
type: type,
schema_path: schema_item.schema_path,
schema: schema_item.schema
}
});
}
} else {
description = description ||
schema_item.schema.type ||
schema_item.schema.description;
type_arr.push({
title: description,
value: {
type: undefined,
schema_path: schema_item.schema_path,
schema: schema_item.schema
}
});
}
}
}
if (type_arr.length > 1) {
return gadget.declareGadget("gadget_html5_select.html", {scope: scope}) return gadget.declareGadget("gadget_html5_select.html", {scope: scope})
.push(function (g) { .push(function (g) {
var i, var x,
item_list = [[title, title]], item_list = [[title, title]],
render_options; render_options,
if (!type_arr || type_arr === true) { item,
type_arr = [ jsonify = type_arr[0].title;
"string", for (x = 0; x < type_arr.length; x += 1) {
"number", item = type_arr[x];
"boolean", if (jsonify) {
"array", item_list.push([item.title, JSON.stringify(item.value)]);
"object", } else {
"null" item_list.push([item, item]);
]; }
}
for (i = 0; i < type_arr.length; i += 1) {
item_list.push([type_arr[i], type_arr[i]]);
} }
render_options = { render_options = {
name: scope, name: scope,
...@@ -202,7 +277,13 @@ ...@@ -202,7 +277,13 @@
event: function () { event: function () {
return g.getContent() return g.getContent()
.push(function (value) { .push(function (value) {
return event(value[scope]); if (jsonify) {
return event(JSON.parse(value[scope]));
}
return event({
schema_path: schema_path,
schema: { type: value[scope] }
});
}) })
.push(function () { .push(function () {
return g.render(render_options); return g.render(render_options);
...@@ -225,7 +306,7 @@ ...@@ -225,7 +306,7 @@
input.type = "button"; input.type = "button";
gadget.props.add_buttons.push({ gadget.props.add_buttons.push({
element: input, element: input,
event: event.bind(gadget, undefined) event: event.bind(gadget, schema_arr[0])
}); });
return input; return input;
}); });
...@@ -254,15 +335,22 @@ ...@@ -254,15 +335,22 @@
item_schema = json_field.items; item_schema = json_field.items;
queue queue
.push(render_select_type.bind(gadget, gadget, "add item to array", item_schema, function (value) { .push(function () {
return addSubForm({ return expandSchema(gadget, item_schema, schema_path + '/items');
gadget: gadget, })
parent_type: 'array', .push(function (schema_arr) {
schema_path: schema_path + '/items', return render_select_type(gadget, "add item to array",
schema_part: (value && {type: value}) || item_schema schema_arr, function (value) {
}) return addSubForm({
.push(element_append); gadget: gadget,
})) parent_type: 'array',
type: value.type,
schema_path: value.schema_path,
schema_part: value.schema
})
.push(element_append);
});
})
.push(function (element) { .push(function (element) {
input = element; input = element;
// XXX update on every add/delete item // XXX update on every add/delete item
...@@ -293,15 +381,27 @@ ...@@ -293,15 +381,27 @@
} }
function expandSchema(g, schema, schema_path) { function expandSchema(g, schema, schema_path) {
if (schema === undefined) {
schema = true;
}
if (schema.anyOf !== undefined) {
return anyOf(g, schema.anyOf, schema_path);
}
if (schema.allOf !== undefined) {
return allOf(g, schema.allOf, schema_path);
}
if (schema.$ref) { if (schema.$ref) {
return g.loadJSONSchema(schema.$ref, schema_path) return g.loadJSONSchema(schema.$ref, schema_path)
.push(function (schema_part) { .push(function (schema_part) {
return schema_part; return expandSchema(g, schema_part, schema_path);
}); });
} }
return RSVP.Queue() return RSVP.Queue()
.push(function () { .push(function () {
return schema; return [{
schema: schema,
schema_path: schema_path
}];
}); });
} }
...@@ -317,27 +417,63 @@ ...@@ -317,27 +417,63 @@
}) })
.push(function (arr) { .push(function (arr) {
var i, var i,
x,
y,
key, key,
next_schema, next_schema,
schema = arr[0]; schema,
for (i = 1; i < arr.length; i += 1) { schema_item,
next_schema = arr[i]; summ_arr;
for (key in next_schema) { for (i = 0; i < arr.length - 1; i += 1) {
if (next_schema.hasOwnProperty(key)) { summ_arr = [];
if (schema.hasOwnProperty(key)) { for (x = 0; x < arr[i].length; x += 1) {
// XXX need use many many rules for merging for (y = 0; y < arr[i + 1].length; y += 1) {
schema[key] = next_schema[key]; schema = arr[i][x].schema;
next_schema = arr[i + 1][y].schema;
if (schema === true && next_schema === true) {
schema_item = {
schema: true,
schema_path: arr[i][x].schema_path
};
} else if (schema === false || next_schema === false) {
schema_item = {
schema: false,
schema_path: arr[i][x].schema_path
};
} else { } else {
schema[key] = next_schema[key]; if (schema === true) {
schema = {};
}
if (next_schema === true) {
next_schema = {};
}
// copy before change
schema = JSON.parse(JSON.stringify(schema));
for (key in next_schema) {
if (next_schema.hasOwnProperty(key)) {
if (schema.hasOwnProperty(key)) {
// XXX need use many many rules for merging
schema[key] = next_schema[key];
} else {
schema[key] = next_schema[key];
}
}
}
schema_item = {
schema: schema,
schema_path: arr[i][x].schema_path
};
} }
summ_arr.push(schema_item);
} }
} }
arr[i + 1] = summ_arr;
} }
return schema; return arr[arr.length - 1];
}); });
} }
function render_field(gadget, key, path, json_field, default_value, root, schema_path) { function render_field(gadget, key, path, json_field, default_value, root, schema_path, type) {
var div, var div,
label, label,
div_input, div_input,
...@@ -345,8 +481,7 @@ ...@@ -345,8 +481,7 @@
span_error, span_error,
input, input,
first_path, first_path,
queue = RSVP.Queue(), queue = RSVP.Queue();
type;
if (path && key) { if (path && key) {
first_path = path + encodeJsonPointer(key); first_path = path + encodeJsonPointer(key);
...@@ -358,21 +493,9 @@ ...@@ -358,21 +493,9 @@
json_field = getDocumentSchema(default_value); json_field = getDocumentSchema(default_value);
} }
if (json_field.allOf !== undefined) { if (getDocumentType(json_field.type) === "string") {
return allOf(gadget, json_field.allOf, schema_path) type = json_field.type;
.push(function (schema_part) { } // else json_field.type is array so we use type
return render_field(gadget, key, path, schema_part, default_value, root, schema_path);
});
}
if (json_field.$ref !== undefined) {
return gadget.loadJSONSchema(json_field.$ref, schema_path)
.push(function (schema_part) {
return render_field(gadget, key, path, schema_part, default_value, root, schema_path);
});
}
type = json_field.type;
if (type === undefined && default_value) { if (type === undefined && default_value) {
type = getDocumentType(default_value); type = getDocumentType(default_value);
} }
...@@ -612,16 +735,21 @@ ...@@ -612,16 +735,21 @@
div_input.appendChild(input); div_input.appendChild(input);
queue queue
.push(render_select_type.bind(g, g, "add custom property", schema, function (value) { .push(function () {
return addSubForm({ return expandSchema(g, schema, schema_path + '/additionalProperties');
gadget: g, })
element: input, .push(function (schema_arr) {
path: path, return render_select_type(g, "add custom property", schema_arr, function (value) {
schema_path: schema_path + '/additionalProperties', return addSubForm({
schema_part: (value && {type: value}) || schema gadget: g,
}) element: input,
.push(element_append); path: path,
})) schema_path: value.schema_path,
schema_part: value.schema
})
.push(element_append);
});
})
.push(function (input) { .push(function (input) {
// XXX update on every add/delete item // XXX update on every add/delete item
div_input.appendChild(input); div_input.appendChild(input);
...@@ -1043,7 +1171,8 @@ ...@@ -1043,7 +1171,8 @@
g.props.delete_button = delete_button; g.props.delete_button = delete_button;
root.appendChild(delete_button); root.appendChild(delete_button);
} }
return render_field(g, property_name, "", schema, options.document, root, options.schema_path) return render_field(g, property_name, "", schema,
options.document, root, options.schema_path, options.type)
.push(function () { .push(function () {
g.listenEvents(); g.listenEvents();
return g.element; return g.element;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment