@perses-dev/dashboards 0.50.1 → 0.51.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (189) hide show
  1. package/dist/cjs/components/Dashboard/Dashboard.js +1 -3
  2. package/dist/cjs/components/DashboardToolbar/DashboardToolbar.js +3 -3
  3. package/dist/cjs/components/Datasources/DatasourceEditor.js +2 -5
  4. package/dist/cjs/components/Datasources/EditDatasourcesButton.js +2 -5
  5. package/dist/cjs/components/DeletePanelDialog/DeletePanelDialog.js +2 -0
  6. package/dist/cjs/components/DeletePanelGroupDialog/DeletePanelGroupDialog.js +4 -3
  7. package/dist/cjs/components/DownloadButton/DownloadButton.js +135 -29
  8. package/dist/cjs/components/EditJsonDialog/EditJsonDialog.js +5 -7
  9. package/dist/cjs/components/EmptyDashboard/EmptyDashboard.js +1 -1
  10. package/dist/cjs/components/GridLayout/GridItemContent.js +4 -3
  11. package/dist/cjs/components/GridLayout/GridLayout.js +5 -6
  12. package/dist/cjs/components/GridLayout/GridTitle.js +3 -3
  13. package/dist/cjs/components/Panel/HeaderIconButton.js +27 -0
  14. package/dist/cjs/components/Panel/Panel.js +16 -10
  15. package/dist/cjs/components/Panel/PanelActions.js +365 -0
  16. package/dist/cjs/components/Panel/PanelContent.js +59 -13
  17. package/dist/cjs/components/Panel/PanelHeader.js +14 -141
  18. package/dist/cjs/components/Panel/PanelLinks.js +5 -6
  19. package/dist/cjs/components/Panel/PanelPluginLoader.js +56 -0
  20. package/dist/cjs/components/Panel/index.js +1 -0
  21. package/dist/cjs/components/PanelDrawer/PanelDrawer.js +9 -6
  22. package/dist/cjs/components/PanelDrawer/PanelEditorForm.js +17 -35
  23. package/dist/cjs/components/PanelDrawer/PanelPreview.js +4 -5
  24. package/dist/cjs/components/PanelGroupDialog/PanelGroupDialog.js +1 -1
  25. package/dist/cjs/components/QuerySummaryTable/QuerySummaryTable.js +3 -5
  26. package/dist/cjs/components/SaveChangesConfirmationDialog/SaveChangesConfirmationDialog.js +2 -4
  27. package/dist/cjs/components/Variables/BuiltinVariableAccordions.js +5 -12
  28. package/dist/cjs/components/Variables/Variable.js +30 -36
  29. package/dist/cjs/components/Variables/VariableEditor.js +14 -23
  30. package/dist/cjs/components/Variables/VariableList.js +4 -6
  31. package/dist/cjs/constants/styles.js +12 -0
  32. package/dist/cjs/constants/user-interface-text.js +1 -1
  33. package/dist/cjs/context/DashboardProvider/DashboardProvider.js +5 -6
  34. package/dist/cjs/context/DashboardProvider/DashboardProviderWithQueryParams.js +1 -1
  35. package/dist/cjs/context/DashboardProvider/common.js +2 -2
  36. package/dist/cjs/context/DashboardProvider/dashboard-provider-api.js +13 -3
  37. package/dist/cjs/context/DashboardProvider/delete-panel-slice.js +1 -2
  38. package/dist/cjs/context/DashboardProvider/panel-editor-slice.js +3 -6
  39. package/dist/cjs/context/DashboardProvider/panel-group-editor-slice.js +1 -2
  40. package/dist/cjs/context/DashboardProvider/panel-group-slice.js +3 -4
  41. package/dist/cjs/context/DashboardProvider/view-panel-slice.js +1 -2
  42. package/dist/cjs/context/DatasourceStoreProvider.js +15 -22
  43. package/dist/cjs/context/VariableProvider/VariableProvider.js +8 -11
  44. package/dist/cjs/context/VariableProvider/hydrationUtils.js +3 -6
  45. package/dist/cjs/context/VariableProvider/utils.js +2 -2
  46. package/dist/cjs/stories/decorators/WithDashboard.js +1 -1
  47. package/dist/cjs/stories/decorators/WithDatasourceStore.js +1 -1
  48. package/dist/cjs/stories/decorators/WithVariables.js +1 -1
  49. package/dist/cjs/test/plugin-registry.js +8 -3
  50. package/dist/cjs/test/render.js +13 -11
  51. package/dist/cjs/views/ViewDashboard/DashboardApp.js +4 -3
  52. package/dist/cjs/views/ViewDashboard/ViewDashboard.js +5 -5
  53. package/dist/components/Dashboard/Dashboard.js +1 -3
  54. package/dist/components/Dashboard/Dashboard.js.map +1 -1
  55. package/dist/components/DashboardToolbar/DashboardToolbar.d.ts +2 -0
  56. package/dist/components/DashboardToolbar/DashboardToolbar.d.ts.map +1 -1
  57. package/dist/components/DashboardToolbar/DashboardToolbar.js +3 -3
  58. package/dist/components/DashboardToolbar/DashboardToolbar.js.map +1 -1
  59. package/dist/components/Datasources/DatasourceEditor.js +2 -5
  60. package/dist/components/Datasources/DatasourceEditor.js.map +1 -1
  61. package/dist/components/Datasources/EditDatasourcesButton.js +2 -5
  62. package/dist/components/Datasources/EditDatasourcesButton.js.map +1 -1
  63. package/dist/components/DeletePanelDialog/DeletePanelDialog.js +3 -1
  64. package/dist/components/DeletePanelDialog/DeletePanelDialog.js.map +1 -1
  65. package/dist/components/DeletePanelGroupDialog/DeletePanelGroupDialog.d.ts.map +1 -1
  66. package/dist/components/DeletePanelGroupDialog/DeletePanelGroupDialog.js +5 -4
  67. package/dist/components/DeletePanelGroupDialog/DeletePanelGroupDialog.js.map +1 -1
  68. package/dist/components/DownloadButton/DownloadButton.d.ts +1 -5
  69. package/dist/components/DownloadButton/DownloadButton.d.ts.map +1 -1
  70. package/dist/components/DownloadButton/DownloadButton.js +94 -29
  71. package/dist/components/DownloadButton/DownloadButton.js.map +1 -1
  72. package/dist/components/EditJsonDialog/EditJsonDialog.js +5 -7
  73. package/dist/components/EditJsonDialog/EditJsonDialog.js.map +1 -1
  74. package/dist/components/EmptyDashboard/EmptyDashboard.js +1 -1
  75. package/dist/components/EmptyDashboard/EmptyDashboard.js.map +1 -1
  76. package/dist/components/GridLayout/GridItemContent.d.ts.map +1 -1
  77. package/dist/components/GridLayout/GridItemContent.js +5 -4
  78. package/dist/components/GridLayout/GridItemContent.js.map +1 -1
  79. package/dist/components/GridLayout/GridLayout.js +6 -7
  80. package/dist/components/GridLayout/GridLayout.js.map +1 -1
  81. package/dist/components/GridLayout/GridTitle.js +3 -3
  82. package/dist/components/GridLayout/GridTitle.js.map +1 -1
  83. package/dist/components/Panel/HeaderIconButton.d.ts +5 -0
  84. package/dist/components/Panel/HeaderIconButton.d.ts.map +1 -0
  85. package/dist/components/Panel/HeaderIconButton.js +19 -0
  86. package/dist/components/Panel/HeaderIconButton.js.map +1 -0
  87. package/dist/components/Panel/Panel.d.ts +7 -2
  88. package/dist/components/Panel/Panel.d.ts.map +1 -1
  89. package/dist/components/Panel/Panel.js +22 -11
  90. package/dist/components/Panel/Panel.js.map +1 -1
  91. package/dist/components/Panel/PanelActions.d.ts +22 -0
  92. package/dist/components/Panel/PanelActions.d.ts.map +1 -0
  93. package/dist/components/Panel/PanelActions.js +352 -0
  94. package/dist/components/Panel/PanelActions.js.map +1 -0
  95. package/dist/components/Panel/PanelContent.d.ts +5 -4
  96. package/dist/components/Panel/PanelContent.d.ts.map +1 -1
  97. package/dist/components/Panel/PanelContent.js +61 -15
  98. package/dist/components/Panel/PanelContent.js.map +1 -1
  99. package/dist/components/Panel/PanelHeader.d.ts +7 -11
  100. package/dist/components/Panel/PanelHeader.d.ts.map +1 -1
  101. package/dist/components/Panel/PanelHeader.js +18 -140
  102. package/dist/components/Panel/PanelHeader.js.map +1 -1
  103. package/dist/components/Panel/PanelLinks.js +5 -6
  104. package/dist/components/Panel/PanelLinks.js.map +1 -1
  105. package/dist/components/Panel/PanelPluginLoader.d.ts +13 -0
  106. package/dist/components/Panel/PanelPluginLoader.d.ts.map +1 -0
  107. package/dist/components/Panel/PanelPluginLoader.js +51 -0
  108. package/dist/components/Panel/PanelPluginLoader.js.map +1 -0
  109. package/dist/components/Panel/index.d.ts +1 -0
  110. package/dist/components/Panel/index.d.ts.map +1 -1
  111. package/dist/components/Panel/index.js +1 -0
  112. package/dist/components/Panel/index.js.map +1 -1
  113. package/dist/components/PanelDrawer/PanelDrawer.d.ts.map +1 -1
  114. package/dist/components/PanelDrawer/PanelDrawer.js +10 -7
  115. package/dist/components/PanelDrawer/PanelDrawer.js.map +1 -1
  116. package/dist/components/PanelDrawer/PanelEditorForm.js +17 -35
  117. package/dist/components/PanelDrawer/PanelEditorForm.js.map +1 -1
  118. package/dist/components/PanelDrawer/PanelPreview.js +4 -5
  119. package/dist/components/PanelDrawer/PanelPreview.js.map +1 -1
  120. package/dist/components/PanelGroupDialog/PanelGroupDialog.js +1 -1
  121. package/dist/components/PanelGroupDialog/PanelGroupDialog.js.map +1 -1
  122. package/dist/components/QuerySummaryTable/QuerySummaryTable.js +3 -5
  123. package/dist/components/QuerySummaryTable/QuerySummaryTable.js.map +1 -1
  124. package/dist/components/SaveChangesConfirmationDialog/SaveChangesConfirmationDialog.js +2 -4
  125. package/dist/components/SaveChangesConfirmationDialog/SaveChangesConfirmationDialog.js.map +1 -1
  126. package/dist/components/Variables/BuiltinVariableAccordions.js +5 -12
  127. package/dist/components/Variables/BuiltinVariableAccordions.js.map +1 -1
  128. package/dist/components/Variables/Variable.js +30 -36
  129. package/dist/components/Variables/Variable.js.map +1 -1
  130. package/dist/components/Variables/VariableEditor.js +14 -23
  131. package/dist/components/Variables/VariableEditor.js.map +1 -1
  132. package/dist/components/Variables/VariableList.js +4 -6
  133. package/dist/components/Variables/VariableList.js.map +1 -1
  134. package/dist/constants/styles.d.ts +3 -0
  135. package/dist/constants/styles.d.ts.map +1 -1
  136. package/dist/constants/styles.js +3 -0
  137. package/dist/constants/styles.js.map +1 -1
  138. package/dist/constants/user-interface-text.d.ts +1 -1
  139. package/dist/constants/user-interface-text.d.ts.map +1 -1
  140. package/dist/constants/user-interface-text.js +1 -1
  141. package/dist/constants/user-interface-text.js.map +1 -1
  142. package/dist/context/DashboardProvider/DashboardProvider.js +5 -6
  143. package/dist/context/DashboardProvider/DashboardProvider.js.map +1 -1
  144. package/dist/context/DashboardProvider/DashboardProviderWithQueryParams.js +1 -1
  145. package/dist/context/DashboardProvider/DashboardProviderWithQueryParams.js.map +1 -1
  146. package/dist/context/DashboardProvider/common.js +2 -2
  147. package/dist/context/DashboardProvider/common.js.map +1 -1
  148. package/dist/context/DashboardProvider/dashboard-provider-api.d.ts +11 -2
  149. package/dist/context/DashboardProvider/dashboard-provider-api.d.ts.map +1 -1
  150. package/dist/context/DashboardProvider/dashboard-provider-api.js +13 -4
  151. package/dist/context/DashboardProvider/dashboard-provider-api.js.map +1 -1
  152. package/dist/context/DashboardProvider/delete-panel-slice.js +1 -2
  153. package/dist/context/DashboardProvider/delete-panel-slice.js.map +1 -1
  154. package/dist/context/DashboardProvider/panel-editor-slice.js +3 -6
  155. package/dist/context/DashboardProvider/panel-editor-slice.js.map +1 -1
  156. package/dist/context/DashboardProvider/panel-group-editor-slice.js +1 -2
  157. package/dist/context/DashboardProvider/panel-group-editor-slice.js.map +1 -1
  158. package/dist/context/DashboardProvider/panel-group-slice.js +3 -4
  159. package/dist/context/DashboardProvider/panel-group-slice.js.map +1 -1
  160. package/dist/context/DashboardProvider/view-panel-slice.js +1 -2
  161. package/dist/context/DashboardProvider/view-panel-slice.js.map +1 -1
  162. package/dist/context/DatasourceStoreProvider.js +15 -22
  163. package/dist/context/DatasourceStoreProvider.js.map +1 -1
  164. package/dist/context/VariableProvider/VariableProvider.js +8 -11
  165. package/dist/context/VariableProvider/VariableProvider.js.map +1 -1
  166. package/dist/context/VariableProvider/hydrationUtils.js +3 -6
  167. package/dist/context/VariableProvider/hydrationUtils.js.map +1 -1
  168. package/dist/context/VariableProvider/utils.js +2 -2
  169. package/dist/context/VariableProvider/utils.js.map +1 -1
  170. package/dist/stories/decorators/WithDashboard.js +1 -1
  171. package/dist/stories/decorators/WithDashboard.js.map +1 -1
  172. package/dist/stories/decorators/WithDatasourceStore.js +1 -1
  173. package/dist/stories/decorators/WithDatasourceStore.js.map +1 -1
  174. package/dist/stories/decorators/WithVariables.js +1 -1
  175. package/dist/stories/decorators/WithVariables.js.map +1 -1
  176. package/dist/test/plugin-registry.d.ts.map +1 -1
  177. package/dist/test/plugin-registry.js +8 -3
  178. package/dist/test/plugin-registry.js.map +1 -1
  179. package/dist/test/render.d.ts.map +1 -1
  180. package/dist/test/render.js +9 -7
  181. package/dist/test/render.js.map +1 -1
  182. package/dist/views/ViewDashboard/DashboardApp.d.ts +2 -0
  183. package/dist/views/ViewDashboard/DashboardApp.d.ts.map +1 -1
  184. package/dist/views/ViewDashboard/DashboardApp.js +4 -3
  185. package/dist/views/ViewDashboard/DashboardApp.js.map +1 -1
  186. package/dist/views/ViewDashboard/ViewDashboard.d.ts.map +1 -1
  187. package/dist/views/ViewDashboard/ViewDashboard.js +5 -5
  188. package/dist/views/ViewDashboard/ViewDashboard.js.map +1 -1
  189. package/package.json +8 -7
