@perses-dev/plugin-system 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 (55) hide show
  1. package/dist/cjs/components/MultiQueryEditor/MultiQueryEditor.js +5 -2
  2. package/dist/cjs/components/MultiQueryEditor/QueryEditorContainer.js +13 -4
  3. package/dist/cjs/components/PanelSpecEditor/PanelSpecEditor.js +7 -5
  4. package/dist/cjs/components/PluginEditor/PluginEditor.js +16 -11
  5. package/dist/cjs/components/Variables/VariableEditorForm/VariableEditorForm.js +37 -87
  6. package/dist/cjs/components/Variables/VariableEditorForm/VariablePreview.js +12 -17
  7. package/dist/cjs/context/query-params.js +4 -4
  8. package/dist/cjs/runtime/TimeRangeProvider/TimeRangeProvider.js +6 -1
  9. package/dist/cjs/runtime/TimeRangeProvider/query-params.js +27 -27
  10. package/dist/cjs/test/utils.js +17 -8
  11. package/dist/cjs/utils/variables.js +109 -14
  12. package/dist/components/MultiQueryEditor/MultiQueryEditor.d.ts +3 -2
  13. package/dist/components/MultiQueryEditor/MultiQueryEditor.d.ts.map +1 -1
  14. package/dist/components/MultiQueryEditor/MultiQueryEditor.js +6 -3
  15. package/dist/components/MultiQueryEditor/MultiQueryEditor.js.map +1 -1
  16. package/dist/components/MultiQueryEditor/QueryEditorContainer.d.ts +3 -2
  17. package/dist/components/MultiQueryEditor/QueryEditorContainer.d.ts.map +1 -1
  18. package/dist/components/MultiQueryEditor/QueryEditorContainer.js +13 -4
  19. package/dist/components/MultiQueryEditor/QueryEditorContainer.js.map +1 -1
  20. package/dist/components/PanelSpecEditor/PanelSpecEditor.d.ts +3 -2
  21. package/dist/components/PanelSpecEditor/PanelSpecEditor.d.ts.map +1 -1
  22. package/dist/components/PanelSpecEditor/PanelSpecEditor.js +7 -5
  23. package/dist/components/PanelSpecEditor/PanelSpecEditor.js.map +1 -1
  24. package/dist/components/PluginEditor/PluginEditor.d.ts +3 -3
  25. package/dist/components/PluginEditor/PluginEditor.d.ts.map +1 -1
  26. package/dist/components/PluginEditor/PluginEditor.js +17 -12
  27. package/dist/components/PluginEditor/PluginEditor.js.map +1 -1
  28. package/dist/components/PluginEditor/plugin-editor-api.d.ts +4 -0
  29. package/dist/components/PluginEditor/plugin-editor-api.d.ts.map +1 -1
  30. package/dist/components/PluginEditor/plugin-editor-api.js.map +1 -1
  31. package/dist/components/TimeRangeControls/TimeRangeControls.js.map +1 -1
  32. package/dist/components/Variables/VariableEditorForm/VariableEditorForm.d.ts.map +1 -1
  33. package/dist/components/Variables/VariableEditorForm/VariableEditorForm.js +38 -47
  34. package/dist/components/Variables/VariableEditorForm/VariableEditorForm.js.map +1 -1
  35. package/dist/components/Variables/VariableEditorForm/VariablePreview.d.ts +0 -2
  36. package/dist/components/Variables/VariableEditorForm/VariablePreview.d.ts.map +1 -1
  37. package/dist/components/Variables/VariableEditorForm/VariablePreview.js +13 -18
  38. package/dist/components/Variables/VariableEditorForm/VariablePreview.js.map +1 -1
  39. package/dist/context/query-params.js +4 -4
  40. package/dist/context/query-params.js.map +1 -1
  41. package/dist/runtime/TimeRangeProvider/TimeRangeProvider.d.ts.map +1 -1
  42. package/dist/runtime/TimeRangeProvider/TimeRangeProvider.js +6 -1
  43. package/dist/runtime/TimeRangeProvider/TimeRangeProvider.js.map +1 -1
  44. package/dist/runtime/TimeRangeProvider/query-params.d.ts +7 -12
  45. package/dist/runtime/TimeRangeProvider/query-params.d.ts.map +1 -1
  46. package/dist/runtime/TimeRangeProvider/query-params.js +20 -23
  47. package/dist/runtime/TimeRangeProvider/query-params.js.map +1 -1
  48. package/dist/test/utils.d.ts.map +1 -1
  49. package/dist/test/utils.js +17 -8
  50. package/dist/test/utils.js.map +1 -1
  51. package/dist/utils/variables.d.ts +24 -2
  52. package/dist/utils/variables.d.ts.map +1 -1
  53. package/dist/utils/variables.js +102 -14
  54. package/dist/utils/variables.js.map +1 -1
  55. package/package.json +4 -4
