diff --git a/web_timeline/README.rst b/web_timeline/README.rst index 285516b26..05f77fe35 100644 --- a/web_timeline/README.rst +++ b/web_timeline/README.rst @@ -7,7 +7,7 @@ Web timeline !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:c8c5da5c7631fad4d64b447787e487826952622707762815d1166990b565fcd0 + !! source digest: sha256:bd504d36989179a1e11223c03dbf38ac45f0a792c6ad15a2786c9283bc64650b !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Production%2FStable-green.png diff --git a/web_timeline/__manifest__.py b/web_timeline/__manifest__.py index 4fb09bfdf..310d17726 100644 --- a/web_timeline/__manifest__.py +++ b/web_timeline/__manifest__.py @@ -4,7 +4,7 @@ { "name": "Web timeline", "summary": "Interactive visualization chart to show events in time", - "version": "16.0.1.1.2", + "version": "16.0.1.1.4", "development_status": "Production/Stable", "author": "ACSONE SA/NV, " "Tecnativa, " diff --git a/web_timeline/static/description/index.html b/web_timeline/static/description/index.html index 6d389b88f..00d9c2ebb 100644 --- a/web_timeline/static/description/index.html +++ b/web_timeline/static/description/index.html @@ -8,10 +8,11 @@ /* :Author: David Goodger (goodger@python.org) -:Id: $Id: html4css1.css 8954 2022-01-20 10:10:25Z milde $ +:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $ :Copyright: This stylesheet has been placed in the public domain. Default cascading style sheet for the HTML output of Docutils. +Despite the name, some widely supported CSS2 features are used. See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to customize this style sheet. @@ -274,7 +275,7 @@ pre.literal-block, pre.doctest-block, pre.math, pre.code { margin-left: 2em ; margin-right: 2em } -pre.code .ln { color: grey; } /* line numbers */ +pre.code .ln { color: gray; } /* line numbers */ pre.code, code { background-color: #eeeeee } pre.code .comment, code .comment { color: #5C6576 } pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold } @@ -300,7 +301,7 @@ span.option { span.pre { white-space: pre } -span.problematic { +span.problematic, pre.problematic { color: red } span.section-subtitle { @@ -366,7 +367,7 @@ ul.auto-toc { !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!! source digest: sha256:c8c5da5c7631fad4d64b447787e487826952622707762815d1166990b565fcd0 +!! source digest: sha256:bd504d36989179a1e11223c03dbf38ac45f0a792c6ad15a2786c9283bc64650b !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->

Production/Stable License: AGPL-3 OCA/web Translate me on Weblate Try me on Runboat

Define a new view displaying events in an interactive visualization chart.

@@ -614,7 +615,9 @@ If you spotted it first, help us to smash it by providing a detailed and welcome

Maintainers

This module is maintained by the OCA.

-Odoo Community Association + +Odoo Community Association +

OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use.

diff --git a/web_timeline/static/src/js/timeline_renderer.js b/web_timeline/static/src/js/timeline_renderer.js index 14d387ed6..10f90cc0a 100644 --- a/web_timeline/static/src/js/timeline_renderer.js +++ b/web_timeline/static/src/js/timeline_renderer.js @@ -41,6 +41,7 @@ odoo.define("web_timeline.TimelineRenderer", function (require) { this.fields = params.fields; this.timeline = false; + this.initial_data_loaded = false; }, /** @@ -48,11 +49,6 @@ odoo.define("web_timeline.TimelineRenderer", function (require) { */ start: function () { const attrs = this.arch.attrs; - this.current_window = { - start: new moment(), - end: new moment().add(24, "hours"), - }; - this.$el.addClass(attrs.class); this.$timeline = this.$(".oe_timeline_widget"); @@ -85,7 +81,6 @@ odoo.define("web_timeline.TimelineRenderer", function (require) { // Prevent Double Rendering on Updates if (!this.timeline) { this.init_timeline(); - $(window).trigger("resize"); } }); }, @@ -96,13 +91,11 @@ odoo.define("web_timeline.TimelineRenderer", function (require) { * @private */ _onTodayClicked: function () { - this.current_window = { - start: new moment(), - end: new moment().add(24, "hours"), - }; - if (this.timeline) { - this.timeline.setWindow(this.current_window); + this.timeline.setWindow({ + start: new moment(), + end: new moment().add(24, "hours"), + }); } }, @@ -112,7 +105,7 @@ odoo.define("web_timeline.TimelineRenderer", function (require) { * @private */ _onScaleDayClicked: function () { - this._scaleCurrentWindow(24); + this._scaleCurrentWindow(() => 24); }, /** @@ -121,7 +114,7 @@ odoo.define("web_timeline.TimelineRenderer", function (require) { * @private */ _onScaleWeekClicked: function () { - this._scaleCurrentWindow(24 * 7); + this._scaleCurrentWindow(() => 24 * 7); }, /** @@ -130,9 +123,7 @@ odoo.define("web_timeline.TimelineRenderer", function (require) { * @private */ _onScaleMonthClicked: function () { - this._scaleCurrentWindow( - 24 * moment(this.current_window.start).daysInMonth() - ); + this._scaleCurrentWindow((start) => 24 * moment(start).daysInMonth()); }, /** @@ -142,24 +133,22 @@ odoo.define("web_timeline.TimelineRenderer", function (require) { */ _onScaleYearClicked: function () { this._scaleCurrentWindow( - 24 * (moment(this.current_window.start).isLeapYear() ? 366 : 365) + (start) => 24 * (moment(start).isLeapYear() ? 366 : 365) ); }, /** * Scales the timeline window based on the current window. * - * @param {Integer} factor The timespan (in hours) the window must be scaled to. + * @param {function} getHoursFromStart Function which returns the timespan + * (in hours) the window must be scaled to, starting from the "start" moment. * @private */ - _scaleCurrentWindow: function (factor) { + _scaleCurrentWindow: function (getHoursFromStart) { if (this.timeline) { - this.current_window = this.timeline.getWindow(); - this.current_window.end = moment(this.current_window.start).add( - factor, - "hours" - ); - this.timeline.setWindow(this.current_window); + const start = this.timeline.getWindow().start; + const end = moment(start).add(getHoursFromStart(start), "hours"); + this.timeline.setWindow(start, end); } }, @@ -219,6 +208,7 @@ odoo.define("web_timeline.TimelineRenderer", function (require) { onUpdate: this.on_update, onRemove: this.on_remove, }); + this.options.xss = {disabled: true}; this.qweb = new QWeb(session.debug, {_s: session.origin}, false); if (this.arch.children.length) { const tmpl = utils.json_node_to_xml( @@ -227,25 +217,17 @@ odoo.define("web_timeline.TimelineRenderer", function (require) { this.qweb.add_template(tmpl); } - this.timeline = new vis.Timeline( - this.$timeline.get(0), - {}, - {xss: {disabled: true}} - ); - this.timeline.setOptions(this.options); - if (this.mode && this["on_scale_" + this.mode + "_clicked"]) { - this["on_scale_" + this.mode + "_clicked"](); - } + this.timeline = new vis.Timeline(this.$timeline.get(0), {}, this.options); this.timeline.on("click", this.on_group_click); const group_bys = this.arch.attrs.default_group_by.split(","); this.last_group_bys = group_bys; this.last_domains = this.modelClass.data.domain; - this.on_data_loaded(this.modelClass.data.data, group_bys); this.$centerContainer = $(this.timeline.dom.centerContainer); this.canvas = new TimelineCanvas(this); this.canvas.appendTo(this.$centerContainer); this.timeline.on("changed", () => { this.draw_canvas(); + this.load_initial_data(); }); }, @@ -313,6 +295,16 @@ odoo.define("web_timeline.TimelineRenderer", function (require) { ); }, + /* Load initial data. This is called once after each redraw; we only handle the first one. + * Deferring this initial load here avoids rendering issues. */ + load_initial_data: function () { + if (!this.initial_data_loaded) { + this.on_data_loaded(this.modelClass.data.data, this.last_group_bys); + this.initial_data_loaded = true; + this.timeline.redraw(); + } + }, + /** * Load display_name of records. * diff --git a/web_timeline/static/src/js/timeline_view.js b/web_timeline/static/src/js/timeline_view.js index 9d9a5bc50..f9e0f1e56 100644 --- a/web_timeline/static/src/js/timeline_view.js +++ b/web_timeline/static/src/js/timeline_view.js @@ -86,10 +86,6 @@ odoo.define("web_timeline.TimelineView", function (require) { const mode = attrs.mode || attrs.default_window || "fit"; const min_height = attrs.min_height || 300; - const current_window = { - start: new moment(), - end: new moment().add(24, "hours"), - }; if (!isNullOrUndef(attrs.quick_create_instance)) { this.quick_create_instance = "instance." + attrs.quick_create_instance; } @@ -104,7 +100,6 @@ odoo.define("web_timeline.TimelineView", function (require) { this.rendererParams.model = this.modelName; this.rendererParams.view = this; this.rendererParams.options = this._preapre_vis_timeline_options(attrs); - this.rendererParams.current_window = current_window; this.rendererParams.date_start = date_start; this.rendererParams.date_stop = date_stop; this.rendererParams.date_delay = date_delay;