@perses-dev/dashboards 0.52.0-beta.5 → 0.52.0-rc.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.
Files changed (127) hide show
  1. package/dist/cjs/components/GridLayout/GridLayout.js +78 -126
  2. package/dist/cjs/components/GridLayout/Row.js +150 -0
  3. package/dist/cjs/components/GridLayout/index.js +1 -0
  4. package/dist/cjs/components/LeaveDialog/LeaveDialog.js +72 -0
  5. package/dist/cjs/components/LeaveDialog/index.js +30 -0
  6. package/dist/cjs/components/Panel/Panel.js +5 -1
  7. package/dist/cjs/components/Panel/PanelActions.js +4 -4
  8. package/dist/cjs/components/Panel/PanelHeader.js +32 -15
  9. package/dist/cjs/components/PanelDrawer/PanelDrawer.js +58 -21
  10. package/dist/cjs/components/PanelDrawer/PanelEditorForm.js +204 -185
  11. package/dist/cjs/components/PanelGroupDialog/PanelGroupDialog.js +3 -0
  12. package/dist/cjs/components/PanelGroupDialog/PanelGroupEditorForm.js +35 -15
  13. package/dist/cjs/components/Variables/VariableEditor.js +22 -15
  14. package/dist/cjs/components/index.js +1 -0
  15. package/dist/cjs/context/DashboardProvider/DashboardProvider.js +7 -8
  16. package/dist/cjs/context/DashboardProvider/DashboardProviderWithQueryParams.js +27 -5
  17. package/dist/cjs/context/DashboardProvider/panel-editor-slice.js +1 -0
  18. package/dist/cjs/context/DashboardProvider/panel-group-editor-slice.js +6 -2
  19. package/dist/cjs/context/DashboardProvider/panel-group-slice.js +1 -0
  20. package/dist/cjs/context/DashboardProvider/view-panel-slice.js +10 -3
  21. package/dist/cjs/context/VariableProvider/VariableProvider.js +1 -1
  22. package/dist/cjs/context/VariableProvider/query-params.js +12 -14
  23. package/dist/cjs/context/useDashboard.js +5 -4
  24. package/dist/cjs/test/render.js +6 -8
  25. package/dist/cjs/views/ViewDashboard/DashboardApp.js +7 -3
  26. package/dist/cjs/views/ViewDashboard/ViewDashboard.js +9 -8
  27. package/dist/components/DashboardToolbar/DashboardToolbar.d.ts +2 -2
  28. package/dist/components/DashboardToolbar/DashboardToolbar.d.ts.map +1 -1
  29. package/dist/components/DashboardToolbar/DashboardToolbar.js.map +1 -1
  30. package/dist/components/GridLayout/GridLayout.d.ts +8 -0
  31. package/dist/components/GridLayout/GridLayout.d.ts.map +1 -1
  32. package/dist/components/GridLayout/GridLayout.js +72 -126
  33. package/dist/components/GridLayout/GridLayout.js.map +1 -1
  34. package/dist/components/GridLayout/Row.d.ts +17 -0
  35. package/dist/components/GridLayout/Row.d.ts.map +1 -0
  36. package/dist/components/GridLayout/Row.js +142 -0
  37. package/dist/components/GridLayout/Row.js.map +1 -0
  38. package/dist/components/GridLayout/index.d.ts +1 -0
  39. package/dist/components/GridLayout/index.d.ts.map +1 -1
  40. package/dist/components/GridLayout/index.js +1 -0
  41. package/dist/components/GridLayout/index.js.map +1 -1
  42. package/dist/components/LeaveDialog/LeaveDialog.d.ts +12 -0
  43. package/dist/components/LeaveDialog/LeaveDialog.d.ts.map +1 -0
  44. package/dist/components/LeaveDialog/LeaveDialog.js +61 -0
  45. package/dist/components/LeaveDialog/LeaveDialog.js.map +1 -0
  46. package/dist/components/LeaveDialog/index.d.ts +2 -0
  47. package/dist/components/LeaveDialog/index.d.ts.map +1 -0
  48. package/dist/components/LeaveDialog/index.js +15 -0
  49. package/dist/components/LeaveDialog/index.js.map +1 -0
  50. package/dist/components/Panel/HeaderIconButton.d.ts +1 -1
  51. package/dist/components/Panel/Panel.d.ts +5 -0
  52. package/dist/components/Panel/Panel.d.ts.map +1 -1
  53. package/dist/components/Panel/Panel.js +5 -1
  54. package/dist/components/Panel/Panel.js.map +1 -1
  55. package/dist/components/Panel/PanelActions.d.ts +2 -0
  56. package/dist/components/Panel/PanelActions.d.ts.map +1 -1
  57. package/dist/components/Panel/PanelActions.js +4 -4
  58. package/dist/components/Panel/PanelActions.js.map +1 -1
  59. package/dist/components/Panel/PanelHeader.d.ts +6 -1
  60. package/dist/components/Panel/PanelHeader.d.ts.map +1 -1
  61. package/dist/components/Panel/PanelHeader.js +33 -16
  62. package/dist/components/Panel/PanelHeader.js.map +1 -1
  63. package/dist/components/PanelDrawer/PanelDrawer.d.ts.map +1 -1
  64. package/dist/components/PanelDrawer/PanelDrawer.js +59 -22
  65. package/dist/components/PanelDrawer/PanelDrawer.js.map +1 -1
  66. package/dist/components/PanelDrawer/PanelEditorForm.d.ts.map +1 -1
  67. package/dist/components/PanelDrawer/PanelEditorForm.js +207 -188
  68. package/dist/components/PanelDrawer/PanelEditorForm.js.map +1 -1
  69. package/dist/components/PanelGroupDialog/PanelGroupDialog.d.ts.map +1 -1
  70. package/dist/components/PanelGroupDialog/PanelGroupDialog.js +3 -0
  71. package/dist/components/PanelGroupDialog/PanelGroupDialog.js.map +1 -1
  72. package/dist/components/PanelGroupDialog/PanelGroupEditorForm.d.ts +1 -0
  73. package/dist/components/PanelGroupDialog/PanelGroupEditorForm.d.ts.map +1 -1
  74. package/dist/components/PanelGroupDialog/PanelGroupEditorForm.js +36 -16
  75. package/dist/components/PanelGroupDialog/PanelGroupEditorForm.js.map +1 -1
  76. package/dist/components/Variables/VariableEditor.d.ts.map +1 -1
  77. package/dist/components/Variables/VariableEditor.js +24 -17
  78. package/dist/components/Variables/VariableEditor.js.map +1 -1
  79. package/dist/components/index.d.ts +1 -0
  80. package/dist/components/index.d.ts.map +1 -1
  81. package/dist/components/index.js +1 -0
  82. package/dist/components/index.js.map +1 -1
  83. package/dist/context/DashboardProvider/DashboardProvider.d.ts +5 -5
  84. package/dist/context/DashboardProvider/DashboardProvider.d.ts.map +1 -1
  85. package/dist/context/DashboardProvider/DashboardProvider.js +7 -8
  86. package/dist/context/DashboardProvider/DashboardProvider.js.map +1 -1
  87. package/dist/context/DashboardProvider/DashboardProviderWithQueryParams.d.ts.map +1 -1
  88. package/dist/context/DashboardProvider/DashboardProviderWithQueryParams.js +27 -5
  89. package/dist/context/DashboardProvider/DashboardProviderWithQueryParams.js.map +1 -1
  90. package/dist/context/DashboardProvider/common.d.ts +1 -1
  91. package/dist/context/DashboardProvider/common.d.ts.map +1 -1
  92. package/dist/context/DashboardProvider/common.js.map +1 -1
  93. package/dist/context/DashboardProvider/panel-editor-slice.d.ts +1 -0
  94. package/dist/context/DashboardProvider/panel-editor-slice.d.ts.map +1 -1
  95. package/dist/context/DashboardProvider/panel-editor-slice.js +1 -0
  96. package/dist/context/DashboardProvider/panel-editor-slice.js.map +1 -1
  97. package/dist/context/DashboardProvider/panel-group-editor-slice.d.ts +1 -0
  98. package/dist/context/DashboardProvider/panel-group-editor-slice.d.ts.map +1 -1
  99. package/dist/context/DashboardProvider/panel-group-editor-slice.js +6 -2
  100. package/dist/context/DashboardProvider/panel-group-editor-slice.js.map +1 -1
  101. package/dist/context/DashboardProvider/panel-group-slice.d.ts +3 -0
  102. package/dist/context/DashboardProvider/panel-group-slice.d.ts.map +1 -1
  103. package/dist/context/DashboardProvider/panel-group-slice.js +1 -0
  104. package/dist/context/DashboardProvider/panel-group-slice.js.map +1 -1
  105. package/dist/context/DashboardProvider/view-panel-slice.d.ts +6 -2
  106. package/dist/context/DashboardProvider/view-panel-slice.d.ts.map +1 -1
  107. package/dist/context/DashboardProvider/view-panel-slice.js +10 -3
  108. package/dist/context/DashboardProvider/view-panel-slice.js.map +1 -1
  109. package/dist/context/VariableProvider/VariableProvider.js +1 -1
  110. package/dist/context/VariableProvider/VariableProvider.js.map +1 -1
  111. package/dist/context/VariableProvider/query-params.d.ts +4 -3
  112. package/dist/context/VariableProvider/query-params.d.ts.map +1 -1
  113. package/dist/context/VariableProvider/query-params.js +9 -14
  114. package/dist/context/VariableProvider/query-params.js.map +1 -1
  115. package/dist/context/useDashboard.js +5 -4
  116. package/dist/context/useDashboard.js.map +1 -1
  117. package/dist/test/render.d.ts.map +1 -1
  118. package/dist/test/render.js +6 -8
  119. package/dist/test/render.js.map +1 -1
  120. package/dist/views/ViewDashboard/DashboardApp.d.ts +7 -6
  121. package/dist/views/ViewDashboard/DashboardApp.d.ts.map +1 -1
  122. package/dist/views/ViewDashboard/DashboardApp.js +8 -4
  123. package/dist/views/ViewDashboard/DashboardApp.js.map +1 -1
  124. package/dist/views/ViewDashboard/ViewDashboard.d.ts.map +1 -1
  125. package/dist/views/ViewDashboard/ViewDashboard.js +9 -8
  126. package/dist/views/ViewDashboard/ViewDashboard.js.map +1 -1
  127. package/package.json +6 -6
