@perses-dev/dashboards 0.0.0-snapshot-profile-89b306f → 0.0.0-snapshot-panel-actions-520389b

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 (28) hide show
  1. package/dist/cjs/components/Panel/Panel.js +60 -1
  2. package/dist/cjs/components/Panel/PanelActions.js +86 -16
  3. package/dist/cjs/components/Panel/PanelContent.js +1 -1
  4. package/dist/cjs/components/Panel/PanelHeader.js +47 -3
  5. package/dist/cjs/components/Panel/PanelPluginLoader.js +1 -1
  6. package/dist/cjs/components/PanelDrawer/PanelPreview.js +2 -2
  7. package/dist/cjs/components/QuerySummaryTable/QuerySummaryTable.js +1 -1
  8. package/dist/components/Panel/Panel.d.ts +5 -0
  9. package/dist/components/Panel/Panel.d.ts.map +1 -1
  10. package/dist/components/Panel/Panel.js +60 -1
  11. package/dist/components/Panel/Panel.js.map +1 -1
  12. package/dist/components/Panel/PanelActions.d.ts +5 -3
  13. package/dist/components/Panel/PanelActions.d.ts.map +1 -1
  14. package/dist/components/Panel/PanelActions.js +87 -17
  15. package/dist/components/Panel/PanelActions.js.map +1 -1
  16. package/dist/components/Panel/PanelContent.js +1 -1
  17. package/dist/components/Panel/PanelContent.js.map +1 -1
  18. package/dist/components/Panel/PanelHeader.d.ts +5 -1
  19. package/dist/components/Panel/PanelHeader.d.ts.map +1 -1
  20. package/dist/components/Panel/PanelHeader.js +47 -3
  21. package/dist/components/Panel/PanelHeader.js.map +1 -1
  22. package/dist/components/Panel/PanelPluginLoader.js +1 -1
  23. package/dist/components/Panel/PanelPluginLoader.js.map +1 -1
  24. package/dist/components/PanelDrawer/PanelPreview.js +2 -2
  25. package/dist/components/PanelDrawer/PanelPreview.js.map +1 -1
  26. package/dist/components/QuerySummaryTable/QuerySummaryTable.js +1 -1
  27. package/dist/components/QuerySummaryTable/QuerySummaryTable.js.map +1 -1
  28. package/package.json +6 -6
@@ -33,8 +33,41 @@ function _interop_require_default(obj) {
33
33
  default: obj
34
34
  };
35
35
  }
