diff --git a/addons/web/static/src/views/fields/domain/domain_field.js b/addons/web/static/src/views/fields/domain/domain_field.js
index 37719cea4c104..3c27a2958ef3a 100644
--- a/addons/web/static/src/views/fields/domain/domain_field.js
+++ b/addons/web/static/src/views/fields/domain/domain_field.js
@@ -25,10 +25,12 @@ export class DomainField extends Component {
editInDialog: { type: Boolean, optional: true },
resModel: { type: String, optional: true },
isFoldable: { type: Boolean, optional: true },
+ countLimit: { type: Number, optional: true },
};
static defaultProps = {
editInDialog: false,
isFoldable: false,
+ countLimit: 10000,
};
setup() {
@@ -41,6 +43,7 @@ export class DomainField extends Component {
this.state = useState({
isValid: null,
recordCount: null,
+ hasLimitedCount: null,
folded: this.props.isFoldable,
facets: [],
});
@@ -169,24 +172,32 @@ export class DomainField extends Component {
const domain = this.getEvaluatedDomain(props);
if (domain.isInvalid) {
- this.updateState({ isValid: false, recordCount: 0 });
+ this.updateState({ isValid: false, recordCount: 0, hasLimitedCount: false });
return;
}
let recordCount;
+ let hasLimitedCount = false;
const context = this.getContext(props);
+ let limit;
+ if (props.countLimit !== Number.MAX_SAFE_INTEGER) {
+ limit = props.countLimit + 1;
+ }
try {
- recordCount = await this.orm.silent.searchCount(resModel, domain, { context });
+ recordCount = await this.orm.silent.searchCount(resModel, domain, { context, limit });
} catch (error) {
if (error.data?.name === "builtins.KeyError" && error.data.message === resModel) {
// we don't want to support invalid models
throw new Error(`Invalid model: ${resModel}`);
}
- this.updateState({ isValid: false, recordCount: 0 });
+ this.updateState({ isValid: false, recordCount: 0, hasLimitedCount: false });
return;
}
-
- this.updateState({ isValid: true, recordCount });
+ if (limit && recordCount >= limit) {
+ hasLimitedCount = true;
+ recordCount = props.countLimit;
+ }
+ this.updateState({ isValid: true, recordCount, hasLimitedCount });
}
onButtonClick() {
@@ -256,6 +267,7 @@ export class DomainField extends Component {
Object.assign(this.state, {
isValid: "isValid" in params ? params.isValid : null,
recordCount: "recordCount" in params ? params.recordCount : null,
+ hasLimitedCount: "hasLimitedCount" in params ? params.hasLimitedCount : null,
});
}
}
@@ -280,6 +292,11 @@ export const domainField = {
name: "model",
type: "string",
},
+ {
+ label: _t("Count Limit"),
+ name: "count_limit",
+ type: "number",
+ },
],
supportedTypes: ["char"],
isEmpty: () => false,
@@ -288,6 +305,7 @@ export const domainField = {
editInDialog: options.in_dialog,
isFoldable: options.foldable,
resModel: options.model,
+ countLimit: options.count_limit,
context: dynamicInfo.context,
};
},
diff --git a/addons/web/static/src/views/fields/domain/domain_field.xml b/addons/web/static/src/views/fields/domain/domain_field.xml
index 76563237337be..9cba8ea9aaed4 100644
--- a/addons/web/static/src/views/fields/domain/domain_field.xml
+++ b/addons/web/static/src/views/fields/domain/domain_field.xml
@@ -32,7 +32,7 @@
@@ -61,7 +61,7 @@
diff --git a/addons/web/static/tests/core/domain_field.test.js b/addons/web/static/tests/core/domain_field.test.js
index c5757571abe21..a3f9d4d32df36 100644
--- a/addons/web/static/tests/core/domain_field.test.js
+++ b/addons/web/static/tests/core/domain_field.test.js
@@ -554,6 +554,114 @@ test("domain field: does not wait for the count to render", async function () {
expect(".o_domain_show_selection_button").toHaveText("2 record(s)");
});
+test("domain field: have a default count limit of 10000", async function () {
+ serverState.debug = true;
+
+ Partner._fields.bar = fields.Char();
+ Partner._records = [
+ {
+ foo: "[]",
+ bar: "product",
+ },
+ ];
+ Partner._views = {
+ form: `
+ `,
+ search: ``,
+ };
+
+ onRpc("search_count", ({ kwargs }) => {
+ expect.step(kwargs.limit);
+ return 99999;
+ });
+
+ await mountWithCleanup(WebClient);
+ await getService("action").doAction({
+ name: "test",
+ res_id: 1,
+ res_model: "partner",
+ type: "ir.actions.act_window",
+ views: [[false, "form"]],
+ });
+ expect.verifySteps([10001]);
+ expect(".o_domain_show_selection_button").toHaveText("10000+ record(s)");
+});
+
+test("domain field: foldable and count limit reached", async function () {
+ serverState.debug = true;
+
+ Partner._fields.bar = fields.Char();
+ Partner._records = [
+ {
+ foo: "[]",
+ bar: "product",
+ },
+ ];
+ Partner._views = {
+ form: `
+ `,
+ search: ``,
+ };
+
+ onRpc("search_count", ({ kwargs }) => {
+ expect.step(kwargs.limit);
+ return 99999;
+ });
+
+ await mountWithCleanup(WebClient);
+ await getService("action").doAction({
+ name: "test",
+ res_id: 1,
+ res_model: "partner",
+ type: "ir.actions.act_window",
+ views: [[false, "form"]],
+ });
+ expect.verifySteps([10001]);
+ expect(".o_domain_show_selection_button").toHaveText("10000+ record(s)");
+});
+
+test("domain field: configurable count limit", async function () {
+ serverState.debug = true;
+
+ Partner._fields.bar = fields.Char();
+ Partner._records = [
+ {
+ foo: "[]",
+ bar: "product",
+ },
+ ];
+ Partner._views = {
+ form: `
+ `,
+ search: ``,
+ };
+
+ onRpc("search_count", ({ kwargs }) => {
+ expect.step(kwargs.limit);
+ return 99999;
+ });
+
+ await mountWithCleanup(WebClient);
+ await getService("action").doAction({
+ name: "test",
+ res_id: 1,
+ res_model: "partner",
+ type: "ir.actions.act_window",
+ views: [[false, "form"]],
+ });
+ expect.verifySteps([11]);
+ expect(".o_domain_show_selection_button").toHaveText("10+ record(s)");
+});
+
test("domain field: edit domain with dynamic content", async function () {
expect.assertions(3);