Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions lib/database/adapters/RunTagsAdapter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/**
* @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.
*/

/**
* RunTagsAdapter
*/
class RunTagsAdapter {
/**
* Converts the given database object to an entity object.
*
* @param {Object} databaseObject Object to convert.
* @returns {Object} Converted entity object.
*/
static toEntity({ runId, tagId }) {
return { runId, tagId };
}

/**
* Converts the given entity object to a database object.
*
* @param {Object} entityObject Object to convert.
* @returns {Object} Converted database object.
*/
static toDatabase(entityObject) {
return entityObject;
}
}

module.exports = RunTagsAdapter;
25 changes: 25 additions & 0 deletions lib/database/repositories/RunTagsRepository.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ const {
tables: {
RunTags,
},

utilities: {
QueryBuilder,
},
} = require('..');
const Repository = require('./Repository');

Expand All @@ -29,6 +33,27 @@ class RunTagsRepository extends Repository {
super(RunTags);
}

/**
* Returns run tag rows by grouping them by run id
*
* @param {QueryBuilder} queryBuilder The QueryBuilder to use.
* @returns {Promise} Promise object representing the full data
*/
async findAllAndGroup(queryBuilder = new QueryBuilder()) {
const result = await this.findAll(queryBuilder);

const groupedResult = result.reduce((accumulator, currentValue) => {
if (accumulator[currentValue.runId]) {
accumulator[currentValue.runId].push(currentValue.tagId);
} else {
accumulator[currentValue.runId] = [currentValue.tagId];
}
return accumulator;
}, {});

return Object.entries(groupedResult).map(([key, value]) => ({ runId: key, tagIds: value }));
}

/**
* Remove all tags & runs relations by run id
* @param {number} runId - run ID to delete tags for
Expand Down
48 changes: 48 additions & 0 deletions lib/domain/dtos/GetAllRunsDto.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,64 @@
*/

const Joi = require('joi');
const EntityIdDto = require('./EntityIdDto');
const PaginationDto = require('./PaginationDto');

const customJoi = Joi.extend((joi) => ({
base: joi.array(),
type: 'stringArray',
coerce: (value) => ({ value: value.split ? value.split(',') : value }),
}));

const customDateFilterErrorMessages = {
'date.base': 'Creation date must be a real date and in format YYYY-MM-DD or YYYY/MM/DD',
'date.max': 'Creation date must be today ({#limit}) or earlier',
'date.min': 'Creation date "to" cannot be before the "from" date',
};
const DateFilterDto = Joi.object({
from: Joi.date()
.max(new Date().setHours(0, 0, 0, 0))
.messages(customDateFilterErrorMessages),
to: Joi.date()
.max(new Date().setHours(23, 59, 59, 999))
.when('from', {
is: Joi.exist(),
then: Joi.date().min(Joi.ref('from')),
})
.messages(customDateFilterErrorMessages),
});

const TagFilterDto = Joi.object({
values: customJoi.stringArray().items(EntityIdDto).single().required(),
operation: Joi.string().valid('and', 'or').required(),
});

const SortDto = Joi.object({
id: Joi.string()
.valid('asc', 'desc'),
text: Joi.string()
.valid('asc', 'desc'),
});

const FilterDto = Joi.object({
runNumber: EntityIdDto,
tag: TagFilterDto,
o2start: DateFilterDto,
o2end: DateFilterDto,
trgStart: DateFilterDto,
trgEnd: DateFilterDto,
environmentId: Joi.string().trim(),
nDetectors: EntityIdDto,
nFlps: EntityIdDto,
ddflp: Joi.boolean(),
dcs: Joi.boolean(),
epn: Joi.boolean(),
epnTopology: Joi.string().trim(),
detectors: Joi.string().trim(),
});

