From 8cde3e84bb70a2bd097921c08c0059bf65bee602 Mon Sep 17 00:00:00 2001 From: Jorge Pinna Puissant Date: Tue, 14 Feb 2023 15:02:41 +0000 Subject: [PATCH] [REF] web, * : simplify concrete fields API - remove update prop This commit, is part of a series of commits that aim to simplifie the concrete fields API. In this commit we will remove update prop from concrete fields. Now each field will directly use this.props.record.update to make changes, and handle the save in fields that need to (e.g. priority). As a consequence of this, the record props need to be mandatory. task-id 3179751 Part-of: odoo/odoo#112792 --- .../analytic_distribution.js | 2 +- .../views/fields/assign_user_command_hook.js | 20 +++++++++------- addons/mrp/static/src/widgets/timer.js | 2 +- .../components/chatter/chatter_composer.js | 9 ++++---- .../components/chatter/chatter_composer.xml | 10 ++++---- .../static/src/views/fields/ace/ace_field.js | 2 +- .../badge_selection/badge_selection_field.js | 8 ++++--- .../src/views/fields/boolean/boolean_field.js | 2 +- .../boolean_favorite_field.js | 4 ++++ .../boolean_favorite_field.xml | 2 +- .../fields/boolean_icon/boolean_icon_field.js | 4 ++++ .../boolean_icon/boolean_icon_field.xml | 2 +- .../boolean_toggle/boolean_toggle_field.js | 12 ++++++++++ .../list_boolean_toggle_field.js | 2 +- .../src/views/fields/char/char_field.js | 7 +++--- .../src/views/fields/color/color_field.xml | 2 +- .../fields/color_picker/color_picker_field.js | 2 +- .../src/views/fields/date/date_field.js | 2 +- .../views/fields/daterange/daterange_field.js | 2 +- .../views/fields/datetime/datetime_field.js | 2 +- .../src/views/fields/domain/domain_field.js | 4 ++-- addons/web/static/src/views/fields/field.js | 14 ----------- .../src/views/fields/float/float_field.js | 10 +++++--- .../fields/float_factor/float_factor_field.js | 23 ++++++++----------- .../float_factor/float_factor_field.xml | 8 ------- .../fields/float_toggle/float_toggle_field.js | 4 +++- .../font_selection/font_selection_field.js | 2 +- .../src/views/fields/image/image_field.js | 4 ++-- .../src/views/fields/input_field_hook.js | 17 ++++++-------- .../views/fields/many2one/many2one_field.js | 16 +++++++++---- .../views/fields/priority/priority_field.js | 18 ++++++++++++--- .../fields/properties/properties_field.js | 10 ++++---- .../src/views/fields/radio/radio_field.js | 4 ++-- .../views/fields/reference/reference_field.js | 15 ++++++------ .../remaining_days/remaining_days_field.js | 4 ++-- .../views/fields/selection/selection_field.js | 8 ++++--- .../views/fields/signature/signature_field.js | 2 +- .../src/views/fields/standard_field_props.js | 3 +-- .../state_selection/state_selection_field.js | 14 ++++++++++- .../state_selection/state_selection_field.xml | 2 +- .../views/fields/statusbar/statusbar_field.js | 16 +++++++++++-- .../src/views/fields/text/text_field.js | 8 ++++--- .../web/static/src/views/relational_model.js | 11 +++++---- .../fields/upgrade_boolean_field.js | 2 +- .../web/static/tests/views/list_view_tests.js | 2 +- addons/web/static/tests/views/record_tests.js | 2 +- .../static/src/js/backend/html_field.js | 10 ++++---- 47 files changed, 194 insertions(+), 137 deletions(-) delete mode 100644 addons/web/static/src/views/fields/float_factor/float_factor_field.xml 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 }); } } }