diff --git a/addons/web/static/src/views/kanban/kanban_model.js b/addons/web/static/src/views/kanban/kanban_model.js index 3ce8822d669..3284181ae4f 100644 --- a/addons/web/static/src/views/kanban/kanban_model.js +++ b/addons/web/static/src/views/kanban/kanban_model.js @@ -277,18 +277,22 @@ class KanbanGroup extends Group { await this.checkActiveValue(); } + /** + * @param {number} index + * @returns {Promise} + */ async validateQuickCreate(index) { const record = this.list.quickCreateRecord; - if (!record) { - return false; - } - const saved = await record.save(); - if (saved) { - this.addRecord(this.removeRecord(record), index); - this.count++; - this.list.count++; - return record; + if (record) { + const saved = await record.save(); + if (saved) { + this.addRecord(this.removeRecord(record), index); + this.count++; + this.list.count++; + return record; + } } + return false; } // ------------------------------------------------------------------------ diff --git a/addons/web/static/src/views/relational_model.js b/addons/web/static/src/views/relational_model.js index cc3b98091ca..5373cef3d91 100644 --- a/addons/web/static/src/views/relational_model.js +++ b/addons/web/static/src/views/relational_model.js @@ -242,7 +242,7 @@ class DataPoint { this.model = model; this.resModel = params.resModel; this.fields = params.fields; - this.activeFields = params.activeFields || {}; + this.setActiveFields(params.activeFields); this.rawContext = params.rawContext; this.defaultContext = params.defaultContext; @@ -324,6 +324,13 @@ class DataPoint { } } + /** + * @param {Object} [activeFields={}] + */ + setActiveFields(activeFields) { + this.activeFields = activeFields || {}; + } + // ------------------------------------------------------------------------- // Protected // ------------------------------------------------------------------------- @@ -397,8 +404,6 @@ export class Record extends DataPoint { this.onChanges = params.onChanges || (() => {}); this._invalidFields = new Set(); - this._requiredFields = {}; - this._setRequiredFields(); this.preloadedData = {}; this.preloadedDataCaches = {}; this.isInQuickCreation = params.isInQuickCreation || false; @@ -783,6 +788,7 @@ export class Record extends DataPoint { * @param {Object} [params.changes] */ async load(params = {}) { + this.data = {}; this._cache = {}; for (const fieldName in this.activeFields) { const field = this.fields[fieldName]; @@ -868,6 +874,23 @@ export class Record extends DataPoint { return this.model.mutex.exec(() => this._save(options)); } + /** + * Overridden to set required fields based on the new active fields. + * + * @override + */ + setActiveFields(activeFields) { + super.setActiveFields(activeFields); + + this._requiredFields = {}; + for (const [fieldName, activeField] of Object.entries(this.activeFields)) { + const { modifiers } = activeField; + if (modifiers && modifiers.required) { + this._requiredFields[fieldName] = modifiers.required; + } + } + } + async setInvalidField(fieldName) { if (this.selected && this.model.multiEdit) { const dialogProps = { @@ -1258,7 +1281,7 @@ export class Record extends DataPoint { * @returns {Promise} */ async _save(options = { stayInEdition: false, noReload: false }) { - if (!(await this._checkValidity())) { + if (!this._checkValidity()) { const invalidFields = [...this._invalidFields].map((fieldName) => { return `
  • ${escape(this.fields[fieldName].string || fieldName)}
  • `; }, this); @@ -1304,7 +1327,7 @@ export class Record extends DataPoint { // Switch to the parent active fields if (this.parentActiveFields) { - this.activeFields = this.parentActiveFields; + this.setActiveFields(this.parentActiveFields); this.parentActiveFields = false; } this.isInQuickCreation = false; @@ -1317,15 +1340,6 @@ export class Record extends DataPoint { return true; } - _setRequiredFields() { - for (const [fieldName, activeField] of Object.entries(this.activeFields)) { - const { modifiers } = activeField; - if (modifiers && modifiers.required) { - this._requiredFields[fieldName] = modifiers.required; - } - } - } - async _update(changes) { await this._applyChanges(changes); if (this.selected && this.model.multiEdit) { @@ -1769,7 +1783,6 @@ export class DynamicRecordList extends DynamicList { resModel: this.resModel, fields: this.fields, activeFields: this.activeFields, - parentActiveFields: this.activeFields, onRecordWillSwitchMode: this.onRecordWillSwitchMode, defaultContext: this.defaultContext, rawContext: { @@ -2033,7 +2046,6 @@ export class DynamicGroupList extends DynamicList { this.openGroupsByDefault = params.openGroupsByDefault || false; /** @type {Group[]} */ this.groups = state.groups || []; - this.activeFields = params.activeFields; this.isGrouped = true; this.quickCreateInfo = null; // Lazy loaded; this.expand = params.expand; diff --git a/addons/web/static/tests/views/kanban_view_tests.js b/addons/web/static/tests/views/kanban_view_tests.js index 1ea59ca73e3..9c56be0b5cc 100644 --- a/addons/web/static/tests/views/kanban_view_tests.js +++ b/addons/web/static/tests/views/kanban_view_tests.js @@ -3,8 +3,8 @@ import { makeFakeDialogService } from "@web/../tests/helpers/mock_services"; import { click, - drag, clickSave, + drag, dragAndDrop, editInput, getFixture, @@ -12,6 +12,7 @@ import { makeDeferred, nextTick, patchWithCleanup, + selectDropdownItem, triggerEvent, triggerHotkey, } from "@web/../tests/helpers/utils"; @@ -27,16 +28,16 @@ import { makeView, setupViewRegistries } from "@web/../tests/views/helpers"; 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, RPCError } from "@web/core/network/rpc_service"; import { registry } from "@web/core/registry"; +import { tooltipService } from "@web/core/tooltip/tooltip_service"; import { nbsp } from "@web/core/utils/strings"; import { getNextTabableElement } from "@web/core/utils/ui"; import { session } from "@web/session"; import { KanbanAnimatedNumber } from "@web/views/kanban/kanban_animated_number"; import { kanbanView } from "@web/views/kanban/kanban_view"; -import { ViewButton } from "@web/views/view_button/view_button"; import { DynamicRecordList } from "@web/views/relational_model"; +import { ViewButton } from "@web/views/view_button/view_button"; import AbstractField from "web.AbstractField"; import legacyFieldRegistry from "web.field_registry"; @@ -11759,4 +11760,53 @@ QUnit.module("Views", (hooks) => { "onchange", // reopen the quick create automatically ]); }); + + QUnit.test("Move new record with onchanges and different active fields", async (assert) => { + serverData.models.partner.fields.foo.default = "abc"; + serverData.models.partner.onchanges = { + bar(obj) { + obj.foo = [...obj.foo].reverse().join(""); + }, + }; + serverData.views["partner,some_view_ref,form"] = /* xml */ ` +
    + + + `; + + await makeView({ + type: "kanban", + resModel: "partner", + serverData, + arch: /* xml */ ` + + + + +
    + + +
    +
    +
    + `, + groupBy: ["bar"], + }); + + assert.deepEqual(getCardTexts(0), ["blip-4"]); + assert.deepEqual(getCardTexts(1), ["yop10", "blip9", "gnap17"]); + + await quickCreateRecord(0); + await editQuickCreateInput("int_field", "13"); + await selectDropdownItem(target, "category_ids", "gold"); + await validateRecord(); + + assert.deepEqual(getCardTexts(0), ["abc13", "blip-4"]); + assert.deepEqual(getCardTexts(1), ["yop10", "blip9", "gnap17"]); + + await dragAndDrop(".o_kanban_record", ".o_kanban_group:nth-child(2)"); + + assert.deepEqual(getCardTexts(0), ["blip-4"]); + assert.deepEqual(getCardTexts(1), ["yop10", "blip9", "gnap17", "cba13"]); + }); });