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;
margin-top: 30pt;
margin-right: 12pt;
......@@ -9,4 +9,12 @@
border-style: solid;
min-width: 8em;
line-height: 1.5;
}
#wrap1 iframe {
height: 100%;
}
#wrap2 iframe {
height: 100%;
}
\ No newline at end of file
......@@ -242,7 +242,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>961.39587.62437.8823</string> </value>
<value> <string>961.52407.42575.23859</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -260,7 +260,7 @@
</tuple>
<state>
<tuple>
<float>1503561791.86</float>
<float>1504527393.27</float>
<string>UTC</string>
</tuple>
</state>
......
......@@ -12,9 +12,6 @@
<script src="rsvp.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 -->
<script src="gadget_erp5_page_homepage.js" type="text/javascript"></script>
<link rel="stylesheet" type="text/css" href="gadget_erp5_page_homepage.css">
......@@ -24,31 +21,26 @@
<h1 style="font-size:2em;font-weight:bold;text-align:center">Customer Support Dashboard</h1>
<form>
<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 class='ui-field-contain'>
<div class='left'>
<div style="width: 100% height: 200%">
<canvas id="bar-chart-grouped" responsive="true"></canvas>
</div>
<div class='left' style="height:50%; width:100%">
<div class="ui-icon-spinner ui-btn-icon-notext first-loader graph-spinner"></div>
<div id="wrap1" style="height:300px;"></div>
</div>
<div class='right'>
<div style="width: 50%">
<canvas id="pie-chart" responsive="true"></canvas>
</div>
<div class='right' style="height:50%; width:100%">
<div class="ui-icon-spinner ui-btn-icon-notext first-loader graph-spinner"></div>
<div id="wrap2" style="height:300px;"></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>
</form>
</body>
</html>
\ No newline at end of file
......@@ -234,7 +234,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>961.39558.32635.51763</string> </value>
<value> <string>961.56620.20048.26265</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -252,7 +252,7 @@
</tuple>
<state>
<tuple>
<float>1503561223.16</float>
<float>1504526707.1</float>
<string>UTC</string>
</tuple>
</state>
......
/*global document, window, Option, rJS, RSVP, Chart, loopEventListener*/
/*global document, window, Option, rJS, RSVP, loopEventListener*/
/*jslint nomen: true, indent: 2, maxerr: 3 */
(function (window, rJS, RSVP, loopEventListener) {
"use strict";
......@@ -26,44 +26,19 @@
.allowPublicAcquisition("updateHeader", function () {
return;
})
/////////////////////////////////////////////////////////////////
// declared methods
/////////////////////////////////////////////////////////////////
.declareMethod("render", function () {
.declareMethod("render", function (options) {
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) {
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');
}
return RSVP.all([
result_list[1].render({
jio_key: "support_request_module",
view: last_href
})
]);
return gadget.changeState({
render: true
})
.push(function () {
return gadget.changeState({
field_listbox_begin_from: options.field_listbox_begin_from
});
})
.push(function () {
return gadget.updateHeader({
......@@ -71,91 +46,196 @@
});
});
})
.declareService(function () {
var gadget = this;
.declareJob("renderGraph", function () {
var gadget = this,
option_dict = gadget.property_dict.option_dict;
return gadget.getSetting("hateoas_url")
.push(function (hateoas_url) {
return gadget.jio_getAttachment(
return RSVP.all([gadget.jio_getAttachment(
'support_request_module',
hateoas_url + 'support_request_module'
+ "/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) {
new Chart(document.getElementById("bar-chart-grouped"), {
type: 'bar',
data: {
labels: ["Less than 2 days", "2-7 days", "7-30 days", "More than 30 days"],
datasets: [
{
label: "Opened",
backgroundColor: "#3e95cd",
data: [
result.le2.validated,
result['2to7'].validated,
result['7to30'].validated,
result.gt30.validated
]
},
{
label: "Submitted",
backgroundColor: "#e8c3b9",
data: [
result.le2.submitted,
result['2to7'].submitted,
result['7to30'].submitted,
result.gt30.submitted
]
},
{
label: "Suspended",
backgroundColor: "#3cba9f",
data: [
result.le2.suspended,
result['2to7'].suspended,
result['7to30'].suspended,
result.gt30.suspended
]
},
{
label: "Closed",
backgroundColor: "#8e5ea2",
data: [
result.le2.invalidated,
result['2to7'].invalidated,
result['7to30'].invalidated,
result.gt30.invalidated
]
.push(function (result_list) {
var sp_data = result_list[0], graph_gadget_1 = result_list[1], graph_gadget_2 = result_list[2];
gadget.property_dict.graph_widget = graph_gadget_1;
return RSVP.all([graph_gadget_1.render(
{
value: {
data: [
{
value_dict: {
0: ["Less than 2 days", "2-7 days", "7-30 days", "More than 30 days"],
1: [
sp_data.le2.validated,
sp_data['2to7'].validated,
sp_data['7to30'].validated,
sp_data.gt30.validated
]
},
colors: ['#d48265'],
type: "bar",
title: "Opened"
},
{
value_dict: {
0: ["Less than 2 days", "2-7 days", "7-30 days", "More than 30 days"],
1: [
sp_data.le2.submitted,
sp_data['2to7'].submitted,
sp_data['7to30'].submitted,
sp_data.gt30.submitted
]
},
colors: ['#61a0a8'],
type: "bar",
title: "Submitted"
},
{
value_dict: {
0: ["Less than 2 days", "2-7 days", "7-30 days", "More than 30 days"],
1: [
sp_data.le2.suspended,
sp_data['2to7'].suspended,
sp_data['7to30'].suspended,
sp_data.gt30.suspended
]
},
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: {
labels: ["Opened", "Closed", "Suspended", "Submitted"],
datasets: [{
label: "All Support Requests Status",
backgroundColor: ["#3e95cd", "#8e5ea2", "#3cba9f", "#e8c3b9"],
data: [result.validated, result.invalidated, result.suspended, result.submitted]
}]
},
options: {
responsive : true,
title: {
display: true,
text: 'Support Requests state since last 30 days'
});
})
.onStateChange(function (modification_dict) {
var gadget = this,
queue = new RSVP.Queue();
if (modification_dict.hasOwnProperty("field_listbox_begin_from")) {
// render the erp5 form
queue
.push(function () {
return gadget.getDeclaredGadget("last");
})
.push(function (result_list) {
var erp5_form = result_list,
tmp;
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 () {
var gadget = this;
......
......@@ -236,7 +236,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>961.50969.9466.33160</string> </value>
<value> <string>961.56651.42335.12800</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -254,7 +254,7 @@
</tuple>
<state>
<tuple>
<float>1504187369.74</float>
<float>1504528133.07</float>
<string>UTC</string>
</tuple>
</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 @@
</tr>
<tr>
<td>waitForElementPresent</td>
<td>//canvas[@id='bar-chart-grouped']</td>
<td>//a[@id='generate-rss']</td>
<td></td>
</tr>
<tr>
<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>
</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