@perses-dev/dashboards 0.50.1 → 0.50.3
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/DownloadButton/DownloadButton.js +135 -29
- package/dist/cjs/components/PanelDrawer/PanelEditorForm.js +21 -11
- package/dist/cjs/components/Variables/Variable.js +10 -1
- package/dist/cjs/constants/user-interface-text.js +0 -1
- package/dist/cjs/context/VariableProvider/VariableProvider.js +12 -11
- package/dist/components/DownloadButton/DownloadButton.d.ts +1 -5
- package/dist/components/DownloadButton/DownloadButton.d.ts.map +1 -1
- package/dist/components/DownloadButton/DownloadButton.js +94 -29
- package/dist/components/DownloadButton/DownloadButton.js.map +1 -1
- package/dist/components/PanelDrawer/PanelEditorForm.d.ts.map +1 -1
- package/dist/components/PanelDrawer/PanelEditorForm.js +21 -11
- package/dist/components/PanelDrawer/PanelEditorForm.js.map +1 -1
- package/dist/components/Variables/Variable.js +10 -1
- package/dist/components/Variables/Variable.js.map +1 -1
- package/dist/constants/user-interface-text.d.ts +0 -1
- package/dist/constants/user-interface-text.d.ts.map +1 -1
- package/dist/constants/user-interface-text.js +0 -1
- package/dist/constants/user-interface-text.js.map +1 -1
- package/dist/context/VariableProvider/VariableProvider.d.ts.map +1 -1
- package/dist/context/VariableProvider/VariableProvider.js +12 -11
- package/dist/context/VariableProvider/VariableProvider.js.map +1 -1
- package/package.json +7 -6
|
@@ -21,53 +21,159 @@ Object.defineProperty(exports, "DownloadButton", {
|
|
|
21
21
|
}
|
|
22
22
|
});
|
|
23
23
|
const _jsxruntime = require("react/jsx-runtime");
|
|
24
|
-
const
|
|
25
|
-
const _DownloadOutline = /*#__PURE__*/ _interop_require_default(require("mdi-material-ui/DownloadOutline"));
|
|
24
|
+
const _material = require("@mui/material");
|
|
26
25
|
const _components = require("@perses-dev/components");
|
|
27
|
-
const
|
|
26
|
+
const _DownloadOutline = /*#__PURE__*/ _interop_require_default(require("mdi-material-ui/DownloadOutline"));
|
|
27
|
+
const _react = /*#__PURE__*/ _interop_require_wildcard(require("react"));
|
|
28
|
+
const _yaml = require("yaml");
|
|
28
29
|
const _context = require("../../context");
|
|
29
30
|
function _interop_require_default(obj) {
|
|
30
31
|
return obj && obj.__esModule ? obj : {
|
|
31
32
|
default: obj
|
|
32
33
|
};
|
|
33
34
|
}
|
|
34
|
-
function
|
|
35
|
+
function _getRequireWildcardCache(nodeInterop) {
|
|
36
|
+
if (typeof WeakMap !== "function") return null;
|
|
37
|
+
var cacheBabelInterop = new WeakMap();
|
|
38
|
+
var cacheNodeInterop = new WeakMap();
|
|
39
|
+
return (_getRequireWildcardCache = function(nodeInterop) {
|
|
40
|
+
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
|
|
41
|
+
})(nodeInterop);
|
|
42
|
+
}
|
|
43
|
+
function _interop_require_wildcard(obj, nodeInterop) {
|
|
44
|
+
if (!nodeInterop && obj && obj.__esModule) {
|
|
45
|
+
return obj;
|
|
46
|
+
}
|
|
47
|
+
if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
|
|
48
|
+
return {
|
|
49
|
+
default: obj
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
var cache = _getRequireWildcardCache(nodeInterop);
|
|
53
|
+
if (cache && cache.has(obj)) {
|
|
54
|
+
return cache.get(obj);
|
|
55
|
+
}
|
|
56
|
+
var newObj = {
|
|
57
|
+
__proto__: null
|
|
58
|
+
};
|
|
59
|
+
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
|
|
60
|
+
for(var key in obj){
|
|
61
|
+
if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
62
|
+
var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
|
|
63
|
+
if (desc && (desc.get || desc.set)) {
|
|
64
|
+
Object.defineProperty(newObj, key, desc);
|
|
65
|
+
} else {
|
|
66
|
+
newObj[key] = obj[key];
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
newObj.default = obj;
|
|
71
|
+
if (cache) {
|
|
72
|
+
cache.set(obj, newObj);
|
|
73
|
+
}
|
|
74
|
+
return newObj;
|
|
75
|
+
}
|
|
76
|
+
function DownloadButton() {
|
|
35
77
|
const { dashboard } = (0, _context.useDashboard)();
|
|
36
78
|
const hiddenLinkRef = (0, _react.useRef)(null);
|
|
37
|
-
const
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const hiddenLinkUrl = URL.createObjectURL(new Blob([
|
|
42
|
-
JSON.stringify(dashboard)
|
|
43
|
-
], {
|
|
44
|
-
type: 'application/json'
|
|
45
|
-
}));
|
|
46
|
-
// Simulate click
|
|
47
|
-
hiddenLinkRef.current.href = hiddenLinkUrl;
|
|
48
|
-
hiddenLinkRef.current.click();
|
|
49
|
-
// Remove blob URL (for memory management)
|
|
50
|
-
URL.revokeObjectURL(hiddenLinkUrl);
|
|
79
|
+
const [anchorEl, setAnchorEl] = _react.default.useState(null);
|
|
80
|
+
const open = Boolean(anchorEl);
|
|
81
|
+
const handleClick = (event)=>{
|
|
82
|
+
setAnchorEl(event.currentTarget);
|
|
51
83
|
};
|
|
84
|
+
const handleItemClick = (format, shape)=>()=>{
|
|
85
|
+
setAnchorEl(null);
|
|
86
|
+
let type, content = '';
|
|
87
|
+
switch(format){
|
|
88
|
+
case 'json':
|
|
89
|
+
type = 'application/json';
|
|
90
|
+
content = JSON.stringify(dashboard, null, 2);
|
|
91
|
+
break;
|
|
92
|
+
case 'yaml':
|
|
93
|
+
{
|
|
94
|
+
type = 'application/yaml';
|
|
95
|
+
if (shape === 'cr') {
|
|
96
|
+
const name = dashboard.metadata.name.toLowerCase().replace(/[^a-z0-9-]/g, '-');
|
|
97
|
+
content = (0, _yaml.stringify)({
|
|
98
|
+
apiVersion: 'perses.dev/v1alpha1',
|
|
99
|
+
kind: 'PersesDashboard',
|
|
100
|
+
metadata: {
|
|
101
|
+
labels: {
|
|
102
|
+
'app.kubernetes.io/name': 'perses-dashboard',
|
|
103
|
+
'app.kubernetes.io/instance': name,
|
|
104
|
+
'app.kubernetes.io/part-of': 'perses-operator'
|
|
105
|
+
},
|
|
106
|
+
name
|
|
107
|
+
},
|
|
108
|
+
namespace: dashboard.metadata.project,
|
|
109
|
+
spec: dashboard.spec
|
|
110
|
+
});
|
|
111
|
+
} else {
|
|
112
|
+
content = (0, _yaml.stringify)(dashboard);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
break;
|
|
116
|
+
}
|
|
117
|
+
if (!hiddenLinkRef || !hiddenLinkRef.current) return;
|
|
118
|
+
// Create blob URL
|
|
119
|
+
const hiddenLinkUrl = URL.createObjectURL(new Blob([
|
|
120
|
+
content
|
|
121
|
+
], {
|
|
122
|
+
type
|
|
123
|
+
}));
|
|
124
|
+
// Simulate click
|
|
125
|
+
hiddenLinkRef.current.download = `${dashboard.metadata.name}${shape === 'cr' ? '-cr' : ''}.${format}`;
|
|
126
|
+
hiddenLinkRef.current.href = hiddenLinkUrl;
|
|
127
|
+
hiddenLinkRef.current.click();
|
|
128
|
+
// Remove blob URL (for memory management)
|
|
129
|
+
URL.revokeObjectURL(hiddenLinkUrl);
|
|
130
|
+
};
|
|
52
131
|
return /*#__PURE__*/ (0, _jsxruntime.jsxs)(_jsxruntime.Fragment, {
|
|
53
132
|
children: [
|
|
54
|
-
/*#__PURE__*/ (0, _jsxruntime.jsx)(_components.
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
133
|
+
/*#__PURE__*/ (0, _jsxruntime.jsx)(_components.ToolbarIconButton, {
|
|
134
|
+
id: "download-dashboard-button",
|
|
135
|
+
"aria-controls": open ? 'basic-menu' : undefined,
|
|
136
|
+
"aria-haspopup": "true",
|
|
137
|
+
"aria-expanded": open ? 'true' : undefined,
|
|
138
|
+
onClick: handleClick,
|
|
139
|
+
children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_DownloadOutline.default, {})
|
|
140
|
+
}),
|
|
141
|
+
/*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Menu, {
|
|
142
|
+
id: "download-dashboard-formats",
|
|
143
|
+
anchorEl: anchorEl,
|
|
144
|
+
open: open,
|
|
145
|
+
hideBackdrop: true,
|
|
146
|
+
onClose: ()=>setAnchorEl(null),
|
|
147
|
+
MenuListProps: {
|
|
148
|
+
'aria-labelledby': 'download-dashboard-button'
|
|
149
|
+
},
|
|
150
|
+
children: /*#__PURE__*/ (0, _jsxruntime.jsx)("div", {
|
|
151
|
+
children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.ClickAwayListener, {
|
|
152
|
+
onClickAway: ()=>setAnchorEl(null),
|
|
153
|
+
children: /*#__PURE__*/ (0, _jsxruntime.jsxs)(_material.MenuList, {
|
|
154
|
+
children: [
|
|
155
|
+
/*#__PURE__*/ (0, _jsxruntime.jsx)(_material.MenuItem, {
|
|
156
|
+
onClick: handleItemClick('json'),
|
|
157
|
+
children: "JSON"
|
|
158
|
+
}),
|
|
159
|
+
/*#__PURE__*/ (0, _jsxruntime.jsx)(_material.MenuItem, {
|
|
160
|
+
onClick: handleItemClick('yaml'),
|
|
161
|
+
children: "YAML"
|
|
162
|
+
}),
|
|
163
|
+
/*#__PURE__*/ (0, _jsxruntime.jsx)(_material.MenuItem, {
|
|
164
|
+
onClick: handleItemClick('yaml', 'cr'),
|
|
165
|
+
children: "YAML (CR)"
|
|
166
|
+
})
|
|
167
|
+
]
|
|
168
|
+
})
|
|
169
|
+
})
|
|
63
170
|
})
|
|
64
171
|
}),
|
|
65
172
|
/*#__PURE__*/ (0, _jsxruntime.jsx)("a", {
|
|
66
173
|
ref: hiddenLinkRef,
|
|
67
174
|
style: {
|
|
68
175
|
display: 'none'
|
|
69
|
-
}
|
|
70
|
-
download: `${dashboard.metadata.name}.json`
|
|
176
|
+
}
|
|
71
177
|
})
|
|
72
178
|
]
|
|
73
179
|
});
|
|
@@ -44,6 +44,12 @@ function PanelEditorForm(props) {
|
|
|
44
44
|
const { panelDefinition, setName, setDescription, setLinks, setQueries, setPlugin, setPanelDefinition } = (0, _usePanelEditor.usePanelEditor)(initialValues.panelDefinition);
|
|
45
45
|
const { plugin } = panelDefinition.spec;
|
|
46
46
|
const [isDiscardDialogOpened, setDiscardDialogOpened] = (0, _react.useState)(false);
|
|
47
|
+
const { panelEditorSchema } = (0, _pluginsystem.useValidationSchemas)();
|
|
48
|
+
const form = (0, _reacthookform.useForm)({
|
|
49
|
+
resolver: (0, _zod.zodResolver)(panelEditorSchema),
|
|
50
|
+
mode: 'onBlur',
|
|
51
|
+
defaultValues: initialValues
|
|
52
|
+
});
|
|
47
53
|
// Use common plugin editor logic even though we've split the inputs up in this form
|
|
48
54
|
const pluginEditor = (0, _pluginsystem.usePluginEditor)({
|
|
49
55
|
pluginTypes: [
|
|
@@ -72,12 +78,6 @@ function PanelEditorForm(props) {
|
|
|
72
78
|
});
|
|
73
79
|
const titleAction = (0, _pluginsystem.getTitleAction)(initialAction, true);
|
|
74
80
|
const submitText = (0, _pluginsystem.getSubmitText)(initialAction, true);
|
|
75
|
-
const { panelEditorSchema } = (0, _pluginsystem.useValidationSchemas)();
|
|
76
|
-
const form = (0, _reacthookform.useForm)({
|
|
77
|
-
resolver: (0, _zod.zodResolver)(panelEditorSchema),
|
|
78
|
-
mode: 'onBlur',
|
|
79
|
-
defaultValues: initialValues
|
|
80
|
-
});
|
|
81
81
|
const links = (0, _reacthookform.useWatch)({
|
|
82
82
|
control: form.control,
|
|
83
83
|
name: 'panelDefinition.spec.links'
|
|
@@ -111,6 +111,18 @@ function PanelEditorForm(props) {
|
|
|
111
111
|
}
|
|
112
112
|
setPanelDefinition(nextPanelDef);
|
|
113
113
|
};
|
|
114
|
+
const watchedName = (0, _reacthookform.useWatch)({
|
|
115
|
+
control: form.control,
|
|
116
|
+
name: 'panelDefinition.spec.display.name'
|
|
117
|
+
});
|
|
118
|
+
const watchedDescription = (0, _reacthookform.useWatch)({
|
|
119
|
+
control: form.control,
|
|
120
|
+
name: 'panelDefinition.spec.display.description'
|
|
121
|
+
});
|
|
122
|
+
const watchedPluginKind = (0, _reacthookform.useWatch)({
|
|
123
|
+
control: form.control,
|
|
124
|
+
name: 'panelDefinition.spec.plugin.kind'
|
|
125
|
+
});
|
|
114
126
|
return /*#__PURE__*/ (0, _jsxruntime.jsxs)(_reacthookform.FormProvider, {
|
|
115
127
|
...form,
|
|
116
128
|
children: [
|
|
@@ -169,7 +181,6 @@ function PanelEditorForm(props) {
|
|
|
169
181
|
name: "panelDefinition.spec.display.name",
|
|
170
182
|
render: ({ field, fieldState })=>{
|
|
171
183
|
var _fieldState_error;
|
|
172
|
-
var _field_value;
|
|
173
184
|
return /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.TextField, {
|
|
174
185
|
...field,
|
|
175
186
|
required: true,
|
|
@@ -177,7 +188,7 @@ function PanelEditorForm(props) {
|
|
|
177
188
|
label: "Name",
|
|
178
189
|
error: !!fieldState.error,
|
|
179
190
|
helperText: (_fieldState_error = fieldState.error) === null || _fieldState_error === void 0 ? void 0 : _fieldState_error.message,
|
|
180
|
-
value:
|
|
191
|
+
value: watchedName !== null && watchedName !== void 0 ? watchedName : '',
|
|
181
192
|
onChange: (event)=>{
|
|
182
193
|
field.onChange(event);
|
|
183
194
|
setName(event.target.value);
|
|
@@ -224,14 +235,13 @@ function PanelEditorForm(props) {
|
|
|
224
235
|
name: "panelDefinition.spec.display.description",
|
|
225
236
|
render: ({ field, fieldState })=>{
|
|
226
237
|
var _fieldState_error;
|
|
227
|
-
var _field_value;
|
|
228
238
|
return /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.TextField, {
|
|
229
239
|
...field,
|
|
230
240
|
fullWidth: true,
|
|
231
241
|
label: "Description",
|
|
232
242
|
error: !!fieldState.error,
|
|
233
243
|
helperText: (_fieldState_error = fieldState.error) === null || _fieldState_error === void 0 ? void 0 : _fieldState_error.message,
|
|
234
|
-
value:
|
|
244
|
+
value: watchedDescription !== null && watchedDescription !== void 0 ? watchedDescription : '',
|
|
235
245
|
onChange: (event)=>{
|
|
236
246
|
field.onChange(event);
|
|
237
247
|
setDescription(event.target.value);
|
|
@@ -262,7 +272,7 @@ function PanelEditorForm(props) {
|
|
|
262
272
|
helperText: (_pluginEditor_error_message = (_pluginEditor_error = pluginEditor.error) === null || _pluginEditor_error === void 0 ? void 0 : _pluginEditor_error.message) !== null && _pluginEditor_error_message !== void 0 ? _pluginEditor_error_message : (_fieldState_error = fieldState.error) === null || _fieldState_error === void 0 ? void 0 : _fieldState_error.message,
|
|
263
273
|
value: {
|
|
264
274
|
type: 'Panel',
|
|
265
|
-
kind:
|
|
275
|
+
kind: watchedPluginKind
|
|
266
276
|
},
|
|
267
277
|
onChange: (event)=>{
|
|
268
278
|
field.onChange(event.kind);
|
|
@@ -219,6 +219,8 @@ function ListVariable({ name, source }) {
|
|
|
219
219
|
const { setVariableValue, setVariableLoading, setVariableOptions } = (0, _context.useVariableDefinitionActions)();
|
|
220
220
|
const { selectedOptions, value, loading, options, viewOptions } = useListVariableState(definition === null || definition === void 0 ? void 0 : definition.spec, ctx.state, variablesOptionsQuery);
|
|
221
221
|
const [inputWidth, setInputWidth] = (0, _react.useState)(_constants.MIN_VARIABLE_WIDTH);
|
|
222
|
+
// Used for multiple value variables, it will not clear variable input when selecting an option
|
|
223
|
+
const [inputValue, setInputValue] = (0, _react.useState)('');
|
|
222
224
|
var _definition_spec_display_name;
|
|
223
225
|
const title = (_definition_spec_display_name = definition === null || definition === void 0 ? void 0 : (_definition_spec_display = definition.spec.display) === null || _definition_spec_display === void 0 ? void 0 : _definition_spec_display.name) !== null && _definition_spec_display_name !== void 0 ? _definition_spec_display_name : name;
|
|
224
226
|
const allowMultiple = (definition === null || definition === void 0 ? void 0 : definition.spec.allowMultiple) === true;
|
|
@@ -270,7 +272,8 @@ function ListVariable({ name, source }) {
|
|
|
270
272
|
renderInput: (params)=>{
|
|
271
273
|
return allowMultiple ? /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.TextField, {
|
|
272
274
|
...params,
|
|
273
|
-
label: title
|
|
275
|
+
label: title,
|
|
276
|
+
onChange: (e)=>setInputValue(e.target.value)
|
|
274
277
|
}) : /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.TextField, {
|
|
275
278
|
...params,
|
|
276
279
|
label: title,
|
|
@@ -295,11 +298,17 @@ function ListVariable({ name, source }) {
|
|
|
295
298
|
setVariableValue(name, variableOptionToVariableValue(value), source);
|
|
296
299
|
}
|
|
297
300
|
},
|
|
301
|
+
inputValue: allowMultiple ? inputValue : undefined,
|
|
298
302
|
onInputChange: (_, newInputValue)=>{
|
|
299
303
|
if (!allowMultiple) {
|
|
300
304
|
setInputWidth(getWidthPx(newInputValue, 'list'));
|
|
301
305
|
}
|
|
302
306
|
},
|
|
307
|
+
onBlur: ()=>{
|
|
308
|
+
if (allowMultiple) {
|
|
309
|
+
setInputValue('');
|
|
310
|
+
}
|
|
311
|
+
},
|
|
303
312
|
options: viewOptions
|
|
304
313
|
}),
|
|
305
314
|
loading && /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.LinearProgress, {})
|
|
@@ -52,6 +52,7 @@ const _zustand = require("zustand");
|
|
|
52
52
|
const _traditional = require("zustand/traditional");
|
|
53
53
|
const _immer = require("zustand/middleware/immer");
|
|
54
54
|
const _middleware = require("zustand/middleware");
|
|
55
|
+
const _shallow = require("zustand/shallow");
|
|
55
56
|
const _immer1 = /*#__PURE__*/ _interop_require_default(require("immer"));
|
|
56
57
|
const _pluginsystem = require("@perses-dev/plugin-system");
|
|
57
58
|
const _core = require("@perses-dev/core");
|
|
@@ -126,7 +127,7 @@ function useVariableDefinitionAndState(name, source) {
|
|
|
126
127
|
}
|
|
127
128
|
function useVariableDefinitionActions() {
|
|
128
129
|
const store = useVariableDefinitionStoreCtx();
|
|
129
|
-
return (0,
|
|
130
|
+
return (0, _traditional.useStoreWithEqualityFn)(store, (s)=>{
|
|
130
131
|
return {
|
|
131
132
|
setVariableValue: s.setVariableValue,
|
|
132
133
|
setVariableLoading: s.setVariableLoading,
|
|
@@ -135,7 +136,7 @@ function useVariableDefinitionActions() {
|
|
|
135
136
|
setVariableDefaultValues: s.setVariableDefaultValues,
|
|
136
137
|
getSavedVariablesStatus: s.getSavedVariablesStatus
|
|
137
138
|
};
|
|
138
|
-
});
|
|
139
|
+
}, _shallow.shallow);
|
|
139
140
|
}
|
|
140
141
|
function useVariableDefinitions() {
|
|
141
142
|
const store = useVariableDefinitionStoreCtx();
|
|
@@ -372,10 +373,10 @@ function createVariableDefinitionStore({ initialVariableDefinitions = [], extern
|
|
|
372
373
|
return store; // TODO: @Gladorme check if we can avoid this cast
|
|
373
374
|
}
|
|
374
375
|
function VariableProvider({ children, initialVariableDefinitions = [], externalVariableDefinitions = [], builtinVariableDefinitions = [] }) {
|
|
375
|
-
const [store] = (0, _react.useState)(createVariableDefinitionStore({
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
376
|
+
const [store] = (0, _react.useState)(()=>createVariableDefinitionStore({
|
|
377
|
+
initialVariableDefinitions,
|
|
378
|
+
externalVariableDefinitions
|
|
379
|
+
}));
|
|
379
380
|
return /*#__PURE__*/ (0, _jsxruntime.jsx)(VariableDefinitionStoreContext.Provider, {
|
|
380
381
|
value: store,
|
|
381
382
|
children: /*#__PURE__*/ (0, _jsxruntime.jsx)(PluginProvider, {
|
|
@@ -387,11 +388,11 @@ function VariableProvider({ children, initialVariableDefinitions = [], externalV
|
|
|
387
388
|
function VariableProviderWithQueryParams({ children, initialVariableDefinitions = [], externalVariableDefinitions = [], builtinVariableDefinitions: builtinVariables = [] }) {
|
|
388
389
|
const allVariableDefs = (0, _utils.mergeVariableDefinitions)(initialVariableDefinitions, externalVariableDefinitions);
|
|
389
390
|
const queryParams = (0, _queryparams.useVariableQueryParams)(allVariableDefs);
|
|
390
|
-
const [store] = (0, _react.useState)(createVariableDefinitionStore({
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
391
|
+
const [store] = (0, _react.useState)(()=>createVariableDefinitionStore({
|
|
392
|
+
initialVariableDefinitions,
|
|
393
|
+
externalVariableDefinitions,
|
|
394
|
+
queryParams
|
|
395
|
+
}));
|
|
395
396
|
return /*#__PURE__*/ (0, _jsxruntime.jsx)(VariableDefinitionStoreContext.Provider, {
|
|
396
397
|
value: store,
|
|
397
398
|
children: /*#__PURE__*/ (0, _jsxruntime.jsx)(PluginProvider, {
|
|
@@ -1,7 +1,3 @@
|
|
|
1
1
|
import { ReactElement } from 'react';
|
|
2
|
-
|
|
3
|
-
heightPx?: number;
|
|
4
|
-
}
|
|
5
|
-
export declare function DownloadButton({ heightPx }: DownloadButtonProps): ReactElement;
|
|
6
|
-
export {};
|
|
2
|
+
export declare function DownloadButton(): ReactElement;
|
|
7
3
|
//# sourceMappingURL=DownloadButton.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DownloadButton.d.ts","sourceRoot":"","sources":["../../../src/components/DownloadButton/DownloadButton.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"DownloadButton.d.ts","sourceRoot":"","sources":["../../../src/components/DownloadButton/DownloadButton.tsx"],"names":[],"mappings":"AAgBA,OAAc,EAAE,YAAY,EAAU,MAAM,OAAO,CAAC;AAKpD,wBAAgB,cAAc,IAAI,YAAY,CAgG7C"}
|
|
@@ -11,49 +11,114 @@
|
|
|
11
11
|
// See the License for the specific language governing permissions and
|
|
12
12
|
// limitations under the License.
|
|
13
13
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
14
|
-
import {
|
|
14
|
+
import { ClickAwayListener, Menu, MenuItem, MenuList } from '@mui/material';
|
|
15
|
+
import { ToolbarIconButton } from '@perses-dev/components';
|
|
15
16
|
import DownloadIcon from 'mdi-material-ui/DownloadOutline';
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
17
|
+
import React, { useRef } from 'react';
|
|
18
|
+
import { stringify } from 'yaml';
|
|
18
19
|
import { useDashboard } from '../../context';
|
|
19
20
|
// Button that enables downloading the dashboard as a JSON file
|
|
20
|
-
export function DownloadButton(
|
|
21
|
+
export function DownloadButton() {
|
|
21
22
|
const { dashboard } = useDashboard();
|
|
22
23
|
const hiddenLinkRef = useRef(null);
|
|
23
|
-
const
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
const hiddenLinkUrl = URL.createObjectURL(new Blob([
|
|
28
|
-
JSON.stringify(dashboard)
|
|
29
|
-
], {
|
|
30
|
-
type: 'application/json'
|
|
31
|
-
}));
|
|
32
|
-
// Simulate click
|
|
33
|
-
hiddenLinkRef.current.href = hiddenLinkUrl;
|
|
34
|
-
hiddenLinkRef.current.click();
|
|
35
|
-
// Remove blob URL (for memory management)
|
|
36
|
-
URL.revokeObjectURL(hiddenLinkUrl);
|
|
24
|
+
const [anchorEl, setAnchorEl] = React.useState(null);
|
|
25
|
+
const open = Boolean(anchorEl);
|
|
26
|
+
const handleClick = (event)=>{
|
|
27
|
+
setAnchorEl(event.currentTarget);
|
|
37
28
|
};
|
|
29
|
+
const handleItemClick = (format, shape)=>()=>{
|
|
30
|
+
setAnchorEl(null);
|
|
31
|
+
let type, content = '';
|
|
32
|
+
switch(format){
|
|
33
|
+
case 'json':
|
|
34
|
+
type = 'application/json';
|
|
35
|
+
content = JSON.stringify(dashboard, null, 2);
|
|
36
|
+
break;
|
|
37
|
+
case 'yaml':
|
|
38
|
+
{
|
|
39
|
+
type = 'application/yaml';
|
|
40
|
+
if (shape === 'cr') {
|
|
41
|
+
const name = dashboard.metadata.name.toLowerCase().replace(/[^a-z0-9-]/g, '-');
|
|
42
|
+
content = stringify({
|
|
43
|
+
apiVersion: 'perses.dev/v1alpha1',
|
|
44
|
+
kind: 'PersesDashboard',
|
|
45
|
+
metadata: {
|
|
46
|
+
labels: {
|
|
47
|
+
'app.kubernetes.io/name': 'perses-dashboard',
|
|
48
|
+
'app.kubernetes.io/instance': name,
|
|
49
|
+
'app.kubernetes.io/part-of': 'perses-operator'
|
|
50
|
+
},
|
|
51
|
+
name
|
|
52
|
+
},
|
|
53
|
+
namespace: dashboard.metadata.project,
|
|
54
|
+
spec: dashboard.spec
|
|
55
|
+
});
|
|
56
|
+
} else {
|
|
57
|
+
content = stringify(dashboard);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
if (!hiddenLinkRef || !hiddenLinkRef.current) return;
|
|
63
|
+
// Create blob URL
|
|
64
|
+
const hiddenLinkUrl = URL.createObjectURL(new Blob([
|
|
65
|
+
content
|
|
66
|
+
], {
|
|
67
|
+
type
|
|
68
|
+
}));
|
|
69
|
+
// Simulate click
|
|
70
|
+
hiddenLinkRef.current.download = `${dashboard.metadata.name}${shape === 'cr' ? '-cr' : ''}.${format}`;
|
|
71
|
+
hiddenLinkRef.current.href = hiddenLinkUrl;
|
|
72
|
+
hiddenLinkRef.current.click();
|
|
73
|
+
// Remove blob URL (for memory management)
|
|
74
|
+
URL.revokeObjectURL(hiddenLinkUrl);
|
|
75
|
+
};
|
|
38
76
|
return /*#__PURE__*/ _jsxs(_Fragment, {
|
|
39
77
|
children: [
|
|
40
|
-
/*#__PURE__*/ _jsx(
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
78
|
+
/*#__PURE__*/ _jsx(ToolbarIconButton, {
|
|
79
|
+
id: "download-dashboard-button",
|
|
80
|
+
"aria-controls": open ? 'basic-menu' : undefined,
|
|
81
|
+
"aria-haspopup": "true",
|
|
82
|
+
"aria-expanded": open ? 'true' : undefined,
|
|
83
|
+
onClick: handleClick,
|
|
84
|
+
children: /*#__PURE__*/ _jsx(DownloadIcon, {})
|
|
85
|
+
}),
|
|
86
|
+
/*#__PURE__*/ _jsx(Menu, {
|
|
87
|
+
id: "download-dashboard-formats",
|
|
88
|
+
anchorEl: anchorEl,
|
|
89
|
+
open: open,
|
|
90
|
+
hideBackdrop: true,
|
|
91
|
+
onClose: ()=>setAnchorEl(null),
|
|
92
|
+
MenuListProps: {
|
|
93
|
+
'aria-labelledby': 'download-dashboard-button'
|
|
94
|
+
},
|
|
95
|
+
children: /*#__PURE__*/ _jsx("div", {
|
|
96
|
+
children: /*#__PURE__*/ _jsx(ClickAwayListener, {
|
|
97
|
+
onClickAway: ()=>setAnchorEl(null),
|
|
98
|
+
children: /*#__PURE__*/ _jsxs(MenuList, {
|
|
99
|
+
children: [
|
|
100
|
+
/*#__PURE__*/ _jsx(MenuItem, {
|
|
101
|
+
onClick: handleItemClick('json'),
|
|
102
|
+
children: "JSON"
|
|
103
|
+
}),
|
|
104
|
+
/*#__PURE__*/ _jsx(MenuItem, {
|
|
105
|
+
onClick: handleItemClick('yaml'),
|
|
106
|
+
children: "YAML"
|
|
107
|
+
}),
|
|
108
|
+
/*#__PURE__*/ _jsx(MenuItem, {
|
|
109
|
+
onClick: handleItemClick('yaml', 'cr'),
|
|
110
|
+
children: "YAML (CR)"
|
|
111
|
+
})
|
|
112
|
+
]
|
|
113
|
+
})
|
|
114
|
+
})
|
|
49
115
|
})
|
|
50
116
|
}),
|
|
51
117
|
/*#__PURE__*/ _jsx("a", {
|
|
52
118
|
ref: hiddenLinkRef,
|
|
53
119
|
style: {
|
|
54
120
|
display: 'none'
|
|
55
|
-
}
|
|
56
|
-
download: `${dashboard.metadata.name}.json`
|
|
121
|
+
}
|
|
57
122
|
})
|
|
58
123
|
]
|
|
59
124
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/DownloadButton/DownloadButton.tsx"],"sourcesContent":["// Copyright 2023 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 {
|
|
1
|
+
{"version":3,"sources":["../../../src/components/DownloadButton/DownloadButton.tsx"],"sourcesContent":["// Copyright 2023 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 { ClickAwayListener, Menu, MenuItem, MenuList } from '@mui/material';\nimport { ToolbarIconButton } from '@perses-dev/components';\nimport DownloadIcon from 'mdi-material-ui/DownloadOutline';\nimport React, { ReactElement, useRef } from 'react';\nimport { stringify } from 'yaml';\nimport { useDashboard } from '../../context';\n\n// Button that enables downloading the dashboard as a JSON file\nexport function DownloadButton(): ReactElement {\n const { dashboard } = useDashboard();\n const hiddenLinkRef = useRef<HTMLAnchorElement>(null);\n const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);\n const open = Boolean(anchorEl);\n const handleClick = (event: React.MouseEvent<HTMLButtonElement>): void => {\n setAnchorEl(event.currentTarget);\n };\n const handleItemClick = (format: 'json' | 'yaml', shape?: 'cr') => (): void => {\n setAnchorEl(null);\n\n let type,\n content = '';\n\n switch (format) {\n case 'json':\n type = 'application/json';\n content = JSON.stringify(dashboard, null, 2);\n break;\n case 'yaml':\n {\n type = 'application/yaml';\n\n if (shape === 'cr') {\n const name = dashboard.metadata.name.toLowerCase().replace(/[^a-z0-9-]/g, '-');\n content = stringify({\n apiVersion: 'perses.dev/v1alpha1',\n kind: 'PersesDashboard',\n metadata: {\n labels: {\n 'app.kubernetes.io/name': 'perses-dashboard',\n 'app.kubernetes.io/instance': name,\n 'app.kubernetes.io/part-of': 'perses-operator',\n },\n name,\n },\n namespace: dashboard.metadata.project,\n spec: dashboard.spec,\n });\n } else {\n content = stringify(dashboard);\n }\n }\n break;\n }\n\n if (!hiddenLinkRef || !hiddenLinkRef.current) return;\n // Create blob URL\n const hiddenLinkUrl = URL.createObjectURL(new Blob([content], { type }));\n // Simulate click\n hiddenLinkRef.current.download = `${dashboard.metadata.name}${shape === 'cr' ? '-cr' : ''}.${format}`;\n hiddenLinkRef.current.href = hiddenLinkUrl;\n hiddenLinkRef.current.click();\n // Remove blob URL (for memory management)\n URL.revokeObjectURL(hiddenLinkUrl);\n };\n\n return (\n <>\n <ToolbarIconButton\n id=\"download-dashboard-button\"\n aria-controls={open ? 'basic-menu' : undefined}\n aria-haspopup=\"true\"\n aria-expanded={open ? 'true' : undefined}\n onClick={handleClick}\n >\n <DownloadIcon />\n </ToolbarIconButton>\n\n <Menu\n id=\"download-dashboard-formats\"\n anchorEl={anchorEl}\n open={open}\n hideBackdrop={true}\n onClose={() => setAnchorEl(null)}\n MenuListProps={{\n 'aria-labelledby': 'download-dashboard-button',\n }}\n >\n <div>\n <ClickAwayListener onClickAway={() => setAnchorEl(null)}>\n <MenuList>\n <MenuItem onClick={handleItemClick('json')}>JSON</MenuItem>\n <MenuItem onClick={handleItemClick('yaml')}>YAML</MenuItem>\n <MenuItem onClick={handleItemClick('yaml', 'cr')}>YAML (CR)</MenuItem>\n </MenuList>\n </ClickAwayListener>\n </div>\n </Menu>\n\n {/* Hidden link to download the dashboard as a JSON or YAML file */}\n {/* eslint-disable jsx-a11y/anchor-has-content */}\n {/* eslint-disable jsx-a11y/anchor-is-valid */}\n <a ref={hiddenLinkRef} style={{ display: 'none' }} />\n </>\n );\n}\n"],"names":["ClickAwayListener","Menu","MenuItem","MenuList","ToolbarIconButton","DownloadIcon","React","useRef","stringify","useDashboard","DownloadButton","dashboard","hiddenLinkRef","anchorEl","setAnchorEl","useState","open","Boolean","handleClick","event","currentTarget","handleItemClick","format","shape","type","content","JSON","name","metadata","toLowerCase","replace","apiVersion","kind","labels","namespace","project","spec","current","hiddenLinkUrl","URL","createObjectURL","Blob","download","href","click","revokeObjectURL","id","aria-controls","undefined","aria-haspopup","aria-expanded","onClick","hideBackdrop","onClose","MenuListProps","div","onClickAway","a","ref","style","display"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PanelEditorForm.d.ts","sourceRoot":"","sources":["../../../src/components/PanelDrawer/PanelEditorForm.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAE,YAAY,EAAuB,MAAM,OAAO,CAAC;AAE1D,OAAO,EAAE,MAAM,EAAmB,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAgB9E,MAAM,WAAW,oBAAoB;IACnC,aAAa,EAAE,iBAAiB,CAAC;IACjC,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,CAAC,MAAM,EAAE,iBAAiB,KAAK,IAAI,CAAC;IAC5C,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,GAAG,YAAY,
|
|
1
|
+
{"version":3,"file":"PanelEditorForm.d.ts","sourceRoot":"","sources":["../../../src/components/PanelDrawer/PanelEditorForm.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAE,YAAY,EAAuB,MAAM,OAAO,CAAC;AAE1D,OAAO,EAAE,MAAM,EAAmB,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAgB9E,MAAM,WAAW,oBAAoB;IACnC,aAAa,EAAE,iBAAiB,CAAC;IACjC,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,CAAC,MAAM,EAAE,iBAAiB,KAAK,IAAI,CAAC;IAC5C,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,GAAG,YAAY,CA8NzE;AAED;;GAEG;AACH,eAAO,MAAM,iBAAiB,sBAAsB,CAAC"}
|