[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). Before4cd379cf, 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. From4cd379cf, 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
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user