diff --git a/lib/public/views/Runs/Details/RunDetailsModel.js b/lib/public/views/Runs/Details/RunDetailsModel.js index e175d38d99..0efc1acc5a 100644 --- a/lib/public/views/Runs/Details/RunDetailsModel.js +++ b/lib/public/views/Runs/Details/RunDetailsModel.js @@ -53,7 +53,6 @@ export class RunDetailsModel extends Observable { this.editionTagPickerModel = new TagSelectionDropdownModel(); this._runPatch = new RunPatch(); this._runPatch.bubbleTo(this); - this._tabbedPanelModel = new RunDetailsTabbedPanelModel(); this._tabbedPanelModel.bubbleTo(this); diff --git a/lib/public/views/Runs/Details/RunPatch.js b/lib/public/views/Runs/Details/RunPatch.js index 3b000b8223..54f7e347c6 100644 --- a/lib/public/views/Runs/Details/RunPatch.js +++ b/lib/public/views/Runs/Details/RunPatch.js @@ -9,6 +9,7 @@ import { RunQualities } from '../../../domain/enums/RunQualities.js'; * @property {string} category * @property {string} title * @property {string} description + * @property {string|null} [lastEditedName] */ /** @@ -75,7 +76,8 @@ export class RunPatch extends Observable { } if (this._eorReasons.length !== this._run.eorReasons.length || this._eorReasons.some(({ id }) => id === undefined)) { - ret.eorReasons = this._eorReasons; + // Strip lastEditedName — the server's EorReasonDto only accepts id, reasonTypeId, and description + ret.eorReasons = this._eorReasons.map(({ id, reasonTypeId, description }) => ({ id, reasonTypeId, description })); } if (this._hasRunQualityChange()) { @@ -126,7 +128,12 @@ export class RunPatch extends Observable { } = this._run || {}; this._runQuality = runQuality; - this._eorReasons = eorReasons.map(({ id, description, reasonTypeId }) => ({ id, description, reasonTypeId })); + this._eorReasons = eorReasons.map(({ id, description, reasonTypeId, lastEditedName }) => ({ + id, + description, + reasonTypeId, + lastEditedName, + })); this._tags = tags.map(({ text }) => text); this.formData = { diff --git a/lib/public/views/Runs/Details/runDetailsComponent.js b/lib/public/views/Runs/Details/runDetailsComponent.js index ebb7ae4fe7..a609e0a828 100644 --- a/lib/public/views/Runs/Details/runDetailsComponent.js +++ b/lib/public/views/Runs/Details/runDetailsComponent.js @@ -40,7 +40,7 @@ import { RunDefinition } from '../../../domain/enums/RunDefinition.js'; import { formatFloat } from '../../../utilities/formatting/formatFloat.js'; import { formatEditableNumber } from '../format/formatEditableNumber.js'; import { editRunEorReasons } from '../format/editRunEorReasons.js'; -import { formatEorReason } from '../format/formatEorReason.mjs'; +import { eorReasonComponent } from '../format/eorReasonComponent.js'; import { selectionDropdown } from '../../../components/common/selection/dropdown/selectionDropdown.js'; import { formatRunCalibrationStatus } from '../format/formatRunCalibrationStatus.js'; import { BeamModes } from '../../../domain/enums/BeamModes.js'; @@ -533,7 +533,10 @@ export const runDetailsComponent = (runDetailsModel, router) => runDetailsModel. h('#eor-reasons.flex-row', [ runDetailsModel.isEditModeEnabled ? editRunEorReasons(runDetailsModel) - : h('.flex-column.g2', run.eorReasons.map((eorReason) => h('.eor-reason', formatEorReason(eorReason)))), + : h( + '.flex-column.g2.w-100', + run.eorReasons.map((eorReason) => h('.eor-reason', eorReasonComponent(eorReason))), + ), ]), ]), ]), diff --git a/lib/public/views/Runs/format/editRunEorReasons.js b/lib/public/views/Runs/format/editRunEorReasons.js index 56c69e6f04..3f6577d316 100644 --- a/lib/public/views/Runs/format/editRunEorReasons.js +++ b/lib/public/views/Runs/format/editRunEorReasons.js @@ -94,20 +94,23 @@ export const editRunEorReasons = (runDetailsModel) => { */ runDetailsModel.runPatch.eorReasons.length > 0 ? runDetailsModel.runPatch.eorReasons.map((eorReason) => { - const { reasonTypeId, description } = eorReason; + const { reasonTypeId, description, lastEditedName } = eorReason; const { category = '-', title } = eorReasonTypes.find((eorReasonType) => eorReasonType.id === reasonTypeId) || {}; const titleString = title ? ` - ${title}` : ''; const descriptionString = description ? ` - ${description}` : ''; return h( - '.flex-row.items-center', + '.flex-row.justify-between', { key: `${category} ${titleString} ${descriptionString}`, }, [ - h('label.remove-eor-reason.danger.ph1.actionable-icon', { - onclick: () => runDetailsModel.runPatch.removeEorReason(eorReason), - }, iconTrash()), - h('.w-wrapped', `${category} ${titleString} ${descriptionString}`), + h('.flex-row.items-center', [ + h('label.remove-eor-reason.danger.ph1.actionable-icon', { + onclick: () => runDetailsModel.runPatch.removeEorReason(eorReason), + }, iconTrash()), + h('.w-wrapped', `${category} ${titleString} ${descriptionString}`), + ]), + h('.w-wrapped', lastEditedName || ''), ], ); }) diff --git a/lib/public/views/Runs/format/eorReasonComponent.js b/lib/public/views/Runs/format/eorReasonComponent.js new file mode 100644 index 0000000000..def2e73354 --- /dev/null +++ b/lib/public/views/Runs/format/eorReasonComponent.js @@ -0,0 +1,36 @@ +/** + * @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'; +import { tooltip } from '../../../../components/common/popover/tooltip.js'; +import { formatEorReason } from './formatEorReason.mjs'; + +/** + * Display the given EoR reason as a vdom component with lastEditedName tooltip + * + * @param {Partial<{ + * category: string, + * title: string, + * description: string, + * lastEditedName: string, + * }>} eorReason the EoR reason to display + * @return {Component} the vdom component + */ +export const eorReasonComponent = (eorReason) => { + const { lastEditedName } = eorReason; + const reasonText = formatEorReason(eorReason); + return h('.w-100.flex-row.justify-between', [ + h('', reasonText), + lastEditedName ? tooltip(h('.w-wrapped', lastEditedName), 'Last edited by') : '', + ]); +}; diff --git a/test/public/runs/detail.test.js b/test/public/runs/detail.test.js index fa94143746..c4d13cffbd 100644 --- a/test/public/runs/detail.test.js +++ b/test/public/runs/detail.test.js @@ -208,10 +208,10 @@ module.exports = () => { expect(eorReasons).to.lengthOf(2); expect(await eorReasons[0].evaluate((element) => element.innerText)) - .to.equal('DETECTORS - TPC - Some Reason other than selected plus one'); + .to.equal('DETECTORS - TPC - Some Reason other than selected plus one\nAnonymous'); expect(await eorReasons[1].evaluate((element) => element.innerText)) - .to.equal('DETECTORS - CPV - A new EOR reason'); + .to.equal('DETECTORS - CPV - A new EOR reason\nAnonymous'); }); it('should successfully revert the update end of run reasons', async () => { @@ -234,10 +234,10 @@ module.exports = () => { expect(eorReasons).to.lengthOf(2); expect(await eorReasons[0].evaluate((element) => element.innerText)) - .to.equal('DETECTORS - TPC - Some Reason other than selected plus one'); + .to.equal('DETECTORS - TPC - Some Reason other than selected plus one\nAnonymous'); expect(await eorReasons[1].evaluate((element) => element.innerText)) - .to.equal('DETECTORS - CPV - A new EOR reason'); + .to.equal('DETECTORS - CPV - A new EOR reason\nAnonymous'); }); it('should successfully update inelasticInteractionRate values of PbPb run', async () => {