@perses-dev/dashboards 0.0.0-snapshot-time-zone-selector-946f408 → 0.0.0-snapshot-timeseries-panel-actions-e28c1fe

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 (52) hide show
  1. package/dist/cjs/components/DashboardToolbar/DashboardToolbar.js +98 -109
  2. package/dist/cjs/components/DownloadButton/DownloadButton.js +3 -33
  3. package/dist/cjs/components/DownloadButton/serializeDashboard.js +64 -0
  4. package/dist/cjs/components/Panel/Panel.js +85 -1
  5. package/dist/cjs/components/Panel/PanelActions.js +45 -8
  6. package/dist/cjs/components/Panel/PanelHeader.js +11 -3
  7. package/dist/cjs/components/SaveChangesConfirmationDialog/SaveChangesConfirmationDialog.js +1 -13
  8. package/dist/cjs/components/SaveDashboardButton/SaveDashboardButton.js +3 -10
  9. package/dist/cjs/context/DashboardProvider/DashboardProvider.js +2 -4
  10. package/dist/cjs/context/useDashboard.js +1 -3
  11. package/dist/cjs/views/ViewDashboard/ViewDashboard.js +0 -2
  12. package/dist/components/DashboardToolbar/DashboardToolbar.d.ts.map +1 -1
  13. package/dist/components/DashboardToolbar/DashboardToolbar.js +100 -111
  14. package/dist/components/DashboardToolbar/DashboardToolbar.js.map +1 -1
  15. package/dist/components/DownloadButton/DownloadButton.d.ts.map +1 -1
  16. package/dist/components/DownloadButton/DownloadButton.js +3 -33
  17. package/dist/components/DownloadButton/DownloadButton.js.map +1 -1
  18. package/dist/components/DownloadButton/serializeDashboard.d.ts +8 -0
  19. package/dist/components/DownloadButton/serializeDashboard.d.ts.map +1 -0
  20. package/dist/components/DownloadButton/serializeDashboard.js +56 -0
  21. package/dist/components/DownloadButton/serializeDashboard.js.map +1 -0
  22. package/dist/components/Panel/Panel.d.ts.map +1 -1
  23. package/dist/components/Panel/Panel.js +87 -3
  24. package/dist/components/Panel/Panel.js.map +1 -1
  25. package/dist/components/Panel/PanelActions.d.ts +4 -3
  26. package/dist/components/Panel/PanelActions.d.ts.map +1 -1
  27. package/dist/components/Panel/PanelActions.js +45 -8
  28. package/dist/components/Panel/PanelActions.js.map +1 -1
  29. package/dist/components/Panel/PanelHeader.d.ts +2 -1
  30. package/dist/components/Panel/PanelHeader.d.ts.map +1 -1
  31. package/dist/components/Panel/PanelHeader.js +11 -3
  32. package/dist/components/Panel/PanelHeader.js.map +1 -1
  33. package/dist/components/SaveChangesConfirmationDialog/SaveChangesConfirmationDialog.d.ts.map +1 -1
  34. package/dist/components/SaveChangesConfirmationDialog/SaveChangesConfirmationDialog.js +2 -14
  35. package/dist/components/SaveChangesConfirmationDialog/SaveChangesConfirmationDialog.js.map +1 -1
  36. package/dist/components/SaveDashboardButton/SaveDashboardButton.d.ts.map +1 -1
  37. package/dist/components/SaveDashboardButton/SaveDashboardButton.js +4 -11
  38. package/dist/components/SaveDashboardButton/SaveDashboardButton.js.map +1 -1
  39. package/dist/context/DashboardProvider/DashboardProvider.d.ts +0 -1
  40. package/dist/context/DashboardProvider/DashboardProvider.d.ts.map +1 -1
  41. package/dist/context/DashboardProvider/DashboardProvider.js +3 -5
  42. package/dist/context/DashboardProvider/DashboardProvider.js.map +1 -1
  43. package/dist/context/DashboardProvider/save-changes-dialog-slice.d.ts +1 -2
  44. package/dist/context/DashboardProvider/save-changes-dialog-slice.d.ts.map +1 -1
  45. package/dist/context/DashboardProvider/save-changes-dialog-slice.js.map +1 -1
  46. package/dist/context/useDashboard.d.ts.map +1 -1
  47. package/dist/context/useDashboard.js +1 -3
  48. package/dist/context/useDashboard.js.map +1 -1
  49. package/dist/views/ViewDashboard/ViewDashboard.d.ts.map +1 -1
  50. package/dist/views/ViewDashboard/ViewDashboard.js +1 -3
  51. package/dist/views/ViewDashboard/ViewDashboard.js.map +1 -1
  52. package/package.json +5 -5
