diff --git a/addons/web/static/src/views/kanban/kanban_renderer.js b/addons/web/static/src/views/kanban/kanban_renderer.js index 03ff47a1fbb..686fb6739b7 100644 --- a/addons/web/static/src/views/kanban/kanban_renderer.js +++ b/addons/web/static/src/views/kanban/kanban_renderer.js @@ -397,8 +397,8 @@ export class KanbanRenderer extends Component { resModel: this.props.list.resModel, context, title: this.env._t("Create"), - onRecordSaved: (record) => { - group.addRecord(record, 0); + onRecordSaved: async (record) => { + await group.addExistingRecord(record.resId, true); }, }, { diff --git a/addons/web/static/src/views/relational_model.js b/addons/web/static/src/views/relational_model.js index 4fc7371a6ab..d3ed22e7825 100644 --- a/addons/web/static/src/views/relational_model.js +++ b/addons/web/static/src/views/relational_model.js @@ -1753,6 +1753,33 @@ export class DynamicRecordList extends DynamicList { // Public // ------------------------------------------------------------------------- + /** + * @param {number} resId + * @param {boolean} [atFirstPosition] + * @returns {Promise} the newly created record + */ + async addExistingRecord(resId, atFirstPosition) { + const newRecord = this.model.createDataPoint("record", { + resModel: this.resModel, + fields: this.fields, + activeFields: this.activeFields, + parentActiveFields: this.activeFields, + onRecordWillSwitchMode: this.onRecordWillSwitchMode, + defaultContext: this.defaultContext, + rawContext: { + parent: this.rawContext, + make: () => this.context, + }, + resId, + }); + if (this.model.useSampleModel) { + this.model.useSampleModel = false; + await this.load(); + } + await this.model.keepLast.add(this.model.mutex.exec(() => newRecord.load())); + return this.addRecord(newRecord, atFirstPosition ? 0 : this.count); + } + /** * @param {Record} record * @param {number} [index] @@ -2447,6 +2474,11 @@ export class Group extends DataPoint { return this.list.addRecord(record, index); } + addExistingRecord(resId, atFirstPosition = false) { + this.count++; + return this.list.addExistingRecord(resId, atFirstPosition); + } + createRecord(params = {}, atFirstPosition = false) { this.count++; this.list.createRecord(params, atFirstPosition); diff --git a/addons/web/static/tests/views/kanban_view_tests.js b/addons/web/static/tests/views/kanban_view_tests.js index 5a7510223b9..57cf66609ff 100644 --- a/addons/web/static/tests/views/kanban_view_tests.js +++ b/addons/web/static/tests/views/kanban_view_tests.js @@ -4,6 +4,7 @@ import { makeFakeDialogService } from "@web/../tests/helpers/mock_services"; import { click, drag, + clickSave, dragAndDrop, editInput, getFixture, @@ -27,7 +28,7 @@ import { createWebClient, doAction } from "@web/../tests/webclient/helpers"; import { browser } from "@web/core/browser/browser"; import { dialogService } from "@web/core/dialog/dialog_service"; import { tooltipService } from "@web/core/tooltip/tooltip_service"; -import { makeErrorFromResponse } from "@web/core/network/rpc_service"; +import { makeErrorFromResponse, RPCError } from "@web/core/network/rpc_service"; import { registry } from "@web/core/registry"; import { nbsp } from "@web/core/utils/strings"; import { getNextTabableElement } from "@web/core/utils/ui"; @@ -11471,4 +11472,93 @@ QUnit.module("Views", (hooks) => { assert.doesNotHaveClass(getColumn(1), "o_column_folded"); assert.containsN(getColumn(1), ".o_kanban_record", 3); }); + + QUnit.test("quick create record in grouped kanban in a form view dialog", async (assert) => { + serverData.models.partner.fields.foo.default = "ABC"; + serverData.views = { + "partner,false,form": ` +
+ + + `, + }; + + await makeView({ + type: "kanban", + resModel: "partner", + serverData, + arch: ` + + + + + +
+ +
+
+
+
+ `, + groupBy: ["product_id"], + async mockRPC(route, { method }) { + assert.step(method || route); + if (method === "name_create") { + throw new RPCError(); + } + }, + }); + + assert.containsN( + target, + ".o_kanban_group:first-child .o_kanban_record", + 2, + "first column should contain two records" + ); + + assert.deepEqual( + [...target.querySelectorAll(".o_kanban_group:first-child .o_kanban_record")].map( + (el) => el.innerText + ), + ["yop", "gnap"] + ); + + assert.containsNone(target, ".modal"); + + // click on 'Create', fill the quick create and validate + await createRecord(); + await editQuickCreateInput("display_name", "new partner"); + await validateRecord(); + + assert.containsOnce(target, ".modal"); + await clickSave(target.querySelector(".modal")); + + assert.containsN( + target, + ".o_kanban_group:first-child .o_kanban_record", + 3, + "first column should contain three records" + ); + + assert.deepEqual( + [...target.querySelectorAll(".o_kanban_group:first-child .o_kanban_record")].map( + (el) => el.innerText + ), + ["ABC", "yop", "gnap"] + ); + + assert.verifySteps([ + "get_views", + "web_read_group", // initial read_group + "web_search_read", // initial search_read (first column) + "web_search_read", // initial search_read (second column) + "onchange", // quick create + "name_create", // should perform a name_create to create the record + "get_views", // load views for form view dialog + "onchange", // load of a virtual record in form view dialog + "create", // save virtual record + "read", // read the created record to get foo value + "onchange", // reopen the quick create automatically + ]); + }); });