diff --git a/addons/analytic/static/src/components/analytic_distribution/analytic_distribution.js b/addons/analytic/static/src/components/analytic_distribution/analytic_distribution.js index 357f472c651..b15cfa83630 100644 --- a/addons/analytic/static/src/components/analytic_distribution/analytic_distribution.js +++ b/addons/analytic/static/src/components/analytic_distribution/analytic_distribution.js @@ -415,7 +415,7 @@ export class AnalyticDistribution extends Component { async save() { const currentDistribution = this.listForJson; const dataToSave = currentDistribution; - await this.props.update(dataToSave); + await this.props.record.update({ [this.props.name]: dataToSave }); } onSaveNew() { diff --git a/addons/mail/static/src/views/fields/assign_user_command_hook.js b/addons/mail/static/src/views/fields/assign_user_command_hook.js index 39440f3e485..07592037215 100644 --- a/addons/mail/static/src/views/fields/assign_user_command_hook.js +++ b/addons/mail/static/src/views/fields/assign_user_command_hook.js @@ -33,22 +33,26 @@ export function useAssignUserCommand() { const add = async (record) => { if (component.props.type === "many2one") { - component.props.update(record); + component.props.record.update({ [component.props.name]: record }); } else if (component.props.type === "many2many") { - component.props.update({ - operation: "REPLACE_WITH", - resIds: [...getCurrentIds(), record[0]], + component.props.record.update({ + [component.props.name]: { + operation: "REPLACE_WITH", + resIds: [...getCurrentIds(), record[0]], + }, }); } }; const remove = async (record) => { if (component.props.type === "many2one") { - component.props.update([]); + component.props.record.update({ [component.props.name]: [] }); } else if (component.props.type === "many2many") { - component.props.update({ - operation: "REPLACE_WITH", - resIds: getCurrentIds().filter((id) => id !== record[0]), + component.props.record.update({ + [component.props.name]: { + operation: "REPLACE_WITH", + resIds: getCurrentIds().filter((id) => id !== record[0]), + }, }); } }; diff --git a/addons/mrp/static/src/widgets/timer.js b/addons/mrp/static/src/widgets/timer.js index f3d8dedc538..365e2efd3a0 100644 --- a/addons/mrp/static/src/widgets/timer.js +++ b/addons/mrp/static/src/widgets/timer.js @@ -8,7 +8,7 @@ import { standardFieldProps } from "@web/views/fields/standard_field_props"; const { Component, useState, onWillUpdateProps, onWillStart, onWillDestroy } = owl; -function formatMinutes(value) { +export function formatMinutes(value) { if (value === false) { return ""; } diff --git a/addons/project/static/src/project_sharing/components/chatter/chatter_composer.js b/addons/project/static/src/project_sharing/components/chatter/chatter_composer.js index f4219ea8acb..3905c3eba29 100644 --- a/addons/project/static/src/project_sharing/components/chatter/chatter_composer.js +++ b/addons/project/static/src/project_sharing/components/chatter/chatter_composer.js @@ -4,8 +4,7 @@ import { useService } from '@web/core/utils/hooks'; import { TextField } from '@web/views/fields/text/text_field'; import { PortalAttachDocument } from '../portal_attach_document/portal_attach_document'; import { ChatterAttachmentsViewer } from './chatter_attachments_viewer'; - -const { Component, useState, onWillUpdateProps } = owl; +import { Component, useState, onWillUpdateProps, useRef } from "@odoo/owl"; export class ChatterComposer extends Component { setup() { @@ -16,6 +15,7 @@ export class ChatterComposer extends Component { message: '', loading: false, }); + this.inputRef = useRef("textarea"); onWillUpdateProps(this.onWillUpdateProps); } @@ -23,6 +23,7 @@ export class ChatterComposer extends Component { onWillUpdateProps(nextProps) { this.clearErrors(); this.state.message = ''; + this.inputRef.el.value = ""; this.state.attachments = nextProps.attachments.map(file => file.state === 'done'); } @@ -30,9 +31,9 @@ export class ChatterComposer extends Component { return `${window.location.href.split('#')[0]}#discussion`; } - update(change) { + update() { this.clearErrors(); - this.state.message = change; + this.state.message = this.inputRef.el.value; } prepareMessageData() { diff --git a/addons/project/static/src/project_sharing/components/chatter/chatter_composer.xml b/addons/project/static/src/project_sharing/components/chatter/chatter_composer.xml index 6fda276a2a4..47cf7239a38 100644 --- a/addons/project/static/src/project_sharing/components/chatter/chatter_composer.xml +++ b/addons/project/static/src/project_sharing/components/chatter/chatter_composer.xml @@ -20,11 +20,13 @@
- option[0] === value)); + this.props.record.update({ + [this.props.name]: this.options.find((option) => option[0] === value), + }); } break; case "selection": - this.props.update(value); + this.props.record.update({ [this.props.name]: value }); break; } } diff --git a/addons/web/static/src/views/fields/boolean/boolean_field.js b/addons/web/static/src/views/fields/boolean/boolean_field.js index c2eb677138e..fd50b015f83 100644 --- a/addons/web/static/src/views/fields/boolean/boolean_field.js +++ b/addons/web/static/src/views/fields/boolean/boolean_field.js @@ -22,7 +22,7 @@ export class BooleanField extends Component { * @param {boolean} newValue */ onChange(newValue) { - this.props.update(newValue); + this.props.record.update({ [this.props.name]: newValue }); } } diff --git a/addons/web/static/src/views/fields/boolean_favorite/boolean_favorite_field.js b/addons/web/static/src/views/fields/boolean_favorite/boolean_favorite_field.js index f969361e061..e5f0af08a75 100644 --- a/addons/web/static/src/views/fields/boolean_favorite/boolean_favorite_field.js +++ b/addons/web/static/src/views/fields/boolean_favorite/boolean_favorite_field.js @@ -16,6 +16,10 @@ export class BooleanFavoriteField extends Component { static defaultProps = { noLabel: false, }; + + update() { + this.props.record.update({ [this.props.name]: !this.props.value }); + } } export const booleanFavoriteField = { diff --git a/addons/web/static/src/views/fields/boolean_favorite/boolean_favorite_field.xml b/addons/web/static/src/views/fields/boolean_favorite/boolean_favorite_field.xml index a491fe70ebc..16b399a041c 100644 --- a/addons/web/static/src/views/fields/boolean_favorite/boolean_favorite_field.xml +++ b/addons/web/static/src/views/fields/boolean_favorite/boolean_favorite_field.xml @@ -2,7 +2,7 @@ -
+
-
- +
diff --git a/addons/web/static/src/views/fields/statusbar/statusbar_field.js b/addons/web/static/src/views/fields/statusbar/statusbar_field.js index 4131c280a65..ae477bb9942 100644 --- a/addons/web/static/src/views/fields/statusbar/statusbar_field.js +++ b/addons/web/static/src/views/fields/statusbar/statusbar_field.js @@ -192,12 +192,24 @@ export class StatusBarField extends Component { } selectItem(item) { + const rootRecord = + this.props.record.model.root instanceof this.props.record.constructor && + this.props.record.model.root; + const isInEdition = rootRecord ? rootRecord.isInEdition : this.props.record.isInEdition; switch (this.props.type) { case "many2one": - this.props.update([item.id, item.name]); + this.props.record.update({ [this.props.name]: [item.id, item.name] }); + // We save only if we're on view mode readonly and no readonly field modifier + if (!isInEdition) { + return this.props.record.save(); + } break; case "selection": - this.props.update(item.id); + this.props.record.update({ [this.props.name]: item.id }); + // We save only if we're on view mode readonly and no readonly field modifier + if (!isInEdition) { + return this.props.record.save(); + } break; } } diff --git a/addons/web/static/src/views/fields/text/text_field.js b/addons/web/static/src/views/fields/text/text_field.js index f43817ce93b..ef6b17e23f8 100644 --- a/addons/web/static/src/views/fields/text/text_field.js +++ b/addons/web/static/src/views/fields/text/text_field.js @@ -73,9 +73,11 @@ export class TextField extends Component { let dynamicPlaceholder = "{{object." + chain.join("."); dynamicPlaceholder += defaultValue && defaultValue !== "" ? ` or '''${defaultValue}'''}}` : "}}"; - this.props.update( - this.textareaRef.el.value.replace(triggerKeyReplaceRegex, "") + dynamicPlaceholder - ); + this.props.record.update({ + [this.props.name]: + this.textareaRef.el.value.replace(triggerKeyReplaceRegex, "") + + dynamicPlaceholder, + }); } } onDynamicPlaceholderClose() { diff --git a/addons/web/static/src/views/relational_model.js b/addons/web/static/src/views/relational_model.js index 3b594e4a611..ff3fcce2072 100644 --- a/addons/web/static/src/views/relational_model.js +++ b/addons/web/static/src/views/relational_model.js @@ -1669,10 +1669,13 @@ class DynamicList extends DataPoint { fieldNodes: this.model.fieldNodes, }; this.model.trigger("list-confirmation-dialog-will-open"); - await this.model.dialogService.add(ListConfirmationDialog, dialogProps, { - onClose: () => { - this.model.trigger("list-confirmation-dialog-closed"); - }, + await new Promise((resolve) => { + this.model.dialogService.add(ListConfirmationDialog, dialogProps, { + onClose: () => { + this.model.trigger("list-confirmation-dialog-closed"); + resolve(); + }, + }); }); } else { await record._save(); diff --git a/addons/web/static/src/webclient/settings_form_view/fields/upgrade_boolean_field.js b/addons/web/static/src/webclient/settings_form_view/fields/upgrade_boolean_field.js index ac3ade9fb70..f8b1bd8f265 100644 --- a/addons/web/static/src/webclient/settings_form_view/fields/upgrade_boolean_field.js +++ b/addons/web/static/src/webclient/settings_form_view/fields/upgrade_boolean_field.js @@ -24,7 +24,7 @@ export class UpgradeBooleanField extends BooleanField { {}, { onClose: () => { - this.props.update(false); + this.props.record.update({ [this.props.name]: false }); }, } ); diff --git a/addons/web/static/tests/views/list_view_tests.js b/addons/web/static/tests/views/list_view_tests.js index 44e34548b72..516b7ca1b32 100644 --- a/addons/web/static/tests/views/list_view_tests.js +++ b/addons/web/static/tests/views/list_view_tests.js @@ -11811,7 +11811,7 @@ QUnit.module("Views", (hooks) => { ); // Close the confirmation dialog - await click(target.querySelector(".modal .btn-primary")); + await click(target.querySelectorAll(".modal")[1], ".btn-primary"); assert.strictEqual( target.querySelector(".o_data_cell").innerText, diff --git a/addons/web/static/tests/views/record_tests.js b/addons/web/static/tests/views/record_tests.js index 2c54d4fcd91..4008695ff74 100644 --- a/addons/web/static/tests/views/record_tests.js +++ b/addons/web/static/tests/views/record_tests.js @@ -277,7 +277,7 @@ QUnit.module("Record Component", (hooks) => { Parent.components = { Record, Many2OneField }; Parent.template = xml` - + `; diff --git a/addons/web_editor/static/src/js/backend/html_field.js b/addons/web_editor/static/src/js/backend/html_field.js index fa053c9d4ce..9a87a60a4cd 100644 --- a/addons/web_editor/static/src/js/backend/html_field.js +++ b/addons/web_editor/static/src/js/backend/html_field.js @@ -284,7 +284,7 @@ export class HtmlField extends Component { if (value !== null && !(!lastValue && stripHistoryIds(value) === "


") && value !== lastValue) { this.props.setDirty(false); this.currentEditingValue = value; - await this.props.update(value); + await this.props.record.update({ [this.props.name]: value }); } } async startWysiwyg(wysiwyg) { @@ -320,12 +320,12 @@ export class HtmlField extends Component { if (this.state.showCodeView) { this.wysiwyg.odooEditor.toolbarHide(); const value = this.wysiwyg.getValue(); - this.props.update(value); + this.props.record.update({ [this.props.name]: value }); } else { this.wysiwyg.odooEditor.observerActive('toggleCodeView'); const $codeview = $(this.codeViewRef.el); const value = $codeview.val(); - this.props.update(value); + this.props.record.update({ [this.props.name]: value }); } } @@ -562,7 +562,7 @@ export class HtmlField extends Component { checked: !checked, }); if (value) { - this.props.update(value); + this.props.record.update({ [this.props.name]: value }); } } async _onReadonlyClickStar(ev) { @@ -590,7 +590,7 @@ export class HtmlField extends Component { rating, }); if (value) { - this.props.update(value); + this.props.record.update({ [this.props.name]: value }); } } }