@@ -0,0 +1,365 @@
1
+ // Copyright 2025 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, "PanelActions", {
18
+ enumerable: true,
19
+ get: function() {
20
+ return PanelActions;
21
+ }
22
+ });
23
+ const _jsxruntime = require("react/jsx-runtime");
24
+ const _material = require("@mui/material");
25
+ const _react = require("react");
26
+ const _components = require("@perses-dev/components");
27
+ const _ArrowCollapse = /*#__PURE__*/ _interop_require_default(require("mdi-material-ui/ArrowCollapse"));
28
+ const _ArrowExpand = /*#__PURE__*/ _interop_require_default(require("mdi-material-ui/ArrowExpand"));
29
+ const _PencilOutline = /*#__PURE__*/ _interop_require_default(require("mdi-material-ui/PencilOutline"));
30
+ const _DeleteOutline = /*#__PURE__*/ _interop_require_default(require("mdi-material-ui/DeleteOutline"));
31
+ const _DragVertical = /*#__PURE__*/ _interop_require_default(require("mdi-material-ui/DragVertical"));
32
+ const _ContentCopy = /*#__PURE__*/ _interop_require_default(require("mdi-material-ui/ContentCopy"));
33
+ const _Menu = /*#__PURE__*/ _interop_require_default(require("mdi-material-ui/Menu"));
34
+ const _Alert = /*#__PURE__*/ _interop_require_default(require("mdi-material-ui/Alert"));
35
+ const _InformationOutline = /*#__PURE__*/ _interop_require_default(require("mdi-material-ui/InformationOutline"));
36
+ const _constants = require("../../constants");
37
+ const _HeaderIconButton = require("./HeaderIconButton");
38
+ const _PanelLinks = require("./PanelLinks");
39
+ function _interop_require_default(obj) {
40
+ return obj && obj.__esModule ? obj : {
41
+ default: obj
42
+ };
43
+ }
44
+ const ConditionalBox = (0, _material.styled)(_material.Box)({
45
+ display: 'none',
46
+ alignItems: 'center',
47
+ flexGrow: 1,
48
+ justifyContent: 'flex-end'
49
+ });
50
+ const PanelActions = ({ editHandlers, readHandlers, extra, title, description, descriptionTooltipId, links, queryResults })=>{
51
+ const descriptionAction = (0, _react.useMemo)(()=>{
52
+ if (description && description.trim().length > 0) {
53
+ return /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.InfoTooltip, {
54
+ id: descriptionTooltipId,
55
+ description: description,
56
+ enterDelay: 100,
57
+ children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_HeaderIconButton.HeaderIconButton, {
58
+ "aria-label": "panel description",
59
+ size: "small",
60
+ children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_InformationOutline.default, {
61
+ "aria-describedby": "info-tooltip",
62
+ "aria-hidden": false,
63
+ fontSize: "inherit",
64
+ sx: {
65
+ color: (theme)=>theme.palette.text.secondary
66
+ }
67
+ })
68
+ })
69
+ });
70
+ }
71
+ return undefined;
72
+ }, [
73
+ descriptionTooltipId,
74
+ description
75
+ ]);
76
+ const linksAction = links && links.length > 0 && /*#__PURE__*/ (0, _jsxruntime.jsx)(_PanelLinks.PanelLinks, {
77
+ links: links
78
+ });
79
+ const extraActions = editHandlers === undefined && extra;
80
+ const queryStateIndicator = (0, _react.useMemo)(()=>{
81
+ const hasData = queryResults.some((q)=>q.data);
82
+ const isFetching = queryResults.some((q)=>q.isFetching);
83
+ const queryErrors = queryResults.filter((q)=>q.error);
84
+ if (isFetching && hasData) {
85
+ // If the panel has no data, the panel content will show the loading overlay.
86
+ // Therefore, show the circular loading indicator only in case the panel doesn't display the loading overlay already.
87
+ return /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.CircularProgress, {
88
+ "aria-label": "loading",
89
+ size: "1.125rem"
90
+ });
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');
94
+ return /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.InfoTooltip, {
95
+ description: errorTexts,
96
+ children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_HeaderIconButton.HeaderIconButton, {
97
+ "aria-label": "panel errors",
98
+ size: "small",
99
+ children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_Alert.default, {
100
+ fontSize: "inherit"
101
+ })
102
+ })
103
+ });
104
+ }
105
+ }, [
106
+ queryResults
107
+ ]);
108
+ const readActions = (0, _react.useMemo)(()=>{
109
+ if (readHandlers !== undefined) {
110
+ return /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.InfoTooltip, {
111
+ description: _constants.TOOLTIP_TEXT.viewPanel,
112
+ children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_HeaderIconButton.HeaderIconButton, {
113
+ "aria-label": _constants.ARIA_LABEL_TEXT.viewPanel(title),
114
+ size: "small",
115
+ onClick: readHandlers.onViewPanelClick,
116
+ children: readHandlers.isPanelViewed ? /*#__PURE__*/ (0, _jsxruntime.jsx)(_ArrowCollapse.default, {
117
+ fontSize: "inherit"
118
+ }) : /*#__PURE__*/ (0, _jsxruntime.jsx)(_ArrowExpand.default, {
119
+ fontSize: "inherit"
120
+ })
121
+ })
122
+ });
123
+ }
124
+ return undefined;
125
+ }, [
126
+ readHandlers,
127
+ title
128
+ ]);
129
+ const editActions = (0, _react.useMemo)(()=>{
130
+ if (editHandlers !== undefined) {
131
+ // If there are edit handlers, always just show the edit buttons
132
+ return /*#__PURE__*/ (0, _jsxruntime.jsxs)(_jsxruntime.Fragment, {
133
+ children: [
134
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.InfoTooltip, {
135
+ description: _constants.TOOLTIP_TEXT.editPanel,
136
+ children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_HeaderIconButton.HeaderIconButton, {
137
+ "aria-label": _constants.ARIA_LABEL_TEXT.editPanel(title),
138
+ size: "small",
139
+ onClick: editHandlers.onEditPanelClick,
140
+ children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_PencilOutline.default, {
141
+ fontSize: "inherit"
142
+ })
143
+ })
144
+ }),
145
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.InfoTooltip, {
146
+ description: _constants.TOOLTIP_TEXT.duplicatePanel,
147
+ children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_HeaderIconButton.HeaderIconButton, {
148
+ "aria-label": _constants.ARIA_LABEL_TEXT.duplicatePanel(title),
149
+ size: "small",
150
+ onClick: editHandlers.onDuplicatePanelClick,
151
+ children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_ContentCopy.default, {
152
+ fontSize: "inherit",
153
+ sx: {
154
+ // Shrink this icon a little bit to look more consistent
155
+ // with the other icons in the header.
156
+ transform: 'scale(0.925)'
157
+ }
158
+ })
159
+ })
160
+ }),
161
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.InfoTooltip, {
162
+ description: _constants.TOOLTIP_TEXT.deletePanel,
163
+ children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_HeaderIconButton.HeaderIconButton, {
164
+ "aria-label": _constants.ARIA_LABEL_TEXT.deletePanel(title),
165
+ size: "small",
166
+ onClick: editHandlers.onDeletePanelClick,
167
+ children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_DeleteOutline.default, {
168
+ fontSize: "inherit"
169
+ })
170
+ })
171
+ })
172
+ ]
173
+ });
174
+ }
175
+ return undefined;
176
+ }, [
177
+ editHandlers,
178
+ title
179
+ ]);
180
+ const moveAction = (0, _react.useMemo)(()=>{
181
+ if (editActions && !readHandlers?.isPanelViewed) {
182
+ return /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.InfoTooltip, {
183
+ description: _constants.TOOLTIP_TEXT.movePanel,
184
+ children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_HeaderIconButton.HeaderIconButton, {
185
+ "aria-label": _constants.ARIA_LABEL_TEXT.movePanel(title),
186
+ size: "small",
187
+ children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_DragVertical.default, {
188
+ className: "drag-handle",
189
+ sx: {
190
+ cursor: 'grab'
191
+ },
192
+ fontSize: "inherit"
193
+ })
194
+ })
195
+ });
196
+ }
197
+ return undefined;
198
+ }, [
199
+ editActions,
200
+ readHandlers,
201
+ title
202
+ ]);
203
+ const divider = /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Box, {
204
+ sx: {
205
+ flexGrow: 1
206
+ }
207
+ });
208
+ // if the panel is in non-editing, non-fullscreen mode, show certain icons only on hover
209
+ const OnHover = ({ children })=>editHandlers === undefined && !readHandlers?.isPanelViewed ? /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Box, {
210
+ sx: {
211
+ display: 'var(--panel-hover, none)'
212
+ },
213
+ children: children
214
+ }) : /*#__PURE__*/ (0, _jsxruntime.jsx)(_jsxruntime.Fragment, {
215
+ children: children
216
+ });
217
+ return /*#__PURE__*/ (0, _jsxruntime.jsxs)(_jsxruntime.Fragment, {
218
+ children: [
219
+ /*#__PURE__*/ (0, _jsxruntime.jsxs)(ConditionalBox, {
220
+ sx: (theme)=>({
221
+ [theme.containerQueries(_constants.HEADER_ACTIONS_CONTAINER_NAME).between(0, _constants.HEADER_SMALL_WIDTH)]: {
222
+ display: 'flex'
223
+ }
224
+ }),
225
+ children: [
226
+ divider,
227
+ /*#__PURE__*/ (0, _jsxruntime.jsxs)(OnHover, {
228
+ children: [
229
+ /*#__PURE__*/ (0, _jsxruntime.jsxs)(OverflowMenu, {
230
+ title: title,
231
+ children: [
232
+ descriptionAction,
233
+ " ",
234
+ linksAction,
235
+ " ",
236
+ queryStateIndicator,
237
+ " ",
238
+ extraActions,
239
+ " ",
240
+ readActions,
241
+ " ",
242
+ editActions
243
+ ]
244
+ }),
245
+ moveAction
246
+ ]
247
+ })
248
+ ]
249
+ }),
250
+ /*#__PURE__*/ (0, _jsxruntime.jsxs)(ConditionalBox, {
251
+ sx: (theme)=>({
252
+ [theme.containerQueries(_constants.HEADER_ACTIONS_CONTAINER_NAME).between(_constants.HEADER_SMALL_WIDTH, _constants.HEADER_MEDIUM_WIDTH)]: {
253
+ display: 'flex'
254
+ }
255
+ }),
256
+ children: [
257
+ /*#__PURE__*/ (0, _jsxruntime.jsxs)(OnHover, {
258
+ children: [
259
+ descriptionAction,
260
+ " ",
261
+ linksAction
262
+ ]
263
+ }),
264
+ divider,
265
+ " ",
266
+ queryStateIndicator,
267
+ /*#__PURE__*/ (0, _jsxruntime.jsxs)(OnHover, {
268
+ children: [
269
+ extraActions,
270
+ " ",
271
+ readActions,
272
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(OverflowMenu, {
273
+ title: title,
274
+ children: editActions
275
+ }),
276
+ moveAction
277
+ ]
278
+ })
279
+ ]
280
+ }),
281
+ /*#__PURE__*/ (0, _jsxruntime.jsxs)(ConditionalBox, {
282
+ sx: (theme)=>({
283
+ // flip the logic here; if the browser (or jsdom) does not support container queries, always show all icons
284
+ display: 'flex',
285
+ [theme.containerQueries(_constants.HEADER_ACTIONS_CONTAINER_NAME).down(_constants.HEADER_MEDIUM_WIDTH)]: {
286
+ display: 'none'
287
+ }
288
+ }),
289
+ children: [
290
+ /*#__PURE__*/ (0, _jsxruntime.jsxs)(OnHover, {
291
+ children: [
292
+ descriptionAction,
293
+ " ",
294
+ linksAction
295
+ ]
296
+ }),
297
+ divider,
298
+ " ",
299
+ queryStateIndicator,
300
+ /*#__PURE__*/ (0, _jsxruntime.jsxs)(OnHover, {
301
+ children: [
302
+ extraActions,
303
+ " ",
304
+ readActions,
305
+ " ",
306
+ editActions,
307
+ " ",
308
+ moveAction
309
+ ]
310
+ })
311
+ ]
312
+ })
313
+ ]
314
+ });
315
+ };
316
+ const OverflowMenu = ({ children, title })=>{
317
+ const [anchorPosition, setAnchorPosition] = (0, _react.useState)();
318
+ // do not show overflow menu if there is no content (for example, edit actions are hidden)
319
+ const hasContent = /*#__PURE__*/ (0, _react.isValidElement)(children) || Array.isArray(children) && children.some(_react.isValidElement);
320
+ if (!hasContent) {
321
+ return undefined;
322
+ }
323
+ const handleClick = (event)=>{
324
+ setAnchorPosition(event.currentTarget.getBoundingClientRect());
325
+ };
326
+ const handleClose = ()=>{
327
+ setAnchorPosition(undefined);
328
+ };
329
+ const open = Boolean(anchorPosition);
330
+ const id = open ? 'actions-menu' : undefined;
331
+ return /*#__PURE__*/ (0, _jsxruntime.jsxs)(_jsxruntime.Fragment, {
332
+ children: [
333
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_HeaderIconButton.HeaderIconButton, {
334
+ className: "show-actions",
335
+ "aria-describedby": id,
336
+ onClick: handleClick,
337
+ "aria-label": _constants.ARIA_LABEL_TEXT.showPanelActions(title),
338
+ size: "small",
339
+ children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_Menu.default, {
340
+ fontSize: "inherit"
341
+ })
342
+ }),
343
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Popover, {
344
+ id: id,
345
+ open: open,
346
+ anchorReference: "anchorPosition",
347
+ anchorPosition: anchorPosition,
348
+ onClose: handleClose,
349
+ anchorOrigin: {
350
+ vertical: 'bottom',
351
+ horizontal: 'left'
352
+ },
353
+ children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Stack, {
354
+ direction: "row",
355
+ alignItems: "center",
356
+ sx: {
357
+ padding: 1
358
+ },
359
+ onClick: handleClose,
360
+ children: children
361
+ })
362
+ })
363
+ ]
364
+ });
365
+ };
@@ -22,27 +22,73 @@ Object.defineProperty(exports, "PanelContent", {
22
22
  });