@@ -23,6 +23,7 @@ Object.defineProperty(exports, "PanelDrawer", {
23
23
  const _jsxruntime = require("react/jsx-runtime");
24
24
  const _react = require("react");
25
25
  const _components = require("@perses-dev/components");
26
+ const _pluginsystem = require("@perses-dev/plugin-system");
26
27
  const _context = require("../../context");
27
28
  const _PanelEditorForm = require("./PanelEditorForm");
28
29
  const PanelDrawer = ()=>{
@@ -30,42 +31,78 @@ const PanelDrawer = ()=>{
30
31
  // When the user clicks close, start closing but don't call the store yet to keep values stable during animtation
31
32
  const [isClosing, setIsClosing] = (0, _react.useState)(false);
32
33
  // Drawer is open if we have a model and we're not transitioning out
33
- const isOpen = panelEditor !== undefined && isClosing === false;
34
- function handleSave(values) {
34
+ const isOpen = panelEditor !== undefined && !isClosing;
35
+ const handleSave = (0, _react.useCallback)((values)=>{
35
36
  // This shouldn't happen since we don't render the submit button until we have a model, but check to make TS happy
36
37
  if (panelEditor === undefined || values === undefined) {
37
38
  throw new Error('Cannot apply changes');
38
39
  }
39
40
  panelEditor.applyChanges(values);
40
41
  setIsClosing(true);
41
- }
42
+ }, [
43
+ panelEditor
44
+ ]);
42
45
  const handleClose = ()=>{
43
46
  setIsClosing(true);
44
47
  };
45
48
  // Don't call closeDrawer on the store until the Drawer has completely transitioned out and reset close state
46
- const handleExited = ()=>{
49
+ const handleExited = (0, _react.useCallback)(()=>{
47
50
  panelEditor?.close();
48
51
  setIsClosing(false);
49
- };
52
+ }, [
53
+ panelEditor
54
+ ]);
50
55
  // Disables closing on click out. This is a quick-win solution to avoid losing draft changes.
51
56
  // -> TODO find a way to enable closing by clicking-out in edit view, with a discard confirmation modal popping up
52
57
  const handleClickOut = ()=>{
53
58
  /* do nothing */ };
54
- return /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.Drawer, {
55
- isOpen: isOpen,
56
- onClose: handleClickOut,
57
- SlideProps: {
58
- onExited: handleExited
59
- },
60
- "data-testid": "panel-editor",
61
- children: panelEditor && /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.ErrorBoundary, {
62
- FallbackComponent: _components.ErrorAlert,
63
- children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_PanelEditorForm.PanelEditorForm, {
64
- initialAction: panelEditor.mode,
65
- initialValues: panelEditor.initialValues,
66
- onSave: handleSave,
67
- onClose: handleClose
59
+ const drawer = (0, _react.useMemo)(()=>{
60
+ return /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.Drawer, {
61
+ isOpen: isOpen,
62
+ onClose: handleClickOut,
63
+ SlideProps: {
64
+ onExited: handleExited
65
+ },
66
+ "data-testid": "panel-editor",
67
+ children: panelEditor && /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.ErrorBoundary, {
68
+ FallbackComponent: _components.ErrorAlert,
69
+ children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_PanelEditorForm.PanelEditorForm, {
70
+ initialAction: panelEditor.mode,
71
+ initialValues: panelEditor.initialValues,
72
+ onSave: handleSave,
73
+ onClose: handleClose
74
+ })
68
75
  })
69
- })
70
- });
76
+ });
77
+ }, [
78
+ handleExited,
79
+ handleSave,
80
+ isOpen,
81
+ panelEditor
82
+ ]);
83
+ // If the panel editor is using a repeat variable, we need to wrap the drawer in a VariableContext.Provider
84
+ if (panelEditor?.panelGroupItemId?.repeatVariable) {
85
+ return /*#__PURE__*/ (0, _jsxruntime.jsx)(RepeatVariableWrapper, {
86
+ repeatVariable: panelEditor.panelGroupItemId.repeatVariable,
87
+ children: drawer
88
+ });
89
+ }
90
+ return drawer;
71
91
  };