@@ -24,7 +24,6 @@ const _jsxruntime = require("react/jsx-runtime");
24
24
  const _material = require("@mui/material");
25
25
  const _components = require("@perses-dev/components");
26
26
  const _pluginsystem = require("@perses-dev/plugin-system");
27
- const _react = require("react");
28
27
  const _context = require("../../context");
29
28
  const _AddPanelButton = require("../AddPanelButton");
30
29
  const _AddGroupButton = require("../AddGroupButton");
@@ -40,126 +39,116 @@ const DashboardToolbar = (props)=>{
40
39
  const { isEditMode } = (0, _context.useEditMode)();
41
40
  const isBiggerThanSm = (0, _material.useMediaQuery)((0, _material.useTheme)().breakpoints.up('sm'));
42
41
  const isBiggerThanMd = (0, _material.useMediaQuery)((0, _material.useTheme)().breakpoints.up('md'));
43
- const { timeZone, setTimeZone } = (0, _pluginsystem.useTimeZone)();
44
- const timeZoneOptions = (0, _components.getTimeZoneOptions)();
45
42
  const dashboardTitle = dashboardTitleComponent ? dashboardTitleComponent : /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Typography, {
46
43
  variant: "h2",
47
44
  children: dashboardName
48
45
  });
49
46
  const testId = 'dashboard-toolbar';
