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..e808d158ec 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, @@ -263,18 +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 (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 f87e6598b6..bfd9985753 100644 --- a/test/lib/usecases/run/GetAllRunsUseCase.test.js +++ b/test/lib/usecases/run/GetAllRunsUseCase.test.js @@ -575,6 +575,78 @@ 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 <= 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 === 200)).to.be.true; + + ctfFileCount.operator = '>='; + ({ runs } = await new GetAllRunsUseCase().execute(getAllRunsDto)); + expect(runs).to.be.an('array'); + expect(runs).to.have.lengthOf(7); + 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 () => { + 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 <= 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 === 30)).to.be.true; + + tfFileCount.operator = '>='; + ({ runs } = await new GetAllRunsUseCase().execute(getAllRunsDto)); + expect(runs).to.be.an('array'); + expect(runs).to.have.lengthOf(8); + 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 () => { getAllRunsDto.query = { filter: {