mirror of https://github.com/OCA/web.git
[MIG] web_timeline: Migration to 18.0
parent
d2bca998b0
commit
cf61ce8216
|
@ -17,13 +17,13 @@ Web timeline
|
||||||
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
|
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
|
||||||
:alt: License: AGPL-3
|
:alt: License: AGPL-3
|
||||||
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fweb-lightgray.png?logo=github
|
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fweb-lightgray.png?logo=github
|
||||||
:target: https://github.com/OCA/web/tree/17.0/web_timeline
|
:target: https://github.com/OCA/web/tree/18.0/web_timeline
|
||||||
:alt: OCA/web
|
:alt: OCA/web
|
||||||
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
|
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
|
||||||
:target: https://translation.odoo-community.org/projects/web-17-0/web-17-0-web_timeline
|
:target: https://translation.odoo-community.org/projects/web-18-0/web-18-0-web_timeline
|
||||||
:alt: Translate me on Weblate
|
:alt: Translate me on Weblate
|
||||||
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
|
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
|
||||||
:target: https://runboat.odoo-community.org/builds?repo=OCA/web&target_branch=17.0
|
:target: https://runboat.odoo-community.org/builds?repo=OCA/web&target_branch=18.0
|
||||||
:alt: Try me on Runboat
|
:alt: Try me on Runboat
|
||||||
|
|
||||||
|badge1| |badge2| |badge3| |badge4| |badge5|
|
|badge1| |badge2| |badge3| |badge4| |badge5|
|
||||||
|
@ -202,7 +202,7 @@ More evolved example, from ``project_timeline``:
|
||||||
<record id="project.action_view_task" model="ir.actions.act_window">
|
<record id="project.action_view_task" model="ir.actions.act_window">
|
||||||
<field
|
<field
|
||||||
name="view_mode"
|
name="view_mode"
|
||||||
>kanban,tree,form,calendar,timeline,pivot,graph,activity</field>
|
>kanban,list,form,calendar,timeline,pivot,graph,activity</field>
|
||||||
</record>
|
</record>
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|
||||||
|
@ -264,7 +264,7 @@ Bug Tracker
|
||||||
Bugs are tracked on `GitHub Issues <https://github.com/OCA/web/issues>`_.
|
Bugs are tracked on `GitHub Issues <https://github.com/OCA/web/issues>`_.
|
||||||
In case of trouble, please check there if your issue has already been reported.
|
In case of trouble, please check there if your issue has already been reported.
|
||||||
If you spotted it first, help us to smash it by providing a detailed and welcomed
|
If you spotted it first, help us to smash it by providing a detailed and welcomed
|
||||||
`feedback <https://github.com/OCA/web/issues/new?body=module:%20web_timeline%0Aversion:%2017.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
|
`feedback <https://github.com/OCA/web/issues/new?body=module:%20web_timeline%0Aversion:%2018.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
|
||||||
|
|
||||||
Do not contact contributors directly about support or help with technical issues.
|
Do not contact contributors directly about support or help with technical issues.
|
||||||
|
|
||||||
|
@ -327,6 +327,6 @@ Current `maintainer <https://odoo-community.org/page/maintainer-role>`__:
|
||||||
|
|
||||||
|maintainer-tarteo|
|
|maintainer-tarteo|
|
||||||
|
|
||||||
This module is part of the `OCA/web <https://github.com/OCA/web/tree/17.0/web_timeline>`_ project on GitHub.
|
This module is part of the `OCA/web <https://github.com/OCA/web/tree/18.0/web_timeline>`_ project on GitHub.
|
||||||
|
|
||||||
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
|
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
|
||||||
|
|
|
@ -5,7 +5,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": "17.0.1.0.1",
|
"version": "18.0.1.0.0",
|
||||||
"development_status": "Production/Stable",
|
"development_status": "Production/Stable",
|
||||||
"author": "ACSONE SA/NV, "
|
"author": "ACSONE SA/NV, "
|
||||||
"Tecnativa, "
|
"Tecnativa, "
|
||||||
|
@ -34,7 +34,6 @@
|
||||||
"web_timeline/static/src/views/timeline/timeline_controller.xml",
|
"web_timeline/static/src/views/timeline/timeline_controller.xml",
|
||||||
"web_timeline/static/src/views/timeline/timeline_model.esm.js",
|
"web_timeline/static/src/views/timeline/timeline_model.esm.js",
|
||||||
"web_timeline/static/src/views/timeline/timeline_canvas.esm.js",
|
"web_timeline/static/src/views/timeline/timeline_canvas.esm.js",
|
||||||
"web_timeline/static/src/views/timeline/timeline_view.xml",
|
|
||||||
],
|
],
|
||||||
"web_timeline.vis-timeline_lib": [
|
"web_timeline.vis-timeline_lib": [
|
||||||
"/web_timeline/static/lib/vis-timeline/vis-timeline-graph2d.js",
|
"/web_timeline/static/lib/vis-timeline/vis-timeline-graph2d.js",
|
||||||
|
|
|
@ -9,6 +9,6 @@
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
<record id="base.ir_cron_act" model="ir.actions.act_window">
|
<record id="base.ir_cron_act" model="ir.actions.act_window">
|
||||||
<field name="view_mode">tree,form,calendar,timeline</field>
|
<field name="view_mode">list,form,calendar,timeline</field>
|
||||||
</record>
|
</record>
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|
|
@ -14,3 +14,6 @@ class IrUIView(models.Model):
|
||||||
|
|
||||||
def _is_qweb_based_view(self, view_type):
|
def _is_qweb_based_view(self, view_type):
|
||||||
return view_type == TIMELINE_VIEW[0] or super()._is_qweb_based_view(view_type)
|
return view_type == TIMELINE_VIEW[0] or super()._is_qweb_based_view(view_type)
|
||||||
|
|
||||||
|
def _get_view_info(self):
|
||||||
|
return {"timeline": {"icon": "fa fa-tasks"}} | super()._get_view_info()
|
||||||
|
|
|
@ -85,7 +85,7 @@ More evolved example, from `project_timeline`:
|
||||||
<record id="project.action_view_task" model="ir.actions.act_window">
|
<record id="project.action_view_task" model="ir.actions.act_window">
|
||||||
<field
|
<field
|
||||||
name="view_mode"
|
name="view_mode"
|
||||||
>kanban,tree,form,calendar,timeline,pivot,graph,activity</field>
|
>kanban,list,form,calendar,timeline,pivot,graph,activity</field>
|
||||||
</record>
|
</record>
|
||||||
</odoo>
|
</odoo>
|
||||||
```
|
```
|
||||||
|
|
|
@ -369,7 +369,7 @@ ul.auto-toc {
|
||||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
!! source digest: sha256:2fb5b8c01ee5f36a21f88358b673738a05282e9cf75f10aa33d38565ecfac956
|
!! source digest: sha256:2fb5b8c01ee5f36a21f88358b673738a05282e9cf75f10aa33d38565ecfac956
|
||||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
||||||
<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/17.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-17-0/web-17-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=17.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/18.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-18-0/web-18-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=18.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
|
<p>Define a new view displaying events in an interactive visualization
|
||||||
chart.</p>
|
chart.</p>
|
||||||
<p>The widget is based on the external library
|
<p>The widget is based on the external library
|
||||||
|
@ -579,7 +579,7 @@ view example added onto cron tasks.</p>
|
||||||
</span><span class="nt"><record</span><span class="w"> </span><span class="na">id=</span><span class="s">"project.action_view_task"</span><span class="w"> </span><span class="na">model=</span><span class="s">"ir.actions.act_window"</span><span class="nt">></span><span class="w">
|
</span><span class="nt"><record</span><span class="w"> </span><span class="na">id=</span><span class="s">"project.action_view_task"</span><span class="w"> </span><span class="na">model=</span><span class="s">"ir.actions.act_window"</span><span class="nt">></span><span class="w">
|
||||||
</span><span class="nt"><field</span><span class="w">
|
</span><span class="nt"><field</span><span class="w">
|
||||||
</span><span class="na">name=</span><span class="s">"view_mode"</span><span class="w">
|
</span><span class="na">name=</span><span class="s">"view_mode"</span><span class="w">
|
||||||
</span><span class="nt">></span>kanban,tree,form,calendar,timeline,pivot,graph,activity<span class="nt"></field></span><span class="w">
|
</span><span class="nt">></span>kanban,list,form,calendar,timeline,pivot,graph,activity<span class="nt"></field></span><span class="w">
|
||||||
</span><span class="nt"></record></span><span class="w">
|
</span><span class="nt"></record></span><span class="w">
|
||||||
</span><span class="nt"></odoo></span>
|
</span><span class="nt"></odoo></span>
|
||||||
</pre>
|
</pre>
|
||||||
|
@ -636,7 +636,7 @@ not open that item.</li>
|
||||||
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/web/issues">GitHub Issues</a>.
|
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/web/issues">GitHub Issues</a>.
|
||||||
In case of trouble, please check there if your issue has already been reported.
|
In case of trouble, please check there if your issue has already been reported.
|
||||||
If you spotted it first, help us to smash it by providing a detailed and welcomed
|
If you spotted it first, help us to smash it by providing a detailed and welcomed
|
||||||
<a class="reference external" href="https://github.com/OCA/web/issues/new?body=module:%20web_timeline%0Aversion:%2017.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
|
<a class="reference external" href="https://github.com/OCA/web/issues/new?body=module:%20web_timeline%0Aversion:%2018.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
|
||||||
<p>Do not contact contributors directly about support or help with technical issues.</p>
|
<p>Do not contact contributors directly about support or help with technical issues.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="section" id="credits">
|
<div class="section" id="credits">
|
||||||
|
@ -690,7 +690,7 @@ mission is to support the collaborative development of Odoo features and
|
||||||
promote its widespread use.</p>
|
promote its widespread use.</p>
|
||||||
<p>Current <a class="reference external" href="https://odoo-community.org/page/maintainer-role">maintainer</a>:</p>
|
<p>Current <a class="reference external" href="https://odoo-community.org/page/maintainer-role">maintainer</a>:</p>
|
||||||
<p><a class="reference external image-reference" href="https://github.com/tarteo"><img alt="tarteo" src="https://github.com/tarteo.png?size=40px" /></a></p>
|
<p><a class="reference external image-reference" href="https://github.com/tarteo"><img alt="tarteo" src="https://github.com/tarteo.png?size=40px" /></a></p>
|
||||||
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/web/tree/17.0/web_timeline">OCA/web</a> project on GitHub.</p>
|
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/web/tree/18.0/web_timeline">OCA/web</a> project on GitHub.</p>
|
||||||
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
|
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
/** @odoo-module **/
|
|
||||||
/**
|
/**
|
||||||
* Copyright 2024 Tecnativa - Carlos López
|
* Copyright 2024 Tecnativa - Carlos López
|
||||||
* License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
* License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||||
*/
|
*/
|
||||||
import {_t} from "@web/core/l10n/translation";
|
import {_t} from "@web/core/l10n/translation";
|
||||||
import {archParseBoolean} from "@web/views/utils";
|
import {exprToBoolean} from "@web/core/utils/strings";
|
||||||
import {parseExpr} from "@web/core/py_js/py";
|
import {parseExpr} from "@web/core/py_js/py";
|
||||||
import {visitXML} from "@web/core/utils/xml";
|
import {visitXML} from "@web/core/utils/xml";
|
||||||
|
|
||||||
|
@ -71,7 +70,7 @@ export class TimelineArchParser {
|
||||||
node.getAttribute("dependency_arrow");
|
node.getAttribute("dependency_arrow");
|
||||||
}
|
}
|
||||||
if (node.hasAttribute("stack")) {
|
if (node.hasAttribute("stack")) {
|
||||||
archInfo.options.stack = archParseBoolean(
|
archInfo.options.stack = exprToBoolean(
|
||||||
node.getAttribute("stack"),
|
node.getAttribute("stack"),
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
|
@ -97,24 +96,24 @@ export class TimelineArchParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (node.hasAttribute("event_open_popup")) {
|
if (node.hasAttribute("event_open_popup")) {
|
||||||
archInfo.open_popup_action = archParseBoolean(
|
archInfo.open_popup_action = exprToBoolean(
|
||||||
node.getAttribute("event_open_popup")
|
node.getAttribute("event_open_popup")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (node.hasAttribute("create")) {
|
if (node.hasAttribute("create")) {
|
||||||
archInfo.canCreate = archParseBoolean(
|
archInfo.canCreate = exprToBoolean(
|
||||||
node.getAttribute("create"),
|
node.getAttribute("create"),
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (node.hasAttribute("edit")) {
|
if (node.hasAttribute("edit")) {
|
||||||
archInfo.canUpdate = archParseBoolean(
|
archInfo.canUpdate = exprToBoolean(
|
||||||
node.getAttribute("edit"),
|
node.getAttribute("edit"),
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (node.hasAttribute("delete")) {
|
if (node.hasAttribute("delete")) {
|
||||||
archInfo.canDelete = archParseBoolean(
|
archInfo.canDelete = exprToBoolean(
|
||||||
node.getAttribute("delete"),
|
node.getAttribute("delete"),
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
/** @odoo-module **/
|
|
||||||
/* Copyright 2018 Onestein
|
/* Copyright 2018 Onestein
|
||||||
Copyright 2024 Tecnativa - Carlos López
|
Copyright 2024 Tecnativa - Carlos López
|
||||||
* License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). */
|
* License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). */
|
||||||
|
@ -15,7 +14,16 @@ export class TimelineCanvas {
|
||||||
* Clears all drawings (svg elements) from the canvas.
|
* Clears all drawings (svg elements) from the canvas.
|
||||||
*/
|
*/
|
||||||
clear() {
|
clear() {
|
||||||
$(this.canvas_ref).find(" > :not(defs)").remove();
|
if (this.canvas_ref) {
|
||||||
|
const tempElement = document.createElement("div");
|
||||||
|
tempElement.innerHTML = this.canvas_ref;
|
||||||
|
Array.from(tempElement.children).forEach((child) => {
|
||||||
|
if (child.tagName.toLowerCase() !== "defs") {
|
||||||
|
child.remove();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.canvas_ref = tempElement.innerHTML;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -107,24 +115,34 @@ export class TimelineCanvas {
|
||||||
* @param {Number} breakLineAt The space between the line turns
|
* @param {Number} breakLineAt The space between the line turns
|
||||||
* @returns {HTMLElement} The created SVG polyline
|
* @returns {HTMLElement} The created SVG polyline
|
||||||
*/
|
*/
|
||||||
draw_line(from, to, color, width, markerStart, widthMarker, breakLineAt) {
|
draw_line(
|
||||||
const $from = $(from);
|
from,
|
||||||
const childPosFrom = $from.offset();
|
to,
|
||||||
const parentPosFrom = $from.closest(".vis-center").offset();
|
color = "#000",
|
||||||
|
width = 1,
|
||||||
|
markerStart,
|
||||||
|
widthMarker,
|
||||||
|
breakLineAt
|
||||||
|
) {
|
||||||
|
const fromElement =
|
||||||
|
typeof from === "string" ? document.querySelector(from) : from;
|
||||||
|
const toElement = typeof to === "string" ? document.querySelector(to) : to;
|
||||||
|
if (!fromElement || !toElement) return;
|
||||||
|
const childPosFrom = fromElement.getBoundingClientRect();
|
||||||
|
const parentFrom = fromElement.closest(".vis-center")?.getBoundingClientRect();
|
||||||
const rectFrom = {
|
const rectFrom = {
|
||||||
x: childPosFrom.left - parentPosFrom.left,
|
x: childPosFrom.left - (parentFrom?.left || 0),
|
||||||
y: childPosFrom.top - parentPosFrom.top,
|
y: childPosFrom.top - (parentFrom?.top || 0),
|
||||||
w: $from.width(),
|
w: fromElement.offsetWidth,
|
||||||
h: $from.height(),
|
h: fromElement.offsetHeight,
|
||||||
};
|
};
|
||||||
const $to = $(to);
|
const childPosTo = toElement.getBoundingClientRect();
|
||||||
const childPosTo = $to.offset();
|
const parentTo = toElement.closest(".vis-center")?.getBoundingClientRect();
|
||||||
const parentPosTo = $to.closest(".vis-center").offset();
|
|
||||||
const rectTo = {
|
const rectTo = {
|
||||||
x: childPosTo.left - parentPosTo.left,
|
x: childPosTo.left - (parentTo?.left || 0),
|
||||||
y: childPosTo.top - parentPosTo.top,
|
y: childPosTo.top - (parentTo?.top || 0),
|
||||||
w: $to.width(),
|
w: toElement.offsetWidth,
|
||||||
h: $to.height(),
|
h: toElement.offsetHeight,
|
||||||
};
|
};
|
||||||
const points = this.get_polyline_points(
|
const points = this.get_polyline_points(
|
||||||
rectFrom,
|
rectFrom,
|
||||||
|
@ -134,13 +152,15 @@ export class TimelineCanvas {
|
||||||
);
|
);
|
||||||
const line = document.createElementNS("http://www.w3.org/2000/svg", "polyline");
|
const line = document.createElementNS("http://www.w3.org/2000/svg", "polyline");
|
||||||
line.setAttribute("points", points.flat().join(","));
|
line.setAttribute("points", points.flat().join(","));
|
||||||
line.setAttribute("stroke", color || "#000");
|
line.setAttribute("stroke", color);
|
||||||
line.setAttribute("stroke-width", width || 1);
|
line.setAttribute("stroke-width", width);
|
||||||
line.setAttribute("fill", "none");
|
line.setAttribute("fill", "none");
|
||||||
if (markerStart) {
|
if (markerStart) {
|
||||||
line.setAttribute("marker-start", "url(" + markerStart + ")");
|
line.setAttribute("marker-start", `url(${markerStart})`);
|
||||||
|
}
|
||||||
|
if (this.canvas_ref instanceof HTMLElement) {
|
||||||
|
this.canvas_ref.appendChild(line);
|
||||||
}
|
}
|
||||||
this.canvas_ref.append(line);
|
|
||||||
return line;
|
return line;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,12 +16,10 @@ import {useDebounced} from "@web/core/utils/timing";
|
||||||
import {useModel} from "@web/model/model";
|
import {useModel} from "@web/model/model";
|
||||||
import {useSearchBarToggler} from "@web/search/search_bar/search_bar_toggler";
|
import {useSearchBarToggler} from "@web/search/search_bar/search_bar_toggler";
|
||||||
import {useService} from "@web/core/utils/hooks";
|
import {useService} from "@web/core/utils/hooks";
|
||||||
import {useSetupView} from "@web/views/view_hook";
|
import {useSetupAction} from "@web/search/action_hook";
|
||||||
|
|
||||||
const {DateTime} = luxon;
|
const {DateTime} = luxon;
|
||||||
|
|
||||||
// Import time from "web.time";
|
|
||||||
|
|
||||||
export class TimelineController extends Component {
|
export class TimelineController extends Component {
|
||||||
/**
|
/**
|
||||||
* @override
|
* @override
|
||||||
|
@ -29,7 +27,7 @@ export class TimelineController extends Component {
|
||||||
setup() {
|
setup() {
|
||||||
this.rootRef = useRef("root");
|
this.rootRef = useRef("root");
|
||||||
this.model = useModel(this.props.Model, this.props.modelParams);
|
this.model = useModel(this.props.Model, this.props.modelParams);
|
||||||
useSetupView({rootRef: useRef("root")});
|
useSetupAction({rootRef: useRef("root")});
|
||||||
this.searchBarToggler = useSearchBarToggler();
|
this.searchBarToggler = useSearchBarToggler();
|
||||||
this.date_start = this.props.modelParams.date_start;
|
this.date_start = this.props.modelParams.date_start;
|
||||||
this.date_stop = this.props.modelParams.date_stop;
|
this.date_stop = this.props.modelParams.date_stop;
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
/** @odoo-module **/
|
|
||||||
/**
|
/**
|
||||||
* Copyright 2024 Tecnativa - Carlos López
|
* Copyright 2024 Tecnativa - Carlos López
|
||||||
* License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
* License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
/** @odoo-module **/
|
|
||||||
/* global vis */
|
/* global vis */
|
||||||
/**
|
/**
|
||||||
* Copyright 2024 Tecnativa - Carlos López
|
* Copyright 2024 Tecnativa - Carlos López
|
||||||
|
@ -35,7 +34,7 @@ export class TimelineRenderer extends Component {
|
||||||
this.fields = this.params.fields;
|
this.fields = this.params.fields;
|
||||||
this.timeline = false;
|
this.timeline = false;
|
||||||
this.initial_data_loaded = false;
|
this.initial_data_loaded = false;
|
||||||
this.canvas_ref = $(renderToString("TimelineView.Canvas", {}));
|
this.canvas_ref = renderToString("TimelineView.Canvas", {});
|
||||||
onWillUpdateProps(async (props) => {
|
onWillUpdateProps(async (props) => {
|
||||||
this.on_data_loaded(props.model.data);
|
this.on_data_loaded(props.model.data);
|
||||||
});
|
});
|
||||||
|
@ -55,16 +54,23 @@ export class TimelineRenderer extends Component {
|
||||||
* Triggered when the timeline is attached to the DOM.
|
* Triggered when the timeline is attached to the DOM.
|
||||||
*/
|
*/
|
||||||
on_attach_callback() {
|
on_attach_callback() {
|
||||||
const $root = $(this.rootRef.el);
|
const $root = this.rootRef.el;
|
||||||
$root.addClass(this.params.class);
|
if (this.params.class) {
|
||||||
const height =
|
$root.classList.add(this.params.class);
|
||||||
$root.parent().height() - $root.find(".oe_timeline_buttons").height();
|
}
|
||||||
|
if (this.rootRef.el) {
|
||||||
|
const parentHeight = this.rootRef.el.parentElement?.clientHeight || 0;
|
||||||
|
const buttonHeight =
|
||||||
|
this.rootRef.el.querySelector(".oe_timeline_buttons")?.clientHeight ||
|
||||||
|
0;
|
||||||
|
const height = parentHeight - buttonHeight;
|
||||||
if (height > this.min_height && this.timeline) {
|
if (height > this.min_height && this.timeline) {
|
||||||
this.timeline.setOptions({
|
this.timeline.setOptions({
|
||||||
height: height,
|
height: height,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Set the timeline window to today (day).
|
* Set the timeline window to today (day).
|
||||||
*
|
*
|
||||||
|
@ -202,9 +208,11 @@ export class TimelineRenderer extends Component {
|
||||||
// In read-only mode, catch double-clicks this way.
|
// In read-only mode, catch double-clicks this way.
|
||||||
this.timeline.on("doubleClick", this.on_timeline_double_click.bind(this));
|
this.timeline.on("doubleClick", this.on_timeline_double_click.bind(this));
|
||||||
}
|
}
|
||||||
this.$centerContainer = $(this.timeline.dom.centerContainer);
|
this.$centerContainer = this.timeline.dom.centerContainer;
|
||||||
this.canvas = new TimelineCanvas(this.canvas_ref);
|
this.canvas = new TimelineCanvas(this.canvas_ref);
|
||||||
this.canvas_ref.appendTo(this.$centerContainer);
|
if (this.$centerContainer.el) {
|
||||||
|
this.$centerContainer.el.appendChild(this.canvas_ref);
|
||||||
|
}
|
||||||
this.timeline.on("changed", () => {
|
this.timeline.on("changed", () => {
|
||||||
this.draw_canvas();
|
this.draw_canvas();
|
||||||
this.load_initial_data();
|
this.load_initial_data();
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
/** @odoo-module **/
|
|
||||||
/* Odoo web_timeline
|
/* Odoo web_timeline
|
||||||
* Copyright 2015 ACSONE SA/NV
|
* Copyright 2015 ACSONE SA/NV
|
||||||
* Copyright 2016 Pedro M. Baeza <pedro.baeza@tecnativa.com>
|
* Copyright 2016 Pedro M. Baeza <pedro.baeza@tecnativa.com>
|
||||||
|
@ -10,13 +9,13 @@ import {TimelineArchParser} from "./timeline_arch_parser.esm";
|
||||||
import {TimelineController} from "./timeline_controller.esm";
|
import {TimelineController} from "./timeline_controller.esm";
|
||||||
import {TimelineModel} from "./timeline_model.esm";
|
import {TimelineModel} from "./timeline_model.esm";
|
||||||
import {TimelineRenderer} from "./timeline_renderer.esm";
|
import {TimelineRenderer} from "./timeline_renderer.esm";
|
||||||
import {_lt} from "@web/core/l10n/translation";
|
import {_t} from "@web/core/l10n/translation";
|
||||||
import {registry} from "@web/core/registry";
|
import {registry} from "@web/core/registry";
|
||||||
|
|
||||||
const viewRegistry = registry.category("views");
|
const viewRegistry = registry.category("views");
|
||||||
|
|
||||||
export const TimelineView = {
|
export const TimelineView = {
|
||||||
display_name: _lt("Timeline"),
|
display_name: _t("Timeline"),
|
||||||
icon: "fa fa-tasks",
|
icon: "fa fa-tasks",
|
||||||
multiRecord: true,
|
multiRecord: true,
|
||||||
ArchParser: TimelineArchParser,
|
ArchParser: TimelineArchParser,
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
/** @odoo-module **/
|
|
||||||
|
|
||||||
export const FAKE_ORDER_FIELDS = {
|
export const FAKE_ORDER_FIELDS = {
|
||||||
display_name: {string: "Display Name", type: "char"},
|
display_name: {string: "Display Name", type: "char"},
|
||||||
date_start: {string: "Date start", type: "date"},
|
date_start: {string: "Date start", type: "date"},
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
/** @odoo-module **/
|
|
||||||
import {
|
import {
|
||||||
TimelineArchParser,
|
TimelineArchParser,
|
||||||
TimelineParseArchError,
|
TimelineParseArchError,
|
||||||
|
@ -17,23 +16,23 @@ function check(assert, paramName, paramValue, expectedName, expectedValue) {
|
||||||
const data = parseArch(arch);
|
const data = parseArch(arch);
|
||||||
assert.strictEqual(data[expectedName], expectedValue);
|
assert.strictEqual(data[expectedName], expectedValue);
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line no-undef
|
|
||||||
QUnit.module("TimelineView - ArchParser");
|
QUnit.module("TimelineView - ArchParser");
|
||||||
// eslint-disable-next-line no-undef
|
|
||||||
QUnit.test("throw if date_start is not set", (assert) => {
|
QUnit.test("throw if date_start is not set", (assert) => {
|
||||||
assert.throws(
|
assert.throws(
|
||||||
() => parseArch(`<timeline default_group_by="partner_id"/>`),
|
() => parseArch(`<timeline default_group_by="partner_id"/>`),
|
||||||
TimelineParseArchError
|
TimelineParseArchError
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
// eslint-disable-next-line no-undef
|
|
||||||
QUnit.test("throw if default_group_by is not set", (assert) => {
|
QUnit.test("throw if default_group_by is not set", (assert) => {
|
||||||
assert.throws(
|
assert.throws(
|
||||||
() => parseArch(`<timeline date_start="date_start"/>`),
|
() => parseArch(`<timeline date_start="date_start"/>`),
|
||||||
TimelineParseArchError
|
TimelineParseArchError
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
// eslint-disable-next-line no-undef
|
|
||||||
QUnit.test("hasEditDialog", (assert) => {
|
QUnit.test("hasEditDialog", (assert) => {
|
||||||
check(assert, "event_open_popup", "", "open_popup_action", false);
|
check(assert, "event_open_popup", "", "open_popup_action", false);
|
||||||
check(assert, "event_open_popup", "true", "open_popup_action", true);
|
check(assert, "event_open_popup", "true", "open_popup_action", true);
|
||||||
|
@ -43,7 +42,7 @@ QUnit.test("hasEditDialog", (assert) => {
|
||||||
check(assert, "event_open_popup", "False", "open_popup_action", false);
|
check(assert, "event_open_popup", "False", "open_popup_action", false);
|
||||||
check(assert, "event_open_popup", "0", "open_popup_action", false);
|
check(assert, "event_open_popup", "0", "open_popup_action", false);
|
||||||
});
|
});
|
||||||
// eslint-disable-next-line no-undef
|
|
||||||
QUnit.test("create", (assert) => {
|
QUnit.test("create", (assert) => {
|
||||||
check(assert, "create", "", "canCreate", true);
|
check(assert, "create", "", "canCreate", true);
|
||||||
check(assert, "create", "true", "canCreate", true);
|
check(assert, "create", "true", "canCreate", true);
|
||||||
|
@ -54,7 +53,7 @@ QUnit.test("create", (assert) => {
|
||||||
check(assert, "create", "0", "canCreate", false);
|
check(assert, "create", "0", "canCreate", false);
|
||||||
check(assert, "create", "12", "canCreate", true);
|
check(assert, "create", "12", "canCreate", true);
|
||||||
});
|
});
|
||||||
// eslint-disable-next-line no-undef
|
|
||||||
QUnit.test("edit", (assert) => {
|
QUnit.test("edit", (assert) => {
|
||||||
check(assert, "edit", "", "canUpdate", true);
|
check(assert, "edit", "", "canUpdate", true);
|
||||||
check(assert, "edit", "true", "canUpdate", true);
|
check(assert, "edit", "true", "canUpdate", true);
|
||||||
|
@ -66,7 +65,6 @@ QUnit.test("edit", (assert) => {
|
||||||
check(assert, "edit", "12", "canUpdate", true);
|
check(assert, "edit", "12", "canUpdate", true);
|
||||||
});
|
});
|
||||||
|
|
||||||
// eslint-disable-next-line no-undef
|
|
||||||
QUnit.test("delete", (assert) => {
|
QUnit.test("delete", (assert) => {
|
||||||
check(assert, "delete", "", "canDelete", true);
|
check(assert, "delete", "", "canDelete", true);
|
||||||
check(assert, "delete", "true", "canDelete", true);
|
check(assert, "delete", "true", "canDelete", true);
|
||||||
|
@ -77,7 +75,7 @@ QUnit.test("delete", (assert) => {
|
||||||
check(assert, "delete", "0", "canDelete", false);
|
check(assert, "delete", "0", "canDelete", false);
|
||||||
check(assert, "delete", "12", "canDelete", true);
|
check(assert, "delete", "12", "canDelete", true);
|
||||||
});
|
});
|
||||||
// eslint-disable-next-line no-undef
|
|
||||||
QUnit.test("mode", (assert) => {
|
QUnit.test("mode", (assert) => {
|
||||||
check(assert, "mode", "day", "mode", "day");
|
check(assert, "mode", "day", "mode", "day");
|
||||||
check(assert, "mode", "week", "mode", "week");
|
check(assert, "mode", "week", "mode", "week");
|
||||||
|
@ -94,7 +92,7 @@ QUnit.test("mode", (assert) => {
|
||||||
);
|
);
|
||||||
}, TimelineParseArchError);
|
}, TimelineParseArchError);
|
||||||
});
|
});
|
||||||
// eslint-disable-next-line no-undef
|
|
||||||
QUnit.test("colors", (assert) => {
|
QUnit.test("colors", (assert) => {
|
||||||
const archInfo = parseArch(`
|
const archInfo = parseArch(`
|
||||||
<timeline date_start="start_date" default_group_by="partner_id" colors="gray: state == 'cancel'; #ec7063: state == 'done'"/>
|
<timeline date_start="start_date" default_group_by="partner_id" colors="gray: state == 'cancel'; #ec7063: state == 'done'"/>
|
||||||
|
@ -118,7 +116,7 @@ QUnit.test("colors", (assert) => {
|
||||||
"fieldNames should include field state"
|
"fieldNames should include field state"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
// eslint-disable-next-line no-undef
|
|
||||||
QUnit.test("templates", (assert) => {
|
QUnit.test("templates", (assert) => {
|
||||||
const archInfo = parseArch(`
|
const archInfo = parseArch(`
|
||||||
<timeline date_start="start_date" default_group_by="partner_id">
|
<timeline date_start="start_date" default_group_by="partner_id">
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
/** @odoo-module **/
|
|
||||||
import {click, getFixture} from "@web/../tests/helpers/utils";
|
import {click, getFixture} from "@web/../tests/helpers/utils";
|
||||||
import {makeView, setupViewRegistries} from "@web/../tests/views/helpers";
|
import {makeView, setupViewRegistries} from "@web/../tests/views/helpers";
|
||||||
import {FAKE_ORDER_FIELDS} from "./helpers.esm";
|
import {FAKE_ORDER_FIELDS} from "./helpers.esm";
|
||||||
|
@ -6,7 +5,7 @@ import {loadBundle} from "@web/core/assets";
|
||||||
|
|
||||||
let serverData = {};
|
let serverData = {};
|
||||||
let target = null;
|
let target = null;
|
||||||
// eslint-disable-next-line no-undef
|
|
||||||
QUnit.module("Views", (hooks) => {
|
QUnit.module("Views", (hooks) => {
|
||||||
loadBundle("web_timeline.vis-timeline_lib");
|
loadBundle("web_timeline.vis-timeline_lib");
|
||||||
hooks.beforeEach(async () => {
|
hooks.beforeEach(async () => {
|
||||||
|
@ -65,9 +64,9 @@ QUnit.module("Views", (hooks) => {
|
||||||
setupViewRegistries();
|
setupViewRegistries();
|
||||||
target = getFixture();
|
target = getFixture();
|
||||||
});
|
});
|
||||||
// eslint-disable-next-line no-undef
|
|
||||||
QUnit.module("TimelineView - View");
|
QUnit.module("TimelineView - View");
|
||||||
// eslint-disable-next-line no-undef
|
|
||||||
QUnit.test("Test basic timeline view", async (assert) => {
|
QUnit.test("Test basic timeline view", async (assert) => {
|
||||||
await makeView({
|
await makeView({
|
||||||
type: "timeline",
|
type: "timeline",
|
||||||
|
@ -77,7 +76,7 @@ QUnit.module("Views", (hooks) => {
|
||||||
});
|
});
|
||||||
assert.containsOnce(target, ".oe_timeline_view");
|
assert.containsOnce(target, ".oe_timeline_view");
|
||||||
});
|
});
|
||||||
// eslint-disable-next-line no-undef
|
|
||||||
QUnit.test("click today slot", async (assert) => {
|
QUnit.test("click today slot", async (assert) => {
|
||||||
await makeView({
|
await makeView({
|
||||||
type: "timeline",
|
type: "timeline",
|
||||||
|
@ -117,7 +116,7 @@ QUnit.module("Views", (hooks) => {
|
||||||
"year should no have classnames btn-primary"
|
"year should no have classnames btn-primary"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
// eslint-disable-next-line no-undef
|
|
||||||
QUnit.test("click month slot", async (assert) => {
|
QUnit.test("click month slot", async (assert) => {
|
||||||
await makeView({
|
await makeView({
|
||||||
type: "timeline",
|
type: "timeline",
|
||||||
|
@ -157,7 +156,7 @@ QUnit.module("Views", (hooks) => {
|
||||||
"year should no have classnames btn-primary"
|
"year should no have classnames btn-primary"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
// eslint-disable-next-line no-undef
|
|
||||||
QUnit.test("Check button delete", async (assert) => {
|
QUnit.test("Check button delete", async (assert) => {
|
||||||
await makeView({
|
await makeView({
|
||||||
type: "timeline",
|
type: "timeline",
|
||||||
|
@ -174,7 +173,7 @@ QUnit.module("Views", (hooks) => {
|
||||||
await click($item_content);
|
await click($item_content);
|
||||||
assert.containsOnce($item_content.parentElement, ".vis-delete");
|
assert.containsOnce($item_content.parentElement, ".vis-delete");
|
||||||
});
|
});
|
||||||
// eslint-disable-next-line no-undef
|
|
||||||
QUnit.test("Check button delete disabled", async (assert) => {
|
QUnit.test("Check button delete disabled", async (assert) => {
|
||||||
await makeView({
|
await makeView({
|
||||||
type: "timeline",
|
type: "timeline",
|
||||||
|
|
|
@ -8,16 +8,18 @@ from odoo.tests.common import HttpCase
|
||||||
class TestWebTimeline(HttpCase):
|
class TestWebTimeline(HttpCase):
|
||||||
def test_timeline_arch(self):
|
def test_timeline_arch(self):
|
||||||
self.browser_js(
|
self.browser_js(
|
||||||
"/web/tests?filter=TimelineView - ArchParser",
|
"/web/tests/legacy?mod=web&filter=TimelineView - ArchParser",
|
||||||
"",
|
"",
|
||||||
login="admin",
|
login="admin",
|
||||||
timeout=1800,
|
timeout=1800,
|
||||||
|
success_signal="QUnit test suite done.",
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_timeline_view(self):
|
def test_timeline_view(self):
|
||||||
self.browser_js(
|
self.browser_js(
|
||||||
"/web/tests?filter=TimelineView - View",
|
"/web/tests/legacy?mod=web&filter=TimelineView - View",
|
||||||
"",
|
"",
|
||||||
login="admin",
|
login="admin",
|
||||||
timeout=1800,
|
timeout=1800,
|
||||||
|
success_signal="QUnit test suite done.",
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in New Issue