[FIX] web: decoration on a many2one field

Before this commit, in a list view, the style of a decoration on a m2o
widget was ignored. For example, when applying the danger decoration,
we want the m2o field to be in red.

How to reproduce:

Go to a list view with a field having the many2one widget and
a danger-decoration.
Have a line that respects the decoration condition.
Before this commit:
m2o field text uses its base colour (blue)

After this commit:
m2o field text uses the colour red for danger decoration

closes odoo/odoo#116621

Forward-port-of: #115831
X-original-commit: 9e0eac2
Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
This commit is contained in:
FrancoisGe
2023-03-29 09:33:38 +02:00
parent 4e974e5977
commit a7ed23a41c
3 changed files with 37 additions and 5 deletions
@@ -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,
@@ -27,7 +27,7 @@
<t t-else="">
<a
t-if="value"
class="o_form_uri"
t-attf-class="o_form_uri #{classFromDecoration}"
t-att-href="value ? `#id=${value[0]}&amp;model=${relation}` : '#'"
t-on-click.prevent="onClick"
>
@@ -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: `
<tree>
<field name="user_id" decoration-danger="int_field > 9" widget="many2one"/>
<field name="int_field"/>
</tree>`,
});
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) {