50
- const handleTimeZoneChange = (0, _react.useCallback)((timeZoneOption)=>{
51
- setTimeZone(timeZoneOption.value);
52
- }, [
53
- setTimeZone
54
- ]);
55
- return /*#__PURE__*/ (0, _jsxruntime.jsxs)(_material.Stack, {
56
- "data-testid": testId,
57
- children: [
58
- /*#__PURE__*/ (0, _jsxruntime.jsxs)(_material.Box, {
59
- px: 2,
60
- py: 1.5,
61
- display: "flex",
62
- sx: {
63
- backgroundColor: (theme)=>theme.palette.primary.main + (isEditMode ? '30' : '0')
64
- },
65
- children: [
66
- dashboardTitle,
67
- isEditMode ? /*#__PURE__*/ (0, _jsxruntime.jsxs)(_material.Stack, {
68
- direction: "row",
69
- gap: 1,
70
- ml: "auto",
71
- children: [
72
- isReadonly && /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Alert, {
73
- severity: "warning",
74
- sx: {
75
- backgroundColor: 'transparent',
76
- padding: 0
77
- },
78
- children: "Dashboard managed via code only. Download JSON and commit changes to save."
79
- }),
80
- /*#__PURE__*/ (0, _jsxruntime.jsxs)(_material.Stack, {
81
- direction: "row",
82
- spacing: 0.5,
83
- ml: 1,
84
- whiteSpace: "nowrap",
85
- children: [
86
- isVariableEnabled && /*#__PURE__*/ (0, _jsxruntime.jsx)(_Variables.EditVariablesButton, {}),
87
- isDatasourceEnabled && /*#__PURE__*/ (0, _jsxruntime.jsx)(_Datasources.EditDatasourcesButton, {}),
88
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_AddPanelButton.AddPanelButton, {}),
89
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_AddGroupButton.AddGroupButton, {})
90
- ]
91
- }),
92
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_SaveDashboardButton.SaveDashboardButton, {
93
- onSave: onSave,
94
- isDisabled: isReadonly
95
- }),
96
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Button, {
97
- variant: "outlined",
98
- onClick: onCancelButtonClick,
99
- children: "Cancel"
100
- })
101
- ]
102
- }) : /*#__PURE__*/ (0, _jsxruntime.jsx)(_jsxruntime.Fragment, {
103
- children: isBiggerThanSm && /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Stack, {
47
+ return /*#__PURE__*/ (0, _jsxruntime.jsx)(_jsxruntime.Fragment, {
48
+ children: /*#__PURE__*/ (0, _jsxruntime.jsxs)(_material.Stack, {
49
+ "data-testid": testId,
50
+ children: [
51
+ /*#__PURE__*/ (0, _jsxruntime.jsxs)(_material.Box, {
52
+ px: 2,
53
+ py: 1.5,
54
+ display: "flex",
55
+ sx: {
56
+ backgroundColor: (theme)=>theme.palette.primary.main + (isEditMode ? '30' : '0')
57
+ },
58
+ children: [
59
+ dashboardTitle,
60
+ isEditMode ? /*#__PURE__*/ (0, _jsxruntime.jsxs)(_material.Stack, {
104
61
  direction: "row",
105
62
  gap: 1,
106
63
  ml: "auto",
107
- children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_EditButton.EditButton, {
108
- onClick: onEditButtonClick
109
- })
110
- })
111
- })
112
- ]
113
- }),
114
- /*#__PURE__*/ (0, _jsxruntime.jsxs)(_material.Box, {
115
- sx: {
116
- display: 'flex',
117
- width: '100%',
118
- alignItems: 'start',
119
- padding: (theme)=>theme.spacing(1, 2, 0, 2),
120
- flexDirection: isBiggerThanMd ? 'row' : 'column',
121
- flexWrap: 'nowrap',
122
- gap: 1
123
- },
124
- children: [
125
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Box, {
126
- width: "100%",
127
- children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.ErrorBoundary, {
128
- FallbackComponent: _components.ErrorAlert,
129
- children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_DashboardStickyToolbar.DashboardStickyToolbar, {
130
- initialVariableIsSticky: initialVariableIsSticky,
131
- sx: {
132
- backgroundColor: ({ palette })=>palette.background.default
133
- }
134
- })
135
- })
136
- }),
137
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Stack, {
138
- direction: "row",
139
- ml: "auto",
140
- flexWrap: "wrap",
141
- justifyContent: "end",
142
- children: /*#__PURE__*/ (0, _jsxruntime.jsxs)(_material.Stack, {
143
- direction: "row",
144
- spacing: 1,
145
- mt: 1,
146
- ml: 1,
147
64
  children: [
148
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_pluginsystem.TimeRangeControls, {}),
149
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.TimeZoneSelector, {
150
- timeZoneOptions: timeZoneOptions,
151
- value: timeZone,
152
- onChange: handleTimeZoneChange
65
+ isReadonly && /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Alert, {
66
+ severity: "warning",
67
+ sx: {
68
+ backgroundColor: 'transparent',
69
+ padding: 0
70
+ },
71
+ children: "Dashboard managed via code only. Download JSON and commit changes to save."
153
72
  }),
154
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_DownloadButton.DownloadButton, {}),
155
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_EditJsonButton.EditJsonButton, {
156
- isReadonly: !isEditMode
73
+ /*#__PURE__*/ (0, _jsxruntime.jsxs)(_material.Stack, {
74
+ direction: "row",
75
+ spacing: 0.5,
76
+ ml: 1,
77
+ whiteSpace: "nowrap",
78
+ children: [
79
+ isVariableEnabled && /*#__PURE__*/ (0, _jsxruntime.jsx)(_Variables.EditVariablesButton, {}),
80
+ isDatasourceEnabled && /*#__PURE__*/ (0, _jsxruntime.jsx)(_Datasources.EditDatasourcesButton, {}),
81
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_AddPanelButton.AddPanelButton, {}),
82
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_AddGroupButton.AddGroupButton, {})
83
+ ]
84
+ }),
85
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_SaveDashboardButton.SaveDashboardButton, {
86
+ onSave: onSave,
87
+ isDisabled: isReadonly
88
+ }),
89
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Button, {
90
+ variant: "outlined",
91
+ onClick: onCancelButtonClick,
92
+ children: "Cancel"
157
93
  })
158
94
  ]
95
+ }) : /*#__PURE__*/ (0, _jsxruntime.jsx)(_jsxruntime.Fragment, {
96
+ children: isBiggerThanSm && /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Stack, {
97
+ direction: "row",
98
+ gap: 1,
99
+ ml: "auto",
100
+ children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_EditButton.EditButton, {
101
+ onClick: onEditButtonClick
102
+ })
103
+ })
104
+ })
105
+ ]
106
+ }),
107
+ /*#__PURE__*/ (0, _jsxruntime.jsxs)(_material.Box, {
108
+ sx: {
109
+ display: 'flex',
110
+ width: '100%',
111
+ alignItems: 'start',
112
+ padding: (theme)=>theme.spacing(1, 2, 0, 2),
113
+ flexDirection: isBiggerThanMd ? 'row' : 'column',
114
+ flexWrap: 'nowrap',
115
+ gap: 1
116
+ },
117
+ children: [
118
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Box, {
119
+ width: "100%",
120
+ children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.ErrorBoundary, {
121
+ FallbackComponent: _components.ErrorAlert,
122
+ children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_DashboardStickyToolbar.DashboardStickyToolbar, {
123
+ initialVariableIsSticky: initialVariableIsSticky,
124
+ sx: {
125
+ backgroundColor: ({ palette })=>palette.background.default
126
+ }
127
+ })
128
+ })
129
+ }),
130
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Stack, {
131
+ direction: "row",
132
+ ml: "auto",
133
+ flexWrap: "wrap",
134
+ justifyContent: "end",
135
+ children: /*#__PURE__*/ (0, _jsxruntime.jsxs)(_material.Stack, {
136
+ direction: "row",
137
+ spacing: 1,
138
+ mt: 1,
139
+ ml: 1,
140
+ children: [
141
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_pluginsystem.TimeRangeControls, {}),
142
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_DownloadButton.DownloadButton, {}),
143
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_EditJsonButton.EditJsonButton, {
144
+ isReadonly: !isEditMode
145
+ })
146
+ ]
147
+ })
159
148
  })
