-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
/** | ||
* @license | ||
* Copyright CERN and copyright holders of ALICE O2. This software is | ||
* distributed under the terms of the GNU General Public License v3 (GPL | ||
* Version 3), copied verbatim in the file "COPYING". | ||
* | ||
* See http://alice-o2.web.cern.ch/license for full licensing information. | ||
* | ||
* In applying this license CERN does not waive the privileges and immunities | ||
* granted to it by virtue of its status as an Intergovernmental Organization | ||
* or submit itself to any jurisdiction. | ||
*/ | ||
|
||
import { Observable } from '/js/src/index.js'; | ||
import { FilterModel } from './FilterModel.js'; | ||
import { ToggleableModel } from '../../common/toggle/TogglableModel.js'; | ||
|
||
/** | ||
* Model representing a filtering system, including filter inputs visibility, filters values and so on | ||
*/ | ||
export class FilteringModel extends Observable { | ||
/** | ||
* Constructor | ||
* | ||
* @param {FilterModel} filters the filters list model | ||
*/ | ||
constructor(filters) { | ||
super(); | ||
|
||
this._visualChange$ = new Observable(); | ||
|
||
this._toggleModel = new ToggleableModel(); | ||
this._toggleModel.bubbleTo(this._visualChange$); | ||
|
||
/** | ||
* @type {Map<string, {filter: FilterModel, humanName: (string|undefined)}>} | ||
* @private | ||
*/ | ||
this._filtersMeta = new Map(); | ||
for (const propertyKey in filters) { | ||
this._addFilter(propertyKey, filters[propertyKey]); | ||
} | ||
|
||
this._filtersStore = filters; | ||
} | ||
|
||
/** | ||
* Reset the filters | ||
* | ||
* @return {void} | ||
*/ | ||
reset() { | ||
this._filtersMeta.forEach(({ filter }) => filter.reset()); | ||
} | ||
|
||
/** | ||
* Returns the normalized value of all the filters, without null values | ||
* | ||
* @return {Object} the normalized values | ||
*/ | ||
get normalized() { | ||
const ret = {}; | ||
for (const [filterKey, { filter }] of this._filtersMeta) { | ||
if (!filter.isEmpty) { | ||
ret[filterKey] = filter.normalized; | ||
} | ||
} | ||
return ret; | ||
} | ||
|
||
/** | ||
* States if there is currently at least one filter active | ||
* | ||
* @return {boolean} true if at least one filter is active | ||
*/ | ||
isAnyFilterActive() { | ||
for (const [, { filter }] of this._filtersMeta) { | ||
if (!filter.isEmpty) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
|
||
/** | ||
* Returns the list of human-readable names of currently active filters | ||
* | ||
* @return {string} the active filters names | ||
*/ | ||
get activeFiltersNames() { | ||
const ret = []; | ||
for (const [, { filter, humanName }] of this._filtersMeta) { | ||
if (!filter.isEmpty) { | ||
ret.push(humanName); | ||
} | ||
} | ||
return ret.join(', '); | ||
} | ||
|
||
/** | ||
* Returns the observable notified any time there is a visual change which has no impact on the actual filtering | ||
* | ||
* @return {Observable} the filters visibility observable | ||
*/ | ||
get visualChange$() { | ||
return this._visualChange$; | ||
} | ||
|
||
/** | ||
* Returns the object storing all the filters models | ||
* | ||
* @return {Object} the filters store | ||
*/ | ||
get filters() { | ||
return this._filtersStore; | ||
} | ||
|
||
/** | ||
* The visibility state of the filters popup | ||
* | ||
* @return {ToggleableModel} the toggle model | ||
*/ | ||
get toggleModel() { | ||
return this._toggleModel; | ||
} | ||
|
||
/** | ||
* Add a filter to the list of registered filters, and bubble filters events (global and visual) to this model | ||
* | ||
* @param {string} filterKey the key of the filter, used to normalize filtering request | ||
* @param {FilterModel} filter the filter model | ||
* @return {void} | ||
* @private | ||
*/ | ||
_addFilter(filterKey, filter) { | ||
this._filtersMeta.set( | ||
filterKey, | ||
{ | ||
filter, | ||
humanName: `${filterKey[0].toUpperCase()}${filterKey.slice(1).replaceAll(/([A-Z])/g, ' $1').toLowerCase()}`, | ||
}, | ||
); | ||
filter.bubbleTo(this); | ||
filter.visualChange$.bubbleTo(this._visualChange$); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
/** | ||
* @license | ||
* Copyright CERN and copyright holders of ALICE O2. This software is | ||
* distributed under the terms of the GNU General Public License v3 (GPL | ||
* Version 3), copied verbatim in the file "COPYING". | ||
* | ||
* See http://alice-o2.web.cern.ch/license for full licensing information. | ||
* | ||
* In applying this license CERN does not waive the privileges and immunities | ||
* granted to it by virtue of its status as an Intergovernmental Organization | ||
* or submit itself to any jurisdiction. | ||
*/ | ||
import { arrayHasSameContent } from '../../../../utilities/arrayHasSameContent.js'; | ||
import { FilterModel } from '../FilterModel.js'; | ||
|
||
/** | ||
* Model for a coma separated values filter | ||
* | ||
* This filter input is a comma separated list of values and its value is an array of values | ||
*/ | ||
export class CommaSeparatedValuesFilterModel extends FilterModel { | ||
/** | ||
* Constructor | ||
*/ | ||
constructor() { | ||
super(); | ||
Check warning on line 26 in lib/public/components/Filters/common/filters/CommaSeparatedValuesFilterModel.js Codecov / codecov/patchlib/public/components/Filters/common/filters/CommaSeparatedValuesFilterModel.js#L25-L26
|
||
|
||
this._values = null; | ||
this._raw = ''; | ||
Check warning on line 29 in lib/public/components/Filters/common/filters/CommaSeparatedValuesFilterModel.js Codecov / codecov/patchlib/public/components/Filters/common/filters/CommaSeparatedValuesFilterModel.js#L28-L29
|
||
} | ||
|
||
// eslint-disable-next-line valid-jsdoc | ||
/** | ||
* @inheritDoc | ||
* @override | ||
*/ | ||
reset() { | ||
this._values = null; | ||
this._raw = ''; | ||
Check warning on line 39 in lib/public/components/Filters/common/filters/CommaSeparatedValuesFilterModel.js Codecov / codecov/patchlib/public/components/Filters/common/filters/CommaSeparatedValuesFilterModel.js#L37-L39
|
||
} | ||
|
||
// eslint-disable-next-line valid-jsdoc | ||
/** | ||
* @inheritDoc | ||
* @override | ||
*/ | ||
get isEmpty() { | ||
const { values } = this; | ||
return !values || values.length === 0; | ||
Check warning on line 49 in lib/public/components/Filters/common/filters/CommaSeparatedValuesFilterModel.js Codecov / codecov/patchlib/public/components/Filters/common/filters/CommaSeparatedValuesFilterModel.js#L47-L49
|
||
} | ||
|
||
// eslint-disable-next-line valid-jsdoc | ||
/** | ||
* @inheritDoc | ||
* @override | ||
*/ | ||
get normalized() { | ||
return this.values; | ||
Check warning on line 58 in lib/public/components/Filters/common/filters/CommaSeparatedValuesFilterModel.js Codecov / codecov/patchlib/public/components/Filters/common/filters/CommaSeparatedValuesFilterModel.js#L57-L58
|
||
} | ||
|
||
/** | ||
* Define the current value of the filter | ||
* | ||
* @param {string} raw the raw value of the filter | ||
* @param {array} values the list of parsed values of the filter | ||
* | ||
* @return {void} | ||
*/ | ||
update(raw, values) { | ||
const previousValues = [...this._values || []]; | ||
Check warning on line 70 in lib/public/components/Filters/common/filters/CommaSeparatedValuesFilterModel.js Codecov / codecov/patchlib/public/components/Filters/common/filters/CommaSeparatedValuesFilterModel.js#L69-L70
|
||
|
||
this._values = values; | ||
this._raw = raw; | ||
Check warning on line 73 in lib/public/components/Filters/common/filters/CommaSeparatedValuesFilterModel.js Codecov / codecov/patchlib/public/components/Filters/common/filters/CommaSeparatedValuesFilterModel.js#L72-L73
|
||
|
||
if (arrayHasSameContent(values || [], previousValues)) { | ||
// Only raw value changed | ||
this.visualChange$.notify(); | ||
} else { | ||
this.notify(); | ||
} | ||
} | ||
|
||
/** | ||
* Returns the raw value of the filter (the user input) | ||
* | ||
* @return {string} the raw value | ||
*/ | ||
get raw() { | ||
return this._raw; | ||
Check warning on line 89 in lib/public/components/Filters/common/filters/CommaSeparatedValuesFilterModel.js Codecov / codecov/patchlib/public/components/Filters/common/filters/CommaSeparatedValuesFilterModel.js#L88-L89
|
||
} | ||
|
||
/** | ||
* Return the parsed values of the filter | ||
* | ||
* @return {array} the parsed values | ||
*/ | ||
get values() { | ||
if (!Array.isArray(this._values) || this._values.length === 0) { | ||
return null; | ||
Check warning on line 99 in lib/public/components/Filters/common/filters/CommaSeparatedValuesFilterModel.js Codecov / codecov/patchlib/public/components/Filters/common/filters/CommaSeparatedValuesFilterModel.js#L97-L99
|
||
} | ||
return this._values; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
/** | ||
* @license | ||
* Copyright CERN and copyright holders of ALICE O2. This software is | ||
* distributed under the terms of the GNU General Public License v3 (GPL | ||
* Version 3), copied verbatim in the file "COPYING". | ||
* | ||
* See http://alice-o2.web.cern.ch/license for full licensing information. | ||
* | ||
* In applying this license CERN does not waive the privileges and immunities | ||
* granted to it by virtue of its status as an Intergovernmental Organization | ||
* or submit itself to any jurisdiction. | ||
*/ | ||
|
||
import { FilterModel } from '../FilterModel.js'; | ||
|
||
export const COMPARISON_OPERATORS = ['<', '<=', '=', '>=', '>']; | ||
export const DEFAULT_COMPARISON_OPERATOR = '='; | ||
|
||
/** | ||
* Model representing comparison operator filter | ||
* | ||
* @template T | ||
*/ | ||
export class ComparisonOperatorFilterModel extends FilterModel { | ||
/** | ||
* Constructor | ||
*/ | ||
constructor() { | ||
super(); | ||
|
||
this._operator = DEFAULT_COMPARISON_OPERATOR; | ||
|
||
/** | ||
* @type {(T|null)} | ||
* @private | ||
*/ | ||
this._limit = null; | ||
} | ||
|
||
// eslint-disable-next-line valid-jsdoc | ||
/** | ||
* @override | ||
* @inheritDoc | ||
*/ | ||
reset() { | ||
this._operator = DEFAULT_COMPARISON_OPERATOR; | ||
this._limit = null; | ||
} | ||
|
||
// eslint-disable-next-line valid-jsdoc | ||
/** | ||
* @inheritDoc | ||
* @override | ||
*/ | ||
get isEmpty() { | ||
return this._limit === null; | ||
} | ||
|
||
/** | ||
* Updates the value of the operator and limit | ||
* | ||
* @param {object} raw the raw operator or/and limit of the filter | ||
* | ||
* @return {void} | ||
*/ | ||
update({ operator: rawOperator, limit: rawLimit }) { | ||
const operator = COMPARISON_OPERATORS.includes(rawOperator) ? rawOperator : this._operator; | ||
let limit = this._limit; | ||
if (rawLimit !== undefined) { | ||
try { | ||
limit = this.parseLimit(rawLimit); | ||
} catch (e) { | ||
// Keep the current limit | ||
} | ||
} | ||
const previousOperator = this._operator; | ||
this._operator = operator; | ||
|
||
const previousLimit = this._limit; | ||
this._limit = limit; | ||
|
||
if (previousOperator !== this._operator || previousLimit !== this._limit) { | ||
this.notify(); | ||
} else { | ||
this.visualChange$.notify(); | ||
} | ||
} | ||
|
||
/** | ||
* Parse the given limit into a limit compatible for the current filter | ||
* | ||
* As a default, returns raw limit without modification. Models for specific comparison filter must handle parse here | ||
* | ||
* @param {*} rawLimit the raw value of the limit | ||
* | ||
* @return {T} the parsed limit | ||
* @protected | ||
*/ | ||
parseLimit(rawLimit) { | ||
return rawLimit; | ||
Check warning on line 100 in lib/public/components/Filters/common/filters/ComparisonOperatorFilterModel.js Codecov / codecov/patchlib/public/components/Filters/common/filters/ComparisonOperatorFilterModel.js#L99-L100
|
||
} | ||
|
||
/** | ||
* Returns the current operator | ||
* | ||
* @return {string} the operator | ||
*/ | ||
get operator() { | ||
return this._operator; | ||
Check warning on line 109 in lib/public/components/Filters/common/filters/ComparisonOperatorFilterModel.js Codecov / codecov/patchlib/public/components/Filters/common/filters/ComparisonOperatorFilterModel.js#L108-L109
|
||
} | ||
|
||
/** | ||
* Returns the current limit | ||
* | ||
* @return {T} the current limit | ||
*/ | ||
get limit() { | ||
return this._limit; | ||
Check warning on line 118 in lib/public/components/Filters/common/filters/ComparisonOperatorFilterModel.js Codecov / codecov/patchlib/public/components/Filters/common/filters/ComparisonOperatorFilterModel.js#L117-L118
|
||
} | ||
} |