From 1d091b5f77bd1f1bd783cb5622c1de2ec7da8504 Mon Sep 17 00:00:00 2001 From: Julien Banken Date: Wed, 1 Feb 2023 12:47:25 +0000 Subject: [PATCH] [FIX] web: fix inconsistencies in the standard view props definition Currently, there are a few mistakes in the standard view props definition: 1. To check the type of each element in an array, the prop definition has to include an "element" entry. In the standard view props definition, we included an "elements" entry which will completely be ignored by the schema validator of owl in debug mode. 2. The "element" entry is only used when the `type` entry of the prop definition is `Array`. We will therefore simplify the property definition and remove the "element" entry for the props that are not arrays. 3. The `orderBy` definition of the standard view props mismatch with the `orderBy` definition of the `WithSearch` component and the search model. This commit will fix that inconsistency for all those components and update the tests and the JSDoc accordingly. It will then be possible to set the `orderBy` value from the props of the `View` component without getting an error in debug mode. task-3056268 X-original-commit: 4911e6cd366eadc60923940364274b30372e1584 Part-of: odoo/odoo#112600 --- addons/web/static/src/search/search_model.js | 15 ++++++++------- .../static/src/search/with_search/with_search.js | 2 +- .../web/static/src/views/standard_view_props.js | 10 +++++----- addons/web/static/src/views/utils.js | 2 ++ addons/web/static/src/views/view.js | 4 +++- .../web/static/tests/search/with_search_tests.js | 4 ++-- addons/web/static/tests/views/view_tests.js | 8 ++++---- 7 files changed, 25 insertions(+), 20 deletions(-) diff --git a/addons/web/static/src/search/search_model.js b/addons/web/static/src/search/search_model.js index e25071048e0..27bcaf15af5 100644 --- a/addons/web/static/src/search/search_model.js +++ b/addons/web/static/src/search/search_model.js @@ -20,6 +20,8 @@ import { FACET_ICONS } from "./utils/misc"; import { EventBus, toRaw } from "@odoo/owl"; const { DateTime } = luxon; +/** @typedef {import("../views/relational_model").OrderTerm} OrderTerm */ + /** * @typedef {Object} ComparisonDomain * @property {DomainListRepr} arrayRepr @@ -38,7 +40,7 @@ const { DateTime } = luxon; * @property {Context} context * @property {DomainListRepr} domain * @property {string[]} groupBy - * @property {string[]} orderBy + * @property {OrderTerm[]} orderBy * @property {boolean} [useSampleModel] to remove? */ @@ -198,7 +200,7 @@ export class SearchModel extends EventBus { * @param {string[]} [config.groupBy=[]] * @param {boolean} [config.loadIrFilters=false] * @param {boolean} [config.display.searchPanel=true] - * @param {string[]} [config.orderBy=[]] + * @param {OrderTerm[]} [config.orderBy=[]] * @param {string[]} [config.searchMenuTypes=["filter", "groupBy", "favorite"]] * @param {Object} [config.state] */ @@ -376,7 +378,7 @@ export class SearchModel extends EventBus { * @param {Object} [config.context={}] * @param {Array} [config.domain=[]] * @param {string[]} [config.groupBy=[]] - * @param {string[]} [config.orderBy=[]] + * @param {OrderTerm[]} [config.orderBy=[]] */ async reload(config = {}) { this._reset(); @@ -496,7 +498,7 @@ export class SearchModel extends EventBus { } /** - * @returns {string[]} + * @returns {OrderTerm[]} */ get orderBy() { if (!this._orderBy) { @@ -1801,7 +1803,7 @@ export class SearchModel extends EventBus { } /** - * @returns {string[]} + * @returns {OrderTerm[]} */ _getOrderBy() { const groups = this._getGroups(); @@ -1815,8 +1817,7 @@ export class SearchModel extends EventBus { } } } - orderBy = orderBy.length ? orderBy : this.globalOrderBy; - return typeof orderBy === "string" ? [orderBy] : orderBy; + return orderBy.length ? orderBy : this.globalOrderBy; } /** diff --git a/addons/web/static/src/search/with_search/with_search.js b/addons/web/static/src/search/with_search/with_search.js index 8fd1304bd24..148f8ecf510 100644 --- a/addons/web/static/src/search/with_search/with_search.js +++ b/addons/web/static/src/search/with_search/with_search.js @@ -73,7 +73,7 @@ WithSearch.props = { context: { type: Object, optional: true }, domain: { type: Array, element: [String, Array], optional: true }, groupBy: { type: Array, element: String, optional: true }, - orderBy: { type: Array, element: String, optional: true }, + orderBy: { type: Array, element: Object, optional: true }, // search view description searchViewArch: { type: String, optional: true }, diff --git a/addons/web/static/src/views/standard_view_props.js b/addons/web/static/src/views/standard_view_props.js index ec7b669637d..92951708c35 100644 --- a/addons/web/static/src/views/standard_view_props.js +++ b/addons/web/static/src/views/standard_view_props.js @@ -26,16 +26,16 @@ export const standardViewProps = { createRecord: { type: Function, optional: true }, display: { type: Object, optional: true }, domain: { type: Array }, - fields: { type: Object, elements: Object }, + fields: { type: Object }, globalState: { type: Object, optional: true }, - groupBy: { type: Array, elements: String }, + groupBy: { type: Array, element: String }, limit: { type: Number, optional: true }, noBreadcrumbs: { type: Boolean, optional: true }, - orderBy: { type: Array, elements: String }, - relatedModels: { type: Object, elements: Object, optional: true }, + orderBy: { type: Array, element: Object }, + relatedModels: { type: Object, optional: true }, resId: { type: [Number, Boolean], optional: true }, resIds: { type: Array, optional: true }, - searchMenuTypes: { type: Array, elements: String }, + searchMenuTypes: { type: Array, element: String }, selectRecord: { type: Function, optional: true }, state: { type: Object, optional: true }, useSampleModel: { type: Boolean }, diff --git a/addons/web/static/src/views/utils.js b/addons/web/static/src/views/utils.js index b5d58444bd1..78891d7e414 100644 --- a/addons/web/static/src/views/utils.js +++ b/addons/web/static/src/views/utils.js @@ -7,6 +7,8 @@ export const X2M_TYPES = ["one2many", "many2many"]; const RELATIONAL_TYPES = [...X2M_TYPES, "many2one"]; const NUMERIC_TYPES = ["integer", "float", "monetary"]; +/** @typedef {import("./relational_model").OrderTerm} OrderTerm */ + /** * @typedef ViewActiveActions { * @property {"view"} type diff --git a/addons/web/static/src/views/view.js b/addons/web/static/src/views/view.js index c52ff016ea9..d9461a0461f 100644 --- a/addons/web/static/src/views/view.js +++ b/addons/web/static/src/views/view.js @@ -69,6 +69,8 @@ export function getDefaultConfig() { return config; } +/** @typedef {import("./relational_model").OrderTerm} OrderTerm */ + /** @typedef {Object} ViewProps * @property {string} resModel * @property {string} type @@ -89,7 +91,7 @@ export function getDefaultConfig() { * @property {Object} [context={}] * @property {DomainRepr} [domain] * @property {string[]} [groupBy] - * @property {string[]} [orderBy] + * @property {OrderTerm[]} [orderBy] * * @property {boolean} [useSampleModel] * @property {string} [noContentHelp] diff --git a/addons/web/static/tests/search/with_search_tests.js b/addons/web/static/tests/search/with_search_tests.js index 0f47764c463..5ef3cd32131 100644 --- a/addons/web/static/tests/search/with_search_tests.js +++ b/addons/web/static/tests/search/with_search_tests.js @@ -111,7 +111,7 @@ QUnit.module("Search", (hooks) => { }); assert.deepEqual(domain, [[0, "=", 1]]); assert.deepEqual(groupBy, ["birthday"]); - assert.deepEqual(orderBy, ["bar"]); + assert.deepEqual(orderBy, [{name: "bar", asc: true}]); } } TestComponent.template = xml`
Test component content
`; @@ -123,7 +123,7 @@ QUnit.module("Search", (hooks) => { domain: [[0, "=", 1]], groupBy: ["birthday"], context: { key: "val" }, - orderBy: ["bar"], + orderBy: [{name: "bar", asc: true}], }); } ); diff --git a/addons/web/static/tests/views/view_tests.js b/addons/web/static/tests/views/view_tests.js index fcccbeed1d8..9de54366c54 100644 --- a/addons/web/static/tests/views/view_tests.js +++ b/addons/web/static/tests/views/view_tests.js @@ -1425,7 +1425,7 @@ QUnit.module("Views", (hooks) => { }); assert.deepEqual(domain, [[0, "=", 1]]); assert.deepEqual(groupBy, ["birthday"]); - assert.deepEqual(orderBy, ["bar"]); + assert.deepEqual(orderBy, [{name: "bar", asc: true}]); } } ToyController.template = xml`
`; @@ -1439,7 +1439,7 @@ QUnit.module("Views", (hooks) => { domain: [[0, "=", 1]], groupBy: ["birthday"], context: { key: "val" }, - orderBy: ["bar"], + orderBy: [{name: "bar", asc: true}], }; await mount(View, target, { env, props }); } @@ -1593,7 +1593,7 @@ QUnit.module("Views", (hooks) => { }); assert.deepEqual(domain, ["&", [0, "=", 1], [1, "=", 1]]); assert.deepEqual(groupBy, ["name"]); - assert.deepEqual(orderBy, ["bar"]); + assert.deepEqual(orderBy, [{name: "bar", asc: true}]); } } ToyController.template = xml`
`; @@ -1607,7 +1607,7 @@ QUnit.module("Views", (hooks) => { domain: [[0, "=", 1]], groupBy: ["birthday"], context: { search_default_filter: 1, search_default_group_by: 1 }, - orderBy: ["bar"], + orderBy: [{name: "bar", asc: true}], }; await mount(View, target, { env, props }); }