Browse Source

[ADD] web_timeline: JSdocs

[ADD] web_timeline: JSdocs
pull/1087/head
tarteo 6 years ago
parent
commit
086080e0da
  1. 2
      web_timeline/__manifest__.py
  2. 55
      web_timeline/static/src/js/timeline_canvas.js
  3. 88
      web_timeline/static/src/js/timeline_controller.js
  4. 23
      web_timeline/static/src/js/timeline_model.js
  5. 179
      web_timeline/static/src/js/timeline_renderer.js
  6. 12
      web_timeline/static/src/js/timeline_view.js

2
web_timeline/__manifest__.py

@ -4,7 +4,7 @@
{ {
'name': "Web timeline", 'name': "Web timeline",
'summary': "Interactive visualization chart to show events in time", 'summary': "Interactive visualization chart to show events in time",
"version": "11.0.1.4.0",
"version": "11.0.1.4.1",
'author': 'ACSONE SA/NV, ' 'author': 'ACSONE SA/NV, '
'Tecnativa, ' 'Tecnativa, '
'Monk Software, ' 'Monk Software, '

55
web_timeline/static/src/js/timeline_canvas.js

@ -5,14 +5,37 @@ odoo.define('web_timeline.TimelineCanvas', function (require) {
"use strict"; "use strict";
var Widget = require('web.Widget'); var Widget = require('web.Widget');
/**
* Used to draw stuff on upon the timeline view.
*/
var TimelineCanvas = Widget.extend({ var TimelineCanvas = Widget.extend({
template: 'TimelineView.Canvas', template: 'TimelineView.Canvas',
clear: function() {
/**
* Clears all drawings (svg elements) from the canvas.
*/
clear: function () {
this.$el.find(' > :not(defs)').remove(); this.$el.find(' > :not(defs)').remove();
}, },
get_polyline_points: function(coordx1, coordy1, coordx2, coordy2, width1, height1, width2, height2, widthMarker, breakAt) {
/**
* Gets the path from one point to another.
*
* @param {Number} coordx1
* @param {Number} coordy1
* @param {Number} coordx2
* @param {Number} coordy2
* @param {Number} width1
* @param {Number} height1
* @param {Number} width2
* @param {Number} height2
* @param {Number} widthMarker The marker's width of the polyline
* @param {Number} breakAt The space between the line turns
* @returns {Array} Each item represents a coordinate
*/
get_polyline_points: function (coordx1, coordy1, coordx2, coordy2,
width1, height1, width2, height2,
widthMarker, breakAt) {
var halfHeight1 = height1 / 2; var halfHeight1 = height1 / 2;
var halfHeight2 = height2 / 2; var halfHeight2 = height2 / 2;
var x1 = coordx1 - widthMarker; var x1 = coordx1 - widthMarker;
@ -47,11 +70,32 @@ odoo.define('web_timeline.TimelineCanvas', function (require) {
return points; return points;
}, },
draw_arrow: function(from, to, color, width) {
/**
* Draws an arrow.
*
* @param {HTMLElement} from Element to draw the arrow from
* @param {HTMLElement} to Element to draw the arrow to
* @param {String} color Color of the line
* @param {Number} width Width of the line
* @returns {HTMLElement} The created SVG polyline
*/
draw_arrow: function (from, to, color, width) {
return this.draw_line(from, to, color, width, '#arrowhead', 10, 12); return this.draw_line(from, to, color, width, '#arrowhead', 10, 12);
}, },
draw_line: function(from, to, color, width, markerStart, widthMarker, breakLineAt) {
/**
* Draws a line.
*
* @param {HTMLElement} from Element to draw the line from
* @param {HTMLElement} to Element to draw the line to
* @param {String} color Color of the line
* @param {Number} width Width of the line
* @param {String} markerStart Start marker of the line
* @param {Number} widthMarker The marker's width of the polyline
* @param {Number} breakLineAt The space between the line turns
* @returns {HTMLElement} The created SVG polyline
*/
draw_line: function (from, to, color, width, markerStart, widthMarker, breakLineAt) {
var x1 = from.offsetLeft, var x1 = from.offsetLeft,
y1 = from.offsetTop + from.parentElement.offsetTop, y1 = from.offsetTop + from.parentElement.offsetTop,
x2 = to.offsetLeft, x2 = to.offsetLeft,
@ -81,8 +125,7 @@ odoo.define('web_timeline.TimelineCanvas', function (require) {
} }
this.$el.append(line); this.$el.append(line);
return line; return line;
}
},
}); });
return TimelineCanvas; return TimelineCanvas;

88
web_timeline/static/src/js/timeline_controller.js

@ -1,15 +1,15 @@
odoo.define('web_timeline.TimelineController', function (require) { odoo.define('web_timeline.TimelineController', function (require) {
"use strict";
"use strict";
var AbstractController = require('web.AbstractController');
var dialogs = require('web.view_dialogs');
var core = require('web.core');
var time = require('web.time');
var Dialog = require('web.Dialog');
var AbstractController = require('web.AbstractController');
var dialogs = require('web.view_dialogs');
var core = require('web.core');
var time = require('web.time');
var Dialog = require('web.Dialog');
var _t = core._t;
var _t = core._t;
var CalendarController = AbstractController.extend({
var TimelineController = AbstractController.extend({
custom_events: _.extend({}, AbstractController.prototype.custom_events, { custom_events: _.extend({}, AbstractController.prototype.custom_events, {
onGroupClick: '_onGroupClick', onGroupClick: '_onGroupClick',
onUpdate: '_onUpdate', onUpdate: '_onUpdate',
@ -18,6 +18,10 @@ var CalendarController = AbstractController.extend({
onAdd: '_onAdd', onAdd: '_onAdd',
}), }),
/**
* @constructor
* @override
*/
init: function (parent, model, renderer, params) { init: function (parent, model, renderer, params) {
this._super.apply(this, arguments); this._super.apply(this, arguments);
this.open_popup_action = params.open_popup_action; this.open_popup_action = params.open_popup_action;
@ -29,7 +33,10 @@ var CalendarController = AbstractController.extend({
this.debouncedInternalMove = _.debounce(this.internalMove, 0); this.debouncedInternalMove = _.debounce(this.internalMove, 0);
}, },
update: function(params, options) {
/**
* @override
*/
update: function (params, options) {
this._super.apply(this, arguments); this._super.apply(this, arguments);
if (_.isEmpty(params)){ if (_.isEmpty(params)){
return; return;
@ -69,6 +76,12 @@ var CalendarController = AbstractController.extend({
}); });
}, },
/**
* Gets triggered when a group in the timeline is clicked (by the TimelineRenderer).
*
* @private
* @returns {jQuery.Deferred}
*/
_onGroupClick: function (event) { _onGroupClick: function (event) {
var groupField = this.renderer.last_group_bys[0]; var groupField = this.renderer.last_group_bys[0];
return this.do_action({ return this.do_action({
@ -80,7 +93,12 @@ var CalendarController = AbstractController.extend({
}); });
}, },
_onUpdate: function(event) {
/**
* Opens a form view of a clicked timeline item (triggered by the TimelineRenderer).
*
* @private
*/
_onUpdate: function (event) {
var self = this; var self = this;
this.renderer = event.data.renderer; this.renderer = event.data.renderer;
var rights = event.data.rights; var rights = event.data.rights;
@ -112,7 +130,12 @@ var CalendarController = AbstractController.extend({
} }
}, },
_onMove: function(event) {
/**
* Gets triggered when a timeline item is moved (triggered by the TimelineRenderer).
*
* @private
*/
_onMove: function (event) {
var item = event.data.item; var item = event.data.item;
var view = this.renderer.view; var view = this.renderer.view;
var fields = view.fields; var fields = view.fields;
@ -150,7 +173,13 @@ var CalendarController = AbstractController.extend({
this.debouncedInternalMove(); this.debouncedInternalMove();
}, },
internalMove: function() {
/**
* Write enqueued moves to Odoo. After all writes are finished it updates the view once
* (prevents flickering of the view when multiple timeline items are moved at once).
*
* @returns {jQuery.Deferred}
*/
internalMove: function () {
var self = this; var self = this;
var queue = this.moveQueue.slice(); var queue = this.moveQueue.slice();
this.moveQueue = []; this.moveQueue = [];
@ -175,7 +204,14 @@ var CalendarController = AbstractController.extend({
}); });
}, },
_onRemove: function(e) {
/**
* Triggered when a timeline item gets removed from the view.
* Requires user confirmation before it gets actually deleted.
*
* @private
* @returns {jQuery.Deferred}
*/
_onRemove: function (e) {
var self = this; var self = this;
function do_it(event) { function do_it(event) {
@ -186,9 +222,9 @@ var CalendarController = AbstractController.extend({
[event.data.item.id], [event.data.item.id],
], ],
context: self.getSession().user_context, context: self.getSession().user_context,
}).then(function() {
}).then(function () {
var unlink_index = false; var unlink_index = false;
for (var i=0; i<self.model.data.data.length; i++) {
for (var i = 0; i < self.model.data.data.length; i++) {
if (self.model.data.data[i].id === event.data.item.id) { if (self.model.data.data[i].id === event.data.item.id) {
unlink_index = i; unlink_index = i;
} }
@ -214,7 +250,12 @@ var CalendarController = AbstractController.extend({
return def.promise(); return def.promise();
}, },
_onAdd: function(event) {
/**
* Triggered when a timeline item gets added and opens a form view.
*
* @private
*/
_onAdd: function (event) {
var self = this; var self = this;
var item = event.data.item; var item = event.data.item;
// Initialize default values for creation // Initialize default values for creation
@ -241,13 +282,19 @@ var CalendarController = AbstractController.extend({
on_saved: function (record) { on_saved: function (record) {
self.create_completed([record.res_id]); self.create_completed([record.res_id]);
}, },
}).open().on('closed', this, function() {
}).open().on('closed', this, function () {
event.data.callback(); event.data.callback();
}); });
return false; return false;
}, },
/**
* Triggered upon completion of a new record.
* Updates the timeline view with the new record.
*
* @returns {jQuery.Deferred}
*/
create_completed: function (id) { create_completed: function (id) {
var self = this; var self = this;
return this._rpc({ return this._rpc({
@ -268,6 +315,9 @@ var CalendarController = AbstractController.extend({
}); });
}, },
/**
* Triggered upon completion of writing a record.
*/
write_completed: function (options) { write_completed: function (options) {
var params = { var params = {
domain: this.renderer.last_domains, domain: this.renderer.last_domains,
@ -277,7 +327,7 @@ var CalendarController = AbstractController.extend({
this.update(params, options); this.update(params, options);
}, },
});
});
return CalendarController;
return TimelineController;
}); });

23
web_timeline/static/src/js/timeline_model.js

@ -1,13 +1,20 @@
odoo.define('web_timeline.TimelineModel', function (require) { odoo.define('web_timeline.TimelineModel', function (require) {
"use strict";
"use strict";
var AbstractModel = require('web.AbstractModel');
var AbstractModel = require('web.AbstractModel');
var TimelineModel = AbstractModel.extend({
var TimelineModel = AbstractModel.extend({
/**
* @constructor
*/
init: function () { init: function () {
this._super.apply(this, arguments); this._super.apply(this, arguments);
}, },
/**
* @override
*/
load: function (params) { load: function (params) {
var self = this; var self = this;
this.modelName = params.modelName; this.modelName = params.modelName;
@ -34,6 +41,12 @@ var TimelineModel = AbstractModel.extend({
return this.preload_def.then(this._loadTimeline.bind(this)); return this.preload_def.then(this._loadTimeline.bind(this));
}, },
/**
* Read the records for the timeline.
*
* @private
* @returns {jQuery.Deferred}
*/
_loadTimeline: function () { _loadTimeline: function () {
var self = this; var self = this;
return self._rpc({ return self._rpc({
@ -52,7 +65,7 @@ var TimelineModel = AbstractModel.extend({
}; };
}); });
}, },
});
});
return TimelineModel;
return TimelineModel;
}); });

179
web_timeline/static/src/js/timeline_renderer.js

@ -1,23 +1,26 @@
odoo.define('web_timeline.TimelineRenderer', function (require) { odoo.define('web_timeline.TimelineRenderer', function (require) {
"use strict";
"use strict";
var AbstractRenderer = require('web.AbstractRenderer');
var core = require('web.core');
var time = require('web.time');
var utils = require('web.utils');
var session = require('web.session');
var QWeb = require('web.QWeb');
var field_utils = require('web.field_utils');
var TimelineCanvas = require('web_timeline.TimelineCanvas');
var AbstractRenderer = require('web.AbstractRenderer');
var core = require('web.core');
var time = require('web.time');
var utils = require('web.utils');
var session = require('web.session');
var QWeb = require('web.QWeb');
var field_utils = require('web.field_utils');
var TimelineCanvas = require('web_timeline.TimelineCanvas');
var _t = core._t;
var _t = core._t;
var CalendarRenderer = AbstractRenderer.extend({
var TimelineRenderer = AbstractRenderer.extend({
template: "TimelineView", template: "TimelineView",
events: _.extend({}, AbstractRenderer.prototype.events, { events: _.extend({}, AbstractRenderer.prototype.events, {
}), }),
/**
* @constructor
*/
init: function (parent, state, params) { init: function (parent, state, params) {
this._super.apply(this, arguments); this._super.apply(this, arguments);
this.modelName = params.model; this.modelName = params.model;
@ -36,6 +39,9 @@ var CalendarRenderer = AbstractRenderer.extend({
this.modelClass = this.view.model; this.modelClass = this.view.model;
}, },
/**
* @override
*/
start: function () { start: function () {
var self = this; var self = this;
var attrs = this.arch.attrs; var attrs = this.arch.attrs;
@ -53,6 +59,9 @@ var CalendarRenderer = AbstractRenderer.extend({
this._super.apply(this, self); this._super.apply(this, self);
}, },
/**
* Triggered when the timeline is attached to the DOM.
*/
on_attach_callback: function() { on_attach_callback: function() {
var height = this.$el.parent().height() - this.$el.find('.oe_timeline_buttons').height(); var height = this.$el.parent().height() - this.$el.find('.oe_timeline_buttons').height();
if (height > this.min_height) { if (height > this.min_height) {
@ -62,6 +71,9 @@ var CalendarRenderer = AbstractRenderer.extend({
} }
}, },
/**
* @override
*/
_render: function () { _render: function () {
this.add_events(); this.add_events();
var self = this; var self = this;
@ -74,7 +86,12 @@ var CalendarRenderer = AbstractRenderer.extend({
}); });
}, },
add_events: function() {
/**
* Binds events to buttons.
* @private
*/
add_events: function () {
var self = this; var self = this;
this.$(".oe_timeline_button_today").click(function() { this.$(".oe_timeline_button_today").click(function() {
self._onTodayClicked(); self._onTodayClicked();
@ -93,6 +110,11 @@ var CalendarRenderer = AbstractRenderer.extend({
}); });
}, },
/**
* Set the timeline window to today (day).
*
* @private
*/
_onTodayClicked: function () { _onTodayClicked: function () {
this.current_window = { this.current_window = {
start: new moment(), start: new moment(),
@ -104,22 +126,48 @@ var CalendarRenderer = AbstractRenderer.extend({
} }
}, },
/**
* Scale the timeline window to a day.
*
* @private
*/
_onScaleDayClicked: function () { _onScaleDayClicked: function () {
this._scaleCurrentWindow(24); this._scaleCurrentWindow(24);
}, },
/**
* Scale the timeline window to a week.
*
* @private
*/
_onScaleWeekClicked: function () { _onScaleWeekClicked: function () {
this._scaleCurrentWindow(24 * 7); this._scaleCurrentWindow(24 * 7);
}, },
/**
* Scale the timeline window to a month.
*
* @private
*/
_onScaleMonthClicked: function () { _onScaleMonthClicked: function () {
this._scaleCurrentWindow(24 * 30); this._scaleCurrentWindow(24 * 30);
}, },
/**
* Scale the timeline window to a year.
*
* @private
*/
_onScaleYearClicked: function () { _onScaleYearClicked: function () {
this._scaleCurrentWindow(24 * 365); this._scaleCurrentWindow(24 * 365);
}, },
/**
* Scales the timeline window based on the current window.
*
* @param {Integer} factor The timespan (in hours) the window must be scaled to.
* @private
*/
_scaleCurrentWindow: function (factor) { _scaleCurrentWindow: function (factor) {
if (this.timeline) { if (this.timeline) {
this.current_window = this.timeline.getWindow(); this.current_window = this.timeline.getWindow();
@ -128,7 +176,12 @@ var CalendarRenderer = AbstractRenderer.extend({
} }
}, },
_computeMode: function() {
/**
* Computes the initial visible window.
*
* @private
*/
_computeMode: function () {
if (this.mode) { if (this.mode) {
var start = false, end = false; var start = false, end = false;
switch (this.mode) { switch (this.mode) {
@ -154,6 +207,11 @@ var CalendarRenderer = AbstractRenderer.extend({
} }
}, },
/**
* Initializes the timeline (http://visjs.org/docs/timeline/).
*
* @private
*/
init_timeline: function () { init_timeline: function () {
var self = this; var self = this;
this._computeMode(); this._computeMode();
@ -205,14 +263,24 @@ var CalendarRenderer = AbstractRenderer.extend({
}); });
}, },
draw_canvas: function() {
/**
* Clears and draws the canvas items.
*
* @private
*/
draw_canvas: function () {
this.canvas.clear(); this.canvas.clear();
if (this.dependency_arrow) { if (this.dependency_arrow) {
this.draw_dependencies(); this.draw_dependencies();
} }
}, },
draw_dependencies: function() {
/**
* Draw item dependencies on canvas.
*
* @private
*/
draw_dependencies: function () {
var self = this; var self = this;
var items = this.timeline.itemSet.items; var items = this.timeline.itemSet.items;
_.each(items, function(item) { _.each(items, function(item) {
@ -227,7 +295,17 @@ var CalendarRenderer = AbstractRenderer.extend({
}); });
}, },
draw_dependency: function(from, to, options) {
/**
* Draws a dependency arrow between 2 timeline items.
*
* @param {Object} from Start timeline item
* @param {Object} to Destination timeline item
* @param {Object} options
* @param {Object} options.line_color Color of the line
* @param {Object} options.line_width The width of the line
* @private
*/
draw_dependency: function (from, to, options) {
if (!from.displayed || !to.displayed) { if (!from.displayed || !to.displayed) {
return; return;
} }
@ -240,6 +318,12 @@ var CalendarRenderer = AbstractRenderer.extend({
this.canvas.draw_arrow(from.dom.box, to.dom.box, defaults.line_color, defaults.line_width); this.canvas.draw_arrow(from.dom.box, to.dom.box, defaults.line_color, defaults.line_width);
}, },
/**
* Load display_name of records.
*
* @private
* @returns {jQuery.Deferred}
*/
on_data_loaded: function (events, group_bys, adjust_window) { on_data_loaded: function (events, group_bys, adjust_window) {
var self = this; var self = this;
var ids = _.pluck(events, "id"); var ids = _.pluck(events, "id");
@ -262,6 +346,11 @@ var CalendarRenderer = AbstractRenderer.extend({
}); });
}, },
/**
* Set groups and events.
*
* @private
*/
on_data_loaded_2: function (events, group_bys, adjust_window) { on_data_loaded_2: function (events, group_bys, adjust_window) {
var self = this; var self = this;
var data = []; var data = [];
@ -282,7 +371,12 @@ var CalendarRenderer = AbstractRenderer.extend({
} }
}, },
// get the groups
/**
* Get the groups.
*
* @private
* @returns {Array}
*/
split_groups: function (events, group_bys) { split_groups: function (events, group_bys) {
if (group_bys.length === 0) { if (group_bys.length === 0) {
return events; return events;
@ -310,7 +404,12 @@ var CalendarRenderer = AbstractRenderer.extend({
return groups; return groups;
}, },
/* Transform Odoo event object to timeline event object */
/**
* Transform Odoo event object to timeline event object.
*
* @private
* @returns {Object}
*/
event_data_transform: function (evt) { event_data_transform: function (evt) {
var self = this; var self = this;
var date_start = new moment(); var date_start = new moment();
@ -368,7 +467,14 @@ var CalendarRenderer = AbstractRenderer.extend({
return r; return r;
}, },
render_timeline_item: function(evt) {
/**
* Render timeline item template.
*
* @param {Object} evt Record
* @private
* @returns {String} Rendered template
*/
render_timeline_item: function (evt) {
if(this.qweb.has_template('timeline-item')) { if(this.qweb.has_template('timeline-item')) {
return this.qweb.render('timeline-item', { return this.qweb.render('timeline-item', {
'record': evt, 'record': evt,
@ -381,8 +487,12 @@ var CalendarRenderer = AbstractRenderer.extend({
); );
}, },
/**
* Handle a click on a group header.
*
* @private
*/
on_group_click: function (e) { on_group_click: function (e) {
// handle a click on a group header
if (e.what === 'group-label' && e.group !== -1) { if (e.what === 'group-label' && e.group !== -1) {
this._trigger(e, function() { this._trigger(e, function() {
// Do nothing // Do nothing
@ -390,22 +500,47 @@ var CalendarRenderer = AbstractRenderer.extend({
} }
}, },
/**
* Trigger onUpdate.
*
* @private
*/
on_update: function (item, callback) { on_update: function (item, callback) {
this._trigger(item, callback, 'onUpdate'); this._trigger(item, callback, 'onUpdate');
}, },
/**
* Trigger onMove.
*
* @private
*/
on_move: function (item, callback) { on_move: function (item, callback) {
this._trigger(item, callback, 'onMove'); this._trigger(item, callback, 'onMove');
}, },
/**
* Trigger onRemove.
*
* @private
*/
on_remove: function (item, callback) { on_remove: function (item, callback) {
this._trigger(item, callback, 'onRemove'); this._trigger(item, callback, 'onRemove');
}, },
/**
* Trigger onAdd.
*
* @private
*/
on_add: function (item, callback) { on_add: function (item, callback) {
this._trigger(item, callback, 'onAdd'); this._trigger(item, callback, 'onAdd');
}, },
/**
* trigger_up encapsulation adds by default the rights, and the renderer.
*
* @private
*/
_trigger: function (item, callback, trigger) { _trigger: function (item, callback, trigger) {
this.trigger_up(trigger, { this.trigger_up(trigger, {
'item': item, 'item': item,
@ -415,7 +550,7 @@ var CalendarRenderer = AbstractRenderer.extend({
}); });
}, },
});
});
return CalendarRenderer;
return TimelineRenderer;
}); });

12
web_timeline/static/src/js/timeline_view.js

@ -39,6 +39,10 @@ odoo.define('web_timeline.TimelineView', function (require) {
Renderer: TimelineRenderer, Renderer: TimelineRenderer,
}, },
/**
* @constructor
* @override
*/
init: function (viewInfo, params) { init: function (viewInfo, params) {
this._super.apply(this, arguments); this._super.apply(this, arguments);
var self = this; var self = this;
@ -144,6 +148,9 @@ odoo.define('web_timeline.TimelineView', function (require) {
return this; return this;
}, },
/**
* Order function for groups.
*/
group_order: function (grp1, grp2) { group_order: function (grp1, grp2) {
// display non grouped elements first // display non grouped elements first
if (grp1.id === -1) { if (grp1.id === -1) {
@ -156,6 +163,11 @@ odoo.define('web_timeline.TimelineView', function (require) {
}, },
/**
* Parse the colors attribute.
*
* @private
*/
parse_colors: function () { parse_colors: function () {
if (this.arch.attrs.colors) { if (this.arch.attrs.colors) {
this.colors = _(this.arch.attrs.colors.split(';')).chain().compact().map(function (color_pair) { this.colors = _(this.arch.attrs.colors.split(';')).chain().compact().map(function (color_pair) {

Loading…
Cancel
Save