Skip to content

Commit bd1b836

Browse files
committed
[O2B-1505] Processed feedback, timeValidator JOI updated, debounce removed, SBDuration filter frontend fixed
1 parent f113473 commit bd1b836

7 files changed

Lines changed: 53 additions & 45 deletions

File tree

lib/domain/dtos/filters/LhcFillsFilterDto.js

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,12 @@
1212
*/
1313
const Joi = require('joi');
1414
const { validateRange } = require('../../../utilities/rangeUtils');
15-
const { validateTime } = require('../../../utilities/validateTime');
15+
const { validateTimeDuration } = require('../../../utilities/validateTime');
1616

1717
exports.LhcFillsFilterDto = Joi.object({
1818
hasStableBeams: Joi.boolean(),
1919
fillNumbers: Joi.string().trim().custom(validateRange).messages({
2020
'any.invalid': '{{#message}}',
2121
}),
22-
beamDuration: {
23-
limit: Joi.string().trim().min(8).max(8).custom(validateTime).messages({
24-
'any.invalid': '{{#message}}',
25-
}),
26-
operator: Joi.string().trim().min(1).max(2),
27-
},
22+
beamDuration: validateTimeDuration,
2823
});

lib/public/components/Filters/LhcFillsFilter/beamDurationFilter.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ import { rawTextFilter } from '../common/filters/rawTextFilter.js';
2323
export const beamDurationFilter = (beamDurationFilterModel) => {
2424
const amountFilter = rawTextFilter(
2525
beamDurationFilterModel.operandInputModel,
26-
{ classes: ['w-100', 'beam-duration-filter'], placeholder: 'e.g 16:14:15 (HH:MM:SS)' },
26+
{ id: 'beam-duration-filter-operand', classes: ['w-100', 'beam-duration-filter'], placeholder: 'e.g 16:14:15 (HH:MM:SS)' },
2727
);
2828

29-
return comparisonOperatorFilter(amountFilter, beamDurationFilterModel.operatorSelectionModel.value, (value) =>
30-
beamDurationFilterModel.operatorSelectionModel.select(value));
29+
return comparisonOperatorFilter(amountFilter, beamDurationFilterModel.operatorSelectionModel.current, (value) =>
30+
beamDurationFilterModel.operatorSelectionModel.select(value), { id: 'beam-duration-filter-operator' });
3131
};

lib/public/components/Filters/common/filters/TextComparisonFilterModel.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,12 @@ export class TextComparisonFilterModel extends FilterModel {
2626

2727
this._operatorSelectionModel = new ComparisonSelectionModel();
2828
this._operatorSelectionModel.visualChange$.bubbleTo(this._visualChange$);
29+
// Unless the filter contains a value don't apply the filters.
30+
this._operatorSelectionModel.observe(() => this._operandInputModel.value ? this.notify() : this._visualChange$.notify());
2931

3032
this._operandInputModel = new RawTextFilterModel();
3133
this._operandInputModel.visualChange$.bubbleTo(this._visualChange$);
3234
this._operandInputModel.bubbleTo(this);
33-
34-
this._operatorSelectionModel.observe(() => this._operandInputModel.value ? this.notify() : this._visualChange$.notify());
3535
}
3636

