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
8 changes: 8 additions & 0 deletions lib/database/adapters/LogAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ class LogAdapter {
*/
this.dataPassAdapter = null;

/**
* @type {SimulationPassAdapter|null}
*/
this.simulationPassAdapter = null;

/**
* @typedef {EnvironmentAdapter|null}
*/
Expand Down Expand Up @@ -80,6 +85,7 @@ class LogAdapter {
runs,
lhcFills: sequelizeLhcFills,
dataPasses: sequelizeDataPasses,
simulationPasses: sequelizeSimulationPasses,
attachments: sequelizeAttachments,
environments: sequelizeEnvironments,
} = databaseObject;
Expand All @@ -89,6 +95,7 @@ class LogAdapter {
const attachments = (sequelizeAttachments || []).map(this.attachmentAdapter.toEntity);
const lhcFills = (sequelizeLhcFills || []).map(this.lhcFillAdapter.toEntity);
const dataPasses = (sequelizeDataPasses || []).map(this.dataPassAdapter.toMinifiedEntity);
const simulationPasses = (sequelizeSimulationPasses || []).map(this.simulationPassAdapter.toMinifiedEntity);
Comment thread
graduta marked this conversation as resolved.
const environments = (sequelizeEnvironments || []).map(this.environmentAdapter.toEntity);

const entityObject = {
Expand All @@ -105,6 +112,7 @@ class LogAdapter {
tags,
lhcFills,
dataPasses,
simulationPasses,
attachments,
environments,
};
Expand Down
11 changes: 11 additions & 0 deletions lib/database/adapters/SimulationPassAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class SimulationPassAdapter {
*/
constructor() {
this.toEntity = this.toEntity.bind(this);
this.toMinifiedEntity = this.toMinifiedEntity.bind(this);
}

/**
Expand Down Expand Up @@ -58,6 +59,16 @@ class SimulationPassAdapter {
pdpBeamTypes,
};
}

/**
* Converts the given database object to a minified entity object (only identification fields).
*
* @param {SequelizeSimulationPass} databaseObject Object to convert.
* @returns {{id: number, name: string}} Converted minified entity object.
*/
toMinifiedEntity({ id, name }) {
return { id, name };
}
}

module.exports = SimulationPassAdapter;
1 change: 1 addition & 0 deletions lib/database/adapters/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ lhcPeriodStatisticsAdapter.lhcPeriodAdapter = lhcPeriodAdapter;

logAdapter.attachmentAdapter = attachmentAdapter;
logAdapter.dataPassAdapter = dataPassAdapter;
logAdapter.simulationPassAdapter = simulationPassAdapter;
logAdapter.environmentAdapter = environmentAdapter;
logAdapter.lhcFillAdapter = lhcFillAdapter;
logAdapter.runAdapter = runAdapter;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/**
* @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.
*/

'use strict';

/** @type {import('sequelize-cli').Migration} */
module.exports = {
up: async (queryInterface, Sequelize) => queryInterface.createTable('log_simulation_passes', {
log_id: {
type: Sequelize.INTEGER,
primaryKey: true,
allowNull: false,
references: { model: 'logs', key: 'id' },
onUpdate: 'CASCADE',
onDelete: 'CASCADE',
},
simulation_pass_id: {
type: Sequelize.INTEGER,
primaryKey: true,
allowNull: false,
references: { model: 'simulation_passes', key: 'id' },
onUpdate: 'CASCADE',
onDelete: 'CASCADE',
},
created_at: {
allowNull: false,
type: Sequelize.DATE,
defaultValue: Sequelize.literal('CURRENT_TIMESTAMP'),
},
updated_at: {
allowNull: false,
type: Sequelize.DATE,
defaultValue: Sequelize.literal('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'),
},
}),

down: async (queryInterface) => queryInterface.dropTable('log_simulation_passes'),
};
7 changes: 7 additions & 0 deletions lib/database/models/log.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,13 @@ module.exports = (sequelize) => {
otherKey: 'data_pass_id',
});

Log.belongsToMany(models.SimulationPass, {
as: 'simulationPasses',
through: 'log_simulation_passes',
foreignKey: 'log_id',
otherKey: 'simulation_pass_id',
});

Log.hasMany(models.Attachment, { as: 'attachments', foreignKey: 'log_id' });
};

Expand Down
7 changes: 7 additions & 0 deletions lib/database/models/simulationPass.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,13 @@ module.exports = (sequelize) => {
foreignKey: 'simulation_pass_id',
through: 'simulation_pass_quality_control_flag',
});

SimulationPass.belongsToMany(models.Log, {
as: 'logs',
through: 'log_simulation_passes',
foreignKey: 'simulation_pass_id',
otherKey: 'log_id',
});
};