36
+ // Function to extract project name from URL (kept as fallback)
37
+ const extractProjectNameFromUrl = ()=>{
38
+ try {
39
+ if (process.env.NODE_ENV === 'test') {
40
+ return 'test-project';
41
+ }
42
+ if (typeof window !== 'undefined' && (window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1')) {
43
+ const urlPath = window.location.pathname;
44
+ if (urlPath === '/' || urlPath === '') {
45
+ return 'dev-project';
46
+ }
47
+ }
48
+ const urlPath = window.location.pathname;
49
+ // Split the path and look for the project name after "/projects/"
50
+ const pathSegments = urlPath.split('/').filter((segment)=>segment.length > 0);
51
+ const projectsIndex = pathSegments.findIndex((segment)=>segment === 'projects');
52
+ if (projectsIndex !== -1 && projectsIndex + 1 < pathSegments.length) {
53
+ const projectName = pathSegments[projectsIndex + 1];
54
+ if (projectName && projectName.trim().length > 0) {
55
+ return projectName;
56
+ }
57
+ }
58
+ // Fallback: try to extract from URL parameters
59
+ const urlParams = new URLSearchParams(window.location.search);
60
+ const projectParam = urlParams.get('project');
61
+ if (projectParam && projectParam.trim().length > 0) {
62
+ return projectParam;
63
+ }
64
+ return 'unknown-project';
65
+ } catch {
66
+ return 'unknown-project';
67
+ }
68
+ };
36
69
  const Panel = /*#__PURE__*/ (0, _react.memo)(function Panel(props) {
37
- const { definition, readHandlers, editHandlers, onMouseEnter, onMouseLeave, sx, panelOptions, panelGroupItemId, ...others } = props;
70
+ const { definition, readHandlers, editHandlers, onMouseEnter, onMouseLeave, sx, panelOptions, panelGroupItemId, projectName: providedProjectName, ...others } = props;
38
71
  // Make sure we have an ID we can use for aria attributes
39
72
  const generatedPanelId = (0, _components.useId)('Panel');
40
73
  const headerId = `${generatedPanelId}-header`;
@@ -54,6 +87,29 @@ const Panel = /*#__PURE__*/ (0, _react.memo)(function Panel(props) {
54
87
  ]);
55
88
  const chartsTheme = (0, _components.useChartsTheme)();
56
89
  const { queryResults } = (0, _pluginsystem.useDataQueriesContext)();
90
+ // Use provided project name or extract from URL as fallback
91
+ const projectName = (0, _react.useMemo)(()=>{
92
+ return providedProjectName || extractProjectNameFromUrl();
93
+ }, [
94
+ providedProjectName
95
+ ]);
96
+ const panelPropsForActions = (0, _react.useMemo)(()=>{
97
+ return {
98
+ spec: definition.spec.plugin.spec,
99
+ queryResults: queryResults.map((query)=>({
100
+ definition: query.definition,
101
+ data: query.data
102
+ })),
103
+ contentDimensions,
104
+ definition,
105
+ projectName
106
+ };
107
+ }, [
108
+ definition,
109
+ contentDimensions,
110
+ queryResults,
111
+ projectName
112
+ ]);
57
113
  const handleMouseEnter = (e)=>{
58
114
  onMouseEnter?.(e);
59
115
  };
@@ -88,9 +144,12 @@ const Panel = /*#__PURE__*/ (0, _react.memo)(function Panel(props) {
88
144
  title: definition.spec.display.name,
89
145
  description: definition.spec.display.description,
90
146
  queryResults: queryResults,
147
+ panelPluginKind: definition.spec.plugin.kind,
91
148
  readHandlers: readHandlers,
92
149
  editHandlers: editHandlers,
93
150
  links: definition.spec.links,
151
+ projectName: projectName,
152
+ panelProps: panelPropsForActions,
94
153
  sx: {
95
154
  paddingX: `${chartsTheme.container.padding.default}px`
96
155
  }
@@ -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,72 @@ 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, queryResults, panelPluginKind, projectName: _propsProjectName, panelProps })=>{
52
+ const { isFetching, errors } = (0, _pluginsystem.useDataQueriesContext)();
53
+ const { getPlugin } = (0, _pluginsystem.usePluginRegistry)();
54
+ const [pluginActions, setPluginActions] = (0, _react.useState)([]);
55
+ (0, _react.useEffect)(()=>{
56
+ let cancelled = false;
57
+ const loadPluginActions = async ()=>{
58
+ if (!panelPluginKind || !panelProps) {
59
+ if (!cancelled) {
60
+ setPluginActions([]);
61
+ }
62
+ return;
63
+ }
64
+ try {
65
+ // Add defensive check for getPlugin availability
66
+ if (!getPlugin || typeof getPlugin !== 'function') {
67
+ if (!cancelled) {
68
+ setPluginActions([]);
69
+ }
70
+ return;
71
+ }
72
+ const plugin = await getPlugin('Panel', panelPluginKind);
73
+ if (cancelled) return;
74
+ // More defensive checking for plugin and actions
75
+ if (!plugin || typeof plugin !== 'object' || !plugin.actions || !Array.isArray(plugin.actions) || plugin.actions.length === 0) {
76
+ if (!cancelled) {
77
+ setPluginActions([]);
78
+ }
79
+ return;
80
+ }
81
+ // Render plugin actions in header location
82
+ const headerActions = plugin.actions.filter((action)=>!action.location || action.location === 'header').map((action, index)=>{
83
+ const ActionComponent = action.component;
84
+ try {
85
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
86
+ return /*#__PURE__*/ (0, _jsxruntime.jsx)(ActionComponent, {
87
+ ...panelProps
88
+ }, `plugin-action-${index}`);
89
+ } catch (error) {
90
+ console.warn(`Failed to render plugin action ${index}:`, error);
91
+ return null;
92
+ }
93
+ }).filter((item)=>Boolean(item));
94
+ if (!cancelled) {
95
+ setPluginActions(headerActions);
96
+ }
97
+ } catch (error) {
98
+ if (!cancelled) {
99
+ console.warn('Failed to load plugin actions:', error);
100
+ setPluginActions([]);
101
+ }
102
+ }
103
+ };
104
+ // Use setTimeout to defer the async operation to the next tick
105
+ const timeoutId = setTimeout(()=>{
106
+ loadPluginActions();
107
+ }, 0);
108
+ return ()=>{
109
+ cancelled = true;
110
+ clearTimeout(timeoutId);
111
+ };
112
+ }, [
113
+ panelPluginKind,
114
+ panelProps,
115
+ getPlugin
116
+ ]);
51
117
  const descriptionAction = (0, _react.useMemo)(()=>{
52
118
  if (description && description.trim().length > 0) {
53
119
  return /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.InfoTooltip, {
@@ -78,19 +144,23 @@ const PanelActions = ({ editHandlers, readHandlers, extra, title, description, d
78
144
  });
79
145
  const extraActions = editHandlers === undefined && extra;
80
146
  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);
147
+ const hasData = queryResults && queryResults.series && queryResults.series.length > 0;
84
148
  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
149
  return /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.CircularProgress, {
88
150
  "aria-label": "loading",
89
151
  size: "1.125rem"
90
152
  });
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');
153
+ }
154
+ const validErrors = (errors || []).filter((error)=>error !== null);
155
+ if (validErrors.length > 0) {
156
+ const errorTexts = validErrors.map((e)=>{
157
+ if (typeof e === 'string') return e;
158
+ if (e && typeof e === 'object') {
159
+ const errorObj = e;
160
+ return errorObj.message ?? errorObj.toString?.() ?? 'Unknown error';
161
+ }
162
+ return 'Unknown error';
163
+ }).join('\n');
94
164
  return /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.InfoTooltip, {
95
165
  description: errorTexts,
96
166
  children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_HeaderIconButton.HeaderIconButton, {
@@ -103,7 +173,9 @@ const PanelActions = ({ editHandlers, readHandlers, extra, title, description, d
103
173
  });
104
174
  }
105
175
  }, [
106
- queryResults
176
+ queryResults,
177
+ isFetching,
178
+ errors
107
179
  ]);
108
180
  const readActions = (0, _react.useMemo)(()=>{
109
181
  if (readHandlers !== undefined) {
@@ -128,7 +200,6 @@ const PanelActions = ({ editHandlers, readHandlers, extra, title, description, d
128
200
  ]);
129
201
  const editActions = (0, _react.useMemo)(()=>{
130
202
  if (editHandlers !== undefined) {
131
- // If there are edit handlers, always just show the edit buttons
132
203
  return /*#__PURE__*/ (0, _jsxruntime.jsxs)(_jsxruntime.Fragment, {
133
204
  children: [
134
205
  /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.InfoTooltip, {
@@ -151,8 +222,6 @@ const PanelActions = ({ editHandlers, readHandlers, extra, title, description, d
151
222
  children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_ContentCopy.default, {
152
223
  fontSize: "inherit",
153
224
  sx: {
154
- // Shrink this icon a little bit to look more consistent
155
- // with the other icons in the header.
156
225
  transform: 'scale(0.925)'
157
226
  }
158
227
  })
@@ -242,6 +311,7 @@ const PanelActions = ({ editHandlers, readHandlers, extra, title, description, d
242
311
  editActions
243
312
  ]
244
313
  }),
314
+ pluginActions,
245
315
  moveAction
246
316
  ]
247
317
  })
@@ -269,6 +339,7 @@ const PanelActions = ({ editHandlers, readHandlers, extra, title, description, d
269
339
  extraActions,
270
340
  " ",
271
341
  readActions,
342
+ pluginActions,
272
343
  /*#__PURE__*/ (0, _jsxruntime.jsx)(OverflowMenu, {
273
344
  title: title,
274
345
  children: editActions
@@ -280,7 +351,6 @@ const PanelActions = ({ editHandlers, readHandlers, extra, title, description, d
280
351
  }),
281
352
  /*#__PURE__*/ (0, _jsxruntime.jsxs)(ConditionalBox, {
282
353
  sx: (theme)=>({
283
- // flip the logic here; if the browser (or jsdom) does not support container queries, always show all icons
284
354
  display: 'flex',
285
355
  [theme.containerQueries(_constants.HEADER_ACTIONS_CONTAINER_NAME).down(_constants.HEADER_MEDIUM_WIDTH)]: {
286
356
  display: 'none'
@@ -302,7 +372,7 @@ const PanelActions = ({ editHandlers, readHandlers, extra, title, description, d
302
372
  extraActions,
303
373
  " ",
304
374
  readActions,
305
- " ",
375
+ pluginActions,
306
376
  editActions,
307
377
  " ",
308
378
  moveAction
@@ -315,7 +385,7 @@ const PanelActions = ({ editHandlers, readHandlers, extra, title, description, d
315
385
  };
316
386
  const OverflowMenu = ({ children, title })=>{
317
387
  const [anchorPosition, setAnchorPosition] = (0, _react.useState)();
318
- // do not show overflow menu if there is no content (for example, edit actions are hidden)
388
+ // do not show overflow menu if there is no content
319
389
  const hasContent = /*#__PURE__*/ (0, _react.isValidElement)(children) || Array.isArray(children) && children.some(_react.isValidElement);
320
390
  if (!hasContent) {
321
391
  return undefined;
@@ -28,7 +28,7 @@ const _PanelPluginLoader = require("./PanelPluginLoader");
28
28
  function PanelContent(props) {
29
29
  const { panelPluginKind, definition, queryResults, spec, contentDimensions } = props;
30
30
  const { data: plugin, isLoading: isPanelLoading } = (0, _pluginsystem.usePlugin)('Panel', panelPluginKind, {
31
- throwOnError: true
31
+ useErrorBoundary: true
32
32
  });
33
33
  // Show fullsize skeleton if the panel plugin is loading.
34
34
  if (isPanelLoading) {
@@ -24,13 +24,53 @@ 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, panelPluginKind, projectName, panelProps, ...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
+ const timeSeriesDataForExport = (0, _react.useMemo)(()=>{
36
+ // Collect all series from all queries
37
+ const allSeries = [];
38
+ let timeRange = undefined;
39
+ let stepMs = undefined;
40
+ let metadata = undefined;
41
+ queryResults.forEach((query)=>{
42
+ if (query.data && 'series' in query.data) {
43
+ const timeSeriesData = query.data;
44
+ // Collect series from this query
45
+ if (timeSeriesData.series && timeSeriesData.series.length > 0) {
46
+ allSeries.push(...timeSeriesData.series);
47
+ // Use the first query's metadata/timeRange/stepMs as the base
48
+ if (!timeRange && timeSeriesData.timeRange) {
49
+ timeRange = timeSeriesData.timeRange;
50
+ }
51
+ if (!stepMs && timeSeriesData.stepMs) {
52
+ stepMs = timeSeriesData.stepMs;
53
+ }
54
+ if (!metadata && timeSeriesData.metadata) {
55
+ metadata = timeSeriesData.metadata;
56
+ }
57
+ }
58
+ }
59
+ });
60
+ // If we found series, create a combined TimeSeriesData object
61
+ if (allSeries.length > 0) {
62
+ const combinedData = {
63
+ series: allSeries,
64
+ timeRange,
65
+ stepMs,
66
+ metadata
67
+ };
68
+ return combinedData;
69
+ }
70
+ return undefined;
71
+ }, [
72
+ queryResults
73
+ ]);
34
74
  return /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.CardHeader, {
35
75
  id: id,
36
76
  component: "header",
@@ -59,10 +99,14 @@ function PanelHeader({ id, title: rawTitle, description: rawDescription, links,
59
99
  description: description,
60
100
  descriptionTooltipId: descriptionTooltipId,
61
101
  links: links,
62
- queryResults: queryResults,
102
+ queryResults: timeSeriesDataForExport,
103
+ panelPluginKind: panelPluginKind,
63
104
  readHandlers: readHandlers,
64
105
  editHandlers: editHandlers,
65
- extra: extra
106
+ extra: extra,
107
+ projectName: projectName,
108
+ // ========== ADDED: Pass panel props for actions ==========
109
+ panelProps: panelProps
66
110
  })
67
111
  ]
68
112
  }),
@@ -26,7 +26,7 @@ const _material = require("@mui/material");
26
26
  function PanelPluginLoader(props) {
27
27
  const { kind, spec, contentDimensions, definition, queryResults } = props;
28
28
  const { data: plugin, isLoading: isPanelLoading } = (0, _pluginsystem.usePlugin)('Panel', kind, {
29
- throwOnError: true
29
+ useErrorBoundary: true
30
30
  });
31
31
  const PanelComponent = plugin?.PanelComponent;
32
32
  const supportedQueryTypes = plugin?.supportedQueryTypes || [];
@@ -34,8 +34,8 @@ function PanelPreview({ panelDefinition }) {
34
34
  width = boxRef.current.getBoundingClientRect().width;
35
35
  }
36
36
  const suggestedStepMs = (0, _pluginsystem.useSuggestedStepMs)(width);
37
- const { data: plugin, isPending } = (0, _pluginsystem.usePlugin)('Panel', panelDefinition.spec.plugin.kind);
38
- if (isPending) {
37
+ const { data: plugin, isLoading } = (0, _pluginsystem.usePlugin)('Panel', panelDefinition.spec.plugin.kind);
38
+ if (isLoading) {
39
39
  return null;
40
40
  }
41
41
  if (panelDefinition.spec.plugin.kind === '') {
@@ -34,7 +34,7 @@ function QuerySummaryTable(props) {
34
34
  // for displaying a summary of recent query results
35
35
  const queryClient = (0, _reactquery.useQueryClient)();
36
36
  const queries = queryClient.getQueryCache().findAll();
37
- const activeQueries = queries.filter((query)=>query.state.status === 'pending');
37
+ const activeQueries = queries.filter((query)=>query.state.status === 'loading');
38
38
  const completedQueries = queries.filter((query)=>query.state.status === 'success');
39
39
  const querySummary = (0, _pluginsystem.useActiveTimeSeriesQueries)();
40
40
  if (datasourceClient.isLoading === true) {
@@ -9,6 +9,11 @@ export interface PanelProps extends CardProps<'section'> {
9
9
  editHandlers?: PanelHeaderProps['editHandlers'];
10
10
  panelOptions?: PanelOptions;
11
11
  panelGroupItemId?: PanelGroupItemId;
12
+ /**
13
+ * Project name to use for the panel. If not provided, will attempt to extract from URL.
14
+ * @default extracted from URL or 'unknown-project'
15
+ */
16
+ projectName?: string;
12
17
  }
13
18
  export type PanelOptions = {
14
19
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"Panel.d.ts","sourceRoot":"","sources":["../../../src/components/Panel/Panel.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAqB,SAAS,EAAE,MAAM,eAAe,CAAC;AAE7D,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAEnD,OAAO,EAAE,SAAS,EAA2B,MAAM,OAAO,CAAC;AAE3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEjD,OAAO,EAAe,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAE9D,MAAM,WAAW,UAAW,SAAQ,SAAS,CAAC,SAAS,CAAC;IACtD,UAAU,EAAE,eAAe,CAAC;IAC5B,YAAY,CAAC,EAAE,gBAAgB,CAAC,cAAc,CAAC,CAAC;IAChD,YAAY,CAAC,EAAE,gBAAgB,CAAC,cAAc,CAAC,CAAC;IAChD,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;CACrC;AAED,MAAM,MAAM,YAAY,GAAG;IACzB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,SAAS,CAAC;CAC/C,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B;;OAEG;IACH,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC;;OAEG;IACH,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;CACrC,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,KAAK,kDAmGhB,CAAC"}
1
+ {"version":3,"file":"Panel.d.ts","sourceRoot":"","sources":["../../../src/components/Panel/Panel.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAqB,SAAS,EAAE,MAAM,eAAe,CAAC;AAE7D,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAEnD,OAAO,EAAE,SAAS,EAA2B,MAAM,OAAO,CAAC;AAE3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEjD,OAAO,EAAe,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAE9D,MAAM,WAAW,UAAW,SAAQ,SAAS,CAAC,SAAS,CAAC;IACtD,UAAU,EAAE,eAAe,CAAC;IAC5B,YAAY,CAAC,EAAE,gBAAgB,CAAC,cAAc,CAAC,CAAC;IAChD,YAAY,CAAC,EAAE,gBAAgB,CAAC,cAAc,CAAC,CAAC;IAChD,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,MAAM,YAAY,GAAG;IACzB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,SAAS,CAAC;CAC/C,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B;;OAEG;IACH,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC;;OAEG;IACH,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;CACrC,CAAC;AA8CF;;;;;;;GAOG;AACH,eAAO,MAAM,KAAK,kDAyHhB,CAAC"}
@@ -18,6 +18,39 @@ import { memo, useMemo, useState } from 'react';
18
18
  import useResizeObserver from 'use-resize-observer';
19
19
  import { PanelContent } from './PanelContent';
20
20
  import { PanelHeader } from './PanelHeader';
21
+ // Function to extract project name from URL (kept as fallback)
22
+ const extractProjectNameFromUrl = ()=>{
23
+ try {
24
+ if (process.env.NODE_ENV === 'test') {
25
+ return 'test-project';
26
+ }
27
+ if (typeof window !== 'undefined' && (window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1')) {
28
+ const urlPath = window.location.pathname;
29
+ if (urlPath === '/' || urlPath === '') {
30
+ return 'dev-project';
31
+ }
32
+ }
33
+ const urlPath = window.location.pathname;
34
+ // Split the path and look for the project name after "/projects/"
35
+ const pathSegments = urlPath.split('/').filter((segment)=>segment.length > 0);
36
+ const projectsIndex = pathSegments.findIndex((segment)=>segment === 'projects');
37
+ if (projectsIndex !== -1 && projectsIndex + 1 < pathSegments.length) {
38
+ const projectName = pathSegments[projectsIndex + 1];
39
+ if (projectName && projectName.trim().length > 0) {
40
+ return projectName;
41
+ }
42
+ }
43
+ // Fallback: try to extract from URL parameters
44
+ const urlParams = new URLSearchParams(window.location.search);
45
+ const projectParam = urlParams.get('project');
46
+ if (projectParam && projectParam.trim().length > 0) {
47
+ return projectParam;
48
+ }
49
+ return 'unknown-project';
50
+ } catch {
51
+ return 'unknown-project';
52
+ }
53
+ };
21
54
  /**
22
55
  * Renders a PanelDefinition's content inside of a Card.
23
56
  *
@@ -26,7 +59,7 @@ import { PanelHeader } from './PanelHeader';
26
59
  * <PanelContent> // renders loading, error or panel based on the queries' status
27
60
  * <PanelPluginLoader> // loads a panel plugin from the plugin registry and renders the PanelComponent with data from props.queryResults
28
61
  */ export const Panel = /*#__PURE__*/ memo(function Panel(props) {
29
- const { definition, readHandlers, editHandlers, onMouseEnter, onMouseLeave, sx, panelOptions, panelGroupItemId, ...others } = props;
62
+ const { definition, readHandlers, editHandlers, onMouseEnter, onMouseLeave, sx, panelOptions, panelGroupItemId, projectName: providedProjectName, ...others } = props;
30
63
  // Make sure we have an ID we can use for aria attributes
31
64
  const generatedPanelId = useId('Panel');
32
65
  const headerId = `${generatedPanelId}-header`;
@@ -46,6 +79,29 @@ import { PanelHeader } from './PanelHeader';
46
79
  ]);
47
80
  const chartsTheme = useChartsTheme();
48
81
  const { queryResults } = useDataQueriesContext();
82
+ // Use provided project name or extract from URL as fallback
83
+ const projectName = useMemo(()=>{
84
+ return providedProjectName || extractProjectNameFromUrl();
85
+ }, [
86
+ providedProjectName
87
+ ]);
88
+ const panelPropsForActions = useMemo(()=>{
89
+ return {
90
+ spec: definition.spec.plugin.spec,
91
+ queryResults: queryResults.map((query)=>({
92
+ definition: query.definition,
93
+ data: query.data
94
+ })),
95
+ contentDimensions,
96
+ definition,
97
+ projectName
98
+ };
99
+ }, [
100
+ definition,
101
+ contentDimensions,
102
+ queryResults,
103
+ projectName
104
+ ]);
49
105
  const handleMouseEnter = (e)=>{
50
106
  onMouseEnter?.(e);
51
107
  };
@@ -80,9 +136,12 @@ import { PanelHeader } from './PanelHeader';
80
136
  title: definition.spec.display.name,
81
137
  description: definition.spec.display.description,
82
138
  queryResults: queryResults,
139
+ panelPluginKind: definition.spec.plugin.kind,
83
140
  readHandlers: readHandlers,
84
141
  editHandlers: editHandlers,
85
142
  links: definition.spec.links,
143
+ projectName: projectName,
144
+ panelProps: panelPropsForActions,
86
145
  sx: {
87
146
  paddingX: `${chartsTheme.container.padding.default}px`
88
147
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/Panel/Panel.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 { Card, CardContent, CardProps } from '@mui/material';\nimport { ErrorAlert, ErrorBoundary, combineSx, useChartsTheme, useId } from '@perses-dev/components';\nimport { PanelDefinition } from '@perses-dev/core';\nimport { useDataQueriesContext } from '@perses-dev/plugin-system';\nimport { ReactNode, memo, useMemo, useState } from 'react';\nimport useResizeObserver from 'use-resize-observer';\nimport { PanelGroupItemId } from '../../context';\nimport { PanelContent } from './PanelContent';\nimport { PanelHeader, PanelHeaderProps } from './PanelHeader';\n\nexport interface PanelProps extends CardProps<'section'> {\n definition: PanelDefinition;\n readHandlers?: PanelHeaderProps['readHandlers'];\n editHandlers?: PanelHeaderProps['editHandlers'];\n panelOptions?: PanelOptions;\n panelGroupItemId?: PanelGroupItemId;\n}\n\nexport type PanelOptions = {\n /**\n * Allow you to hide the panel header if desired.\n * This can be useful in embedded mode for example.\n */\n hideHeader?: boolean;\n /**\n * Content to render in right of the panel header. (top right of the panel)\n * It will only be rendered when the panel is in edit mode.\n */\n extra?: (props: PanelExtraProps) => ReactNode;\n};\n\nexport type PanelExtraProps = {\n /**\n * The PanelDefinition for the panel.\n */\n panelDefinition?: PanelDefinition;\n /**\n * The PanelGroupItemId for the panel.\n */\n panelGroupItemId?: PanelGroupItemId;\n};\n\n/**\n * Renders a PanelDefinition's content inside of a Card.\n *\n * Internal structure:\n * <Panel> // renders an entire panel, incl. header and action buttons\n * <PanelContent> // renders loading, error or panel based on the queries' status\n * <PanelPluginLoader> // loads a panel plugin from the plugin registry and renders the PanelComponent with data from props.queryResults\n */\nexport const Panel = memo(function Panel(props: PanelProps) {\n const {\n definition,\n readHandlers,\n editHandlers,\n onMouseEnter,\n onMouseLeave,\n sx,\n panelOptions,\n panelGroupItemId,\n ...others\n } = props;\n\n // Make sure we have an ID we can use for aria attributes\n const generatedPanelId = useId('Panel');\n const headerId = `${generatedPanelId}-header`;\n\n const [contentElement, setContentElement] = useState<HTMLElement | null>(null);\n\n const { width, height } = useResizeObserver({ ref: contentElement });\n\n const contentDimensions = useMemo(() => {\n if (width === undefined || height === undefined) return undefined;\n return { width, height };\n }, [width, height]);\n\n const chartsTheme = useChartsTheme();\n\n const { queryResults } = useDataQueriesContext();\n\n const handleMouseEnter: CardProps['onMouseEnter'] = (e) => {\n onMouseEnter?.(e);\n };\n\n const handleMouseLeave: CardProps['onMouseLeave'] = (e) => {\n onMouseLeave?.(e);\n };\n\n return (\n <Card\n component=\"section\"\n sx={combineSx(\n {\n width: '100%',\n height: '100%',\n display: 'flex',\n flexFlow: 'column nowrap',\n ':hover': { '--panel-hover': 'block' },\n },\n sx\n )}\n variant=\"outlined\"\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n aria-labelledby={headerId}\n aria-describedby={headerId}\n data-testid=\"panel\"\n {...others}\n >\n {!panelOptions?.hideHeader && (\n <PanelHeader\n extra={panelOptions?.extra?.({ panelDefinition: definition, panelGroupItemId })}\n id={headerId}\n title={definition.spec.display.name}\n description={definition.spec.display.description}\n queryResults={queryResults}\n readHandlers={readHandlers}\n editHandlers={editHandlers}\n links={definition.spec.links}\n sx={{ paddingX: `${chartsTheme.container.padding.default}px` }}\n />\n )}\n <CardContent\n component=\"figure\"\n sx={{\n position: 'relative',\n overflow: 'hidden',\n flexGrow: 1,\n margin: 0,\n padding: 0,\n // Override MUI default style for last-child\n ':last-child': {\n padding: 0,\n },\n }}\n ref={setContentElement}\n >\n <ErrorBoundary FallbackComponent={ErrorAlert} resetKeys={[definition.spec]}>\n <PanelContent\n definition={definition}\n panelPluginKind={definition.spec.plugin.kind}\n spec={definition.spec.plugin.spec}\n contentDimensions={contentDimensions}\n queryResults={queryResults}\n />\n </ErrorBoundary>\n </CardContent>\n </Card>\n );\n});\n"],"names":["Card","CardContent","ErrorAlert","ErrorBoundary","combineSx","useChartsTheme","useId","useDataQueriesContext","memo","useMemo","useState","useResizeObserver","PanelContent","PanelHeader","Panel","props","definition","readHandlers","editHandlers","onMouseEnter","onMouseLeave","sx","panelOptions","panelGroupItemId","others","generatedPanelId","headerId","contentElement","setContentElement","width","height","ref","contentDimensions","undefined","chartsTheme","queryResults","handleMouseEnter","e","handleMouseLeave","component","display","flexFlow","variant","aria-labelledby","aria-describedby","data-testid","hideHeader","extra","panelDefinition","id","title","spec","name","description","links","paddingX","container","padding","default","position","overflow","flexGrow","margin","FallbackComponent","resetKeys","panelPluginKind","plugin","kind"],"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,IAAI,EAAEC,WAAW,QAAmB,gBAAgB;AAC7D,SAASC,UAAU,EAAEC,aAAa,EAAEC,SAAS,EAAEC,cAAc,EAAEC,KAAK,QAAQ,yBAAyB;AAErG,SAASC,qBAAqB,QAAQ,4BAA4B;AAClE,SAAoBC,IAAI,EAAEC,OAAO,EAAEC,QAAQ,QAAQ,QAAQ;AAC3D,OAAOC,uBAAuB,sBAAsB;AAEpD,SAASC,YAAY,QAAQ,iBAAiB;AAC9C,SAASC,WAAW,QAA0B,gBAAgB;AAkC9D;;;;;;;CAOC,GACD,OAAO,MAAMC,sBAAQN,KAAK,SAASM,MAAMC,KAAiB;IACxD,MAAM,EACJC,UAAU,EACVC,YAAY,EACZC,YAAY,EACZC,YAAY,EACZC,YAAY,EACZC,EAAE,EACFC,YAAY,EACZC,gBAAgB,EAChB,GAAGC,QACJ,GAAGT;IAEJ,yDAAyD;IACzD,MAAMU,mBAAmBnB,MAAM;IAC/B,MAAMoB,WAAW,GAAGD,iBAAiB,OAAO,CAAC;IAE7C,MAAM,CAACE,gBAAgBC,kBAAkB,GAAGlB,SAA6B;IAEzE,MAAM,EAAEmB,KAAK,EAAEC,MAAM,EAAE,GAAGnB,kBAAkB;QAAEoB,KAAKJ;IAAe;IAElE,MAAMK,oBAAoBvB,QAAQ;QAChC,IAAIoB,UAAUI,aAAaH,WAAWG,WAAW,OAAOA;QACxD,OAAO;YAAEJ;YAAOC;QAAO;IACzB,GAAG;QAACD;QAAOC;KAAO;IAElB,MAAMI,cAAc7B;IAEpB,MAAM,EAAE8B,YAAY,EAAE,GAAG5B;IAEzB,MAAM6B,mBAA8C,CAACC;QACnDlB,eAAekB;IACjB;IAEA,MAAMC,mBAA8C,CAACD;QACnDjB,eAAeiB;IACjB;IAEA,qBACE,MAACrC;QACCuC,WAAU;QACVlB,IAAIjB,UACF;YACEyB,OAAO;YACPC,QAAQ;YACRU,SAAS;YACTC,UAAU;YACV,UAAU;gBAAE,iBAAiB;YAAQ;QACvC,GACApB;QAEFqB,SAAQ;QACRvB,cAAciB;QACdhB,cAAckB;QACdK,mBAAiBjB;QACjBkB,oBAAkBlB;QAClBmB,eAAY;QACX,GAAGrB,MAAM;;YAET,CAACF,cAAcwB,4BACd,KAACjC;gBACCkC,OAAOzB,cAAcyB,QAAQ;oBAAEC,iBAAiBhC;oBAAYO;gBAAiB;gBAC7E0B,IAAIvB;gBACJwB,OAAOlC,WAAWmC,IAAI,CAACX,OAAO,CAACY,IAAI;gBACnCC,aAAarC,WAAWmC,IAAI,CAACX,OAAO,CAACa,WAAW;gBAChDlB,cAAcA;gBACdlB,cAAcA;gBACdC,cAAcA;gBACdoC,OAAOtC,WAAWmC,IAAI,CAACG,KAAK;gBAC5BjC,IAAI;oBAAEkC,UAAU,GAAGrB,YAAYsB,SAAS,CAACC,OAAO,CAACC,OAAO,CAAC,EAAE,CAAC;gBAAC;;0BAGjE,KAACzD;gBACCsC,WAAU;gBACVlB,IAAI;oBACFsC,UAAU;oBACVC,UAAU;oBACVC,UAAU;oBACVC,QAAQ;oBACRL,SAAS;oBACT,4CAA4C;oBAC5C,eAAe;wBACbA,SAAS;oBACX;gBACF;gBACA1B,KAAKH;0BAEL,cAAA,KAACzB;oBAAc4D,mBAAmB7D;oBAAY8D,WAAW;wBAAChD,WAAWmC,IAAI;qBAAC;8BACxE,cAAA,KAACvC;wBACCI,YAAYA;wBACZiD,iBAAiBjD,WAAWmC,IAAI,CAACe,MAAM,CAACC,IAAI;wBAC5ChB,MAAMnC,WAAWmC,IAAI,CAACe,MAAM,CAACf,IAAI;wBACjCnB,mBAAmBA;wBACnBG,cAAcA;;;;;;AAM1B,GAAG"}
1
+ {"version":3,"sources":["../../../src/components/Panel/Panel.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 { Card, CardContent, CardProps } from '@mui/material';\nimport { ErrorAlert, ErrorBoundary, combineSx, useChartsTheme, useId } from '@perses-dev/components';\nimport { PanelDefinition } from '@perses-dev/core';\nimport { useDataQueriesContext } from '@perses-dev/plugin-system';\nimport { ReactNode, memo, useMemo, useState } from 'react';\nimport useResizeObserver from 'use-resize-observer';\nimport { PanelGroupItemId } from '../../context';\nimport { PanelContent } from './PanelContent';\nimport { PanelHeader, PanelHeaderProps } from './PanelHeader';\n\nexport interface PanelProps extends CardProps<'section'> {\n definition: PanelDefinition;\n readHandlers?: PanelHeaderProps['readHandlers'];\n editHandlers?: PanelHeaderProps['editHandlers'];\n panelOptions?: PanelOptions;\n panelGroupItemId?: PanelGroupItemId;\n /**\n * Project name to use for the panel. If not provided, will attempt to extract from URL.\n * @default extracted from URL or 'unknown-project'\n */\n projectName?: string;\n}\n\nexport type PanelOptions = {\n /**\n * Allow you to hide the panel header if desired.\n * This can be useful in embedded mode for example.\n */\n hideHeader?: boolean;\n /**\n * Content to render in right of the panel header. (top right of the panel)\n * It will only be rendered when the panel is in edit mode.\n */\n extra?: (props: PanelExtraProps) => ReactNode;\n};\n\nexport type PanelExtraProps = {\n /**\n * The PanelDefinition for the panel.\n */\n panelDefinition?: PanelDefinition;\n /**\n * The PanelGroupItemId for the panel.\n */\n panelGroupItemId?: PanelGroupItemId;\n};\n\n// Function to extract project name from URL (kept as fallback)\nconst extractProjectNameFromUrl = (): string => {\n try {\n if (process.env.NODE_ENV === 'test') {\n return 'test-project';\n }\n\n if (\n typeof window !== 'undefined' &&\n (window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1')\n ) {\n const urlPath = window.location.pathname;\n\n if (urlPath === '/' || urlPath === '') {\n return 'dev-project';\n }\n }\n\n const urlPath = window.location.pathname;\n\n // Split the path and look for the project name after \"/projects/\"\n const pathSegments = urlPath.split('/').filter((segment) => segment.length > 0);\n const projectsIndex = pathSegments.findIndex((segment) => segment === 'projects');\n\n if (projectsIndex !== -1 && projectsIndex + 1 < pathSegments.length) {\n const projectName = pathSegments[projectsIndex + 1];\n if (projectName && projectName.trim().length > 0) {\n return projectName;\n }\n }\n\n // Fallback: try to extract from URL parameters\n const urlParams = new URLSearchParams(window.location.search);\n const projectParam = urlParams.get('project');\n if (projectParam && projectParam.trim().length > 0) {\n return projectParam;\n }\n\n return 'unknown-project';\n } catch {\n return 'unknown-project';\n }\n};\n\n/**\n * Renders a PanelDefinition's content inside of a Card.\n *\n * Internal structure:\n * <Panel> // renders an entire panel, incl. header and action buttons\n * <PanelContent> // renders loading, error or panel based on the queries' status\n * <PanelPluginLoader> // loads a panel plugin from the plugin registry and renders the PanelComponent with data from props.queryResults\n */\nexport const Panel = memo(function Panel(props: PanelProps) {\n const {\n definition,\n readHandlers,\n editHandlers,\n onMouseEnter,\n onMouseLeave,\n sx,\n panelOptions,\n panelGroupItemId,\n projectName: providedProjectName,\n ...others\n } = props;\n\n // Make sure we have an ID we can use for aria attributes\n const generatedPanelId = useId('Panel');\n const headerId = `${generatedPanelId}-header`;\n\n const [contentElement, setContentElement] = useState<HTMLElement | null>(null);\n\n const { width, height } = useResizeObserver({ ref: contentElement });\n\n const contentDimensions = useMemo(() => {\n if (width === undefined || height === undefined) return undefined;\n return { width, height };\n }, [width, height]);\n\n const chartsTheme = useChartsTheme();\n\n const { queryResults } = useDataQueriesContext();\n\n // Use provided project name or extract from URL as fallback\n const projectName = useMemo(() => {\n return providedProjectName || extractProjectNameFromUrl();\n }, [providedProjectName]);\n\n const panelPropsForActions = useMemo(() => {\n return {\n spec: definition.spec.plugin.spec,\n queryResults: queryResults.map((query) => ({\n definition: query.definition,\n data: query.data,\n })),\n contentDimensions,\n definition,\n projectName,\n };\n }, [definition, contentDimensions, queryResults, projectName]);\n\n const handleMouseEnter: CardProps['onMouseEnter'] = (e) => {\n onMouseEnter?.(e);\n };\n\n const handleMouseLeave: CardProps['onMouseLeave'] = (e) => {\n onMouseLeave?.(e);\n };\n\n return (\n <Card\n component=\"section\"\n sx={combineSx(\n {\n width: '100%',\n height: '100%',\n display: 'flex',\n flexFlow: 'column nowrap',\n ':hover': { '--panel-hover': 'block' },\n },\n sx\n )}\n variant=\"outlined\"\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n aria-labelledby={headerId}\n aria-describedby={headerId}\n data-testid=\"panel\"\n {...others}\n >\n {!panelOptions?.hideHeader && (\n <PanelHeader\n extra={panelOptions?.extra?.({ panelDefinition: definition, panelGroupItemId })}\n id={headerId}\n title={definition.spec.display.name}\n description={definition.spec.display.description}\n queryResults={queryResults}\n panelPluginKind={definition.spec.plugin.kind}\n readHandlers={readHandlers}\n editHandlers={editHandlers}\n links={definition.spec.links}\n projectName={projectName}\n panelProps={panelPropsForActions}\n sx={{ paddingX: `${chartsTheme.container.padding.default}px` }}\n />\n )}\n <CardContent\n component=\"figure\"\n sx={{\n position: 'relative',\n overflow: 'hidden',\n flexGrow: 1,\n margin: 0,\n padding: 0,\n // Override MUI default style for last-child\n ':last-child': {\n padding: 0,\n },\n }}\n ref={setContentElement}\n >\n <ErrorBoundary FallbackComponent={ErrorAlert} resetKeys={[definition.spec]}>\n <PanelContent\n definition={definition}\n panelPluginKind={definition.spec.plugin.kind}\n spec={definition.spec.plugin.spec}\n contentDimensions={contentDimensions}\n queryResults={queryResults}\n />\n </ErrorBoundary>\n </CardContent>\n </Card>\n );\n});\n"],"names":["Card","CardContent","ErrorAlert","ErrorBoundary","combineSx","useChartsTheme","useId","useDataQueriesContext","memo","useMemo","useState","useResizeObserver","PanelContent","PanelHeader","extractProjectNameFromUrl","process","env","NODE_ENV","window","location","hostname","urlPath","pathname","pathSegments","split","filter","segment","length","projectsIndex","findIndex","projectName","trim","urlParams","URLSearchParams","search","projectParam","get","Panel","props","definition","readHandlers","editHandlers","onMouseEnter","onMouseLeave","sx","panelOptions","panelGroupItemId","providedProjectName","others","generatedPanelId","headerId","contentElement","setContentElement","width","height","ref","contentDimensions","undefined","chartsTheme","queryResults","panelPropsForActions","spec","plugin","map","query","data","handleMouseEnter","e","handleMouseLeave","component","display","flexFlow","variant","aria-labelledby","aria-describedby","data-testid","hideHeader","extra","panelDefinition","id","title","name","description","panelPluginKind","kind","links","panelProps","paddingX","container","padding","default","position","overflow","flexGrow","margin","FallbackComponent","resetKeys"],"mappings":"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"}
@@ -1,12 +1,12 @@
1
1
  /// <reference types="react" />
2
- import { QueryData } from '@perses-dev/plugin-system';
3
- import { Link } from '@perses-dev/core';
2
+ import { Link, TimeSeriesData } from '@perses-dev/core';
4
3
  export interface PanelActionsProps {
5
4
  title: string;
6
5
  description?: string;
7
6
  descriptionTooltipId: string;
8
7
  links?: Link[];
9
8
  extra?: React.ReactNode;
9
+ panelPluginKind: string;
10
10
  editHandlers?: {
11
11
  onEditPanelClick: () => void;
12
12
  onDuplicatePanelClick: () => void;
@@ -16,7 +16,9 @@ export interface PanelActionsProps {
16
16
  isPanelViewed?: boolean;
17
17
  onViewPanelClick: () => void;
18
18
  };
19
- queryResults: QueryData[];
19
+ queryResults: TimeSeriesData | undefined;
20
+ projectName?: string;
21
+ panelProps?: Record<string, unknown>;
20
22
  }
21
23
  export declare const PanelActions: React.FC<PanelActionsProps>;
22
24
  //# sourceMappingURL=PanelActions.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"PanelActions.d.ts","sourceRoot":"","sources":["../../../src/components/Panel/PanelActions.tsx"],"names":[],"mappings":";AAuBA,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAGtD,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAWxC,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC;IACf,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,YAAY,CAAC,EAAE;QACb,gBAAgB,EAAE,MAAM,IAAI,CAAC;QAC7B,qBAAqB,EAAE,MAAM,IAAI,CAAC;QAClC,kBAAkB,EAAE,MAAM,IAAI,CAAC;KAChC,CAAC;IACF,YAAY,CAAC,EAAE;QACb,aAAa,CAAC,EAAE,OAAO,CAAC;QACxB,gBAAgB,EAAE,MAAM,IAAI,CAAC;KAC9B,CAAC;IACF,YAAY,EAAE,SAAS,EAAE,CAAC;CAC3B;AASD,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAqMpD,CAAC"}
1
+ {"version":3,"file":"PanelActions.d.ts","sourceRoot":"","sources":["../../../src/components/Panel/PanelActions.tsx"],"names":[],"mappings":";AA0BA,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAWxD,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC;IACf,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE;QACb,gBAAgB,EAAE,MAAM,IAAI,CAAC;QAC7B,qBAAqB,EAAE,MAAM,IAAI,CAAC;QAClC,kBAAkB,EAAE,MAAM,IAAI,CAAC;KAChC,CAAC;IACF,YAAY,CAAC,EAAE;QACb,aAAa,CAAC,EAAE,OAAO,CAAC;QACxB,gBAAgB,EAAE,MAAM,IAAI,CAAC;KAC9B,CAAC;IACF,YAAY,EAAE,cAAc,GAAG,SAAS,CAAC;IACzC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AASD,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CA6RpD,CAAC"}