@@ -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,6 +71,9 @@ 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: [
@@ -124,4 +128,5 @@ function PluginEditor(props) {
124
128
  })
125
129
  ]
126
130
  });
127
- }
131
+ });
132
+ PluginEditor.displayName = 'PluginEditor';
@@ -21,57 +21,17 @@ Object.defineProperty(exports, "VariableEditorForm", {
21
21
  }
22
22
  });
23
23
  const _jsxruntime = require("react/jsx-runtime");
24
- const _react = /*#__PURE__*/ _interop_require_wildcard(require("react"));
24
+ const _react = require("react");
25
25
  const _material = require("@mui/material");
26
26
  const _components = require("@perses-dev/components");
27
27
  const _reacthookform = require("react-hook-form");
28
28
  const _zod = require("@hookform/resolvers/zod");
29
29
  const _utils = require("../../../utils");
30
- const _variablemodel = require("../variable-model");
31
30
  const _PluginEditor = require("../../PluginEditor");
32
31
  const _context = require("../../../context");
32
+ const _variablemodel = require("../variable-model");
33
+ const _runtime = require("../../../runtime");
33
34
  const _VariablePreview = require("./VariablePreview");
34
- function _getRequireWildcardCache(nodeInterop) {
35
- if (typeof WeakMap !== "function") return null;
36
- var cacheBabelInterop = new WeakMap();
37
- var cacheNodeInterop = new WeakMap();
38
- return (_getRequireWildcardCache = function(nodeInterop) {
39
- return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
40
- })(nodeInterop);
41
- }
42
- function _interop_require_wildcard(obj, nodeInterop) {
43
- if (!nodeInterop && obj && obj.__esModule) {
44
- return obj;
45
- }
46
- if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
47
- return {
48
- default: obj
49
- };
50
- }
51
- var cache = _getRequireWildcardCache(nodeInterop);
52
- if (cache && cache.has(obj)) {
53
- return cache.get(obj);
54
- }
55
- var newObj = {
56
- __proto__: null
57
- };
58
- var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
59
- for(var key in obj){
60
- if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
61
- var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
62
- if (desc && (desc.get || desc.set)) {
63
- Object.defineProperty(newObj, key, desc);
64
- } else {
65
- newObj[key] = obj[key];
66
- }
67
- }
68
- }
69
- newObj.default = obj;
70
- if (cache) {
71
- cache.set(obj, newObj);
72
- }
73
- return newObj;
74
- }
75
35
  function FallbackPreview() {
76
36
  return /*#__PURE__*/ (0, _jsxruntime.jsx)("div", {
77
37
  children: "Error previewing values"
@@ -146,10 +106,7 @@ function ListVariableEditorForm({ action, control }) {
146
106
  /** We use `previewSpec` to know when to explicitly update the
147
107
  * spec that will be used for preview. The reason why we do this is to avoid
148
108
  * having to re-fetch the values when the user is still editing the spec.
149
- */ const [previewSpec, setPreviewSpec] = (0, _react.useState)(form.getValues());
150
- const refreshPreview = ()=>{
151
- setPreviewSpec(form.getValues());
152
- };
109
+ */ const previewSpec = form.getValues();
153
110
  const plugin = (0, _reacthookform.useWatch)({
154
111
  control,
155
112
  name: 'spec.plugin'
@@ -169,6 +126,7 @@ function ListVariableEditorForm({ action, control }) {
169
126
  if (values.spec.allowMultiple === undefined) {
170
127
  form.setValue('spec.allowMultiple', false);
171
128
  }
129
+ const { refresh } = (0, _runtime.useTimeRange)();
172
130
  return /*#__PURE__*/ (0, _jsxruntime.jsxs)(_jsxruntime.Fragment, {
173
131
  children: [
174
132
  /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Typography, {
@@ -187,53 +145,45 @@ function ListVariableEditorForm({ action, control }) {
187
145
  previewSpec
188
146
  ],
189
147
  children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_VariablePreview.VariableListPreview, {
190
- definition: previewSpec,
191
- onRefresh: refreshPreview
148
+ definition: previewSpec
192
149
  })
193
150
  })
194
151
  }) : /*#__PURE__*/ (0, _jsxruntime.jsx)(_VariablePreview.VariablePreview, {
195
152
  isLoading: true
196
153
  }),
197
- /*#__PURE__*/ (0, _jsxruntime.jsxs)(_material.Stack, {
198
- children: [
199
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.ClickAwayListener, {
200
- onClickAway: ()=>refreshPreview(),
201
- children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Box, {})
202
- }),
203
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.ErrorBoundary, {
204
- FallbackComponent: _components.ErrorAlert,
205
- children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_reacthookform.Controller, {
206
- control: control,
207
- name: "spec.plugin",
208
- render: ({ field })=>{
209
- return /*#__PURE__*/ (0, _jsxruntime.jsx)(_PluginEditor.PluginEditor, {
210
- withRunQueryButton: true,
211
- width: "100%",
212
- pluginTypes: [
213
- 'Variable'
214
- ],
215
- pluginKindLabel: "Source",
216
- value: {
217
- selection: {
218
- type: 'Variable',
219
- kind: kind ?? 'StaticListVariable'
220
- },
221
- spec: pluginSpec ?? {
222
- values: []
223
- }
154
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Stack, {
155
+ children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.ErrorBoundary, {
156
+ FallbackComponent: _components.ErrorAlert,
157
+ children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_reacthookform.Controller, {
158
+ control: control,
159
+ name: "spec.plugin",
160
+ render: ({ field })=>{
161
+ return /*#__PURE__*/ (0, _jsxruntime.jsx)(_PluginEditor.PluginEditor, {
162
+ postExecuteRunQuery: refresh,
163
+ withRunQueryButton: true,
164
+ width: "100%",
165
+ pluginTypes: [
166
+ 'Variable'
167
+ ],
168
+ pluginKindLabel: "Source",
169
+ value: {
170
+ selection: {
171
+ type: 'Variable',
172
+ kind: kind ?? 'StaticListVariable'
224
173
  },
225
- isReadonly: action === 'read',
226
- onChange: (v)=>{
227
- field.onChange({
228
- kind: v.selection.kind,
229
- spec: v.spec
230
- });
231
- }
232
- });
233
- }
234
- })
174
+ spec: pluginSpec ?? {}
175
+ },
176
+ isReadonly: action === 'read',
177
+ onChange: (v)=>{
178
+ field.onChange({
179
+ kind: v.selection.kind,
180
+ spec: v.spec
181
+ });
182
+ }
183
+ });
184
+ }
235
185
  })
236
- ]
186
+ })
237
187
  }),
238
188
  /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Stack, {
239
189
  children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_reacthookform.Controller, {
@@ -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,13 +163,17 @@ function VariablePreview(props) {
172
163
  });
173
164
  }
174
165
  function VariableListPreview(props) {
175
- const { definition, onRefresh } = props;
166
+ const { definition } = props;
176
167
  const { data, isFetching, error } = (0, _variablemodel.useListVariablePluginValues)(definition);
177
168
  const errorMessage = error?.message;
178
- return /*#__PURE__*/ (0, _jsxruntime.jsx)(VariablePreview, {
179
- values: data?.map((val)=>val.value) || [],
180
- onRefresh: onRefresh,
181
- isLoading: isFetching,
182
- error: errorMessage
183
- });
169
+ const variablePreview = (0, _react.useMemo)(()=>/*#__PURE__*/ (0, _jsxruntime.jsx)(VariablePreview, {
170
+ values: data?.map((val)=>val.value) || [],
171
+ isLoading: isFetching,
172
+ error: errorMessage
173
+ }), [
174
+ errorMessage,
175
+ isFetching,
176
+ data
177
+ ]);
178
+ return variablePreview;
184
179
  }
@@ -21,12 +21,12 @@ Object.defineProperty(exports, "useSetProjectParams", {
21
21
  }
22
22
  });
23
23
  const _react = require("react");
24
- const _usequeryparams = require("use-query-params");
24
+ const _nuqs = require("nuqs");
25
25
  function useSetProjectParams(enabledURLParams = true) {
26
- const [query, setQuery] = (0, _usequeryparams.useQueryParams)({
27
- project: ''
26
+ const [query, setQuery] = (0, _nuqs.useQueryStates)({
27
+ project: _nuqs.parseAsString
28
28
  }, {
29
- updateType: 'replaceIn'
29
+ history: 'replace'
30
30
  });
31
31
  const [projectState, setProjectState] = (0, _react.useState)('none');
32
32
  const setProject = (0, _react.useCallback)((project)=>{
@@ -100,7 +100,12 @@ function useSuggestedStepMs(width) {
100
100
  }
101
101
  function TimeRangeProvider(props) {
102
102
  const { timeRange, refreshInterval, children, setTimeRange, setRefreshInterval } = props;
103
- const [localTimeRange, setLocalTimeRange] = (0, _react.useState)(timeRange);
103
+ /**
104
+ * TODO: The hook needs refactor. There is a bug here with refreshKey. If the refreshInterval is not set,
105
+ * refreshKey string includes an undefined xx:yy:zz:undefined:0
106
+ * I think exposing refresh functionality also is very risky. A careless usage of refresh may cause
107
+ * infinite rendering loop.
108
+ */ const [localTimeRange, setLocalTimeRange] = (0, _react.useState)(timeRange);
104
109
  const [localRefreshInterval, setLocalRefreshInterval] = (0, _react.useState)(refreshInterval);
105
110
  const [refreshCounter, setRefreshCounter] = (0, _react.useState)(0);
106
111
  (0, _react.useEffect)(()=>{
@@ -21,20 +21,20 @@ function _export(target, all) {
21
21
  });
22
22
  }
23
23
  _export(exports, {
24
- TimeRangeParam: function() {
25
- return TimeRangeParam;
26
- },
27
24
  decodeTimeRangeValue: function() {
28
25
  return decodeTimeRangeValue;
29
26
  },
30
27
  encodeTimeRangeValue: function() {
31
28
  return encodeTimeRangeValue;
32
29
  },
33
- refreshIntervalQueryConfig: function() {
34
- return refreshIntervalQueryConfig;
30
+ parseAsRefreshInterval: function() {
31
+ return parseAsRefreshInterval;
32
+ },
33
+ parseAsTimeRange: function() {
34
+ return parseAsTimeRange;
35
35
  },
36
- timeRangeQueryConfig: function() {
37
- return timeRangeQueryConfig;
36
+ parseAsTimeRangeValue: function() {
37
+ return parseAsTimeRangeValue;
38
38
  },
39
39
  useInitialRefreshInterval: function() {
40
40
  return useInitialRefreshInterval;
@@ -50,9 +50,9 @@ _export(exports, {
50
50
  }
51
51
  });
52
52
  const _react = require("react");
53
- const _usequeryparams = require("use-query-params");
54
53
  const _datefns = require("date-fns");
55
54
  const _core = require("@perses-dev/core");
55
+ const _nuqs = require("nuqs");
56
56
  /* Interprets an encoded string and returns either the string or null/undefined if not available */ function getEncodedValue(input, allowEmptyString) {
57
57
  // '' or []
58
58
  if (!input || input.length === 0 && (!allowEmptyString || allowEmptyString && input !== '')) {
@@ -69,7 +69,7 @@ const _core = require("@perses-dev/core");
69
69
  }
70
70
  function encodeTimeRangeValue(timeOptionValue) {
71
71
  if (!timeOptionValue) {
72
- return timeOptionValue;
72
+ return '';
73
73
  }
74
74
  if (typeof timeOptionValue === 'string') {
75
75
  if ((0, _core.isDurationString)(timeOptionValue)) {
@@ -83,25 +83,25 @@ function decodeTimeRangeValue(input) {
83
83
  if (!paramString) return null;
84
84
  return (0, _core.isDurationString)(paramString) ? paramString : new Date(Number(paramString));
85
85
  }
86
- const TimeRangeParam = {
87
- encode: encodeTimeRangeValue,
88
- decode: decodeTimeRangeValue,
89
- equals: (valueA, valueB)=>{
86
+ const parseAsTimeRangeValue = (0, _nuqs.createParser)({
87
+ parse: decodeTimeRangeValue,
88
+ serialize: encodeTimeRangeValue,
89
+ eq: (valueA, valueB)=>{
90
90
  if (valueA === valueB) return true;
91
91
  if (!valueA || !valueB) return valueA === valueB;
92
92
  return valueA.valueOf() === valueB.valueOf();
93
93
  }
94
+ });
95
+ const parseAsTimeRange = {
96
+ start: parseAsTimeRangeValue,
97
+ end: parseAsTimeRangeValue
94
98
  };
95
- const timeRangeQueryConfig = {
96
- start: TimeRangeParam,
97
- end: TimeRangeParam
98
- };
99
- const refreshIntervalQueryConfig = {
100
- refresh: TimeRangeParam
99
+ const parseAsRefreshInterval = {
100
+ refresh: parseAsTimeRangeValue
101
101
  };
102
102
  function useInitialTimeRange(dashboardDuration) {
103
- const [query] = (0, _usequeryparams.useQueryParams)(timeRangeQueryConfig, {
104
- updateType: 'replaceIn'
103
+ const [query] = (0, _nuqs.useQueryStates)(parseAsTimeRange, {
104
+ history: 'replace'
105
105
  });
106
106
  const { start, end } = query;
107
107
  return (0, _react.useMemo)(()=>{
@@ -130,8 +130,8 @@ function useInitialTimeRange(dashboardDuration) {
130
130
  ]);
131
131
  }
132
132
  function useTimeRangeParams(initialTimeRange) {
133
- const [query, setQuery] = (0, _usequeryparams.useQueryParams)(timeRangeQueryConfig, {
134
- updateType: 'replaceIn'
133
+ const [query, setQuery] = (0, _nuqs.useQueryStates)(parseAsTimeRange, {
134
+ history: 'replace'
135
135
  });
136
136
  // determine whether initial param had previously been populated to fix back btn
137
137
  const [paramsLoaded, setParamsLoaded] = (0, _react.useState)(false);
@@ -171,8 +171,8 @@ function useTimeRangeParams(initialTimeRange) {
171
171
  };
172
172
  }
173
173
  function useInitialRefreshInterval(dashboardDuration) {
174
- const [query] = (0, _usequeryparams.useQueryParams)(refreshIntervalQueryConfig, {
175
- updateType: 'replaceIn'
174
+ const [query] = (0, _nuqs.useQueryStates)(parseAsRefreshInterval, {
175
+ history: 'replace'
176
176
  });
177
177
  const { refresh } = query;
178
178
  return (0, _react.useMemo)(()=>{
@@ -191,8 +191,8 @@ function useInitialRefreshInterval(dashboardDuration) {
191
191
  ]);
192
192
  }
193
193
  function useSetRefreshIntervalParams(initialRefreshInterval) {
194
- const [query, setQuery] = (0, _usequeryparams.useQueryParams)(refreshIntervalQueryConfig, {
195
- updateType: 'replaceIn'
194
+ const [query, setQuery] = (0, _nuqs.useQueryStates)(parseAsRefreshInterval, {
195
+ history: 'replace'
196
196
  });
197
197
  // determine whether initial param had previously been populated to fix back btn
198
198
  const [paramsLoaded, setParamsLoaded] = (0, _react.useState)(false);
@@ -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
  };