Commit 2dc9f19a authored by Jérome Perrin's avatar Jérome Perrin

Update officejs support request app for strict CSP

This is a first step to stop using "unsafe" web sections.

This updates support request app to not require `script-src: unsafe-eval` and `style-src: unsafe-inline` in the CSP.
Dropping `script-src: unsafe-eval` is made possible by using domsugar instead of handlebars for dynamic content. Dropping `style-src: unsafe-inline` by using CSS files instead of inline `style` attributes in the DOM. One minor regression is that the tooltips from the graph on the front page gadget will cause warning because of `unsafe-inline` and not render the series color.

This application was also modernized a bit, it now uses the HTML viewer gadget to display post contents and supports translation.

See merge request nexedi/erp5!1821
parents 8e3d2599 21828d69
...@@ -1405,6 +1405,12 @@ msgstr "Attacher un document" ...@@ -1405,6 +1405,12 @@ msgstr "Attacher un document"
msgid "Attachment" msgid "Attachment"
msgstr "Pièce jointe" msgstr "Pièce jointe"
msgid "Attachment:"
msgstr "Pièce jointe:"
msgid "Attachment: "
msgstr "Pièce jointe: "
msgid "Attachments" msgid "Attachments"
msgstr "Pièces jointes" msgstr "Pièces jointes"
...@@ -1897,6 +1903,9 @@ msgstr "Le business template a été mis à jour avec succès" ...@@ -1897,6 +1903,9 @@ msgstr "Le business template a été mis à jour avec succès"
msgid "Buyer" msgid "Buyer"
msgstr "Acheteur" msgstr "Acheteur"
msgid "By"
msgstr "Par"
msgid "CAD Library" msgid "CAD Library"
msgstr "Nom du fichier Lectra" msgstr "Nom du fichier Lectra"
...@@ -2722,6 +2731,9 @@ msgstr "Commentaires entrés par un utilisateur. Les commentaires ne seront visi ...@@ -2722,6 +2731,9 @@ msgstr "Commentaires entrés par un utilisateur. Les commentaires ne seront visi
msgid "Comments which can be read by internal users but which, unlike description, are not printed out on official documents." msgid "Comments which can be read by internal users but which, unlike description, are not printed out on official documents."
msgstr "Commentaires accessibles aux utilisateurs internes de l'application qui, contrairement à la description, ne sont pas repris ou imprimés sur les documents officiels." msgstr "Commentaires accessibles aux utilisateurs internes de l'application qui, contrairement à la description, ne sont pas repris ou imprimés sur les documents officiels."
msgid "Comments:"
msgstr "Commentaires:"
msgid "Compare" msgid "Compare"
msgstr "Comparer" msgstr "Comparer"
...@@ -6586,6 +6598,9 @@ msgstr "Dernier" ...@@ -6586,6 +6598,9 @@ msgstr "Dernier"
msgid "Last In, First Out" msgid "Last In, First Out"
msgstr "Dernier entré, premier sorti" msgstr "Dernier entré, premier sorti"
msgid "Last Month Activity"
msgstr "Activité du mois"
msgid "Last Name" msgid "Last Name"
msgstr "Nom" msgstr "Nom"
...@@ -10309,6 +10324,9 @@ msgstr "Hiérarchie d'expression de besoins" ...@@ -10309,6 +10324,9 @@ msgstr "Hiérarchie d'expression de besoins"
msgid "Reset" msgid "Reset"
msgstr "Réinitialiser" msgstr "Réinitialiser"
msgid "Reset Filter"
msgstr "Réinitialiser le filtre"
msgid "Reset List Setting" msgid "Reset List Setting"
msgstr "Réinitialiser la configuration de la liste" msgstr "Réinitialiser la configuration de la liste"
...@@ -11740,6 +11758,9 @@ msgstr "Soumettre au manager (action)" ...@@ -11740,6 +11758,9 @@ msgstr "Soumettre au manager (action)"
msgid "Submit Message" msgid "Submit Message"
msgstr "Soumettre le message" msgstr "Soumettre le message"
msgid "Submit New Support Request"
msgstr "Soumettre une nouvelle demande d'assistance"
msgid "Submit Project" msgid "Submit Project"
msgstr "Soumettre le projet" msgstr "Soumettre le projet"
...@@ -11905,6 +11926,9 @@ msgstr "Rapport détaillé" ...@@ -11905,6 +11926,9 @@ msgstr "Rapport détaillé"
msgid "Support Request Module" msgid "Support Request Module"
msgstr "Module des demandes d'assistance" msgstr "Module des demandes d'assistance"
msgid "Support Request Pipe"
msgstr "Demandes d'assistance en cours"
msgid "Support Request Status" msgid "Support Request Status"
msgstr "État" msgstr "État"
...@@ -11917,6 +11941,9 @@ msgstr "Reference du type de la demande d'assistance" ...@@ -11917,6 +11941,9 @@ msgstr "Reference du type de la demande d'assistance"
msgid "Support Request Types" msgid "Support Request Types"
msgstr "Types des demandes d'assistance" msgstr "Types des demandes d'assistance"
msgid "Support Request WorkLists"
msgstr "Listes de travail des demandes d'assistance"
msgid "Support Requests" msgid "Support Requests"
msgstr "Demandes d'assistance" msgstr "Demandes d'assistance"
......
html {
height: 300px;
}
body {
height: 100%;
margin: 0;
}
.graph-content {
height: 95%;
width: 95%;
}
\ No newline at end of file
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="Web Manifest" module="erp5.portal_type"/> <global name="Web Style" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
...@@ -23,7 +23,6 @@ ...@@ -23,7 +23,6 @@
<key> <string>_Add_portal_content_Permission</string> </key> <key> <string>_Add_portal_content_Permission</string> </key>
<value> <value>
<tuple> <tuple>
<string>Assignee</string>
<string>Assignor</string> <string>Assignor</string>
<string>Manager</string> <string>Manager</string>
</tuple> </tuple>
...@@ -42,8 +41,6 @@ ...@@ -42,8 +41,6 @@
<key> <string>_Modify_portal_content_Permission</string> </key> <key> <string>_Modify_portal_content_Permission</string> </key>
<value> <value>
<tuple> <tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string> <string>Manager</string>
</tuple> </tuple>
</value> </value>
...@@ -61,14 +58,6 @@ ...@@ -61,14 +58,6 @@
</tuple> </tuple>
</value> </value>
</item> </item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>contributor/person_module/1</string>
</tuple>
</value>
</item>
<item> <item>
<key> <string>content_md5</string> </key> <key> <string>content_md5</string> </key>
<value> <value>
...@@ -77,11 +66,13 @@ ...@@ -77,11 +66,13 @@
</item> </item>
<item> <item>
<key> <string>content_type</string> </key> <key> <string>content_type</string> </key>
<value> <string>text/plain</string> </value> <value>
<none/>
</value>
</item> </item>
<item> <item>
<key> <string>default_reference</string> </key> <key> <string>default_reference</string> </key>
<value> <string>gadget_field_graph_echarts.appcache</string> </value> <value> <string>gadget_field_graph_echarts.css</string> </value>
</item> </item>
<item> <item>
<key> <string>description</string> </key> <key> <string>description</string> </key>
...@@ -91,44 +82,21 @@ ...@@ -91,44 +82,21 @@
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
<value> <string>gadget_field_graph_echarts_appcache</string> </value> <value> <string>gadget_field_graph_echarts_css</string> </value>
</item> </item>
<item> <item>
<key> <string>language</string> </key> <key> <string>language</string> </key>
<value> <string>en</string> </value> <value> <string>en</string> </value>
</item> </item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Web Manifest</string> </value>
</item>
<item> <item>
<key> <string>short_title</string> </key> <key> <string>short_title</string> </key>
<value> <value>
<none/> <none/>
</value> </value>
</item> </item>
<item>
<key> <string>text_content</string> </key>
<value> <string>CACHE MANIFEST\n
# v1.1.1\n
CACHE:\n
gadget_field_graph_echarts.html/echarts-all.js\n
gadget_field_graph_echarts.html/gadget_global.js\n
gadget_field_graph_echarts.html/renderjs.js\n
gadget_field_graph_echarts.html/rsvp.js\n
gadget_field_graph_echarts.html/unsafe/gadget_field_graph_echarts.js\n
NETWORK:\n
*</string> </value>
</item>
<item> <item>
<key> <string>title</string> </key> <key> <string>title</string> </key>
<value> <string>Officejs ECharts Cache</string> </value> <value> <string>Field Graph With Echarts CSS</string> </value>
</item>
<item>
<key> <string>url_string</string> </key>
<value>
<none/>
</value>
</item> </item>
<item> <item>
<key> <string>version</string> </key> <key> <string>version</string> </key>
...@@ -190,11 +158,11 @@ NETWORK:\n ...@@ -190,11 +158,11 @@ NETWORK:\n
<dictionary> <dictionary>
<item> <item>
<key> <string>action</string> </key> <key> <string>action</string> </key>
<value> <string>publish_alive</string> </value> <value> <string>publish</string> </value>
</item> </item>
<item> <item>
<key> <string>actor</string> </key> <key> <string>actor</string> </key>
<value> <string>zope</string> </value> <value> <string>ERP5TypeTestCase</string> </value>
</item> </item>
<item> <item>
<key> <string>comment</string> </key> <key> <string>comment</string> </key>
...@@ -218,7 +186,7 @@ NETWORK:\n ...@@ -218,7 +186,7 @@ NETWORK:\n
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1506525352.34</float> <float>1694150959.89</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
...@@ -227,7 +195,7 @@ NETWORK:\n ...@@ -227,7 +195,7 @@ NETWORK:\n
</item> </item>
<item> <item>
<key> <string>validation_state</string> </key> <key> <string>validation_state</string> </key>
<value> <string>published_alive</string> </value> <value> <string>published</string> </value>
</item> </item>
</dictionary> </dictionary>
</list> </list>
...@@ -253,7 +221,7 @@ NETWORK:\n ...@@ -253,7 +221,7 @@ NETWORK:\n
</item> </item>
<item> <item>
<key> <string>actor</string> </key> <key> <string>actor</string> </key>
<value> <string>zope</string> </value> <value> <string>ERP5TypeTestCase</string> </value>
</item> </item>
<item> <item>
<key> <string>comment</string> </key> <key> <string>comment</string> </key>
...@@ -267,7 +235,7 @@ NETWORK:\n ...@@ -267,7 +235,7 @@ NETWORK:\n
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>962.25486.15124.29883</string> </value> <value> <string>1010.64822.48938.57036</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -287,8 +255,8 @@ NETWORK:\n ...@@ -287,8 +255,8 @@ NETWORK:\n
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1538646068.83</float> <float>1694152130.18</float>
<string>GMT+9</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
</object> </object>
...@@ -314,11 +282,13 @@ NETWORK:\n ...@@ -314,11 +282,13 @@ NETWORK:\n
<dictionary> <dictionary>
<item> <item>
<key> <string>action</string> </key> <key> <string>action</string> </key>
<value> <string>detect_converted_file</string> </value> <value>
<none/>
</value>
</item> </item>
<item> <item>
<key> <string>actor</string> </key> <key> <string>actor</string> </key>
<value> <string>zope</string> </value> <value> <string>ERP5TypeTestCase</string> </value>
</item> </item>
<item> <item>
<key> <string>comment</string> </key> <key> <string>comment</string> </key>
...@@ -330,7 +300,7 @@ NETWORK:\n ...@@ -330,7 +300,7 @@ NETWORK:\n
</item> </item>
<item> <item>
<key> <string>external_processing_state</string> </key> <key> <string>external_processing_state</string> </key>
<value> <string>converted</string> </value> <value> <string>empty</string> </value>
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
...@@ -350,7 +320,7 @@ NETWORK:\n ...@@ -350,7 +320,7 @@ NETWORK:\n
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1506524633.84</float> <float>1694150865.83</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
<!DOCTYPE html> <!DOCTYPE html>
<html manifest="gadget_field_graph_echarts.appcache" style="height: 300px"> <html>
<head> <head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" /> <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width" /> <meta name="viewport" content="width=device-width" />
...@@ -9,19 +9,20 @@ ...@@ -9,19 +9,20 @@
<link rel="http://www.renderjs.org/rel/interface" href="gadget_field_graph_interface.html"> <link rel="http://www.renderjs.org/rel/interface" href="gadget_field_graph_interface.html">
<!-- renderjs --> <!-- renderjs -->
<script src="rsvp.js" type="text/javascript"></script> <script src="rsvp.js"></script>
<script src="renderjs.js" type="text/javascript"></script> <script src="renderjs.js"></script>
<!-- libraries needed for graphs --> <!-- libraries needed for graphs -->
<script src="echarts-all.js" type="text/javascript"></script> <script src="echarts-all.js"></script>
<!-- custom script --> <!-- custom script -->
<script src="gadget_global.js" type="text/javascript"></script> <script src="gadget_global.js"></script>
<script src="unsafe/gadget_field_graph_echarts.js" type="text/javascript"></script> <script src="gadget_field_graph_echarts.js"></script>
<link rel="stylesheet" type="text/css" href="gadget_field_graph_echarts.css">
</head> </head>
<body style="height: 100%; margin: 0"> <body>
<div class="graph-content" style="height: 95%; width: 95%" disabled> <div class="graph-content" disabled>
</div> </div>
</body> </body>
</html> </html>
\ No newline at end of file
...@@ -64,9 +64,7 @@ ...@@ -64,9 +64,7 @@
<item> <item>
<key> <string>categories</string> </key> <key> <string>categories</string> </key>
<value> <value>
<tuple> <tuple/>
<string>classification/collaborative/team</string>
</tuple>
</value> </value>
</item> </item>
<item> <item>
...@@ -268,8 +266,8 @@ ...@@ -268,8 +266,8 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1538645729.6</float> <float>1694152073.26</float>
<string>GMT+9</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
</object> </object>
......
...@@ -64,9 +64,7 @@ ...@@ -64,9 +64,7 @@
<item> <item>
<key> <string>categories</string> </key> <key> <string>categories</string> </key>
<value> <value>
<tuple> <tuple/>
<string>contributor/person_module/1</string>
</tuple>
</value> </value>
</item> </item>
<item> <item>
......
...@@ -66,6 +66,9 @@ ...@@ -66,6 +66,9 @@
for (j = 0; j < sp_list.length; j += 1) { for (j = 0; j < sp_list.length; j += 1) {
sp_select.options[j] = new Option(sp_list[j][0], sp_list[j][1]); sp_select.options[j] = new Option(sp_list[j][0], sp_list[j][1]);
} }
if (sp_select.options.length === 2) {
sp_select.selectedIndex = 1;
}
}); });
}) })
.onEvent('change', function (evt) { .onEvent('change', function (evt) {
......
...@@ -264,7 +264,7 @@ ...@@ -264,7 +264,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1607511772.31</float> <float>1607511772.32</float>
<string>GMT+1</string> <string>GMT+1</string>
</tuple> </tuple>
</state> </state>
......
...@@ -26,11 +26,11 @@ ...@@ -26,11 +26,11 @@
line-height: 1.5; line-height: 1.5;
} }
#wrap1 iframe { #wrap1, #wrap2 {
height: 100%; height: 300px;
} }
#wrap2 iframe { #wrap1 iframe, #wrap2 iframe {
height: 100%; height: 100%;
} }
...@@ -40,6 +40,12 @@ ...@@ -40,6 +40,12 @@
width: 120px; width: 120px;
} }
.gadget-content .ui-field-contain > .left,
.gadget-content .ui-field-contain > .right {
height: 50%;
width: 100%;
}
.gadget-content .ui-field-contain .bottom .first-line-buttons { .gadget-content .ui-field-contain .bottom .first-line-buttons {
-webkit-appearance: none; -webkit-appearance: none;
margin-top: 0; margin-top: 0;
......
...@@ -268,7 +268,7 @@ ...@@ -268,7 +268,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1505897718.64</float> <float>1694151687.28</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<!-- <!--
data-i18n=Homepage data-i18n="Count"
data-i18n="Customer Support Dashboard"
data-i18n="Days"
data-i18n="Homepage"
data-i18n="Last Month Activity"
data-i18n="Support Request Pipe"
--> -->
<head> <head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" /> <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
...@@ -26,14 +31,14 @@ ...@@ -26,14 +31,14 @@
</div> </div>
<div class="ui-field-contain"> <div class="ui-field-contain">
<div class="left" style="height:50%; width:100%"> <div class="left">
<div class="ui-icon-spinner ui-btn-icon-notext first-loader graph-spinner"></div> <div class="ui-icon-spinner ui-btn-icon-notext first-loader graph-spinner"></div>
<div id="wrap1" style="height:300px;"></div> <div id="wrap1"></div>
</div> </div>
<div class="right" style="height:50%; width:100%"> <div class="right">
<div class="ui-icon-spinner ui-btn-icon-notext first-loader graph-spinner"></div> <div class="ui-icon-spinner ui-btn-icon-notext first-loader graph-spinner"></div>
<div id="wrap2" style="height:300px;"></div> <div id="wrap2"></div>
</div> </div>
</div> </div>
...@@ -42,7 +47,7 @@ ...@@ -42,7 +47,7 @@
</div> </div>
<div data-gadget-url="gadget_erp5_page_form.html" data-gadget-scope="last"></div> <div data-gadget-url="gadget_erp5_page_form.html" data-gadget-scope="last"></div>
<h1 data-i18n="[value]Support Request WorkLists" class="ui-title ui-override-theme worklist-title">Support Request WorkLists</h1> <h1 data-i18n="Support Request WorkLists" class="ui-title ui-override-theme worklist-title">Support Request WorkLists</h1>
<div data-gadget-url="gadget_supportrequest_page_worklist.html" data-gadget-scope="worklist"></div> <div data-gadget-url="gadget_supportrequest_page_worklist.html" data-gadget-scope="worklist"></div>
</body> </body>
</html> </html>
...@@ -260,7 +260,7 @@ ...@@ -260,7 +260,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1613489292.9</float> <float>1694151614.07</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
/*global document, window, Option, rJS, RSVP, promiseEventListener */ /*global document, window, Option, rJS, RSVP */
/*jslint nomen: true, indent: 2, maxerr: 3 */ /*jslint nomen: true, indent: 2, maxerr: 3 */
(function (window, rJS, RSVP, promiseEventListener, loopEventListener) { (function (window, rJS, RSVP) {
"use strict"; "use strict";
function getActionListByName(action_object, name) { function getActionListByName(action_object, name) {
...@@ -47,7 +47,8 @@ ...@@ -47,7 +47,8 @@
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
.declareAcquiredMethod("jio_getAttachment", "jio_getAttachment") .declareAcquiredMethod("jio_getAttachment", "jio_getAttachment")
.declareAcquiredMethod("getUrlParameter", "getUrlParameter") .declareAcquiredMethod("getUrlParameter", "getUrlParameter")
.declareAcquiredMethod("translateHtml", "translateHtml") .declareAcquiredMethod("translate", "translate")
.declareAcquiredMethod("getTranslationList", "getTranslationList")
.declareAcquiredMethod("redirect", "redirect") .declareAcquiredMethod("redirect", "redirect")
.declareAcquiredMethod("updateHeader", "updateHeader") .declareAcquiredMethod("updateHeader", "updateHeader")
.declareAcquiredMethod("updateConfiguration", "updateConfiguration") .declareAcquiredMethod("updateConfiguration", "updateConfiguration")
...@@ -89,7 +90,8 @@ ...@@ -89,7 +90,8 @@
search_criteria = '( translated_simulation_state_title: "' + seriesName + '" AND delivery.start_date: >= ' + begin_date.toISOString().slice(0, 10) + ' AND delivery.start_date: < ' + end_date.toISOString().slice(0, 10) + ' )'; search_criteria = '( translated_simulation_state_title: "' + seriesName + '" AND delivery.start_date: >= ' + begin_date.toISOString().slice(0, 10) + ' AND delivery.start_date: < ' + end_date.toISOString().slice(0, 10) + ' )';
} else { } else {
// Situation 2: Search Support Request by state with limit of 30 days. // Situation 2: Search Support Request by state with limit of 30 days.
search_criteria = '( translated_simulation_state_title: "' + name + '" AND delivery.start_date: >= ' + days_30.toISOString().slice(0, 10) + ' )'; end_date = days_30;
search_criteria = '( translated_simulation_state_title: "' + name + '" AND delivery.start_date: >= ' + end_date.toISOString().slice(0, 10) + ' )';
} }
return search_criteria; return search_criteria;
}) })
...@@ -133,8 +135,21 @@ ...@@ -133,8 +135,21 @@
}); });
}) })
.push(function () { .push(function () {
return gadget.updateHeader({ return gadget.translate('Customer Support Dashboard')
page_title: 'Customer Support Dashboard' .push(function (translated_text) {
return gadget.updateHeader({
page_title: translated_text
});
});
}).push(function () {
return gadget.getTranslationList([
"Submit New Support Request",
"Reset Filter",
"Support Request WorkLists"
]).push(function (translation_list) {
gadget.element.querySelector('[data-i18n="[value]Submit New Support Request"]').value = translation_list[0];
gadget.element.querySelector('[data-i18n="[value]Reset Filter"]').value = translation_list[1];
gadget.element.querySelector('[data-i18n="Support Request WorkLists"]').innerText = translation_list[2];
}); });
}); });
}) })
...@@ -163,7 +178,10 @@ ...@@ -163,7 +178,10 @@
sandbox: "iframe", sandbox: "iframe",
element: gadget.property_dict.element.querySelector("#wrap2") element: gadget.property_dict.element.querySelector("#wrap2")
} }
) ),
gadget.translate("Support Request Pipe"),
gadget.translate("Days"),
gadget.translate("Count")
]); ]);
}) })
.push(function (result) { .push(function (result) {
...@@ -180,10 +198,12 @@ ...@@ -180,10 +198,12 @@
var sp_data = result_list[0], var sp_data = result_list[0],
graph_gadget_1 = result_list[1], graph_gadget_1 = result_list[1],
graph_gadget_2 = result_list[2], graph_gadget_2 = result_list[2],
translated_message_support_request_pipe = result_list[3],
translated_message_days = result_list[4],
translated_message_count = result_list[5],
count_by_state_and_date_range = sp_data.count_by_state_and_date_range; count_by_state_and_date_range = sp_data.count_by_state_and_date_range;
return RSVP.all([ return RSVP.all([graph_gadget_1.render(
// render first graph {
graph_gadget_1.render({
value: { value: {
data: [ data: [
{ {
...@@ -216,50 +236,56 @@ ...@@ -216,50 +236,56 @@
], ],
layout: { layout: {
axis_dict : { axis_dict : {
'0': {"title": "Days"}, '0': {"title": translated_message_days},
'1': {"title": "Number", "value_type": "number"} '1': {"title": translated_message_count, "value_type": "number"}
}, },
title: "Support Request Pipe" title: translated_message_support_request_pipe
} }
} }
}), }
),
// render second graph sp_data,
graph_gadget_2.render({ graph_gadget_2,
value: gadget.translate("Last Month Activity")
{ ]);
data: [ })
{ .push(function (result_list) {
value_dict: { var sp_data = result_list[1],
0: [ graph_gadget = result_list[2],
sp_data.state_title_by_state_id.validated, translated_message_last_month_activity = result_list[3];
sp_data.state_title_by_state_id.submitted, return graph_gadget.render({
sp_data.state_title_by_state_id.suspended, value:
sp_data.state_title_by_state_id.invalidated {
], data: [
1: [ {
sp_data.count_by_state.validated || 0, value_dict: {
sp_data.count_by_state.submitted || 0, 0: [
sp_data.count_by_state.suspended || 0, sp_data.state_title_by_state_id.validated,
sp_data.count_by_state.invalidated || 0 sp_data.state_title_by_state_id.submitted,
] sp_data.state_title_by_state_id.suspended,
}, sp_data.state_title_by_state_id.invalidated
colors: ['#d48265', '#61a0a8', '#c23531', '#2f4554'], ],
type: "pie", 1: [
title: "Support Request" sp_data.count_by_state.validated || 0,
} sp_data.count_by_state.submitted || 0,
], sp_data.count_by_state.suspended || 0,
layout: { sp_data.count_by_state.invalidated || 0
axis_dict : { ]
0: {"title": "date"},
1: {"title": "value", "value_type": "number"}
}, },
title: "Last Month Activity" colors: ['#d48265', '#61a0a8', '#c23531', '#2f4554'],
type: "pie",
title: "Support Request"
} }
],
layout: {
axis_dict : {
0: {"title": "date"},
1: {"title": "value", "value_type": "number"}
},
title: translated_message_last_month_activity
} }
}) }
});
]);
}); });
}) })
.declareService(function () { .declareService(function () {
...@@ -278,7 +304,7 @@ ...@@ -278,7 +304,7 @@
return new RSVP.Queue() return new RSVP.Queue()
.push(function () { .push(function () {
var restore_filter_input = gadget.element.querySelectorAll("input")[1], var restore_filter_input = gadget.element.querySelectorAll("input")[1],
one = loopEventListener(restore_filter_input, "click", false, function () { one = rJS.loopEventListener(restore_filter_input, "click", false, function () {
restore_filter_input.disabled = true; restore_filter_input.disabled = true;
restore_filter_input.classList.add("ui-disabled"); restore_filter_input.classList.add("ui-disabled");
return gadget.redirect({ return gadget.redirect({
...@@ -311,8 +337,7 @@ ...@@ -311,8 +337,7 @@
view_list = erp5_document._links.view || []; view_list = erp5_document._links.view || [];
gadget.property_dict.option_dict = { gadget.property_dict.option_dict = {
// graph_gadget: Keep ending slash to be consistent with the automatically set "base" tag graph_gadget: "gadget_field_graph_echarts.html",
graph_gadget: "unsafe/gadget_field_graph_echarts.html/",
listbox_gadget: getActionListByName(view_list, "view_last_support_request")[0].href, listbox_gadget: getActionListByName(view_list, "view_last_support_request")[0].href,
listbox_jio_key: "support_request_module", listbox_jio_key: "support_request_module",
field_listbox_begin_from: field_listbox_begin_from field_listbox_begin_from: field_listbox_begin_from
...@@ -344,4 +369,4 @@ ...@@ -344,4 +369,4 @@
}); });
}); });
}(window, rJS, RSVP, promiseEventListener, rJS.loopEventListener)); }(window, rJS, RSVP));
...@@ -248,7 +248,7 @@ ...@@ -248,7 +248,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>989.27549.43950.31078</string> </value> <value> <string>1010.61995.46538.53572</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -268,7 +268,7 @@ ...@@ -268,7 +268,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1613149261.83</float> <float>1694082778.57</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<!--
data-i18n=Worklist
data-i18n=All work caught up!
-->
<head> <head>
<!--
data-i18n="All work caught up!"
-->
<meta http-equiv="Content-type" content="text/html; charset=utf-8" /> <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width" /> <meta name="viewport" content="width=device-width" />
<title>ERP5 Page Worklist</title> <title>ERP5 Page Worklist</title>
<!-- renderjs --> <!-- renderjs -->
<script src="rsvp.js" type="text/javascript"></script> <script src="rsvp.js"></script>
<script src="renderjs.js" type="text/javascript"></script> <script src="renderjs.js"></script>
<script src="handlebars.js" type="text/javascript"></script> <script src="jiodev.js"></script>
<script src="jiodev.js" type="text/javascript"></script>
<!-- custom script --> <!-- custom script -->
<script src="gadget_global.js" type="text/javascript"></script> <script src="domsugar.js"></script>
<script src="gadget_supportrequest_page_worklist.js" type="text/javascript"></script> <script src="gadget_global.js"></script>
<script src="gadget_supportrequest_page_worklist.js"></script>
<!-- XXX must set theme here! -->
<script id="table-template" type="text/x-handlebars-template">
{{#if document_list }}
<ul data-role="listview" data-theme="c" class="document-listview ui-listview-inset ui-corner-all">
{{#each document_list}}
<li class="ui-li-has-count" data-icon="false" ><a class="ui-body-inherit" href="{{link}}">{{title}} <span class="ui-li-count">{{count}}</span></a></li>
{{/each}}
</ul>
{{else}}
<p>All work caught up!</p>
{{/if}}
</script>
</head> </head>
<body> <body>
<section class="document_list"></section> <section class="document_list"></section>
......
...@@ -260,7 +260,7 @@ ...@@ -260,7 +260,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1506514266.01</float> <float>1694060576.91</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
/*global window, rJS, RSVP, Handlebars, Query */ /*global window, rJS, RSVP, Query, domsugar */
/*jslint nomen: true, indent: 2, maxerr: 3 */ /*jslint nomen: true, indent: 2, maxerr: 3 */
(function (window, rJS, RSVP, Handlebars, Query) { (function (window, rJS, RSVP, Query, domsugar) {
"use strict"; "use strict";
///////////////////////////////////////////////////////////////// rJS(window)
// Handlebars
/////////////////////////////////////////////////////////////////
// Precompile the templates while loading the first gadget instance
var gadget_klass = rJS(window),
source = gadget_klass.__template_element
.getElementById("table-template")
.innerHTML,
table_template = Handlebars.compile(source);
gadget_klass
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
// Acquired methods // Acquired methods
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
.declareAcquiredMethod("jio_getAttachment", "jio_getAttachment") .declareAcquiredMethod("jio_getAttachment", "jio_getAttachment")
.declareAcquiredMethod("translateHtml", "translateHtml") .declareAcquiredMethod("translate", "translate")
.declareAcquiredMethod("updateHeader", "updateHeader") .declareAcquiredMethod("updateHeader", "updateHeader")
.declareAcquiredMethod("getSetting", "getSetting") .declareAcquiredMethod("getSetting", "getSetting")
.declareAcquiredMethod("getUrlFor", "getUrlFor") .declareAcquiredMethod("getUrlFor", "getUrlFor")
...@@ -70,17 +60,54 @@ ...@@ -70,17 +60,54 @@
return RSVP.all(promise_list); return RSVP.all(promise_list);
}) })
.push(function (result_list) { .push(function (result_list) {
var line_list = [], i; if (result_list.length) {
for (i = 0; i < result_list.length; i += 1) { return domsugar(
line_list.push({ "ul",
link: result_list[i][0], {
title: result_list[i][1], "data-role": "listview",
count: result_list[i][2] "data-theme": "c",
}); "class": "document-listview ui-listview-inset ui-corner-all"
},
result_list.map(function (r) {
var link = r[0], title = r[1], count = r[2];
return domsugar(
"li",
{
"class": "ui-li-has-count",
"data-icon": "false"
},
[
domsugar(
"a",
{
"class": "ui-body-inherit",
"href": link
},
[
title,
" ",
domsugar(
"span",
{ "class": "ui-li-count" },
[count.toString()]
)
]
)
]
);
})
);
} }
gadget.element.querySelector('.document_list').innerHTML = table_template({ return gadget.translate("All work caught up!")
document_list: line_list .push(function (messageNoWorklist) {
}); return domsugar("p", [messageNoWorklist]);
});
})
.push(function (dom_list) {
domsugar(
gadget.element.querySelector('.document_list'),
[dom_list]
);
}); });
}); });
}(window, rJS, RSVP, Handlebars, Query)); }(window, rJS, RSVP, Query, domsugar));
\ No newline at end of file \ No newline at end of file
...@@ -260,7 +260,7 @@ ...@@ -260,7 +260,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1506505200.17</float> <float>1694062935.94</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
...@@ -3,75 +3,54 @@ ...@@ -3,75 +3,54 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" /> <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width" /> <meta name="viewport" content="width=device-width" />
<title>ERP5 Panel</title> <title>Support Requests Panel</title>
<link rel="http://www.renderjs.org/rel/interface" href="interface_panel.html">
<!--
data-i18n="Home"
data-i18n="Support Requests"
data-i18n="Preferences"
data-i18n="Logout"
data-i18n="Views"
data-i18n="Decisions"
data-i18n="Actions"
data-i18n="Jumps"
-->
<!-- renderjs --> <!-- renderjs -->
<script src="rsvp.js" type="text/javascript"></script> <script src="rsvp.js"></script>
<script src="renderjs.js" type="text/javascript"></script> <script src="renderjs.js"></script>
<script src="handlebars.js" type="text/javascript"></script> <script src="domsugar.js"></script>
<script src="gadget_global.js" type="text/javascript"></script> <script src="jiodev.js"></script>
<script src="gadget_global.js"></script>
<script src="gadget_erp5_global.js"></script>
<script id="panel-template-header" type="text/x-handlebars-template"> <!-- custom script -->
<div data-role="header" class="ui-bar-inherit"> <script src="gadget_supportrequest_panel.js"></script>
<div class="ui-controlgroup ui-controlgroup-horizontal ui-btn-left">
</head>
<body>
<div>
<div data-role="header">
<div class="ui-btn-left">
<div class="ui-controlgroup-controls"> <div class="ui-controlgroup-controls">
<button data-i18n="Close" class="ui-btn ui-btn-icon-notext ui-icon-delete">Close</button> <button data-i18n="Close" class="ui-btn-icon-notext ui-icon-delete">Close</button>
</div> </div>
</div> </div>
<div class="panel_img"> <div class="panel_img">
<img class="ui-title" alt="ERP5" src="gadget_erp5_panel.png"/> <img alt="ERP5" src="gadget_erp5_panel.png"/>
</div> </div>
</div> </div>
</script> <div>
<script id="panel-template-body" type="text/x-handlebars-template"> <form>
<div class="ui-content"> <button type="submit" class="ui-icon-action ui-btn-icon-right ui-screen-hidden">Submit</button>
<form class="dialog_form">
<button type="submit" class="ui-btn ui-btn-b ui-btn-inline
ui-icon-action ui-btn-icon-right ui-screen-hidden">Submit</button>
<div data-gadget-url="gadget_erp5_searchfield.html" <div data-gadget-url="gadget_erp5_searchfield.html"
data-gadget-scope="erp5_searchfield" data-gadget-scope="erp5_searchfield"
data-gadget-sandbox="public"></div> data-gadget-sandbox="public"></div>
</form> </form>
<ul></ul>
<ul data-role="listview" class="ui-listview" data-enhanced="true">
<li class="ui-first-child"><a href="#" class="ui-btn ui-btn-icon-left ui-icon-home" data-i18n="Home">Home</a></li>
<li><a href="{{supportrequest_href}}" class="ui-btn ui-btn-icon-left ui-icon-life-ring" data-i18n="Support Requests">Support Requests</a></li>
<li><a href="{{preference_href}}" class="ui-btn ui-btn-icon-left ui-icon-sliders" data-i18n="Preferences">Preferences</a></li>
<li class="ui-last-child"><a href="{{logout_href}}" class="ui-btn ui-btn-icon-left ui-icon-power-off" data-i18n="Logout" accesskey="o">Logout</a></li>
</ul>
<dl></dl> <dl></dl>
</div> </div>
</script> </div>
<script id="panel-template-body-desktop" type="text/x-handlebars-template">
<dt class="ui-content-title ui-body-c ui-btn ui-btn-icon-left ui-icon-eye" data-i18n="Views">Views</dt>
{{#each view_list}}
<dd data-role="listview" data-theme="c" data-inset="true" class="document-listview">
<a data-i18n="{{title}}" class="ui-body-inherit" href="{{href}}">{{title}}</a>
</dd>
{{/each}}
<dt class="ui-content-title ui-body-c ui-btn ui-btn-icon-left ui-icon-cogs" data-i18n="Decisions">Decisions</dt>
{{#each workflow_list}}
<dd data-role="listview" data-theme="c" data-inset="true" class="document-listview">
<a data-i18n="{{title}}" class="ui-body-inherit" href="{{href}}">{{title}}</a>
</dd>
{{/each}}
<dt class="ui-content-title ui-body-c ui-btn ui-btn-icon-left ui-icon-plane" data-i18n="Jumps">Jumps</dt>
{{#each jump_list}}
<dd data-role="listview" data-theme="c" data-inset="true" class="document-listview">
<a data-i18n="{{title}}" class="ui-body-inherit" href="{{href}}">{{title}}</a>
</dd>
{{/each}}
</script>
<!-- custom script -->
<script src="gadget_supportrequest_panel.js" type="text/javascript"></script>
</head>
<body>
<div class="jqm-navmenu-panel"></div>
</body> </body>
</html> </html>
\ No newline at end of file
...@@ -260,7 +260,7 @@ ...@@ -260,7 +260,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1625463570.56</float> <float>1694148611.08</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
/*jslint nomen: true, indent: 2, maxerr: 3 */ /*jslint nomen: true, indent: 2, maxerr: 3, unparam: true */
/*global window, document, rJS, Handlebars, RSVP, Node */ /*global window, document, rJS, RSVP, Node, asBoolean , ensureArray,
(function (window, document, rJS, Handlebars, RSVP, Node, loopEventListener) { mergeGlobalActionWithRawActionList, domsugar*/
(function (window, document, rJS, RSVP, Node, asBoolean, ensureArray,
mergeGlobalActionWithRawActionList, domsugar) {
"use strict"; "use strict";
///////////////////////////////////////////////////////////////// /**
// temlates * This gadget is same as web_page_module/rjs_gadget_erp5_panel_js with the following differences:
///////////////////////////////////////////////////////////////// * - only Home, Support Requests, Preferences and Logout actions ( no "Modules", "Worklists", "History", ... )
// Precompile templates while loading the first gadget instance * - no [ ] editable checkbox
var gadget_klass = rJS(window), * - object actions does not show "Actions" and "Workflows" is named "Decision"
template_element = gadget_klass.__template_element, * - search only search support requests
panel_template_header = Handlebars.compile(template_element */
.getElementById("panel-template-header")
.innerHTML),
panel_template_body = Handlebars.compile(template_element
.getElementById("panel-template-body")
.innerHTML),
panel_template_body_desktop = Handlebars.compile(template_element
.getElementById("panel-template-body-desktop")
.innerHTML);
gadget_klass function appendDt(fragment, dt_title, dt_icon,
action_list, href_list, index) {
// <dt class="ui-btn-icon-left ui-icon-eye">Views</dt>
// {{#each view_list}}
// <dd class="document-listview">
// <a class="{{class_name}}" href="{{href}}">{{title}}</a>
// </dd>
// {{/each}}
//////////////////////
var element_list = [
domsugar('dt', {
text: dt_title,
'class': 'ui-btn-icon-left ui-icon-' + dt_icon
})
],
i;
for (i = 0; i < action_list.length; i += 1) {
element_list.push(domsugar('dd', {'class': 'document-listview'}, [
domsugar('a', {
href: href_list[index + i],
text: action_list[i].title,
'class': action_list[i].class_name || null
})
]));
}
fragment.appendChild(domsugar(null, element_list));
}
rJS(window)
.setState({ .setState({
visible: false, visible: false
desktop: false
}) })
////////////////////////////////////////////// //////////////////////////////////////////////
// acquired method // acquired method
////////////////////////////////////////////// //////////////////////////////////////////////
.declareAcquiredMethod("jio_getAttachment", "jio_getAttachment") .declareAcquiredMethod("getUrlForList", "getUrlForList")
.declareAcquiredMethod("getUrlFor", "getUrlFor") .declareAcquiredMethod("getTranslationList", "getTranslationList")
.declareAcquiredMethod("translateHtml", "translateHtml") .declareAcquiredMethod("getTranslationDict", "getTranslationDict")
.declareAcquiredMethod("getSetting", "getSetting")
.declareAcquiredMethod("redirect", "redirect") .declareAcquiredMethod("redirect", "redirect")
.declareAcquiredMethod("getUrlParameter", "getUrlParameter")
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
// declared methods // declared methods
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
.declareMethod('toggle', function () { .declareMethod('toggle', function toggle() {
return this.changeState({ return this.changeState({
visible: !this.state.visible visible: !this.state.visible
}); });
}) })
.declareMethod('close', function () { .declareMethod('close', function close() {
return this.changeState({ return this.changeState({
visible: false visible: false
}); });
}) })
.declareMethod('render', function (options) { .declareMethod('render', function render(options) {
var erp5_document = options.erp5_document, var erp5_document = options.erp5_document,
jio_key = options.jio_key,
view = options.view,
jump_view = options.jump_view,
visible = options.visible,
extra_menu_list = options.extra_menu_list,
display_workflow_list,
context = this,
workflow_list, workflow_list,
group_mapping,
view_list, view_list,
// action_list,
// clone_list,
jump_list; jump_list;
if (erp5_document !== undefined) {
workflow_list = erp5_document._links.action_workflow || []; if (visible === undefined) {
view_list = erp5_document._links.action_object_view || []; visible = context.state.visible;
jump_list = erp5_document._links.action_object_jio_jump || []; }
if (workflow_list.constructor !== Array) {
workflow_list = [workflow_list]; if (options.display_workflow_list === undefined) {
} display_workflow_list = true;
if (view_list.constructor !== Array) { } else {
view_list = [view_list]; display_workflow_list = asBoolean(options.display_workflow_list);
} }
if (jump_list.constructor !== Array) {
jump_list = [jump_list]; if ((erp5_document !== undefined) && (jio_key !== undefined)) {
} group_mapping = mergeGlobalActionWithRawActionList(jio_key,
// Prevent as much as possible to modify the DOM panel view, jump_view,
// stateChange prefer to compare strings erp5_document._links, [
workflow_list = JSON.stringify(workflow_list); "action_workflow",
view_list = JSON.stringify(view_list); "action_object_view", [
jump_list = JSON.stringify(jump_list); "action_object_jio_action",
"action_object_jio_button",
"action_object_jio_fast_input"
],
"action_object_clone_action",
"action_object_jio_jump"
], {
"action_object_jio_action": "display_dialog_with_history",
"action_object_clone_action": "display_dialog_with_history"
}, {
"action_object_clone_action": true
});
workflow_list = JSON.stringify(group_mapping.action_workflow);
view_list = JSON.stringify(group_mapping.action_object_view);
// action_list = JSON.stringify(group_mapping.action_object_jio_action);
// clone_list = JSON.stringify(group_mapping.action_object_clone_action);
jump_list = JSON.stringify(group_mapping.action_object_jio_jump);
} }
return this.changeState({
workflow_list: workflow_list,
view_list: view_list,
jump_list: jump_list,
global: true,
editable: options.editable
});
})
.onStateChange(function (modification_dict) { if (extra_menu_list !== undefined) {
var context = this, extra_menu_list = JSON.stringify(extra_menu_list);
}
return context.getUrlParameter('editable')
.push(function (editable) {
return context.changeState({
visible: visible,
display_workflow_list: display_workflow_list,
workflow_list: workflow_list,
view_list: view_list,
// action_list: action_list,
// clone_list: clone_list,
jump_list: jump_list,
global: true,
jio_key: jio_key,
view: view,
jump_view: jump_view,
editable: false, // asBoolean(options.editable) || asBoolean(editable) || false,
extra_menu_list: extra_menu_list
});
});
})
.onStateChange(function onStateChange(modification_dict) {
var i,
gadget = this, gadget = this,
queue = new RSVP.Queue(), workflow_list,
tmp_element; view_list,
jump_list,
dl_fragment,
queue = new RSVP.Queue();
if (modification_dict.hasOwnProperty("visible")) { if (modification_dict.hasOwnProperty("visible")) {
if (this.state.visible) { if (this.state.visible) {
...@@ -101,212 +167,210 @@ ...@@ -101,212 +167,210 @@
if (modification_dict.hasOwnProperty("global")) { if (modification_dict.hasOwnProperty("global")) {
queue queue
.push(function () { .push(function () {
return RSVP.all([ return gadget.getDeclaredGadget('erp5_searchfield');
context.getUrlFor({command: 'display', options: {page: "supportrequest_preference"}}),
context.getUrlFor({command: 'display', options: {page: "logout"}}),
context.getUrlFor({command: 'display_stored_state', options: {jio_key: "support_request_module"}})
]);
})
.push(function (result_list) {
// XXX: Customize panel header!
return context.translateHtml(
panel_template_header() +
panel_template_body({
"preference_href": result_list[0],
"logout_href": result_list[1],
"supportrequest_href": result_list[2]
})
);
})
.push(function (my_translated_or_plain_html) {
tmp_element = document.createElement('div');
tmp_element.innerHTML = my_translated_or_plain_html;
return context.declareGadget('gadget_erp5_searchfield.html', {
scope: "erp5_searchfield",
element: tmp_element.querySelector('[data-gadget-scope="erp5_searchfield"]')
});
}) })
.push(function (search_gadget) { .push(function (search_gadget) {
return search_gadget.render({ return search_gadget.render({
focus: false focus: false,
extended_search: ''
}); });
}) });
}
if (modification_dict.hasOwnProperty("editable")) {
queue
// Update the global links
.push(function () { .push(function () {
context.element.querySelector("div").appendChild(tmp_element); return RSVP.hash({
return context.listenResize(); url_list: gadget.getUrlForList([
{command: 'display'},
{command: 'display', options: {jio_key: "support_request_module"}},
{command: 'display', options: {page: "supportrequest_preference"}},
{command: 'display', options: {page: "logout"}}
]),
translation_list: gadget.getTranslationList([
'Home',
'Support Requests',
'Preferences',
'Logout'
])
});
})
.push(function (result_dict) {
var element_list = [],
icon_and_key_list = [
'home', null,
'life-ring', null,
'sliders', null,
'power-off', 'o'
];
for (i = 0; i < result_dict.url_list.length; i += 1) {
// <li><a href="URL" class="ui-btn-icon-left ui-icon-ICON" data-i18n="TITLE" accesskey="KEY"></a></li>
element_list.push(domsugar('li', [
domsugar('a', {
href: result_dict.url_list[i],
'class': 'ui-btn-icon-left ui-icon-' + icon_and_key_list[2 * i],
accesskey: icon_and_key_list[2 * i],
text: result_dict.translation_list[i]
})
]));
}
domsugar(gadget.element.querySelector("ul"),
[domsugar(null, element_list)]);
}); });
} }
if ((this.state.global === true) && if ((this.state.global === true) &&
(modification_dict.hasOwnProperty("desktop") || (modification_dict.hasOwnProperty("editable") ||
modification_dict.hasOwnProperty("editable") || modification_dict.hasOwnProperty("view") ||
modification_dict.hasOwnProperty("jump_view") ||
modification_dict.hasOwnProperty("workflow_list") || modification_dict.hasOwnProperty("workflow_list") ||
modification_dict.hasOwnProperty("jump_list") ||
modification_dict.hasOwnProperty("jio_key") ||
modification_dict.hasOwnProperty("view_list") || modification_dict.hasOwnProperty("view_list") ||
modification_dict.hasOwnProperty("jump_list"))) { modification_dict.hasOwnProperty("extra_menu_list"))) {
if (!(this.state.desktop && (this.state.view_list !== undefined))) {
dl_fragment = document.createDocumentFragment();
gadget.element.querySelector("dl").textContent = '';
if (this.state.view_list !== undefined) {
queue queue
.push(function () { .push(function () {
gadget.element.querySelector("dl").textContent = ''; var parameter_list = [];
view_list = JSON.parse(gadget.state.view_list);
jump_list = JSON.parse(gadget.state.jump_list);
workflow_list = JSON.parse(gadget.state.workflow_list);
parameter_list = view_list
.concat(workflow_list)
.concat(jump_list)
.map(function (options) {
return options.url_kw;
});
return RSVP.hash({
url_list: gadget.getUrlForList(parameter_list),
translation_dict: gadget.getTranslationDict([
'Views', 'Decisions', 'Jumps'
])
});
})
.push(function (result_dict) {
appendDt(dl_fragment, result_dict.translation_dict.Views, 'eye',
view_list, result_dict.url_list, 0);
if (gadget.state.display_workflow_list) {
// show Workflows only on document
appendDt(dl_fragment, result_dict.translation_dict.Decisions, 'cogs',
workflow_list, result_dict.url_list, view_list.length);
}
appendDt(dl_fragment, result_dict.translation_dict.Jumps, 'plane',
jump_list, result_dict.url_list,
view_list.length + workflow_list.length);
}); });
} else { }
if (gadget.state.hasOwnProperty("extra_menu_list") &&
gadget.state.extra_menu_list) {
queue queue
.push(function () { .push(function () {
var i = 0, return gadget.getTranslationList(['Global']);
promise_list = [],
workflow_list = JSON.parse(gadget.state.workflow_list),
view_list = JSON.parse(gadget.state.view_list),
jump_list = JSON.parse(gadget.state.jump_list);
for (i = 0; i < workflow_list.length; i += 1) {
promise_list.push(
gadget.getUrlFor({
command: 'change',
options: {
view: workflow_list[i].href,
page: undefined
}
})
);
}
for (i = 0; i < view_list.length; i += 1) {
promise_list.push(
gadget.getUrlFor({
command: 'change',
options: {
view: view_list[i].href,
page: undefined
}
})
);
}
for (i = 0; i < jump_list.length; i += 1) {
promise_list.push(
gadget.getUrlFor({
command: 'change',
options: {
view: jump_list[i].href,
page: undefined
}
})
);
}
return RSVP.all(promise_list);
}) })
.push(function (result_list) { .push(function (translation_list) {
var i, var extra_menu_list = JSON.parse(gadget.state.extra_menu_list),
result_workflow_list = [], href_list = [];
result_view_list = [], for (i = 0; i < extra_menu_list.length; i += 1) {
result_jump_list = [], href_list.push(extra_menu_list[i].href);
workflow_list = JSON.parse(gadget.state.workflow_list), extra_menu_list[i] = {
view_list = JSON.parse(gadget.state.view_list), "class_name": extra_menu_list[i].active ? "active" : "",
jump_list = JSON.parse(gadget.state.jump_list); "title": extra_menu_list[i].title
for (i = 0; i < workflow_list.length; i += 1) { };
result_workflow_list.push({
title: workflow_list[i].title,
href: result_list[i]
});
}
for (i = 0; i < view_list.length; i += 1) {
result_view_list.push({
title: view_list[i].title,
href: result_list[i + workflow_list.length]
});
}
for (i = 0; i < jump_list.length; i += 1) {
result_jump_list.push({
title: jump_list[i].title,
href: result_list[i + workflow_list.length + view_list.length]
});
} }
return gadget.translateHtml( appendDt(dl_fragment, translation_list[0], 'globe',
panel_template_body_desktop({ extra_menu_list, href_list, 0);
workflow_list: result_workflow_list,
view_list: result_view_list,
jump_list: result_jump_list
})
).push(function (my_translated_or_plain_html) {
gadget.element.querySelector("dl").innerHTML = my_translated_or_plain_html;
})
}); });
} }
} }
queue
.push(function () {
if (dl_fragment) {
domsugar(gadget.element.querySelector("dl"), [dl_fragment]);
}
});
return queue; return queue;
}) })
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
// declared services // declared services
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
.onEvent('click', function (evt) { .onEvent('click', function click(evt) {
if ((evt.target.nodeType === Node.ELEMENT_NODE) && if ((evt.target.nodeType === Node.ELEMENT_NODE) &&
(evt.target.tagName === 'BUTTON')) { (evt.target.tagName === 'BUTTON')) {
return this.toggle(); return this.toggle();
} }
}, false, false) }, false, false)
.declareJob('listenResize', function () { .allowPublicAcquisition("notifyFocus", function notifyFocus() {
// resize should be only trigger after the render method // All html5 fields in ERP5JS triggers this method when focus
// as displaying the panel rely on external gadget (for translation for example) // is triggered. This is usefull to display error text.
var result, // But, in the case of panel, we don't need to handle anything.
event, return;
context = this; })
function extractSizeAndDispatch() { .allowPublicAcquisition("notifyBlur", function notifyFocus() {
if (window.matchMedia("(min-width: 90em)").matches) { // All html5 fields in ERP5JS triggers this method when blur
return context.changeState({ // is triggered now. This is usefull to display error text.
desktop: true // But, in the case of panel, we don't need to handle anything.
}); return;
}
return context.changeState({
desktop: false
});
}
result = loopEventListener(window, 'resize', false,
extractSizeAndDispatch);
event = document.createEvent("Event");
event.initEvent('resize', true, true);
window.dispatchEvent(event);
return result;
}) })
.allowPublicAcquisition('notifyChange', function () { .allowPublicAcquisition('notifyChange', function notifyChange() {
// Typing a search query should not modify the header status
return;
}, {mutex: 'changestate'})
.allowPublicAcquisition('notifyValid', function notifyValid() {
// Typing a search query should not modify the header status // Typing a search query should not modify the header status
return; return;
}) })
.onEvent('submit', function () {
var gadget = this;
return gadget.getDeclaredGadget("erp5_searchfield") .onEvent('submit', function submit() {
.push(function (search_gadget) { var gadget = this,
search_gadget,
redirect_options = {
page: "search"
};
return gadget
.getDeclaredGadget("erp5_searchfield")
.push(function (declared_gadget) {
search_gadget = declared_gadget;
return search_gadget.getContent(); return search_gadget.getContent();
}) })
.push(function (data) { .push(function (data) {
var options = {
page: "search"
};
if (data.search) { if (data.search) {
options.extended_search = '(' + data.search + ' AND portal_type: "Support Request")'; redirect_options.extended_search = '(' + data.search + ' AND portal_type: "Support Request")';
} else { } else {
options.extended_search = '( portal_type: "Support Request")'; redirect_options.extended_search = '( portal_type: "Support Request")';
} }
// Remove focus from the search field // let the search gadget know its current state (value and focus)
document.activeElement.blur(); // in order to be able to zero it out in the next Promise
return gadget.redirect({command: 'display', options: options}); // input gadget's state does not reflect immediate reality
// so we need to manage its state from the parent
return search_gadget.render({
extended_search: data.search,
focus: true
});
})
.push(function () {
// we want the search field in side panel to be empty and blured
return search_gadget.render({
extended_search: '',
focus: false // we don't want focus on the empty field for sure
});
})
.push(function () {
return gadget.redirect({command: 'store_and_display', options: redirect_options}, true);
}); });
}, false, true) }, /*useCapture=*/false, /*preventDefault=*/true);
.onEvent('click', function (evt) {
if ((evt.target.nodeType === Node.ELEMENT_NODE) &&
(evt.target.tagName === 'BUTTON')) {
return this.toggle();
}
}, false, false)
.onEvent('blur', function (evt) {
// XXX Horrible hack to clear the search when focus is lost
// This does not follow renderJS design, as a gadget should not touch
// another gadget content
if (evt.target.type === 'search') {
evt.target.value = "";
}
}, true, false);
}(window, document, rJS, Handlebars, RSVP, Node, rJS.loopEventListener)); }(window, document, rJS, RSVP, Node, asBoolean, ensureArray,
mergeGlobalActionWithRawActionList, domsugar));
\ No newline at end of file
...@@ -262,7 +262,7 @@ ...@@ -262,7 +262,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1625467130.12</float> <float>1694147830.81</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
...@@ -11,47 +11,9 @@ hr#post_item { ...@@ -11,47 +11,9 @@ hr#post_item {
margin-bottom: 20px; margin-bottom: 20px;
} }
#post_list li ol { .comments-header {
list-style: initial; background-color:#0E81C2;
list-style-type: decimal; color:white;
padding-left: 2em; margin:1em 0;
} padding:0.5em;
#post_list li ul {
list-style: initial;
padding-left: 2em;
}
#post_list li p {
margin-block-start: 1em;
margin-block-end: 1em;
}
#post_list li h1 {
font-size: 2em;
font-weight: bold;
}
#post_list li h2 {
font-size: 1.5em;
font-weight: bold;
}
#post_list li h3 {
font-size: 1.17em;
font-weight: bold;
}
#post_list li h4 {
font-weight: bold;
}
#post_list li h5 {
font-size: 0.83em;
font-weight: bold;
}
#post_list li h6 {
font-size: 0.67em;
font-weight: bold;
} }
...@@ -268,8 +268,8 @@ ...@@ -268,8 +268,8 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1542361236.16</float> <float>1694060317.8</float>
<string>GMT+9</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
</object> </object>
......
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<!--
data-i18n="Posting comment"
data-i18n="Post content can not be empty!"
data-i18n="Comment added"
data-i18n="No comment yet."
data-i18n="By"
data-i18n="Attachment:"
-->
<head> <head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" /> <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width" /> <meta name="viewport" content="width=device-width" />
<title>ERP5 PT Form View</title> <title>ERP5 PT Form View</title>
<!-- renderjs --> <!-- renderjs -->
<script src="rsvp.js" type="text/javascript"></script> <script src="rsvp.js"></script>
<script src="renderjs.js" type="text/javascript"></script> <script src="renderjs.js"></script>
<!-- custom script --> <!-- custom script -->
<script src="handlebars.js" type="text/javascript"></script> <script src="domsugar.js"></script>
<script src="gadget_global.js" type="text/javascript"></script> <script src="gadget_global.js"></script>
<script src="jiodev.js" type="text/javascript"></script> <script src="jiodev.js"></script>
<script src="gadget_erp5_global.js" type="text/javascript"></script> <script src="gadget_erp5_global.js"></script>
<script src="gadget_erp5_pt_form_view_discussable.js" type="text/javascript"></script> <script src="gadget_erp5_pt_form_view_discussable.js"></script>
<link rel="stylesheet" type="text/css" href="gadget_erp5_pt_form_view_discussable.css"> <link rel="stylesheet" type="text/css" href="gadget_erp5_pt_form_view_discussable.css">
<!-- templates -->
<script id="template-document-list" type="text/x-handlebars-template">
{{#if comments }}
{{#each comments }}
<li>By <strong>{{ user }}</strong> -
<time datetime="{{ date }}" title="{{ date_formatted }}">{{ date_relative }}</time>
<br/>
{{{ text }}}
{{#if attachment_link }}
<br/>
<strong>Attachment: </strong>
<a href="{{attachment_link}}">{{ attachment_name }}</a>
{{/if}}
<hr id="post_item">
</li>
{{/each }}
{{else }}
<p><em>No comment yet.</em></p><hr id="post_item">
{{/if }}
</script>
</head> </head>
<body> <body>
...@@ -49,18 +36,21 @@ ...@@ -49,18 +36,21 @@
</div> </div>
<form> <form>
<p style="background-color:#0E81C2;color:white;margin:1em 0;padding:0.5em">Comments:</p> <div>
<ol id="post_list"></ol> <p class="comments-header" data-i18n="Comments:">Comments:</p>
<h3 class="ui-content-title ui-body-c ui-icon ui-icon-custom ui-icon-random" id="comment-title" name="comment-title">&nbsp;Post a comment</h3> <ol id="post_list"></ol>
<h3 class="ui-content-title ui-body-c ui-icon ui-icon-custom ui-icon-random" id="comment-title" name="comment-title" data-i18n="Post Comment">&nbsp;Post a comment</h3>
</div>
<div data-gadget-url="gadget_editor.html" <div data-gadget-url="gadget_editor.html"
data-gadget-scope="editor" data-gadget-scope="editor"
data-gadget-sandbox=""> data-gadget-sandbox="">
</div> </div>
<div id="file_upload_div"> <div id="file_upload_div">
<input value="" name="attachment" id="attachment" type="file" title="Upload"> <input value="" name="attachment" id="attachment" type="file" title="Upload">
</div> </div>
<input data-theme="b" data-inline="true" type="submit" data-i18n="[value]Post Comment" value="Post Comment" data-icon="check" disabled class="ui-disabled"/> <div>
<input data-theme="b" data-inline="true" type="submit" data-i18n="[value]Post Comment" value="Post Comment" data-icon="check" disabled class="ui-disabled"/>
</div>
</form> </form>
</div> </div>
</body> </body>
......
...@@ -240,7 +240,7 @@ ...@@ -240,7 +240,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>974.28140.2414.14967</string> </value> <value> <string>1010.62469.29459.39441</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>1554190620.27</float> <float>1694063872.02</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
/*global window, rJS, RSVP, calculatePageTitle, FormData, URI, jIO, moment, Handlebars */ /*global window, rJS, RSVP, calculatePageTitle, FormData, URI, jIO, moment */
/*jslint nomen: true, indent: 2, maxerr: 3 */ /*jslint nomen: true, indent: 2, maxerr: 3 */
(function (window, rJS, RSVP, calculatePageTitle, moment, Handlebars) { (function (window, rJS, RSVP, calculatePageTitle, moment) {
"use strict"; "use strict";
var gadget_klass = rJS(window),
comment_list_template = Handlebars.compile(
gadget_klass.__template_element.getElementById("template-document-list").innerHTML
);
gadget_klass /**
* french locale for momentjs, copied from https://momentjs.com/docs/
*/
moment.locale('fr', {
months : 'janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre'.split('_'),
monthsShort : 'janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.'.split('_'),
monthsParseExact : true,
weekdays : 'dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi'.split('_'),
weekdaysShort : 'dim._lun._mar._mer._jeu._ven._sam.'.split('_'),
weekdaysMin : 'Di_Lu_Ma_Me_Je_Ve_Sa'.split('_'),
weekdaysParseExact : true,
longDateFormat : {
LT : 'HH:mm',
LTS : 'HH:mm:ss',
L : 'DD/MM/YYYY',
LL : 'D MMMM YYYY',
LLL : 'D MMMM YYYY HH:mm',
LLLL : 'dddd D MMMM YYYY HH:mm'
},
calendar : {
sameDay : '[Aujourd’hui à] LT',
nextDay : '[Demain à] LT',
nextWeek : 'dddd [à] LT',
lastDay : '[Hier à] LT',
lastWeek : 'dddd [dernier à] LT',
sameElse : 'L'
},
relativeTime : {
future : 'dans %s',
past : 'il y a %s',
s : 'quelques secondes',
m : 'une minute',
mm : '%d minutes',
h : 'une heure',
hh : '%d heures',
d : 'un jour',
dd : '%d jours',
M : 'un mois',
MM : '%d mois',
y : 'un an',
yy : '%d ans'
},
dayOfMonthOrdinalParse : /\d{1,2}(er|e)/,
ordinal : function (number) {
return number + (number === 1 ? 'er' : 'e');
},
meridiemParse : /PD|MD/,
isPM : function (input) {
return input.charAt(0) === 'M';
},
// In case the meridiem units are not separated around 12, then implement
// this function (look at locale/id.js for an example).
// meridiemHour : function (hour, meridiem) {
// return /* 0-23 hour, given meridiem token and hour 1-12 */ ;
// },
meridiem : function (hours, minutes, isLower) {
return hours < 12 ? 'PD' : 'MD';
},
week : {
dow : 1, // Monday is the first day of the week.
doy : 4 // Used to determine first week of the year.
}
});
rJS(window)
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
// Acquired methods // Acquired methods
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
.declareAcquiredMethod("updateHeader", "updateHeader") .declareAcquiredMethod("updateHeader", "updateHeader")
.declareAcquiredMethod("translate", "translate")
.declareAcquiredMethod("translateHtml", "translateHtml")
.declareAcquiredMethod("getTranslationList", "getTranslationList")
.declareAcquiredMethod("getSetting", "getSetting") .declareAcquiredMethod("getSetting", "getSetting")
.declareAcquiredMethod("getSettingList", "getSettingList") .declareAcquiredMethod("getSettingList", "getSettingList")
.declareAcquiredMethod("jio_getAttachment", "jio_getAttachment") .declareAcquiredMethod("jio_getAttachment", "jio_getAttachment")
...@@ -125,7 +189,19 @@ ...@@ -125,7 +189,19 @@
maximize: true maximize: true
})]); })]);
} }
).push(function () { )
.push(function() {
return gadget.getTranslationList([
"Comments:",
"Post Comment",
"Post Comment",
]).push(function(translation_list) {
gadget.element.querySelector("[data-i18n='Comments:']").innerText = translation_list[0];
gadget.element.querySelector("[data-i18n='Post Comment']").innerText = "\u00A0" + translation_list[1];
gadget.element.querySelector("[data-i18n='[value]Post Comment']").value = translation_list[2];
});
})
.push(function () {
// make our submit button editable // make our submit button editable
var element = gadget.element.querySelector('input[type="submit"]'); var element = gadget.element.querySelector('input[type="submit"]');
element.removeAttribute('disabled'); element.removeAttribute('disabled');
...@@ -169,35 +245,93 @@ ...@@ -169,35 +245,93 @@
}); });
}) })
.push(function () { .push(function () {
return gadget.jio_getAttachment( return RSVP.all([
'post_module', gadget.jio_getAttachment(
gadget.hateoas_url + gadget.options.jio_key + "/SupportRequest_getCommentPostListAsJson" 'post_module',
); gadget.hateoas_url + gadget.options.jio_key + "/SupportRequest_getCommentPostListAsJson"
),
gadget.getTranslationList(["By", "Attachment:",])
]);
}) })
.push(function (post_list) { .push(
function getPostWithLinkAndLocalDate(post) { function (post_list_and_translation_list) {
post.date_formatted = moment(post.date).format('LLLL'); var post_list = post_list_and_translation_list[0],
post.date_relative = moment(post.date).fromNow(); translationBy = post_list_and_translation_list[1][0],
if (post.attachment_link === null) { translationAttachment = post_list_and_translation_list[1][1];
return post; function getPostWithLinkAndLocalDate(post) {
} post.date_formatted = moment(post.date).format('LLLL');
return gadget.getDocumentUrl(post.attachment_link).push( post.date_relative = moment(post.date).fromNow();
function (attachment_link) { if (post.attachment_link === null) {
post.attachment_link = attachment_link;
return post; return post;
} }
); return gadget.getDocumentUrl(post.attachment_link).push(
} function (attachment_link) {
// build links with attachments and localized dates post.attachment_link = attachment_link;
var queue_list = [], i = 0; return post;
for (i = 0; i < post_list.length; i += 1) { }
queue_list.push(getPostWithLinkAndLocalDate(post_list[i])); );
} }
return RSVP.all(queue_list);
return RSVP.all(post_list.map(getPostWithLinkAndLocalDate))
.then(function(post_list){
function getPostDomList(post) {
var dom_list = [
translationBy + " ", // XXX translations can not have leading space ?
domsugar("strong", [post.user]),
" - ",
domsugar("time", {
datetime: post.date,
title: post.date_formatted
},
[post.date_relative]
),
domsugar("br"),
// the post content is set as an attribute for now, we'll use a
// gadget_html_viewer to render each post
domsugar("div", {
'data-gadget-html-viewer-value': post.text,
})
];
if (post.attachment_link) {
dom_list.push(domsugar("br"))
dom_list.push(domsugar("strong", [translationAttachment]))
dom_list.push(domsugar("a", { href: post.attachment_link }, [post.attachment_name]))
}
return [
domsugar("li", dom_list),
domsugar("hr", { id: "post_item" })
];
}
return post_list.map(getPostDomList)
});
}) })
.push(function (comment_list) { .push(function(dom_list) {
var comments = gadget.element.querySelector("#post_list"); return gadget.getElement()
comments.innerHTML = comment_list_template({comments: comment_list}); .push(function (element) {
var all_dom_list = [], gadget_list = [], element_list, i, element;
// add to DOM all the posts, with data-gadget-html-viewer-value attribute
for (var i = 0; i < dom_list.length; i += 1) {
all_dom_list = all_dom_list.concat(dom_list[i]);
}
domsugar(element.querySelector("#post_list"), all_dom_list);
// make gadget html viewer for each post
element_list = element.querySelector("#post_list").querySelectorAll('[data-gadget-html-viewer-value]');
for (i = 0; i < element_list.length; i += 1) {
gadget_list.push(
gadget.declareGadget("gadget_html_viewer.html", {
element: element_list[i],
scope: "html_viewer",
sandbox: "public"
})
.push(function (g) {
return g.render({ value: g.element.getAttribute("data-gadget-html-viewer-value") });
})
);
}
return RSVP.all(gadget_list);
});
}); });
}) })
.declareJob('submitPostComment', function () { .declareJob('submitPostComment', function () {
...@@ -209,9 +343,12 @@ ...@@ -209,9 +343,12 @@
.push(function (e) { .push(function (e) {
return e.getContent(); return e.getContent();
}) })
.push(function (content) { .push(function (content) {
if (content.comment === '') { if (content.comment === '') {
return gadget.notifySubmitted({message: "Post content can not be empty!"}); return gadget.translate("Post content can not be empty!")
.push(function (translated_message) {
return gadget.notifySubmitted({message: translated_message});
})
} }
submitButton = gadget.element.querySelector("input[type=submit]"); submitButton = gadget.element.querySelector("input[type=submit]");
...@@ -222,7 +359,10 @@ ...@@ -222,7 +359,10 @@
submitButton.disabled = false; submitButton.disabled = false;
submitButton.classList.remove("ui-disabled"); submitButton.classList.remove("ui-disabled");
} }
queue = gadget.notifySubmitted({message: "Posting comment"}) queue = gadget.translate("Posting comment").
push(function (message_posting_comment) {
return gadget.notifySubmitted({message: message_posting_comment})
})
.push(function () { .push(function () {
var choose_file_html_element = gadget.element.querySelector('#attachment'), var choose_file_html_element = gadget.element.querySelector('#attachment'),
file_blob = choose_file_html_element.files[0], file_blob = choose_file_html_element.files[0],
...@@ -250,8 +390,12 @@ ...@@ -250,8 +390,12 @@
}); });
}) })
.push(function () { .push(function () {
return new RSVP.Queue().push(function () { return new RSVP.Queue().push(
gadget.notifySubmitted({message: "Comment added", status: "success"}); function(){
return gadget.translate("Comment added")
}
).push(function (message_comment_added) {
gadget.notifySubmitted({message: message_comment_added, status: "success"});
}).push(function () { }).push(function () {
return gadget.redirect({command: 'reload'}); return gadget.redirect({command: 'reload'});
}); });
...@@ -273,4 +417,4 @@ ...@@ -273,4 +417,4 @@
.onEvent('submit', function () { .onEvent('submit', function () {
return this.submitPostComment(); return this.submitPostComment();
}); });
}(window, rJS, RSVP, calculatePageTitle, moment, Handlebars)); }(window, rJS, RSVP, calculatePageTitle, moment));
...@@ -240,7 +240,7 @@ ...@@ -240,7 +240,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>985.17756.63769.9284</string> </value> <value> <string>1010.63187.6525.24985</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>1625719287.68</float> <float>1694063993.84</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
...@@ -366,7 +366,7 @@ ...@@ -366,7 +366,7 @@
</item> </item>
<item> <item>
<key> <string>configuration_content_security_policy</string> </key> <key> <string>configuration_content_security_policy</string> </key>
<value> <string>default-src \'self\'; img-src \'self\' data:; media-src \'self\' blob:; connect-src \'self\' data:; script-src \'self\' \'unsafe-eval\'; font-src \'self\'; style-src \'self\' \'unsafe-inline\' data:; frame-src \'self\' data:</string> </value> <value> <string>default-src \'self\'; img-src \'self\' data:; media-src \'self\' blob:; connect-src \'self\' data:; script-src \'self\'; font-src \'self\'; style-src \'self\' data:; frame-src \'self\' data:</string> </value>
</item> </item>
<item> <item>
<key> <string>configuration_default_view_action_reference</string> </key> <key> <string>configuration_default_view_action_reference</string> </key>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Web Section" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Add_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Add_portal_folders_Permission</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Copy_or_Move_Permission</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Delete_objects_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>
<string>Owner</string>
</tuple>
</value>
</item>
<item>
<key> <string>__before_publishing_traverse__</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="MultiHook" module="ZPublisher.BeforeTraverse"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state>
<dictionary>
<item>
<key> <string>_defined_in_class</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>_hookname</string> </key>
<value> <string>__before_publishing_traverse__</string> </value>
</item>
<item>
<key> <string>_list</string> </key>
<value>
<list>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</list>
</value>
</item>
<item>
<key> <string>_prior</string> </key>
<value>
<none/>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>__before_traverse__</string> </key>
<value>
<dictionary>
<item>
<key>
<tuple>
<int>99</int>
<string>ERP5 Web Section/unsafe</string>
</tuple>
</key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>_identity_criterion</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
<item>
<key> <string>_local_properties</string> </key>
<value>
<tuple>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>configuration_content_security_policy</string> </value>
</item>
<item>
<key> <string>type</string> </key>
<value> <string>string</string> </value>
</item>
</dictionary>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>configuration_x_frame_options</string> </value>
</item>
<item>
<key> <string>type</string> </key>
<value> <string>string</string> </value>
</item>
</dictionary>
</tuple>
</value>
</item>
<item>
<key> <string>_range_criterion</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
</value>
</item>
<item>
<key> <string>configuration_content_security_policy</string> </key>
<value> <string>default-src \'self\' data: blob: ; script-src \'self\' \'unsafe-eval\'; style-src \'self\' \'unsafe-inline\'</string> </value>
</item>
<item>
<key> <string>configuration_x_frame_options</string> </key>
<value> <string>SAMEORIGIN</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>empty_criterion_valid</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>unsafe</string> </value>
</item>
<item>
<key> <string>int_index</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>membership_criterion_category</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Web Section</string> </value>
</item>
<item>
<key> <string>short_title</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>string_index</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>test_method_id</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Unsafe</string> </value>
</item>
<item>
<key> <string>visible</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAU=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="WebSectionTraversalHook" module="Products.ERP5.Document.WebSection"/>
</pickle>
<pickle>
<dictionary/>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="5" aka="AAAAAAAAAAU=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>category_publication_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAY=</string> </persistent>
</value>
</item>
<item>
<key> <string>edit_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAc=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="6" aka="AAAAAAAAAAY=">
<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>
<none/>
</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>1501748238.58</float>
<string>UTC</string>
</tuple>
</state>
</object>
</value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>embedded</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="7" aka="AAAAAAAAAAc=">
<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>961.50869.49076.30293</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>1504539105.96</float>
<string>UTC</string>
</tuple>
</state>
</object>
</value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -11,10 +11,7 @@ workflow = portal.portal_workflow.ticket_workflow ...@@ -11,10 +11,7 @@ workflow = portal.portal_workflow.ticket_workflow
for state in workflow.getStateValueList(): for state in workflow.getStateValueList():
state_title = state.title_or_id() state_title = state.title_or_id()
if 0: state_title = unicode(translateString(
# We don't translate yet, it needs several other fixes
# see https://lab.nexedi.com/nexedi/erp5/merge_requests/778
state_title = unicode(translateString(
'%s [state in %s]' % (state_title, workflow.getId()), '%s [state in %s]' % (state_title, workflow.getId()),
default=unicode(translateString(state_title)))) default=unicode(translateString(state_title))))
info[state.getReference()] = state_title info[state.getReference()] = state_title
......
url_list = [ url_list = [
'handlebars.js',
'gadget_supportrequest_header.html', 'gadget_supportrequest_header.html',
'gadget_supportrequest_header.js', 'gadget_supportrequest_header.js',
'gadget_erp5_page_homepage.css', 'gadget_erp5_page_homepage.css',
...@@ -14,19 +13,15 @@ url_list = [ ...@@ -14,19 +13,15 @@ url_list = [
'gadget_erp5_pt_form_view_discussable.css', 'gadget_erp5_pt_form_view_discussable.css',
'gadget_erp5_pt_form_view_discussable.html', 'gadget_erp5_pt_form_view_discussable.html',
'gadget_erp5_pt_form_view_discussable.js', 'gadget_erp5_pt_form_view_discussable.js',
'gadget_field_graph_echarts.html',
'gadget_field_graph_echarts.js',
'gadget_supportrequest_page_worklist.html', 'gadget_supportrequest_page_worklist.html',
'gadget_supportrequest_page_worklist.js', 'gadget_supportrequest_page_worklist.js',
'gadget_supportrequest_panel.html', 'gadget_supportrequest_panel.html',
'gadget_supportrequest_panel.js', 'gadget_supportrequest_panel.js',
# Echarts. Should probably be a separated script # Echarts. Could probably be a separated script
'unsafe/gadget_field_graph_echarts.html/', 'gadget_field_graph_echarts.html',
'unsafe/gadget_field_graph_echarts.html/rsvp.js', 'gadget_field_graph_echarts.css',
'unsafe/gadget_field_graph_echarts.html/renderjs.js', 'gadget_field_graph_echarts.js',
'unsafe/gadget_field_graph_echarts.html/echarts-all.js', 'echarts-all.js',
'unsafe/gadget_field_graph_echarts.html/gadget_global.js',
'unsafe/gadget_field_graph_echarts.html/unsafe/gadget_field_graph_echarts.js',
] ]
return url_list return url_list
...@@ -71,7 +71,7 @@ ...@@ -71,7 +71,7 @@
</tr> </tr>
<tr> <tr>
<td>waitForText</td> <td>waitForText</td>
<td>//ol[@id="post_list"]//li/p</td> <td>//ol[@id="post_list"]//li//p</td>
<td>Post test</td> <td>Post test</td>
</tr> </tr>
<tr> <tr>
......
...@@ -90,7 +90,7 @@ ...@@ -90,7 +90,7 @@
</tr> </tr>
<tr> <tr>
<td>waitForText</td> <td>waitForText</td>
<td>//ol[@id="post_list"]//li/p</td> <td>//ol[@id="post_list"]//li//p</td>
<td>Post test</td> <td>Post test</td>
</tr> </tr>
<tr> <tr>
...@@ -207,12 +207,12 @@ ...@@ -207,12 +207,12 @@
</tal:block> </tal:block>
<tr> <tr>
<td>waitForElementPresent</td> <td>waitForElementPresent</td>
<td>//a[@data-i18n="Home"]</td> <td>//a[contains(@class, "ui-icon-home") and text() = "Home"]</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
<td>click</td> <td>click</td>
<td>//a[@data-i18n="Home"]</td> <td>//a[contains(@class, "ui-icon-home") and text() = "Home"]</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
...@@ -324,12 +324,12 @@ ...@@ -324,12 +324,12 @@
</tr> </tr>
<tr> <tr>
<td>waitForElementPresent</td> <td>waitForElementPresent</td>
<td>//div[@data-gadget-scope="panel"]//a[@data-i18n="Documents"]</td> <td>//div[@data-gadget-scope="panel"]//a[text() = "Documents"]</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
<td>click</td> <td>click</td>
<td>//div[@data-gadget-scope="panel"]//a[@data-i18n="Documents"]</td> <td>//div[@data-gadget-scope="panel"]//a[text() = "Documents"]</td>
<td></td> <td></td>
</tr> </tr>
<tal:block tal:define="notification_configuration python: {'class': 'success', <tal:block tal:define="notification_configuration python: {'class': 'success',
......
...@@ -56,12 +56,7 @@ ...@@ -56,12 +56,7 @@
<tr> <tr>
<td>waitForText</td> <td>waitForText</td>
<td>//ol[@id="post_list"]//li[1]/p</td> <td>//ol[@id="post_list"]//li[1]//p</td>
<td>Post test 1</td>
</tr>
<tr>
<td>waitForText</td>
<td>//ol[@id="post_list"]//li[1]/p</td>
<td>Post test 1</td> <td>Post test 1</td>
</tr> </tr>
<tr> <tr>
...@@ -115,12 +110,12 @@ displayed ...@@ -115,12 +110,12 @@ displayed
</tr> </tr>
<tr> <tr>
<td>waitForText</td> <td>waitForText</td>
<td>//ol[@id="post_list"]//li[2]/p</td> <td>//ol[@id="post_list"]//li[2]//p</td>
<td>Post test 2</td> <td>Post test 2</td>
</tr> </tr>
<tr> <tr>
<td>assertText</td> <td>assertText</td>
<td>//ol[@id="post_list"]//li[1]/p</td> <td>//ol[@id="post_list"]//li[1]//p</td>
<td>Post test 1</td> <td>Post test 1</td>
</tr> </tr>
<tr> <tr>
...@@ -171,17 +166,17 @@ post ingested when submitting a new support request. ...@@ -171,17 +166,17 @@ post ingested when submitting a new support request.
</tr> </tr>
<tr> <tr>
<td>waitForText</td> <td>waitForText</td>
<td>//ol[@id="post_list"]//li[3]/p</td> <td>//ol[@id="post_list"]//li[3]//p</td>
<td>Post test 3</td> <td>Post test 3</td>
</tr> </tr>
<tr> <tr>
<td>assertText</td> <td>assertText</td>
<td>//ol[@id="post_list"]//li[1]/p</td> <td>//ol[@id="post_list"]//li[1]//p</td>
<td>Post test 1</td> <td>Post test 1</td>
</tr> </tr>
<tr> <tr>
<td>assertText</td> <td>assertText</td>
<td>//ol[@id="post_list"]//li[2]/p</td> <td>//ol[@id="post_list"]//li[2]//p</td>
<td>Post test 2</td> <td>Post test 2</td>
</tr> </tr>
...@@ -252,7 +247,7 @@ and check that the relative time was updated. ...@@ -252,7 +247,7 @@ and check that the relative time was updated.
</tr> </tr>
<tr> <tr>
<td>waitForText</td> <td>waitForText</td>
<td>//ol[@id="post_list"]//li[3]/p</td> <td>//ol[@id="post_list"]//li[3]//p</td>
<td>Post test 4</td> <td>Post test 4</td>
</tr> </tr>
</tbody></table> </tbody></table>
......
...@@ -56,7 +56,7 @@ ...@@ -56,7 +56,7 @@
<tr> <tr>
<td>waitForText</td> <td>waitForText</td>
<td>//ol[@id="post_list"]//li[1]/p</td> <td>//ol[@id="post_list"]//li[1]//p</td>
<td>First Post Content</td> <td>First Post Content</td>
</tr> </tr>
...@@ -136,18 +136,18 @@ ...@@ -136,18 +136,18 @@
<!-- The second post was submitted only once. --> <!-- The second post was submitted only once. -->
<tr> <tr>
<td>waitForText</td> <td>waitForText</td>
<td>//ol[@id="post_list"]//li[1]/p</td> <td>//ol[@id="post_list"]//li[1]//p</td>
<td>First Post Content</td> <td>First Post Content</td>
</tr> </tr>
<tr> <tr>
<td>waitForText</td> <td>waitForText</td>
<td>//ol[@id="post_list"]//li[2]/p</td> <td>//ol[@id="post_list"]//li[2]//p</td>
<td>Second Post Content</td> <td>Second Post Content</td>
</tr> </tr>
<tr> <tr>
<td>assertElementNotPresent</td> <td>assertElementNotPresent</td>
<td>//ol[@id="post_list"]//li[3]/p</td> <td>//ol[@id="post_list"]//li[3]//p</td>
<td></td> <td></td>
</tr> </tr>
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
</item> </item>
<item> <item>
<key> <string>width</string> </key> <key> <string>width</string> </key>
<value> <int>390</int> </value> <value> <int>488</int> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
...@@ -64,7 +64,7 @@ ...@@ -64,7 +64,7 @@
<tr><td colspan="3"><b>Verify the rendering of the graph matches our reference snapshot</b></td></tr> <tr><td colspan="3"><b>Verify the rendering of the graph matches our reference snapshot</b></td></tr>
<tr><td>verifyImageMatchSnapshot</td> <tr><td>verifyImageMatchSnapshot</td>
<td>//canvas</td> <td>//canvas</td>
<td>20</td></tr> <td>0</td></tr>
<tr><td colspan="3"><b>Clicking on a serie filter the listbox of recent updates</b></td></tr> <tr><td colspan="3"><b>Clicking on a serie filter the listbox of recent updates</b></td></tr>
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
</item> </item>
<item> <item>
<key> <string>width</string> </key> <key> <string>width</string> </key>
<value> <int>404</int> </value> <value> <int>503</int> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
...@@ -81,7 +81,7 @@ ...@@ -81,7 +81,7 @@
<tr><td colspan="3"><b>Verify the rendering of the graph matches our reference snapshot</b></td></tr> <tr><td colspan="3"><b>Verify the rendering of the graph matches our reference snapshot</b></td></tr>
<tr><td>verifyImageMatchSnapshot</td> <tr><td>verifyImageMatchSnapshot</td>
<td>//canvas</td> <td>//canvas</td>
<td>20</td></tr> <td>0</td></tr>
<tr><td colspan="3"><b>Clicking on a serie filter the listbox of recent updates</b></td></tr> <tr><td colspan="3"><b>Clicking on a serie filter the listbox of recent updates</b></td></tr>
......
...@@ -26,17 +26,12 @@ ...@@ -26,17 +26,12 @@
</tr> </tr>
<tr> <tr>
<td>waitForElementPresent</td> <td>waitForElementPresent</td>
<td>//a[@data-i18n="Support Requests"]</td> <td>//a[contains(@class, "ui-icon-life-ring") and text() = "Support Requests"]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//a[@data-i18n="Support Requests"]</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
<td>click</td> <td>click</td>
<td>//a[@data-i18n="Support Requests"]</td> <td>//a[contains(@class, "ui-icon-life-ring") and text() = "Support Requests"]</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
......
...@@ -72,10 +72,10 @@ ...@@ -72,10 +72,10 @@
<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/wait_for_content_loaded" /> <tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/wait_for_content_loaded" />
<tr><td>waitForText</td> <tr><td>waitForText</td>
<td>//ol[@id="post_list"]//li/p</td> <td>//ol[@id="post_list"]//li//p</td>
<td>Post test</td></tr> <td>Post test</td></tr>
<tr><td>assertText</td> <tr><td>assertText</td>
<td>//ol[@id="post_list"]//li/p</td> <td>//ol[@id="post_list"]//li//p</td>
<td>Post test</td></tr> <td>Post test</td></tr>
<tr><td colspan="3"><b>Go back ot front page and check "latest post" columns</b></td></tr> <tr><td colspan="3"><b>Go back ot front page and check "latest post" columns</b></td></tr>
......
...@@ -18,13 +18,13 @@ ...@@ -18,13 +18,13 @@
<tr> <tr>
<td>click</td> <td>click</td>
<td>//a[@data-i18n='Support Requests']</td> <td>//a[contains(@class, "ui-icon-life-ring") and text() = "Support Requests"]</td>
<td></td> <td></td>
</tr> </tr>
<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/wait_for_content_loaded" /> <tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/wait_for_content_loaded" />
<tr> <tr>
<td>assertElementPresent</td> <td>assertElementPresent</td>
<td>//a[@data-i18n='Support Requests']</td> <td>//a[contains(@class, "ui-icon-life-ring") and text() = "Support Requests"]</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
......
...@@ -16,17 +16,12 @@ ...@@ -16,17 +16,12 @@
</tr> </tr>
<tr> <tr>
<td>waitForElementPresent</td> <td>waitForElementPresent</td>
<td>//a[@data-i18n="Support Requests"]</td> <td>//a[contains(@class, "ui-icon-life-ring") and text() = "Support Requests"]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//a[@data-i18n="Support Requests"]</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
<td>click</td> <td>click</td>
<td>//a[@data-i18n="Support Requests"]</td> <td>//a[contains(@class, "ui-icon-life-ring") and text() = "Support Requests"]</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
......
...@@ -21,10 +21,9 @@ ...@@ -21,10 +21,9 @@
<tr> <tr>
<td>assertElementPresent</td> <td>assertElementPresent</td>
<td>//h1[@data-i18n="[value]Support Request WorkLists"]</td> <td>//h1[@data-i18n="Support Request WorkLists"]</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
<td>assertElementPresent</td> <td>assertElementPresent</td>
<td>//section[@class="document_list"]//li[1]</td> <td>//section[@class="document_list"]//li[1]</td>
......
...@@ -54,7 +54,7 @@ ...@@ -54,7 +54,7 @@
</item> </item>
<item> <item>
<key> <string>title</string> </key> <key> <string>title</string> </key>
<value> <unicode></unicode> </value> <value> <unicode>Home Page Listbox Translation</unicode> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
<html> <html>
<head> <head>
<title tal:content="template/title">The title</title> <title tal:content="template/title_and_id"></title>
<meta http-equiv="content-type" content="text/html;charset=utf-8"> <meta http-equiv="content-type" content="text/html;charset=utf-8">
</head> </head>
<body> <body>
<table cellpadding="1" cellspacing="1" border="1"> <table cellpadding="1" cellspacing="1" border="1">
<thead> <thead>
<tr><td rowspan="1" colspan="3">Home Page Listbox Translation</td></tr> <tr><td rowspan="1" colspan="3" tal:content="template/title_and_id"></td></tr>
</thead><tbody> </thead><tbody>
<tal:block metal:use-macro="here/Zuite_SupportRequestUITemplate/macros/init" /> <tal:block metal:use-macro="here/Zuite_SupportRequestUITemplate/macros/init" />
<tal:block metal:use-macro="here/Zuite_SupportRequestUITemplate/macros/cleanup_module" /> <tal:block metal:use-macro="here/Zuite_SupportRequestUITemplate/macros/cleanup_module" />
...@@ -24,11 +24,6 @@ ...@@ -24,11 +24,6 @@
<td>//input[@data-i18n='[value]Submit New Support Request']</td> <td>//input[@data-i18n='[value]Submit New Support Request']</td>
<td></td> <td></td>
</tr> </tr>
<tr>
<td>assertElementPresent</td>
<td>//input[@data-i18n='[value]Submit New Support Request']</td>
<td></td>
</tr>
<tr> <tr>
<td>waitForElementPresent</td> <td>waitForElementPresent</td>
<td>//div[@class="document_table"]//tr/td[1]</td> <td>//div[@class="document_table"]//tr/td[1]</td>
......
<html>
<head>
<title tal:content="template/title">The title</title>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
</head>
<body>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">Home Page Panel Translation</td></tr>
</thead><tbody>
<tal:block metal:use-macro="here/Zuite_SupportRequestUITemplate/macros/init" />
<tr>
<td>open</td>
<td>${base_url}/web_site_module/erp5_officejs_support_request_ui/fr/</td>
<td></td>
</tr>
<!-- hack to display Views&Decisions on panel for small screen-->
<tr>
<td>getEval</td>
<td>window.matchMedia = function () {return {matches:true}}</td>
<td></td>
</tr>
<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/wait_for_app_loaded" />
<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/wait_for_listbox_loaded" />
<tr>
<td>waitForElementPresent</td>
<td>//input[@data-i18n='[value]Submit New Support Request']</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//input[@data-i18n='[value]Submit New Support Request']</td>
<td></td>
</tr>
<tr>
<td>waitForElementPresent</td>
<td>//div[contains(@class, "panel")]//a</td>
<td></td>
</tr>
<tr>
<td>assertText</td>
<td>//div[contains(@class, "panel")]//a[contains(@class, "ui-icon-home")]</td>
<td>Accueil</td>
</tr>
<tr>
<td>assertText</td>
<td>//div[contains(@class, "panel")]//a[contains(@class, "ui-icon-life-ring")]</td>
<td>Demandes d'assistance</td>
</tr>
<tr>
<td>assertText</td>
<td>//div[contains(@class, "panel")]//a[contains(@class, "ui-icon-sliders")]</td>
<td>Préférences</td>
</tr>
<tr>
<td>assertText</td>
<td>//div[contains(@class, "panel")]//a[contains(@class, "ui-icon-power-off")]</td>
<td>Déconnexion</td>
</tr>
<tr>
<td>waitForElementPresent</td>
<td>//div[contains(@class, "panel")]//dt[contains(@class, "ui-icon-eye")]</td>
<td></td>
</tr>
<tr>
<td>assertText</td>
<td>//div[contains(@class, "panel")]//dt[contains(@class, "ui-icon-eye")]</td>
<td>Vues</td>
</tr>
<tr>
<td>assertText</td>
<td>//div[contains(@class, "panel")]//dt[contains(@class, "ui-icon-cogs")]</td>
<td>Décisions</td>
</tr>
</tbody></table>
</body>
</html>
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Image" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>__name__</string> </key>
<value> <string>testHomePageTranslation-reference-snapshot-1.png</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>image/png</string> </value>
</item>
<item>
<key> <string>height</string> </key>
<value> <int>285</int> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>width</string> </key>
<value> <int>503</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Image" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>__name__</string> </key>
<value> <string>testHomePageTranslation-reference-snapshot-2.png</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>image/png</string> </value>
</item>
<item>
<key> <string>height</string> </key>
<value> <int>285</int> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>width</string> </key>
<value> <int>488</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -46,7 +46,7 @@ ...@@ -46,7 +46,7 @@
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
<value> <string>testHomePagePanelTranslation</string> </value> <value> <string>testHomePageTranslation</string> </value>
</item> </item>
<item> <item>
<key> <string>output_encoding</string> </key> <key> <string>output_encoding</string> </key>
...@@ -54,7 +54,7 @@ ...@@ -54,7 +54,7 @@
</item> </item>
<item> <item>
<key> <string>title</string> </key> <key> <string>title</string> </key>
<value> <unicode></unicode> </value> <value> <unicode>Home Page Translation</unicode> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
<html>
<head>
<title tal:content="template/title_and_id"></title>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
</head>
<body>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr>
<td rowspan="1" colspan="3" tal:content="template/title_and_id"></td>
</tr>
</thead>
<tbody>
<tal:block metal:use-macro="here/Zuite_SupportRequestUITemplate/macros/init" />
<tr>
<td>open</td>
<td>${base_url}/web_site_module/erp5_officejs_support_request_ui/fr/</td>
<td></td>
</tr>
<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/wait_for_app_loaded" />
<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/wait_for_listbox_loaded" />
<tr>
<td>waitForElementPresent</td>
<td>//input[@data-i18n='[value]Submit New Support Request']</td>
<td></td>
</tr>
<!-- check graphs match snapshots -->
<tr>
<td>waitForElementPresent</td>
<td>css=#wrap1 iframe</td>
<td></td>
</tr>
<tr>
<td>selectFrame</td>
<td>css=#wrap1 iframe</td>
<td></td>
</tr>
<tr>
<td>waitForElementPresent</td>
<td>//canvas</td>
<td></td>
</tr>
<tr>
<td>waitForElementPresent</td>
<td>//div[@class="graph-content" and not(@disabled)]</td>
<td></td>
</tr>
<tr>
<td>verifyImageMatchSnapshot</td>
<td>//canvas</td>
<td>0</td>
</tr>
<!-- TODO: click and check listbox -->
<tr>
<td>selectFrame</td>
<td>relative=top</td>
<td></td>
</tr>
<tr>
<td>waitForElementPresent</td>
<td>css=#wrap2 iframe</td>
<td></td>
</tr>
<tr>
<td>selectFrame</td>
<td>css=#wrap2 iframe</td>
<td></td>
</tr>
<tr>
<td>waitForElementPresent</td>
<td>//canvas</td>
<td></td>
</tr>
<tr>
<td>waitForElementPresent</td>
<td>//div[@class="graph-content" and not(@disabled)]</td>
<td></td>
</tr>
<tr>
<td>verifyImageMatchSnapshot</td>
<td>//canvas</td>
<td>0</td>
</tr>
<!-- TODO: click and check listbox -->
<tr>
<td>selectFrame</td>
<td>relative=top</td>
<td></td>
</tr>
<!-- worklists -->
<tr>
<td>assertText</td>
<td>//h1[@data-i18n="Support Request WorkLists"]</td>
<td>Listes de travail des demandes d'assistance</td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//div[@data-gadget-scope="worklist"]//ul/li/a[text()="Demandes d'assistance à ouvrir"]/span[text()="1"]</td>
<td></td>
</tr>
</tbody>
</table>
</body>
</html>
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ZopePageTemplate" module="Products.PageTemplates.ZopePageTemplate"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>text/html</string> </value>
</item>
<item>
<key> <string>expand</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>testSubmitSupportRequestTranslation</string> </value>
</item>
<item>
<key> <string>output_encoding</string> </key>
<value> <string>utf-8</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <unicode>Submit Request Request Translation</unicode> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<html>
<head>
<title tal:content="template/title_and_id"></title>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
</head>
<body>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr>
<td rowspan="1" colspan="3" tal:content="template/title_and_id"></td>
</tr>
</thead>
<tbody>
<tal:block metal:use-macro="here/Zuite_SupportRequestUITemplate/macros/init" />
<tal:block metal:use-macro="here/Zuite_SupportRequestUITemplate/macros/cleanup_module" />
<tal:block metal:use-macro="here/Zuite_SupportRequestUITemplate/macros/create_data" />
<tr>
<td>open</td>
<td>${base_url}/web_site_module/erp5_officejs_support_request_ui/fr/</td>
<td></td>
</tr>
<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/wait_for_app_loaded" />
<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/wait_for_listbox_loaded" />
<tr>
<td>waitForElementPresent</td>
<td>//input[@data-i18n='[value]Submit New Support Request']</td>
<td></td>
</tr>
<tr>
<td>assertValue</td>
<td>//input[@data-i18n='[value]Submit New Support Request']</td>
<td>Soumettre une nouvelle demande d'assistance</td>
</tr>
<tr>
<td>click</td>
<td>//a/input[@data-i18n="[value]Submit New Support Request"]</td>
<td></td>
</tr>
<tr>
<td>waitForElementPresent</td>
<td>//input[@class="dialogconfirm"]</td>
<td></td>
</tr>
<tr>
<td>assertValue</td>
<td>//input[@class="dialogconfirm"]</td>
<td>Soumettre une nouvelle demande d'assistance</td>
</tr>
<tr>
<td>assertText</td>
<td>//h3[contains(@class, "ui-content-title")]</td>
<td>Soumettre une nouvelle demande d'assistance</td>
</tr>
<tr>
<td>setFile</td>
<td>field_your_file</td>
<td>portal_skins/erp5_officejs_support_request_test/test_support_request_text.pdf test_support_request_text.pdf
</td>
</tr>
<tr>
<td>type</td>
<td>field_your_title</td>
<td>à l'aide !</td>
</tr>
<tr>
<td>assertSelected</td>
<td>field_your_project</td>
<td>RobotMaking</td>
</tr>
<tr>
<td>waitForElementPresent</td>
<td>//select[@name="field_your_resource"]/option[text()="FeatureRequire"]</td>
<td></td>
</tr>
<tr>
<td>select</td>
<td>field_your_resource</td>
<td>FeatureRequire</td>
</tr>
<tal:block tal:define="text_content string:Le message">
<tal:block metal:use-macro="container/Zuite_CommonTemplateForRenderjsUi/macros/type_ckeditor_text_content" />
</tal:block>
<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/submit_dialog" />
<!-- XXX this is here/Zuite_CommonTemplateForRenderjsUi/macros/wait_for_notification but with a trick to escape the message that already contain a ' which needs to be escaped -->
<tal:block>
<tr>
<td colspan="3"><b>Wait for the notification message</b></td>
</tr>
<tr>
<td>waitForElementPresent</td>
<td>//div[@data-gadget-scope='notification' and @class='visible']//button[@class='success' and
text()="Nouvelle demande d'assistance créée."]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//div[@data-gadget-scope='notification' and @class='visible']//button[@class='success' and
text()="Nouvelle demande d'assistance créée."]</td>
<td></td>
</tr>
<tr>
<td colspan="3">
<p></p>
</td>
</tr>
</tal:block>
<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/wait_for_content_loaded" />
<tr>
<td>waitForText</td>
<td>//ol[@id="post_list"]//li[1]//p</td>
<td>Le message</td>
</tr>
<tr>
<td>assertText</td>
<td>//ol[@id="post_list"]//li[1]</td>
<td>regex:Par .*-.*il y a quelques secondes.*</td>
</tr>
<tr>
<td>assertText</td>
<td>//ol[@id="post_list"]//li[1]/strong[2]</td>
<td>Pièce jointe:</td>
</tr>
<tr>
<td>assertText</td>
<td>//p[@data-i18n="Comments:"]</td>
<td>Commentaires:</td>
</tr>
</tbody>
</table>
</body>
</html>
\ No newline at end of file
...@@ -54,7 +54,7 @@ ...@@ -54,7 +54,7 @@
</item> </item>
<item> <item>
<key> <string>title</string> </key> <key> <string>title</string> </key>
<value> <unicode></unicode> </value> <value> <unicode>Support Request Panel Translation</unicode> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
<html> <html>
<head> <head>
<title tal:content="template/title">Support Request Panel Translation</title> <title tal:content="template/title_and_id"></title>
<meta http-equiv="content-type" content="text/html;charset=utf-8"> <meta http-equiv="content-type" content="text/html;charset=utf-8">
</head> </head>
<body> <body>
<table cellpadding="1" cellspacing="1" border="1"> <table cellpadding="1" cellspacing="1" border="1">
<thead> <thead>
<tr><td rowspan="1" colspan="3">Support Request Panel Translation</td></tr> <tr><td rowspan="1" colspan="3" tal:content="template/title_and_id"></td></tr>
</thead><tbody> </thead><tbody>
<tal:block metal:use-macro="here/Zuite_SupportRequestUITemplate/macros/init" /> <tal:block metal:use-macro="here/Zuite_SupportRequestUITemplate/macros/init" />
<tal:block metal:use-macro="here/Zuite_SupportRequestUITemplate/macros/cleanup_module" /> <tal:block metal:use-macro="here/Zuite_SupportRequestUITemplate/macros/cleanup_module" />
...@@ -54,55 +54,55 @@ ...@@ -54,55 +54,55 @@
<tr> <tr>
<td>assertText</td> <td>assertText</td>
<td>//div[contains(@class, "panel")]//a[contains(@class, "ui-icon-home")]</td> <td>//div[@data-gadget-scope="panel"]//a[contains(@class, "ui-icon-home")]</td>
<td>Accueil</td> <td>Accueil</td>
</tr> </tr>
<tr> <tr>
<td>assertText</td> <td>assertText</td>
<td>//div[contains(@class, "panel")]//a[contains(@class, "ui-icon-life-ring")]</td> <td>//div[@data-gadget-scope="panel"]//a[contains(@class, "ui-icon-life-ring")]</td>
<td>Demandes d'assistance</td> <td>Demandes d'assistance</td>
</tr> </tr>
<tr> <tr>
<td>assertText</td> <td>assertText</td>
<td>//div[contains(@class, "panel")]//a[contains(@class, "ui-icon-sliders")]</td> <td>//div[@data-gadget-scope="panel"]//a[contains(@class, "ui-icon-sliders")]</td>
<td>Préférences</td> <td>Préférences</td>
</tr> </tr>
<tr> <tr>
<td>assertText</td> <td>assertText</td>
<td>//div[contains(@class, "panel")]//a[contains(@class, "ui-icon-power-off")]</td> <td>//div[@data-gadget-scope="panel"]//a[contains(@class, "ui-icon-power-off")]</td>
<td>Déconnexion</td> <td>Déconnexion</td>
</tr> </tr>
<tr> <tr>
<td>waitForElementPresent</td> <td>waitForElementPresent</td>
<td>//div[contains(@class, "panel")]//dt[contains(@class, "ui-icon-eye")]</td> <td>//div[@data-gadget-scope="panel"]//dt[contains(@class, "ui-icon-eye")]</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
<td>assertText</td> <td>assertText</td>
<td>//div[contains(@class, "panel")]//dt[contains(@class, "ui-icon-eye")]</td> <td>//div[@data-gadget-scope="panel"]//dt[contains(@class, "ui-icon-eye")]</td>
<td>Vues</td> <td>Vues</td>
</tr> </tr>
<tr> <tr>
<td>assertText</td> <td>assertText</td>
<td>//div[contains(@class, "panel")]//dl/dd[1]</td> <td>//div[@data-gadget-scope="panel"]//dl/dd[1]</td>
<td>Général</td> <td>Général</td>
</tr> </tr>
<tr> <tr>
<td>assertText</td> <td>assertText</td>
<td>//div[contains(@class, "panel")]//dl/dd[2]</td> <td>//div[@data-gadget-scope="panel"]//dl/dd[2]</td>
<td>Historique</td> <td>Historique</td>
</tr> </tr>
<tr> <tr>
<td>assertText</td> <td>assertText</td>
<td>//div[contains(@class, "panel")]//dt[contains(@class, "ui-icon-cogs")]</td> <td>//div[@data-gadget-scope="panel"]//dt[contains(@class, "ui-icon-cogs")]</td>
<td>Décisions</td> <td>Décisions</td>
</tr> </tr>
<tr> <tr>
<td>assertElementPresent</td> <td>assertElementPresent</td>
<td>//div[contains(@class, "panel")]//dl/dd/a[text() = "Clôturer le ticket"]</td> <td>//div[@data-gadget-scope="panel"]//dl/dd/a[text() = "Clôturer le ticket"]</td>
<td></td> <td></td>
</tr> </tr>
......
...@@ -19,14 +19,6 @@ ...@@ -19,14 +19,6 @@
<script src="jiodev.js" type="text/javascript"></script> <script src="jiodev.js" type="text/javascript"></script>
<script src="domsugar.js" type="text/javascript"></script> <script src="domsugar.js" type="text/javascript"></script>
<script id="dialog-button-template" type="text/x-handlebars-template">
{{#if show_update_button}}
<button disabled name="action_update" type="button" data-i18n="Update">Update</button>
{{/if}}
<input disabled name="action_confirm" class="dialogconfirm" type="submit" data-i18n="[value]Proceed" value="Proceed" />
<a class="dialogcancel" data-i18n="Cancel">Cancel</a>
</script>
<!-- custom script --> <!-- custom script -->
<script src="gadget_global.js" type="text/javascript"></script> <script src="gadget_global.js" type="text/javascript"></script>
<script src="gadget_erp5_global.js" type="text/javascript"></script> <script src="gadget_erp5_global.js" type="text/javascript"></script>
......
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