diff --git a/addons/web/static/src/views/kanban/kanban_model.js b/addons/web/static/src/views/kanban/kanban_model.js index d563c7793ad..45738c6cd81 100644 --- a/addons/web/static/src/views/kanban/kanban_model.js +++ b/addons/web/static/src/views/kanban/kanban_model.js @@ -349,6 +349,7 @@ export class KanbanDynamicGroupList extends DynamicGroupList { this.model.addEventListener("group-updated", ({ detail }) => { if (this.groups.some((g) => g.id === detail.group.id)) { this.updateGroupProgressData([detail.group], detail.withProgressBars); + this.model.notify(); } }); } @@ -417,8 +418,6 @@ export class KanbanDynamicGroupList extends DynamicGroupList { const result = await promises.readProgressBar; await Promise.all(groups.map((group) => group.updateProgressData(result))); } - - this.model.notify(); } /** @@ -447,6 +446,7 @@ export class KanbanDynamicGroupList extends DynamicGroupList { } // Move from one group to another + const fullyLoadGroup = targetGroup.isFolded; if (dataGroupId !== targetGroupId) { const refIndex = targetGroup.list.records.findIndex((r) => r.id === refId); // Quick update: moves the record at the right position and notifies components @@ -470,14 +470,24 @@ export class KanbanDynamicGroupList extends DynamicGroupList { throw err; } - // Record can be loaded along with the group metadata - await Promise.all([ - this.updateGroupProgressData([sourceGroup, targetGroup], true), - record.load(), - ]); + const promises = [this.updateGroupProgressData([sourceGroup, targetGroup], true)]; + if (fullyLoadGroup) { + // The group is folded: we need to load it + // In this case since we load after saving the record there is no + // need to reload the record nor to resequence the list. + promises.push(targetGroup.toggle()); + } else { + // Record can be loaded along with the group metadata + promises.push(record.load()); + } + + await Promise.all(promises); } - await targetGroup.list.resequence(dataRecordId, refId); + if (!fullyLoadGroup) { + // Only trigger resequence if the group hasn't been fully loaded + await targetGroup.list.resequence(dataRecordId, refId); + } this.model.transaction.commit(dataRecordId); } diff --git a/addons/web/static/src/views/relational_model.js b/addons/web/static/src/views/relational_model.js index f7578659e33..6a59fa898bd 100644 --- a/addons/web/static/src/views/relational_model.js +++ b/addons/web/static/src/views/relational_model.js @@ -2423,7 +2423,6 @@ export class Group extends DataPoint { */ addRecord(record, index) { this.count++; - this.isFolded = false; return this.list.addRecord(record, index); } diff --git a/addons/web/static/tests/views/kanban_view_tests.js b/addons/web/static/tests/views/kanban_view_tests.js index 934bf3a042e..ad389ed013d 100644 --- a/addons/web/static/tests/views/kanban_view_tests.js +++ b/addons/web/static/tests/views/kanban_view_tests.js @@ -11053,4 +11053,99 @@ QUnit.module("Views", (hooks) => { productFieldName + "..." ); }); + + QUnit.test("fold a column and drag record on it should unfold it", async (assert) => { + let searchReadProm; + await makeView({ + type: "kanban", + resModel: "partner", + serverData, + arch: /* xml */ ` + + +
+ +
+
+
`, + groupBy: ["product_id"], + async mockRPC(_route, { method }) { + if (method === "web_search_read") { + await searchReadProm; + } + }, + }); + + assert.containsN(target, ".o_kanban_group", 2); + assert.containsN(getColumn(0), ".o_kanban_record", 2); + assert.containsN(getColumn(1), ".o_kanban_record", 2); + + const clickColumnAction = await toggleColumnActions(1); + await clickColumnAction("Fold"); + + assert.containsN(getColumn(0), ".o_kanban_record", 2); + assert.hasClass(getColumn(1), "o_column_folded"); + assert.strictEqual(getColumn(1).innerText, "xmo (2)"); + + searchReadProm = makeDeferred(); + + await dragAndDrop(".o_kanban_group:first-child .o_kanban_record", ".o_column_folded"); + + assert.containsN(getColumn(0), ".o_kanban_record", 1); + assert.hasClass(getColumn(1), "o_column_folded"); + assert.strictEqual(getColumn(1).innerText, "xmo (3)"); + + searchReadProm.resolve(); + await nextTick(); + + assert.containsN(getColumn(0), ".o_kanban_record", 1); + assert.doesNotHaveClass(getColumn(1), "o_column_folded"); + assert.containsN(getColumn(1), ".o_kanban_record", 3); + }); + + QUnit.test("drag record on initially folded column should load it", async (assert) => { + let searchReadProm; + await makeView({ + type: "kanban", + resModel: "partner", + serverData, + arch: /* xml */ ` + + +
+ +
+
+
`, + 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; + } else if (args.method === "web_search_read") { + await searchReadProm; + } + }, + }); + + assert.containsN(getColumn(0), ".o_kanban_record", 2); + assert.hasClass(getColumn(1), "o_column_folded"); + assert.strictEqual(getColumn(1).innerText, "xmo (2)"); + + searchReadProm = makeDeferred(); + + await dragAndDrop(".o_kanban_group:first-child .o_kanban_record", ".o_column_folded"); + + assert.containsN(getColumn(0), ".o_kanban_record", 1); + assert.hasClass(getColumn(1), "o_column_folded"); + assert.strictEqual(getColumn(1).innerText, "xmo (3)"); + + searchReadProm.resolve(); + await nextTick(); + + assert.containsN(getColumn(0), ".o_kanban_record", 1); + assert.doesNotHaveClass(getColumn(1), "o_column_folded"); + assert.containsN(getColumn(1), ".o_kanban_record", 3); + }); });