Skip to content
Open
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
57 changes: 24 additions & 33 deletions QualityControl/public/common/timestampSelectForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,38 +20,29 @@ import { prettyFormatDate } from './utils.js';
* @param {Model} model - root model of the application
* @returns {vnode} - virtual node element
*/
export default ({ object: objectModel }) => {
const { objects, selected } = objectModel;
const isObjectLoaded = selected && objects?.[selected.name]?.isSuccess();
return h(
export const timestampSelectForm = ({ versions = [], selectedId = null, onSelect }) =>
h(
'.w-100.flex-row',
isObjectLoaded &&
h('select.form-control.gray-darker.text-center', {
onchange: (e) => {
const { value } = e.target;
if (selected && value !== 'Invalid Timestamp') {
const valueJson = JSON.parse(value);
objectModel.loadObjectByName(selected.name, valueJson.validFrom, valueJson.id);
}
},
}, [
objectModel.getObjectVersions(selected.name)
.map((version) => {
const versionString = JSON.stringify(version);
const object = objects[selected.name].payload;
return h('option.text-center', {
id: versionString,
key: versionString,
value: versionString,
selected: version.createdAt === object.createdAt ? true : false,
}, [
'Created: ',
prettyFormatDate(version.createdAt),
' (id: ',
version.id,
')',
]);
}),
]),
h('select.form-control.gray-darker.text-center', {
onchange: (e) => {
const { value } = e.target;
if (value && value !== 'Invalid Timestamp') {
onSelect?.(JSON.parse(value));
}
},
}, versions.map((version) => {
const versionString = JSON.stringify(version);
return h('option.text-center', {
id: versionString,
key: versionString,
value: versionString,
selected: selectedId ? version.id === selectedId : false,
}, [
'Created: ',
prettyFormatDate(version.createdAt),
' (id: ',
version.id,
')',
]);
})),
);
};
6 changes: 3 additions & 3 deletions QualityControl/public/object/QCObject.js
Original file line number Diff line number Diff line change
Expand Up @@ -345,11 +345,11 @@ export default class QCObject extends BaseViewModel {
/**
* Indicate that the object loaded is wrong. Used after trying to print it with jsroot
* @param {string} name - name of the object
* @param {string} reason - the reason for invalidating the object
* @param {object} details - object containing detail information for invalidation
* @returns {undefined}
*/
invalidObject(name, reason) {
this.objects[name] = RemoteData.failure(reason || 'JSROOT was unable to draw this object');
invalidObject(name, details) {
this.objects[name] = RemoteData.failure(details || 'JSROOT was unable to draw this object');
this.notify();
}

Expand Down
103 changes: 66 additions & 37 deletions QualityControl/public/object/objectTreePage.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* @license
* @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.
Expand All @@ -23,7 +23,7 @@ import {
} from '/js/src/index.js';
import { spinner } from '../common/spinner.js';
import { draw } from '../common/object/draw.js';
import timestampSelectForm from './../common/timestampSelectForm.js';
import { timestampSelectForm } from './../common/timestampSelectForm.js';
import virtualTable from './virtualTable.js';
import { defaultRowAttributes, qcObjectInfoPanel } from '../common/object/objectInfoCard.js';
import { downloadButton } from '../common/downloadButton.js';
Expand Down Expand Up @@ -93,14 +93,13 @@ export default (model) => {
*/
function objectPanel(model) {
const selectedObjectName = model.object.selected.name;
if (model.object.objects && model.object.objects[selectedObjectName]) {
if (model.object.objects?.[selectedObjectName]) {
return model.object.objects[selectedObjectName].match({
NotAsked: () => null,
Loading: () =>
h('.h-100.w-100.flex-column.items-center.justify-center.f5', [spinner(3), h('', 'Loading Object')]),
Success: (data) => drawPlot(model, data),
Failure: (error) =>
h('.h-100.w-100.flex-column.items-center.justify-center.f5', [h('.f1', iconCircleX()), error]),
Failure: (invalidObjectDetails) => drawFailure(model, invalidObjectDetails),
});
}
return null;
Expand All @@ -113,46 +112,76 @@ function objectPanel(model) {
* @returns {vnode} - virtual node element
*/
const drawPlot = (model, object) => {
const { name, qcObject, validFrom, id } = object;
const { root } = qcObject;
const href = validFrom ?
`?page=objectView&objectName=${name}&ts=${validFrom}&id=${id}`
: `?page=objectView&objectName=${name}`;
return h('', { style: 'height:100%; display: flex; flex-direction: column' }, [
h('.item-action-row.flex-row.g1.p1', [
downloadRootImageButton(`${name}.png`, root, ['stat']),
downloadButton({
href: model.objectViewModel.getDownloadQcdbObjectUrl(id),
title: 'Download root object',
}),
h(
'a.btn#fullscreen-button',
{
title: 'Open object plot in full screen',
href,
onclick: (e) => model.router.handleLinkEvent(e),
},
iconResizeBoth(),
),
h(
'a.btn#close-button',
{
title: 'Close the object plot',
onclick: () => model.object.select(),
},
iconCircleX(),
),
]),
const { name, qcObject, validFrom, id, versions } = object;
return h('.h-100.flex-column', [
actionButtonsRow(model, name, qcObject, validFrom, id),
h('', { style: 'height:77%;' }, draw(model.object.objects[name], { }, ['stat'], (error) => {
model.object.invalidObject(name, error.message);
const invalidObjectDetails = { name, message: error.message, validFrom, id, versions };
model.object.invalidObject(name, invalidObjectDetails);
})),
h('.scroll-y', {}, [
h('.w-100.flex-row', { style: 'justify-content: center' }, h('.w-80', timestampSelectForm(model))),
h('.w-100.flex-row.justify-center', h('.w-80', timestampSelectForm({
versions: versions ?? [],
selectedId: id ?? null,
onSelect: (version) => model.object.loadObjectByName(name, version.validFrom, version.id),
}))),
qcObjectInfoPanel(object, { 'font-size': '.875rem;' }, defaultRowAttributes(model.notification)),
]),
]);
};

/**
* Draw the failure message when object cannot be drawn
* @param {Model} model - root model of the application
* @param {object} invalidObjectDetails - details about the invalid object
* @returns {vnode} - virtual node element
*/
const drawFailure = (model, invalidObjectDetails) => {
const { name, message, validFrom, id, versions } = invalidObjectDetails ?? {};
return h('.h-100.flex-column', [
actionButtonsRow(model, name, null, validFrom, id),
h(
'.h-100.flex-column.items-center.justify-center.text-center.f5',
[h('.f1', iconCircleX()), message],
),
h('.w-100.flex-row.justify-center.pv2', h('.w-80', timestampSelectForm({
versions: versions ?? [],
selectedId: id ?? null,
onSelect: (version) => model.object.loadObjectByName(name, version.validFrom, version.id),
}))),
]);
};

const actionButtonsRow = (model, objectName, root, validFrom, id) => {
const href = validFrom
? `?page=objectView&objectName=${objectName}&ts=${validFrom}&id=${id}`
: `?page=objectView&objectName=${objectName}`;
return h('.item-action-row.flex-row.g1.p1', [
root && downloadRootImageButton(`${objectName}.png`, root, ['stat']),
downloadButton({
href: model.objectViewModel.getDownloadQcdbObjectUrl(id),
title: 'Download root object',
}),
h(
'a.btn#fullscreen-button',
{
title: 'Open object plot in full screen',
href,
onclick: (e) => model.router.handleLinkEvent(e),
},
iconResizeBoth(),
),
h(
'a.btn#close-button',
{
title: 'Close the object plot',
onclick: () => model.object.select(),
},
iconCircleX(),
),
]);
};

/**
* Shows status of current tree with its options (online, loaded, how many)
* @param {Model} model - root model of the application
Expand Down
Loading