Skip to content

Commit 43bdefc

Browse files
[O2B-1106] Set up log-templating for on-call (#1404)
* [O2B-1106] Create log templating * Add tests * Fix some tests * Fix linter * Add required inputs information
1 parent 89ca6b4 commit 43bdefc

12 files changed

Lines changed: 665 additions & 91 deletions

lib/public/app.css

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -641,7 +641,6 @@ label {
641641
border-bottom: 1px solid var(--color-gray-dark);
642642
}
643643

644-
645644
/**
646645
* Breakpoints :
647646
* small : x < 600 (default styles)

lib/public/components/common/panel/LabelPanelHeaderComponent.js

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,14 @@ import { h } from '/js/src/index.js';
1818
*/
1919
export const LabelPanelHeaderComponent = {
2020
// eslint-disable-next-line require-jsdoc
21-
view: function ({ children, attrs }) {
22-
return h('label.label.form-check-label.panel-header', attrs, children);
21+
view: function ({ children, attrs: { required, ...attrs } }) {
22+
return h(
23+
'label.label.form-check-label.panel-header',
24+
{
25+
...required ? { title: 'This field is mandatory' } : {},
26+
...attrs,
27+
},
28+
required ? h('span.flex-row.g1', [children, h('.danger', '*')]) : children,
29+
);
2330
},
2431
};

lib/public/views/Logs/Create/LogCreationModel.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ export class LogCreationModel extends Observable {
9494
this.notify();
9595

9696
const { title, text, parentLogId, runNumbers, environments, lhcFills, attachments } = this;
97-
const tagsTexts = this.tagsPickerModel.selected;
97+
const tagsTexts = this._creationTagsPickerModel.selected;
9898
const environmentsIds = environments ? environments.split(',').map((environment) => environment.trim()) : [];
9999
const lhcFillNumbers = lhcFills ? lhcFills.split(',').map((lhcFillNumber) => lhcFillNumber.trim()) : [];
100100

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
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 { ObservableData } from '../../../utilities/ObservableData.js';
15+
import { Observable, RemoteData, sessionService } from '/js/src/index.js';
16+
import { detectorsProvider } from '../../../services/detectors/detectorsProvider.js';
17+
18+
/**
19+
* List of alice systems that are not included in detectors list
20+
*
21+
* @type {string[]}
22+
*/
23+
const ALICE_SYSTEMS = ['FLP', 'ECS', 'EPN', 'DCS', 'OTHER'];
24+
25+
/**
26+
* Log template for on-call log
27+
*/
28+
export class OnCallLogTemplate extends Observable {
29+
/**
30+
* Constructor
31+
*/
32+
constructor() {
33+
super();
34+
35+
/**
36+
* @type {ObservableData<RemoteData<Detector[], ApiError>>}
37+
* @private
38+
*/
39+
this._detectors = new ObservableData(RemoteData.loading());
40+
this._detectors.bubbleTo(this);
41+
detectorsProvider.getAll().then(
42+
(detectors) => this._detectors.setCurrent(RemoteData.success(detectors)),
43+
(error) => this._detectors.setCurrent(RemoteData.failure(error)),
44+
);
45+
46+
/**
47+
* @type {Partial<OnCallLogTemplateFormData>}
48+
*/
49+
this.formData = {
50+
shortDescription: '',
51+
shifterName: sessionService.get().name,
52+
lhcBeamMode: '',
53+
issueDescription: '',
54+
reason: '',
55+
alreadyTakenActions: '',
56+
};
57+
}
58+
59+
/**
60+
* Apply a patch on current form data
61+
*
62+
* @param {Partial<OnCallLogTemplateFormData>} patch the patch to apply
63+
* @return {void}
64+
*/
65+
patchFormData(patch) {
66+
this.formData = {
67+
...this.formData,
68+
...patch,
69+
};
70+
this.notify();
71+
}
72+
73+
/**
74+
* Return the list of names of all the detectors and subsystems
75+
*
76+
* @return {RemoteData<string[]>} the list of names
77+
*/
78+
get detectorsAndSystems() {
79+
return this._detectors.getCurrent().apply({
80+
Success: (detectors) => [
81+
...detectors.map(({ name }) => name),
82+
...ALICE_SYSTEMS,
83+
],
84+
});
85+
}
86+
87+
/**
88+
* States if the log creation form is valid
89+
*
90+
* @return {boolean} true if the form is valid
91+
*/
92+
get isValid() {
93+
return Boolean(this.formData.shortDescription.length >= 4 && this.formData.shortDescription.length <= 30
94+
&& this.formData.detectorOrSubsystem
95+
&& this.formData.severity
96+
&& this.formData.scope
97+
&& this.formData.shifterPosition
98+
&& this.formData.lhcBeamMode.length
99+
&& this.formData.issueDescription.length
100+
&& this.formData.reason.length
101+
&& this.formData.alreadyTakenActions.length);
102+
}
103+
104+
/**
105+
* Return the log title
106+
*
107+
* @return {string} the log title
108+
*/
109+
get title() {
110+
return `${this.formData.shortDescription} - Call on-call for ${this.formData.detectorOrSubsystem}`;
111+
}
112+
113+
/**
114+
* Return the log text
115+
*
116+
* @return {string} the log text
117+
*/
118+
get text() {
119+
const textParts = [`TITLE: ${this.title}`];
120+
let importancePart = `IMPORTANCE: ${this.formData.severity}`;
121+
if (this.formData.scope) {
122+
importancePart = `${importancePart} for ${this.formData.scope}`;
123+
}
124+
textParts.push(importancePart);
125+
textParts.push(`SHIFTER: ${this.formData.shifterName} - ${this.formData.shifterPosition}`);
126+
textParts.push(`LHC BEAM MODE: ${this.formData.lhcBeamMode}`);
127+
textParts.push(`DESCRIPTION:\n${this.formData.issueDescription}`);
128+
textParts.push(`REASON TO CALL THIS ON-CALL:\n${this.formData.reason}`);
129+
textParts.push(`ACTIONS ALREADY TAKEN:\n${this.formData.alreadyTakenActions}`);
130+
131+
return textParts.join('\n\n');
132+
}
133+
}
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
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+
import { LogCreationModel } from './LogCreationModel.js';
14+
import { OnCallLogTemplate } from './OnCallLogTemplate.js';
15+
16+
/**
17+
* @typedef OnCallLogTemplateFormData
18+
* @property {string} shortDescription
19+
* @property {string} detectorOrSubsystem
20+
* @property {string} severity
21+
* @property {string} scope
22+
* @property {string} shifterName
23+
* @property {string} shifterPosition
24+
* @property {string} lhcBeamMode
25+
* @property {string} issueDescription
26+
* @property {string} reason
27+
* @property {string} alreadyTakenActions
28+
*/
29+
30+
// Only one template for now
31+
/**
32+
* @typedef {OnCallLogTemplate} LogTemplate
33+
*/
34+
35+
/**
36+
* @typedef {'on-call'} logTemplateKey
37+
*/
38+
39+
/**
40+
* Return a new instance of log template for the given key
41+
*
42+
* @param {logTemplateKey} key the template key
43+
* @return {LogTemplate|null} the new log template
44+
*/
45+
const logTemplatesFactory = (key) => {
46+
const templateClass = { ['on-call']: OnCallLogTemplate }[key] ?? null;
47+
if (templateClass) {
48+
return new templateClass();
49+
}
50+
return null;
51+
};
52+
53+
/**
54+
* Log creation model based on templates
55+
*/
56+
export class TemplatedLogCreationModel extends LogCreationModel {
57+
/**
58+
* Constructor
59+
*
60+
* @param {function} [onCreation] function called when log is created, with the id of the created log
61+
* @param {LogCreationRelations} relations the relations of the log
62+
*/
63+
constructor(onCreation, relations) {
64+
super(onCreation, relations);
65+
66+
/**
67+
* @type {logTemplateKey|null}
68+
* @private
69+
*/
70+
this._templateKey = null;
71+
72+
/**
73+
* @type {LogTemplate|null}
74+
* @private
75+
*/
76+
this._templateModel = null;
77+
}
78+
79+
/**
80+
* Defines the template to use, defined by its key
81+
*
82+
* @param {logTemplateKey|null} key the key of the template to use (there may be no model for the given key)
83+
* @return {void}
84+
*/
85+
useTemplate(key) {
86+
const templateModel = logTemplatesFactory(key);
87+
if (templateModel) {
88+
templateModel.bubbleTo(this);
89+
}
90+
this._templateModel = templateModel;
91+
this._templateKey = key;
92+
this.notify();
93+
}
94+
95+
/**
96+
* Set the current template key
97+
*
98+
* @return {logTemplateKey} the current key
99+
*/
100+
get templateKey() {
101+
return this._templateKey;
102+
}
103+
104+
/**
105+
* Return the current template model
106+
*
107+
* @return {LogTemplate|null} the template model
108+
*/
109+
get templateModel() {
110+
return this._templateModel;
111+
}
112+
113+
/**
114+
* States if the log creation is valid
115+
*
116+
* @return {boolean} true if the form is valid
117+
*/
118+
get isValid() {
119+
return this._templateModel?.isValid ?? super.isValid;
120+
}
121+
122+
/*
123+
* Return log properties generated by the current template if it exists, else return the parent's property
124+
*/
125+
126+
// eslint-disable-next-line valid-jsdoc
127+
/**
128+
* @inheritDoc
129+
*/
130+
get title() {
131+
return this._templateModel?.title ?? super.title;
132+
}
133+
134+
// eslint-disable-next-line valid-jsdoc
135+
/**
136+
* @inheritDoc
137+
*/
138+
set title(title) {
139+
super.title = title;
140+
}
141+
142+
// eslint-disable-next-line valid-jsdoc
143+
/**
144+
* @inheritDoc
145+
*/
146+
get text() {
147+
return this._templateModel?.text ?? super.text;
148+
}
149+
150+
// eslint-disable-next-line valid-jsdoc
151+
/**
152+
* @inheritDoc
153+
*/
154+
set text(text) {
155+
super.text = text;
156+
}
157+
}

0 commit comments

Comments
 (0)