-
Notifications
You must be signed in to change notification settings - Fork 14
Expand file tree
/
Copy pathobjectInfoCard.js
More file actions
159 lines (142 loc) · 5.46 KB
/
objectInfoCard.js
File metadata and controls
159 lines (142 loc) · 5.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/**
* @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.p
*/
import { h, isContextSecure } from '/js/src/index.js';
import { iconExternalLink } from '/js/src/icons.js';
import { camelToTitleCase, copyToClipboard, prettyFormatDate } from './../utils.js';
import { getBkpRunDetailsUrl } from '../../common/utils.js';
const SPECIFIC_KEY_LABELS = {
id: 'ID (etag)',
};
const DATE_FIELDS = ['validFrom', 'validUntil', 'createdAt', 'lastModified'];
const TO_REMOVE_FIELDS = ['etag', 'qcObject', 'versions', 'name', 'location'];
const HIGHLIGHTED_FIELDS = ['runNumber', 'runType', 'path', 'qcVersion'];
const KEY_TO_RENDER_FIRST = 'path';
/**
* Builds a panel with information of the object; Fields are parsed according to their category
* @param {QCObjectDTO} qcObject - QC object with its associated details
* @param {object} style - properties of the vnode
* @param {function(Notification): function(string, string): object} rowAttributes -
* An optional curried function that returns the VNode attribute builder.
* Use {@link defaultRowAttributes} exported from this module, supplying the Notification API.
* @returns {vnode} - panel with information about the object
* @example
* ```
* qcObjectInfoPanel(qcObject, {}, defaultRowAttributes(model.notification))
* ```
*/
export const qcObjectInfoPanel = (qcObject, style = {}, rowAttributes = () => undefined) =>
h('.flex-column.scroll-y#qcObjectInfoPanel', { style }, [
[
KEY_TO_RENDER_FIRST,
...Object.keys(qcObject)
.filter((key) =>
key !== KEY_TO_RENDER_FIRST && !TO_REMOVE_FIELDS.includes(key)),
]
.map((key) => infoRow(key, qcObject[key], rowAttributes)),
]);
/**
* Builds a raw with the key and value information parsed based on their type
* @param {string} key - key of the object info
* @param {string|number|object|undefined} value - value of the object info
* @param {function(key, value)} infoRowAttributes - function that return given attributes for the row
* @returns {vnode} - row with object information key and value
*/
const infoRow = (key, value, infoRowAttributes) => {
const highlightedClasses = HIGHLIGHTED_FIELDS.includes(key) ? '.highlighted' : '';
const formattedValue = infoPretty(key, value);
const formattedKey = getUILabel(key);
const hasValue = value != null && value !== '' && (!Array.isArray(value) || value.length !== 0);
const bkpRunDetailsUrl = key === 'runNumber' ? getBkpRunDetailsUrl(value) : null;
return h(`.flex-row.g2.info-row${highlightedClasses}`, [
h('b.w-25.w-wrapped', formattedKey),
h('.flex-row.w-75', [
h(
'.cursor-pointer.flex-row',
hasValue && infoRowAttributes(formattedKey, formattedValue),
formattedValue,
),
bkpRunDetailsUrl && hasValue
? h('a.ph2.text-right.actionable-icon', {
id: 'openRunInBookkeeping',
title: 'Open run in Bookkeeping',
href: bkpRunDetailsUrl,
target: '_blank',
}, iconExternalLink())
: '',
]),
]);
};
/**
* Retrieves the final UI-friendly label for given data key
* * Priority:
* 1. Manual override using `SPECIFIC_KEY_LABELS`
* 2. Use `defaultKeyTransform` to generate a label
* @param {string} key - key of the object info
* @returns {string} - formatted label for the given key
*/
const getUILabel = (key) => {
if (Object.hasOwn(SPECIFIC_KEY_LABELS, key)) {
return SPECIFIC_KEY_LABELS[key];
}
return camelToTitleCase(key);
};
/**
* Parses the value and returns it in a specific format based on type
* safely handeling nulls and objects.
* @param {string} key - key of the object info
* @param {string|number|object|undefined} value - value of the object info
* @returns {string} - string representation of the value passed
*/
const infoPretty = (key, value) => {
if (value == null) {
return '-';
}
if (DATE_FIELDS.includes(key)) {
return prettyFormatDate(value);
}
if (Array.isArray(value)) {
return value.length > 0
? value.join(', ')
: '-';
}
if (typeof value === 'object') {
return JSON.stringify(value);
}
return String(value);
};
/**
* Default function to configure the info row vnode attributes
* @typedef {import('/js/src/index.js').Notification} Notification
* @param {Notification} notification - Notification API from WebUI framework
* @returns {function(string, string): object} object containing the constructed vnode attributes
*/
export const defaultRowAttributes = (notification) =>
(key, value) => ({
onclick: async (e) => {
// to allowing the default behaviour for clicking multiple times
const clickCount = e.detail;
if (clickCount === 1) {
if (!isContextSecure()) {
return;
}
try {
await copyToClipboard(value);
notification.show('Value has been successfully copied to clipboard', 'success', 1500);
} catch (error) {
notification.show(`Failed to copy to clipboard: ${error.message}`, 'danger', 1500);
}
}
},
title: `Copy ${key}`,
});