3737
/**

lib/public/components/Filters/common/filters/rawTextFilter.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,12 @@ import { h } from '/js/src/index.js';
2323
* @return {Component} the filter
2424
*/
2525
export const rawTextFilter = (filterModel, configuration) => {
26-
const { classes = [], placeholder = '' } = configuration || {};
26+
const { classes = [], placeholder = '', id = '' } = configuration || {};
2727
return h(
2828
'input',
2929
{
3030
type: 'text',
31+
id: id,
3132
class: classes.join(' '),
3233
value: filterModel.value,
3334
placeholder: placeholder,

lib/public/views/LhcFills/Overview/LhcFillsOverviewModel.js

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import { StableBeamFilterModel } from '../../../components/Filters/LhcFillsFilte
1717
import { RawTextFilterModel } from '../../../components/Filters/common/filters/RawTextFilterModel.js';
1818
import { OverviewPageModel } from '../../../models/OverviewModel.js';
1919
import { addStatisticsToLhcFill } from '../../../services/lhcFill/addStatisticsToLhcFill.js';
20-
import { debounce } from '../../../utilities/debounce.js';
2120
import { TextComparisonFilterModel } from '../../../components/Filters/common/filters/TextComparisonFilterModel.js';
2221

2322
/**
@@ -41,20 +40,14 @@ export class LhcFillsOverviewModel extends OverviewPageModel {
4140
hasStableBeams: new StableBeamFilterModel(),
4241
});
4342

44-
this._filteringModel.observe(() => this._applyFilters(true));
43+
this._filteringModel.observe(() => this._applyFilters());
4544
this._filteringModel.visualChange$.bubbleTo(this);
4645

4746
this.reset(false);
4847

4948
if (stableBeamsOnly) {
5049
this._filteringModel.get('hasStableBeams').setStableBeamsOnly(true);
5150
}
52-
53-
const updateDebounceTime = () => {
54-
this._debouncedLoad = debounce(this.load.bind(this), model.inputDebounceTime);
55-
};
56-
model.appConfiguration$.observe(() => updateDebounceTime());
57-
updateDebounceTime();
5851
}
5952

6053
/**
@@ -96,7 +89,7 @@ export class LhcFillsOverviewModel extends OverviewPageModel {
9689
this._filteringModel.reset();
9790

9891
if (fetch) {
99-
this._applyFilters(true);
92+
this._applyFilters();
10093
}
10194
}
10295

@@ -123,8 +116,8 @@ export class LhcFillsOverviewModel extends OverviewPageModel {
123116
*
124117
* @return {void}
125118
*/
126-
_applyFilters(now = false) {
119+
_applyFilters() {
127120
this._pagination.currentPage = 1;
128-
now ? this.load() : this._debouncedLoad(true);
121+
this.load();
129122
}
130123
}

lib/utilities/validateTime.js

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,42 @@
1-
import Joi from 'joi';
2-
31
/**
4-
* Validates digital time in string format
2+
* @license
3+
* Copyright CERN and copyright holders of ALICE O2. This software is
4+
* distributed under the terms of the GNU General Public License v3 (GPL
5+
* Version 3), copied verbatim in the file "COPYING".
6+
*
7+
* See http://alice-o2.web.cern.ch/license for full licensing information.
58
*
6-
* @param {*} incomingValue The time to validate
7-
* @param {*} helpers The helpers object
8-
* @returns {number|import("joi").ValidationError} The value if validation passes, as seconds (Number)
9+
* In applying this license CERN does not waive the privileges and immunities
10+
* granted to it by virtue of its status as an Intergovernmental Organization
11+
* or submit itself to any jurisdiction.
912
*/
10-
export const validateTime = (incomingValue, helpers) => {
11-
// Checks for valid time format.
12-
const { error, value } = Joi.string().pattern(/^\d{2}:[0-5]\d:[0-5]\d$/).validate(incomingValue);
13+
import Joi from 'joi';
1314

14-
if (error !== undefined) {
15-
return helpers.error('any.invalid', { message: `Validation error: ${error?.message ?? 'failed to validate time'}` });
16-
}
15+
const joiTimeDurationErrorText = 'Invalid duration value';
1716

17+
/**
18+
* Transform digital time in string format
19+
*
20+
* @param {*} incomingValue The time to transform
21+
* @returns {number} The value as seconds (Number)
22+
*/
23+
export const transformTime = (incomingValue) => {
1824
// Extract time to seconds...
19-
const [hoursStr, minutesStr, secondsStr] = value.split(':');
20-
21-
const hours = Number(hoursStr);
22-
const minutes = Number(minutesStr);
23-
const seconds = Number(secondsStr);
25+
const [hoursStr, minutesStr, secondsStr] = incomingValue.split(':');
2426

25-
return hours * 3600 + minutes * 60 + seconds;
27+
return Number(hoursStr) * 3600 + Number(minutesStr) * 60 + Number(secondsStr);
2628
};
29+
30+
/**
31+
* Joi object that validates time duration filters.
32+
* This is for duration, not a point in time. 10000:59:59 is valid.
33+
* The operator is also validated.
34+
*/
35+
export const validateTimeDuration = Joi.object({
36+
limit: Joi.string().trim().pattern(/^\d+:[0-5]?\d:[0-5]?\d$/).custom(transformTime).messages({
37+
'string.pattern.base': joiTimeDurationErrorText,
38+
'string.base': joiTimeDurationErrorText,
39+
'any.invalid': joiTimeDurationErrorText,
40+
}),
41+
operator: Joi.string().trim().min(1).max(2),
42+
});

test/public/lhcFills/overview.test.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -268,14 +268,17 @@ module.exports = () => {
268268

269269
it('should successfully display filter elements', async () => {
270270
const filterSBExpect = { selector: '.stableBeams-filter .w-30', value: 'Stable Beams Only' };
271-
const filterFillNRExpect = {selector: 'div.items-baseline:nth-child(1) > div:nth-child(1)', value: 'Fill #'}
272-
const filterSBDurationExpect = {selector: 'div.items-baseline:nth-child(3) > div:nth-child(1)', value: 'SB Duration'}
273-
const filterSBDurationPlaceholderExpect = {selector: 'input.w-100:nth-child(2)', value: 'e.g 16:14:15 (HH:MM:SS)'}
271+
const filterFillNRExpect = {selector: 'div.items-baseline:nth-child(1) > div:nth-child(1)', value: 'Fill #'};
272+
const filterSBDurationExpect = {selector: 'div.items-baseline:nth-child(3) > div:nth-child(1)', value: 'SB Duration'};
273+
const filterSBDurationPlaceholderExpect = {selector: 'input.w-100:nth-child(2)', value: 'e.g 16:14:15 (HH:MM:SS)'};
274+
const filterSBDurationOperatorExpect = { value: true };
274275

275276

276277
await goToPage(page, 'lhc-fill-overview');
277278
// Open the filtering panel
278279
await openFilteringPanel(page);
280+
// Note: expectAttributeValue does not work here.
281+
expect(await page.evaluate(() => document.querySelector('#beam-duration-filter-operator > option:nth-child(3)').selected)).to.equal(filterSBDurationOperatorExpect.value);
279282
await expectInnerText(page, filterSBExpect.selector, filterSBExpect.value);
280283
await expectInnerText(page, filterFillNRExpect.selector, filterFillNRExpect.value);
281284
await expectInnerText(page, filterSBDurationExpect.selector, filterSBDurationExpect.value);

0 commit comments

Comments
 (0)