@perses-dev/plugin-system 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.
Files changed (54) hide show
  1. package/dist/cjs/components/DatasourceSelect.js +2 -1
  2. package/dist/cjs/components/LegendOptionsEditor/LegendOptionsEditor.js +73 -73
  3. package/dist/cjs/components/MultiQueryEditor/MultiQueryEditor.js +5 -2
  4. package/dist/cjs/components/MultiQueryEditor/QueryEditorContainer.js +13 -4
  5. package/dist/cjs/components/PanelSpecEditor/PanelSpecEditor.js +7 -5
  6. package/dist/cjs/components/PluginEditor/PluginEditor.js +25 -21
  7. package/dist/cjs/components/PluginKindSelect/PluginKindSelect.js +6 -3
  8. package/dist/cjs/components/Variables/VariableEditorForm/VariableEditorForm.js +5 -11
  9. package/dist/cjs/components/Variables/VariableEditorForm/VariablePreview.js +2 -13
  10. package/dist/cjs/context/query-params.js +1 -1
  11. package/dist/cjs/test/utils.js +17 -8
  12. package/dist/components/DatasourceSelect.d.ts.map +1 -1
  13. package/dist/components/DatasourceSelect.js +2 -1
  14. package/dist/components/DatasourceSelect.js.map +1 -1
  15. package/dist/components/LegendOptionsEditor/LegendOptionsEditor.d.ts.map +1 -1
  16. package/dist/components/LegendOptionsEditor/LegendOptionsEditor.js +75 -75
  17. package/dist/components/LegendOptionsEditor/LegendOptionsEditor.js.map +1 -1
  18. package/dist/components/MultiQueryEditor/MultiQueryEditor.d.ts +3 -2
  19. package/dist/components/MultiQueryEditor/MultiQueryEditor.d.ts.map +1 -1
  20. package/dist/components/MultiQueryEditor/MultiQueryEditor.js +6 -3
  21. package/dist/components/MultiQueryEditor/MultiQueryEditor.js.map +1 -1
  22. package/dist/components/MultiQueryEditor/QueryEditorContainer.d.ts +3 -2
  23. package/dist/components/MultiQueryEditor/QueryEditorContainer.d.ts.map +1 -1
  24. package/dist/components/MultiQueryEditor/QueryEditorContainer.js +13 -4
  25. package/dist/components/MultiQueryEditor/QueryEditorContainer.js.map +1 -1
  26. package/dist/components/PanelSpecEditor/PanelSpecEditor.d.ts +3 -2
  27. package/dist/components/PanelSpecEditor/PanelSpecEditor.d.ts.map +1 -1
  28. package/dist/components/PanelSpecEditor/PanelSpecEditor.js +7 -5
  29. package/dist/components/PanelSpecEditor/PanelSpecEditor.js.map +1 -1
  30. package/dist/components/PluginEditor/PluginEditor.d.ts +3 -3
  31. package/dist/components/PluginEditor/PluginEditor.d.ts.map +1 -1
  32. package/dist/components/PluginEditor/PluginEditor.js +26 -22
  33. package/dist/components/PluginEditor/PluginEditor.js.map +1 -1
  34. package/dist/components/PluginEditor/plugin-editor-api.d.ts +4 -0
  35. package/dist/components/PluginEditor/plugin-editor-api.d.ts.map +1 -1
  36. package/dist/components/PluginEditor/plugin-editor-api.js.map +1 -1
  37. package/dist/components/PluginKindSelect/PluginKindSelect.d.ts.map +1 -1
  38. package/dist/components/PluginKindSelect/PluginKindSelect.js +7 -4
  39. package/dist/components/PluginKindSelect/PluginKindSelect.js.map +1 -1
  40. package/dist/components/Variables/VariableEditorForm/VariableEditorForm.d.ts.map +1 -1
  41. package/dist/components/Variables/VariableEditorForm/VariableEditorForm.js +5 -11
  42. package/dist/components/Variables/VariableEditorForm/VariableEditorForm.js.map +1 -1
  43. package/dist/components/Variables/VariableEditorForm/VariablePreview.d.ts +0 -2
  44. package/dist/components/Variables/VariableEditorForm/VariablePreview.d.ts.map +1 -1
  45. package/dist/components/Variables/VariableEditorForm/VariablePreview.js +2 -13
  46. package/dist/components/Variables/VariableEditorForm/VariablePreview.js.map +1 -1
  47. package/dist/context/query-params.js +1 -1
  48. package/dist/context/query-params.js.map +1 -1
  49. package/dist/runtime/TimeRangeProvider/query-params.d.ts.map +1 -1
  50. package/dist/runtime/TimeRangeProvider/query-params.js.map +1 -1
  51. package/dist/test/utils.d.ts.map +1 -1
  52. package/dist/test/utils.js +17 -8
  53. package/dist/test/utils.js.map +1 -1
  54. package/package.json +5 -5
@@ -61,7 +61,7 @@ const emptyDatasourceOption = {
61
61
  value: ''
62
62
  };
