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

support anyOf in object.additionalProperties and array.items

parent 1cca3113
......@@ -160,6 +160,7 @@
form_gadget.element.setAttribute("data-json-property-name", property_name);
}
return form_gadget.renderForm({
type: options.type,
schema: options.schema_part,
schema_path: options.schema_path,
document: options.default_dict,
......@@ -169,26 +170,100 @@
});
}
function render_select_type(gadget, title, type_arr, event) {
var scope = Math.random().toString(36).substr(2, 9);
if (!type_arr || type_arr === true) {
function anyOf(g, schema_array, schema_path) {
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][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})
.push(function (g) {
var i,
var x,
item_list = [[title, title]],
render_options;
if (!type_arr || type_arr === true) {
type_arr = [
"string",
"number",
"boolean",
"array",
"object",
"null"
];
}
for (i = 0; i < type_arr.length; i += 1) {
item_list.push([type_arr[i], type_arr[i]]);
render_options,
item,
jsonify = type_arr[0].title;
for (x = 0; x < type_arr.length; x += 1) {
item = type_arr[x];
if (jsonify) {
item_list.push([item.title, JSON.stringify(item.value)]);
} else {
item_list.push([item, item]);
}
}
render_options = {
name: scope,
......@@ -202,7 +277,13 @@
event: function () {
return g.getContent()
.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 () {
return g.render(render_options);
......@@ -225,7 +306,7 @@
input.type = "button";
gadget.props.add_buttons.push({
element: input,
event: event.bind(gadget, undefined)
event: event.bind(gadget, schema_arr[0])
});
return input;
});
......@@ -254,15 +335,22 @@
item_schema = json_field.items;
queue
.push(render_select_type.bind(gadget, gadget, "add item to array", item_schema, function (value) {
return addSubForm({
gadget: gadget,
parent_type: 'array',
schema_path: schema_path + '/items',
schema_part: (value && {type: value}) || item_schema
})
.push(element_append);
}))
.push(function () {
return expandSchema(gadget, item_schema, schema_path + '/items');
})
.push(function (schema_arr) {
return render_select_type(gadget, "add item to array",
schema_arr, function (value) {
return addSubForm({
gadget: gadget,
parent_type: 'array',
type: value.type,
schema_path: value.schema_path,
schema_part: value.schema
})
.push(element_append);
});
})
.push(function (element) {
input = element;
// XXX update on every add/delete item
......@@ -293,15 +381,27 @@
}
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) {
return g.loadJSONSchema(schema.$ref, schema_path)
.push(function (schema_part) {
return schema_part;
return expandSchema(g, schema_part, schema_path);
});
}
return RSVP.Queue()
.push(function () {
return schema;
return [{
schema: schema,
schema_path: schema_path
}];
});
}
......@@ -317,27 +417,63 @@
})
.push(function (arr) {
var i,
x,
y,
key,
next_schema,
schema = arr[0];
for (i = 1; i < arr.length; i += 1) {
next_schema = arr[i];
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];
schema,
schema_item,
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;
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 {
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,
label,
div_input,
......@@ -345,8 +481,7 @@
span_error,
input,
first_path,
queue = RSVP.Queue(),
type;
queue = RSVP.Queue();
if (path && key) {
first_path = path + encodeJsonPointer(key);
......@@ -358,21 +493,9 @@
json_field = getDocumentSchema(default_value);
}
if (json_field.allOf !== undefined) {
return allOf(gadget, json_field.allOf, schema_path)
.push(function (schema_part) {
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 (getDocumentType(json_field.type) === "string") {
type = json_field.type;
} // else json_field.type is array so we use type
if (type === undefined && default_value) {
type = getDocumentType(default_value);
}
......@@ -612,16 +735,21 @@
div_input.appendChild(input);
queue
.push(render_select_type.bind(g, g, "add custom property", schema, function (value) {
return addSubForm({
gadget: g,
element: input,
path: path,
schema_path: schema_path + '/additionalProperties',
schema_part: (value && {type: value}) || schema
})
.push(element_append);
}))
.push(function () {
return expandSchema(g, schema, schema_path + '/additionalProperties');
})
.push(function (schema_arr) {
return render_select_type(g, "add custom property", schema_arr, function (value) {
return addSubForm({
gadget: g,
element: input,
path: path,
schema_path: value.schema_path,
schema_part: value.schema
})
.push(element_append);
});
})
.push(function (input) {
// XXX update on every add/delete item
div_input.appendChild(input);
......@@ -1043,7 +1171,8 @@
g.props.delete_button = 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 () {
g.listenEvents();
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