Commit 376897f7 authored by Romain Courteaud's avatar Romain Courteaud

erp5_web_renderjs_ui: drop translateHTML usage

Keep compatibility with existing officejs tests, by keeping the
data-i18n attributes, even if useless.
parent d3187304
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
<!-- renderjs --> <!-- renderjs -->
<script src="rsvp.js" type="text/javascript"></script> <script src="rsvp.js" type="text/javascript"></script>
<script src="renderjs.js" type="text/javascript"></script> <script src="renderjs.js" type="text/javascript"></script>
<script src="handlebars.js" type="text/javascript"></script> <script src="domsugar.js" type="text/javascript"></script>
<script src="gadget_global.js" type="text/javascript"></script> <script src="gadget_global.js" type="text/javascript"></script>
<!-- custom script --> <!-- custom script -->
......
...@@ -151,11 +151,13 @@ ...@@ -151,11 +151,13 @@
</record> </record>
<record id="3" aka="AAAAAAAAAAM="> <record id="3" aka="AAAAAAAAAAM=">
<pickle> <pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.patches.WorkflowTool"/> <global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle> </pickle>
<pickle> <pickle>
<tuple> <dictionary>
<none/> <item>
<key> <string>_log</string> </key>
<value>
<list> <list>
<dictionary> <dictionary>
<item> <item>
...@@ -199,16 +201,20 @@ ...@@ -199,16 +201,20 @@
</item> </item>
</dictionary> </dictionary>
</list> </list>
</tuple> </value>
</item>
</dictionary>
</pickle> </pickle>
</record> </record>
<record id="4" aka="AAAAAAAAAAQ="> <record id="4" aka="AAAAAAAAAAQ=">
<pickle> <pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.patches.WorkflowTool"/> <global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle> </pickle>
<pickle> <pickle>
<tuple> <dictionary>
<none/> <item>
<key> <string>_log</string> </key>
<value>
<list> <list>
<dictionary> <dictionary>
<item> <item>
...@@ -231,7 +237,7 @@ ...@@ -231,7 +237,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>943.11066.53976.45397</string> </value> <value> <string>981.40707.13352.51541</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -249,8 +255,8 @@ ...@@ -249,8 +255,8 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1432223713.82</float> <float>1583326977.12</float>
<string>GMT</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
</object> </object>
...@@ -258,16 +264,20 @@ ...@@ -258,16 +264,20 @@
</item> </item>
</dictionary> </dictionary>
</list> </list>
</tuple> </value>
</item>
</dictionary>
</pickle> </pickle>
</record> </record>
<record id="5" aka="AAAAAAAAAAU="> <record id="5" aka="AAAAAAAAAAU=">
<pickle> <pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.patches.WorkflowTool"/> <global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle> </pickle>
<pickle> <pickle>
<tuple> <dictionary>
<none/> <item>
<key> <string>_log</string> </key>
<value>
<list> <list>
<dictionary> <dictionary>
<item> <item>
...@@ -315,7 +325,9 @@ ...@@ -315,7 +325,9 @@
</item> </item>
</dictionary> </dictionary>
</list> </list>
</tuple> </value>
</item>
</dictionary>
</pickle> </pickle>
</record> </record>
</ZopeData> </ZopeData>
...@@ -288,6 +288,30 @@ ...@@ -288,6 +288,30 @@
} }
return param_list; return param_list;
}) })
.allowPublicAcquisition("translate", function (param_list) {
if (this.setLanguage) {
return this.getDeclaredGadget("translate")
.push(function (translation_gadget) {
return translation_gadget.translate.apply(
translation_gadget,
param_list
);
});
}
return param_list;
})
.allowPublicAcquisition("getTranslationList", function (param_list) {
if (this.setLanguage) {
return this.getDeclaredGadget("translate")
.push(function (translation_gadget) {
return translation_gadget.getTranslationList.apply(
translation_gadget,
param_list
);
});
}
return param_list;
})
.allowPublicAcquisition("whoWantToDisplayThis", function (param_list) { .allowPublicAcquisition("whoWantToDisplayThis", function (param_list) {
// Hey, I want to display some URL // Hey, I want to display some URL
......
...@@ -147,11 +147,13 @@ ...@@ -147,11 +147,13 @@
</record> </record>
<record id="3" aka="AAAAAAAAAAM="> <record id="3" aka="AAAAAAAAAAM=">
<pickle> <pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.patches.WorkflowTool"/> <global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle> </pickle>
<pickle> <pickle>
<tuple> <dictionary>
<none/> <item>
<key> <string>_log</string> </key>
<value>
<list> <list>
<dictionary> <dictionary>
<item> <item>
...@@ -195,16 +197,20 @@ ...@@ -195,16 +197,20 @@
</item> </item>
</dictionary> </dictionary>
</list> </list>
</tuple> </value>
</item>
</dictionary>
</pickle> </pickle>
</record> </record>
<record id="4" aka="AAAAAAAAAAQ="> <record id="4" aka="AAAAAAAAAAQ=">
<pickle> <pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.patches.WorkflowTool"/> <global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle> </pickle>
<pickle> <pickle>
<tuple> <dictionary>
<none/> <item>
<key> <string>_log</string> </key>
<value>
<list> <list>
<dictionary> <dictionary>
<item> <item>
...@@ -227,7 +233,7 @@ ...@@ -227,7 +233,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>949.36660.60257.7577</string> </value> <value> <string>981.40707.13352.51541</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -245,7 +251,7 @@ ...@@ -245,7 +251,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1456920319.64</float> <float>1583327151.4</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
...@@ -254,16 +260,20 @@ ...@@ -254,16 +260,20 @@
</item> </item>
</dictionary> </dictionary>
</list> </list>
</tuple> </value>
</item>
</dictionary>
</pickle> </pickle>
</record> </record>
<record id="5" aka="AAAAAAAAAAU="> <record id="5" aka="AAAAAAAAAAU=">
<pickle> <pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.patches.WorkflowTool"/> <global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle> </pickle>
<pickle> <pickle>
<tuple> <dictionary>
<none/> <item>
<key> <string>_log</string> </key>
<value>
<list> <list>
<dictionary> <dictionary>
<item> <item>
...@@ -311,7 +321,9 @@ ...@@ -311,7 +321,9 @@
</item> </item>
</dictionary> </dictionary>
</list> </list>
</tuple> </value>
</item>
</dictionary>
</pickle> </pickle>
</record> </record>
</ZopeData> </ZopeData>
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
<script src="rsvp.js" type="text/javascript"></script> <script src="rsvp.js" type="text/javascript"></script>
<script src="renderjs.js" type="text/javascript"></script> <script src="renderjs.js" type="text/javascript"></script>
<script src="gadget_global.js" type="text/javascript"></script> <script src="gadget_global.js" type="text/javascript"></script>
<script src="domsugar.js" type="text/javascript"></script>
<!-- custom script --> <!-- custom script -->
<script src="gadget_erp5_header.js" type="text/javascript"></script> <script src="gadget_erp5_header.js" type="text/javascript"></script>
......
...@@ -152,11 +152,13 @@ ...@@ -152,11 +152,13 @@
</record> </record>
<record id="3" aka="AAAAAAAAAAM="> <record id="3" aka="AAAAAAAAAAM=">
<pickle> <pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.patches.WorkflowTool"/> <global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle> </pickle>
<pickle> <pickle>
<tuple> <dictionary>
<none/> <item>
<key> <string>_log</string> </key>
<value>
<list> <list>
<dictionary> <dictionary>
<item> <item>
...@@ -200,16 +202,20 @@ ...@@ -200,16 +202,20 @@
</item> </item>
</dictionary> </dictionary>
</list> </list>
</tuple> </value>
</item>
</dictionary>
</pickle> </pickle>
</record> </record>
<record id="4" aka="AAAAAAAAAAQ="> <record id="4" aka="AAAAAAAAAAQ=">
<pickle> <pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.patches.WorkflowTool"/> <global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle> </pickle>
<pickle> <pickle>
<tuple> <dictionary>
<none/> <item>
<key> <string>_log</string> </key>
<value>
<list> <list>
<dictionary> <dictionary>
<item> <item>
...@@ -232,7 +238,7 @@ ...@@ -232,7 +238,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>971.18968.42363.15974</string> </value> <value> <string>982.18030.39356.30993</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -250,7 +256,7 @@ ...@@ -250,7 +256,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1540898036.46</float> <float>1583231026.08</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
...@@ -259,16 +265,20 @@ ...@@ -259,16 +265,20 @@
</item> </item>
</dictionary> </dictionary>
</list> </list>
</tuple> </value>
</item>
</dictionary>
</pickle> </pickle>
</record> </record>
<record id="5" aka="AAAAAAAAAAU="> <record id="5" aka="AAAAAAAAAAU=">
<pickle> <pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.patches.WorkflowTool"/> <global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle> </pickle>
<pickle> <pickle>
<tuple> <dictionary>
<none/> <item>
<key> <string>_log</string> </key>
<value>
<list> <list>
<dictionary> <dictionary>
<item> <item>
...@@ -316,7 +326,9 @@ ...@@ -316,7 +326,9 @@
</item> </item>
</dictionary> </dictionary>
</list> </list>
</tuple> </value>
</item>
</dictionary>
</pickle> </pickle>
</record> </record>
</ZopeData> </ZopeData>
/*jslint nomen: true, indent: 2, maxerr: 3 */ /*jslint nomen: true, indent: 2, maxerr: 3 */
/*global window, rJS, document, RSVP */ /*global window, rJS, document, RSVP, domsugar */
(function (window, rJS, document, RSVP) { (function (window, rJS, document, RSVP, domsugar) {
"use strict"; "use strict";
var possible_left_button_list = [ var possible_left_button_list = [
...@@ -39,36 +39,51 @@ ...@@ -39,36 +39,51 @@
['upload_url', 'Upload', 'upload'], ['upload_url', 'Upload', 'upload'],
['download_url', 'Download', 'download'] ['download_url', 'Download', 'download']
], ],
header_button_template = function (data) { promiseHeaderButton = function (gadget, data) {
// <form><button name='{{name}}' data-i18n="{{title}}" type='submit' class='ui-icon-{{icon}} ui-btn-icon-left {{class}}'>{{title}}</button></form> return gadget.translate(data.title)
var form_element = document.createElement('form'), .push(function (result) {
button_element = document.createElement('button'); return domsugar('form', [
domsugar('button', {
button_element.setAttribute('name', data.name); name: data.name,
button_element.setAttribute('data-i18n', data.title); text: result,
button_element.setAttribute('type', 'submit'); // XXX Compatibility with existing application tests
button_element.setAttribute('class', 'ui-icon-' + data.icon + ' ui-btn-icon-left ' + data.class); 'data-i18n': data.title,
form_element.appendChild(button_element); type: 'submit',
return form_element.outerHTML; 'class': 'ui-icon-' + data.icon + ' ui-btn-icon-left ' +
data.class
})
]);
});
}, },
sub_header_template = function (data) {
promiseSubHeader = function (gadget, data) {
// {{#each sub_header_list}} // {{#each sub_header_list}}
// <li><a href="{{url}}" data-i18n="{{title}}" class="ui-btn-icon-top ui-icon-{{icon}} {{class}}">{{title}}</a></li> // <li><a href="{{url}}" data-i18n="{{title}}" class="ui-btn-icon-top ui-icon-{{icon}} {{class}}">{{title}}</a></li>
// {{/each}} // {{/each}}
var fragment = document.createElement('div'), var i,
li_element, translation_list = [];
a_element,
i; for (i = 0; i < data.sub_header_list.length; i += 1) {
translation_list.push(data.sub_header_list[i].title);
}
return gadget.getTranslationList(translation_list)
.push(function (result_list) {
var dom_list = [];
for (i = 0; i < data.sub_header_list.length; i += 1) { for (i = 0; i < data.sub_header_list.length; i += 1) {
li_element = document.createElement('li'); dom_list.push(domsugar('li', [
a_element = document.createElement('a'); domsugar('a', {
a_element.setAttribute('href', data.sub_header_list[i].url); text: result_list[i],
a_element.setAttribute('data-i18n', data.sub_header_list[i].title); // XXX Compatibility with existing application tests
a_element.setAttribute('class', 'ui-btn-icon-top ui-icon-' + data.sub_header_list[i].icon + ' ' + data.sub_header_list[i].class); 'data-i18n': data.sub_header_list[i].title,
li_element.appendChild(a_element); href: data.sub_header_list[i].url,
fragment.appendChild(li_element); 'class': 'ui-btn-icon-top ui-icon-' +
} data.sub_header_list[i].icon + ' ' +
return fragment.innerHTML; data.sub_header_list[i].class
})
]));
}
return domsugar('ul', dom_list);
});
}; };
rJS(window) rJS(window)
...@@ -81,25 +96,12 @@ ...@@ -81,25 +96,12 @@
title_icon: undefined, title_icon: undefined,
title_url: undefined title_url: undefined
}) })
/////////////////////////////////////////////////////////////////
// ready
/////////////////////////////////////////////////////////////////
// Init local properties
.ready(function ready() {
this.props = {
element_list: [
this.element.querySelector("h1"),
this.element.querySelector(".ui-btn-left > div"),
this.element.querySelector(".ui-btn-right > div"),
this.element.querySelector(".ui-subheader").querySelector("ul")
]
};
})
////////////////////////////////////////////// //////////////////////////////////////////////
// acquired methods // acquired methods
////////////////////////////////////////////// //////////////////////////////////////////////
.declareAcquiredMethod("translateHtml", "translateHtml") .declareAcquiredMethod("translate", "translate")
.declareAcquiredMethod("getTranslationList", "getTranslationList")
.declareAcquiredMethod("triggerSubmit", "triggerSubmit") .declareAcquiredMethod("triggerSubmit", "triggerSubmit")
.declareAcquiredMethod("triggerPanel", "triggerPanel") .declareAcquiredMethod("triggerPanel", "triggerPanel")
.declareAcquiredMethod("triggerMaximize", "triggerMaximize") .declareAcquiredMethod("triggerMaximize", "triggerMaximize")
...@@ -250,9 +252,7 @@ ...@@ -250,9 +252,7 @@
default_title_icon = "", default_title_icon = "",
default_right_icon = "", default_right_icon = "",
title_link, title_link,
title_button, promise_list = [];
promise_list = [],
tmp_element;
// Main title // Main title
if (modification_dict.hasOwnProperty('error') || if (modification_dict.hasOwnProperty('error') ||
modification_dict.hasOwnProperty('loaded') || modification_dict.hasOwnProperty('loaded') ||
...@@ -273,35 +273,50 @@ ...@@ -273,35 +273,50 @@
// Be careful, this is CPU costly // Be careful, this is CPU costly
document.title = gadget.state.title_text; document.title = gadget.state.title_text;
} }
// H1
title_link = { title_link = {
title: gadget.state.title_text, title: gadget.state.title_text,
icon: default_title_icon || gadget.state.title_icon, icon: default_title_icon || gadget.state.title_icon,
url: gadget.state.title_url url: gadget.state.title_url
}; };
if (gadget.state.title_button_name) { if (gadget.state.title_button_name) {
title_button = { promise_list.push(promiseHeaderButton(gadget, {
title: gadget.state.title_text, title: gadget.state.title_text,
icon: default_title_icon || gadget.state.title_button_icon, icon: default_title_icon || gadget.state.title_button_icon,
name: gadget.state.title_button_name name: gadget.state.title_button_name
}; }));
promise_list.push(gadget.translateHtml(header_button_template(title_button)));
} else if (title_link.url === undefined) { } else if (title_link.url === undefined) {
// <span data-i18n="{{title}}" class="ui-btn-icon-left ui-icon-{{icon}}" >{{title}}</span> // <span data-i18n="{{title}}" class="ui-btn-icon-left ui-icon-{{icon}}" >{{title}}</span>
tmp_element = document.createElement('span'); promise_list.push(
tmp_element.setAttribute('data-i18n', title_link.title); gadget.translate(title_link.title)
tmp_element.setAttribute('class', 'ui-btn-icon-left ui-icon-' + title_link.icon); .push(function (result) {
promise_list.push(gadget.translateHtml(tmp_element.outerHTML)); return domsugar('span', {
'class': 'ui-btn-icon-left ui-icon-' + title_link.icon,
text: result,
// XXX Compatibility with existing application tests
'data-i18n': title_link.title
});
})
);
} else { } else {
// <a data-i18n="{{title}}" class="ui-btn-icon-left ui-icon-{{icon}}" href="{{url}}" accesskey="u">{{title}}</a> // <a data-i18n="{{title}}" class="ui-btn-icon-left ui-icon-{{icon}}" href="{{url}}" accesskey="u">{{title}}</a>
tmp_element = document.createElement('a'); promise_list.push(
tmp_element.setAttribute('data-i18n', title_link.title); gadget.translate(title_link.title)
tmp_element.setAttribute('class', 'ui-btn-icon-left ui-icon-' + title_link.icon); .push(function (result) {
tmp_element.setAttribute('href', title_link.url); return domsugar('a', {
tmp_element.setAttribute('accesskey', 'u'); 'class': 'ui-btn-icon-left ui-icon-' + title_link.icon,
promise_list.push(gadget.translateHtml(tmp_element.outerHTML)); 'href': title_link.url,
'accesskey': 'u',
text: result,
// XXX Compatibility with existing application tests
'data-i18n': title_link.title
});
})
);
} }
} else { } else {
promise_list.push(null); promise_list.push(gadget.element.querySelector("h1").firstChild);
} }
// Left button // Left button
...@@ -311,14 +326,14 @@ ...@@ -311,14 +326,14 @@
if (gadget.state.left_button_title === undefined) { if (gadget.state.left_button_title === undefined) {
promise_list.push(""); promise_list.push("");
} else { } else {
promise_list.push(gadget.translateHtml(header_button_template({ promise_list.push(promiseHeaderButton(gadget, {
title: gadget.state.left_button_title, title: gadget.state.left_button_title,
icon: gadget.state.left_button_icon, icon: gadget.state.left_button_icon,
name: gadget.state.left_button_name name: gadget.state.left_button_name
}))); }));
} }
} else { } else {
promise_list.push(null); promise_list.push(gadget.element.querySelector(".ui-btn-left > div"));
} }
// Handle right link // Handle right link
...@@ -354,38 +369,67 @@ ...@@ -354,38 +369,67 @@
} }
if (right_button !== undefined) { if (right_button !== undefined) {
promise_list.push(gadget.translateHtml(header_button_template(right_button))); promise_list.push(promiseHeaderButton(gadget, right_button));
} else if (right_link !== undefined) { } else if (right_link !== undefined) {
// <a data-i18n="{{title}}" href="{{url}}" class="ui-icon-{{icon}} ui-btn-icon-left {{class}}">{{title}}</a> // <a data-i18n="{{title}}" href="{{url}}" class="ui-icon-{{icon}} ui-btn-icon-left {{class}}">{{title}}</a>
tmp_element = document.createElement('a'); promise_list.push(
tmp_element.setAttribute('data-i18n', right_link.title); gadget.translate(right_link.title)
tmp_element.setAttribute('class', 'ui-icon-' + right_link.icon + ' ui-btn-icon-left ' + right_link.class); .push(function (result) {
tmp_element.setAttribute('href', right_link.url); return domsugar('a', {
promise_list.push(gadget.translateHtml(tmp_element.outerHTML)); text: result,
// XXX Compatibility with existing application tests
'data-i18n': right_link.title,
'class': 'ui-icon-' + right_link.icon + ' ui-btn-icon-left ' +
right_link.class,
href: right_link.url
});
})
);
} else { } else {
promise_list.push(""); promise_list.push("");
} }
} else { } else {
promise_list.push(null); promise_list.push(gadget.element.querySelector(".ui-btn-right > div"));
} }
// Handle sub header // Handle sub header
if (modification_dict.hasOwnProperty('sub_header_list')) { if (modification_dict.hasOwnProperty('sub_header_list')) {
promise_list.push(gadget.translateHtml(sub_header_template({ promise_list.push(promiseSubHeader(gadget, {
sub_header_list: gadget.state.sub_header_list sub_header_list: gadget.state.sub_header_list
}))); }));
} else { } else {
promise_list.push(null); promise_list.push(gadget.element.querySelector(".ui-subheader")
.querySelector("ul"));
} }
return new RSVP.Queue(RSVP.all(promise_list)) return new RSVP.Queue(RSVP.all(promise_list))
.push(function (result_list) { .push(function (result_list) {
var j; domsugar(gadget.element, [
for (j = 0; j < result_list.length; j += 1) { domsugar('div', {'data-role': 'header', class: 'ui-header'}, [
if (result_list[j] !== null) {
gadget.props.element_list[j].innerHTML = result_list[j]; // Left button
} domsugar('div', {class: 'ui-btn-left'}, [
} domsugar('div', {class: 'ui-controlgroup-controls'}, [
result_list[1]
])
]),
// H1
domsugar('h1', [result_list[0]]),
// Right button
domsugar('div', {class: 'ui-btn-right'}, [
domsugar('div', {class: 'ui-controlgroup-controls'}, [
result_list[2]
])
]),
// Subheader
domsugar('div', {class: 'ui-subheader'}, [
result_list[3]
])
])
]);
}); });
}) })
...@@ -406,4 +450,4 @@ ...@@ -406,4 +450,4 @@
throw new Error("Unsupported button " + name); throw new Error("Unsupported button " + name);
}); });
}(window, rJS, document, RSVP)); }(window, rJS, document, RSVP, domsugar));
\ No newline at end of file \ No newline at end of file
...@@ -240,7 +240,7 @@ ...@@ -240,7 +240,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>982.16970.11028.17066</string> </value> <value> <string>982.19516.32766.33143</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -258,7 +258,7 @@ ...@@ -258,7 +258,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1583167358.84</float> <float>1583323848.61</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </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