return SimulationPass;
Expand Down
1 change: 1 addition & 0 deletions lib/database/models/typedefs/SequelizeLog.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,5 @@
* @property {SequelizeAttachment[]|null} attachments
* @property {SequelizeEnvironment[]|null} environments
* @property {SequelizeDataPass[]|null} dataPasses
* @property {SequelizeSimulationPass[]|null} simulationPasses
*/
39 changes: 39 additions & 0 deletions lib/database/repositories/LogSimulationPassesRepository.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.
*/

const { tables: { LogSimulationPasses } } = require('..');
const Repository = require('./Repository');

/**
* Sequelize implementation of the LogSimulationPassesRepository.
*/
class LogSimulationPassesRepository extends Repository {
/**
* Creates a new `LogSimulationPassesRepository` instance.
*/
constructor() {
super(LogSimulationPasses);
}

/**
* Bulk insert logSimulationPasses.
*
* @param {{logId: number, simulationPassId: number}[]} entities the links to insert
* @returns {Promise} Promise object represents the recently inserted LogSimulationPasses.
*/
async bulkInsert(entities) {
return LogSimulationPasses.bulkCreate(entities, { returning: true });
}
}

module.exports = new LogSimulationPassesRepository();
2 changes: 2 additions & 0 deletions lib/database/repositories/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const LhcPeriodStatisticsRepository = require('./LhcPeriodStatisticsRepository')
const LogEnvironmentsRepository = require('./LogEnvironmentsRepository');
const LogLhcFillsRepository = require('./LogLhcFillsRepository');
const LogDataPassesRepository = require('./LogDataPassesRepository');
const LogSimulationPassesRepository = require('./LogSimulationPassesRepository');
const LogRepository = require('./LogRepository');
const LogRunsRepository = require('./LogRunsRepository');
const LogTagsRepository = require('./LogTagsRepository');
Expand Down Expand Up @@ -79,6 +80,7 @@ module.exports = {
LogEnvironmentsRepository,
LogLhcFillsRepository,
LogDataPassesRepository,
LogSimulationPassesRepository,
LogRepository,
LogRunsRepository,
LogTagsRepository,
Expand Down
28 changes: 28 additions & 0 deletions lib/database/seeders/20240125141300-log-simulation-passes.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.
*/

/** @type {import('sequelize-cli').Migration} */
module.exports = {
up: async (queryInterface) =>
queryInterface.sequelize.transaction((transaction) =>
queryInterface.bulkInsert('log_simulation_passes', [
{ log_id: 1, simulation_pass_id: 1 },
{ log_id: 1, simulation_pass_id: 2 },
{ log_id: 2, simulation_pass_id: 3 },
{ log_id: 119, simulation_pass_id: 1 },
], { transaction })),

down: async (queryInterface) =>
queryInterface.sequelize.transaction((transaction) =>
queryInterface.bulkDelete('log_simulation_passes', null, { transaction })),
};
2 changes: 2 additions & 0 deletions lib/database/tables/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,15 @@ const LogEnvironments = require('./logenvironments');
const RunTags = require('./runtags');
const LogLhcFills = require('./loglhcfills');
const LogDataPasses = require('./logdatapasses');
const LogSimulationPasses = require('./logsimulationpasses');

module.exports = (sequelize) => {
const models = {
LogTags: LogTags(sequelize),
LogRuns: LogRuns(sequelize),
LogLhcFills: LogLhcFills(sequelize),
LogDataPasses: LogDataPasses(sequelize),
LogSimulationPasses: LogSimulationPasses(sequelize),
LogEnvironments: LogEnvironments(sequelize),
RunTags: RunTags(sequelize),
};
Expand Down
38 changes: 38 additions & 0 deletions lib/database/tables/logsimulationpasses.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/**
* @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.
*/

module.exports = (sequelize) => {
const Sequelize = require('sequelize');

const LogSimulationPasses = sequelize.define('log_simulation_passes', {
logId: {
allowNull: false,
primaryKey: true,
type: Sequelize.INTEGER,
},
simulationPassId: {
allowNull: false,
primaryKey: true,
type: Sequelize.INTEGER,
},
});

LogSimulationPasses.removeAttribute('id');

LogSimulationPasses.associate = (models) => {
LogSimulationPasses.belongsTo(models.SimulationPass, { foreignKey: 'simulation_pass_id', as: 'simulationPass' });
LogSimulationPasses.belongsTo(models.Log, { foreignKey: 'log_id', as: 'log' });
};

return LogSimulationPasses;
};
3 changes: 3 additions & 0 deletions lib/domain/dtos/CreateLogDto.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ const BodyDto = Joi.object({
dataPasses: Joi.array()
.optional()
.items(Joi.string()),
simulationPasses: Joi.array()
.optional()
.items(Joi.string()),
parentLogId: EntityIdDto.optional(),
runNumbers: Joi.string().optional(),
});
Expand Down
1 change: 1 addition & 0 deletions lib/domain/entities/Log.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,6 @@
* @property {SequelizeTag[]|null} tags
* @property {SequelizeEnvironment[]|null} environments
* @property {{id: number, name: string}[]} dataPasses - minified version of it
* @property {{id: number, name: string}[]} simulationPasses - minified version of it
* @property {SequelizeAttachment[]|null} attachments
*/
30 changes: 27 additions & 3 deletions lib/public/views/Logs/Create/LogCreationModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const DATA_DISPLAY_DELIMITER = ',';
* @property {number[]} [runNumbers] run numbers associated with log being created
* @property {number[]} [lhcFillNumbers] lhc fill numbers associated with log being created
* @property {string[]} [dataPassNames] data pass names associated with log being created
* @property {string[]} [simulationPassNames] simulation pass names associated with log being created
* @property {number[]} [environmentIds] environment ids associated with log being created
*/

Expand All @@ -45,10 +46,11 @@ export class LogCreationModel extends Observable {
this._creationTagsPickerModel.bubbleTo(this);
this._creationTagsPickerModel.visualChange$.bubbleTo(this);

const { runNumbers = [], environmentIds = [], lhcFillNumbers = [], dataPassNames = [] } = relations;
const { runNumbers = [], environmentIds = [], lhcFillNumbers = [], dataPassNames = [], simulationPassNames = [] } = relations;
this._runNumbers = runNumbers.join(DATA_DISPLAY_DELIMITER);
this._lhcFills = lhcFillNumbers.join(DATA_DISPLAY_DELIMITER);
this._dataPasses = dataPassNames.join(DATA_DISPLAY_DELIMITER);
this._simulationPasses = simulationPassNames.join(DATA_DISPLAY_DELIMITER);
this._environments = environmentIds.join(DATA_DISPLAY_DELIMITER);
this._isRunNumbersReadonly = Boolean(this._runNumbers);

Expand Down Expand Up @@ -95,12 +97,13 @@ export class LogCreationModel extends Observable {
this._createdLog = RemoteData.loading();
this.notify();

const { title, text, parentLogId, runNumbers, environments, lhcFills, dataPasses, attachments } = this;
const { title, text, parentLogId, runNumbers, environments, lhcFills, dataPasses, simulationPasses, attachments } = this;
const tagsTexts = this._creationTagsPickerModel.selected;
const environmentsIds = environments ? environments.split(',').map((environment) => environment.trim()) : [];
const lhcFillNumbers = lhcFills ? lhcFills.split(',').map((lhcFillNumber) => lhcFillNumber.trim()) : [];

const dataPassNames = dataPasses.split(',').map((name) => name.trim()).filter(Boolean);
const simulationPassNames = simulationPasses.split(',').map((name) => name.trim()).filter(Boolean);

const body = {
title,
Expand All @@ -114,13 +117,15 @@ export class LogCreationModel extends Observable {
headers: { Accept: 'application/json' },
};

const hasMultipartFields = [attachments, tagsTexts, environmentsIds, lhcFillNumbers, dataPassNames].some(({ length }) => length > 0);
const multipartFields = [attachments, tagsTexts, environmentsIds, lhcFillNumbers, dataPassNames, simulationPassNames];
const hasMultipartFields = multipartFields.some(({ length }) => length > 0);
if (hasMultipartFields) {
const formData = new FormData();
Object.entries(body).forEach(([key, value]) => formData.append(key, value));
environmentsIds.forEach((environmentId) => formData.append('environments[]', environmentId));
lhcFillNumbers.forEach((fillNumber) => formData.append('lhcFills[]', fillNumber));
dataPassNames.forEach((name) => formData.append('dataPasses[]', name));
simulationPassNames.forEach((name) => formData.append('simulationPasses[]', name));
tagsTexts.forEach((tagText) => formData.append('tags[]', tagText));
[...attachments].forEach((attachment, index) => formData.append(`attachments.${index}`, attachment));

Expand Down Expand Up @@ -253,6 +258,25 @@ export class LogCreationModel extends Observable {
this.notify();
}

/**
* Returns the simulation passes which the log will be linked to, as a comma separated string of names
*
* @returns {string} the simulation pass names
*/
get simulationPasses() {
return `${this._simulationPasses}`;
}

/**
* Set the simulation passes which the log will be linked to, as a comma separated string of names
*
* @param {string} value the new simulation pass names list
*/
set simulationPasses(value) {
this._simulationPasses = value;
this.notify();
}

/**
* Set the environments which the log will be linked to, as a comma separated string
*
Expand Down
Loading
Loading