[FIX] web: various filtering kanban column scenarii

BEFORE
Various scenarii leads to inconsistencies on the progressbars when a filter is activated:
- when dropping in a non matching record
- when the view domain is updated (e.g. from some input in the search panel)

NOW
These scenarii works fine.

Taskid-2491196
Taskid-2454209
This commit is contained in:
Bruno Boi
2021-06-30 12:06:28 +00:00
parent 177dbd60a2
commit e248773826
3 changed files with 299 additions and 2 deletions
@@ -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 ?)
@@ -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({
@@ -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: `
<kanban default_group_by="bar">
<progressbar field="foo" colors='{"yop": "success", "blip": "danger"}'/>
<field name="foo"/>
<field name="bar"/>
<templates>
<t t-name="kanban-box">
<div>
<field name="id"/>
<field name="foo"/>
</div>
</t>
</templates>
</kanban>
`,
});
// 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: `
<kanban default_group_by="bar">
<progressbar field="foo" colors='{"yop": "success", "blip": "danger"}'/>
<field name="foo"/>
<field name="bar"/>
<templates>
<t t-name="kanban-box">
<div>
<field name="id"/>
<field name="foo"/>
</div>
</t>
</templates>
</kanban>
`,
});
// 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: `
<kanban default_group_by="bar">
<progressbar field="foo" colors='{"yop": "success", "blip": "danger"}'/>
<field name="foo"/>
<field name="bar"/>
<templates>
<t t-name="kanban-box">
<div>
<field name="id"/>
<field name="foo"/>
</div>
</t>
</templates>
</kanban>
`,
});
// 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();
});
});
});