From 6a8e1b53e3a01a74aa21b834964994e8d186b653 Mon Sep 17 00:00:00 2001 From: Aaron Bohy Date: Tue, 19 Feb 2019 10:10:47 +0000 Subject: [FIX] web: search more in many2one: filter on ids Let's assume a many2one field with a lot of possible values. The user clicks on 'Search More...'. In the opened dialog, only 160 records are available (their ids have been obtained with a name_search, with the optional text the user could have typed in the many2one input). Before 4cd379cf, that extra domain on ids was removed automatically as soon as the user interacted with the search view in the dialog. This was especially useful when there were more than 160 records. However, this was rather an happy coincidence than a designed feature. From 4cd379cf, the ids selection was added to the initial domain of the list, so they couldn't be removed from the domain afterwards. The user was thus stucked with its preselected 160 records. This rev. doesn't restore the former behavior, but rather improves the current one, as follows: - when there is no text in the many2one input (i.e. no value to filter on), we bypass the name_search, s.t. all records are available in the dialog - when there is some text in the input, we perform a name_search (as before) to get a list of record ids, and we add a special filter to the search view in the dialog (the filter on those ids), s.t. the user can remove it if he wants to access the remaining records. - finally, the limit is now set to 320, to mitigate the problem Issue reported on the saas-12.1 migration pad. closes odoo/odoo#31232 --- .../web/static/src/js/fields/relational_fields.js | 34 ++++++++++++++++++---- addons/web/static/src/js/views/abstract_view.js | 3 ++ .../js/views/control_panel/control_panel_view.js | 21 +++++++++++-- addons/web/static/src/js/views/view_dialogs.js | 2 ++ 4 files changed, 52 insertions(+), 8 deletions(-) (limited to 'addons/web/static/src/js') diff --git a/addons/web/static/src/js/fields/relational_fields.js b/addons/web/static/src/js/fields/relational_fields.js index 14eb10c663c..6005c9f1a66 100644 --- a/addons/web/static/src/js/fields/relational_fields.js +++ b/addons/web/static/src/js/fields/relational_fields.js @@ -107,6 +107,7 @@ var FieldMany2One = AbstractField.extend({ 'click': '_onClick', }), AUTOCOMPLETE_DELAY: 200, + SEARCH_MORE_LIMIT: 320, /** * @override @@ -501,18 +502,33 @@ var FieldMany2One = AbstractField.extend({ values.push({ label: _t("Search More..."), action: function () { - self._rpc({ + var prom; + if (search_val !== '') { + prom = self._rpc({ model: self.field.relation, method: 'name_search', kwargs: { name: search_val, args: domain, operator: "ilike", - limit: 160, + limit: self.SEARCH_MORE_LIMIT, context: context, }, - }) - .then(self._searchCreatePopup.bind(self, "search")); + }); + } + $.when(prom).then(function (results) { + var dynamicFilters; + if (results) { + var ids = _.map(results, function (x) { + return x[0]; + }); + dynamicFilters = [{ + description: _.str.sprintf(_t('Quick search: %s'), search_val), + domain: [['id', 'in', ids]], + }]; + } + self._searchCreatePopup("search", false, {}, dynamicFilters); + }); }, classname: 'o_m2o_dropdown_option', }); @@ -555,19 +571,25 @@ var FieldMany2One = AbstractField.extend({ /** * all search/create popup handling * + * TODO: ids argument is no longer used, remove it in master (as well as + * initial_ids param of the dialog) + * * @private * @param {any} view * @param {any} ids * @param {any} context + * @param {Object[]} [dynamicFilters=[]] filters to add to the search view + * in the dialog (each filter has keys 'description' and 'domain') */ - _searchCreatePopup: function (view, ids, context) { + _searchCreatePopup: function (view, ids, context, dynamicFilters) { var self = this; return new dialogs.SelectCreateDialog(this, _.extend({}, this.nodeOptions, { res_model: this.field.relation, domain: this.record.getDomain({fieldName: this.name}), context: _.extend({}, this.record.getContext(this.recordParams), context || {}), + dynamicFilters: dynamicFilters || [], title: (view === 'search' ? _t("Search: ") : _t("Create: ")) + this.string, - initial_ids: ids ? _.map(ids, function (x) { return x[0]; }) : undefined, + initial_ids: ids, initial_view: view, disable_multiple_selection: true, no_create: !self.can_create, diff --git a/addons/web/static/src/js/views/abstract_view.js b/addons/web/static/src/js/views/abstract_view.js index 5921c1b4bc3..a2e6c5e699c 100644 --- a/addons/web/static/src/js/views/abstract_view.js +++ b/addons/web/static/src/js/views/abstract_view.js @@ -78,6 +78,8 @@ var AbstractView = Factory.extend({ * @param {string} [params.controllerState] * @param {string} [params.displayName] * @param {Array[]} [params.domain=[]] + * @param {Object[]} [params.dynamicFilters] transmitted to the + * ControlPanelView * @param {number[]} [params.ids] * @param {boolean} [params.isEmbedded=false] * @param {Object} [params.searchQuery={}] @@ -165,6 +167,7 @@ var AbstractView = Factory.extend({ this.controlPanelParams = { action: action, activateDefaultFavorite: params.activateDefaultFavorite, + dynamicFilters: params.dynamicFilters, breadcrumbs: params.breadcrumbs, context: this.loadParams.context, domain: this.loadParams.domain, diff --git a/addons/web/static/src/js/views/control_panel/control_panel_view.js b/addons/web/static/src/js/views/control_panel/control_panel_view.js index edda0e3c9ac..c81093f28ff 100644 --- a/addons/web/static/src/js/views/control_panel/control_panel_view.js +++ b/addons/web/static/src/js/views/control_panel/control_panel_view.js @@ -43,8 +43,12 @@ var ControlPanelView = Factory.extend({ * breadcrumbs won't be rendered * @param {boolean} [params.withSearchBar=true] if set to false, no default * search bar will be rendered - * @param {boolean} [activateDefaultFavorite=false] determine if the default - * custom filters can be activated + * @param {boolean} [params.activateDefaultFavorite] determine if the + * default custom filters can be activated + * @param {Object[]} [params.dynamicFilters=[]] filters to add to the + * search (in addition to those described in the arch), each filter being + * an object with keys 'description' (what is displayed in the searchbar) + * and 'domain' */ init: function (params) { var self = this; @@ -103,6 +107,19 @@ var ControlPanelView = Factory.extend({ INTERVAL_OPTIONS = INTERVAL_OPTIONS.map(function (option) { return _.extend(option, {description: option.description.toString()}); }); + + // add a filter group with the dynamic filters, if any + if (params.dynamicFilters && params.dynamicFilters.length) { + var dynamicFiltersGroup = params.dynamicFilters.map(function (filter) { + return { + description: filter.description, + domain: JSON.stringify(filter.domain), + isDefault: true, + type: 'filter', + }; + }); + this.loadParams.groups.unshift(dynamicFiltersGroup); + } }, //-------------------------------------------------------------------------- diff --git a/addons/web/static/src/js/views/view_dialogs.js b/addons/web/static/src/js/views/view_dialogs.js index fb9cd5afa0c..96f6286cd3e 100644 --- a/addons/web/static/src/js/views/view_dialogs.js +++ b/addons/web/static/src/js/views/view_dialogs.js @@ -304,6 +304,7 @@ var SelectCreateDialog = ViewDialog.extend({ * - list_view_options: dict of options to pass to the List View * - on_selected: optional callback to execute when records are selected * - disable_multiple_selection: true to allow create/select multiple records + * - dynamicFilters: filters to add to the searchview */ init: function () { this._super.apply(this, arguments); @@ -346,6 +347,7 @@ var SelectCreateDialog = ViewDialog.extend({ controlPanelFieldsView: fieldsViews.search, }, action_buttons: false, + dynamicFilters: this.options.dynamicFilters, context: this.context, domain: domain, hasSelectors: !this.options.disable_multiple_selection, -- cgit v1.2.3