[MIG] web_timeline: Migration to 13.0

Thong Nguyen Van 2019-12-30 21:21:46 +07:00 committed by JasminSForgeFlow
parent fbeee7438e
commit f07afdc0d9
20 changed files with 279 additions and 280 deletions

4
web_timeline/README.rst 100755 → 100644
View File

@ -28,7 +28,7 @@ Web timeline
Define a new view displaying events in an interactive visualization chart.
The widget is based on the external library
http://visjs.org/timeline_examples.html
https://visjs.github.io/vis-timeline/examples/timeline
**Table of contents**
@ -173,6 +173,7 @@ Authors
* Tecnativa
* Monk Software
* Onestein
* Trobz
Contributors
~~~~~~~~~~~~
@ -183,6 +184,7 @@ Contributors
* Leonardo Donelli <donelli@webmonks.it>
* Adrien Didenot <adrien.didenot@horanet.com>
* Dennis Sluijk <d.sluijk@onestein.nl>
* Thong Nguyen Van <thongnv@trobz.com>
Other credits
~~~~~~~~~~~~~

View File

@ -4,20 +4,21 @@
{
"name": "Web timeline",
"summary": "Interactive visualization chart to show events in time",
"version": "12.0.1.0.5",
"version": "13.0.1.0.0",
"development_status": "Production/Stable",
"author": "ACSONE SA/NV, "
"Tecnativa, "
"Monk Software, "
"Onestein, "
"Trobz, "
"Odoo Community Association (OCA)",
"category": "web",
"license": "AGPL-3",
"application": False,
"installable": True,
"website": "https://github.com/OCA/web",
"depends": ["web"],
"qweb": ["static/src/xml/web_timeline.xml"],
"data": ["views/web_timeline.xml"],
"maintainers": ["tarteo"],
"application": False,
"installable": True,
}

View File

@ -1,4 +1,4 @@
# Copyright 2016 ACSONE SA/NV (<http://acsone.eu>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from . import ir_view
from . import ir_ui_view

View File

@ -1,7 +1,7 @@
# Copyright 2016 ACSONE SA/NV (<http://acsone.eu>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from openerp import fields, models
from odoo import fields, models
TIMELINE_VIEW = ("timeline", "Timeline")

View File

@ -4,3 +4,4 @@
* Leonardo Donelli <donelli@webmonks.it>
* Adrien Didenot <adrien.didenot@horanet.com>
* Dennis Sluijk <d.sluijk@onestein.nl>
* Thong Nguyen Van <thongnv@trobz.com>

View File

@ -1,4 +1,4 @@
Define a new view displaying events in an interactive visualization chart.
The widget is based on the external library
http://visjs.org/timeline_examples.html
https://visjs.github.io/vis-timeline/examples/timeline

View File

