summaryrefslogtreecommitdiff
path: root/addons
diff options
context:
space:
mode:
authorAaron Bohy <aab@odoo.com>2020-12-18 10:52:33 +0000
committerAaron Bohy <aab@odoo.com>2020-12-18 13:39:48 +0000
commit47a74f2aaf54bddf51a828c4b5a76c392944bcd5 (patch)
treeeaf6dcb77fc2f04ba8710f0534a8d3e398ba2e26 /addons
parenteb5398cac2bcf671ccadf99b129e661faffa92d7 (diff)
[FIX] website: dashboard: mounted called twice
Before this commit, the 'mounted' method of the ControlPanel in the website dashboard was called twice, when entering the dashboard. It happened because the dashboard updated the ControlPanel before being actually mounted, so mounted was called once when the dashboard was mounted, and once when the update was applied. Ideally, this should not be an issue (this isn't an issue with owl). However, in Odoo, we mix layers of Owl Components and legacy widgets. In these situations, the above scenario isn't properly handled (and can't be). As a consequence, in mobile (enterprise), it crashed because an handler bound in mounted (thus twice) was only unbound once. This commit avoids the issue by correctly setting the control panel props before rendering it (the update was actually useless). opw~2417307 closes odoo/odoo#63574 Signed-off-by: Géry Debongnie (ged) <ged@openerp.com>
Diffstat (limited to 'addons')
-rw-r--r--addons/website/static/src/js/backend/dashboard.js46
-rw-r--r--addons/website/static/tests/dashboard_tests.js67
-rw-r--r--addons/website/views/assets.xml1
3 files changed, 88 insertions, 26 deletions
diff --git a/addons/website/static/src/js/backend/dashboard.js b/addons/website/static/src/js/backend/dashboard.js
index 7b37557987c..d9daa81b45a 100644
--- a/addons/website/static/src/js/backend/dashboard.js
+++ b/addons/website/static/src/js/backend/dashboard.js
@@ -66,8 +66,8 @@ var Dashboard = AbstractAction.extend({
start: function() {
var self = this;
+ this._computeControlPanelProps();
return this._super().then(function() {
- self.update_cp();
self.render_graphs();
});
},
@@ -344,7 +344,6 @@ var Dashboard = AbstractAction.extend({
on_reverse_breadcrumb: function() {
var self = this;
web_client.do_push_state({});
- this.update_cp();
this.fetch_data().then(function() {
self.$('.o_website_dashboard').empty();
self.render_dashboards();
@@ -393,33 +392,28 @@ var Dashboard = AbstractAction.extend({
});
},
- update_cp: function() {
- var self = this;
- if (!this.$searchview) {
- this.$searchview = $(QWeb.render("website.DateRangeButtons", {
- widget: this,
- }));
- this.$searchview.find('button.js_date_range').click(function(ev) {
- self.$searchview.find('button.js_date_range.active').removeClass('active');
- $(ev.target).addClass('active');
- self.on_date_range_button($(ev.target).data('date'));
- });
- this.$searchview.find('button.js_website').click(function(ev) {
- self.$searchview.find('button.js_website.active').removeClass('active');
- $(ev.target).addClass('active');
- self.on_website_button($(ev.target).data('website-id'));
- });
- }
+ /**
+ * @private
+ */
+ _computeControlPanelProps() {
+ const $searchview = $(QWeb.render("website.DateRangeButtons", {
+ widget: this,
+ }));
+ $searchview.find('button.js_date_range').click((ev) => {
+ $searchview.find('button.js_date_range.active').removeClass('active');
+ $(ev.target).addClass('active');
+ this.on_date_range_button($(ev.target).data('date'));
+ });
+ $searchview.find('button.js_website').click((ev) => {
+ $searchview.find('button.js_website.active').removeClass('active');
+ $(ev.target).addClass('active');
+ this.on_website_button($(ev.target).data('website-id'));
+ });
- var $buttons = $(QWeb.render("website.GoToButtons"));
+ const $buttons = $(QWeb.render("website.GoToButtons"));
$buttons.on('click', this.on_go_to_website.bind(this));
- this.updateControlPanel({
- cp_content: {
- $searchview: this.$searchview,
- $buttons: $buttons,
- },
- });
+ this.controlPanelProps.cp_content = { $searchview, $buttons };
},
// Loads Analytics API
diff --git a/addons/website/static/tests/dashboard_tests.js b/addons/website/static/tests/dashboard_tests.js
new file mode 100644
index 00000000000..37ee6b24a09
--- /dev/null
+++ b/addons/website/static/tests/dashboard_tests.js
@@ -0,0 +1,67 @@
+odoo.define('website/static/tests/dashboard_tests', function (require) {
+"use strict";
+
+const ControlPanel = require('web.ControlPanel');
+const Dashboard = require('website.backend.dashboard');
+const testUtils = require("web.test_utils");
+
+const { createParent, nextTick, prepareTarget } = testUtils;
+
+QUnit.module('Website Backend Dashboard', {
+}, function () {
+ QUnit.test("mounted is called once for the dashboarrd's ControlPanel", async function (assert) {
+ // This test can be removed as soon as we don't mix legacy and owl layers anymore.
+ assert.expect(5);
+
+ ControlPanel.patch('test.ControlPanel', T => {
+ class ControlPanelPatchTest extends T {
+ mounted() {
+ assert.step('mounted');
+ super.mounted(...arguments);
+ }
+ willUnmount() {
+ assert.step('willUnmount');
+ super.mounted(...arguments);
+ }
+ }
+ return ControlPanelPatchTest;
+ });
+
+ const params = {
+ mockRPC: (route) => {
+ if (route === '/website/fetch_dashboard_data') {
+ return Promise.resolve({
+ dashboards: {
+ visits: {},
+ sales: { summary: {} },
+ },
+ groups: { system: true, website_designer: true },
+ websites: [
+ {id: 1, name: "My Website", domain: "", selected: true},
+ ],
+ });
+ }
+ return this._super(...arguments);
+ },
+ };
+ const parent = await createParent(params);
+ const dashboard = new Dashboard(parent, {});
+ await dashboard.appendTo(document.createDocumentFragment());
+
+ assert.verifySteps([]);
+
+ dashboard.$el.appendTo(prepareTarget());
+ dashboard.on_attach_callback();
+
+ await nextTick();
+
+ assert.verifySteps(['mounted']);
+
+ dashboard.destroy();
+ assert.verifySteps(['willUnmount']);
+
+ ControlPanel.unpatch('test.ControlPanel');
+ });
+});
+
+});
diff --git a/addons/website/views/assets.xml b/addons/website/views/assets.xml
index ec696753ff6..e6a65bc7afd 100644
--- a/addons/website/views/assets.xml
+++ b/addons/website/views/assets.xml
@@ -48,6 +48,7 @@
<template id="qunit_suite" inherit_id="web.qunit_suite_tests">
<xpath expr="//script[last()]" position="after">
+ <script type="text/javascript" src="/website/static/tests/dashboard_tests.js"/>
<script type="text/javascript" src="/website/static/tests/website_tests.js"/>
</xpath>
</template>