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)
$(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