diff --git a/addons/web/static/src/js/views/kanban/kanban_column.js b/addons/web/static/src/js/views/kanban/kanban_column.js index ffb63ad90833e..57ecc6f4b4e54 100644 --- a/addons/web/static/src/js/views/kanban/kanban_column.js +++ b/addons/web/static/src/js/views/kanban/kanban_column.js @@ -173,6 +173,7 @@ var KanbanColumn = Widget.extend({ * into a fragment, the focus has to be set manually once in the DOM. */ on_attach_callback: function () { + _.invoke(this.records, 'on_attach_callback'); if (this.quickCreateWidget) { this.quickCreateWidget.on_attach_callback(); } diff --git a/addons/web/static/src/js/views/kanban/kanban_renderer.js b/addons/web/static/src/js/views/kanban/kanban_renderer.js index 9356311d51c04..3dc0cae5540e9 100644 --- a/addons/web/static/src/js/views/kanban/kanban_renderer.js +++ b/addons/web/static/src/js/views/kanban/kanban_renderer.js @@ -127,6 +127,7 @@ var KanbanRenderer = BasicRenderer.extend({ * Called each time the renderer is attached into the DOM. */ on_attach_callback: function () { + this._isInDom = true; _.invoke(this.widgets, 'on_attach_callback'); if (this.quickCreate) { this.quickCreate.on_attach_callback(); @@ -136,6 +137,7 @@ var KanbanRenderer = BasicRenderer.extend({ * Called each time the renderer is detached from the DOM. */ on_detach_callback: function () { + this._isInDom = false; _.invoke(this.widgets, 'on_detach_callback'); }, @@ -377,6 +379,7 @@ var KanbanRenderer = BasicRenderer.extend({ * @private */ _renderView: function () { + var self = this; var oldWidgets = this.widgets; this.widgets = []; this.$el.empty(); @@ -397,6 +400,9 @@ var KanbanRenderer = BasicRenderer.extend({ var defs = this.defs; return this._super.apply(this, arguments).then(function () { _.invoke(oldWidgets, 'destroy'); + if (self._isInDom) { + _.invoke(self.widgets, 'on_attach_callback'); + } return $.when.apply(null, defs); }); }, diff --git a/addons/web/static/tests/fields/basic_fields_tests.js b/addons/web/static/tests/fields/basic_fields_tests.js index 70effe45e7226..cb864afdf7e24 100644 --- a/addons/web/static/tests/fields/basic_fields_tests.js +++ b/addons/web/static/tests/fields/basic_fields_tests.js @@ -2324,9 +2324,9 @@ QUnit.module('basic_fields', { concurrency.delay(0).then(function () { return concurrency.delay(0); }).then(function () { - assert.strictEqual(kanban.$('.o_kanban_record:first() .o_graph_barchart').length, 1, + assert.strictEqual(kanban.$('.o_kanban_record:first() .o_graph_barchart svg').length, 1, "graph of first record should be a barchart"); - assert.strictEqual(kanban.$('.o_kanban_record:nth(1) .o_graph_linechart').length, 1, + assert.strictEqual(kanban.$('.o_kanban_record:nth(1) .o_graph_linechart svg').length, 1, "graph of second record should be a linechart"); var evt = document.createEvent("MouseEvents"); //taken ref from https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/initMouseEvent @@ -2357,14 +2357,15 @@ QUnit.module('basic_fields', { // when being destroyed before nv has been loaded assert.expect(2); - var destroy = basicFields.JournalDashboardGraph.prototype.destroy; - basicFields.JournalDashboardGraph.prototype.destroy = function () { - assert.step('destroy'); - var nv = window.nv; - delete window.nv; - destroy.apply(this, arguments); - window.nv = nv; - }; + testUtils.patch(basicFields.JournalDashboardGraph, { + destroy: function () { + assert.step('destroy'); + var nv = window.nv; + delete window.nv; + this._super.apply(this, arguments); + window.nv = nv; + } + }); var kanban = createView({ View: KanbanView, @@ -2382,9 +2383,12 @@ QUnit.module('basic_fields', { }); kanban.destroy(); - basicFields.JournalDashboardGraph.prototype.destroy = destroy; + testUtils.unpatch(basicFields.JournalDashboardGraph); assert.verifySteps(['destroy']); + + // Wait nvd3 to fully render the graph. If ommited, may slow down following tests. + return concurrency.delay(0); }); QUnit.test('graph dashboard widget can be destroyed when nv is partially loaded', function (assert) { @@ -2424,6 +2428,79 @@ QUnit.module('basic_fields', { testUtils.unpatch(basicFields.JournalDashboardGraph); assert.verifySteps(['destroy']); + + // Wait nvd3 to fully render the graph. If ommited, may slow down following tests. + return concurrency.delay(0); + }); + + QUnit.test('rendering of a field with dashboard_graph widget in an updated kanban view (ungrouped)', function (assert) { + + var done = assert.async(); + assert.expect(2); + + createAsyncView({ + View: KanbanView, + model: 'partner', + data: this.data, + arch: '' + + '' + + '' + + '
' + + '' + + '
' + + '
' + + '
', + domain: [['id', 'in', [1, 2]]], + }).then(function (kanban) { + concurrency.delay(0).then(function () { + return concurrency.delay(0); + }).then(function () { + assert.strictEqual(kanban.$('.o_dashboard_graph svg').length, 2, "there should be two graph rendered"); + return kanban.update({}); + }).then(function () { + return concurrency.delay(0); // one graph is re-rendered + }).then(function () { + return concurrency.delay(0); // one graph is re-rendered + }).then(function () { + assert.strictEqual(kanban.$('.o_dashboard_graph svg').length, 2, "there should be one graph rendered"); + kanban.destroy(); + done(); + }); + }); + }); + + QUnit.test('rendering of a field with dashboard_graph widget in an updated kanban view (grouped)', function (assert) { + + var done = assert.async(); + assert.expect(2); + + createAsyncView({ + View: KanbanView, + model: 'partner', + data: this.data, + arch: '' + + '' + + '' + + '
' + + '' + + '
' + + '
' + + '
', + domain: [['id', 'in', [1, 2]]], + }).then(function (kanban) { + concurrency.delay(0).then(function () { + return concurrency.delay(0); + }).then(function () { + assert.strictEqual(kanban.$('.o_dashboard_graph svg').length, 2, "there should be two graph rendered"); + return kanban.update({groupBy: ['selection'], domain: [['int_field', '=', 10]]}); + }).then(function () { + return concurrency.delay(0); + }).then(function () { + assert.strictEqual(kanban.$('.o_dashboard_graph svg').length, 1, "there should be one graph rendered"); + kanban.destroy(); + done(); + }); + }); }); QUnit.module('AceEditor');