@ -370,7 +370,7 @@ ul.auto-toc {
<p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Production/Stable" src="https://img.shields.io/badge/maturity-Production%2FStable-green.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/OCA/web/tree/12.0/web_timeline"><img alt="OCA/web" src="https://img.shields.io/badge/github-OCA%2Fweb-lightgray.png?logo=github" /></a> <a class="reference external" href="https://translation.odoo-community.org/projects/web-12-0/web-12-0-web_timeline"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external" href="https://runbot.odoo-community.org/runbot/162/12.0"><img alt="Try me on Runbot" src="https://img.shields.io/badge/runbot-Try%20me-875A7B.png" /></a></p>
<p>Define a new view displaying events in an interactive visualization chart.</p>
<p>The widget is based on the external library
<a class="reference external" href="http://visjs.org/timeline_examples.html">http://visjs.org/timeline_examples.html</a></p>
<a class="reference external" href="https://visjs.github.io/vis-timeline/examples/timeline">https://visjs.github.io/vis-timeline/examples/timeline</a></p>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
@ -549,6 +549,7 @@ If you spotted it first, help us smashing it by providing a detailed and welcome
<li>Tecnativa</li>
<li>Monk Software</li>
<li>Onestein</li>
<li>Trobz</li>
</ul>
</div>
<div class="section" id="contributors">
@ -560,6 +561,7 @@ If you spotted it first, help us smashing it by providing a detailed and welcome
<li>Leonardo Donelli &lt;<a class="reference external" href="mailto:donelli&#64;webmonks.it">donelli&#64;webmonks.it</a>&gt;</li>
<li>Adrien Didenot &lt;<a class="reference external" href="mailto:adrien.didenot&#64;horanet.com">adrien.didenot&#64;horanet.com</a>&gt;</li>
<li>Dennis Sluijk &lt;<a class="reference external" href="mailto:d.sluijk&#64;onestein.nl">d.sluijk&#64;onestein.nl</a>&gt;</li>
<li>Thong Nguyen Van &lt;<a class="reference external" href="mailto:thongnv&#64;trobz.com">thongnv&#64;trobz.com</a>&gt;</li>
</ul>
</div>
<div class="section" id="other-credits">

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,31 +0,0 @@
/* Button style */
.openerp .oe_view_manager .oe_view_manager_switch .oe_vm_switch_timeline:after {
content: "N";
}
/* very light gray background in weekends */
.vis-timeline .vis-grid.vis-saturday,
.vis-timeline .vis-grid.vis-sunday {
background: #DCDCDC;
}
.vis-item .vis-item-overflow {
overflow: visible;
}
.oe_chatter_toggle {
padding: 15px;
}
.oe_timeline_view .vlabel .inner:hover{
cursor: pointer;
}
.oe_timeline_view svg.oe_timeline_view_canvas {
display: block;
width: 100%;
height: 100%;
position: absolute;
left: 0px;
top: 0px;
}

View File

@ -15,7 +15,7 @@ odoo.define('web_timeline.TimelineCanvas', function (require) {
* Clears all drawings (svg elements) from the canvas.
*/
clear: function () {
this.$el.find(' > :not(defs)').remove();
this.$(' > :not(defs)').remove();
},
/**
@ -33,9 +33,7 @@ odoo.define('web_timeline.TimelineCanvas', function (require) {
* @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) {
get_polyline_points: function (coordx1, coordy1, coordx2, coordy2, width1, height1, width2, height2, widthMarker, breakAt) {
var halfHeight1 = height1 / 2;
var halfHeight2 = height2 / 2;
var x1 = coordx1 - widthMarker;
@ -52,7 +50,7 @@ odoo.define('web_timeline.TimelineCanvas', function (require) {
if (xDiff > threshold) {
points.push([x1 - breakAt, y1]);
points.push([x1 - breakAt, y1 - yDiff]);
} else if (xDiff <= threshold) {
} else {
var yDiffSpace = yDiff > 0 ? spaceY : -spaceY;
points.push([x1 - breakAt, y1]);
points.push([x1 - breakAt, y2 + yDiffSpace]);
@ -105,9 +103,7 @@ odoo.define('web_timeline.TimelineCanvas', function (require) {
width2 = to.clientWidth,
height2 = to.clientHeight;
var points = this.get_polyline_points(
x1, y1, x2, y2, width1, height1, width2, height2, widthMarker, breakLineAt
);
var points = this.get_polyline_points(x1, y1, x2, y2, width1, height1, width2, height2, widthMarker, breakLineAt);
var polyline_points = _.map(points, function (point) {
return point.join(',');

View File

@ -19,7 +19,6 @@ odoo.define('web_timeline.TimelineController', function (require) {
}),
/**
* @constructor
* @override
*/
init: function (parent, model, renderer, params) {
@ -42,7 +41,7 @@ odoo.define('web_timeline.TimelineController', function (require) {
return res;
}
var defaults = _.defaults({}, options, {
adjust_window: true
adjust_window: true,
});
var self = this;
var domains = params.domain;
@ -50,14 +49,11 @@ odoo.define('web_timeline.TimelineController', function (require) {
var group_bys = params.groupBy;
this.last_domains = domains;
this.last_contexts = contexts;
// select the group by
var n_group_bys = [];
if (this.renderer.arch.attrs.default_group_by) {
// Select the group by
var n_group_bys = group_bys;
if (!n_group_bys.length && this.renderer.arch.attrs.default_group_by) {
n_group_bys = this.renderer.arch.attrs.default_group_by.split(',');
}
if (group_bys.length) {
n_group_bys = group_bys;
}
this.renderer.last_group_bys = n_group_bys;
this.renderer.last_domains = domains;
@ -83,6 +79,7 @@ odoo.define('web_timeline.TimelineController', function (require) {
* Gets triggered when a group in the timeline is clicked (by the TimelineRenderer).
*
* @private
* @param {EventObject} event
* @returns {jQuery.Deferred}
*/
_onGroupClick: function (event) {
@ -92,7 +89,7 @@ odoo.define('web_timeline.TimelineController', function (require) {
res_model: this.renderer.view.fields[groupField].relation,
res_id: event.data.item.group,
target: 'new',
views: [[false, 'form']]
views: [[false, 'form']],
});
},
@ -100,18 +97,19 @@ odoo.define('web_timeline.TimelineController', function (require) {
* Opens a form view of a clicked timeline item (triggered by the TimelineRenderer).
*
* @private
* @param {EventObject} event
*/
_onUpdate: function (event) {
var self = this;
this.renderer = event.data.renderer;
var rights = event.data.rights;
var item = event.data.item;
var id = item.evt.id;
var id = Number(item.evt.id) || item.evt.id;
var title = item.evt.__name;
if (this.open_popup_action) {
new dialogs.FormViewDialog(this, {
res_model: this.model.modelName,
res_id: parseInt(id, 10).toString() === id ? parseInt(id, 10) : id,
res_id: id,
context: this.getSession().user_context,
title: title,
view_id: Number(this.open_popup_action),
@ -126,7 +124,7 @@ odoo.define('web_timeline.TimelineController', function (require) {
}
this.trigger_up('switch_view', {
view_type: 'form',
res_id: parseInt(id, 10).toString() === id ? parseInt(id, 10) : id,
res_id: id,
mode: mode,
model: this.model.modelName,
});
@ -137,6 +135,7 @@ odoo.define('web_timeline.TimelineController', function (require) {
* Gets triggered when a timeline item is moved (triggered by the TimelineRenderer).
*
* @private
* @param {EventObject} event
*/
_onMove: function (event) {
var item = event.data.item;
@ -149,7 +148,8 @@ odoo.define('web_timeline.TimelineController', function (require) {
group = item.group;
}
var data = {};
// In case of a move event, the date_delay stay the same, only date_start and stop must be updated
// In case of a move event, the date_delay stay the same,
// only date_start and stop must be updated
data[this.date_start] = time.auto_date_to_str(event_start, fields[this.date_start].type);
if (this.date_stop) {
// In case of instantaneous event, item.end is not defined
@ -170,7 +170,7 @@ odoo.define('web_timeline.TimelineController', function (require) {
this.moveQueue.push({
id: event.data.item.id,
data: data,
event: event
event: event,
});
this.debouncedInternalMove();
@ -184,10 +184,10 @@ odoo.define('web_timeline.TimelineController', function (require) {
*/
internalMove: function () {
var self = this;
var queue = this.moveQueue.slice();
var queues = this.moveQueue.slice();
this.moveQueue = [];
var defers = [];
_.each(queue, function(item) {
for (const item of queues) {
defers.push(self._rpc({
model: self.model.modelName,
method: 'write',
@ -199,10 +199,10 @@ odoo.define('web_timeline.TimelineController', function (require) {
}).then(function () {
item.event.data.callback(item.event.data.item);
}));
});
}
return $.when.apply($, defers).done(function () {
self.write_completed({
adjust_window: false
adjust_window: false,
});
});
},
@ -212,51 +212,30 @@ odoo.define('web_timeline.TimelineController', function (require) {
* Requires user confirmation before it gets actually deleted.
*
* @private
* @param {EventObject} event
* @returns {jQuery.Deferred}
*/
_onRemove: function (e) {
_onRemove: function (event) {
var self = this;
function do_it(event) {
return self._rpc({
model: self.model.modelName,
method: 'unlink',
args: [
[event.data.item.id],
],
context: self.getSession().user_context,
}).then(function () {
var unlink_index = false;
for (var i = 0; i < self.model.data.data.length; i++) {
if (self.model.data.data[i].id === event.data.item.id) {
unlink_index = i;
}
}
if (!isNaN(unlink_index)) {
self.model.data.data.splice(unlink_index, 1);
}
event.data.callback(event.data.item);
});
}
var message = _t("Are you sure you want to delete this record?");
var def = $.Deferred();
Dialog.confirm(this, message, {
Dialog.confirm(this, _t("Are you sure you want to delete this record?"), {
title: _t("Warning"),
confirm_callback: function () {
do_it(e)
.done(def.resolve.bind(def, true))
.fail(def.reject.bind(def));
self.remove_completed(event).then(def.resolve.bind(def));
},
cancel_callback: def.resolve.bind(def),
});
return def.promise();
return def;
},
/**
* Triggered when a timeline item gets added and opens a form view.
*
* @private
* @param {EventObject} event
* @returns {dialogs.FormViewDialog}
*/
_onAdd: function (event) {
var self = this;
@ -300,6 +279,7 @@ odoo.define('web_timeline.TimelineController', function (require) {
* Triggered upon completion of a new record.
* Updates the timeline view with the new record.
*
* @param {RecordId} id
* @returns {jQuery.Deferred}
*/
create_completed: function (id) {
@ -312,8 +292,7 @@ odoo.define('web_timeline.TimelineController', function (require) {
this.model.fieldNames,
],
context: this.context,
})
.then(function (records) {
}).then(function (records) {
var new_event = self.renderer.event_data_transform(records[0]);
var items = self.renderer.timeline.itemsData;
items.add(new_event);
@ -324,6 +303,7 @@ odoo.define('web_timeline.TimelineController', function (require) {
/**
* Triggered upon completion of writing a record.
* @param {ControllerOptions} options
*/
write_completed: function (options) {
var params = {
@ -331,9 +311,34 @@ odoo.define('web_timeline.TimelineController', function (require) {
context: this.context,
groupBy: this.renderer.last_group_bys,
};
this.update(params, options);
},
/**
* Triggered upon confirm of removing a record.
* @param {EventObject} event
* @returns {jQuery.Deferred}
*/
remove_completed: function (event) {
var self = this;
return self._rpc({
model: self.modelName,
method: 'unlink',
args: [[event.data.item.id]],
context: self.getSession().user_context,
}).then(function () {
var unlink_index = false;
for (var i = 0; i < self.model.data.data.length; i++) {
if (self.model.data.data[i].id === event.data.item.id) {
unlink_index = i;
}
}
if (!isNaN(unlink_index)) {
self.model.data.data.splice(unlink_index, 1);
}
event.data.callback(event.data.item);
});
},
});
return TimelineController;

View File

@ -5,16 +5,10 @@ odoo.define('web_timeline.TimelineModel', function (require) {
var TimelineModel = AbstractModel.extend({
/**
* @constructor
*/
init: function () {
this._super.apply(this, arguments);
},
/**
* @override
*/
load: function (params) {
var self = this;
this.modelName = params.modelName;
@ -22,10 +16,22 @@ odoo.define('web_timeline.TimelineModel', function (require) {
if (!this.preload_def) {
this.preload_def = $.Deferred();
$.when(
this._rpc({model: this.modelName, method: 'check_access_rights', args: ["write", false]}),
this._rpc({model: this.modelName, method: 'check_access_rights', args: ["unlink", false]}),
this._rpc({model: this.modelName, method: 'check_access_rights', args: ["create", false]}))
.then(function (write, unlink, create) {
this._rpc({
model: this.modelName,
method: 'check_access_rights',
args: ["write", false],
}),
this._rpc({
model: this.modelName,
method: 'check_access_rights',
args: ["unlink", false],
}),
this._rpc({
model: this.modelName,
method: 'check_access_rights',
args: ["create", false],
})
).then(function (write, unlink, create) {
self.write_right = write;
self.unlink_right = unlink;
self.create_right = create;
@ -55,8 +61,7 @@ odoo.define('web_timeline.TimelineModel', function (require) {
context: self.data.context,
fields: self.fieldNames,
domain: self.data.domain,
})
.then(function (events) {
}).then(function (events) {
self.data.data = events;
self.data.rights = {
'unlink': self.unlink_right,

View File

@ -24,9 +24,6 @@ odoo.define('web_timeline.TimelineRenderer', function (require) {
'click .oe_timeline_button_scale_year': '_onScaleYearClicked',
}),
/**
* @constructor
*/
init: function (parent, state, params) {
this._super.apply(this, arguments);
this.modelName = params.model;
@ -53,11 +50,11 @@ odoo.define('web_timeline.TimelineRenderer', function (require) {
var attrs = this.arch.attrs;
this.current_window = {
start: new moment(),
end: new moment().add(24, 'hours')
end: new moment().add(24, 'hours'),
};
this.$el.addClass(attrs.class);
this.$timeline = this.$el.find(".oe_timeline_widget");
this.$timeline = this.$('.oe_timeline_widget');
if (!this.date_start) {
throw new Error(_t("Timeline view has not defined 'date_start' attribute."));
@ -69,10 +66,10 @@ odoo.define('web_timeline.TimelineRenderer', function (require) {
* Triggered when the timeline is attached to the DOM.
*/
on_attach_callback: function () {
var height = this.$el.parent().height() - this.$el.find('.oe_timeline_buttons').height();
if (height > this.min_height) {
var height = this.$el.parent().height() - this.$('.oe_timeline_buttons').height();
if (height > this.min_height && this.timeline) {
this.timeline.setOptions({
height: height
height: height,
});
}
},
@ -99,7 +96,7 @@ odoo.define('web_timeline.TimelineRenderer', function (require) {
_onTodayClicked: function () {
this.current_window = {
start: new moment(),
end: new moment().add(24, 'hours')
end: new moment().add(24, 'hours'),
};
if (this.timeline) {
@ -131,7 +128,7 @@ odoo.define('web_timeline.TimelineRenderer', function (require) {
* @private
*/
_onScaleMonthClicked: function () {
this._scaleCurrentWindow(24 * 30);
this._scaleCurrentWindow(24 * moment(this.current_window.start).daysInMonth());
},
/**
@ -140,7 +137,7 @@ odoo.define('web_timeline.TimelineRenderer', function (require) {
* @private
*/
_onScaleYearClicked: function () {
this._scaleCurrentWindow(24 * 365);
this._scaleCurrentWindow(24 * (moment(this.current_window.start).isLeapYear() ? 366 : 365));
},
/**
@ -189,7 +186,7 @@ odoo.define('web_timeline.TimelineRenderer', function (require) {
},
/**
* Initializes the timeline (http://visjs.org/docs/timeline/).
* Initializes the timeline (https://visjs.github.io/vis-timeline/docs/timeline).
*
* @private
*/
@ -197,20 +194,20 @@ odoo.define('web_timeline.TimelineRenderer', function (require) {
var self = this;
this._computeMode();
this.options.editable = {
// add new items by double tapping
// Add new items by double tapping
add: this.modelClass.data.rights.create,
// drag items horizontally
// Drag items horizontally
updateTime: this.modelClass.data.rights.write,
// drag items from one group to another
// Drag items from one group to another
updateGroup: this.modelClass.data.rights.write,
// delete an item by tapping the delete button top right
// Delete an item by tapping the delete button top right
remove: this.modelClass.data.rights.unlink,
};
$.extend(this.options, {
onAdd: self.on_add,
onMove: self.on_move,
onUpdate: self.on_update,
onRemove: self.on_remove
onRemove: self.on_remove,
});
this.qweb = new QWeb(session.debug, {_s: session.origin}, false);
if (this.arch.children.length) {
@ -222,7 +219,7 @@ odoo.define('web_timeline.TimelineRenderer', function (require) {
this.qweb.add_template(tmpl);
}
this.timeline = new vis.Timeline(self.$timeline.empty().get(0));
this.timeline = new vis.Timeline(self.$timeline.get(0));
this.timeline.setOptions(this.options);
if (self.mode && self['on_scale_' + self.mode + '_clicked']) {
self['on_scale_' + self.mode + '_clicked']();
@ -239,7 +236,8 @@ odoo.define('web_timeline.TimelineRenderer', function (require) {
self.draw_canvas();
self.canvas.$el.attr(
'style',
self.$el.find('.vis-content').attr('style') + self.$el.find('.vis-itemset').attr('style')
self.$('.vis-content').attr('style') +
self.$('.vis-itemset').attr('style')
);
});
},
@ -264,16 +262,16 @@ odoo.define('web_timeline.TimelineRenderer', function (require) {
draw_dependencies: function () {
var self = this;
var items = this.timeline.itemSet.items;
_.each(items, function(item) {
for (const item of items) {
if (!item.data.evt) {
return;
}
_.each(item.data.evt[self.dependency_arrow], function(id) {
for (const id of item.data.evt[self.dependency_arrow]) {
if (id in items) {
self.draw_dependency(item, items[id]);
}
});
});
}
}
},
/**
@ -293,7 +291,7 @@ odoo.define('web_timeline.TimelineRenderer', function (require) {
var defaults = _.defaults({}, options, {
line_color: 'black',
line_width: 1
line_width: 1,
});
this.canvas.draw_arrow(from.dom.box, to.dom.box, defaults.line_color, defaults.line_width);
@ -320,7 +318,7 @@ odoo.define('web_timeline.TimelineRenderer', function (require) {
return _.extend({
__name: _.detect(names, function (name) {
return name[0] === event.id;
})[1]
})[1],
}, event);
});
return self.on_data_loaded_2(nevents, group_bys, adjust_window);
@ -337,11 +335,11 @@ odoo.define('web_timeline.TimelineRenderer', function (require) {
var data = [];
var groups = [];
this.grouped_by = group_bys;
_.each(events, function (event) {
if (event[self.date_start]) {
data.push(self.event_data_transform(event));
for (const evt of events) {
if (evt[self.date_start]) {
data.push(self.event_data_transform(evt));
}
}
});
groups = this.split_groups(events, group_bys);
this.timeline.setGroups(groups);
this.timeline.setItems(data);
@ -364,24 +362,22 @@ odoo.define('web_timeline.TimelineRenderer', function (require) {
}
var groups = [];
groups.push({id: -1, content: _t('-')});
_.each(events, function (event) {
var group_name = event[_.first(group_bys)];
for (const evt of events) {
var group_name = evt[_.first(group_bys)];
if (group_name) {
if (group_name instanceof Array) {
var group = _.find(groups, function (existing_group) {
return _.isEqual(existing_group.id, group_name[0]);
return existing_group.id === group_name[0];
});
if (_.isUndefined(group)) {
group = {
groups.push({
id: group_name[0],
content: group_name[1]
};
groups.push(group);
}
}
}
content: group_name[1],
});
}
}
}
}
return groups;
},
@ -412,7 +408,7 @@ odoo.define('web_timeline.TimelineRenderer', function (require) {
}
if (!date_stop && date_delay) {
date_stop = moment(date_start).add(date_delay, 'hours').toDate();
date_stop = date_start.clone().add(date_delay, 'hours').toDate();
}
var group = evt[self.last_group_bys[0]];
@ -421,13 +417,14 @@ odoo.define('web_timeline.TimelineRenderer', function (require) {
} else {
group = -1;
}
_.each(self.colors, function (color) {
if (eval("'" + evt[color.field] + "' " + color.opt + " '" + color.value + "'")) {
for (const color of self.colors) {
if (py.eval("'" + evt[color.field] + "' " + color.opt + " '" + color.value + "'")) {
self.color = color.color;
}
});
}
var content = _.isUndefined(evt.__name) ? evt.display_name : evt.__name;
var content = evt.__name || evt.display_name;
if (this.arch.children.length) {
content = this.render_timeline_item(evt);
}
@ -438,13 +435,14 @@ odoo.define('web_timeline.TimelineRenderer', function (require) {
'id': evt.id,
'group': group,
'evt': evt,
'style': 'background-color: ' + self.color + ';'
'style': `background-color: ${this.color};`,
};
// Check if the event is instantaneous, if so, display it with a point on the timeline (no 'end')
// Check if the event is instantaneous,
// if so, display it with a point on the timeline (no 'end')
if (date_stop && !moment(date_start).isSame(date_stop)) {
r.end = date_stop;
}
self.color = null;
this.color = null;
return r;
},
@ -459,7 +457,7 @@ odoo.define('web_timeline.TimelineRenderer', function (require) {
if (this.qweb.has_template('timeline-item')) {
return this.qweb.render('timeline-item', {
'record': evt,
'field_utils': field_utils
'field_utils': field_utils,
});
}
@ -518,7 +516,7 @@ odoo.define('web_timeline.TimelineRenderer', function (require) {
},
/**
* trigger_up encapsulation adds by default the rights, and the renderer.
* Trigger_up encapsulation adds by default the rights, and the renderer.
*
* @private
*/

View File

@ -3,25 +3,18 @@
* Copyright 2016 Pedro M. Baeza <pedro.baeza@tecnativa.com>
* License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). */
_.str.toBoolElse = function (str, elseValues, trueValues, falseValues) {
var ret = _.str.toBool(str, trueValues, falseValues);
if (_.isUndefined(ret)) {
return elseValues;
}
return ret;
};
odoo.define('web_timeline.TimelineView', function (require) {
"use strict";
var core = require('web.core');
var utils = require('web.utils');
var view_registry = require('web.view_registry');
var AbstractView = require('web.AbstractView');
var TimelineRenderer = require('web_timeline.TimelineRenderer');
var TimelineController = require('web_timeline.TimelineController');
var TimelineModel = require('web_timeline.TimelineModel');
var _lt = core._lt;
function isNullOrUndef(value) {
@ -31,8 +24,8 @@ odoo.define('web_timeline.TimelineView', function (require) {
var TimelineView = AbstractView.extend({
display_name: _lt('Timeline'),
icon: 'fa-clock-o',
jsLibs: ['/web_timeline/static/lib/vis/vis-timeline-graph2d.min.js'],
cssLibs: ['/web_timeline/static/lib/vis/vis-timeline-graph2d.min.css'],
jsLibs: ['/web_timeline/static/lib/vis-timeline/vis-timeline-graph2d.min.js'],
cssLibs: ['/web_timeline/static/lib/vis-timeline/vis-timeline-graph2d.min.css'],
config: {
Model: TimelineModel,
Controller: TimelineController,
@ -40,7 +33,6 @@ odoo.define('web_timeline.TimelineView', function (require) {
},
/**
* @constructor
* @override
*/
init: function (viewInfo, params) {
@ -65,13 +57,13 @@ odoo.define('web_timeline.TimelineView', function (require) {
fieldsToGather.push(attrs.default_group_by);
_.each(fieldsToGather, function (field) {
for (const field of fieldsToGather) {
if (attrs[field]) {
var fieldName = attrs[field];
mapping[field] = fieldName;
fieldNames.push(fieldName);
}
});
}
var archFieldNames = _.map(_.filter(this.arch.children, function (item) {
return item.tag === 'field';
@ -84,8 +76,8 @@ odoo.define('web_timeline.TimelineView', function (require) {
);
this.parse_colors();
for (var i=0; i<this.colors.length; i++) {
fieldNames.push(this.colors[i].field);
for (const color of this.colors) {
fieldNames.push(color.field);
}
if (attrs.dependency_arrow) {
@ -107,13 +99,13 @@ odoo.define('web_timeline.TimelineView', function (require) {
this.current_window = {
start: new moment(),
end: new moment().add(24, 'hours')
end: new moment().add(24, 'hours'),
};
if (!isNullOrUndef(attrs.quick_create_instance)) {
self.quick_create_instance = 'instance.' + attrs.quick_create_instance;
}
this.stack = true;
if (!isNullOrUndef(attrs.stack) && !_.str.toBoolElse(attrs.stack, "true")) {
if (!isNullOrUndef(attrs.stack) && !utils.toBoolElse(attrs.stack, true)) {
this.stack = false;
}
this.options = {
@ -124,9 +116,9 @@ odoo.define('web_timeline.TimelineView', function (require) {
showCurrentTime: true,
stack: this.stack,
margin: JSON.parse(this.margin),
zoomKey: this.zoomKey
zoomKey: this.zoomKey,
};
if (isNullOrUndef(attrs.event_open_popup) || !_.str.toBoolElse(attrs.event_open_popup, true)) {
if (isNullOrUndef(attrs.event_open_popup) || !utils.toBoolElse(attrs.event_open_popup, true)) {
this.open_popup_action = false;
} else {
this.open_popup_action = attrs.event_open_popup;
@ -152,23 +144,23 @@ odoo.define('web_timeline.TimelineView', function (require) {
this.controllerParams.date_stop = this.date_stop;
this.controllerParams.date_delay = this.date_delay;
this.controllerParams.actionContext = this.action.context;
return this;
this.withSearchPanel = false;
},
/**
* Order function for groups.
* @returns {Integer}
*/
group_order: function (grp1, grp2) {
// display non grouped elements first
// Display non grouped elements first
if (grp1.id === -1) {
return -1;
}
if (grp2.id === -1) {
return +1;
return 1;
}
return grp1.content.localeCompare(grp2.content);
},
/**
@ -185,7 +177,7 @@ odoo.define('web_timeline.TimelineView', function (require) {
'color': color,
'field': temp.expressions[0].value,
'opt': temp.operators[0],
'value': temp.expressions[1].value
'value': temp.expressions[1].value,
};
}).value();
} else {

View File

@ -0,0 +1,17 @@
.oe_timeline_view .vis-timeline {
.vis-grid {
.vis-saturday, .vis-sunday {
// very light gray background in weekends
background: #DCDCDC;
}
}
.vis-item {
&.vis-box:hover {
cursor: pointer !important;
}
&.vis-item-overflow {
overflow: visible;
}
}
}

View File

@ -1,3 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<template>
<t t-name="TimelineView">
<div class="oe_timeline_view">
@ -15,8 +16,7 @@
</div>
</t>
<svg t-name="TimelineView.Canvas"
class="oe_timeline_view_canvas">
<svg t-name="TimelineView.Canvas" class="oe_timeline_view_canvas">
<defs>
<marker id="arrowhead" markerWidth="10" markerHeight="7" refX="10" refY="3.5" orient="auto">
<polygon points="10 0, 10 7, 0 3.5"/>

View File

@ -1,12 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="assets_backend" name="web_timeline assets" inherit_id="web.assets_backend">
<xpath expr="." position="inside">
<link rel="stylesheet" href="/web_timeline/static/lib/vis/vis-timeline-graph2d.min.css"/>
<link rel="stylesheet" href="/web_timeline/static/src/css/web_timeline.css"/>
<link rel="stylesheet" type="text/css" href="/web_timeline/static/lib/vis-timeline/vis-timeline-graph2d.min.css"/>
<link rel="stylesheet" type="text/scss" href="/web_timeline/static/src/scss/web_timeline.scss"/>
<script type="text/javascript" src="/web_timeline/static/lib/vis/vis-timeline-graph2d.min.js"/>
<script type="text/javascript" src="/web_timeline/static/lib/vis-timeline/vis-timeline-graph2d.min.js"/>
<script type="text/javascript" src="/web_timeline/static/src/js/timeline_view.js"/>
<script type="text/javascript" src="/web_timeline/static/src/js/timeline_renderer.js"/>
<script type="text/javascript" src="/web_timeline/static/src/js/timeline_controller.js"/>
@ -14,5 +13,4 @@
<script type="text/javascript" src="/web_timeline/static/src/js/timeline_canvas.js"/>
</xpath>
</template>
</odoo>