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);
+ });
});