mirror of https://github.com/OCA/web.git
parent
fad3ec6c27
commit
086080e0da
|
@ -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, '
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 AbstractController = require('web.AbstractController');
|
||||||
var dialogs = require('web.view_dialogs');
|
var dialogs = require('web.view_dialogs');
|
||||||
var core = require('web.core');
|
var core = require('web.core');
|
||||||
var time = require('web.time');
|
var time = require('web.time');
|
||||||
var Dialog = require('web.Dialog');
|
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;
|
||||||
});
|
});
|
||||||
|
|
|
@ -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;
|
||||||
});
|
});
|
||||||
|
|
|
@ -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 AbstractRenderer = require('web.AbstractRenderer');
|
||||||
var core = require('web.core');
|
var core = require('web.core');
|
||||||
var time = require('web.time');
|
var time = require('web.time');
|
||||||
var utils = require('web.utils');
|
var utils = require('web.utils');
|
||||||
var session = require('web.session');
|
var session = require('web.session');
|
||||||
var QWeb = require('web.QWeb');
|
var QWeb = require('web.QWeb');
|
||||||
var field_utils = require('web.field_utils');
|
var field_utils = require('web.field_utils');
|
||||||
var TimelineCanvas = require('web_timeline.TimelineCanvas');
|
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;
|
||||||
});
|
});
|
||||||
|
|
|
@ -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…
Reference in New Issue