Skip to content

Commit 6a47048

Browse files
committed
[O2B-1505] Processed feedback
1 parent a533088 commit 6a47048

10 files changed

Lines changed: 135 additions & 75 deletions

File tree

lib/domain/dtos/filters/LhcFillsFilterDto.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@ exports.LhcFillsFilterDto = Joi.object({
1919
fillNumbers: Joi.string().trim().custom(validateRange).messages({
2020
'any.invalid': '{{#message}}',
2121
}),
22-
beamDuration: Joi.string().trim().min(8).max(8).custom(validateTime).messages({
23-
'any.invalid': '{{#message}}',
24-
}),
25-
beamDurationOperator: Joi.string().trim().min(1).max(2),
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+
},
2628
});

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

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,15 @@ import { rawTextFilter } from '../common/filters/rawTextFilter.js';
1717
/**
1818
* Component to filter LHC-fills by beam duration
1919
*
20-
* @param {rawTextFilter} beamDurationFilterModel beamDurationFilterModel
21-
* @param {string} beamDurationOperator beam duration operator value
22-
* @param {(string) => undefined} beamDurationOperatorUpdate beam duration operator setter function
20+
* @param {TextComparisonFilterModel} beamDurationFilterModel beamDurationFilterModel
2321
* @returns {Component} the text field
2422
*/
25-
export const beamDurationFilter = (beamDurationFilterModel, beamDurationOperator, beamDurationOperatorUpdate) => {
23+
export const beamDurationFilter = (beamDurationFilterModel) => {
2624
const amountFilter = rawTextFilter(
27-
beamDurationFilterModel,
25+
beamDurationFilterModel.operandInputModel,
2826
{ classes: ['w-100', 'beam-duration-filter'], placeholder: 'e.g 16:14:15 (HH:MM:SS)' },
2927
);
3028

31-
return comparisonOperatorFilter(amountFilter, beamDurationOperator, (value) => beamDurationOperatorUpdate(value));
29+
return comparisonOperatorFilter(amountFilter, beamDurationFilterModel.operatorSelectionModel.value, (value) =>
30+
beamDurationFilterModel.operatorSelectionModel.select(value));
3231
};
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/**
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.
8+
*
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.
12+
*/
13+
import { ComparisonSelectionModel } from './ComparisonSelectionModel.js';
14+
import { FilterModel } from '../FilterModel.js';
15+
import { RawTextFilterModel } from './RawTextFilterModel.js';
16+
17+
/**
18+
* TextComparisonFilterModel
19+
*/
20+
export class TextComparisonFilterModel extends FilterModel {
21+
/**
22+
* Constructor
23+
*/
24+
constructor() {
25+
super();
26+
27+
this._operatorSelectionModel = new ComparisonSelectionModel();
28+
this._operatorSelectionModel.visualChange$.bubbleTo(this._visualChange$);
29+
30+
this._operandInputModel = new RawTextFilterModel();
31+
this._operandInputModel.visualChange$.bubbleTo(this._visualChange$);
32+
this._operandInputModel.bubbleTo(this);
33+
34+
this._operatorSelectionModel.observe(() => this._operandInputModel.value ? this.notify() : this._visualChange$.notify());
35+
}
36+
37+
/**
38+
* Return raw text filter model
39+
*
40+
* @return {RawTextFilterModel} operand input model
41+
*/
42+
get operandInputModel() {
43+
return this._operandInputModel;
44+
}
45+
46+
/**
47+
* Get operator selection model
48+
*
49+
* @return {ComparisonSelectionModel} selection model
50+
*/
51+
get operatorSelectionModel() {
52+
return this._operatorSelectionModel;
53+
}
54+
55+
/**
56+
* @inheritDoc
57+
*/
58+
reset() {
59+
this._operandInputModel.reset();
60+
this._operatorSelectionModel.reset();
61+
}
62+
63+
/**
64+
* @inheritDoc
65+
*/
66+
get normalized() {
67+
return {
68+
operator: this._operatorSelectionModel.current,
69+
limit: this._operandInputModel.value,
70+
};
71+
}
72+
73+
/**
74+
* @inheritDoc
75+
*/
76+
get isEmpty() {
77+
return !this._operandInputModel.value;
78+
}
79+
}

lib/public/views/Home/Overview/HomePageModel.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export class HomePageModel extends Observable {
3232
this._logsOverviewModel = new LogsOverviewModel(model, true);
3333
this._logsOverviewModel.bubbleTo(this);
3434

35-
this._lhcFillsOverviewModel = new LhcFillsOverviewModel(true);
35+
this._lhcFillsOverviewModel = new LhcFillsOverviewModel(model, true);
3636
this._lhcFillsOverviewModel.bubbleTo(this);
3737
}
3838

lib/public/views/LhcFills/ActiveColumns/lhcFillsActiveColumns.js

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -109,11 +109,7 @@ export const lhcFillsActiveColumns = {
109109

110110
return '-';
111111
},
112-
filter: (lhcFillModel) => beamDurationFilter(
113-
lhcFillModel.filteringModel.get('beamDuration'),
114-
lhcFillModel.getBeamDurationOperator(),
115-
(value) => lhcFillModel.setBeamDurationOperator(value),
116-
),
112+
filter: (lhcFillModel) => beamDurationFilter(lhcFillModel.filteringModel.get('beamDuration')),
117113
profiles: {
118114
lhcFill: true,
119115
environment: true,

lib/public/views/LhcFills/LhcFills.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export default class LhcFills extends Observable {
2929
this.model = model;
3030

3131
// Sub-models
32-
this._overviewModel = new LhcFillsOverviewModel(true);
32+
this._overviewModel = new LhcFillsOverviewModel(model, true);
3333
this._overviewModel.bubbleTo(this);
3434

3535
this._detailsModel = new LhcFillDetailsModel();

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

Lines changed: 15 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ 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';
21+
import { TextComparisonFilterModel } from '../../../components/Filters/common/filters/TextComparisonFilterModel.js';
2022

2123
const defaultBeamDurationOperator = '=';
2224

@@ -29,14 +31,15 @@ export class LhcFillsOverviewModel extends OverviewPageModel {
2931
/**
3032
* Constructor
3133
*
34+
* @param {model} model global model
3235
* @param {boolean} [stableBeamsOnly=false] if true, overview will load stable beam only
3336
*/
34-
constructor(stableBeamsOnly = false) {
37+
constructor(model, stableBeamsOnly = false) {
3538
super();
3639

3740
this._filteringModel = new FilteringModel({
3841
fillNumbers: new RawTextFilterModel(),
39-
beamDuration: new RawTextFilterModel(),
42+
beamDuration: new TextComparisonFilterModel(),
4043
hasStableBeams: new StableBeamFilterModel(),
4144
});
4245

@@ -50,6 +53,12 @@ export class LhcFillsOverviewModel extends OverviewPageModel {
5053
if (stableBeamsOnly) {
5154
this._filteringModel.get('hasStableBeams').setStableBeamsOnly(true);
5255
}
56+
57+
const updateDebounceTime = () => {
58+
this._debouncedLoad = debounce(this.load.bind(this), model.inputDebounceTime);
59+
};
60+
model.appConfiguration$.observe(() => updateDebounceTime());
61+
updateDebounceTime();
5362
}
5463

5564
/**
@@ -68,29 +77,10 @@ export class LhcFillsOverviewModel extends OverviewPageModel {
6877
getRootEndpoint() {
6978
const params = {
7079
filter: this.filteringModel.normalized,
71-
...this._filteringModel.get('beamDuration').isEmpty === false && {
72-
'filter[beamDurationOperator]': this._beamDurationOperator,
73-
},
7480
};
7581
return buildUrl('/api/lhcFills', params);
7682
}
7783

78-
/**
79-
* Beam duration operator setter
80-
*/
81-
setBeamDurationOperator(beamDurationOperator) {
82-
this._beamDurationOperator = beamDurationOperator;
83-
this._applyFilters();
84-
this.notify();
85-
}
86-
87-
/**
88-
* Beam duration operator getter
89-
*/
90-
getBeamDurationOperator() {
91-
return this._beamDurationOperator;
92-
}
93-
9484
/**
9585
* Returns all filtering, sorting and pagination settings to their default values
9686
* @param {boolean} [fetch = true] whether to refetch all data after filters have been reset
@@ -120,8 +110,7 @@ export class LhcFillsOverviewModel extends OverviewPageModel {
120110
* @return {Boolean} If any filter is active
121111
*/
122112
isAnyFilterActive() {
123-
return this._filteringModel.isAnyFilterActive()
124-
|| this._beamDurationOperator !== defaultBeamDurationOperator;
113+
return this._filteringModel.isAnyFilterActive();
125114
}
126115

127116
/**
@@ -135,11 +124,12 @@ export class LhcFillsOverviewModel extends OverviewPageModel {
135124

136125
/**
137126
* Apply the current filtering and update the remote data list
127+
* @param {boolean} now if true, filtering will be applied now without debouncing
138128
*
139129
* @return {void}
140130
*/
141-
_applyFilters() {
131+
_applyFilters(now = false) {
142132
this._pagination.currentPage = 1;
143-
this.load();
133+
now ? this.load() : this._debouncedLoad(true);
144134
}
145135
}

lib/usecases/lhcFill/GetAllLhcFillsUseCase.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ class GetAllLhcFillsUseCase {
4545
const queryBuilder = new QueryBuilder();
4646

4747
if (filter) {
48-
const { hasStableBeams, fillNumbers, beamDurationOperator, beamDuration } = filter;
48+
const { hasStableBeams, fillNumbers, beamDuration } = filter;
4949
if (hasStableBeams) {
5050
// For now, if a stableBeamsStart is present, then a beam is stable
5151
queryBuilder.where('stableBeamsStart').not().is(null);
@@ -61,10 +61,10 @@ class GetAllLhcFillsUseCase {
6161
queryBuilder.where('fillNumber').oneOf(...finalFillnumberList);
6262
}
6363
}
64-
// Beam duration filter and corresponding operator.
65-
if (beamDuration !== null && beamDuration !== undefined && beamDurationOperator) {
66-
beamDuration === 0 ? queryBuilder.where('stableBeamsDuration').applyOperator(beamDurationOperator, null)
67-
: queryBuilder.where('stableBeamsDuration').applyOperator(beamDurationOperator, beamDuration);
64+
// Beam duration filter, limit and corresponding operator.
65+
if (beamDuration?.limit !== undefined && beamDuration?.operator) {
66+
const beamDurationLimit = Number(beamDuration.limit) === 0 ? null : beamDuration.limit;
67+
queryBuilder.where('stableBeamsDuration').applyOperator(beamDuration.operator, beamDurationLimit);
6868
}
6969
}
7070

lib/utilities/validateTime.js

Lines changed: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,26 @@
1+
import Joi from 'joi';
2+
13
/**
24
* Validates digital time in string format
35
*
4-
* @param {*} value The time to validate
6+
* @param {*} incomingValue The time to validate
57
* @param {*} helpers The helpers object
68
* @returns {number|import("joi").ValidationError} The value if validation passes, as seconds (Number)
79
*/
8-
export const validateTime = (value, helpers) => {
9-
const timeSectionsString = value.split(':');
10-
let timeSeconds = 0;
11-
let powerValue = 2;
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);
1213

13-
for (const timeSectionString of timeSectionsString) {
14-
if (!Number.isNaN(timeSectionString)) {
15-
const timeSection = Number(timeSectionString);
16-
if (timeSection <= 60 && timeSection >= 0) {
17-
if (powerValue !== 0) {
18-
timeSeconds += timeSection * 60 ** powerValue;
19-
} else {
20-
timeSeconds += timeSection;
21-
}
22-
} else {
23-
return helpers.error('any.invalid', { message: `Invalid time period: ${timeSection}` });
24-
}
25-
} else {
26-
return helpers.error('any.invalid', { message: `Invalid time: ${timeSectionString}` });
27-
}
28-
powerValue--;
14+
if (error !== undefined) {
15+
return helpers.error('any.invalid', { message: `Validation error: ${error?.message ?? 'failed to validate time'}` });
2916
}
3017

31-
return timeSeconds;
18+
// 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);
24+
25+
return hours * 3600 + minutes * 60 + seconds;
3226
};

test/lib/usecases/lhcFill/GetAllLhcFillsUseCase.test.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ module.exports = () => {
104104
// Beam duration filter tests
105105

106106
it('should only contain specified stable beam durations, < 12:00:00', async () => {
107-
getAllLhcFillsDto.query = { filter: { beamDuration: '43200', beamDurationOperator: '<' } };
107+
getAllLhcFillsDto.query = { filter: { beamDuration: {limit: '43200', operator: '<'} } };
108108
const { lhcFills } = await new GetAllLhcFillsUseCase().execute(getAllLhcFillsDto);
109109
expect(lhcFills).to.be.an('array').and.lengthOf(3)
110110
lhcFills.forEach((lhcFill) => {
@@ -113,7 +113,7 @@ module.exports = () => {
113113
});
114114

115115
it('should only contain specified stable beam durations, <= 12:00:00', async () => {
116-
getAllLhcFillsDto.query = { filter: { beamDuration: '43200', beamDurationOperator: '<=' } };
116+
getAllLhcFillsDto.query = { filter: { beamDuration: {limit: '43200', operator: '<='} } };
117117
const { lhcFills } = await new GetAllLhcFillsUseCase().execute(getAllLhcFillsDto)
118118
expect(lhcFills).to.be.an('array').and.lengthOf(4)
119119
lhcFills.forEach((lhcFill) => {
@@ -122,7 +122,7 @@ module.exports = () => {
122122
})
123123

124124
it('should only contain specified stable beam durations, = 00:01:40', async () => {
125-
getAllLhcFillsDto.query = { filter: { beamDuration: '100', beamDurationOperator: '=' } };
125+
getAllLhcFillsDto.query = { filter: { beamDuration: {limit: '100', operator: '='} } };
126126
const { lhcFills } = await new GetAllLhcFillsUseCase().execute(getAllLhcFillsDto)
127127
expect(lhcFills).to.be.an('array').and.lengthOf(3)
128128
lhcFills.forEach((lhcFill) => {
@@ -131,7 +131,7 @@ module.exports = () => {
131131
});
132132

133133
it('should only contain specified stable beam durations, >= 00:01:40', async () => {
134-
getAllLhcFillsDto.query = { filter: { beamDuration: '100', beamDurationOperator: '>=' } };
134+
getAllLhcFillsDto.query = { filter: { beamDuration: {limit: '100', operator: '>='} } };
135135
const { lhcFills } = await new GetAllLhcFillsUseCase().execute(getAllLhcFillsDto)
136136

137137
expect(lhcFills).to.be.an('array').and.lengthOf(4)
@@ -141,7 +141,7 @@ module.exports = () => {
141141
})
142142

143143
it('should only contain specified stable beam durations, > 00:01:40', async () => {
144-
getAllLhcFillsDto.query = { filter: { beamDuration: '100', beamDurationOperator: '>' } };
144+
getAllLhcFillsDto.query = { filter: { beamDuration: {limit: '100', operator: '>'} } };
145145
const { lhcFills } = await new GetAllLhcFillsUseCase().execute(getAllLhcFillsDto)
146146

147147
expect(lhcFills).to.be.an('array').and.lengthOf(1)
@@ -152,7 +152,7 @@ module.exports = () => {
152152

153153
it('should only contain specified stable beam durations, = 00:00:00', async () => {
154154
// Tests the usecase's ability to replace the request for 0 to a request for null.
155-
getAllLhcFillsDto.query = { filter: { hasStableBeams: true, beamDuration: 0, beamDurationOperator: '=' } };
155+
getAllLhcFillsDto.query = { filter: { hasStableBeams: true, beamDuration: {limit: '0', operator: '='} } };
156156
const { lhcFills } = await new GetAllLhcFillsUseCase().execute(getAllLhcFillsDto)
157157

158158
expect(lhcFills).to.be.an('array').and.lengthOf(1)

0 commit comments

Comments
 (0)