160
- })
161
- ]
162
- })
163
- ]
149
+ ]
150
+ })
151
+ ]
152
+ })
164
153
  });
165
154
  };
@@ -25,8 +25,8 @@ const _material = require("@mui/material");
25
25
  const _components = require("@perses-dev/components");
26
26
  const _DownloadOutline = /*#__PURE__*/ _interop_require_default(require("mdi-material-ui/DownloadOutline"));
27
27
  const _react = /*#__PURE__*/ _interop_require_wildcard(require("react"));
28
- const _yaml = require("yaml");
29
28
  const _context = require("../../context");
29
+ const _serializeDashboard = require("./serializeDashboard");
30
30
  function _interop_require_default(obj) {
31
31
  return obj && obj.__esModule ? obj : {
32
32
  default: obj
@@ -83,43 +83,13 @@ function DownloadButton() {
83
83
  };
84
84
  const handleItemClick = (format, shape)=>()=>{
85
85
  setAnchorEl(null);
86
- let type, content = '';
87
- switch(format){
88
- case 'json':
89
- type = 'application/json';
90
- content = JSON.stringify(dashboard, null, 2);
91
- break;
92
- case 'yaml':
93
- {
94
- type = 'application/yaml';
95
- if (shape === 'cr') {
96
- const name = dashboard.metadata.name.toLowerCase().replace(/[^a-z0-9-]/g, '-');
97
- content = (0, _yaml.stringify)({
98
- apiVersion: 'perses.dev/v1alpha1',
99
- kind: 'PersesDashboard',
100
- metadata: {
101
- labels: {
102
- 'app.kubernetes.io/name': 'perses-dashboard',
103
- 'app.kubernetes.io/instance': name,
104
- 'app.kubernetes.io/part-of': 'perses-operator'
105
- },
106
- name
107
- },
108
- namespace: dashboard.metadata.project,
109
- spec: dashboard.spec
110
- });
111
- } else {
112
- content = (0, _yaml.stringify)(dashboard);
113
- }
114
- }
115
- break;
116
- }
86
+ const { contentType, content } = (0, _serializeDashboard.serializeDashboard)(dashboard, format, shape);
117
87
  if (!hiddenLinkRef || !hiddenLinkRef.current) return;
118
88
  // Create blob URL
119
89
  const hiddenLinkUrl = URL.createObjectURL(new Blob([
120
90
  content
121
91
  ], {
122
- type
92
+ type: contentType
123
93
  }));
124
94
  // Simulate click
125
95
  hiddenLinkRef.current.download = `${dashboard.metadata.name}${shape === 'cr' ? '-cr' : ''}.${format}`;
@@ -0,0 +1,64 @@
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, "serializeDashboard", {
18
+ enumerable: true,
19
+ get: function() {
20
+ return serializeDashboard;
21
+ }
22
+ });
23
+ const _yaml = require("yaml");
24
+ function serializeYaml(dashboard, shape) {
25
+ let content;
26
+ if (shape === 'cr') {
27
+ const name = dashboard.metadata.name.toLowerCase().replace(/[^a-z0-9-]/g, '-');
28
+ content = (0, _yaml.stringify)({
29
+ apiVersion: 'perses.dev/v1alpha1',
30
+ kind: 'PersesDashboard',
31
+ metadata: {
32
+ labels: {
33
+ 'app.kubernetes.io/name': 'perses-dashboard',
34
+ 'app.kubernetes.io/instance': name,
35
+ 'app.kubernetes.io/part-of': 'perses-operator'
36
+ },
37
+ name,
38
+ namespace: dashboard.metadata.project
39
+ },
40
+ spec: dashboard.spec
41
+ }, {
42
+ schema: 'yaml-1.1'
43
+ });
44
+ } else {
45
+ content = (0, _yaml.stringify)(dashboard, {
46
+ schema: 'yaml-1.1'
47
+ });
48
+ }
49
+ return {
50
+ contentType: 'application/yaml',
51
+ content
52
+ };
53
+ }
54
+ function serializeDashboard(dashboard, format, shape) {
55
+ switch(format){
56
+ case 'json':
57
+ return {
58
+ contentType: 'application/json',
59
+ content: JSON.stringify(dashboard, null, 2)
60
+ };
61
+ case 'yaml':
62
+ return serializeYaml(dashboard, shape);
63
+ }
64
+ }
@@ -54,6 +54,88 @@ const Panel = /*#__PURE__*/ (0, _react.memo)(function Panel(props) {
54
54
  ]);
55
55
  const chartsTheme = (0, _components.useChartsTheme)();
56
56
  const { queryResults } = (0, _pluginsystem.useDataQueriesContext)();
57
+ const { getPlugin } = (0, _pluginsystem.usePluginRegistry)();
58
+ const panelPropsForActions = (0, _react.useMemo)(()=>{
59
+ return {
60
+ spec: definition.spec.plugin.spec,
61
+ queryResults: queryResults.map((query)=>({
62
+ definition: query.definition,
63
+ data: query.data
64
+ })),
65
+ contentDimensions,
66
+ definition
67
+ };
68
+ }, [
69
+ definition,
70
+ contentDimensions,
71
+ queryResults
72
+ ]);
73
+ // Load plugin actions from the plugin
74
+ const [pluginActions, setPluginActions] = (0, _react.useState)([]);
75
+ (0, _react.useEffect)(()=>{
76
+ let cancelled = false;
77
+ const loadPluginActions = async ()=>{
78
+ const panelPluginKind = definition.spec.plugin.kind;
79
+ const panelProps = panelPropsForActions;
80
+ if (!panelPluginKind || !panelProps) {
81
+ if (!cancelled) {
82
+ setPluginActions([]);
83
+ }
84
+ return;
85
+ }
86
+ try {
87
+ // Add defensive check for getPlugin availability
88
+ if (!getPlugin || typeof getPlugin !== 'function') {
89
+ if (!cancelled) {
90
+ setPluginActions([]);
91
+ }
92
+ return;
93
+ }
94
+ const plugin = await getPlugin('Panel', panelPluginKind);
95
+ if (cancelled) return;
96
+ // More defensive checking for plugin and actions
97
+ if (!plugin || typeof plugin !== 'object' || !plugin.actions || !Array.isArray(plugin.actions) || plugin.actions.length === 0) {
98
+ if (!cancelled) {
99
+ setPluginActions([]);
100
+ }
101
+ return;
102
+ }
103
+ // Render plugin actions in header location
104
+ const headerActions = plugin.actions.filter((action)=>!action.location || action.location === 'header').map((action, index)=>{
105
+ const ActionComponent = action.component;
106
+ try {
107
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
108
+ return /*#__PURE__*/ (0, _jsxruntime.jsx)(ActionComponent, {
109
+ ...panelProps
110
+ }, `plugin-action-${index}`);
111
+ } catch (error) {
112
+ console.warn(`Failed to render plugin action ${index}:`, error);
113
+ return null;
114
+ }
115
+ }).filter((item)=>Boolean(item));
116
+ if (!cancelled) {
117
+ setPluginActions(headerActions);
118
+ }
119
+ } catch (error) {
120
+ if (!cancelled) {
121
+ console.warn('Failed to load plugin actions:', error);
122
+ setPluginActions([]);
123
+ }
124
+ }
125
+ };
126
+ // Use setTimeout to defer the async operation to the next tick
127
+ const timeoutId = setTimeout(()=>{
128
+ loadPluginActions();
129
+ }, 0);
130
+ return ()=>{
131
+ cancelled = true;
132
+ clearTimeout(timeoutId);
133
+ };
134
+ }, [
135
+ definition.spec.plugin.kind,
136
+ panelPropsForActions,
137
+ getPlugin
138
+ ]);
57
139
  const handleMouseEnter = (e)=>{
58
140
  onMouseEnter?.(e);
59
141
  };
@@ -91,6 +173,7 @@ const Panel = /*#__PURE__*/ (0, _react.memo)(function Panel(props) {
91
173
  readHandlers: readHandlers,
92
174
  editHandlers: editHandlers,
93
175
  links: definition.spec.links,
176
+ pluginActions: pluginActions,
94
177
  sx: {
95
178
  paddingX: `${chartsTheme.container.padding.default}px`
96
179
  }
@@ -112,7 +195,8 @@ const Panel = /*#__PURE__*/ (0, _react.memo)(function Panel(props) {
112
195
  children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.ErrorBoundary, {
113
196
  FallbackComponent: _components.ErrorAlert,
114
197
  resetKeys: [
115
- definition.spec
198
+ definition.spec,
199
+ queryResults
116
200
  ],
117
201
  children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_PanelContent.PanelContent, {
118
202
  definition: definition,
@@ -24,6 +24,7 @@ const _jsxruntime = require("react/jsx-runtime");
24
24
  const _material = require("@mui/material");
25
25
  const _react = require("react");
26
26
  const _components = require("@perses-dev/components");
27
+ const _pluginsystem = require("@perses-dev/plugin-system");
27
28
  const _ArrowCollapse = /*#__PURE__*/ _interop_require_default(require("mdi-material-ui/ArrowCollapse"));
28
29
  const _ArrowExpand = /*#__PURE__*/ _interop_require_default(require("mdi-material-ui/ArrowExpand"));
29
30
  const _PencilOutline = /*#__PURE__*/ _interop_require_default(require("mdi-material-ui/PencilOutline"));
@@ -47,7 +48,10 @@ const ConditionalBox = (0, _material.styled)(_material.Box)({
47
48
  flexGrow: 1,
48
49
  justifyContent: 'flex-end'
49
50
  });
50
- const PanelActions = ({ editHandlers, readHandlers, extra, title, description, descriptionTooltipId, links, queryResults })=>{
51
+ const PanelActions = ({ editHandlers, readHandlers, extra, title, description, descriptionTooltipId, links, panelContentProps, pluginActions = [] })=>{
52
+ const { isFetching, errors } = (0, _pluginsystem.useDataQueriesContext)();
53
+ // Only destructure queryResults since we removed panelPluginKind and spec
54
+ const { queryResults } = panelContentProps;
51
55
  const descriptionAction = (0, _react.useMemo)(()=>{
52
56
  if (description && description.trim().length > 0) {
53
57
  return /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.InfoTooltip, {
@@ -78,19 +82,45 @@ const PanelActions = ({ editHandlers, readHandlers, extra, title, description, d
78
82
  });
79
83
  const extraActions = editHandlers === undefined && extra;
80
84
  const queryStateIndicator = (0, _react.useMemo)(()=>{
81
- const hasData = queryResults.some((q)=>q.data);
82
- const isFetching = queryResults.some((q)=>q.isFetching);
85
+ // Check if any query is fetching
86
+ const isQueryFetching = queryResults.some((q)=>q.isFetching);
87
+ // Get query-specific errors
83
88
  const queryErrors = queryResults.filter((q)=>q.error);
84
- if (isFetching && hasData) {
89
+ // Convert QueryData[] to TimeSeriesData format for data availability check
90
+ const timeSeriesData = queryResults && queryResults.length > 0 ? {
91
+ series: queryResults.flatMap((q)=>{
92
+ // Only extract series if the data type is TimeSeriesData
93
+ if (q.data && typeof q.data === 'object' && 'series' in q.data) {
94
+ return q.data.series || [];
95
+ }
96
+ return [];
97
+ })
98
+ } : undefined;
99
+ const hasData = timeSeriesData && timeSeriesData.series && timeSeriesData.series.length > 0;
100
+ // Show loading indicator if queries are fetching AND we already have data
101
+ if ((isFetching || isQueryFetching) && hasData) {
85
102
  // If the panel has no data, the panel content will show the loading overlay.
86
103
  // Therefore, show the circular loading indicator only in case the panel doesn't display the loading overlay already.
87
104
  return /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.CircularProgress, {
88
105
  "aria-label": "loading",
89
106
  size: "1.125rem"
90
107
  });
91
- } else if (queryErrors.length > 0) {
92
- const errorTexts = queryErrors.map((q)=>q.error).map((e)=>e?.message ?? e?.toString() ?? 'Unknown error') // eslint-disable-line @typescript-eslint/no-explicit-any
93
- .join('\n');
108
+ }
109
+ // Check for errors from both context and query results
110
+ const contextErrors = (errors || []).filter((error)=>error !== null);
111
+ const allErrors = [
112
+ ...contextErrors,
113
+ ...queryErrors.map((q)=>q.error)
114
+ ].filter(Boolean);
115
+ if (allErrors.length > 0) {
116
+ const errorTexts = allErrors.map((e)=>{
117
+ if (typeof e === 'string') return e;
118
+ if (e && typeof e === 'object') {
119
+ const errorObj = e;
120
+ return errorObj.message ?? errorObj.toString?.() ?? 'Unknown error';
121
+ }
122
+ return 'Unknown error';
123
+ }).join('\n');
94
124
  return /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.InfoTooltip, {
95
125
  description: errorTexts,
96
126
  children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_HeaderIconButton.HeaderIconButton, {
@@ -103,7 +133,9 @@ const PanelActions = ({ editHandlers, readHandlers, extra, title, description, d
103
133
  });
104
134
  }
105
135
  }, [
106
- queryResults
136
+ queryResults,
137
+ isFetching,
138
+ errors
107
139
  ]);
108
140
  const readActions = (0, _react.useMemo)(()=>{
109
141
  if (readHandlers !== undefined) {
@@ -242,6 +274,7 @@ const PanelActions = ({ editHandlers, readHandlers, extra, title, description, d
242
274
  editActions
243
275
  ]
244
276
  }),
277
+ pluginActions,
245
278
  moveAction
246
279
  ]
247
280
  })
@@ -269,6 +302,8 @@ const PanelActions = ({ editHandlers, readHandlers, extra, title, description, d
269
302
  extraActions,
270
303
  " ",
271
304
  readActions,
305
+ " ",
306
+ pluginActions,
272
307
  /*#__PURE__*/ (0, _jsxruntime.jsx)(OverflowMenu, {
273
308
  title: title,
274
309
  children: editActions
@@ -303,6 +338,8 @@ const PanelActions = ({ editHandlers, readHandlers, extra, title, description, d
303
338
  " ",
304
339
  readActions,
305
340
  " ",
341
+ pluginActions,
342
+ " ",
306
343
  editActions,
307
344
  " ",
308
345
  moveAction
@@ -24,13 +24,20 @@ const _jsxruntime = require("react/jsx-runtime");
24
24
  const _material = require("@mui/material");
25
25
  const _components = require("@perses-dev/components");
26
26
  const _pluginsystem = require("@perses-dev/plugin-system");
27
+ const _react = require("react");
27
28
  const _constants = require("../../constants");
28
29
  const _PanelActions = require("./PanelActions");
29
- function PanelHeader({ id, title: rawTitle, description: rawDescription, links, queryResults, readHandlers, editHandlers, sx, extra, ...rest }) {
30
+ function PanelHeader({ id, title: rawTitle, description: rawDescription, links, queryResults, readHandlers, editHandlers, sx, extra, pluginActions, ...rest }) {
30
31
  const titleElementId = `${id}-title`;
31
32
  const descriptionTooltipId = `${id}-description`;
32
33
  const title = (0, _pluginsystem.useReplaceVariablesInString)(rawTitle);
33
34
  const description = (0, _pluginsystem.useReplaceVariablesInString)(rawDescription);
35
+ // Create the panelContentProps object with only queryResults
36
+ const panelContentProps = (0, _react.useMemo)(()=>({
37
+ queryResults
38
+ }), [
39
+ queryResults
40
+ ]);
34
41
  return /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.CardHeader, {
35
42
  id: id,
36
43
  component: "header",
@@ -59,10 +66,11 @@ function PanelHeader({ id, title: rawTitle, description: rawDescription, links,
59
66
  description: description,
60
67
  descriptionTooltipId: descriptionTooltipId,
61
68
  links: links,
62
- queryResults: queryResults,
63
69
  readHandlers: readHandlers,
64
70
  editHandlers: editHandlers,
65
- extra: extra
71
+ extra: extra,
72
+ panelContentProps: panelContentProps,
73
+ pluginActions: pluginActions
66
74
  })
67
75
  ]
68
76
  }),
@@ -31,11 +31,8 @@ const SaveChangesConfirmationDialog = ()=>{
31
31
  const { saveChangesConfirmationDialog: dialog } = (0, _context.useSaveChangesConfirmationDialog)();
32
32
  const isSavedDurationModified = dialog?.isSavedDurationModified ?? true;
33
33
  const isSavedVariableModified = dialog?.isSavedVariableModified ?? true;
34
- const isSavedTimeZoneModified = dialog?.isSavedTimeZoneModified ?? true;
35
34
  const [saveDefaultTimeRange, setSaveDefaultTimeRange] = (0, _react.useState)(isSavedDurationModified);
36
35
  const [saveDefaultVariables, setSaveDefaultVariables] = (0, _react.useState)(isSavedVariableModified);
37
- const [saveDefaultTimeZone, setSaveDefaultTimeZone] = (0, _react.useState)(isSavedTimeZoneModified);
38
- const { timeZone } = (0, _pluginsystem.useTimeZone)();
39
36
  const { getSavedVariablesStatus } = (0, _context.useVariableDefinitionActions)();
40
37
  const { modifiedVariableNames } = getSavedVariablesStatus();
41
38
  const isOpen = dialog !== undefined;
@@ -43,7 +40,6 @@ const SaveChangesConfirmationDialog = ()=>{
43
40
  const currentTimeRangeText = (0, _core.isRelativeTimeRange)(timeRange) ? `(Last ${timeRange.pastDuration})` : '(Absolute time ranges can not be saved)';
44
41
  const saveTimeRangeText = `Save current time range as new default ${currentTimeRangeText}`;
45
42
  const saveVariablesText = `Save current variable values as new default (${modifiedVariableNames.length > 0 ? modifiedVariableNames.join(', ') : 'No modified variables'})`;
46
- const saveTimeZoneText = `Save time zone as "${timeZone}" time`;
47
43
  return /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.Dialog, {
48
44
  open: isOpen,
49
45
  children: dialog !== undefined && /*#__PURE__*/ (0, _jsxruntime.jsxs)(_jsxruntime.Fragment, {
@@ -75,14 +71,6 @@ const SaveChangesConfirmationDialog = ()=>{
75
71
  onChange: (e)=>setSaveDefaultVariables(e.target.checked)
76
72
  }),
77
73
  label: saveVariablesText
78
- }),
79
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.FormControlLabel, {
80
- control: /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Checkbox, {
81
- disabled: !isSavedTimeZoneModified,
82
- checked: saveDefaultTimeZone && isSavedTimeZoneModified,
83
- onChange: (e)=>setSaveDefaultTimeZone(e.target.checked)
84
- }),
85
- label: saveTimeZoneText
86
74
  })
87
75
  ]
88
76
  })
@@ -92,7 +80,7 @@ const SaveChangesConfirmationDialog = ()=>{
92
80
  children: [
93
81
  /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.Dialog.PrimaryButton, {
94
82
  onClick: ()=>{
95
- return dialog.onSaveChanges(saveDefaultTimeRange, saveDefaultVariables, saveDefaultTimeZone);
83
+ return dialog.onSaveChanges(saveDefaultTimeRange, saveDefaultVariables);
96
84
  },
97
85
  children: "Save Changes"
98
86
  }),