summaryrefslogtreecommitdiff
path: root/addons/web/static/src/js/views/search_panel.js
diff options
context:
space:
mode:
Diffstat (limited to 'addons/web/static/src/js/views/search_panel.js')
-rw-r--r--addons/web/static/src/js/views/search_panel.js473
1 files changed, 219 insertions, 254 deletions
diff --git a/addons/web/static/src/js/views/search_panel.js b/addons/web/static/src/js/views/search_panel.js
index b15411da2a7..a820e46f529 100644
--- a/addons/web/static/src/js/views/search_panel.js
+++ b/addons/web/static/src/js/views/search_panel.js
@@ -6,18 +6,20 @@ odoo.define('web.SearchPanel', function (require) {
* filter/manage data easily.
*/
-var core = require('web.core');
-var Domain = require('web.Domain');
-var pyUtils = require('web.py_utils');
-var viewUtils = require('web.viewUtils');
-var Widget = require('web.Widget');
+const core = require('web.core');
+const Domain = require('web.Domain');
+const pyUtils = require('web.py_utils');
+const { sortBy } = require('web.utils');
+const viewUtils = require('web.viewUtils');
+const Widget = require('web.Widget');
-var qweb = core.qweb;
+const qweb = core.qweb;
// defaultViewTypes is the list of view types for which the searchpanel is
// present by default (if not explicitly stated in the 'view_types' attribute
// in the arch)
-var defaultViewTypes = ['kanban', 'tree'];
+const defaultViewTypes = ['kanban', 'tree'];
+let nextSectionId = 1;
const SEARCH_PANEL_LIMIT = 200;
@@ -30,19 +32,16 @@ const SEARCH_PANEL_LIMIT = 200;
* @returns {Object}
*/
function _processSearchPanelNode(node, fields) {
- var sections = {};
+ const sections = {};
node.children.forEach((childNode, index) => {
- if (childNode.tag !== 'field') {
+ if (childNode.tag !== 'field' || childNode.attrs.invisible === "1") {
return;
}
- if (childNode.attrs.invisible === "1") {
- return;
- }
- var fieldName = childNode.attrs.name;
- var type = childNode.attrs.select === 'multi' ? 'filter' : 'category';
+ const fieldName = childNode.attrs.name;
+ const type = childNode.attrs.select === 'multi' ? 'filter' : 'category';
- var sectionId = _.uniqueId('section_');
- var section = {
+ const sectionId = `section_${nextSectionId++}`;
+ const section = {
color: childNode.attrs.color,
description: childNode.attrs.string || fields[fieldName].string,
fieldName: fieldName,
@@ -64,7 +63,7 @@ function _processSearchPanelNode(node, fields) {
return sections;
}
-var SearchPanel = Widget.extend({
+const SearchPanel = Widget.extend({
className: 'o_search_panel',
events: {
'click .o_search_panel_category_value header': '_onCategoryValueClicked',
@@ -75,7 +74,7 @@ var SearchPanel = Widget.extend({
},
/**
- * @override
+ * @constructor
* @param {Object} params
* @param {Object} [params.defaultValues={}] the value(s) to activate by
* default, for each filter and category
@@ -90,22 +89,21 @@ var SearchPanel = Widget.extend({
* @param {Object} [params.state] state exported by another searchpanel
* instance
*/
- init: function (parent, params) {
- this._super.apply(this, arguments);
-
- this.categories = _.pick(params.sections, function (section) {
- return section.type === 'category';
- });
- this.filters = _.pick(params.sections, function (section) {
- return section.type === 'filter';
- });
+ init(parent, params) {
+ this._super(...arguments);
+
+ this.categories = {};
+ this.filters = {};
+ for (const section of Object.values(params.sections)) {
+ const key = section.type === 'category' ? 'categories' : 'filters';
+ this[key][section.id] = section;
+ }
this.initialState = params.state;
this.scrollTop = this.initialState && this.initialState.scrollTop || null;
this.defaultValues = params.defaultValues || {};
if (params.defaultNoFilter) {
- Object.keys(this.categories).forEach((categoryId) => {
- var fieldName = this.categories[categoryId].fieldName;
+ Object.values(this.categories).forEach(({ fieldName }) => {
this.defaultValues[fieldName] = this.defaultValues[fieldName] || false;
});
}
@@ -118,38 +116,37 @@ var SearchPanel = Widget.extend({
/**
* @override
*/
- willStart: function () {
- var self = this;
- var loadCategoriesProm;
+ async willStart() {
+ const _super = this._super;
if (this.initialState) {
this.filters = this.initialState.filters;
this.categories = this.initialState.categories;
} else {
- loadCategoriesProm = this._fetchCategories().then(function () {
- return self._fetchFilters().then(self._applyDefaultFilterValues.bind(self));
- });
+ await this._fetchCategories();
+ await this._fetchFilters();
+ await this._applyDefaultFilterValues();
}
- return Promise.all([loadCategoriesProm, this._super.apply(this, arguments)]);
+ return _super.call(this, ...arguments);
},
/**
* @override
*/
- start: function () {
+ start() {
this._render();
- return this._super.apply(this, arguments);
+ return this._super(...arguments);
},
/**
* Called each time the searchPanel is attached into the DOM.
*/
- on_attach_callback: function () {
+ on_attach_callback() {
if (this.scrollTop !== null) {
this.el.scrollTop = this.scrollTop;
}
},
- //--------------------------------------------------------------------------
+ //-------------------------------------------------------------------------
// Public
- //--------------------------------------------------------------------------
+ //-------------------------------------------------------------------------
/**
* Parse a given search view arch to extract the searchpanel information
@@ -163,44 +160,40 @@ var SearchPanel = Widget.extend({
* or may not instantiate a SearchPanel.
*
* @static
- * @params {Object} viewInfo the viewInfo of a search view
- * @params {string} viewInfo.arch
- * @params {Object} viewInfo.fields
- * @params {string} viewType the type of the current view (e.g. 'kanban')
- * @returns {Object|undefined}
+ * @param {Object} viewInfo the viewInfo of a search view
+ * @param {string} viewInfo.arch
+ * @param {Object} viewInfo.fields
+ * @param {string} viewType the type of the current view (e.g. 'kanban')
+ * @returns {Object}
*/
- computeSearchPanelParams: function (arch, fields, viewType) {
- var searchPanelSections;
- var classes;
+ computeSearchPanelParams(arch, fields, viewType) {
+ const searchPanelParams = {};
if (arch && fields) {
- viewType = viewType === 'list' ? 'tree' : viewType;
- arch = viewUtils.parseArch(arch);
- const searchPanelNode = arch.children.find(child => child.tag === 'searchpanel');
+ const parsedArch = viewUtils.parseArch(arch);
+ const searchPanelNode = parsedArch.children.find(child => child.tag === 'searchpanel');
if (searchPanelNode) {
- var attrs = searchPanelNode.attrs;
- var viewTypes = defaultViewTypes;
+ const { attrs } = searchPanelNode;
+ const type = viewType === 'list' ? 'tree' : viewType;
+ let viewTypes = defaultViewTypes;
if (attrs.view_types) {
viewTypes = attrs.view_types.split(',');
}
if (attrs.class) {
- classes = attrs.class.split(' ');
+ searchPanelParams.classes = attrs.class.split(' ');
}
- if (viewTypes.includes(viewType)) {
- searchPanelSections = _processSearchPanelNode(searchPanelNode, fields);
+ if (viewTypes.includes(type)) {
+ searchPanelParams.sections = _processSearchPanelNode(searchPanelNode, fields);
}
}
}
- return {
- sections: searchPanelSections,
- classes: classes,
- };
+ return searchPanelParams;
},
/**
* Export the current state (categories and filters) of the searchpanel.
*
* @returns {Object}
*/
- exportState: function () {
+ exportState() {
return {
categories: this.categories,
filters: this.filters,
@@ -211,7 +204,7 @@ var SearchPanel = Widget.extend({
* @returns {Array[]} the current searchPanel domain based on active
* categories and checked filters
*/
- getDomain: function () {
+ getDomain() {
return this._getCategoryDomain().concat(this._getFilterDomain());
},
/**
@@ -221,7 +214,7 @@ var SearchPanel = Widget.extend({
* @param {Object} state.filters.
* @param {Object} state.categories
*/
- importState: function (state) {
+ importState(state) {
this.categories = state.categories || this.categories;
this.filters = state.filters || this.filters;
this.scrollTop = state.scrollTop;
@@ -236,22 +229,21 @@ var SearchPanel = Widget.extend({
* @param {Array[]} params.viewDomain domain coming from view
* @returns {Promise}
*/
- update: function (params) {
+ async update(params) {
const currentDomain = JSON.stringify([...this.searchDomain, ...this.viewDomain]);
const newDomain = JSON.stringify([...params.searchDomain, ...params.viewDomain]);
- var filtersProm;
if (this.needReload || (currentDomain !== newDomain)) {
this.needReload = false;
this.searchDomain = params.searchDomain;
this.viewDomain = params.viewDomain;
- filtersProm = this._fetchFilters();
+ await this._fetchFilters();
}
- return Promise.resolve(filtersProm).then(this._render.bind(this));
+ return this._render();
},
- //--------------------------------------------------------------------------
+ //-------------------------------------------------------------------------
// Private
- //--------------------------------------------------------------------------
+ //-------------------------------------------------------------------------
/**
* Set active values for each filter (coming from context). This needs to be
@@ -259,19 +251,15 @@ var SearchPanel = Widget.extend({
*
* @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) {
+ _applyDefaultFilterValues() {
+ Object.values(this.filters).forEach(filter => {
+ const defaultValues = this.defaultValues[filter.fieldName] || [];
+ defaultValues.forEach(value => {
if (filter.values[value]) {
filter.values[value].checked = true;
}
});
- Object.keys(filter.groups || []).forEach(function (groupId) {
- self._updateFilterGroupState(filter.groups[groupId]);
- });
+ Object.values(filter.groups || []).forEach(this._updateFilterGroupState);
});
},
/**
@@ -279,9 +267,8 @@ var SearchPanel = Widget.extend({
* @param {string} categoryId
* @param {Object[]} values
*/
- _createCategoryTree: function (categoryId, values) {
- var category = this.categories[categoryId];
-
+ _createCategoryTree(categoryId, values) {
+ const category = this.categories[categoryId];
let parentField = category.parentField;
if (values.length === SEARCH_PANEL_LIMIT) {
category.limitAttained = true;
@@ -292,36 +279,36 @@ var SearchPanel = Widget.extend({
}
category.values = {};
- _.each(values, function (value) {
- category.values[value.id] = _.extend({}, value, {
+ values.forEach(value => {
+ category.values[value.id] = Object.assign({}, value, {
childrenIds: [],
folded: true,
parentId: value[parentField] && value[parentField][0] || false,
});
});
- _.map(values, function (value) {
- var value = category.values[value.id];
- var parentCategoryId = value.parentId;
+ values.forEach(value => {
+ const { parentId: parentCategoryId } = category.values[value.id];
if (parentCategoryId && parentCategoryId in category.values) {
category.values[parentCategoryId].childrenIds.push(value.id);
}
});
- category.rootIds = _.filter(_.map(values, function (value) {
- return value.id;
- }), function (valueId) {
- var value = category.values[valueId];
- return value.parentId === false;
- });
+ category.rootIds = [];
+ for (const value of values) {
+ const { parentId } = category.values[value.id];
+ if (!parentId) {
+ category.rootIds.push(value.id);
+ }
+ }
// set active value
- var validValues = _.pluck(category.values, 'id').concat([false]);
- var value = this._getCategoryDefaultValue(category, validValues);
- category.activeValueId = _.contains(validValues, value) ? value : false;
+ const validValues = [...Object.values(category.values).map(v => v.id), false];
+ const value = this._getCategoryDefaultValue(category, validValues);
+ category.activeValueId = validValues.includes(value) ? value : false;
// unfold ancestor values of active value to make it is visible
if (category.activeValueId) {
- var parentValueIds = this._getAncestorValueIds(category, category.activeValueId);
- parentValueIds.forEach(function (parentValue) {
+ const parentValueIds = this._getAncestorValueIds(category, category.activeValueId);
+ parentValueIds.forEach(parentValue => {
category.values[parentValue].folded = false;
});
}
@@ -331,25 +318,25 @@ var SearchPanel = Widget.extend({
* @param {string} filterId
* @param {Object[]} values
*/
- _createFilterTree: function (filterId, values) {
- var filter = this.filters[filterId];
+ _createFilterTree(filterId, values) {
+ const filter = this.filters[filterId];
if (values.length === SEARCH_PANEL_LIMIT) {
filter.limitAttained = true;
}
// restore checked property
- values.forEach(function (value) {
- var oldValue = filter.values && filter.values[value.id];
+ values.forEach(value => {
+ const oldValue = filter.values && filter.values[value.id];
value.checked = oldValue && oldValue.checked || false;
});
filter.values = {};
- var groupIds = [];
+ const groupIds = [];
if (filter.groupBy) {
- var groups = {};
- values.forEach(function (value) {
- var groupId = JSON.stringify(value.group_id);
+ const groups = {};
+ values.forEach(value => {
+ const groupId = JSON.stringify(value.group_id);
if (!groups[groupId]) {
if (groupId !== 'false') {
groupIds.push(groupId);
@@ -365,7 +352,7 @@ var SearchPanel = Widget.extend({
sortedValueIds: [],
};
// restore former checked and folded state
- var oldGroup = filter.groups && filter.groups[groupId];
+ const oldGroup = filter.groups && filter.groups[groupId];
groups[groupId].state = oldGroup && oldGroup.state || false;
groups[groupId].folded = oldGroup && oldGroup.folded || false;
}
@@ -373,19 +360,17 @@ var SearchPanel = Widget.extend({
groups[groupId].sortedValueIds.push(value.id);
});
filter.groups = groups;
- filter.sortedGroupIds = _.sortBy(groupIds, function (groupId) {
- return groups[groupId].sequence || groups[groupId].name;
- });
- Object.keys(filter.groups).forEach(function (groupId) {
- filter.values = _.extend(filter.values, filter.groups[groupId].values);
+ filter.sortedGroupIds = sortBy(groupIds,
+ id => groups[id].sequence || groups[id].name
+ );
+ Object.values(filter.groups).forEach(group => {
+ Object.assign(filter.values, group.values);
});
} else {
- values.forEach(function (value) {
+ values.forEach(value => {
filter.values[value.id] = value;
});
- filter.sortedValueIds = values.map(function (value) {
- return value.id;
- });
+ filter.sortedValueIds = values.map(value => value.id);
}
},
/**
@@ -394,31 +379,31 @@ var SearchPanel = Widget.extend({
* @private
* @returns {Promise} resolved when all categories have been fetched
*/
- _fetchCategories: function () {
- var self = this;
- var proms = Object.keys(this.categories).map(function (categoryId) {
- var category = self.categories[categoryId];
- var field = self.fields[category.fieldName];
- var categoriesProm;
+ _fetchCategories() {
+ const proms = [];
+ let prom;
+ for (const category of Object.values(this.categories)) {
+ const field = this.fields[category.fieldName];
if (field.type === 'selection') {
- var values = field.selection.map(function (value) {
- return {id: value[0], display_name: value[1]};
+ const values = field.selection.map(value => {
+ return { id: value[0], display_name: value[1] };
});
- categoriesProm = Promise.resolve(values);
+ prom = Promise.resolve(values);
} else {
- categoriesProm = self._rpc({
+ prom = this._rpc({
method: 'search_panel_select_range',
- model: self.model,
+ model: this.model,
args: [category.fieldName],
- }).then(function (result) {
+ }).then(result => {
category.parentField = result.parent_field;
return result.values;
});
}
- return categoriesProm.then(function (values) {
- self._createCategoryTree(categoryId, values);
+ prom.then(values => {
+ this._createCategoryTree(category.id, values);
});
- });
+ proms.push(prom);
+ }
return Promise.all(proms);
},
/**
@@ -428,20 +413,18 @@ var SearchPanel = Widget.extend({
* @private
* @returns {Promise} resolved when all filters have been fetched
*/
- _fetchFilters: function () {
- var self = this;
- var evalContext = {};
- Object.keys(this.categories).forEach(function (categoryId) {
- var category = self.categories[categoryId];
+ _fetchFilters() {
+ const evalContext = {};
+ for (const category of Object.values(this.categories)) {
evalContext[category.fieldName] = category.activeValueId;
- });
- var categoryDomain = this._getCategoryDomain();
- var filterDomain = this._getFilterDomain();
- var proms = Object.keys(this.filters).map(function (filterId) {
- var filter = self.filters[filterId];
- return self._rpc({
+ }
+ const categoryDomain = this._getCategoryDomain();
+ const filterDomain = this._getFilterDomain();
+ const proms = [];
+ for (const filter of Object.values(this.filters)) {
+ const prom = this._rpc({
method: 'search_panel_select_multi_range',
- model: self.model,
+ model: this.model,
args: [filter.fieldName],
kwargs: {
category_domain: categoryDomain,
@@ -449,12 +432,11 @@ var SearchPanel = Widget.extend({
disable_counters: filter.disableCounters,
filter_domain: filterDomain,
group_by: filter.groupBy || false,
- search_domain: [...self.searchDomain, ...self.viewDomain],
+ search_domain: [...this.searchDomain, ...this.viewDomain],
},
- }).then(function (values) {
- self._createFilterTree(filterId, values);
- });
- });
+ }).then(values => { this._createFilterTree(filter.id, values); });
+ proms.push(prom);
+ }
return Promise.all(proms);
},
/**
@@ -463,13 +445,13 @@ var SearchPanel = Widget.extend({
* @param {Array} validValues
* @returns id of the default item of the category or false
*/
- _getCategoryDefaultValue: function (category, validValues) {
+ _getCategoryDefaultValue(category, validValues) {
// set active value from context
- var value = this.defaultValues[category.fieldName];
+ const 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)) {
- var storageKey = this._getLocalStorageKey(category);
+ if (!validValues.includes(value)) {
+ const storageKey = this._getLocalStorageKey(category);
return this.call('local_storage', 'getItem', storageKey);
}
return value;
@@ -480,20 +462,16 @@ var SearchPanel = Widget.extend({
* @private
* @returns {Array[]}
*/
- _getCategoryDomain: function () {
- var self = this;
-
- function categoryToDomain(domain, categoryId) {
- var category = self.categories[categoryId];
+ _getCategoryDomain() {
+ const domain = [];
+ for (const category of Object.values(this.categories)) {
if (category.activeValueId) {
- var field = self.fields[category.fieldName];
- var op = (field.type === 'many2one' && category.parentField) ? 'child_of' : '=';
+ const field = this.fields[category.fieldName];
+ const op = (field.type === 'many2one' && category.parentField) ? 'child_of' : '=';
domain.push([category.fieldName, op, category.activeValueId]);
}
- return domain;
}
-
- return Object.keys(this.categories).reduce(categoryToDomain, []);
+ return domain;
},
/**
* Compute and return the domain based on the current checked filters.
@@ -504,40 +482,36 @@ var SearchPanel = Widget.extend({
* a group (and grouped using an 'OR').
*
* @private
+ * @param {string} filterId
* @returns {Array[]}
*/
- _getFilterDomain: function () {
- var self = this;
+ _getFilterDomain(filterId) {
+ const domain = [];
- function getCheckedValueIds(values) {
- return Object.keys(values).reduce(function (checkedValues, valueId) {
- if (values[valueId].checked) {
- checkedValues.push(values[valueId].id);
- }
- return checkedValues;
- }, []);
+ function addCondition(fieldName, checkedValues) {
+ if (checkedValues.length) {
+ const ids = checkedValues.map(v => v.id);
+ domain.push([fieldName, 'in', ids]);
+ }
}
- function filterToDomain(domain, filterId) {
- var filter = self.filters[filterId];
+ for (const filter of Object.values(this.filters)) {
+ if (filter.id === filterId) {
+ continue;
+ }
+ const { fieldName } = filter;
+ let checkedValues;
if (filter.groups) {
- Object.keys(filter.groups).forEach(function (groupId) {
- var group = filter.groups[groupId];
- var checkedValues = getCheckedValueIds(group.values);
- if (checkedValues.length) {
- domain.push([filter.fieldName, 'in', checkedValues]);
- }
- });
- } else if (filter.values) {
- var checkedValues = getCheckedValueIds(filter.values);
- if (checkedValues.length) {
- domain.push([filter.fieldName, 'in', checkedValues]);
+ for (const group of Object.values(filter.groups)) {
+ checkedValues = Object.values(group.values).filter(v => v.checked);
+ addCondition(fieldName, checkedValues);
}
+ } else if (filter.values) {
+ checkedValues = Object.values(filter.values).filter(v => v.checked);
+ addCondition(fieldName, checkedValues);
}
- return domain;
}
-
- return Object.keys(this.filters).reduce(filterToDomain, []);
+ return domain;
},
/**
* The active id of each category is stored in the localStorage, s.t. it
@@ -547,7 +521,7 @@ var SearchPanel = Widget.extend({
* @param {Object} category
* @returns {string}
*/
- _getLocalStorageKey: function (category) {
+ _getLocalStorageKey(category) {
return 'searchpanel_' + this.model + '_' + category.fieldName;
},
/**
@@ -557,9 +531,8 @@ var SearchPanel = Widget.extend({
* @returns {integer[]} list of ids of the ancestors of the given value in
* the given category
*/
- _getAncestorValueIds: function (category, categoryValueId) {
- var categoryValue = category.values[categoryValueId];
- var parentId = categoryValue.parentId;
+ _getAncestorValueIds(category, categoryValueId) {
+ const { parentId } = category.values[categoryValueId];
if (parentId) {
return [parentId].concat(this._getAncestorValueIds(category, parentId));
}
@@ -575,7 +548,7 @@ var SearchPanel = Widget.extend({
*
* @private
*/
- _notifyDomainUpdated: function () {
+ _notifyDomainUpdated() {
this.needReload = true;
this.trigger_up('search_panel_domain_updated', {
domain: this.getDomain(),
@@ -584,27 +557,20 @@ var SearchPanel = Widget.extend({
/**
* @private
*/
- _render: function () {
- var self = this;
+ _render() {
this.$el.empty();
// sort categories and filters according to their index
- var categories = Object.keys(this.categories).map(function (categoryId) {
- return self.categories[categoryId];
- });
- var filters = Object.keys(this.filters).map(function (filterId) {
- return self.filters[filterId];
- });
- var sections = categories.concat(filters).sort(function (s1, s2) {
- return s1.index - s2.index;
- });
+ const categories = Object.values(this.categories);
+ const filters = Object.values(this.filters);
+ const sections = categories.concat(filters).sort((s1, s2) => s1.index - s2.index);
- sections.forEach(function (section) {
+ sections.forEach(section => {
if (Object.keys(section.values).length) {
if (section.type === 'category') {
- self.$el.append(self._renderCategory(section));
+ this.$el.append(this._renderCategory(section));
} else {
- self.$el.append(self._renderFilter(section));
+ this.$el.append(this._renderFilter(section));
}
}
});
@@ -614,30 +580,29 @@ var SearchPanel = Widget.extend({
* @param {Object} category
* @returns {string}
*/
- _renderCategory: function (category) {
- return qweb.render('SearchPanel.Category', {category: category});
+ _renderCategory(category) {
+ return qweb.render('SearchPanel.Category', { category });
},
/**
* @private
* @param {Object} filter
- * @returns {jQuery}
+ * @returns {HTMLElement}
*/
- _renderFilter: function (filter) {
- var $filter = $(qweb.render('SearchPanel.Filter', {filter: filter}));
+ _renderFilter(filter) {
+ const filterElement = $(qweb.render('SearchPanel.Filter', { filter }))[0];
// set group inputs in indeterminate state when necessary
- Object.keys(filter.groups || {}).forEach(function (groupId) {
- var state = filter.groups[groupId].state;
+ Object.keys(filter.groups || {}).forEach(groupId => {
+ const group = filter.groups[groupId];
+ const { state } = group;
// group 'false' is not displayed
if (groupId !== 'false' && state === 'indeterminate') {
- $filter
- .find('.o_search_panel_filter_group[data-group-id=' + groupId + '] input')
- .get(0)
- .indeterminate = true;
+ const sel = `.o_search_panel_filter_group[data-group-id="${groupId}"] input`;
+ filterElement.querySelector(sel).indeterminate = true;
}
});
- return $filter;
+ return filterElement;
},
/**
* Updates the state property of a given filter's group according to the
@@ -646,37 +611,38 @@ var SearchPanel = Widget.extend({
* @private
* @param {Object} group
*/
- _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';
+ _updateFilterGroupState(group) {
+ if (Object.values(group.values).some(v => v.checked)) {
+ if (Object.values(group.values).some(v => !v.checked)) {
+ group.state = 'indeterminate';
+ } else {
+ group.state = 'checked';
+ }
} else {
group.state = 'unchecked';
}
},
- //--------------------------------------------------------------------------
+ //-------------------------------------------------------------------------
// Handlers
- //--------------------------------------------------------------------------
+ //-------------------------------------------------------------------------
/**
* @private
* @param {MouseEvent} ev
*/
- _onCategoryValueClicked: function (ev) {
+ _onCategoryValueClicked(ev) {
ev.stopPropagation();
- var $item = $(ev.currentTarget).closest('.o_search_panel_category_value');
- var category = this.categories[$item.data('categoryId')];
- var valueId = $item.data('id') || false;
+ const item = ev.currentTarget.closest('.o_search_panel_category_value');
+ const category = this.categories[item.dataset.categoryId];
+ const valueId = !isNaN(item.dataset.id) ?
+ Number(item.dataset.id) :
+ item.dataset.id || false;
category.activeValueId = valueId;
if (category.values[valueId]) {
category.values[valueId].folded = !category.values[valueId].folded;
}
- var storageKey = this._getLocalStorageKey(category);
+ const storageKey = this._getLocalStorageKey(category);
this.call('local_storage', 'setItem', storageKey, valueId);
this._notifyDomainUpdated();
},
@@ -684,15 +650,14 @@ var SearchPanel = Widget.extend({
* @private
* @param {MouseEvent} ev
*/
- _onFilterGroupChanged: function (ev) {
+ _onFilterGroupChanged(ev) {
ev.stopPropagation();
- var $item = $(ev.target).closest('.o_search_panel_filter_group');
- var filter = this.filters[$item.data('filterId')];
- var groupId = $item.data('groupId');
- var group = filter.groups[groupId];
+ const item = ev.target.closest('.o_search_panel_filter_group');
+ const filter = this.filters[item.dataset.filterId];
+ const group = filter.groups[item.dataset.groupId];
group.state = group.state === 'checked' ? 'unchecked' : 'checked';
- Object.keys(group.values).forEach(function (valueId) {
- group.values[valueId].checked = group.state === 'checked';
+ Object.values(group.values).forEach(value => {
+ value.checked = group.state === 'checked';
});
this._notifyDomainUpdated();
},
@@ -700,14 +665,14 @@ var SearchPanel = Widget.extend({
* @private
* @param {MouseEvent} ev
*/
- _onFilterValueChanged: function (ev) {
+ _onFilterValueChanged(ev) {
ev.stopPropagation();
- var $item = $(ev.target).closest('.o_search_panel_filter_value');
- var valueId = $item.data('valueId');
- var filter = this.filters[$item.data('filterId')];
- var value = filter.values[valueId];
+ const item = ev.target.closest('.o_search_panel_filter_value');
+ const filter = this.filters[item.dataset.filterId];
+ const value = filter.values[item.dataset.valueId];
value.checked = !value.checked;
- var group = filter.groups && filter.groups[value.group_id];
+ const groupId = JSON.stringify(value.group_id);
+ const group = filter.groups && filter.groups[groupId];
if (group) {
this._updateFilterGroupState(group);
}
@@ -717,12 +682,12 @@ var SearchPanel = Widget.extend({
* @private
* @param {MouseEvent} ev
*/
- _onToggleFoldCategory: function (ev) {
+ _onToggleFoldCategory(ev) {
ev.preventDefault();
ev.stopPropagation();
- var $item = $(ev.currentTarget).closest('.o_search_panel_category_value');
- var category = this.categories[$item.data('categoryId')];
- var valueId = $item.data('id');
+ const item = ev.currentTarget.closest('.o_search_panel_category_value');
+ const category = this.categories[item.dataset.categoryId];
+ const valueId = item.dataset.id;
category.values[valueId].folded = !category.values[valueId].folded;
this._render();
},
@@ -730,12 +695,12 @@ var SearchPanel = Widget.extend({
* @private
* @param {MouseEvent} ev
*/
- _onToggleFoldFilterGroup: function (ev) {
+ _onToggleFoldFilterGroup(ev) {
ev.preventDefault();
ev.stopPropagation();
- var $item = $(ev.currentTarget).closest('.o_search_panel_filter_group');
- var filter = this.filters[$item.data('filterId')];
- var groupId = $item.data('groupId');
+ const item = ev.currentTarget.closest('.o_search_panel_filter_group');
+ const filter = this.filters[item.dataset.filterId];
+ const groupId = item.dataset.groupId;
filter.groups[groupId].folded = !filter.groups[groupId].folded;
this._render();
},