Commit 347a9303 authored by Tomáš Peterka's avatar Tomáš Peterka Committed by Tomáš Peterka

[renderjs_ui] Use global functions in gadgets to prevent common struggles

parent 075e87a0
......@@ -9,6 +9,7 @@
<script src="rsvp.js" type="text/javascript"></script>
<script src="renderjs.js" type="text/javascript"></script>
<!-- custom script -->
<script src="gadget_erp5_global.js" type="text/javascript"></script>
<script src="gadget_erp5_field_checkbox.js" type="text/javascript"></script>
</head>
......
......@@ -234,7 +234,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>954.35642.48652.3413</string> </value>
<value> <string>960.5523.58984.43537</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -252,7 +252,7 @@
</tuple>
<state>
<tuple>
<float>1476273705.86</float>
<float>1517998717.51</float>
<string>UTC</string>
</tuple>
</state>
......
/*global window, rJS */
/*global window, rJS, asBoolean, getFirstNonEmpty */
/*jslint indent: 2, maxerr: 3, maxlen: 80 */
(function (window, rJS) {
(function (window, rJS, asBoolean, getFirstNonEmpty) {
"use strict";
function asBool(obj) {
if (typeof obj === "boolean") {
return obj;
}
if (typeof obj === "string") {
return obj.toLowerCase() === "true" || obj === "1";
}
if (typeof obj === "number") {
return obj !== 0;
}
return Boolean(obj);
}
rJS(window)
.setState({
type: 'checkbox',
......@@ -25,7 +12,7 @@
.declareMethod('render', function (options) {
var field_json = options.field_json || {},
state_dict = {
checked: asBool(field_json.value || field_json.default),
checked: asBoolean(getFirstNonEmpty(field_json.value, field_json.default)),
editable: field_json.editable,
id: field_json.key,
name: field_json.key,
......@@ -96,4 +83,4 @@
}
return true;
}, {mutex: 'changestate'});
}(window, rJS));
\ No newline at end of file
}(window, rJS, asBoolean, getFirstNonEmpty));
\ No newline at end of file
......@@ -230,7 +230,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>965.12118.35525.1655</string> </value>
<value> <string>965.20745.23601.55773</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -248,7 +248,7 @@
</tuple>
<state>
<tuple>
<float>1517929521.54</float>
<float>1517998687.67</float>
<string>UTC</string>
</tuple>
</state>
......
/*global window, RSVP */
/*global window, RSVP, Array, isNaN */
/*jslint indent: 2, maxerr: 3, nomen: true, unparam: true */
(function (window, RSVP) {
(function (window, RSVP, Array, isNaN) {
"use strict";
window.calculatePageTitle = function (gadget, erp5_document) {
......@@ -22,7 +22,8 @@
function isEmpty(value) {
return (value === undefined ||
value === null ||
value.length === 0);
value.length === 0 ||
(typeof value === "number" && isNaN(value)));
}
window.isEmpty = isEmpty;
......@@ -57,4 +58,19 @@
}
window.getFirstNonEmpty = getFirstNonEmpty;
}(window, RSVP));
\ No newline at end of file
/** Convert anything to boolean value correctly (even "false" will be false)*/
function asBoolean(obj) {
if (typeof obj === "boolean") {
return obj;
}
if (typeof obj === "string") {
return obj.toLowerCase() === "true" || obj === "1";
}
if (typeof obj === "number") {
return obj !== 0;
}
return Boolean(obj);
}
window.asBoolean = asBoolean;
}(window, RSVP, Array, isNaN));
\ No newline at end of file
......@@ -230,7 +230,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>960.5523.58984.43537</string> </value>
<value> <string>965.21896.64692.61286</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -248,7 +248,7 @@
</tuple>
<state>
<tuple>
<float>1517406504.9</float>
<float>1517998628.97</float>
<string>UTC</string>
</tuple>
</state>
......
......@@ -9,6 +9,7 @@
<script src="rsvp.js" type="text/javascript"></script>
<script src="renderjs.js" type="text/javascript"></script>
<!-- custom script -->
<script src="gadget_erp5_global.js" type="text/javascript"></script>
<script src="gadget_erp5_field_integer.js" type="text/javascript"></script>
</head>
......
......@@ -234,7 +234,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>956.15544.49991.48571</string> </value>
<value> <string>960.5523.58984.43537</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -252,7 +252,7 @@
</tuple>
<state>
<tuple>
<float>1482832904.74</float>
<float>1517932442.53</float>
<string>UTC</string>
</tuple>
</state>
......
/*global window, rJS */
/*global window, rJS, getFirstNonEmpty */
/*jslint indent: 2, maxerr: 3 */
(function (window, rJS) {
(function (window, rJS, getFirstNonEmpty) {
"use strict";
rJS(window)
......@@ -13,7 +13,7 @@
.declareMethod('render', function (options) {
var field_json = options.field_json || {},
state_dict = {
value: field_json.value || field_json.default || "",
value: getFirstNonEmpty(field_json.value, field_json.default, ""),
editable: field_json.editable,
required: field_json.required,
id: field_json.key,
......@@ -78,4 +78,4 @@
return true;
}, {mutex: 'changestate'});
}(window, rJS));
\ No newline at end of file
}(window, rJS, getFirstNonEmpty));
\ No newline at end of file
/*global window, rJS, isEmpty, getFirstNonEmpty */
/*global window, rJS, isEmpty, getFirstNonEmpty, ensureArray */
/*jslint nomen: true, indent: 2, maxerr: 3, maxlen: 80 */
(function (window, rJS, getFirstNonEmpty) {
(function (window, rJS, getFirstNonEmpty, ensureArray) {
"use strict";
rJS(window)
......@@ -10,10 +10,14 @@
.declareMethod('render', function (options) {
var field_json = options.field_json || {},
item_list = ensureArray(field_json.items).map(function (item) {
if (Array.isArray(item)) {return item; }
else {return [item, item]; }
}),
state_dict = {
value: getFirstNonEmpty(field_json.value, field_json['default'], ""),
item_list: JSON.stringify(field_json.items),
editable: field_json.editable,
item_list: JSON.stringify(item_list),
required: field_json.required,
name: field_json.key,
title: field_json.title,
......@@ -111,4 +115,4 @@
return true;
}, {mutex: 'changestate'});
}(window, rJS, getFirstNonEmpty));
\ No newline at end of file
}(window, rJS, getFirstNonEmpty, ensureArray));
\ No newline at end of file
......@@ -230,7 +230,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>965.10978.44363.39543</string> </value>
<value> <string>965.32182.25672.48110</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -248,7 +248,7 @@
</tuple>
<state>
<tuple>
<float>1517406625.1</float>
<float>1518615992.91</float>
<string>UTC</string>
</tuple>
</state>
......
......@@ -30,7 +30,10 @@
rJS(window)
.declareMethod('render', function (options) {
var field_json = options.field_json || {},
item_list = ensureArray(field_json.items),
item_list = ensureArray(field_json.items).map(function (item) {
if (Array.isArray(item)) {return item; }
else {return [item, item]; }
}),
state_dict = {
value_list: JSON.stringify(
ensureArray(
......@@ -48,11 +51,6 @@
// as user may have modified the input value
render_timestamp: new Date().getTime()
};
// Items can be simply an array of values. It is a valid input produced
// usually by TALES expression
if (item_list.length > 0 && !Array.isArray(item_list[0])) {
item_list = item_list.map(function (item) {return [item, item]; });
}
if ((item_list.length === 0) || (item_list[0][0] !== "")) {
item_list.unshift(["", ""]);
}
......
......@@ -230,7 +230,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>965.12125.45407.61132</string> </value>
<value> <string>965.32192.21351.33041</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -248,7 +248,7 @@
</tuple>
<state>
<tuple>
<float>1517413617.75</float>
<float>1518616357.15</float>
<string>UTC</string>
</tuple>
</state>
......
/*global window, rJS, RSVP, Handlebars, calculatePageTitle */
/*global window, rJS, RSVP, Handlebars, calculatePageTitle, ensureArray */
/*jslint nomen: true, indent: 2, maxerr: 3 */
(function (window, rJS, RSVP, Handlebars, calculatePageTitle) {
(function (window, rJS, RSVP, Handlebars, calculatePageTitle, ensureArray) {
"use strict";
/////////////////////////////////////////////////////////////////
......@@ -53,11 +53,6 @@
});
}
function asArray(obj) {
if (!obj) {return []; }
if (Array.isArray(obj)) {return obj; }
return [obj];
}
gadget_klass
/////////////////////////////////////////////////////////////////
......@@ -84,10 +79,10 @@
return gadget.jio_getAttachment(options.jio_key, options.view || "links")
.push(function (result) {
erp5_document = result;
transition_list = asArray(erp5_document._links.action_workflow);
action_list = asArray(erp5_document._links.action_object_jio_action),
clone_list = asArray(erp5_document._links.action_object_clone_action),
delete_list = asArray(erp5_document._links.action_object_delete_action);
transition_list = ensureArray(erp5_document._links.action_workflow);
action_list = ensureArray(erp5_document._links.action_object_jio_action),
clone_list = ensureArray(erp5_document._links.action_object_clone_action),
delete_list = ensureArray(erp5_document._links.action_object_delete_action);
return RSVP.all([
renderLinkList(gadget, "Workflows", "random", transition_list),
......@@ -111,4 +106,4 @@
});
});
}(window, rJS, RSVP, Handlebars, calculatePageTitle));
\ No newline at end of file
}(window, rJS, RSVP, Handlebars, calculatePageTitle, ensureArray));
\ No newline at end of file
......@@ -230,7 +230,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>965.24762.29617.41557</string> </value>
<value> <string>965.24781.43913.41642</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -248,7 +248,7 @@
</tuple>
<state>
<tuple>
<float>1518773411.41</float>
<float>1518183970.49</float>
<string>UTC</string>
</tuple>
</state>
......
......@@ -234,7 +234,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>962.12738.19263.46301</string> </value>
<value> <string>965.23602.19682.54818</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -252,7 +252,7 @@
</tuple>
<state>
<tuple>
<float>1505910576.07</float>
<float>1518182112.45</float>
<string>UTC</string>
</tuple>
</state>
......
/*global window, rJS, RSVP, Handlebars, calculatePageTitle */
/*global window, rJS, RSVP, Handlebars, calculatePageTitle, ensureArray */
/*jslint nomen: true, indent: 2, maxerr: 3 */
(function (window, rJS, RSVP, Handlebars, calculatePageTitle) {
(function (window, rJS, RSVP, Handlebars, calculatePageTitle, ensureArray) {
"use strict";
/////////////////////////////////////////////////////////////////
......@@ -53,12 +53,6 @@
});
}
function asArray(obj) {
if (!obj) {return []; }
if (Array.isArray(obj)) {return obj; }
return [obj];
}
gadget_klass
/////////////////////////////////////////////////////////////////
// Acquired methods
......@@ -82,8 +76,8 @@
return gadget.jio_getAttachment(options.jio_key, options.view || "links")
.push(function (result) {
erp5_document = result;
report_list = asArray(erp5_document._links.action_object_jio_report),
print_list = asArray(erp5_document._links.action_object_jio_print);
report_list = ensureArray(erp5_document._links.action_object_jio_report),
print_list = ensureArray(erp5_document._links.action_object_jio_print);
return RSVP.all([
renderLinkList(gadget, "Reports", "bar-chart-o", report_list),
......@@ -105,4 +99,4 @@
});
});
}(window, rJS, RSVP, Handlebars, calculatePageTitle));
\ No newline at end of file
}(window, rJS, RSVP, Handlebars, calculatePageTitle, ensureArray));
\ No newline at end of file
......@@ -230,7 +230,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>965.24790.41231.802</string> </value>
<value> <string>965.24987.20289.62754</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -248,7 +248,7 @@
</tuple>
<state>
<tuple>
<float>1518172272.43</float>
<float>1518184046.23</float>
<string>UTC</string>
</tuple>
</state>
......
......@@ -10,6 +10,7 @@
<script src="renderjs.js" type="text/javascript"></script>
<!-- custom script -->
<script src="gadget_erp5_global.js" type="text/javascript"></script>
<script src="gadget_erp5_page_form.js" type="text/javascript"></script>
</head>
......
......@@ -234,7 +234,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>960.5523.58984.43537</string> </value>
<value> <string>961.19210.8471.60620</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -252,7 +252,7 @@
</tuple>
<state>
<tuple>
<float>1501681620.31</float>
<float>1518685706.64</float>
<string>UTC</string>
</tuple>
</state>
......
/*global window, rJS, URI, RSVP */
/*global window, rJS, URI, RSVP, asBoolean */
/*jslint nomen: true, indent: 2, maxerr: 3 */
(function (window, rJS, URI, RSVP) {
(function (window, rJS, URI, RSVP, asBoolean) {
"use strict";
/** Return local modifications to editable form fields after leaving the form
......@@ -16,7 +16,7 @@
if (typeof result[key] === "object" &&
result[key].hasOwnProperty("key") &&
gadget.state.options.form_content[result[key].key]) {
result[key].default = gadget.state.options.form_content[result[key].key];
result[key]['default'] = gadget.state.options.form_content[result[key].key];
}
}
}
......@@ -77,7 +77,7 @@
})
/**
* Render obtain ERP5 Document and assigned Form Definition.
*
*
* Arguments:
* `erp5_document` or parameters to obtain one: `jio_key`, `view`
* `editable`
......@@ -119,7 +119,7 @@
}
// options.editable differs when it comes from the erp5_launcher of FormBox - try to unify it here
if (options.editable === "true" || options.editable === true || options.editable === "1" || options.editable === 1) {
if (asBoolean(options.editable)) {
options.editable = 1;
} else {
options.editable = 0;
......@@ -228,4 +228,4 @@
return this.render(options);
});
}(window, rJS, URI, RSVP));
\ No newline at end of file
}(window, rJS, URI, RSVP, asBoolean));
\ No newline at end of file
......@@ -230,7 +230,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>964.45640.391.48230</string> </value>
<value> <string>965.39414.4325.38963</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -248,7 +248,7 @@
</tuple>
<state>
<tuple>
<float>1516294817.06</float>
<float>1519050232.16</float>
<string>UTC</string>
</tuple>
</state>
......
......@@ -78,6 +78,7 @@
</script>
<!-- custom script -->
<script src="gadget_erp5_global.js" type="text/javascript"></script>
<script src="gadget_erp5_panel.js" type="text/javascript"></script>
</head>
......
......@@ -234,7 +234,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>965.24762.29617.41557</string> </value>
<value> <string>965.39086.65235.37700</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -252,7 +252,7 @@
</tuple>
<state>
<tuple>
<float>1518773364.85</float>
<float>1519039107.29</float>
<string>UTC</string>
</tuple>
</state>
......
/*jslint nomen: true, indent: 2, maxerr: 3, unparam: true */
/*global window, document, rJS, Handlebars, RSVP, Node, loopEventListener */
(function (window, document, rJS, Handlebars, RSVP, Node, loopEventListener) {
/*global window, document, rJS, Handlebars, RSVP, Node, URL, loopEventListener, asBoolean , ensureArray*/
(function (window, document, rJS, Handlebars, RSVP, Node, URL, loopEventListener, asBoolean, ensureArray) {
"use strict";
/////////////////////////////////////////////////////////////////
......@@ -51,25 +51,18 @@
.declareMethod('render', function (options) {
var erp5_document = options.erp5_document,
view = options.view,
context = this,
workflow_list,
view_list,
action_list,
view = options.view,
i,
context = this;
i;
if (erp5_document !== undefined) {
workflow_list = erp5_document._links.action_workflow || [];
view_list = erp5_document._links.action_object_view || [];
action_list = erp5_document._links.action_object_jio_action || [];
if (workflow_list.constructor !== Array) {
workflow_list = [workflow_list];
}
if (view_list.constructor !== Array) {
view_list = [view_list];
}
if (action_list.constructor !== Array) {
action_list = [action_list];
}
workflow_list = ensureArray(erp5_document._links.action_workflow);
view_list = ensureArray(erp5_document._links.action_object_view);
action_list = ensureArray(erp5_document._links.action_object_jio_action);
if (view === 'view') {
for (i = 0; i < view_list.length; i += 1) {
view_list[i].class_name = view_list[i].name === view ? 'active' : '';
......@@ -98,7 +91,7 @@
view_list: view_list,
action_list: action_list,
global: true,
editable: options.editable || editable || false
editable: asBoolean(options.editable) || asBoolean(editable) || false
});
});
})
......@@ -381,4 +374,4 @@
}, /*useCapture=*/false, /*preventDefault=*/true);
}(window, document, rJS, Handlebars, RSVP, Node, loopEventListener));
}(window, document, rJS, Handlebars, RSVP, Node, URL, loopEventListener, asBoolean, ensureArray));
......@@ -230,7 +230,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>965.29136.38081.57361</string> </value>
<value> <string>965.30842.26935.32494</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -248,7 +248,7 @@
</tuple>
<state>
<tuple>
<float>1518441170.76</float>
<float>1518535361.1</float>
<string>UTC</string>
</tuple>
</state>
......
/*global window, rJS, RSVP, calculatePageTitle */
/*global window, rJS, RSVP, calculatePageTitle, isEmpty */
/*jslint nomen: true, indent: 2, maxerr: 3 */
(function (window, rJS, RSVP, calculatePageTitle) {
(function (window, rJS, RSVP, calculatePageTitle, isEmpty) {
"use strict";
/** Return true if `field` resembles non-empty and non-editable field. */
......@@ -12,12 +12,8 @@
if (field.type === "FormBox") {return true; }
// hidden fields should not be obviously rendered
if (field.hidden === 1) {return false; }
// field without default
if (!field['default']) {return false; }
if (field['default'].length === 0) {return false; }
if (field['default'].length === 1 && (!field['default'][0])) {return false; }
return true;
// empty default value is bad and final decision
return !isEmpty(field['default']);
}
rJS(window)
......@@ -138,4 +134,4 @@
});
});
}(window, rJS, RSVP, calculatePageTitle));
}(window, rJS, RSVP, calculatePageTitle, isEmpty));
\ No newline at end of file
......@@ -230,7 +230,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>965.39384.38396.19200</string> </value>
<value> <string>965.24991.31929.23654</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -248,7 +248,7 @@
</tuple>
<state>
<tuple>
<float>1519047884.69</float>
<float>1518620258.94</float>
<string>UTC</string>
</tuple>
</state>
......
/*global window, rJS, RSVP, Handlebars, URI, calculatePageTitle */
/*global window, rJS, RSVP, Handlebars, URI, calculatePageTitle, ensureArray */
/*jslint nomen: true, indent: 2, maxerr: 3 */
/** Page for displaying Views, Jump and BreadCrumb navigation for a document.
*/
(function (window, rJS, RSVP, Handlebars, URI, calculatePageTitle) {
(function (window, rJS, RSVP, Handlebars, URI, calculatePageTitle, ensureArray) {
"use strict";
/////////////////////////////////////////////////////////////////
......@@ -91,17 +91,9 @@
var i,
promise_list = [];
erp5_document = result;
view_list = erp5_document._links.view || [];
jump_list = erp5_document._links.action_object_jump || [];
view_list = ensureArray(erp5_document._links.view);
jump_list = ensureArray(erp5_document._links.action_object_jump);
// All ERP5 document should at least have one view.
// So, no need normally to test undefined
if (view_list.constructor !== Array) {
view_list = [view_list];
}
if (jump_list.constructor !== Array) {
jump_list = [jump_list];
}
for (i = 0; i < view_list.length; i += 1) {
promise_list.push(gadget.getUrlFor({command: 'change', options: {
view: view_list[i].href,
......@@ -178,4 +170,4 @@
});
});
}(window, rJS, RSVP, Handlebars, URI, calculatePageTitle));
\ No newline at end of file
}(window, rJS, RSVP, Handlebars, URI, calculatePageTitle, ensureArray));
\ No newline at end of file
......@@ -230,7 +230,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>965.39422.59074.24098</string> </value>
<value> <string>965.40488.36901.26163</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -248,7 +248,7 @@
</tuple>
<state>
<tuple>
<float>1519114113.71</float>
<float>1519115533.6</float>
<string>UTC</string>
</tuple>
</state>
......
......@@ -9,6 +9,7 @@
<script src="renderjs.js" type="text/javascript"></script>
<script src="jiodev.js" type="text/javascript"></script>
<!-- custom script -->
<script src="gadget_erp5_global.js" type="text/javascript"></script>
<script src="gadget_html5_input.js" type="text/javascript"></script>
</head>
<body><input /></body>
......
......@@ -234,7 +234,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>954.45675.44850.53452</string> </value>
<value> <string>965.20795.64203.38007</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -252,7 +252,7 @@
</tuple>
<state>
<tuple>
<float>1476952312.41</float>
<float>1517933587.68</float>
<string>UTC</string>
</tuple>
</state>
......
/*global window, document, rJS, RSVP, jIO */
/*global window, document, rJS, RSVP, jIO, getFirstNonEmpty */
/*jslint indent: 2, maxerr: 3, maxlen: 80 */
(function (window, document, rJS, RSVP, jIO) {
(function (window, document, rJS, RSVP, jIO, getFirstNonEmpty) {
"use strict";
/** Missing value can have different values based on type.
*
* In general `undefined` and `null` are considered missing values
* Float is missing when `NaN`
*/
function is_missing(value) {
if (value === undefined || value === null) {return true; }
if (typeof value === "number") {return window.isNaN(value); }
return false;
}
rJS(window)
.declareMethod('render', function (options) {
return this.changeState({
// display nothing for missing values
value: is_missing(options.value) ? "" : options.value,
value: getFirstNonEmpty(options.value, ""),
checked: options.checked,
editable: options.editable,
required: options.required,
......@@ -203,4 +191,4 @@
return this.notifyInvalid(evt.target.validationMessage);
}, true, false);
}(window, document, rJS, RSVP, jIO));
\ No newline at end of file
}(window, document, rJS, RSVP, jIO, getFirstNonEmpty));
\ No newline at end of file
......@@ -230,7 +230,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>964.58989.24664.17868</string> </value>
<value> <string>965.20728.48723.60859</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -248,7 +248,7 @@
</tuple>
<state>
<tuple>
<float>1516352669.6</float>
<float>1517936015.16</float>
<string>UTC</string>
</tuple>
</state>
......
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