diff --git a/addons/web/static/src/legacy/js/views/kanban/kanban_column_progressbar.js b/addons/web/static/src/legacy/js/views/kanban/kanban_column_progressbar.js
index abf9a7136e8..bc9ac922bd1 100644
--- a/addons/web/static/src/legacy/js/views/kanban/kanban_column_progressbar.js
+++ b/addons/web/static/src/legacy/js/views/kanban/kanban_column_progressbar.js
@@ -43,7 +43,7 @@ var KanbanColumnProgressBar = Widget.extend({
this.groupCount = state.groupCount;
this.subgroupCounts = state.subgroupCounts;
this.totalCounterValue = state.totalCounterValue;
- this.activeFilter = state.activeFilter;
+ this.activeFilter = columnState.activeFilter || state.activeFilter;
}
// Prepare currency (TODO this should be automatic... use a field ?)
diff --git a/addons/web/static/src/legacy/js/views/kanban/kanban_model.js b/addons/web/static/src/legacy/js/views/kanban/kanban_model.js
index 3fdde47ea34..a6d2703fead 100644
--- a/addons/web/static/src/legacy/js/views/kanban/kanban_model.js
+++ b/addons/web/static/src/legacy/js/views/kanban/kanban_model.js
@@ -167,6 +167,8 @@ var KanbanModel = BasicModel.extend({
} else {
result.isGroupedByM2ONoColumn = false;
}
+ // Keep activeFilter
+ result.activeFilter = dp.activeFilter;
// Add progressBarValues, loadMoreCount and loadMoreOffset key
let loadMoreCount = result.count - result.data.length;
let loadMoreOffset = result.data.length;
@@ -264,6 +266,11 @@ var KanbanModel = BasicModel.extend({
if (index >= 0) {
old_group.data.splice(index, 1);
old_group.count--;
+ if (!old_group.activeFilter || old_group.activeFilter.value === record.data[parent.progressBar.field]) {
+ // Here, the record leaving the old group matches its domain,
+ // so we must decrease the domainCount too.
+ old_group.domainCount--;
+ }
old_group.res_ids = _.without(old_group.res_ids, resID);
self._updateParentResIDs(old_group);
break;
@@ -355,6 +362,10 @@ var KanbanModel = BasicModel.extend({
if (params.progressBar) {
dataPoint.progressBar = params.progressBar;
}
+ // In Kanban view, we sometimes drag into a group records that are
+ // outside of its domain. Here we make sure to remember the initial
+ // domain count. This is useful for e.g. progressbars computations.
+ dataPoint.domainCount = dataPoint.count;
return dataPoint;
},
/**
@@ -403,7 +414,7 @@ var KanbanModel = BasicModel.extend({
// Compute records count for progressbar field values
// not specified in the progressbar attributes
const counts = Object.assign({
- __false: group.count - valuesCountTotal
+ __false: group.domainCount - valuesCountTotal
}, valuesCount);
group.progressBarValues = Object.assign({
diff --git a/addons/web/static/tests/legacy/views/kanban_tests.js b/addons/web/static/tests/legacy/views/kanban_tests.js
index 697330e7e9a..a8cc0afc07b 100644
--- a/addons/web/static/tests/legacy/views/kanban_tests.js
+++ b/addons/web/static/tests/legacy/views/kanban_tests.js
@@ -7803,6 +7803,292 @@ QUnit.module('Views', {
kanban.destroy();
});
+
+ QUnit.test("progressbar filter state is kept unchanged when domain is updated (records still in group)", async function (assert) {
+ assert.expect(16);
+
+ const kanban = await createView({
+ View: KanbanView,
+ model: "partner",
+ data: this.data,
+ arch: `
+
+
+
+
+
+
+
+
+
+
+
+
+
+ `,
+ });
+
+ // Check that we have 2 columns and check their progressbar's state
+ assert.containsN(kanban.el, ".o_kanban_group", 2);
+ assert.containsNone(kanban.el, ".o_kanban_group.o_kanban_group_show");
+ assert.deepEqual(
+ [...kanban.el.querySelectorAll(".o_column_title")].map(el => el.innerText),
+ ["false", "true"],
+ );
+ assert.deepEqual(
+ [...kanban.el.querySelectorAll(".o_kanban_group:nth-child(1) .o_kanban_counter .progress-bar")].map(el => el.dataset.originalTitle),
+ ["0 yop", "1 blip", "0 __false"],
+ );
+ assert.deepEqual(
+ [...kanban.el.querySelectorAll(".o_kanban_group:nth-child(2) .o_kanban_counter .progress-bar")].map(el => el.dataset.originalTitle),
+ ["1 yop", "1 blip", "1 __false"],
+ );
+
+ // Apply an active filter
+ await testUtils.dom.click(kanban.el.querySelector(".o_kanban_group:nth-child(2) .progress-bar[data-filter=yop]"));
+ assert.containsOnce(kanban.el, ".o_kanban_group.o_kanban_group_show");
+ assert.strictEqual(kanban.el.querySelector(".o_kanban_group.o_kanban_group_show .o_column_title").innerText, "true");
+
+ // Add searchdomain to something restricting progressbars' values (records still in filtered group)
+ await kanban.update({ domain: [["foo", "=", "yop"]] });
+
+ // Check that we have now 1 column only and check its progressbar's state
+ assert.containsOnce(kanban.el, ".o_kanban_group");
+ assert.containsOnce(kanban.el, ".o_kanban_group.o_kanban_group_show");
+ assert.strictEqual(kanban.el.querySelector(".o_column_title").innerText, "true");
+ assert.deepEqual(
+ [...kanban.el.querySelectorAll(".o_kanban_group .o_kanban_counter .progress-bar")].map(el => el.dataset.originalTitle),
+ ["1 yop", "0 blip", "0 __false"],
+ );
+
+ // Undo searchdomain
+ await kanban.update({ domain: [] });
+
+ // Check that we have 2 columns back and check their progressbar's state
+ assert.containsN(kanban.el, ".o_kanban_group", 2);
+ assert.containsOnce(kanban.el, ".o_kanban_group.o_kanban_group_show");
+ assert.deepEqual(
+ [...kanban.el.querySelectorAll(".o_column_title")].map(el => el.innerText),
+ ["false", "true"],
+ );
+ assert.deepEqual(
+ [...kanban.el.querySelectorAll(".o_kanban_group:nth-child(1) .o_kanban_counter .progress-bar")].map(el => el.dataset.originalTitle),
+ ["0 yop", "1 blip", "0 __false"],
+ );
+ assert.deepEqual(
+ [...kanban.el.querySelectorAll(".o_kanban_group:nth-child(2) .o_kanban_counter .progress-bar")].map(el => el.dataset.originalTitle),
+ ["1 yop", "1 blip", "1 __false"],
+ );
+
+ kanban.destroy();
+ });
+
+ QUnit.test("progressbar filter state is kept unchanged when domain is updated (emptying group)", async function (assert) {
+ assert.expect(25);
+
+ const kanban = await createView({
+ View: KanbanView,
+ model: "partner",
+ data: this.data,
+ arch: `
+
+
+
+
+
+
+
+
+
+
+
+
+
+ `,
+ });
+
+ // Check that we have 2 columns, check their progressbar's state and check records
+ assert.containsN(kanban.el, ".o_kanban_group", 2);
+ assert.containsNone(kanban.el, ".o_kanban_group.o_kanban_group_show");
+ assert.deepEqual(
+ [...kanban.el.querySelectorAll(".o_column_title")].map(el => el.innerText),
+ ["false", "true"],
+ );
+ assert.deepEqual(
+ [...kanban.el.querySelectorAll(".o_kanban_group:nth-child(1) .o_kanban_counter .progress-bar")].map(el => el.dataset.originalTitle),
+ ["0 yop", "1 blip", "0 __false"],
+ );
+ assert.deepEqual(
+ [...kanban.el.querySelectorAll(".o_kanban_group:nth-child(1) .o_kanban_record")].map(el => el.innerText),
+ ["4 blip"],
+ );
+ assert.deepEqual(
+ [...kanban.el.querySelectorAll(".o_kanban_group:nth-child(2) .o_kanban_counter .progress-bar")].map(el => el.dataset.originalTitle),
+ ["1 yop", "1 blip", "1 __false"],
+ );
+ assert.deepEqual(
+ [...kanban.el.querySelectorAll(".o_kanban_group:nth-child(2) .o_kanban_record")].map(el => el.innerText),
+ ["1 yop", "2 blip", "3 gnap"],
+ );
+
+ // Apply an active filter
+ await testUtils.dom.click(kanban.el.querySelector(".o_kanban_group:nth-child(2) .progress-bar[data-filter=yop]"));
+ assert.containsOnce(kanban.el, ".o_kanban_group.o_kanban_group_show");
+ assert.strictEqual(kanban.el.querySelector(".o_kanban_group.o_kanban_group_show .o_column_title").innerText, "true");
+ assert.deepEqual(
+ [...kanban.el.querySelectorAll(".o_kanban_group.o_kanban_group_show .o_kanban_counter .progress-bar")].map(el => el.dataset.originalTitle),
+ ["1 yop", "1 blip", "1 __false"],
+ );
+ assert.deepEqual(
+ [...kanban.el.querySelectorAll(".o_kanban_group.o_kanban_group_show .o_kanban_record")].map(el => el.innerText),
+ ["1 yop"],
+ );
+
+ // Add searchdomain to something restricting progressbars' values + emptying the filtered group
+ await kanban.update({ domain: [["foo", "=", "blip"]] });
+
+ // Check that we still have 2 columns, check their progressbar's state and check records
+ assert.containsN(kanban.el, ".o_kanban_group", 2);
+ assert.containsNone(kanban.el, ".o_kanban_group.o_kanban_group_show");
+ assert.deepEqual(
+ [...kanban.el.querySelectorAll(".o_column_title")].map(el => el.innerText),
+ ["false", "true"],
+ );
+ assert.deepEqual(
+ [...kanban.el.querySelectorAll(".o_kanban_group:nth-child(1) .o_kanban_counter .progress-bar")].map(el => el.dataset.originalTitle),
+ ["0 yop", "1 blip", "0 __false"],
+ );
+ assert.deepEqual(
+ [...kanban.el.querySelectorAll(".o_kanban_group:nth-child(1) .o_kanban_record")].map(el => el.innerText),
+ ["4 blip"],
+ );
+ assert.deepEqual(
+ [...kanban.el.querySelectorAll(".o_kanban_group:nth-child(2) .o_kanban_counter .progress-bar")].map(el => el.dataset.originalTitle),
+ ["0 yop", "1 blip", "0 __false"],
+ );
+ assert.deepEqual(
+ [...kanban.el.querySelectorAll(".o_kanban_group:nth-child(2) .o_kanban_record")].map(el => el.innerText),
+ [],
+ );
+
+ // Undo searchdomain
+ await kanban.update({ domain: [] });
+
+ // Check that we still have 2 columns and check their progressbar's state
+ assert.containsN(kanban.el, ".o_kanban_group", 2);
+ assert.containsOnce(kanban.el, ".o_kanban_group.o_kanban_group_show");
+ assert.deepEqual(
+ [...kanban.el.querySelectorAll(".o_column_title")].map(el => el.innerText),
+ ["false", "true"],
+ );
+ assert.deepEqual(
+ [...kanban.el.querySelectorAll(".o_kanban_group:nth-child(1) .o_kanban_counter .progress-bar")].map(el => el.dataset.originalTitle),
+ ["0 yop", "1 blip", "0 __false"],
+ );
+ assert.deepEqual(
+ [...kanban.el.querySelectorAll(".o_kanban_group:nth-child(1) .o_kanban_record")].map(el => el.innerText),
+ ["4 blip"],
+ );
+ assert.deepEqual(
+ [...kanban.el.querySelectorAll(".o_kanban_group:nth-child(2) .o_kanban_counter .progress-bar")].map(el => el.dataset.originalTitle),
+ ["1 yop", "1 blip", "1 __false"],
+ );
+ assert.deepEqual(
+ [...kanban.el.querySelectorAll(".o_kanban_group:nth-child(2) .o_kanban_record")].map(el => el.innerText),
+ ["1 yop"],
+ );
+
+ kanban.destroy();
+ });
+
+ QUnit.test("filtered column keeps consistent counters when dropping in a non-matching record", async function (assert) {
+ assert.expect(19);
+
+ const kanban = await createView({
+ View: KanbanView,
+ model: "partner",
+ data: this.data,
+ arch: `
+
+
+
+
+
+
+
+
+
+
+
+
+
+ `,
+ });
+
+ // Check that we have 2 columns, check their progressbar's state, and check records
+ assert.containsN(kanban.el, ".o_kanban_group", 2);
+ assert.containsNone(kanban.el, ".o_kanban_group.o_kanban_group_show");
+ assert.deepEqual(
+ [...kanban.el.querySelectorAll(".o_column_title")].map(el => el.innerText),
+ ["false", "true"],
+ );
+ assert.deepEqual(
+ [...kanban.el.querySelectorAll(".o_kanban_group:nth-child(1) .o_kanban_counter .progress-bar")].map(el => el.dataset.originalTitle),
+ ["0 yop", "1 blip", "0 __false"],
+ );
+ assert.deepEqual(
+ [...kanban.el.querySelectorAll(".o_kanban_group:nth-child(1) .o_kanban_record")].map(el => el.innerText),
+ ["4 blip"],
+ );
+ assert.deepEqual(
+ [...kanban.el.querySelectorAll(".o_kanban_group:nth-child(2) .o_kanban_counter .progress-bar")].map(el => el.dataset.originalTitle),
+ ["1 yop", "1 blip", "1 __false"],
+ );
+ assert.deepEqual(
+ [...kanban.el.querySelectorAll(".o_kanban_group:nth-child(2) .o_kanban_record")].map(el => el.innerText),
+ ["1 yop", "2 blip", "3 gnap"],
+ );
+
+ // Apply an active filter
+ await testUtils.dom.click(kanban.el.querySelector(".o_kanban_group:nth-child(2) .progress-bar[data-filter=yop]"));
+ assert.hasClass(kanban.el.querySelector(".o_kanban_group:nth-child(2)"), "o_kanban_group_show");
+ assert.containsOnce(kanban.el, ".o_kanban_group.o_kanban_group_show");
+ assert.strictEqual(kanban.el.querySelector(".o_kanban_group.o_kanban_group_show .o_column_title").innerText, "true");
+ assert.containsOnce(kanban.el, ".o_kanban_group.o_kanban_group_show .o_kanban_record");
+ assert.strictEqual(kanban.el.querySelector(".o_kanban_group.o_kanban_group_show .o_kanban_record").innerText, "1 yop");
+
+ // Drop in the non-matching record from first column
+ await testUtils.dom.dragAndDrop(
+ kanban.el.querySelector(".o_kanban_group:nth-child(1) .o_kanban_record"),
+ kanban.el.querySelector(".o_kanban_group.o_kanban_group_show")
+ );
+
+ // Check that we have 2 columns, check their progressbar's state, and check records
+ assert.containsN(kanban.el, ".o_kanban_group", 2);
+ assert.containsOnce(kanban.el, ".o_kanban_group.o_kanban_group_show");
+ assert.deepEqual(
+ [...kanban.el.querySelectorAll(".o_column_title")].map(el => el.innerText),
+ ["false", "true"],
+ );
+ assert.deepEqual(
+ [...kanban.el.querySelectorAll(".o_kanban_group:nth-child(1) .o_kanban_counter .progress-bar")].map(el => el.dataset.originalTitle),
+ ["0 yop", "0 blip", "0 __false"],
+ );
+ assert.deepEqual(
+ [...kanban.el.querySelectorAll(".o_kanban_group:nth-child(1) .o_kanban_record")].map(el => el.innerText),
+ [],
+ );
+ assert.deepEqual(
+ [...kanban.el.querySelectorAll(".o_kanban_group:nth-child(2) .o_kanban_counter .progress-bar")].map(el => el.dataset.originalTitle),
+ ["1 yop", "2 blip", "1 __false"],
+ );
+ assert.deepEqual(
+ [...kanban.el.querySelectorAll(".o_kanban_group:nth-child(2) .o_kanban_record")].map(el => el.innerText),
+ ["1 yop", "4 blip"],
+ );
+
+ kanban.destroy();
+ });
});
});