[FIX] web: domain selector: operators with same key

Before that commit, we could get two operators with the same key to
display at the same time. In that case, an error would be thrown by OWL:
Got duplicate key in t-foreach... . We fix that problem.

Part-of: odoo/odoo#121688
This commit is contained in:
Mathieu Duckerts-Antoine
2023-07-13 14:47:11 +02:00
parent cb8a590bfa
commit a3b00f2dca
3 changed files with 39 additions and 5 deletions
@@ -11,7 +11,7 @@ import { Component, onWillStart, onWillUpdateProps } from "@odoo/owl";
import { Domain } from "@web/core/domain";
import { Dropdown } from "@web/core/dropdown/dropdown";
import { DropdownItem } from "@web/core/dropdown/dropdown_item";
import { getOperatorInfo } from "@web/core/domain_selector/domain_selector_operators";
import { getOperatorInfo, toOperator } from "@web/core/domain_selector/domain_selector_operators";
import {
Editor,
PathEditor,
@@ -207,8 +207,10 @@ export class DomainSelector extends Component {
this.notifyChanges();
}
updateLeafOperator(node, operator) {
updateLeafOperator(node, operatorKey) {
const [operator, negate] = toOperator(operatorKey);
const previousOperatorInfo = getOperatorInfo(node.operator);
node.negate = negate;
node.operator = operator;
const operatorInfo = getOperatorInfo(operator);
if (previousOperatorInfo.valueCount !== operatorInfo.valueCount) {
@@ -1,8 +1,9 @@
/** @odoo-module **/
import { _lt } from "@web/core/l10n/translation";
import { formatValue } from "@web/core/domain_tree";
import { formatValue, toValue } from "@web/core/domain_tree";
import { sprintf } from "@web/core/utils/strings";
import { parseExpr } from "@web/core/py_js/py";
/**
* @typedef {Object} OperatorInfo
@@ -41,6 +42,22 @@ export const OPERATOR_DESCRIPTIONS = {
between: { label: _lt("is between"), valueCount: 2 },
};
function toKey(operator, negate = false) {
if (!negate && typeof operator === "string" && operator in OPERATOR_DESCRIPTIONS) {
// this case is the main one. We keep it simple
return operator;
}
return JSON.stringify([formatValue(operator), negate]);
}
export function toOperator(key) {
if (!key.includes("[")) {
return [key, false];
}
const [expr, negate] = JSON.parse(key);
return [toValue(parseExpr(expr)), negate];
}
/**
* @param {import("@web/core/domain_tree").Value} operator
* @param {boolean} [negate=false]
@@ -48,12 +65,19 @@ export const OPERATOR_DESCRIPTIONS = {
*/
export function getOperatorInfo(operator, negate = false) {
let operatorInfo;
const key = toKey(operator, negate);
if (typeof operator === "string" && operator in OPERATOR_DESCRIPTIONS) {
const { label, valueCount } = OPERATOR_DESCRIPTIONS[operator];
operatorInfo = { key: operator, label: label.toString(), operator, negate, valueCount };
operatorInfo = {
key,
label: label.toString(),
operator,
negate,
valueCount,
};
} else {
operatorInfo = {
key: "__unknown__",
key,
label: formatValue(operator),
operator,
negate,
@@ -1405,4 +1405,12 @@ QUnit.module("Components", (hooks) => {
});
assert.strictEqual(target.querySelector(".o_domain_leaf").textContent, `Foo = uid`);
});
QUnit.test("display of an operator without negation defined (edit)", async (assert) => {
await makeDomainSelector({
resModel: "partner",
domain: `["!", (expr, "parent_of", "a")]`,
});
assert.strictEqual(getSelectedOperator(target), `not parent of`);
});
});