Skip to content

Commit 237683a

Browse files
Merge branch 'main' into improv/O2B-1534/Migrate-Log-Overview-to-use-FilteringModel-pattern
2 parents 0d8d3d4 + cc248ef commit 237683a

16 files changed

Lines changed: 462 additions & 235 deletions
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* @license
3+
* Copyright CERN and copyright holders of ALICE O2. This software is
4+
* distributed under the terms of the GNU General Public License v3 (GPL
5+
* Version 3), copied verbatim in the file "COPYING".
6+
*
7+
* See http://alice-o2.web.cern.ch/license for full licensing information.
8+
*
9+
* In applying this license CERN does not waive the privileges and immunities
10+
* granted to it by virtue of its status as an Intergovernmental Organization
11+
* or submit itself to any jurisdiction.
12+
*/
13+
14+
'use strict';
15+
16+
/** @type {import('sequelize-cli').Migration} */
17+
module.exports = {
18+
up: async (queryInterface) => queryInterface.sequelize.transaction(async (transaction) => {
19+
await queryInterface.addIndex('quality_control_flags', {
20+
name: 'quality_control_flags_run_detector_idx',
21+
fields: ['run_number', 'detector_id'],
22+
}, { transaction });
23+
}),
24+
25+
down: async (queryInterface) => queryInterface.sequelize.transaction(async (transaction) => {
26+
await queryInterface.removeIndex('quality_control_flags', 'quality_control_flags_run_detector_idx', { transaction });
27+
}),
28+
};
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/**
2+
* @license
3+
* Copyright CERN and copyright holders of ALICE O2. This software is
4+
* distributed under the terms of the GNU General Public License v3 (GPL
5+
* Version 3), copied verbatim in the file "COPYING".
6+
*
7+
* See http://alice-o2.web.cern.ch/license for full licensing information.
8+
*
9+
* In applying this license CERN does not waive the privileges and immunities
10+
* granted to it by virtue of its status as an Intergovernmental Organization
11+
* or submit itself to any jurisdiction.
12+
*/
13+
14+
import { DetectorType } from './DetectorTypes.js';
15+
16+
/**
17+
* Defines priority mappings for detector types.
18+
* Each key is a mapping between {@link DetectorType} values and their numeric priority
19+
* (larger values will appear first - see detectorsProvider LN88).
20+
*
21+
* - **DEFAULT**: Standard ordering used across most views.
22+
* - **RCT**: Ordering used in the Run Condition Table, which prioritizes PHYSICAL detectors.
23+
*/
24+
export const DetectorOrders = Object.freeze({
25+
DEFAULT: {
26+
[DetectorType.OTHER]: 0,
27+
[DetectorType.VIRTUAL]: 1,
28+
[DetectorType.PHYSICAL]: 2,
29+
[DetectorType.AOT_GLO]: 3,
30+
[DetectorType.AOT_EVENT]: 4,
31+
[DetectorType.MUON_GLO]: 5,
32+
[DetectorType.QC_ONLY]: 6,
33+
},
34+
RCT: {
35+
[DetectorType.OTHER]: 0,
36+
[DetectorType.AOT_GLO]: 1,
37+
[DetectorType.AOT_EVENT]: 2,
38+
[DetectorType.MUON_GLO]: 3,
39+
[DetectorType.VIRTUAL]: 4,
40+
[DetectorType.PHYSICAL]: 5,
41+
[DetectorType.QC_ONLY]: 6,
42+
},
43+
});

lib/public/services/detectors/detectorsProvider.js

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { switchCase } from '/js/src/index.js';
1515
import { getRemoteData } from '../../utilities/fetch/getRemoteData.js';
1616
import { ObservableData } from '../../utilities/ObservableData.js';
1717
import { DetectorType, DATA_TAKING_DETECTOR_TYPES, QC_DETECTORS } from '../../domain/enums/DetectorTypes.js';
18+
import { DetectorOrders } from '../../domain/enums/DetectorOrders.js';
1819

1920
import { NonPhysicalDetector } from '../../domain/enums/detectorsNames.mjs';
2021

