Commit 6c4baa94 authored by Romain Courteaud's avatar Romain Courteaud

slapos_jio: rewrite JSON editor

* jslint
* drop duplicated loopEventListener
* use rjs.onEvent method to reduce the number of created listeners
* use domsugar to make the code more readable
* start to use mutex
parent 1d4a4b51
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
<script src="URI.js" type="text/javascript"></script> <script src="URI.js" type="text/javascript"></script>
<script src="jquery.js" type="text/javascript"></script> <script src="jquery.js" type="text/javascript"></script>
<script src="vkbeautify.js" type="text/javascript"></script> <script src="vkbeautify.js" type="text/javascript"></script>
<script src="domsugar.js" type="text/javascript"></script>
<script src="gadget_erp5_page_slap_parameter_form.js" type="text/javascript"></script> <script src="gadget_erp5_page_slap_parameter_form.js" type="text/javascript"></script>
<link href="gadget_erp5_page_slap_parameter_form.css" rel="stylesheet" type="text/css"/> <link href="gadget_erp5_page_slap_parameter_form.css" rel="stylesheet" type="text/css"/>
</head> </head>
......
...@@ -238,7 +238,7 @@ ...@@ -238,7 +238,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>971.50899.9801.15428</string> </value> <value> <string>998.21971.45138.37495</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -256,7 +256,7 @@ ...@@ -256,7 +256,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1542813409.18</float> <float>1649668690.43</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
/*jslint nomen: true, maxlen: 200, indent: 2*/ /*jslint nomen: true, maxlen: 200, indent: 2, unparam: true*/
/*global rJS, console, window, document, RSVP, btoa, atob, $, XMLSerializer, jQuery, URI, vkbeautify */ /*global rJS, console, window, document, RSVP, btoa, atob, $, XMLSerializer,
jQuery, URI, vkbeautify, domsugar, Boolean */
(function (window, document, rJS, $, XMLSerializer, jQuery, vkbeautify) { (function (window, document, rJS, $, XMLSerializer, jQuery, vkbeautify,
loopEventListener, domsugar, Boolean) {
"use strict"; "use strict";
var gk = rJS(window); var DISPLAY_JSON_FORM = 'display_json_form',
DISPLAY_RAW_XML = 'display_raw_xml';
function jsonDictToParameterXML(json) { function jsonDictToParameterXML(json) {
var parameter_id, var parameter_id,
xml_output = $($.parseXML('<?xml version="1.0" encoding="utf-8" ?><instance />')); xml_output = $($.parseXML('<?xml version="1.0" encoding="UTF-8" ?>\n<instance />'));
// Used by serialisation XML // Used by serialisation XML
for (parameter_id in json) { for (parameter_id in json) {
if (json.hasOwnProperty(parameter_id)) { if (json.hasOwnProperty(parameter_id)) {
...@@ -25,7 +28,7 @@ ...@@ -25,7 +28,7 @@
} }
function jsonDictToParameterJSONInXML(json) { function jsonDictToParameterJSONInXML(json) {
var xml_output = $($.parseXML('<?xml version="1.0" encoding="utf-8" ?><instance />')); var xml_output = $($.parseXML('<?xml version="1.0" encoding="UTF-8" ?>\n<instance />'));
// Used by serialisation XML // Used by serialisation XML
$('instance', xml_output).append( $('instance', xml_output).append(
$('<parameter />', xml_output) $('<parameter />', xml_output)
...@@ -37,133 +40,68 @@ ...@@ -37,133 +40,68 @@
); );
} }
function loopEventListener(target, type, useCapture, callback,
prevent_default) {
//////////////////////////
// Infinite event listener (promise is never resolved)
// eventListener is removed when promise is cancelled/rejected
//////////////////////////
var handle_event_callback,
callback_promise;
if (prevent_default === undefined) {
prevent_default = true;
}
function cancelResolver() {
if ((callback_promise !== undefined) &&
(typeof callback_promise.cancel === "function")) {
callback_promise.cancel();
}
}
function canceller() {
if (handle_event_callback !== undefined) {
target.removeEventListener(type, handle_event_callback, useCapture);
}
cancelResolver();
}
function itsANonResolvableTrap(resolve, reject) {
var result;
handle_event_callback = function (evt) {
if (prevent_default) {
evt.stopPropagation();
evt.preventDefault();
}
cancelResolver();
try {
result = callback(evt);
} catch (e) {
result = RSVP.reject(e);
}
callback_promise = result;
new RSVP.Queue()
.push(function () {
return result;
})
.push(undefined, function (error) {
if (!(error instanceof RSVP.CancellationError)) {
canceller();
reject(error);
}
});
};
target.addEventListener(type, handle_event_callback, useCapture);
}
return new RSVP.Promise(itsANonResolvableTrap, canceller);
}
function render_selection(json_field, default_value) { function render_selection(json_field, default_value) {
var input = document.createElement("select"), var option_list = [domsugar('option', {
option = document.createElement("option"), value: "",
option_index, selected: (default_value === undefined)
optionz; })],
input.size = 1; option_index;
option.value = "";
if (default_value === undefined) {
option.selected = true;
}
input.appendChild(option);
for (option_index in json_field['enum']) { for (option_index in json_field['enum']) {
if (json_field['enum'].hasOwnProperty(option_index)) { if (json_field['enum'].hasOwnProperty(option_index)) {
optionz = document.createElement("option"); option_list.push(domsugar('option', {
optionz.value = json_field['enum'][option_index]; value: json_field['enum'][option_index],
optionz.textContent = json_field['enum'][option_index]; text: json_field['enum'][option_index],
if (json_field['enum'][option_index] === default_value) { selected: (json_field['enum'][option_index] === default_value)
optionz.selected = true; }));
} }
input.appendChild(optionz);
} }
} return domsugar('select', {
return input; size: 1
}, option_list);
} }
function render_selection_oneof(json_field, default_value) { function render_selection_oneof(json_field, default_value) {
var input = document.createElement("select"), var option_list = [domsugar('option', {
option = document.createElement("option"), value: "",
optionz; selected: (default_value === undefined)
input.size = 1; })];
option.value = "";
if (default_value === undefined) { json_field.oneOf.forEach(function (element) {
option.selected = true;
}
input.appendChild(option);
json_field.oneOf.forEach(function (element, index) {
if ((element['const'] !== undefined) && (element.title !== undefined)) { if ((element['const'] !== undefined) && (element.title !== undefined)) {
var value; var value;
if ((json_field.type == 'array') || (json_field.type == 'object')) { if ((json_field.type === 'array') || (json_field.type === 'object')) {
// Support for unusual types // Support for unusual types
value = JSON.stringify(element['const']); value = JSON.stringify(element['const']);
} else { } else {
value = element['const']; value = element['const'];
} }
optionz = document.createElement("option"); option_list.push(domsugar('option', {
optionz.value = value; value: value,
optionz.textContent = element.title; text: element.title,
if (value === default_value) { selected: (value === default_value)
optionz.selected = true; }));
}
input.appendChild(optionz);
} }
}); });
return input;
return domsugar('select', {
size: 1
}, option_list);
} }
function render_textarea(json_field, default_value, data_format) { function render_textarea(json_field, default_value, data_format) {
var input = document.createElement("textarea"); var value = '';
if (default_value !== undefined) { if (default_value !== undefined) {
if (default_value instanceof Array) { if (default_value instanceof Array) {
input.value = default_value.join("\n"); value = default_value.join("\n");
} else { } else {
input.value = default_value; value = default_value;
} }
} }
input["data-format"] = data_format; return domsugar('textarea', {
return input; value: value,
"data-format": data_format
});
} }
function render_field(json_field, default_value) { function render_field(json_field, default_value) {
...@@ -195,23 +133,27 @@ ...@@ -195,23 +133,27 @@
return render_textarea(json_field, default_value, "string"); return render_textarea(json_field, default_value, "string");
} }
var input = document.createElement("input"); var value,
type;
if (default_value !== undefined) { if (default_value !== undefined) {
input.value = default_value; value = default_value;
} }
if (json_field.type === "integer") { if (json_field.type === "integer") {
input.type = "number"; type = "number";
} else if (json_field.type === "number") { } else if (json_field.type === "number") {
input.type = "number"; type = "number";
} else if (json_field.type === "hidden") { } else if (json_field.type === "hidden") {
input.type = "hidden"; type = "hidden";
} else { } else {
input.type = "text"; type = "text";
} }
return input; return domsugar('input', {
value: value,
type: type
});
} }
function render_subform(json_field, default_dict, root, path, restricted) { function render_subform(json_field, default_dict, root, path, restricted) {
...@@ -219,7 +161,6 @@ ...@@ -219,7 +161,6 @@
key, key,
div, div,
label, label,
close_span,
input, input,
default_value, default_value,
default_used_list = [], default_used_list = [],
...@@ -238,54 +179,56 @@ ...@@ -238,54 +179,56 @@
if (json_field.patternProperties !== undefined) { if (json_field.patternProperties !== undefined) {
if (json_field.patternProperties['.*'] !== undefined) { if (json_field.patternProperties['.*'] !== undefined) {
div = document.createElement("div"); div = domsugar("div", {
div.setAttribute("class", "subfield"); "class": "subfield",
div.title = json_field.description; title: json_field.description
});
if (restricted !== true) { if (restricted !== true) {
div_input = domsugar("div", {
div_input = document.createElement("div"); "class": "input"
div_input.setAttribute("class", "input"); }, [
domsugar('input', {
input = document.createElement("input"); type: "text",
input.type = "text";
// Name is only meaningfull to automate tests // Name is only meaningfull to automate tests
input.name = "ADD" + path; name: "ADD" + path
div_input.appendChild(input); }),
domsugar('button', {
input = document.createElement("button"); value: btoa(JSON.stringify(json_field.patternProperties['.*'])),
input.value = btoa(JSON.stringify(json_field.patternProperties['.*'])); "class": "add-sub-form",
input.setAttribute("class", "add-sub-form"); type: "button",
input.type = "button"; name: path,
input.name = path; text: "+"
input.textContent = "+"; })
div_input.appendChild(input); ]);
div.appendChild(div_input); div.appendChild(div_input);
} }
for (default_value in default_dict) { for (default_value in default_dict) {
if (default_dict.hasOwnProperty(default_value)) { if (default_dict.hasOwnProperty(default_value)) {
default_div = document.createElement("div"); default_div = domsugar("div", {
default_div.setAttribute("class", "slapos-parameter-dict-key"); "class": "slapos-parameter-dict-key"
label = document.createElement("label"); }, [
label.textContent = default_value; domsugar('label', {
label.setAttribute("class", "slapos-parameter-dict-key"); text: default_value,
close_span = document.createElement("span"); 'class': "slapos-parameter-dict-key"
close_span.textContent = "×"; }, [
close_span.setAttribute("class", "bt_close CLOSE" + path + "/" + default_value); domsugar('span', {
close_span.setAttribute("title", "Remove this parameter section."); text: "×",
label.appendChild(close_span); "class": "bt_close CLOSE" + path + "/" + default_value,
default_div.appendChild(label); title: "Remove this parameter section."
default_div = render_subform( })
])
]);
div.appendChild(render_subform(
json_field.patternProperties['.*'], json_field.patternProperties['.*'],
default_dict[default_value], default_dict[default_value],
default_div, default_div,
path + "/" + default_value, path + "/" + default_value,
restricted restricted
); ));
div.appendChild(default_div);
} }
} }
root.appendChild(div); root.appendChild(div);
...@@ -433,10 +376,6 @@ ...@@ -433,10 +376,6 @@
return multi_level_dict; return multi_level_dict;
} }
function validateForm(gadget, json_url) {
return gadget.processValidation(json_url);
}
function collapseParameter(element) { function collapseParameter(element) {
$(element).parent().children("div").toggle(300); $(element).parent().children("div").toggle(300);
if ($(element).hasClass("slapos-parameter-dict-key-colapse")) { if ($(element).hasClass("slapos-parameter-dict-key-colapse")) {
...@@ -453,21 +392,21 @@ ...@@ -453,21 +392,21 @@
return false; return false;
} }
function addSubForm(element) { function addSubForm(gadget, element) {
var subform_json = JSON.parse(atob(element.value)), var subform_json = JSON.parse(atob(element.value)),
input_text = element.parentNode.querySelector("input[type='text']"), input_text = element.parentNode.querySelector("input[type='text']"),
div = document.createElement("div"), div;
label;
if (input_text.value === "") { if (input_text.value === "") {
return false; return false;
} }
div.setAttribute("class", "slapos-parameter-dict-key"); div = domsugar('div', {
label = document.createElement("label"); 'class': "slapos-parameter-dict-key"
label.textContent = input_text.value; }, [domsugar('label', {
label.setAttribute("class", "slapos-parameter-dict-key"); 'class': "slapos-parameter-dict-key",
div.appendChild(label); text: input_text.value
})]);
div = render_subform(subform_json, {}, div, element.name + "/" + input_text.value); div = render_subform(subform_json, {}, div, element.name + "/" + input_text.value);
...@@ -477,54 +416,6 @@ ...@@ -477,54 +416,6 @@
return div; return div;
} }
function loadEventList(gadget) {
var g = gadget,
field_list = g.element.querySelectorAll(".slapos-parameter"),
button_list = g.element.querySelectorAll('button.add-sub-form'),
label_list = g.element.querySelectorAll('label.slapos-parameter-dict-key'),
close_list = g.element.querySelectorAll(".bt_close"),
i,
promise_list = [];
for (i = 0; i < field_list.length; i = i + 1) {
promise_list.push(loopEventListener(
field_list[i],
'change',
false,
validateForm.bind(g, g, g.options.value.parameter.json_url)
));
}
for (i = 0; i < button_list.length; i = i + 1) {
promise_list.push(loopEventListener(
button_list[i],
'click',
false,
addSubForm.bind(g, button_list[i])
));
}
for (i = 0; i < label_list.length; i = i + 1) {
promise_list.push(loopEventListener(
label_list[i],
'click',
false,
collapseParameter.bind(g, label_list[i])
));
}
for (i = 0; i < close_list.length; i = i + 1) {
promise_list.push(loopEventListener(
close_list[i],
'click',
false,
removeSubParameter.bind(g, close_list [i])
));
}
return RSVP.all(promise_list);
}
function getSoftwareTypeFromForm(element) { function getSoftwareTypeFromForm(element) {
var input = element.querySelector(".slapos-software-type"); var input = element.querySelector(".slapos-software-type");
...@@ -543,7 +434,7 @@ ...@@ -543,7 +434,7 @@
return ""; return "";
} }
/*
function getSchemaUrlFromForm(element) { function getSchemaUrlFromForm(element) {
var input = element.querySelector(".parameter_schema_url"); var input = element.querySelector(".parameter_schema_url");
...@@ -552,43 +443,70 @@ ...@@ -552,43 +443,70 @@
} }
return ""; return "";
} }
*/
gk.declareMethod("loadJSONSchema", function (url, serialisation) { function showParameterForm(g) {
return this.getDeclaredGadget('loadschema') var e = g.element.getElementsByTagName('select')[0],
.push(function (gadget) { to_hide = g.element.querySelector("button.slapos-show-form"),
return gadget.loadJSONSchema(url, serialisation); to_show = g.element.querySelector("button.slapos-show-raw-parameter");
});
})
.declareMethod("validateJSON", function (base_url, schema_url, generated_json) { if (e === undefined) {
return this.getDeclaredGadget('loadschema') throw new Error("Select not found.");
.push(function (gadget) { }
return gadget.validateJSON(base_url, schema_url, generated_json);
$(to_hide).addClass("hidden-button");
$(to_show).removeClass("hidden-button");
return g.changeState({
display_step: DISPLAY_JSON_FORM,
softwareindex: e.selectedOptions[0]["data-id"],
// Force refresh in any case
render_timestamp: new Date().getTime()
}); });
}) }
.declareMethod("getBaseUrl", function (url) { function showRawParameter(g) {
return this.getDeclaredGadget('loadschema') var e = g.element.querySelector("button.slapos-show-raw-parameter"),
.push(function (gadget) { to_show = g.element.querySelector("button.slapos-show-form");
return gadget.getBaseUrl(url);
$(e).addClass("hidden-button");
$(to_show).removeClass("hidden-button");
return g.changeState({
display_step: DISPLAY_RAW_XML,
// Force refresh in any case
render_timestamp: new Date().getTime()
}); });
}) }
.declareMethod("loadSoftwareJSON", function (url) {
return this.getDeclaredGadget('loadschema') function updateParameterForm(g) {
.push(function (gadget) { var e = g.element.getElementsByTagName('select')[0],
return gadget.loadSoftwareJSON(url); parameter_shared = g.element.querySelector('input.parameter_shared');
if (e === undefined) {
throw new Error("Select not found.");
}
parameter_shared.value = e.selectedOptions[0]["data-shared"];
return g.changeState({
softwareindex: e.selectedOptions[0]["data-id"],
// Force refresh in any case
render_timestamp: new Date().getTime()
}); });
}) }
.declareMethod('processValidation', function (json_url) { /////////////////////////////////////////////////////
var g = this, // check the form validity
/////////////////////////////////////////////////////
function checkValidity(g) {
var json_url = g.state.json_url,
software_type = getSoftwareTypeFromForm(g.element), software_type = getSoftwareTypeFromForm(g.element),
json_dict = getFormValuesAsJSONDict(g.element), json_dict = getFormValuesAsJSONDict(g.element),
schema_url = getSchemaUrlFromForm(g.element), // schema_url = getSchemaUrlFromForm(g.element),
serialisation_type = getSerialisationTypeFromForm(g.element); serialisation_type = getSerialisationTypeFromForm(g.element);
if (software_type === "") { if (software_type === "") {
if (g.options.value.parameter.shared) { if (g.state.shared) {
throw new Error("The software type is not part of the json (" + software_type + " as slave)"); throw new Error("The software type is not part of the json (" + software_type + " as slave)");
} }
throw new Error("The software type is not part of the json (" + software_type + ")"); throw new Error("The software type is not part of the json (" + software_type + ")");
...@@ -621,7 +539,7 @@ ...@@ -621,7 +539,7 @@
xml_output = jsonDictToParameterXML(json_dict); xml_output = jsonDictToParameterXML(json_dict);
} }
parameter_hash_input.value = btoa(xml_output); parameter_hash_input.value = btoa(xml_output);
g.options.value.parameter.parameter_hash = btoa(xml_output); // g.options.value.parameter.parameter_hash = btoa(xml_output);
// console.log(parameter_hash_input.value); // console.log(parameter_hash_input.value);
// console.log(xml_output); // console.log(xml_output);
if (validation.valid) { if (validation.valid) {
...@@ -646,36 +564,19 @@ ...@@ -646,36 +564,19 @@
} }
return "ERROR"; return "ERROR";
}); });
}) }
.declareMethod('renderParameterForm', function (json_url, default_dict, restricted_parameter, serialisation) {
var g = this;
return g.loadJSONSchema(json_url, serialisation)
.push(function (json) {
var fieldset_list = g.element.querySelectorAll('fieldset'),
fieldset = document.createElement("fieldset");
fieldset = render_subform(json, default_dict, fieldset, undefined, restricted_parameter);
$(fieldset_list[1]).replaceWith(fieldset);
return fieldset_list;
});
})
.declareMethod('renderFailoverTextArea', function (content, error) { /////////////////////////////////////////////////////
var g = this, // main render display functions
div = document.createElement("div"), /////////////////////////////////////////////////////
div_error = document.createElement("div"), function renderDisplayRawXml(g, error_text) {
span_error = document.createElement("span"), var fieldset,
detail_error = document.createElement("details"),
detail_error_summary = document.createElement("summary"),
detail_error_span = document.createElement("span"),
textarea = document.createElement("textarea"),
fieldset = document.createElement("fieldset"),
fieldset_list = g.element.querySelectorAll('fieldset'), fieldset_list = g.element.querySelectorAll('fieldset'),
div_error,
show_raw_button = g.element.querySelector("button.slapos-show-raw-parameter"), show_raw_button = g.element.querySelector("button.slapos-show-raw-parameter"),
show_form_button = g.element.querySelector("button.slapos-show-form"); show_form_button = g.element.querySelector("button.slapos-show-form");
if (error_text) {
if (show_raw_button !== null) { if (show_raw_button !== null) {
$(show_raw_button).addClass("hidden-button"); $(show_raw_button).addClass("hidden-button");
} }
...@@ -684,79 +585,60 @@ ...@@ -684,79 +585,60 @@
$(show_form_button).removeClass("hidden-button"); $(show_form_button).removeClass("hidden-button");
} }
div.setAttribute("class", "field"); div_error = domsugar('div', {
textarea.setAttribute("rows", "10"); 'class': 'error'
textarea.setAttribute("cols", "80"); }, [
domsugar('span', {
textarea.setAttribute("name", "text_content"); 'class': 'error',
textarea.textContent = content; text: "Parameter form is not available, use the textarea above for edit the instance parameters."
}),
span_error.setAttribute("class", "error"); domsugar('details', [
span_error.textContent = "Parameter form is not available, use the textarea above for edit the instance parameters."; domsugar('summary', {
text: "More information..."
detail_error_summary.textContent = "More information..." }),
detail_error_span.setAttribute("class", "error_msg"); domsugar('span', {
detail_error_span.textContent = error; 'class': 'error_msg',
text: error_text
detail_error.appendChild(detail_error_summary); })
detail_error.appendChild(detail_error_span); ])
div_error.setAttribute("class", "error"); ]);
} else {
div.appendChild(textarea); div_error = domsugar('div');
div_error.appendChild(span_error); }
div_error.appendChild(detail_error); fieldset = domsugar('fieldset', [
domsugar('div', {
fieldset.appendChild(div); 'class': 'field'
fieldset.appendChild(div_error); }, [
domsugar('textarea', {
rows: "10",
cols: "80",
name: "text_content",
text: g.state.parameter_xml
})
]),
// div error
div_error
]);
// Do not hide the Software type, let the user edit it. // Do not hide the Software type, let the user edit it.
//fieldset_list[0].innerHTML = '';
$(fieldset_list[1]).replaceWith(fieldset); $(fieldset_list[1]).replaceWith(fieldset);
fieldset_list[2].innerHTML = ''; fieldset_list[2].innerHTML = '';
return fieldset; return fieldset;
}) }
.declareMethod('renderRawParameterTextArea', function (content) {
var g = this,
div = document.createElement("div"),
div_error = document.createElement("div"),
textarea = document.createElement("textarea"),
fieldset = document.createElement("fieldset"),
fieldset_list = g.element.querySelectorAll('fieldset');
div.setAttribute("class", "field");
textarea.setAttribute("rows", "10");
textarea.setAttribute("cols", "80");
textarea.setAttribute("name", "text_content");
textarea.textContent = content;
div.appendChild(textarea);
div.appendChild(textarea);
fieldset.appendChild(div);
fieldset.appendChild(div_error);
$(fieldset_list[1]).replaceWith(fieldset);
fieldset_list[2].innerHTML = '';
return fieldset; function renderDisplayJsonForm(gadget) {
})
.declareMethod('render', function (options) { var serialisation = gadget.state.serialisation,
var gadget = this, json_url = gadget.state.json_url,
parameter_xml = gadget.state.parameter_xml,
restricted_softwaretype = gadget.state.restricted_softwaretype,
restricted_parameter = gadget.state.restricted_parameter,
shared = gadget.state.shared,
softwaretype = gadget.state.softwaretype,
softwareindex = gadget.state.softwareindex,
to_hide = gadget.element.querySelector("button.slapos-show-form"), to_hide = gadget.element.querySelector("button.slapos-show-form"),
to_show = gadget.element.querySelector("button.slapos-show-raw-parameter"), to_show = gadget.element.querySelector("button.slapos-show-raw-parameter");
softwaretype,
json_url = options.value.parameter.json_url;
gadget.options = options;
if (options.value.parameter.parameter_hash !== undefined) {
// A JSON where provided via gadgetfield
options.value.parameter.parameter_xml = atob(options.value.parameter.parameter_hash);
}
if (json_url === undefined) { if (json_url === undefined) {
throw new Error("undefined json_url"); throw new Error("undefined json_url");
...@@ -773,9 +655,8 @@ ...@@ -773,9 +655,8 @@
.push(function (json) { .push(function (json) {
var option_index, var option_index,
option, option,
option_selected = options.value.parameter.softwaretype, option_selected = softwaretype,
option_selected_index = options.value.parameter.softwaretypeindex, option_selected_index = softwareindex,
restricted_softwaretype = options.value.parameter.restricted_softwaretype,
input = gadget.element.querySelector('select.slapos-software-type'), input = gadget.element.querySelector('select.slapos-software-type'),
parameter_shared = gadget.element.querySelector('input.parameter_shared'), parameter_shared = gadget.element.querySelector('input.parameter_shared'),
parameter_schema_url = gadget.element.querySelector('input.parameter_schema_url'), parameter_schema_url = gadget.element.querySelector('input.parameter_schema_url'),
...@@ -827,8 +708,8 @@ ...@@ -827,8 +708,8 @@
} else { } else {
parameter_shared.value = false; parameter_shared.value = false;
} }
if (options.value.parameter.shared === undefined) { if (shared === undefined) {
options.value.parameter.shared = parameter_shared.value; shared = parameter_shared.value;
} }
} }
...@@ -840,7 +721,7 @@ ...@@ -840,7 +721,7 @@
if ((option_selected_index === undefined) && if ((option_selected_index === undefined) &&
(option.value === option_selected) && (option.value === option_selected) &&
(options.value.parameter.shared == json['software-type'][option_index].shared)) { (Boolean(shared) === Boolean(json['software-type'][option_index].shared))) {
option.selected = true; option.selected = true;
option_selected_index = option_index; option_selected_index = option_index;
if (json['software-type'][option_index].shared === true) { if (json['software-type'][option_index].shared === true) {
...@@ -851,8 +732,8 @@ ...@@ -851,8 +732,8 @@
} }
if (restricted_softwaretype === true) { if (restricted_softwaretype === true) {
if (option.value === options.value.parameter.softwaretype) { if (option.value === softwaretype) {
if (options.value.parameter.shared == json['software-type'][option_index].shared) { if (Boolean(shared) === Boolean(json['software-type'][option_index].shared)) {
selection_option_list.push(option); selection_option_list.push(option);
} }
} }
...@@ -868,14 +749,16 @@ ...@@ -868,14 +749,16 @@
}); });
for (option_index in selection_option_list) { for (option_index in selection_option_list) {
if (selection_option_list.hasOwnProperty(option_index)) {
input.appendChild(selection_option_list[option_index]); input.appendChild(selection_option_list[option_index]);
} }
}
if (softwaretype === undefined) { if (softwaretype === undefined) {
softwaretype = option_selected; softwaretype = option_selected;
} }
if (input.children.length === 0) { if (input.children.length === 0) {
if (options.value.parameter.shared) { if (shared) {
throw new Error("The software type is not part of the json (" + softwaretype + " as slave)"); throw new Error("The software type is not part of the json (" + softwaretype + " as slave)");
} }
throw new Error("The software type is not part of the json (" + softwaretype + ")"); throw new Error("The software type is not part of the json (" + softwaretype + ")");
...@@ -886,10 +769,10 @@ ...@@ -886,10 +769,10 @@
if (json['software-type'][option_selected_index].serialisation !== undefined) { if (json['software-type'][option_selected_index].serialisation !== undefined) {
s_input.value = json['software-type'][option_selected_index].serialisation; s_input.value = json['software-type'][option_selected_index].serialisation;
options.serialisation = json['software-type'][option_selected_index].serialisation; serialisation = json['software-type'][option_selected_index].serialisation;
} else { } else {
s_input.value = json.serialisation; s_input.value = json.serialisation;
options.serialisation = json.serialisation; serialisation = json.serialisation;
} }
// Save current schema on the field // Save current schema on the field
...@@ -898,54 +781,60 @@ ...@@ -898,54 +781,60 @@
return parameter_schema_url.value; return parameter_schema_url.value;
}) })
.push(function (parameter_json_schema_url) { .push(function (parameter_json_schema_url) {
var parameter_dict = {}, parameter_list, json_url_uri, prefix, parameter_entry, var parameter_dict = {}, parameter_list, json_url_uri, prefix, parameter_entry;
restricted_parameter = options.value.parameter.restricted_parameter;
if (options.value.parameter.parameter_xml !== undefined) { if (parameter_xml !== undefined) {
if (options.serialisation === "json-in-xml") { if (serialisation === "json-in-xml") {
parameter_list = jQuery.parseXML( parameter_list = jQuery.parseXML(
options.value.parameter.parameter_xml) parameter_xml
.querySelectorAll("parameter") ).querySelectorAll("parameter");
if (parameter_list.length > 1) { if (parameter_list.length > 1) {
throw new Error("The current parameter should contains only _ parameter (json-in-xml).") throw new Error("The current parameter should contains only _ parameter (json-in-xml).");
} }
parameter_entry = jQuery.parseXML( parameter_entry = jQuery.parseXML(
options.value.parameter.parameter_xml parameter_xml
).querySelector("parameter[id='_']"); ).querySelector("parameter[id='_']");
if (parameter_entry !== null) { if (parameter_entry !== null) {
parameter_dict = JSON.parse(parameter_entry.textContent); parameter_dict = JSON.parse(parameter_entry.textContent);
} else if (parameter_list.length == 1) { } else if (parameter_list.length === 1) {
throw new Error( throw new Error(
"The current parameter should contains only _ parameter (json-in-xml).") "The current parameter should contains only _ parameter (json-in-xml)."
);
} }
} else if (["", "xml"].indexOf(options.serialisation) >= 0) { } else if (["", "xml"].indexOf(serialisation) >= 0) {
parameter_entry = jQuery.parseXML( parameter_entry = jQuery.parseXML(
options.value.parameter.parameter_xml parameter_xml
).querySelector("parameter[id='_']"); ).querySelector("parameter[id='_']");
if (parameter_entry !== null) { if (parameter_entry !== null) {
throw new Error("The current parameter values should NOT contains _ parameter (xml)."); throw new Error("The current parameter values should NOT contains _ parameter (xml).");
} }
$(jQuery.parseXML(options.value.parameter.parameter_xml) $(jQuery.parseXML(parameter_xml)
.querySelectorAll("parameter")) .querySelectorAll("parameter"))
.each(function (key, p) { .each(function (key, p) {
parameter_dict[p.id] = p.textContent; parameter_dict[p.id] = p.textContent;
}); });
} else { } else {
throw new Error("Unknown serialisation: " + options.serialisation); throw new Error("Unknown serialisation: " + serialisation);
} }
} }
if (URI(parameter_json_schema_url).protocol() === "") { if (URI(parameter_json_schema_url).protocol() === "") {
// URL is relative, turn into absolute // URL is relative, turn into absolute
json_url_uri = URI(options.value.parameter.json_url); json_url_uri = URI(json_url);
prefix = json_url_uri.path().split("/"); prefix = json_url_uri.path().split("/");
prefix.pop(); prefix.pop();
prefix = options.value.parameter.json_url.split(json_url_uri.path())[0] + prefix.join("/"); prefix = json_url.split(json_url_uri.path())[0] + prefix.join("/");
parameter_json_schema_url = prefix + "/" + parameter_json_schema_url; parameter_json_schema_url = prefix + "/" + parameter_json_schema_url;
} }
return gadget.renderParameterForm(parameter_json_schema_url, return gadget.loadJSONSchema(parameter_json_schema_url, serialisation)
parameter_dict, restricted_parameter, .push(function (json) {
options.serialisation); var fieldset_list = gadget.element.querySelectorAll('fieldset'),
fieldset = document.createElement("fieldset");
fieldset = render_subform(json, parameter_dict, fieldset, undefined, restricted_parameter);
$(fieldset_list[1]).replaceWith(fieldset);
return fieldset_list;
});
}) })
.push(function () { .push(function () {
var i, div_list = gadget.element.querySelectorAll('.slapos-parameter-dict-key > div'), var i, div_list = gadget.element.querySelectorAll('.slapos-parameter-dict-key > div'),
...@@ -960,133 +849,150 @@ ...@@ -960,133 +849,150 @@
for (i = 0; i < label_list.length; i = i + 1) { for (i = 0; i < label_list.length; i = i + 1) {
$(label_list[i]).addClass("slapos-parameter-dict-key-colapse"); $(label_list[i]).addClass("slapos-parameter-dict-key-colapse");
} }
return gadget;
})
.push(function (gadget) {
/* console.log("FINISHED TO RENDER, RETURNING THE GADGET"); */
return loadEventList(gadget);
}) })
.fail(function (error) { .fail(function (error) {
var parameter_xml = '';
console.warn(error); console.warn(error);
console.log(error.stack); console.log(error.stack);
if (gadget.options.value.parameter.parameter_hash !== undefined) { return renderDisplayRawXml(gadget, error.toString());
parameter_xml = atob(gadget.options.value.parameter.parameter_hash); });
} }
return gadget.renderFailoverTextArea(parameter_xml, error.toString())
.push(function () { /////////////////////////////////////////////////////
error = undefined; // Gadget methods
return loadEventList(gadget); /////////////////////////////////////////////////////
rJS(window)
.setState({
display_step: DISPLAY_JSON_FORM
})
.declareMethod("loadJSONSchema", function (url, serialisation) {
return this.getDeclaredGadget('loadschema')
.push(function (gadget) {
return gadget.loadJSONSchema(url, serialisation);
}); });
})
.declareMethod("validateJSON", function (base_url, schema_url, generated_json) {
return this.getDeclaredGadget('loadschema')
.push(function (gadget) {
return gadget.validateJSON(base_url, schema_url, generated_json);
}); });
}) })
.declareService(function () { .declareMethod("getBaseUrl", function (url) {
var g = this, return this.getDeclaredGadget('loadschema')
element = g.element.getElementsByTagName('select')[0]; .push(function (gadget) {
return gadget.getBaseUrl(url);
});
})
.declareMethod("loadSoftwareJSON", function (url) {
return this.getDeclaredGadget('loadschema')
.push(function (gadget) {
return gadget.loadSoftwareJSON(url);
});
})
.declareMethod('render', function (options) {
var parameter_hash = options.value.parameter.parameter_hash,
// XXX Do we directly get parameter_xml parameter?
parameter_xml = options.value.parameter.parameter_xml;
if (element === undefined) { if (parameter_hash !== undefined) {
return true; // A JSON where provided via gadgetfield
parameter_xml = atob(parameter_hash);
}
return this.changeState({
// Not used parameters
// editable: options.editable,
// hidden: options.hidden,
// key: options.key,
serialisation: options.serialisation,
json_url: options.value.parameter.json_url,
parameter_xml: parameter_xml,
restricted_softwaretype: options.value.parameter.restricted_softwaretype,
restricted_parameter: options.value.parameter.restricted_parameter,
shared: options.value.parameter.shared,
softwaretype: options.value.parameter.softwaretype,
softwareindex: options.value.parameter.softwareindex,
// Force refresh in any case
render_timestamp: new Date().getTime()
});
})
.onStateChange(function () {
if (this.state.display_step === DISPLAY_JSON_FORM) {
return renderDisplayJsonForm(this);
}
if (this.state.display_step === DISPLAY_RAW_XML) {
return renderDisplayRawXml(this);
} }
throw new Error('Unhandled display step: ' + this.state.display_step);
})
function updateParameterForm(evt) { .onEvent("change", function (evt) {
var e = g.element.getElementsByTagName('select')[0], var gadget = this,
parameter_shared = g.element.querySelector('input.parameter_shared'); software_type_element = gadget.element.getElementsByTagName('select')[0];
if (e === undefined) { if (evt.target === software_type_element) {
throw new Error("Select not found."); return updateParameterForm(gadget);
} }
g.options.value.parameter.softwaretype = e.value; if (evt.target.className.indexOf("slapos-parameter") !== -1) {
g.options.value.parameter.softwaretypeindex = e.selectedOptions[0]["data-id"]; // getContent is protected by a mutex which prevent
parameter_shared.value = e.selectedOptions[0]["data-shared"]; // onchangestate to be called in parallel
return g.render(g.options) return gadget.getContent();
.push(function () {
return loadEventList(g);
});
} }
return loopEventListener( }, false, false)
element,
'change',
false,
updateParameterForm.bind(g)
);
})
.declareService(function () {
var g = this,
element = g.element.querySelector("button.slapos-show-raw-parameter");
if (element === undefined) { .onEvent("click", function (evt) {
return true; // Only handle click on BUTTON element
var gadget = this,
queue,
tag_name = evt.target.tagName;
if ((tag_name === 'LABEL') &&
(evt.target.className.indexOf("slapos-parameter-dict-key") !== -1)) {
return collapseParameter(evt.target);
} }
function showRawParameter(evt) { if (evt.target.className.indexOf("bt_close") !== -1) {
var e = g.element.querySelector("button.slapos-show-raw-parameter"), return removeSubParameter(evt.target);
to_show = g.element.querySelector("button.slapos-show-form"), }
parameter_xml;
if (g.options.value.parameter.parameter_hash !== undefined) { if (tag_name === 'BUTTON') {
parameter_xml = atob(g.options.value.parameter.parameter_hash); // Disable any button. It must be managed by this gadget
evt.preventDefault();
} }
$(e).addClass("hidden-button"); // Always get content to ensure the possible displayed form
$(to_show).removeClass("hidden-button"); // is checked and content propagated to the gadget state value
queue = gadget.getContent();
return g.renderRawParameterTextArea(parameter_xml) if ((tag_name === 'BUTTON') &&
(evt.target.className.indexOf("slapos-show-form") !== -1)) {
return queue
.push(function () { .push(function () {
return loadEventList(g); return showParameterForm(gadget);
}); });
} }
return loopEventListener( if ((tag_name === 'BUTTON') &&
element, (evt.target.className.indexOf("slapos-show-raw-parameter") !== -1)) {
'click', return queue
false, .push(function () {
showRawParameter.bind(g) return showRawParameter(gadget);
); });
})
.declareService(function () {
var g = this,
element = g.element.querySelector("button.slapos-show-form");
function showParameterForm(evt) {
var e = g.element.getElementsByTagName('select')[0],
to_hide = g.element.querySelector("button.slapos-show-form"),
to_show = g.element.querySelector("button.slapos-show-raw-parameter"),
text_content = g.element.querySelector('textarea[name=text_content]');
if (e === undefined) {
throw new Error("Select not found.");
} }
$(to_hide).addClass("hidden-button"); if ((tag_name === 'BUTTON') &&
$(to_show).removeClass("hidden-button"); (evt.target.className.indexOf("add-sub-form") !== -1)) {
return queue
g.options.value.parameter.softwaretype = e.value;
g.options.value.parameter.softwaretypeindex = e.selectedOptions[0]["data-id"];
g.options.value.parameter.parameter_xml = text_content.value;
g.options.value.parameter.parameter_hash = btoa(text_content.value);
return g.render(g.options)
.push(function () { .push(function () {
return loadEventList(g); return addSubForm(gadget, evt.target);
}); });
} }
}, false, false)
return loopEventListener(
element,
'click',
false,
showParameterForm.bind(g)
);
})
.declareService(function () {
return loadEventList(this);
})
.declareMethod('getContent', function () { .declareMethod('getContent', function () {
var gadget = this, var gadget = this,
...@@ -1097,24 +1003,25 @@ ...@@ -1097,24 +1003,25 @@
software_type = element.querySelector('select[name=software_type]'), software_type = element.querySelector('select[name=software_type]'),
shared = element.querySelector('input[name=shared]'); shared = element.querySelector('input[name=shared]');
if (software_type !== null) { if (software_type !== null) {
gadget.state.softwaretype = software_type.value;
content_dict.software_type = software_type.value; content_dict.software_type = software_type.value;
} }
if ((shared !== null) && (shared.value === "true")) { if ((shared !== null) && (shared.value === "true")) {
gadget.state.shared = 1;
content_dict.shared = 1; content_dict.shared = 1;
} }
if (text_content !== null) { if (text_content !== null) {
return text_content.value; return text_content.value;
} }
return gadget.processValidation(gadget.options.value.parameter.json_url); return checkValidity(gadget);
}) })
.push(function (xml_result) { .push(function (xml_result) {
// Update gadget state
gadget.state.parameter_xml = xml_result;
content_dict.text_content = xml_result; content_dict.text_content = xml_result;
return content_dict; return content_dict;
})
.fail(function (e) {
return {};
});
}); });
}, {mutex: 'statechange'});
//.declareService(function () { //.declareService(function () {
// var gadget = this; // var gadget = this;
...@@ -1133,4 +1040,5 @@ ...@@ -1133,4 +1040,5 @@
// }); // });
//}); //});
}(window, document, rJS, $, XMLSerializer, jQuery, vkbeautify)); }(window, document, rJS, $, XMLSerializer, jQuery, vkbeautify,
\ No newline at end of file rJS.loopEventListener, domsugar, Boolean));
\ No newline at end of file
...@@ -280,7 +280,7 @@ ...@@ -280,7 +280,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>999.23324.48841.24558</string> </value> <value> <string>999.42820.18181.40192</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -298,7 +298,7 @@ ...@@ -298,7 +298,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1649686520.32</float> <float>1650370742.0</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
...@@ -124,13 +124,13 @@ ...@@ -124,13 +124,13 @@
<tr> <tr>
<td>assertValue</td> <td>assertValue</td>
<td>//textarea[@name="text_content"]</td> <td>//textarea[@name="text_content"]</td>
<td>&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt;&lt;instance&gt;&lt;/instance&gt;</td> <td>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;<br>&lt;instance/&gt;</td>
</tr> </tr>
<tr> <tr>
<td>type</td> <td>type</td>
<td>//textarea[@name="text_content"]</td> <td>//textarea[@name="text_content"]</td>
<td>&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt;&lt;instance&gt;&lt;parameter id=&quot;ram-size&quot;&gt;1024&lt;/parameter&gt;&lt;/instance&gt;</td> <td>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; ?&gt;&lt;instance&gt;&lt;parameter id=&quot;ram-size&quot;&gt;1024&lt;/parameter&gt;&lt;/instance&gt;</td>
</tr> </tr>
<tr> <tr>
...@@ -202,7 +202,7 @@ ...@@ -202,7 +202,7 @@
<tr> <tr>
<td>assertValue</td> <td>assertValue</td>
<td>//textarea[@name="text_content"]</td> <td>//textarea[@name="text_content"]</td>
<td>&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt;&lt;instance&gt;&lt;parameter id=&quot;ram-size&quot;&gt;1024&lt;/parameter&gt;&lt;/instance&gt;</td> <td>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; ?&gt;&lt;instance&gt;&lt;parameter id=&quot;ram-size&quot;&gt;1024&lt;/parameter&gt;&lt;/instance&gt;</td>
</tr> </tr>
<tr> <tr>
...@@ -221,7 +221,7 @@ ...@@ -221,7 +221,7 @@
<tr> <tr>
<td>type</td> <td>type</td>
<td>//textarea[@name="text_content"]</td> <td>//textarea[@name="text_content"]</td>
<td>&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;&lt;instance&gt;&lt;parameter id=&quot;_&quot;&gt;{&quot;kvm-partition-dict&quot;: {&quot;T&quot;: {&quot;ram-size&quot;: 2048}}}&lt;/parameter&gt;&lt;/instance&gt;</td> <td>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&lt;instance&gt;&lt;parameter id=&quot;_&quot;&gt;{&quot;kvm-partition-dict&quot;: {&quot;T&quot;: {&quot;ram-size&quot;: 2048}}}&lt;/parameter&gt;&lt;/instance&gt;</td>
</tr> </tr>
<tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/click_proceed" /> <tal:block metal:use-macro="here/Zuite_SlapOSCommonTemplate/macros/click_proceed" />
......
...@@ -125,13 +125,13 @@ ...@@ -125,13 +125,13 @@
<tr> <tr>
<td>assertValue</td> <td>assertValue</td>
<td>//textarea[@name="text_content"]</td> <td>//textarea[@name="text_content"]</td>
<td>&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt;&lt;instance&gt;&lt;/instance&gt;</td> <td>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;<br>&lt;instance/&gt;</td>
</tr> </tr>
<tr> <tr>
<td>type</td> <td>type</td>
<td>//textarea[@name="text_content"]</td> <td>//textarea[@name="text_content"]</td>
<td>&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt;&lt;instance&gt;&lt;parameter id=&quot;ram-size&quot;&gt;1024&lt;/parameter&gt;&lt;/instance&gt;</td> <td>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; ?&gt;&lt;instance&gt;&lt;parameter id=&quot;ram-size&quot;&gt;1024&lt;/parameter&gt;&lt;/instance&gt;</td>
</tr> </tr>
......
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