Skip to content

Commit

Permalink
[OGUI-1413] Add action panel calibration page (#2189)
Browse files Browse the repository at this point in the history
* adds a new card in calibration run page for each detector & run type configuration
* new card, action card, allows the user to start a new calibration run page and follow the progress
* updates API GET request to return configurations grouped by detector and runType rather than as a list
  • Loading branch information
graduta authored Nov 2, 2023
1 parent 1e18c6e commit 6bb4c0a
Show file tree
Hide file tree
Showing 7 changed files with 128 additions and 29 deletions.
9 changes: 5 additions & 4 deletions Control/lib/services/Run.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,13 @@ class RunService {

/**
* Based on already loaded calibration configuration mapping from KV store, retrieve runs with those characteristics from Bookkeeping
* @return {Promise<Object<String, Array<RunSummary>.Error>} - list of calibration runs grouped by detector
* @return {Promise<Object<String(Detector), Map<String(RunType), Object(CalibrationConfiguration, RunSummary, RunSummary)>.Error>} - list of calibration runs grouped by detector
*/
async retrieveCalibrationRunsGroupedByDetector() {
const calibrationRunsPerDetector = {};
for (const detector in this._calibrationConfigurationPerDetectorMap) {
const calibrationConfigurationList = this._calibrationConfigurationPerDetectorMap[detector] ?? [];
calibrationRunsPerDetector[detector] = [];
calibrationRunsPerDetector[detector] = {};
for (const calibrationConfiguration of calibrationConfigurationList) {
const runTypeId = this._runTypes[calibrationConfiguration.runType];
const lastCalibrationRun = await this._bkpService.getRun({
Expand All @@ -99,10 +99,11 @@ class RunService {
calibrationStatuses: RunCalibrationStatus.SUCCESS
});
if (lastCalibrationRun || lastSuccessfulCalibrationRun) {
calibrationRunsPerDetector[detector].push({
calibrationRunsPerDetector[detector][calibrationConfiguration.runType] = {
configuration: calibrationConfiguration,
lastCalibrationRun,
lastSuccessfulCalibrationRun,
});
};
}
}
}
Expand Down
31 changes: 29 additions & 2 deletions Control/public/pages/CalibrationRuns/CalibrationRuns.model.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,12 @@ export class CalibrationRunsModel extends Observable {
* @example
* RemoteData {
* "TPC": [
* {<RunSummary>},
* {<RunSummary>}
* {
* configuration: <CalibrationConfiguration>,
* ongoingCalibrationRun: RemoteData<EnvironmentSummary>,
* lastCalibrationRun: <RunSummary>,
* lastSuccessfulCalibrationRun: <RunSummary>
* },
* ]
* }
*/
Expand All @@ -55,6 +59,29 @@ export class CalibrationRunsModel extends Observable {
this.notify();
}

/**
* Send an HTTP POST request to trigger a new auto transitioning environment
* @param {String} detector - for which the environment should be created
* @param {String} runType - of the type of environment
* @param {String} configurationName - name of the saved configuration to use
* @return {void}
*/
async newCalibrationRun(detector, runType, configurationName) {
if (this._calibrationRuns.isSuccess()) {
this._calibrationRuns.payload[detector][runType].ongoingCalibrationRun = RemoteData.loading();
this.notify();

const payload = {
configurationName
};
const {result, ok} = await this._model.loader.post('/api/environment/auto', payload);

this._calibrationRuns.payload[detector][runType].ongoingCalibrationRun =
ok ? RemoteData.success(result) : RemoteData.failure(result.message);
this.notify();
}
}

/**
* Getters & Setters
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/**
* @license
* Copyright 2019-2020 CERN and copyright holders of ALICE O2.
* See http://alice-o2.web.cern.ch/copyright for details of the copyright holders.
* All rights not expressly granted are reserved.
*
* This software is distributed under the terms of the GNU General Public
* License v3 (GPL Version 3), copied verbatim in the file "COPYING".
*
* 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, iconPlayCircle} from '/js/src/index.js';
import {miniCard} from './../../../common/card/miniCard.js';
import pageLoading from './../../../common/pageLoading.js';
import errorComponent from './../../../common/errorComponent.js';

/**
* Builds a card with information and actions allowed on that type of run calibration for that detector
* @param {CalibrationConfiguration} calibrationConfiguration - information about the run
* @param {RemoteData<RunSummary.Error>} ongoingCalibrationRun - information on ongoing calibration run
* @param {String} detector - to which the run belongs to
* @param {Function} onclick - action to trigger when clicking on button
* @return {vnode}
*/
export const calibrationActionCard = (calibrationConfiguration, ongoingCalibrationRun, detector, onclick) => {
const {runType, configuration, label} = calibrationConfiguration;
return miniCard(
h('.flex-row.justify-between', [
h('.flex-row.gc1', [
h('button.btn.btn-sm.btn-success', {
onclick: () => onclick(detector, runType, configuration),
title: `Start a calibration run for ${detector} with run type ${runType}`,
}, iconPlayCircle()),
h('strong', label),
]),
h('small', `${configuration}`)
]), [
ongoingCalibrationRun && ongoingCalibrationRun.match({
NotAsked: () => null,
Loading: () => pageLoading(1),
Success: (result) => h('', result),
Failure: (error) => errorComponent(error),
})
], ['w-50', 'g0', 'gr1', 'p1']
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,6 @@ import {calibrationRunCardTitle} from './calibrationRunCardTitle.js';
export const calibrationRunCard = (run) => miniCard(
calibrationRunCardTitle(run), [
rowForCard(formatTimeDuration(run.runDuration), `Start: ${new Date(run.startTime).toLocaleString()}`),
rowForCard(`${run.detectors}/${run.runType}`, `End: ${new Date(run.endTime).toLocaleString()}`),
], ['w-30', 'g0', 'p2']
rowForCard(null, `End: ${new Date(run.endTime).toLocaleString()}`),
], ['w-25', 'g0', 'p2']
);
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import {h} from '/js/src/index.js';
import {miniCard} from '../../../common/card/miniCard.js';
import {calibrationRunCard} from './calibrationRunCard.js';
import {calibrationActionCard} from './calibrationActionCard.js';

/**
* @file contains grouped needed for displaying actions and information on calibration runs that are grouped
Expand All @@ -28,14 +29,15 @@ import {calibrationRunCard} from './calibrationRunCard.js';
* Panel which contains all calibration runs data grouped by detector.
* If there are not any runs for at least a detector, an informative message will be displayed.
* @param {Object<String, Array<RunSummary>} calibrationsRunsByDetector - object with calibration runs information grouped by their detector
* @param {CalibrationRunsModel} calibrationRunsModel - model to use for actions on calibration runs
* @return {vnode}
*/
export const groupedCalibrationRunsPanel = (calibrationsRunsByDetector) => {
export const groupedCalibrationRunsPanel = (calibrationsRunsByDetector, calibrationRunsModel) => {
const detectorsGroupPanel = [];
for (const detector in calibrationsRunsByDetector) {
const runsForDetector = calibrationsRunsByDetector[detector];
if (runsForDetector?.length > 0) {
detectorsGroupPanel.push(calibrationRunsPerDetectorCard(runsForDetector));
if (Object.keys(runsForDetector)?.length > 0) {
detectorsGroupPanel.push(calibrationRunsPerDetectorCard(detector, runsForDetector, calibrationRunsModel));
}
}
if (detectorsGroupPanel.length === 0) {
Expand All @@ -49,16 +51,24 @@ export const groupedCalibrationRunsPanel = (calibrationsRunsByDetector) => {

/**
* Component for mapping each detector to its group of calibration runs
* @param {Array<RunSummary>} runs - list of runs for which to build the components
* @param {String} detector - to which the run group belongs to
* @param {Object<String, RunSummary|CalibrationConfiguration|RemoteData>} runGroups - list of runs for which to build the components
* @param {CalibrationRunsModel} calibrationRunsModel - model of the component
* @return {vnode}
*/
const calibrationRunsPerDetectorCard = (runGroups) =>
miniCard(null, [
runGroups.map((group) =>
h('.p1.flex-row.g2',
const calibrationRunsPerDetectorCard = (detector, runGroups, calibrationRunsModel) => {
const {newCalibrationRun} = calibrationRunsModel;
return miniCard(null, [
Object.values(runGroups).map((runGroup) => {
const {configuration, lastCalibrationRun, lastSuccessfulCalibrationRun, ongoingCalibrationRun} = runGroup;
return h('.p1.flex-row.g2',
[
calibrationRunCard(group.lastCalibrationRun),
calibrationRunCard(group.lastSuccessfulCalibrationRun),
calibrationActionCard(
configuration, ongoingCalibrationRun, detector, newCalibrationRun.bind(calibrationRunsModel)
),
calibrationRunCard(lastCalibrationRun),
calibrationRunCard(lastSuccessfulCalibrationRun),
])
)
})
], ['m1', 'g1', 'p1']);
};
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export const calibrationRunsContent = (calibrationRunsModel) => {
return calibrationRuns.match({
NotAsked: () => h('.f7.flex-column', 'Calibration Runs data not asked'),
Loading: () => pageLoading(2),
Success: (runsGroupedByDetector) => groupedCalibrationRunsPanel(runsGroupedByDetector),
Success: (runsGroupedByDetector) => groupedCalibrationRunsPanel(runsGroupedByDetector, calibrationRunsModel),
Failure: (error) => errorPage(error),
})
});
};
28 changes: 20 additions & 8 deletions Control/test/lib/services/mocha-run.service.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,14 +96,26 @@ describe(`'RunService' test suite`, async () => {
};
const result = await runSrv.retrieveCalibrationRunsGroupedByDetector();
assert.deepStrictEqual(result, {
TPC: [
{lastCalibrationRun: {runNumber: 1}, lastSuccessfulCalibrationRun: {runNumber: 1}},
{lastCalibrationRun: {runNumber: 2}, lastSuccessfulCalibrationRun: {runNumber: 2}}
],
ABC: [
{lastCalibrationRun: {runNumber: 3}, lastSuccessfulCalibrationRun: {runNumber: 2}},
],
XYZ: []
TPC: {
NOISE: {
configuration: {runType: 'NOISE', configuration: 'cpv-noise', label: 'CPV NOISE'},
lastCalibrationRun: {runNumber: 1},
lastSuccessfulCalibrationRun: {runNumber: 1}
},
PULSE: {
configuration: {runType: 'PULSE', configuration: 'cpv-pulse', label: 'CPV PULSE'},
lastCalibrationRun: {runNumber: 2},
lastSuccessfulCalibrationRun: {runNumber: 2}
}
},
ABC: {
SOMEOTHER: {
configuration: {runType: 'SOMEOTHER', configuration: 'abc-someother', label: 'ABC SOME OTHER'},
lastCalibrationRun: {runNumber: 3},
lastSuccessfulCalibrationRun: {runNumber: 2}
},
},
XYZ: {}
});
});
});
Expand Down

0 comments on commit 6bb4c0a

Please sign in to comment.