@@ -44,9 +45,12 @@ const getQcDetectorsFromAllDetectors = (allDetectors) => allDetectors
4445
export class DetectorsProvider extends RemoteDataProvider {
4546
/**
4647
* Constructor
48+
*
49+
* @param {DetectorOrders} detectorOrder the order to base sorting on, default is DetectorOrders.DEFAULT
4750
*/
48-
constructor() {
51+
constructor(detectorOrder = DetectorOrders.DEFAULT) {
4952
super();
53+
this._detectorOrder = detectorOrder;
5054
this._physical$ = ObservableData.builder()
5155
.source(this._items$)
5256
.apply((remoteDetectors) => remoteDetectors.apply({
@@ -74,21 +78,14 @@ export class DetectorsProvider extends RemoteDataProvider {
7478
*/
7579
async getRemoteData() {
7680
const { data: detectors } = await getRemoteData('/api/detectors');
77-
const typeToOrderingKey = (type) => switchCase(type, {
78-
[DetectorType.OTHER]: 0,
79-
[DetectorType.VIRTUAL]: 1,
80-
[DetectorType.PHYSICAL]: 2,
81-
[DetectorType.AOT_GLO]: 3,
82-
[DetectorType.AOT_EVENT]: 4,
83-
[DetectorType.MUON_GLO]: 5,
84-
[DetectorType.QC_ONLY]: 6,
85-
});
81+
const typeToOrderingKey = (type) => switchCase(type, this._detectorOrder);
8682

8783
const orderingKey = (detector1, detector2) => {
8884
const specialPair = ['ZDC', 'TST'];
8985
if (specialPair.includes(detector1.name) && specialPair.includes(detector2.name)) {
9086
return detector1.name === 'ZDC' ? 1 : -1;
9187
}
88+
// Note the negative sign to have larger priority types appear first
9289
return -(typeToOrderingKey(detector1.type) - typeToOrderingKey(detector2.type)) * 10 + detector1.name.localeCompare(detector2.name);
9390
};
9491

@@ -161,3 +158,4 @@ export class DetectorsProvider extends RemoteDataProvider {
161158
}
162159

163160
export const detectorsProvider = new DetectorsProvider();
161+
export const rctDetectorsProvider = new DetectorsProvider(DetectorOrders.RCT);

lib/public/views/Runs/Details/RunPatch.js

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { RunQualities } from '../../../domain/enums/RunQualities.js';
99
* @property {string} category
1010
* @property {string} title
1111
* @property {string} description
12+
* @property {string|null} [lastEditedName]
1213
*/
1314

1415
/**
@@ -75,7 +76,8 @@ export class RunPatch extends Observable {
7576
}
7677

7778
if (this._eorReasons.length !== this._run.eorReasons.length || this._eorReasons.some(({ id }) => id === undefined)) {
78-
ret.eorReasons = this._eorReasons;
79+
// Strip lastEditedName — the server's EorReasonDto only accepts id, reasonTypeId, and description
80+
ret.eorReasons = this._eorReasons.map(({ id, reasonTypeId, description }) => ({ id, reasonTypeId, description }));
7981
}
8082

8183
if (this._hasRunQualityChange()) {
@@ -126,7 +128,12 @@ export class RunPatch extends Observable {
126128
} = this._run || {};
127129

128130
this._runQuality = runQuality;
129-
this._eorReasons = eorReasons.map(({ id, description, reasonTypeId }) => ({ id, description, reasonTypeId }));
131+
this._eorReasons = eorReasons.map(({ id, description, reasonTypeId, lastEditedName }) => ({
132+
id,
133+
description,
134+
reasonTypeId,
135+
lastEditedName,
136+
}));
130137
this._tags = tags.map(({ text }) => text);
131138

132139
this.formData = {

lib/public/views/Runs/Details/runDetailsComponent.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ import { RunDefinition } from '../../../domain/enums/RunDefinition.js';
4040
import { formatFloat } from '../../../utilities/formatting/formatFloat.js';
4141
import { formatEditableNumber } from '../format/formatEditableNumber.js';
4242
import { editRunEorReasons } from '../format/editRunEorReasons.js';
43-
import { formatEorReason } from '../format/formatEorReason.mjs';
43+
import { formatRunEorReason } from '../format/formatRunEorReason.js';
4444
import { selectionDropdown } from '../../../components/common/selection/dropdown/selectionDropdown.js';
4545
import { formatRunCalibrationStatus } from '../format/formatRunCalibrationStatus.js';
4646
import { BeamModes } from '../../../domain/enums/BeamModes.js';
@@ -533,7 +533,10 @@ export const runDetailsComponent = (runDetailsModel, router) => runDetailsModel.
533533
h('#eor-reasons.flex-row', [
534534
runDetailsModel.isEditModeEnabled
535535
? editRunEorReasons(runDetailsModel)
536-
: h('.flex-column.g2', run.eorReasons.map((eorReason) => h('.eor-reason', formatEorReason(eorReason)))),
536+
: h(
537+
'.flex-column.g2.w-100',
538+
run.eorReasons.map((eorReason) => h('.eor-reason', formatRunEorReason(eorReason))),
539+
),
537540
]),
538541
]),
539542
]),

lib/public/views/Runs/RunPerDataPass/RunsPerDataPassOverviewModel.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { buildUrl, RemoteData } from '/js/src/index.js';
1414
import { ObservableData } from '../../../utilities/ObservableData.js';
1515
import { getRemoteDataSlice } from '../../../utilities/fetch/getRemoteDataSlice.js';
1616
import { getRemoteData } from '../../../utilities/fetch/getRemoteData.js';
17-
import { detectorsProvider } from '../../../services/detectors/detectorsProvider.js';
17+
import { rctDetectorsProvider } from '../../../services/detectors/detectorsProvider.js';
1818
import { FixedPdpBeamTypeRunsOverviewModel } from '../Overview/FixedPdpBeamTypeRunsOverviewModel.js';
1919
import { jsonPatch } from '../../../utilities/fetch/jsonPatch.js';
2020
import { jsonPut } from '../../../utilities/fetch/jsonPut.js';
@@ -43,7 +43,7 @@ export class RunsPerDataPassOverviewModel extends FixedPdpBeamTypeRunsOverviewMo
4343

4444
this._detectors$ = ObservableData
4545
.builder()
46-
.sources([detectorsProvider.qc$, this._dataPass$])
46+
.sources([rctDetectorsProvider.qc$, this._dataPass$])
4747
.apply((remoteDataList) => mergeRemoteData(remoteDataList)
4848
.apply({ Success: ([detectors, dataPass]) => ALL_CPASS_PRODUCTIONS_REGEX.test(dataPass.name)
4949
? detectors.filter(({ name, type }) => type !== DetectorType.AOT_GLO || DETECTOR_NAMES_NOT_IN_CPASSES.includes(name))

lib/public/views/Runs/RunPerPeriod/RunsPerLhcPeriodOverviewModel.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
*/
1313
import { buildUrl, RemoteData } from '/js/src/index.js';
1414
import { TabbedPanelModel } from '../../../components/TabbedPanel/TabbedPanelModel.js';
15-
import { detectorsProvider } from '../../../services/detectors/detectorsProvider.js';
15+
import { rctDetectorsProvider } from '../../../services/detectors/detectorsProvider.js';
1616
import { jsonFetch } from '../../../utilities/fetch/jsonFetch.js';
1717
import { DetectorType } from '../../../domain/enums/DetectorTypes.js';
1818
import { ObservableData } from '../../../utilities/ObservableData.js';
@@ -38,11 +38,11 @@ export class RunsPerLhcPeriodOverviewModel extends FixedPdpBeamTypeRunsOverviewM
3838
this._lhcPeriodId = null;
3939
this._lhcPeriodStatistics$ = new ObservableData(RemoteData.notAsked());
4040

41-
this._onlineDetectors$ = detectorsProvider.physical$;
41+
this._onlineDetectors$ = rctDetectorsProvider.physical$;
4242

4343
this._syncDetectors$ = ObservableData
4444
.builder()
45-
.source(detectorsProvider.qc$)
45+
.source(rctDetectorsProvider.qc$)
4646
.apply((remoteDetectors) =>
4747
remoteDetectors.apply({
4848
Success: (detectors) => detectors.filter(({ type }) => [DetectorType.PHYSICAL, DetectorType.MUON_GLO].includes(type)),

lib/public/views/Runs/RunsPerSimulationPass/RunsPerSimulationPassOverviewModel.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
import { buildUrl, RemoteData } from '/js/src/index.js';
1414
import { ObservableData } from '../../../utilities/ObservableData.js';
1515
import { getRemoteData } from '../../../utilities/fetch/getRemoteData.js';
16-
import { detectorsProvider } from '../../../services/detectors/detectorsProvider.js';
16+
import { rctDetectorsProvider } from '../../../services/detectors/detectorsProvider.js';
1717
import { FixedPdpBeamTypeRunsOverviewModel } from '../Overview/FixedPdpBeamTypeRunsOverviewModel.js';
1818

1919
/**
@@ -29,7 +29,7 @@ export class RunsPerSimulationPassOverviewModel extends FixedPdpBeamTypeRunsOver
2929

3030
this._simulationPass$ = new ObservableData(RemoteData.notAsked());
3131

32-
this._detectors$ = detectorsProvider.qc$;
32+
this._detectors$ = rctDetectorsProvider.qc$;
3333

3434
this.registerObervablesQcSummaryDependesOn([this._detectors$]);
3535
this.registerDetectorsNotBadFractionFilterModels(this._detectors$);

lib/public/views/Runs/format/editRunEorReasons.js

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -94,20 +94,23 @@ export const editRunEorReasons = (runDetailsModel) => {
9494
*/
9595
runDetailsModel.runPatch.eorReasons.length > 0
9696
? runDetailsModel.runPatch.eorReasons.map((eorReason) => {
97-
const { reasonTypeId, description } = eorReason;
97+
const { reasonTypeId, description, lastEditedName } = eorReason;
9898
const { category = '-', title } = eorReasonTypes.find((eorReasonType) => eorReasonType.id === reasonTypeId) || {};
9999
const titleString = title ? ` - ${title}` : '';
100100
const descriptionString = description ? ` - ${description}` : '';
101101
return h(
102-
'.flex-row.items-center',
102+
'.flex-row.justify-between',
103103
{
104104
key: `${category} ${titleString} ${descriptionString}`,
105105
},
106106
[
107-
h('label.remove-eor-reason.danger.ph1.actionable-icon', {
108-
onclick: () => runDetailsModel.runPatch.removeEorReason(eorReason),
109-
}, iconTrash()),
110-
h('.w-wrapped', `${category} ${titleString} ${descriptionString}`),
107+
h('.flex-row.items-center', [
108+
h('label.remove-eor-reason.danger.ph1.actionable-icon', {
109+
onclick: () => runDetailsModel.runPatch.removeEorReason(eorReason),
110+
}, iconTrash()),
111+
h('.w-wrapped', `${category} ${titleString} ${descriptionString}`),
112+
]),
113+
h('.w-wrapped', lastEditedName || null),
111114
],
112115
);
113116
})
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/**
2+
* @license
3+
* Copyright CERN and copyright holders of ALICE O2. This software is
4+
* distributed under the terms of the GNU General Public License v3 (GPL
5+
* Version 3), copied verbatim in the file "COPYING".
6+
*
7+
* See http://alice-o2.web.cern.ch/license for full licensing information.
8+
*
9+
* In applying this license CERN does not waive the privileges and immunities
10+
* granted to it by virtue of its status as an Intergovernmental Organization
11+
* or submit itself to any jurisdiction.
12+
*/
13+
14+
import { h } from '/js/src/index.js';
15+
import { tooltip } from '../../../../components/common/popover/tooltip.js';
16+
import { formatEorReason } from './formatEorReason.mjs';
17+
18+
/**
19+
* Display the given EoR reason as a vnode component with lastEditedName tooltip
20+
*
21+
* @param {Partial<{
22+
* category: string,
23+
* title: string,
24+
* description: string,
25+
* lastEditedName: string,
26+
* }>} eorReason the EoR reason to display
27+
* @return {VNode} the vnode component
28+
*/
29+
export const formatRunEorReason = (eorReason) => {
30+
const { lastEditedName } = eorReason;
31+
const reasonText = formatEorReason(eorReason);
32+
return h('.w-100.flex-row.justify-between', [
33+
h('', reasonText),
34+
lastEditedName ? tooltip(h('.w-wrapped', lastEditedName), 'Last edited by') : null,
35+
]);
36+
};

0 commit comments

Comments
 (0)