const QueryDto = Joi.object({
filter: FilterDto,
page: PaginationDto,
sort: SortDto,
token: Joi.string(),
Expand Down
1 change: 1 addition & 0 deletions lib/public/Model.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ export default class Model extends Observable {
// Prevent loading extra rows when it's not necessary
if (!this.runs.isInfiniteScrollEnabled()) {
this.runs.fetchAllRuns();
this.tags.fetchAllTags();
}
break;
case 'run-detail':
Expand Down
2 changes: 1 addition & 1 deletion lib/public/components/Filters/LogsFilter/runs.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { h } from '/js/src/index.js';
* @return {vnode} A text box that allows the user to enter runNumbers to filter the logs
*/
const runsFilter = (model) => h('input.w-75.mt1', {
type: 'text',
type: 'number',
id: 'runsFilterText',
value: model.logs.getRunsFilter(),
oninput: (e) => model.logs.setRunsFilter(e.target.value),
Expand Down
36 changes: 36 additions & 0 deletions lib/public/components/Filters/RunsFilter/dcs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/**
* @license
* Copyright CERN and copyright holders of ALICE Trg. 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-Trg.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.
*/

import { h } from '/js/src/index.js';

/**
* Returns the creation date filter components
* @param {Object} model The global model object
* @return {vnode} Two date selection boxes to control the minimum and maximum creation dates for the log filters
*/
const dcsOperationRadioButtons = (model) => h('.form-group-header.flex-row', [true].map((operation) =>
h('.form-check.mr2', [
h('input.form-check-input', {
onclick: () => model.runs.setDcsFilterOperation(operation),
id: `dcsFilterOperationRadioButton${operation}`,
checked: operation === model.runs.getDcsFilterOperation(),
type: 'radio',
name: 'operationRadioButtons2',
value: model.runs.getDcsFilterOperation(),
}, ''),
h('label.form-check-label', {
for: `dcsFilterOperationRadioButton${operation}`,
}, operation),
])));

export default dcsOperationRadioButtons;
35 changes: 35 additions & 0 deletions lib/public/components/Filters/RunsFilter/ddflp.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* @license
* Copyright CERN and copyright holders of ALICE Trg. 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-Trg.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.
*/

import { h } from '/js/src/index.js';

/**
* Returns the creation date filter components
* @param {Object} model The global model object
* @return {vnode} Two date selection boxes to control the minimum and maximum creation dates for the log filters
*/
const ddflpOperationRadioButtons = (model) => h('.form-group-header.flex-row', [true].map((operation) =>
h('.form-check.mr2', [
h('input.form-check-input', {
onclick: () => model.runs.setDdflpFilterOperation(operation),
id: `ddflpFilterOperationRadioButton${operation}`,
checked: operation === model.runs.getDdflpFilterOperation(),
type: 'radio',
name: 'operationRadioButtons1',
value: model.runs.getDdflpFilterOperation(),
}, ''),
h('label.form-check-label', {
for: `ddflpFilterOperationRadioButton${operation}`,
}, operation),
])));
export default ddflpOperationRadioButtons;
28 changes: 28 additions & 0 deletions lib/public/components/Filters/RunsFilter/detectors.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/**
* @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.
*/

import { h } from '/js/src/index.js';

/**
* Returns the author filter component
* @param {Object} model The global model object
* @return {vnode} A text box that lets the user look for logs with a specific author
*/
const runNumberFilter = (model) => h('input.w-75.mt1', {
type: 'detectors',
id: 'detectors',
value: model.runs.getDetectorsFilter(),
oninput: (e) => model.runs.setDetectorsFilter(e.target.value),
}, '');

export default runNumberFilter;
28 changes: 28 additions & 0 deletions lib/public/components/Filters/RunsFilter/environmentId.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/**
* @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.
*/

import { h } from '/js/src/index.js';

/**
* Returns the title filter component
* @param {Object} model The global model object
* @return {vnode} A text box that allows the user to enter a title substring to match against all logs
*/
const titleFilter = (model) => h('input.w-75.mt1', {
type: 'text',
id: 'titleFilterText',
value: model.runs.getEnvFilter(),
oninput: (e) => model.runs.setEnvironmentIdFilter(e.target.value),
}, '');

export default titleFilter;
36 changes: 36 additions & 0 deletions lib/public/components/Filters/RunsFilter/epn.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/**
* @license
* Copyright CERN and copyright holders of ALICE Trg. 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-Trg.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.
*/

import { h } from '/js/src/index.js';

/**
* Returns the creation date filter components
* @param {Object} model The global model object
* @return {vnode} Two date selection boxes to control the minimum and maximum creation dates for the log filters
*/
const epnOperationRadioButtons = (model) => h('.form-group-header.flex-row', [true].map((operation) =>
h('.form-check.mr2', [
h('input.form-check-input', {
onclick: () => model.runs.setEpnFilterOperation(operation),
id: `epnFilterOperationRadioButton${operation}`,
checked: operation === model.runs.getEpnFilterOperation(),
type: 'radio',
name: 'operationRadioButtons3',
value: model.runs.getEpnFilterOperation(),
}, ''),
h('label.form-check-label', {
for: `epnFilterOperationRadioButton${operation}`,
}, operation),
])));

export default epnOperationRadioButtons;
28 changes: 28 additions & 0 deletions lib/public/components/Filters/RunsFilter/epnTopology.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/**
* @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.
*/

import { h } from '/js/src/index.js';

/**
* Returns the title filter component
* @param {Object} model The global model object
* @return {vnode} A text box that allows the user to enter a title substring to match against all logs
*/
const titleFilter = (model) => h('input.w-75.mt1', {
type: 'text',
id: 'epnTopology',
value: model.runs.getEpnTopologyFilter(),
oninput: (e) => model.runs.setEpnTopologyFilter(e.target.value),
}, '');

export default titleFilter;
16 changes: 6 additions & 10 deletions lib/public/components/Filters/RunsFilter/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,22 @@
*/

import { h } from '/js/src/index.js';
import { iconChevronBottom, iconChevronRight } from '/js/src/icons.js';

/**
* Render a complete filter collection
* @param {Object} model The global model object
* @param {Object} columns The columns representing the table
* @return {vnode} The full collection of filters accessible through dropdowns
*/
const filters = (model, columns) =>
const filtersRuns = (model, columns) =>
h('.w-100.shadow-level1.p2', [
h('.f3.mb1', 'Filters'),
Object.entries(columns).reduce((accumulator, [key, column]) => {
if (column.filter) {
accumulator.push([
h('.flex-row.items-center.clickable', {
onclick: () => model.runs.toggleFilterExpanded(key),
id: `${key}FilterToggle`,
}, [
h('', model.runs.isFilterExpanded(key) ? iconChevronBottom() : iconChevronRight()),
h('.f4.ml1', column.name),
h('.flex-row.items-baseline.ph1', [
h('.w-80.p2.m2.f4.ml2', column.name),
h('.w-100.p1.m1', column.filter),
]),
model.runs.isFilterExpanded(key) && column.filter,
]);
Expand All @@ -40,8 +36,8 @@ const filters = (model, columns) =>
}, []),
h('button.btn.btn-danger.mt2', {
disabled: !model.runs.isAnyFilterActive(),
onclick: () => model.runs.resetLogsParams(),
onclick: () => model.runs.resetRunsParams(),
}, 'Reset all filters'),
]);

export default filters;
export default filtersRuns;
Loading