[FIX] web: crash in grouped kanban's progressbar with folded column

Steps to reproduce:

- Open Odoo on small screen
- Go to "Project" app
- Select project > Traceback

The Kanban progress bar's refactoring [1] didn't completely took into
account the fact that, on smaller screen, the "folded" columns aren't
actually folded (like on dekstop-like screen sizes) but instead their
records aren't loaded by default. As a result, in one case the progress
bar is shown (small screen) and in the other hidden.

As the progressbar's information is memoized in `getGroupInfo`, this
getter should have been called wherever those information are read.

This commit fixes the issue by properly calling the `getGroupInfo`
getter instead of using the "private" `_groupsInfo` object (which may
not yet have been populated, due to the memoization).

task-3336233

[1] https://github.com/odoo/odoo/commit/58ca40b03215ef4c6c575267494dc8bccc30a033

closes odoo/odoo#122214

X-original-commit: c2efa7f059c92298ae5fb22b83e812453e2eb8ea
Signed-off-by: Pierre Paridans (app) <app@odoo.com>
This commit is contained in:
Romain Estievenart
2023-05-24 06:29:41 +02:00
committed by Pierre Paridans
parent ae6e5be25a
commit 0ff71ab65f
2 changed files with 112 additions and 5 deletions
@@ -137,7 +137,7 @@ class ProgressBarState {
async selectBar(groupId, bar) {
const group = this.model.root.groups.find((group) => group.id === groupId);
const progressBar = this._groupsInfo[groupId];
const progressBar = this.getGroupInfo(group);
const nextActiveBar = {};
if (bar.value && this.activeBars[group.value]?.value !== bar.value) {
nextActiveBar.value = bar.value;
@@ -157,7 +157,7 @@ class ProgressBarState {
const proms = [];
proms.push(
group.applyFilter(filterDomain).then((res) => {
const groupInfo = this._groupsInfo[group.id];
const groupInfo = this.getGroupInfo(group);
nextActiveBar.count = groupInfo.bars.find(
(x) => x.value === nextActiveBar.value
).count;
@@ -171,7 +171,7 @@ class ProgressBarState {
}
_updateAggregateGroup(group, activeBar) {
const groupInfo = this._groupsInfo[group.id];
const groupInfo = this.getGroupInfo(group);
const filterDomain = _createFilterDomain(
this.progressAttributes.fieldName,
groupInfo.bars,
@@ -253,7 +253,7 @@ class ProgressBarState {
}
for (const group of this.model.root.groups) {
if (!group.isFolded) {
const groupInfo = this._groupsInfo[group.id];
const groupInfo = this.getGroupInfo(group);
let groupValue = group.displayName || group.value;
if (groupValue === true) {
groupValue = "True";
@@ -299,7 +299,7 @@ class ProgressBarState {
}
getGroupCount(group) {
const progressBarInfo = this._groupsInfo[group.id];
const progressBarInfo = this.getGroupInfo(group);
if (progressBarInfo.activeBar) {
const progressBar = progressBarInfo.bars.find(
(b) => b.value === progressBarInfo.activeBar
@@ -0,0 +1,107 @@
/** @odoo-module **/
import { makeView, setupViewRegistries } from "@web/../tests/views/helpers";
import { click, getFixture, patchWithCleanup} from "@web/../tests/helpers/utils";
import { AnimatedNumber } from "@web/views/view_components/animated_number";
let serverData;
let target;
QUnit.module("Views", (hooks) => {
hooks.beforeEach(() => {
patchWithCleanup(AnimatedNumber, { enableAnimations: false });
serverData = {
models: {
partner: {
fields: {
foo: { string: "Foo", type: "char" },
product_id: {
string: "something_id",
type: "many2one",
relation: "product",
},
},
records: [
{
id: 1,
foo: "yop",
product_id: 3,
},
{
id: 2,
foo: "blip",
product_id: 5,
},
{
id: 3,
foo: "gnap",
product_id: 3,
},
{
id: 4,
foo: "blip",
product_id: 5,
},
],
},
product: {
fields: {
id: { string: "ID", type: "integer" },
name: { string: "Display Name", type: "char" },
},
records: [
{ id: 3, name: "hello" },
{ id: 5, name: "xmo" },
],
},
},
views: {},
};
target = getFixture();
setupViewRegistries();
});
QUnit.module("KanbanView");
QUnit.test("Should load grouped kanban with folded column", async (assert) => {
await makeView({
type: "kanban",
resModel: "partner",
serverData,
arch: `
<kanban>
<progressbar field="foo" colors='{"yop": "success", "blip": "danger"}'/>
<field name="product_id"/>
<templates>
<t t-name="kanban-box">
<div><field name="foo"/></div>
</t>
</templates>
</kanban>`,
groupBy: ["product_id"],
async mockRPC(route, args, performRPC) {
if (args.method === "web_read_group") {
const result = await performRPC(route, args);
result.groups[1].__fold = true;
return result;
}
},
});
assert.containsN(target, ".o_column_progress", 2, "Should have 2 progress bar");
assert.containsN(target, ".o_kanban_group", 2, "Should have 2 grouped column");
assert.containsN(target, ".o_kanban_record", 2, "Should have 2 loaded record");
assert.containsOnce(
target,
".o_kanban_load_more",
"Should have a folded column with a load more button"
);
await click(target, ".o_kanban_load_more button");
assert.containsNone(
target,
".o_kanban_load_more",
"Shouldn't have a load more button"
);
assert.containsN(target, ".o_kanban_record", 4, "Should have 4 loaded record");
});
});