[FIX] web: domain selector dialog: validate domain on confirm

With ab4f45b, the domain validation done
on confirmation in the domain selector dialog was removed. Now that we
have a new route /web/domain/validate (see previous commit) that allows
us to quickly check the validity of a domain, we can reintroduce the
validation.

closes odoo/odoo#128913

X-original-commit: fa7788fac3c48e95dcbe78abb66ac5c284d27c56
Related: odoo/enterprise#44291
Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
Signed-off-by: Mathieu Duckerts-Antoine (dam) <dam@odoo.com>
This commit is contained in:
Mathieu Duckerts-Antoine
2023-07-19 11:40:10 +02:00
parent afdb546e44
commit 4e70ca384d
5 changed files with 124 additions and 15 deletions
@@ -10,6 +10,7 @@ import { useService } from "../utils/hooks";
export class DomainSelectorDialog extends Component {
setup() {
this.notification = useService("notification");
this.rpc = useService("rpc");
this.orm = useService("orm");
this.user = useService("user");
this.state = useState({ domain: this.props.domain });
@@ -50,13 +51,23 @@ export class DomainSelectorDialog extends Component {
};
}
onConfirm() {
async onConfirm() {
this.confirmButtonRef.el.disabled = true;
const evalContext = { ...this.user.context, ...this.props.context };
let domain;
let isValid;
try {
const domain = new Domain(this.state.domain);
domain.toList(evalContext);
const evalContext = { ...this.user.context, ...this.props.context };
domain = new Domain(this.state.domain).toList(evalContext);
} catch {
isValid = false;
}
if (isValid === undefined) {
isValid = await this.rpc("/web/domain/validate", {
model: this.props.resModel,
domain,
});
}
if (!isValid) {
if (this.confirmButtonRef.el) {
this.confirmButtonRef.el.disabled = false;
}
@@ -109,15 +109,16 @@ QUnit.module("Components", (hooks) => {
assert.strictEqual(domain, "[('foo', '=', uid)]");
assert.step("confirmed");
},
mockRPC(_, args) {
if (args.method === "search_count") {
assert.step("rpc validation");
mockRPC(route) {
if (route === "/web/domain/validate") {
assert.step("validation");
return true;
}
},
});
const confirmButton = fixture.querySelector(".o_dialog footer button");
await click(confirmButton);
assert.verifySteps(["confirmed"]);
assert.verifySteps(["validation", "confirmed"]);
});
QUnit.test("can extend eval context", async (assert) => {
@@ -129,15 +130,16 @@ QUnit.module("Components", (hooks) => {
assert.step("confirmed");
},
mockRPC(_, args) {
if (args.method === "search_count") {
assert.step("rpc validation");
mockRPC(route) {
if (route === "/web/domain/validate") {
assert.step("validation");
return true;
}
},
});
const confirmButton = fixture.querySelector(".o_dialog footer button");
await click(confirmButton);
assert.verifySteps(["confirmed"]);
assert.verifySteps(["validation", "confirmed"]);
});
QUnit.test("a domain with an unknown expression is not valid", async (assert) => {
@@ -146,9 +148,9 @@ QUnit.module("Components", (hooks) => {
onConfirm() {
assert.step("confirmed");
},
mockRPC(_, args) {
if (args.method === "search_count") {
assert.step("rpc validation");
mockRPC(route) {
if (route === "/web/domain/validate") {
assert.step("validation");
}
},
});
@@ -1612,6 +1612,11 @@ QUnit.module("Search", (hooks) => {
context: {
search_default_filter: true,
},
mockRPC(route) {
if (route === "/web/domain/validate") {
return true;
}
},
});
assert.deepEqual(getFacetTexts(target), ["Filter"]);
assert.deepEqual(getDomain(controlPanel), [["foo", "=", "abc"]]);
@@ -1669,6 +1674,11 @@ QUnit.module("Search", (hooks) => {
searchMenuTypes: ["filter"],
searchViewId: false,
searchViewArch: `<search />`,
mockRPC(route) {
if (route === "/web/domain/validate") {
return true;
}
},
});
assert.deepEqual(getFacetTexts(target), []);
assert.deepEqual(getDomain(controlPanel), []);
@@ -1694,6 +1704,11 @@ QUnit.module("Search", (hooks) => {
searchMenuTypes: ["filter"],
searchViewId: false,
searchViewArch: `<search />`,
mockRPC(route) {
if (route === "/web/domain/validate") {
return true;
}
},
});
assert.deepEqual(getFacetTexts(target), []);
assert.deepEqual(getDomain(controlPanel), []);
@@ -1717,6 +1732,11 @@ QUnit.module("Search", (hooks) => {
searchMenuTypes: ["filter"],
searchViewId: false,
searchViewArch: `<search />`,
mockRPC(route) {
if (route === "/web/domain/validate") {
return true;
}
},
});
await toggleSearchBarMenu(target);
await openAddCustomFilterDialog(target);
@@ -1747,6 +1767,11 @@ QUnit.module("Search", (hooks) => {
resModel: "foo",
Component: SearchBar,
searchMenuTypes: ["filter"],
mockRPC(route) {
if (route === "/web/domain/validate") {
return true;
}
},
});
assert.deepEqual(getFacetTexts(target), []);
assert.deepEqual(getDomain(controlPanel), []);
@@ -1796,6 +1821,42 @@ QUnit.module("Search", (hooks) => {
assert.deepEqual(getDomain(controlPanel), [["boolean", "!=", true]]);
});
QUnit.test("Add a custom filter: notification on invalid domain", async function (assert) {
assert.expect(3);
patchWithCleanup(odoo, { debug: true });
registry.category("services").add(
"notification",
{
start() {
return {
add(message, options) {
assert.strictEqual(message, "Domain is invalid. Please correct it");
assert.deepEqual(options, { type: "danger" });
},
};
},
},
{ force: true }
);
await makeWithSearch({
serverData,
resModel: "foo",
Component: SearchBar,
searchMenuTypes: ["filter"],
mockRPC(route) {
if (route === "/web/domain/validate") {
return false;
}
},
});
await toggleSearchBarMenu(target);
await openAddCustomFilterDialog(target);
await editInput(target, ".o_domain_debug_input", "[(uid, uid, uid)]");
await click(target.querySelector(".modal footer button"));
assert.containsOnce(target, ".modal .o_domain_selector");
});
QUnit.test("display names in facets", async function (assert) {
patchWithCleanup(odoo, { debug: true });
serverData.models.partner = {
@@ -1813,6 +1874,11 @@ QUnit.module("Search", (hooks) => {
searchMenuTypes: ["filter"],
searchViewId: false,
searchViewArch: `<search />`,
mockRPC(route) {
if (route === "/web/domain/validate") {
return true;
}
},
});
await toggleSearchBarMenu(target);
await openAddCustomFilterDialog(target);
@@ -1440,6 +1440,11 @@ QUnit.module("Search", (hooks) => {
search_default_filter: true,
search_default_bool: true,
},
mockRPC(route) {
if (route === "/web/domain/validate") {
return true;
}
},
});
assert.deepEqual(getFacetTexts(target), ["Filter", "Bool"]);
assert.containsN(target, ".o_searchview_facet .o_searchview_facet_label", 2);
@@ -1497,6 +1502,11 @@ QUnit.module("Search", (hooks) => {
context: {
search_default_filter: true,
},
mockRPC(route) {
if (route === "/web/domain/validate") {
return true;
}
},
});
assert.deepEqual(getFacetTexts(target), ["Filter"]);
assert.deepEqual(getContext(controlPanel).specialKey, "abc");
@@ -1533,6 +1543,11 @@ QUnit.module("Search", (hooks) => {
</search>
`,
irFilters,
mockRPC(route) {
if (route === "/web/domain/validate") {
return true;
}
},
});
assert.deepEqual(getFacetTexts(target), ["My favorite"]);
assert.containsOnce(
@@ -1578,6 +1593,11 @@ QUnit.module("Search", (hooks) => {
context: {
search_default_birthday: true,
},
mockRPC(route) {
if (route === "/web/domain/validate") {
return true;
}
},
});
assert.deepEqual(getFacetTexts(target), ["Birthday: April 2023"]);
assert.containsOnce(
@@ -1633,6 +1653,11 @@ QUnit.module("Search", (hooks) => {
context: {
search_default_foo: "abc",
},
mockRPC(route) {
if (route === "/web/domain/validate") {
return true;
}
},
});
assert.deepEqual(getFacetTexts(target), ["Foo\nabc"]);
assert.containsOnce(
@@ -914,6 +914,11 @@ QUnit.module("Fields", (hooks) => {
<form>
<field name="display_name" widget="domain" options="{'model': 'partner', 'in_dialog': True}"/>
</form>`,
mockRPC: (route) => {
if (route === "/web/domain/validate") {
return true;
}
},
});
assert.containsNone(target, ".o_domain_leaf");
assert.containsNone(target, ".modal");