92
+ // Wraps the drawer in a VariableContext.Provider to provide the repeat variable value
93
+ // This is necessary for previewing panels that use repeat variables and query editor
94
+ function RepeatVariableWrapper({ repeatVariable, children }) {
95
+ const variables = (0, _pluginsystem.useVariableValues)();
96
+ return /*#__PURE__*/ (0, _jsxruntime.jsx)(_pluginsystem.VariableContext.Provider, {
97
+ value: {
98
+ state: {
99
+ ...variables,
100
+ [repeatVariable[0]]: {
101
+ value: repeatVariable[1],
102
+ loading: false
103
+ }
104
+ }
105
+ },
106
+ children: children
107
+ });
108
+ }
@@ -31,6 +31,7 @@ _export(exports, {
31
31
  const _jsxruntime = require("react/jsx-runtime");
32
32
  const _react = require("react");
33
33
  const _material = require("@mui/material");
34
+ const _core = require("@perses-dev/core");
34
35
  const _components = require("@perses-dev/components");
35
36
  const _pluginsystem = require("@perses-dev/plugin-system");
36
37
  const _reacthookform = require("react-hook-form");
@@ -40,6 +41,7 @@ const _PanelPreview = require("./PanelPreview");
40
41
  const _usePanelEditor = require("./usePanelEditor");
41
42
  function PanelEditorForm(props) {
42
43
  const { initialValues, initialAction, onSave, onClose } = props;
44
+ const pluginEditorRef = (0, _react.useRef)(null);
43
45
  const panelGroups = (0, _context.useListPanelGroups)();
44
46
  const { panelDefinition, setName, setDescription, setLinks, setQueries, setPlugin, setPanelDefinition } = (0, _usePanelEditor.usePanelEditor)(initialValues.panelDefinition);
45
47
  const { plugin } = panelDefinition.spec;
@@ -50,6 +52,9 @@ function PanelEditorForm(props) {
50
52
  mode: 'onBlur',
51
53
  defaultValues: initialValues
52
54
  });
55
+ const { dashboard } = (0, _context.useDashboard)();
56
+ const dashboardDuration = dashboard?.kind === 'Dashboard' ? dashboard.spec.duration : _core.DEFAULT_DASHBOARD_DURATION;
57
+ const initialTimeRange = (0, _pluginsystem.useInitialTimeRange)(dashboardDuration);
53
58
  // Use common plugin editor logic even though we've split the inputs up in this form
54
59
  const pluginEditor = (0, _pluginsystem.usePluginEditor)({
55
60
  pluginTypes: [
@@ -88,9 +93,11 @@ function PanelEditorForm(props) {
88
93
  setLinks,
89
94
  links
90
95
  ]);
91
- const processForm = (data)=>{
96
+ const processForm = (0, _react.useCallback)((data)=>{
92
97
  onSave(data);
93
- };
98
+ }, [
99
+ onSave
100
+ ]);
94
101
  // When user click on cancel, several possibilities:
95
102
  // - create action: ask for discard approval
96
103
  // - update action: ask for discard approval if changed
@@ -123,199 +130,211 @@ function PanelEditorForm(props) {
123
130
  control: form.control,
124
131
  name: 'panelDefinition.spec.plugin.kind'
125
132
  });
126
- return /*#__PURE__*/ (0, _jsxruntime.jsxs)(_reacthookform.FormProvider, {
127
- ...form,
128
- children: [
129
- /*#__PURE__*/ (0, _jsxruntime.jsxs)(_material.Box, {
130
- sx: {
131
- display: 'flex',
132
- alignItems: 'center',
133
- padding: (theme)=>theme.spacing(1, 2),
134
- borderBottom: (theme)=>`1px solid ${theme.palette.divider}`
135
- },
136
- children: [
137
- /*#__PURE__*/ (0, _jsxruntime.jsxs)(_material.Typography, {
138
- variant: "h2",
139
- children: [
140
- titleAction,
141
- " Panel"
142
- ]
143
- }),
144
- /*#__PURE__*/ (0, _jsxruntime.jsxs)(_material.Stack, {
145
- direction: "row",
146
- spacing: 1,
147
- marginLeft: "auto",
148
- children: [
149
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Button, {
150
- variant: "contained",
151
- disabled: !form.formState.isValid,
152
- onClick: form.handleSubmit(processForm),
153
- children: submitText
154
- }),
155
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Button, {
156
- color: "secondary",
157
- variant: "outlined",
158
- onClick: handleCancel,
159
- children: "Cancel"
160
- })
161
- ]
162
- })
163
- ]
164
- }),
165
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Box, {
166
- id: panelEditorFormId,
167
- sx: {
168
- flex: 1,
169
- overflowY: 'scroll',
170
- padding: (theme)=>theme.spacing(2)
171
- },
172
- children: /*#__PURE__*/ (0, _jsxruntime.jsxs)(_material.Grid, {
173
- container: true,
174
- spacing: 2,
133
+ const { timeRange } = (0, _pluginsystem.useTimeRangeParams)(initialTimeRange);
134
+ const handleSubmit = (0, _react.useCallback)(()=>{
135
+ pluginEditorRef.current?.flushChanges?.();
136
+ form.handleSubmit(processForm)();
137
+ }, [
138
+ form,
139
+ processForm
140
+ ]);
141
+ return /*#__PURE__*/ (0, _jsxruntime.jsx)(_pluginsystem.TimeRangeProvider, {
142
+ timeRange: timeRange,
143
+ children: /*#__PURE__*/ (0, _jsxruntime.jsxs)(_reacthookform.FormProvider, {
144
+ ...form,
145
+ children: [
146
+ /*#__PURE__*/ (0, _jsxruntime.jsxs)(_material.Box, {
147
+ sx: {
148
+ display: 'flex',
149
+ alignItems: 'center',
150
+ padding: (theme)=>theme.spacing(1, 2),
151
+ borderBottom: (theme)=>`1px solid ${theme.palette.divider}`
152
+ },
175
153
  children: [
176
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Grid, {
177
- item: true,
178
- xs: 8,
179
- children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_reacthookform.Controller, {
180
- control: form.control,
181
- name: "panelDefinition.spec.display.name",
182
- render: ({ field, fieldState })=>/*#__PURE__*/ (0, _jsxruntime.jsx)(_material.TextField, {
183
- ...field,
184
- required: true,
185
- fullWidth: true,
186
- label: "Name",
187
- error: !!fieldState.error,
188
- helperText: fieldState.error?.message,
189
- value: watchedName ?? '',
190
- onChange: (event)=>{
191
- field.onChange(event);
192
- setName(event.target.value);
193
- }
194
- })
195
- })
196
- }),
197
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Grid, {
198
- item: true,
199
- xs: 4,
200
- children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_reacthookform.Controller, {
201
- control: form.control,
202
- name: "groupId",
203
- render: ({ field, fieldState })=>/*#__PURE__*/ (0, _jsxruntime.jsx)(_material.TextField, {
204
- select: true,
205
- ...field,
206
- required: true,
207
- fullWidth: true,
208
- label: "Group",
209
- error: !!fieldState.error,
210
- helperText: fieldState.error?.message,
211
- onChange: (event)=>{
212
- field.onChange(event);
213
- },
214
- children: panelGroups.map((panelGroup, index)=>/*#__PURE__*/ (0, _jsxruntime.jsx)(_material.MenuItem, {
215
- value: panelGroup.id,
216
- children: panelGroup.title ?? `Group ${index + 1}`
217
- }, panelGroup.id))
218
- })
219
- })
220
- }),
221
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Grid, {
222
- item: true,
223
- xs: 8,
224
- children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_reacthookform.Controller, {
225
- control: form.control,
226
- name: "panelDefinition.spec.display.description",
227
- render: ({ field, fieldState })=>/*#__PURE__*/ (0, _jsxruntime.jsx)(_material.TextField, {
228
- ...field,
229
- fullWidth: true,
230
- label: "Description",
231
- error: !!fieldState.error,
232
- helperText: fieldState.error?.message,
233
- value: watchedDescription ?? '',
234
- onChange: (event)=>{
235
- field.onChange(event);
236
- setDescription(event.target.value);
237
- }
238
- })
239
- })
240
- }),
241
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Grid, {
242
- item: true,
243
- xs: 4,
244
- children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_reacthookform.Controller, {
245
- control: form.control,
246
- name: "panelDefinition.spec.plugin.kind",
247
- render: ({ field, fieldState })=>/*#__PURE__*/ (0, _jsxruntime.jsx)(_pluginsystem.PluginKindSelect, {
248
- ...field,
249
- pluginTypes: [
250
- 'Panel'
251
- ],
252
- required: true,
253
- fullWidth: true,
254
- label: "Type",
255
- disabled: pluginEditor.isLoading,
256
- error: !!pluginEditor.error || !!fieldState.error,
257
- helperText: pluginEditor.error?.message ?? fieldState.error?.message,
258
- value: {
259
- type: 'Panel',
260
- kind: watchedPluginKind
261
- },
262
- onChange: (event)=>{
263
- field.onChange(event.kind);
264
- pluginEditor.onSelectionChange(event);
265
- }
266
- })
267
- })
154
+ /*#__PURE__*/ (0, _jsxruntime.jsxs)(_material.Typography, {
155
+ variant: "h2",
156
+ children: [
157
+ titleAction,
158
+ " Panel"
159
+ ]
268
160
  }),
269
- /*#__PURE__*/ (0, _jsxruntime.jsxs)(_material.Grid, {
270
- item: true,
271
- xs: 12,
161
+ /*#__PURE__*/ (0, _jsxruntime.jsxs)(_material.Stack, {
162
+ direction: "row",
163
+ spacing: 1,
164
+ marginLeft: "auto",
272
165
  children: [
273
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Typography, {
274
- variant: "h4",
275
- marginBottom: 1,
276
- children: "Preview"
166
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Button, {
167
+ variant: "contained",
168
+ disabled: !form.formState.isValid,
169
+ onClick: handleSubmit,
170
+ children: submitText
277
171
  }),
278
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.ErrorBoundary, {
279
- FallbackComponent: _components.ErrorAlert,
280
- children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_PanelPreview.PanelPreview, {
281
- panelDefinition: panelDefinition
282
- })
172
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Button, {
173
+ color: "secondary",
174
+ variant: "outlined",
175
+ onClick: handleCancel,
176
+ children: "Cancel"
283
177
  })
284
178
  ]
285
- }),
286
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Grid, {
287
- item: true,
288
- xs: 12,
289
- children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.ErrorBoundary, {
290
- FallbackComponent: _components.ErrorAlert,
291
- children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_pluginsystem.PanelSpecEditor, {
179
+ })
180
+ ]
181
+ }),
182
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Box, {
183
+ id: panelEditorFormId,
184
+ sx: {
185
+ flex: 1,
186
+ overflowY: 'scroll',
187
+ padding: (theme)=>theme.spacing(2)
188
+ },
189
+ children: /*#__PURE__*/ (0, _jsxruntime.jsxs)(_material.Grid, {
190
+ container: true,
191
+ spacing: 2,
192
+ children: [
193
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Grid, {
194
+ item: true,
195
+ xs: 8,
196
+ children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_reacthookform.Controller, {
197
+ control: form.control,
198
+ name: "panelDefinition.spec.display.name",
199
+ render: ({ field, fieldState })=>/*#__PURE__*/ (0, _jsxruntime.jsx)(_material.TextField, {
200
+ ...field,
201
+ required: true,
202
+ fullWidth: true,
203
+ label: "Name",
204
+ error: !!fieldState.error,
205
+ helperText: fieldState.error?.message,
206
+ value: watchedName ?? '',
207
+ onChange: (event)=>{
208
+ field.onChange(event);
209
+ setName(event.target.value);
210
+ }
211
+ })
212
+ })
213
+ }),
214
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Grid, {
215
+ item: true,
216
+ xs: 4,
217
+ children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_reacthookform.Controller, {
218
+ control: form.control,
219
+ name: "groupId",
220
+ render: ({ field, fieldState })=>/*#__PURE__*/ (0, _jsxruntime.jsx)(_material.TextField, {
221
+ select: true,
222
+ ...field,
223
+ required: true,
224
+ fullWidth: true,
225
+ label: "Group",
226
+ error: !!fieldState.error,
227
+ helperText: fieldState.error?.message,
228
+ onChange: (event)=>{
229
+ field.onChange(event);
230
+ },
231
+ children: panelGroups.map((panelGroup, index)=>/*#__PURE__*/ (0, _jsxruntime.jsx)(_material.MenuItem, {
232
+ value: panelGroup.id,
233
+ children: panelGroup.title ?? `Group ${index + 1}`
234
+ }, panelGroup.id))
235
+ })
236
+ })
237
+ }),
238
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Grid, {
239
+ item: true,
240
+ xs: 8,
241
+ children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_reacthookform.Controller, {
242
+ control: form.control,
243
+ name: "panelDefinition.spec.display.description",
244
+ render: ({ field, fieldState })=>/*#__PURE__*/ (0, _jsxruntime.jsx)(_material.TextField, {
245
+ ...field,
246
+ fullWidth: true,
247
+ label: "Description",
248
+ error: !!fieldState.error,
249
+ helperText: fieldState.error?.message,
250
+ value: watchedDescription ?? '',
251
+ onChange: (event)=>{
252
+ field.onChange(event);
253
+ setDescription(event.target.value);
254
+ }
255
+ })
256
+ })
257
+ }),
258
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Grid, {
259
+ item: true,
260
+ xs: 4,
261
+ children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_reacthookform.Controller, {
292
262
  control: form.control,
293
- panelDefinition: panelDefinition,
294
- onJSONChange: handlePanelDefinitionChange,
295
- onQueriesChange: (queries)=>{
296
- setQueries(queries);
297
- },
298
- onPluginSpecChange: (spec)=>{
299
- pluginEditor.onSpecChange(spec);
300
- }
263
+ name: "panelDefinition.spec.plugin.kind",
264
+ render: ({ field, fieldState })=>/*#__PURE__*/ (0, _jsxruntime.jsx)(_pluginsystem.PluginKindSelect, {
265
+ ...field,
266
+ pluginTypes: [
267
+ 'Panel'
268
+ ],
269
+ required: true,
270
+ fullWidth: true,
271
+ label: "Type",
272
+ disabled: pluginEditor.isLoading,
273
+ error: !!pluginEditor.error || !!fieldState.error,
274
+ helperText: pluginEditor.error?.message ?? fieldState.error?.message,
275
+ value: {
276
+ type: 'Panel',
277
+ kind: watchedPluginKind
278
+ },
279
+ onChange: (event)=>{
280
+ field.onChange(event.kind);
281
+ pluginEditor.onSelectionChange(event);
282
+ }
283
+ })
284
+ })
285
+ }),
286
+ /*#__PURE__*/ (0, _jsxruntime.jsxs)(_material.Grid, {
287
+ item: true,
288
+ xs: 12,
289
+ children: [
290
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Typography, {
291
+ variant: "h4",
292
+ marginBottom: 1,
293
+ children: "Preview"
294
+ }),
295
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.ErrorBoundary, {
296
+ FallbackComponent: _components.ErrorAlert,
297
+ children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_PanelPreview.PanelPreview, {
298
+ panelDefinition: panelDefinition
299
+ })
300
+ })
301
+ ]
302
+ }),
303
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Grid, {
304
+ item: true,
305
+ xs: 12,
306
+ children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.ErrorBoundary, {
307
+ FallbackComponent: _components.ErrorAlert,
308
+ children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_pluginsystem.PanelSpecEditor, {
309
+ ref: pluginEditorRef,
310
+ control: form.control,
311
+ panelDefinition: panelDefinition,
312
+ onJSONChange: handlePanelDefinitionChange,
313
+ onQueriesChange: (queries)=>{
314
+ setQueries(queries);
315
+ },
316
+ onPluginSpecChange: (spec)=>{
317
+ pluginEditor.onSpecChange(spec);
318
+ }
319
+ })
301
320
  })
