@perses-dev/dashboards 0.52.0-rc.0 → 0.52.0
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/LeaveDialog/LeaveDialog.js +45 -17
- package/dist/cjs/components/Panel/PanelActions.js +1 -1
- package/dist/cjs/components/PanelDrawer/PanelEditorForm.js +204 -185
- package/dist/cjs/components/Variables/VariableEditor.js +22 -15
- package/dist/cjs/context/DashboardProvider/DashboardProviderWithQueryParams.js +1 -1
- package/dist/cjs/context/DashboardProvider/duplicate-panel-slice.js +1 -1
- package/dist/cjs/context/DashboardProvider/panel-editor-slice.js +1 -2
- package/dist/components/LeaveDialog/LeaveDialog.d.ts +6 -1
- package/dist/components/LeaveDialog/LeaveDialog.d.ts.map +1 -1
- package/dist/components/LeaveDialog/LeaveDialog.js +40 -15
- package/dist/components/LeaveDialog/LeaveDialog.js.map +1 -1
- package/dist/components/Panel/HeaderIconButton.d.ts +1 -1
- package/dist/components/Panel/PanelActions.js +1 -1
- package/dist/components/Panel/PanelActions.js.map +1 -1
- package/dist/components/PanelDrawer/PanelEditorForm.d.ts.map +1 -1
- package/dist/components/PanelDrawer/PanelEditorForm.js +207 -188
- package/dist/components/PanelDrawer/PanelEditorForm.js.map +1 -1
- package/dist/components/Variables/VariableEditor.d.ts.map +1 -1
- package/dist/components/Variables/VariableEditor.js +24 -17
- package/dist/components/Variables/VariableEditor.js.map +1 -1
- package/dist/context/DashboardProvider/DashboardProviderWithQueryParams.d.ts.map +1 -1
- package/dist/context/DashboardProvider/DashboardProviderWithQueryParams.js +1 -1
- package/dist/context/DashboardProvider/DashboardProviderWithQueryParams.js.map +1 -1
- package/dist/context/DashboardProvider/duplicate-panel-slice.js +2 -2
- package/dist/context/DashboardProvider/duplicate-panel-slice.js.map +1 -1
- package/dist/context/DashboardProvider/panel-editor-slice.d.ts.map +1 -1
- package/dist/context/DashboardProvider/panel-editor-slice.js +2 -3
- package/dist/context/DashboardProvider/panel-editor-slice.js.map +1 -1
- package/dist/utils/panelUtils.d.ts +3 -0
- package/dist/utils/panelUtils.d.ts.map +1 -1
- package/dist/utils/panelUtils.js +3 -0
- package/dist/utils/panelUtils.js.map +1 -1
- package/package.json +6 -6
|
@@ -11,17 +11,19 @@
|
|
|
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 } from "react/jsx-runtime";
|
|
14
|
-
import { useEffect, useState } from 'react';
|
|
14
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
15
15
|
import { Box, Button, Grid, MenuItem, Stack, TextField, Typography } from '@mui/material';
|
|
16
|
+
import { DEFAULT_DASHBOARD_DURATION } from '@perses-dev/core';
|
|
16
17
|
import { DiscardChangesConfirmationDialog, ErrorAlert, ErrorBoundary } from '@perses-dev/components';
|
|
17
|
-
import { PluginKindSelect, usePluginEditor, PanelSpecEditor, getTitleAction, getSubmitText, useValidationSchemas } from '@perses-dev/plugin-system';
|
|
18
|
+
import { PluginKindSelect, usePluginEditor, PanelSpecEditor, getTitleAction, getSubmitText, useValidationSchemas, TimeRangeProvider, useTimeRangeParams, useInitialTimeRange } from '@perses-dev/plugin-system';
|
|
18
19
|
import { Controller, FormProvider, useForm, useWatch } from 'react-hook-form';
|
|
19
20
|
import { zodResolver } from '@hookform/resolvers/zod';
|
|
20
|
-
import { useListPanelGroups } from '../../context';
|
|
21
|
+
import { useDashboard, useListPanelGroups } from '../../context';
|
|
21
22
|
import { PanelPreview } from './PanelPreview';
|
|
22
23
|
import { usePanelEditor } from './usePanelEditor';
|
|
23
24
|
export function PanelEditorForm(props) {
|
|
24
25
|
const { initialValues, initialAction, onSave, onClose } = props;
|
|
26
|
+
const pluginEditorRef = useRef(null);
|
|
25
27
|
const panelGroups = useListPanelGroups();
|
|
26
28
|
const { panelDefinition, setName, setDescription, setLinks, setQueries, setPlugin, setPanelDefinition } = usePanelEditor(initialValues.panelDefinition);
|
|
27
29
|
const { plugin } = panelDefinition.spec;
|
|
@@ -32,6 +34,9 @@ export function PanelEditorForm(props) {
|
|
|
32
34
|
mode: 'onBlur',
|
|
33
35
|
defaultValues: initialValues
|
|
34
36
|
});
|
|
37
|
+
const { dashboard } = useDashboard();
|
|
38
|
+
const dashboardDuration = dashboard?.kind === 'Dashboard' ? dashboard.spec.duration : DEFAULT_DASHBOARD_DURATION;
|
|
39
|
+
const initialTimeRange = useInitialTimeRange(dashboardDuration);
|
|
35
40
|
// Use common plugin editor logic even though we've split the inputs up in this form
|
|
36
41
|
const pluginEditor = usePluginEditor({
|
|
37
42
|
pluginTypes: [
|
|
@@ -70,9 +75,11 @@ export function PanelEditorForm(props) {
|
|
|
70
75
|
setLinks,
|
|
71
76
|
links
|
|
72
77
|
]);
|
|
73
|
-
const processForm = (data)=>{
|
|
78
|
+
const processForm = useCallback((data)=>{
|
|
74
79
|
onSave(data);
|
|
75
|
-
}
|
|
80
|
+
}, [
|
|
81
|
+
onSave
|
|
82
|
+
]);
|
|
76
83
|
// When user click on cancel, several possibilities:
|
|
77
84
|
// - create action: ask for discard approval
|
|
78
85
|
// - update action: ask for discard approval if changed
|
|
@@ -105,199 +112,211 @@ export function PanelEditorForm(props) {
|
|
|
105
112
|
control: form.control,
|
|
106
113
|
name: 'panelDefinition.spec.plugin.kind'
|
|
107
114
|
});
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
spacing: 1,
|
|
129
|
-
marginLeft: "auto",
|
|
130
|
-
children: [
|
|
131
|
-
/*#__PURE__*/ _jsx(Button, {
|
|
132
|
-
variant: "contained",
|
|
133
|
-
disabled: !form.formState.isValid,
|
|
134
|
-
onClick: form.handleSubmit(processForm),
|
|
135
|
-
children: submitText
|
|
136
|
-
}),
|
|
137
|
-
/*#__PURE__*/ _jsx(Button, {
|
|
138
|
-
color: "secondary",
|
|
139
|
-
variant: "outlined",
|
|
140
|
-
onClick: handleCancel,
|
|
141
|
-
children: "Cancel"
|
|
142
|
-
})
|
|
143
|
-
]
|
|
144
|
-
})
|
|
145
|
-
]
|
|
146
|
-
}),
|
|
147
|
-
/*#__PURE__*/ _jsx(Box, {
|
|
148
|
-
id: panelEditorFormId,
|
|
149
|
-
sx: {
|
|
150
|
-
flex: 1,
|
|
151
|
-
overflowY: 'scroll',
|
|
152
|
-
padding: (theme)=>theme.spacing(2)
|
|
153
|
-
},
|
|
154
|
-
children: /*#__PURE__*/ _jsxs(Grid, {
|
|
155
|
-
container: true,
|
|
156
|
-
spacing: 2,
|
|
115
|
+
const { timeRange } = useTimeRangeParams(initialTimeRange);
|
|
116
|
+
const handleSubmit = useCallback(()=>{
|
|
117
|
+
pluginEditorRef.current?.flushChanges?.();
|
|
118
|
+
form.handleSubmit(processForm)();
|
|
119
|
+
}, [
|
|
120
|
+
form,
|
|
121
|
+
processForm
|
|
122
|
+
]);
|
|
123
|
+
return /*#__PURE__*/ _jsx(TimeRangeProvider, {
|
|
124
|
+
timeRange: timeRange,
|
|
125
|
+
children: /*#__PURE__*/ _jsxs(FormProvider, {
|
|
126
|
+
...form,
|
|
127
|
+
children: [
|
|
128
|
+
/*#__PURE__*/ _jsxs(Box, {
|
|
129
|
+
sx: {
|
|
130
|
+
display: 'flex',
|
|
131
|
+
alignItems: 'center',
|
|
132
|
+
padding: (theme)=>theme.spacing(1, 2),
|
|
133
|
+
borderBottom: (theme)=>`1px solid ${theme.palette.divider}`
|
|
134
|
+
},
|
|
157
135
|
children: [
|
|
158
|
-
/*#__PURE__*/
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
render: ({ field, fieldState })=>/*#__PURE__*/ _jsx(TextField, {
|
|
165
|
-
...field,
|
|
166
|
-
required: true,
|
|
167
|
-
fullWidth: true,
|
|
168
|
-
label: "Name",
|
|
169
|
-
error: !!fieldState.error,
|
|
170
|
-
helperText: fieldState.error?.message,
|
|
171
|
-
value: watchedName ?? '',
|
|
172
|
-
onChange: (event)=>{
|
|
173
|
-
field.onChange(event);
|
|
174
|
-
setName(event.target.value);
|
|
175
|
-
}
|
|
176
|
-
})
|
|
177
|
-
})
|
|
178
|
-
}),
|
|
179
|
-
/*#__PURE__*/ _jsx(Grid, {
|
|
180
|
-
item: true,
|
|
181
|
-
xs: 4,
|
|
182
|
-
children: /*#__PURE__*/ _jsx(Controller, {
|
|
183
|
-
control: form.control,
|
|
184
|
-
name: "groupId",
|
|
185
|
-
render: ({ field, fieldState })=>/*#__PURE__*/ _jsx(TextField, {
|
|
186
|
-
select: true,
|
|
187
|
-
...field,
|
|
188
|
-
required: true,
|
|
189
|
-
fullWidth: true,
|
|
190
|
-
label: "Group",
|
|
191
|
-
error: !!fieldState.error,
|
|
192
|
-
helperText: fieldState.error?.message,
|
|
193
|
-
onChange: (event)=>{
|
|
194
|
-
field.onChange(event);
|
|
195
|
-
},
|
|
196
|
-
children: panelGroups.map((panelGroup, index)=>/*#__PURE__*/ _jsx(MenuItem, {
|
|
197
|
-
value: panelGroup.id,
|
|
198
|
-
children: panelGroup.title ?? `Group ${index + 1}`
|
|
199
|
-
}, panelGroup.id))
|
|
200
|
-
})
|
|
201
|
-
})
|
|
202
|
-
}),
|
|
203
|
-
/*#__PURE__*/ _jsx(Grid, {
|
|
204
|
-
item: true,
|
|
205
|
-
xs: 8,
|
|
206
|
-
children: /*#__PURE__*/ _jsx(Controller, {
|
|
207
|
-
control: form.control,
|
|
208
|
-
name: "panelDefinition.spec.display.description",
|
|
209
|
-
render: ({ field, fieldState })=>/*#__PURE__*/ _jsx(TextField, {
|
|
210
|
-
...field,
|
|
211
|
-
fullWidth: true,
|
|
212
|
-
label: "Description",
|
|
213
|
-
error: !!fieldState.error,
|
|
214
|
-
helperText: fieldState.error?.message,
|
|
215
|
-
value: watchedDescription ?? '',
|
|
216
|
-
onChange: (event)=>{
|
|
217
|
-
field.onChange(event);
|
|
218
|
-
setDescription(event.target.value);
|
|
219
|
-
}
|
|
220
|
-
})
|
|
221
|
-
})
|
|
222
|
-
}),
|
|
223
|
-
/*#__PURE__*/ _jsx(Grid, {
|
|
224
|
-
item: true,
|
|
225
|
-
xs: 4,
|
|
226
|
-
children: /*#__PURE__*/ _jsx(Controller, {
|
|
227
|
-
control: form.control,
|
|
228
|
-
name: "panelDefinition.spec.plugin.kind",
|
|
229
|
-
render: ({ field, fieldState })=>/*#__PURE__*/ _jsx(PluginKindSelect, {
|
|
230
|
-
...field,
|
|
231
|
-
pluginTypes: [
|
|
232
|
-
'Panel'
|
|
233
|
-
],
|
|
234
|
-
required: true,
|
|
235
|
-
fullWidth: true,
|
|
236
|
-
label: "Type",
|
|
237
|
-
disabled: pluginEditor.isLoading,
|
|
238
|
-
error: !!pluginEditor.error || !!fieldState.error,
|
|
239
|
-
helperText: pluginEditor.error?.message ?? fieldState.error?.message,
|
|
240
|
-
value: {
|
|
241
|
-
type: 'Panel',
|
|
242
|
-
kind: watchedPluginKind
|
|
243
|
-
},
|
|
244
|
-
onChange: (event)=>{
|
|
245
|
-
field.onChange(event.kind);
|
|
246
|
-
pluginEditor.onSelectionChange(event);
|
|
247
|
-
}
|
|
248
|
-
})
|
|
249
|
-
})
|
|
136
|
+
/*#__PURE__*/ _jsxs(Typography, {
|
|
137
|
+
variant: "h2",
|
|
138
|
+
children: [
|
|
139
|
+
titleAction,
|
|
140
|
+
" Panel"
|
|
141
|
+
]
|
|
250
142
|
}),
|
|
251
|
-
/*#__PURE__*/ _jsxs(
|
|
252
|
-
|
|
253
|
-
|
|
143
|
+
/*#__PURE__*/ _jsxs(Stack, {
|
|
144
|
+
direction: "row",
|
|
145
|
+
spacing: 1,
|
|
146
|
+
marginLeft: "auto",
|
|
254
147
|
children: [
|
|
255
|
-
/*#__PURE__*/ _jsx(
|
|
256
|
-
variant: "
|
|
257
|
-
|
|
258
|
-
|
|
148
|
+
/*#__PURE__*/ _jsx(Button, {
|
|
149
|
+
variant: "contained",
|
|
150
|
+
disabled: !form.formState.isValid,
|
|
151
|
+
onClick: handleSubmit,
|
|
152
|
+
children: submitText
|
|
259
153
|
}),
|
|
260
|
-
/*#__PURE__*/ _jsx(
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
154
|
+
/*#__PURE__*/ _jsx(Button, {
|
|
155
|
+
color: "secondary",
|
|
156
|
+
variant: "outlined",
|
|
157
|
+
onClick: handleCancel,
|
|
158
|
+
children: "Cancel"
|
|
265
159
|
})
|
|
266
160
|
]
|
|
267
|
-
})
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
161
|
+
})
|
|
162
|
+
]
|
|
163
|
+
}),
|
|
164
|
+
/*#__PURE__*/ _jsx(Box, {
|
|
165
|
+
id: panelEditorFormId,
|
|
166
|
+
sx: {
|
|
167
|
+
flex: 1,
|
|
168
|
+
overflowY: 'scroll',
|
|
169
|
+
padding: (theme)=>theme.spacing(2)
|
|
170
|
+
},
|
|
171
|
+
children: /*#__PURE__*/ _jsxs(Grid, {
|
|
172
|
+
container: true,
|
|
173
|
+
spacing: 2,
|
|
174
|
+
children: [
|
|
175
|
+
/*#__PURE__*/ _jsx(Grid, {
|
|
176
|
+
item: true,
|
|
177
|
+
xs: 8,
|
|
178
|
+
children: /*#__PURE__*/ _jsx(Controller, {
|
|
179
|
+
control: form.control,
|
|
180
|
+
name: "panelDefinition.spec.display.name",
|
|
181
|
+
render: ({ field, fieldState })=>/*#__PURE__*/ _jsx(TextField, {
|
|
182
|
+
...field,
|
|
183
|
+
required: true,
|
|
184
|
+
fullWidth: true,
|
|
185
|
+
label: "Name",
|
|
186
|
+
error: !!fieldState.error,
|
|
187
|
+
helperText: fieldState.error?.message,
|
|
188
|
+
value: watchedName ?? '',
|
|
189
|
+
onChange: (event)=>{
|
|
190
|
+
field.onChange(event);
|
|
191
|
+
setName(event.target.value);
|
|
192
|
+
}
|
|
193
|
+
})
|
|
194
|
+
})
|
|
195
|
+
}),
|
|
196
|
+
/*#__PURE__*/ _jsx(Grid, {
|
|
197
|
+
item: true,
|
|
198
|
+
xs: 4,
|
|
199
|
+
children: /*#__PURE__*/ _jsx(Controller, {
|
|
200
|
+
control: form.control,
|
|
201
|
+
name: "groupId",
|
|
202
|
+
render: ({ field, fieldState })=>/*#__PURE__*/ _jsx(TextField, {
|
|
203
|
+
select: true,
|
|
204
|
+
...field,
|
|
205
|
+
required: true,
|
|
206
|
+
fullWidth: true,
|
|
207
|
+
label: "Group",
|
|
208
|
+
error: !!fieldState.error,
|
|
209
|
+
helperText: fieldState.error?.message,
|
|
210
|
+
onChange: (event)=>{
|
|
211
|
+
field.onChange(event);
|
|
212
|
+
},
|
|
213
|
+
children: panelGroups.map((panelGroup, index)=>/*#__PURE__*/ _jsx(MenuItem, {
|
|
214
|
+
value: panelGroup.id,
|
|
215
|
+
children: panelGroup.title ?? `Group ${index + 1}`
|
|
216
|
+
}, panelGroup.id))
|
|
217
|
+
})
|
|
218
|
+
})
|
|
219
|
+
}),
|
|
220
|
+
/*#__PURE__*/ _jsx(Grid, {
|
|
221
|
+
item: true,
|
|
222
|
+
xs: 8,
|
|
223
|
+
children: /*#__PURE__*/ _jsx(Controller, {
|
|
224
|
+
control: form.control,
|
|
225
|
+
name: "panelDefinition.spec.display.description",
|
|
226
|
+
render: ({ field, fieldState })=>/*#__PURE__*/ _jsx(TextField, {
|
|
227
|
+
...field,
|
|
228
|
+
fullWidth: true,
|
|
229
|
+
label: "Description",
|
|
230
|
+
error: !!fieldState.error,
|
|
231
|
+
helperText: fieldState.error?.message,
|
|
232
|
+
value: watchedDescription ?? '',
|
|
233
|
+
onChange: (event)=>{
|
|
234
|
+
field.onChange(event);
|
|
235
|
+
setDescription(event.target.value);
|
|
236
|
+
}
|
|
237
|
+
})
|
|
238
|
+
})
|
|
239
|
+
}),
|
|
240
|
+
/*#__PURE__*/ _jsx(Grid, {
|
|
241
|
+
item: true,
|
|
242
|
+
xs: 4,
|
|
243
|
+
children: /*#__PURE__*/ _jsx(Controller, {
|
|
274
244
|
control: form.control,
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
245
|
+
name: "panelDefinition.spec.plugin.kind",
|
|
246
|
+
render: ({ field, fieldState })=>/*#__PURE__*/ _jsx(PluginKindSelect, {
|
|
247
|
+
...field,
|
|
248
|
+
pluginTypes: [
|
|
249
|
+
'Panel'
|
|
250
|
+
],
|
|
251
|
+
required: true,
|
|
252
|
+
fullWidth: true,
|
|
253
|
+
label: "Type",
|
|
254
|
+
disabled: pluginEditor.isLoading,
|
|
255
|
+
error: !!pluginEditor.error || !!fieldState.error,
|
|
256
|
+
helperText: pluginEditor.error?.message ?? fieldState.error?.message,
|
|
257
|
+
value: {
|
|
258
|
+
type: 'Panel',
|
|
259
|
+
kind: watchedPluginKind
|
|
260
|
+
},
|
|
261
|
+
onChange: (event)=>{
|
|
262
|
+
field.onChange(event.kind);
|
|
263
|
+
pluginEditor.onSelectionChange(event);
|
|
264
|
+
}
|
|
265
|
+
})
|
|
266
|
+
})
|
|
267
|
+
}),
|
|
268
|
+
/*#__PURE__*/ _jsxs(Grid, {
|
|
269
|
+
item: true,
|
|
270
|
+
xs: 12,
|
|
271
|
+
children: [
|
|
272
|
+
/*#__PURE__*/ _jsx(Typography, {
|
|
273
|
+
variant: "h4",
|
|
274
|
+
marginBottom: 1,
|
|
275
|
+
children: "Preview"
|
|
276
|
+
}),
|
|
277
|
+
/*#__PURE__*/ _jsx(ErrorBoundary, {
|
|
278
|
+
FallbackComponent: ErrorAlert,
|
|
279
|
+
children: /*#__PURE__*/ _jsx(PanelPreview, {
|
|
280
|
+
panelDefinition: panelDefinition
|
|
281
|
+
})
|
|
282
|
+
})
|
|
283
|
+
]
|
|
284
|
+
}),
|
|
285
|
+
/*#__PURE__*/ _jsx(Grid, {
|
|
286
|
+
item: true,
|
|
287
|
+
xs: 12,
|
|
288
|
+
children: /*#__PURE__*/ _jsx(ErrorBoundary, {
|
|
289
|
+
FallbackComponent: ErrorAlert,
|
|
290
|
+
children: /*#__PURE__*/ _jsx(PanelSpecEditor, {
|
|
291
|
+
ref: pluginEditorRef,
|
|
292
|
+
control: form.control,
|
|
293
|
+
panelDefinition: panelDefinition,
|
|
294
|
+
onJSONChange: handlePanelDefinitionChange,
|
|
295
|
+
onQueriesChange: (queries)=>{
|
|
296
|
+
setQueries(queries);
|
|
297
|
+
},
|
|
298
|
+
onPluginSpecChange: (spec)=>{
|
|
299
|
+
pluginEditor.onSpecChange(spec);
|
|
300
|
+
}
|
|
301
|
+
})
|
|
283
302
|
})
|
|
284
303
|
})
|
|
285
|
-
|
|
286
|
-
|
|
304
|
+
]
|
|
305
|
+
})
|
|
306
|
+
}),
|
|
307
|
+
/*#__PURE__*/ _jsx(DiscardChangesConfirmationDialog, {
|
|
308
|
+
description: "You have unapplied changes in this panel. Are you sure you want to discard these changes? Changes cannot be recovered.",
|
|
309
|
+
isOpen: isDiscardDialogOpened,
|
|
310
|
+
onCancel: ()=>{
|
|
311
|
+
setDiscardDialogOpened(false);
|
|
312
|
+
},
|
|
313
|
+
onDiscardChanges: ()=>{
|
|
314
|
+
setDiscardDialogOpened(false);
|
|
315
|
+
onClose();
|
|
316
|
+
}
|
|
287
317
|
})
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
description: "You have unapplied changes in this panel. Are you sure you want to discard these changes? Changes cannot be recovered.",
|
|
291
|
-
isOpen: isDiscardDialogOpened,
|
|
292
|
-
onCancel: ()=>{
|
|
293
|
-
setDiscardDialogOpened(false);
|
|
294
|
-
},
|
|
295
|
-
onDiscardChanges: ()=>{
|
|
296
|
-
setDiscardDialogOpened(false);
|
|
297
|
-
onClose();
|
|
298
|
-
}
|
|
299
|
-
})
|
|
300
|
-
]
|
|
318
|
+
]
|
|
319
|
+
})
|
|
301
320
|
});
|
|
302
321
|
}
|
|
303
322
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/PanelDrawer/PanelEditorForm.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 { ReactElement, useEffect, useState } from 'react';\nimport { Box, Button, Grid, MenuItem, Stack, TextField, Typography } from '@mui/material';\nimport { Action, PanelDefinition, PanelEditorValues } from '@perses-dev/core';\nimport { DiscardChangesConfirmationDialog, ErrorAlert, ErrorBoundary } from '@perses-dev/components';\nimport {\n PluginKindSelect,\n usePluginEditor,\n PanelSpecEditor,\n getTitleAction,\n getSubmitText,\n useValidationSchemas,\n} from '@perses-dev/plugin-system';\nimport { Controller, FormProvider, SubmitHandler, useForm, useWatch } from 'react-hook-form';\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { useListPanelGroups } from '../../context';\nimport { PanelPreview } from './PanelPreview';\nimport { usePanelEditor } from './usePanelEditor';\n\nexport interface PanelEditorFormProps {\n initialValues: PanelEditorValues;\n initialAction: Action;\n onSave: (values: PanelEditorValues) => void;\n onClose: () => void;\n}\n\nexport function PanelEditorForm(props: PanelEditorFormProps): ReactElement {\n const { initialValues, initialAction, onSave, onClose } = props;\n const panelGroups = useListPanelGroups();\n const { panelDefinition, setName, setDescription, setLinks, setQueries, setPlugin, setPanelDefinition } =\n usePanelEditor(initialValues.panelDefinition);\n const { plugin } = panelDefinition.spec;\n const [isDiscardDialogOpened, setDiscardDialogOpened] = useState<boolean>(false);\n\n const { panelEditorSchema } = useValidationSchemas();\n const form = useForm<PanelEditorValues>({\n resolver: zodResolver(panelEditorSchema),\n mode: 'onBlur',\n defaultValues: initialValues,\n });\n\n // Use common plugin editor logic even though we've split the inputs up in this form\n const pluginEditor = usePluginEditor({\n pluginTypes: ['Panel'],\n value: { selection: { kind: plugin.kind, type: 'Panel' }, spec: plugin.spec },\n onChange: (plugin) => {\n form.setValue('panelDefinition.spec.plugin', { kind: plugin.selection.kind, spec: plugin.spec });\n setPlugin({\n kind: plugin.selection.kind,\n spec: plugin.spec,\n });\n },\n onHideQueryEditorChange: (isHidden) => {\n setQueries(undefined, isHidden);\n },\n });\n\n const titleAction = getTitleAction(initialAction, true);\n const submitText = getSubmitText(initialAction, true);\n\n const links = useWatch({ control: form.control, name: 'panelDefinition.spec.links' });\n useEffect(() => {\n setLinks(links);\n }, [setLinks, links]);\n\n const processForm: SubmitHandler<PanelEditorValues> = (data) => {\n onSave(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(initialValues) !== JSON.stringify(form.getValues())) {\n setDiscardDialogOpened(true);\n } else {\n onClose();\n }\n }\n\n const handlePanelDefinitionChange = (nextPanelDefStr: string): void => {\n const nextPanelDef: PanelDefinition = JSON.parse(nextPanelDefStr);\n const { kind: pluginKind, spec: pluginSpec } = nextPanelDef.spec.plugin;\n // if panel plugin kind and spec are modified, then need to save current spec\n if (\n panelDefinition.spec.plugin.kind !== pluginKind &&\n JSON.stringify(panelDefinition.spec.plugin.spec) !== JSON.stringify(pluginSpec)\n ) {\n pluginEditor.rememberCurrentSpecState();\n }\n setPanelDefinition(nextPanelDef);\n };\n\n const watchedName = useWatch({ control: form.control, name: 'panelDefinition.spec.display.name' });\n const watchedDescription = useWatch({ control: form.control, name: 'panelDefinition.spec.display.description' });\n const watchedPluginKind = useWatch({ control: form.control, name: 'panelDefinition.spec.plugin.kind' });\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} Panel</Typography>\n <Stack direction=\"row\" spacing={1} marginLeft=\"auto\">\n <Button variant=\"contained\" disabled={!form.formState.isValid} onClick={form.handleSubmit(processForm)}>\n {submitText}\n </Button>\n <Button color=\"secondary\" variant=\"outlined\" onClick={handleCancel}>\n Cancel\n </Button>\n </Stack>\n </Box>\n <Box id={panelEditorFormId} sx={{ flex: 1, overflowY: 'scroll', padding: (theme) => theme.spacing(2) }}>\n <Grid container spacing={2}>\n <Grid item xs={8}>\n <Controller\n control={form.control}\n name=\"panelDefinition.spec.display.name\"\n render={({ field, fieldState }) => (\n <TextField\n {...field}\n required\n fullWidth\n label=\"Name\"\n error={!!fieldState.error}\n helperText={fieldState.error?.message}\n value={watchedName ?? ''}\n onChange={(event) => {\n field.onChange(event);\n setName(event.target.value);\n }}\n />\n )}\n />\n </Grid>\n <Grid item xs={4}>\n <Controller\n control={form.control}\n name=\"groupId\"\n render={({ field, fieldState }) => (\n <TextField\n select\n {...field}\n required\n fullWidth\n label=\"Group\"\n error={!!fieldState.error}\n helperText={fieldState.error?.message}\n onChange={(event) => {\n field.onChange(event);\n }}\n >\n {panelGroups.map((panelGroup, index) => (\n <MenuItem key={panelGroup.id} value={panelGroup.id}>\n {panelGroup.title ?? `Group ${index + 1}`}\n </MenuItem>\n ))}\n </TextField>\n )}\n />\n </Grid>\n <Grid item xs={8}>\n <Controller\n control={form.control}\n name=\"panelDefinition.spec.display.description\"\n render={({ field, fieldState }) => (\n <TextField\n {...field}\n fullWidth\n label=\"Description\"\n error={!!fieldState.error}\n helperText={fieldState.error?.message}\n value={watchedDescription ?? ''}\n onChange={(event) => {\n field.onChange(event);\n setDescription(event.target.value);\n }}\n />\n )}\n />\n </Grid>\n <Grid item xs={4}>\n <Controller\n control={form.control}\n name=\"panelDefinition.spec.plugin.kind\"\n render={({ field, fieldState }) => (\n <PluginKindSelect\n {...field}\n pluginTypes={['Panel']}\n required\n fullWidth\n label=\"Type\"\n disabled={pluginEditor.isLoading}\n error={!!pluginEditor.error || !!fieldState.error}\n helperText={pluginEditor.error?.message ?? fieldState.error?.message}\n value={{ type: 'Panel', kind: watchedPluginKind }}\n onChange={(event) => {\n field.onChange(event.kind);\n pluginEditor.onSelectionChange(event);\n }}\n />\n )}\n />\n </Grid>\n <Grid item xs={12}>\n <Typography variant=\"h4\" marginBottom={1}>\n Preview\n </Typography>\n <ErrorBoundary FallbackComponent={ErrorAlert}>\n <PanelPreview panelDefinition={panelDefinition} />\n </ErrorBoundary>\n </Grid>\n <Grid item xs={12}>\n <ErrorBoundary FallbackComponent={ErrorAlert}>\n <PanelSpecEditor\n control={form.control}\n panelDefinition={panelDefinition}\n onJSONChange={handlePanelDefinitionChange}\n onQueriesChange={(queries) => {\n setQueries(queries);\n }}\n onPluginSpecChange={(spec) => {\n pluginEditor.onSpecChange(spec);\n }}\n />\n </ErrorBoundary>\n </Grid>\n </Grid>\n </Box>\n <DiscardChangesConfirmationDialog\n description=\"You have unapplied changes in this panel. 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\n/**\n * The `id` attribute added to the `PanelEditorForm` component, allowing submit buttons to live outside the form.\n */\nexport const panelEditorFormId = 'panel-editor-form';\n"],"names":["useEffect","useState","Box","Button","Grid","MenuItem","Stack","TextField","Typography","DiscardChangesConfirmationDialog","ErrorAlert","ErrorBoundary","PluginKindSelect","usePluginEditor","PanelSpecEditor","getTitleAction","getSubmitText","useValidationSchemas","Controller","FormProvider","useForm","useWatch","zodResolver","useListPanelGroups","PanelPreview","usePanelEditor","PanelEditorForm","props","initialValues","initialAction","onSave","onClose","panelGroups","panelDefinition","setName","setDescription","setLinks","setQueries","setPlugin","setPanelDefinition","plugin","spec","isDiscardDialogOpened","setDiscardDialogOpened","panelEditorSchema","form","resolver","mode","defaultValues","pluginEditor","pluginTypes","value","selection","kind","type","onChange","setValue","onHideQueryEditorChange","isHidden","undefined","titleAction","submitText","links","control","name","processForm","data","handleCancel","JSON","stringify","getValues","handlePanelDefinitionChange","nextPanelDefStr","nextPanelDef","parse","pluginKind","pluginSpec","rememberCurrentSpecState","watchedName","watchedDescription","watchedPluginKind","sx","display","alignItems","padding","theme","spacing","borderBottom","palette","divider","variant","direction","marginLeft","disabled","formState","isValid","onClick","handleSubmit","color","id","panelEditorFormId","flex","overflowY","container","item","xs","render","field","fieldState","required","fullWidth","label","error","helperText","message","event","target","select","map","panelGroup","index","title","isLoading","onSelectionChange","marginBottom","FallbackComponent","onJSONChange","onQueriesChange","queries","onPluginSpecChange","onSpecChange","description","isOpen","onCancel","onDiscardChanges"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/components/PanelDrawer/PanelEditorForm.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 { ReactElement, useCallback, useEffect, useRef, useState } from 'react';\nimport { Box, Button, Grid, MenuItem, Stack, TextField, Typography } from '@mui/material';\nimport { Action, DEFAULT_DASHBOARD_DURATION, PanelDefinition, PanelEditorValues } from '@perses-dev/core';\nimport { DiscardChangesConfirmationDialog, ErrorAlert, ErrorBoundary } from '@perses-dev/components';\nimport {\n PluginKindSelect,\n usePluginEditor,\n PanelSpecEditor,\n getTitleAction,\n getSubmitText,\n useValidationSchemas,\n PluginEditorRef,\n TimeRangeProvider,\n useTimeRangeParams,\n useInitialTimeRange,\n} from '@perses-dev/plugin-system';\nimport { Controller, FormProvider, SubmitHandler, useForm, useWatch } from 'react-hook-form';\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { useDashboard, useListPanelGroups } from '../../context';\nimport { PanelPreview } from './PanelPreview';\nimport { usePanelEditor } from './usePanelEditor';\n\nexport interface PanelEditorFormProps {\n initialValues: PanelEditorValues;\n initialAction: Action;\n onSave: (values: PanelEditorValues) => void;\n onClose: () => void;\n}\n\nexport function PanelEditorForm(props: PanelEditorFormProps): ReactElement {\n const { initialValues, initialAction, onSave, onClose } = props;\n const pluginEditorRef = useRef<PluginEditorRef>(null);\n const panelGroups = useListPanelGroups();\n const { panelDefinition, setName, setDescription, setLinks, setQueries, setPlugin, setPanelDefinition } =\n usePanelEditor(initialValues.panelDefinition);\n const { plugin } = panelDefinition.spec;\n const [isDiscardDialogOpened, setDiscardDialogOpened] = useState<boolean>(false);\n\n const { panelEditorSchema } = useValidationSchemas();\n const form = useForm<PanelEditorValues>({\n resolver: zodResolver(panelEditorSchema),\n mode: 'onBlur',\n defaultValues: initialValues,\n });\n\n const { dashboard } = useDashboard();\n const dashboardDuration = dashboard?.kind === 'Dashboard' ? dashboard.spec.duration : DEFAULT_DASHBOARD_DURATION;\n const initialTimeRange = useInitialTimeRange(dashboardDuration);\n\n // Use common plugin editor logic even though we've split the inputs up in this form\n const pluginEditor = usePluginEditor({\n pluginTypes: ['Panel'],\n value: { selection: { kind: plugin.kind, type: 'Panel' }, spec: plugin.spec },\n onChange: (plugin) => {\n form.setValue('panelDefinition.spec.plugin', { kind: plugin.selection.kind, spec: plugin.spec });\n setPlugin({\n kind: plugin.selection.kind,\n spec: plugin.spec,\n });\n },\n onHideQueryEditorChange: (isHidden) => {\n setQueries(undefined, isHidden);\n },\n });\n\n const titleAction = getTitleAction(initialAction, true);\n const submitText = getSubmitText(initialAction, true);\n\n const links = useWatch({ control: form.control, name: 'panelDefinition.spec.links' });\n useEffect(() => {\n setLinks(links);\n }, [setLinks, links]);\n\n const processForm: SubmitHandler<PanelEditorValues> = useCallback(\n (data) => {\n onSave(data);\n },\n [onSave]\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(initialValues) !== JSON.stringify(form.getValues())) {\n setDiscardDialogOpened(true);\n } else {\n onClose();\n }\n }\n\n const handlePanelDefinitionChange = (nextPanelDefStr: string): void => {\n const nextPanelDef: PanelDefinition = JSON.parse(nextPanelDefStr);\n const { kind: pluginKind, spec: pluginSpec } = nextPanelDef.spec.plugin;\n // if panel plugin kind and spec are modified, then need to save current spec\n if (\n panelDefinition.spec.plugin.kind !== pluginKind &&\n JSON.stringify(panelDefinition.spec.plugin.spec) !== JSON.stringify(pluginSpec)\n ) {\n pluginEditor.rememberCurrentSpecState();\n }\n setPanelDefinition(nextPanelDef);\n };\n\n const watchedName = useWatch({ control: form.control, name: 'panelDefinition.spec.display.name' });\n const watchedDescription = useWatch({ control: form.control, name: 'panelDefinition.spec.display.description' });\n const watchedPluginKind = useWatch({ control: form.control, name: 'panelDefinition.spec.plugin.kind' });\n const { timeRange } = useTimeRangeParams(initialTimeRange);\n\n const handleSubmit = useCallback(() => {\n pluginEditorRef.current?.flushChanges?.();\n form.handleSubmit(processForm)();\n }, [form, processForm]);\n\n return (\n <TimeRangeProvider timeRange={timeRange}>\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} Panel</Typography>\n <Stack direction=\"row\" spacing={1} marginLeft=\"auto\">\n <Button variant=\"contained\" disabled={!form.formState.isValid} onClick={handleSubmit}>\n {submitText}\n </Button>\n <Button color=\"secondary\" variant=\"outlined\" onClick={handleCancel}>\n Cancel\n </Button>\n </Stack>\n </Box>\n <Box id={panelEditorFormId} sx={{ flex: 1, overflowY: 'scroll', padding: (theme) => theme.spacing(2) }}>\n <Grid container spacing={2}>\n <Grid item xs={8}>\n <Controller\n control={form.control}\n name=\"panelDefinition.spec.display.name\"\n render={({ field, fieldState }) => (\n <TextField\n {...field}\n required\n fullWidth\n label=\"Name\"\n error={!!fieldState.error}\n helperText={fieldState.error?.message}\n value={watchedName ?? ''}\n onChange={(event) => {\n field.onChange(event);\n setName(event.target.value);\n }}\n />\n )}\n />\n </Grid>\n <Grid item xs={4}>\n <Controller\n control={form.control}\n name=\"groupId\"\n render={({ field, fieldState }) => (\n <TextField\n select\n {...field}\n required\n fullWidth\n label=\"Group\"\n error={!!fieldState.error}\n helperText={fieldState.error?.message}\n onChange={(event) => {\n field.onChange(event);\n }}\n >\n {panelGroups.map((panelGroup, index) => (\n <MenuItem key={panelGroup.id} value={panelGroup.id}>\n {panelGroup.title ?? `Group ${index + 1}`}\n </MenuItem>\n ))}\n </TextField>\n )}\n />\n </Grid>\n <Grid item xs={8}>\n <Controller\n control={form.control}\n name=\"panelDefinition.spec.display.description\"\n render={({ field, fieldState }) => (\n <TextField\n {...field}\n fullWidth\n label=\"Description\"\n error={!!fieldState.error}\n helperText={fieldState.error?.message}\n value={watchedDescription ?? ''}\n onChange={(event) => {\n field.onChange(event);\n setDescription(event.target.value);\n }}\n />\n )}\n />\n </Grid>\n <Grid item xs={4}>\n <Controller\n control={form.control}\n name=\"panelDefinition.spec.plugin.kind\"\n render={({ field, fieldState }) => (\n <PluginKindSelect\n {...field}\n pluginTypes={['Panel']}\n required\n fullWidth\n label=\"Type\"\n disabled={pluginEditor.isLoading}\n error={!!pluginEditor.error || !!fieldState.error}\n helperText={pluginEditor.error?.message ?? fieldState.error?.message}\n value={{ type: 'Panel', kind: watchedPluginKind }}\n onChange={(event) => {\n field.onChange(event.kind);\n pluginEditor.onSelectionChange(event);\n }}\n />\n )}\n />\n </Grid>\n <Grid item xs={12}>\n <Typography variant=\"h4\" marginBottom={1}>\n Preview\n </Typography>\n <ErrorBoundary FallbackComponent={ErrorAlert}>\n <PanelPreview panelDefinition={panelDefinition} />\n </ErrorBoundary>\n </Grid>\n <Grid item xs={12}>\n <ErrorBoundary FallbackComponent={ErrorAlert}>\n <PanelSpecEditor\n ref={pluginEditorRef}\n control={form.control}\n panelDefinition={panelDefinition}\n onJSONChange={handlePanelDefinitionChange}\n onQueriesChange={(queries) => {\n setQueries(queries);\n }}\n onPluginSpecChange={(spec) => {\n pluginEditor.onSpecChange(spec);\n }}\n />\n </ErrorBoundary>\n </Grid>\n </Grid>\n </Box>\n <DiscardChangesConfirmationDialog\n description=\"You have unapplied changes in this panel. 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 </TimeRangeProvider>\n );\n}\n\n/**\n * The `id` attribute added to the `PanelEditorForm` component, allowing submit buttons to live outside the form.\n */\nexport const panelEditorFormId = 'panel-editor-form';\n"],"names":["useCallback","useEffect","useRef","useState","Box","Button","Grid","MenuItem","Stack","TextField","Typography","DEFAULT_DASHBOARD_DURATION","DiscardChangesConfirmationDialog","ErrorAlert","ErrorBoundary","PluginKindSelect","usePluginEditor","PanelSpecEditor","getTitleAction","getSubmitText","useValidationSchemas","TimeRangeProvider","useTimeRangeParams","useInitialTimeRange","Controller","FormProvider","useForm","useWatch","zodResolver","useDashboard","useListPanelGroups","PanelPreview","usePanelEditor","PanelEditorForm","props","initialValues","initialAction","onSave","onClose","pluginEditorRef","panelGroups","panelDefinition","setName","setDescription","setLinks","setQueries","setPlugin","setPanelDefinition","plugin","spec","isDiscardDialogOpened","setDiscardDialogOpened","panelEditorSchema","form","resolver","mode","defaultValues","dashboard","dashboardDuration","kind","duration","initialTimeRange","pluginEditor","pluginTypes","value","selection","type","onChange","setValue","onHideQueryEditorChange","isHidden","undefined","titleAction","submitText","links","control","name","processForm","data","handleCancel","JSON","stringify","getValues","handlePanelDefinitionChange","nextPanelDefStr","nextPanelDef","parse","pluginKind","pluginSpec","rememberCurrentSpecState","watchedName","watchedDescription","watchedPluginKind","timeRange","handleSubmit","current","flushChanges","sx","display","alignItems","padding","theme","spacing","borderBottom","palette","divider","variant","direction","marginLeft","disabled","formState","isValid","onClick","color","id","panelEditorFormId","flex","overflowY","container","item","xs","render","field","fieldState","required","fullWidth","label","error","helperText","message","event","target","select","map","panelGroup","index","title","isLoading","onSelectionChange","marginBottom","FallbackComponent","ref","onJSONChange","onQueriesChange","queries","onPluginSpecChange","onSpecChange","description","isOpen","onCancel","onDiscardChanges"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VariableEditor.d.ts","sourceRoot":"","sources":["../../../src/components/Variables/VariableEditor.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAqB,YAAY,EAAE,MAAM,OAAO,CAAC;AAuBxD,OAAO,EAAU,yBAAyB,
|
|
1
|
+
{"version":3,"file":"VariableEditor.d.ts","sourceRoot":"","sources":["../../../src/components/Variables/VariableEditor.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAqB,YAAY,EAAE,MAAM,OAAO,CAAC;AAuBxD,OAAO,EAAU,yBAAyB,EAA8B,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAUrH,OAAO,EAGL,aAAa,EAId,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EAAE,0BAA0B,EAAqD,MAAM,eAAe,CAAC;AAuB9G,wBAAgB,cAAc,CAAC,KAAK,EAAE;IACpC,mBAAmB,EAAE,kBAAkB,EAAE,CAAC;IAC1C,2BAA2B,EAAE,0BAA0B,EAAE,CAAC;IAC1D,0BAA0B,EAAE,yBAAyB,EAAE,CAAC;IACxD,QAAQ,EAAE,CAAC,mBAAmB,EAAE,kBAAkB,EAAE,KAAK,IAAI,CAAC;IAC9D,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB,GAAG,YAAY,CA4Uf;AAMD,wBAAgB,YAAY,CAAC,KAAK,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,aAAa,GAAG,SAAS,CAAA;CAAE,GAAG,YAAY,CAoBpG"}
|
|
@@ -14,6 +14,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
14
14
|
import { useState, useMemo } from 'react';
|
|
15
15
|
import { Button, Stack, Box, TableContainer, TableBody, TableRow, TableCell as MuiTableCell, Table, TableHead, Switch, Typography, IconButton, Alert, styled, capitalize, Tooltip, Accordion, AccordionSummary, AccordionDetails } from '@mui/material';
|
|
16
16
|
import AddIcon from 'mdi-material-ui/Plus';
|
|
17
|
+
import { DEFAULT_DASHBOARD_DURATION } from '@perses-dev/core';
|
|
17
18
|
import { useImmer } from 'use-immer';
|
|
18
19
|
import PencilIcon from 'mdi-material-ui/Pencil';
|
|
19
20
|
import TrashIcon from 'mdi-material-ui/TrashCan';
|
|
@@ -22,9 +23,9 @@ import ArrowDown from 'mdi-material-ui/ArrowDown';
|
|
|
22
23
|
import ContentDuplicate from 'mdi-material-ui/ContentDuplicate';
|
|
23
24
|
import OpenInNewIcon from 'mdi-material-ui/OpenInNew';
|
|
24
25
|
import ExpandMoreIcon from 'mdi-material-ui/ChevronUp';
|
|
25
|
-
import { ValidationProvider, VariableEditorForm, VARIABLE_TYPES } from '@perses-dev/plugin-system';
|
|
26
|
+
import { ValidationProvider, VariableEditorForm, VARIABLE_TYPES, useInitialTimeRange, TimeRangeProvider } from '@perses-dev/plugin-system';
|
|
26
27
|
import { InfoTooltip } from '@perses-dev/components';
|
|
27
|
-
import { useDiscardChangesConfirmationDialog } from '../../context';
|
|
28
|
+
import { useDashboard, useDiscardChangesConfirmationDialog } from '../../context';
|
|
28
29
|
import { hydrateVariableDefinitionStates } from '../../context/VariableProvider/hydrationUtils';
|
|
29
30
|
import { BuiltinVariableAccordions } from './BuiltinVariableAccordions';
|
|
30
31
|
function getVariableLabelByKind(kind) {
|
|
@@ -140,26 +141,32 @@ export function VariableEditor(props) {
|
|
|
140
141
|
draft.push(v);
|
|
141
142
|
});
|
|
142
143
|
};
|
|
144
|
+
const { dashboard } = useDashboard();
|
|
145
|
+
const dashboardDuration = dashboard?.kind === 'Dashboard' ? dashboard.spec.duration : DEFAULT_DASHBOARD_DURATION;
|
|
146
|
+
const initialTimeRange = useInitialTimeRange(dashboardDuration);
|
|
143
147
|
return /*#__PURE__*/ _jsxs(_Fragment, {
|
|
144
148
|
children: [
|
|
145
149
|
currentEditingVariableDefinition && /*#__PURE__*/ _jsx(ValidationProvider, {
|
|
146
|
-
children: /*#__PURE__*/ _jsx(
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
150
|
+
children: /*#__PURE__*/ _jsx(TimeRangeProvider, {
|
|
151
|
+
timeRange: initialTimeRange,
|
|
152
|
+
children: /*#__PURE__*/ _jsx(VariableEditorForm, {
|
|
153
|
+
initialVariableDefinition: currentEditingVariableDefinition,
|
|
154
|
+
action: variableFormAction,
|
|
155
|
+
isDraft: true,
|
|
156
|
+
onActionChange: setVariableFormAction,
|
|
157
|
+
onSave: (definition)=>{
|
|
158
|
+
setVariableDefinitions((draft)=>{
|
|
159
|
+
draft[variableEditIdx] = definition;
|
|
160
|
+
setVariableEditIdx(null);
|
|
161
|
+
});
|
|
162
|
+
},
|
|
163
|
+
onClose: ()=>{
|
|
164
|
+
if (variableFormAction === 'create') {
|
|
165
|
+
removeVariable(variableEditIdx);
|
|
166
|
+
}
|
|
154
167
|
setVariableEditIdx(null);
|
|
155
|
-
});
|
|
156
|
-
},
|
|
157
|
-
onClose: ()=>{
|
|
158
|
-
if (variableFormAction === 'create') {
|
|
159
|
-
removeVariable(variableEditIdx);
|
|
160
168
|
}
|
|
161
|
-
|
|
162
|
-
}
|
|
169
|
+
})
|
|
163
170
|
})
|
|
164
171
|
}),
|
|
165
172
|
!currentEditingVariableDefinition && /*#__PURE__*/ _jsxs(_Fragment, {
|