diff --git a/lib/public/models/FilterableOverviewPageModel.js b/lib/public/models/FilterableOverviewPageModel.js new file mode 100644 index 0000000000..b3d954e05d --- /dev/null +++ b/lib/public/models/FilterableOverviewPageModel.js @@ -0,0 +1,132 @@ +/** + * @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 { buildUrl } from '/js/src/index.js'; +import { OverviewPageModel } from './OverviewModel.js'; +import { FilteringModel } from '../components/Filters/common/FilteringModel.js'; + +/** + * Base model for a filterable overview page + * + * @template T the type of data displayed in the overview page + */ +export class FilterableOverviewPageModel extends OverviewPageModel { + /** + * Constructor + * @param {QueryRouter} router router that controls the application's page navigation + * @param {string} pageIdentifier string that indicates what page this model represents + * @param {Object} filters the filters with their label and model + */ + constructor(router, pageIdentifier, filters) { + super(); + this._filteringModel = new FilteringModel(router, filters, this._warnings); + + this._filteringModel.pageIdentifier = pageIdentifier; + this._filteringModel.visualChange$.bubbleTo(this); + this._filteringModel.observe(() => this._applyFilters()); + this._sortModel.unobserve(this._sortModelCallback); + this._sortModel.observe(() => this._applyFilters()); + this._debouncedLoad = (_time) => {}; // Abstract, does nothing on purpose + this._fetchInstantly = true; + } + + /** + * Builds a url string from filters and a base string + * + * @param {string} base the base string from which the endpoint will be built + * @return {string} + */ + buildRootEndpoint(base) { + return buildUrl(base, { filter: this.getFilterParams() }); + } + + /** + * Sets the fetchInstantly boolean + * @param {boolean} bool the value to set + * @return {void} + */ + set fetchInstantly(bool) { + this._fetchInstantly = bool; + } + + /** + * Returns all filtering, sorting and pagination settings to their default values + * @param {boolean} [fetch = true] whether to refetch all data after filters have been reset + * @return {void} + */ + reset(fetch = true) { + super.reset(); + this.resetFiltering(fetch); + } + + /** + * Reset all filtering models + * @param {boolean} fetch Whether to refetch all data after filters have been reset + * @param {boolean} [clearUrl=false] if true filters will be removed from the url + * @return {void} + */ + resetFiltering(fetch = true, clearUrl = false) { + this._filteringModel.reset(false, clearUrl); + + if (fetch) { + this._applyFilters(true); + } + } + + /** + * Checks if any filter value has been modified from their default (empty) + * @return {Boolean} If any filter is active + */ + isAnyFilterActive() { + return this._filteringModel.isAnyFilterActive(); + } + + /** + * Apply the current filtering and update the remote data list + * + * @param {boolean} now if true, filtering will be applied now without debouncing + * + * @return {void} + */ + _applyFilters() { + this._pagination.silentlySetCurrentPage(1); + this._fetchInstantly ? this.load() : this._debouncedLoad(); + } + + /** + * Set underlying FilteringModel's filters from the query parameters in the URL + * + * @param {boolean} notify if the FilteringModel should notify it's observers after finishing setting the filters + */ + setFilterFromURL(notify) { + this._filteringModel.setFilterFromURL(notify); + } + + /** + * Return the filtering model + * + * @return {FilteringModel} the filtering model + */ + get filteringModel() { + return this._filteringModel; + } + + /** + * Return filter params of base model + * + * @return {object} filter + */ + getFilterParams() { + return this._filteringModel.normalized; + } +} diff --git a/lib/public/models/OverviewModel.js b/lib/public/models/OverviewModel.js index d278c4d0ed..73334c204b 100644 --- a/lib/public/models/OverviewModel.js +++ b/lib/public/models/OverviewModel.js @@ -40,10 +40,13 @@ export class OverviewPageModel extends Observable { super(); this._warnings = new Map(); this._sortModel = new SortModel(); - this._sortModel.observe(() => { + + this._sortModelCallback = () => { this._pagination.silentlySetCurrentPage(1); this.load(); - }); + }; + + this._sortModel.observe(this._sortModelCallback); this._sortModel.visualChange$.bubbleTo(this); // Single page data handling diff --git a/lib/public/views/DataPasses/DataPassesOverviewModel.js b/lib/public/views/DataPasses/DataPassesOverviewModel.js index 2834e1db1d..4d07c34e51 100644 --- a/lib/public/views/DataPasses/DataPassesOverviewModel.js +++ b/lib/public/views/DataPasses/DataPassesOverviewModel.js @@ -11,77 +11,29 @@ * or submit itself to any jurisdiction. */ import { SelectionModel } from '../../components/common/selection/SelectionModel.js'; -import { FilteringModel } from '../../components/Filters/common/FilteringModel.js'; import { TextTokensFilterModel } from '../../components/Filters/common/filters/TextTokensFilterModel.js'; import { NON_PHYSICS_PRODUCTIONS_NAMES_WORDS } from '../../domain/enums/NonPhysicsProductionsNamesWords.js'; -import { OverviewPageModel } from '../../models/OverviewModel.js'; +import { FilterableOverviewPageModel } from '../../models/FilterableOverviewPageModel.js'; /** * Data Passes overview model */ -export class DataPassesOverviewModel extends OverviewPageModel { +export class DataPassesOverviewModel extends FilterableOverviewPageModel { /** * Constructor * @param {QueryRouter} router router that controls the application's page navigation * @param {string} pageIdentifier string that indicates what page this model represents */ constructor(router, pageIdentifier) { - super(); - this._filteringModel = new FilteringModel( + super( router, + pageIdentifier, { names: new TextTokensFilterModel(), permittedNonPhysicsNames: new SelectionModel({ availableOptions: NON_PHYSICS_PRODUCTIONS_NAMES_WORDS.map((word) => ({ label: word.toUpperCase(), value: word })), }), }, - this._warnings, ); - - this._filteringModel.pageIdentifier = pageIdentifier; - this._filteringModel.visualChange$.bubbleTo(this); - this._filteringModel.observe(() => { - this._pagination.currentPage = 1; - this.load(); - }); - } - - /** - * Return filter params of base model - * - * @return {object} filter - */ - getFilterParams() { - return this._filteringModel.normalized; - } - - /** - * Set underlying FilteringModel's filters from the query parameters in the URL - * - * @param {boolean} notify if the FilteringModel should notify it's observers after finishing setting the filters - */ - setFilterFromURL(notify) { - this._filteringModel.setFilterFromURL(notify); - } - - /** - * Reset this model to its default - * - * @param {boolean} _fetch Whether to refetch all data after filters have been reset - * @param {boolean} [clearUrl=false] if true filters will be removed from the url - * @return {void} - */ - reset(_fetch = true, clearUrl = false) { - this._filteringModel.reset(false, clearUrl); - super.reset(); - } - - /** - * Return the filtering model - * - * @return {FilteringModel} the filtering model - */ - get filteringModel() { - return this._filteringModel; } } diff --git a/lib/public/views/Environments/Overview/EnvironmentOverviewModel.js b/lib/public/views/Environments/Overview/EnvironmentOverviewModel.js index 5d6eb72cb3..9621e4df33 100644 --- a/lib/public/views/Environments/Overview/EnvironmentOverviewModel.js +++ b/lib/public/views/Environments/Overview/EnvironmentOverviewModel.js @@ -11,30 +11,26 @@ * or submit itself to any jurisdiction. */ -import { buildUrl } from '/js/src/index.js'; -import { FilteringModel } from '../../../components/Filters/common/FilteringModel.js'; -import { OverviewPageModel } from '../../../models/OverviewModel.js'; import { TimeRangeInputModel } from '../../../components/Filters/common/filters/TimeRangeInputModel.js'; import { RawTextFilterModel } from '../../../components/Filters/common/filters/RawTextFilterModel.js'; -import { debounce } from '../../../utilities/debounce.js'; import { coloredEnvironmentStatusComponent } from '../ColoredEnvironmentStatusComponent.js'; import { StatusAcronym } from '../../../domain/enums/statusAcronym.mjs'; import { SelectionModel } from '../../../components/common/selection/SelectionModel.js'; +import { FilterableOverviewPageModel } from '../../../models/FilterableOverviewPageModel.js'; /** * Environment overview page model */ -export class EnvironmentOverviewModel extends OverviewPageModel { +export class EnvironmentOverviewModel extends FilterableOverviewPageModel { /** * Constructor * @param {Model} model global model * @param {string} pageIdentifier string that indicates what page this model represents */ constructor(model, pageIdentifier) { - super(); - - this._filteringModel = new FilteringModel( + super( model.router, + pageIdentifier, { created: new TimeRangeInputModel(), runNumbers: new RawTextFilterModel(), @@ -48,35 +44,14 @@ export class EnvironmentOverviewModel extends OverviewPageModel { }), ids: new RawTextFilterModel(), }, - this._warnings, ); - - this._filteringModel.pageIdentifier = pageIdentifier; - this._filteringModel.observe(() => this._applyFilters(true)); - this._filteringModel.visualChange$?.bubbleTo(this); - - const updateDebounceTime = () => { - this._debouncedLoad = debounce(this.load.bind(this), model.inputDebounceTime); - }; - - model.appConfiguration$.observe(() => updateDebounceTime()); - updateDebounceTime(); } /** * @inheritDoc */ getRootEndpoint() { - return buildUrl('/api/environments', { filter: this.filteringModel.normalized }); - } - - /** - * Set underlying FilteringModel's filters from the query parameters in the URL - * - * @param {boolean} notify if the FilteringModel should notify it's observers after finishing setting the filters - */ - setFilterFromURL(notify) { - this._filteringModel.setFilterFromURL(notify); + return this.buildRootEndpoint('/api/environments'); } /** @@ -87,57 +62,4 @@ export class EnvironmentOverviewModel extends OverviewPageModel { get environments() { return this.items; } - - /** - * Returns all filtering, sorting and pagination settings to their default values - * @param {boolean} [fetch = true] whether to refetch all data after filters have been reset - * @return {void} - */ - reset(fetch = true) { - super.reset(); - this.resetFiltering(fetch); - } - - /** - * Reset all filtering models - * @param {boolean} fetch Whether to refetch all data after filters have been reset - * @param {boolean} [clearUrl=false] if true filters will be removed from the url - * @return {void} - */ - resetFiltering(fetch = true, clearUrl = false) { - this._filteringModel.reset(false, clearUrl); - - if (fetch) { - this._applyFilters(true); - } - } - - /** - * Checks if any filter value has been modified from their default (empty) - * @return {Boolean} If any filter is active - */ - isAnyFilterActive() { - return this._filteringModel.isAnyFilterActive(); - } - - /** - * Return the filtering model - * - * @return {FilteringModel} the filtering model - */ - get filteringModel() { - return this._filteringModel; - } - - /** - * Apply the current filtering and update the remote data list - * - * @param {boolean} now if true, filtering will be applied now without debouncing - * - * @return {void} - */ - _applyFilters(now = false) { - this._pagination.currentPage = 1; - now ? this.load() : this._debouncedLoad(true); - } } diff --git a/lib/public/views/LhcFills/Overview/LhcFillsOverviewModel.js b/lib/public/views/LhcFills/Overview/LhcFillsOverviewModel.js index 567182d3c5..3e73c2fa0f 100644 --- a/lib/public/views/LhcFills/Overview/LhcFillsOverviewModel.js +++ b/lib/public/views/LhcFills/Overview/LhcFillsOverviewModel.js @@ -11,22 +11,20 @@ * or submit itself to any jurisdiction. */ -import { buildUrl } from '/js/src/index.js'; -import { FilteringModel } from '../../../components/Filters/common/FilteringModel.js'; import { RawTextFilterModel } from '../../../components/Filters/common/filters/RawTextFilterModel.js'; -import { OverviewPageModel } from '../../../models/OverviewModel.js'; import { addStatisticsToLhcFill } from '../../../services/lhcFill/addStatisticsToLhcFill.js'; import { BeamTypeFilterModel } from '../../../components/Filters/LhcFillsFilter/BeamTypeFilterModel.js'; import { TextComparisonFilterModel } from '../../../components/Filters/common/filters/TextComparisonFilterModel.js'; import { TimeRangeFilterModel } from '../../../components/Filters/RunsFilter/TimeRangeFilter.js'; import { ToggleFilterModel } from '../../../components/Filters/common/filters/ToggleFilterModel.js'; +import { FilterableOverviewPageModel } from '../../../models/FilterableOverviewPageModel.js'; /** * Model for the LHC fills overview page * * @implements {OverviewModel} */ -export class LhcFillsOverviewModel extends OverviewPageModel { +export class LhcFillsOverviewModel extends FilterableOverviewPageModel { /** * Constructor * @@ -35,10 +33,9 @@ export class LhcFillsOverviewModel extends OverviewPageModel { * @param {string} pageIdentifier string that indicates what page this model represents */ constructor(router, stableBeamsOnly = false, pageIdentifier) { - super(); - - this._filteringModel = new FilteringModel( + super( router, + pageIdentifier, { fillNumbers: new RawTextFilterModel(), beamDuration: new TextComparisonFilterModel(), @@ -49,12 +46,7 @@ export class LhcFillsOverviewModel extends OverviewPageModel { beamTypes: new BeamTypeFilterModel(), schemeName: new RawTextFilterModel(), }, - this._warnings, ); - - this._filteringModel.pageIdentifier = pageIdentifier; - this._filteringModel.observe(() => this._applyFilters()); - this._filteringModel.visualChange$.bubbleTo(this); } /** @@ -71,66 +63,6 @@ export class LhcFillsOverviewModel extends OverviewPageModel { * @inheritDoc */ getRootEndpoint() { - return buildUrl('/api/lhcFills', { filter: this.filteringModel.normalized }); - } - - /** - * Set underlying FilteringModel's filters from the query parameters in the URL - * - * @param {boolean} notify if the FilteringModel should notify it's observers after finishing setting the filters - */ - setFilterFromURL(notify) { - this._filteringModel.setFilterFromURL(notify); - } - - /** - * Returns all filtering, sorting and pagination settings to their default values - * @param {boolean} [fetch = true] whether to refetch all data after filters have been reset - * @return {void} - */ - reset(fetch = true) { - super.reset(); - this.resetFiltering(fetch); - } - - /** - * Reset all filtering models - * @param {boolean} fetch Whether to refetch all data after filters have been reset - * @param {boolean} [clearUrl=false] if true filters will be removed from the url - * @return {void} - */ - resetFiltering(fetch = true, clearUrl = false) { - this._filteringModel.reset(false, clearUrl); - - if (fetch) { - this._applyFilters(); - } - } - - /** - * Checks if any filter value has been modified from their default (empty) - * @return {Boolean} If any filter is active - */ - isAnyFilterActive() { - return this._filteringModel.isAnyFilterActive(); - } - - /** - * Return the filtering model - * - * @return {FilteringModel} the filtering model - */ - get filteringModel() { - return this._filteringModel; - } - - /** - * Apply the current filtering and update the remote data list - * - * @return {void} - */ - _applyFilters() { - this._pagination.currentPage = 1; - this.load(); + return this.buildRootEndpoint('/api/lhcFills'); } } diff --git a/lib/public/views/Logs/Overview/LogsOverviewModel.js b/lib/public/views/Logs/Overview/LogsOverviewModel.js index de0f597c97..f8244d42a8 100644 --- a/lib/public/views/Logs/Overview/LogsOverviewModel.js +++ b/lib/public/views/Logs/Overview/LogsOverviewModel.js @@ -11,22 +11,19 @@ * or submit itself to any jurisdiction. */ -import { buildUrl } from '/js/src/index.js'; import { TagFilterModel } from '../../../components/Filters/common/TagFilterModel.js'; -import { debounce } from '../../../utilities/debounce.js'; import { AuthorFilterModel } from '../../../components/Filters/LogsFilter/author/AuthorFilterModel.js'; import { tagsProvider } from '../../../services/tag/tagsProvider.js'; -import { FilteringModel } from '../../../components/Filters/common/FilteringModel.js'; import { RawTextFilterModel } from '../../../components/Filters/common/filters/RawTextFilterModel.js'; import { TimeRangeInputModel } from '../../../components/Filters/common/filters/TimeRangeInputModel.js'; -import { OverviewPageModel } from '../../../models/OverviewModel.js'; +import { FilterableOverviewPageModel } from '../../../models/FilterableOverviewPageModel.js'; /** * Model representing handlers for log entries page * * @implements {OverviewModel} */ -export class LogsOverviewModel extends OverviewPageModel { +export class LogsOverviewModel extends FilterableOverviewPageModel { /** * The constructor of the Overview model object * @@ -35,9 +32,9 @@ export class LogsOverviewModel extends OverviewPageModel { * @param {string} pageIdentifier string that indicates what page this model represents */ constructor(model, excludeAnonymous = false, pageIdentifier) { - super(); - this._filteringModel = new FilteringModel( + super( model.router, + pageIdentifier, { author: new AuthorFilterModel(), title: new RawTextFilterModel(), @@ -48,84 +45,15 @@ export class LogsOverviewModel extends OverviewPageModel { fillNumbers: new RawTextFilterModel(), created: new TimeRangeInputModel(), }, - this._warnings, ); - const updateDebounceTime = () => { - this._debouncedLoad = debounce(this.load.bind(this), model.inputDebounceTime); - }; - - updateDebounceTime(); - model.appConfiguration$.observe(() => updateDebounceTime()); - - // Filters - this.filteringModel.pageIdentifier = pageIdentifier; excludeAnonymous && this._filteringModel.get('author').update('!Anonymous'); - this._filteringModel.observe(() => this._applyFilters()); - this._filteringModel.visualChange$.bubbleTo(this); - - // Sub-models - this._sortModel.observe(() => this._applyFilters(true)); - } - - /** - * Set underlying FilteringModel's filters from the query parameters in the URL - * - * @param {boolean} notify if the FilteringModel should notify it's observers after finishing setting the filters - */ - setFilterFromURL(notify) { - this._filteringModel.setFilterFromURL(notify); } /** * @inheritdoc */ getRootEndpoint() { - return buildUrl('/api/logs', { filter: this.filteringModel.normalized }); - } - - /** - * Reset all filtering, sorting and pagination settings to their default values - * - * @param {boolean} _fetch Whether to refetch all data after filters have been reset - * @param {boolean} [clearUrl=false] if true filters will be removed from the url - * @return {void} - */ - reset(_fetch = true, clearUrl = false) { - this._filteringModel.reset(false, clearUrl); - this._pagination.reset(); - - if (fetch) { - this._applyFilters(true); - } - } - - /** - * Checks if any filter value has been modified from their default (empty) - * @returns {boolean} If any filter is active - */ - isAnyFilterActive() { - return this._filteringModel.isAnyFilterActive(); - } - - /** - * Return the model managing all filters - * - * @return {FilteringModel} the filtering model - */ - get filteringModel() { - return this._filteringModel; - } - - /** - * Apply the current filtering and update the remote data list - * - * @param {boolean} now if true, filtering will be applied now without debouncing - * - * @return {void} - */ - _applyFilters(now = false) { - this._pagination.silentlySetCurrentPage(1); - now ? this.load() : this._debouncedLoad(); + return this.buildRootEndpoint('/api/logs'); } } diff --git a/lib/public/views/QcFlagTypes/Overview/QcFlagTypesOverviewModel.js b/lib/public/views/QcFlagTypes/Overview/QcFlagTypesOverviewModel.js index a87baedaa5..8f12861e8f 100644 --- a/lib/public/views/QcFlagTypes/Overview/QcFlagTypesOverviewModel.js +++ b/lib/public/views/QcFlagTypes/Overview/QcFlagTypesOverviewModel.js @@ -12,85 +12,34 @@ */ import { TextTokensFilterModel } from '../../../components/Filters/common/filters/TextTokensFilterModel.js'; -import { OverviewPageModel } from '../../../models/OverviewModel.js'; -import { buildUrl } from '/js/src/index.js'; -import { FilteringModel } from '../../../components/Filters/common/FilteringModel.js'; import { RadioButtonFilterModel } from '../../../components/Filters/common/RadioButtonFilterModel.js'; +import { FilterableOverviewPageModel } from '../../../models/FilterableOverviewPageModel.js'; /** * QcFlagTypesOverviewModel */ -export class QcFlagTypesOverviewModel extends OverviewPageModel { +export class QcFlagTypesOverviewModel extends FilterableOverviewPageModel { /** * Constructor * @param {QueryRouter} router router that controls the application's page navigation * @param {string} pageIdentifier string that indicates what page this model represents */ constructor(router, pageIdentifier) { - super(); - - this._filteringModel = new FilteringModel( + super( router, + pageIdentifier, { names: new TextTokensFilterModel(), methods: new TextTokensFilterModel(), bad: new RadioButtonFilterModel([{ label: 'Any' }, { label: 'Bad', value: true }, { label: 'Not Bad', value: false }]), }, - this._warnings, ); - - this._filteringModel.pageIdentifier = pageIdentifier; - this._filteringModel.observe(() => { - this._pagination.silentlySetCurrentPage(1); - this.load(); - }); - - this._filteringModel.visualChange$.bubbleTo(this); } /** * @inheritdoc */ getRootEndpoint() { - return buildUrl('/api/qcFlagTypes', { filter: this._filteringModel.normalized }); - } - - /** - * Set underlying FilteringModel's filters from the query parameters in the URL - * - * @param {boolean} notify if the FilteringModel should notify it's observers after finishing setting the filters - */ - setFilterFromURL(notify) { - this._filteringModel.setFilterFromURL(notify); - } - - /** - * Return the model managing all filters - * - * @return {FilteringModel} the filtering model - */ - get filteringModel() { - return this._filteringModel; - } - - /** - * States whether any filter is active - * - * @return {boolean} true if any filter is active - */ - isAnyFilterActive() { - return this._filteringModel.isAnyFilterActive(); - } - - /** - * Reset this model to its default - * - * @param {boolean} _fetch Whether to refetch all data after filters have been reset - * @param {boolean} [clearUrl=false] if true filters will be removed from the url - * @return {void} - */ - reset(_fetch = true, clearUrl = false) { - this._filteringModel.reset(false, clearUrl); - super.reset(); + return this.buildRootEndpoint('/api/qcFlagTypes'); } } diff --git a/lib/public/views/Runs/Overview/RunsOverviewModel.js b/lib/public/views/Runs/Overview/RunsOverviewModel.js index 1b15fff0dc..c6912513b6 100644 --- a/lib/public/views/Runs/Overview/RunsOverviewModel.js +++ b/lib/public/views/Runs/Overview/RunsOverviewModel.js @@ -11,18 +11,15 @@ * or submit itself to any jurisdiction. */ -import { buildUrl } from '/js/src/index.js'; import { TagFilterModel } from '../../../components/Filters/common/TagFilterModel.js'; -import { debounce } from '../../../utilities/debounce.js'; import { DetectorsFilterModel } from '../../../components/Filters/RunsFilter/DetectorsFilterModel.js'; import { RunTypesFilterModel } from '../../../components/runTypes/RunTypesFilterModel.js'; import { EorReasonFilterModel } from '../../../components/Filters/RunsFilter/EorReasonFilterModel.js'; -import { OverviewPageModel } from '../../../models/OverviewModel.js'; +import { FilterableOverviewPageModel } from '../../../models/FilterableOverviewPageModel.js'; import { CombinationOperator } from '../../../components/Filters/common/CombinationOperatorChoiceModel.js'; import { NumericalComparisonFilterModel } from '../../../components/Filters/common/filters/NumericalComparisonFilterModel.js'; import { detectorsProvider } from '../../../services/detectors/detectorsProvider.js'; import { MagnetsFilteringModel } from '../../../components/Filters/RunsFilter/MagnetsFilteringModel.js'; -import { FilteringModel } from '../../../components/Filters/common/FilteringModel.js'; import { tagsProvider } from '../../../services/tag/tagsProvider.js'; import { eorReasonTypeProvider } from '../../../services/eorReason/eorReasonTypeProvider.js'; import { runTypesProvider } from '../../../services/runTypes/runTypesProvider.js'; @@ -44,17 +41,16 @@ import { TRIGGER_VALUES } from '../../../domain/enums/TriggerValue.js'; * * @implements {OverviewModel} */ -export class RunsOverviewModel extends OverviewPageModel { +export class RunsOverviewModel extends FilterableOverviewPageModel { /** * The constructor of the Overview model object * @param {Model} model global model * @param {string} pageIdentifier string that indicates what page this model represents */ constructor(model, pageIdentifier) { - super(); - - this._filteringModel = new FilteringModel( + super( model.router, + pageIdentifier, { runNumbers: new RawTextFilterModel(), detectors: new DetectorsFilterModel(detectorsProvider.dataTaking$), @@ -100,103 +96,36 @@ export class RunsOverviewModel extends OverviewPageModel { epn: new RadioButtonFilterModel([{ label: 'ANY' }, { label: 'ON', value: true }, { label: 'OFF', value: false }]), triggerValues: new SelectionModel({ availableOptions: TRIGGER_VALUES.map((value) => ({ label: value, value })) }), }, - this._warnings, ); - this._filteringModel.pageIdentifier = pageIdentifier; - this._filteringModel.observe(() => this._applyFilters(true)); - this._filteringModel.visualChange$.bubbleTo(this); - - const updateDebounceTime = () => { - this._debouncedLoad = debounce(this.load.bind(this), model.inputDebounceTime); - }; - this._exportModel = new DataExportModel(this._allItems$, dataExportConfiguration, () => this.loadAll()); this._exportModel.bubbleTo(this); this._item$.observe(() => { this._exportModel.setDisabled(!this.hasAnyData()); this._exportModel.setTotalExistingItemsCount(this._pagination.itemsCount); }); - - model.appConfiguration$.observe(() => updateDebounceTime()); - updateDebounceTime(); - } - - /** - * Get export model - * @return {DataExportModel} export model - */ - get exportModel() { - return this._exportModel; } /** * @inheritdoc */ - getRootEndpoint() { - return buildUrl('/api/runs', { filter: this.filteringModel.normalized }); - } - - /** - * Returns all filtering, sorting and pagination settings to their default values - * @param {boolean} [fetch = true] whether to refetch all data after filters have been reset - * @return {void} - */ reset(fetch = true) { - super.reset(); this._exportModel?.reset(); - this.resetFiltering(fetch); - } - - /** - * Reset all filtering models - * @param {boolean} fetch Whether to refetch all data after filters have been reset - * @param {boolean} [clearUrl=false] if true filters will be removed from the url - * @return {void} - */ - resetFiltering(fetch = true, clearUrl = false) { - this._filteringModel.reset(false, clearUrl); - - if (fetch) { - this._applyFilters(true); - } - } - - /** - * Set underlying FilteringModel's filters from the query parameters in the URL - * - * @param {boolean} notify if the FilteringModel should notify it's observers after finishing setting the filters - */ - setFilterFromURL(notify) { - this._filteringModel.setFilterFromURL(notify); - } - - /** - * Checks if any filter value has been modified from their default (empty) - * @return {Boolean} If any filter is active - */ - isAnyFilterActive() { - return this._filteringModel.isAnyFilterActive(); + super.reset(fetch); } /** - * Return the filtering model - * - * @return {FilteringModel} the filtering model + * Get export model + * @return {DataExportModel} export model */ - get filteringModel() { - return this._filteringModel; + get exportModel() { + return this._exportModel; } /** - * Apply the current filtering and update the remote data list - * - * @param {boolean} now if true, filtering will be applied now without debouncing - * - * @return {void} + * @inheritdoc */ - _applyFilters(now = false) { - this._pagination.currentPage = 1; - now ? this.load() : this._debouncedLoad(true); + getRootEndpoint() { + return this.buildRootEndpoint('/api/runs'); } } diff --git a/lib/public/views/SimulationPasses/AnchoredOverview/AnchoredSimulationPassesOverviewModel.js b/lib/public/views/SimulationPasses/AnchoredOverview/AnchoredSimulationPassesOverviewModel.js index 810789c17f..3054251391 100644 --- a/lib/public/views/SimulationPasses/AnchoredOverview/AnchoredSimulationPassesOverviewModel.js +++ b/lib/public/views/SimulationPasses/AnchoredOverview/AnchoredSimulationPassesOverviewModel.js @@ -10,47 +10,26 @@ * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. */ -import { buildUrl, RemoteData } from '/js/src/index.js'; +import { RemoteData } from '/js/src/index.js'; import { TextTokensFilterModel } from '../../../components/Filters/common/filters/TextTokensFilterModel.js'; -import { OverviewPageModel } from '../../../models/OverviewModel.js'; import { getRemoteData } from '../../../utilities/fetch/getRemoteData.js'; import { ObservableData } from '../../../utilities/ObservableData.js'; -import { FilteringModel } from '../../../components/Filters/common/FilteringModel.js'; +import { FilterableOverviewPageModel } from '../../../models/FilterableOverviewPageModel.js'; /** * Simulation Passes Per Data Pass overview model */ -export class AnchoredSimulationPassesOverviewModel extends OverviewPageModel { +export class AnchoredSimulationPassesOverviewModel extends FilterableOverviewPageModel { /** * Constructor * @param {QueryRouter} router router that controls the application's page navigation * @param {string} pageIdentifier string that indicates what page this model represents */ constructor(router, pageIdentifier) { - super(); - - this._filteringModel = new FilteringModel(router, { names: new TextTokensFilterModel() }, this._warnings); - - this._filteringModel.pageIdentifier = pageIdentifier; - this._filteringModel.observe(() => { - this._pagination.silentlySetCurrentPage(1); - this.load(); - }); - - this._filteringModel.visualChange$.bubbleTo(this); - + super(router, pageIdentifier, { names: new TextTokensFilterModel() }); this._dataPass = new ObservableData(RemoteData.notAsked()); } - /** - * Set underlying FilteringModel's filters from the query parameters in the URL - * - * @param {boolean} notify if the FilteringModel should notify it's observers after finishing setting the filters - */ - setFilterFromURL(notify) { - this._filteringModel.setFilterFromURL(notify); - } - /** * Fetch data pass info which simulation passes are fetched * @return {Promise} promise @@ -76,30 +55,15 @@ export class AnchoredSimulationPassesOverviewModel extends OverviewPageModel { /** * @inheritdoc */ - getRootEndpoint() { - const filter = { ...this._filteringModel.normalized, dataPassIds: [this._dataPassId] }; - return buildUrl('/api/simulationPasses', { filter }); + getFilterParams() { + return { ...super.getFilterParams(), dataPassIds: [this._dataPassId] }; } /** - * Reset this model to its default - * - * @param {boolean} _fetch Whether to refetch all data after filters have been reset - * @param {boolean} [clearUrl=false] if true filters will be removed from the url - * @return {void} - */ - reset(_fetch = true, clearUrl = false) { - this._filteringModel.reset(false, clearUrl); - super.reset(); - } - - /** - * Return the model managing all filters - * - * @return {FilteringModel} the filtering model + * @inheritdoc */ - get filteringModel() { - return this._filteringModel; + getRootEndpoint() { + return this.buildRootEndpoint('/api/simulationPasses'); } /** @@ -116,12 +80,4 @@ export class AnchoredSimulationPassesOverviewModel extends OverviewPageModel { get dataPass() { return this._dataPass.getCurrent(); } - - /** - * States whether any filter is active - * @return {boolean} true if any filter is active - */ - isAnyFilterActive() { - return this._filteringModel.isAnyFilterActive(); - } } diff --git a/lib/public/views/SimulationPasses/PerLhcPeriodOverview/SimulationPassesPerLhcPeriodOverviewModel.js b/lib/public/views/SimulationPasses/PerLhcPeriodOverview/SimulationPassesPerLhcPeriodOverviewModel.js index ffc2eb5e02..0980a8c961 100644 --- a/lib/public/views/SimulationPasses/PerLhcPeriodOverview/SimulationPassesPerLhcPeriodOverviewModel.js +++ b/lib/public/views/SimulationPasses/PerLhcPeriodOverview/SimulationPassesPerLhcPeriodOverviewModel.js @@ -11,32 +11,22 @@ * or submit itself to any jurisdiction. */ import { TextTokensFilterModel } from '../../../components/Filters/common/filters/TextTokensFilterModel.js'; -import { OverviewPageModel } from '../../../models/OverviewModel.js'; -import { buildUrl, RemoteData } from '/js/src/index.js'; +import { RemoteData } from '/js/src/index.js'; import { ObservableData } from '../../../utilities/ObservableData.js'; import { getRemoteData } from '../../../utilities/fetch/getRemoteData.js'; -import { FilteringModel } from '../../../components/Filters/common/FilteringModel.js'; +import { FilterableOverviewPageModel } from '../../../models/FilterableOverviewPageModel.js'; /** * Simulation Passes Per LHC Period overview model */ -export class SimulationPassesPerLhcPeriodOverviewModel extends OverviewPageModel { +export class SimulationPassesPerLhcPeriodOverviewModel extends FilterableOverviewPageModel { /** * Constructor * @param {QueryRouter} router router that controls the application's page navigation * @param {string} pageIdentifier string that indicates what page this model represents */ constructor(router, pageIdentifier) { - super(); - - this._filteringModel = new FilteringModel(router, { names: new TextTokensFilterModel() }, this._warnings); - - this._filteringModel.pageIdentifier = pageIdentifier; - this._filteringModel.visualChange$.bubbleTo(this); - this._filteringModel.observe(() => { - this._pagination.silentlySetCurrentPage(1); - this.load(); - }); + super(router, pageIdentifier, { names: new TextTokensFilterModel() }); this._lhcPeriod = new ObservableData(RemoteData.notAsked()); this._lhcPeriod.bubbleTo(this); @@ -58,24 +48,6 @@ export class SimulationPassesPerLhcPeriodOverviewModel extends OverviewPageModel } } - /** - * Set underlying FilteringModel's filters from the query parameters in the URL - * - * @param {boolean} notify if the FilteringModel should notify it's observers after finishing setting the filters - */ - setFilterFromURL(notify) { - this._filteringModel.setFilterFromURL(notify); - } - - /** - * Return the model managing all filters - * - * @return {FilteringModel} the filtering model - */ - get filteringModel() { - return this._filteringModel; - } - /** * @inheritdoc */ @@ -87,21 +59,15 @@ export class SimulationPassesPerLhcPeriodOverviewModel extends OverviewPageModel /** * @inheritdoc */ - getRootEndpoint() { - const filter = { ...this._filteringModel.normalized, lhcPeriodIds: [this._lhcPeriodId] }; - return buildUrl('/api/simulationPasses', { filter }); + getFilterParams() { + return { ...super.getFilterParams(), lhcPeriodIds: [this._lhcPeriodId] }; } /** - * Reset this model to its default - * - * @param {boolean} _fetch Whether to refetch all data after filters have been reset - * @param {boolean} [clearUrl=false] if true filters will be removed from the url - * @return {void} + * @inheritdoc */ - reset(_fetch = true, clearUrl = false) { - this._filteringModel.reset(false, clearUrl); - super.reset(); + getRootEndpoint() { + return this.buildRootEndpoint('/api/simulationPasses'); } /** @@ -118,12 +84,4 @@ export class SimulationPassesPerLhcPeriodOverviewModel extends OverviewPageModel get lhcPeriod() { return this._lhcPeriod.getCurrent(); } - - /** - * States whether any filter is active - * @return {boolean} true if any filter is active - */ - isAnyFilterActive() { - return this._filteringModel.isAnyFilterActive(); - } } diff --git a/lib/public/views/lhcPeriods/Overview/LhcPeriodsOverviewModel.js b/lib/public/views/lhcPeriods/Overview/LhcPeriodsOverviewModel.js index f517fe02e7..88bf797877 100644 --- a/lib/public/views/lhcPeriods/Overview/LhcPeriodsOverviewModel.js +++ b/lib/public/views/lhcPeriods/Overview/LhcPeriodsOverviewModel.js @@ -11,66 +11,37 @@ * or submit itself to any jurisdiction. */ -import { FilteringModel } from '../../../components/Filters/common/FilteringModel.js'; import { TextTokensFilterModel } from '../../../components/Filters/common/filters/TextTokensFilterModel.js'; -import { OverviewPageModel } from '../../../models/OverviewModel.js'; -import { buildUrl } from '/js/src/index.js'; +import { FilterableOverviewPageModel } from '../../../models/FilterableOverviewPageModel.js'; /** * LHC Periods overview model * * @implements {OverviewModel} */ -export class LhcPeriodsOverviewModel extends OverviewPageModel { +export class LhcPeriodsOverviewModel extends FilterableOverviewPageModel { /** * The constructor of the Overview model object * @param {QueryRouter} router router that controls the application's page navigation * @param {string} pageIdentifier string that indicates what page this model represents */ constructor(router, pageIdentifier) { - super(); - - this._filteringModel = new FilteringModel( + super( router, + pageIdentifier, { names: new TextTokensFilterModel(), years: new TextTokensFilterModel(), pdpBeamTypes: new TextTokensFilterModel(), }, - this._warnings, ); - - this._filteringModel.pageIdentifier = pageIdentifier; - this._filteringModel.visualChange$.bubbleTo(this); - this._filteringModel.observe(() => { - this._pagination.silentlySetCurrentPage(1); - this.load(); - }); } /** * @inheritdoc */ getRootEndpoint() { - return buildUrl('/api/lhcPeriodsStatistics', { filter: this._filteringModel.normalized }); - } - - /** - * Set underlying FilteringModel's filters from the query parameters in the URL - * - * @param {boolean} notify if the FilteringModel should notify it's observers after finishing setting the filters - */ - setFilterFromURL(notify) { - this._filteringModel.setFilterFromURL(notify); - } - - /** - * Return the model managing all filters - * - * @return {FilteringModel} the filtering model - */ - get filteringModel() { - return this._filteringModel; + return this.buildRootEndpoint('/api/lhcPeriodsStatistics'); } /** @@ -88,24 +59,4 @@ export class LhcPeriodsOverviewModel extends OverviewPageModel { }; }); } - - /** - * Reset this model to its default - * - * @param {boolean} _fetch Whether to refetch all data after filters have been reset - * @param {boolean} [clearUrl=false] if true filters will be removed from the url - * @return {void} - */ - reset(_fetch = true, clearUrl = false) { - super.reset(); - this._filteringModel.reset(false, clearUrl); - } - - /** - * States whether any filter is active - * @return {boolean} true if any filter is active - */ - isAnyFilterActive() { - return this._filteringModel.isAnyFilterActive(); - } }