Commit 412a10fa authored by Sebastien Robin's avatar Sebastien Robin

officejs: first version of a timeline gadget

parent 9562e715
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, user-scalable=no" />
<title>ERP5 Widget Timeline with Vis</title>
<!-- interfaces -->
<link rel="http://www.renderjs.org/rel/interface" href="gadget_officejs_interface_widget_timeline.html">
<!-- renderjs -->
<script src="rsvp.js" type="text/javascript"></script>
<script src="renderjs.js" type="text/javascript"></script>
<!-- custom script -->
<script src="gadget_officejs_delivery_timeline.js" type="text/javascript"></script>
<style>
</style>
</head>
<body>
<div class="timeline-content">
</div>
</body>
</html>
\ No newline at end of file
/*global window, rJS, RSVP, console */
/*jslint nomen: true, indent: 2 */
(function (window, rJS, RSVP) {
"use strict";
/////////////////////////////////////////////////////////////////
// templates
/////////////////////////////////////////////////////////////////
var gadget_klass = rJS(window);
/////////////////////////////////////////////////////////////////
// some methods
/////////////////////////////////////////////////////////////////
gadget_klass
/////////////////////////////////////////////////////////////////
// ready
/////////////////////////////////////////////////////////////////
.ready(function (gadget) {
gadget.property_dict = {};
})
/////////////////////////////////////////////////////////////////
// published methods
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
// acquired methods
/////////////////////////////////////////////////////////////////
.declareAcquiredMethod("jio_allDocs", "jio_allDocs")
/////////////////////////////////////////////////////////////////
// declared methods
/////////////////////////////////////////////////////////////////
.declareMethod('render', function (option_dict) {
var gadget = this,
container,
graph_data_and_parameter,
chart;
gadget.property_dict.option_dict = option_dict.value;
console.log("gantt option_dict", option_dict.value);
gadget.renderGantt(); //Launched as service, not blocking
})
.declareJob("renderGantt", function () {
var gadget = this,
option_dict = gadget.property_dict.option_dict;
return gadget.declareGadget(
"unsafe/gadget_officejs_widget_timeline_fullcalendar.html",
{scope: "timeline",
sandbox: "iframe",
element: gadget.element.querySelector(".timeline-content")
})
.push(function (timeline_widget) {
var query;
gadget.property_dict.timeline_widget = timeline_widget;
console.log("timeline_widget", timeline_widget);
// portal_type:="Sale Order Line" AND relative_url:"sale_order_module/4572/%"
query = 'portal_type:="' + option_dict.portal_type + '" AND relative_url:"' + option_dict.relative_url + '"';
return gadget.jio_allDocs({
query: query,
limit: 10000,
sort_on: [['reference', 'ascending']],
select_list: ['reference', 'title', 'start_date', 'stop_date', 'parent_uid', 'uid', 'source_title']
});
})
.push(function (line_list) {
var i, line,
timeline_data = {},
data_list = [],
tree_list = [],
tree_data,
sale_order_uid,
color_list = ['blue', 'green', 'purple', 'orange', 'grey', 'black', 'red', 'pink'],
color,
source_list = [],
line_data;
line_list = line_list.data.rows;
console.log("line_list", line_list);
for (i = 0; i < line_list.length; i = i + 1) {
line = line_list[i].value;
if (i === 0) {
// We assume that by the sort on order_reference that the first line is a level 1 line
sale_order_uid = line.parent_uid;
}
if (line.start_date !== undefined && line.stop_date !== undefined) {
tree_data = {'title': line.title,
'id': line.uid
};
if (source_list.indexOf(line.source_title) === -1) {
source_list.push(line.source_title);
}
console.log('source_list', source_list);
color = color_list[source_list.indexOf(line.source_title) % color_list.length];
line_data = {'title': line.title,
'id': line.uid,
'tree_id': line.uid,
'start_date': new Date(line.start_date).toISOString(),
'stop_date': new Date(line.stop_date).toISOString(),
'background_color': color};
if (line.parent_uid !== sale_order_uid) {
tree_data.parent_id = line.parent_uid;
}
data_list.push(line_data);
tree_list.push(tree_data);
}
}
timeline_data.data_list = data_list;
timeline_data.tree_list = tree_list;
timeline_data.tree_title = "Tasks";
console.log("timeline_data", timeline_data);
return gadget.property_dict.timeline_widget.render(timeline_data);
});
});
}(window, rJS, RSVP));
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<title>Timeline Interface</title>
</head>
<body>
<h1>widget_timeline_interface</h1>
<h3>A timeline gadget allows to display various types of schedules</h3>
<dl>
<dt>render</dt>
<dd>render a timeline</dd>
<dl>
<dt data-parameter-required="required" data-parameter-type="object">configuration_dict</dt>
<dd><code style="display:block;white-space:pre-wrap">
Generic timeline gadget. The purpose of this gadget is to provide an unique
API for various timeline libraries
Options supported are :
{
"$schema": "http://json-schema.org/draft-04/schema#",
"description": "Parameters to generate a graph",
"properties": {
"tree_title": {
"description": "The title of the tree",
"type": "string"
},
"tree_list": {
"description": "the list of item needed to construct resource tree",
"items": {
"properties" : {
"title": {
"description": "The title of the resource",
"type": "string"
},
"id": {
"description": "an identifier for the resource",
"type": "string"
},
"parent_id": {
"description": "the identifier of the parent resource",
"type": "string"
},
},
"additionalProperties": false,
"type": "object",
},
"type": "array",
},
"data_list": {
"description": "the list of task to be displayed in timeline",
"items": {
"properties" : {
"title": {
"description": "The title of the task",
"type": "string"
},
"id": {
"description": "an identifier for the task",
"type": "string"
},
"tree_id": {
"description": "the identifier of the corresponding resource",
"type": "string"
},
"start_date": {
"description": "task starting date",
"type": "string"
},
"stop_date": {
"description": "task end date",
"type": "string"
},
"background_color": {
"description": "task color",
"type": "string"
},
},
"additionalProperties": false,
"type": "object",
},
"type": "array",
}
},
"additionalProperties": false
}
Example of options:
{ tree_title: "Tasks",
tree_list: [{'title': 'Phase 1',
'id': '1'},
{'title': 'Phase 1.1',
'id': '1.1',
'parent_id': '1'},
{'title': 'Phase 1.1.1',
'id': '1.1.1',
'parent_id': '1.1'},
{'title': 'Phase 2',
'id': '2'}],
data_list : [{'id': '1',
'tree_id': '1.1.1',
'title': 'Task A in Phase 1.1.1',
'start_date': '2017-03-01',
'stop_date': '2017-04-15'},
{'id': '2',
'tree_id': '2',
'title': 'Task B in Group 2',
'start_date': '2017-04-15',
'stop_date': '2017-06-30',
'background_color': 'green'}]
}
</code></dd>
</dl>
</dl>
</body>
</html>
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, user-scalable=no" />
<title>ERP5 Widget Graph</title>
<!-- interfaces -->
<link rel="http://www.renderjs.org/rel/interface" href="gadget_officejs_interface_widget_timeline.html">
<!-- renderjs -->
<script src="rsvp.js" type="text/javascript"></script>
<script src="renderjs.js" type="text/javascript"></script>
<!-- libraries needed for graphs -->
<link href='fullcalendar.css' rel='stylesheet' />
<script src='moment.js'type="text/javascript"></script>
<script src='jquery.js'type="text/javascript"></script>
<script src='fullcalendar.js' type="text/javascript"></script>
<!-- custom script -->
<script src="gadget_officejs_widget_timeline_fullcalendar.js" type="text/javascript"></script>
</head>
<body>
<div id='calendar'></div>
</body>
</html>
\ No newline at end of file
/*global window, rJS, RSVP, console, $ */
/*jslint nomen: true, indent: 2 */
(function (window, rJS, RSVP, $) {
"use strict";
/////////////////////////////////////////////////////////////////
// templates
/////////////////////////////////////////////////////////////////
var gadget_klass = rJS(window);
var getDataAndParameterFromConfiguration = function (configuration_dict) {
var parameter_dict = {}, parent_resource, data_item,
resource, event, tree_item, resource_dict = {},
i, eventDrop;
eventDrop = function (event, dayDelta, minuteDelta) {
console.log(event);
console.log(event.start);
console.log(event.end);
console.log(event.id);
};
parameter_dict = {
eventDrop: eventDrop,
schedulerLicenseKey: 'GPL-My-Project-Is-Open-Source',
//now: '2017-04-24',
editable: true,
aspectRatio: 1.8,
scrollTime: '00:00',
timezone: 'local',
header: {
left: 'today prev,next',
center: 'title',
right: 'timelineDay,timelineTenDay,timelineMonth,timelineYear,timelineTenYears'
},
defaultView: 'timelineDay',
views: {
timelineDay: {
buttonText: ':15 slots',
slotDuration: '00:15'
},
timelineTenDay: {
type: 'timeline',
duration: { days: 10 }
},
timelineTenYears: {
type: 'timeline',
buttonText: 'Ten years',
duration: { days: 365.25 * 10 }
}
},
navLinks: true,
resourceAreaWidth: '25%',
resourceLabelText: configuration_dict.tree_title || ""
};
parameter_dict.resources = [];
parameter_dict.events = [];
for (i = 0 ; i < configuration_dict.tree_list.length; i = i + 1) {
tree_item = configuration_dict.tree_list[i];
resource = {id: tree_item.id,
eventColor: 'green',
title: tree_item.title};
resource_dict[tree_item.id] = resource;
if (tree_item.parent_id !== undefined) {
parent_resource = resource_dict[tree_item.parent_id];
if (parent_resource.children === undefined) {
parent_resource.children = [];
}
parent_resource.children.push(resource);
} else {
parameter_dict.resources.push(resource);
}
}
for (i = 0 ; i < configuration_dict.data_list.length; i = i + 1) {
data_item = configuration_dict.data_list[i];
if (data_item.background_color !== undefined) {
resource_dict[data_item.tree_id].eventColor = data_item.background_color;
}
event = {resourceId: data_item.tree_id,
start: data_item.start_date,
end: data_item.stop_date,
title: data_item.title,
id: data_item.id};
parameter_dict.events.push(event);
}
console.log('parameter_dict', parameter_dict);
return parameter_dict;
};
/////////////////////////////////////////////////////////////////
// some methods
/////////////////////////////////////////////////////////////////
gadget_klass
/////////////////////////////////////////////////////////////////
// ready
/////////////////////////////////////////////////////////////////
.ready(function (gadget) {
gadget.property_dict = {};
})
/////////////////////////////////////////////////////////////////
// published methods
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
// acquired methods
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
// declared methods
/////////////////////////////////////////////////////////////////
.declareMethod('render', function (configuration_dict) {
var gadget = this,
container,
data_and_parameter,
chart;
container = gadget.element.querySelector(".graph-content");
gadget.property_dict.container = container;
console.log("container inside iframe");
data_and_parameter = getDataAndParameterFromConfiguration(configuration_dict);
console.log("graph_data_and_parameter", data_and_parameter);
$('#calendar').fullCalendar(data_and_parameter);
})
.declareMethod('updateConfiguration', function (configuration_dict) {
/* Update the graph with new data/configuration.
There is many functions in Plotly for updating style, adding points to data, for adding new series of data, etc.
Though, this is way too complex to guess what has been changed to know if we could just call a few functions to
take into account changes. Therefore just erase and redraw the whole graph.
*/
var gadget = this,
data_and_parameter;
console.log("updateConfiguration");
data_and_parameter = getDataAndParameterFromConfiguration(configuration_dict);
});
}(window, rJS, RSVP, $));
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