diff --git a/addons/web/static/src/js/views/kanban/kanban_view.js b/addons/web/static/src/js/views/kanban/kanban_view.js
index b7484e7d409..37f7fdd42ef 100644
--- a/addons/web/static/src/js/views/kanban/kanban_view.js
+++ b/addons/web/static/src/js/views/kanban/kanban_view.js
@@ -143,16 +143,16 @@ var KanbanView = BasicView.extend({
*/
_createSearchPanel: function (parent) {
var self = this;
- var defaultCategoryValues = {};
+ var defaultValues = {};
Object.keys(this.loadParams.context).forEach(function (key) {
var match = /^searchpanel_default_(.*)$/.exec(key);
if (match) {
- defaultCategoryValues[match[1]] = self.loadParams.context[key];
+ defaultValues[match[1]] = self.loadParams.context[key];
}
});
var controlPanelDomain = this.loadParams.domain;
var searchPanel = new this.config.SearchPanel(parent, {
- defaultCategoryValues: defaultCategoryValues,
+ defaultValues: defaultValues,
fields: this.fields,
model: this.loadParams.modelName,
searchDomain: controlPanelDomain,
diff --git a/addons/web/static/src/js/views/kanban/search_panel.js b/addons/web/static/src/js/views/kanban/search_panel.js
index 9062714e0c1..b906d02b89a 100644
--- a/addons/web/static/src/js/views/kanban/search_panel.js
+++ b/addons/web/static/src/js/views/kanban/search_panel.js
@@ -25,8 +25,8 @@ var SearchPanel = Widget.extend({
/**
* @override
* @param {Object} params
- * @param {Object} [params.defaultCategoryValues={}] the category value to
- * activate by default, for each category
+ * @param {Object} [params.defaultValues={}] the value(s) to activate by
+ * default, for each filter and category
* @param {Object} params.fields
* @param {string} params.model
* @param {Object} params.sections
@@ -42,7 +42,7 @@ var SearchPanel = Widget.extend({
return section.type === 'filter';
});
- this.defaultCategoryValues = params.defaultCategoryValues || {};
+ this.defaultValues = params.defaultValues || {};
this.fields = params.fields;
this.model = params.model;
this.searchDomain = params.searchDomain;
@@ -53,7 +53,7 @@ var SearchPanel = Widget.extend({
willStart: function () {
var self = this;
var loadProm = this._fetchCategories().then(function () {
- return self._fetchFilters();
+ return self._fetchFilters().then(self._applyDefaultFilterValues.bind(self));
});
return $.when(loadProm, this._super.apply(this, arguments));
},
@@ -100,6 +100,27 @@ var SearchPanel = Widget.extend({
// Private
//--------------------------------------------------------------------------
+ /**
+ * Set active values for each filter (coming from context). This needs to be
+ * done only once, at widget startup.
+ *
+ * @private
+ */
+ _applyDefaultFilterValues: function () {
+ var self = this;
+ Object.keys(this.filters).forEach(function (filterId) {
+ var filter = self.filters[filterId];
+ var defaultValues = self.defaultValues[filter.fieldName] || [];
+ defaultValues.forEach(function (value) {
+ if (filter.values[value]) {
+ filter.values[value].checked = true;
+ }
+ });
+ Object.keys(filter.groups || []).forEach(function (groupId) {
+ self._updateFilterGroupState(filter.groups[groupId]);
+ });
+ });
+ },
/**
* @private
* @param {string} categoryId
@@ -131,7 +152,7 @@ var SearchPanel = Widget.extend({
// set active value
var validValues = _.pluck(category.values, 'id').concat([false]);
// set active value from context
- var value = this.defaultCategoryValues[category.fieldName];
+ var value = this.defaultValues[category.fieldName];
// if not set in context, or set to an unknown value, set active value
// from localStorage
if (!_.contains(validValues, value)) {
@@ -359,6 +380,22 @@ var SearchPanel = Widget.extend({
}
return [];
},
+ /**
+ * Compute the current searchPanel domain based on categories and filters,
+ * and notify environment of the domain change.
+ *
+ * Note that this assumes that the environment will update the searchPanel.
+ * This is done as such to ensure the coordination between the reloading of
+ * the searchPanel and the reloading of the data.
+ *
+ * @private
+ */
+ _notifyDomainUpdated: function () {
+ this.needReload = true;
+ this.trigger_up('search_panel_domain_updated', {
+ domain: this.getDomain(),
+ });
+ },
/**
* @private
*/
@@ -418,20 +455,23 @@ var SearchPanel = Widget.extend({
return $filter;
},
/**
- * Compute the current searchPanel domain based on categories and filters,
- * and notify environment of the domain change.
- *
- * Note that this assumes that the environment will update the searchPanel.
- * This is done as such to ensure the coordination between the reloading of
- * the searchPanel and the reloading of the data.
+ * Updates the state property of a given filter's group according to the
+ * checked property of its values.
*
* @private
+ * @param {Object} group
*/
- _notifyDomainUpdated: function () {
- this.needReload = true;
- this.trigger_up('search_panel_domain_updated', {
- domain: this.getDomain(),
+ _updateFilterGroupState: function (group) {
+ var valuePartition = _.partition(Object.keys(group.values), function (valueId) {
+ return group.values[valueId].checked;
});
+ if (valuePartition[0].length && valuePartition[1].length) {
+ group.state = 'indeterminate';
+ } else if (valuePartition[0].length) {
+ group.state = 'checked';
+ } else {
+ group.state = 'unchecked';
+ }
},
//--------------------------------------------------------------------------
@@ -481,16 +521,7 @@ var SearchPanel = Widget.extend({
value.checked = !value.checked;
var group = filter.groups && filter.groups[value.group_id];
if (group) {
- var valuePartition = _.partition(Object.keys(group.values), function (valueId) {
- return group.values[valueId].checked;
- });
- if (valuePartition[0].length && valuePartition[1].length) {
- group.state = 'indeterminate';
- } else if (valuePartition[0].length) {
- group.state = 'checked';
- } else {
- group.state = 'unchecked';
- }
+ this._updateFilterGroupState(group);
}
this._notifyDomainUpdated();
},
diff --git a/addons/web/static/tests/views/search_panel_tests.js b/addons/web/static/tests/views/search_panel_tests.js
index 4f9e20f70ac..9814a887b39 100644
--- a/addons/web/static/tests/views/search_panel_tests.js
+++ b/addons/web/static/tests/views/search_panel_tests.js
@@ -1443,6 +1443,121 @@ QUnit.module('Views', {
kanban.destroy();
});
+
+ QUnit.test('specify active filter values in context', function (assert) {
+ assert.expect(4);
+
+ var expectedDomain = [
+ ['company_id', 'in', [5]],
+ ['state', 'in', ['abc', 'ghi']],
+ ];
+ var kanban = createView({
+ View: KanbanView,
+ model: 'partner',
+ data: this.data,
+ services: this.services,
+ arch: '' +
+ '' +
+ '' +
+ '' +
+ '
' +
+ '' +
+ '' +
+ '' +
+ '' +
+ '' +
+ '',
+ mockRPC: function (route, args) {
+ if (route === '/web/dataset/search_read') {
+ assert.deepEqual(args.domain, expectedDomain);
+ }
+ return this._super.apply(this, arguments);
+ },
+ context: {
+ searchpanel_default_company_id: [5],
+ searchpanel_default_state: ['abc', 'ghi'],
+ },
+ });
+
+ assert.containsN(kanban, '.o_search_panel_filter_value input:checked', 3);
+
+ // manually untick a default value
+ expectedDomain = [['state', 'in', ['abc', 'ghi']]];
+ testUtils.dom.click(kanban.$('.o_search_panel_filter:first .o_search_panel_filter_value:nth(1) input'));
+
+ assert.containsN(kanban, '.o_search_panel_filter_value input:checked', 2);
+
+ kanban.destroy();
+ });
+
+ QUnit.test('retrieved filter value from context does not exist', function (assert) {
+ assert.expect(1);
+
+ var kanban = createView({
+ View: KanbanView,
+ model: 'partner',
+ data: this.data,
+ services: this.services,
+ arch: '' +
+ '' +
+ '' +
+ '' +
+ '
' +
+ '' +
+ '' +
+ '' +
+ '' +
+ '',
+ mockRPC: function (route, args) {
+ if (route === '/web/dataset/search_read') {
+ assert.deepEqual(args.domain, [["company_id", "in", [3]]]);
+ }
+ return this._super.apply(this, arguments);
+ },
+ context: {
+ searchpanel_default_company_id: [1, 3],
+ },
+ });
+
+ kanban.destroy();
+ });
+
+ QUnit.test('filter with groupby and default values in context', function (assert) {
+ assert.expect(2);
+
+ this.data.company.records.push({id: 11, name: 'camptocamp', category_id: 7});
+
+ var kanban = createView({
+ View: KanbanView,
+ model: 'partner',
+ data: this.data,
+ services: this.services,
+ arch: '' +
+ '' +
+ '' +
+ '' +
+ '
' +
+ '' +
+ '' +
+ '' +
+ '' +
+ '',
+ mockRPC: function (route, args) {
+ if (route === '/web/dataset/search_read') {
+ assert.deepEqual(args.domain, [['company_id', 'in', [5]]]);
+ }
+ return this._super.apply(this, arguments);
+ },
+ context: {
+ searchpanel_default_company_id: [5],
+ },
+ });
+
+ var secondGroupCheckbox = kanban.$('.o_search_panel_filter_group:nth(1) > div > input').get(0);
+ assert.strictEqual(secondGroupCheckbox.indeterminate, true);
+
+ kanban.destroy();
+ });
});
});