diff --git a/addons/lunch/static/src/js/lunch_kanban_controller.js b/addons/lunch/static/src/js/lunch_kanban_controller.js index 7713c192bb3..6e75d4839b3 100644 --- a/addons/lunch/static/src/js/lunch_kanban_controller.js +++ b/addons/lunch/static/src/js/lunch_kanban_controller.js @@ -81,12 +81,9 @@ var LunchKanbanController = KanbanController.extend({ * to the searchDomain (coming from the controlPanel). * * @override - * @private */ - _getSearchDomain: function () { - var searchDomain = this._super.apply(this, arguments) || []; - var locationId = this.model.getCurrentLocationId(); - return searchDomain.concat([['is_available_at', 'in', [locationId]]]); + _getViewDomain: async function () { + return this.model.getLocationDomain(); }, /** * Renders and appends the lunch banner widget. diff --git a/addons/lunch/static/src/js/lunch_kanban_model.js b/addons/lunch/static/src/js/lunch_kanban_model.js index 7ab7b279e43..07acbcd8b69 100644 --- a/addons/lunch/static/src/js/lunch_kanban_model.js +++ b/addons/lunch/static/src/js/lunch_kanban_model.js @@ -22,12 +22,6 @@ var LunchKanbanModel = KanbanModel.extend({ // Public //-------------------------------------------------------------------------- - /** - * @returns {integer|false} - */ - getCurrentLocationId: function () { - return this.locationId; - }, /** * @return {Promise} resolved with the location domain */ @@ -84,12 +78,11 @@ var LunchKanbanModel = KanbanModel.extend({ * Builds the domain leaf corresponding to the current user's location * * @private - * @return {Array} + * @return {(Array[])|undefined} */ _buildLocationDomainLeaf: function () { - var locationId = this.getCurrentLocationId(); - if (locationId) { - return ['is_available_at', 'in', [locationId]]; + if (this.locationId) { + return ['is_available_at', 'in', [this.locationId]]; } }, _getUserLocation: function () { diff --git a/addons/lunch/static/src/js/lunch_kanban_view.js b/addons/lunch/static/src/js/lunch_kanban_view.js index 8dda159f006..0b54497fc55 100644 --- a/addons/lunch/static/src/js/lunch_kanban_view.js +++ b/addons/lunch/static/src/js/lunch_kanban_view.js @@ -24,19 +24,11 @@ var LunchKanbanView = KanbanView.extend({ //-------------------------------------------------------------------------- /** - * Injects an additional domain in the search panel - * - * @private * @override */ - _createSearchPanel: function (parent, params) { - var self = this; - var model = this.getModel(parent); - var _super = this._super.bind(this); - return model.getLocationDomain().then(function (domain) { - self.loadParams.domain = self.loadParams.domain.concat(domain); - return _super(parent, params); - }); + _getViewDomain: function (parent) { + const model = this.getModel(parent); + return model.getLocationDomain(); }, }); diff --git a/addons/lunch/static/tests/lunch_kanban_tests.js b/addons/lunch/static/tests/lunch_kanban_tests.js index 6dfb524ef9e..bb2b0beb3f7 100644 --- a/addons/lunch/static/tests/lunch_kanban_tests.js +++ b/addons/lunch/static/tests/lunch_kanban_tests.js @@ -212,8 +212,9 @@ QUnit.module('LunchKanbanView', { }); QUnit.test('search panel domain location', async function (assert) { - assert.expect(10); - const locationId = this.data['lunch.location'].records[0].id; + assert.expect(20); + let expectedLocation = 1; + let locationId = this.data['lunch.location'].records[0].id; const regularInfos = _.extend({}, this.regularInfos); const kanban = await createLunchKanbanView({ @@ -233,30 +234,49 @@ QUnit.module('LunchKanbanView', { assert.step(route); if (route.startsWith('/lunch')) { + if (route === '/lunch/user_location_set') { + locationId = args.location_id; + return Promise.resolve(true); + } return mockLunchRPC({ infos: regularInfos, userLocation: locationId, }).apply(this, arguments); } if (args.method === 'search_panel_select_multi_range') { - assert.deepEqual(args.kwargs.search_domain, [["is_available_at", "in", [locationId]]], + assert.deepEqual(args.kwargs.search_domain, [["is_available_at", "in", [expectedLocation]]], 'The initial domain of the search panel must contain the user location'); } if (route === '/web/dataset/search_read') { - assert.deepEqual(args.domain, [["is_available_at", "in", [locationId]]], + assert.deepEqual(args.domain, [["is_available_at", "in", [expectedLocation]]], 'The domain for fetching actual data should be correct'); } return this._super.apply(this, arguments); - } + }, }); + + expectedLocation = 2; + await testUtils.fields.many2one.clickOpenDropdown('locations'); + await testUtils.fields.many2one.clickItem('locations', "Office 2"); + assert.verifySteps([ + // Initial state '/lunch/user_location_get', '/web/dataset/call_kw/product/search_panel_select_multi_range', '/web/dataset/call_kw/product/search_panel_select_multi_range', '/web/dataset/search_read', '/lunch/infos', '/web/dataset/call_kw/ir.model.data/xmlid_to_res_id', - ]) + // Click m2o + '/web/dataset/call_kw/lunch.location/name_search', + // Click new location + '/lunch/user_location_set', + '/web/dataset/call_kw/product/search_panel_select_multi_range', + '/web/dataset/call_kw/product/search_panel_select_multi_range', + '/web/dataset/search_read', + '/lunch/infos', + '/web/dataset/call_kw/ir.model.data/xmlid_to_res_id', + ]); kanban.destroy(); }); diff --git a/addons/web/static/src/js/views/abstract_controller.js b/addons/web/static/src/js/views/abstract_controller.js index 09451cdcbfa..866abb03d65 100644 --- a/addons/web/static/src/js/views/abstract_controller.js +++ b/addons/web/static/src/js/views/abstract_controller.js @@ -228,7 +228,11 @@ var AbstractController = mvc.Controller.extend(ActionMixin, { this._searchPanel.importState(controllerState.spState); this.searchPanelDomain = this._searchPanel.getDomain(); } else { - searchPanelUpdateProm = this._searchPanel.update({searchDomain: this._getSearchDomain()}); + const viewDomain = await this._getViewDomain(); + searchPanelUpdateProm = this._searchPanel.update({ + searchDomain: this.controlPanelDomain, + viewDomain, + }); postponeRendering = !params.noRender; params.noRender = true; // wait for searchpanel to be ready to render } @@ -299,16 +303,13 @@ var AbstractController = mvc.Controller.extend(ActionMixin, { return null; }, /** - * Return the current search domain. This is the searchDomain used to update - * the searchpanel. It returns the domain coming from the controlpanel. This - * function can be overridden to add sub-domains coming from other parts of - * the interface. + * Get the domain defined by the view. It is meant to be overridden. * * @private - * @returns {Array[]} + * @returns {Promise} */ - _getSearchDomain: function () { - return this.controlPanelDomain; + _getViewDomain: async function () { + return []; }, /** * Meant to be overriden to return a proper object. diff --git a/addons/web/static/src/js/views/abstract_view.js b/addons/web/static/src/js/views/abstract_view.js index c720a2a515e..4cd503ff480 100644 --- a/addons/web/static/src/js/views/abstract_view.js +++ b/addons/web/static/src/js/views/abstract_view.js @@ -296,9 +296,11 @@ var AbstractView = Factory.extend({ } }); var controlPanelDomain = this.loadParams.domain; + const viewDomain = await this._getViewDomain(parent); var spParams = _.extend({}, this.searchPanelParams, { defaultValues: defaultValues, searchDomain: controlPanelDomain, + viewDomain, classes: params.classes || [], }); var searchPanel = new this.config.SearchPanel(parent, spParams); @@ -351,6 +353,17 @@ var AbstractView = Factory.extend({ withSearchPanel: this.withSearchPanel, }; }, + /** + * Get the domain defined by the view. It is meant to be overridden. The parent + * is provided in case some subcomponents need to be retrieved. + * + * @private + * @param {Object} parent + * @returns {Promise} + */ + _getViewDomain: async function (parent) { + return []; + }, /** * Processes a fieldsView. In particular, parses its arch. * diff --git a/addons/web/static/src/js/views/search_panel.js b/addons/web/static/src/js/views/search_panel.js index 590d52e4941..377eb723621 100644 --- a/addons/web/static/src/js/views/search_panel.js +++ b/addons/web/static/src/js/views/search_panel.js @@ -83,6 +83,7 @@ var SearchPanel = Widget.extend({ * @param {Object} params.fields * @param {string} params.model * @param {Array[]} params.searchDomain domain coming from controlPanel + * @param {Array[]} params.viewDomain domain coming from the view (ill advised) * @param {Object} params.sections * @param {Object} [params.state] state exported by another searchpanel * instance @@ -110,6 +111,7 @@ var SearchPanel = Widget.extend({ this.model = params.model; this.className = params.classes.concat(['o_search_panel']).join(' '); this.searchDomain = params.searchDomain; + this.viewDomain = params.viewDomain; }, /** * @override @@ -229,15 +231,17 @@ var SearchPanel = Widget.extend({ * * @param {Object} params * @param {Array[]} params.searchDomain domain coming from controlPanel + * @param {Array[]} params.viewDomain domain coming from view * @returns {Promise} */ update: function (params) { - var currentSearchDomainStr = JSON.stringify(this.searchDomain); - var newSearchDomainStr = JSON.stringify(params.searchDomain); + const currentDomain = JSON.stringify([...this.searchDomain, ...this.viewDomain]); + const newDomain = JSON.stringify([...params.searchDomain, ...params.viewDomain]); var filtersProm; - if (this.needReload || (currentSearchDomainStr !== newSearchDomainStr)) { + if (this.needReload || (currentDomain !== newDomain)) { this.needReload = false; this.searchDomain = params.searchDomain; + this.viewDomain = params.viewDomain; filtersProm = this._fetchFilters(); } return Promise.resolve(filtersProm).then(this._render.bind(this)); @@ -431,7 +435,7 @@ var SearchPanel = Widget.extend({ disable_counters: filter.disableCounters, filter_domain: filterDomain, group_by: filter.groupBy || false, - search_domain: self.searchDomain, + search_domain: [...self.searchDomain, ...self.viewDomain], }, }).then(function (values) { self._createFilterTree(filterId, values);