Commit 13ec0948 authored by Boxiang Sun's avatar Boxiang Sun Committed by Eteri

erp5_officejs_support_request_ui: Switch the backend chart library from Chartjs to ECharts.

ECharts has better visual effect than Chartjs.
And also update the tests.
parent ccca3a23
#generate-rss { #generate-rss {
padding: 8pt; padding: 8pt;
margin-top: 30pt; margin-top: 30pt;
margin-right: 12pt; margin-right: 12pt;
...@@ -9,4 +9,12 @@ ...@@ -9,4 +9,12 @@
border-style: solid; border-style: solid;
min-width: 8em; min-width: 8em;
line-height: 1.5; line-height: 1.5;
}
#wrap1 iframe {
height: 100%;
}
#wrap2 iframe {
height: 100%;
} }
\ No newline at end of file
...@@ -242,7 +242,7 @@ ...@@ -242,7 +242,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>961.39587.62437.8823</string> </value> <value> <string>961.52407.42575.23859</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>1503561791.86</float> <float>1504527393.27</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
...@@ -12,9 +12,6 @@ ...@@ -12,9 +12,6 @@
<script src="rsvp.js" type="text/javascript"></script> <script src="rsvp.js" type="text/javascript"></script>
<script src="renderjs.js" type="text/javascript"></script> <script src="renderjs.js" type="text/javascript"></script>
<!-- libraries needed for graphs -->
<script src="chart.js" type="text/javascript"></script>
<!-- custom script --> <!-- custom script -->
<script src="gadget_erp5_page_homepage.js" type="text/javascript"></script> <script src="gadget_erp5_page_homepage.js" type="text/javascript"></script>
<link rel="stylesheet" type="text/css" href="gadget_erp5_page_homepage.css"> <link rel="stylesheet" type="text/css" href="gadget_erp5_page_homepage.css">
...@@ -24,31 +21,26 @@ ...@@ -24,31 +21,26 @@
<h1 style="font-size:2em;font-weight:bold;text-align:center">Customer Support Dashboard</h1> <h1 style="font-size:2em;font-weight:bold;text-align:center">Customer Support Dashboard</h1>
<form> <form>
<div style="text-align:center;"> <div style="text-align:center;">
<input data-theme="b" data-inline="true" type="submit" data-i18n="[value]Submit New Support Request" value="Submit New Support Request" data-icon="check" name="create"/> <input data-theme="b" data-inline="true" type="submit" data-i18n="[value]Submit New Support Request" value="Submit New Support Request" data-icon="check" />
</div> </div>
<div class='ui-field-contain'> <div class='ui-field-contain'>
<div class='left'> <div class='left' style="height:50%; width:100%">
<div style="width: 100% height: 200%"> <div class="ui-icon-spinner ui-btn-icon-notext first-loader graph-spinner"></div>
<canvas id="bar-chart-grouped" responsive="true"></canvas> <div id="wrap1" style="height:300px;"></div>
</div>
</div> </div>
<div class='right'> <div class='right' style="height:50%; width:100%">
<div style="width: 50%"> <div class="ui-icon-spinner ui-btn-icon-notext first-loader graph-spinner"></div>
<canvas id="pie-chart" responsive="true"></canvas> <div id="wrap2" style="height:300px;"></div>
</div>
</div> </div>
</div> </div>
<div class='bottom'>
<a id="generate-rss">
Generate RSS
</a>
</div>
<div class='bottom'>
<a id="generate-rss">Generate RSS</a>
</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>
</form> </form>
</body> </body>
</html> </html>
\ No newline at end of file
...@@ -234,7 +234,7 @@ ...@@ -234,7 +234,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>961.39558.32635.51763</string> </value> <value> <string>961.56620.20048.26265</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -252,7 +252,7 @@ ...@@ -252,7 +252,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1503561223.16</float> <float>1504526707.1</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
/*global document, window, Option, rJS, RSVP, Chart, loopEventListener*/ /*global document, window, Option, rJS, RSVP, loopEventListener*/
/*jslint nomen: true, indent: 2, maxerr: 3 */ /*jslint nomen: true, indent: 2, maxerr: 3 */
(function (window, rJS, RSVP, loopEventListener) { (function (window, rJS, RSVP, loopEventListener) {
"use strict"; "use strict";
...@@ -26,44 +26,19 @@ ...@@ -26,44 +26,19 @@
.allowPublicAcquisition("updateHeader", function () { .allowPublicAcquisition("updateHeader", function () {
return; return;
}) })
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
// declared methods // declared methods
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
.declareMethod("render", function () { .declareMethod("render", function (options) {
var gadget = this; var gadget = this;
return new RSVP.Queue()
.push(function () {
return RSVP.all([
gadget.jio_getAttachment("support_request_module", "links"),
gadget.getDeclaredGadget("last")
]);
})
.push(function (result_list) {
var i,
erp5_document = result_list[0],
view_list = erp5_document._links.action_object_view || [],
last_href;
if (view_list.constructor !== Array) {
view_list = [view_list];
}
for (i = 0; i < view_list.length; i += 1) { return gadget.changeState({
if (view_list[i].name === 'view_last_support_request') { render: true
last_href = view_list[i].href; })
} .push(function () {
} return gadget.changeState({
if (last_href === undefined) { field_listbox_begin_from: options.field_listbox_begin_from
throw new Error('Cant find the list document view'); });
}
return RSVP.all([
result_list[1].render({
jio_key: "support_request_module",
view: last_href
})
]);
}) })
.push(function () { .push(function () {
return gadget.updateHeader({ return gadget.updateHeader({
...@@ -71,91 +46,196 @@ ...@@ -71,91 +46,196 @@
}); });
}); });
}) })
.declareService(function () { .declareJob("renderGraph", function () {
var gadget = this; var gadget = this,
option_dict = gadget.property_dict.option_dict;
return gadget.getSetting("hateoas_url") return gadget.getSetting("hateoas_url")
.push(function (hateoas_url) { .push(function (hateoas_url) {
return gadget.jio_getAttachment( return RSVP.all([gadget.jio_getAttachment(
'support_request_module', 'support_request_module',
hateoas_url + 'support_request_module' hateoas_url + 'support_request_module'
+ "/SupportRequest_getSupportRequestStatisticsAsJson" + "/SupportRequest_getSupportRequestStatisticsAsJson"
); ),
gadget.declareGadget(
option_dict.graph_gadget,
{
scope: "graph",
sandbox: "iframe",
element: gadget.property_dict.element.querySelector("#wrap1")
}
),
gadget.declareGadget(
option_dict.graph_gadget,
{
scope: "graph",
sandbox: "iframe",
element: gadget.property_dict.element.querySelector("#wrap2")
}
)
]);
}) })
.push(function (result) { .push(function (result_list) {
new Chart(document.getElementById("bar-chart-grouped"), { var sp_data = result_list[0], graph_gadget_1 = result_list[1], graph_gadget_2 = result_list[2];
type: 'bar', gadget.property_dict.graph_widget = graph_gadget_1;
data: { return RSVP.all([graph_gadget_1.render(
labels: ["Less than 2 days", "2-7 days", "7-30 days", "More than 30 days"], {
datasets: [ value: {
{ data: [
label: "Opened", {
backgroundColor: "#3e95cd", value_dict: {
data: [ 0: ["Less than 2 days", "2-7 days", "7-30 days", "More than 30 days"],
result.le2.validated, 1: [
result['2to7'].validated, sp_data.le2.validated,
result['7to30'].validated, sp_data['2to7'].validated,
result.gt30.validated sp_data['7to30'].validated,
] sp_data.gt30.validated
}, ]
{ },
label: "Submitted", colors: ['#d48265'],
backgroundColor: "#e8c3b9", type: "bar",
data: [ title: "Opened"
result.le2.submitted, },
result['2to7'].submitted, {
result['7to30'].submitted, value_dict: {
result.gt30.submitted 0: ["Less than 2 days", "2-7 days", "7-30 days", "More than 30 days"],
] 1: [
}, sp_data.le2.submitted,
{ sp_data['2to7'].submitted,
label: "Suspended", sp_data['7to30'].submitted,
backgroundColor: "#3cba9f", sp_data.gt30.submitted
data: [ ]
result.le2.suspended, },
result['2to7'].suspended, colors: ['#61a0a8'],
result['7to30'].suspended, type: "bar",
result.gt30.suspended title: "Submitted"
] },
}, {
{ value_dict: {
label: "Closed", 0: ["Less than 2 days", "2-7 days", "7-30 days", "More than 30 days"],
backgroundColor: "#8e5ea2", 1: [
data: [ sp_data.le2.suspended,
result.le2.invalidated, sp_data['2to7'].suspended,
result['2to7'].invalidated, sp_data['7to30'].suspended,
result['7to30'].invalidated, sp_data.gt30.suspended
result.gt30.invalidated ]
] },
colors: ['#c23531'],
type: "bar",
title: "Suspended"
},
{
value_dict: {
0: ["Less than 2 days", "2-7 days", "7-30 days", "More than 30 days"],
1: [
sp_data.le2.invalidated,
sp_data['2to7'].invalidated,
sp_data['7to30'].invalidated,
sp_data.gt30.invalidated
]
},
colors: ['#2f4554'],
type: "bar",
title: "Closed"
}
],
layout: {
axis_dict : {
'0': {"title": "Days"},
'1': {"title": "Number", "value_type": "number"}
},
title: "Support Request state since last 30 days"
} }
]
},
options: {
responsive : true,
title: {
display: true,
text: 'Support Requests activities'
} }
} }
),
sp_data,
graph_gadget_2
]);
})
.push(function (result_list) {
var sp_data = result_list[1], graph_gadget = result_list[2];
gadget.property_dict.graph_widget = graph_gadget;
return graph_gadget.render({
value:
{
data: [
{
value_dict: {
0: ["Opened", "Submitted", "Suspended", "Closed"],
1: [sp_data.validated, sp_data.submitted, sp_data.suspended, sp_data.invalidated]
},
colors: ['#d48265', '#61a0a8', '#c23531', '#2f4554'],
type: "pie",
title: "Support Request"
}
],
layout: {
axis_dict : {
0: {"title": "date"},
1: {"title": "value", "value_type": "number"}
},
title: "Support Request activites"
}
}
}); });
new Chart(document.getElementById("pie-chart"), { });
type: 'pie', })
data: { .onStateChange(function (modification_dict) {
labels: ["Opened", "Closed", "Suspended", "Submitted"], var gadget = this,
datasets: [{ queue = new RSVP.Queue();
label: "All Support Requests Status", if (modification_dict.hasOwnProperty("field_listbox_begin_from")) {
backgroundColor: ["#3e95cd", "#8e5ea2", "#3cba9f", "#e8c3b9"], // render the erp5 form
data: [result.validated, result.invalidated, result.suspended, result.submitted] queue
}] .push(function () {
}, return gadget.getDeclaredGadget("last");
options: { })
responsive : true, .push(function (result_list) {
title: { var erp5_form = result_list,
display: true, tmp;
text: 'Support Requests state since last 30 days'
tmp = JSON.parse(erp5_form.state.erp5_form);
tmp.field_listbox_begin_from = modification_dict.field_listbox_begin_from;
return erp5_form.changeState({erp5_form: JSON.stringify(tmp)});
});
}
if (modification_dict.hasOwnProperty("render")) {
queue
.push(function () {
return RSVP.all([
gadget.jio_getAttachment("support_request_module", "links"),
gadget.getDeclaredGadget("last")
]);
})
.push(function (result_list) {
var i,
erp5_document = result_list[0],
view_list = erp5_document._links.action_object_view || [],
last_href;
if (view_list.constructor !== Array) {
view_list = [view_list];
}
for (i = 0; i < view_list.length; i += 1) {
if (view_list[i].name === 'view_last_support_request') {
last_href = view_list[i].href;
} }
} }
if (last_href === undefined) {
throw new Error('Cant find the list document view');
}
gadget.property_dict.option_dict = {graph_gadget: "unsafe/gadget_field_graph_echarts.html"};
return RSVP.all([
result_list[1].render({
jio_key: "support_request_module",
view: last_href
}),
gadget.renderGraph() //Launched as service, not blocking
]);
}); });
}); }
return queue;
}) })
.declareService(function () { .declareService(function () {
var gadget = this; var gadget = this;
......
...@@ -236,7 +236,7 @@ ...@@ -236,7 +236,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>961.50969.9466.33160</string> </value> <value> <string>961.56651.42335.12800</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -254,7 +254,7 @@ ...@@ -254,7 +254,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1504187369.74</float> <float>1504528133.07</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
<?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="MultiHook" module="ZPublisher.BeforeTraverse"/>
</klass>
<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>0</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>unsafe</string> </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>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.patches.WorkflowTool"/>
</pickle>
<pickle>
<tuple>
<none/>
<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="DateTime" module="DateTime.DateTime"/>
</klass>
<tuple>
<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>
</tuple>
</pickle>
</record>
<record id="7" aka="AAAAAAAAAAc=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.patches.WorkflowTool"/>
</pickle>
<pickle>
<tuple>
<none/>
<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>
<persistent> <string encoding="base64">AAAAAAAAAAg=</string> </persistent>
</value>
</item>
<item>
<key> <string>error_message</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>0.0.0.0</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="DateTime" module="DateTime.DateTime"/>
</klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>1501748238.6</float>
<string>UTC</string>
</tuple>
</state>
</object>
</value>
</item>
</dictionary>
</list>
</tuple>
</pickle>
</record>
<record id="8" aka="AAAAAAAAAAg=">
<pickle>
<global name="Message" module="Products.ERP5Type.Message"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default</string> </key>
<value> <string>Object copied from ${source_item}</string> </value>
</item>
<item>
<key> <string>domain</string> </key>
<value> <string>erp5_ui</string> </value>
</item>
<item>
<key> <string>mapping</string> </key>
<value>
<dictionary>
<item>
<key> <string>source_item</string> </key>
<value> <string>/erp5/web_site_module/renderjs_runner/unsafe</string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>message</string> </key>
<value> <string>Object copied from ${source_item}</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -21,12 +21,17 @@ ...@@ -21,12 +21,17 @@
</tr> </tr>
<tr> <tr>
<td>waitForElementPresent</td> <td>waitForElementPresent</td>
<td>//canvas[@id='bar-chart-grouped']</td> <td>//a[@id='generate-rss']</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
<td>waitForElementPresent</td> <td>waitForElementPresent</td>
<td>//canvas[@id='pie-chart']</td> <td>//div[@id='wrap1']</td>
<td></td>
</tr>
<tr>
<td>waitForElementPresent</td>
<td>//div[@id='wrap2']</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment