diff --git a/addons/web/static/src/js/chrome/search_view.js b/addons/web/static/src/js/chrome/search_view.js index 6c3adcafcca..630183d89ff 100644 --- a/addons/web/static/src/js/chrome/search_view.js +++ b/addons/web/static/src/js/chrome/search_view.js @@ -603,6 +603,34 @@ var SearchView = Widget.extend({ current_category = filter.category; }); }, + + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- + + /** + * Activates a filter for a given domain. + * FIXME: the way it is done could be improved, but the actual state of the + * searchview doesn't allow to do much better. For instance, if the same + * filter is added twice, it appears twice in the facets. This should be + * improved when the searchview will be rewrote. + + * @param {string} domain the domain to filter on + * @param {string} help the text to display in the facet + */ + addFilter: function (domain, help) { + var filter = { + attrs: { + domain: domain, + help: help, + }, + }; + var filterWidget = new search_inputs.Filter(filter); + var filterGroup = new search_inputs.FilterGroup([filterWidget], this); + var facet = filterGroup.make_facet([filterGroup.make_value(filter)]); + this.query.add([facet], {silent: true}); + this.query.trigger('reset'); + }, }); _.extend(SearchView, { diff --git a/addons/web/static/src/js/chrome/view_manager.js b/addons/web/static/src/js/chrome/view_manager.js index d89f035d34d..8f62ff101f7 100644 --- a/addons/web/static/src/js/chrome/view_manager.js +++ b/addons/web/static/src/js/chrome/view_manager.js @@ -28,6 +28,7 @@ var ViewManager = Widget.extend(ControlPanelMixin, { _.extend(this.env, this._process_search_data(d.domains, d.contexts, d.groupbys)); this.active_view.controller.reload(_.extend({}, this.env)); }, + add_filter: '_onAddFilter', switch_view: function(event) { if ('res_id' in event.data) { this.env.currentId = event.data.res_id; @@ -649,6 +650,14 @@ var ViewManager = Widget.extend(ControlPanelMixin, { // Handlers //-------------------------------------------------------------------------- + /** + * @private + */ + _onAddFilter: function (event) { + if (this.searchview) { + this.searchview.addFilter(event.data.domain, event.data.help); + } + }, /** * This handler is probably called by a sub form view when the user discards * its value. The usual result of this is that we switch back to the diff --git a/addons/web/static/src/js/fields/relational_fields.js b/addons/web/static/src/js/fields/relational_fields.js index f396699bc3d..d70071b2fec 100644 --- a/addons/web/static/src/js/fields/relational_fields.js +++ b/addons/web/static/src/js/fields/relational_fields.js @@ -1656,6 +1656,18 @@ var FormFieldMany2ManyTags = FieldMany2ManyTags.extend({ }); var KanbanFieldMany2ManyTags = FieldMany2ManyTags.extend({ + events: _.extend({}, FieldMany2ManyTags.prototype.events, { + 'click .o_tag': '_onTagClicked', + }), + + //-------------------------------------------------------------------------- + // Private + //-------------------------------------------------------------------------- + + /** + * @override + * @private + */ _render: function () { var self = this; this.$el.empty().addClass('o_field_many2manytags o_kanban_tags'); @@ -1670,6 +1682,7 @@ var KanbanFieldMany2ManyTags = FieldMany2ManyTags.extend({ $tag.hide(); } else { $tag.addClass('o_tag o_tag_color_' + m2m.data[self.colorField]); + $tag.data('res_id', m2m.res_id); } } else { // display tags in grey by default @@ -1677,6 +1690,24 @@ var KanbanFieldMany2ManyTags = FieldMany2ManyTags.extend({ } }); }, + + //-------------------------------------------------------------------------- + // Handlers + //-------------------------------------------------------------------------- + + /** + * @private + * @param {MouseEvent} e + */ + _onTagClicked: function (e) { + var resID = $(e.currentTarget).data('res_id'); + var record = _.findWhere(this.value.data, {res_id: resID}); + var displayName = record.data.display_name; + this.trigger_up('add_filter', { + domain: "[['" + this.name + "','=','" + displayName + "']]", + help: displayName, + }); + } }); var FieldMany2ManyCheckBoxes = AbstractField.extend({ diff --git a/addons/web/static/tests/views/kanban_tests.js b/addons/web/static/tests/views/kanban_tests.js index 5a9d7b039e6..204847ab3bf 100644 --- a/addons/web/static/tests/views/kanban_tests.js +++ b/addons/web/static/tests/views/kanban_tests.js @@ -505,8 +505,8 @@ QUnit.module('Views', { kanban.destroy(); }); - QUnit.test('many2many_tags are correctly fetched and displayed', function (assert) { - assert.expect(10); + QUnit.test('many2many_tags in kanban views', function (assert) { + assert.expect(11); this.data.partner.records[0].category_ids = [6, 7]; this.data.partner.records[1].category_ids = [7]; @@ -528,6 +528,14 @@ QUnit.module('Views', { assert.step(route); return this._super.apply(this, arguments); }, + intercepts: { + add_filter: function (event) { + assert.deepEqual(event.data, { + domain: "[['category_ids','=','gold']]", + help: 'gold', + }, "should trigger an 'add_filter' event with correct data"); + }, + }, }); var $first_record = kanban.$('.o_kanban_record:first()'); @@ -550,6 +558,9 @@ QUnit.module('Views', { assert.strictEqual(kanban.$('.o_kanban_record:first()').find('.o_field_many2manytags .o_tag').length, 2, 'first record should still contain only 2 tags'); + // click on a tag to trigger a search by tag + kanban.$('.o_tag:contains(gold):first').click(); + kanban.destroy(); });