diff --git a/addons/web/static/src/js/control_panel/control_panel_model.js b/addons/web/static/src/js/control_panel/control_panel_model.js index a9500999793..d09c6eeaa58 100644 --- a/addons/web/static/src/js/control_panel/control_panel_model.js +++ b/addons/web/static/src/js/control_panel/control_panel_model.js @@ -959,6 +959,9 @@ odoo.define('web.ControlPanelModel', function (require) { filter.defaultRank = -10; filter.defaultAutocompleteValue = attrs.defaultAutocompleteValue; } + if (attrs.widget) { // FIXME: drop support in master + filter.widget = attrs.widget; + } break; } } diff --git a/addons/web/static/src/js/control_panel/search_bar.js b/addons/web/static/src/js/control_panel/search_bar.js index a86e22a10b8..3082c38c055 100644 --- a/addons/web/static/src/js/control_panel/search_bar.js +++ b/addons/web/static/src/js/control_panel/search_bar.js @@ -92,34 +92,41 @@ odoo.define('web.SearchBar', function (require) { * @returns {Object} */ _createSource(filter) { + const field = this.props.fields[filter.fieldName]; + const type = filter.widget || field.type; const source = { active: true, description: filter.description, - fieldName: filter.fieldName, filterId: filter.id, filterOperator: filter.operator, id: sourceId ++, - operator: CHAR_FIELDS.includes(filter.fieldType) ? 'ilike' : '=', + operator: CHAR_FIELDS.includes(type) ? 'ilike' : '=', parent: false, + type, }; - switch (filter.fieldType) { - case 'selection': + switch (type) { + case 'selection': { source.active = false; - source.selection = this.props.fields[filter.fieldName].selection; + source.selection = field.selection || []; break; - case 'boolean': + } + case 'boolean': { source.active = false; source.selection = [ [true, this.env._t("Yes")], [false, this.env._t("No")], ]; break; - case 'many2one': + } + case 'many2one': { source.expand = true; source.expanded = false; + source.context = field.context; + source.relation = field.relation; if (filter.domain) { source.domain = filter.domain; } + } } return source; } @@ -133,7 +140,6 @@ odoo.define('web.SearchBar', function (require) { _createSubSource(source, [value, label], active = true) { const subSource = { active, - fieldName: source.fieldName, filterId: source.filterId, filterOperator: source.filterOperator, id: sourceId ++, @@ -161,16 +167,15 @@ odoo.define('web.SearchBar', function (require) { args = []; } } - const { context, relation } = this.props.fields[source.fieldName]; const results = await this.rpc({ kwargs: { args, - context, + context: source.context, limit: 8, name: this.state.inputValue.trim(), }, method: 'name_search', - model: relation, + model: source.relation, }); const options = results.map(result => this._createSubSource(source, result)); const parentIndex = this.state.sources.indexOf(source); @@ -235,8 +240,7 @@ odoo.define('web.SearchBar', function (require) { * @param {Object} source * @returns {string} */ - _parseWithSource(rawValue, source) { - const { type } = this.props.fields[source.fieldName]; + _parseWithSource(rawValue, { type }) { const parser = field_utils.parse[type]; let parsedValue; switch (type) { diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml index fab3018fb46..abe3856b91e 100644 --- a/addons/web/static/src/xml/base.xml +++ b/addons/web/static/src/xml/base.xml @@ -604,7 +604,7 @@ - + Search at: Search for: diff --git a/addons/web/static/tests/control_panel/search_bar_tests.js b/addons/web/static/tests/control_panel/search_bar_tests.js index e58c2c3ae6d..412688aa52c 100644 --- a/addons/web/static/tests/control_panel/search_bar_tests.js +++ b/addons/web/static/tests/control_panel/search_bar_tests.js @@ -528,5 +528,53 @@ odoo.define('web.search_bar_tests', function (require) { actionManager.destroy(); }); + + QUnit.test("widgets are supported in search view", async function (assert) { + assert.expect(7); + + this.data.partner.fields.ref = { type: 'reference', string: "Reference" }; + this.data.partner.records.forEach((record, i) => { + record.ref = `ref${String(i).padStart(3, "0")}`; + }); + const archs = Object.assign({}, this.archs, { + 'partner,false,search': ` + + + `, + }); + const actionManager = await createActionManager({ + actions: this.actions, + archs, + data: this.data, + async mockRPC(route, { domain }) { + if (route === '/web/dataset/search_read') { + assert.step(JSON.stringify(domain)); + } + return this._super(...arguments); + + } + }); + await actionManager.doAction(1); + + await cpHelpers.editSearch(actionManager, "ref"); + await cpHelpers.validateSearch(actionManager); + + assert.containsN(actionManager, ".o_data_row", 5); + + await cpHelpers.removeFacet(actionManager, 0); + await cpHelpers.editSearch(actionManager, "ref002"); + await cpHelpers.validateSearch(actionManager); + + assert.containsOnce(actionManager, ".o_data_row"); + + assert.verifySteps([ + '[]', + '[["ref","ilike","ref"]]', + '[]', + '[["ref","ilike","ref002"]]', + ]); + + actionManager.destroy(); + }); }); });