[REF] web: search panel goes ESNext

This commit is contained in:
Mathieu Duckerts-Antoine
2020-05-05 19:23:20 +00:00
parent d21c412985
commit c19dcf3983
+221 -256
View File
@@ -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);
init(parent, params) {
this._super(...arguments);
this.categories = _.pick(params.sections, function (section) {
return section.type === 'category';
});
this.filters = _.pick(params.sections, function (section) {
return section.type === 'filter';
});
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 filterToDomain(domain, filterId) {
var filter = self.filters[filterId];
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]);
}
function addCondition(fieldName, checkedValues) {
if (checkedValues.length) {
const ids = checkedValues.map(v => v.id);
domain.push([fieldName, 'in', ids]);
}
return domain;
}
return Object.keys(this.filters).reduce(filterToDomain, []);
for (const filter of Object.values(this.filters)) {
if (filter.id === filterId) {
continue;
}
const { fieldName } = filter;
let checkedValues;
if (filter.groups) {
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;
},
/**
* 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();
},