From 2ecfed335d469459b50df5e1973d72cf2a47afcf Mon Sep 17 00:00:00 2001 From: FrancoisGe Date: Tue, 21 Mar 2023 14:59:52 +0000 Subject: [PATCH] [REF] *: extractProps receive dynamicInfo Before this commit, the use of multiple with the same name in a view was not well supported. Why was this? Some Field components need to know information related to the such as context, domain, required and readonly. The solution used before this commit to access this information is to use the getFieldContext, getFieldDomain, isReadonly, isRequired functions of the model. Unfortunately, these only take into account the last occurrence of the because the model is not aware that the same field is present several times on the view. The information must therefore not come from the model. For example, it was not possible to have the same field twice with 2 different domains. It will use the domain of the last field for both. Solution: We will add the object "dynamicInfo" to the fieldInfo passed to the Fields extractProps function. This object will contain a getter to get the value of required, readonly, domain and context for the current . If a Field needs one of its information, it will just have to get it from extractProps. Part of Task: 3179751 closes odoo/odoo#115197 Related: odoo/enterprise#38151 Signed-off-by: Aaron Bohy (aab) --- .../src/views/fields/many2many_attendee.js | 7 +- .../filterable_selection_field.js | 11 +-- .../web/fields/assign_user_command_hook.js | 9 +- .../many2many_tags_email.js | 12 ++- .../many2one_avatar_user_field.js | 22 +++-- .../static/src/js/mailing_m2o_filter.js | 11 +-- .../static/src/js/mass_mailing_html_field.js | 13 +-- .../project_task_state_selection.js | 12 +-- .../project_task_state_selection.xml | 6 +- .../project_task_priority_switch_field.js | 9 +- .../sale/static/src/js/sale_product_field.js | 57 ++++++++----- .../src/components/phone_field/phone_field.js | 9 +- .../src/legacy/js/views/basic/basic_model.js | 4 +- .../src/views/basic_relational_model.js | 38 +++++---- .../badge_selection/badge_selection_field.js | 4 +- .../src/views/fields/boolean/boolean_field.js | 8 -- .../views/fields/boolean/boolean_field.xml | 2 +- .../boolean_toggle/boolean_toggle_field.js | 11 +-- .../list_boolean_toggle_field.js | 2 +- .../src/views/fields/color/color_field.js | 12 +-- .../src/views/fields/color/color_field.xml | 4 +- .../src/views/fields/domain/domain_field.js | 14 ++-- addons/web/static/src/views/fields/field.js | 52 ++++++++++-- .../fields/float_factor/float_factor_field.js | 9 +- .../font_selection/font_selection_field.js | 13 +-- .../font_selection/font_selection_field.xml | 2 +- .../many2many_checkboxes_field.js | 4 +- .../many2many_tags/many2many_tags_field.js | 28 +++---- .../many2many_tags/many2many_tags_field.xml | 2 +- .../many2many_tags_avatar_field.js | 23 ++--- .../many2many_tags_avatar_field.xml | 2 +- .../views/fields/many2one/many2one_field.js | 20 +++-- .../many2one_avatar/many2one_avatar_field.js | 20 ++--- .../many2one_barcode_field.js | 9 +- .../views/fields/priority/priority_field.js | 12 +-- .../views/fields/priority/priority_field.xml | 2 +- .../properties/kanban_properties_field.xml | 2 +- .../fields/properties/properties_field.js | 23 ++--- .../fields/properties/properties_field.xml | 2 +- .../src/views/fields/radio/radio_field.js | 4 +- .../views/fields/reference/reference_field.js | 9 +- .../views/fields/selection/selection_field.js | 17 ++-- .../fields/selection/selection_field.xml | 2 +- .../state_selection/state_selection_field.js | 20 ++--- .../state_selection/state_selection_field.xml | 2 +- .../views/fields/statusbar/statusbar_field.js | 8 +- .../timezone_mismatch_field.js | 11 +-- .../src/views/fields/x2many/x2many_field.js | 14 ++-- .../static/src/views/list/list_renderer.js | 28 +++---- .../static/src/views/list/list_renderer.xml | 2 +- .../web/static/src/views/relational_model.js | 56 +++++++------ .../tests/legacy/views/basic_model_tests.js | 56 ------------- .../views/fields/many2one_field_tests.js | 54 ------------ .../views/fields/one2many_field_tests.js | 5 +- .../tests/views/form/form_view_tests.js | 83 ------------------- .../static/src/js/backend/html_field.js | 6 +- 56 files changed, 381 insertions(+), 498 deletions(-) diff --git a/addons/calendar/static/src/views/fields/many2many_attendee.js b/addons/calendar/static/src/views/fields/many2many_attendee.js index 7459a970fb1..723ac3aabed 100644 --- a/addons/calendar/static/src/views/fields/many2many_attendee.js +++ b/addons/calendar/static/src/views/fields/many2many_attendee.js @@ -39,15 +39,14 @@ export const many2ManyAttendee = { registry.category("fields").add("many2manyattendee", many2ManyAttendee); -export function preloadMany2ManyAttendee(orm, record, fieldName) { - const context = record.getFieldContext(fieldName); +export function preloadMany2ManyAttendee(orm, record, fieldName, { context }) { return orm.call( "res.partner", "get_attendee_detail", - [record.data[fieldName].records.map(rec => rec.resId), [record.resId || false]], + [record.data[fieldName].records.map((rec) => rec.resId), [record.resId || false]], { context, - }, + } ); } diff --git a/addons/loyalty/static/src/js/filterable_selection_field/filterable_selection_field.js b/addons/loyalty/static/src/js/filterable_selection_field/filterable_selection_field.js index e27de0e3f0d..eb01defd0e9 100644 --- a/addons/loyalty/static/src/js/filterable_selection_field/filterable_selection_field.js +++ b/addons/loyalty/static/src/js/filterable_selection_field/filterable_selection_field.js @@ -36,11 +36,12 @@ FilterableSelectionField.props = { export const filterableSelectionField = { ...selectionField, component: FilterableSelectionField, - extractProps: (fieldInfo) => ({ - ...selectionField.extractProps(fieldInfo), - whitelisted_values: fieldInfo.options.whitelisted_values, - blacklisted_values: fieldInfo.options.blacklisted_values, - }), + extractProps({ options }) { + const props = selectionField.extractProps(...arguments); + props.whitelisted_values = options.whitelisted_values; + props.blacklisted_values = options.blacklisted_values; + return props; + }, }; registry.category("fields").add("filterable_selection", filterableSelectionField); diff --git a/addons/mail/static/src/web/fields/assign_user_command_hook.js b/addons/mail/static/src/web/fields/assign_user_command_hook.js index 3647b7a34c2..793efd7428f 100644 --- a/addons/mail/static/src/web/fields/assign_user_command_hook.js +++ b/addons/mail/static/src/web/fields/assign_user_command_hook.js @@ -57,17 +57,18 @@ export function useAssignUserCommand() { const provide = async (env, options) => { const value = options.searchValue.trim(); - let domain = component.props.record.getFieldDomain(component.props.name); - const context = component.props.record.getFieldContext(component.props.name); + let domain = + component.props.domain || component.props.record.getFieldDomain(component.props.name); + const context = component.props.context; if (type === "many2many") { const selectedUserIds = getCurrentIds(); if (selectedUserIds.length) { - domain = Domain.and([domain, [["id", "not in", selectedUserIds]]]); + domain = Domain.and([domain, [["id", "not in", selectedUserIds]]]).toList(); } } const searchResult = await orm.call(component.relation, "name_search", [], { name: value, - args: domain.toList(), + args: domain, operator: "ilike", limit: 80, context, diff --git a/addons/mail/static/src/web/fields/many2many_tags_email/many2many_tags_email.js b/addons/mail/static/src/web/fields/many2many_tags_email/many2many_tags_email.js index 51a5f783c55..d58c02f30d6 100644 --- a/addons/mail/static/src/web/fields/many2many_tags_email/many2many_tags_email.js +++ b/addons/mail/static/src/web/fields/many2many_tags_email/many2many_tags_email.js @@ -17,6 +17,11 @@ export class FieldMany2ManyTagsEmailTagsList extends TagsList {} FieldMany2ManyTagsEmailTagsList.template = "FieldMany2ManyTagsEmailTagsList"; export class FieldMany2ManyTagsEmail extends Many2ManyTagsField { + static props = { + ...Many2ManyTagsField.props, + context: { type: Object, optional: true }, + }; + setup() { super.setup(); @@ -54,7 +59,7 @@ export class FieldMany2ManyTagsEmail extends Many2ManyTagsField { dialogDefs.push( this.openMany2xRecord({ resId: record.resId, - context: props.record.getFieldContext(this.props.name), + context: props.context, title: sprintf(_t("Edit: %s"), record.data.display_name), }) ); @@ -101,6 +106,11 @@ FieldMany2ManyTagsEmail.components = { export const fieldMany2ManyTagsEmail = { ...many2ManyTagsField, component: FieldMany2ManyTagsEmail, + extractProps(fieldInfo, dynamicInfo) { + const props = many2ManyTagsField.extractProps(...arguments); + props.context = dynamicInfo.context; + return props; + }, relatedFields: (fieldInfo) => { return [...many2ManyTagsField.relatedFields(fieldInfo), { name: "email", type: "char" }]; }, diff --git a/addons/mail/static/src/web/fields/many2one_avatar_user_field/many2one_avatar_user_field.js b/addons/mail/static/src/web/fields/many2one_avatar_user_field/many2one_avatar_user_field.js index 6485697cfcb..a3bc7d4ae53 100644 --- a/addons/mail/static/src/web/fields/many2one_avatar_user_field/many2one_avatar_user_field.js +++ b/addons/mail/static/src/web/fields/many2one_avatar_user_field/many2one_avatar_user_field.js @@ -29,6 +29,8 @@ export class Many2OneAvatarUserField extends Many2OneAvatarField { static template = "mail.Many2OneAvatarUserField"; static props = { ...Many2OneAvatarField.props, + context: { type: Object, optional: true }, + domain: { type: Array, optional: true }, withCommand: { type: Boolean, optional: true }, }; } @@ -38,10 +40,13 @@ export const many2OneAvatarUserField = { ...many2OneAvatarField, component: Many2OneAvatarUserField, additionalClasses: ["o_field_many2one_avatar"], - extractProps: (fieldInfo) => ({ - ...many2OneAvatarField.extractProps(fieldInfo), - withCommand: fieldInfo.viewType === "form", - }), + extractProps(fieldInfo, dynamicInfo) { + const props = many2OneAvatarField.extractProps(...arguments); + props.context = dynamicInfo.context; + props.domain = dynamicInfo.domain; + props.withCommand = fieldInfo.viewType === "form"; + return props; + }, }; registry.category("fields").add("many2one_avatar_user", many2OneAvatarUserField); @@ -77,10 +82,11 @@ export const kanbanMany2OneAvatarUserField = { ...kanbanMany2OneAvatarField, component: KanbanMany2OneAvatarUserField, additionalClasses: [...kanbanMany2OneAvatarField.additionalClasses, "o_field_many2one_avatar"], - extractProps: (fieldInfo) => ({ - ...kanbanMany2OneAvatarField.extractProps(fieldInfo), - displayAvatarName: fieldInfo.options.display_avatar_name || false, - }), + extractProps({ options }) { + const props = kanbanMany2OneAvatarField.extractProps(...arguments); + props.displayAvatarName = options.display_avatar_name || false; + return props; + }, }; registry.category("fields").add("kanban.many2one_avatar_user", kanbanMany2OneAvatarUserField); diff --git a/addons/mass_mailing/static/src/js/mailing_m2o_filter.js b/addons/mass_mailing/static/src/js/mailing_m2o_filter.js index 740100d5081..42d5c63ddfb 100644 --- a/addons/mass_mailing/static/src/js/mailing_m2o_filter.js +++ b/addons/mass_mailing/static/src/js/mailing_m2o_filter.js @@ -153,11 +153,12 @@ FieldMany2OneMailingFilter.defaultProps = { export const fieldMany2OneMailingFilter = { ...many2OneField, component: FieldMany2OneMailingFilter, - extractProps: (fieldInfo) => ({ - ...many2OneField.extractProps(fieldInfo), - domain_field: fieldInfo.options.domain_field, - model_field: fieldInfo.options.model_field, - }), + extractProps({ options }) { + const props = many2OneField.extractProps(...arguments); + props.domain_field = options.domain_field; + props.model_field = options.model_field; + return props; + }, }; registry.category("fields").add("mailing_filter", fieldMany2OneMailingFilter); diff --git a/addons/mass_mailing/static/src/js/mass_mailing_html_field.js b/addons/mass_mailing/static/src/js/mass_mailing_html_field.js index 65a96dbb685..614e62f17ec 100644 --- a/addons/mass_mailing/static/src/js/mass_mailing_html_field.js +++ b/addons/mass_mailing/static/src/js/mass_mailing_html_field.js @@ -609,12 +609,13 @@ export const massMailingHtmlField = { ...htmlField, component: MassMailingHtmlField, displayName: _lt("Email"), - extractProps: (fieldInfo) => ({ - ...htmlField.extractProps(fieldInfo), - filterTemplates: fieldInfo.options.filterTemplates, - inlineField: fieldInfo.options['inline-field'], - iframeHtmlClass: fieldInfo.attrs.iframeHtmlClass, - }), + extractProps({ attrs, options }) { + const props = htmlField.extractProps(...arguments); + props.filterTemplates = options.filterTemplates; + props.inlineField = options['inline-field']; + props.iframeHtmlClass = attrs.iframeHtmlClass; + return props; + }, }; registry.category("fields").add("mass_mailing_html", massMailingHtmlField); diff --git a/addons/project/static/src/components/project_task_state_selection/project_task_state_selection.js b/addons/project/static/src/components/project_task_state_selection/project_task_state_selection.js index 6216abc5fd2..7d016d75a6e 100644 --- a/addons/project/static/src/components/project_task_state_selection/project_task_state_selection.js +++ b/addons/project/static/src/components/project_task_state_selection/project_task_state_selection.js @@ -169,12 +169,12 @@ export const projectTaskStateSelection = { ...stateSelectionField, component: ProjectTaskStateSelection, fieldDependencies: [{ name: "project_id", type: "many2one" }], - extractProps: ({ options, viewType }) => ({ - ...stateSelectionField.extractProps({ options }), - isToggleMode: Boolean(options.is_toggle_mode), - viewType, - }), - + extractProps({ options, viewType }) { + const props = stateSelectionField.extractProps(...arguments); + props.isToggleMode = Boolean(options.is_toggle_mode); + props.viewType = viewType; + return props; + }, } registry.category("fields").add("project_task_state_selection", projectTaskStateSelection); diff --git a/addons/project/static/src/components/project_task_state_selection/project_task_state_selection.xml b/addons/project/static/src/components/project_task_state_selection/project_task_state_selection.xml index 7a4bf701f7d..91b417c6ccc 100644 --- a/addons/project/static/src/components/project_task_state_selection/project_task_state_selection.xml +++ b/addons/project/static/src/components/project_task_state_selection/project_task_state_selection.xml @@ -1,11 +1,11 @@ - + {{ stateIcon(currentValue) }} {{ statusColor(currentValue) }} - +