63
63
  function DatasourceSelect(props) {
64
- const { datasourcePluginKind, value, project, onChange, ...others } = props;
64
+ const { datasourcePluginKind, value, project, readOnly, onChange, ...others } = props;
65
65
  const { data, isLoading } = (0, _runtime.useListDatasourceSelectItems)(datasourcePluginKind, project);
66
66
  const variables = (0, _runtime.useVariableValues)();
67
67
  const defaultValue = (0, _react.useMemo)(()=>{
@@ -132,6 +132,7 @@ function DatasourceSelect(props) {
132
132
  // eslint-disable-next-line @typescript-eslint/no-empty-function
133
133
  const fakeActionEvent = ()=>{};
134
134
  return /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Autocomplete, {
135
+ readOnly: readOnly,
135
136
  options: options,
136
137
  renderInput: (params)=>/*#__PURE__*/ (0, _jsxruntime.jsx)(_material.TextField, {
137
138
  ...params,
@@ -32,12 +32,6 @@ const POSITION_OPTIONS = Object.entries(_model.LEGEND_POSITIONS_CONFIG).map(([id
32
32
  ...config
33
33
  };
34
34
  });
35
- const MODE_OPTIONS = Object.entries(_model.LEGEND_MODE_CONFIG).map(([id, config])=>{
36
- return {
37
- id: id,
38
- ...config
39
- };
40
- });
41
35
  const SIZE_OPTIONS = Object.entries(_model.LEGEND_SIZE_CONFIG).map(([id, config])=>{
42
36
  return {
43
37
  id: id,
@@ -58,13 +52,6 @@ function LegendOptionsEditor({ value, onChange, showValuesEditor = true, calcula
58
52
  position: newValue.id
59
53
  });
60
54
  };
61
- const handleLegendModeChange = (_, newValue)=>{
62
- onChange({
63
- ...value,
64
- position: currentPosition,
65
- mode: newValue.id
66
- });
67
- };
68
55
  const handleLegendSizeChange = (_, newValue)=>{
69
56
  onChange({
70
57
  ...value,
@@ -85,7 +72,6 @@ function LegendOptionsEditor({ value, onChange, showValuesEditor = true, calcula
85
72
  const currentPosition = (0, _core.getLegendPosition)(value?.position);
86
73
  const legendPositionConfig = _model.LEGEND_POSITIONS_CONFIG[currentPosition];
87
74
  const currentMode = (0, _core.getLegendMode)(value?.mode);
88
- const legendModeConfig = _model.LEGEND_MODE_CONFIG[currentMode];
89
75
  const currentSize = (0, _core.getLegendSize)(value?.size);
90
76
  const legendSizeConfig = _model.LEGEND_SIZE_CONFIG[currentSize];
91
77
  const legendValuesConfig = (0, _react.useMemo)(()=>{
@@ -147,65 +133,79 @@ function LegendOptionsEditor({ value, onChange, showValuesEditor = true, calcula
147
133
  onChange: handleLegendShowChange
148
134
  })
149
135
  }),
150
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.OptionsEditorControl, {
151
- label: "Position",
152
- control: /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.SettingsAutocomplete, {
153
- value: {
154
- ...legendPositionConfig,
155
- id: currentPosition
156
- },
157
- options: POSITION_OPTIONS,
158
- onChange: handleLegendPositionChange,
159
- disabled: value === undefined,
160
- disableClearable: true
161
- })
162
- }),
163
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.OptionsEditorControl, {
164
- label: "Mode",
165
- control: /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.SettingsAutocomplete, {
166
- value: {
167
- ...legendModeConfig,
168
- id: currentMode
169
- },
170
- options: MODE_OPTIONS,
171
- onChange: handleLegendModeChange,
172
- disabled: !value,
173
- disableClearable: true
174
- })
175
- }),
176
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.OptionsEditorControl, {
177
- label: "Size",
178
- control: /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.SettingsAutocomplete, {
179
- value: {
180
- ...legendSizeConfig,
181
- id: currentSize
182
- },
183
- options: SIZE_OPTIONS,
184
- onChange: handleLegendSizeChange,
185
- // TODO: enable sizes for list mode when we normalize the layout of
186
- // lists to more closely match tables.
187
- disabled: !value || currentMode !== 'table',
188
- disableClearable: true
189
- })
190
- }),
191
- showValuesEditor && /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.OptionsEditorControl, {
192
- label: "Values",
193
- control: // For some reason, the inferred option type doesn't always seem to work
194
- // quite right when `multiple` is true. Explicitly setting the generics
195
- // to work around this.
196
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.SettingsAutocomplete, {
197
- multiple: true,
198
- disableCloseOnSelect: true,
199
- disableClearable: true,
200
- value: legendValuesConfig,
201
- options: valueOptions,
202
- onChange: handleLegendValueChange,
203
- disabled: !value || currentMode !== 'table',
204
- limitTags: 1,
205
- ChipProps: {
206
- size: 'small'
207
- }
208
- })
136
+ value && /*#__PURE__*/ (0, _jsxruntime.jsxs)(_jsxruntime.Fragment, {
137
+ children: [
138
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.OptionsEditorControl, {
139
+ label: "Position",
140
+ control: /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.SettingsAutocomplete, {
141
+ value: {
142
+ ...legendPositionConfig,
143
+ id: currentPosition
144
+ },
145
+ options: POSITION_OPTIONS,
146
+ onChange: handleLegendPositionChange,
147
+ disableClearable: true
148
+ })
149
+ }),
150
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.OptionsEditorControl, {
151
+ label: "Mode",
152
+ control: /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.ToggleButtonGroup, {
153
+ color: "primary",
154
+ exclusive: true,
155
+ value: currentMode,
156
+ "aria-label": "Mode",
157
+ onChange: (__, newValue)=>{
158
+ onChange({
159
+ ...value,
160
+ position: currentPosition,
161
+ mode: newValue
162
+ });
163
+ },
164
+ children: Object.entries(_model.LEGEND_MODE_CONFIG).map(([modeId, config])=>/*#__PURE__*/ (0, _jsxruntime.jsx)(_material.ToggleButton, {
165
+ value: modeId,
166
+ selected: currentMode === modeId,
167
+ "aria-label": `display ${modeId} mode`,
168
+ children: config.label
169
+ }, modeId))
170
+ })
171
+ }),
172
+ currentMode === 'table' && /*#__PURE__*/ (0, _jsxruntime.jsxs)(_jsxruntime.Fragment, {
173
+ children: [
174
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.OptionsEditorControl, {
175
+ label: "Size",
176
+ control: /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.SettingsAutocomplete, {
177
+ value: {
178
+ ...legendSizeConfig,
179
+ id: currentSize
180
+ },
181
+ options: SIZE_OPTIONS,
182
+ onChange: handleLegendSizeChange,
183
+ // TODO: enable sizes for list mode when we normalize the layout of
184
+ // lists to more closely match tables.
185
+ disableClearable: true
186
+ })
187
+ }),
188
+ showValuesEditor && /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.OptionsEditorControl, {
189
+ label: "Values",
190
+ control: // For some reason, the inferred option type doesn't always seem to work
191
+ // quite right when `multiple` is true. Explicitly setting the generics
192
+ // to work around this.
193
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.SettingsAutocomplete, {
194
+ multiple: true,
195
+ disableCloseOnSelect: true,
196
+ disableClearable: true,
197
+ value: legendValuesConfig,
198
+ options: valueOptions,
199
+ onChange: handleLegendValueChange,
200
+ limitTags: 1,
201
+ ChipProps: {
202
+ size: 'small'
203
+ }
204
+ })
205
+ })
206
+ ]
207
+ })
208
+ ]
209
209
  })
