diff --git a/addons/web/static/src/views/fields/many2one/many2one_field.js b/addons/web/static/src/views/fields/many2one/many2one_field.js index e361bd293c1..9fec3b28898 100644 --- a/addons/web/static/src/views/fields/many2one/many2one_field.js +++ b/addons/web/static/src/views/fields/many2one/many2one_field.js @@ -1,15 +1,16 @@ /** @odoo-module **/ import { browser } from "@web/core/browser/browser"; +import { isMobileOS } from "@web/core/browser/feature_detection"; import { Dialog } from "@web/core/dialog/dialog"; -import { registry } from "@web/core/registry"; import { _lt } from "@web/core/l10n/translation"; +import { evaluateExpr } from "@web/core/py_js/py"; +import { registry } from "@web/core/registry"; import { useChildRef, useOwnedDialogs, useService } from "@web/core/utils/hooks"; import { sprintf } from "@web/core/utils/strings"; -import { standardFieldProps } from "../standard_field_props"; import { Many2XAutocomplete, useOpenMany2XRecord } from "@web/views/fields/relational_utils"; -import { isMobileOS } from "@web/core/browser/feature_detection"; import * as BarcodeScanner from "@web/webclient/barcode/barcode_scanner"; +import { standardFieldProps } from "../standard_field_props"; import { Component, onWillUpdateProps, useState } from "@odoo/owl"; @@ -61,6 +62,7 @@ export class Many2OneField extends Component { canScanBarcode: { type: Boolean, optional: true }, update: { type: Function, optional: true }, value: { optional: true }, + decorations: { type: Object, optional: true }, }; static defaultProps = { canOpen: true, @@ -73,6 +75,7 @@ export class Many2OneField extends Component { string: "", canScanBarcode: false, context: {}, + decorations: {}, }; static SEARCH_MORE_LIMIT = 320; @@ -160,6 +163,15 @@ export class Many2OneField extends Component { get context() { return this.props.context; } + get classFromDecoration() { + const evalContext = this.props.record.evalContext; + for (const decorationName in this.props.decorations) { + if (evaluateExpr(this.props.decorations[decorationName], evalContext)) { + return `text-${decorationName}`; + } + } + return ""; + } get displayName() { return this.value ? this.value[1].split("\n")[0] : ""; } @@ -299,7 +311,7 @@ export const many2OneField = { component: Many2OneField, displayName: _lt("Many2one"), supportedTypes: ["many2one"], - extractProps({ attrs, options, string }, dynamicInfo) { + extractProps({ attrs, decorations, options, string }, dynamicInfo) { const canCreate = attrs.can_create && Boolean(JSON.parse(attrs.can_create)) && !options.no_create; return { @@ -310,6 +322,7 @@ export const many2OneField = { canQuickCreate: canCreate && !options.no_quick_create, canCreateEdit: canCreate && !options.no_create_edit, context: dynamicInfo.context, + decorations, domain: dynamicInfo.domain, nameCreateField: options.create_name_field, canScanBarcode: !!options.can_scan_barcode, diff --git a/addons/web/static/src/views/fields/many2one/many2one_field.xml b/addons/web/static/src/views/fields/many2one/many2one_field.xml index c5fc1bbe65e..89067067251 100644 --- a/addons/web/static/src/views/fields/many2one/many2one_field.xml +++ b/addons/web/static/src/views/fields/many2one/many2one_field.xml @@ -27,7 +27,7 @@ diff --git a/addons/web/static/tests/views/fields/many2one_field_tests.js b/addons/web/static/tests/views/fields/many2one_field_tests.js index cc3ac1cae4f..2e843444412 100644 --- a/addons/web/static/tests/views/fields/many2one_field_tests.js +++ b/addons/web/static/tests/views/fields/many2one_field_tests.js @@ -775,6 +775,25 @@ QUnit.module("Fields", (hooks) => { } ); + QUnit.test( + "using a many2one widget must take into account the decorations", + async function (assert) { + await makeView({ + type: "list", + resModel: "partner", + serverData, + arch: ` + + + + `, + }); + + assert.containsOnce(target, ".o_list_many2one a.text-danger"); + assert.containsN(target, ".o_data_row", 3); + } + ); + QUnit.test( "onchanges on many2ones trigger when editing record in form view", async function (assert) {