@perses-dev/plugin-system 0.0.0-snapshot-react-18-v-0-51-rc-0-8090608 → 0.0.0-snapshot-time-zone-selector-946f408

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 (58) hide show
  1. package/dist/cjs/components/MultiQueryEditor/MultiQueryEditor.js +1 -1
  2. package/dist/cjs/components/PanelSpecEditor/PanelSpecEditor.js +2 -2
  3. package/dist/cjs/components/TimeRangeControls/TimeRangeControls.js +3 -1
  4. package/dist/cjs/components/Variables/variable-model.js +4 -2
  5. package/dist/cjs/constants/user-interface-text.js +1 -0
  6. package/dist/cjs/remote/PluginRuntime.js +6 -6
  7. package/dist/cjs/runtime/TimeRangeProvider/TimeRangeProvider.js +30 -3
  8. package/dist/cjs/runtime/TimeRangeProvider/TimeRangeProviderWithQueryParams.js +5 -1
  9. package/dist/cjs/runtime/TimeRangeProvider/query-params.js +31 -0
  10. package/dist/cjs/runtime/time-series-queries.js +1 -1
  11. package/dist/cjs/test/render-hook.js +31 -0
  12. package/dist/cjs/test/render.js +4 -21
  13. package/dist/cjs/test/utils.js +49 -0
  14. package/dist/components/MultiQueryEditor/MultiQueryEditor.js +1 -1
  15. package/dist/components/MultiQueryEditor/MultiQueryEditor.js.map +1 -1
  16. package/dist/components/PanelSpecEditor/PanelSpecEditor.js +2 -2
  17. package/dist/components/PanelSpecEditor/PanelSpecEditor.js.map +1 -1
  18. package/dist/components/TimeRangeControls/TimeRangeControls.d.ts.map +1 -1
  19. package/dist/components/TimeRangeControls/TimeRangeControls.js +4 -2
  20. package/dist/components/TimeRangeControls/TimeRangeControls.js.map +1 -1
  21. package/dist/components/Variables/variable-model.d.ts.map +1 -1
  22. package/dist/components/Variables/variable-model.js +4 -2
  23. package/dist/components/Variables/variable-model.js.map +1 -1
  24. package/dist/constants/user-interface-text.d.ts +1 -0
  25. package/dist/constants/user-interface-text.d.ts.map +1 -1
  26. package/dist/constants/user-interface-text.js +1 -0
  27. package/dist/constants/user-interface-text.js.map +1 -1
  28. package/dist/remote/PluginRuntime.js +6 -6
  29. package/dist/remote/PluginRuntime.js.map +1 -1
  30. package/dist/runtime/TimeRangeProvider/TimeRangeProvider.d.ts +12 -0
  31. package/dist/runtime/TimeRangeProvider/TimeRangeProvider.d.ts.map +1 -1
  32. package/dist/runtime/TimeRangeProvider/TimeRangeProvider.js +28 -4
  33. package/dist/runtime/TimeRangeProvider/TimeRangeProvider.js.map +1 -1
  34. package/dist/runtime/TimeRangeProvider/TimeRangeProviderWithQueryParams.d.ts +1 -0
  35. package/dist/runtime/TimeRangeProvider/TimeRangeProviderWithQueryParams.d.ts.map +1 -1
  36. package/dist/runtime/TimeRangeProvider/TimeRangeProviderWithQueryParams.js +6 -2
  37. package/dist/runtime/TimeRangeProvider/TimeRangeProviderWithQueryParams.js.map +1 -1
  38. package/dist/runtime/TimeRangeProvider/query-params.d.ts +4 -0
  39. package/dist/runtime/TimeRangeProvider/query-params.d.ts.map +1 -1
  40. package/dist/runtime/TimeRangeProvider/query-params.js +29 -1
  41. package/dist/runtime/TimeRangeProvider/query-params.js.map +1 -1
  42. package/dist/runtime/time-series-queries.d.ts +1 -1
  43. package/dist/runtime/time-series-queries.d.ts.map +1 -1
  44. package/dist/runtime/time-series-queries.js +2 -2
  45. package/dist/runtime/time-series-queries.js.map +1 -1
  46. package/dist/test/render-hook.d.ts +8 -0
  47. package/dist/test/render-hook.d.ts.map +1 -0
  48. package/dist/test/render-hook.js +26 -0
  49. package/dist/test/render-hook.js.map +1 -0
  50. package/dist/test/render.d.ts +1 -5
  51. package/dist/test/render.d.ts.map +1 -1
  52. package/dist/test/render.js +4 -21
  53. package/dist/test/render.js.map +1 -1
  54. package/dist/test/utils.d.ts +9 -0
  55. package/dist/test/utils.d.ts.map +1 -0
  56. package/dist/test/utils.js +41 -0
  57. package/dist/test/utils.js.map +1 -0
  58. package/package.json +5 -5