23
23
  const _jsxruntime = require("react/jsx-runtime");
24
24
  const _pluginsystem = require("@perses-dev/plugin-system");
25
+ const _components = require("@perses-dev/components");
25
26
  const _material = require("@mui/material");
27
+ const _PanelPluginLoader = require("./PanelPluginLoader");
26
28
  function PanelContent(props) {
27
- const { panelPluginKind, contentDimensions, definition, ...others } = props;
28
- const { data: plugin, isLoading } = (0, _pluginsystem.usePlugin)('Panel', panelPluginKind, {
29
- useErrorBoundary: true
29
+ const { panelPluginKind, definition, queryResults, spec, contentDimensions } = props;
30
+ const { data: plugin, isLoading: isPanelLoading } = (0, _pluginsystem.usePlugin)('Panel', panelPluginKind, {
31
+ throwOnError: true
30
32
  });
31
- const PanelComponent = plugin === null || plugin === void 0 ? void 0 : plugin.PanelComponent;
32
- if (isLoading) {
33
+ // Show fullsize skeleton if the panel plugin is loading.
34
+ if (isPanelLoading) {
33
35
  return /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Skeleton, {
34
36
  variant: "rectangular",
35
- width: contentDimensions === null || contentDimensions === void 0 ? void 0 : contentDimensions.width,
36
- height: contentDimensions === null || contentDimensions === void 0 ? void 0 : contentDimensions.height,
37
+ width: contentDimensions?.width,
38
+ height: contentDimensions?.height,
37
39
  "aria-label": "Loading..."
38
40
  });
39
41
  }
40
- if (PanelComponent === undefined) {
41
- throw new Error(`Missing PanelComponent from panel plugin for kind '${panelPluginKind}'`);
42
+ // Render the panel if any query has data, or the panel doesn't have a query attached (for example MarkdownPanel).
43
+ // Loading indicator or errors of other queries are shown in the panel header.
44
+ const queryResultsWithData = queryResults.flatMap((q)=>q.data ? [
45
+ {
46
+ data: q.data,
47
+ definition: q.definition
48
+ }
49
+ ] : []);
50
+ if (queryResultsWithData.length > 0 || queryResults.length === 0) {
51
+ return /*#__PURE__*/ (0, _jsxruntime.jsx)(_PanelPluginLoader.PanelPluginLoader, {
52
+ kind: panelPluginKind,
53
+ spec: spec,
54
+ contentDimensions: contentDimensions,
55
+ definition: definition,
56
+ queryResults: queryResultsWithData
57
+ });
58
+ }
59
+ // No query has data, show loading overlay if any query is fetching data.
60
+ if (queryResults.some((q)=>q.isFetching)) {
61
+ return /*#__PURE__*/ (0, _jsxruntime.jsx)(PanelLoading, {
62
+ plugin: plugin,
63
+ spec: spec,
64
+ definition: definition,
65
+ contentDimensions: contentDimensions
66
+ });
67
+ }
68
+ // No query has data or is loading, show the error if any query has an error.
69
+ // The error will be catched in <ErrorBoundary> of <Panel>.
70
+ const queryError = queryResults.find((q)=>q.error);
71
+ if (queryError) {
72
+ throw queryError.error;
42
73
  }
43
- return /*#__PURE__*/ (0, _jsxruntime.jsx)(PanelComponent, {
44
- ...others,
45
- contentDimensions: contentDimensions,
46
- definition: definition
74
+ // At this point, one or more queries are defined, but no query has data, is loading, or has an error.
75
+ // This can happen if all queries are disabled (e.g. dependent dashboard variables are loading, or they are not in the viewport of the browser).
76
+ // Most likely, some query will be enabled later. Render the panel loading skeleton.
77
+ return /*#__PURE__*/ (0, _jsxruntime.jsx)(PanelLoading, {
78
+ plugin: plugin,
79
+ spec: spec,
80
+ definition: definition,
81
+ contentDimensions: contentDimensions
47
82
  });
48
83
  }
84
+ function PanelLoading({ plugin, spec, definition, contentDimensions }) {
85
+ if (plugin?.LoadingComponent) {
86
+ return /*#__PURE__*/ (0, _jsxruntime.jsx)(plugin.LoadingComponent, {
87
+ spec: spec,
88
+ contentDimensions: contentDimensions,
89
+ definition: definition,
90
+ queryResults: []
91
+ });
92
+ }
93
+ return /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.LoadingOverlay, {});
94
+ }
@@ -1,4 +1,4 @@
1
- // Copyright 2023 The Perses Authors
1
+ // Copyright 2025 The Perses Authors
2
2
  // Licensed under the Apache License, Version 2.0 (the "License");
3
3
  // you may not use this file except in compliance with the License.
4
4
  // You may obtain a copy of the License at
@@ -23,102 +23,14 @@ Object.defineProperty(exports, "PanelHeader", {
23
23
  const _jsxruntime = require("react/jsx-runtime");
24
24
  const _material = require("@mui/material");
25
25
  const _components = require("@perses-dev/components");
26
- const _InformationOutline = /*#__PURE__*/ _interop_require_default(require("mdi-material-ui/InformationOutline"));
27
- const _PencilOutline = /*#__PURE__*/ _interop_require_default(require("mdi-material-ui/PencilOutline"));
28
- const _DeleteOutline = /*#__PURE__*/ _interop_require_default(require("mdi-material-ui/DeleteOutline"));
29
- const _DragVertical = /*#__PURE__*/ _interop_require_default(require("mdi-material-ui/DragVertical"));
30
- const _ArrowExpand = /*#__PURE__*/ _interop_require_default(require("mdi-material-ui/ArrowExpand"));
31
- const _ArrowCollapse = /*#__PURE__*/ _interop_require_default(require("mdi-material-ui/ArrowCollapse"));
32
- const _ContentCopy = /*#__PURE__*/ _interop_require_default(require("mdi-material-ui/ContentCopy"));
33
26
  const _pluginsystem = require("@perses-dev/plugin-system");
34
27
  const _constants = require("../../constants");
35
- const _PanelLinks = require("./PanelLinks");
36
- function _interop_require_default(obj) {
37
- return obj && obj.__esModule ? obj : {
38
- default: obj
39
- };
40
- }
41
- function PanelHeader({ id, title: rawTitle, description: rawDescription, links, readHandlers, editHandlers, sx, extra, ...rest }) {
28
+ const _PanelActions = require("./PanelActions");
29
+ function PanelHeader({ id, title: rawTitle, description: rawDescription, links, queryResults, readHandlers, editHandlers, sx, extra, ...rest }) {
42
30
  const titleElementId = `${id}-title`;
43
31
  const descriptionTooltipId = `${id}-description`;
44
32
  const title = (0, _pluginsystem.useReplaceVariablesInString)(rawTitle);
45
33
  const description = (0, _pluginsystem.useReplaceVariablesInString)(rawDescription);
46
- let readActions = undefined;
47
- if (readHandlers !== undefined) {
48
- readActions = /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.InfoTooltip, {
49
- description: _constants.TOOLTIP_TEXT.viewPanel,
50
- children: /*#__PURE__*/ (0, _jsxruntime.jsx)(HeaderIconButton, {
51
- "aria-label": _constants.ARIA_LABEL_TEXT.viewPanel(title),
52
- size: "small",
53
- onClick: readHandlers.onViewPanelClick,
54
- children: readHandlers.isPanelViewed ? /*#__PURE__*/ (0, _jsxruntime.jsx)(_ArrowCollapse.default, {
55
- fontSize: "inherit"
56
- }) : /*#__PURE__*/ (0, _jsxruntime.jsx)(_ArrowExpand.default, {
57
- fontSize: "inherit"
58
- })
59
- })
60
- });
61
- }
62
- let editActions = undefined;
63
- if (editHandlers !== undefined) {
64
- // If there are edit handlers, always just show the edit buttons
65
- editActions = /*#__PURE__*/ (0, _jsxruntime.jsxs)(_jsxruntime.Fragment, {
66
- children: [
67
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.InfoTooltip, {
68
- description: _constants.TOOLTIP_TEXT.editPanel,
69
- children: /*#__PURE__*/ (0, _jsxruntime.jsx)(HeaderIconButton, {
70
- "aria-label": _constants.ARIA_LABEL_TEXT.editPanel(title),
71
- size: "small",
72
- onClick: editHandlers.onEditPanelClick,
73
- children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_PencilOutline.default, {
74
- fontSize: "inherit"
75
- })
76
- })
77
- }),
78
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.InfoTooltip, {
79
- description: _constants.TOOLTIP_TEXT.duplicatePanel,
80
- children: /*#__PURE__*/ (0, _jsxruntime.jsx)(HeaderIconButton, {
81
- "aria-label": _constants.ARIA_LABEL_TEXT.duplicatePanel(title),
82
- size: "small",
83
- onClick: editHandlers.onDuplicatePanelClick,
84
- children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_ContentCopy.default, {
85
- fontSize: "inherit",
86
- sx: {
87
- // Shrink this icon a little bit to look more consistent
88
- // with the other icons in the header.
89
- transform: 'scale(0.925)'
90
- }
91
- })
92
- })
93
- }),
94
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.InfoTooltip, {
95
- description: _constants.TOOLTIP_TEXT.deletePanel,
96
- children: /*#__PURE__*/ (0, _jsxruntime.jsx)(HeaderIconButton, {
97
- "aria-label": _constants.ARIA_LABEL_TEXT.deletePanel(title),
98
- size: "small",
99
- onClick: editHandlers.onDeletePanelClick,
100
- children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_DeleteOutline.default, {
101
- fontSize: "inherit"
102
- })
103
- })
104
- }),
105
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.InfoTooltip, {
106
- description: _constants.TOOLTIP_TEXT.movePanel,
107
- children: /*#__PURE__*/ (0, _jsxruntime.jsx)(HeaderIconButton, {
108
- "aria-label": _constants.ARIA_LABEL_TEXT.movePanel(title),
109
- size: "small",
110
- children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_DragVertical.default, {
111
- className: "drag-handle",
112
- sx: {
113
- cursor: 'grab'
114
- },
115
- fontSize: "inherit"
116
- })
117
- })
118
- })
119
- ]
120
- });
121
- }
122
34
  return /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.CardHeader, {
123
35
  id: id,
124
36
  component: "header",
@@ -135,73 +47,34 @@ function PanelHeader({ id, title: rawTitle, description: rawDescription, links,
135
47
  // `minHeight` guarantees that the header has the correct height
136
48
  // when there is no title (i.e. in the preview)
137
49
  lineHeight: '24px',
138
- minHeight: '24px',
50
+ minHeight: '26px',
139
51
  whiteSpace: 'nowrap',
140
52
  overflow: 'hidden',
141
53
  textOverflow: 'ellipsis'
142
54
  },
143
55
  children: title
144
56
  }),
