@perses-dev/plugin-system 0.53.0-rc.3 → 0.53.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/components/Variables/VariableEditorForm/VariableEditorForm.js +50 -22
- package/dist/cjs/utils/csv-export.js +248 -0
- package/dist/cjs/utils/index.js +1 -0
- package/dist/components/Variables/VariableEditorForm/VariableEditorForm.d.ts.map +1 -1
- package/dist/components/Variables/VariableEditorForm/VariableEditorForm.js +50 -22
- package/dist/components/Variables/VariableEditorForm/VariableEditorForm.js.map +1 -1
- package/dist/utils/csv-export.d.ts +39 -0
- package/dist/utils/csv-export.d.ts.map +1 -0
- package/dist/utils/csv-export.js +214 -0
- package/dist/utils/csv-export.js.map +1 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1 -0
- package/dist/utils/index.js.map +1 -1
- package/package.json +3 -3
|
@@ -137,6 +137,10 @@ function ListVariableEditorForm({ action, control }) {
|
|
|
137
137
|
control: control,
|
|
138
138
|
name: 'spec.allowAllValue'
|
|
139
139
|
});
|
|
140
|
+
const _customAllValue = (0, _reacthookform.useWatch)({
|
|
141
|
+
control: control,
|
|
142
|
+
name: 'spec.customAllValue'
|
|
143
|
+
});
|
|
140
144
|
const sortMethod = (0, _reacthookform.useWatch)({
|
|
141
145
|
control: control,
|
|
142
146
|
name: 'spec.sort'
|
|
@@ -333,30 +337,54 @@ function ListVariableEditorForm({ action, control }) {
|
|
|
333
337
|
variant: "caption",
|
|
334
338
|
children: "Enables an option to include all variable values"
|
|
335
339
|
}),
|
|
336
|
-
_allowAllValue && /*#__PURE__*/ (0, _jsxruntime.
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
onChange: (event)=>{
|
|
353
|
-
if (event.target.value === '') {
|
|
354
|
-
field.onChange(undefined);
|
|
355
|
-
} else {
|
|
356
|
-
field.onChange(event);
|
|
340
|
+
_allowAllValue && /*#__PURE__*/ (0, _jsxruntime.jsxs)(_material.Stack, {
|
|
341
|
+
spacing: 1,
|
|
342
|
+
children: [
|
|
343
|
+
/*#__PURE__*/ (0, _jsxruntime.jsx)(_material.FormControlLabel, {
|
|
344
|
+
label: "Use Custom All Value",
|
|
345
|
+
control: /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Switch, {
|
|
346
|
+
checked: _customAllValue !== undefined,
|
|
347
|
+
readOnly: action === 'read',
|
|
348
|
+
onChange: (event)=>{
|
|
349
|
+
if (action === 'read') return;
|
|
350
|
+
const isEnabled = event.target.checked;
|
|
351
|
+
if (isEnabled) {
|
|
352
|
+
form.setValue('spec.customAllValue', '');
|
|
353
|
+
} else {
|
|
354
|
+
form.setValue('spec.customAllValue', undefined);
|
|
355
|
+
}
|
|
357
356
|
}
|
|
358
|
-
}
|
|
357
|
+
})
|
|
358
|
+
}),
|
|
359
|
+
/*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Typography, {
|
|
360
|
+
variant: "caption",
|
|
361
|
+
sx: {
|
|
362
|
+
mt: -0.5
|
|
363
|
+
},
|
|
364
|
+
children: 'Enable to set a custom value when "All" is selected'
|
|
365
|
+
}),
|
|
366
|
+
_customAllValue !== undefined && /*#__PURE__*/ (0, _jsxruntime.jsx)(_reacthookform.Controller, {
|
|
367
|
+
control: control,
|
|
368
|
+
name: "spec.customAllValue",
|
|
369
|
+
render: ({ field, fieldState })=>/*#__PURE__*/ (0, _jsxruntime.jsx)(_material.TextField, {
|
|
370
|
+
...field,
|
|
371
|
+
fullWidth: true,
|
|
372
|
+
label: "Custom All Value",
|
|
373
|
+
InputLabelProps: {
|
|
374
|
+
shrink: action === 'read' ? true : undefined
|
|
375
|
+
},
|
|
376
|
+
InputProps: {
|
|
377
|
+
readOnly: action === 'read'
|
|
378
|
+
},
|
|
379
|
+
error: !!fieldState.error,
|
|
380
|
+
helperText: fieldState.error?.message,
|
|
381
|
+
value: field.value ?? '',
|
|
382
|
+
onChange: (event)=>{
|
|
383
|
+
field.onChange(event.target.value || '');
|
|
384
|
+
}
|
|
385
|
+
})
|
|
359
386
|
})
|
|
387
|
+
]
|
|
360
388
|
})
|
|
361
389
|
]
|
|
362
390
|
})
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
// Copyright The Perses Authors
|
|
2
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
3
|
+
// you may not use this file except in compliance with the License.
|
|
4
|
+
// You may obtain a copy of the License at
|
|
5
|
+
//
|
|
6
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
+
//
|
|
8
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
9
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
10
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
|
+
// See the License for the specific language governing permissions and
|
|
12
|
+
// limitations under the License.
|
|
13
|
+
"use strict";
|
|
14
|
+
Object.defineProperty(exports, "__esModule", {
|
|
15
|
+
value: true
|
|
16
|
+
});
|
|
17
|
+
function _export(target, all) {
|
|
18
|
+
for(var name in all)Object.defineProperty(target, name, {
|
|
19
|
+
enumerable: true,
|
|
20
|
+
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
_export(exports, {
|
|
24
|
+
get escapeCsvValue () {
|
|
25
|
+
return escapeCsvValue;
|
|
26
|
+
},
|
|
27
|
+
get exportDataAsCSV () {
|
|
28
|
+
return exportDataAsCSV;
|
|
29
|
+
},
|
|
30
|
+
get extractExportableData () {
|
|
31
|
+
return extractExportableData;
|
|
32
|
+
},
|
|
33
|
+
get formatLegendName () {
|
|
34
|
+
return formatLegendName;
|
|
35
|
+
},
|
|
36
|
+
get formatTimestampISO () {
|
|
37
|
+
return formatTimestampISO;
|
|
38
|
+
},
|
|
39
|
+
get isExportableData () {
|
|
40
|
+
return isExportableData;
|
|
41
|
+
},
|
|
42
|
+
get sanitizeColumnName () {
|
|
43
|
+
return sanitizeColumnName;
|
|
44
|
+
},
|
|
45
|
+
get sanitizeFilename () {
|
|
46
|
+
return sanitizeFilename;
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
const isExportableData = (data)=>{
|
|
50
|
+
return !!(data && typeof data === 'object' && 'series' in data && Array.isArray(data.series) && data.series.length > 0);
|
|
51
|
+
};
|
|
52
|
+
const extractExportableData = (queryResults)=>{
|
|
53
|
+
if (!queryResults || queryResults.length === 0) return undefined;
|
|
54
|
+
const allSeries = [];
|
|
55
|
+
let timeRange = undefined;
|
|
56
|
+
let stepMs = undefined;
|
|
57
|
+
let metadata = undefined;
|
|
58
|
+
queryResults.forEach((query)=>{
|
|
59
|
+
if (query?.data && typeof query.data === 'object' && 'series' in query.data) {
|
|
60
|
+
const data = query.data;
|
|
61
|
+
if (data.series && Array.isArray(data.series) && data.series.length > 0) {
|
|
62
|
+
allSeries.push(...data.series);
|
|
63
|
+
if (!timeRange && data.timeRange) {
|
|
64
|
+
timeRange = data.timeRange;
|
|
65
|
+
}
|
|
66
|
+
if (!stepMs && data.stepMs) {
|
|
67
|
+
stepMs = data.stepMs;
|
|
68
|
+
}
|
|
69
|
+
if (!metadata && data.metadata) {
|
|
70
|
+
metadata = data.metadata;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
if (allSeries.length > 0) {
|
|
76
|
+
return {
|
|
77
|
+
series: allSeries,
|
|
78
|
+
timeRange,
|
|
79
|
+
stepMs,
|
|
80
|
+
metadata
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
return undefined;
|
|
84
|
+
};
|
|
85
|
+
const formatLegendName = (series, seriesIndex)=>{
|
|
86
|
+
const seriesAny = series;
|
|
87
|
+
let legendName = series.formattedName || series.name;
|
|
88
|
+
if (!legendName || legendName === `Series ${seriesIndex + 1}`) {
|
|
89
|
+
legendName = seriesAny.legendName || seriesAny.displayName || seriesAny.legend || series.name || '';
|
|
90
|
+
}
|
|
91
|
+
if ((!legendName || legendName === series.name) && series.labels) {
|
|
92
|
+
const labels = series.labels;
|
|
93
|
+
const displayLabels = {
|
|
94
|
+
...labels
|
|
95
|
+
};
|
|
96
|
+
const metricName = displayLabels.__name__;
|
|
97
|
+
delete displayLabels.__name__;
|
|
98
|
+
const labelPairs = Object.entries(displayLabels).filter(([value])=>value !== undefined && value !== null && value !== '').map(([key, value])=>`${key}="${value}"`).join(', ');
|
|
99
|
+
if (metricName && labelPairs) {
|
|
100
|
+
legendName = `${metricName}{${labelPairs}}`;
|
|
101
|
+
} else if (metricName) {
|
|
102
|
+
legendName = metricName;
|
|
103
|
+
} else if (labelPairs) {
|
|
104
|
+
legendName = `{${labelPairs}}`;
|
|
105
|
+
} else {
|
|
106
|
+
legendName = labels.job || labels.instance || labels.metric || `Series ${seriesIndex + 1}`;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
if (!legendName || legendName.trim() === '') {
|
|
110
|
+
legendName = `Series ${seriesIndex + 1}`;
|
|
111
|
+
}
|
|
112
|
+
return legendName;
|
|
113
|
+
};
|
|
114
|
+
const sanitizeColumnName = (name)=>{
|
|
115
|
+
return name.replace(/[,"\n\r]/g, '_').replace(/\s+/g, '_').replace(/_+/g, '_').replace(/^_|_$/g, '').substring(0, 255);
|
|
116
|
+
};
|
|
117
|
+
const sanitizeFilename = (filename)=>{
|
|
118
|
+
return filename.replace(/[<>:"/\\|?*]/g, ' ').trim().split(/\s+/).filter((word)=>word.length > 0).map((word, index)=>{
|
|
119
|
+
if (index === 0) {
|
|
120
|
+
return word.toLowerCase();
|
|
121
|
+
}
|
|
122
|
+
return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
|
|
123
|
+
}).join('');
|
|
124
|
+
};
|
|
125
|
+
const formatTimestampISO = (timestamp)=>{
|
|
126
|
+
let timestampMs;
|
|
127
|
+
if (typeof timestamp === 'string') {
|
|
128
|
+
const date = new Date(timestamp);
|
|
129
|
+
if (isNaN(date.getTime())) {
|
|
130
|
+
return timestamp;
|
|
131
|
+
}
|
|
132
|
+
timestampMs = date.getTime();
|
|
133
|
+
} else {
|
|
134
|
+
timestampMs = timestamp > 1e10 ? timestamp : timestamp * 1000;
|
|
135
|
+
}
|
|
136
|
+
const date = new Date(timestampMs);
|
|
137
|
+
if (isNaN(date.getTime())) {
|
|
138
|
+
return new Date(timestampMs).toISOString();
|
|
139
|
+
}
|
|
140
|
+
return date.toISOString();
|
|
141
|
+
};
|
|
142
|
+
const escapeCsvValue = (value)=>{
|
|
143
|
+
if (value === null || value === undefined) {
|
|
144
|
+
return '';
|
|
145
|
+
}
|
|
146
|
+
const stringValue = String(value);
|
|
147
|
+
if (stringValue.includes(',') || stringValue.includes('"') || stringValue.includes('\n') || stringValue.includes('\r')) {
|
|
148
|
+
return `"${stringValue.replace(/"/g, '""')}"`;
|
|
149
|
+
}
|
|
150
|
+
return stringValue;
|
|
151
|
+
};
|
|
152
|
+
const exportDataAsCSV = ({ data })=>{
|
|
153
|
+
if (!isExportableData(data)) {
|
|
154
|
+
console.warn('No valid data found to export to CSV.');
|
|
155
|
+
return new Blob([
|
|
156
|
+
''
|
|
157
|
+
], {
|
|
158
|
+
type: 'text/csv;charset=utf-8'
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
let csvString = '';
|
|
162
|
+
const result = {};
|
|
163
|
+
const seriesInfo = [];
|
|
164
|
+
let validSeriesCount = 0;
|
|
165
|
+
for(let i = 0; i < data.series.length; i++){
|
|
166
|
+
const series = data.series[i];
|
|
167
|
+
if (!series) {
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
if (!Array.isArray(series.values) || series.values.length === 0) {
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
const legendName = formatLegendName(series, i);
|
|
174
|
+
const columnName = sanitizeColumnName(legendName);
|
|
175
|
+
const currentSeriesInfo = {
|
|
176
|
+
legendName,
|
|
177
|
+
columnName: columnName || `Series_${i + 1}`,
|
|
178
|
+
originalName: series.name || ''
|
|
179
|
+
};
|
|
180
|
+
seriesInfo.push(currentSeriesInfo);
|
|
181
|
+
validSeriesCount++;
|
|
182
|
+
for(let j = 0; j < series.values.length; j++){
|
|
183
|
+
const entry = series.values[j];
|
|
184
|
+
let timestamp;
|
|
185
|
+
let value;
|
|
186
|
+
if (Array.isArray(entry) && entry.length >= 2) {
|
|
187
|
+
timestamp = entry[0];
|
|
188
|
+
value = entry[1];
|
|
189
|
+
} else if (typeof entry === 'object' && entry !== null && 'timestamp' in entry && 'value' in entry) {
|
|
190
|
+
const dataPoint = entry;
|
|
191
|
+
timestamp = dataPoint.timestamp;
|
|
192
|
+
value = dataPoint.value;
|
|
193
|
+
} else {
|
|
194
|
+
continue;
|
|
195
|
+
}
|
|
196
|
+
if (value === null || value === undefined) {
|
|
197
|
+
continue;
|
|
198
|
+
}
|
|
199
|
+
const dateTime = formatTimestampISO(timestamp);
|
|
200
|
+
if (!result[dateTime]) {
|
|
201
|
+
result[dateTime] = {};
|
|
202
|
+
}
|
|
203
|
+
/* linter complains, so assert result[dateTime]
|
|
204
|
+
It has already been checked by the if statement
|
|
205
|
+
*/ result[dateTime][currentSeriesInfo.columnName] = value;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
if (validSeriesCount === 0 || seriesInfo.length === 0) {
|
|
209
|
+
console.warn('No valid data found to export to CSV.');
|
|
210
|
+
return new Blob([
|
|
211
|
+
''
|
|
212
|
+
], {
|
|
213
|
+
type: 'text/csv;charset=utf-8'
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
const timestampCount = Object.keys(result).length;
|
|
217
|
+
if (timestampCount === 0) {
|
|
218
|
+
console.warn('No valid timestamp data found to export to CSV.');
|
|
219
|
+
return new Blob([
|
|
220
|
+
''
|
|
221
|
+
], {
|
|
222
|
+
type: 'text/csv;charset=utf-8'
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
const columnNames = seriesInfo.map((info)=>info.columnName);
|
|
226
|
+
csvString += `DateTime,${columnNames.join(',')}\n`;
|
|
227
|
+
const sortedDateTimes = Object.keys(result).sort((a, b)=>{
|
|
228
|
+
const dateA = new Date(a).getTime();
|
|
229
|
+
const dateB = new Date(b).getTime();
|
|
230
|
+
return dateA - dateB;
|
|
231
|
+
});
|
|
232
|
+
for (const dateTime of sortedDateTimes){
|
|
233
|
+
const rowData = result[dateTime];
|
|
234
|
+
const values = [];
|
|
235
|
+
if (rowData) {
|
|
236
|
+
for (const columnName of columnNames){
|
|
237
|
+
const value = rowData[columnName];
|
|
238
|
+
values.push(escapeCsvValue(value));
|
|
239
|
+
}
|
|
240
|
+
csvString += `${escapeCsvValue(dateTime)},${values.join(',')}\n`;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
return new Blob([
|
|
244
|
+
csvString
|
|
245
|
+
], {
|
|
246
|
+
type: 'text/csv;charset=utf-8'
|
|
247
|
+
});
|
|
248
|
+
};
|
package/dist/cjs/utils/index.js
CHANGED
|
@@ -17,6 +17,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
17
17
|
_export_star(require("./action"), exports);
|
|
18
18
|
_export_star(require("./event"), exports);
|
|
19
19
|
_export_star(require("./variables"), exports);
|
|
20
|
+
_export_star(require("./csv-export"), exports);
|
|
20
21
|
function _export_star(from, to) {
|
|
21
22
|
Object.keys(from).forEach(function(k) {
|
|
22
23
|
if (k !== "default" && !Object.prototype.hasOwnProperty.call(to, k)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VariableEditorForm.d.ts","sourceRoot":"","sources":["../../../../src/components/Variables/VariableEditorForm/VariableEditorForm.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAE,qBAAqB,EAAE,YAAY,EAAyB,MAAM,OAAO,CAAC;AAEnF,OAAO,EAAE,kBAAkB,EAA0B,MAAM,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"VariableEditorForm.d.ts","sourceRoot":"","sources":["../../../../src/components/Variables/VariableEditorForm/VariableEditorForm.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAE,qBAAqB,EAAE,YAAY,EAAyB,MAAM,OAAO,CAAC;AAEnF,OAAO,EAAE,kBAAkB,EAA0B,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAkWtF,UAAU,uBAAuB;IAC/B,yBAAyB,EAAE,kBAAkB,CAAC;IAC9C,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,MAAM,EAAE,CAAC,GAAG,EAAE,kBAAkB,KAAK,IAAI,CAAC;IAC1C,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,CAAC,EAAE,qBAAqB,CAAC;CAClC;AAED,wBAAgB,kBAAkB,CAAC,EACjC,yBAAyB,EACzB,MAAM,EACN,OAAO,EACP,UAAU,EACV,cAAc,EACd,MAAM,EACN,OAAO,EACP,QAAQ,GACT,EAAE,uBAAuB,GAAG,YAAY,CAoMxC"}
|
|
@@ -127,6 +127,10 @@ function ListVariableEditorForm({ action, control }) {
|
|
|
127
127
|
control: control,
|
|
128
128
|
name: 'spec.allowAllValue'
|
|
129
129
|
});
|
|
130
|
+
const _customAllValue = useWatch({
|
|
131
|
+
control: control,
|
|
132
|
+
name: 'spec.customAllValue'
|
|
133
|
+
});
|
|
130
134
|
const sortMethod = useWatch({
|
|
131
135
|
control: control,
|
|
132
136
|
name: 'spec.sort'
|
|
@@ -323,30 +327,54 @@ function ListVariableEditorForm({ action, control }) {
|
|
|
323
327
|
variant: "caption",
|
|
324
328
|
children: "Enables an option to include all variable values"
|
|
325
329
|
}),
|
|
326
|
-
_allowAllValue && /*#__PURE__*/
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
onChange: (event)=>{
|
|
343
|
-
if (event.target.value === '') {
|
|
344
|
-
field.onChange(undefined);
|
|
345
|
-
} else {
|
|
346
|
-
field.onChange(event);
|
|
330
|
+
_allowAllValue && /*#__PURE__*/ _jsxs(Stack, {
|
|
331
|
+
spacing: 1,
|
|
332
|
+
children: [
|
|
333
|
+
/*#__PURE__*/ _jsx(FormControlLabel, {
|
|
334
|
+
label: "Use Custom All Value",
|
|
335
|
+
control: /*#__PURE__*/ _jsx(Switch, {
|
|
336
|
+
checked: _customAllValue !== undefined,
|
|
337
|
+
readOnly: action === 'read',
|
|
338
|
+
onChange: (event)=>{
|
|
339
|
+
if (action === 'read') return;
|
|
340
|
+
const isEnabled = event.target.checked;
|
|
341
|
+
if (isEnabled) {
|
|
342
|
+
form.setValue('spec.customAllValue', '');
|
|
343
|
+
} else {
|
|
344
|
+
form.setValue('spec.customAllValue', undefined);
|
|
345
|
+
}
|
|
347
346
|
}
|
|
348
|
-
}
|
|
347
|
+
})
|
|
348
|
+
}),
|
|
349
|
+
/*#__PURE__*/ _jsx(Typography, {
|
|
350
|
+
variant: "caption",
|
|
351
|
+
sx: {
|
|
352
|
+
mt: -0.5
|
|
353
|
+
},
|
|
354
|
+
children: 'Enable to set a custom value when "All" is selected'
|
|
355
|
+
}),
|
|
356
|
+
_customAllValue !== undefined && /*#__PURE__*/ _jsx(Controller, {
|
|
357
|
+
control: control,
|
|
358
|
+
name: "spec.customAllValue",
|
|
359
|
+
render: ({ field, fieldState })=>/*#__PURE__*/ _jsx(TextField, {
|
|
360
|
+
...field,
|
|
361
|
+
fullWidth: true,
|
|
362
|
+
label: "Custom All Value",
|
|
363
|
+
InputLabelProps: {
|
|
364
|
+
shrink: action === 'read' ? true : undefined
|
|
365
|
+
},
|
|
366
|
+
InputProps: {
|
|
367
|
+
readOnly: action === 'read'
|
|
368
|
+
},
|
|
369
|
+
error: !!fieldState.error,
|
|
370
|
+
helperText: fieldState.error?.message,
|
|
371
|
+
value: field.value ?? '',
|
|
372
|
+
onChange: (event)=>{
|
|
373
|
+
field.onChange(event.target.value || '');
|
|
374
|
+
}
|
|
375
|
+
})
|
|
349
376
|
})
|
|
377
|
+
]
|
|
350
378
|
})
|
|
351
379
|
]
|
|
352
380
|
})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/Variables/VariableEditorForm/VariableEditorForm.tsx"],"sourcesContent":["// Copyright The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { DispatchWithoutAction, ReactElement, useCallback, useState } from 'react';\nimport { Box, Typography, Switch, TextField, Grid, FormControlLabel, MenuItem, Stack, Divider } from '@mui/material';\nimport { VariableDefinition, ListVariableDefinition, Action } from '@perses-dev/core';\nimport { DiscardChangesConfirmationDialog, ErrorAlert, ErrorBoundary, FormActions } from '@perses-dev/components';\nimport { Control, Controller, FormProvider, SubmitHandler, useForm, useFormContext, useWatch } from 'react-hook-form';\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { useQueryClient } from '@tanstack/react-query';\nimport { getSubmitText, getTitleAction } from '../../../utils';\nimport { PluginEditor } from '../../PluginEditor';\nimport { useValidationSchemas } from '../../../context';\nimport { VARIABLE_TYPES } from '../variable-model';\nimport { VariableListPreview, VariablePreview } from './VariablePreview';\nimport { SORT_METHODS, SortMethodName } from './variable-editor-form-model';\n\nfunction FallbackPreview(): ReactElement {\n return <div>Error previewing values</div>;\n}\n\ninterface KindVariableEditorFormProps {\n action: Action;\n control: Control<VariableDefinition>;\n}\n\nfunction TextVariableEditorForm({ action, control }: KindVariableEditorFormProps): ReactElement {\n return (\n <>\n <Typography py={1} variant=\"subtitle1\">\n Text Options\n </Typography>\n <Stack spacing={2}>\n <Controller\n control={control}\n name=\"spec.value\"\n render={({ field, fieldState }) => (\n <>\n <Box>\n <VariablePreview values={[field.value]} />\n </Box>\n <TextField\n {...field}\n label=\"Value\"\n InputLabelProps={{ shrink: action === 'read' ? true : undefined }}\n InputProps={{\n readOnly: action === 'read',\n }}\n error={!!fieldState.error}\n helperText={fieldState.error?.message}\n value={field.value ?? ''}\n onChange={(event) => {\n field.onChange(event);\n }}\n />\n </>\n )}\n />\n <Controller\n control={control}\n name=\"spec.constant\"\n render={({ field }) => (\n <FormControlLabel\n label=\"Constant\"\n control={\n <Switch\n {...field}\n checked={!!field.value}\n readOnly={action === 'read'}\n value={field.value ?? false}\n onChange={(event) => {\n if (action === 'read') return; // ReadOnly prop is not blocking user interaction...\n field.onChange(event);\n }}\n />\n }\n />\n )}\n />\n </Stack>\n </>\n );\n}\n\nfunction ListVariableEditorForm({ action, control }: KindVariableEditorFormProps): ReactElement {\n const form = useFormContext<VariableDefinition>();\n const queryClient = useQueryClient();\n\n const values = form.getValues() as ListVariableDefinition;\n /* We use `previewDefinition` to explicitly update the spec\n * that will be used for preview when running query. The reason why we do this is to avoid\n * having to re-fetch the values when the user is still editing the spec.\n * Using structuredClone to not have reference issues with nested objects.\n */\n const [previewDefinition, setPreviewDefinition] = useState(structuredClone(values));\n\n const handleRunQuery = useCallback(async () => {\n if (JSON.stringify(previewDefinition) === JSON.stringify(values)) {\n await queryClient.invalidateQueries({ queryKey: ['variable', previewDefinition] });\n } else {\n setPreviewDefinition(structuredClone(values));\n }\n }, [previewDefinition, queryClient, values]);\n\n const plugin = useWatch<VariableDefinition, 'spec.plugin'>({ control, name: 'spec.plugin' });\n const kind = plugin?.kind;\n const pluginSpec = plugin?.spec;\n\n const _allowAllValue = useWatch<VariableDefinition, 'spec.allowAllValue'>({\n control: control,\n name: 'spec.allowAllValue',\n });\n\n const sortMethod = useWatch<VariableDefinition, 'spec.sort'>({\n control: control,\n name: 'spec.sort',\n }) as SortMethodName;\n\n // When variable kind is selected we need to provide default values\n // TODO: check if react-hook-form has a better way to do this\n if (values.spec.allowAllValue === undefined) {\n form.setValue('spec.allowAllValue', false);\n }\n\n if (values.spec.allowMultiple === undefined) {\n form.setValue('spec.allowMultiple', false);\n }\n\n if (!values.spec.plugin) {\n form.setValue('spec.plugin', { kind: 'StaticListVariable', spec: {} });\n }\n\n if (!values.spec.sort) {\n form.setValue('spec.sort', 'none');\n }\n\n return (\n <>\n <Typography py={1} variant=\"subtitle1\">\n List Options\n </Typography>\n <Stack spacing={2} mb={2}>\n <Box>\n <ErrorBoundary FallbackComponent={FallbackPreview} resetKeys={[previewDefinition]}>\n <VariableListPreview sortMethod={sortMethod} definition={previewDefinition} />\n </ErrorBoundary>\n </Box>\n <Stack>\n <ErrorBoundary FallbackComponent={ErrorAlert}>\n <Controller\n control={control}\n name=\"spec.plugin\"\n render={({ field }) => {\n return (\n <PluginEditor\n withRunQueryButton\n width=\"100%\"\n pluginTypes={['Variable']}\n pluginKindLabel=\"Source\"\n value={{\n selection: {\n type: 'Variable',\n kind: kind ?? 'StaticListVariable',\n },\n spec: pluginSpec ?? {},\n }}\n isReadonly={action === 'read'}\n onChange={(v) => {\n field.onChange({ kind: v.selection.kind, spec: v.spec });\n }}\n onRunQuery={handleRunQuery}\n />\n );\n }}\n />\n </ErrorBoundary>\n </Stack>\n\n <Stack>\n <Controller\n control={control}\n name=\"spec.capturingRegexp\"\n render={({ field, fieldState }) => (\n <TextField\n {...field}\n label=\"Capturing Regexp Filter\"\n InputLabelProps={{ shrink: action === 'read' ? true : undefined }}\n InputProps={{\n readOnly: action === 'read',\n }}\n error={!!fieldState.error}\n value={field.value ?? ''}\n onChange={(event) => {\n if (event.target.value === '') {\n field.onChange(undefined);\n } else {\n field.onChange(event);\n }\n }}\n helperText={\n fieldState.error?.message\n ? fieldState.error.message\n : 'Optional, if you want to filter on captured result.'\n }\n />\n )}\n />\n </Stack>\n\n <Stack>\n <Controller\n control={control}\n name=\"spec.sort\"\n render={({ field, fieldState }) => (\n <TextField\n select\n {...field}\n fullWidth\n label=\"Sort\"\n InputLabelProps={{ shrink: action === 'read' ? true : undefined }}\n InputProps={{\n readOnly: action === 'read',\n }}\n error={!!fieldState.error}\n helperText={fieldState.error?.message}\n value={field.value ?? 'none'}\n onChange={(event) => {\n field.onChange(event);\n }}\n >\n {Object.keys(SORT_METHODS).map((key) => {\n if (!SORT_METHODS[key as SortMethodName]) return null;\n const { label } = SORT_METHODS[key as SortMethodName];\n return (\n <MenuItem key={key} value={key}>\n {label}\n </MenuItem>\n );\n })}\n </TextField>\n )}\n />\n </Stack>\n </Stack>\n\n <Divider />\n\n <Typography py={1} variant=\"subtitle1\">\n Dropdown Options\n </Typography>\n <Stack spacing=\"2\">\n <Stack>\n <Controller\n control={control}\n name=\"spec.allowMultiple\"\n render={({ field }) => (\n <FormControlLabel\n label=\"Allow Multiple Values\"\n control={\n <Switch\n {...field}\n checked={!!field.value}\n readOnly={action === 'read'}\n value={field.value ?? false}\n onChange={(event) => {\n if (action === 'read') return; // ReadOnly prop is not blocking user interaction...\n field.onChange(event);\n }}\n />\n }\n />\n )}\n />\n <Typography variant=\"caption\">Enables multiple values to be selected at the same time</Typography>\n </Stack>\n <Stack>\n <Controller\n control={control}\n name=\"spec.allowAllValue\"\n render={({ field }) => (\n <FormControlLabel\n label=\"Allow All option\"\n control={\n <Switch\n {...field}\n checked={!!field.value}\n readOnly={action === 'read'}\n value={field.value ?? false}\n onChange={(event) => {\n if (action === 'read') return; // ReadOnly prop is not blocking user interaction...\n field.onChange(event);\n }}\n />\n }\n />\n )}\n />\n <Typography mb={1} variant=\"caption\">\n Enables an option to include all variable values\n </Typography>\n {_allowAllValue && (\n <Controller\n control={control}\n name=\"spec.customAllValue\"\n render={({ field, fieldState }) => (\n <TextField\n {...field}\n fullWidth\n label=\"Custom All Value\"\n InputLabelProps={{ shrink: action === 'read' ? true : undefined }}\n InputProps={{\n readOnly: action === 'read',\n }}\n error={!!fieldState.error}\n helperText={\n fieldState.error?.message\n ? fieldState.error.message\n : 'When All is selected, this value will be used'\n }\n value={field.value ?? ''}\n onChange={(event) => {\n if (event.target.value === '') {\n field.onChange(undefined);\n } else {\n field.onChange(event);\n }\n }}\n />\n )}\n />\n )}\n </Stack>\n </Stack>\n </>\n );\n}\n\ninterface VariableEditorFormProps {\n initialVariableDefinition: VariableDefinition;\n action: Action;\n isDraft: boolean;\n isReadonly?: boolean;\n onActionChange?: (action: Action) => void;\n onSave: (def: VariableDefinition) => void;\n onClose: () => void;\n onDelete?: DispatchWithoutAction;\n}\n\nexport function VariableEditorForm({\n initialVariableDefinition,\n action,\n isDraft,\n isReadonly,\n onActionChange,\n onSave,\n onClose,\n onDelete,\n}: VariableEditorFormProps): ReactElement {\n const [isDiscardDialogOpened, setDiscardDialogOpened] = useState<boolean>(false);\n const titleAction = getTitleAction(action, isDraft);\n const submitText = getSubmitText(action, isDraft);\n\n const { variableEditorSchema } = useValidationSchemas();\n const form = useForm<VariableDefinition>({\n resolver: zodResolver(variableEditorSchema),\n mode: 'onBlur',\n defaultValues: initialVariableDefinition,\n });\n\n const kind = useWatch({ control: form.control, name: 'kind' });\n\n function clearFormData(data: VariableDefinition): VariableDefinition {\n const result = { ...data };\n if (\n result.spec.display?.name === undefined &&\n result.spec.display?.description === undefined &&\n result.spec.display?.hidden === undefined\n ) {\n delete result.spec.display;\n }\n return result;\n }\n\n const processForm: SubmitHandler<VariableDefinition> = (data: VariableDefinition) => {\n // reset display attributes to undefined when empty, because we don't want to save empty strings\n onSave(clearFormData(data));\n };\n\n // When user click on cancel, several possibilities:\n // - create action: ask for discard approval\n // - update action: ask for discard approval if changed\n // - read action: don´t ask for discard approval\n function handleCancel(): void {\n if (JSON.stringify(initialVariableDefinition) !== JSON.stringify(clearFormData(form.getValues()))) {\n setDiscardDialogOpened(true);\n } else {\n onClose();\n }\n }\n\n return (\n <FormProvider {...form}>\n <Box\n sx={{\n display: 'flex',\n alignItems: 'center',\n padding: (theme) => theme.spacing(1, 2),\n borderBottom: (theme) => `1px solid ${theme.palette.divider}`,\n }}\n >\n <Typography variant=\"h2\">{titleAction} Variable</Typography>\n <FormActions\n action={action}\n submitText={submitText}\n isReadonly={isReadonly}\n isValid={form.formState.isValid}\n onActionChange={onActionChange}\n onSubmit={form.handleSubmit(processForm)}\n onDelete={onDelete}\n onCancel={handleCancel}\n />\n </Box>\n <Box padding={2} sx={{ overflowY: 'scroll' }}>\n <Grid container spacing={2} mb={2}>\n <Grid item xs={8}>\n <Controller\n control={form.control}\n name=\"spec.name\"\n render={({ field, fieldState }) => (\n <TextField\n {...field}\n required\n fullWidth\n label=\"Name\"\n InputLabelProps={{ shrink: action === 'read' ? true : undefined }}\n InputProps={{\n disabled: action === 'update' && !isDraft,\n readOnly: action === 'read',\n }}\n error={!!fieldState.error}\n helperText={fieldState.error?.message}\n value={field.value ?? ''}\n onChange={(event) => {\n field.onChange(event);\n }}\n />\n )}\n />\n </Grid>\n <Grid item xs={4}>\n <Controller\n control={form.control}\n name=\"spec.display.name\"\n render={({ field, fieldState }) => (\n <TextField\n {...field}\n fullWidth\n label=\"Display Label\"\n InputLabelProps={{ shrink: action === 'read' ? true : undefined }}\n InputProps={{\n readOnly: action === 'read',\n }}\n error={!!fieldState.error}\n helperText={fieldState.error?.message}\n value={field.value ?? ''}\n onChange={(event) => {\n field.onChange(event);\n }}\n />\n )}\n />\n </Grid>\n <Grid item xs={8}>\n <Controller\n control={form.control}\n name=\"spec.display.description\"\n render={({ field, fieldState }) => (\n <TextField\n {...field}\n fullWidth\n label=\"Description\"\n InputLabelProps={{ shrink: action === 'read' ? true : undefined }}\n InputProps={{\n readOnly: action === 'read',\n }}\n error={!!fieldState.error}\n helperText={fieldState.error?.message}\n value={field.value ?? ''}\n onChange={(event) => {\n field.onChange(event);\n }}\n />\n )}\n />\n </Grid>\n <Grid item xs={4}>\n <Controller\n control={form.control}\n name=\"kind\"\n render={({ field, fieldState }) => (\n <TextField\n select\n {...field}\n fullWidth\n label=\"Type\"\n InputLabelProps={{ shrink: action === 'read' ? true : undefined }}\n InputProps={{\n readOnly: action === 'read',\n }}\n error={!!fieldState.error}\n helperText={fieldState.error?.message}\n value={field.value ?? 'TextVariable'}\n onChange={(event) => {\n field.onChange(event);\n }}\n >\n {VARIABLE_TYPES.map((v) => (\n <MenuItem key={v.kind} value={v.kind}>\n {v.label}\n </MenuItem>\n ))}\n </TextField>\n )}\n />\n </Grid>\n </Grid>\n\n <Divider />\n\n {kind === 'TextVariable' && (\n <ErrorBoundary FallbackComponent={ErrorAlert}>\n <TextVariableEditorForm action={action} control={form.control} />\n </ErrorBoundary>\n )}\n {kind === 'ListVariable' && (\n <ErrorBoundary FallbackComponent={ErrorAlert}>\n <ListVariableEditorForm action={action} control={form.control} />\n </ErrorBoundary>\n )}\n </Box>\n <DiscardChangesConfirmationDialog\n description=\"Are you sure you want to discard these changes? Changes cannot be recovered.\"\n isOpen={isDiscardDialogOpened}\n onCancel={() => {\n setDiscardDialogOpened(false);\n }}\n onDiscardChanges={() => {\n setDiscardDialogOpened(false);\n onClose();\n }}\n />\n </FormProvider>\n );\n}\n"],"names":["useCallback","useState","Box","Typography","Switch","TextField","Grid","FormControlLabel","MenuItem","Stack","Divider","DiscardChangesConfirmationDialog","ErrorAlert","ErrorBoundary","FormActions","Controller","FormProvider","useForm","useFormContext","useWatch","zodResolver","useQueryClient","getSubmitText","getTitleAction","PluginEditor","useValidationSchemas","VARIABLE_TYPES","VariableListPreview","VariablePreview","SORT_METHODS","FallbackPreview","div","TextVariableEditorForm","action","control","py","variant","spacing","name","render","field","fieldState","values","value","label","InputLabelProps","shrink","undefined","InputProps","readOnly","error","helperText","message","onChange","event","checked","ListVariableEditorForm","form","queryClient","getValues","previewDefinition","setPreviewDefinition","structuredClone","handleRunQuery","JSON","stringify","invalidateQueries","queryKey","plugin","kind","pluginSpec","spec","_allowAllValue","sortMethod","allowAllValue","setValue","allowMultiple","sort","mb","FallbackComponent","resetKeys","definition","withRunQueryButton","width","pluginTypes","pluginKindLabel","selection","type","isReadonly","v","onRunQuery","target","select","fullWidth","Object","keys","map","key","VariableEditorForm","initialVariableDefinition","isDraft","onActionChange","onSave","onClose","onDelete","isDiscardDialogOpened","setDiscardDialogOpened","titleAction","submitText","variableEditorSchema","resolver","mode","defaultValues","clearFormData","data","result","display","description","hidden","processForm","handleCancel","sx","alignItems","padding","theme","borderBottom","palette","divider","isValid","formState","onSubmit","handleSubmit","onCancel","overflowY","container","item","xs","required","disabled","isOpen","onDiscardChanges"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/Variables/VariableEditorForm/VariableEditorForm.tsx"],"sourcesContent":["// Copyright The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { DispatchWithoutAction, ReactElement, useCallback, useState } from 'react';\nimport { Box, Typography, Switch, TextField, Grid, FormControlLabel, MenuItem, Stack, Divider } from '@mui/material';\nimport { VariableDefinition, ListVariableDefinition, Action } from '@perses-dev/core';\nimport { DiscardChangesConfirmationDialog, ErrorAlert, ErrorBoundary, FormActions } from '@perses-dev/components';\nimport { Control, Controller, FormProvider, SubmitHandler, useForm, useFormContext, useWatch } from 'react-hook-form';\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { useQueryClient } from '@tanstack/react-query';\nimport { getSubmitText, getTitleAction } from '../../../utils';\nimport { PluginEditor } from '../../PluginEditor';\nimport { useValidationSchemas } from '../../../context';\nimport { VARIABLE_TYPES } from '../variable-model';\nimport { VariableListPreview, VariablePreview } from './VariablePreview';\nimport { SORT_METHODS, SortMethodName } from './variable-editor-form-model';\n\nfunction FallbackPreview(): ReactElement {\n return <div>Error previewing values</div>;\n}\n\ninterface KindVariableEditorFormProps {\n action: Action;\n control: Control<VariableDefinition>;\n}\n\nfunction TextVariableEditorForm({ action, control }: KindVariableEditorFormProps): ReactElement {\n return (\n <>\n <Typography py={1} variant=\"subtitle1\">\n Text Options\n </Typography>\n <Stack spacing={2}>\n <Controller\n control={control}\n name=\"spec.value\"\n render={({ field, fieldState }) => (\n <>\n <Box>\n <VariablePreview values={[field.value]} />\n </Box>\n <TextField\n {...field}\n label=\"Value\"\n InputLabelProps={{ shrink: action === 'read' ? true : undefined }}\n InputProps={{\n readOnly: action === 'read',\n }}\n error={!!fieldState.error}\n helperText={fieldState.error?.message}\n value={field.value ?? ''}\n onChange={(event) => {\n field.onChange(event);\n }}\n />\n </>\n )}\n />\n <Controller\n control={control}\n name=\"spec.constant\"\n render={({ field }) => (\n <FormControlLabel\n label=\"Constant\"\n control={\n <Switch\n {...field}\n checked={!!field.value}\n readOnly={action === 'read'}\n value={field.value ?? false}\n onChange={(event) => {\n if (action === 'read') return; // ReadOnly prop is not blocking user interaction...\n field.onChange(event);\n }}\n />\n }\n />\n )}\n />\n </Stack>\n </>\n );\n}\n\nfunction ListVariableEditorForm({ action, control }: KindVariableEditorFormProps): ReactElement {\n const form = useFormContext<VariableDefinition>();\n const queryClient = useQueryClient();\n\n const values = form.getValues() as ListVariableDefinition;\n /* We use `previewDefinition` to explicitly update the spec\n * that will be used for preview when running query. The reason why we do this is to avoid\n * having to re-fetch the values when the user is still editing the spec.\n * Using structuredClone to not have reference issues with nested objects.\n */\n const [previewDefinition, setPreviewDefinition] = useState(structuredClone(values));\n\n const handleRunQuery = useCallback(async () => {\n if (JSON.stringify(previewDefinition) === JSON.stringify(values)) {\n await queryClient.invalidateQueries({ queryKey: ['variable', previewDefinition] });\n } else {\n setPreviewDefinition(structuredClone(values));\n }\n }, [previewDefinition, queryClient, values]);\n\n const plugin = useWatch<VariableDefinition, 'spec.plugin'>({ control, name: 'spec.plugin' });\n const kind = plugin?.kind;\n const pluginSpec = plugin?.spec;\n\n const _allowAllValue = useWatch<VariableDefinition, 'spec.allowAllValue'>({\n control: control,\n name: 'spec.allowAllValue',\n });\n\n const _customAllValue = useWatch<VariableDefinition, 'spec.customAllValue'>({\n control: control,\n name: 'spec.customAllValue',\n });\n\n const sortMethod = useWatch<VariableDefinition, 'spec.sort'>({\n control: control,\n name: 'spec.sort',\n }) as SortMethodName;\n\n // When variable kind is selected we need to provide default values\n // TODO: check if react-hook-form has a better way to do this\n if (values.spec.allowAllValue === undefined) {\n form.setValue('spec.allowAllValue', false);\n }\n\n if (values.spec.allowMultiple === undefined) {\n form.setValue('spec.allowMultiple', false);\n }\n\n if (!values.spec.plugin) {\n form.setValue('spec.plugin', { kind: 'StaticListVariable', spec: {} });\n }\n\n if (!values.spec.sort) {\n form.setValue('spec.sort', 'none');\n }\n\n return (\n <>\n <Typography py={1} variant=\"subtitle1\">\n List Options\n </Typography>\n <Stack spacing={2} mb={2}>\n <Box>\n <ErrorBoundary FallbackComponent={FallbackPreview} resetKeys={[previewDefinition]}>\n <VariableListPreview sortMethod={sortMethod} definition={previewDefinition} />\n </ErrorBoundary>\n </Box>\n <Stack>\n <ErrorBoundary FallbackComponent={ErrorAlert}>\n <Controller\n control={control}\n name=\"spec.plugin\"\n render={({ field }) => {\n return (\n <PluginEditor\n withRunQueryButton\n width=\"100%\"\n pluginTypes={['Variable']}\n pluginKindLabel=\"Source\"\n value={{\n selection: {\n type: 'Variable',\n kind: kind ?? 'StaticListVariable',\n },\n spec: pluginSpec ?? {},\n }}\n isReadonly={action === 'read'}\n onChange={(v) => {\n field.onChange({ kind: v.selection.kind, spec: v.spec });\n }}\n onRunQuery={handleRunQuery}\n />\n );\n }}\n />\n </ErrorBoundary>\n </Stack>\n\n <Stack>\n <Controller\n control={control}\n name=\"spec.capturingRegexp\"\n render={({ field, fieldState }) => (\n <TextField\n {...field}\n label=\"Capturing Regexp Filter\"\n InputLabelProps={{ shrink: action === 'read' ? true : undefined }}\n InputProps={{\n readOnly: action === 'read',\n }}\n error={!!fieldState.error}\n value={field.value ?? ''}\n onChange={(event) => {\n if (event.target.value === '') {\n field.onChange(undefined);\n } else {\n field.onChange(event);\n }\n }}\n helperText={\n fieldState.error?.message\n ? fieldState.error.message\n : 'Optional, if you want to filter on captured result.'\n }\n />\n )}\n />\n </Stack>\n\n <Stack>\n <Controller\n control={control}\n name=\"spec.sort\"\n render={({ field, fieldState }) => (\n <TextField\n select\n {...field}\n fullWidth\n label=\"Sort\"\n InputLabelProps={{ shrink: action === 'read' ? true : undefined }}\n InputProps={{\n readOnly: action === 'read',\n }}\n error={!!fieldState.error}\n helperText={fieldState.error?.message}\n value={field.value ?? 'none'}\n onChange={(event) => {\n field.onChange(event);\n }}\n >\n {Object.keys(SORT_METHODS).map((key) => {\n if (!SORT_METHODS[key as SortMethodName]) return null;\n const { label } = SORT_METHODS[key as SortMethodName];\n return (\n <MenuItem key={key} value={key}>\n {label}\n </MenuItem>\n );\n })}\n </TextField>\n )}\n />\n </Stack>\n </Stack>\n\n <Divider />\n\n <Typography py={1} variant=\"subtitle1\">\n Dropdown Options\n </Typography>\n <Stack spacing=\"2\">\n <Stack>\n <Controller\n control={control}\n name=\"spec.allowMultiple\"\n render={({ field }) => (\n <FormControlLabel\n label=\"Allow Multiple Values\"\n control={\n <Switch\n {...field}\n checked={!!field.value}\n readOnly={action === 'read'}\n value={field.value ?? false}\n onChange={(event) => {\n if (action === 'read') return; // ReadOnly prop is not blocking user interaction...\n field.onChange(event);\n }}\n />\n }\n />\n )}\n />\n <Typography variant=\"caption\">Enables multiple values to be selected at the same time</Typography>\n </Stack>\n <Stack>\n <Controller\n control={control}\n name=\"spec.allowAllValue\"\n render={({ field }) => (\n <FormControlLabel\n label=\"Allow All option\"\n control={\n <Switch\n {...field}\n checked={!!field.value}\n readOnly={action === 'read'}\n value={field.value ?? false}\n onChange={(event) => {\n if (action === 'read') return; // ReadOnly prop is not blocking user interaction...\n field.onChange(event);\n }}\n />\n }\n />\n )}\n />\n <Typography mb={1} variant=\"caption\">\n Enables an option to include all variable values\n </Typography>\n {_allowAllValue && (\n <Stack spacing={1}>\n <FormControlLabel\n label=\"Use Custom All Value\"\n control={\n <Switch\n checked={_customAllValue !== undefined}\n readOnly={action === 'read'}\n onChange={(event) => {\n if (action === 'read') return;\n const isEnabled = event.target.checked;\n if (isEnabled) {\n form.setValue('spec.customAllValue', '');\n } else {\n form.setValue('spec.customAllValue', undefined);\n }\n }}\n />\n }\n />\n <Typography variant=\"caption\" sx={{ mt: -0.5 }}>\n Enable to set a custom value when "All" is selected\n </Typography>\n {_customAllValue !== undefined && (\n <Controller\n control={control}\n name=\"spec.customAllValue\"\n render={({ field, fieldState }) => (\n <TextField\n {...field}\n fullWidth\n label=\"Custom All Value\"\n InputLabelProps={{ shrink: action === 'read' ? true : undefined }}\n InputProps={{\n readOnly: action === 'read',\n }}\n error={!!fieldState.error}\n helperText={fieldState.error?.message}\n value={field.value ?? ''}\n onChange={(event) => {\n field.onChange(event.target.value || '');\n }}\n />\n )}\n />\n )}\n </Stack>\n )}\n </Stack>\n </Stack>\n </>\n );\n}\n\ninterface VariableEditorFormProps {\n initialVariableDefinition: VariableDefinition;\n action: Action;\n isDraft: boolean;\n isReadonly?: boolean;\n onActionChange?: (action: Action) => void;\n onSave: (def: VariableDefinition) => void;\n onClose: () => void;\n onDelete?: DispatchWithoutAction;\n}\n\nexport function VariableEditorForm({\n initialVariableDefinition,\n action,\n isDraft,\n isReadonly,\n onActionChange,\n onSave,\n onClose,\n onDelete,\n}: VariableEditorFormProps): ReactElement {\n const [isDiscardDialogOpened, setDiscardDialogOpened] = useState<boolean>(false);\n const titleAction = getTitleAction(action, isDraft);\n const submitText = getSubmitText(action, isDraft);\n\n const { variableEditorSchema } = useValidationSchemas();\n const form = useForm<VariableDefinition>({\n resolver: zodResolver(variableEditorSchema),\n mode: 'onBlur',\n defaultValues: initialVariableDefinition,\n });\n\n const kind = useWatch({ control: form.control, name: 'kind' });\n\n function clearFormData(data: VariableDefinition): VariableDefinition {\n const result = { ...data };\n if (\n result.spec.display?.name === undefined &&\n result.spec.display?.description === undefined &&\n result.spec.display?.hidden === undefined\n ) {\n delete result.spec.display;\n }\n return result;\n }\n\n const processForm: SubmitHandler<VariableDefinition> = (data: VariableDefinition) => {\n // reset display attributes to undefined when empty, because we don't want to save empty strings\n onSave(clearFormData(data));\n };\n\n // When user click on cancel, several possibilities:\n // - create action: ask for discard approval\n // - update action: ask for discard approval if changed\n // - read action: don´t ask for discard approval\n function handleCancel(): void {\n if (JSON.stringify(initialVariableDefinition) !== JSON.stringify(clearFormData(form.getValues()))) {\n setDiscardDialogOpened(true);\n } else {\n onClose();\n }\n }\n\n return (\n <FormProvider {...form}>\n <Box\n sx={{\n display: 'flex',\n alignItems: 'center',\n padding: (theme) => theme.spacing(1, 2),\n borderBottom: (theme) => `1px solid ${theme.palette.divider}`,\n }}\n >\n <Typography variant=\"h2\">{titleAction} Variable</Typography>\n <FormActions\n action={action}\n submitText={submitText}\n isReadonly={isReadonly}\n isValid={form.formState.isValid}\n onActionChange={onActionChange}\n onSubmit={form.handleSubmit(processForm)}\n onDelete={onDelete}\n onCancel={handleCancel}\n />\n </Box>\n <Box padding={2} sx={{ overflowY: 'scroll' }}>\n <Grid container spacing={2} mb={2}>\n <Grid item xs={8}>\n <Controller\n control={form.control}\n name=\"spec.name\"\n render={({ field, fieldState }) => (\n <TextField\n {...field}\n required\n fullWidth\n label=\"Name\"\n InputLabelProps={{ shrink: action === 'read' ? true : undefined }}\n InputProps={{\n disabled: action === 'update' && !isDraft,\n readOnly: action === 'read',\n }}\n error={!!fieldState.error}\n helperText={fieldState.error?.message}\n value={field.value ?? ''}\n onChange={(event) => {\n field.onChange(event);\n }}\n />\n )}\n />\n </Grid>\n <Grid item xs={4}>\n <Controller\n control={form.control}\n name=\"spec.display.name\"\n render={({ field, fieldState }) => (\n <TextField\n {...field}\n fullWidth\n label=\"Display Label\"\n InputLabelProps={{ shrink: action === 'read' ? true : undefined }}\n InputProps={{\n readOnly: action === 'read',\n }}\n error={!!fieldState.error}\n helperText={fieldState.error?.message}\n value={field.value ?? ''}\n onChange={(event) => {\n field.onChange(event);\n }}\n />\n )}\n />\n </Grid>\n <Grid item xs={8}>\n <Controller\n control={form.control}\n name=\"spec.display.description\"\n render={({ field, fieldState }) => (\n <TextField\n {...field}\n fullWidth\n label=\"Description\"\n InputLabelProps={{ shrink: action === 'read' ? true : undefined }}\n InputProps={{\n readOnly: action === 'read',\n }}\n error={!!fieldState.error}\n helperText={fieldState.error?.message}\n value={field.value ?? ''}\n onChange={(event) => {\n field.onChange(event);\n }}\n />\n )}\n />\n </Grid>\n <Grid item xs={4}>\n <Controller\n control={form.control}\n name=\"kind\"\n render={({ field, fieldState }) => (\n <TextField\n select\n {...field}\n fullWidth\n label=\"Type\"\n InputLabelProps={{ shrink: action === 'read' ? true : undefined }}\n InputProps={{\n readOnly: action === 'read',\n }}\n error={!!fieldState.error}\n helperText={fieldState.error?.message}\n value={field.value ?? 'TextVariable'}\n onChange={(event) => {\n field.onChange(event);\n }}\n >\n {VARIABLE_TYPES.map((v) => (\n <MenuItem key={v.kind} value={v.kind}>\n {v.label}\n </MenuItem>\n ))}\n </TextField>\n )}\n />\n </Grid>\n </Grid>\n\n <Divider />\n\n {kind === 'TextVariable' && (\n <ErrorBoundary FallbackComponent={ErrorAlert}>\n <TextVariableEditorForm action={action} control={form.control} />\n </ErrorBoundary>\n )}\n {kind === 'ListVariable' && (\n <ErrorBoundary FallbackComponent={ErrorAlert}>\n <ListVariableEditorForm action={action} control={form.control} />\n </ErrorBoundary>\n )}\n </Box>\n <DiscardChangesConfirmationDialog\n description=\"Are you sure you want to discard these changes? Changes cannot be recovered.\"\n isOpen={isDiscardDialogOpened}\n onCancel={() => {\n setDiscardDialogOpened(false);\n }}\n onDiscardChanges={() => {\n setDiscardDialogOpened(false);\n onClose();\n }}\n />\n </FormProvider>\n );\n}\n"],"names":["useCallback","useState","Box","Typography","Switch","TextField","Grid","FormControlLabel","MenuItem","Stack","Divider","DiscardChangesConfirmationDialog","ErrorAlert","ErrorBoundary","FormActions","Controller","FormProvider","useForm","useFormContext","useWatch","zodResolver","useQueryClient","getSubmitText","getTitleAction","PluginEditor","useValidationSchemas","VARIABLE_TYPES","VariableListPreview","VariablePreview","SORT_METHODS","FallbackPreview","div","TextVariableEditorForm","action","control","py","variant","spacing","name","render","field","fieldState","values","value","label","InputLabelProps","shrink","undefined","InputProps","readOnly","error","helperText","message","onChange","event","checked","ListVariableEditorForm","form","queryClient","getValues","previewDefinition","setPreviewDefinition","structuredClone","handleRunQuery","JSON","stringify","invalidateQueries","queryKey","plugin","kind","pluginSpec","spec","_allowAllValue","_customAllValue","sortMethod","allowAllValue","setValue","allowMultiple","sort","mb","FallbackComponent","resetKeys","definition","withRunQueryButton","width","pluginTypes","pluginKindLabel","selection","type","isReadonly","v","onRunQuery","target","select","fullWidth","Object","keys","map","key","isEnabled","sx","mt","VariableEditorForm","initialVariableDefinition","isDraft","onActionChange","onSave","onClose","onDelete","isDiscardDialogOpened","setDiscardDialogOpened","titleAction","submitText","variableEditorSchema","resolver","mode","defaultValues","clearFormData","data","result","display","description","hidden","processForm","handleCancel","alignItems","padding","theme","borderBottom","palette","divider","isValid","formState","onSubmit","handleSubmit","onCancel","overflowY","container","item","xs","required","disabled","isOpen","onDiscardChanges"],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export interface SeriesDataPoint {
|
|
2
|
+
timestamp: number | string;
|
|
3
|
+
value: unknown;
|
|
4
|
+
}
|
|
5
|
+
export interface DataSeries {
|
|
6
|
+
name?: string;
|
|
7
|
+
formattedName?: string;
|
|
8
|
+
legendName?: string;
|
|
9
|
+
displayName?: string;
|
|
10
|
+
legend?: string;
|
|
11
|
+
labels?: Record<string, string>;
|
|
12
|
+
values: Array<[number | string, unknown]> | SeriesDataPoint[];
|
|
13
|
+
}
|
|
14
|
+
export interface ExportableData {
|
|
15
|
+
series: DataSeries[];
|
|
16
|
+
timeRange?: {
|
|
17
|
+
start: string | number;
|
|
18
|
+
end: string | number;
|
|
19
|
+
};
|
|
20
|
+
stepMs?: number;
|
|
21
|
+
metadata?: Record<string, unknown>;
|
|
22
|
+
}
|
|
23
|
+
export declare const isExportableData: (data: unknown) => data is ExportableData;
|
|
24
|
+
export interface QueryDataInput {
|
|
25
|
+
data?: unknown;
|
|
26
|
+
error?: unknown;
|
|
27
|
+
isFetching?: boolean;
|
|
28
|
+
}
|
|
29
|
+
export declare const extractExportableData: (queryResults: QueryDataInput[]) => ExportableData | undefined;
|
|
30
|
+
export declare const formatLegendName: (series: DataSeries, seriesIndex: number) => string;
|
|
31
|
+
export declare const sanitizeColumnName: (name: string) => string;
|
|
32
|
+
export declare const sanitizeFilename: (filename: string) => string;
|
|
33
|
+
export declare const formatTimestampISO: (timestamp: number | string) => string;
|
|
34
|
+
export declare const escapeCsvValue: (value: unknown) => string;
|
|
35
|
+
export interface ExportDataOptions {
|
|
36
|
+
data: ExportableData;
|
|
37
|
+
}
|
|
38
|
+
export declare const exportDataAsCSV: ({ data }: ExportDataOptions) => Blob;
|
|
39
|
+
//# sourceMappingURL=csv-export.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"csv-export.d.ts","sourceRoot":"","sources":["../../src/utils/csv-export.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;IAC3B,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,MAAM,EAAE,KAAK,CAAC,CAAC,MAAM,GAAG,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,eAAe,EAAE,CAAC;CAC/D;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,UAAU,EAAE,CAAC;IACrB,SAAS,CAAC,EAAE;QACV,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;QACvB,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;KACtB,CAAC;IACF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,eAAO,MAAM,gBAAgB,SAAU,OAAO,2BAQ7C,CAAC;AAEF,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,eAAO,MAAM,qBAAqB,iBAAkB,cAAc,EAAE,KAAG,cAAc,GAAG,SAoCvF,CAAC;AAEF,eAAO,MAAM,gBAAgB,WAAY,UAAU,eAAe,MAAM,KAAG,MA0C1E,CAAC;AAEF,eAAO,MAAM,kBAAkB,SAAU,MAAM,KAAG,MAOjD,CAAC;AAEF,eAAO,MAAM,gBAAgB,aAAc,MAAM,KAAG,MAanD,CAAC;AAEF,eAAO,MAAM,kBAAkB,cAAe,MAAM,GAAG,MAAM,KAAG,MAmB/D,CAAC;AAEF,eAAO,MAAM,cAAc,UAAW,OAAO,KAAG,MAiB/C,CAAC;AAEF,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,cAAc,CAAC;CACtB;AAED,eAAO,MAAM,eAAe,aAAc,iBAAiB,KAAG,IAsG7D,CAAC"}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
// Copyright The Perses Authors
|
|
2
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
3
|
+
// you may not use this file except in compliance with the License.
|
|
4
|
+
// You may obtain a copy of the License at
|
|
5
|
+
//
|
|
6
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
+
//
|
|
8
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
9
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
10
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
|
+
// See the License for the specific language governing permissions and
|
|
12
|
+
// limitations under the License.
|
|
13
|
+
export const isExportableData = (data)=>{
|
|
14
|
+
return !!(data && typeof data === 'object' && 'series' in data && Array.isArray(data.series) && data.series.length > 0);
|
|
15
|
+
};
|
|
16
|
+
export const extractExportableData = (queryResults)=>{
|
|
17
|
+
if (!queryResults || queryResults.length === 0) return undefined;
|
|
18
|
+
const allSeries = [];
|
|
19
|
+
let timeRange = undefined;
|
|
20
|
+
let stepMs = undefined;
|
|
21
|
+
let metadata = undefined;
|
|
22
|
+
queryResults.forEach((query)=>{
|
|
23
|
+
if (query?.data && typeof query.data === 'object' && 'series' in query.data) {
|
|
24
|
+
const data = query.data;
|
|
25
|
+
if (data.series && Array.isArray(data.series) && data.series.length > 0) {
|
|
26
|
+
allSeries.push(...data.series);
|
|
27
|
+
if (!timeRange && data.timeRange) {
|
|
28
|
+
timeRange = data.timeRange;
|
|
29
|
+
}
|
|
30
|
+
if (!stepMs && data.stepMs) {
|
|
31
|
+
stepMs = data.stepMs;
|
|
32
|
+
}
|
|
33
|
+
if (!metadata && data.metadata) {
|
|
34
|
+
metadata = data.metadata;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
if (allSeries.length > 0) {
|
|
40
|
+
return {
|
|
41
|
+
series: allSeries,
|
|
42
|
+
timeRange,
|
|
43
|
+
stepMs,
|
|
44
|
+
metadata
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
return undefined;
|
|
48
|
+
};
|
|
49
|
+
export const formatLegendName = (series, seriesIndex)=>{
|
|
50
|
+
const seriesAny = series;
|
|
51
|
+
let legendName = series.formattedName || series.name;
|
|
52
|
+
if (!legendName || legendName === `Series ${seriesIndex + 1}`) {
|
|
53
|
+
legendName = seriesAny.legendName || seriesAny.displayName || seriesAny.legend || series.name || '';
|
|
54
|
+
}
|
|
55
|
+
if ((!legendName || legendName === series.name) && series.labels) {
|
|
56
|
+
const labels = series.labels;
|
|
57
|
+
const displayLabels = {
|
|
58
|
+
...labels
|
|
59
|
+
};
|
|
60
|
+
const metricName = displayLabels.__name__;
|
|
61
|
+
delete displayLabels.__name__;
|
|
62
|
+
const labelPairs = Object.entries(displayLabels).filter(([value])=>value !== undefined && value !== null && value !== '').map(([key, value])=>`${key}="${value}"`).join(', ');
|
|
63
|
+
if (metricName && labelPairs) {
|
|
64
|
+
legendName = `${metricName}{${labelPairs}}`;
|
|
65
|
+
} else if (metricName) {
|
|
66
|
+
legendName = metricName;
|
|
67
|
+
} else if (labelPairs) {
|
|
68
|
+
legendName = `{${labelPairs}}`;
|
|
69
|
+
} else {
|
|
70
|
+
legendName = labels.job || labels.instance || labels.metric || `Series ${seriesIndex + 1}`;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (!legendName || legendName.trim() === '') {
|
|
74
|
+
legendName = `Series ${seriesIndex + 1}`;
|
|
75
|
+
}
|
|
76
|
+
return legendName;
|
|
77
|
+
};
|
|
78
|
+
export const sanitizeColumnName = (name)=>{
|
|
79
|
+
return name.replace(/[,"\n\r]/g, '_').replace(/\s+/g, '_').replace(/_+/g, '_').replace(/^_|_$/g, '').substring(0, 255);
|
|
80
|
+
};
|
|
81
|
+
export const sanitizeFilename = (filename)=>{
|
|
82
|
+
return filename.replace(/[<>:"/\\|?*]/g, ' ').trim().split(/\s+/).filter((word)=>word.length > 0).map((word, index)=>{
|
|
83
|
+
if (index === 0) {
|
|
84
|
+
return word.toLowerCase();
|
|
85
|
+
}
|
|
86
|
+
return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
|
|
87
|
+
}).join('');
|
|
88
|
+
};
|
|
89
|
+
export const formatTimestampISO = (timestamp)=>{
|
|
90
|
+
let timestampMs;
|
|
91
|
+
if (typeof timestamp === 'string') {
|
|
92
|
+
const date = new Date(timestamp);
|
|
93
|
+
if (isNaN(date.getTime())) {
|
|
94
|
+
return timestamp;
|
|
95
|
+
}
|
|
96
|
+
timestampMs = date.getTime();
|
|
97
|
+
} else {
|
|
98
|
+
timestampMs = timestamp > 1e10 ? timestamp : timestamp * 1000;
|
|
99
|
+
}
|
|
100
|
+
const date = new Date(timestampMs);
|
|
101
|
+
if (isNaN(date.getTime())) {
|
|
102
|
+
return new Date(timestampMs).toISOString();
|
|
103
|
+
}
|
|
104
|
+
return date.toISOString();
|
|
105
|
+
};
|
|
106
|
+
export const escapeCsvValue = (value)=>{
|
|
107
|
+
if (value === null || value === undefined) {
|
|
108
|
+
return '';
|
|
109
|
+
}
|
|
110
|
+
const stringValue = String(value);
|
|
111
|
+
if (stringValue.includes(',') || stringValue.includes('"') || stringValue.includes('\n') || stringValue.includes('\r')) {
|
|
112
|
+
return `"${stringValue.replace(/"/g, '""')}"`;
|
|
113
|
+
}
|
|
114
|
+
return stringValue;
|
|
115
|
+
};
|
|
116
|
+
export const exportDataAsCSV = ({ data })=>{
|
|
117
|
+
if (!isExportableData(data)) {
|
|
118
|
+
console.warn('No valid data found to export to CSV.');
|
|
119
|
+
return new Blob([
|
|
120
|
+
''
|
|
121
|
+
], {
|
|
122
|
+
type: 'text/csv;charset=utf-8'
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
let csvString = '';
|
|
126
|
+
const result = {};
|
|
127
|
+
const seriesInfo = [];
|
|
128
|
+
let validSeriesCount = 0;
|
|
129
|
+
for(let i = 0; i < data.series.length; i++){
|
|
130
|
+
const series = data.series[i];
|
|
131
|
+
if (!series) {
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
if (!Array.isArray(series.values) || series.values.length === 0) {
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
const legendName = formatLegendName(series, i);
|
|
138
|
+
const columnName = sanitizeColumnName(legendName);
|
|
139
|
+
const currentSeriesInfo = {
|
|
140
|
+
legendName,
|
|
141
|
+
columnName: columnName || `Series_${i + 1}`,
|
|
142
|
+
originalName: series.name || ''
|
|
143
|
+
};
|
|
144
|
+
seriesInfo.push(currentSeriesInfo);
|
|
145
|
+
validSeriesCount++;
|
|
146
|
+
for(let j = 0; j < series.values.length; j++){
|
|
147
|
+
const entry = series.values[j];
|
|
148
|
+
let timestamp;
|
|
149
|
+
let value;
|
|
150
|
+
if (Array.isArray(entry) && entry.length >= 2) {
|
|
151
|
+
timestamp = entry[0];
|
|
152
|
+
value = entry[1];
|
|
153
|
+
} else if (typeof entry === 'object' && entry !== null && 'timestamp' in entry && 'value' in entry) {
|
|
154
|
+
const dataPoint = entry;
|
|
155
|
+
timestamp = dataPoint.timestamp;
|
|
156
|
+
value = dataPoint.value;
|
|
157
|
+
} else {
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
if (value === null || value === undefined) {
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
const dateTime = formatTimestampISO(timestamp);
|
|
164
|
+
if (!result[dateTime]) {
|
|
165
|
+
result[dateTime] = {};
|
|
166
|
+
}
|
|
167
|
+
/* linter complains, so assert result[dateTime]
|
|
168
|
+
It has already been checked by the if statement
|
|
169
|
+
*/ result[dateTime][currentSeriesInfo.columnName] = value;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
if (validSeriesCount === 0 || seriesInfo.length === 0) {
|
|
173
|
+
console.warn('No valid data found to export to CSV.');
|
|
174
|
+
return new Blob([
|
|
175
|
+
''
|
|
176
|
+
], {
|
|
177
|
+
type: 'text/csv;charset=utf-8'
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
const timestampCount = Object.keys(result).length;
|
|
181
|
+
if (timestampCount === 0) {
|
|
182
|
+
console.warn('No valid timestamp data found to export to CSV.');
|
|
183
|
+
return new Blob([
|
|
184
|
+
''
|
|
185
|
+
], {
|
|
186
|
+
type: 'text/csv;charset=utf-8'
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
const columnNames = seriesInfo.map((info)=>info.columnName);
|
|
190
|
+
csvString += `DateTime,${columnNames.join(',')}\n`;
|
|
191
|
+
const sortedDateTimes = Object.keys(result).sort((a, b)=>{
|
|
192
|
+
const dateA = new Date(a).getTime();
|
|
193
|
+
const dateB = new Date(b).getTime();
|
|
194
|
+
return dateA - dateB;
|
|
195
|
+
});
|
|
196
|
+
for (const dateTime of sortedDateTimes){
|
|
197
|
+
const rowData = result[dateTime];
|
|
198
|
+
const values = [];
|
|
199
|
+
if (rowData) {
|
|
200
|
+
for (const columnName of columnNames){
|
|
201
|
+
const value = rowData[columnName];
|
|
202
|
+
values.push(escapeCsvValue(value));
|
|
203
|
+
}
|
|
204
|
+
csvString += `${escapeCsvValue(dateTime)},${values.join(',')}\n`;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return new Blob([
|
|
208
|
+
csvString
|
|
209
|
+
], {
|
|
210
|
+
type: 'text/csv;charset=utf-8'
|
|
211
|
+
});
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
//# sourceMappingURL=csv-export.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utils/csv-export.ts"],"sourcesContent":["// Copyright The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nexport interface SeriesDataPoint {\n timestamp: number | string;\n value: unknown;\n}\n\nexport interface DataSeries {\n name?: string;\n formattedName?: string;\n legendName?: string;\n displayName?: string;\n legend?: string;\n labels?: Record<string, string>;\n values: Array<[number | string, unknown]> | SeriesDataPoint[];\n}\n\nexport interface ExportableData {\n series: DataSeries[];\n timeRange?: {\n start: string | number;\n end: string | number;\n };\n stepMs?: number;\n metadata?: Record<string, unknown>;\n}\n\nexport const isExportableData = (data: unknown): data is ExportableData => {\n return !!(\n data &&\n typeof data === 'object' &&\n 'series' in data &&\n Array.isArray((data as ExportableData).series) &&\n (data as ExportableData).series.length > 0\n );\n};\n\nexport interface QueryDataInput {\n data?: unknown;\n error?: unknown;\n isFetching?: boolean;\n}\n\nexport const extractExportableData = (queryResults: QueryDataInput[]): ExportableData | undefined => {\n if (!queryResults || queryResults.length === 0) return undefined;\n\n const allSeries: DataSeries[] = [];\n let timeRange: ExportableData['timeRange'] = undefined;\n let stepMs: number | undefined = undefined;\n let metadata: ExportableData['metadata'] = undefined;\n\n queryResults.forEach((query) => {\n if (query?.data && typeof query.data === 'object' && 'series' in query.data) {\n const data = query.data as ExportableData;\n if (data.series && Array.isArray(data.series) && data.series.length > 0) {\n allSeries.push(...data.series);\n if (!timeRange && data.timeRange) {\n timeRange = data.timeRange;\n }\n if (!stepMs && data.stepMs) {\n stepMs = data.stepMs;\n }\n if (!metadata && data.metadata) {\n metadata = data.metadata;\n }\n }\n }\n });\n\n if (allSeries.length > 0) {\n return {\n series: allSeries,\n timeRange,\n stepMs,\n metadata,\n };\n }\n\n return undefined;\n};\n\nexport const formatLegendName = (series: DataSeries, seriesIndex: number): string => {\n const seriesAny = series as DataSeries & {\n formattedName?: string;\n legendName?: string;\n displayName?: string;\n legend?: string;\n labels?: Record<string, string>;\n };\n\n let legendName = series.formattedName || series.name;\n\n if (!legendName || legendName === `Series ${seriesIndex + 1}`) {\n legendName = seriesAny.legendName || seriesAny.displayName || seriesAny.legend || series.name || '';\n }\n\n if ((!legendName || legendName === series.name) && series.labels) {\n const labels = series.labels;\n const displayLabels = { ...labels };\n const metricName = displayLabels.__name__;\n delete displayLabels.__name__;\n\n const labelPairs = Object.entries(displayLabels)\n .filter(([value]) => value !== undefined && value !== null && value !== '')\n .map(([key, value]) => `${key}=\"${value}\"`)\n .join(', ');\n\n if (metricName && labelPairs) {\n legendName = `${metricName}{${labelPairs}}`;\n } else if (metricName) {\n legendName = metricName;\n } else if (labelPairs) {\n legendName = `{${labelPairs}}`;\n } else {\n legendName = labels.job || labels.instance || labels.metric || `Series ${seriesIndex + 1}`;\n }\n }\n\n if (!legendName || legendName.trim() === '') {\n legendName = `Series ${seriesIndex + 1}`;\n }\n\n return legendName;\n};\n\nexport const sanitizeColumnName = (name: string): string => {\n return name\n .replace(/[,\"\\n\\r]/g, '_')\n .replace(/\\s+/g, '_')\n .replace(/_+/g, '_')\n .replace(/^_|_$/g, '')\n .substring(0, 255);\n};\n\nexport const sanitizeFilename = (filename: string): string => {\n return filename\n .replace(/[<>:\"/\\\\|?*]/g, ' ')\n .trim()\n .split(/\\s+/)\n .filter((word) => word.length > 0)\n .map((word, index) => {\n if (index === 0) {\n return word.toLowerCase();\n }\n return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();\n })\n .join('');\n};\n\nexport const formatTimestampISO = (timestamp: number | string): string => {\n let timestampMs: number;\n\n if (typeof timestamp === 'string') {\n const date = new Date(timestamp);\n if (isNaN(date.getTime())) {\n return timestamp;\n }\n timestampMs = date.getTime();\n } else {\n timestampMs = timestamp > 1e10 ? timestamp : timestamp * 1000;\n }\n\n const date = new Date(timestampMs);\n if (isNaN(date.getTime())) {\n return new Date(timestampMs).toISOString();\n }\n\n return date.toISOString();\n};\n\nexport const escapeCsvValue = (value: unknown): string => {\n if (value === null || value === undefined) {\n return '';\n }\n\n const stringValue = String(value);\n\n if (\n stringValue.includes(',') ||\n stringValue.includes('\"') ||\n stringValue.includes('\\n') ||\n stringValue.includes('\\r')\n ) {\n return `\"${stringValue.replace(/\"/g, '\"\"')}\"`;\n }\n\n return stringValue;\n};\n\nexport interface ExportDataOptions {\n data: ExportableData;\n}\n\nexport const exportDataAsCSV = ({ data }: ExportDataOptions): Blob => {\n if (!isExportableData(data)) {\n console.warn('No valid data found to export to CSV.');\n return new Blob([''], { type: 'text/csv;charset=utf-8' });\n }\n\n let csvString = '';\n const result: Record<string, Record<string, unknown>> = {};\n const seriesInfo: Array<{ legendName: string; columnName: string; originalName: string }> = [];\n let validSeriesCount = 0;\n\n for (let i = 0; i < data.series.length; i++) {\n const series = data.series[i];\n\n if (!series) {\n continue;\n }\n\n if (!Array.isArray(series.values) || series.values.length === 0) {\n continue;\n }\n\n const legendName = formatLegendName(series, i);\n const columnName = sanitizeColumnName(legendName);\n\n const currentSeriesInfo = {\n legendName,\n columnName: columnName || `Series_${i + 1}`,\n originalName: series.name || '',\n };\n\n seriesInfo.push(currentSeriesInfo);\n validSeriesCount++;\n\n for (let j = 0; j < series.values.length; j++) {\n const entry = series.values[j];\n\n let timestamp: number | string;\n let value: unknown;\n\n if (Array.isArray(entry) && entry.length >= 2) {\n timestamp = entry[0];\n value = entry[1];\n } else if (typeof entry === 'object' && entry !== null && 'timestamp' in entry && 'value' in entry) {\n const dataPoint = entry as SeriesDataPoint;\n timestamp = dataPoint.timestamp;\n value = dataPoint.value;\n } else {\n continue;\n }\n\n if (value === null || value === undefined) {\n continue;\n }\n\n const dateTime = formatTimestampISO(timestamp);\n\n if (!result[dateTime]) {\n result[dateTime] = {};\n }\n /* linter complains, so assert result[dateTime] \n It has already been checked by the if statement\n */\n result[dateTime]![currentSeriesInfo.columnName] = value;\n }\n }\n\n if (validSeriesCount === 0 || seriesInfo.length === 0) {\n console.warn('No valid data found to export to CSV.');\n return new Blob([''], { type: 'text/csv;charset=utf-8' });\n }\n\n const timestampCount = Object.keys(result).length;\n if (timestampCount === 0) {\n console.warn('No valid timestamp data found to export to CSV.');\n return new Blob([''], { type: 'text/csv;charset=utf-8' });\n }\n\n const columnNames = seriesInfo.map((info) => info.columnName);\n csvString += `DateTime,${columnNames.join(',')}\\n`;\n\n const sortedDateTimes = Object.keys(result).sort((a, b) => {\n const dateA = new Date(a).getTime();\n const dateB = new Date(b).getTime();\n return dateA - dateB;\n });\n\n for (const dateTime of sortedDateTimes) {\n const rowData = result[dateTime];\n const values: string[] = [];\n\n if (rowData) {\n for (const columnName of columnNames) {\n const value = rowData[columnName];\n values.push(escapeCsvValue(value));\n }\n\n csvString += `${escapeCsvValue(dateTime)},${values.join(',')}\\n`;\n }\n }\n\n return new Blob([csvString], { type: 'text/csv;charset=utf-8' });\n};\n"],"names":["isExportableData","data","Array","isArray","series","length","extractExportableData","queryResults","undefined","allSeries","timeRange","stepMs","metadata","forEach","query","push","formatLegendName","seriesIndex","seriesAny","legendName","formattedName","name","displayName","legend","labels","displayLabels","metricName","__name__","labelPairs","Object","entries","filter","value","map","key","join","job","instance","metric","trim","sanitizeColumnName","replace","substring","sanitizeFilename","filename","split","word","index","toLowerCase","charAt","toUpperCase","slice","formatTimestampISO","timestamp","timestampMs","date","Date","isNaN","getTime","toISOString","escapeCsvValue","stringValue","String","includes","exportDataAsCSV","console","warn","Blob","type","csvString","result","seriesInfo","validSeriesCount","i","values","columnName","currentSeriesInfo","originalName","j","entry","dataPoint","dateTime","timestampCount","keys","columnNames","info","sortedDateTimes","sort","a","b","dateA","dateB","rowData"],"mappings":"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"}
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAaA,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAaA,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC"}
|
package/dist/utils/index.js
CHANGED
package/dist/utils/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utils/index.ts"],"sourcesContent":["// Copyright The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nexport * from './action';\nexport * from './event';\nexport * from './variables';\n"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;AAEjC,cAAc,WAAW;AACzB,cAAc,UAAU;AACxB,cAAc,cAAc"}
|
|
1
|
+
{"version":3,"sources":["../../src/utils/index.ts"],"sourcesContent":["// Copyright The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nexport * from './action';\nexport * from './event';\nexport * from './variables';\nexport * from './csv-export';\n"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;AAEjC,cAAc,WAAW;AACzB,cAAc,UAAU;AACxB,cAAc,cAAc;AAC5B,cAAc,eAAe"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@perses-dev/plugin-system",
|
|
3
|
-
"version": "0.53.
|
|
3
|
+
"version": "0.53.1",
|
|
4
4
|
"description": "The plugin feature in Pereses",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://github.com/perses/perses/blob/main/README.md",
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"@module-federation/enhanced": "^0.21.4",
|
|
32
|
-
"@perses-dev/components": "0.53.
|
|
33
|
-
"@perses-dev/core": "0.53.0
|
|
32
|
+
"@perses-dev/components": "0.53.1",
|
|
33
|
+
"@perses-dev/core": "0.53.0",
|
|
34
34
|
"date-fns": "^4.1.0",
|
|
35
35
|
"date-fns-tz": "^3.2.0",
|
|
36
36
|
"immer": "^10.1.1",
|