302
321
  })
303
- })
304
- ]
322
+ ]
323
+ })
324
+ }),
325
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.DiscardChangesConfirmationDialog, {
326
+ description: "You have unapplied changes in this panel. Are you sure you want to discard these changes? Changes cannot be recovered.",
327
+ isOpen: isDiscardDialogOpened,
328
+ onCancel: ()=>{
329
+ setDiscardDialogOpened(false);
330
+ },
331
+ onDiscardChanges: ()=>{
332
+ setDiscardDialogOpened(false);
333
+ onClose();
334
+ }
305
335
  })
306
- }),
307
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.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
- }
317
- })
318
- ]
336
+ ]
337
+ })
319
338
  });
320
339
  }
321
340
  const panelEditorFormId = 'panel-editor-form';
@@ -24,6 +24,7 @@ const _jsxruntime = require("react/jsx-runtime");
24
24
  const _material = require("@mui/material");
25
25
  const _Close = /*#__PURE__*/ _interop_require_default(require("mdi-material-ui/Close"));
26
26
  const _react = require("react");
27
+ const _pluginsystem = require("@perses-dev/plugin-system");
27
28
  const _context = require("../../context");
28
29
  const _PanelGroupEditorForm = require("./PanelGroupEditorForm");
29
30
  function _interop_require_default(obj) {
@@ -33,6 +34,7 @@ function _interop_require_default(obj) {
33
34
  }
34
35
  function PanelGroupDialog() {
35
36
  const panelGroupEditor = (0, _context.usePanelGroupEditor)();
37
+ const variables = (0, _pluginsystem.useVariableValues)();
36
38
  // When the user clicks close, start closing but don't call the store yet to keep values stable during animtation
37
39
  const [isClosing, setIsClosing] = (0, _react.useState)(false);
38
40
  const handleClose = ()=>setIsClosing(true);
@@ -81,6 +83,7 @@ function PanelGroupDialog() {
81
83
  },
82
84
  children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_PanelGroupEditorForm.PanelGroupEditorForm, {
83
85
  initialValues: panelGroupEditor.initialValues,
86
+ variables: Object.keys(variables),
84
87
  onSubmit: handleSubmit
85
88
  })
86
89
  }),