145
- description !== undefined && description.trim().length > 0 && /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.InfoTooltip, {
146
- id: descriptionTooltipId,
57
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_PanelActions.PanelActions, {
58
+ title: title,
147
59
  description: description,
148
- enterDelay: 100,
149
- children: /*#__PURE__*/ (0, _jsxruntime.jsx)(HeaderIconButton, {
150
- "aria-label": "panel description",
151
- size: "small",
152
- children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_InformationOutline.default, {
153
- "aria-describedby": "info-tooltip",
154
- "aria-hidden": false,
155
- fontSize: "inherit",
156
- sx: {
157
- color: (theme)=>theme.palette.text.secondary
158
- }
159
- })
160
- })
161
- }),
162
- links !== undefined && links.length > 0 && /*#__PURE__*/ (0, _jsxruntime.jsx)(_PanelLinks.PanelLinks, {
163
- links: links
60
+ descriptionTooltipId: descriptionTooltipId,
61
+ links: links,
62
+ queryResults: queryResults,
63
+ readHandlers: readHandlers,
64
+ editHandlers: editHandlers,
65
+ extra: extra
164
66
  })
165
67
  ]
166
68
  }),
167
- action: /*#__PURE__*/ (0, _jsxruntime.jsxs)(HeaderActionWrapper, {
168
- direction: "row",
169
- spacing: 0.25,
170
- alignItems: "center",
171
- children: [
172
- editHandlers === undefined && extra,
173
- " ",
174
- readActions,
175
- " ",
176
- editActions
177
- ]
178
- }),
179
69
  sx: (0, _components.combineSx)((theme)=>({
70
+ containerType: 'inline-size',
71
+ containerName: _constants.HEADER_ACTIONS_CONTAINER_NAME,
180
72
  padding: theme.spacing(1),
181
73
  borderBottom: `solid 1px ${theme.palette.divider}`,
182
74
  '.MuiCardHeader-content': {
183
75
  overflow: 'hidden'
184
- },
185
- '.MuiCardHeader-action': {
186
- // Overriding the negative margins from MUI's defaults, so we
187
- // can vertically center the icons. Moving these values to a wrapper
188
- // inside the action in `HeaderActionWrapper` below.
189
- // https://github.com/mui/material-ui/blob/master/packages/mui-material/src/CardHeader/CardHeader.js#L56-L58
190
- margin: 'auto'
191
76
  }
192
77
  }), sx),
193
78
  ...rest
194
79
  });
195
80
  }
196
- const HeaderIconButton = (0, _material.styled)(_material.IconButton)(({ theme })=>({
197
- borderRadius: theme.shape.borderRadius,
198
- padding: '4px'
199
- }));
200
- const HeaderActionWrapper = (0, _material.styled)(_material.Stack)(()=>({
201
- // Adding back the negative margins from MUI's defaults for actions, so we
202
- // avoid increasing the header size when actions are present while also being
203
- // able to vertically center the actions.
204
- // https://github.com/mui/material-ui/blob/master/packages/mui-material/src/CardHeader/CardHeader.js#L56-L58
205
- marginTop: -4,
206
- marginBottom: -4
207
- }));