mirror of https://github.com/OCA/web.git
[FIX] web_timeline: Redraw issues with initial mode
This commit fixes redraw issues when setting a `mode` attribute in the `timeline` view tag. This mode specifies a default scale one would want to set; same as when clicking on Day/Week/Month buttons at the top of the view. Initial rendering had issues here because data was loaded too soon, before the timeline component was rendered/ready. The fix is to load data into the component only after initial redraw event, called `changed` (see <https://visjs.github.io/vis-timeline/docs/timeline/#Events>). There was old code attempting to call `on_scale_xxx_clicked` methods at load time to simulate clicks on these Day/Week/Month buttons, but these methods have been renamed so this code is no longer working. This commit also removes the `current_window` instance variable, not needed and actually confusing as the timeline component already maintains its own start/end information (which we can query with `timeline.getWindow()`).pull/2969/head
parent
c8490eb2f3
commit
0d816893a7
|
@ -7,7 +7,7 @@ Web timeline
|
||||||
!! This file is generated by oca-gen-addon-readme !!
|
!! This file is generated by oca-gen-addon-readme !!
|
||||||
!! changes will be overwritten. !!
|
!! changes will be overwritten. !!
|
||||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
!! source digest: sha256:c8c5da5c7631fad4d64b447787e487826952622707762815d1166990b565fcd0
|
!! source digest: sha256:bd504d36989179a1e11223c03dbf38ac45f0a792c6ad15a2786c9283bc64650b
|
||||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
|
|
||||||
.. |badge1| image:: https://img.shields.io/badge/maturity-Production%2FStable-green.png
|
.. |badge1| image:: https://img.shields.io/badge/maturity-Production%2FStable-green.png
|
||||||
|
|
|
@ -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": "16.0.1.1.2",
|
"version": "16.0.1.1.4",
|
||||||
"development_status": "Production/Stable",
|
"development_status": "Production/Stable",
|
||||||
"author": "ACSONE SA/NV, "
|
"author": "ACSONE SA/NV, "
|
||||||
"Tecnativa, "
|
"Tecnativa, "
|
||||||
|
|
|
@ -8,10 +8,11 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
:Author: David Goodger (goodger@python.org)
|
: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.
|
:Copyright: This stylesheet has been placed in the public domain.
|
||||||
|
|
||||||
Default cascading style sheet for the HTML output of Docutils.
|
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
|
See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to
|
||||||
customize this style sheet.
|
customize this style sheet.
|
||||||
|
@ -274,7 +275,7 @@ pre.literal-block, pre.doctest-block, pre.math, pre.code {
|
||||||
margin-left: 2em ;
|
margin-left: 2em ;
|
||||||
margin-right: 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, code { background-color: #eeeeee }
|
||||||
pre.code .comment, code .comment { color: #5C6576 }
|
pre.code .comment, code .comment { color: #5C6576 }
|
||||||
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
|
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
|
||||||
|
@ -300,7 +301,7 @@ span.option {
|
||||||
span.pre {
|
span.pre {
|
||||||
white-space: pre }
|
white-space: pre }
|
||||||
|
|
||||||
span.problematic {
|
span.problematic, pre.problematic {
|
||||||
color: red }
|
color: red }
|
||||||
|
|
||||||
span.section-subtitle {
|
span.section-subtitle {
|
||||||
|
@ -366,7 +367,7 @@ ul.auto-toc {
|
||||||
!! This file is generated by oca-gen-addon-readme !!
|
!! This file is generated by oca-gen-addon-readme !!
|
||||||
!! changes will be overwritten. !!
|
!! changes will be overwritten. !!
|
||||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
!! source digest: sha256:c8c5da5c7631fad4d64b447787e487826952622707762815d1166990b565fcd0
|
!! source digest: sha256:bd504d36989179a1e11223c03dbf38ac45f0a792c6ad15a2786c9283bc64650b
|
||||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
||||||
<p><a class="reference external image-reference" 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 image-reference" 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 image-reference" href="https://github.com/OCA/web/tree/16.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 image-reference" href="https://translation.odoo-community.org/projects/web-16-0/web-16-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 image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/web&target_branch=16.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
|
<p><a class="reference external image-reference" 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 image-reference" 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 image-reference" href="https://github.com/OCA/web/tree/16.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 image-reference" href="https://translation.odoo-community.org/projects/web-16-0/web-16-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 image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/web&target_branch=16.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
|
||||||
<p>Define a new view displaying events in an interactive visualization chart.</p>
|
<p>Define a new view displaying events in an interactive visualization chart.</p>
|
||||||
|
@ -614,7 +615,9 @@ If you spotted it first, help us to smash it by providing a detailed and welcome
|
||||||
<div class="section" id="maintainers">
|
<div class="section" id="maintainers">
|
||||||
<h2><a class="toc-backref" href="#toc-entry-8">Maintainers</a></h2>
|
<h2><a class="toc-backref" href="#toc-entry-8">Maintainers</a></h2>
|
||||||
<p>This module is maintained by the OCA.</p>
|
<p>This module is maintained by the OCA.</p>
|
||||||
<a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a>
|
<a class="reference external image-reference" href="https://odoo-community.org">
|
||||||
|
<img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" />
|
||||||
|
</a>
|
||||||
<p>OCA, or the Odoo Community Association, is a nonprofit organization whose
|
<p>OCA, or the Odoo Community Association, is a nonprofit organization whose
|
||||||
mission is to support the collaborative development of Odoo features and
|
mission is to support the collaborative development of Odoo features and
|
||||||
promote its widespread use.</p>
|
promote its widespread use.</p>
|
||||||
|
|
|
@ -41,6 +41,7 @@ odoo.define("web_timeline.TimelineRenderer", function (require) {
|
||||||
this.fields = params.fields;
|
this.fields = params.fields;
|
||||||
|
|
||||||
this.timeline = false;
|
this.timeline = false;
|
||||||
|
this.initial_data_loaded = false;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -48,11 +49,6 @@ odoo.define("web_timeline.TimelineRenderer", function (require) {
|
||||||
*/
|
*/
|
||||||
start: function () {
|
start: function () {
|
||||||
const attrs = this.arch.attrs;
|
const attrs = this.arch.attrs;
|
||||||
this.current_window = {
|
|
||||||
start: new moment(),
|
|
||||||
end: new moment().add(24, "hours"),
|
|
||||||
};
|
|
||||||
|
|
||||||
this.$el.addClass(attrs.class);
|
this.$el.addClass(attrs.class);
|
||||||
this.$timeline = this.$(".oe_timeline_widget");
|
this.$timeline = this.$(".oe_timeline_widget");
|
||||||
|
|
||||||
|
@ -85,7 +81,6 @@ odoo.define("web_timeline.TimelineRenderer", function (require) {
|
||||||
// Prevent Double Rendering on Updates
|
// Prevent Double Rendering on Updates
|
||||||
if (!this.timeline) {
|
if (!this.timeline) {
|
||||||
this.init_timeline();
|
this.init_timeline();
|
||||||
$(window).trigger("resize");
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -96,13 +91,11 @@ odoo.define("web_timeline.TimelineRenderer", function (require) {
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
_onTodayClicked: function () {
|
_onTodayClicked: function () {
|
||||||
this.current_window = {
|
if (this.timeline) {
|
||||||
|
this.timeline.setWindow({
|
||||||
start: new moment(),
|
start: new moment(),
|
||||||
end: new moment().add(24, "hours"),
|
end: new moment().add(24, "hours"),
|
||||||
};
|
});
|
||||||
|
|
||||||
if (this.timeline) {
|
|
||||||
this.timeline.setWindow(this.current_window);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -112,7 +105,7 @@ odoo.define("web_timeline.TimelineRenderer", function (require) {
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
_onScaleDayClicked: function () {
|
_onScaleDayClicked: function () {
|
||||||
this._scaleCurrentWindow(24);
|
this._scaleCurrentWindow(() => 24);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -121,7 +114,7 @@ odoo.define("web_timeline.TimelineRenderer", function (require) {
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
_onScaleWeekClicked: function () {
|
_onScaleWeekClicked: function () {
|
||||||
this._scaleCurrentWindow(24 * 7);
|
this._scaleCurrentWindow(() => 24 * 7);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -130,9 +123,7 @@ odoo.define("web_timeline.TimelineRenderer", function (require) {
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
_onScaleMonthClicked: function () {
|
_onScaleMonthClicked: function () {
|
||||||
this._scaleCurrentWindow(
|
this._scaleCurrentWindow((start) => 24 * moment(start).daysInMonth());
|
||||||
24 * moment(this.current_window.start).daysInMonth()
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -142,24 +133,22 @@ odoo.define("web_timeline.TimelineRenderer", function (require) {
|
||||||
*/
|
*/
|
||||||
_onScaleYearClicked: function () {
|
_onScaleYearClicked: function () {
|
||||||
this._scaleCurrentWindow(
|
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.
|
* 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
|
* @private
|
||||||
*/
|
*/
|
||||||
_scaleCurrentWindow: function (factor) {
|
_scaleCurrentWindow: function (getHoursFromStart) {
|
||||||
if (this.timeline) {
|
if (this.timeline) {
|
||||||
this.current_window = this.timeline.getWindow();
|
const start = this.timeline.getWindow().start;
|
||||||
this.current_window.end = moment(this.current_window.start).add(
|
const end = moment(start).add(getHoursFromStart(start), "hours");
|
||||||
factor,
|
this.timeline.setWindow(start, end);
|
||||||
"hours"
|
|
||||||
);
|
|
||||||
this.timeline.setWindow(this.current_window);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -219,6 +208,7 @@ odoo.define("web_timeline.TimelineRenderer", function (require) {
|
||||||
onUpdate: this.on_update,
|
onUpdate: this.on_update,
|
||||||
onRemove: this.on_remove,
|
onRemove: this.on_remove,
|
||||||
});
|
});
|
||||||
|
this.options.xss = {disabled: true};
|
||||||
this.qweb = new QWeb(session.debug, {_s: session.origin}, false);
|
this.qweb = new QWeb(session.debug, {_s: session.origin}, false);
|
||||||
if (this.arch.children.length) {
|
if (this.arch.children.length) {
|
||||||
const tmpl = utils.json_node_to_xml(
|
const tmpl = utils.json_node_to_xml(
|
||||||
|
@ -227,25 +217,17 @@ odoo.define("web_timeline.TimelineRenderer", function (require) {
|
||||||
this.qweb.add_template(tmpl);
|
this.qweb.add_template(tmpl);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.timeline = new vis.Timeline(
|
this.timeline = new vis.Timeline(this.$timeline.get(0), {}, this.options);
|
||||||
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.on("click", this.on_group_click);
|
this.timeline.on("click", this.on_group_click);
|
||||||
const group_bys = this.arch.attrs.default_group_by.split(",");
|
const group_bys = this.arch.attrs.default_group_by.split(",");
|
||||||
this.last_group_bys = group_bys;
|
this.last_group_bys = group_bys;
|
||||||
this.last_domains = this.modelClass.data.domain;
|
this.last_domains = this.modelClass.data.domain;
|
||||||
this.on_data_loaded(this.modelClass.data.data, group_bys);
|
|
||||||
this.$centerContainer = $(this.timeline.dom.centerContainer);
|
this.$centerContainer = $(this.timeline.dom.centerContainer);
|
||||||
this.canvas = new TimelineCanvas(this);
|
this.canvas = new TimelineCanvas(this);
|
||||||
this.canvas.appendTo(this.$centerContainer);
|
this.canvas.appendTo(this.$centerContainer);
|
||||||
this.timeline.on("changed", () => {
|
this.timeline.on("changed", () => {
|
||||||
this.draw_canvas();
|
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.
|
* Load display_name of records.
|
||||||
*
|
*
|
||||||
|
|
|
@ -86,10 +86,6 @@ odoo.define("web_timeline.TimelineView", function (require) {
|
||||||
const mode = attrs.mode || attrs.default_window || "fit";
|
const mode = attrs.mode || attrs.default_window || "fit";
|
||||||
const min_height = attrs.min_height || 300;
|
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)) {
|
if (!isNullOrUndef(attrs.quick_create_instance)) {
|
||||||
this.quick_create_instance = "instance." + 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.model = this.modelName;
|
||||||
this.rendererParams.view = this;
|
this.rendererParams.view = this;
|
||||||
this.rendererParams.options = this._preapre_vis_timeline_options(attrs);
|
this.rendererParams.options = this._preapre_vis_timeline_options(attrs);
|
||||||
this.rendererParams.current_window = current_window;
|
|
||||||
this.rendererParams.date_start = date_start;
|
this.rendererParams.date_start = date_start;
|
||||||
this.rendererParams.date_stop = date_stop;
|
this.rendererParams.date_stop = date_stop;
|
||||||
this.rendererParams.date_delay = date_delay;
|
this.rendererParams.date_delay = date_delay;
|
||||||
|
|
Loading…
Reference in New Issue