@@ -32,18 +32,16 @@ const _jsxruntime = require("react/jsx-runtime");
32
32
  const _react = require("react");
33
33
  const _material = require("@mui/material");
34
34
  function PanelGroupEditorForm(props) {
35
- const { initialValues, onSubmit } = props;
35
+ const { initialValues, variables, onSubmit } = props;
36
36
  const [title, setTitle] = (0, _react.useState)(initialValues.title);
37
37
  const [isCollapsed, setIsCollapsed] = (0, _react.useState)(initialValues.isCollapsed);
38
- const handleCollapsedChange = (e)=>{
39
- const next = e.target.value;
40
- setIsCollapsed(next === 'Closed');
41
- };
38
+ const [repeatVariable, setRepeatVariable] = (0, _react.useState)(initialValues.repeatVariable);
42
39
  const handleSubmit = (e)=>{
43
40
  e.preventDefault();
44
41
  onSubmit({
45
42
  title,
46
- isCollapsed
43
+ isCollapsed,
44
+ repeatVariable
47
45
  });
48
46
  };
49
47
  return /*#__PURE__*/ (0, _jsxruntime.jsxs)("form", {
@@ -58,25 +56,21 @@ function PanelGroupEditorForm(props) {
58
56
  label: "Name",
59
57
  variant: "outlined",
60
58
  value: title,
61
- onChange: (e)=>setTitle(e.target.value)
59
+ onChange: (e)=>setTitle(e.target.value),
60
+ "data-testid": "panel-group-editor-name"
62
61
  })
63
62
  }),