@@ -43,7 +43,7 @@ function useDefaultQueryDefinition(queryTypes) {
43
43
  const { defaultPluginKinds } = (0, _runtime.usePluginRegistry)();
44
44
  const defaultQueryKind = defaultPluginKinds?.[defaultQueryType] ?? queryPlugins?.[0]?.spec.name ?? '';
45
45
  const { data: defaultQueryPlugin } = (0, _runtime.usePlugin)(defaultQueryType, defaultQueryKind, {
46
- throwOnError: true,
46
+ useErrorBoundary: true,
47
47
  enabled: true
48
48
  });
49
49
  // This default query definition is used if no query is provided initially or when we add a new query
@@ -29,14 +29,14 @@ const _MultiQueryEditor = require("../MultiQueryEditor");
29
29
  function PanelSpecEditor(props) {
30
30
  const { control, panelDefinition, onJSONChange, onQueriesChange, onPluginSpecChange } = props;
31
31
  const { kind } = panelDefinition.spec.plugin;
32
- const { data: plugin, isPending, error } = (0, _runtime.usePlugin)('Panel', kind);
32
+ const { data: plugin, isLoading, error } = (0, _runtime.usePlugin)('Panel', kind);
33
33
  if (error) {
34
34
  return /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.ErrorAlert, {
35
35
  error: error
36
36
  });
37
37
  }
38
38
  // TODO: Proper loading indicator
39
- if (isPending) {
39
+ if (isLoading) {
40
40
  return null;
41
41
  }
42
42
  if (plugin === undefined) {
@@ -84,6 +84,7 @@ const DEFAULT_REFRESH_INTERVAL_OPTIONS = [
84
84
  const DEFAULT_HEIGHT = '34px';
85
85
  function TimeRangeControls({ heightPx, showTimeRangeSelector = true, showRefreshButton = true, showRefreshInterval = true, showCustomTimeRange, showZoomButtons = true, timePresets }) {
86
86
  const { timeRange, setTimeRange, refresh, refreshInterval, setRefreshInterval } = (0, _runtime.useTimeRange)();
87
+ const { timeZone } = (0, _runtime.useTimeZone)();
87
88
  const showCustomTimeRangeValue = (0, _runtime.useShowCustomTimeRangeSetting)(showCustomTimeRange);
88
89
  const showZoomInOutButtons = (0, _runtime.useShowZoomRangeSetting)(showZoomButtons);
89
90
  const timePresetsValue = (0, _runtime.useTimeRangeOptionsSetting)(timePresets);
@@ -172,7 +173,8 @@ function TimeRangeControls({ heightPx, showTimeRangeSelector = true, showRefresh
172
173
  value: timeRange,
173
174
  onChange: setTimeRange,
174
175
  height: height,
175
- showCustomTimeRange: showCustomTimeRangeValue
176
+ showCustomTimeRange: showCustomTimeRangeValue,
177
+ timeZone: timeZone
176
178
  }),
177
179
  showZoomInOutButtons && /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.InfoTooltip, {
178
180
  description: _constants.TOOLTIP_TEXT.zoomOut,
@@ -73,11 +73,13 @@ function useListVariablePluginValues(definition) {
73
73
  };
74
74
  const spec = definition.spec.plugin.spec;
75
75
  const capturingRegexp = definition.spec.capturingRegexp !== undefined ? new RegExp(definition.spec.capturingRegexp, 'g') : undefined;
76
- let dependsOnVariables;
76
+ let dependsOnVariables = Object.keys(allVariables); // Default to all variables
77
77
  if (variablePlugin?.dependsOn) {
78
78
  const dependencies = variablePlugin.dependsOn(spec, variablePluginCtx);
79
- dependsOnVariables = dependencies.variables;
79
+ dependsOnVariables = dependencies.variables ? dependencies.variables : dependsOnVariables;
80
80
  }
81
+ // Exclude self variable to avoid circular dependency
82
+ dependsOnVariables = dependsOnVariables.filter((v)=>v !== definition.spec.name);
81
83
  const variables = (0, _runtime.useAllVariableValues)(dependsOnVariables);
82
84
  let waitToLoad = false;
83
85
  if (dependsOnVariables) {
@@ -27,6 +27,7 @@ const TOOLTIP_TEXT = {
27
27
  // Time range controls buttons
28
28
  refresh: 'Refresh',
29
29
  refreshInterval: 'Auto refresh interval',
30
+ timezone: 'Timezone',
30
31
  zoomIn: 'Zoom in',
31
32
  zoomOut: 'Zoom out'
32
33
  };
@@ -112,11 +112,11 @@ const getPluginRuntime = ()=>{
112
112
  }
113
113
  },
114
114
  '@tanstack/react-query': {
115
- version: '5.64.2',
115
+ version: '4.39.1',
116
116
  lib: ()=>_reactquery,
117
117
  shareConfig: {
118
118
  singleton: true,
119
- requiredVersion: '^5.64.2'
119
+ requiredVersion: '^4.39.1'
120
120
  }
121
121
  },
122
122
  'react-hook-form': {
@@ -140,7 +140,7 @@ const getPluginRuntime = ()=>{
140
140
  lib: ()=>require('@perses-dev/components'),
141
141
  shareConfig: {
142
142
  singleton: true,
143
- requiredVersion: '^0.51.0-beta.0'
143
+ requiredVersion: '^0.51.0-rc.0'
144
144
  }
145
145
  },
146
146
  '@perses-dev/plugin-system': {
@@ -148,7 +148,7 @@ const getPluginRuntime = ()=>{
148
148
  lib: ()=>require('@perses-dev/plugin-system'),
149
149
  shareConfig: {
150
150
  singleton: true,
151
- requiredVersion: '^0.51.0-beta.0'
151
+ requiredVersion: '^0.51.0-rc.0'
152
152
  }
153
153
  },
154
154
  '@perses-dev/explore': {
@@ -156,7 +156,7 @@ const getPluginRuntime = ()=>{
156
156
  lib: ()=>require('@perses-dev/explore'),
157
157
  shareConfig: {
158
158
  singleton: true,
159
- requiredVersion: '^0.51.0-beta.0'
159
+ requiredVersion: '^0.51.0-rc.0'
160
160
  }
161
161
  },
162
162
  '@perses-dev/dashboards': {
@@ -164,7 +164,7 @@ const getPluginRuntime = ()=>{
164
164
  lib: ()=>require('@perses-dev/dashboards'),
165
165
  shareConfig: {
166
166
  singleton: true,
167
- requiredVersion: '^0.51.0-beta.0'
167
+ requiredVersion: '^0.51.0-rc.0'
168
168
  }
169
169
  },
170
170
  // Below are the shared modules that are used by the plugins, this can be part of the SDK
@@ -35,11 +35,15 @@ _export(exports, {
35
35
  },
36
36
  useTimeRangeContext: function() {
37
37
  return useTimeRangeContext;
38
+ },
39
+ useTimeZone: function() {
40
+ return useTimeZone;
38
41
  }
39
42
  });
40
43
  const _jsxruntime = require("react/jsx-runtime");
41
44
  const _react = /*#__PURE__*/ _interop_require_wildcard(require("react"));
42
45
  const _core = require("@perses-dev/core");
46
+ const _components = require("@perses-dev/components");
43
47
  const _refreshinterval = require("./refresh-interval");
44
48
  function _getRequireWildcardCache(nodeInterop) {
45
49
  if (typeof WeakMap !== "function") return null;
@@ -93,15 +97,29 @@ function useTimeRangeContext() {
93
97
  function useTimeRange() {
94
98
  return useTimeRangeContext();
95
99
  }
100
+ function useTimeZone() {
101
+ const { timeZone, setTimeZone } = useTimeRangeContext();
102
+ return {
103
+ timeZone,
104
+ setTimeZone,
105
+ formatWithUserTimeZone: (date, formatString)=>{
106
+ return (0, _components.formatWithTimeZone)(date, formatString, timeZone);
107
+ },
108
+ dateFormatOptionsWithUserTimeZone: (dateFormatOptions)=>{
109
+ return (0, _components.dateFormatOptionsWithTimeZone)(dateFormatOptions, timeZone);
110
+ }
111
+ };
112
+ }
96
113
  function useSuggestedStepMs(width) {
97
114
  const { absoluteTimeRange } = useTimeRange();
98
115
  if (width === undefined) return 0;
99
116
  return (0, _core.getSuggestedStepMs)(absoluteTimeRange, width);
100
117
  }
101
118
  function TimeRangeProvider(props) {
102
- const { timeRange, refreshInterval, children, setTimeRange, setRefreshInterval } = props;
119
+ const { timeRange, refreshInterval, children, setTimeRange, setRefreshInterval, timeZone = _core.DEFAULT_DASHBOARD_TIMEZONE, setTimeZone } = props;
103
120
  const [localTimeRange, setLocalTimeRange] = (0, _react.useState)(timeRange);
104
121
  const [localRefreshInterval, setLocalRefreshInterval] = (0, _react.useState)(refreshInterval);
122
+ const [localTimeZone, setLocalTimeZone] = (0, _react.useState)(timeZone);
105
123
  const [refreshCounter, setRefreshCounter] = (0, _react.useState)(0);
106
124
  (0, _react.useEffect)(()=>{
107
125
  setLocalTimeRange(timeRange);
@@ -114,6 +132,11 @@ function TimeRangeProvider(props) {
114
132
  }, [
115
133
  refreshInterval
116
134
  ]);
135
+ (0, _react.useEffect)(()=>{
136
+ setLocalTimeZone(timeZone);
137
+ }, [
138
+ timeZone
139
+ ]);
117
140
  const refresh = (0, _react.useCallback)(()=>{
118
141
  setRefreshCounter((counter)=>counter + 1);
119
142
  }, [
@@ -135,22 +158,26 @@ function TimeRangeProvider(props) {
135
158
  const absoluteTimeRange = (0, _core.isRelativeTimeRange)(localTimeRange) ? (0, _core.toAbsoluteTimeRange)(localTimeRange) : localTimeRange;
136
159
  return {
137
160
  timeRange: localTimeRange,
161
+ timeZone: localTimeZone,
138
162
  setTimeRange: setTimeRange ?? setLocalTimeRange,
139
163
  absoluteTimeRange,
140
164
  refresh,
141
165
  refreshKey: `${absoluteTimeRange.start}:${absoluteTimeRange.end}:${localRefreshInterval}:${refreshCounter}`,
142
166
  refreshInterval: localRefreshInterval,
143
167
  refreshIntervalInMs: refreshIntervalInMs,
144
- setRefreshInterval: setRefreshInterval ?? setLocalRefreshInterval
168
+ setRefreshInterval: setRefreshInterval ?? setLocalRefreshInterval,
169
+ setTimeZone: setTimeZone ?? setLocalTimeZone
145
170
  };
146
171
  }, [
147
172
  localTimeRange,
173
+ localTimeZone,
148
174
  setTimeRange,
149
175
  refresh,
150
176
  localRefreshInterval,
151
177
  refreshCounter,
152
178
  refreshIntervalInMs,
153
- setRefreshInterval
179
+ setRefreshInterval,
180
+ setTimeZone
154
181
  ]);
155
182
  return /*#__PURE__*/ (0, _jsxruntime.jsx)(TimeRangeContext.Provider, {
156
183
  value: ctx,
@@ -21,6 +21,7 @@ Object.defineProperty(exports, "TimeRangeProviderWithQueryParams", {
21
21
  }
22
22
  });
23
23
  const _jsxruntime = require("react/jsx-runtime");
24
+ const _core = require("@perses-dev/core");
24
25
  const _react = /*#__PURE__*/ _interop_require_default(require("react"));
25
26
  const _TimeRangeProvider = require("./TimeRangeProvider");
26
27
  const _queryparams = require("./query-params");
@@ -30,14 +31,17 @@ function _interop_require_default(obj) {
30
31
  };
31
32
  }
32
33
  function TimeRangeProviderWithQueryParams(props) {
33
- const { initialTimeRange, initialRefreshInterval, children } = props;
34
+ const { initialTimeRange, initialRefreshInterval, children, initialTimeZone = _core.DEFAULT_DASHBOARD_TIMEZONE } = props;
34
35
  const { timeRange, setTimeRange } = (0, _queryparams.useTimeRangeParams)(initialTimeRange);
35
36
  const { refreshInterval, setRefreshInterval } = (0, _queryparams.useSetRefreshIntervalParams)(initialRefreshInterval);
37
+ const { timeZone, setTimeZone } = (0, _queryparams.useSetTimeZoneParams)(initialTimeZone);
36
38
  return /*#__PURE__*/ (0, _jsxruntime.jsx)(_TimeRangeProvider.TimeRangeProvider, {
37
39
  timeRange: timeRange,
38
40
  refreshInterval: refreshInterval,
39
41
  setTimeRange: setTimeRange,
40
42
  setRefreshInterval: setRefreshInterval,
43
+ timeZone: timeZone,
44
+ setTimeZone: setTimeZone,
41
45
  children: children
42
46
  });
43
47
  }
@@ -45,6 +45,9 @@ _export(exports, {
45
45
  useSetRefreshIntervalParams: function() {
46
46
  return useSetRefreshIntervalParams;
47
47
  },
48
+ useSetTimeZoneParams: function() {
49
+ return useSetTimeZoneParams;
50
+ },
48
51
  useTimeRangeParams: function() {
49
52
  return useTimeRangeParams;
50
53
  }
@@ -221,3 +224,31 @@ function useSetRefreshIntervalParams(initialRefreshInterval) {
221
224
  setRefreshInterval: setRefreshInterval
222
225
  };
223
226
  }
227
+ function useSetTimeZoneParams(initialTimeZone) {
228
+ const [query, setQuery] = (0, _usequeryparams.useQueryParams)({
229
+ timeZone: _usequeryparams.StringParam
230
+ }, {
231
+ updateType: 'replaceIn'
232
+ });
233
+ const { timeZone } = query;
234
+ (0, _react.useEffect)(()=>{
235
+ if (!timeZone) {
236
+ setQuery({
237
+ timeZone: initialTimeZone
238
+ });
239
+ }
240
+ }, [
241
+ setQuery,
242
+ timeZone,
243
+ initialTimeZone
244
+ ]);
245
+ const setTimeZone = (0, _react.useCallback)((timeZone)=>setQuery({
246
+ timeZone
247
+ }), [
248
+ setQuery
249
+ ]);
250
+ return {
251
+ timeZone: timeZone ? timeZone : initialTimeZone,
252
+ setTimeZone: setTimeZone
253
+ };
254
+ }
@@ -38,11 +38,11 @@ _export(exports, {
38
38
  }
39
39
  });
40
40
  const _reactquery = require("@tanstack/react-query");
41
- const _variables = require("./variables");
42
41
  const _TimeRangeProvider = require("./TimeRangeProvider");
43
42
  const _datasources = require("./datasources");
44
43
  const _pluginregistry = require("./plugin-registry");
45
44
  const _utils = require("./utils");
45
+ const _variables = require("./variables");
46
46
  const TIME_SERIES_QUERY_KEY = 'TimeSeriesQuery';
47
47
  function getQueryOptions({ plugin, definition, context }) {
48
48
  const { timeRange, datasourceStore, suggestedStepMs, mode, variableState, refreshKey } = context;
@@ -0,0 +1,31 @@
1
+ // Copyright 2023 The Perses Authors
2
+ // Licensed under the Apache License, Version 2.0 (the "License");
3
+ // you may not use this file except in compliance with the License.
4
+ // You may obtain a copy of the License at
5
+ //
6
+ // http://www.apache.org/licenses/LICENSE-2.0
7
+ //
8
+ // Unless required by applicable law or agreed to in writing, software
9
+ // distributed under the License is distributed on an "AS IS" BASIS,
10
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ // See the License for the specific language governing permissions and
12
+ // limitations under the License.
13
+ "use strict";
14
+ Object.defineProperty(exports, "__esModule", {
15
+ value: true
16
+ });
17
+ Object.defineProperty(exports, "renderHookWithContext", {
18
+ enumerable: true,
19
+ get: function() {
20
+ return renderHookWithContext;
21
+ }
22
+ });
23
+ const _react = require("@testing-library/react");
24
+ const _utils = require("./utils");
25
+ function renderHookWithContext(callback, contextOptions, renderHookOptions) {
26
+ const wrapper = (0, _utils.getTestContextWrapper)(contextOptions);
27
+ return (0, _react.renderHook)(callback, {
28
+ wrapper,
29
+ ...renderHookOptions
30
+ });
31
+ }
@@ -22,27 +22,10 @@ Object.defineProperty(exports, "renderWithContext", {
22
22
  });
23
23
  const _jsxruntime = require("react/jsx-runtime");
24
24
  const _react = require("@testing-library/react");
25
- const _reactquery = require("@tanstack/react-query");
26
- const _PluginRegistry = require("../components/PluginRegistry");
27
- const _testplugins = require("./test-plugins");
25
+ const _utils = require("./utils");
28
26
  function renderWithContext(ui, renderOptions, contextOptions) {
29
- // Create a new QueryClient for each test to avoid caching issues
30
- const queryClient = new _reactquery.QueryClient({
31
- defaultOptions: {
32
- queries: {
33
- refetchOnWindowFocus: false,
34
- retry: false
35
- }
36
- }
37
- });
38
- return (0, _react.render)(/*#__PURE__*/ (0, _jsxruntime.jsx)(_reactquery.QueryClientProvider, {
39
- client: queryClient,
40
- children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_PluginRegistry.PluginRegistry, {
41
- pluginLoader: _testplugins.testPluginLoader,
42
- defaultPluginKinds: contextOptions?.defaultPluginKinds ?? {
43
- TimeSeriesQuery: 'PrometheusTimeSeriesQuery'
44
- },
45
- children: ui
46
- })
27
+ const Wrapper = (0, _utils.getTestContextWrapper)(contextOptions);
28
+ return (0, _react.render)(/*#__PURE__*/ (0, _jsxruntime.jsx)(Wrapper, {
29
+ children: ui
47
30
  }), renderOptions);
48
31
  }
@@ -0,0 +1,49 @@
1
+ // Copyright 2023 The Perses Authors
2
+ // Licensed under the Apache License, Version 2.0 (the "License");
3
+ // you may not use this file except in compliance with the License.
4
+ // You may obtain a copy of the License at
5
+ //
6
+ // http://www.apache.org/licenses/LICENSE-2.0
7
+ //
8
+ // Unless required by applicable law or agreed to in writing, software
9
+ // distributed under the License is distributed on an "AS IS" BASIS,
10
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ // See the License for the specific language governing permissions and
12
+ // limitations under the License.
13
+ "use strict";
14
+ Object.defineProperty(exports, "__esModule", {
15
+ value: true
16
+ });
17
+ Object.defineProperty(exports, "getTestContextWrapper", {
18
+ enumerable: true,
19
+ get: function() {
20
+ return getTestContextWrapper;
21
+ }
22
+ });
23
+ const _jsxruntime = require("react/jsx-runtime");
24
+ const _reactquery = require("@tanstack/react-query");
25
+ const _components = require("../components");
26
+ const _testplugins = require("./test-plugins");
27
+ function getTestContextWrapper(contextOptions) {
28
+ // Create a new QueryClient for each test to avoid caching issues
29
+ const queryClient = new _reactquery.QueryClient({
30
+ defaultOptions: {
31
+ queries: {
32
+ refetchOnWindowFocus: false,
33
+ retry: false
34
+ }
35
+ }
36
+ });
37
+ 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
46
+ })
47
+ });
48
+ };
49
+ }
@@ -28,7 +28,7 @@ function useDefaultQueryDefinition(queryTypes) {
28
28
  const { defaultPluginKinds } = usePluginRegistry();
29
29
  const defaultQueryKind = defaultPluginKinds?.[defaultQueryType] ?? queryPlugins?.[0]?.spec.name ?? '';
30
30
  const { data: defaultQueryPlugin } = usePlugin(defaultQueryType, defaultQueryKind, {
31
- throwOnError: true,
31
+ useErrorBoundary: true,
32
32
  enabled: true
33
33
  });
34
34
  // This default query definition is used if no query is provided initially or when we add a new query
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/MultiQueryEditor/MultiQueryEditor.tsx"],"sourcesContent":["// Copyright 2024 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { ReactElement, useState } from 'react';\nimport { produce } from 'immer';\nimport { Button, Stack } from '@mui/material';\nimport AddIcon from 'mdi-material-ui/Plus';\nimport { QueryDefinition, QueryPluginType } from '@perses-dev/core';\nimport { useListPluginMetadata, usePlugin, usePluginRegistry } from '../../runtime';\nimport { QueryEditorContainer } from './QueryEditorContainer';\n\nexport interface MultiQueryEditorProps {\n queryTypes: QueryPluginType[];\n queries?: QueryDefinition[];\n onChange: (queries: QueryDefinition[]) => void;\n}\n\nfunction useDefaultQueryDefinition(queryTypes: QueryPluginType[]): {\n defaultInitialQueryDefinition: QueryDefinition;\n isLoading: boolean;\n} {\n // Build the default query plugin\n // This will be used only if the queries are empty, to open a starting query\n\n // Firs the default query type\n const defaultQueryType = queryTypes[0]!;\n\n // Then the default plugin kind\n // Use as default the plugin kind explicitly set as default or the first in the list\n const { data: queryPlugins, isLoading } = useListPluginMetadata(queryTypes);\n const { defaultPluginKinds } = usePluginRegistry();\n const defaultQueryKind = defaultPluginKinds?.[defaultQueryType] ?? queryPlugins?.[0]?.spec.name ?? '';\n\n const { data: defaultQueryPlugin } = usePlugin(defaultQueryType, defaultQueryKind, {\n throwOnError: true,\n enabled: true,\n });\n\n // This default query definition is used if no query is provided initially or when we add a new query\n return {\n defaultInitialQueryDefinition: {\n kind: defaultQueryType,\n spec: {\n plugin: { kind: defaultQueryKind, spec: defaultQueryPlugin?.createInitialOptions() || {} },\n },\n },\n isLoading,\n };\n}\n\n/**\n * A component render a list of {@link QueryEditorContainer} for the given query definitions.\n * It allows adding, removing and editing queries.\n * @param queryTypes The list of query types that the underlying editor will propose\n * @param queries The list of query definitions to render\n * @param onChange The callback to call when the queries are modified\n * @constructor\n */\nexport function MultiQueryEditor({ queryTypes, queries = [], onChange }: MultiQueryEditorProps): ReactElement {\n const { defaultInitialQueryDefinition, isLoading } = useDefaultQueryDefinition(queryTypes);\n\n // State for which queries are collapsed\n const [queriesCollapsed, setQueriesCollapsed] = useState(queries.map(() => false));\n\n // Query handlers\n const handleQueryChange = (index: number, queryDef: QueryDefinition): void => {\n onChange(\n produce(queries, (draft) => {\n if (draft) {\n draft[index] = queryDef;\n } else {\n draft = [queryDef];\n }\n })\n );\n };\n\n const handleQueryAdd = (): void => {\n onChange(\n produce(queries, (draft) => {\n if (draft) {\n draft.push(defaultInitialQueryDefinition);\n } else {\n draft = [...queries, defaultInitialQueryDefinition];\n }\n })\n );\n setQueriesCollapsed((queriesCollapsed) => {\n queriesCollapsed.push(false);\n return [...queriesCollapsed];\n });\n };\n\n const handleQueryDelete = (index: number): void => {\n onChange(\n produce(queries, (draft) => {\n draft.splice(index, 1);\n })\n );\n setQueriesCollapsed((queriesCollapsed) => {\n queriesCollapsed.splice(index, 1);\n return [...queriesCollapsed];\n });\n };\n\n const handleQueryCollapseExpand = (index: number): void => {\n setQueriesCollapsed((queriesCollapsed) => {\n queriesCollapsed[index] = !queriesCollapsed[index];\n return [...queriesCollapsed];\n });\n };\n\n // show one query input if queries is empty\n const queryDefinitions: QueryDefinition[] = queries.length\n ? queries\n : !isLoading\n ? [defaultInitialQueryDefinition]\n : [];\n\n return (\n <>\n <Stack spacing={1}>\n {queryDefinitions.map((query: QueryDefinition, i: number) => (\n <QueryEditorContainer\n queryTypes={queryTypes}\n key={i}\n index={i}\n query={query}\n isCollapsed={!!queriesCollapsed[i]}\n onChange={handleQueryChange}\n onDelete={queries.length > 1 ? handleQueryDelete : undefined}\n onCollapseExpand={handleQueryCollapseExpand}\n />\n ))}\n </Stack>\n <Button variant=\"contained\" startIcon={<AddIcon />} sx={{ marginTop: 1 }} onClick={handleQueryAdd}>\n Add Query\n </Button>\n </>\n );\n}\n"],"names":["useState","produce","Button","Stack","AddIcon","useListPluginMetadata","usePlugin","usePluginRegistry","QueryEditorContainer","useDefaultQueryDefinition","queryTypes","defaultQueryType","data","queryPlugins","isLoading","defaultPluginKinds","defaultQueryKind","spec","name","defaultQueryPlugin","throwOnError","enabled","defaultInitialQueryDefinition","kind","plugin","createInitialOptions","MultiQueryEditor","queries","onChange","queriesCollapsed","setQueriesCollapsed","map","handleQueryChange","index","queryDef","draft","handleQueryAdd","push","handleQueryDelete","splice","handleQueryCollapseExpand","queryDefinitions","length","spacing","query","i","isCollapsed","onDelete","undefined","onCollapseExpand","variant","startIcon","sx","marginTop","onClick"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/components/MultiQueryEditor/MultiQueryEditor.tsx"],"sourcesContent":["// Copyright 2024 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { ReactElement, useState } from 'react';\nimport { produce } from 'immer';\nimport { Button, Stack } from '@mui/material';\nimport AddIcon from 'mdi-material-ui/Plus';\nimport { QueryDefinition, QueryPluginType } from '@perses-dev/core';\nimport { useListPluginMetadata, usePlugin, usePluginRegistry } from '../../runtime';\nimport { QueryEditorContainer } from './QueryEditorContainer';\n\nexport interface MultiQueryEditorProps {\n queryTypes: QueryPluginType[];\n queries?: QueryDefinition[];\n onChange: (queries: QueryDefinition[]) => void;\n}\n\nfunction useDefaultQueryDefinition(queryTypes: QueryPluginType[]): {\n defaultInitialQueryDefinition: QueryDefinition;\n isLoading: boolean;\n} {\n // Build the default query plugin\n // This will be used only if the queries are empty, to open a starting query\n\n // Firs the default query type\n const defaultQueryType = queryTypes[0]!;\n\n // Then the default plugin kind\n // Use as default the plugin kind explicitly set as default or the first in the list\n const { data: queryPlugins, isLoading } = useListPluginMetadata(queryTypes);\n const { defaultPluginKinds } = usePluginRegistry();\n const defaultQueryKind = defaultPluginKinds?.[defaultQueryType] ?? queryPlugins?.[0]?.spec.name ?? '';\n\n const { data: defaultQueryPlugin } = usePlugin(defaultQueryType, defaultQueryKind, {\n useErrorBoundary: true,\n enabled: true,\n });\n\n // This default query definition is used if no query is provided initially or when we add a new query\n return {\n defaultInitialQueryDefinition: {\n kind: defaultQueryType,\n spec: {\n plugin: { kind: defaultQueryKind, spec: defaultQueryPlugin?.createInitialOptions() || {} },\n },\n },\n isLoading,\n };\n}\n\n/**\n * A component render a list of {@link QueryEditorContainer} for the given query definitions.\n * It allows adding, removing and editing queries.\n * @param queryTypes The list of query types that the underlying editor will propose\n * @param queries The list of query definitions to render\n * @param onChange The callback to call when the queries are modified\n * @constructor\n */\nexport function MultiQueryEditor({ queryTypes, queries = [], onChange }: MultiQueryEditorProps): ReactElement {\n const { defaultInitialQueryDefinition, isLoading } = useDefaultQueryDefinition(queryTypes);\n\n // State for which queries are collapsed\n const [queriesCollapsed, setQueriesCollapsed] = useState(queries.map(() => false));\n\n // Query handlers\n const handleQueryChange = (index: number, queryDef: QueryDefinition): void => {\n onChange(\n produce(queries, (draft) => {\n if (draft) {\n draft[index] = queryDef;\n } else {\n draft = [queryDef];\n }\n })\n );\n };\n\n const handleQueryAdd = (): void => {\n onChange(\n produce(queries, (draft) => {\n if (draft) {\n draft.push(defaultInitialQueryDefinition);\n } else {\n draft = [...queries, defaultInitialQueryDefinition];\n }\n })\n );\n setQueriesCollapsed((queriesCollapsed) => {\n queriesCollapsed.push(false);\n return [...queriesCollapsed];\n });\n };\n\n const handleQueryDelete = (index: number): void => {\n onChange(\n produce(queries, (draft) => {\n draft.splice(index, 1);\n })\n );\n setQueriesCollapsed((queriesCollapsed) => {\n queriesCollapsed.splice(index, 1);\n return [...queriesCollapsed];\n });\n };\n\n const handleQueryCollapseExpand = (index: number): void => {\n setQueriesCollapsed((queriesCollapsed) => {\n queriesCollapsed[index] = !queriesCollapsed[index];\n return [...queriesCollapsed];\n });\n };\n\n // show one query input if queries is empty\n const queryDefinitions: QueryDefinition[] = queries.length\n ? queries\n : !isLoading\n ? [defaultInitialQueryDefinition]\n : [];\n\n return (\n <>\n <Stack spacing={1}>\n {queryDefinitions.map((query: QueryDefinition, i: number) => (\n <QueryEditorContainer\n queryTypes={queryTypes}\n key={i}\n index={i}\n query={query}\n isCollapsed={!!queriesCollapsed[i]}\n onChange={handleQueryChange}\n onDelete={queries.length > 1 ? handleQueryDelete : undefined}\n onCollapseExpand={handleQueryCollapseExpand}\n />\n ))}\n </Stack>\n <Button variant=\"contained\" startIcon={<AddIcon />} sx={{ marginTop: 1 }} onClick={handleQueryAdd}>\n Add Query\n </Button>\n </>\n );\n}\n"],"names":["useState","produce","Button","Stack","AddIcon","useListPluginMetadata","usePlugin","usePluginRegistry","QueryEditorContainer","useDefaultQueryDefinition","queryTypes","defaultQueryType","data","queryPlugins","isLoading","defaultPluginKinds","defaultQueryKind","spec","name","defaultQueryPlugin","useErrorBoundary","enabled","defaultInitialQueryDefinition","kind","plugin","createInitialOptions","MultiQueryEditor","queries","onChange","queriesCollapsed","setQueriesCollapsed","map","handleQueryChange","index","queryDef","draft","handleQueryAdd","push","handleQueryDelete","splice","handleQueryCollapseExpand","queryDefinitions","length","spacing","query","i","isCollapsed","onDelete","undefined","onCollapseExpand","variant","startIcon","sx","marginTop","onClick"],"mappings":"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"}
@@ -19,14 +19,14 @@ import { MultiQueryEditor } from '../MultiQueryEditor';
19
19
  export function PanelSpecEditor(props) {
20
20
  const { control, panelDefinition, onJSONChange, onQueriesChange, onPluginSpecChange } = props;
21
21
  const { kind } = panelDefinition.spec.plugin;
22
- const { data: plugin, isPending, error } = usePlugin('Panel', kind);
22
+ const { data: plugin, isLoading, error } = usePlugin('Panel', kind);
23
23
  if (error) {
24
24
  return /*#__PURE__*/ _jsx(ErrorAlert, {
25
25
  error: error
26
26
  });
27
27
  }
28
28
  // TODO: Proper loading indicator
29
- if (isPending) {
29
+ if (isLoading) {
30
30
  return null;
31
31
  }
32
32
  if (plugin === undefined) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/PanelSpecEditor/PanelSpecEditor.tsx"],"sourcesContent":["// Copyright 2023 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { ErrorAlert, JSONEditor, LinksEditor } from '@perses-dev/components';\nimport { PanelDefinition, PanelEditorValues, QueryDefinition, UnknownSpec } from '@perses-dev/core';\nimport { Control, Controller } from 'react-hook-form';\nimport { ReactElement } from 'react';\nimport { QueryCountProvider, usePlugin } from '../../runtime';\nimport { PanelPlugin } from '../../model';\nimport { OptionsEditorTabsProps, OptionsEditorTabs } from '../OptionsEditorTabs';\nimport { MultiQueryEditor } from '../MultiQueryEditor';\n\nexport interface PanelSpecEditorProps {\n control: Control<PanelEditorValues>;\n panelDefinition: PanelDefinition;\n onQueriesChange: (queries: QueryDefinition[]) => void;\n onPluginSpecChange: (spec: UnknownSpec) => void;\n onJSONChange: (panelDefinitionStr: string) => void;\n}\n\nexport function PanelSpecEditor(props: PanelSpecEditorProps): ReactElement | null {\n const { control, panelDefinition, onJSONChange, onQueriesChange, onPluginSpecChange } = props;\n const { kind } = panelDefinition.spec.plugin;\n const { data: plugin, isPending, error } = usePlugin('Panel', kind);\n\n if (error) {\n return <ErrorAlert error={error} />;\n }\n\n // TODO: Proper loading indicator\n if (isPending) {\n return null;\n }\n\n if (plugin === undefined) {\n throw new Error(`Missing implementation for panel plugin with kind '${kind}'`);\n }\n\n const { panelOptionsEditorComponents, hideQueryEditor } = plugin as PanelPlugin;\n let tabs: OptionsEditorTabsProps['tabs'] = [];\n\n if (!hideQueryEditor) {\n tabs.push({\n label: 'Query',\n content: (\n <Controller\n control={control}\n name=\"panelDefinition.spec.queries\"\n render={({ field }) => (\n <MultiQueryEditor\n queryTypes={plugin.supportedQueryTypes ?? []}\n queries={panelDefinition.spec.queries ?? []}\n onChange={(queries) => {\n field.onChange(queries);\n onQueriesChange(queries);\n }}\n />\n )}\n />\n ),\n });\n }\n\n if (panelOptionsEditorComponents !== undefined) {\n tabs = tabs.concat(\n panelOptionsEditorComponents.map(({ label, content: OptionsEditorComponent }) => ({\n label,\n content: (\n <Controller\n control={control}\n name=\"panelDefinition.spec.plugin.spec\"\n render={({ field }) => (\n <OptionsEditorComponent\n value={panelDefinition.spec.plugin.spec}\n onChange={(spec) => {\n field.onChange(spec);\n onPluginSpecChange(spec);\n }}\n />\n )}\n />\n ),\n }))\n );\n }\n\n // always show json editor and links editor by default\n tabs.push({\n label: 'Links',\n content: <LinksEditor control={control} />,\n });\n tabs.push({\n label: 'JSON',\n content: (\n <Controller\n control={control}\n name=\"panelDefinition\"\n render={({ field }) => (\n <JSONEditor\n maxHeight=\"80vh\"\n value={panelDefinition}\n onChange={(json) => {\n field.onChange(JSON.parse(json));\n onJSONChange(json);\n }}\n />\n )}\n />\n ),\n });\n\n return (\n <QueryCountProvider queryCount={(panelDefinition.spec.queries ?? []).length}>\n <OptionsEditorTabs key={tabs.length} tabs={tabs} />\n </QueryCountProvider>\n );\n}\n"],"names":["ErrorAlert","JSONEditor","LinksEditor","Controller","QueryCountProvider","usePlugin","OptionsEditorTabs","MultiQueryEditor","PanelSpecEditor","props","control","panelDefinition","onJSONChange","onQueriesChange","onPluginSpecChange","kind","spec","plugin","data","isPending","error","undefined","Error","panelOptionsEditorComponents","hideQueryEditor","tabs","push","label","content","name","render","field","queryTypes","supportedQueryTypes","queries","onChange","concat","map","OptionsEditorComponent","value","maxHeight","json","JSON","parse","queryCount","length"],"mappings":"AAAA,oCAAoC;AACpC,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;;AAEjC,SAASA,UAAU,EAAEC,UAAU,EAAEC,WAAW,QAAQ,yBAAyB;AAE7E,SAAkBC,UAAU,QAAQ,kBAAkB;AAEtD,SAASC,kBAAkB,EAAEC,SAAS,QAAQ,gBAAgB;AAE9D,SAAiCC,iBAAiB,QAAQ,uBAAuB;AACjF,SAASC,gBAAgB,QAAQ,sBAAsB;AAUvD,OAAO,SAASC,gBAAgBC,KAA2B;IACzD,MAAM,EAAEC,OAAO,EAAEC,eAAe,EAAEC,YAAY,EAAEC,eAAe,EAAEC,kBAAkB,EAAE,GAAGL;IACxF,MAAM,EAAEM,IAAI,EAAE,GAAGJ,gBAAgBK,IAAI,CAACC,MAAM;IAC5C,MAAM,EAAEC,MAAMD,MAAM,EAAEE,SAAS,EAAEC,KAAK,EAAE,GAAGf,UAAU,SAASU;IAE9D,IAAIK,OAAO;QACT,qBAAO,KAACpB;YAAWoB,OAAOA;;IAC5B;IAEA,iCAAiC;IACjC,IAAID,WAAW;QACb,OAAO;IACT;IAEA,IAAIF,WAAWI,WAAW;QACxB,MAAM,IAAIC,MAAM,CAAC,mDAAmD,EAAEP,KAAK,CAAC,CAAC;IAC/E;IAEA,MAAM,EAAEQ,4BAA4B,EAAEC,eAAe,EAAE,GAAGP;IAC1D,IAAIQ,OAAuC,EAAE;IAE7C,IAAI,CAACD,iBAAiB;QACpBC,KAAKC,IAAI,CAAC;YACRC,OAAO;YACPC,uBACE,KAACzB;gBACCO,SAASA;gBACTmB,MAAK;gBACLC,QAAQ,CAAC,EAAEC,KAAK,EAAE,iBAChB,KAACxB;wBACCyB,YAAYf,OAAOgB,mBAAmB,IAAI,EAAE;wBAC5CC,SAASvB,gBAAgBK,IAAI,CAACkB,OAAO,IAAI,EAAE;wBAC3CC,UAAU,CAACD;4BACTH,MAAMI,QAAQ,CAACD;4BACfrB,gBAAgBqB;wBAClB;;;QAKV;IACF;IAEA,IAAIX,iCAAiCF,WAAW;QAC9CI,OAAOA,KAAKW,MAAM,CAChBb,6BAA6Bc,GAAG,CAAC,CAAC,EAAEV,KAAK,EAAEC,SAASU,sBAAsB,EAAE,GAAM,CAAA;gBAChFX;gBACAC,uBACE,KAACzB;oBACCO,SAASA;oBACTmB,MAAK;oBACLC,QAAQ,CAAC,EAAEC,KAAK,EAAE,iBAChB,KAACO;4BACCC,OAAO5B,gBAAgBK,IAAI,CAACC,MAAM,CAACD,IAAI;4BACvCmB,UAAU,CAACnB;gCACTe,MAAMI,QAAQ,CAACnB;gCACfF,mBAAmBE;4BACrB;;;YAKV,CAAA;IAEJ;IAEA,sDAAsD;IACtDS,KAAKC,IAAI,CAAC;QACRC,OAAO;QACPC,uBAAS,KAAC1B;YAAYQ,SAASA;;IACjC;IACAe,KAAKC,IAAI,CAAC;QACRC,OAAO;QACPC,uBACE,KAACzB;YACCO,SAASA;YACTmB,MAAK;YACLC,QAAQ,CAAC,EAAEC,KAAK,EAAE,iBAChB,KAAC9B;oBACCuC,WAAU;oBACVD,OAAO5B;oBACPwB,UAAU,CAACM;wBACTV,MAAMI,QAAQ,CAACO,KAAKC,KAAK,CAACF;wBAC1B7B,aAAa6B;oBACf;;;IAKV;IAEA,qBACE,KAACrC;QAAmBwC,YAAY,AAACjC,CAAAA,gBAAgBK,IAAI,CAACkB,OAAO,IAAI,EAAE,AAAD,EAAGW,MAAM;kBACzE,cAAA,KAACvC;YAAoCmB,MAAMA;WAAnBA,KAAKoB,MAAM;;AAGzC"}
1
+ {"version":3,"sources":["../../../src/components/PanelSpecEditor/PanelSpecEditor.tsx"],"sourcesContent":["// Copyright 2023 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { ErrorAlert, JSONEditor, LinksEditor } from '@perses-dev/components';\nimport { PanelDefinition, PanelEditorValues, QueryDefinition, UnknownSpec } from '@perses-dev/core';\nimport { Control, Controller } from 'react-hook-form';\nimport { ReactElement } from 'react';\nimport { QueryCountProvider, usePlugin } from '../../runtime';\nimport { PanelPlugin } from '../../model';\nimport { OptionsEditorTabsProps, OptionsEditorTabs } from '../OptionsEditorTabs';\nimport { MultiQueryEditor } from '../MultiQueryEditor';\n\nexport interface PanelSpecEditorProps {\n control: Control<PanelEditorValues>;\n panelDefinition: PanelDefinition;\n onQueriesChange: (queries: QueryDefinition[]) => void;\n onPluginSpecChange: (spec: UnknownSpec) => void;\n onJSONChange: (panelDefinitionStr: string) => void;\n}\n\nexport function PanelSpecEditor(props: PanelSpecEditorProps): ReactElement | null {\n const { control, panelDefinition, onJSONChange, onQueriesChange, onPluginSpecChange } = props;\n const { kind } = panelDefinition.spec.plugin;\n const { data: plugin, isLoading, error } = usePlugin('Panel', kind);\n\n if (error) {\n return <ErrorAlert error={error} />;\n }\n\n // TODO: Proper loading indicator\n if (isLoading) {\n return null;\n }\n\n if (plugin === undefined) {\n throw new Error(`Missing implementation for panel plugin with kind '${kind}'`);\n }\n\n const { panelOptionsEditorComponents, hideQueryEditor } = plugin as PanelPlugin;\n let tabs: OptionsEditorTabsProps['tabs'] = [];\n\n if (!hideQueryEditor) {\n tabs.push({\n label: 'Query',\n content: (\n <Controller\n control={control}\n name=\"panelDefinition.spec.queries\"\n render={({ field }) => (\n <MultiQueryEditor\n queryTypes={plugin.supportedQueryTypes ?? []}\n queries={panelDefinition.spec.queries ?? []}\n onChange={(queries) => {\n field.onChange(queries);\n onQueriesChange(queries);\n }}\n />\n )}\n />\n ),\n });\n }\n\n if (panelOptionsEditorComponents !== undefined) {\n tabs = tabs.concat(\n panelOptionsEditorComponents.map(({ label, content: OptionsEditorComponent }) => ({\n label,\n content: (\n <Controller\n control={control}\n name=\"panelDefinition.spec.plugin.spec\"\n render={({ field }) => (\n <OptionsEditorComponent\n value={panelDefinition.spec.plugin.spec}\n onChange={(spec) => {\n field.onChange(spec);\n onPluginSpecChange(spec);\n }}\n />\n )}\n />\n ),\n }))\n );\n }\n\n // always show json editor and links editor by default\n tabs.push({\n label: 'Links',\n content: <LinksEditor control={control} />,\n });\n tabs.push({\n label: 'JSON',\n content: (\n <Controller\n control={control}\n name=\"panelDefinition\"\n render={({ field }) => (\n <JSONEditor\n maxHeight=\"80vh\"\n value={panelDefinition}\n onChange={(json) => {\n field.onChange(JSON.parse(json));\n onJSONChange(json);\n }}\n />\n )}\n />\n ),\n });\n\n return (\n <QueryCountProvider queryCount={(panelDefinition.spec.queries ?? []).length}>\n <OptionsEditorTabs key={tabs.length} tabs={tabs} />\n </QueryCountProvider>\n );\n}\n"],"names":["ErrorAlert","JSONEditor","LinksEditor","Controller","QueryCountProvider","usePlugin","OptionsEditorTabs","MultiQueryEditor","PanelSpecEditor","props","control","panelDefinition","onJSONChange","onQueriesChange","onPluginSpecChange","kind","spec","plugin","data","isLoading","error","undefined","Error","panelOptionsEditorComponents","hideQueryEditor","tabs","push","label","content","name","render","field","queryTypes","supportedQueryTypes","queries","onChange","concat","map","OptionsEditorComponent","value","maxHeight","json","JSON","parse","queryCount","length"],"mappings":"AAAA,oCAAoC;AACpC,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;;AAEjC,SAASA,UAAU,EAAEC,UAAU,EAAEC,WAAW,QAAQ,yBAAyB;AAE7E,SAAkBC,UAAU,QAAQ,kBAAkB;AAEtD,SAASC,kBAAkB,EAAEC,SAAS,QAAQ,gBAAgB;AAE9D,SAAiCC,iBAAiB,QAAQ,uBAAuB;AACjF,SAASC,gBAAgB,QAAQ,sBAAsB;AAUvD,OAAO,SAASC,gBAAgBC,KAA2B;IACzD,MAAM,EAAEC,OAAO,EAAEC,eAAe,EAAEC,YAAY,EAAEC,eAAe,EAAEC,kBAAkB,EAAE,GAAGL;IACxF,MAAM,EAAEM,IAAI,EAAE,GAAGJ,gBAAgBK,IAAI,CAACC,MAAM;IAC5C,MAAM,EAAEC,MAAMD,MAAM,EAAEE,SAAS,EAAEC,KAAK,EAAE,GAAGf,UAAU,SAASU;IAE9D,IAAIK,OAAO;QACT,qBAAO,KAACpB;YAAWoB,OAAOA;;IAC5B;IAEA,iCAAiC;IACjC,IAAID,WAAW;QACb,OAAO;IACT;IAEA,IAAIF,WAAWI,WAAW;QACxB,MAAM,IAAIC,MAAM,CAAC,mDAAmD,EAAEP,KAAK,CAAC,CAAC;IAC/E;IAEA,MAAM,EAAEQ,4BAA4B,EAAEC,eAAe,EAAE,GAAGP;IAC1D,IAAIQ,OAAuC,EAAE;IAE7C,IAAI,CAACD,iBAAiB;QACpBC,KAAKC,IAAI,CAAC;YACRC,OAAO;YACPC,uBACE,KAACzB;gBACCO,SAASA;gBACTmB,MAAK;gBACLC,QAAQ,CAAC,EAAEC,KAAK,EAAE,iBAChB,KAACxB;wBACCyB,YAAYf,OAAOgB,mBAAmB,IAAI,EAAE;wBAC5CC,SAASvB,gBAAgBK,IAAI,CAACkB,OAAO,IAAI,EAAE;wBAC3CC,UAAU,CAACD;4BACTH,MAAMI,QAAQ,CAACD;4BACfrB,gBAAgBqB;wBAClB;;;QAKV;IACF;IAEA,IAAIX,iCAAiCF,WAAW;QAC9CI,OAAOA,KAAKW,MAAM,CAChBb,6BAA6Bc,GAAG,CAAC,CAAC,EAAEV,KAAK,EAAEC,SAASU,sBAAsB,EAAE,GAAM,CAAA;gBAChFX;gBACAC,uBACE,KAACzB;oBACCO,SAASA;oBACTmB,MAAK;oBACLC,QAAQ,CAAC,EAAEC,KAAK,EAAE,iBAChB,KAACO;4BACCC,OAAO5B,gBAAgBK,IAAI,CAACC,MAAM,CAACD,IAAI;4BACvCmB,UAAU,CAACnB;gCACTe,MAAMI,QAAQ,CAACnB;gCACfF,mBAAmBE;4BACrB;;;YAKV,CAAA;IAEJ;IAEA,sDAAsD;IACtDS,KAAKC,IAAI,CAAC;QACRC,OAAO;QACPC,uBAAS,KAAC1B;YAAYQ,SAASA;;IACjC;IACAe,KAAKC,IAAI,CAAC;QACRC,OAAO;QACPC,uBACE,KAACzB;YACCO,SAASA;YACTmB,MAAK;YACLC,QAAQ,CAAC,EAAEC,KAAK,EAAE,iBAChB,KAAC9B;oBACCuC,WAAU;oBACVD,OAAO5B;oBACPwB,UAAU,CAACM;wBACTV,MAAMI,QAAQ,CAACO,KAAKC,KAAK,CAACF;wBAC1B7B,aAAa6B;oBACf;;;IAKV;IAEA,qBACE,KAACrC;QAAmBwC,YAAY,AAACjC,CAAAA,gBAAgBK,IAAI,CAACkB,OAAO,IAAI,EAAE,AAAD,EAAGW,MAAM;kBACzE,cAAA,KAACvC;YAAoCmB,MAAMA;WAAnBA,KAAKoB,MAAM;;AAGzC"}
@@ -1 +1 @@
1
- {"version":3,"file":"TimeRangeControls.d.ts","sourceRoot":"","sources":["../../../src/components/TimeRangeControls/TimeRangeControls.tsx"],"names":[],"mappings":"AAmBA,OAAO,EAGL,UAAU,EAIX,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,YAAY,EAAe,MAAM,OAAO,CAAC;AASlD,eAAO,MAAM,gCAAgC,EAAE,UAAU,EAOxD,CAAC;AAIF,UAAU,sBAAsB;IAE9B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC;CAC5B;AAED,wBAAgB,iBAAiB,CAAC,EAChC,QAAQ,EACR,qBAA4B,EAC5B,iBAAwB,EACxB,mBAA0B,EAC1B,mBAAmB,EACnB,eAAsB,EACtB,WAAW,GACZ,EAAE,sBAAsB,GAAG,YAAY,CA0IvC"}
1
+ {"version":3,"file":"TimeRangeControls.d.ts","sourceRoot":"","sources":["../../../src/components/TimeRangeControls/TimeRangeControls.tsx"],"names":[],"mappings":"AAmBA,OAAO,EAGL,UAAU,EAIX,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,YAAY,EAAe,MAAM,OAAO,CAAC;AAUlD,eAAO,MAAM,gCAAgC,EAAE,UAAU,EAOxD,CAAC;AAIF,UAAU,sBAAsB;IAE9B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC;CAC5B;AAED,wBAAgB,iBAAiB,CAAC,EAChC,QAAQ,EACR,qBAA4B,EAC5B,iBAAwB,EACxB,mBAA0B,EAC1B,mBAAmB,EACnB,eAAsB,EACtB,WAAW,GACZ,EAAE,sBAAsB,GAAG,YAAY,CA4IvC"}
@@ -21,7 +21,7 @@ import { RefreshIntervalPicker, InfoTooltip, ToolbarIconButton, TimeRangeSelecto
21
21
  import { parseDurationString } from '@perses-dev/core';
22
22
  import { useCallback } from 'react';
23
23
  import { TOOLTIP_TEXT } from '../../constants';
24
- import { useTimeRange, useShowCustomTimeRangeSetting, useTimeRangeOptionsSetting, useShowZoomRangeSetting } from '../../runtime';
24
+ import { useTimeRange, useTimeZone, useShowCustomTimeRangeSetting, useTimeRangeOptionsSetting, useShowZoomRangeSetting } from '../../runtime';
25
25
  export const DEFAULT_REFRESH_INTERVAL_OPTIONS = [
26
26
  {
27
27
  value: {
@@ -63,6 +63,7 @@ export const DEFAULT_REFRESH_INTERVAL_OPTIONS = [
63
63
  const DEFAULT_HEIGHT = '34px';
64
64
  export function TimeRangeControls({ heightPx, showTimeRangeSelector = true, showRefreshButton = true, showRefreshInterval = true, showCustomTimeRange, showZoomButtons = true, timePresets }) {
65
65
  const { timeRange, setTimeRange, refresh, refreshInterval, setRefreshInterval } = useTimeRange();
66
+ const { timeZone } = useTimeZone();
66
67
  const showCustomTimeRangeValue = useShowCustomTimeRangeSetting(showCustomTimeRange);
67
68
  const showZoomInOutButtons = useShowZoomRangeSetting(showZoomButtons);
68
69
  const timePresetsValue = useTimeRangeOptionsSetting(timePresets);
@@ -151,7 +152,8 @@ export function TimeRangeControls({ heightPx, showTimeRangeSelector = true, show
151
152
  value: timeRange,
152
153
  onChange: setTimeRange,
153
154
  height: height,
154
- showCustomTimeRange: showCustomTimeRangeValue
155
+ showCustomTimeRange: showCustomTimeRangeValue,
156
+ timeZone: timeZone
155
157
  }),
156
158
  showZoomInOutButtons && /*#__PURE__*/ _jsx(InfoTooltip, {
157
159
  description: TOOLTIP_TEXT.zoomOut,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/TimeRangeControls/TimeRangeControls.tsx"],"sourcesContent":["// Copyright 2024 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport RefreshIcon from 'mdi-material-ui/Refresh';\n// eslint-disable-next-line import/no-duplicates\nimport ZoomIn from 'mdi-material-ui/PlusCircleOutline';\n// eslint-disable-next-line import/no-duplicates\nimport ZoomOut from 'mdi-material-ui/MinusCircleOutline';\nimport { Stack } from '@mui/material';\nimport {\n RefreshIntervalPicker,\n InfoTooltip,\n TimeOption,\n ToolbarIconButton,\n TimeRangeSelector,\n buildRelativeTimeOption,\n} from '@perses-dev/components';\nimport { AbsoluteTimeRange, DurationString, parseDurationString, RelativeTimeRange } from '@perses-dev/core';\nimport { ReactElement, useCallback } from 'react';\nimport { TOOLTIP_TEXT } from '../../constants';\nimport {\n useTimeRange,\n useShowCustomTimeRangeSetting,\n useTimeRangeOptionsSetting,\n useShowZoomRangeSetting,\n} from '../../runtime';\n\nexport const DEFAULT_REFRESH_INTERVAL_OPTIONS: TimeOption[] = [\n { value: { pastDuration: '0s' }, display: 'Off' },\n { value: { pastDuration: '5s' }, display: '5s' },\n { value: { pastDuration: '10s' }, display: '10s' },\n { value: { pastDuration: '15s' }, display: '15s' },\n { value: { pastDuration: '30s' }, display: '30s' },\n { value: { pastDuration: '60s' }, display: '1m' },\n];\n\nconst DEFAULT_HEIGHT = '34px';\n\ninterface TimeRangeControlsProps {\n // The controls look best at heights >= 28 pixels\n heightPx?: number;\n showTimeRangeSelector?: boolean;\n showRefreshButton?: boolean;\n showRefreshInterval?: boolean;\n showCustomTimeRange?: boolean;\n showZoomButtons?: boolean;\n timePresets?: TimeOption[];\n}\n\nexport function TimeRangeControls({\n heightPx,\n showTimeRangeSelector = true,\n showRefreshButton = true,\n showRefreshInterval = true,\n showCustomTimeRange,\n showZoomButtons = true,\n timePresets,\n}: TimeRangeControlsProps): ReactElement {\n const { timeRange, setTimeRange, refresh, refreshInterval, setRefreshInterval } = useTimeRange();\n\n const showCustomTimeRangeValue = useShowCustomTimeRangeSetting(showCustomTimeRange);\n const showZoomInOutButtons = useShowZoomRangeSetting(showZoomButtons);\n const timePresetsValue = useTimeRangeOptionsSetting(timePresets);\n\n // Convert height to a string, then use the string for styling\n const height = heightPx === undefined ? DEFAULT_HEIGHT : `${heightPx}px`;\n\n // add time preset if one does not match duration given in time range\n if (\n 'pastDuration' in timeRange &&\n !timePresetsValue.some((option) => option.value.pastDuration === timeRange['pastDuration'])\n ) {\n timePresetsValue.push(buildRelativeTimeOption(timeRange['pastDuration']));\n }\n\n // set the new refresh interval both in the dashboard context & as query param\n const handleRefreshIntervalChange = useCallback(\n (duration: DurationString) => {\n setRefreshInterval(duration);\n },\n [setRefreshInterval]\n );\n\n const fromDurationToMillis = (strDuration: string): number => {\n const duration = parseDurationString(strDuration);\n const millis =\n // eslint-disable-next-line prettier/prettier\n ((duration.seconds ?? 0) +\n (duration.minutes ?? 0) * 60 +\n (duration.hours ?? 0) * 3600 +\n (duration.days ?? 0) * 86400 +\n (duration.weeks ?? 0) * 7 * 86400 +\n (duration.months ?? 0) * 30.436875 * 86400 + // avg month duration is ok for zoom purposes\n (duration.years ?? 0) * 365.2425 * 86400) * // avg year duration is ok for zoom purposes\n // eslint-disable-next-line prettier/prettier\n 1000; // to milliseconds\n return millis;\n };\n\n // Function to double current time range, adding 50% before current start and 50% after current end\n const doubleTimeRange = (): AbsoluteTimeRange => {\n let newStart, newEnd, extendEndsBy;\n const now = new Date();\n if (Object.hasOwn(timeRange, 'start')) {\n // current range is absolute\n const absVal = timeRange as AbsoluteTimeRange;\n extendEndsBy = (absVal.end.getTime() - absVal.start.getTime()) / 2; // half it to add 50% before current start and after current end\n newStart = new Date(absVal.start.getTime() - extendEndsBy);\n newEnd = new Date(absVal.end.getTime() + extendEndsBy);\n } else {\n // current range is relative\n const relVal = timeRange as RelativeTimeRange;\n extendEndsBy = fromDurationToMillis(relVal.pastDuration) / 2;\n newEnd = typeof relVal.end === 'undefined' ? now : new Date(relVal.end.getTime() + extendEndsBy);\n newStart = new Date(newEnd.getTime() - extendEndsBy * 4);\n }\n if (newEnd.getTime() > now.getTime()) {\n // if the new computed end is in the future\n newEnd = now;\n newStart.setTime(now.getTime() - extendEndsBy * 4);\n }\n if (newStart.getTime() < 1) {\n newStart.setTime(1);\n }\n return { start: newStart, end: newEnd };\n };\n\n // Function to half current time range, cutting 25% before current start and 25% after current end\n const halfTimeRange = (): AbsoluteTimeRange => {\n let newStart, newEnd;\n if (Object.hasOwn(timeRange, 'start')) {\n const absVal = timeRange as AbsoluteTimeRange;\n const shrinkEndsBy = (absVal.end.getTime() - absVal.start.getTime()) / 4;\n newStart = new Date(absVal.start.getTime() + shrinkEndsBy);\n newEnd = new Date(absVal.end.getTime() - shrinkEndsBy);\n } else {\n const relVal = timeRange as RelativeTimeRange;\n const shrinkEndsBy = fromDurationToMillis(relVal.pastDuration) / 4; // 25% of it to cut after current start and before current end\n const endIsAbsolute = typeof relVal.end !== 'undefined';\n newEnd = endIsAbsolute ? new Date(relVal.end!.getTime() - shrinkEndsBy) : new Date();\n newStart = new Date(newEnd.getTime() - shrinkEndsBy * 2);\n }\n if (newStart.getTime() >= newEnd.getTime() - 1000) {\n newStart.setTime(newEnd.getTime() - 1000);\n }\n return { start: newStart, end: newEnd };\n };\n\n const setHalfTimeRange = (): void => setTimeRange(halfTimeRange());\n const setDoubleTimeRange = (): void => setTimeRange(doubleTimeRange());\n\n return (\n <Stack direction=\"row\" spacing={1}>\n {showTimeRangeSelector && (\n <TimeRangeSelector\n timeOptions={timePresetsValue}\n value={timeRange}\n onChange={setTimeRange}\n height={height}\n showCustomTimeRange={showCustomTimeRangeValue}\n />\n )}\n {showZoomInOutButtons && (\n <InfoTooltip description={TOOLTIP_TEXT.zoomOut}>\n <ToolbarIconButton aria-label={TOOLTIP_TEXT.zoomOut} onClick={setDoubleTimeRange} sx={{ height }}>\n <ZoomOut />\n </ToolbarIconButton>\n </InfoTooltip>\n )}\n {showZoomInOutButtons && (\n <InfoTooltip description={TOOLTIP_TEXT.zoomIn}>\n <ToolbarIconButton aria-label={TOOLTIP_TEXT.zoomIn} onClick={setHalfTimeRange} sx={{ height }}>\n <ZoomIn />\n </ToolbarIconButton>\n </InfoTooltip>\n )}\n {showRefreshButton && (\n <InfoTooltip description={TOOLTIP_TEXT.refresh}>\n <ToolbarIconButton aria-label={TOOLTIP_TEXT.refresh} onClick={refresh} sx={{ height }}>\n <RefreshIcon />\n </ToolbarIconButton>\n </InfoTooltip>\n )}\n {showRefreshInterval && (\n <InfoTooltip description={TOOLTIP_TEXT.refreshInterval}>\n <RefreshIntervalPicker\n timeOptions={DEFAULT_REFRESH_INTERVAL_OPTIONS}\n value={refreshInterval}\n onChange={handleRefreshIntervalChange}\n height={height}\n />\n </InfoTooltip>\n )}\n </Stack>\n );\n}\n"],"names":["RefreshIcon","ZoomIn","ZoomOut","Stack","RefreshIntervalPicker","InfoTooltip","ToolbarIconButton","TimeRangeSelector","buildRelativeTimeOption","parseDurationString","useCallback","TOOLTIP_TEXT","useTimeRange","useShowCustomTimeRangeSetting","useTimeRangeOptionsSetting","useShowZoomRangeSetting","DEFAULT_REFRESH_INTERVAL_OPTIONS","value","pastDuration","display","DEFAULT_HEIGHT","TimeRangeControls","heightPx","showTimeRangeSelector","showRefreshButton","showRefreshInterval","showCustomTimeRange","showZoomButtons","timePresets","timeRange","setTimeRange","refresh","refreshInterval","setRefreshInterval","showCustomTimeRangeValue","showZoomInOutButtons","timePresetsValue","height","undefined","some","option","push","handleRefreshIntervalChange","duration","fromDurationToMillis","strDuration","millis","seconds","minutes","hours","days","weeks","months","years","doubleTimeRange","newStart","newEnd","extendEndsBy","now","Date","Object","hasOwn","absVal","end","getTime","start","relVal","setTime","halfTimeRange","shrinkEndsBy","endIsAbsolute","setHalfTimeRange","setDoubleTimeRange","direction","spacing","timeOptions","onChange","description","zoomOut","aria-label","onClick","sx","zoomIn"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/components/TimeRangeControls/TimeRangeControls.tsx"],"sourcesContent":["// Copyright 2024 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport RefreshIcon from 'mdi-material-ui/Refresh';\n// eslint-disable-next-line import/no-duplicates\nimport ZoomIn from 'mdi-material-ui/PlusCircleOutline';\n// eslint-disable-next-line import/no-duplicates\nimport ZoomOut from 'mdi-material-ui/MinusCircleOutline';\nimport { Stack } from '@mui/material';\nimport {\n RefreshIntervalPicker,\n InfoTooltip,\n TimeOption,\n ToolbarIconButton,\n TimeRangeSelector,\n buildRelativeTimeOption,\n} from '@perses-dev/components';\nimport { AbsoluteTimeRange, DurationString, parseDurationString, RelativeTimeRange } from '@perses-dev/core';\nimport { ReactElement, useCallback } from 'react';\nimport { TOOLTIP_TEXT } from '../../constants';\nimport {\n useTimeRange,\n useTimeZone,\n useShowCustomTimeRangeSetting,\n useTimeRangeOptionsSetting,\n useShowZoomRangeSetting,\n} from '../../runtime';\n\nexport const DEFAULT_REFRESH_INTERVAL_OPTIONS: TimeOption[] = [\n { value: { pastDuration: '0s' }, display: 'Off' },\n { value: { pastDuration: '5s' }, display: '5s' },\n { value: { pastDuration: '10s' }, display: '10s' },\n { value: { pastDuration: '15s' }, display: '15s' },\n { value: { pastDuration: '30s' }, display: '30s' },\n { value: { pastDuration: '60s' }, display: '1m' },\n];\n\nconst DEFAULT_HEIGHT = '34px';\n\ninterface TimeRangeControlsProps {\n // The controls look best at heights >= 28 pixels\n heightPx?: number;\n showTimeRangeSelector?: boolean;\n showRefreshButton?: boolean;\n showRefreshInterval?: boolean;\n showCustomTimeRange?: boolean;\n showZoomButtons?: boolean;\n timePresets?: TimeOption[];\n}\n\nexport function TimeRangeControls({\n heightPx,\n showTimeRangeSelector = true,\n showRefreshButton = true,\n showRefreshInterval = true,\n showCustomTimeRange,\n showZoomButtons = true,\n timePresets,\n}: TimeRangeControlsProps): ReactElement {\n const { timeRange, setTimeRange, refresh, refreshInterval, setRefreshInterval } = useTimeRange();\n const { timeZone } = useTimeZone();\n\n const showCustomTimeRangeValue = useShowCustomTimeRangeSetting(showCustomTimeRange);\n const showZoomInOutButtons = useShowZoomRangeSetting(showZoomButtons);\n const timePresetsValue = useTimeRangeOptionsSetting(timePresets);\n\n // Convert height to a string, then use the string for styling\n const height = heightPx === undefined ? DEFAULT_HEIGHT : `${heightPx}px`;\n\n // add time preset if one does not match duration given in time range\n if (\n 'pastDuration' in timeRange &&\n !timePresetsValue.some((option) => option.value.pastDuration === timeRange['pastDuration'])\n ) {\n timePresetsValue.push(buildRelativeTimeOption(timeRange['pastDuration']));\n }\n\n // set the new refresh interval both in the dashboard context & as query param\n const handleRefreshIntervalChange = useCallback(\n (duration: DurationString) => {\n setRefreshInterval(duration);\n },\n [setRefreshInterval]\n );\n\n const fromDurationToMillis = (strDuration: string): number => {\n const duration = parseDurationString(strDuration);\n const millis =\n // eslint-disable-next-line prettier/prettier\n ((duration.seconds ?? 0) +\n (duration.minutes ?? 0) * 60 +\n (duration.hours ?? 0) * 3600 +\n (duration.days ?? 0) * 86400 +\n (duration.weeks ?? 0) * 7 * 86400 +\n (duration.months ?? 0) * 30.436875 * 86400 + // avg month duration is ok for zoom purposes\n (duration.years ?? 0) * 365.2425 * 86400) * // avg year duration is ok for zoom purposes\n // eslint-disable-next-line prettier/prettier\n 1000; // to milliseconds\n return millis;\n };\n\n // Function to double current time range, adding 50% before current start and 50% after current end\n const doubleTimeRange = (): AbsoluteTimeRange => {\n let newStart, newEnd, extendEndsBy;\n const now = new Date();\n if (Object.hasOwn(timeRange, 'start')) {\n // current range is absolute\n const absVal = timeRange as AbsoluteTimeRange;\n extendEndsBy = (absVal.end.getTime() - absVal.start.getTime()) / 2; // half it to add 50% before current start and after current end\n newStart = new Date(absVal.start.getTime() - extendEndsBy);\n newEnd = new Date(absVal.end.getTime() + extendEndsBy);\n } else {\n // current range is relative\n const relVal = timeRange as RelativeTimeRange;\n extendEndsBy = fromDurationToMillis(relVal.pastDuration) / 2;\n newEnd = typeof relVal.end === 'undefined' ? now : new Date(relVal.end.getTime() + extendEndsBy);\n newStart = new Date(newEnd.getTime() - extendEndsBy * 4);\n }\n if (newEnd.getTime() > now.getTime()) {\n // if the new computed end is in the future\n newEnd = now;\n newStart.setTime(now.getTime() - extendEndsBy * 4);\n }\n if (newStart.getTime() < 1) {\n newStart.setTime(1);\n }\n return { start: newStart, end: newEnd };\n };\n\n // Function to half current time range, cutting 25% before current start and 25% after current end\n const halfTimeRange = (): AbsoluteTimeRange => {\n let newStart, newEnd;\n if (Object.hasOwn(timeRange, 'start')) {\n const absVal = timeRange as AbsoluteTimeRange;\n const shrinkEndsBy = (absVal.end.getTime() - absVal.start.getTime()) / 4;\n newStart = new Date(absVal.start.getTime() + shrinkEndsBy);\n newEnd = new Date(absVal.end.getTime() - shrinkEndsBy);\n } else {\n const relVal = timeRange as RelativeTimeRange;\n const shrinkEndsBy = fromDurationToMillis(relVal.pastDuration) / 4; // 25% of it to cut after current start and before current end\n const endIsAbsolute = typeof relVal.end !== 'undefined';\n newEnd = endIsAbsolute ? new Date(relVal.end!.getTime() - shrinkEndsBy) : new Date();\n newStart = new Date(newEnd.getTime() - shrinkEndsBy * 2);\n }\n if (newStart.getTime() >= newEnd.getTime() - 1000) {\n newStart.setTime(newEnd.getTime() - 1000);\n }\n return { start: newStart, end: newEnd };\n };\n\n const setHalfTimeRange = (): void => setTimeRange(halfTimeRange());\n const setDoubleTimeRange = (): void => setTimeRange(doubleTimeRange());\n\n return (\n <Stack direction=\"row\" spacing={1}>\n {showTimeRangeSelector && (\n <TimeRangeSelector\n timeOptions={timePresetsValue}\n value={timeRange}\n onChange={setTimeRange}\n height={height}\n showCustomTimeRange={showCustomTimeRangeValue}\n timeZone={timeZone}\n />\n )}\n {showZoomInOutButtons && (\n <InfoTooltip description={TOOLTIP_TEXT.zoomOut}>\n <ToolbarIconButton aria-label={TOOLTIP_TEXT.zoomOut} onClick={setDoubleTimeRange} sx={{ height }}>\n <ZoomOut />\n </ToolbarIconButton>\n </InfoTooltip>\n )}\n {showZoomInOutButtons && (\n <InfoTooltip description={TOOLTIP_TEXT.zoomIn}>\n <ToolbarIconButton aria-label={TOOLTIP_TEXT.zoomIn} onClick={setHalfTimeRange} sx={{ height }}>\n <ZoomIn />\n </ToolbarIconButton>\n </InfoTooltip>\n )}\n {showRefreshButton && (\n <InfoTooltip description={TOOLTIP_TEXT.refresh}>\n <ToolbarIconButton aria-label={TOOLTIP_TEXT.refresh} onClick={refresh} sx={{ height }}>\n <RefreshIcon />\n </ToolbarIconButton>\n </InfoTooltip>\n )}\n {showRefreshInterval && (\n <InfoTooltip description={TOOLTIP_TEXT.refreshInterval}>\n <RefreshIntervalPicker\n timeOptions={DEFAULT_REFRESH_INTERVAL_OPTIONS}\n value={refreshInterval}\n onChange={handleRefreshIntervalChange}\n height={height}\n />\n </InfoTooltip>\n )}\n </Stack>\n );\n}\n"],"names":["RefreshIcon","ZoomIn","ZoomOut","Stack","RefreshIntervalPicker","InfoTooltip","ToolbarIconButton","TimeRangeSelector","buildRelativeTimeOption","parseDurationString","useCallback","TOOLTIP_TEXT","useTimeRange","useTimeZone","useShowCustomTimeRangeSetting","useTimeRangeOptionsSetting","useShowZoomRangeSetting","DEFAULT_REFRESH_INTERVAL_OPTIONS","value","pastDuration","display","DEFAULT_HEIGHT","TimeRangeControls","heightPx","showTimeRangeSelector","showRefreshButton","showRefreshInterval","showCustomTimeRange","showZoomButtons","timePresets","timeRange","setTimeRange","refresh","refreshInterval","setRefreshInterval","timeZone","showCustomTimeRangeValue","showZoomInOutButtons","timePresetsValue","height","undefined","some","option","push","handleRefreshIntervalChange","duration","fromDurationToMillis","strDuration","millis","seconds","minutes","hours","days","weeks","months","years","doubleTimeRange","newStart","newEnd","extendEndsBy","now","Date","Object","hasOwn","absVal","end","getTime","start","relVal","setTime","halfTimeRange","shrinkEndsBy","endIsAbsolute","setHalfTimeRange","setDoubleTimeRange","direction","spacing","timeOptions","onChange","description","zoomOut","aria-label","onClick","sx","zoomIn"],"mappings":"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"}