Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
3bc171a
feat: update filteringModel to set filters to the url when they are u…
Apr 21, 2026
0957b9e
chore: mover router instantiation to before the pageModel instantiations
Apr 21, 2026
23d02fc
chore: pass router to the dataPassOverview models
Apr 21, 2026
51b8827
chore: pass router to the EnvironmentOverviewModel models
Apr 21, 2026
22efa5f
chore: pass router to the EnvironmentOverviewModel models
Apr 21, 2026
325fb6e
chore: pass router to the LhcPeriodOverview model
Apr 21, 2026
69521dc
chore: pass router to the LogsOverview model
Apr 21, 2026
fda7ea1
chore: pass router to the QcFlagTypesOverview model
Apr 21, 2026
555cd6d
chore: pass router to the RunsOverview model
Apr 21, 2026
2da2473
chore: pass router to the Simulation pass overview models
Apr 21, 2026
61bcae0
fixup: the import of buildUrl
Apr 21, 2026
3f06051
chore: add pageidentifiers field to FilteringModel
Apr 21, 2026
fb562c8
chore: add page identifiers to all of the overview page models
Apr 21, 2026
fda9365
Merge branch 'improv/O2B-1557/Force-all-filters-managed-by-FilteringM…
Apr 21, 2026
3a3fa99
test: create tests for logsOverviewPage
Apr 22, 2026
4b7b1f1
test: create tests for logsOverviewPage
Apr 22, 2026
fd8d650
feat: remove url params upon reset
Apr 22, 2026
5a54dfe
test: create tests for lhcFillsOverviewPage
Apr 22, 2026
aa0fdba
test: create tests for runsOverviewPage
Apr 22, 2026
f1218bd
fix: add semicolon
Apr 22, 2026
f8372f9
test: create tests for flagtypes overview and lhcperiod overview
Apr 23, 2026
c9f979a
test add runsPerLhcPeriodOverview tests
Apr 23, 2026
3045d5a
test add DataPassesPerLhcPeriodOverview tests
Apr 23, 2026
c11492b
test add anchoredSimulationPassOverview tests
Apr 23, 2026
e2ac217
test add DataPassesPerSimulationPassOverview tests
Apr 23, 2026
fda76f8
add runs per simulationpass and datapass tests
Apr 23, 2026
8806283
add filters index file
Apr 23, 2026
78923f2
chore: remove router from the observable constructor in DatapassesModel
Apr 23, 2026
edbcbc3
fix lint issues
Apr 23, 2026
cbd335d
add clearUrl parameter to filterIngModel
Apr 23, 2026
1ec54b2
test: upgrade the fillInput function
Apr 23, 2026
1a6fe58
chore: fix eslint errors
Apr 23, 2026
d45eded
chore: add missing reset filtering params for logs
Apr 24, 2026
7df7607
chore: move the pageIdentifier definitions to the entity models
Apr 24, 2026
4a30d27
chore: rename pageIdentifiers to pageIdentifier
Apr 24, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions lib/public/Model.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,21 +95,27 @@ export default class Model extends Observable {
this._appConfiguration$ = new Observable();
this._inputDebounceTime = INPUT_DEBOUNCE_TIME;

// Setup router
this.router = new QueryRouter();
this.router.observe(this.handleLocationChange.bind(this));
this.router.bubbleTo(this);
registerFrontLinkListener((e) => this.router.handleLinkEvent(e));

// Models

this.home = new HomePageModel(this);
this.home.bubbleTo(this);

this.lhcPeriods = new LhcPeriodsModel(this);
this.lhcPeriods = new LhcPeriodsModel(this.router);
this.lhcPeriods.bubbleTo(this);

this.dataPasses = new DataPassesModel(this);
this.dataPasses = new DataPassesModel(this.router);
this.dataPasses.bubbleTo(this);

this.qcFlags = new QcFlagsModel(this);
this.qcFlags.bubbleTo(this);

this.simulationPasses = new SimulationPassesModel(this);
this.simulationPasses = new SimulationPassesModel(this.router);
this.simulationPasses.bubbleTo(this);

this.qcFlagTypes = new QcFlagTypesModel(this);
Expand Down Expand Up @@ -178,12 +184,6 @@ export default class Model extends Observable {
this.errorModel = new ErrorModel();
this.errorModel.bubbleTo(this);

// Setup router
this.router = new QueryRouter();
this.router.observe(this.handleLocationChange.bind(this));
this.router.bubbleTo(this);
registerFrontLinkListener((e) => this.router.handleLinkEvent(e));

// Init pages
this.handleLocationChange();
this.window.addEventListener('resize', debounce(() => this.notify(), 100));
Expand Down
46 changes: 41 additions & 5 deletions lib/public/components/Filters/common/FilteringModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import { expandQueryLikeNestedKey } from '../../../utilities/expandNestedKey.js';
import { SelectionModel } from '../../common/selection/SelectionModel.js';
import { FilterModel } from './FilterModel.js';
import { Observable } from '/js/src/index.js';
import { buildUrl, Observable } from '/js/src/index.js';

/**
* Model representing a filtering system, including filter inputs visibility, filters values and so on
Expand All @@ -23,32 +23,52 @@ export class FilteringModel extends Observable {
/**
* Constructor
*
* @param {QueryRouter} router router that controls the application's page navigation
* @param {Object<string, FilterModel>} filters the filters with their label and model
*/
constructor(filters) {
constructor(router, filters) {
super();

this._visualChange$ = new Observable();
this._pageIdentifier = null;

this._router = router;
this._filters = {};
this._filterModels = [];
Object.entries(filters).forEach(([key, model]) => this.put(key, model));
}

/**
* Sets the page identifiers
*
* @param {string} identifier a string identifies a page from the router params.
* Used to prevent unneeded reads/writes from/to the url
* @returns {void}
*/
set pageIdentifier(identifier) {
this._pageIdentifier = identifier;
}

/**
* Reset the filters
*
* @param {boolean} [notify=false] if true the model notifies its observers
* @param {boolean} [clearUrl=false] if true filters will be removed from the url
* @return {void}
*/
reset(notify = false) {
reset(notify = false, clearUrl = false) {
for (const model of this._filterModels) {
model.reset();
}

if (notify) {
this.notify();
}

if (clearUrl) {
const { params } = this._router;
delete params.filter;
this._router.go(buildUrl('?', params), false, true);
}
}

/**
Expand Down Expand Up @@ -104,6 +124,22 @@ export class FilteringModel extends Observable {
return this._filters[key];
}

/**
* When the user updates the displayed Objects, the filters should be placed in the URL as well
* @returns {undefined}
*/
setFilterToURL() {
const { params } = this._router;
const newParams = { ...params };
newParams.filter = this.normalized;

if (this._pageIdentifier === params.page) {
this._router.go(buildUrl('?', newParams), false, true);
}

this.notify();
}

/**
* Add new filter
*
Expand All @@ -123,7 +159,7 @@ export class FilteringModel extends Observable {

this._filters[key] = filter;
this._filterModels.push(filter);
filter.bubbleTo(this);
filter.observe(() => this.setFilterToURL());
filter.visualChange$?.bubbleTo(this._visualChange$);
}
}
4 changes: 2 additions & 2 deletions lib/public/components/Filters/common/filtersPanelPopover.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ const filtersToggleContentHeader = (filteringModel) => h('.flex-row.justify-betw
'button#reset-filters.btn.btn-danger',
{
onclick: () => filteringModel.resetFiltering
? filteringModel.resetFiltering()
: filteringModel.reset(true),
? filteringModel.resetFiltering(true, true)
: filteringModel.reset(true, true),
disabled: !filteringModel.isAnyFilterActive(),
},
'Reset all filters',
Expand Down
7 changes: 4 additions & 3 deletions lib/public/views/DataPasses/DataPassesModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,15 @@ import { DataPassesPerSimulationPassOverviewModel } from './PerSimulationPassOve
export class DataPassesModel extends Observable {
/**
* The constructor of the model
* @param {QueryRouter} router router that controls the application's page navigation
*/
constructor() {
constructor(router) {
super();

this._perLhcPeriodOverviewModel = new DataPassesPerLhcPeriodOverviewModel();
this._perLhcPeriodOverviewModel = new DataPassesPerLhcPeriodOverviewModel(router, 'data-passes-per-lhc-period-overview');
this._perLhcPeriodOverviewModel.bubbleTo(this);

this._perSimulationPassOverviewModel = new DataPassesPerSimulationPassOverviewModel();
this._perSimulationPassOverviewModel = new DataPassesPerSimulationPassOverviewModel(router, 'data-passes-per-simulation-pass-overview');
this._perSimulationPassOverviewModel.bubbleTo(this);
}

Expand Down
28 changes: 18 additions & 10 deletions lib/public/views/DataPasses/DataPassesOverviewModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,22 @@ import { OverviewPageModel } from '../../models/OverviewModel.js';
export class DataPassesOverviewModel 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
*/
constructor() {
constructor(router, pageIdentifier) {
super();
this._filteringModel = new FilteringModel({
names: new TextTokensFilterModel(),
'include[byName]': new SelectionFilterModel({
availableOptions: NON_PHYSICS_PRODUCTIONS_NAMES_WORDS.map((word) => ({ label: word.toUpperCase(), value: word })),
}),
});
this._filteringModel = new FilteringModel(
router,
{
names: new TextTokensFilterModel(),
'include[byName]': new SelectionFilterModel({
availableOptions: NON_PHYSICS_PRODUCTIONS_NAMES_WORDS.map((word) => ({ label: word.toUpperCase(), value: word })),
}),
},
);

this._filteringModel.pageIdentifier = pageIdentifier;
this._filteringModel.visualChange$.bubbleTo(this);
this._filteringModel.observe(() => {
this._pagination.currentPage = 1;
Expand All @@ -51,10 +57,12 @@ export class DataPassesOverviewModel extends OverviewPageModel {
/**
* Reset this model to its default
*
* @returns {void}
* @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() {
this._filteringModel.reset();
reset(_fetch = true, clearUrl = false) {
this._filteringModel.reset(false, clearUrl);
super.reset();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@ import { buildUrl } from '/js/src/index.js';
export class DataPassesPerLhcPeriodOverviewModel extends DataPassesOverviewModel {
/**
* Constructor
* @param {QueryRouter} router router that controls the application's page navigation
* @param {string} pageIdentifier string that indicates what page this model represents
*/
constructor() {
super();
constructor(router, pageIdentifier) {
super(router, pageIdentifier);
this._lhcPeriodId = null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@ import { DataPassesOverviewModel } from '../DataPassesOverviewModel.js';
export class DataPassesPerSimulationPassOverviewModel extends DataPassesOverviewModel {
/**
* Constructor
* @param {QueryRouter} router router that controls the application's page navigation
* @param {string} pageIdentifier string that indicates what page this model represents
*/
constructor() {
super();
constructor(router, pageIdentifier) {
super(router, pageIdentifier);
this._simulationPass = new ObservableData(RemoteData.notAsked());
this._simulationPass.bubbleTo(this);
}
Expand Down
2 changes: 1 addition & 1 deletion lib/public/views/Environments/EnvironmentModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export class EnvironmentModel extends Observable {
super();

// Sub-models
this._overviewModel = new EnvironmentOverviewModel(model);
this._overviewModel = new EnvironmentOverviewModel(model, 'env-overview');
this._overviewModel.bubbleTo(this);

this._detailsModel = new EnvironmentDetailsModel();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,24 +28,29 @@ export class EnvironmentOverviewModel extends OverviewPageModel {
/**
* Constructor
* @param {Model} model global model
* @param {string} pageIdentifier string that indicates what page this model represents
*/
constructor(model) {
constructor(model, pageIdentifier) {
super();

this._filteringModel = new FilteringModel({
created: new TimeRangeInputModel(),
runNumbers: new RawTextFilterModel(),
statusHistory: new RawTextFilterModel(),
currentStatus: new SelectionFilterModel({
availableOptions: Object.keys(StatusAcronym).map((status) => ({
value: status,
label: coloredEnvironmentStatusComponent(status),
rawLabel: status,
})),
}),
ids: new RawTextFilterModel(),
});
this._filteringModel = new FilteringModel(
model.router,
{
created: new TimeRangeInputModel(),
runNumbers: new RawTextFilterModel(),
statusHistory: new RawTextFilterModel(),
currentStatus: new SelectionFilterModel({
availableOptions: Object.keys(StatusAcronym).map((status) => ({
value: status,
label: coloredEnvironmentStatusComponent(status),
rawLabel: status,
})),
}),
ids: new RawTextFilterModel(),
},
);

this._filteringModel.pageIdentifier = pageIdentifier;
this._filteringModel.observe(() => this._applyFilters(true));
this._filteringModel.visualChange$?.bubbleTo(this);

Expand Down Expand Up @@ -87,10 +92,11 @@ export class EnvironmentOverviewModel extends OverviewPageModel {
/**
* 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) {
this._filteringModel.reset();
resetFiltering(fetch = true, clearUrl = false) {
this._filteringModel.reset(false, clearUrl);

if (fetch) {
this._applyFilters(true);
Expand Down
6 changes: 3 additions & 3 deletions lib/public/views/Home/Overview/HomePageModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@ export class HomePageModel extends Observable {
*/
constructor(model) {
super();
this._runsOverviewModel = new RunsOverviewModel(model);
this._runsOverviewModel = new RunsOverviewModel(model, 'home');
this._runsOverviewModel.bubbleTo(this);

this._logsOverviewModel = new LogsOverviewModel(model, true);
this._logsOverviewModel = new LogsOverviewModel(model, true, 'home');
this._logsOverviewModel.bubbleTo(this);

this._lhcFillsOverviewModel = new LhcFillsOverviewModel(true);
this._lhcFillsOverviewModel = new LhcFillsOverviewModel(model.router, true, 'home');
this._lhcFillsOverviewModel.bubbleTo(this);
}

Expand Down
2 changes: 1 addition & 1 deletion lib/public/views/LhcFills/LhcFills.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export default class LhcFills extends Observable {
this.model = model;

// Sub-models
this._overviewModel = new LhcFillsOverviewModel(true);
this._overviewModel = new LhcFillsOverviewModel(model.router, true, 'lhc-fill-overview');
this._overviewModel.bubbleTo(this);

this._detailsModel = new LhcFillDetailsModel();
Expand Down
33 changes: 20 additions & 13 deletions lib/public/views/LhcFills/Overview/LhcFillsOverviewModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,22 +30,28 @@ export class LhcFillsOverviewModel extends OverviewPageModel {
/**
* Constructor
*
* @param {QueryRouter} router router that controls the application's page navigation
* @param {boolean} [stableBeamsOnly=false] if true, overview will load stable beam only
* @param {string} pageIdentifier string that indicates what page this model represents
*/
constructor(stableBeamsOnly = false) {
constructor(router, stableBeamsOnly = false, pageIdentifier) {
super();

this._filteringModel = new FilteringModel({
fillNumbers: new RawTextFilterModel(),
beamDuration: new TextComparisonFilterModel(),
runDuration: new TextComparisonFilterModel(),
hasStableBeams: new ToggleFilterModel(stableBeamsOnly),
stableBeamsStart: new TimeRangeFilterModel(),
stableBeamsEnd: new TimeRangeFilterModel(),
beamTypes: new BeamTypeFilterModel(),
schemeName: new RawTextFilterModel(),
});
this._filteringModel = new FilteringModel(
router,
{
fillNumbers: new RawTextFilterModel(),
beamDuration: new TextComparisonFilterModel(),
runDuration: new TextComparisonFilterModel(),
hasStableBeams: new ToggleFilterModel(stableBeamsOnly),
stableBeamsStart: new TimeRangeFilterModel(),
stableBeamsEnd: new TimeRangeFilterModel(),
beamTypes: new BeamTypeFilterModel(),
schemeName: new RawTextFilterModel(),
},
);

this._filteringModel.pageIdentifier = pageIdentifier;
this._filteringModel.observe(() => this._applyFilters());
this._filteringModel.visualChange$.bubbleTo(this);

Expand Down Expand Up @@ -85,10 +91,11 @@ export class LhcFillsOverviewModel extends OverviewPageModel {
/**
* 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) {
this._filteringModel.reset();
resetFiltering(fetch = true, clearUrl = false) {
this._filteringModel.reset(false, clearUrl);

if (fetch) {
this._applyFilters();
Expand Down
Loading
Loading