64
63
  /*#__PURE__*/ (0, _jsxruntime.jsxs)(_material.FormControl, {
65
64
  fullWidth: true,
66
65
  margin: "normal",
67
66
  children: [
68
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.InputLabel, {
69
- id: "select-collapse-state",
70
- children: "Collapse State"
71
- }),
72
- /*#__PURE__*/ (0, _jsxruntime.jsxs)(_material.Select, {
67
+ /*#__PURE__*/ (0, _jsxruntime.jsxs)(_material.TextField, {
68
+ select: true,
73
69
  required: true,
74
- displayEmpty: true,
75
- labelId: "select-collapse-state",
76
70
  label: "Collapse State",
77
71
  size: "small",
78
72
  value: isCollapsed ? 'Closed' : 'Open',
79
- onChange: handleCollapsedChange,
73
+ onChange: (e)=>setIsCollapsed(e.target.value === 'Closed'),
80
74
  children: [
81
75
  /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.MenuItem, {
82
76
  value: "Open",
@@ -87,6 +81,32 @@ function PanelGroupEditorForm(props) {
87
81
  children: "Closed"
88
82
  })
89
83
  ]
84
+ }),
85
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.FormControl, {
86
+ fullWidth: true,
87
+ margin: "normal",
88
+ children: /*#__PURE__*/ (0, _jsxruntime.jsxs)(_material.TextField, {
89
+ select: true,
90
+ label: "Repeat Variable",
91
+ variant: "outlined",
92
+ value: repeatVariable ?? '',
93
+ onChange: (e)=>setRepeatVariable(e.target.value === '' ? undefined : e.target.value),
94
+ children: [
95
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.MenuItem, {
96
+ value: "",
97
+ children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Typography, {
98
+ sx: {
99
+ fontStyle: 'italic'
100
+ },
101
+ children: "None"
102
+ })
103
+ }),
104
+ variables?.sort((a, b)=>a.localeCompare(b)).map((variable)=>/*#__PURE__*/ (0, _jsxruntime.jsx)(_material.MenuItem, {
105
+ value: variable,
106
+ children: variable
107
+ }, variable))
108
+ ]
109
+ })
90
110
  })
91
111
  ]
92
112
  })