Commit a6bb4db3 authored by Rafael Monnerat's avatar Rafael Monnerat

Split JSON Editor from the parameter form implementation

See merge request nexedi/slapos.core!518
parents 4c58c4b9 f253d674
...@@ -94,6 +94,9 @@ url_list = [ ...@@ -94,6 +94,9 @@ url_list = [
"gadget_erp5_page_slap_parameter_form.css", "gadget_erp5_page_slap_parameter_form.css",
"gadget_erp5_page_slap_parameter_form.html", "gadget_erp5_page_slap_parameter_form.html",
"gadget_erp5_page_slap_parameter_form.js", "gadget_erp5_page_slap_parameter_form.js",
"gadget_erp5_page_slap_json_form.css",
"gadget_erp5_page_slap_json_form.html",
"gadget_erp5_page_slap_json_form.js",
"gadget_erp5_page_slap_payment_result.html", "gadget_erp5_page_slap_payment_result.html",
"gadget_erp5_page_slap_person_get_token.html", "gadget_erp5_page_slap_person_get_token.html",
"gadget_erp5_page_slap_person_get_token.js", "gadget_erp5_page_slap_person_get_token.js",
......
.subfield span:not(.slapos-parameter) {
font-weight: normal;
font-style: italic;
padding-left: 7px;
color: rgb(94, 127, 141)
}
.subfield select { margin-bottom: 10px;}
.subfield textarea {width: 250px; height: 60px;}
.subfield .error {
color: #E82525;
font-weight: 700;
}
.input button {margin-left: 10px;}
.bt_close, .subfield .slapos-parameter-dict-key span.bt_close{
padding: 0 6px;
display: block;
float: right;
text-overflow:clip;
white-space:nowrap;
overflow: hidden;
font-size: 1.5em;
border-radius: 2px;
}
.bt_close:hover {
background: #c9c9c9;
color: #fff;
}
.display-none {
display: none;
}
.non-editable > div.input {border: 1px solid rgb(201, 201, 201); padding: 5px; background: white; font-weight: normal;
margin: 5px 0 10px; max-height: 250px; width: 80%;}
textarea.slapos-parameter {
width: 400px;
height: 100px;
}
label.slapos-parameter-dict-key::before {
content: "\25BC Parameter Entry: ";
}
label.slapos-parameter-dict-key-colapse::before {
content: "\25BA Parameter Entry: ";
}
div.slapos-parameter-dict-key {
margin-top: 10px;
margin-left: 6px;
background: rgb(245, 245, 245);
border: 1px solid rgb(230, 230, 230);
padding: 5px;
}
/* cleanup */
fieldset > .subfield > label:not(.slapos-parameter-dict-key) {
color: rgb(112, 125, 136);
}
fieldset > div.subfield {
padding-left: 15px;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.field input ~ span,
.subfield input ~ span {
position: relative;
top: -27px;
pointer-events: none;
cursor: text;
}
.field input:not(:placeholder-shown) ~ span:not(.error),
.subfield input:not(:placeholder-shown) ~ span:not(.error),
.field select:not(:placeholder-shown) ~ span:not(.error),
.subfield select:not(:placeholder-shown) ~ span:not(.error) {
visibility: hidden;
}
.field input ~ span:not(.error),
.subfield input ~ span:not(.error),
.field select ~ span:not(.error),
.subfield select ~ span:not(.error) {
opacity: .7;
}
.field input:focus ~ span,
.subfield input:focus ~ span,
.field select:focus ~ span,
.subfield select:focus ~ span {
visibility: hidden;
}
.subfield .input {
margin-bottom: -15px;
}
.subfield .error {
float: right;
margin-right: 30px;
}
.subfield .input textarea {
margin-bottom: 16px;
}
.slapos-parameter-dict-key {
cursor: pointer;
font-style: italic;
color: #000;
}
label.slapos-parameter-dict-key {
text-transform: capitalize;
}
label.slapos-parameter-dict-key ~ div.input label {
color: rgb(112, 125, 136);
}
.slapos-parameter-dict-key label {
color: rgb(112, 125, 136);
}
/* add button */
.slapos-parameter-dict-key ~ .subfield .input {
position: relative;
margin-bottom: 0;
}
.input .add-sub-form {
position: absolute;
right: 10px;
top: 0;
bottom: 0;
text-decoration: none;
cursor: pointer;
color: #000;
margin: 0;
}
.add-sub-form:before {
background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='50px' height='50px'><path fill='#000' d='m6,17.16589l12.55862,0l0,-15.274l12.88276,0l0,15.274l12.55862,0l0,15.66822l-12.55862,0l0,15.274l-12.88276,0l0,-15.274l-12.55862,0l0,-15.66822z' fill-opacity='0.5'/></svg>");
background-size: contain;
content: "";
width: 16px;
height: 16px;
position: absolute;
background-repeat: no-repeat;
top: 8px;
left: 4px;
}
.subfield {
padding-top: 3px;
min-height: 5em;
}
.subfield select {
margin-bottom: 0;
}
.subfield .input select + span {
position: relative;
top: -1.9em;
opacity: .7;
}
select.readonly {
background: #EEE;
pointer-events: none;
touch-action: none;
}
div.slap_json_form {
display: block;
margin-inline-start: 2px;
margin-inline-end: 2px;
padding-block-start: 0.35em;
padding-inline-start: 0.75em;
padding-inline-end: 0.75em;
padding-block-end: 0.625em;
min-inline-size: min-content;
border-width: 2px;
border-style: groove;
border-color: threedface;
border-image: initial;
}
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Web Style" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Access_contents_information_Permission</string> </key>
<value>
<tuple>
<string>Anonymous</string>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Add_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Change_local_roles_Permission</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Modify_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_View_Permission</string> </key>
<value>
<tuple>
<string>Anonymous</string>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>content_md5</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>content_type</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>creators</string> </key>
<value>
<tuple>
<string>zope</string>
</tuple>
</value>
</item>
<item>
<key> <string>default_reference</string> </key>
<value> <string>gadget_erp5_page_slap_json_form.css</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>rjs_gadget_erp5_page_slap_json_form_css</string> </value>
</item>
<item>
<key> <string>language</string> </key>
<value> <string>en</string> </value>
</item>
<item>
<key> <string>modification_date</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="DateTime" module="DateTime.DateTime"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state>
<tuple>
<float>1523884648.28</float>
<string>UTC</string>
</tuple>
</state>
</object>
</value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Web Style</string> </value>
</item>
<item>
<key> <string>short_title</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Gadget Slapos JSON Form Style</string> </value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>001</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>document_publication_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
<item>
<key> <string>edit_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
</value>
</item>
<item>
<key> <string>processing_status_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAU=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>publish_alive</string> </value>
</item>
<item>
<key> <string>actor</string> </key>
<value> <string>zope</string> </value>
</item>
<item>
<key> <string>comment</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>error_message</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>time</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="DateTime" module="DateTime.DateTime"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state>
<tuple>
<float>1682015684.98</float>
<string>UTC</string>
</tuple>
</state>
</object>
</value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>published_alive</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>edit</string> </value>
</item>
<item>
<key> <string>actor</string> </key>
<value> <string>zope</string> </value>
</item>
<item>
<key> <string>comment</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>error_message</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>1007.63576.46581.3566</string> </value>
</item>
<item>
<key> <string>state</string> </key>
<value> <string>current</string> </value>
</item>
<item>
<key> <string>time</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="DateTime" module="DateTime.DateTime"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state>
<tuple>
<float>1682455625.16</float>
<string>UTC</string>
</tuple>
</state>
</object>
</value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="5" aka="AAAAAAAAAAU=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>detect_converted_file</string> </value>
</item>
<item>
<key> <string>actor</string> </key>
<value> <string>zope</string> </value>
</item>
<item>
<key> <string>comment</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>error_message</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>external_processing_state</string> </key>
<value> <string>converted</string> </value>
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>0.0.0.0</string> </value>
</item>
<item>
<key> <string>time</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="DateTime" module="DateTime.DateTime"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state>
<tuple>
<float>1682015393.14</float>
<string>UTC</string>
</tuple>
</state>
</object>
</value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<!DOCTYPE html>
<html manifest="gadget_erp5.appcache">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>ERP5</title>
<link rel="shortcut icon" href="favicon.ico">
<script src="rsvp.js" type="text/javascript"></script>
<script src="renderjs.js" type="text/javascript"></script>
<script src="domsugar.js" type="text/javascript"></script>
<script src="gadget_erp5_page_slap_json_form.js" type="text/javascript"></script>
<link href="gadget_erp5_page_slap_json_form.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<div class="json_form"></div>
<div class="json_form_load_schema"
data-gadget-url="gadget_erp5_page_slap_load_schema.html"
data-gadget-scope="json_form_load_schema" >
</div>
</body>
</html>
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Web Page" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Access_contents_information_Permission</string> </key>
<value>
<tuple>
<string>Anonymous</string>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Add_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Change_local_roles_Permission</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Modify_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_View_Permission</string> </key>
<value>
<tuple>
<string>Anonymous</string>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>content_md5</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>text/html</string> </value>
</item>
<item>
<key> <string>default_reference</string> </key>
<value> <string>gadget_erp5_page_slap_json_form.html</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>Parameter</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>rjs_gadget_erp5_page_slap_json_form_html</string> </value>
</item>
<item>
<key> <string>language</string> </key>
<value> <string>en</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Web Page</string> </value>
</item>
<item>
<key> <string>short_title</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Gadget for slap json form</string> </value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>001</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>document_publication_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
<item>
<key> <string>edit_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
</value>
</item>
<item>
<key> <string>processing_status_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAU=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>publish_alive</string> </value>
</item>
<item>
<key> <string>actor</string> </key>
<value> <string>zope</string> </value>
</item>
<item>
<key> <string>comment</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>error_message</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>time</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="DateTime" module="DateTime.DateTime"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state>
<tuple>
<float>1681412170.2</float>
<string>UTC</string>
</tuple>
</state>
</object>
</value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>published_alive</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>edit</string> </value>
</item>
<item>
<key> <string>actor</string> </key>
<value> <string>zope</string> </value>
</item>
<item>
<key> <string>comment</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>error_message</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>1007.63578.16504.55022</string> </value>
</item>
<item>
<key> <string>state</string> </key>
<value> <string>current</string> </value>
</item>
<item>
<key> <string>time</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="DateTime" module="DateTime.DateTime"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state>
<tuple>
<float>1682453471.82</float>
<string>UTC</string>
</tuple>
</state>
</object>
</value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="5" aka="AAAAAAAAAAU=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>detect_converted_file</string> </value>
</item>
<item>
<key> <string>actor</string> </key>
<value> <string>zope</string> </value>
</item>
<item>
<key> <string>comment</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>error_message</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>external_processing_state</string> </key>
<value> <string>converted</string> </value>
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>0.0.0.0</string> </value>
</item>
<item>
<key> <string>time</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="DateTime" module="DateTime.DateTime"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state>
<tuple>
<float>1681412127.46</float>
<string>UTC</string>
</tuple>
</state>
</object>
</value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
/*jslint nomen: true, maxlen: 200, indent: 2, unparam: true*/
/*global window, rJS, domsugar, Boolean, btoa, atob */
(function (window, rJS, domsugar, Boolean, btoa, atob) {
"use strict";
function render_selection(json_field, default_value, is_required, editable) {
var input,
option_list = [domsugar('option', {
value: "",
selected: (default_value === undefined)
})],
option_index,
selected,
is_selected = (default_value === undefined),
data_format = "string",
property_dict = {
size: 1,
"placeholder": " ",
"class": "slapos-parameter"
};
if (json_field.type === "integer" || json_field.type === "number") {
data_format = "number";
} else if (json_field.type === "boolean") {
data_format = "boolean";
}
if (default_value === undefined) {
default_value = "";
}
for (option_index in json_field['enum']) {
if (json_field['enum'].hasOwnProperty(option_index)) {
selected = (json_field['enum'][option_index].toString() === default_value.toString());
is_selected = (is_selected || selected);
option_list.push(domsugar('option', {
value: json_field['enum'][option_index],
text: json_field['enum'][option_index],
"data-format": data_format,
selected: selected
}));
}
}
if (!is_selected) {
// The default value should be included even if it is
// outside the enum.
option_list.push(domsugar('option', {
value: default_value,
text: default_value,
"data-format": data_format,
selected: true
}));
}
property_dict["data-format"] = data_format;
if (is_required) {
property_dict.required = true;
}
input = domsugar('select', property_dict, option_list);
if (!editable) {
input.classList.add("readonly");
input["aria-disabled"] = "true";
input["tab-index"] = "-1";
}
return input;
}
function render_selection_oneof(json_field, default_value, is_required, editable) {
var input,
option_list = [domsugar('option', {
value: "",
selected: (default_value === undefined)
})],
property_dict = {
size: 1,
"placeholder": " ",
"class": "slapos-parameter"
};
json_field.oneOf.forEach(function (element) {
if ((element['const'] !== undefined) && (element.title !== undefined)) {
var value;
if ((json_field.type === 'array') || (json_field.type === 'object')) {
// Support for unusual types
value = JSON.stringify(element['const']);
} else {
value = element['const'];
}
option_list.push(domsugar('option', {
value: value,
text: element.title,
selected: (value === default_value)
}));
}
});
if (is_required) {
property_dict.required = true;
}
input = domsugar('select', property_dict, option_list);
if (!editable) {
input.classList.add("readonly");
input["aria-disabled"] = "true";
input["tab-index"] = "-1";
}
return input;
}
function render_textarea(json_field, default_value, data_format, is_required, editable) {
var input, property_dict = {
"data-format": data_format,
"placeholder": " ",
"class": "slapos-parameter"
};
if (default_value !== undefined) {
if (default_value instanceof Array) {
property_dict.value = default_value.join("\n");
} else {
property_dict.value = default_value;
}
}
if (is_required) {
property_dict.required = true;
}
input = domsugar('textarea', property_dict);
if (!editable) {
input.setAttribute('readonly', true);
}
return input;
}
function render_field(json_field, default_value, is_required, editable) {
var input,
data_format,
domsugar_input_dict = {"placeholder": " ", "class": "slapos-parameter"};
if (json_field['enum'] !== undefined) {
return render_selection(json_field, default_value, is_required, editable);
}
if (json_field.oneOf !== undefined) {
return render_selection_oneof(json_field, default_value, is_required, editable);
}
if (json_field.type === "boolean") {
json_field['enum'] = [true, false];
if (default_value === "true") {
default_value = true;
}
if (default_value === "false") {
default_value = false;
}
return render_selection(json_field, default_value, is_required, editable);
}
if (json_field.type === "array") {
data_format = json_field.type;
if (json_field.items !== undefined) {
if (json_field.items.type === "number" || json_field.items.type === "integer") {
data_format = "array-number";
}
}
return render_textarea(json_field, default_value, data_format, is_required, editable);
}
if (json_field.type === "string" && json_field.textarea === true) {
return render_textarea(json_field, default_value, "string", is_required, editable);
}
if (default_value !== undefined) {
domsugar_input_dict.value = default_value;
}
if (json_field.type === "integer") {
domsugar_input_dict.type = "number";
} else if (json_field.type === "number") {
domsugar_input_dict.type = "number";
domsugar_input_dict.step = "any";
} else if (json_field.type === "hidden") {
domsugar_input_dict.type = "hidden";
} else {
domsugar_input_dict.type = "text";
}
if (is_required) {
domsugar_input_dict.required = true;
}
input = domsugar('input', domsugar_input_dict);
if (!editable) {
input.setAttribute('readonly', true);
}
return input;
}
function render_subform(json_field, default_dict, root, path, editable) {
var div_input,
key,
div,
label,
input,
default_value,
default_used_list = [],
is_required;
if (default_dict === undefined) {
default_dict = {};
}
if (path === undefined) {
path = "/";
}
if (json_field.patternProperties !== undefined) {
if (json_field.patternProperties['.*'] !== undefined) {
div = domsugar("div", {
"class": "subfield",
title: json_field.description
});
if (editable) {
div_input = domsugar("div", {
"class": "input"
}, [
domsugar('input', {
type: "text",
// Name is only meaningfull to automate tests
name: "ADD" + path
}),
domsugar('button', {
value: btoa(JSON.stringify(json_field.patternProperties['.*'])),
"class": "add-sub-form",
type: "button",
name: path,
text: "+"
})
]);
div.appendChild(div_input);
}
for (default_value in default_dict) {
if (default_dict.hasOwnProperty(default_value)) {
if (editable) {
label = domsugar('label', {
text: default_value,
'class': "slapos-parameter-dict-key slapos-parameter-dict-key-colapse"
}, [
domsugar('span', {
text: "×",
"class": "bt_close CLOSE" + path + "/" + default_value,
title: "Remove this parameter section."
})
]);
} else {
label = domsugar('label', {
text: default_value,
'class': "slapos-parameter-dict-key slapos-parameter-dict-key-colapse"
});
}
div.appendChild(render_subform(
json_field.patternProperties['.*'],
default_dict[default_value],
domsugar("div", {
"class": "slapos-parameter-dict-key"
}, [label]),
path + "/" + default_value,
editable
));
}
}
root.appendChild(div);
return div;
}
}
// Expand by force the allOf recomposing the properties and required.
for (key in json_field.allOf) {
if (json_field.allOf.hasOwnProperty(key)) {
if (json_field.properties === undefined) {
json_field.properties = json_field.allOf[key].properties;
} else if (json_field.allOf[key].properties !== undefined) {
json_field.properties = Object.assign({},
json_field.properties,
json_field.allOf[key].properties
);
}
if (json_field.required === undefined) {
json_field.required = json_field.allOf[key].required;
} else if (json_field.allOf[key].required !== undefined) {
json_field.required.push.apply(
json_field.required,
json_field.allOf[key].required
);
}
}
}
for (key in json_field.properties) {
if (json_field.properties.hasOwnProperty(key)) {
if (editable || default_dict[key] !== undefined) {
label = domsugar("label", {
'text': json_field.properties[key].title
});
is_required = false;
if ((Array.isArray(json_field.required)) && (json_field.required.includes(key))) {
is_required = true;
}
if (json_field.properties[key].type === 'object') {
label.setAttribute("class", "slapos-parameter-dict-key slapos-parameter-dict-key-collapse");
div_input = render_subform(json_field.properties[key],
default_dict[key],
domsugar("div", {"class": "input"}),
path + "/" + key,
editable);
} else {
input = render_field(
json_field.properties[key],
default_dict[key],
is_required,
editable
);
input.name = path + "/" + key;
div_input = domsugar("div", {"class": "input"}, [input]);
}
default_used_list.push(key);
if (json_field.properties[key]['default'] !== undefined) {
div_input.appendChild(
domsugar("span",
{'text': '(default = ' + json_field.properties[key]['default'] + ')'})
);
}
div_input.appendChild(domsugar("span", {'class': 'error'}));
root.appendChild(
domsugar("div", {
"class": "subfield",
title: json_field.properties[key].description
}, [label, div_input])
);
}
}
}
for (key in default_dict) {
if (default_dict.hasOwnProperty(key)) {
if (default_used_list.indexOf(key) < 0) {
if (typeof default_dict[key] === 'object') {
div = domsugar("div", {title: key}, [
domsugar("label", {
text: key,
"class": "slapos-parameter-dict-key slapos-parameter-dict-key-colapse"
}),
render_subform({},
default_dict[key],
domsugar("div", {"class": "input"}),
path + "/" + key,
editable)
]);
} else {
input = render_field({"type": "string", "textarea": true}, default_dict[key], false, editable);
input.name = path + "/" + key;
div = domsugar("div", {
title: key,
"class": "subfield"
}, [
domsugar("label", {text: key}),
domsugar("div", {"class": "input"}, [
input,
domsugar("span", {text: '(Not part of the schema)'}),
domsugar("span", {'class': 'error'})
])
]);
}
default_used_list.push(key);
root.appendChild(div);
}
}
}
return root;
}
function getFormValuesAsJSONDict(element) {
var json_dict = {},
entry,
entry_list,
multi_level_dict = {};
element.querySelectorAll(".slapos-parameter").forEach(function (input, index) {
var index_e, data_format = input.getAttribute("data-format");
if (input.value !== "") {
if (input.type === 'number') {
json_dict[input.name] = parseFloat(input.value);
} else if (input.tagName === "TEXTAREA") {
if (data_format === "string") {
json_dict[input.name] = input.value;
} else if (data_format === "array") {
json_dict[input.name] = input.value.split('\n');
} else if (data_format === "array-number") {
json_dict[input.name] = [];
entry_list = input.value.split("\n");
for (index_e in entry_list) {
if (entry_list.hasOwnProperty(index_e)) {
if (isNaN(parseFloat(entry_list[index_e]))) {
json_dict[input.name].push(entry_list[index_e]);
} else {
json_dict[input.name].push(parseFloat(entry_list[index_e]));
}
}
}
} else {
json_dict[input.name] = input.value.split('\n');
}
} else if (input.tagName === "SELECT") {
if (data_format === "number" || data_format === "integer") {
// Integer must use parseFloat, otherwise the value is rounded
// loosing user's input.
if (isNaN(parseFloat(input.value))) {
json_dict[input.name] = input.value;
} else {
json_dict[input.name] = parseFloat(input.value);
}
} else if (input.getAttribute("data-format") === "boolean") {
if (input.value === "true") {
json_dict[input.name] = Boolean(input.value);
} else if (input.value === "false") {
json_dict[input.name] = false;
} else {
json_dict[input.name] = input.value;
}
} else {
json_dict[input.name] = input.value;
}
} else {
json_dict[input.name] = input.value;
}
}
});
function convertOnMultiLevel(key, value, d) {
var i,
kk,
key_list = key.split("/");
for (i = 2; i < key_list.length; i += 1) {
kk = key_list[i];
if (i === key_list.length - 1) {
d[kk] = value;
} else {
if (!d.hasOwnProperty(kk)) {
d[kk] = {};
}
d = d[kk];
}
}
}
for (entry in json_dict) {
if (json_dict.hasOwnProperty(entry)) {
convertOnMultiLevel(entry, json_dict[entry], multi_level_dict);
}
}
return multi_level_dict;
}
function collapseParameter(element) {
element.parentNode.querySelectorAll("div.subfield").forEach(function (div, i) {
div.classList.toggle("display-none");
});
element.classList.toggle("slapos-parameter-dict-key-colapse");
return element;
}
function removeSubParameter(element) {
element.parentNode.parentNode.remove();
return false;
}
function addSubForm(gadget, element) {
var subform_json = JSON.parse(atob(element.value)),
input_text = element.parentNode.querySelector("input[type='text']"),
div;
if (input_text.value === "") {
return false;
}
div = domsugar('div', {
'class': "slapos-parameter-dict-key"
}, [domsugar('label', {
'class': "slapos-parameter-dict-key",
text: input_text.value
})]);
div = render_subform(subform_json, {}, div, element.name + "/" + input_text.value, gadget.state.editable);
element.parentNode.parentNode.insertBefore(div, element.parentNode.parentNode.children[1]);
return div;
}
/////////////////////////////////////////////////////
// Gadget methods
/////////////////////////////////////////////////////
rJS(window)
.declareMethod("validateJSON", function (schema_url, generated_json) {
return this.getDeclaredGadget('json_form_load_schema')
.push(function (gadget) {
if (schema_url === undefined) {
// Skip validation if no schema is provided.
return {errors: []};
}
return gadget.validateJSON(undefined, schema_url, generated_json);
});
})
.declareMethod('render', function (options) {
return this.changeState({
schema_url: options.schema_url,
json_field: options.json_field,
default_dict: options.default_dict,
editable: options.editable,
// Force refresh in any case
render_timestamp: new Date().getTime()
});
})
.onStateChange(function () {
var gadget = this,
i,
div = render_subform(
gadget.state.json_field,
gadget.state.default_dict,
domsugar('div'),
undefined,
gadget.state.editable
),
div_list = div.querySelectorAll('.slapos-parameter-dict-key > div');
for (i = 0; i < div_list.length; i = i + 1) {
// This should be replaced by a proper class hidden-div
div_list[i].classList.add('display-none');
}
if (div.hasChildNodes()) {
div.classList.add("slap_json_form");
}
return domsugar(gadget.element, {}, [div]);
})
.onEvent("change", function (evt) {
var gadget = this;
// @ts-ignore
if (evt.target.className.indexOf("slapos-parameter") !== -1) {
// getContent is protected by a mutex which prevent
// onchangestate to be called in parallel
return gadget.getContent();
}
}, false, false)
.onEvent("click", function (evt) {
// Only handle click on BUTTON element
var gadget = this,
queue,
// @ts-ignore
tag_name = evt.target.tagName;
if ((tag_name === 'LABEL') &&
// @ts-ignore
(evt.target.className.indexOf("slapos-parameter-dict-key") !== -1)) {
return collapseParameter(evt.target);
}
if ((tag_name === 'SPAN') &&
// @ts-ignore
(evt.target.className.indexOf("bt_close") !== -1)) {
return removeSubParameter(evt.target);
}
if (tag_name === 'BUTTON') {
// Disable any button. It must be managed by this gadget
evt.preventDefault();
}
// Always get content to ensure the possible displayed form
// is checked and content propagated to the gadget state value
queue = gadget.getContent();
if ((tag_name === 'BUTTON') &&
// @ts-ignore
(evt.target.className.indexOf("add-sub-form") !== -1)) {
return queue
.push(function () {
return addSubForm(gadget, evt.target);
});
}
}, false, false)
.declareMethod('getContent', function () {
var gadget = this,
json_dict = getFormValuesAsJSONDict(gadget.element);
return gadget.validateJSON(gadget.state.schema_url, json_dict)
.push(function (validation) {
var error_index,
field_name,
div,
input_field,
error_dict;
gadget.element.querySelectorAll("span.error").forEach(function (span, i) {
span.textContent = "";
});
gadget.element.querySelectorAll("div.error-input").forEach(function (div, i) {
div.setAttribute("class", "");
});
// Update fields if errors exist
for (error_index in validation.errors) {
if (validation.errors.hasOwnProperty(error_index)) {
error_dict = validation.errors[error_index];
// error_dict = { error : "", instanceLocation: "#", keyword: "", keywordLocation: "" }
field_name = error_dict.instanceLocation.slice(1);
if (field_name !== "") {
input_field = gadget.element.querySelector(".slapos-parameter[name='/" + field_name + "']");
if (input_field === null) {
field_name = field_name.split("/").slice(0, -1).join("/");
input_field = gadget.element.querySelector(".slapos-parameter[name='/" + field_name + "']");
}
if (input_field !== null) {
div = input_field.parentNode;
div.setAttribute("class", "slapos-parameter error-input");
div.querySelector("span.error").textContent = validation.errors[error_index].error;
}
} else if (error_dict.keyword === "required") {
// Specific use case for required
field_name = "/" + error_dict.key;
input_field = gadget.element.querySelector(".slapos-parameter[name='/" + field_name + "']");
if (input_field === null) {
field_name = field_name.split("/").slice(0, -1).join("/");
input_field = gadget.element.querySelector(".slapos-parameter[name='/" + field_name + "']");
}
if (input_field !== null) {
div = input_field.parentNode;
div.setAttribute("class", "slapos-parameter error-input");
div.querySelector("span.error").textContent = error_dict.error;
}
}
}
}
return json_dict;
});
}, {mutex: 'statechange'});
}(window, rJS, domsugar, Boolean, btoa, atob));
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Web Script" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Access_contents_information_Permission</string> </key>
<value>
<tuple>
<string>Anonymous</string>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Add_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Change_local_roles_Permission</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Copy_or_Move_Permission</string> </key>
<value>
<list>
<string>Manager</string>
<string>Authenticated</string>
<string>Developer</string>
<string>Owner</string>
</list>
</value>
</item>
<item>
<key> <string>_Modify_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_View_Permission</string> </key>
<value>
<tuple>
<string>Anonymous</string>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>content_md5</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>creators</string> </key>
<value>
<tuple>
<string>zope</string>
</tuple>
</value>
</item>
<item>
<key> <string>default_reference</string> </key>
<value> <string>gadget_erp5_page_slap_json_form.js</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>rjs_gadget_erp5_page_slap_json_form_js</string> </value>
</item>
<item>
<key> <string>language</string> </key>
<value> <string>en</string> </value>
</item>
<item>
<key> <string>modification_date</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="DateTime" module="DateTime.DateTime"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state>
<tuple>
<float>1523884648.42</float>
<string>UTC</string>
</tuple>
</state>
</object>
</value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Web Script</string> </value>
</item>
<item>
<key> <string>short_title</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>gadget_erp5_page_slap_json_form.js</string> </value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>001</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>document_publication_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
<item>
<key> <string>edit_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
</value>
</item>
<item>
<key> <string>processing_status_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAU=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>publish_alive</string> </value>
</item>
<item>
<key> <string>actor</string> </key>
<value> <string>zope</string> </value>
</item>
<item>
<key> <string>comment</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>error_message</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>time</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="DateTime" module="DateTime.DateTime"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state>
<tuple>
<float>1682025348.84</float>
<string>UTC</string>
</tuple>
</state>
</object>
</value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>published_alive</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>edit</string> </value>
</item>
<item>
<key> <string>actor</string> </key>
<value> <string>zope</string> </value>
</item>
<item>
<key> <string>comment</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>error_message</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>1008.808.61596.8721</string> </value>
</item>
<item>
<key> <string>state</string> </key>
<value> <string>current</string> </value>
</item>
<item>
<key> <string>time</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="DateTime" module="DateTime.DateTime"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state>
<tuple>
<float>1682619529.51</float>
<string>UTC</string>
</tuple>
</state>
</object>
</value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="5" aka="AAAAAAAAAAU=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>detect_converted_file</string> </value>
</item>
<item>
<key> <string>actor</string> </key>
<value> <string>zope</string> </value>
</item>
<item>
<key> <string>comment</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>error_message</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>external_processing_state</string> </key>
<value> <string>converted</string> </value>
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>0.0.0.0</string> </value>
</item>
<item>
<key> <string>time</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="DateTime" module="DateTime.DateTime"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state>
<tuple>
<float>1681412419.45</float>
<string>UTC</string>
</tuple>
</state>
</object>
</value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -4,46 +4,8 @@ ...@@ -4,46 +4,8 @@
padding-top: 10px; padding-top: 10px;
} }
.subfield span:not(.slapos-parameter) {
font-weight: normal;
font-style: italic;
padding-left: 7px;
color: rgb(94, 127, 141)
}
.subfield select { margin-bottom: 10px;}
.subfield textarea {width: 250px; height: 60px;}
.subfield .error {
color: #E82525;
font-weight: 700;
}
.input button {margin-left: 10px;} .input button {margin-left: 10px;}
.bt_close, .subfield .slapos-parameter-dict-key span.bt_close{
padding: 0 6px;
display: block;
float: right;
text-overflow:clip;
white-space:nowrap;
overflow: hidden;
font-size: 1.5em;
border-radius: 2px;
}
.bt_close:hover {
background: #c9c9c9;
color: #fff;
}
.hs-short-title{
margin-left:6px;
padding-bottom: 10px;
font-size:12px;
font-weight: normal;
display: inline-block;
}
.display-none { .display-none {
display: none; display: none;
} }
...@@ -58,134 +20,48 @@ ...@@ -58,134 +20,48 @@
.non-editable > div.input {border: 1px solid rgb(201, 201, 201); padding: 5px; background: white; font-weight: normal; .non-editable > div.input {border: 1px solid rgb(201, 201, 201); padding: 5px; background: white; font-weight: normal;
margin: 5px 0 10px; max-height: 250px; width: 80%;} margin: 5px 0 10px; max-height: 250px; width: 80%;}
.subfield {
padding-left: 20px;
padding-top: 3px;
}
textarea.slapos-parameter { textarea.slapos-parameter {
width: 400px; width: 400px;
height: 100px; height: 100px;
} }
label.slapos-parameter-dict-key::before { .field input ~ span {
content: "\25BC Parameter Entry: ";
}
label.slapos-parameter-dict-key-colapse::before {
content: "\25BA Parameter Entry: ";
}
div.slapos-parameter-dict-key {
margin-top: 10px;
margin-left: 6px;
background: rgb(245, 245, 245);
border: 1px solid rgb(230, 230, 230);
padding: 5px;
}
/* cleanup */
fieldset > .subfield > label:not(.slapos-parameter-dict-key) {
color: rgb(112, 125, 136);
}
fieldset > div.subfield {
padding-left: 15px;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.field input ~ span,
.subfield input ~ span {
position: relative; position: relative;
top: -27px; top: -27px;
pointer-events: none; pointer-events: none;
cursor: text; cursor: text;
} }
.field input:not(:placeholder-shown) ~ span:not(.error), .field input:not(:placeholder-shown) ~ span:not(.error),
.subfield input:not(:placeholder-shown) ~ span:not(.error), .field select:not(:placeholder-shown) ~ span:not(.error) {
.field select:not(:placeholder-shown) ~ span:not(.error),
.subfield select:not(:placeholder-shown) ~ span:not(.error) {
visibility: hidden; visibility: hidden;
} }
.field input ~ span:not(.error), .field input ~ span:not(.error),
.subfield input ~ span:not(.error), .field select ~ span:not(.error) {
.field select ~ span:not(.error),
.subfield select ~ span:not(.error) {
opacity: .7; opacity: .7;
} }
.field input:focus ~ span, .field input:focus ~ span,
.subfield input:focus ~ span, .field select:focus ~ span {
.field select:focus ~ span,
.subfield select:focus ~ span {
visibility: hidden; visibility: hidden;
} }
.subfield .input {
margin-bottom: -15px;
}
.subfield .error {
float: right;
margin-right: 30px;
}
.subfield .input textarea {
margin-bottom: 16px;
}
.slapos-show-raw-parameter, button.slapos-show-raw-parameter,
.slapos-parameter-dict-key, button.slapos-show-form {
.slapos-show-form {
cursor: pointer;
font-style: italic;
color: #000;
}
.slapos-show-form,
.slapos-show-raw-parameter {
margin: 4px auto;
padding-left: 24px; /* add an icon? */
}
label.slapos-parameter-dict-key {
text-transform: capitalize;
}
label.slapos-parameter-dict-key ~ div.input label {
color: rgb(112, 125, 136);
}
.slapos-parameter-dict-key label {
color: rgb(112, 125, 136);
}
/* add button */
.slapos-parameter-dict-key ~ .subfield .input {
position: relative;
margin-bottom: 0;
}
.input .add-sub-form {
position: absolute;
right: 10px;
top: 0;
bottom: 0;
text-decoration: none;
cursor: pointer; cursor: pointer;
color: #000; color: #212529;
margin: 0; padding: 3pt;
border: 1px solid rgba(0, 0, 0, 0.14);
border-radius: 0.325em;
display: inline-block;
margin-right: 6pt;
} }
.add-sub-form:before { button.slapos-show-raw-parameter:before,
background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='50px' height='50px'><path fill='#000' d='m6,17.16589l12.55862,0l0,-15.274l12.88276,0l0,15.274l12.55862,0l0,15.66822l-12.55862,0l0,15.274l-12.88276,0l0,-15.274l-12.55862,0l0,-15.66822z' fill-opacity='0.5'/></svg>"); button.slapos-show-form:before {
background-size: contain; padding-right: 0.2em;
content: "";
width: 16px;
height: 16px;
position: absolute;
background-repeat: no-repeat;
top: 8px;
left: 4px;
} }
.subfield { button.slapos-show-raw-parameter[disabled],
min-height: 5em; button.slapos-show-form[disabled] {
} color: #999;
.subfield select {
margin-bottom: 0;
}
.subfield .input select + span {
position: relative;
top: -1.9em;
opacity: .7;
} }
select.readonly { select.readonly {
...@@ -193,3 +69,7 @@ select.readonly { ...@@ -193,3 +69,7 @@ select.readonly {
pointer-events: none; pointer-events: none;
touch-action: none; touch-action: none;
} }
div.slapos-parameter-editor-button {
padding: 10px;
}
\ No newline at end of file
...@@ -71,7 +71,9 @@ ...@@ -71,7 +71,9 @@
</item> </item>
<item> <item>
<key> <string>content_type</string> </key> <key> <string>content_type</string> </key>
<value> <string>text/css</string> </value> <value>
<none/>
</value>
</item> </item>
<item> <item>
<key> <string>creators</string> </key> <key> <string>creators</string> </key>
...@@ -271,7 +273,7 @@ ...@@ -271,7 +273,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>1004.33923.4937.19370</string> </value> <value> <string>1007.63569.60065.35225</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -291,7 +293,7 @@ ...@@ -291,7 +293,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1669223474.78</float> <float>1682452927.16</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
...@@ -28,14 +28,19 @@ ...@@ -28,14 +28,19 @@
<input type=hidden name="serialisation_type" class="slapos-serialisation-type"> <input type=hidden name="serialisation_type" class="slapos-serialisation-type">
</div> </div>
</div> </div>
<div class="field" title="hide_show_button"> <div class="field slapos-parameter-editor-button" title="hide_show_button">
<div class="input"> <div class="input">
<button type="button" class="slapos-show-form display-none"> Show Parameter Form </button> <button type="button" class="slapos-show-form ui-btn-icon-left ui-icon-spinner"> Parameter Form </button>
<button type="button" class="slapos-show-raw-parameter"> Show Parameter XML</button> <button type="button" class="slapos-show-raw-parameter ui-btn-icon-left ui-icon-code" disabled> Raw XML</button>
</div> </div>
</div> </div>
</fieldset> </fieldset>
<fieldset id="parameter-main"> </fieldset> <fieldset id="parameter-main">
<div class="parameter_json_form"
data-gadget-url="gadget_erp5_page_slap_json_form.html"
data-gadget-scope="json_form"> </div>
<div class="failover-textarea"> </div>
</fieldset>
<fieldset id="parameter-optional"> </fieldset> <fieldset id="parameter-optional"> </fieldset>
<fieldset id="parameter-xml"> <fieldset id="parameter-xml">
<input type=hidden name="parameter_hash" class="parameter_hash_output"> <input type=hidden name="parameter_hash" class="parameter_hash_output">
......
...@@ -240,7 +240,7 @@ ...@@ -240,7 +240,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>1004.26625.54107.30429</string> </value> <value> <string>1007.63568.41363.15786</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -260,7 +260,7 @@ ...@@ -260,7 +260,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1669223665.45</float> <float>1682453638.42</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
/*jslint nomen: true, maxlen: 200, indent: 2, unparam: true*/ /*jslint nomen: true, maxlen: 200, indent: 2, unparam: true*/
/*global rJS, console, window, document, RSVP, btoa, atob, XMLSerializer, /*global rJS, console, window, btoa, atob, XMLSerializer,
DOMParser, URI, vkbeautify, domsugar, Boolean */ DOMParser, URI, vkbeautify, domsugar, Boolean */
(function (window, document, rJS, XMLSerializer, DOMParser, vkbeautify, (function (window, rJS, XMLSerializer, DOMParser, vkbeautify,
domsugar, Boolean, URI) { domsugar, Boolean, URI) {
"use strict"; "use strict";
...@@ -72,494 +72,6 @@ ...@@ -72,494 +72,6 @@
); );
} }
function render_selection(json_field, default_value, is_required, editable) {
var input,
option_list = [domsugar('option', {
value: "",
selected: (default_value === undefined)
})],
option_index,
selected,
is_selected = (default_value === undefined),
data_format = "string",
property_dict = {
size: 1,
"placeholder": " ",
"class": "slapos-parameter"
};
if (json_field.type === "integer" || json_field.type === "number") {
data_format = "number";
} else if (json_field.type === "boolean") {
data_format = "boolean";
}
if (default_value === undefined) {
default_value = "";
}
for (option_index in json_field['enum']) {
if (json_field['enum'].hasOwnProperty(option_index)) {
selected = (json_field['enum'][option_index].toString() === default_value.toString());
is_selected = (is_selected || selected);
option_list.push(domsugar('option', {
value: json_field['enum'][option_index],
text: json_field['enum'][option_index],
"data-format": data_format,
selected: selected
}));
}
}
if (!is_selected) {
// The default value should be included even if it is
// outside the enum.
option_list.push(domsugar('option', {
value: default_value,
text: default_value,
"data-format": data_format,
selected: true
}));
}
property_dict["data-format"] = data_format;
if (is_required) {
property_dict.required = true;
}
input = domsugar('select', property_dict, option_list);
if (!editable) {
input.classList.add("readonly");
input["aria-disabled"] = "true";
input["tab-index"] = "-1";
}
return input;
}
function render_selection_oneof(json_field, default_value, is_required, editable) {
var input,
option_list = [domsugar('option', {
value: "",
selected: (default_value === undefined)
})],
property_dict = {
size: 1,
"placeholder": " ",
"class": "slapos-parameter"
};
json_field.oneOf.forEach(function (element) {
if ((element['const'] !== undefined) && (element.title !== undefined)) {
var value;
if ((json_field.type === 'array') || (json_field.type === 'object')) {
// Support for unusual types
value = JSON.stringify(element['const']);
} else {
value = element['const'];
}
option_list.push(domsugar('option', {
value: value,
text: element.title,
selected: (value === default_value)
}));
}
});
if (is_required) {
property_dict.required = true;
}
input = domsugar('select', property_dict, option_list);
if (!editable) {
input.classList.add("readonly");
input["aria-disabled"] = "true";
input["tab-index"] = "-1";
}
return input;
}
function render_textarea(json_field, default_value, data_format, is_required, editable) {
var input, property_dict = {
"data-format": data_format,
"placeholder": " ",
"class": "slapos-parameter"
};
if (default_value !== undefined) {
if (default_value instanceof Array) {
property_dict.value = default_value.join("\n");
} else {
property_dict.value = default_value;
}
}
if (is_required) {
property_dict.required = true;
}
input = domsugar('textarea', property_dict);
if (!editable) {
input.setAttribute('readonly', true);
}
return input;
}
function render_field(json_field, default_value, is_required, editable) {
var input,
data_format,
domsugar_input_dict = {"placeholder": " ", "class": "slapos-parameter"};
if (json_field['enum'] !== undefined) {
return render_selection(json_field, default_value, is_required, editable);
}
if (json_field.oneOf !== undefined) {
return render_selection_oneof(json_field, default_value, is_required, editable);
}
if (json_field.type === "boolean") {
json_field['enum'] = [true, false];
if (default_value === "true") {
default_value = true;
}
if (default_value === "false") {
default_value = false;
}
return render_selection(json_field, default_value, is_required, editable);
}
if (json_field.type === "array") {
data_format = json_field.type;
if (json_field.items !== undefined) {
if (json_field.items.type === "number" || json_field.items.type === "integer") {
data_format = "array-number";
}
}
return render_textarea(json_field, default_value, data_format, is_required, editable);
}
if (json_field.type === "string" && json_field.textarea === true) {
return render_textarea(json_field, default_value, "string", is_required, editable);
}
if (default_value !== undefined) {
domsugar_input_dict.value = default_value;
}
if (json_field.type === "integer") {
domsugar_input_dict.type = "number";
} else if (json_field.type === "number") {
domsugar_input_dict.type = "number";
domsugar_input_dict.step = "any";
} else if (json_field.type === "hidden") {
domsugar_input_dict.type = "hidden";
} else {
domsugar_input_dict.type = "text";
}
if (is_required) {
domsugar_input_dict.required = true;
}
input = domsugar('input', domsugar_input_dict);
if (!editable) {
input.setAttribute('readonly', true);
}
return input;
}
function render_subform(json_field, default_dict, root, path, editable) {
var div_input,
key,
div,
label,
input,
default_value,
default_used_list = [],
is_required;
if (default_dict === undefined) {
default_dict = {};
}
if (path === undefined) {
path = "/";
}
if (json_field.patternProperties !== undefined) {
if (json_field.patternProperties['.*'] !== undefined) {
div = domsugar("div", {
"class": "subfield",
title: json_field.description
});
if (editable) {
div_input = domsugar("div", {
"class": "input"
}, [
domsugar('input', {
type: "text",
// Name is only meaningfull to automate tests
name: "ADD" + path
}),
domsugar('button', {
value: btoa(JSON.stringify(json_field.patternProperties['.*'])),
"class": "add-sub-form",
type: "button",
name: path,
text: "+"
})
]);
div.appendChild(div_input);
}
for (default_value in default_dict) {
if (default_dict.hasOwnProperty(default_value)) {
if (editable) {
label = domsugar('label', {
text: default_value,
'class': "slapos-parameter-dict-key"
}, [
domsugar('span', {
text: "×",
"class": "bt_close CLOSE" + path + "/" + default_value,
title: "Remove this parameter section."
})
]);
} else {
label = domsugar('label', {
text: default_value,
'class': "slapos-parameter-dict-key"
});
}
div.appendChild(render_subform(
json_field.patternProperties['.*'],
default_dict[default_value],
domsugar("div", {
"class": "slapos-parameter-dict-key"
}, [label]),
path + "/" + default_value,
editable
));
}
}
root.appendChild(div);
return div;
}
}
// Expand by force the allOf recomposing the properties and required.
for (key in json_field.allOf) {
if (json_field.allOf.hasOwnProperty(key)) {
if (json_field.properties === undefined) {
json_field.properties = json_field.allOf[key].properties;
} else if (json_field.allOf[key].properties !== undefined) {
json_field.properties = Object.assign({},
json_field.properties,
json_field.allOf[key].properties
);
}
if (json_field.required === undefined) {
json_field.required = json_field.allOf[key].required;
} else if (json_field.allOf[key].required !== undefined) {
json_field.required.push.apply(
json_field.required,
json_field.allOf[key].required
);
}
}
}
for (key in json_field.properties) {
if (json_field.properties.hasOwnProperty(key)) {
if (editable || default_dict[key] !== undefined) {
label = domsugar("label", {
'text': json_field.properties[key].title
});
is_required = false;
if ((Array.isArray(json_field.required)) && (json_field.required.includes(key))) {
is_required = true;
}
if (json_field.properties[key].type === 'object') {
label.setAttribute("class", "slapos-parameter-dict-key");
div_input = render_subform(json_field.properties[key],
default_dict[key],
domsugar("div", {"class": "input"}),
path + "/" + key,
editable);
} else {
input = render_field(
json_field.properties[key],
default_dict[key],
is_required,
editable
);
input.name = path + "/" + key;
div_input = domsugar("div", {"class": "input"}, [input]);
}
default_used_list.push(key);
if (json_field.properties[key]['default'] !== undefined) {
div_input.appendChild(
domsugar("span",
{'text': '(default = ' + json_field.properties[key]['default'] + ')'})
);
}
div_input.appendChild(domsugar("span", {'class': 'error'}));
root.appendChild(
domsugar("div", {
"class": "subfield",
title: json_field.properties[key].description
}, [label, div_input])
);
}
}
}
for (key in default_dict) {
if (default_dict.hasOwnProperty(key)) {
if (default_used_list.indexOf(key) < 0) {
if (typeof default_dict[key] === 'object') {
div = domsugar("div", {title: key}, [
domsugar("label", {
text: key,
"class": "slapos-parameter-dict-key"
}),
render_subform({},
default_dict[key],
domsugar("div", {"class": "input"}),
path + "/" + key,
editable)
]);
} else {
input = render_field({"type": "string", "textarea": true}, default_dict[key], false, editable);
input.name = path + "/" + key;
div = domsugar("div", {
title: key,
"class": "subfield"
}, [
domsugar("label", {text: key}),
domsugar("div", {"class": "input"}, [
input,
domsugar("span", {text: '(Not part of the schema)'}),
domsugar("span", {'class': 'error'})
])
]);
}
default_used_list.push(key);
root.appendChild(div);
}
}
}
return root;
}
function getFormValuesAsJSONDict(element) {
var json_dict = {},
entry,
entry_list,
multi_level_dict = {};
element.querySelectorAll(".slapos-parameter").forEach(function (input, index) {
var index_e, data_format = input.getAttribute("data-format");
if (input.value !== "") {
if (input.type === 'number') {
json_dict[input.name] = parseFloat(input.value);
} else if (input.tagName === "TEXTAREA") {
if (data_format === "string") {
json_dict[input.name] = input.value;
} else if (data_format === "array") {
json_dict[input.name] = input.value.split('\n');
} else if (data_format === "array-number") {
json_dict[input.name] = [];
entry_list = input.value.split("\n");
for (index_e in entry_list) {
if (entry_list.hasOwnProperty(index_e)) {
if (isNaN(parseFloat(entry_list[index_e]))) {
json_dict[input.name].push(entry_list[index_e]);
} else {
json_dict[input.name].push(parseFloat(entry_list[index_e]));
}
}
}
} else {
json_dict[input.name] = input.value.split('\n');
}
} else if (input.tagName === "SELECT") {
if (data_format === "number" || data_format === "integer") {
// Integer must use parseFloat, otherwise the value is rounded
// loosing user's input.
if (isNaN(parseFloat(input.value))) {
json_dict[input.name] = input.value;
} else {
json_dict[input.name] = parseFloat(input.value);
}
} else if (input.getAttribute("data-format") === "boolean") {
if (input.value === "true") {
json_dict[input.name] = Boolean(input.value);
} else if (input.value === "false") {
json_dict[input.name] = false;
} else {
json_dict[input.name] = input.value;
}
} else {
json_dict[input.name] = input.value;
}
} else {
json_dict[input.name] = input.value;
}
}
});
function convertOnMultiLevel(key, value, d) {
var i,
kk,
key_list = key.split("/");
for (i = 2; i < key_list.length; i += 1) {
kk = key_list[i];
if (i === key_list.length - 1) {
d[kk] = value;
} else {
if (!d.hasOwnProperty(kk)) {
d[kk] = {};
}
d = d[kk];
}
}
}
for (entry in json_dict) {
if (json_dict.hasOwnProperty(entry)) {
convertOnMultiLevel(entry, json_dict[entry], multi_level_dict);
}
}
return multi_level_dict;
}
function collapseParameter(element) {
element.parentNode.querySelectorAll("div.subfield").forEach(function (div, i) {
div.classList.toggle("display-none");
});
element.classList.toggle("slapos-parameter-dict-key-colapse");
return element;
}
function removeSubParameter(element) {
element.parentNode.parentNode.remove();
return false;
}
function addSubForm(gadget, element) {
var subform_json = JSON.parse(atob(element.value)),
input_text = element.parentNode.querySelector("input[type='text']"),
div;
if (input_text.value === "") {
return false;
}
div = domsugar('div', {
'class': "slapos-parameter-dict-key"
}, [domsugar('label', {
'class': "slapos-parameter-dict-key",
text: input_text.value
})]);
div = render_subform(subform_json, {}, div, element.name + "/" + input_text.value, gadget.state.editable);
element.parentNode.parentNode.insertBefore(div, element.parentNode.parentNode.children[1]);
return div;
}
function getSoftwareTypeFromForm(element) { function getSoftwareTypeFromForm(element) {
var input = element.querySelector(".slapos-software-type"); var input = element.querySelector(".slapos-software-type");
...@@ -578,27 +90,13 @@ ...@@ -578,27 +90,13 @@
return ""; return "";
} }
function getSchemaUrlFromForm(element) {
var input = element.querySelector(".parameter_schema_url");
if (input !== undefined && input !== null) {
return input.value;
}
return "";
}
function showParameterForm(g) { function showParameterForm(g) {
var e = g.element.getElementsByTagName('select')[0], var e = g.element.getElementsByTagName('select')[0];
to_hide = g.element.querySelector("button.slapos-show-form"),
to_show = g.element.querySelector("button.slapos-show-raw-parameter");
if (e === undefined) { if (e === undefined) {
throw new Error("Select not found."); throw new Error("Select not found.");
} }
to_hide.classList.add("display-none");
to_show.classList.remove("display-none");
return g.changeState({ return g.changeState({
display_step: DISPLAY_JSON_FORM, display_step: DISPLAY_JSON_FORM,
softwareindex: e.selectedOptions[0]["data-id"], softwareindex: e.selectedOptions[0]["data-id"],
...@@ -608,12 +106,6 @@ ...@@ -608,12 +106,6 @@
} }
function showRawParameter(g) { function showRawParameter(g) {
var e = g.element.querySelector("button.slapos-show-raw-parameter"),
to_show = g.element.querySelector("button.slapos-show-form");
e.classList.add("display-none");
to_show.classList.remove("display-none");
return g.changeState({ return g.changeState({
display_step: DISPLAY_RAW_XML, display_step: DISPLAY_RAW_XML,
// Force refresh in any case // Force refresh in any case
...@@ -621,31 +113,11 @@ ...@@ -621,31 +113,11 @@
}); });
} }
function updateParameterForm(g) {
var e = g.element.getElementsByTagName('select')[0],
parameter_shared = g.element.querySelector('input.parameter_shared');
if (e === undefined) {
throw new Error("Select not found.");
}
parameter_shared.value = e.selectedOptions[0]["data-shared"];
return g.changeState({
softwareindex: e.selectedOptions[0]["data-id"],
// Force refresh in any case
render_timestamp: new Date().getTime()
});
}
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
// check the form validity // check the form validity
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
function checkValidity(g) { function checkValidity(g) {
var json_url = g.state.json_url, var software_type = getSoftwareTypeFromForm(g.element);
software_type = getSoftwareTypeFromForm(g.element),
json_dict = getFormValuesAsJSONDict(g.element),
schema_url = getSchemaUrlFromForm(g.element),
serialisation_type = getSerialisationTypeFromForm(g.element);
if (software_type === "") { if (software_type === "") {
if (g.state.shared) { if (g.state.shared) {
...@@ -654,67 +126,20 @@ ...@@ -654,67 +126,20 @@
throw new Error("The software type is not part of the json (" + software_type + ")"); throw new Error("The software type is not part of the json (" + software_type + ")");
} }
return g.getBaseUrl(json_url) return g.getDeclaredGadget('json_form')
.push(function (base_url) { .push(function (gadget) {
return g.validateJSON(base_url, schema_url, json_dict); return gadget.getContent();
}) })
.push(function (validation) { .push(function (json_dict) {
var error_index, var parameter_hash_input = g.element.querySelectorAll('.parameter_hash_output')[0],
parameter_hash_input = g.element.querySelectorAll('.parameter_hash_output')[0], serialisation_type = getSerialisationTypeFromForm(g.element),
field_name, xml_output;
div,
xml_output,
input_field,
error_dict;
g.element.querySelectorAll("span.error").forEach(function (span, i) {
span.textContent = "";
});
g.element.querySelectorAll("div.error-input").forEach(function (div, i) {
div.setAttribute("class", "");
});
if (serialisation_type === "json-in-xml") { if (serialisation_type === "json-in-xml") {
xml_output = jsonDictToParameterJSONInXML(json_dict); xml_output = jsonDictToParameterJSONInXML(json_dict);
} else { } else {
xml_output = jsonDictToParameterXML(json_dict); xml_output = jsonDictToParameterXML(json_dict);
} }
parameter_hash_input.value = btoa(xml_output); parameter_hash_input.value = btoa(xml_output);
// Update fields if errors exist
for (error_index in validation.errors) {
if (validation.errors.hasOwnProperty(error_index)) {
error_dict = validation.errors[error_index];
// error_dict = { error : "", instanceLocation: "#", keyword: "", keywordLocation: "" }
field_name = error_dict.instanceLocation.slice(1);
if (field_name !== "") {
input_field = g.element.querySelector(".slapos-parameter[name='/" + field_name + "']");
if (input_field === null) {
field_name = field_name.split("/").slice(0, -1).join("/");
input_field = g.element.querySelector(".slapos-parameter[name='/" + field_name + "']");
}
if (input_field !== null) {
div = input_field.parentNode;
div.setAttribute("class", "slapos-parameter error-input");
div.querySelector("span.error").textContent = validation.errors[error_index].error;
}
} else if (error_dict.keyword === "required") {
// Specific use case for required
field_name = "/" + error_dict.key;
input_field = g.element.querySelector(".slapos-parameter[name='/" + field_name + "']");
if (input_field === null) {
field_name = field_name.split("/").slice(0, -1).join("/");
input_field = g.element.querySelector(".slapos-parameter[name='/" + field_name + "']");
}
if (input_field !== null) {
div = input_field.parentNode;
div.setAttribute("class", "slapos-parameter error-input");
div.querySelector("span.error").textContent = error_dict.error;
}
}
}
}
return xml_output; return xml_output;
}); });
} }
...@@ -723,22 +148,19 @@ ...@@ -723,22 +148,19 @@
// main render display functions // main render display functions
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
function renderDisplayRawXml(g, error_text) { function renderDisplayRawXml(g, error_text) {
var fieldset, var fieldset = g.element.querySelector('fieldset.parameter-optional'),
fieldset_list = g.element.querySelectorAll('fieldset'), failover_div = g.element.querySelector('div.failover-textarea'),
div_error, div_error,
textarea, textarea,
show_raw_button = g.element.querySelector("button.slapos-show-raw-parameter"), show_text_button = g.element.querySelector("button.slapos-show-raw-parameter"),
show_form_button = g.element.querySelector("button.slapos-show-form"); show_form_button = g.element.querySelector("button.slapos-show-form");
if (error_text) { show_text_button.disabled = 1;
if (show_raw_button !== null) { show_text_button.classList.remove("ui-icon-code");
show_raw_button.classList.add("display-none"); show_text_button.classList.add("ui-icon-spinner");
} show_form_button.disabled = 0;
if (show_form_button !== null) {
show_form_button.classList.remove("display-none");
}
if (error_text) {
div_error = domsugar('div', { div_error = domsugar('div', {
'class': 'error' 'class': 'error'
}, [ }, [
...@@ -768,23 +190,27 @@ ...@@ -768,23 +190,27 @@
if (!g.state.editable) { if (!g.state.editable) {
textarea.setAttribute("readonly", true); textarea.setAttribute("readonly", true);
} }
fieldset = domsugar('fieldset', [
domsugar('div', { return g.renderSubForm("", {}, {}, true)
'class': 'field' .push(function () {
}, [ // Do not hide the Software type, let the user edit it.
textarea failover_div = domsugar(failover_div, {}, [
]), domsugar('div', {
// div error 'class': 'field'
div_error }, [
]); textarea
]),
// Do not hide the Software type, let the user edit it. // div error
fieldset_list[1].parentNode.replaceChild( div_error
fieldset, ]);
fieldset_list[1] fieldset = domsugar(fieldset);
); return failover_div;
fieldset_list[2].innerHTML = ''; })
return fieldset; .push(function (failover_div) {
show_text_button.classList.remove("ui-icon-spinner");
show_text_button.classList.add("ui-icon-code");
return failover_div;
});
} }
function renderDisplayJsonForm(gadget) { function renderDisplayJsonForm(gadget) {
...@@ -796,20 +222,18 @@ ...@@ -796,20 +222,18 @@
softwaretype = gadget.state.softwaretype, softwaretype = gadget.state.softwaretype,
softwareindex = gadget.state.softwareindex, softwareindex = gadget.state.softwareindex,
editable = gadget.state.editable, editable = gadget.state.editable,
to_hide = gadget.element.querySelector("button.slapos-show-form"), show_form_button = gadget.element.querySelector("button.slapos-show-form"),
to_show = gadget.element.querySelector("button.slapos-show-raw-parameter"); show_text_button = gadget.element.querySelector("button.slapos-show-raw-parameter");
show_form_button.disabled = 1;
show_form_button.classList.remove("ui-icon-th-list");
show_form_button.classList.add("ui-icon-spinner");
show_text_button.disabled = 0;
if (json_url === undefined) { if (json_url === undefined) {
throw new Error("undefined json_url"); throw new Error("undefined json_url");
} }
if (to_hide !== null) {
to_hide.classList.add("display-none");
}
if (to_show !== null) {
to_show.classList.remove("display-none");
}
return gadget.loadSoftwareJSON(json_url) return gadget.loadSoftwareJSON(json_url)
.push(function (json) { .push(function (json) {
var option_index, var option_index,
...@@ -822,7 +246,13 @@ ...@@ -822,7 +246,13 @@
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,
parameter_json_schema_url,
parameter_dict = {},
parameter_list,
json_url_uri,
prefix,
parameter_entry;
if (!editable || gadget.state.restricted_softwaretype === true) { if (!editable || gadget.state.restricted_softwaretype === true) {
input.classList.add("readonly"); input.classList.add("readonly");
...@@ -951,11 +381,7 @@ ...@@ -951,11 +381,7 @@
// Save current schema on the field // Save current schema on the field
parameter_schema_url.value = json['software-type'][option_selected_index].request; parameter_schema_url.value = json['software-type'][option_selected_index].request;
parameter_json_schema_url = parameter_schema_url.value;
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 (parameter_xml !== undefined) {
if (serialisation === "json-in-xml") { if (serialisation === "json-in-xml") {
...@@ -985,16 +411,24 @@ ...@@ -985,16 +411,24 @@
'text/xml' 'text/xml'
).querySelector("parameter[id='_']"); ).querySelector("parameter[id='_']");
if (parameter_entry !== null) { parameter_list = parseDocumentStringOrFail(
throw new Error("The current parameter values should NOT contains _ parameter (xml).");
}
parseDocumentStringOrFail(
parameter_xml, parameter_xml,
'text/xml' 'text/xml'
).querySelectorAll("parameter") ).querySelectorAll("parameter");
.forEach(function (element, index) {
parameter_dict[element.id] = element.textContent; if (parameter_entry !== null) {
}); if (parameter_entry.textContent !== "{}") {
throw new Error("The current parameter values should NOT contains _ parameter (xml).");
}
}
parameter_list.forEach(
function (element, index) {
if (!((element.id === "_") && (element.textContent === "{}"))) {
parameter_dict[element.id] = element.textContent;
}
}
);
} else { } else {
throw new Error("Unknown serialisation: " + serialisation); throw new Error("Unknown serialisation: " + serialisation);
} }
...@@ -1010,34 +444,26 @@ ...@@ -1010,34 +444,26 @@
} }
return gadget.loadJSONSchema(parameter_json_schema_url, serialisation) return gadget.loadJSONSchema(parameter_json_schema_url, serialisation)
.push(function (json) { .push(function (json) {
var fieldset_list = gadget.element.querySelectorAll('fieldset'), // Reset failover text area
fieldset = document.createElement("fieldset"); domsugar(gadget.element.querySelector('div.failover-textarea'));
return gadget.renderSubForm(
fieldset = render_subform(json, parameter_dict, fieldset, undefined, editable); parameter_json_schema_url,
fieldset_list[1].parentNode.replaceChild( json,
fieldset, parameter_dict,
fieldset_list[1] editable
); );
return fieldset_list;
}); });
}) })
.push(function () { .push(function (changed) {
var i, div_list = gadget.element.querySelectorAll('.slapos-parameter-dict-key > div'), show_form_button.classList.remove("ui-icon-spinner");
label_list = gadget.element.querySelectorAll('label.slapos-parameter-dict-key'); show_form_button.classList.add("ui-icon-th-list");
return changed;
for (i = 0; i < div_list.length; i = i + 1) {
// This should be replaced by a proper class hidden-div
div_list[i].classList.add('display-none');
}
for (i = 0; i < label_list.length; i = i + 1) {
label_list[i].classList.add("slapos-parameter-dict-key-colapse");
}
}) })
.fail(function (error) { .fail(function (error) {
console.warn(error); console.warn(error);
console.log(error.stack); console.log(error.stack);
show_form_button.classList.remove("ui-icon-spinner");
show_form_button.classList.add("ui-icon-th-list");
return renderDisplayRawXml(gadget, error.toString()); return renderDisplayRawXml(gadget, error.toString());
}); });
} }
...@@ -1056,23 +482,22 @@ ...@@ -1056,23 +482,22 @@
}); });
}) })
.declareMethod("validateJSON", function (base_url, schema_url, generated_json) { .declareMethod("loadSoftwareJSON", function (url) {
return this.getDeclaredGadget('loadschema') return this.getDeclaredGadget('loadschema')
.push(function (gadget) { .push(function (gadget) {
return gadget.validateJSON(base_url, schema_url, generated_json); return gadget.loadSoftwareJSON(url);
}); });
}) })
.declareMethod("getBaseUrl", function (url) { .declareMethod("renderSubForm", function (parameter_json_schema_url, json_field, default_dict, editable) {
return this.getDeclaredGadget('loadschema') return this.getDeclaredGadget('json_form')
.push(function (gadget) { .push(function (gadget) {
return gadget.getBaseUrl(url); return gadget.render({
}); schema_url: parameter_json_schema_url,
}) json_field: json_field,
.declareMethod("loadSoftwareJSON", function (url) { default_dict: default_dict,
return this.getDeclaredGadget('loadschema') editable: editable
.push(function (gadget) { });
return gadget.loadSoftwareJSON(url);
}); });
}) })
...@@ -1099,7 +524,6 @@ ...@@ -1099,7 +524,6 @@
software_type_list.push(options.value.parameter.softwaretype); software_type_list.push(options.value.parameter.softwaretype);
} }
return this.changeState({ return this.changeState({
// Not used parameters // Not used parameters
// hidden: options.hidden, // hidden: options.hidden,
...@@ -1129,19 +553,21 @@ ...@@ -1129,19 +553,21 @@
.onEvent("change", function (evt) { .onEvent("change", function (evt) {
var gadget = this, var gadget = this,
software_type_element = gadget.element.getElementsByTagName('select')[0]; software_type_element = gadget.element.getElementsByTagName('select')[0],
parameter_shared = gadget.element.querySelector('input.parameter_shared');
if (evt.target === software_type_element) { if (evt.target === software_type_element) {
return updateParameterForm(gadget); parameter_shared.value = software_type_element.selectedOptions[0]["data-shared"];
} // call get content to ensure data is saved.
return gadget.getContent()
// @ts-ignore .push(function () {
if (evt.target.className.indexOf("slapos-parameter") !== -1) { return gadget.changeState({
// getContent is protected by a mutex which prevent softwareindex: software_type_element.selectedOptions[0]["data-id"],
// onchangestate to be called in parallel // Force refresh in any case
return gadget.getContent(); render_timestamp: new Date().getTime()
});
});
} }
}, false, false) }, false, false)
.onEvent("click", function (evt) { .onEvent("click", function (evt) {
...@@ -1151,18 +577,6 @@ ...@@ -1151,18 +577,6 @@
// @ts-ignore // @ts-ignore
tag_name = evt.target.tagName; tag_name = evt.target.tagName;
if ((tag_name === 'LABEL') &&
// @ts-ignore
(evt.target.className.indexOf("slapos-parameter-dict-key") !== -1)) {
return collapseParameter(evt.target);
}
if ((tag_name === 'SPAN') &&
// @ts-ignore
(evt.target.className.indexOf("bt_close") !== -1)) {
return removeSubParameter(evt.target);
}
if (tag_name === 'BUTTON') { if (tag_name === 'BUTTON') {
// Disable any button. It must be managed by this gadget // Disable any button. It must be managed by this gadget
evt.preventDefault(); evt.preventDefault();
...@@ -1189,15 +603,6 @@ ...@@ -1189,15 +603,6 @@
return showRawParameter(gadget); return showRawParameter(gadget);
}); });
} }
if ((tag_name === 'BUTTON') &&
// @ts-ignore
(evt.target.className.indexOf("add-sub-form") !== -1)) {
return queue
.push(function () {
return addSubForm(gadget, evt.target);
});
}
}, false, false) }, false, false)
.declareMethod('getContent', function () { .declareMethod('getContent', function () {
...@@ -1237,5 +642,5 @@ ...@@ -1237,5 +642,5 @@
}); });
}, {mutex: 'statechange'}); }, {mutex: 'statechange'});
}(window, document, rJS, XMLSerializer, DOMParser, vkbeautify, }(window, rJS, XMLSerializer, DOMParser, vkbeautify,
domsugar, Boolean, URI)); domsugar, Boolean, URI));
...@@ -284,7 +284,7 @@ ...@@ -284,7 +284,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>1005.42112.63718.7782</string> </value> <value> <string>1007.64857.33700.1467</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -304,7 +304,7 @@ ...@@ -304,7 +304,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1676052985.24</float> <float>1682532947.32</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
...@@ -28,14 +28,19 @@ ...@@ -28,14 +28,19 @@
<input type=hidden name="serialisation_type" class="slapos-serialisation-type"> <input type=hidden name="serialisation_type" class="slapos-serialisation-type">
</div> </div>
</div> </div>
<div class="field" title="hide_show_button"> <div class="field slapos-parameter-editor-button" title="hide_show_button">
<div class="input"> <div class="input">
<button type="button" class="slapos-show-form hidden-button"> 展开参数表格 </button> <button type="button" class="slapos-show-form ui-btn-icon-left ui-icon-spinner"> 展开参数表格 </button>
<button type="button" class="slapos-show-raw-parameter"> 展开参数XML</button> <button type="button" class="slapos-show-raw-parameterui-btn-icon-left ui-icon-code" disabled> 展开参数XML</button>
</div> </div>
</div> </div>
</fieldset> </fieldset>
<fieldset id="parameter-main"> </fieldset> <fieldset id="parameter-main">
<div class="parameter_json_form"
data-gadget-url="gadget_erp5_page_slap_json_form.html"
data-gadget-scope="json_form"> </div>
<div class="failover-textarea"> </div>
</fieldset>
<fieldset id="parameter-optional"> </fieldset> <fieldset id="parameter-optional"> </fieldset>
<fieldset id="parameter-xml"> <fieldset id="parameter-xml">
<input type=hidden name="parameter_hash" class="parameter_hash_output"> <input type=hidden name="parameter_hash" class="parameter_hash_output">
......
image_module/gadget_slapos_panel_png
image_module/gadget_slapos_invoice_logo_png image_module/gadget_slapos_invoice_logo_png
image_module/gadget_slapos_panel_png
web_page_module/gadget_erp5_page_slap_cloud_contract_view_html web_page_module/gadget_erp5_page_slap_cloud_contract_view_html
web_page_module/gadget_erp5_page_slap_cloud_contract_view_js web_page_module/gadget_erp5_page_slap_cloud_contract_view_js
web_page_module/gadget_erp5_page_slap_request_contract_activation_html
web_page_module/gadget_erp5_page_slap_request_contract_activation_js
web_page_module/gadget_erp5_page_slap_reject_upgrade_decision_html web_page_module/gadget_erp5_page_slap_reject_upgrade_decision_html
web_page_module/gadget_erp5_page_slap_reject_upgrade_decision_js web_page_module/gadget_erp5_page_slap_reject_upgrade_decision_js
web_page_module/gadget_erp5_page_slap_request_contract_activation_html
web_page_module/gadget_erp5_page_slap_request_contract_activation_js
web_page_module/rjs_gadget_erp5_attention_point_css web_page_module/rjs_gadget_erp5_attention_point_css
web_page_module/rjs_gadget_erp5_attention_point_html web_page_module/rjs_gadget_erp5_attention_point_html
web_page_module/rjs_gadget_erp5_page_slap_language_view_html
web_page_module/rjs_gadget_erp5_page_slap_language_view_js
web_page_module/rjs_gadget_erp5_attention_point_js web_page_module/rjs_gadget_erp5_attention_point_js
web_page_module/rjs_gadget_slapos_annotated_helper_css
web_page_module/rjs_gadget_slapos_annotated_helper_html
web_page_module/rjs_gadget_slapos_annotated_helper_js
web_page_module/rjs_gadget_erp5_page_map_css web_page_module/rjs_gadget_erp5_page_map_css
web_page_module/rjs_gadget_erp5_page_map_html web_page_module/rjs_gadget_erp5_page_map_html
web_page_module/rjs_gadget_erp5_page_map_js web_page_module/rjs_gadget_erp5_page_map_js
web_page_module/rjs_gadget_erp5_page_slap_accept_upgrade_decision_html web_page_module/rjs_gadget_erp5_page_slap_accept_upgrade_decision_html
web_page_module/rjs_gadget_erp5_page_slap_accept_upgrade_decision_js web_page_module/rjs_gadget_erp5_page_slap_accept_upgrade_decision_js
web_page_module/rjs_gadget_erp5_page_slap_access_denied_view_html
web_page_module/rjs_gadget_erp5_page_slap_access_denied_view_js
web_page_module/rjs_gadget_erp5_page_slap_add_compute_node_html web_page_module/rjs_gadget_erp5_page_slap_add_compute_node_html
web_page_module/rjs_gadget_erp5_page_slap_add_compute_node_js web_page_module/rjs_gadget_erp5_page_slap_add_compute_node_js
web_page_module/rjs_gadget_erp5_page_slap_add_instance_tree_html web_page_module/rjs_gadget_erp5_page_slap_add_instance_tree_html
...@@ -47,14 +44,14 @@ web_page_module/rjs_gadget_erp5_page_slap_compute_node_get_token_html ...@@ -47,14 +44,14 @@ web_page_module/rjs_gadget_erp5_page_slap_compute_node_get_token_html
web_page_module/rjs_gadget_erp5_page_slap_compute_node_get_token_js web_page_module/rjs_gadget_erp5_page_slap_compute_node_get_token_js
web_page_module/rjs_gadget_erp5_page_slap_compute_node_list_html web_page_module/rjs_gadget_erp5_page_slap_compute_node_list_html
web_page_module/rjs_gadget_erp5_page_slap_compute_node_list_js web_page_module/rjs_gadget_erp5_page_slap_compute_node_list_js
web_page_module/rjs_gadget_erp5_page_slap_computer_network_view_html
web_page_module/rjs_gadget_erp5_page_slap_computer_network_view_js
web_page_module/rjs_gadget_erp5_page_slap_compute_node_request_certificate_html web_page_module/rjs_gadget_erp5_page_slap_compute_node_request_certificate_html
web_page_module/rjs_gadget_erp5_page_slap_compute_node_request_certificate_js web_page_module/rjs_gadget_erp5_page_slap_compute_node_request_certificate_js
web_page_module/rjs_gadget_erp5_page_slap_compute_node_revoke_certificate_html web_page_module/rjs_gadget_erp5_page_slap_compute_node_revoke_certificate_html
web_page_module/rjs_gadget_erp5_page_slap_compute_node_revoke_certificate_js web_page_module/rjs_gadget_erp5_page_slap_compute_node_revoke_certificate_js
web_page_module/rjs_gadget_erp5_page_slap_compute_node_view_html web_page_module/rjs_gadget_erp5_page_slap_compute_node_view_html
web_page_module/rjs_gadget_erp5_page_slap_compute_node_view_js web_page_module/rjs_gadget_erp5_page_slap_compute_node_view_js
web_page_module/rjs_gadget_erp5_page_slap_computer_network_view_html
web_page_module/rjs_gadget_erp5_page_slap_computer_network_view_js
web_page_module/rjs_gadget_erp5_page_slap_controller_html web_page_module/rjs_gadget_erp5_page_slap_controller_html
web_page_module/rjs_gadget_erp5_page_slap_controller_js web_page_module/rjs_gadget_erp5_page_slap_controller_js
web_page_module/rjs_gadget_erp5_page_slap_delete_network_html web_page_module/rjs_gadget_erp5_page_slap_delete_network_html
...@@ -75,14 +72,17 @@ web_page_module/rjs_gadget_erp5_page_slap_google_login_view_html ...@@ -75,14 +72,17 @@ web_page_module/rjs_gadget_erp5_page_slap_google_login_view_html
web_page_module/rjs_gadget_erp5_page_slap_google_login_view_js web_page_module/rjs_gadget_erp5_page_slap_google_login_view_js
web_page_module/rjs_gadget_erp5_page_slap_instance_tree_view_html web_page_module/rjs_gadget_erp5_page_slap_instance_tree_view_html
web_page_module/rjs_gadget_erp5_page_slap_instance_tree_view_js web_page_module/rjs_gadget_erp5_page_slap_instance_tree_view_js
web_page_module/rjs_gadget_erp5_page_slap_access_denied_view_html
web_page_module/rjs_gadget_erp5_page_slap_access_denied_view_js
web_page_module/rjs_gadget_erp5_page_slap_intent_html web_page_module/rjs_gadget_erp5_page_slap_intent_html
web_page_module/rjs_gadget_erp5_page_slap_intent_js web_page_module/rjs_gadget_erp5_page_slap_intent_js
web_page_module/rjs_gadget_erp5_page_slap_invalidate_login_html web_page_module/rjs_gadget_erp5_page_slap_invalidate_login_html
web_page_module/rjs_gadget_erp5_page_slap_invalidate_login_js web_page_module/rjs_gadget_erp5_page_slap_invalidate_login_js
web_page_module/rjs_gadget_erp5_page_slap_invoice_list_html web_page_module/rjs_gadget_erp5_page_slap_invoice_list_html
web_page_module/rjs_gadget_erp5_page_slap_invoice_list_js web_page_module/rjs_gadget_erp5_page_slap_invoice_list_js
web_page_module/rjs_gadget_erp5_page_slap_json_form_css
web_page_module/rjs_gadget_erp5_page_slap_json_form_html
web_page_module/rjs_gadget_erp5_page_slap_json_form_js
web_page_module/rjs_gadget_erp5_page_slap_language_view_html
web_page_module/rjs_gadget_erp5_page_slap_language_view_js
web_page_module/rjs_gadget_erp5_page_slap_load_schema_html web_page_module/rjs_gadget_erp5_page_slap_load_schema_html
web_page_module/rjs_gadget_erp5_page_slap_load_schema_js web_page_module/rjs_gadget_erp5_page_slap_load_schema_js
web_page_module/rjs_gadget_erp5_page_slap_network_list_html web_page_module/rjs_gadget_erp5_page_slap_network_list_html
...@@ -141,6 +141,10 @@ web_page_module/rjs_gadget_erp5_page_slap_start_instance_tree_js ...@@ -141,6 +141,10 @@ web_page_module/rjs_gadget_erp5_page_slap_start_instance_tree_js
web_page_module/rjs_gadget_erp5_page_slap_stop_instance_tree_html web_page_module/rjs_gadget_erp5_page_slap_stop_instance_tree_html
web_page_module/rjs_gadget_erp5_page_slap_stop_instance_tree_js web_page_module/rjs_gadget_erp5_page_slap_stop_instance_tree_js
web_page_module/rjs_gadget_erp5_page_slap_support_request_view_html web_page_module/rjs_gadget_erp5_page_slap_support_request_view_html
web_page_module/rjs_gadget_erp5_page_slap_test_parameter_form_html
web_page_module/rjs_gadget_erp5_page_slap_test_parameter_form_js
web_page_module/rjs_gadget_erp5_page_slap_test_readonly_parameter_form_html
web_page_module/rjs_gadget_erp5_page_slap_test_readonly_parameter_form_js
web_page_module/rjs_gadget_erp5_page_slap_ticket_list_html web_page_module/rjs_gadget_erp5_page_slap_ticket_list_html
web_page_module/rjs_gadget_erp5_page_slap_ticket_list_js web_page_module/rjs_gadget_erp5_page_slap_ticket_list_js
web_page_module/rjs_gadget_erp5_page_slap_ticket_view_js web_page_module/rjs_gadget_erp5_page_slap_ticket_view_js
...@@ -165,10 +169,12 @@ web_page_module/rjs_gadget_erp5_pt_form_slapos_index_js ...@@ -165,10 +169,12 @@ web_page_module/rjs_gadget_erp5_pt_form_slapos_index_js
web_page_module/rjs_gadget_slapos_alert_listbox_field_css web_page_module/rjs_gadget_slapos_alert_listbox_field_css
web_page_module/rjs_gadget_slapos_alert_listbox_field_html web_page_module/rjs_gadget_slapos_alert_listbox_field_html
web_page_module/rjs_gadget_slapos_alert_listbox_field_js web_page_module/rjs_gadget_slapos_alert_listbox_field_js
web_page_module/rjs_gadget_slapos_annotated_helper_css
web_page_module/rjs_gadget_slapos_annotated_helper_html
web_page_module/rjs_gadget_slapos_annotated_helper_js
web_page_module/rjs_gadget_slapos_appcache web_page_module/rjs_gadget_slapos_appcache
web_page_module/rjs_gadget_slapos_compute_node_map_html web_page_module/rjs_gadget_slapos_compute_node_map_html
web_page_module/rjs_gadget_slapos_compute_node_map_js web_page_module/rjs_gadget_slapos_compute_node_map_js
web_page_module/rjs_gadget_slapos_status_css
web_page_module/rjs_gadget_slapos_event_discussion_entry_css web_page_module/rjs_gadget_slapos_event_discussion_entry_css
web_page_module/rjs_gadget_slapos_event_discussion_entry_html web_page_module/rjs_gadget_slapos_event_discussion_entry_html
web_page_module/rjs_gadget_slapos_event_discussion_entry_js web_page_module/rjs_gadget_slapos_event_discussion_entry_js
...@@ -180,9 +186,11 @@ web_page_module/rjs_gadget_slapos_invoice_state_html ...@@ -180,9 +186,11 @@ web_page_module/rjs_gadget_slapos_invoice_state_html
web_page_module/rjs_gadget_slapos_invoice_state_js web_page_module/rjs_gadget_slapos_invoice_state_js
web_page_module/rjs_gadget_slapos_label_listbox_field_html web_page_module/rjs_gadget_slapos_label_listbox_field_html
web_page_module/rjs_gadget_slapos_label_listbox_field_js web_page_module/rjs_gadget_slapos_label_listbox_field_js
web_page_module/rjs_gadget_slapos_login_page_css
web_page_module/rjs_gadget_slapos_panel_html web_page_module/rjs_gadget_slapos_panel_html
web_page_module/rjs_gadget_slapos_panel_js web_page_module/rjs_gadget_slapos_panel_js
web_page_module/rjs_gadget_slapos_payment_result_js** web_page_module/rjs_gadget_slapos_payment_result_js**
web_page_module/rjs_gadget_slapos_status_css
web_page_module/rjs_gadget_slapos_status_html web_page_module/rjs_gadget_slapos_status_html
web_page_module/rjs_gadget_slapos_status_js web_page_module/rjs_gadget_slapos_status_js
web_page_module/rjs_gadget_slapos_translation_data_js web_page_module/rjs_gadget_slapos_translation_data_js
...@@ -194,11 +202,6 @@ web_page_module/rjs_slapos_load_meta_schema_json ...@@ -194,11 +202,6 @@ web_page_module/rjs_slapos_load_meta_schema_json
web_page_module/rjs_slapos_load_meta_schema_xml_in_json_json web_page_module/rjs_slapos_load_meta_schema_xml_in_json_json
web_page_module/rjs_slapos_load_meta_schema_xml_json web_page_module/rjs_slapos_load_meta_schema_xml_json
web_page_module/rjs_slapos_load_software_schema_json web_page_module/rjs_slapos_load_software_schema_json
web_page_module/rjs_gadget_slapos_login_page_css
web_page_module/rjs_gadget_erp5_page_slap_test_parameter_form_js
web_page_module/rjs_gadget_erp5_page_slap_test_parameter_form_html
web_page_module/rjs_gadget_erp5_page_slap_test_readonly_parameter_form_html
web_page_module/rjs_gadget_erp5_page_slap_test_readonly_parameter_form_js
web_page_module/rjs_vkbeautify_js web_page_module/rjs_vkbeautify_js
web_page_module/slapos_admin_front_page web_page_module/slapos_admin_front_page
web_site_module/hostingjs web_site_module/hostingjs
......
web_site_module/hateoas
web_site_module/hateoas/**
web_site_module/renderjs_runner
portal_types/ERP5 Form
portal_propery_sheets/SlapOSHateoasSystemPreference portal_propery_sheets/SlapOSHateoasSystemPreference
portal_types/ERP5 Form
web_page_module/rjs_gadget_erp5_panel_shortcut_html web_page_module/rjs_gadget_erp5_panel_shortcut_html
web_page_module/rjs_gadget_erp5_panel_shortcut_js web_page_module/rjs_gadget_erp5_panel_shortcut_js
web_page_module/slapos_admin_front_page web_page_module/slapos_admin_front_page
\ No newline at end of file web_site_module/hateoas
web_site_module/hateoas/**
web_site_module/renderjs_runner
\ No newline at end of file
...@@ -79,6 +79,9 @@ web_page_module/rjs_gadget_erp5_page_slap_invalidate_login_html ...@@ -79,6 +79,9 @@ web_page_module/rjs_gadget_erp5_page_slap_invalidate_login_html
web_page_module/rjs_gadget_erp5_page_slap_invalidate_login_js web_page_module/rjs_gadget_erp5_page_slap_invalidate_login_js
web_page_module/rjs_gadget_erp5_page_slap_invoice_list_html web_page_module/rjs_gadget_erp5_page_slap_invoice_list_html
web_page_module/rjs_gadget_erp5_page_slap_invoice_list_js web_page_module/rjs_gadget_erp5_page_slap_invoice_list_js
web_page_module/rjs_gadget_erp5_page_slap_json_form_css
web_page_module/rjs_gadget_erp5_page_slap_json_form_html
web_page_module/rjs_gadget_erp5_page_slap_json_form_js
web_page_module/rjs_gadget_erp5_page_slap_language_view_html web_page_module/rjs_gadget_erp5_page_slap_language_view_html
web_page_module/rjs_gadget_erp5_page_slap_language_view_js web_page_module/rjs_gadget_erp5_page_slap_language_view_js
web_page_module/rjs_gadget_erp5_page_slap_load_schema_html web_page_module/rjs_gadget_erp5_page_slap_load_schema_html
......
...@@ -142,17 +142,17 @@ ...@@ -142,17 +142,17 @@
</tr> </tr>
<tr> <tr>
<td>waitForElementPresent</td> <td>waitForElementPresent</td>
<td>//button[@class="slapos-show-form"]</td> <td>//button[contains(@class,"slapos-show-form")]</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
<td>assertElementPresent</td> <td>assertElementPresent</td>
<td>//button[@class="slapos-show-form"]</td> <td>//button[contains(@class,"slapos-show-form")]</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
<td>click</td> <td>click</td>
<td>//button[@class="slapos-show-form"]</td> <td>//button[contains(@class,"slapos-show-form")]</td>
<td></td> <td></td>
</tr> </tr>
...@@ -228,17 +228,17 @@ ...@@ -228,17 +228,17 @@
</tr> </tr>
<tr> <tr>
<td>waitForElementPresent</td> <td>waitForElementPresent</td>
<td>//button[@class="slapos-show-form"]</td> <td>//button[contains(@class,"slapos-show-form")]</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
<td>assertElementPresent</td> <td>assertElementPresent</td>
<td>//button[@class="slapos-show-form"]</td> <td>//button[contains(@class,"slapos-show-form")]</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
<td>click</td> <td>click</td>
<td>//button[@class="slapos-show-form"]</td> <td>//button[contains(@class,"slapos-show-form")]</td>
<td></td> <td></td>
</tr> </tr>
......
...@@ -50,7 +50,6 @@ ...@@ -50,7 +50,6 @@
<td>//textarea[@name="text_content" and contains(text(), '&lt;instance/&gt;')]</td> <td>//textarea[@name="text_content" and contains(text(), '&lt;instance/&gt;')]</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
<td>type</td> <td>type</td>
<td>//textarea[@name="text_content"]</td> <td>//textarea[@name="text_content"]</td>
...@@ -105,9 +104,29 @@ ...@@ -105,9 +104,29 @@
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
<td>assertValue</td> <td>waitForElementPresent</td>
<td>//textarea[@name="text_content"]</td> <td>//textarea[@name="text_content" and contains(text(), '&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;')]</td>
<td>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; ?&gt;&lt;instance&gt;&lt;parameter id=&quot;simple-string&quot;&gt;1024&lt;/parameter&gt;&lt;/instance&gt;</td> <td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//textarea[@name="text_content" and contains(text(), '&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;')]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//textarea[@name="text_content" and contains(text(), '&lt;instance&gt;')]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//textarea[@name="text_content" and contains(text(), '&lt;parameter id=&quot;simple-string&quot;&gt;1024&lt;/parameter&gt;')]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//textarea[@name="text_content" and contains(text(), '&lt;/instance&gt;')]</td>
<td></td>
</tr> </tr>
<tal:block metal:use-macro="here/Zuite_SlapOSParameterCommonTemplate/macros/show_form_parameter" /> <tal:block metal:use-macro="here/Zuite_SlapOSParameterCommonTemplate/macros/show_form_parameter" />
...@@ -133,9 +152,29 @@ ...@@ -133,9 +152,29 @@
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
<td>assertValue</td> <td>waitForElementPresent</td>
<td>//textarea[@name="text_content"]</td> <td>//textarea[@name="text_content" and contains(text(), '&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;')]</td>
<td>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; ?&gt;&lt;instance&gt;&lt;parameter id=&quot;simple-string&quot;&gt;1024&lt;/parameter&gt;&lt;/instance&gt;</td> <td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//textarea[@name="text_content" and contains(text(), '&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;')]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//textarea[@name="text_content" and contains(text(), '&lt;instance&gt;')]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//textarea[@name="text_content" and contains(text(), '&lt;parameter id=&quot;simple-string&quot;&gt;1024&lt;/parameter&gt;')]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//textarea[@name="text_content" and contains(text(), '&lt;/instance&gt;')]</td>
<td></td>
</tr> </tr>
<tr> <tr>
<td>pause</td> <td>pause</td>
......
...@@ -90,7 +90,7 @@ ...@@ -90,7 +90,7 @@
<tr> <tr>
<td>fireEvent</td> <td>fireEvent</td>
<td>//input[@name="//simple-string" and @type="text"]</td> <td>//input[@name="//simple-string" and @type="text"]</td>
<td>change</td> <td>click</td>
</tr> </tr>
<tr> <tr>
<td colspan="3"><b> Assert Error Messages</b></td> <td colspan="3"><b> Assert Error Messages</b></td>
......
...@@ -83,6 +83,16 @@ ...@@ -83,6 +83,16 @@
<td>//input[@name='url_string']</td> <td>//input[@name='url_string']</td>
<td></td> <td></td>
</tr> </tr>
<tr>
<td>waitForElementPresent</td>
<td>//textarea[@name='text_content']</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//textarea[@name='text_content']</td>
<td></td>
</tr>
</tal:block> </tal:block>
<tal:block metal:define-macro="init_readonly"> <tal:block metal:define-macro="init_readonly">
...@@ -113,6 +123,16 @@ ...@@ -113,6 +123,16 @@
<td>//textarea[@name='parameter_output']</td> <td>//textarea[@name='parameter_output']</td>
<td></td> <td></td>
</tr> </tr>
<tr>
<td>waitForElementPresent</td>
<td>//textarea[@name='text_content']</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//textarea[@name='text_content']</td>
<td></td>
</tr>
</tal:block> </tal:block>
<tal:block metal:define-macro="click_proceed_and_wait_for_hash"> <tal:block metal:define-macro="click_proceed_and_wait_for_hash">
...@@ -143,19 +163,19 @@ ...@@ -143,19 +163,19 @@
<tr> <tr>
<td>waitForElementPresent</td> <td>waitForElementPresent</td>
<td>//div[contains(@data-gadget-url, <td>//div[contains(@data-gadget-url,
'gadget_erp5_page_slap_parameter_form.html')]//button[@class="slapos-show-raw-parameter"]</td> 'gadget_erp5_page_slap_parameter_form.html')]//button[contains(@class, "slapos-show-raw-parameter")]</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
<td>waitForElementPresent</td> <td>waitForElementPresent</td>
<td>//div[contains(@data-gadget-url, <td>//div[contains(@data-gadget-url,
'gadget_erp5_page_slap_parameter_form.html')]//button[@class="slapos-show-raw-parameter"]</td> 'gadget_erp5_page_slap_parameter_form.html')]//button[contains(@class, "slapos-show-raw-parameter")]</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
<td>click</td> <td>click</td>
<td>//div[contains(@data-gadget-url, <td>//div[contains(@data-gadget-url,
'gadget_erp5_page_slap_parameter_form.html')]//button[@class="slapos-show-raw-parameter"]</td> 'gadget_erp5_page_slap_parameter_form.html')]//button[contains(@class, "slapos-show-raw-parameter")]</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
...@@ -174,19 +194,19 @@ ...@@ -174,19 +194,19 @@
<tr> <tr>
<td>waitForElementPresent</td> <td>waitForElementPresent</td>
<td>//div[contains(@data-gadget-url, <td>//div[contains(@data-gadget-url,
'gadget_erp5_page_slap_parameter_form.html')]//button[@class="slapos-show-form"]</td> 'gadget_erp5_page_slap_parameter_form.html')]//button[contains(@class, "slapos-show-form")]</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
<td>waitForElementPresent</td> <td>waitForElementPresent</td>
<td>//div[contains(@data-gadget-url, <td>//div[contains(@data-gadget-url,
'gadget_erp5_page_slap_parameter_form.html')]//button[@class="slapos-show-form"]</td> 'gadget_erp5_page_slap_parameter_form.html')]//button[contains(@class, "slapos-show-form")]</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
<td>click</td> <td>click</td>
<td>//div[contains(@data-gadget-url, <td>//div[contains(@data-gadget-url,
'gadget_erp5_page_slap_parameter_form.html')]//button[@class="slapos-show-form"]</td> 'gadget_erp5_page_slap_parameter_form.html')]//button[contains(@class, "slapos-show-form")]</td>
<td></td> <td></td>
</tr> </tr>
</tal:block> </tal:block>
......
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