From 072a847f06d08ee8093fce7fbed45996cd14a8d1 Mon Sep 17 00:00:00 2001 From: NarrowsProjects Date: Tue, 28 Apr 2026 12:10:15 +0200 Subject: [PATCH 1/6] chore: add warnings object to OverviewModel --- lib/public/models/OverviewModel.js | 12 +++++++++++- lib/public/views/Logs/Overview/LogsOverviewModel.js | 10 ++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/lib/public/models/OverviewModel.js b/lib/public/models/OverviewModel.js index 69ae0c3df3..3e6704fe31 100644 --- a/lib/public/models/OverviewModel.js +++ b/lib/public/models/OverviewModel.js @@ -38,7 +38,7 @@ export class OverviewPageModel extends Observable { */ constructor() { super(); - + this._warnings = new Map(); this._sortModel = new SortModel(); this._sortModel.observe(() => { this._pagination.silentlySetCurrentPage(1); @@ -97,6 +97,7 @@ export class OverviewPageModel extends Observable { reset() { this._item$.setCurrent(RemoteData.notAsked()); this._pagination.reset(); + this._warnings.clear(); } /** @@ -249,4 +250,13 @@ export class OverviewPageModel extends Observable { hasAnyData() { return this._item$.getCurrent().match({ Success: ({ length = 0 } = {}) => length > 0, Other: () => false }); } + + /** + * Returns the warnings object + * + * @return {object} the warning model + */ + get warnings() { + return this._warnings.entries().toArray(); + } } diff --git a/lib/public/views/Logs/Overview/LogsOverviewModel.js b/lib/public/views/Logs/Overview/LogsOverviewModel.js index b3591d4e0b..c67f8d6080 100644 --- a/lib/public/views/Logs/Overview/LogsOverviewModel.js +++ b/lib/public/views/Logs/Overview/LogsOverviewModel.js @@ -38,6 +38,7 @@ export class LogsOverviewModel extends Observable { */ constructor(model, excludeAnonymous = false, pageIdentifier) { super(); + this._warnings = new Map(); this._filteringModel = new FilteringModel( model.router, @@ -175,6 +176,15 @@ export class LogsOverviewModel extends Observable { return this._pagination; } + /** + * Returns the warnings object + * + * @return {object} the warning model + */ + get warnings() { + return Object.entries(this._warnings); + } + /** * Apply the current filtering and update the remote data list * From 6f35f9bc5e1aa0a6f06df7397aa98a642125ba63 Mon Sep 17 00:00:00 2001 From: NarrowsProjects Date: Tue, 28 Apr 2026 12:51:56 +0200 Subject: [PATCH 2/6] chore: update warning object when setting filters from url --- .../components/Filters/common/FilteringModel.js | 13 ++++++++++++- .../views/DataPasses/DataPassesOverviewModel.js | 1 + .../Overview/EnvironmentOverviewModel.js | 1 + .../LhcFills/Overview/LhcFillsOverviewModel.js | 1 + lib/public/views/Logs/Overview/LogsOverviewModel.js | 1 + .../Overview/QcFlagTypesOverviewModel.js | 1 + lib/public/views/Runs/Overview/RunsOverviewModel.js | 1 + .../AnchoredSimulationPassesOverviewModel.js | 2 +- .../SimulationPassesPerLhcPeriodOverviewModel.js | 2 +- .../lhcPeriods/Overview/LhcPeriodsOverviewModel.js | 1 + 10 files changed, 21 insertions(+), 3 deletions(-) diff --git a/lib/public/components/Filters/common/FilteringModel.js b/lib/public/components/Filters/common/FilteringModel.js index 19e59f7b65..707df6d23a 100644 --- a/lib/public/components/Filters/common/FilteringModel.js +++ b/lib/public/components/Filters/common/FilteringModel.js @@ -25,11 +25,13 @@ export class FilteringModel extends Observable { * * @param {QueryRouter} router router that controls the application's page navigation * @param {Object} filters the filters with their label and model + * @param {object} warnings object reference used to define warnings. */ - constructor(router, filters) { + constructor(router, filters, warnings) { super(); this._visualChange$ = new Observable(); this._pageIdentifier = null; + this._warnings = warnings; this._router = router; this._filters = {}; @@ -151,16 +153,25 @@ export class FilteringModel extends Observable { return; } + const unknownFilters = []; + for (const [key, value] of Object.entries(filter)) { const filterModel = this._filters[key]; if (!filterModel) { + unknownFilters.push(key); continue; } filterModel.normalized = value; } + if (unknownFilters.length) { + this._warnings['Unknown Filters'] = unknownFilters.join(', '); + } else { + delete this._warnings['Unknown Filters']; + } + this.notify(); } diff --git a/lib/public/views/DataPasses/DataPassesOverviewModel.js b/lib/public/views/DataPasses/DataPassesOverviewModel.js index 3be195e0b7..c6b4e625b2 100644 --- a/lib/public/views/DataPasses/DataPassesOverviewModel.js +++ b/lib/public/views/DataPasses/DataPassesOverviewModel.js @@ -35,6 +35,7 @@ export class DataPassesOverviewModel extends OverviewPageModel { availableOptions: NON_PHYSICS_PRODUCTIONS_NAMES_WORDS.map((word) => ({ label: word.toUpperCase(), value: word })), }), }, + this._warnings, ); this._filteringModel.pageIdentifier = pageIdentifier; diff --git a/lib/public/views/Environments/Overview/EnvironmentOverviewModel.js b/lib/public/views/Environments/Overview/EnvironmentOverviewModel.js index 5e220e758a..74c5496ceb 100644 --- a/lib/public/views/Environments/Overview/EnvironmentOverviewModel.js +++ b/lib/public/views/Environments/Overview/EnvironmentOverviewModel.js @@ -48,6 +48,7 @@ export class EnvironmentOverviewModel extends OverviewPageModel { }), ids: new RawTextFilterModel(), }, + this._warnings, ); this._filteringModel.pageIdentifier = pageIdentifier; diff --git a/lib/public/views/LhcFills/Overview/LhcFillsOverviewModel.js b/lib/public/views/LhcFills/Overview/LhcFillsOverviewModel.js index 04d746aea3..29984dd72b 100644 --- a/lib/public/views/LhcFills/Overview/LhcFillsOverviewModel.js +++ b/lib/public/views/LhcFills/Overview/LhcFillsOverviewModel.js @@ -49,6 +49,7 @@ export class LhcFillsOverviewModel extends OverviewPageModel { beamTypes: new BeamTypeFilterModel(), schemeName: new RawTextFilterModel(), }, + this._warnings, ); this._filteringModel.pageIdentifier = pageIdentifier; diff --git a/lib/public/views/Logs/Overview/LogsOverviewModel.js b/lib/public/views/Logs/Overview/LogsOverviewModel.js index c67f8d6080..24c91bdabe 100644 --- a/lib/public/views/Logs/Overview/LogsOverviewModel.js +++ b/lib/public/views/Logs/Overview/LogsOverviewModel.js @@ -52,6 +52,7 @@ export class LogsOverviewModel extends Observable { fillNumbers: new RawTextFilterModel(), created: new TimeRangeInputModel(), }, + this._warnings, ); this._overviewSortModel = new SortModel(); diff --git a/lib/public/views/QcFlagTypes/Overview/QcFlagTypesOverviewModel.js b/lib/public/views/QcFlagTypes/Overview/QcFlagTypesOverviewModel.js index 060ce94c9b..21c64830f2 100644 --- a/lib/public/views/QcFlagTypes/Overview/QcFlagTypesOverviewModel.js +++ b/lib/public/views/QcFlagTypes/Overview/QcFlagTypesOverviewModel.js @@ -36,6 +36,7 @@ export class QcFlagTypesOverviewModel extends OverviewPageModel { methods: new TextTokensFilterModel(), bad: new RadioButtonFilterModel([{ label: 'Any' }, { label: 'Bad', value: true }, { label: 'Not Bad', value: false }]), }, + this._warnings, ); this._filteringModel.pageIdentifier = pageIdentifier; diff --git a/lib/public/views/Runs/Overview/RunsOverviewModel.js b/lib/public/views/Runs/Overview/RunsOverviewModel.js index 1b276299f7..9ce38580e2 100644 --- a/lib/public/views/Runs/Overview/RunsOverviewModel.js +++ b/lib/public/views/Runs/Overview/RunsOverviewModel.js @@ -100,6 +100,7 @@ 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; diff --git a/lib/public/views/SimulationPasses/AnchoredOverview/AnchoredSimulationPassesOverviewModel.js b/lib/public/views/SimulationPasses/AnchoredOverview/AnchoredSimulationPassesOverviewModel.js index 42d14c2a3e..e4fb264116 100644 --- a/lib/public/views/SimulationPasses/AnchoredOverview/AnchoredSimulationPassesOverviewModel.js +++ b/lib/public/views/SimulationPasses/AnchoredOverview/AnchoredSimulationPassesOverviewModel.js @@ -29,7 +29,7 @@ export class AnchoredSimulationPassesOverviewModel extends OverviewPageModel { constructor(router, pageIdentifier) { super(); - this._filteringModel = new FilteringModel(router, { names: new TextTokensFilterModel() }); + this._filteringModel = new FilteringModel(router, { names: new TextTokensFilterModel() }, this._warnings); this._filteringModel.pageIdentifier = pageIdentifier; this._filteringModel.setFilterFromURL(); diff --git a/lib/public/views/SimulationPasses/PerLhcPeriodOverview/SimulationPassesPerLhcPeriodOverviewModel.js b/lib/public/views/SimulationPasses/PerLhcPeriodOverview/SimulationPassesPerLhcPeriodOverviewModel.js index 869bf418f9..1ca1c6dc94 100644 --- a/lib/public/views/SimulationPasses/PerLhcPeriodOverview/SimulationPassesPerLhcPeriodOverviewModel.js +++ b/lib/public/views/SimulationPasses/PerLhcPeriodOverview/SimulationPassesPerLhcPeriodOverviewModel.js @@ -29,7 +29,7 @@ export class SimulationPassesPerLhcPeriodOverviewModel extends OverviewPageModel constructor(router, pageIdentifier) { super(); - this._filteringModel = new FilteringModel(router, { names: new TextTokensFilterModel() }); + this._filteringModel = new FilteringModel(router, { names: new TextTokensFilterModel() }, this._warnings); this._filteringModel.pageIdentifier = pageIdentifier; this._filteringModel.setFilterFromURL(); diff --git a/lib/public/views/lhcPeriods/Overview/LhcPeriodsOverviewModel.js b/lib/public/views/lhcPeriods/Overview/LhcPeriodsOverviewModel.js index 2d886ac3e2..fdd6cadc59 100644 --- a/lib/public/views/lhcPeriods/Overview/LhcPeriodsOverviewModel.js +++ b/lib/public/views/lhcPeriods/Overview/LhcPeriodsOverviewModel.js @@ -37,6 +37,7 @@ export class LhcPeriodsOverviewModel extends OverviewPageModel { years: new TextTokensFilterModel(), pdpBeamTypes: new TextTokensFilterModel(), }, + this._warnings, ); this._filteringModel.pageIdentifier = pageIdentifier; From 25b14ba489ac4f007c08c5d821385d96ccde4275 Mon Sep 17 00:00:00 2001 From: NarrowsProjects Date: Tue, 28 Apr 2026 14:34:34 +0200 Subject: [PATCH 3/6] feat: creation of warningComponent warningcomponent fixes --- lib/public/app.css | 6 ++++++ .../common/messages/warningComponent.js | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 lib/public/components/common/messages/warningComponent.js diff --git a/lib/public/app.css b/lib/public/app.css index ec66c3717c..bb67bc66bd 100644 --- a/lib/public/app.css +++ b/lib/public/app.css @@ -266,6 +266,12 @@ th.text-center, td.text-center { border-color: #f5c6cb; } +.alert-warning { + color: var(--color-warning); + background-color: #ffe8c8; + border-color: #fdd69f; +} + .alert-danger hr { border-top-color: #f1b0b7; } diff --git a/lib/public/components/common/messages/warningComponent.js b/lib/public/components/common/messages/warningComponent.js new file mode 100644 index 0000000000..0585467e7f --- /dev/null +++ b/lib/public/components/common/messages/warningComponent.js @@ -0,0 +1,18 @@ +import { h } from '/js/src/index.js'; + +/** + * Component to display whenever a page has warnings. + * + * @param {Array<(string, string)>} warnings an array of warnings and messages + * @returns {Component} the warning componen + */ +export const warningComponent = (warnings) => { + if (!warnings.length) { + return null; + } + + return h('details.alert alert-warning', [ + h('summary', 'Warnings'), + h('ul', warnings.map(([key, message]) => h('li', `${key}: ${message}`))) + ]); +}; From 7a6b76658a256e1b79505a0bfa272a5c79353fe5 Mon Sep 17 00:00:00 2001 From: NarrowsProjects Date: Tue, 28 Apr 2026 15:23:19 +0200 Subject: [PATCH 4/6] chore: add warning component to the toolbar of every overview page page fixes --- .../common/messages/warningComponent.js | 2 +- .../DataPassesPerLhcPeriodOverviewPage.js | 21 +++++++--------- ...DataPassesPerSimulationPassOverviewPage.js | 19 +++++---------- .../Overview/environmentOverviewComponent.js | 9 ++++--- lib/public/views/LhcFills/Overview/index.js | 15 ++++++------ lib/public/views/Logs/Overview/index.js | 15 ++++++------ .../Overview/QcFlagTypesOverviewPage.js | 19 +++++---------- .../views/Runs/Overview/RunsOverviewPage.js | 16 ++++++------- .../RunsPerDataPassOverviewPage.js | 3 +++ .../RunsPerLhcPeriodOverviewPage.js | 13 +++++----- .../RunsPerSimulationPassOverviewPage.js | 13 +++++----- .../AnchoredSimulationPassesOverviewPage.js | 10 ++++---- ...imulationPassesPerLhcPeriodOverviewPage.js | 19 +++++---------- .../Overview/LhcPeriodsOverviewPage.js | 24 +++++++++---------- 14 files changed, 86 insertions(+), 112 deletions(-) diff --git a/lib/public/components/common/messages/warningComponent.js b/lib/public/components/common/messages/warningComponent.js index 0585467e7f..eef7385fa2 100644 --- a/lib/public/components/common/messages/warningComponent.js +++ b/lib/public/components/common/messages/warningComponent.js @@ -13,6 +13,6 @@ export const warningComponent = (warnings) => { return h('details.alert alert-warning', [ h('summary', 'Warnings'), - h('ul', warnings.map(([key, message]) => h('li', `${key}: ${message}`))) + h('ul', warnings.map(([key, message]) => h('li', `${key}: ${message}`))), ]); }; diff --git a/lib/public/views/DataPasses/PerLhcPeriodOverview/DataPassesPerLhcPeriodOverviewPage.js b/lib/public/views/DataPasses/PerLhcPeriodOverview/DataPassesPerLhcPeriodOverviewPage.js index e97dca2170..19593cae8e 100644 --- a/lib/public/views/DataPasses/PerLhcPeriodOverview/DataPassesPerLhcPeriodOverviewPage.js +++ b/lib/public/views/DataPasses/PerLhcPeriodOverview/DataPassesPerLhcPeriodOverviewPage.js @@ -19,6 +19,7 @@ import { filtersPanelPopover } from '../../../components/Filters/common/filtersP import { estimateDisplayableRowsCount } from '../../../utilities/estimateDisplayableRowsCount.js'; import { dataPassesActiveColumns } from '../ActiveColumns/dataPassesActiveColumns.js'; import { DataPassVersionStatus } from '../../../domain/enums/DataPassVersionStatus.js'; +import { warningComponent } from '../../../components/common/messages/warningComponent.js'; const TABLEROW_HEIGHT = 42; // Estimate of the navbar and pagination elements height total; Needs to be updated in case of changes; @@ -42,24 +43,18 @@ const getRowClasses = ({ versions }) => { * @returns {Component} The overview screen */ export const DataPassesPerLhcPeriodOverviewPage = ({ dataPasses: { perLhcPeriodOverviewModel: dataPassesPerLhcPeriodOverviewModel } }) => { - dataPassesPerLhcPeriodOverviewModel.pagination.provideDefaultItemsPerPage(estimateDisplayableRowsCount( - TABLEROW_HEIGHT, - PAGE_USED_HEIGHT, - )); + const { filteringModel, warnings, sortModel, pagination, items } = dataPassesPerLhcPeriodOverviewModel; + + pagination.provideDefaultItemsPerPage(estimateDisplayableRowsCount(TABLEROW_HEIGHT, PAGE_USED_HEIGHT)); return h('', { onremove: () => dataPassesPerLhcPeriodOverviewModel.reset(), }, [ - h('.flex-row.header-container.pv2', filtersPanelPopover(dataPassesPerLhcPeriodOverviewModel.filteringModel, dataPassesActiveColumns)), + h('.flex-row.header-container.pv2', filtersPanelPopover(filteringModel, dataPassesActiveColumns)), + warningComponent(warnings), h('.w-100.flex-column', [ - table( - dataPassesPerLhcPeriodOverviewModel.items, - dataPassesActiveColumns, - { classes: getRowClasses }, - null, - { sort: dataPassesPerLhcPeriodOverviewModel.sortModel }, - ), - paginationComponent(dataPassesPerLhcPeriodOverviewModel.pagination), + table(items, dataPassesActiveColumns, { classes: getRowClasses }, null, { sort: sortModel }), + paginationComponent(pagination), ]), ]); }; diff --git a/lib/public/views/DataPasses/PerSimulationPassOverview/DataPassesPerSimulationPassOverviewPage.js b/lib/public/views/DataPasses/PerSimulationPassOverview/DataPassesPerSimulationPassOverviewPage.js index 2473f3383d..ae6e54f0dc 100644 --- a/lib/public/views/DataPasses/PerSimulationPassOverview/DataPassesPerSimulationPassOverviewPage.js +++ b/lib/public/views/DataPasses/PerSimulationPassOverview/DataPassesPerSimulationPassOverviewPage.js @@ -22,6 +22,7 @@ import { breadcrumbs } from '../../../components/common/navigation/breadcrumbs.j import spinner from '../../../components/common/spinner.js'; import { tooltip } from '../../../components/common/popover/tooltip.js'; import { DataPassVersionStatus } from '../../../domain/enums/DataPassVersionStatus.js'; +import { warningComponent } from '../../../components/common/messages/warningComponent.js'; const TABLEROW_HEIGHT = 42; // Estimate of the navbar and pagination elements height total; Needs to be updated in case of changes; @@ -46,12 +47,9 @@ const getRowClasses = ({ versions }) => { */ export const DataPassesPerSimulationPassOverviewPage = ({ dataPasses: { perSimulationPassOverviewModel: dataPassesPerSimulationPassOverviewModel } }) => { - dataPassesPerSimulationPassOverviewModel.pagination.provideDefaultItemsPerPage(estimateDisplayableRowsCount( - TABLEROW_HEIGHT, - PAGE_USED_HEIGHT, - )); + const { items, simulationPass, pagination, warnings, filteringModel, sortModel } = dataPassesPerSimulationPassOverviewModel; - const { items, simulationPass, pagination } = dataPassesPerSimulationPassOverviewModel; + pagination.provideDefaultItemsPerPage(estimateDisplayableRowsCount(TABLEROW_HEIGHT, PAGE_USED_HEIGHT)); const commonTitle = h('h2#breadcrumb-header', 'Data Passes per MC'); @@ -59,7 +57,7 @@ export const DataPassesPerSimulationPassOverviewPage = ({ dataPasses: { onremove: () => dataPassesPerSimulationPassOverviewModel.reset(), }, [ h('.flex-row.items-center.g2', [ - filtersPanelPopover(dataPassesPerSimulationPassOverviewModel.filteringModel, dataPassesActiveColumns), + filtersPanelPopover(filteringModel, dataPassesActiveColumns), h( '.flex-row.g1.items-center', simulationPass.match({ @@ -70,14 +68,9 @@ export const DataPassesPerSimulationPassOverviewPage = ({ dataPasses: { }), ), ]), + warningComponent(warnings), h('.w-100.flex-column', [ - table( - items, - dataPassesActiveColumns, - { classes: getRowClasses }, - null, - { sort: dataPassesPerSimulationPassOverviewModel.sortModel }, - ), + table(items, dataPassesActiveColumns, { classes: getRowClasses }, null, { sort: sortModel }), paginationComponent(pagination), ]), ]); diff --git a/lib/public/views/Environments/Overview/environmentOverviewComponent.js b/lib/public/views/Environments/Overview/environmentOverviewComponent.js index 7cc60ecd22..0252e02cce 100644 --- a/lib/public/views/Environments/Overview/environmentOverviewComponent.js +++ b/lib/public/views/Environments/Overview/environmentOverviewComponent.js @@ -17,6 +17,7 @@ import { environmentsActiveColumns } from '../ActiveColumns/environmentsActiveCo import { estimateDisplayableRowsCount } from '../../../utilities/estimateDisplayableRowsCount.js'; import { paginationComponent } from '../../../components/Pagination/paginationComponent.js'; import { filtersPanelPopover } from '../../../components/Filters/common/filtersPanelPopover.js'; +import { warningComponent } from '../../../components/common/messages/warningComponent.js'; const TABLEROW_HEIGHT = 58; // Estimate of the navbar and pagination elements height total; Needs to be updated in case of changes; @@ -28,18 +29,16 @@ const PAGE_USED_HEIGHT = 181; * @returns {Object} Html page */ export const environmentOverviewComponent = (envsOverviewModel) => { - const { pagination, environments } = envsOverviewModel; + const { pagination, environments, warnings } = envsOverviewModel; - pagination.provideDefaultItemsPerPage(estimateDisplayableRowsCount( - TABLEROW_HEIGHT, - PAGE_USED_HEIGHT, - )); + pagination.provideDefaultItemsPerPage(estimateDisplayableRowsCount(TABLEROW_HEIGHT, PAGE_USED_HEIGHT)); return h('', [ h( '.flex-row.header-container.g2.pv2', filtersPanelPopover(envsOverviewModel, environmentsActiveColumns), ), + warningComponent(warnings), h('.w-100.flex-column', [ h('.header-container.pv2'), table(environments, environmentsActiveColumns, { classes: 'table-sm' }), diff --git a/lib/public/views/LhcFills/Overview/index.js b/lib/public/views/LhcFills/Overview/index.js index a29abf5145..95f0be1e70 100644 --- a/lib/public/views/LhcFills/Overview/index.js +++ b/lib/public/views/LhcFills/Overview/index.js @@ -19,6 +19,7 @@ import { estimateDisplayableRowsCount } from '../../../utilities/estimateDisplay import { paginationComponent } from '../../../components/Pagination/paginationComponent.js'; import { filtersPanelPopover } from '../../../components/Filters/common/filtersPanelPopover.js'; import { toggleFilter } from '../../../components/Filters/common/filters/toggleFilter.js'; +import { warningComponent } from '../../../components/common/messages/warningComponent.js'; const TABLEROW_HEIGHT = 53.3; // Estimate of the navbar and pagination elements height total; Needs to be updated in case of changes; @@ -41,20 +42,18 @@ export const Index = (model) => h('', { * @returns {Object} Html page */ const showLhcFillsTable = (lhcFillsOverviewModel) => { - lhcFillsOverviewModel.pagination.provideDefaultItemsPerPage(estimateDisplayableRowsCount( - TABLEROW_HEIGHT, - PAGE_USED_HEIGHT, - 1, - )); + const { items, pagination, filteringModel, warnings } = lhcFillsOverviewModel; + pagination.provideDefaultItemsPerPage(estimateDisplayableRowsCount(TABLEROW_HEIGHT, PAGE_USED_HEIGHT, 1)); return [ h('.flex-row.header-container.g2.pv2', [ filtersPanelPopover(lhcFillsOverviewModel, lhcFillsActiveColumns), - toggleFilter(lhcFillsOverviewModel.filteringModel.get('hasStableBeams'), 'STABLE BEAM ONLY'), + toggleFilter(filteringModel.get('hasStableBeams'), 'STABLE BEAM ONLY'), ]), + warningComponent(warnings), h('.w-100.flex-column', [ - table(lhcFillsOverviewModel.items, lhcFillsActiveColumns, null, { tableClasses: '.table-sm' }), - paginationComponent(lhcFillsOverviewModel.pagination), + table(items, lhcFillsActiveColumns, null, { tableClasses: '.table-sm' }), + paginationComponent(pagination), ]), ]; }; diff --git a/lib/public/views/Logs/Overview/index.js b/lib/public/views/Logs/Overview/index.js index 93f58c8c40..41e89b5542 100644 --- a/lib/public/views/Logs/Overview/index.js +++ b/lib/public/views/Logs/Overview/index.js @@ -19,6 +19,7 @@ import { paginationComponent } from '../../../components/Pagination/paginationCo import { frontLink } from '../../../components/common/navigation/frontLink.js'; import { filtersPanelPopover } from '../../../components/Filters/common/filtersPanelPopover.js'; import { excludeAnonymousLogAuthorToggle } from '../../../components/Filters/LogsFilter/author/authorFilter.js'; +import { warningComponent } from '../../../components/common/messages/warningComponent.js'; const TABLEROW_HEIGHT = 69; // Estimate of the navbar and pagination elements height total; Needs to be updated in case of changes; @@ -30,22 +31,22 @@ const PAGE_USED_HEIGHT = 215; * @return {Component} Returns a vnode with the table containing the logs */ const logOverviewScreen = ({ logs: { overviewModel: logsOverviewModel } }) => { - logsOverviewModel.pagination.provideDefaultItemsPerPage(estimateDisplayableRowsCount( - TABLEROW_HEIGHT, - PAGE_USED_HEIGHT, - )); + const { pagination, filteringModel, logs, overviewSortModel, warnings } = logsOverviewModel; + + pagination.provideDefaultItemsPerPage(estimateDisplayableRowsCount(TABLEROW_HEIGHT, PAGE_USED_HEIGHT)); return h('', [ h('#main-action-bar.flex-row.justify-between.header-container.pv2', [ h('.flex-row.g3', [ filtersPanelPopover(logsOverviewModel, logsActiveColumns), - excludeAnonymousLogAuthorToggle(logsOverviewModel.filteringModel.get('author')), + excludeAnonymousLogAuthorToggle(filteringModel.get('author')), ]), actionButtons(), ]), + warningComponent(warnings), h('.w-100.flex-column', [ - table(logsOverviewModel.logs, logsActiveColumns, null, null, { sort: logsOverviewModel.overviewSortModel }), - paginationComponent(logsOverviewModel.pagination), + table(logs, logsActiveColumns, null, null, { sort: overviewSortModel }), + paginationComponent(pagination), ]), ]); }; diff --git a/lib/public/views/QcFlagTypes/Overview/QcFlagTypesOverviewPage.js b/lib/public/views/QcFlagTypes/Overview/QcFlagTypesOverviewPage.js index 6b2a818527..97d5586b53 100644 --- a/lib/public/views/QcFlagTypes/Overview/QcFlagTypesOverviewPage.js +++ b/lib/public/views/QcFlagTypes/Overview/QcFlagTypesOverviewPage.js @@ -19,6 +19,7 @@ import { qcFlagTypesActiveColumns } from '../ActiveColumns/qcFlagTypesActiveColu import { filtersPanelPopover } from '../../../components/Filters/common/filtersPanelPopover.js'; import { frontLink } from '../../../components/common/navigation/frontLink.js'; import { BkpRoles } from '../../../domain/enums/BkpRoles.js'; +import { warningComponent } from '../../../components/common/messages/warningComponent.js'; const TABLEROW_HEIGHT = 30; // Estimate of the navbar and pagination elements height total; Needs to be updated in case of changes; @@ -30,12 +31,9 @@ const PAGE_USED_HEIGHT = 215; * @return {Component} The overview page */ export const QcFlagTypesOverviewPage = ({ qcFlagTypes: { overviewModel } }) => { - overviewModel.pagination.provideDefaultItemsPerPage(estimateDisplayableRowsCount( - TABLEROW_HEIGHT, - PAGE_USED_HEIGHT, - )); + const { items: qcFlagTypes, pagination, warnings, sortModel } = overviewModel; - const { items: qcFlagTypes } = overviewModel; + pagination.provideDefaultItemsPerPage(estimateDisplayableRowsCount(TABLEROW_HEIGHT, PAGE_USED_HEIGHT)); return h('', [ h('.flex-row.justify-between.items-center.g2', [ @@ -50,15 +48,10 @@ export const QcFlagTypesOverviewPage = ({ qcFlagTypes: { overviewModel } }) => { }), ], ]), + warningComponent(warnings), h('.flex-column.w-100', [ - table( - qcFlagTypes, - qcFlagTypesActiveColumns, - { classes: '.table-sm' }, - null, - { sort: overviewModel.sortModel }, - ), - paginationComponent(overviewModel.pagination), + table(qcFlagTypes, qcFlagTypesActiveColumns, { classes: '.table-sm' }, null, { sort: sortModel }), + paginationComponent(pagination), ]), ]); }; diff --git a/lib/public/views/Runs/Overview/RunsOverviewPage.js b/lib/public/views/Runs/Overview/RunsOverviewPage.js index 6355872b9e..9550492cab 100644 --- a/lib/public/views/Runs/Overview/RunsOverviewPage.js +++ b/lib/public/views/Runs/Overview/RunsOverviewPage.js @@ -20,6 +20,7 @@ import { table } from '../../../components/common/table/table.js'; import { switchInput } from '../../../components/common/form/switchInput.js'; import { exportTriggerAndModal } from '../../../components/common/dataExport/exportTriggerAndModal.js'; import { textInputFilter } from '../../../components/Filters/common/filters/textInputFilter.js'; +import { warningComponent } from '../../../components/common/messages/warningComponent.js'; const TABLEROW_HEIGHT = 59; // Estimate of the navbar and pagination elements height total; Needs to be updated in case of changes; @@ -46,21 +47,20 @@ export const togglePhysicsOnlyFilter = (runDefinitionFilterModel) => { * @return {Component} Returns a vnode with the table containing the runs */ export const RunsOverviewPage = ({ runs: { overviewModel: runsOverviewModel }, modalModel }) => { - runsOverviewModel.pagination.provideDefaultItemsPerPage(estimateDisplayableRowsCount( - TABLEROW_HEIGHT, - PAGE_USED_HEIGHT, - )); + const { pagination, items, exportModel, filteringModel, warnings } = runsOverviewModel; + pagination.provideDefaultItemsPerPage(estimateDisplayableRowsCount(TABLEROW_HEIGHT, PAGE_USED_HEIGHT)); return h('', [ h('.flex-row.header-container.g2.pv2', [ filtersPanelPopover(runsOverviewModel, runsActiveColumns), h('.pl2#runOverviewFilter', textInputFilter(runsOverviewModel.filteringModel, 'runNumbers', 'e.g. 534454, 534455...')), - togglePhysicsOnlyFilter(runsOverviewModel.filteringModel.get('definitions')), - exportTriggerAndModal(runsOverviewModel.exportModel, modalModel), + togglePhysicsOnlyFilter(filteringModel.get('definitions')), + exportTriggerAndModal(exportModel, modalModel), ]), + warningComponent(warnings), h('.flex-column.w-100', [ - table(runsOverviewModel.items, runsActiveColumns), - paginationComponent(runsOverviewModel.pagination), + table(items, runsActiveColumns), + paginationComponent(pagination), ]), ]); }; diff --git a/lib/public/views/Runs/RunPerDataPass/RunsPerDataPassOverviewPage.js b/lib/public/views/Runs/RunPerDataPass/RunsPerDataPassOverviewPage.js index 59f396515c..5dd22969de 100644 --- a/lib/public/views/Runs/RunPerDataPass/RunsPerDataPassOverviewPage.js +++ b/lib/public/views/Runs/RunPerDataPass/RunsPerDataPassOverviewPage.js @@ -39,6 +39,7 @@ import { getInelasticInteractionRateColumns } from '../ActiveColumns/getInelasti import { exportTriggerAndModal } from '../../../components/common/dataExport/exportTriggerAndModal.js'; import { textInputFilter } from '../../../components/Filters/common/filters/textInputFilter.js'; import { toggleFilter } from '../../../components/Filters/common/filters/toggleFilter.js'; +import { warningComponent } from '../../../components/common/messages/warningComponent.js'; const TABLEROW_HEIGHT = 59; // Estimate of the navbar and pagination elements height total; Needs to be updated in case of changes; @@ -113,6 +114,7 @@ export const RunsPerDataPassOverviewPage = ({ skimmableRuns: remoteSkimmableRuns, freezeOrUnfreezeActionState, discardAllQcFlagsActionState, + warnings, } = perDataPassOverviewModel; const commonTitle = h('h2#breadcrumb-header', { style: 'white-space: nowrap;' }, 'Physics Runs'); @@ -297,6 +299,7 @@ export const RunsPerDataPassOverviewPage = ({ { alignment: 'right' }, )), ]), + warningComponent(warnings), h( '.intermediate-flex-column', { onremove: () => perDataPassOverviewModel._abortGaqFetches() }, diff --git a/lib/public/views/Runs/RunPerPeriod/RunsPerLhcPeriodOverviewPage.js b/lib/public/views/Runs/RunPerPeriod/RunsPerLhcPeriodOverviewPage.js index 1006c5f44e..7d228672af 100644 --- a/lib/public/views/Runs/RunPerPeriod/RunsPerLhcPeriodOverviewPage.js +++ b/lib/public/views/Runs/RunPerPeriod/RunsPerLhcPeriodOverviewPage.js @@ -29,6 +29,7 @@ import { filtersPanelPopover } from '../../../components/Filters/common/filtersP import { exportTriggerAndModal } from '../../../components/common/dataExport/exportTriggerAndModal.js'; import { textInputFilter } from '../../../components/Filters/common/filters/textInputFilter.js'; import { toggleFilter } from '../../../components/Filters/common/filters/toggleFilter.js'; +import { warningComponent } from '../../../components/common/messages/warningComponent.js'; const TABLEROW_HEIGHT = 62; // Estimate of the navbar and pagination elements height total; Needs to be updated in case of changes; @@ -50,11 +51,6 @@ const getRowClasses = (run) => isRunNotSubjectToQc(run) ? '.danger' : null; * @return {Component} The overview page */ export const RunsPerLhcPeriodOverviewPage = ({ runs: { perLhcPeriodOverviewModel }, modalModel }) => { - perLhcPeriodOverviewModel.pagination.provideDefaultItemsPerPage(estimateDisplayableRowsCount( - TABLEROW_HEIGHT, - PAGE_USED_HEIGHT, - )); - const { items: remoteRuns, lhcPeriodStatistics: remoteLhcPeriodStatistics, @@ -66,8 +62,12 @@ export const RunsPerLhcPeriodOverviewPage = ({ runs: { perLhcPeriodOverviewModel mcReproducibleAsNotBad, qcSummary: remoteQcSummary, pdpBeamTypes, + pagination, + warnings, } = perLhcPeriodOverviewModel; + pagination.provideDefaultItemsPerPage(estimateDisplayableRowsCount(TABLEROW_HEIGHT, PAGE_USED_HEIGHT)); + /** * Render runs table with given detectors' active columns configuration * @@ -110,6 +110,7 @@ export const RunsPerLhcPeriodOverviewPage = ({ runs: { perLhcPeriodOverviewModel filtersPanelPopover(perLhcPeriodOverviewModel, activeColumns, { profile: 'runsPerLhcPeriod' }), h('.pl2#runOverviewFilter', textInputFilter(perLhcPeriodOverviewModel.filteringModel, 'runNumbers', 'e.g. 534454, 534455...')), h('h2.flex-row', ['Good, physics runs of ', lhcPeriodName]), + warningComponent(warnings), toggleFilter(mcReproducibleAsNotBad, h('em', 'MC.R as not-bad'), 'mcReproducibleAsNotBadToggle'), exportTriggerAndModal(perLhcPeriodOverviewModel.exportModel, modalModel), ]), @@ -153,7 +154,7 @@ export const RunsPerLhcPeriodOverviewPage = ({ runs: { perLhcPeriodOverviewModel }, { panelClass: ['scroll-auto'] }, ), - paginationComponent(perLhcPeriodOverviewModel.pagination), + paginationComponent(pagination), ] }), ), ]; diff --git a/lib/public/views/Runs/RunsPerSimulationPass/RunsPerSimulationPassOverviewPage.js b/lib/public/views/Runs/RunsPerSimulationPass/RunsPerSimulationPassOverviewPage.js index 3b4ad6157f..5f664dcd42 100644 --- a/lib/public/views/Runs/RunsPerSimulationPass/RunsPerSimulationPassOverviewPage.js +++ b/lib/public/views/Runs/RunsPerSimulationPass/RunsPerSimulationPassOverviewPage.js @@ -29,6 +29,7 @@ import { exportTriggerAndModal } from '../../../components/common/dataExport/exp import { filtersPanelPopover } from '../../../components/Filters/common/filtersPanelPopover.js'; import { toggleFilter } from '../../../components/Filters/common/filters/toggleFilter.js'; import { textInputFilter } from '../../../components/Filters/common/filters/textInputFilter.js'; +import { warningComponent } from '../../../components/common/messages/warningComponent.js'; const TABLEROW_HEIGHT = 59; // Estimate of the navbar and pagination elements height total; Needs to be updated in case of changes; @@ -52,11 +53,6 @@ export const RunsPerSimulationPassOverviewPage = ({ dplDetectorsUserHasAccessTo: remoteDplDetectorsUserHasAccessTo, modalModel, }) => { - perSimulationPassOverviewModel.pagination.provideDefaultItemsPerPage(estimateDisplayableRowsCount( - TABLEROW_HEIGHT, - PAGE_USED_HEIGHT, - )); - const { items: remoteRuns, detectors: remoteDetectors, @@ -67,8 +63,12 @@ export const RunsPerSimulationPassOverviewPage = ({ sortModel, pdpBeamTypes, mcReproducibleAsNotBad, + pagination, + warnings, } = perSimulationPassOverviewModel; + pagination.provideDefaultItemsPerPage(estimateDisplayableRowsCount(TABLEROW_HEIGHT, PAGE_USED_HEIGHT)); + const commonTitle = h('h2', 'Runs per MC'); const fullPageData = mergeRemoteData([remoteRuns, remoteSimulationPass, remoteDetectors, remoteQcSummary]); @@ -120,6 +120,7 @@ export const RunsPerSimulationPassOverviewPage = ({ }, ), ]), + warningComponent(warnings), h( '.intermediate-flex-column', fullPageData.match({ @@ -136,7 +137,7 @@ export const RunsPerSimulationPassOverviewPage = ({ }, { sort: sortModel }, ), - paginationComponent(perSimulationPassOverviewModel.pagination), + paginationComponent(pagination), ], Loading: () => spinner(), }), diff --git a/lib/public/views/SimulationPasses/AnchoredOverview/AnchoredSimulationPassesOverviewPage.js b/lib/public/views/SimulationPasses/AnchoredOverview/AnchoredSimulationPassesOverviewPage.js index 5894ba1a05..8ae7b0e9b3 100644 --- a/lib/public/views/SimulationPasses/AnchoredOverview/AnchoredSimulationPassesOverviewPage.js +++ b/lib/public/views/SimulationPasses/AnchoredOverview/AnchoredSimulationPassesOverviewPage.js @@ -21,6 +21,7 @@ import { simulationPassesActiveColumns } from '../ActiveColumns/simulationPasses import { breadcrumbs } from '../../../components/common/navigation/breadcrumbs.js'; import spinner from '../../../components/common/spinner.js'; import { tooltip } from '../../../components/common/popover/tooltip.js'; +import { warningComponent } from '../../../components/common/messages/warningComponent.js'; const TABLEROW_HEIGHT = 42; // Estimate of the navbar and pagination elements height total; Needs to be updated in case of changes; @@ -34,13 +35,9 @@ const PAGE_USED_HEIGHT = 215; export const AnchoredSimulationPassesOverviewPage = ({ simulationPasses: { anchoredOverviewModel: anchoredSimulationPassesOverviewModel }, }) => { - anchoredSimulationPassesOverviewModel.pagination.provideDefaultItemsPerPage(estimateDisplayableRowsCount( - TABLEROW_HEIGHT, - PAGE_USED_HEIGHT, - )); - - const { items, dataPass, pagination } = anchoredSimulationPassesOverviewModel; + const { items, dataPass, pagination, warnings } = anchoredSimulationPassesOverviewModel; + pagination.provideDefaultItemsPerPage(estimateDisplayableRowsCount(TABLEROW_HEIGHT, PAGE_USED_HEIGHT)); const commonTitle = h('h2#breadcrumb-header', { style: 'white-space: nowrap;' }, 'Anchored MC'); return h( @@ -61,6 +58,7 @@ export const AnchoredSimulationPassesOverviewPage = ({ }), ), ]), + warningComponent(warnings), h('.w-100.flex-column', [ table( items, diff --git a/lib/public/views/SimulationPasses/PerLhcPeriodOverview/SimulationPassesPerLhcPeriodOverviewPage.js b/lib/public/views/SimulationPasses/PerLhcPeriodOverview/SimulationPassesPerLhcPeriodOverviewPage.js index 3cc12756d0..488157f241 100644 --- a/lib/public/views/SimulationPasses/PerLhcPeriodOverview/SimulationPassesPerLhcPeriodOverviewPage.js +++ b/lib/public/views/SimulationPasses/PerLhcPeriodOverview/SimulationPassesPerLhcPeriodOverviewPage.js @@ -21,6 +21,7 @@ import { simulationPassesActiveColumns } from '../ActiveColumns/simulationPasses import spinner from '../../../components/common/spinner.js'; import { tooltip } from '../../../components/common/popover/tooltip.js'; import { breadcrumbs } from '../../../components/common/navigation/breadcrumbs.js'; +import { warningComponent } from '../../../components/common/messages/warningComponent.js'; const TABLEROW_HEIGHT = 42; // Estimate of the navbar and pagination elements height total; Needs to be updated in case of changes; @@ -33,12 +34,9 @@ const PAGE_USED_HEIGHT = 215; */ export const SimulationPassesPerLhcPeriodOverviewPage = ({ simulationPasses: { perLhcPeriodOverviewModel: simulationPassesPerLhcPeriodOverviewModel } }) => { - simulationPassesPerLhcPeriodOverviewModel.pagination.provideDefaultItemsPerPage(estimateDisplayableRowsCount( - TABLEROW_HEIGHT, - PAGE_USED_HEIGHT, - )); + const { items: simulationPasses, lhcPeriod, pagination, sortModel, warnings } = simulationPassesPerLhcPeriodOverviewModel; - const { items: simulationPasses, lhcPeriod } = simulationPassesPerLhcPeriodOverviewModel; + pagination.provideDefaultItemsPerPage(estimateDisplayableRowsCount(TABLEROW_HEIGHT, PAGE_USED_HEIGHT)); const commonTitle = h('h2#breadcrumb-header', { style: 'white-space: nowrap;' }, 'Monte Carlo'); @@ -57,15 +55,10 @@ export const SimulationPassesPerLhcPeriodOverviewPage = ({ simulationPasses: { }), ), ]), + warningComponent(warnings), h('.w-100.flex-column', [ - table( - simulationPasses, - simulationPassesActiveColumns, - { classes: '.table-sm' }, - null, - { sort: simulationPassesPerLhcPeriodOverviewModel.sortModel }, - ), - paginationComponent(simulationPassesPerLhcPeriodOverviewModel.pagination), + table(simulationPasses, simulationPassesActiveColumns, { classes: '.table-sm' }, null, { sort: sortModel }), + paginationComponent(pagination), ]), ]); }; diff --git a/lib/public/views/lhcPeriods/Overview/LhcPeriodsOverviewPage.js b/lib/public/views/lhcPeriods/Overview/LhcPeriodsOverviewPage.js index b431c62d42..2b63ef96f7 100644 --- a/lib/public/views/lhcPeriods/Overview/LhcPeriodsOverviewPage.js +++ b/lib/public/views/lhcPeriods/Overview/LhcPeriodsOverviewPage.js @@ -18,6 +18,7 @@ import { lhcPeriodsActiveColumns } from '../ActiveColumns/lhcPeriodsActiveColumn import { paginationComponent } from '../../../components/Pagination/paginationComponent.js'; import { filtersPanelPopover } from '../../../components/Filters/common/filtersPanelPopover.js'; import { estimateDisplayableRowsCount } from '../../../utilities/estimateDisplayableRowsCount.js'; +import { warningComponent } from '../../../components/common/messages/warningComponent.js'; const TABLEROW_HEIGHT = 35; // Estimate of the navbar and pagination elements height total; Needs to be updated in case of changes; @@ -29,22 +30,19 @@ const PAGE_USED_HEIGHT = 215; * @returns {Component} The overview screen */ export const LhcPeriodsOverviewPage = ({ lhcPeriods: { overviewModel: lhcPeriodsOverviewModel } }) => { - lhcPeriodsOverviewModel.pagination.provideDefaultItemsPerPage(estimateDisplayableRowsCount( - TABLEROW_HEIGHT, - PAGE_USED_HEIGHT, - )); + const { warnings, sortModel, pagination, items } = lhcPeriodsOverviewModel; + + pagination.provideDefaultItemsPerPage(estimateDisplayableRowsCount(TABLEROW_HEIGHT, PAGE_USED_HEIGHT)); return h('', [ - h('.flex-row.header-container.pv2', filtersPanelPopover(lhcPeriodsOverviewModel, lhcPeriodsActiveColumns)), + h( + '.flex-row.header-container.pv2', + filtersPanelPopover(lhcPeriodsOverviewModel, lhcPeriodsActiveColumns), + ), + warningComponent(warnings), h('.w-100.flex-column', [ - table( - lhcPeriodsOverviewModel.items, - lhcPeriodsActiveColumns, - { classes: '.table-sm' }, - null, - { sort: lhcPeriodsOverviewModel.sortModel }, - ), - paginationComponent(lhcPeriodsOverviewModel.pagination), + table(items, lhcPeriodsActiveColumns, { classes: '.table-sm' }, null, { sort: sortModel }), + paginationComponent(pagination), ]), ]); }; From 2c79c9fa34e5852e3cff5a23fe779a284892ee18 Mon Sep 17 00:00:00 2001 From: NarrowsProjects Date: Wed, 29 Apr 2026 10:38:47 +0200 Subject: [PATCH 5/6] add warning tests --- test/public/components/index.js | 2 ++ test/public/components/warnings.test.js | 40 +++++++++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 test/public/components/warnings.test.js diff --git a/test/public/components/index.js b/test/public/components/index.js index 5e06743c62..700564755c 100644 --- a/test/public/components/index.js +++ b/test/public/components/index.js @@ -12,7 +12,9 @@ */ const NavBarSuite = require('./navBar.test') +const WarningSuite = require('./warnings.test') module.exports = () => { describe('Navbar component', NavBarSuite); + describe('Warning component', WarningSuite) }; diff --git a/test/public/components/warnings.test.js b/test/public/components/warnings.test.js new file mode 100644 index 0000000000..2117da4d65 --- /dev/null +++ b/test/public/components/warnings.test.js @@ -0,0 +1,40 @@ +/** + * @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. + */ + +const { expect } = require('chai'); +const { + defaultBefore, + defaultAfter, + getInnerText, +} = require('../defaults.js'); + +module.exports = () => { + let page; + let browser; + const navTabSelector = 'a.btn-tab[id]'; // ALI FLP doesn't have an id, nor a functional href, hence why it is excluded like this + + before(async () => { + [page, browser] = await defaultBefore(); + }); + + it('Should show warning when a filter in the url is not recognised', async () => { + await page.goto('http://localhost:4000/?page=log-overview&filter[fake]=fake', { waitUntil: 'load' }); + const warningText = await getInnerText('.alert-warning > ul'); + + expect(warningText).to.equal('Unknown Filters: fake'); + }); + + after(async () => { + await defaultAfter(page, browser); + }); +}; From 33291b69166b2d2bdeb177e36927ee6ed1edcdd0 Mon Sep 17 00:00:00 2001 From: NarrowsProjects Date: Wed, 29 Apr 2026 18:06:19 +0200 Subject: [PATCH 6/6] feat: make the warnings removable --- .../Filters/common/FilteringModel.js | 4 +-- .../common/messages/warningComponent.js | 27 +++++++++++++++---- lib/public/models/OverviewModel.js | 2 +- .../DataPassesPerLhcPeriodOverviewPage.js | 4 +-- ...DataPassesPerSimulationPassOverviewPage.js | 4 +-- .../Overview/environmentOverviewComponent.js | 4 +-- lib/public/views/LhcFills/Overview/index.js | 4 +-- .../views/Logs/Overview/LogsOverviewModel.js | 2 +- lib/public/views/Logs/Overview/index.js | 4 +-- .../Overview/QcFlagTypesOverviewPage.js | 4 +-- .../views/Runs/Overview/RunsOverviewPage.js | 4 +-- .../RunsPerDataPassOverviewPage.js | 3 +-- .../RunsPerLhcPeriodOverviewPage.js | 3 +-- .../RunsPerSimulationPassOverviewPage.js | 3 +-- .../AnchoredSimulationPassesOverviewPage.js | 6 ++--- ...imulationPassesPerLhcPeriodOverviewPage.js | 4 +-- .../Overview/LhcPeriodsOverviewPage.js | 4 +-- test/public/components/warnings.test.js | 8 ++++++ 18 files changed, 58 insertions(+), 36 deletions(-) diff --git a/lib/public/components/Filters/common/FilteringModel.js b/lib/public/components/Filters/common/FilteringModel.js index 707df6d23a..86479ed590 100644 --- a/lib/public/components/Filters/common/FilteringModel.js +++ b/lib/public/components/Filters/common/FilteringModel.js @@ -167,9 +167,9 @@ export class FilteringModel extends Observable { } if (unknownFilters.length) { - this._warnings['Unknown Filters'] = unknownFilters.join(', '); + this._warnings.set('Unknown Filters', unknownFilters.join(', ')); } else { - delete this._warnings['Unknown Filters']; + this._warnings.delete('Unknown Filters'); } this.notify(); diff --git a/lib/public/components/common/messages/warningComponent.js b/lib/public/components/common/messages/warningComponent.js index eef7385fa2..b9e3b933ad 100644 --- a/lib/public/components/common/messages/warningComponent.js +++ b/lib/public/components/common/messages/warningComponent.js @@ -1,18 +1,35 @@ import { h } from '/js/src/index.js'; +import { iconX } from '/js/src/icons.js'; /** * Component to display whenever a page has warnings. * - * @param {Array<(string, string)>} warnings an array of warnings and messages + * @param {OverviewPageModel} overviewModel model that controlls an overview page * @returns {Component} the warning componen */ -export const warningComponent = (warnings) => { - if (!warnings.length) { +export const warningComponent = (overviewModel) => { + const { warnings } = overviewModel; + + if (!warnings.size) { return null; } - return h('details.alert alert-warning', [ + return h('details.alert.alert-warning', [ h('summary', 'Warnings'), - h('ul', warnings.map(([key, message]) => h('li', `${key}: ${message}`))), + h('ul', warnings.entries().toArray().map(([key, message]) => + h('li.flex-row.items-center', [ + h( + '.btn.btn-pill.alert-warning.mh1', + { + onclick: () => { + warnings.delete(key); + overviewModel.notify(); + }, + }, + iconX(), + ), + h('strong.mh1', `${key}:`), + h('span', message), + ]))), ]); }; diff --git a/lib/public/models/OverviewModel.js b/lib/public/models/OverviewModel.js index 3e6704fe31..d278c4d0ed 100644 --- a/lib/public/models/OverviewModel.js +++ b/lib/public/models/OverviewModel.js @@ -257,6 +257,6 @@ export class OverviewPageModel extends Observable { * @return {object} the warning model */ get warnings() { - return this._warnings.entries().toArray(); + return this._warnings; } } diff --git a/lib/public/views/DataPasses/PerLhcPeriodOverview/DataPassesPerLhcPeriodOverviewPage.js b/lib/public/views/DataPasses/PerLhcPeriodOverview/DataPassesPerLhcPeriodOverviewPage.js index 19593cae8e..7cb3e5fb65 100644 --- a/lib/public/views/DataPasses/PerLhcPeriodOverview/DataPassesPerLhcPeriodOverviewPage.js +++ b/lib/public/views/DataPasses/PerLhcPeriodOverview/DataPassesPerLhcPeriodOverviewPage.js @@ -43,7 +43,7 @@ const getRowClasses = ({ versions }) => { * @returns {Component} The overview screen */ export const DataPassesPerLhcPeriodOverviewPage = ({ dataPasses: { perLhcPeriodOverviewModel: dataPassesPerLhcPeriodOverviewModel } }) => { - const { filteringModel, warnings, sortModel, pagination, items } = dataPassesPerLhcPeriodOverviewModel; + const { filteringModel, sortModel, pagination, items } = dataPassesPerLhcPeriodOverviewModel; pagination.provideDefaultItemsPerPage(estimateDisplayableRowsCount(TABLEROW_HEIGHT, PAGE_USED_HEIGHT)); @@ -51,7 +51,7 @@ export const DataPassesPerLhcPeriodOverviewPage = ({ dataPasses: { perLhcPeriodO onremove: () => dataPassesPerLhcPeriodOverviewModel.reset(), }, [ h('.flex-row.header-container.pv2', filtersPanelPopover(filteringModel, dataPassesActiveColumns)), - warningComponent(warnings), + warningComponent(dataPassesPerLhcPeriodOverviewModel), h('.w-100.flex-column', [ table(items, dataPassesActiveColumns, { classes: getRowClasses }, null, { sort: sortModel }), paginationComponent(pagination), diff --git a/lib/public/views/DataPasses/PerSimulationPassOverview/DataPassesPerSimulationPassOverviewPage.js b/lib/public/views/DataPasses/PerSimulationPassOverview/DataPassesPerSimulationPassOverviewPage.js index ae6e54f0dc..6e11d594a8 100644 --- a/lib/public/views/DataPasses/PerSimulationPassOverview/DataPassesPerSimulationPassOverviewPage.js +++ b/lib/public/views/DataPasses/PerSimulationPassOverview/DataPassesPerSimulationPassOverviewPage.js @@ -47,7 +47,7 @@ const getRowClasses = ({ versions }) => { */ export const DataPassesPerSimulationPassOverviewPage = ({ dataPasses: { perSimulationPassOverviewModel: dataPassesPerSimulationPassOverviewModel } }) => { - const { items, simulationPass, pagination, warnings, filteringModel, sortModel } = dataPassesPerSimulationPassOverviewModel; + const { items, simulationPass, pagination, filteringModel, sortModel } = dataPassesPerSimulationPassOverviewModel; pagination.provideDefaultItemsPerPage(estimateDisplayableRowsCount(TABLEROW_HEIGHT, PAGE_USED_HEIGHT)); @@ -68,7 +68,7 @@ export const DataPassesPerSimulationPassOverviewPage = ({ dataPasses: { }), ), ]), - warningComponent(warnings), + warningComponent(dataPassesPerSimulationPassOverviewModel), h('.w-100.flex-column', [ table(items, dataPassesActiveColumns, { classes: getRowClasses }, null, { sort: sortModel }), paginationComponent(pagination), diff --git a/lib/public/views/Environments/Overview/environmentOverviewComponent.js b/lib/public/views/Environments/Overview/environmentOverviewComponent.js index 0252e02cce..df8f5a332d 100644 --- a/lib/public/views/Environments/Overview/environmentOverviewComponent.js +++ b/lib/public/views/Environments/Overview/environmentOverviewComponent.js @@ -29,7 +29,7 @@ const PAGE_USED_HEIGHT = 181; * @returns {Object} Html page */ export const environmentOverviewComponent = (envsOverviewModel) => { - const { pagination, environments, warnings } = envsOverviewModel; + const { pagination, environments } = envsOverviewModel; pagination.provideDefaultItemsPerPage(estimateDisplayableRowsCount(TABLEROW_HEIGHT, PAGE_USED_HEIGHT)); @@ -38,7 +38,7 @@ export const environmentOverviewComponent = (envsOverviewModel) => { '.flex-row.header-container.g2.pv2', filtersPanelPopover(envsOverviewModel, environmentsActiveColumns), ), - warningComponent(warnings), + warningComponent(envsOverviewModel), h('.w-100.flex-column', [ h('.header-container.pv2'), table(environments, environmentsActiveColumns, { classes: 'table-sm' }), diff --git a/lib/public/views/LhcFills/Overview/index.js b/lib/public/views/LhcFills/Overview/index.js index 95f0be1e70..f790bb9957 100644 --- a/lib/public/views/LhcFills/Overview/index.js +++ b/lib/public/views/LhcFills/Overview/index.js @@ -42,7 +42,7 @@ export const Index = (model) => h('', { * @returns {Object} Html page */ const showLhcFillsTable = (lhcFillsOverviewModel) => { - const { items, pagination, filteringModel, warnings } = lhcFillsOverviewModel; + const { items, pagination, filteringModel } = lhcFillsOverviewModel; pagination.provideDefaultItemsPerPage(estimateDisplayableRowsCount(TABLEROW_HEIGHT, PAGE_USED_HEIGHT, 1)); return [ @@ -50,7 +50,7 @@ const showLhcFillsTable = (lhcFillsOverviewModel) => { filtersPanelPopover(lhcFillsOverviewModel, lhcFillsActiveColumns), toggleFilter(filteringModel.get('hasStableBeams'), 'STABLE BEAM ONLY'), ]), - warningComponent(warnings), + warningComponent(lhcFillsOverviewModel), h('.w-100.flex-column', [ table(items, lhcFillsActiveColumns, null, { tableClasses: '.table-sm' }), paginationComponent(pagination), diff --git a/lib/public/views/Logs/Overview/LogsOverviewModel.js b/lib/public/views/Logs/Overview/LogsOverviewModel.js index 24c91bdabe..b1f351b8a8 100644 --- a/lib/public/views/Logs/Overview/LogsOverviewModel.js +++ b/lib/public/views/Logs/Overview/LogsOverviewModel.js @@ -183,7 +183,7 @@ export class LogsOverviewModel extends Observable { * @return {object} the warning model */ get warnings() { - return Object.entries(this._warnings); + return this._warnings; } /** diff --git a/lib/public/views/Logs/Overview/index.js b/lib/public/views/Logs/Overview/index.js index 41e89b5542..babeb820e5 100644 --- a/lib/public/views/Logs/Overview/index.js +++ b/lib/public/views/Logs/Overview/index.js @@ -31,7 +31,7 @@ const PAGE_USED_HEIGHT = 215; * @return {Component} Returns a vnode with the table containing the logs */ const logOverviewScreen = ({ logs: { overviewModel: logsOverviewModel } }) => { - const { pagination, filteringModel, logs, overviewSortModel, warnings } = logsOverviewModel; + const { pagination, filteringModel, logs, overviewSortModel } = logsOverviewModel; pagination.provideDefaultItemsPerPage(estimateDisplayableRowsCount(TABLEROW_HEIGHT, PAGE_USED_HEIGHT)); @@ -43,7 +43,7 @@ const logOverviewScreen = ({ logs: { overviewModel: logsOverviewModel } }) => { ]), actionButtons(), ]), - warningComponent(warnings), + warningComponent(logsOverviewModel), h('.w-100.flex-column', [ table(logs, logsActiveColumns, null, null, { sort: overviewSortModel }), paginationComponent(pagination), diff --git a/lib/public/views/QcFlagTypes/Overview/QcFlagTypesOverviewPage.js b/lib/public/views/QcFlagTypes/Overview/QcFlagTypesOverviewPage.js index 97d5586b53..0c3fb2a71e 100644 --- a/lib/public/views/QcFlagTypes/Overview/QcFlagTypesOverviewPage.js +++ b/lib/public/views/QcFlagTypes/Overview/QcFlagTypesOverviewPage.js @@ -31,7 +31,7 @@ const PAGE_USED_HEIGHT = 215; * @return {Component} The overview page */ export const QcFlagTypesOverviewPage = ({ qcFlagTypes: { overviewModel } }) => { - const { items: qcFlagTypes, pagination, warnings, sortModel } = overviewModel; + const { items: qcFlagTypes, pagination, sortModel } = overviewModel; pagination.provideDefaultItemsPerPage(estimateDisplayableRowsCount(TABLEROW_HEIGHT, PAGE_USED_HEIGHT)); @@ -48,7 +48,7 @@ export const QcFlagTypesOverviewPage = ({ qcFlagTypes: { overviewModel } }) => { }), ], ]), - warningComponent(warnings), + warningComponent(overviewModel), h('.flex-column.w-100', [ table(qcFlagTypes, qcFlagTypesActiveColumns, { classes: '.table-sm' }, null, { sort: sortModel }), paginationComponent(pagination), diff --git a/lib/public/views/Runs/Overview/RunsOverviewPage.js b/lib/public/views/Runs/Overview/RunsOverviewPage.js index 9550492cab..4f76d417d9 100644 --- a/lib/public/views/Runs/Overview/RunsOverviewPage.js +++ b/lib/public/views/Runs/Overview/RunsOverviewPage.js @@ -47,7 +47,7 @@ export const togglePhysicsOnlyFilter = (runDefinitionFilterModel) => { * @return {Component} Returns a vnode with the table containing the runs */ export const RunsOverviewPage = ({ runs: { overviewModel: runsOverviewModel }, modalModel }) => { - const { pagination, items, exportModel, filteringModel, warnings } = runsOverviewModel; + const { pagination, items, exportModel, filteringModel } = runsOverviewModel; pagination.provideDefaultItemsPerPage(estimateDisplayableRowsCount(TABLEROW_HEIGHT, PAGE_USED_HEIGHT)); return h('', [ @@ -57,7 +57,7 @@ export const RunsOverviewPage = ({ runs: { overviewModel: runsOverviewModel }, m togglePhysicsOnlyFilter(filteringModel.get('definitions')), exportTriggerAndModal(exportModel, modalModel), ]), - warningComponent(warnings), + warningComponent(runsOverviewModel), h('.flex-column.w-100', [ table(items, runsActiveColumns), paginationComponent(pagination), diff --git a/lib/public/views/Runs/RunPerDataPass/RunsPerDataPassOverviewPage.js b/lib/public/views/Runs/RunPerDataPass/RunsPerDataPassOverviewPage.js index 5dd22969de..fd847389f5 100644 --- a/lib/public/views/Runs/RunPerDataPass/RunsPerDataPassOverviewPage.js +++ b/lib/public/views/Runs/RunPerDataPass/RunsPerDataPassOverviewPage.js @@ -114,7 +114,6 @@ export const RunsPerDataPassOverviewPage = ({ skimmableRuns: remoteSkimmableRuns, freezeOrUnfreezeActionState, discardAllQcFlagsActionState, - warnings, } = perDataPassOverviewModel; const commonTitle = h('h2#breadcrumb-header', { style: 'white-space: nowrap;' }, 'Physics Runs'); @@ -299,7 +298,7 @@ export const RunsPerDataPassOverviewPage = ({ { alignment: 'right' }, )), ]), - warningComponent(warnings), + warningComponent(perDataPassOverviewModel), h( '.intermediate-flex-column', { onremove: () => perDataPassOverviewModel._abortGaqFetches() }, diff --git a/lib/public/views/Runs/RunPerPeriod/RunsPerLhcPeriodOverviewPage.js b/lib/public/views/Runs/RunPerPeriod/RunsPerLhcPeriodOverviewPage.js index 7d228672af..cf26fe1018 100644 --- a/lib/public/views/Runs/RunPerPeriod/RunsPerLhcPeriodOverviewPage.js +++ b/lib/public/views/Runs/RunPerPeriod/RunsPerLhcPeriodOverviewPage.js @@ -63,7 +63,6 @@ export const RunsPerLhcPeriodOverviewPage = ({ runs: { perLhcPeriodOverviewModel qcSummary: remoteQcSummary, pdpBeamTypes, pagination, - warnings, } = perLhcPeriodOverviewModel; pagination.provideDefaultItemsPerPage(estimateDisplayableRowsCount(TABLEROW_HEIGHT, PAGE_USED_HEIGHT)); @@ -110,7 +109,7 @@ export const RunsPerLhcPeriodOverviewPage = ({ runs: { perLhcPeriodOverviewModel filtersPanelPopover(perLhcPeriodOverviewModel, activeColumns, { profile: 'runsPerLhcPeriod' }), h('.pl2#runOverviewFilter', textInputFilter(perLhcPeriodOverviewModel.filteringModel, 'runNumbers', 'e.g. 534454, 534455...')), h('h2.flex-row', ['Good, physics runs of ', lhcPeriodName]), - warningComponent(warnings), + warningComponent(perLhcPeriodOverviewModel), toggleFilter(mcReproducibleAsNotBad, h('em', 'MC.R as not-bad'), 'mcReproducibleAsNotBadToggle'), exportTriggerAndModal(perLhcPeriodOverviewModel.exportModel, modalModel), ]), diff --git a/lib/public/views/Runs/RunsPerSimulationPass/RunsPerSimulationPassOverviewPage.js b/lib/public/views/Runs/RunsPerSimulationPass/RunsPerSimulationPassOverviewPage.js index 5f664dcd42..c64fcbe6c8 100644 --- a/lib/public/views/Runs/RunsPerSimulationPass/RunsPerSimulationPassOverviewPage.js +++ b/lib/public/views/Runs/RunsPerSimulationPass/RunsPerSimulationPassOverviewPage.js @@ -64,7 +64,6 @@ export const RunsPerSimulationPassOverviewPage = ({ pdpBeamTypes, mcReproducibleAsNotBad, pagination, - warnings, } = perSimulationPassOverviewModel; pagination.provideDefaultItemsPerPage(estimateDisplayableRowsCount(TABLEROW_HEIGHT, PAGE_USED_HEIGHT)); @@ -120,7 +119,7 @@ export const RunsPerSimulationPassOverviewPage = ({ }, ), ]), - warningComponent(warnings), + warningComponent(perSimulationPassOverviewModel), h( '.intermediate-flex-column', fullPageData.match({ diff --git a/lib/public/views/SimulationPasses/AnchoredOverview/AnchoredSimulationPassesOverviewPage.js b/lib/public/views/SimulationPasses/AnchoredOverview/AnchoredSimulationPassesOverviewPage.js index 8ae7b0e9b3..f9f752836c 100644 --- a/lib/public/views/SimulationPasses/AnchoredOverview/AnchoredSimulationPassesOverviewPage.js +++ b/lib/public/views/SimulationPasses/AnchoredOverview/AnchoredSimulationPassesOverviewPage.js @@ -35,7 +35,7 @@ const PAGE_USED_HEIGHT = 215; export const AnchoredSimulationPassesOverviewPage = ({ simulationPasses: { anchoredOverviewModel: anchoredSimulationPassesOverviewModel }, }) => { - const { items, dataPass, pagination, warnings } = anchoredSimulationPassesOverviewModel; + const { items, dataPass, pagination, sortModel } = anchoredSimulationPassesOverviewModel; pagination.provideDefaultItemsPerPage(estimateDisplayableRowsCount(TABLEROW_HEIGHT, PAGE_USED_HEIGHT)); const commonTitle = h('h2#breadcrumb-header', { style: 'white-space: nowrap;' }, 'Anchored MC'); @@ -58,14 +58,14 @@ export const AnchoredSimulationPassesOverviewPage = ({ }), ), ]), - warningComponent(warnings), + warningComponent(anchoredSimulationPassesOverviewModel), h('.w-100.flex-column', [ table( items, simulationPassesActiveColumns, { classes: '.table-sm' }, null, - { sort: anchoredSimulationPassesOverviewModel.sortModel }, + { sort: sortModel }, ), paginationComponent(pagination), ]), diff --git a/lib/public/views/SimulationPasses/PerLhcPeriodOverview/SimulationPassesPerLhcPeriodOverviewPage.js b/lib/public/views/SimulationPasses/PerLhcPeriodOverview/SimulationPassesPerLhcPeriodOverviewPage.js index 488157f241..0d2961b5f3 100644 --- a/lib/public/views/SimulationPasses/PerLhcPeriodOverview/SimulationPassesPerLhcPeriodOverviewPage.js +++ b/lib/public/views/SimulationPasses/PerLhcPeriodOverview/SimulationPassesPerLhcPeriodOverviewPage.js @@ -34,7 +34,7 @@ const PAGE_USED_HEIGHT = 215; */ export const SimulationPassesPerLhcPeriodOverviewPage = ({ simulationPasses: { perLhcPeriodOverviewModel: simulationPassesPerLhcPeriodOverviewModel } }) => { - const { items: simulationPasses, lhcPeriod, pagination, sortModel, warnings } = simulationPassesPerLhcPeriodOverviewModel; + const { items: simulationPasses, lhcPeriod, pagination, sortModel } = simulationPassesPerLhcPeriodOverviewModel; pagination.provideDefaultItemsPerPage(estimateDisplayableRowsCount(TABLEROW_HEIGHT, PAGE_USED_HEIGHT)); @@ -55,7 +55,7 @@ export const SimulationPassesPerLhcPeriodOverviewPage = ({ simulationPasses: { }), ), ]), - warningComponent(warnings), + warningComponent(simulationPassesPerLhcPeriodOverviewModel), h('.w-100.flex-column', [ table(simulationPasses, simulationPassesActiveColumns, { classes: '.table-sm' }, null, { sort: sortModel }), paginationComponent(pagination), diff --git a/lib/public/views/lhcPeriods/Overview/LhcPeriodsOverviewPage.js b/lib/public/views/lhcPeriods/Overview/LhcPeriodsOverviewPage.js index 2b63ef96f7..89c0def48c 100644 --- a/lib/public/views/lhcPeriods/Overview/LhcPeriodsOverviewPage.js +++ b/lib/public/views/lhcPeriods/Overview/LhcPeriodsOverviewPage.js @@ -30,7 +30,7 @@ const PAGE_USED_HEIGHT = 215; * @returns {Component} The overview screen */ export const LhcPeriodsOverviewPage = ({ lhcPeriods: { overviewModel: lhcPeriodsOverviewModel } }) => { - const { warnings, sortModel, pagination, items } = lhcPeriodsOverviewModel; + const { sortModel, pagination, items } = lhcPeriodsOverviewModel; pagination.provideDefaultItemsPerPage(estimateDisplayableRowsCount(TABLEROW_HEIGHT, PAGE_USED_HEIGHT)); @@ -39,7 +39,7 @@ export const LhcPeriodsOverviewPage = ({ lhcPeriods: { overviewModel: lhcPeriods '.flex-row.header-container.pv2', filtersPanelPopover(lhcPeriodsOverviewModel, lhcPeriodsActiveColumns), ), - warningComponent(warnings), + warningComponent(lhcPeriodsOverviewModel), h('.w-100.flex-column', [ table(items, lhcPeriodsActiveColumns, { classes: '.table-sm' }, null, { sort: sortModel }), paginationComponent(pagination), diff --git a/test/public/components/warnings.test.js b/test/public/components/warnings.test.js index 2117da4d65..2b59055d32 100644 --- a/test/public/components/warnings.test.js +++ b/test/public/components/warnings.test.js @@ -16,6 +16,7 @@ const { defaultBefore, defaultAfter, getInnerText, + pressElement, } = require('../defaults.js'); module.exports = () => { @@ -34,6 +35,13 @@ module.exports = () => { expect(warningText).to.equal('Unknown Filters: fake'); }); + it('Should remove warnings entry after clicking the x icon', async () => { + await pressElement(page, '.alert-warning .btn', true); + const warning = await page.$('.alert-warning'); + + expect(warning).to.be.null; + }); + after(async () => { await defaultAfter(page, browser); });