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 input; return domsugar('select', {
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 name: "ADD" + path
input.name = "ADD" + path; }),
div_input.appendChild(input); domsugar('button', {
value: btoa(JSON.stringify(json_field.patternProperties['.*'])),
input = document.createElement("button"); "class": "add-sub-form",
input.value = btoa(JSON.stringify(json_field.patternProperties['.*'])); type: "button",
input.setAttribute("class", "add-sub-form"); name: path,
input.type = "button"; text: "+"
input.name = path; })
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);
...@@ -337,15 +280,15 @@ ...@@ -337,15 +280,15 @@
if (default_used_list.indexOf(key) < 0) { if (default_used_list.indexOf(key) < 0) {
div = document.createElement("div"); div = document.createElement("div");
div.title = key; div.title = key;
if (typeof default_dict[key] === 'object') { if (typeof default_dict[key] === 'object') {
div_input = document.createElement("div"); div_input = document.createElement("div");
div_input.setAttribute("class", "input"); div_input.setAttribute("class", "input");
label.setAttribute("class", "slapos-parameter-dict-key"); label.setAttribute("class", "slapos-parameter-dict-key");
div_input = render_subform({}, div_input = render_subform({},
default_dict[key], default_dict[key],
div_input, div_input,
path + "/" + key, path + "/" + key,
restricted); restricted);
} else if (restricted === true) { } else if (restricted === true) {
div_input = document.createElement("div"); div_input = document.createElement("div");
div_input.setAttribute("class", "input"); div_input.setAttribute("class", "input");
...@@ -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,130 +443,140 @@ ...@@ -552,130 +443,140 @@
} }
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);
});
})
.declareMethod("getBaseUrl", function (url) { $(to_hide).addClass("hidden-button");
return this.getDeclaredGadget('loadschema') $(to_show).removeClass("hidden-button");
.push(function (gadget) {
return gadget.getBaseUrl(url);
});
})
.declareMethod("loadSoftwareJSON", function (url) {
return this.getDeclaredGadget('loadschema')
.push(function (gadget) {
return gadget.loadSoftwareJSON(url);
});
})
.declareMethod('processValidation', function (json_url) { return g.changeState({
var g = this, display_step: DISPLAY_JSON_FORM,
software_type = getSoftwareTypeFromForm(g.element), softwareindex: e.selectedOptions[0]["data-id"],
json_dict = getFormValuesAsJSONDict(g.element), // Force refresh in any case
schema_url = getSchemaUrlFromForm(g.element), render_timestamp: new Date().getTime()
serialisation_type = getSerialisationTypeFromForm(g.element); });
}
if (software_type === "") { function showRawParameter(g) {
if (g.options.value.parameter.shared) { var e = g.element.querySelector("button.slapos-show-raw-parameter"),
throw new Error("The software type is not part of the json (" + software_type + " as slave)"); to_show = g.element.querySelector("button.slapos-show-form");
}
throw new Error("The software type is not part of the json (" + software_type + ")");
}
return g.getBaseUrl(json_url) $(e).addClass("hidden-button");
.push(function (base_url) { $(to_show).removeClass("hidden-button");
return g.validateJSON(base_url, json_url, json_dict);
})
.push(function (validation) {
var error_index,
parameter_hash_input = g.element.querySelectorAll('.parameter_hash_output')[0],
field_name,
div,
divm,
missing_index,
missing_field_name,
xml_output;
$(g.element.querySelectorAll("span.error")).each(function (i, span) {
span.textContent = "";
});
$(g.element.querySelectorAll("div.error-input")).each(function (i, div) { return g.changeState({
div.setAttribute("class", ""); display_step: DISPLAY_RAW_XML,
}); // Force refresh in any case
if (serialisation_type === "json-in-xml") { render_timestamp: new Date().getTime()
xml_output = jsonDictToParameterJSONInXML(json_dict); });
} else { }
xml_output = jsonDictToParameterXML(json_dict);
}
parameter_hash_input.value = btoa(xml_output);
g.options.value.parameter.parameter_hash = btoa(xml_output);
// console.log(parameter_hash_input.value);
// console.log(xml_output);
if (validation.valid) {
return xml_output;
}
for (error_index in validation.errors) {
if (validation.errors.hasOwnProperty(error_index)) {
field_name = validation.errors[error_index].dataPath;
div = $(".slapos-parameter[name='/" + field_name + "']")[0].parentNode;
div.setAttribute("class", "slapos-parameter error-input");
div.querySelector("span.error").textContent = validation.errors[error_index].message;
}
}
for (missing_index in validation.missing) { function updateParameterForm(g) {
if (validation.missing.hasOwnProperty(missing_index)) { var e = g.element.getElementsByTagName('select')[0],
missing_field_name = validation.missing[missing_index].dataPath; parameter_shared = g.element.querySelector('input.parameter_shared');
divm = $('.slapos-parameter[name=/' + missing_field_name + "']")[0].parentNode;
divm.setAttribute("class", "error-input"); if (e === undefined) {
divm.querySelector("span.error").textContent = validation.missing[missing_index].message; throw new Error("Select not found.");
} }
}
return "ERROR";
});
})
.declareMethod('renderParameterForm', function (json_url, default_dict, restricted_parameter, serialisation) { 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()
});
}
var g = this; /////////////////////////////////////////////////////
return g.loadJSONSchema(json_url, serialisation) // check the form validity
.push(function (json) { /////////////////////////////////////////////////////
var fieldset_list = g.element.querySelectorAll('fieldset'), function checkValidity(g) {
fieldset = document.createElement("fieldset"); var json_url = g.state.json_url,
software_type = getSoftwareTypeFromForm(g.element),
json_dict = getFormValuesAsJSONDict(g.element),
// schema_url = getSchemaUrlFromForm(g.element),
serialisation_type = getSerialisationTypeFromForm(g.element);
if (software_type === "") {
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 + ")");
}
fieldset = render_subform(json, default_dict, fieldset, undefined, restricted_parameter); return g.getBaseUrl(json_url)
  • This shoulndn't be the json_url but the schema_url.

    The json_url is software.cfg.json an the schema_url is the actually used to render the forum, so the validdation never occur (since the software.cfg.json can be used as json schema too (it will just consider everything as valid).

  • The line of the comment of json/schemaurl is bellow not at the getBaseUrl, see the fix on !383 (merged)

Please register or sign in to reply
$(fieldset_list[1]).replaceWith(fieldset); .push(function (base_url) {
return fieldset_list; return g.validateJSON(base_url, json_url, json_dict);
})
.push(function (validation) {
var error_index,
parameter_hash_input = g.element.querySelectorAll('.parameter_hash_output')[0],
field_name,
div,
divm,
missing_index,
missing_field_name,
xml_output;
$(g.element.querySelectorAll("span.error")).each(function (i, span) {
span.textContent = "";
}); });
})
.declareMethod('renderFailoverTextArea', function (content, error) { $(g.element.querySelectorAll("div.error-input")).each(function (i, div) {
var g = this, div.setAttribute("class", "");
div = document.createElement("div"), });
div_error = document.createElement("div"), if (serialisation_type === "json-in-xml") {
span_error = document.createElement("span"), xml_output = jsonDictToParameterJSONInXML(json_dict);
detail_error = document.createElement("details"), } else {
detail_error_summary = document.createElement("summary"), xml_output = jsonDictToParameterXML(json_dict);
detail_error_span = document.createElement("span"), }
textarea = document.createElement("textarea"), parameter_hash_input.value = btoa(xml_output);
fieldset = document.createElement("fieldset"), // g.options.value.parameter.parameter_hash = btoa(xml_output);
fieldset_list = g.element.querySelectorAll('fieldset'), // console.log(parameter_hash_input.value);
show_raw_button = g.element.querySelector("button.slapos-show-raw-parameter"), // console.log(xml_output);
show_form_button = g.element.querySelector("button.slapos-show-form"); if (validation.valid) {
return xml_output;
}
for (error_index in validation.errors) {
if (validation.errors.hasOwnProperty(error_index)) {
field_name = validation.errors[error_index].dataPath;
div = $(".slapos-parameter[name='/" + field_name + "']")[0].parentNode;
div.setAttribute("class", "slapos-parameter error-input");
div.querySelector("span.error").textContent = validation.errors[error_index].message;
}
}
for (missing_index in validation.missing) {
if (validation.missing.hasOwnProperty(missing_index)) {
missing_field_name = validation.missing[missing_index].dataPath;
divm = $('.slapos-parameter[name=/' + missing_field_name + "']")[0].parentNode;
divm.setAttribute("class", "error-input");
divm.querySelector("span.error").textContent = validation.missing[missing_index].message;
}
}
return "ERROR";
});
}
/////////////////////////////////////////////////////
// main render display functions
/////////////////////////////////////////////////////
function renderDisplayRawXml(g, error_text) {
var fieldset,
fieldset_list = g.element.querySelectorAll('fieldset'),
div_error,
show_raw_button = g.element.querySelector("button.slapos-show-raw-parameter"),
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,437 +585,443 @@ ...@@ -684,437 +585,443 @@
$(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', {
// Do not hide the Software type, let the user edit it. rows: "10",
//fieldset_list[0].innerHTML = ''; cols: "80",
$(fieldset_list[1]).replaceWith(fieldset); name: "text_content",
fieldset_list[2].innerHTML = ''; text: g.state.parameter_xml
})
return fieldset; ]),
}) // div error
div_error
.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;
})
.declareMethod('render', function (options) {
var gadget = this,
to_hide = gadget.element.querySelector("button.slapos-show-form"),
to_show = gadget.element.querySelector("button.slapos-show-raw-parameter"),
softwaretype,
json_url = options.value.parameter.json_url;
gadget.options = options; // Do not hide the Software type, let the user edit it.
$(fieldset_list[1]).replaceWith(fieldset);
fieldset_list[2].innerHTML = '';
if (options.value.parameter.parameter_hash !== undefined) { return fieldset;
// A JSON where provided via gadgetfield }
options.value.parameter.parameter_xml = atob(options.value.parameter.parameter_hash);
}
if (json_url === undefined) { function renderDisplayJsonForm(gadget) {
throw new Error("undefined json_url");
} var serialisation = gadget.state.serialisation,
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_show = gadget.element.querySelector("button.slapos-show-raw-parameter");
if (json_url === undefined) {
throw new Error("undefined json_url");
}
if (to_hide !== null) { if (to_hide !== null) {
$(to_hide).addClass("hidden-button"); $(to_hide).addClass("hidden-button");
} }
if (to_show !== null) { if (to_show !== null) {
$(to_show).removeClass("hidden-button"); $(to_show).removeClass("hidden-button");
} }
return gadget.loadSoftwareJSON(json_url) return gadget.loadSoftwareJSON(json_url)
.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'), s_input = gadget.element.querySelector('input.slapos-serialisation-type'),
s_input = gadget.element.querySelector('input.slapos-serialisation-type'), selection_option_list = [],
selection_option_list = [], lowest_index = 999,
lowest_index = 999, lowest_option_index;
lowest_option_index;
if (input.children.length === 0) {
if (input.children.length === 0) { if (option_selected === undefined) {
if (option_selected === undefined) { // search by the lowest index
// search by the lowest index for (option_index in json['software-type']) {
for (option_index in json['software-type']) { if (json['software-type'].hasOwnProperty(option_index)) {
if (json['software-type'].hasOwnProperty(option_index)) { if (json['software-type'][option_index].index === undefined) {
if (json['software-type'][option_index].index === undefined) { json['software-type'][option_index].index = 999;
json['software-type'][option_index].index = 999; }
}
if (json['software-type'][option_index].index < lowest_index) { if (json['software-type'][option_index].index < lowest_index) {
lowest_index = json['software-type'][option_index].index; lowest_index = json['software-type'][option_index].index;
lowest_option_index = option_index; lowest_option_index = option_index;
}
} }
} }
} }
}
for (option_index in json['software-type']) { for (option_index in json['software-type']) {
if (json['software-type'].hasOwnProperty(option_index)) { if (json['software-type'].hasOwnProperty(option_index)) {
option = document.createElement("option"); option = document.createElement("option");
if (json['software-type'][option_index]['software-type'] !== undefined) { if (json['software-type'][option_index]['software-type'] !== undefined) {
option.value = json['software-type'][option_index]['software-type']; option.value = json['software-type'][option_index]['software-type'];
} else { } else {
option.value = option_index; option.value = option_index;
} }
option['data-id'] = option_index;
option.textContent = json['software-type'][option_index].title;
if (json['software-type'][option_index].index) {
option['data-index'] = json['software-type'][option_index].index;
} else {
option['data-index'] = 999;
}
option['data-id'] = option_index; if (option_index === lowest_option_index) {
option.textContent = json['software-type'][option_index].title; option_selected = option.value;
if (json['software-type'][option_index].index) { option.selected = true;
option['data-index'] = json['software-type'][option_index].index; option_selected_index = option_index;
if (json['software-type'][option_index].shared === true) {
parameter_shared.value = true;
} else { } else {
option['data-index'] = 999; parameter_shared.value = false;
} }
if (shared === undefined) {
if (option_index === lowest_option_index) { shared = parameter_shared.value;
option_selected = option.value;
option.selected = true;
option_selected_index = option_index;
if (json['software-type'][option_index].shared === true) {
parameter_shared.value = true;
} else {
parameter_shared.value = false;
}
if (options.value.parameter.shared === undefined) {
options.value.parameter.shared = parameter_shared.value;
}
} }
}
if (json['software-type'][option_index].shared === undefined) { if (json['software-type'][option_index].shared === undefined) {
json['software-type'][option_index].shared = false; json['software-type'][option_index].shared = false;
} }
option['data-shared'] = json['software-type'][option_index].shared;
option['data-shared'] = json['software-type'][option_index].shared; 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) {
parameter_shared.value = true; parameter_shared.value = true;
} else { } else {
parameter_shared.value = false; parameter_shared.value = false;
}
} }
}
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);
}
} }
} else {
selection_option_list.push(option);
} }
} else {
selection_option_list.push(option);
} }
} }
} }
}
selection_option_list.sort(function (a, b) {
return a["data-index"] - b["data-index"];
});
for (option_index in selection_option_list) { selection_option_list.sort(function (a, b) {
return a["data-index"] - b["data-index"];
});
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 + ")");
}
if (json['software-type'][option_selected_index] === undefined) {
throw new Error("The sotware type is not part of the json (" + softwaretype + ")");
} }
throw new Error("The software type is not part of the json (" + softwaretype + ")");
}
if (json['software-type'][option_selected_index] === undefined) {
throw new Error("The sotware type is not part of the json (" + softwaretype + ")");
}
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 {
s_input.value = json.serialisation;
serialisation = json.serialisation;
}
// Save current schema on the field
parameter_schema_url.value = json['software-type'][option_selected_index].request;
return parameter_schema_url.value;
})
.push(function (parameter_json_schema_url) {
var parameter_dict = {}, parameter_list, json_url_uri, prefix, parameter_entry;
if (parameter_xml !== undefined) {
if (serialisation === "json-in-xml") {
parameter_list = jQuery.parseXML(
parameter_xml
).querySelectorAll("parameter");
if (parameter_list.length > 1) {
throw new Error("The current parameter should contains only _ parameter (json-in-xml).");
}
parameter_entry = jQuery.parseXML(
parameter_xml
).querySelector("parameter[id='_']");
if (parameter_entry !== null) {
parameter_dict = JSON.parse(parameter_entry.textContent);
} else if (parameter_list.length === 1) {
throw new Error(
"The current parameter should contains only _ parameter (json-in-xml)."
);
}
} else if (["", "xml"].indexOf(serialisation) >= 0) {
parameter_entry = jQuery.parseXML(
parameter_xml
).querySelector("parameter[id='_']");
if (parameter_entry !== null) {
throw new Error("The current parameter values should NOT contains _ parameter (xml).");
}
$(jQuery.parseXML(parameter_xml)
.querySelectorAll("parameter"))
.each(function (key, p) {
parameter_dict[p.id] = p.textContent;
});
} else { } else {
s_input.value = json.serialisation; throw new Error("Unknown serialisation: " + serialisation);
options.serialisation = json.serialisation;
} }
}
// Save current schema on the field if (URI(parameter_json_schema_url).protocol() === "") {
parameter_schema_url.value = json['software-type'][option_selected_index].request; // URL is relative, turn into absolute
json_url_uri = URI(json_url);
prefix = json_url_uri.path().split("/");
prefix.pop();
prefix = json_url.split(json_url_uri.path())[0] + prefix.join("/");
parameter_json_schema_url = prefix + "/" + parameter_json_schema_url;
}
return gadget.loadJSONSchema(parameter_json_schema_url, serialisation)
.push(function (json) {
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 () {
var i, div_list = gadget.element.querySelectorAll('.slapos-parameter-dict-key > div'),
label_list = gadget.element.querySelectorAll('label.slapos-parameter-dict-key');
return parameter_schema_url.value; // console.log("Collapse paramaters");
})
.push(function (parameter_json_schema_url) {
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 (options.serialisation === "json-in-xml") {
parameter_list = jQuery.parseXML(
options.value.parameter.parameter_xml)
.querySelectorAll("parameter")
if (parameter_list.length > 1) {
throw new Error("The current parameter should contains only _ parameter (json-in-xml).")
}
parameter_entry = jQuery.parseXML(
options.value.parameter.parameter_xml
).querySelector("parameter[id='_']");
if (parameter_entry !== null) {
parameter_dict = JSON.parse(parameter_entry.textContent);
} else if (parameter_list.length == 1) {
throw new Error(
"The current parameter should contains only _ parameter (json-in-xml).")
}
} else if (["", "xml"].indexOf(options.serialisation) >= 0) {
parameter_entry = jQuery.parseXML(
options.value.parameter.parameter_xml
).querySelector("parameter[id='_']");
if (parameter_entry !== null) {
throw new Error("The current parameter values should NOT contains _ parameter (xml).");
}
$(jQuery.parseXML(options.value.parameter.parameter_xml)
.querySelectorAll("parameter"))
.each(function (key, p) {
parameter_dict[p.id] = p.textContent;
});
} else {
throw new Error("Unknown serialisation: " + options.serialisation);
}
}
if (URI(parameter_json_schema_url).protocol() === "") { for (i = 0; i < div_list.length; i = i + 1) {
// URL is relative, turn into absolute $(div_list[i]).hide();
json_url_uri = URI(options.value.parameter.json_url); }
prefix = json_url_uri.path().split("/");
prefix.pop();
prefix = options.value.parameter.json_url.split(json_url_uri.path())[0] + prefix.join("/");
parameter_json_schema_url = prefix + "/" + parameter_json_schema_url;
}
return gadget.renderParameterForm(parameter_json_schema_url,
parameter_dict, restricted_parameter,
options.serialisation);
})
.push(function () {
var i, div_list = gadget.element.querySelectorAll('.slapos-parameter-dict-key > div'),
label_list = gadget.element.querySelectorAll('label.slapos-parameter-dict-key');
// console.log("Collapse paramaters"); for (i = 0; i < label_list.length; i = i + 1) {
$(label_list[i]).addClass("slapos-parameter-dict-key-colapse");
}
})
for (i = 0; i < div_list.length; i = i + 1) { .fail(function (error) {
$(div_list[i]).hide(); console.warn(error);
} console.log(error.stack);
return renderDisplayRawXml(gadget, error.toString());
});
}
for (i = 0; i < label_list.length; i = i + 1) { /////////////////////////////////////////////////////
$(label_list[i]).addClass("slapos-parameter-dict-key-colapse"); // Gadget methods
} /////////////////////////////////////////////////////
return gadget; rJS(window)
}) .setState({
display_step: DISPLAY_JSON_FORM
})
.declareMethod("loadJSONSchema", function (url, serialisation) {
return this.getDeclaredGadget('loadschema')
.push(function (gadget) { .push(function (gadget) {
/* console.log("FINISHED TO RENDER, RETURNING THE GADGET"); */ return gadget.loadJSONSchema(url, serialisation);
return loadEventList(gadget);
})
.fail(function (error) {
var parameter_xml = '';
console.warn(error);
console.log(error.stack);
if (gadget.options.value.parameter.parameter_hash !== undefined) {
parameter_xml = atob(gadget.options.value.parameter.parameter_hash);
}
return gadget.renderFailoverTextArea(parameter_xml, error.toString())
.push(function () {
error = undefined;
return loadEventList(gadget);
});
}); });
}) })
.declareService(function () { .declareMethod("validateJSON", function (base_url, schema_url, generated_json) {
var g = this, return this.getDeclaredGadget('loadschema')
element = g.element.getElementsByTagName('select')[0]; .push(function (gadget) {
return gadget.validateJSON(base_url, schema_url, generated_json);
if (element === undefined) { });
return true; })
}
function updateParameterForm(evt) { .declareMethod("getBaseUrl", function (url) {
var e = g.element.getElementsByTagName('select')[0], return this.getDeclaredGadget('loadschema')
parameter_shared = g.element.querySelector('input.parameter_shared'); .push(function (gadget) {
return gadget.getBaseUrl(url);
});
})
.declareMethod("loadSoftwareJSON", function (url) {
return this.getDeclaredGadget('loadschema')
.push(function (gadget) {
return gadget.loadSoftwareJSON(url);
});
})
if (e === undefined) { .declareMethod('render', function (options) {
throw new Error("Select not found."); var parameter_hash = options.value.parameter.parameter_hash,
} // XXX Do we directly get parameter_xml parameter?
parameter_xml = options.value.parameter.parameter_xml;
g.options.value.parameter.softwaretype = e.value; if (parameter_hash !== undefined) {
g.options.value.parameter.softwaretypeindex = e.selectedOptions[0]["data-id"]; // A JSON where provided via gadgetfield
parameter_shared.value = e.selectedOptions[0]["data-shared"]; parameter_xml = atob(parameter_hash);
return g.render(g.options)
.push(function () {
return loadEventList(g);
});
} }
return loopEventListener( return this.changeState({
element, // Not used parameters
'change', // editable: options.editable,
false, // hidden: options.hidden,
updateParameterForm.bind(g) // 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()
});
}) })
.declareService(function () { .onStateChange(function () {
var g = this, if (this.state.display_step === DISPLAY_JSON_FORM) {
element = g.element.querySelector("button.slapos-show-raw-parameter"); return renderDisplayJsonForm(this);
if (element === undefined) {
return true;
} }
if (this.state.display_step === DISPLAY_RAW_XML) {
return renderDisplayRawXml(this);
}
throw new Error('Unhandled display step: ' + this.state.display_step);
})
function showRawParameter(evt) { .onEvent("change", function (evt) {
var e = g.element.querySelector("button.slapos-show-raw-parameter"), var gadget = this,
to_show = g.element.querySelector("button.slapos-show-form"), software_type_element = gadget.element.getElementsByTagName('select')[0];
parameter_xml;
if (g.options.value.parameter.parameter_hash !== undefined) {
parameter_xml = atob(g.options.value.parameter.parameter_hash);
}
$(e).addClass("hidden-button"); if (evt.target === software_type_element) {
$(to_show).removeClass("hidden-button"); return updateParameterForm(gadget);
}
return g.renderRawParameterTextArea(parameter_xml) if (evt.target.className.indexOf("slapos-parameter") !== -1) {
.push(function () { // getContent is protected by a mutex which prevent
return loadEventList(g); // onchangestate to be called in parallel
}); return gadget.getContent();
} }
return loopEventListener( }, false, false)
element,
'click', .onEvent("click", function (evt) {
false, // Only handle click on BUTTON element
showRawParameter.bind(g) var gadget = this,
); queue,
}) tag_name = evt.target.tagName;
.declareService(function () { if ((tag_name === 'LABEL') &&
var g = this, (evt.target.className.indexOf("slapos-parameter-dict-key") !== -1)) {
element = g.element.querySelector("button.slapos-show-form"); return collapseParameter(evt.target);
}
function showParameterForm(evt) { if (evt.target.className.indexOf("bt_close") !== -1) {
var e = g.element.getElementsByTagName('select')[0], return removeSubParameter(evt.target);
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) { if (tag_name === 'BUTTON') {
throw new Error("Select not found."); // Disable any button. It must be managed by this gadget
} evt.preventDefault();
}
$(to_hide).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();
g.options.value.parameter.softwaretype = e.value; if ((tag_name === 'BUTTON') &&
g.options.value.parameter.softwaretypeindex = e.selectedOptions[0]["data-id"]; (evt.target.className.indexOf("slapos-show-form") !== -1)) {
g.options.value.parameter.parameter_xml = text_content.value; return queue
g.options.value.parameter.parameter_hash = btoa(text_content.value);
return g.render(g.options)
.push(function () { .push(function () {
return loadEventList(g); return showParameterForm(gadget);
}); });
} }
if ((tag_name === 'BUTTON') &&
(evt.target.className.indexOf("slapos-show-raw-parameter") !== -1)) {
return queue
.push(function () {
return showRawParameter(gadget);
});
}
return loopEventListener( if ((tag_name === 'BUTTON') &&
element, (evt.target.className.indexOf("add-sub-form") !== -1)) {
'click', return queue
false, .push(function () {
showParameterForm.bind(g) return addSubForm(gadget, evt.target);
); });
}) }
}, false, false)
.declareService(function () {
return loadEventList(this);
})
.declareMethod('getContent', function () { .declareMethod('getContent', function () {
var gadget = this, var gadget = this,
content_dict = {}; content_dict = {};
return gadget.getElement() return gadget.getElement()
.push(function (element) { .push(function (element) {
var text_content = element.querySelector('textarea[name=text_content]'), var text_content = element.querySelector('textarea[name=text_content]'),
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