From 03cb4dfcd0819a8ff3fd621c5a114ea917d821dd Mon Sep 17 00:00:00 2001 From: George Raduta Date: Tue, 20 May 2025 16:40:18 +0200 Subject: [PATCH 1/3] Add filtering on runs-overview for file counts --- lib/domain/dtos/filters/RunFilterDto.js | 3 +++ .../views/Runs/ActiveColumns/runsActiveColumns.js | 15 +++++++++++++++ .../views/Runs/Overview/RunsOverviewModel.js | 3 +++ lib/usecases/run/GetAllRunsUseCase.js | 15 +++++++++++++++ 4 files changed, 36 insertions(+) diff --git a/lib/domain/dtos/filters/RunFilterDto.js b/lib/domain/dtos/filters/RunFilterDto.js index e3a703cd51..0131b441cc 100644 --- a/lib/domain/dtos/filters/RunFilterDto.js +++ b/lib/domain/dtos/filters/RunFilterDto.js @@ -81,6 +81,9 @@ exports.RunFilterDto = Joi.object({ nDetectors: IntegerComparisonDto, nEpns: IntegerComparisonDto, nFlps: IntegerComparisonDto, + ctfFileCount: IntegerComparisonDto, + tfFileCount: IntegerComparisonDto, + otherFileCount: IntegerComparisonDto, ddflp: Joi.boolean(), dcs: Joi.boolean(), epn: Joi.boolean(), diff --git a/lib/public/views/Runs/ActiveColumns/runsActiveColumns.js b/lib/public/views/Runs/ActiveColumns/runsActiveColumns.js index 7ac455c148..017a9696da 100644 --- a/lib/public/views/Runs/ActiveColumns/runsActiveColumns.js +++ b/lib/public/views/Runs/ActiveColumns/runsActiveColumns.js @@ -604,6 +604,11 @@ export const runsActiveColumns = { ctfFileCount: { name: 'CTF File Count', visible: false, + classes: 'w-2 f6 w-wrapped', + filter: (runsOverviewModel) => numericalComparisonFilter( + runsOverviewModel.filteringModel.get('ctfFileCount'), + { selectorPrefix: 'ctfFileCount' }, + ), }, ctfFileSize: { name: 'CTF File Size', @@ -612,6 +617,11 @@ export const runsActiveColumns = { tfFileCount: { name: 'TF File Count', visible: false, + classes: 'w-2 f6 w-wrapped', + filter: (runsOverviewModel) => numericalComparisonFilter( + runsOverviewModel.filteringModel.get('tfFileCount'), + { selectorPrefix: 'tfFileCount' }, + ), }, tfFileSize: { name: 'TF File Size', @@ -620,6 +630,11 @@ export const runsActiveColumns = { otherFileCount: { name: 'Other File Count', visible: false, + classes: 'w-2 f6 w-wrapped', + filter: (runsOverviewModel) => numericalComparisonFilter( + runsOverviewModel.filteringModel.get('otherFileCount'), + { selectorPrefix: 'otherFileCount' }, + ), }, otherFileSize: { name: 'Other File Size', diff --git a/lib/public/views/Runs/Overview/RunsOverviewModel.js b/lib/public/views/Runs/Overview/RunsOverviewModel.js index 02beff7ae0..5dc0ca85c2 100644 --- a/lib/public/views/Runs/Overview/RunsOverviewModel.js +++ b/lib/public/views/Runs/Overview/RunsOverviewModel.js @@ -78,6 +78,9 @@ export class RunsOverviewModel extends OverviewPageModel { nDetectors: new NumericalComparisonFilterModel({ integer: true }), nEpns: new NumericalComparisonFilterModel({ integer: true }), nFlps: new NumericalComparisonFilterModel({ integer: true }), + ctfFileCount: new NumericalComparisonFilterModel({ integer: true }), + tfFileCount: new NumericalComparisonFilterModel({ integer: true }), + otherFileCount: new NumericalComparisonFilterModel({ integer: true }), odcTopologyFullName: new RawTextFilterModel(), eorReason: new EorReasonFilterModel(eorReasonTypeProvider.items$), magnets: new MagnetsFilteringModel(magnetsCurrentLevelsProvider.items$), diff --git a/lib/usecases/run/GetAllRunsUseCase.js b/lib/usecases/run/GetAllRunsUseCase.js index 4fbaf0151a..fa811397d5 100644 --- a/lib/usecases/run/GetAllRunsUseCase.js +++ b/lib/usecases/run/GetAllRunsUseCase.js @@ -56,6 +56,9 @@ class GetAllRunsUseCase { nDetectors, nEpns, nFlps, + ctfFileCount, + tfFileCount, + otherFileCount, o2end, o2start, odcTopologyFullName, @@ -271,6 +274,18 @@ class GetAllRunsUseCase { const { operator, limit: nFlpsLimit } = nFlps; filteringQueryBuilder.where('nFlps').applyOperator(operator, nFlpsLimit); } + if (ctfFileCount) { + const { operator, limit: ctfFileCountLimit } = ctfFileCount; + filteringQueryBuilder.where('ctfFileCount').applyOperator(operator, ctfFileCountLimit); + } + if (tfFileCount) { + const { operator, limit: tfFileCountLimit } = tfFileCount; + filteringQueryBuilder.where('tfFileCount').applyOperator(operator, tfFileCountLimit); + } + if (otherFileCount) { + const { operator, limit: otherFileCountLimit } = otherFileCount; + filteringQueryBuilder.where('otherFileCount').applyOperator(operator, otherFileCountLimit); + } if (nEpns) { const { operator, limit: nEpnsLimit } = nEpns; filteringQueryBuilder.where('nEpns').applyOperator(operator, nEpnsLimit); From 1ea6c915dab108b2a61956c555b57b1524e932f4 Mon Sep 17 00:00:00 2001 From: George Raduta Date: Tue, 20 May 2025 16:45:45 +0200 Subject: [PATCH 2/3] Add tests for new filter option --- .../usecases/run/GetAllRunsUseCase.test.js | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/test/lib/usecases/run/GetAllRunsUseCase.test.js b/test/lib/usecases/run/GetAllRunsUseCase.test.js index f87e6598b6..738ea6bac0 100644 --- a/test/lib/usecases/run/GetAllRunsUseCase.test.js +++ b/test/lib/usecases/run/GetAllRunsUseCase.test.js @@ -575,6 +575,80 @@ module.exports = () => { expect(runs).to.have.lengthOf(0); }); + it('should successfully filter on ctf file count number', async () => { + const ctfFileCount = { + operator: '<', + limit: 200, + }; + getAllRunsDto.query = { filter: { ctfFileCount } }; + + let { runs } = await new GetAllRunsUseCase().execute(getAllRunsDto); + expect(runs).to.be.an('array'); + expect(runs).to.have.lengthOf(1); + + ctfFileCount.operator = '<='; + ({ runs } = await new GetAllRunsUseCase().execute(getAllRunsDto)); + expect(runs).to.be.an('array'); + expect(runs).to.have.lengthOf(2); + expect(runs.every((run) => run.ctfFileCount <= 10)).to.be.true; + + ctfFileCount.operator = '='; + ({ runs } = await new GetAllRunsUseCase().execute(getAllRunsDto)); + expect(runs).to.be.an('array'); + expect(runs).to.have.lengthOf(1); + expect(runs.every((run) => run.ctfFileCount === 10)).to.be.true; + + ctfFileCount.limit = 12; + ctfFileCount.operator = '>='; + ({ runs } = await new GetAllRunsUseCase().execute(getAllRunsDto)); + expect(runs).to.be.an('array'); + // 100 is the limit per page, true result must be 101 + expect(runs).to.have.lengthOf(7); + expect(runs.every((run) => run.ctfFileCount >= 12)).to.be.true; + + ctfFileCount.operator = '>'; + ({ runs } = await new GetAllRunsUseCase().execute(getAllRunsDto)); + expect(runs).to.be.an('array'); + expect(runs).to.have.lengthOf(6); + }); + + it('should successfully filter on tf file count number', async () => { + const tfFileCount = { + operator: '<', + limit: 30, + }; + getAllRunsDto.query = { filter: { tfFileCount } }; + + let { runs } = await new GetAllRunsUseCase().execute(getAllRunsDto); + expect(runs).to.be.an('array'); + expect(runs).to.have.lengthOf(0); + + tfFileCount.operator = '<='; + ({ runs } = await new GetAllRunsUseCase().execute(getAllRunsDto)); + expect(runs).to.be.an('array'); + expect(runs).to.have.lengthOf(7); + expect(runs.every((run) => run.tfFileCount <= 10)).to.be.true; + + tfFileCount.operator = '='; + ({ runs } = await new GetAllRunsUseCase().execute(getAllRunsDto)); + expect(runs).to.be.an('array'); + expect(runs).to.have.lengthOf(7); + expect(runs.every((run) => run.tfFileCount === 10)).to.be.true; + + tfFileCount.limit = 12; + tfFileCount.operator = '>='; + ({ runs } = await new GetAllRunsUseCase().execute(getAllRunsDto)); + expect(runs).to.be.an('array'); + // 100 is the limit per page, true result must be 101 + expect(runs).to.have.lengthOf(8); + expect(runs.every((run) => run.tfFileCount >= 12)).to.be.true; + + tfFileCount.operator = '>'; + ({ runs } = await new GetAllRunsUseCase().execute(getAllRunsDto)); + expect(runs).to.be.an('array'); + expect(runs).to.have.lengthOf(1); + }); + it('should successfully return an array, only containing runs found from passed list', async () => { getAllRunsDto.query = { filter: { From 24e1178b6fa7e8df164515a8e49c5e10ae404dbb Mon Sep 17 00:00:00 2001 From: George Raduta Date: Tue, 20 May 2025 17:09:07 +0200 Subject: [PATCH 3/3] Fix tests and apply improvement --- lib/usecases/run/GetAllRunsUseCase.js | 39 +++++++------------ .../usecases/run/GetAllRunsUseCase.test.js | 18 ++++----- 2 files changed, 23 insertions(+), 34 deletions(-) diff --git a/lib/usecases/run/GetAllRunsUseCase.js b/lib/usecases/run/GetAllRunsUseCase.js index fa811397d5..e808d158ec 100644 --- a/lib/usecases/run/GetAllRunsUseCase.js +++ b/lib/usecases/run/GetAllRunsUseCase.js @@ -266,30 +266,21 @@ class GetAllRunsUseCase { if (runQualities) { filteringQueryBuilder.where('runQuality').oneOf(...runQualities); } - if (nDetectors) { - const { operator, limit: nDetectorLimit } = nDetectors; - filteringQueryBuilder.where('nDetectors').applyOperator(operator, nDetectorLimit); - } - if (nFlps) { - const { operator, limit: nFlpsLimit } = nFlps; - filteringQueryBuilder.where('nFlps').applyOperator(operator, nFlpsLimit); - } - if (ctfFileCount) { - const { operator, limit: ctfFileCountLimit } = ctfFileCount; - filteringQueryBuilder.where('ctfFileCount').applyOperator(operator, ctfFileCountLimit); - } - if (tfFileCount) { - const { operator, limit: tfFileCountLimit } = tfFileCount; - filteringQueryBuilder.where('tfFileCount').applyOperator(operator, tfFileCountLimit); - } - if (otherFileCount) { - const { operator, limit: otherFileCountLimit } = otherFileCount; - filteringQueryBuilder.where('otherFileCount').applyOperator(operator, otherFileCountLimit); - } - if (nEpns) { - const { operator, limit: nEpnsLimit } = nEpns; - filteringQueryBuilder.where('nEpns').applyOperator(operator, nEpnsLimit); - } + const fileCountFilters = [ + { field: 'nDetectors', value: nDetectors }, + { field: 'nFlps', value: nFlps }, + { field: 'nEpns', value: nEpns }, + { field: 'ctfFileCount', value: ctfFileCount }, + { field: 'tfFileCount', value: tfFileCount }, + { field: 'otherFileCount', value: otherFileCount }, + ]; + fileCountFilters.forEach(({ field, value }) => { + if (value) { + const { operator, limit } = value; + filteringQueryBuilder.where(field).applyOperator(operator, limit); + } + }); + if (ddflp === false) { filteringQueryBuilder.where('dd_flp').isOrNull(ddflp); } else if (ddflp === true) { diff --git a/test/lib/usecases/run/GetAllRunsUseCase.test.js b/test/lib/usecases/run/GetAllRunsUseCase.test.js index 738ea6bac0..bfd9985753 100644 --- a/test/lib/usecases/run/GetAllRunsUseCase.test.js +++ b/test/lib/usecases/run/GetAllRunsUseCase.test.js @@ -590,26 +590,25 @@ module.exports = () => { ({ runs } = await new GetAllRunsUseCase().execute(getAllRunsDto)); expect(runs).to.be.an('array'); expect(runs).to.have.lengthOf(2); - expect(runs.every((run) => run.ctfFileCount <= 10)).to.be.true; + expect(runs.every((run) => run.ctfFileCount <= 200)).to.be.true; ctfFileCount.operator = '='; ({ runs } = await new GetAllRunsUseCase().execute(getAllRunsDto)); expect(runs).to.be.an('array'); expect(runs).to.have.lengthOf(1); - expect(runs.every((run) => run.ctfFileCount === 10)).to.be.true; + expect(runs.every((run) => run.ctfFileCount === 200)).to.be.true; - ctfFileCount.limit = 12; ctfFileCount.operator = '>='; ({ runs } = await new GetAllRunsUseCase().execute(getAllRunsDto)); expect(runs).to.be.an('array'); - // 100 is the limit per page, true result must be 101 expect(runs).to.have.lengthOf(7); - expect(runs.every((run) => run.ctfFileCount >= 12)).to.be.true; + expect(runs.every((run) => run.ctfFileCount >= 200)).to.be.true; ctfFileCount.operator = '>'; ({ runs } = await new GetAllRunsUseCase().execute(getAllRunsDto)); expect(runs).to.be.an('array'); expect(runs).to.have.lengthOf(6); + expect(runs.every((run) => run.ctfFileCount >= 500)).to.be.true; }); it('should successfully filter on tf file count number', async () => { @@ -627,26 +626,25 @@ module.exports = () => { ({ runs } = await new GetAllRunsUseCase().execute(getAllRunsDto)); expect(runs).to.be.an('array'); expect(runs).to.have.lengthOf(7); - expect(runs.every((run) => run.tfFileCount <= 10)).to.be.true; + expect(runs.every((run) => run.tfFileCount <= 30)).to.be.true; tfFileCount.operator = '='; ({ runs } = await new GetAllRunsUseCase().execute(getAllRunsDto)); expect(runs).to.be.an('array'); expect(runs).to.have.lengthOf(7); - expect(runs.every((run) => run.tfFileCount === 10)).to.be.true; + expect(runs.every((run) => run.tfFileCount === 30)).to.be.true; - tfFileCount.limit = 12; tfFileCount.operator = '>='; ({ runs } = await new GetAllRunsUseCase().execute(getAllRunsDto)); expect(runs).to.be.an('array'); - // 100 is the limit per page, true result must be 101 expect(runs).to.have.lengthOf(8); - expect(runs.every((run) => run.tfFileCount >= 12)).to.be.true; + expect(runs.every((run) => run.tfFileCount >= 30)).to.be.true; tfFileCount.operator = '>'; ({ runs } = await new GetAllRunsUseCase().execute(getAllRunsDto)); expect(runs).to.be.an('array'); expect(runs).to.have.lengthOf(1); + expect(runs.every((run) => run.tfFileCount > 30)).to.be.true; }); it('should successfully return an array, only containing runs found from passed list', async () => {