diff --git a/addons/web/static/src/js/views/search/filters_menu.js b/addons/web/static/src/js/views/search/filters_menu.js index eb35a311fc9..e70cf650399 100644 --- a/addons/web/static/src/js/views/search/filters_menu.js +++ b/addons/web/static/src/js/views/search/filters_menu.js @@ -14,6 +14,8 @@ var _t = core._t; var PERIOD_OPTIONS = TimeRangeMenuOptions.PeriodOptions; +var DEFAULT_PERIOD = 'this_month'; + var FiltersMenu = DropdownMenu.extend({ custom_events: { remove_proposition: '_onRemoveProposition', @@ -54,6 +56,7 @@ var FiltersMenu = DropdownMenu.extend({ this.isMobile = config.device.isMobile; // determines list of options used by filter of type 'date' this.periodOptions = PERIOD_OPTIONS; + this.defaultOptionId = DEFAULT_PERIOD; // determines when the 'Add custom filter' submenu is open this.generatorMenuIsOpen = false; this.propositions = []; @@ -146,9 +149,6 @@ var FiltersMenu = DropdownMenu.extend({ if (item.isPeriod) { item.options = this.periodOptions; } - // super has to be called here because we need to add options to groupby - // before to call it since some keys in a groupby are initialized using - // the keys 'options' and 'defaultOptionId' this._super.apply(this, arguments); }, /** diff --git a/addons/web/static/src/js/views/search/groupby_menu.js b/addons/web/static/src/js/views/search/groupby_menu.js index d686a4d55cb..cf629257c44 100644 --- a/addons/web/static/src/js/views/search/groupby_menu.js +++ b/addons/web/static/src/js/views/search/groupby_menu.js @@ -54,6 +54,7 @@ var GroupByMenu = DropdownMenu.extend({ {description: 'Quarter', optionId: 'quarter', groupId: 1}, {description: 'Year', optionId: 'year', groupId: 1}, ]; + this.defaultOptionId = DEFAULT_INTERVAL; this.groupableFields = []; _.each(fields, function (field, name) { if (field.sortable && _.contains(GROUPABLE_TYPES, field.type)) { @@ -131,6 +132,7 @@ var GroupByMenu = DropdownMenu.extend({ var eventData = _.clone(groupby); this._prepareItem(groupby); if (groupby.hasOptions) { + groupby.defaultOptionId = DEFAULT_INTERVAL; groupby.currentOptionId = DEFAULT_INTERVAL; groupby.isDate = true; eventData.optionId = groupby.currentOptionId; diff --git a/addons/web/static/src/js/views/search/search_inputs.js b/addons/web/static/src/js/views/search/search_inputs.js index 81f53ee4053..1c7873237cc 100644 --- a/addons/web/static/src/js/views/search/search_inputs.js +++ b/addons/web/static/src/js/views/search/search_inputs.js @@ -128,7 +128,7 @@ var Field = Input.extend( /** @lends instance.web.search.Field# */ { __contexts: contexts }); }, - get_groupby: function () { }, + get_groupby: function () {}, /** * Function creating the returned domain for the field, override this * methods in children if you only need to customize the field's domain @@ -143,7 +143,7 @@ var Field = Input.extend( /** @lends instance.web.search.Field# */ { make_domain: function (name, operator, facet) { return [[name, operator, this.value_from(facet)]]; }, - get_domain: function (facet) { + get_domain: function (facet, noDomainEvaluation) { if (!facet.values.length) { return; } var value_to_domain; @@ -166,10 +166,15 @@ var Field = Input.extend( /** @lends instance.web.search.Field# */ { }; } var domains = facet.values.map(value_to_domain); + + // here 'noDomainEvaluation' means 'string representation' + if (noDomainEvaluation) { + domains = domains.map(Domain.prototype.arrayToString); + return pyUtils.assembleDomains(domains, 'OR'); + } if (domains.length === 1) { return domains[0]; } - _.each(domains, Domain.prototype.normalizeArray); var ors = _.times(domains.length - 1, _.constant("|")); return ors.concat.apply(ors, domains); diff --git a/addons/web/static/src/js/views/search/search_view.js b/addons/web/static/src/js/views/search/search_view.js index 8e79b6b057e..e776e5b0467 100644 --- a/addons/web/static/src/js/views/search/search_view.js +++ b/addons/web/static/src/js/views/search/search_view.js @@ -380,7 +380,7 @@ var SearchView = Widget.extend({ break; } } - this.selectedGroupIds = { + this.activeItemIds = { groupByCategory: [], filterCategory: [] }; @@ -627,9 +627,10 @@ var SearchView = Widget.extend({ * @param {Object} ui.item selected completion item */ select_completion: function (e, ui) { + var facet = ui.item.facet; e.preventDefault(); - if(ui.item.facet && ui.item.facet.values && ui.item.facet.values.length && String(ui.item.facet.values[0].value).trim() !== "") { - this.query.add(ui.item.facet); + if(facet && facet.values && facet.values.length && String(facet.values[0].value).trim() !== "") { + this.query.add(facet); } else { this.query.trigger('add'); } @@ -666,7 +667,7 @@ var SearchView = Widget.extend({ _.invoke(this.input_subviews, 'destroy'); this.input_subviews = []; - var selectedGroupIds = { + var activeItemIds = { groupByCategory: [], filterCategory: [], }; @@ -674,29 +675,31 @@ var SearchView = Widget.extend({ this.query.each(function (facet) { var values = facet.get('values'); if (facet.attributes.cat === "groupByCategory") { - selectedGroupIds.groupByCategory = _.uniq( - values.reduce( - function (acc, value) { - var groupby = value.value; - var description = _.findWhere(self.groupbysMapping, {groupby: groupby}); - if (description) { - acc.push(description.groupId); - } - return acc; - }, - [] + activeItemIds.groupByCategory = activeItemIds.groupByCategory.concat( + _.uniq( + values.reduce( + function (acc, value) { + var groupby = value.value; + var description = _.findWhere(self.groupbysMapping, {groupby: groupby}); + if (description) { + acc.push(description.groupbyId); + } + return acc; + }, + [] + ) ) ); } if (facet.attributes.cat === "filterCategory") { - selectedGroupIds.filterCategory = selectedGroupIds.filterCategory.concat( + activeItemIds.filterCategory = activeItemIds.filterCategory.concat( _.uniq( values.reduce( function (acc, value) { var filter = value.value; var description = _.findWhere(self.filtersMapping, {filter: filter}); if (description) { - acc.push(description.groupId); + acc.push(description.filterId); } return acc; }, @@ -729,11 +732,10 @@ var SearchView = Widget.extend({ _.last(self.input_subviews).$el.focus(); } if (self.groupby_menu) { - self._unsetUnusedGroupbys(selectedGroupIds.groupByCategory); + self.groupby_menu.updateItemsStatus(activeItemIds.groupByCategory); } if (self.filters_menu) { - self._unsetUnusedFilters(selectedGroupIds.filterCategory); - } + self.filters_menu.updateItemsStatus(activeItemIds.filterCategory); } if (self.timeRangeMenu && !timeRangeMenuIsActive) { self.timeRangeMenu.deactivate(); } @@ -903,6 +905,7 @@ var SearchView = Widget.extend({ var filterId = _.uniqueId('__filter__'); var isPeriod = filter.attrs.isPeriod; var defaultPeriod = filter.attrs.default_period; + var isActive = !self.hasFavorites && !!self.search_defaults[filter.attrs.name]; filters.push({ itemId: filterId, description: filter.attrs.string || filter.attrs.help || @@ -910,8 +913,8 @@ var SearchView = Widget.extend({ domain: filter.attrs.domain, fieldName: filter.attrs.date, isPeriod: isPeriod, - currentOptionId: defaultPeriod, - isActive: !self.hasFavorites && !!self.search_defaults[filter.attrs.name], + defaultOptionId: defaultPeriod, + isActive: isActive, groupId: groupId, }); self.filtersMapping.push({filterId: filterId, filter: filter, groupId: groupId}); @@ -945,14 +948,15 @@ var SearchView = Widget.extend({ var fieldName = groupby.attrs.fieldName; var isDate = groupby.attrs.isDate; var defaultInterval = groupby.attrs.defaultInterval || DEFAULT_INTERVAL; + var isActive = !self.hasFavorites && !!self.search_defaults[groupby.attrs.name]; groupbys.push({ itemId: groupbyId, description: groupby.attrs.string || groupby.attrs.help || groupby.attrs.name || groupby.attrs.fieldName || 'Ω', isDate: isDate, fieldName: fieldName, - currentOptionId: defaultInterval, - isActive: !self.hasFavorites && !!self.search_defaults[groupby.attrs.name], + defaultOptionId: defaultInterval, + isActive: isActive, groupId: groupId, }); if (isDate) { @@ -990,6 +994,9 @@ var SearchView = Widget.extend({ fv.arch = utils.xml_to_json(doc, true); return fv; }, + /** + * @returns {Deferred} + */ _searchDefaultTimeRange: function () { if (this.timeRanges) { var timeRange = "[]"; @@ -1065,50 +1072,6 @@ var SearchView = Widget.extend({ } }, - /** - * This function ask the groupby menu to deactive all groupbys if no - * groupby is used. - * - * @param {string[]]} selectedGroupIds list of group ids to deactivate - */ - _unsetUnusedGroupbys: function (selectedGroupIds) { - var groupIds = this.groupsMapping.reduce( - function (acc, triple) { - if (triple.category === 'Group By') { - acc.push(triple.groupId); - } - return acc; - }, - [] - ); - this.selectedGroupIds.groupByCategory = selectedGroupIds; - if (selectedGroupIds.length === 0) { - this.groupby_menu.unsetGroups(groupIds); - } - }, - /** - * This function ask the filters menu to deactive all filters with - * corresponding groupId in the list selectedGroupIds. - * - * @private - * @param {string[]]} selectedGroupIds - */ - _unsetUnusedFilters: function (selectedGroupIds) { - var groupIds = this.groupsMapping.reduce( - function (acc, triple) { - if (triple.category === 'Filters') { - if (!_.contains(selectedGroupIds, triple.groupId)) { - acc.push(triple.groupId); - } - } - return acc; - }, - [] - ); - this.selectedGroupIds.filterCategory = selectedGroupIds; - this.filters_menu.unsetGroups(groupIds); - }, - //-------------------------------------------------------------------------- // Handlers //-------------------------------------------------------------------------- diff --git a/addons/web/static/src/js/widgets/dropdown_menu.js b/addons/web/static/src/js/widgets/dropdown_menu.js index 6f8f78a13d5..fdab9b82ebf 100644 --- a/addons/web/static/src/js/widgets/dropdown_menu.js +++ b/addons/web/static/src/js/widgets/dropdown_menu.js @@ -66,14 +66,18 @@ var DropdownMenu = Widget.extend({ //-------------------------------------------------------------------------- /** - * @param {Number[]} groupIds + * @param {string[]} activeItemIds */ - unsetGroups: function (groupIds) { - var self = this; - _.each(self.items, function (item) { - if (_.contains(groupIds, item.groupId)) { + updateItemsStatus: function (activeItemIds) { + _.each(this.items, function (item) { + if (!_.contains(activeItemIds, item.itemId)) { item.isActive = false; item.currentOptionId = false; + } else { + item.isActive = true; + item.currentOptionId = item.hasOptions ? + (item.currentOptionId || item.defaultOptionId) : + false; } }); this._renderMenuItems(); @@ -122,7 +126,8 @@ var DropdownMenu = Widget.extend({ if (item.options && item.options.length !== 0) { item.options = _.sortBy(item.options, 'groupId'); item.hasOptions = true; - item.currentOptionId = item.isActive && item.currentOptionId ? item.currentOptionId : false; + item.defaultOptionId = item.defaultOptionId || this.defaultOptionId; + item.currentOptionId = item.isActive && item.defaultOptionId ? item.defaultOptionId : false; } }, /** diff --git a/addons/web/static/tests/views/search_view_tests.js b/addons/web/static/tests/views/search_view_tests.js index fd847a50ea1..13ec4cab9d5 100644 --- a/addons/web/static/tests/views/search_view_tests.js +++ b/addons/web/static/tests/views/search_view_tests.js @@ -90,6 +90,20 @@ QUnit.module('Search View', { type: 'ir.actions.act_window', views: [[2, 'list']], search_view_id: [7, 'search'], + }, { + id: 9, + name: 'Partners Action 9', + res_model: 'partner', + type: 'ir.actions.act_window', + views: [[false, 'pivot']], + search_view_id: [5, 'search'], + }, { + id: 10, + name: 'Partners Action 10', + res_model: 'partner', + type: 'ir.actions.act_window', + views: [[false, 'pivot']], + search_view_id: [8, 'search'], } ]; @@ -109,6 +123,12 @@ QUnit.module('Search View', { '' + '', + // pivot views + 'partner,false,pivot': '' + + '' + + '' + + '', + // search views 'partner,false,search': ''+ '' + @@ -154,6 +174,15 @@ QUnit.module('Search View', { '' + '' + '', + 'partner,8,search': ''+ + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '', }; }, }, function () { @@ -319,7 +348,7 @@ QUnit.module('Search View', { assert.strictEqual($('.o_content tr.o_group_header').length, 4); actionManager.destroy(); }); - + QUnit.test('a separator in groupbys does not cause problems', function (assert) { assert.expect(6); @@ -523,5 +552,88 @@ QUnit.module('Search View', { } actionManager.destroy(); }); + + QUnit.test('selection via autocompletion modifies appropriately submenus', function (assert) { + assert.expect(4); + + var actionManager = createActionManager({ + actions: this.actions, + archs: this.archs, + data: this.data, + }); + + actionManager.doAction(9); + + $('.o_searchview_input').trigger($.Event('keypress', { + which: 97, + })); + + $('.o_searchview_input').trigger($.Event('keyup', { + which: $.ui.keyCode.ENTER, + keyCode: $.ui.keyCode.ENTER, + })); + + $('.o_searchview_input').trigger($.Event('keypress', { + which: 103, + })); + + $('.o_searchview_input').trigger($.Event('keyup', { + which: $.ui.keyCode.ENTER, + keyCode: $.ui.keyCode.ENTER, + })); + + assert.strictEqual($('.o_searchview_input_container .o_facet_values').eq(0).text().trim(), + "Date Field Filter: This Month", + "There should be a filter facet with label 'Date Field Filter: This Month'"); + assert.strictEqual($('.o_searchview_input_container .o_facet_values').eq(1).text().trim(), + "Date Field Groupby: Day", + "There should be a filter facet with label 'Date Field Groupby: Day'"); + + $('button .fa-filter').click(); + $('.o_filters_menu .o_menu_item').eq(0).click(); + assert.strictEqual($('.o_filters_menu .o_item_option a.selected').text().trim(), "This Month", + "The item 'This Month' should be selected in the filters menu"); + + $('button .fa-bars').click(); + $('.o_group_by_menu .o_menu_item').eq(0).click(); + assert.strictEqual($('.o_group_by_menu .o_item_option a.selected').text().trim(), "Day", + "The item 'Day' should be selected in the groupby menu"); + + actionManager.destroy(); + }); + + QUnit.test('save filters created via autocompletion works', function (assert) { + assert.expect(2); + + var actionManager = createActionManager({ + actions: this.actions, + archs: this.archs, + data: this.data, + intercepts: { + create_filter: function (ev) { + assert.ok(ev.data.filter.domain === "[['foo', 'ilike', 'a']]"); + }, + }, + }); + + actionManager.doAction(10); + + $('.o_searchview_input').trigger($.Event('keypress', { + which: 97, + })); + + $('.o_searchview_input').trigger($.Event('keyup', { + which: $.ui.keyCode.ENTER, + keyCode: $.ui.keyCode.ENTER, + })); + + assert.strictEqual($('.o_searchview_input_container .o_facet_values span').text().trim(), "a"); + + $('button .fa-star').click(); + $('.o_favorites_menu a.o_save_search').click(); + $('.o_favorites_menu div.o_save_name button').click(); + + actionManager.destroy(); + }); }); });