210
210
  ]
211
211
  });
@@ -60,7 +60,8 @@ function useDefaultQueryDefinition(queryTypes) {
60
60
  isLoading
61
61
  };
62
62
  }
63
- function MultiQueryEditor({ queryTypes, queries = [], onChange }) {
63
+ const MultiQueryEditor = /*#__PURE__*/ (0, _react.forwardRef)((props, ref)=>{
64
+ const { queryTypes, queries = [], onChange } = props;
64
65
  const { defaultInitialQueryDefinition, isLoading } = useDefaultQueryDefinition(queryTypes);
65
66
  // State for which queries are collapsed
66
67
  const [queriesCollapsed, setQueriesCollapsed] = (0, _react.useState)(queries.map(()=>false));
@@ -122,6 +123,7 @@ function MultiQueryEditor({ queryTypes, queries = [], onChange }) {
122
123
  /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Stack, {
123
124
  spacing: 1,
124
125
  children: queryDefinitions.map((query, i)=>/*#__PURE__*/ (0, _jsxruntime.jsx)(_QueryEditorContainer.QueryEditorContainer, {
126
+ ref: ref,
125
127
  queryTypes: queryTypes,
126
128
  index: i,
127
129
  query: query,
@@ -142,4 +144,5 @@ function MultiQueryEditor({ queryTypes, queries = [], onChange }) {
142
144
  })
143
145
  ]
144
146
  });
145
- }
147
+ });
148
+ MultiQueryEditor.displayName = 'MultiQueryEditor';
@@ -26,13 +26,16 @@ const _material = require("@mui/material");
26
26
  const _DeleteOutline = /*#__PURE__*/ _interop_require_default(require("mdi-material-ui/DeleteOutline"));
27
27
  const _ChevronDown = /*#__PURE__*/ _interop_require_default(require("mdi-material-ui/ChevronDown"));
28
28
  const _ChevronRight = /*#__PURE__*/ _interop_require_default(require("mdi-material-ui/ChevronRight"));
29
+ const _react = require("react");
29
30
  const _PluginEditor = require("../PluginEditor");
31
+ const _runtime = require("../../runtime");
30
32
  function _interop_require_default(obj) {
31
33
  return obj && obj.__esModule ? obj : {
32
34
  default: obj
33
35
  };
34
36
  }
35
- const QueryEditorContainer = ({ queryTypes, index, query, isCollapsed, onDelete, onChange, onCollapseExpand })=>{
37
+ const QueryEditorContainer = /*#__PURE__*/ (0, _react.forwardRef)((props, ref)=>{
38
+ const { queryTypes, index, query, isCollapsed, onDelete, onChange, onCollapseExpand } = props;
36
39
  return /*#__PURE__*/ (0, _jsxruntime.jsxs)(_material.Stack, {
37
40
  spacing: 1,
38
41
  children: [
@@ -68,21 +71,24 @@ const QueryEditorContainer = ({ queryTypes, index, query, isCollapsed, onDelete,
68
71
  ]
69
72
  }),
70
73
  !isCollapsed && /*#__PURE__*/ (0, _jsxruntime.jsx)(QueryEditor, {
74
+ ref: ref,
71
75
  queryTypes: queryTypes,
72
76
  value: query,
73
77
  onChange: (next)=>onChange(index, next)
74
78
  })
75
79
  ]
76
80
  }, index);
77
- };
81
+ });
82
+ QueryEditorContainer.displayName = 'QueryEditorContainer';
78
83
  /**
79
84
  * Editor for a query definition. This component is responsible for rendering the plugin editor for the given query.
80
85
  * This will allow user to select a plugin extending from the given supported query types, and then edit the plugin
81
86
  * spec for this plugin.
82
87
  * @param props
83
88
  * @constructor
84
- */ function QueryEditor(props) {
89
+ */ const QueryEditor = /*#__PURE__*/ (0, _react.forwardRef)((props, ref)=>{
85
90
  const { value, onChange, queryTypes, ...others } = props;
91
+ const { refresh } = (0, _runtime.useTimeRange)();
86
92
  const handlePluginChange = (next)=>{
87
93
  onChange((0, _immer.produce)(value, (draft)=>{
88
94
  draft.kind = next.selection.type;
@@ -93,6 +99,8 @@ const QueryEditorContainer = ({ queryTypes, index, query, isCollapsed, onDelete,
93
99
  return /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Box, {
94
100
  ...others,
95
101
  children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_PluginEditor.PluginEditor, {
102
+ postExecuteRunQuery: refresh,
103
+ ref: ref,
96
104
  withRunQueryButton: true,
97
105
  pluginTypes: queryTypes,
98
106
  pluginKindLabel: "Query Type",
@@ -106,4 +114,5 @@ const QueryEditorContainer = ({ queryTypes, index, query, isCollapsed, onDelete,
106
114
  onChange: handlePluginChange
107
115
  })
108
116
  });
109
- }
117
+ });
118
+ QueryEditor.displayName = 'QueryEditor';
@@ -23,10 +23,11 @@ Object.defineProperty(exports, "PanelSpecEditor", {
23
23
  const _jsxruntime = require("react/jsx-runtime");
24
24
  const _components = require("@perses-dev/components");
25
25
  const _reacthookform = require("react-hook-form");
26
+ const _react = require("react");
26
27
  const _runtime = require("../../runtime");
27
28
  const _OptionsEditorTabs = require("../OptionsEditorTabs");
28
29
  const _MultiQueryEditor = require("../MultiQueryEditor");
29
- function PanelSpecEditor(props) {
30
+ const PanelSpecEditor = /*#__PURE__*/ (0, _react.forwardRef)((props, ref)=>{
30
31
  const { control, panelDefinition, onJSONChange, onQueriesChange, onPluginSpecChange } = props;
31
32
  const { kind } = panelDefinition.spec.plugin;
32
33
  const { data: plugin, isLoading, error } = (0, _runtime.usePlugin)('Panel', kind);
@@ -35,11 +36,10 @@ function PanelSpecEditor(props) {
35
36
  error: error
36
37
  });
37
38
  }
38
- // TODO: Proper loading indicator
39
39
  if (isLoading) {
40
40
  return null;
41
41
  }
42
- if (plugin === undefined) {
42
+ if (!plugin) {
43
43
  throw new Error(`Missing implementation for panel plugin with kind '${kind}'`);
44
44
  }
45
45
  const { panelOptionsEditorComponents, hideQueryEditor } = plugin;
@@ -51,6 +51,7 @@ function PanelSpecEditor(props) {
51
51
  control: control,
52
52
  name: "panelDefinition.spec.queries",
53
53
  render: ({ field })=>/*#__PURE__*/ (0, _jsxruntime.jsx)(_MultiQueryEditor.MultiQueryEditor, {
54
+ ref: ref,
54
55
  queryTypes: plugin.supportedQueryTypes ?? [],
55
56
  queries: panelDefinition.spec.queries ?? [],
56
57
  onChange: (queries)=>{
@@ -61,7 +62,7 @@ function PanelSpecEditor(props) {
61
62
  })
62
63
  });
63
64
  }
64
- if (panelOptionsEditorComponents !== undefined) {
65
+ if (panelOptionsEditorComponents) {
65
66
  tabs = tabs.concat(panelOptionsEditorComponents.map(({ label, content: OptionsEditorComponent })=>({
66
67
  label,
67
68
  content: /*#__PURE__*/ (0, _jsxruntime.jsx)(_reacthookform.Controller, {
@@ -105,4 +106,5 @@ function PanelSpecEditor(props) {
105
106
  tabs: tabs
106
107
  }, tabs.length)
107
108
  });
108
- }
109
+ });
110
+ PanelSpecEditor.displayName = 'PanelSpecEditor';
@@ -33,17 +33,16 @@ function _interop_require_default(obj) {
33
33
  default: obj
34
34
  };
35
35
  }
36
- function PluginEditor(props) {
37
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
38
- const { value, withRunQueryButton = true, pluginTypes, pluginKindLabel, onChange: _, isReadonly, ...others } = props;
36
+ const PluginEditor = /*#__PURE__*/ (0, _react.forwardRef)((props, ref)=>{
37
+ const { value, withRunQueryButton = true, pluginTypes, pluginKindLabel, onChange: _, isReadonly, postExecuteRunQuery: refresh, ...others } = props;
39
38
  const { pendingSelection, isLoading, error, onSelectionChange, onSpecChange } = (0, _plugineditorapi.usePluginEditor)(props);
40
39
  /*
41
- We could technically merge the watchedQuery, watchedOtherSpecs into a single watched-object,
42
- because at the end of the day, they are all specs.
43
- However, let's have them separated to keep the code simple and readable.
44
- Reason: Only Query string field is common between all of them. Other specs may be different
45
- Example: Legend, and MinSteps
46
- */ const [watchedQuery, setWatchQuery] = (0, _react.useState)(value.spec['query']);
40
+ We could technically merge the watchedQuery, watchedOtherSpecs into a single watched-object,
41
+ because at the end of the day, they are all specs.
42
+ However, let's have them separated to keep the code simple and readable.
43
+ Reason: Only Query string field is common between all of them. Other specs may be different
44
+ Example: Legend, and MinSteps
45
+ */ const [watchedQuery, setWatchQuery] = (0, _react.useState)(value.spec['query']);
47
46
  const [watchedOtherSpecs, setWatchOtherSpecs] = (0, _react.useState)(value.spec);
48
47
  const runQueryHandler = (0, _react.useCallback)(()=>{
49
48
  onSpecChange({
@@ -51,11 +50,13 @@ function PluginEditor(props) {
51
50
  ...watchedOtherSpecs,
52
51
  query: watchedQuery
53
52
  });
53
+ refresh?.();
54
54
  }, [
55
55
  value.spec,
56
56
  onSpecChange,
57
57
  watchedQuery,
58
- watchedOtherSpecs
58
+ watchedOtherSpecs,
59
+ refresh
59
60
  ]);
60
61
  const queryHandlerSettings = (0, _react.useMemo)(()=>{
61
62
  return withRunQueryButton ? {
@@ -70,19 +71,25 @@ function PluginEditor(props) {
70
71
  }, [
71
72
  withRunQueryButton
72
73
  ]);
74
+ (0, _react.useImperativeHandle)(ref, ()=>({
75
+ flushChanges: runQueryHandler
76
+ }));
73
77
  return /*#__PURE__*/ (0, _jsxruntime.jsxs)(_material.Box, {
74
78
  ...others,
75
79
  children: [
76
80
  /*#__PURE__*/ (0, _jsxruntime.jsxs)(_material.Box, {
77
81
  sx: {
78
82
  display: 'flex',
79
- flexDirection: 'row'
83
+ flexDirection: 'row',
84
+ alignItems: 'center',
85
+ justifyContent: 'space-between',
86
+ gap: 1,
87
+ mb: 1
80
88
  },
81
89
  children: [
82
90
  /*#__PURE__*/ (0, _jsxruntime.jsx)(_PluginKindSelect.PluginKindSelect, {
83
91
  fullWidth: false,
84
92
  sx: {
85
- mb: 2,
86
93
  minWidth: 120
87
94
  },
88
95
  margin: "dense",
@@ -90,8 +97,10 @@ function PluginEditor(props) {
90
97
  pluginTypes: pluginTypes,
91
98
  disabled: isLoading,
92
99
  value: pendingSelection ? pendingSelection : value.selection,
93
- InputProps: {
94
- readOnly: isReadonly
100
+ slotProps: {
101
+ input: {
102
+ readOnly: isReadonly
103
+ }
95
104
  },
96
105
  error: !!error,
97
106
  helperText: error?.message,
@@ -100,12 +109,6 @@ function PluginEditor(props) {
100
109
  withRunQueryButton && !isLoading && /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Button, {
101
110
  "data-testid": "run_query_button",
102
111
  variant: "contained",
103
- sx: {
104
- marginTop: 1.5,
105
- marginBottom: 1.5,
106
- paddingTop: 0.5,
107
- marginLeft: 'auto'
108
- },
109
112
  startIcon: /*#__PURE__*/ (0, _jsxruntime.jsx)(_Reload.default, {}),
110
113
  onClick: runQueryHandler,
111
114
  children: "Run Query"
@@ -124,4 +127,5 @@ function PluginEditor(props) {
124
127
  })
125
128
  ]
126
129
  });
127
- }
130
+ });
131
+ PluginEditor.displayName = 'PluginEditor';
@@ -27,6 +27,9 @@ const _runtime = require("../../runtime");
27
27
  const PluginKindSelect = /*#__PURE__*/ (0, _react.forwardRef)((props, ref)=>{
28
28
  const { pluginTypes, value: propValue, onChange, ...others } = props;
29
29
  const { data, isLoading } = (0, _runtime.useListPluginMetadata)(pluginTypes);
30
+ const sortedData = (0, _react.useMemo)(()=>data?.sort((a, b)=>a.spec.display.name.localeCompare(b.spec.display.name)), [
31
+ data
32
+ ]);
30
33
  // Pass an empty value while options are still loading so MUI doesn't complain about us using an "out of range" value
31
34
  const value = !propValue || isLoading ? '' : selectionToOptionValue(propValue);
32
35
  const handleChange = (event)=>{
@@ -37,9 +40,9 @@ const PluginKindSelect = /*#__PURE__*/ (0, _react.forwardRef)((props, ref)=>{
37
40
  return '';
38
41
  }
39
42
  const selectedValue = optionValueToSelection(selected);
40
- return data?.find((v)=>v.kind === selectedValue.type && v.spec.name === selectedValue.kind)?.spec.display.name;
43
+ return sortedData?.find((v)=>v.kind === selectedValue.type && v.spec.name === selectedValue.kind)?.spec.display.name;
41
44
  }, [
42
- data
45
+ sortedData
43
46
  ]);
44
47
  // TODO: Does this need a loading indicator of some kind?
45
48
  return /*#__PURE__*/ (0, _jsxruntime.jsxs)(_material.TextField, {
@@ -58,7 +61,7 @@ const PluginKindSelect = /*#__PURE__*/ (0, _react.forwardRef)((props, ref)=>{
58
61
  value: "",
59
62
  children: "Loading..."
60
63
  }),
61
- data?.map((metadata)=>/*#__PURE__*/ (0, _jsxruntime.jsx)(_material.MenuItem, {
64
+ sortedData?.map((metadata)=>/*#__PURE__*/ (0, _jsxruntime.jsx)(_material.MenuItem, {
62
65
  "data-testid": "option",
63
66
  value: selectionToOptionValue({
64
67
  type: metadata.kind,
@@ -106,12 +106,7 @@ function ListVariableEditorForm({ action, control }) {
106
106
  /** We use `previewSpec` to know when to explicitly update the
107
107
  * spec that will be used for preview. The reason why we do this is to avoid
108
108
  * having to re-fetch the values when the user is still editing the spec.
109
- */ const [previewSpec, setPreviewSpec] = (0, _react.useState)(form.getValues());
110
- const { refresh } = (0, _runtime.useTimeRange)();
111
- const refreshPreview = ()=>{
112
- refresh();
113
- setPreviewSpec(form.getValues());
114
- };
109
+ */ const previewSpec = form.getValues();
115
110
  const plugin = (0, _reacthookform.useWatch)({
116
111
  control,
117
112
  name: 'spec.plugin'
@@ -131,6 +126,7 @@ function ListVariableEditorForm({ action, control }) {
131
126
  if (values.spec.allowMultiple === undefined) {
132
127
  form.setValue('spec.allowMultiple', false);
133
128
  }
129
+ const { refresh } = (0, _runtime.useTimeRange)();
134
130
  return /*#__PURE__*/ (0, _jsxruntime.jsxs)(_jsxruntime.Fragment, {
135
131
  children: [
136
132
  /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Typography, {
@@ -149,8 +145,7 @@ function ListVariableEditorForm({ action, control }) {
149
145
  previewSpec
150
146
  ],
151
147
  children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_VariablePreview.VariableListPreview, {
152
- definition: previewSpec,
153
- onRefresh: refreshPreview
148
+ definition: previewSpec
154
149
  })
155
150
  })
156
151
  }) : /*#__PURE__*/ (0, _jsxruntime.jsx)(_VariablePreview.VariablePreview, {
@@ -164,6 +159,7 @@ function ListVariableEditorForm({ action, control }) {
164
159
  name: "spec.plugin",
165
160
  render: ({ field })=>{
166
161
  return /*#__PURE__*/ (0, _jsxruntime.jsx)(_PluginEditor.PluginEditor, {
162
+ postExecuteRunQuery: refresh,
167
163
  withRunQueryButton: true,
168
164
  width: "100%",
169
165
  pluginTypes: [
@@ -175,9 +171,7 @@ function ListVariableEditorForm({ action, control }) {
175
171
  type: 'Variable',
176
172
  kind: kind ?? 'StaticListVariable'
177
173
  },
178
- spec: pluginSpec ?? {
179
- values: []
180
- }
174
+ spec: pluginSpec ?? {}
181
175
  },
182
176
  isReadonly: action === 'read',
183
177
  onChange: (v)=>{
@@ -32,7 +32,6 @@ const _jsxruntime = require("react/jsx-runtime");
32
32
  const _react = /*#__PURE__*/ _interop_require_wildcard(require("react"));
33
33
  const _material = require("@mui/material");
34
34
  const _components = require("@perses-dev/components");
35
- const _Refresh = /*#__PURE__*/ _interop_require_default(require("mdi-material-ui/Refresh"));
36
35
  const _ClipboardOutline = /*#__PURE__*/ _interop_require_default(require("mdi-material-ui/ClipboardOutline"));
37
36
  const _constants = require("../../../constants");
38
37
  const _variablemodel = require("../variable-model");
@@ -84,7 +83,7 @@ function _interop_require_wildcard(obj, nodeInterop) {
84
83
  }
85
84
  const DEFAULT_MAX_PREVIEW_VALUES = 50;
86
85
  function VariablePreview(props) {
87
- const { values, onRefresh, isLoading, error } = props;
86
+ const { values, isLoading, error } = props;
88
87
  const [maxValues, setMaxValues] = (0, _react.useState)(DEFAULT_MAX_PREVIEW_VALUES);
89
88
  const { infoSnackbar } = (0, _components.useSnackbar)();
90
89
  const showAll = ()=>{
@@ -106,14 +105,6 @@ function VariablePreview(props) {
106
105
  variant: "h4",
107
106
  children: "Preview Values"
108
107
  }),
109
- onRefresh && /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.InfoTooltip, {
110
- description: _constants.TOOLTIP_TEXT.refreshVariableValues,
111
- children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.IconButton, {
112
- onClick: onRefresh,
113
- size: "small",
114
- children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_Refresh.default, {})
115
- })
116
- }),
117
108
  /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.InfoTooltip, {
118
109
  description: _constants.TOOLTIP_TEXT.copyVariableValues,
119
110
  children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.IconButton, {
@@ -172,18 +163,16 @@ function VariablePreview(props) {
172
163
  });
173
164
  }
174
165
  function VariableListPreview(props) {
175
- const { onRefresh, definition } = props;
166
+ const { definition } = props;
176
167
  const { data, isFetching, error } = (0, _variablemodel.useListVariablePluginValues)(definition);
177
168
  const errorMessage = error?.message;
178
169
  const variablePreview = (0, _react.useMemo)(()=>/*#__PURE__*/ (0, _jsxruntime.jsx)(VariablePreview, {
179
170
  values: data?.map((val)=>val.value) || [],
180
- onRefresh: onRefresh,
181
171
  isLoading: isFetching,
182
172
  error: errorMessage
183
173
  }), [
184
174
  errorMessage,
185
175
  isFetching,
186
- onRefresh,
187
176
  data
188
177
  ]);
189
178
  return variablePreview;
@@ -1,4 +1,4 @@
1
- // Copyright 2023 The Perses Authors
1
+ // Copyright 2025 The Perses Authors
2
2
  // Licensed under the Apache License, Version 2.0 (the "License");
3
3
  // you may not use this file except in compliance with the License.
4
4
  // You may obtain a copy of the License at
@@ -22,7 +22,9 @@ Object.defineProperty(exports, "getTestContextWrapper", {
22
22
  });
23
23
  const _jsxruntime = require("react/jsx-runtime");
24
24
  const _reactquery = require("@tanstack/react-query");
25
+ const _core = require("@perses-dev/core");
25
26
  const _components = require("../components");
27
+ const _runtime = require("../runtime");
26
28
  const _testplugins = require("./test-plugins");
27
29
  function getTestContextWrapper(contextOptions) {
28
30
  // Create a new QueryClient for each test to avoid caching issues
@@ -34,15 +36,22 @@ function getTestContextWrapper(contextOptions) {
34
36
  }
35
37
  }
36
38
  });
39
+ const timeRange = {
40
+ start: new Date(Date.now() - Number(_core.DEFAULT_DASHBOARD_DURATION)),
41
+ end: new Date()
42
+ };
37
43
  return function Wrapper({ children }) {
38
- return /*#__PURE__*/ (0, _jsxruntime.jsx)(_reactquery.QueryClientProvider, {
39
- client: queryClient,
40
- children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.PluginRegistry, {
41
- pluginLoader: _testplugins.testPluginLoader,
42
- defaultPluginKinds: contextOptions?.defaultPluginKinds ?? {
43
- TimeSeriesQuery: 'PrometheusTimeSeriesQuery'
44
- },
45
- children: children
44
+ return /*#__PURE__*/ (0, _jsxruntime.jsx)(_runtime.TimeRangeProvider, {
45
+ timeRange: timeRange,
46
+ children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_reactquery.QueryClientProvider, {
47
+ client: queryClient,
48
+ children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.PluginRegistry, {
49
+ pluginLoader: _testplugins.testPluginLoader,
50
+ defaultPluginKinds: contextOptions?.defaultPluginKinds ?? {
51
+ TimeSeriesQuery: 'PrometheusTimeSeriesQuery'
52
+ },
53
+ children: children
54
+ })
46
55
  })
47
56
  });
48
57
  };
@@ -1 +1 @@
1
- {"version":3,"file":"DatasourceSelect.d.ts","sourceRoot":"","sources":["../../src/components/DatasourceSelect.tsx"],"names":[],"mappings":"AAcA,OAAO,EAML,mBAAmB,EACnB,eAAe,EAGhB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACpE,OAAO,EAAE,YAAY,EAAW,MAAM,OAAO,CAAC;AAC9C,OAAO,EAEL,yBAAyB,EACzB,4BAA4B,EAG5B,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAOpB,KAAK,eAAe,GAAG,UAAU,GAAG,OAAO,GAAG,UAAU,CAAC;AAWzD,MAAM,MAAM,qBAAqB,CAAC,CAAC,GAAG,kBAAkB,IAAI,CAAC,GAAG,YAAY,CAAC;AAE7E,MAAM,WAAW,qBAAsB,SAAQ,IAAI,CAAC,mBAAmB,GAAG,eAAe,CAAC,MAAM,CAAC,EAAE,eAAe,CAAC;IACjH,KAAK,EAAE,qBAAqB,CAAC;IAC7B,QAAQ,EAAE,CAAC,IAAI,EAAE,qBAAqB,KAAK,IAAI,CAAC;IAChD,oBAAoB,EAAE,MAAM,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,GAAG,YAAY,CAiH3E;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,OAAO,CAAC;IAAC,UAAU,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,YAAY,CAahH;AAKD;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,4BAA4B,GAAG,YAAY,GAAG,MAAM,CAKnG;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,qBAAqB,CAehF;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,qBAAqB,GAAG,SAAS,GAAG,KAAK,IAAI,YAAY,CAEpG;AAED,eAAO,MAAM,+BAA+B,UACnC,qBAAqB,GAAG,SAAS,aAC7B,gBAAgB,8BACC,yBAAyB,EAAE,GAAG,SAAS,KAClE,kBAAkB,GAAG,SA4BvB,CAAC;AAEF,eAAO,MAAM,kCAAkC,UACtC,qBAAqB,wBACN,MAAM,KAC3B,kBAQF,CAAC"}
1
+ {"version":3,"file":"DatasourceSelect.d.ts","sourceRoot":"","sources":["../../src/components/DatasourceSelect.tsx"],"names":[],"mappings":"AAcA,OAAO,EAML,mBAAmB,EACnB,eAAe,EAGhB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACpE,OAAO,EAAE,YAAY,EAAW,MAAM,OAAO,CAAC;AAC9C,OAAO,EAEL,yBAAyB,EACzB,4BAA4B,EAG5B,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAOpB,KAAK,eAAe,GAAG,UAAU,GAAG,OAAO,GAAG,UAAU,CAAC;AAWzD,MAAM,MAAM,qBAAqB,CAAC,CAAC,GAAG,kBAAkB,IAAI,CAAC,GAAG,YAAY,CAAC;AAE7E,MAAM,WAAW,qBAAsB,SAAQ,IAAI,CAAC,mBAAmB,GAAG,eAAe,CAAC,MAAM,CAAC,EAAE,eAAe,CAAC;IACjH,KAAK,EAAE,qBAAqB,CAAC;IAC7B,QAAQ,EAAE,CAAC,IAAI,EAAE,qBAAqB,KAAK,IAAI,CAAC;IAChD,oBAAoB,EAAE,MAAM,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,GAAG,YAAY,CAkH3E;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,OAAO,CAAC;IAAC,UAAU,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,YAAY,CAahH;AAKD;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,4BAA4B,GAAG,YAAY,GAAG,MAAM,CAKnG;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,qBAAqB,CAehF;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,qBAAqB,GAAG,SAAS,GAAG,KAAK,IAAI,YAAY,CAEpG;AAED,eAAO,MAAM,+BAA+B,UACnC,qBAAqB,GAAG,SAAS,aAC7B,gBAAgB,8BACC,yBAAyB,EAAE,GAAG,SAAS,KAClE,kBAAkB,GAAG,SA4BvB,CAAC;AAEF,eAAO,MAAM,kCAAkC,UACtC,qBAAqB,wBACN,MAAM,KAC3B,kBAQF,CAAC"}
@@ -27,7 +27,7 @@ const emptyDatasourceOption = {
27
27
  * Displays a MUI input for selecting a Datasource of a particular kind. Note: The 'value' and `onChange` handler for
28
28
  * the input deal with a `DatasourceSelector`.
29
29
  */ export function DatasourceSelect(props) {
30
- const { datasourcePluginKind, value, project, onChange, ...others } = props;
30
+ const { datasourcePluginKind, value, project, readOnly, onChange, ...others } = props;
31
31
  const { data, isLoading } = useListDatasourceSelectItems(datasourcePluginKind, project);
32
32
  const variables = useVariableValues();
33
33
  const defaultValue = useMemo(()=>{
@@ -98,6 +98,7 @@ const emptyDatasourceOption = {
98
98
  // eslint-disable-next-line @typescript-eslint/no-empty-function
99
99
  const fakeActionEvent = ()=>{};
100
100
  return /*#__PURE__*/ _jsx(Autocomplete, {
101
+ readOnly: readOnly,
101
102
  options: options,
102
103
  renderInput: (params)=>/*#__PURE__*/ _jsx(TextField, {
103
104
  ...params,