@perses-dev/dashboards 0.0.0-snapshot-time-zone-selector-946f408 → 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 (44) hide show
  1. package/dist/cjs/components/DashboardToolbar/DashboardToolbar.js +98 -109
  2. package/dist/cjs/components/Panel/Panel.js +60 -1
  3. package/dist/cjs/components/Panel/PanelActions.js +86 -16
  4. package/dist/cjs/components/Panel/PanelHeader.js +47 -3
  5. package/dist/cjs/components/SaveChangesConfirmationDialog/SaveChangesConfirmationDialog.js +1 -13
  6. package/dist/cjs/components/SaveDashboardButton/SaveDashboardButton.js +3 -10
  7. package/dist/cjs/context/DashboardProvider/DashboardProvider.js +2 -4
  8. package/dist/cjs/context/useDashboard.js +1 -3
  9. package/dist/cjs/views/ViewDashboard/ViewDashboard.js +0 -2
  10. package/dist/components/DashboardToolbar/DashboardToolbar.d.ts.map +1 -1
  11. package/dist/components/DashboardToolbar/DashboardToolbar.js +100 -111
  12. package/dist/components/DashboardToolbar/DashboardToolbar.js.map +1 -1
  13. package/dist/components/Panel/Panel.d.ts +5 -0
  14. package/dist/components/Panel/Panel.d.ts.map +1 -1
  15. package/dist/components/Panel/Panel.js +60 -1
  16. package/dist/components/Panel/Panel.js.map +1 -1
  17. package/dist/components/Panel/PanelActions.d.ts +5 -3
  18. package/dist/components/Panel/PanelActions.d.ts.map +1 -1
  19. package/dist/components/Panel/PanelActions.js +87 -17
  20. package/dist/components/Panel/PanelActions.js.map +1 -1
  21. package/dist/components/Panel/PanelHeader.d.ts +5 -1
  22. package/dist/components/Panel/PanelHeader.d.ts.map +1 -1
  23. package/dist/components/Panel/PanelHeader.js +47 -3
  24. package/dist/components/Panel/PanelHeader.js.map +1 -1
  25. package/dist/components/SaveChangesConfirmationDialog/SaveChangesConfirmationDialog.d.ts.map +1 -1
  26. package/dist/components/SaveChangesConfirmationDialog/SaveChangesConfirmationDialog.js +2 -14
  27. package/dist/components/SaveChangesConfirmationDialog/SaveChangesConfirmationDialog.js.map +1 -1
  28. package/dist/components/SaveDashboardButton/SaveDashboardButton.d.ts.map +1 -1
  29. package/dist/components/SaveDashboardButton/SaveDashboardButton.js +4 -11
  30. package/dist/components/SaveDashboardButton/SaveDashboardButton.js.map +1 -1
  31. package/dist/context/DashboardProvider/DashboardProvider.d.ts +0 -1
  32. package/dist/context/DashboardProvider/DashboardProvider.d.ts.map +1 -1
  33. package/dist/context/DashboardProvider/DashboardProvider.js +3 -5
  34. package/dist/context/DashboardProvider/DashboardProvider.js.map +1 -1
  35. package/dist/context/DashboardProvider/save-changes-dialog-slice.d.ts +1 -2
  36. package/dist/context/DashboardProvider/save-changes-dialog-slice.d.ts.map +1 -1
  37. package/dist/context/DashboardProvider/save-changes-dialog-slice.js.map +1 -1
  38. package/dist/context/useDashboard.d.ts.map +1 -1
  39. package/dist/context/useDashboard.js +1 -3
  40. package/dist/context/useDashboard.js.map +1 -1
  41. package/dist/views/ViewDashboard/ViewDashboard.d.ts.map +1 -1
  42. package/dist/views/ViewDashboard/ViewDashboard.js +1 -3
  43. package/dist/views/ViewDashboard/ViewDashboard.js.map +1 -1
  44. package/package.json +5 -5
@@ -12,8 +12,9 @@
12
12
  // limitations under the License.
13
13
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
14
14
  import { Stack, Box, Popover, CircularProgress, styled } from '@mui/material';
15
- import { isValidElement, useMemo, useState } from 'react';
15
+ import { isValidElement, useMemo, useState, useEffect } from 'react';
16
16
  import { InfoTooltip } from '@perses-dev/components';
17
+ import { usePluginRegistry, useDataQueriesContext } from '@perses-dev/plugin-system';
17
18
  import ArrowCollapseIcon from 'mdi-material-ui/ArrowCollapse';
18
19
  import ArrowExpandIcon from 'mdi-material-ui/ArrowExpand';
19
20
  import PencilIcon from 'mdi-material-ui/PencilOutline';
@@ -32,7 +33,72 @@ const ConditionalBox = styled(Box)({
32
33
  flexGrow: 1,
33
34
  justifyContent: 'flex-end'
34
35
  });
35
- export const PanelActions = ({ editHandlers, readHandlers, extra, title, description, descriptionTooltipId, links, queryResults })=>{
36
+ export const PanelActions = ({ editHandlers, readHandlers, extra, title, description, descriptionTooltipId, links, queryResults, panelPluginKind, projectName: _propsProjectName, panelProps })=>{
37
+ const { isFetching, errors } = useDataQueriesContext();
38
+ const { getPlugin } = usePluginRegistry();
39
+ const [pluginActions, setPluginActions] = useState([]);
40
+ useEffect(()=>{
41
+ let cancelled = false;
42
+ const loadPluginActions = async ()=>{
43
+ if (!panelPluginKind || !panelProps) {
44
+ if (!cancelled) {
45
+ setPluginActions([]);
46
+ }
47
+ return;
48
+ }
49
+ try {
50
+ // Add defensive check for getPlugin availability
51
+ if (!getPlugin || typeof getPlugin !== 'function') {
52
+ if (!cancelled) {
53
+ setPluginActions([]);
54
+ }
55
+ return;
56
+ }
57
+ const plugin = await getPlugin('Panel', panelPluginKind);
58
+ if (cancelled) return;
59
+ // More defensive checking for plugin and actions
60
+ if (!plugin || typeof plugin !== 'object' || !plugin.actions || !Array.isArray(plugin.actions) || plugin.actions.length === 0) {
61
+ if (!cancelled) {
62
+ setPluginActions([]);
63
+ }
64
+ return;
65
+ }
66
+ // Render plugin actions in header location
67
+ const headerActions = plugin.actions.filter((action)=>!action.location || action.location === 'header').map((action, index)=>{
68
+ const ActionComponent = action.component;
69
+ try {
70
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
71
+ return /*#__PURE__*/ _jsx(ActionComponent, {
72
+ ...panelProps
73
+ }, `plugin-action-${index}`);
74
+ } catch (error) {
75
+ console.warn(`Failed to render plugin action ${index}:`, error);
76
+ return null;
77
+ }
78
+ }).filter((item)=>Boolean(item));
79
+ if (!cancelled) {
80
+ setPluginActions(headerActions);
81
+ }
82
+ } catch (error) {
83
+ if (!cancelled) {
84
+ console.warn('Failed to load plugin actions:', error);
85
+ setPluginActions([]);
86
+ }
87
+ }
88
+ };
89
+ // Use setTimeout to defer the async operation to the next tick
90
+ const timeoutId = setTimeout(()=>{
91
+ loadPluginActions();
92
+ }, 0);
93
+ return ()=>{
94
+ cancelled = true;
95
+ clearTimeout(timeoutId);
96
+ };
97
+ }, [
98
+ panelPluginKind,
99
+ panelProps,
100
+ getPlugin
101
+ ]);
36
102
  const descriptionAction = useMemo(()=>{
37
103
  if (description && description.trim().length > 0) {
38
104
  return /*#__PURE__*/ _jsx(InfoTooltip, {
@@ -63,19 +129,23 @@ export const PanelActions = ({ editHandlers, readHandlers, extra, title, descrip
63
129
  });
64
130
  const extraActions = editHandlers === undefined && extra;
65
131
  const queryStateIndicator = useMemo(()=>{
66
- const hasData = queryResults.some((q)=>q.data);
67
- const isFetching = queryResults.some((q)=>q.isFetching);
68
- const queryErrors = queryResults.filter((q)=>q.error);
132
+ const hasData = queryResults && queryResults.series && queryResults.series.length > 0;
69
133
  if (isFetching && hasData) {
70
- // If the panel has no data, the panel content will show the loading overlay.
71
- // Therefore, show the circular loading indicator only in case the panel doesn't display the loading overlay already.
72
134
  return /*#__PURE__*/ _jsx(CircularProgress, {
73
135
  "aria-label": "loading",
74
136
  size: "1.125rem"
75
137
  });
76
- } else if (queryErrors.length > 0) {
77
- const errorTexts = queryErrors.map((q)=>q.error).map((e)=>e?.message ?? e?.toString() ?? 'Unknown error') // eslint-disable-line @typescript-eslint/no-explicit-any
78
- .join('\n');
138
+ }
139
+ const validErrors = (errors || []).filter((error)=>error !== null);
140
+ if (validErrors.length > 0) {
141
+ const errorTexts = validErrors.map((e)=>{
142
+ if (typeof e === 'string') return e;
143
+ if (e && typeof e === 'object') {
144
+ const errorObj = e;
145
+ return errorObj.message ?? errorObj.toString?.() ?? 'Unknown error';
146
+ }
147
+ return 'Unknown error';
148
+ }).join('\n');
79
149
  return /*#__PURE__*/ _jsx(InfoTooltip, {
80
150
  description: errorTexts,
81
151
  children: /*#__PURE__*/ _jsx(HeaderIconButton, {
@@ -88,7 +158,9 @@ export const PanelActions = ({ editHandlers, readHandlers, extra, title, descrip
88
158
  });
89
159
  }
90
160
  }, [
91
- queryResults
161
+ queryResults,
162
+ isFetching,
163
+ errors
92
164
  ]);
93
165
  const readActions = useMemo(()=>{
94
166
  if (readHandlers !== undefined) {
@@ -113,7 +185,6 @@ export const PanelActions = ({ editHandlers, readHandlers, extra, title, descrip
113
185
  ]);
114
186
  const editActions = useMemo(()=>{
115
187
  if (editHandlers !== undefined) {
116
- // If there are edit handlers, always just show the edit buttons
117
188
  return /*#__PURE__*/ _jsxs(_Fragment, {
118
189
  children: [
119
190
  /*#__PURE__*/ _jsx(InfoTooltip, {
@@ -136,8 +207,6 @@ export const PanelActions = ({ editHandlers, readHandlers, extra, title, descrip
136
207
  children: /*#__PURE__*/ _jsx(ContentCopyIcon, {
137
208
  fontSize: "inherit",
138
209
  sx: {
139
- // Shrink this icon a little bit to look more consistent
140
- // with the other icons in the header.
141
210
  transform: 'scale(0.925)'
142
211
  }
143
212
  })
@@ -227,6 +296,7 @@ export const PanelActions = ({ editHandlers, readHandlers, extra, title, descrip
227
296
  editActions
228
297
  ]
229
298
  }),
299
+ pluginActions,
230
300
  moveAction
231
301
  ]
232
302
  })
@@ -254,6 +324,7 @@ export const PanelActions = ({ editHandlers, readHandlers, extra, title, descrip
254
324
  extraActions,
255
325
  " ",
256
326
  readActions,
327
+ pluginActions,
257
328
  /*#__PURE__*/ _jsx(OverflowMenu, {
258
329
  title: title,
259
330
  children: editActions
@@ -265,7 +336,6 @@ export const PanelActions = ({ editHandlers, readHandlers, extra, title, descrip
265
336
  }),
266
337
  /*#__PURE__*/ _jsxs(ConditionalBox, {
267
338
  sx: (theme)=>({
268
- // flip the logic here; if the browser (or jsdom) does not support container queries, always show all icons
269
339
  display: 'flex',
270
340
  [theme.containerQueries(HEADER_ACTIONS_CONTAINER_NAME).down(HEADER_MEDIUM_WIDTH)]: {
271
341
  display: 'none'
@@ -287,7 +357,7 @@ export const PanelActions = ({ editHandlers, readHandlers, extra, title, descrip
287
357
  extraActions,
288
358
  " ",
289
359
  readActions,
290
- " ",
360
+ pluginActions,
291
361
  editActions,
292
362
  " ",
293
363
  moveAction
@@ -300,7 +370,7 @@ export const PanelActions = ({ editHandlers, readHandlers, extra, title, descrip
300
370
  };
301
371
  const OverflowMenu = ({ children, title })=>{
302
372
  const [anchorPosition, setAnchorPosition] = useState();
303
- // do not show overflow menu if there is no content (for example, edit actions are hidden)
373
+ // do not show overflow menu if there is no content
304
374
  const hasContent = /*#__PURE__*/ isValidElement(children) || Array.isArray(children) && children.some(isValidElement);
305
375
  if (!hasContent) {
306
376
  return undefined;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/Panel/PanelActions.tsx"],"sourcesContent":["// Copyright 2025 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 { Stack, Box, Popover, CircularProgress, styled, PopoverPosition } from '@mui/material';\nimport { isValidElement, PropsWithChildren, ReactNode, useMemo, useState } from 'react';\nimport { InfoTooltip } from '@perses-dev/components';\nimport ArrowCollapseIcon from 'mdi-material-ui/ArrowCollapse';\nimport ArrowExpandIcon from 'mdi-material-ui/ArrowExpand';\nimport PencilIcon from 'mdi-material-ui/PencilOutline';\nimport DeleteIcon from 'mdi-material-ui/DeleteOutline';\nimport DragIcon from 'mdi-material-ui/DragVertical';\nimport ContentCopyIcon from 'mdi-material-ui/ContentCopy';\nimport MenuIcon from 'mdi-material-ui/Menu';\nimport { QueryData } from '@perses-dev/plugin-system';\nimport AlertIcon from 'mdi-material-ui/Alert';\nimport InformationOutlineIcon from 'mdi-material-ui/InformationOutline';\nimport { Link } from '@perses-dev/core';\nimport {\n ARIA_LABEL_TEXT,\n HEADER_ACTIONS_CONTAINER_NAME,\n HEADER_MEDIUM_WIDTH,\n HEADER_SMALL_WIDTH,\n TOOLTIP_TEXT,\n} from '../../constants';\nimport { HeaderIconButton } from './HeaderIconButton';\nimport { PanelLinks } from './PanelLinks';\n\nexport interface PanelActionsProps {\n title: string;\n description?: string;\n descriptionTooltipId: string;\n links?: Link[];\n extra?: React.ReactNode;\n editHandlers?: {\n onEditPanelClick: () => void;\n onDuplicatePanelClick: () => void;\n onDeletePanelClick: () => void;\n };\n readHandlers?: {\n isPanelViewed?: boolean;\n onViewPanelClick: () => void;\n };\n queryResults: QueryData[];\n}\n\nconst ConditionalBox = styled(Box)({\n display: 'none',\n alignItems: 'center',\n flexGrow: 1,\n justifyContent: 'flex-end',\n});\n\nexport const PanelActions: React.FC<PanelActionsProps> = ({\n editHandlers,\n readHandlers,\n extra,\n title,\n description,\n descriptionTooltipId,\n links,\n queryResults,\n}) => {\n const descriptionAction = useMemo(() => {\n if (description && description.trim().length > 0) {\n return (\n <InfoTooltip id={descriptionTooltipId} description={description} enterDelay={100}>\n <HeaderIconButton aria-label=\"panel description\" size=\"small\">\n <InformationOutlineIcon\n aria-describedby=\"info-tooltip\"\n aria-hidden={false}\n fontSize=\"inherit\"\n sx={{ color: (theme) => theme.palette.text.secondary }}\n />\n </HeaderIconButton>\n </InfoTooltip>\n );\n }\n return undefined;\n }, [descriptionTooltipId, description]);\n const linksAction = links && links.length > 0 && <PanelLinks links={links} />;\n const extraActions = editHandlers === undefined && extra;\n\n const queryStateIndicator = useMemo(() => {\n const hasData = queryResults.some((q) => q.data);\n const isFetching = queryResults.some((q) => q.isFetching);\n const queryErrors = queryResults.filter((q) => q.error);\n if (isFetching && hasData) {\n // If the panel has no data, the panel content will show the loading overlay.\n // Therefore, show the circular loading indicator only in case the panel doesn't display the loading overlay already.\n return <CircularProgress aria-label=\"loading\" size=\"1.125rem\" />;\n } else if (queryErrors.length > 0) {\n const errorTexts = queryErrors\n .map((q) => q.error)\n .map((e: any) => e?.message ?? e?.toString() ?? 'Unknown error') // eslint-disable-line @typescript-eslint/no-explicit-any\n .join('\\n');\n\n return (\n <InfoTooltip description={errorTexts}>\n <HeaderIconButton aria-label=\"panel errors\" size=\"small\">\n <AlertIcon fontSize=\"inherit\" />\n </HeaderIconButton>\n </InfoTooltip>\n );\n }\n }, [queryResults]);\n\n const readActions = useMemo(() => {\n if (readHandlers !== undefined) {\n return (\n <InfoTooltip description={TOOLTIP_TEXT.viewPanel}>\n <HeaderIconButton\n aria-label={ARIA_LABEL_TEXT.viewPanel(title)}\n size=\"small\"\n onClick={readHandlers.onViewPanelClick}\n >\n {readHandlers.isPanelViewed ? (\n <ArrowCollapseIcon fontSize=\"inherit\" />\n ) : (\n <ArrowExpandIcon fontSize=\"inherit\" />\n )}\n </HeaderIconButton>\n </InfoTooltip>\n );\n }\n return undefined;\n }, [readHandlers, title]);\n\n const editActions = useMemo(() => {\n if (editHandlers !== undefined) {\n // If there are edit handlers, always just show the edit buttons\n return (\n <>\n <InfoTooltip description={TOOLTIP_TEXT.editPanel}>\n <HeaderIconButton\n aria-label={ARIA_LABEL_TEXT.editPanel(title)}\n size=\"small\"\n onClick={editHandlers.onEditPanelClick}\n >\n <PencilIcon fontSize=\"inherit\" />\n </HeaderIconButton>\n </InfoTooltip>\n <InfoTooltip description={TOOLTIP_TEXT.duplicatePanel}>\n <HeaderIconButton\n aria-label={ARIA_LABEL_TEXT.duplicatePanel(title)}\n size=\"small\"\n onClick={editHandlers.onDuplicatePanelClick}\n >\n <ContentCopyIcon\n fontSize=\"inherit\"\n sx={{\n // Shrink this icon a little bit to look more consistent\n // with the other icons in the header.\n transform: 'scale(0.925)',\n }}\n />\n </HeaderIconButton>\n </InfoTooltip>\n <InfoTooltip description={TOOLTIP_TEXT.deletePanel}>\n <HeaderIconButton\n aria-label={ARIA_LABEL_TEXT.deletePanel(title)}\n size=\"small\"\n onClick={editHandlers.onDeletePanelClick}\n >\n <DeleteIcon fontSize=\"inherit\" />\n </HeaderIconButton>\n </InfoTooltip>\n </>\n );\n }\n return undefined;\n }, [editHandlers, title]);\n\n const moveAction = useMemo(() => {\n if (editActions && !readHandlers?.isPanelViewed) {\n return (\n <InfoTooltip description={TOOLTIP_TEXT.movePanel}>\n <HeaderIconButton aria-label={ARIA_LABEL_TEXT.movePanel(title)} size=\"small\">\n <DragIcon className=\"drag-handle\" sx={{ cursor: 'grab' }} fontSize=\"inherit\" />\n </HeaderIconButton>\n </InfoTooltip>\n );\n }\n return undefined;\n }, [editActions, readHandlers, title]);\n\n const divider = <Box sx={{ flexGrow: 1 }}></Box>;\n\n // if the panel is in non-editing, non-fullscreen mode, show certain icons only on hover\n const OnHover = ({ children }: PropsWithChildren): ReactNode =>\n editHandlers === undefined && !readHandlers?.isPanelViewed ? (\n <Box sx={{ display: 'var(--panel-hover, none)' }}>{children}</Box>\n ) : (\n <>{children}</>\n );\n\n return (\n <>\n {/* small panel width: move all icons except move/grab to overflow menu */}\n <ConditionalBox\n sx={(theme) => ({\n [theme.containerQueries(HEADER_ACTIONS_CONTAINER_NAME).between(0, HEADER_SMALL_WIDTH)]: { display: 'flex' },\n })}\n >\n {divider}\n <OnHover>\n <OverflowMenu title={title}>\n {descriptionAction} {linksAction} {queryStateIndicator} {extraActions} {readActions} {editActions}\n </OverflowMenu>\n {moveAction}\n </OnHover>\n </ConditionalBox>\n\n {/* medium panel width: move edit icons to overflow menu */}\n <ConditionalBox\n sx={(theme) => ({\n [theme.containerQueries(HEADER_ACTIONS_CONTAINER_NAME).between(HEADER_SMALL_WIDTH, HEADER_MEDIUM_WIDTH)]: {\n display: 'flex',\n },\n })}\n >\n <OnHover>\n {descriptionAction} {linksAction}\n </OnHover>\n {divider} {queryStateIndicator}\n <OnHover>\n {extraActions} {readActions}\n <OverflowMenu title={title}>{editActions}</OverflowMenu>\n {moveAction}\n </OnHover>\n </ConditionalBox>\n\n {/* large panel width: show all icons in panel header */}\n <ConditionalBox\n sx={(theme) => ({\n // flip the logic here; if the browser (or jsdom) does not support container queries, always show all icons\n display: 'flex',\n [theme.containerQueries(HEADER_ACTIONS_CONTAINER_NAME).down(HEADER_MEDIUM_WIDTH)]: { display: 'none' },\n })}\n >\n <OnHover>\n {descriptionAction} {linksAction}\n </OnHover>\n {divider} {queryStateIndicator}\n <OnHover>\n {extraActions} {readActions} {editActions} {moveAction}\n </OnHover>\n </ConditionalBox>\n </>\n );\n};\n\nconst OverflowMenu: React.FC<PropsWithChildren<{ title: string }>> = ({ children, title }) => {\n const [anchorPosition, setAnchorPosition] = useState<PopoverPosition>();\n\n // do not show overflow menu if there is no content (for example, edit actions are hidden)\n const hasContent = isValidElement(children) || (Array.isArray(children) && children.some(isValidElement));\n if (!hasContent) {\n return undefined;\n }\n\n const handleClick = (event: React.MouseEvent<HTMLElement>): undefined => {\n setAnchorPosition(event.currentTarget.getBoundingClientRect());\n };\n\n const handleClose = (): undefined => {\n setAnchorPosition(undefined);\n };\n\n const open = Boolean(anchorPosition);\n const id = open ? 'actions-menu' : undefined;\n\n return (\n <>\n <HeaderIconButton\n className=\"show-actions\"\n aria-describedby={id}\n onClick={handleClick}\n aria-label={ARIA_LABEL_TEXT.showPanelActions(title)}\n size=\"small\"\n >\n <MenuIcon fontSize=\"inherit\" />\n </HeaderIconButton>\n <Popover\n id={id}\n open={open}\n anchorReference=\"anchorPosition\"\n anchorPosition={anchorPosition}\n onClose={handleClose}\n anchorOrigin={{\n vertical: 'bottom',\n horizontal: 'left',\n }}\n >\n <Stack direction=\"row\" alignItems=\"center\" sx={{ padding: 1 }} onClick={handleClose}>\n {children}\n </Stack>\n </Popover>\n </>\n );\n};\n"],"names":["Stack","Box","Popover","CircularProgress","styled","isValidElement","useMemo","useState","InfoTooltip","ArrowCollapseIcon","ArrowExpandIcon","PencilIcon","DeleteIcon","DragIcon","ContentCopyIcon","MenuIcon","AlertIcon","InformationOutlineIcon","ARIA_LABEL_TEXT","HEADER_ACTIONS_CONTAINER_NAME","HEADER_MEDIUM_WIDTH","HEADER_SMALL_WIDTH","TOOLTIP_TEXT","HeaderIconButton","PanelLinks","ConditionalBox","display","alignItems","flexGrow","justifyContent","PanelActions","editHandlers","readHandlers","extra","title","description","descriptionTooltipId","links","queryResults","descriptionAction","trim","length","id","enterDelay","aria-label","size","aria-describedby","aria-hidden","fontSize","sx","color","theme","palette","text","secondary","undefined","linksAction","extraActions","queryStateIndicator","hasData","some","q","data","isFetching","queryErrors","filter","error","errorTexts","map","e","message","toString","join","readActions","viewPanel","onClick","onViewPanelClick","isPanelViewed","editActions","editPanel","onEditPanelClick","duplicatePanel","onDuplicatePanelClick","transform","deletePanel","onDeletePanelClick","moveAction","movePanel","className","cursor","divider","OnHover","children","containerQueries","between","OverflowMenu","down","anchorPosition","setAnchorPosition","hasContent","Array","isArray","handleClick","event","currentTarget","getBoundingClientRect","handleClose","open","Boolean","showPanelActions","anchorReference","onClose","anchorOrigin","vertical","horizontal","direction","padding"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/components/Panel/PanelActions.tsx"],"sourcesContent":["// Copyright 2025 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 { Stack, Box, Popover, CircularProgress, styled, PopoverPosition } from '@mui/material';\nimport { isValidElement, PropsWithChildren, ReactNode, useMemo, useState, useEffect, ReactElement } from 'react';\nimport { InfoTooltip } from '@perses-dev/components';\nimport { usePluginRegistry, useDataQueriesContext } from '@perses-dev/plugin-system';\nimport ArrowCollapseIcon from 'mdi-material-ui/ArrowCollapse';\nimport ArrowExpandIcon from 'mdi-material-ui/ArrowExpand';\nimport PencilIcon from 'mdi-material-ui/PencilOutline';\nimport DeleteIcon from 'mdi-material-ui/DeleteOutline';\nimport DragIcon from 'mdi-material-ui/DragVertical';\nimport ContentCopyIcon from 'mdi-material-ui/ContentCopy';\nimport MenuIcon from 'mdi-material-ui/Menu';\nimport AlertIcon from 'mdi-material-ui/Alert';\nimport InformationOutlineIcon from 'mdi-material-ui/InformationOutline';\nimport { Link, TimeSeriesData } from '@perses-dev/core';\nimport {\n ARIA_LABEL_TEXT,\n HEADER_ACTIONS_CONTAINER_NAME,\n HEADER_MEDIUM_WIDTH,\n HEADER_SMALL_WIDTH,\n TOOLTIP_TEXT,\n} from '../../constants';\nimport { HeaderIconButton } from './HeaderIconButton';\nimport { PanelLinks } from './PanelLinks';\n\nexport interface PanelActionsProps {\n title: string;\n description?: string;\n descriptionTooltipId: string;\n links?: Link[];\n extra?: React.ReactNode;\n panelPluginKind: string;\n editHandlers?: {\n onEditPanelClick: () => void;\n onDuplicatePanelClick: () => void;\n onDeletePanelClick: () => void;\n };\n readHandlers?: {\n isPanelViewed?: boolean;\n onViewPanelClick: () => void;\n };\n queryResults: TimeSeriesData | undefined;\n projectName?: string;\n panelProps?: Record<string, unknown>;\n}\n\nconst ConditionalBox = styled(Box)({\n display: 'none',\n alignItems: 'center',\n flexGrow: 1,\n justifyContent: 'flex-end',\n});\n\nexport const PanelActions: React.FC<PanelActionsProps> = ({\n editHandlers,\n readHandlers,\n extra,\n title,\n description,\n descriptionTooltipId,\n links,\n queryResults,\n panelPluginKind,\n projectName: _propsProjectName,\n panelProps,\n}) => {\n const { isFetching, errors } = useDataQueriesContext();\n const { getPlugin } = usePluginRegistry();\n\n const [pluginActions, setPluginActions] = useState<ReactNode[]>([]);\n\n useEffect(() => {\n let cancelled = false;\n\n const loadPluginActions = async (): Promise<void> => {\n if (!panelPluginKind || !panelProps) {\n if (!cancelled) {\n setPluginActions([]);\n }\n return;\n }\n\n try {\n // Add defensive check for getPlugin availability\n if (!getPlugin || typeof getPlugin !== 'function') {\n if (!cancelled) {\n setPluginActions([]);\n }\n return;\n }\n\n const plugin = await getPlugin('Panel', panelPluginKind);\n\n if (cancelled) return;\n\n // More defensive checking for plugin and actions\n if (\n !plugin ||\n typeof plugin !== 'object' ||\n !plugin.actions ||\n !Array.isArray(plugin.actions) ||\n plugin.actions.length === 0\n ) {\n if (!cancelled) {\n setPluginActions([]);\n }\n return;\n }\n\n // Render plugin actions in header location\n const headerActions = plugin.actions\n .filter((action) => !action.location || action.location === 'header')\n .map((action, index): ReactNode | null => {\n const ActionComponent = action.component;\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return <ActionComponent key={`plugin-action-${index}`} {...(panelProps as any)} />;\n } catch (error) {\n console.warn(`Failed to render plugin action ${index}:`, error);\n return null;\n }\n })\n .filter((item): item is ReactNode => Boolean(item));\n\n if (!cancelled) {\n setPluginActions(headerActions);\n }\n } catch (error) {\n if (!cancelled) {\n console.warn('Failed to load plugin actions:', error);\n setPluginActions([]);\n }\n }\n };\n\n // Use setTimeout to defer the async operation to the next tick\n const timeoutId = setTimeout(() => {\n loadPluginActions();\n }, 0);\n\n return (): void => {\n cancelled = true;\n clearTimeout(timeoutId);\n };\n }, [panelPluginKind, panelProps, getPlugin]);\n\n const descriptionAction = useMemo((): ReactNode | undefined => {\n if (description && description.trim().length > 0) {\n return (\n <InfoTooltip id={descriptionTooltipId} description={description} enterDelay={100}>\n <HeaderIconButton aria-label=\"panel description\" size=\"small\">\n <InformationOutlineIcon\n aria-describedby=\"info-tooltip\"\n aria-hidden={false}\n fontSize=\"inherit\"\n sx={{ color: (theme) => theme.palette.text.secondary }}\n />\n </HeaderIconButton>\n </InfoTooltip>\n );\n }\n return undefined;\n }, [descriptionTooltipId, description]);\n\n const linksAction = links && links.length > 0 && <PanelLinks links={links} />;\n const extraActions = editHandlers === undefined && extra;\n\n const queryStateIndicator = useMemo((): ReactNode | undefined => {\n const hasData = queryResults && queryResults.series && queryResults.series.length > 0;\n if (isFetching && hasData) {\n return <CircularProgress aria-label=\"loading\" size=\"1.125rem\" />;\n }\n const validErrors = (errors || []).filter((error) => error !== null);\n if (validErrors.length > 0) {\n const errorTexts = validErrors\n .map((e: unknown) => {\n if (typeof e === 'string') return e;\n if (e && typeof e === 'object') {\n const errorObj = e as { message?: string; toString?: () => string };\n return errorObj.message ?? errorObj.toString?.() ?? 'Unknown error';\n }\n return 'Unknown error';\n })\n .join('\\n');\n\n return (\n <InfoTooltip description={errorTexts}>\n <HeaderIconButton aria-label=\"panel errors\" size=\"small\">\n <AlertIcon fontSize=\"inherit\" />\n </HeaderIconButton>\n </InfoTooltip>\n );\n }\n }, [queryResults, isFetching, errors]);\n\n const readActions = useMemo((): ReactNode | undefined => {\n if (readHandlers !== undefined) {\n return (\n <InfoTooltip description={TOOLTIP_TEXT.viewPanel}>\n <HeaderIconButton\n aria-label={ARIA_LABEL_TEXT.viewPanel(title)}\n size=\"small\"\n onClick={readHandlers.onViewPanelClick}\n >\n {readHandlers.isPanelViewed ? (\n <ArrowCollapseIcon fontSize=\"inherit\" />\n ) : (\n <ArrowExpandIcon fontSize=\"inherit\" />\n )}\n </HeaderIconButton>\n </InfoTooltip>\n );\n }\n return undefined;\n }, [readHandlers, title]);\n\n const editActions = useMemo((): ReactNode | undefined => {\n if (editHandlers !== undefined) {\n return (\n <>\n <InfoTooltip description={TOOLTIP_TEXT.editPanel}>\n <HeaderIconButton\n aria-label={ARIA_LABEL_TEXT.editPanel(title)}\n size=\"small\"\n onClick={editHandlers.onEditPanelClick}\n >\n <PencilIcon fontSize=\"inherit\" />\n </HeaderIconButton>\n </InfoTooltip>\n <InfoTooltip description={TOOLTIP_TEXT.duplicatePanel}>\n <HeaderIconButton\n aria-label={ARIA_LABEL_TEXT.duplicatePanel(title)}\n size=\"small\"\n onClick={editHandlers.onDuplicatePanelClick}\n >\n <ContentCopyIcon\n fontSize=\"inherit\"\n sx={{\n transform: 'scale(0.925)',\n }}\n />\n </HeaderIconButton>\n </InfoTooltip>\n <InfoTooltip description={TOOLTIP_TEXT.deletePanel}>\n <HeaderIconButton\n aria-label={ARIA_LABEL_TEXT.deletePanel(title)}\n size=\"small\"\n onClick={editHandlers.onDeletePanelClick}\n >\n <DeleteIcon fontSize=\"inherit\" />\n </HeaderIconButton>\n </InfoTooltip>\n </>\n );\n }\n return undefined;\n }, [editHandlers, title]);\n\n const moveAction = useMemo((): ReactNode | undefined => {\n if (editActions && !readHandlers?.isPanelViewed) {\n return (\n <InfoTooltip description={TOOLTIP_TEXT.movePanel}>\n <HeaderIconButton aria-label={ARIA_LABEL_TEXT.movePanel(title)} size=\"small\">\n <DragIcon className=\"drag-handle\" sx={{ cursor: 'grab' }} fontSize=\"inherit\" />\n </HeaderIconButton>\n </InfoTooltip>\n );\n }\n return undefined;\n }, [editActions, readHandlers, title]);\n\n const divider = <Box sx={{ flexGrow: 1 }}></Box>;\n\n // if the panel is in non-editing, non-fullscreen mode, show certain icons only on hover\n const OnHover = ({ children }: PropsWithChildren): ReactNode =>\n editHandlers === undefined && !readHandlers?.isPanelViewed ? (\n <Box sx={{ display: 'var(--panel-hover, none)' }}>{children}</Box>\n ) : (\n <>{children}</>\n );\n\n return (\n <>\n {/* small panel width: move all icons except move/grab to overflow menu */}\n <ConditionalBox\n sx={(theme) => ({\n [theme.containerQueries(HEADER_ACTIONS_CONTAINER_NAME).between(0, HEADER_SMALL_WIDTH)]: { display: 'flex' },\n })}\n >\n {divider}\n <OnHover>\n <OverflowMenu title={title}>\n {descriptionAction} {linksAction} {queryStateIndicator} {extraActions} {readActions} {editActions}\n </OverflowMenu>\n {pluginActions}\n {moveAction}\n </OnHover>\n </ConditionalBox>\n\n {/* medium panel width: move edit icons to overflow menu */}\n <ConditionalBox\n sx={(theme) => ({\n [theme.containerQueries(HEADER_ACTIONS_CONTAINER_NAME).between(HEADER_SMALL_WIDTH, HEADER_MEDIUM_WIDTH)]: {\n display: 'flex',\n },\n })}\n >\n <OnHover>\n {descriptionAction} {linksAction}\n </OnHover>\n {divider} {queryStateIndicator}\n <OnHover>\n {extraActions} {readActions}\n {pluginActions}\n <OverflowMenu title={title}>{editActions}</OverflowMenu>\n {moveAction}\n </OnHover>\n </ConditionalBox>\n\n {/* large panel width: show all icons in panel header */}\n <ConditionalBox\n sx={(theme) => ({\n display: 'flex',\n [theme.containerQueries(HEADER_ACTIONS_CONTAINER_NAME).down(HEADER_MEDIUM_WIDTH)]: { display: 'none' },\n })}\n >\n <OnHover>\n {descriptionAction} {linksAction}\n </OnHover>\n {divider} {queryStateIndicator}\n <OnHover>\n {extraActions} {readActions}\n {pluginActions}\n {editActions} {moveAction}\n </OnHover>\n </ConditionalBox>\n </>\n );\n};\n\nconst OverflowMenu: React.FC<PropsWithChildren<{ title: string }>> = ({\n children,\n title,\n}): ReactElement | undefined => {\n const [anchorPosition, setAnchorPosition] = useState<PopoverPosition>();\n\n // do not show overflow menu if there is no content\n const hasContent = isValidElement(children) || (Array.isArray(children) && children.some(isValidElement));\n if (!hasContent) {\n return undefined;\n }\n\n const handleClick = (event: React.MouseEvent<HTMLElement>): void => {\n setAnchorPosition(event.currentTarget.getBoundingClientRect());\n };\n\n const handleClose = (): void => {\n setAnchorPosition(undefined);\n };\n\n const open = Boolean(anchorPosition);\n const id = open ? 'actions-menu' : undefined;\n\n return (\n <>\n <HeaderIconButton\n className=\"show-actions\"\n aria-describedby={id}\n onClick={handleClick}\n aria-label={ARIA_LABEL_TEXT.showPanelActions(title)}\n size=\"small\"\n >\n <MenuIcon fontSize=\"inherit\" />\n </HeaderIconButton>\n <Popover\n id={id}\n open={open}\n anchorReference=\"anchorPosition\"\n anchorPosition={anchorPosition}\n onClose={handleClose}\n anchorOrigin={{\n vertical: 'bottom',\n horizontal: 'left',\n }}\n >\n <Stack direction=\"row\" alignItems=\"center\" sx={{ padding: 1 }} onClick={handleClose}>\n {children}\n </Stack>\n </Popover>\n </>\n );\n};\n"],"names":["Stack","Box","Popover","CircularProgress","styled","isValidElement","useMemo","useState","useEffect","InfoTooltip","usePluginRegistry","useDataQueriesContext","ArrowCollapseIcon","ArrowExpandIcon","PencilIcon","DeleteIcon","DragIcon","ContentCopyIcon","MenuIcon","AlertIcon","InformationOutlineIcon","ARIA_LABEL_TEXT","HEADER_ACTIONS_CONTAINER_NAME","HEADER_MEDIUM_WIDTH","HEADER_SMALL_WIDTH","TOOLTIP_TEXT","HeaderIconButton","PanelLinks","ConditionalBox","display","alignItems","flexGrow","justifyContent","PanelActions","editHandlers","readHandlers","extra","title","description","descriptionTooltipId","links","queryResults","panelPluginKind","projectName","_propsProjectName","panelProps","isFetching","errors","getPlugin","pluginActions","setPluginActions","cancelled","loadPluginActions","plugin","actions","Array","isArray","length","headerActions","filter","action","location","map","index","ActionComponent","component","error","console","warn","item","Boolean","timeoutId","setTimeout","clearTimeout","descriptionAction","trim","id","enterDelay","aria-label","size","aria-describedby","aria-hidden","fontSize","sx","color","theme","palette","text","secondary","undefined","linksAction","extraActions","queryStateIndicator","hasData","series","validErrors","errorTexts","e","errorObj","message","toString","join","readActions","viewPanel","onClick","onViewPanelClick","isPanelViewed","editActions","editPanel","onEditPanelClick","duplicatePanel","onDuplicatePanelClick","transform","deletePanel","onDeletePanelClick","moveAction","movePanel","className","cursor","divider","OnHover","children","containerQueries","between","OverflowMenu","down","anchorPosition","setAnchorPosition","hasContent","some","handleClick","event","currentTarget","getBoundingClientRect","handleClose","open","showPanelActions","anchorReference","onClose","anchorOrigin","vertical","horizontal","direction","padding"],"mappings":"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"}
@@ -11,9 +11,13 @@ export interface PanelHeaderProps extends Omit<CardHeaderProps, OmittedProps> {
11
11
  links?: Link[];
12
12
  extra?: ReactNode;
13
13
  queryResults: QueryData[];
14
+ panelPluginKind: string;
14
15
  readHandlers?: PanelActionsProps['readHandlers'];
15
16
  editHandlers?: PanelActionsProps['editHandlers'];
17
+ projectName?: string;
18
+ panelProps?: Record<string, unknown>;
16
19
  }
17
- export declare function PanelHeader({ id, title: rawTitle, description: rawDescription, links, queryResults, readHandlers, editHandlers, sx, extra, ...rest }: PanelHeaderProps): ReactElement;
20
+ export declare function PanelHeader({ id, title: rawTitle, description: rawDescription, links, queryResults, readHandlers, editHandlers, sx, extra, panelPluginKind, projectName, panelProps, // ========== ADDED ==========
21
+ ...rest }: PanelHeaderProps): ReactElement;
18
22
  export {};
19
23
  //# sourceMappingURL=PanelHeader.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"PanelHeader.d.ts","sourceRoot":"","sources":["../../../src/components/Panel/PanelHeader.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAc,eAAe,EAAqB,MAAM,eAAe,CAAC;AAE/E,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxC,OAAO,EAAE,SAAS,EAA+B,MAAM,2BAA2B,CAAC;AACnF,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEhD,OAAO,EAAgB,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAEjE,KAAK,YAAY,GAAG,UAAU,GAAG,QAAQ,GAAG,OAAO,GAAG,mBAAmB,CAAC;AAE1E,MAAM,WAAW,gBAAiB,SAAQ,IAAI,CAAC,eAAe,EAAE,YAAY,CAAC;IAC3E,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC;IACf,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,YAAY,EAAE,SAAS,EAAE,CAAC;IAC1B,YAAY,CAAC,EAAE,iBAAiB,CAAC,cAAc,CAAC,CAAC;IACjD,YAAY,CAAC,EAAE,iBAAiB,CAAC,cAAc,CAAC,CAAC;CAClD;AAED,wBAAgB,WAAW,CAAC,EAC1B,EAAE,EACF,KAAK,EAAE,QAAQ,EACf,WAAW,EAAE,cAAc,EAC3B,KAAK,EACL,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,EAAE,EACF,KAAK,EACL,GAAG,IAAI,EACR,EAAE,gBAAgB,GAAG,YAAY,CA0DjC"}
1
+ {"version":3,"file":"PanelHeader.d.ts","sourceRoot":"","sources":["../../../src/components/Panel/PanelHeader.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAc,eAAe,EAAqB,MAAM,eAAe,CAAC;AAE/E,OAAO,EAAE,IAAI,EAAkD,MAAM,kBAAkB,CAAC;AACxF,OAAO,EAAE,SAAS,EAA+B,MAAM,2BAA2B,CAAC;AACnF,OAAO,EAAE,YAAY,EAAE,SAAS,EAAW,MAAM,OAAO,CAAC;AAEzD,OAAO,EAAgB,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAEjE,KAAK,YAAY,GAAG,UAAU,GAAG,QAAQ,GAAG,OAAO,GAAG,mBAAmB,CAAC;AAO1E,MAAM,WAAW,gBAAiB,SAAQ,IAAI,CAAC,eAAe,EAAE,YAAY,CAAC;IAC3E,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC;IACf,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,YAAY,EAAE,SAAS,EAAE,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,iBAAiB,CAAC,cAAc,CAAC,CAAC;IACjD,YAAY,CAAC,EAAE,iBAAiB,CAAC,cAAc,CAAC,CAAC;IACjD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED,wBAAgB,WAAW,CAAC,EAC1B,EAAE,EACF,KAAK,EAAE,QAAQ,EACf,WAAW,EAAE,cAAc,EAC3B,KAAK,EACL,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,EAAE,EACF,KAAK,EACL,eAAe,EACf,WAAW,EACX,UAAU,EAAE,8BAA8B;AAC1C,GAAG,IAAI,EACR,EAAE,gBAAgB,GAAG,YAAY,CA2GjC"}
@@ -14,13 +14,53 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
14
14
  import { CardHeader, Stack, Typography } from '@mui/material';
15
15
  import { combineSx } from '@perses-dev/components';
16
16
  import { useReplaceVariablesInString } from '@perses-dev/plugin-system';
17
+ import { useMemo } from 'react';
17
18
  import { HEADER_ACTIONS_CONTAINER_NAME } from '../../constants';
18
19
  import { PanelActions } from './PanelActions';
19
- export function PanelHeader({ id, title: rawTitle, description: rawDescription, links, queryResults, readHandlers, editHandlers, sx, extra, ...rest }) {
20
+ export function PanelHeader({ id, title: rawTitle, description: rawDescription, links, queryResults, readHandlers, editHandlers, sx, extra, panelPluginKind, projectName, panelProps, ...rest }) {
20
21
  const titleElementId = `${id}-title`;
21
22
  const descriptionTooltipId = `${id}-description`;
22
23
  const title = useReplaceVariablesInString(rawTitle);
23
24
  const description = useReplaceVariablesInString(rawDescription);
25
+ const timeSeriesDataForExport = useMemo(()=>{
26
+ // Collect all series from all queries
27
+ const allSeries = [];
28
+ let timeRange = undefined;
29
+ let stepMs = undefined;
30
+ let metadata = undefined;
31
+ queryResults.forEach((query)=>{
32
+ if (query.data && 'series' in query.data) {
33
+ const timeSeriesData = query.data;
34
+ // Collect series from this query
35
+ if (timeSeriesData.series && timeSeriesData.series.length > 0) {
36
+ allSeries.push(...timeSeriesData.series);
37
+ // Use the first query's metadata/timeRange/stepMs as the base
38
+ if (!timeRange && timeSeriesData.timeRange) {
39
+ timeRange = timeSeriesData.timeRange;
40
+ }
41
+ if (!stepMs && timeSeriesData.stepMs) {
42
+ stepMs = timeSeriesData.stepMs;
43
+ }
44
+ if (!metadata && timeSeriesData.metadata) {
45
+ metadata = timeSeriesData.metadata;
46
+ }
47
+ }
48
+ }
49
+ });
50
+ // If we found series, create a combined TimeSeriesData object
51
+ if (allSeries.length > 0) {
52
+ const combinedData = {
53
+ series: allSeries,
54
+ timeRange,
55
+ stepMs,
56
+ metadata
57
+ };
58
+ return combinedData;
59
+ }
60
+ return undefined;
61
+ }, [
62
+ queryResults
63
+ ]);
24
64
  return /*#__PURE__*/ _jsx(CardHeader, {
25
65
  id: id,
26
66
  component: "header",
@@ -49,10 +89,14 @@ export function PanelHeader({ id, title: rawTitle, description: rawDescription,
49
89
  description: description,
50
90
  descriptionTooltipId: descriptionTooltipId,
51
91
  links: links,
52
- queryResults: queryResults,
92
+ queryResults: timeSeriesDataForExport,
93
+ panelPluginKind: panelPluginKind,
53
94
  readHandlers: readHandlers,
54
95
  editHandlers: editHandlers,
55
- extra: extra
96
+ extra: extra,
97
+ projectName: projectName,
98
+ // ========== ADDED: Pass panel props for actions ==========
99
+ panelProps: panelProps
56
100
  })
57
101
  ]
58
102
  }),
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/Panel/PanelHeader.tsx"],"sourcesContent":["// Copyright 2025 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 { CardHeader, CardHeaderProps, Stack, Typography } from '@mui/material';\nimport { combineSx } from '@perses-dev/components';\nimport { Link } from '@perses-dev/core';\nimport { QueryData, useReplaceVariablesInString } from '@perses-dev/plugin-system';\nimport { ReactElement, ReactNode } from 'react';\nimport { HEADER_ACTIONS_CONTAINER_NAME } from '../../constants';\nimport { PanelActions, PanelActionsProps } from './PanelActions';\n\ntype OmittedProps = 'children' | 'action' | 'title' | 'disableTypography';\n\nexport interface PanelHeaderProps extends Omit<CardHeaderProps, OmittedProps> {\n id: string;\n title: string;\n description?: string;\n links?: Link[];\n extra?: ReactNode;\n queryResults: QueryData[];\n readHandlers?: PanelActionsProps['readHandlers'];\n editHandlers?: PanelActionsProps['editHandlers'];\n}\n\nexport function PanelHeader({\n id,\n title: rawTitle,\n description: rawDescription,\n links,\n queryResults,\n readHandlers,\n editHandlers,\n sx,\n extra,\n ...rest\n}: PanelHeaderProps): ReactElement {\n const titleElementId = `${id}-title`;\n const descriptionTooltipId = `${id}-description`;\n\n const title = useReplaceVariablesInString(rawTitle) as string;\n const description = useReplaceVariablesInString(rawDescription);\n\n return (\n <CardHeader\n id={id}\n component=\"header\"\n aria-labelledby={titleElementId}\n aria-describedby={descriptionTooltipId}\n disableTypography\n title={\n <Stack direction=\"row\">\n <Typography\n id={titleElementId}\n variant=\"subtitle1\"\n sx={{\n // `minHeight` guarantees that the header has the correct height\n // when there is no title (i.e. in the preview)\n lineHeight: '24px',\n minHeight: '26px',\n whiteSpace: 'nowrap',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n }}\n >\n {title}\n </Typography>\n <PanelActions\n title={title}\n description={description}\n descriptionTooltipId={descriptionTooltipId}\n links={links}\n queryResults={queryResults}\n readHandlers={readHandlers}\n editHandlers={editHandlers}\n extra={extra}\n />\n </Stack>\n }\n sx={combineSx(\n (theme) => ({\n containerType: 'inline-size',\n containerName: HEADER_ACTIONS_CONTAINER_NAME,\n padding: theme.spacing(1),\n borderBottom: `solid 1px ${theme.palette.divider}`,\n '.MuiCardHeader-content': {\n overflow: 'hidden',\n },\n }),\n sx\n )}\n {...rest}\n />\n );\n}\n"],"names":["CardHeader","Stack","Typography","combineSx","useReplaceVariablesInString","HEADER_ACTIONS_CONTAINER_NAME","PanelActions","PanelHeader","id","title","rawTitle","description","rawDescription","links","queryResults","readHandlers","editHandlers","sx","extra","rest","titleElementId","descriptionTooltipId","component","aria-labelledby","aria-describedby","disableTypography","direction","variant","lineHeight","minHeight","whiteSpace","overflow","textOverflow","theme","containerType","containerName","padding","spacing","borderBottom","palette","divider"],"mappings":"AAAA,oCAAoC;AACpC,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;;AAEjC,SAASA,UAAU,EAAmBC,KAAK,EAAEC,UAAU,QAAQ,gBAAgB;AAC/E,SAASC,SAAS,QAAQ,yBAAyB;AAEnD,SAAoBC,2BAA2B,QAAQ,4BAA4B;AAEnF,SAASC,6BAA6B,QAAQ,kBAAkB;AAChE,SAASC,YAAY,QAA2B,iBAAiB;AAejE,OAAO,SAASC,YAAY,EAC1BC,EAAE,EACFC,OAAOC,QAAQ,EACfC,aAAaC,cAAc,EAC3BC,KAAK,EACLC,YAAY,EACZC,YAAY,EACZC,YAAY,EACZC,EAAE,EACFC,KAAK,EACL,GAAGC,MACc;IACjB,MAAMC,iBAAiB,GAAGZ,GAAG,MAAM,CAAC;IACpC,MAAMa,uBAAuB,GAAGb,GAAG,YAAY,CAAC;IAEhD,MAAMC,QAAQL,4BAA4BM;IAC1C,MAAMC,cAAcP,4BAA4BQ;IAEhD,qBACE,KAACZ;QACCQ,IAAIA;QACJc,WAAU;QACVC,mBAAiBH;QACjBI,oBAAkBH;QAClBI,iBAAiB;QACjBhB,qBACE,MAACR;YAAMyB,WAAU;;8BACf,KAACxB;oBACCM,IAAIY;oBACJO,SAAQ;oBACRV,IAAI;wBACF,gEAAgE;wBAChE,+CAA+C;wBAC/CW,YAAY;wBACZC,WAAW;wBACXC,YAAY;wBACZC,UAAU;wBACVC,cAAc;oBAChB;8BAECvB;;8BAEH,KAACH;oBACCG,OAAOA;oBACPE,aAAaA;oBACbU,sBAAsBA;oBACtBR,OAAOA;oBACPC,cAAcA;oBACdC,cAAcA;oBACdC,cAAcA;oBACdE,OAAOA;;;;QAIbD,IAAId,UACF,CAAC8B,QAAW,CAAA;gBACVC,eAAe;gBACfC,eAAe9B;gBACf+B,SAASH,MAAMI,OAAO,CAAC;gBACvBC,cAAc,CAAC,UAAU,EAAEL,MAAMM,OAAO,CAACC,OAAO,EAAE;gBAClD,0BAA0B;oBACxBT,UAAU;gBACZ;YACF,CAAA,GACAd;QAED,GAAGE,IAAI;;AAGd"}
1
+ {"version":3,"sources":["../../../src/components/Panel/PanelHeader.tsx"],"sourcesContent":["// Copyright 2025 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 { CardHeader, CardHeaderProps, Stack, Typography } from '@mui/material';\nimport { combineSx } from '@perses-dev/components';\nimport { Link, TimeSeriesData, TimeSeries, TimeSeriesMetadata } from '@perses-dev/core';\nimport { QueryData, useReplaceVariablesInString } from '@perses-dev/plugin-system';\nimport { ReactElement, ReactNode, useMemo } from 'react';\nimport { HEADER_ACTIONS_CONTAINER_NAME } from '../../constants';\nimport { PanelActions, PanelActionsProps } from './PanelActions';\n\ntype OmittedProps = 'children' | 'action' | 'title' | 'disableTypography';\n\ninterface AbsoluteTimeRange {\n start: Date;\n end: Date;\n}\n\nexport interface PanelHeaderProps extends Omit<CardHeaderProps, OmittedProps> {\n id: string;\n title: string;\n description?: string;\n links?: Link[];\n extra?: ReactNode;\n queryResults: QueryData[];\n panelPluginKind: string;\n readHandlers?: PanelActionsProps['readHandlers'];\n editHandlers?: PanelActionsProps['editHandlers'];\n projectName?: string;\n panelProps?: Record<string, unknown>;\n}\n\nexport function PanelHeader({\n id,\n title: rawTitle,\n description: rawDescription,\n links,\n queryResults,\n readHandlers,\n editHandlers,\n sx,\n extra,\n panelPluginKind,\n projectName,\n panelProps, // ========== ADDED ==========\n ...rest\n}: PanelHeaderProps): ReactElement {\n const titleElementId = `${id}-title`;\n const descriptionTooltipId = `${id}-description`;\n\n const title = useReplaceVariablesInString(rawTitle) as string;\n const description = useReplaceVariablesInString(rawDescription);\n\n const timeSeriesDataForExport = useMemo(() => {\n // Collect all series from all queries\n const allSeries: TimeSeries[] = [];\n let timeRange: AbsoluteTimeRange | undefined = undefined;\n let stepMs: number | undefined = undefined;\n let metadata: TimeSeriesMetadata | undefined = undefined;\n\n queryResults.forEach((query) => {\n if (query.data && 'series' in query.data) {\n const timeSeriesData = query.data as TimeSeriesData;\n\n // Collect series from this query\n if (timeSeriesData.series && timeSeriesData.series.length > 0) {\n allSeries.push(...timeSeriesData.series);\n\n // Use the first query's metadata/timeRange/stepMs as the base\n if (!timeRange && timeSeriesData.timeRange) {\n timeRange = timeSeriesData.timeRange;\n }\n if (!stepMs && timeSeriesData.stepMs) {\n stepMs = timeSeriesData.stepMs;\n }\n if (!metadata && timeSeriesData.metadata) {\n metadata = timeSeriesData.metadata;\n }\n }\n }\n });\n\n // If we found series, create a combined TimeSeriesData object\n if (allSeries.length > 0) {\n const combinedData: TimeSeriesData = {\n series: allSeries,\n timeRange,\n stepMs,\n metadata,\n };\n\n return combinedData;\n }\n\n return undefined;\n }, [queryResults]);\n\n return (\n <CardHeader\n id={id}\n component=\"header\"\n aria-labelledby={titleElementId}\n aria-describedby={descriptionTooltipId}\n disableTypography\n title={\n <Stack direction=\"row\">\n <Typography\n id={titleElementId}\n variant=\"subtitle1\"\n sx={{\n // `minHeight` guarantees that the header has the correct height\n // when there is no title (i.e. in the preview)\n lineHeight: '24px',\n minHeight: '26px',\n whiteSpace: 'nowrap',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n }}\n >\n {title}\n </Typography>\n <PanelActions\n title={title}\n description={description}\n descriptionTooltipId={descriptionTooltipId}\n links={links}\n queryResults={timeSeriesDataForExport}\n panelPluginKind={panelPluginKind}\n readHandlers={readHandlers}\n editHandlers={editHandlers}\n extra={extra}\n projectName={projectName}\n // ========== ADDED: Pass panel props for actions ==========\n panelProps={panelProps}\n // ========================================================\n />\n </Stack>\n }\n sx={combineSx(\n (theme) => ({\n containerType: 'inline-size',\n containerName: HEADER_ACTIONS_CONTAINER_NAME,\n padding: theme.spacing(1),\n borderBottom: `solid 1px ${theme.palette.divider}`,\n '.MuiCardHeader-content': {\n overflow: 'hidden',\n },\n }),\n sx\n )}\n {...rest}\n />\n );\n}\n"],"names":["CardHeader","Stack","Typography","combineSx","useReplaceVariablesInString","useMemo","HEADER_ACTIONS_CONTAINER_NAME","PanelActions","PanelHeader","id","title","rawTitle","description","rawDescription","links","queryResults","readHandlers","editHandlers","sx","extra","panelPluginKind","projectName","panelProps","rest","titleElementId","descriptionTooltipId","timeSeriesDataForExport","allSeries","timeRange","undefined","stepMs","metadata","forEach","query","data","timeSeriesData","series","length","push","combinedData","component","aria-labelledby","aria-describedby","disableTypography","direction","variant","lineHeight","minHeight","whiteSpace","overflow","textOverflow","theme","containerType","containerName","padding","spacing","borderBottom","palette","divider"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"SaveChangesConfirmationDialog.d.ts","sourceRoot":"","sources":["../../../src/components/SaveChangesConfirmationDialog/SaveChangesConfirmationDialog.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAE,YAAY,EAAY,MAAM,OAAO,CAAC;AAO/C,eAAO,MAAM,6BAA6B,QAAO,YAoFhD,CAAC"}
1
+ {"version":3,"file":"SaveChangesConfirmationDialog.d.ts","sourceRoot":"","sources":["../../../src/components/SaveChangesConfirmationDialog/SaveChangesConfirmationDialog.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAE,YAAY,EAAY,MAAM,OAAO,CAAC;AAO/C,eAAO,MAAM,6BAA6B,QAAO,YAqEhD,CAAC"}
@@ -13,7 +13,7 @@
13
13
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
14
14
  import { useState } from 'react';
15
15
  import { Checkbox, FormGroup, FormControlLabel, Typography } from '@mui/material';
16
- import { useTimeRange, useTimeZone } from '@perses-dev/plugin-system';
16
+ import { useTimeRange } from '@perses-dev/plugin-system';
17
17
  import { isRelativeTimeRange, SAVE_DEFAULTS_DIALOG_TEXT } from '@perses-dev/core';
18
18
  import { Dialog } from '@perses-dev/components';
19
19
  import { useSaveChangesConfirmationDialog, useVariableDefinitionActions } from '../../context';
@@ -21,11 +21,8 @@ export const SaveChangesConfirmationDialog = ()=>{
21
21
  const { saveChangesConfirmationDialog: dialog } = useSaveChangesConfirmationDialog();
22
22
  const isSavedDurationModified = dialog?.isSavedDurationModified ?? true;
23
23
  const isSavedVariableModified = dialog?.isSavedVariableModified ?? true;
24
- const isSavedTimeZoneModified = dialog?.isSavedTimeZoneModified ?? true;
25
24
  const [saveDefaultTimeRange, setSaveDefaultTimeRange] = useState(isSavedDurationModified);
26
25
  const [saveDefaultVariables, setSaveDefaultVariables] = useState(isSavedVariableModified);
27
- const [saveDefaultTimeZone, setSaveDefaultTimeZone] = useState(isSavedTimeZoneModified);
28
- const { timeZone } = useTimeZone();
29
26
  const { getSavedVariablesStatus } = useVariableDefinitionActions();
30
27
  const { modifiedVariableNames } = getSavedVariablesStatus();
31
28
  const isOpen = dialog !== undefined;
@@ -33,7 +30,6 @@ export const SaveChangesConfirmationDialog = ()=>{
33
30
  const currentTimeRangeText = isRelativeTimeRange(timeRange) ? `(Last ${timeRange.pastDuration})` : '(Absolute time ranges can not be saved)';
34
31
  const saveTimeRangeText = `Save current time range as new default ${currentTimeRangeText}`;
35
32
  const saveVariablesText = `Save current variable values as new default (${modifiedVariableNames.length > 0 ? modifiedVariableNames.join(', ') : 'No modified variables'})`;
36
- const saveTimeZoneText = `Save time zone as "${timeZone}" time`;
37
33
  return /*#__PURE__*/ _jsx(Dialog, {
38
34
  open: isOpen,
39
35
  children: dialog !== undefined && /*#__PURE__*/ _jsxs(_Fragment, {
@@ -65,14 +61,6 @@ export const SaveChangesConfirmationDialog = ()=>{
65
61
  onChange: (e)=>setSaveDefaultVariables(e.target.checked)
66
62
  }),
67
63
  label: saveVariablesText
68
- }),
69
- /*#__PURE__*/ _jsx(FormControlLabel, {
70
- control: /*#__PURE__*/ _jsx(Checkbox, {
71
- disabled: !isSavedTimeZoneModified,
72
- checked: saveDefaultTimeZone && isSavedTimeZoneModified,
73
- onChange: (e)=>setSaveDefaultTimeZone(e.target.checked)
74
- }),
75
- label: saveTimeZoneText
76
64
  })
77
65
  ]
78
66
  })
@@ -82,7 +70,7 @@ export const SaveChangesConfirmationDialog = ()=>{
82
70
  children: [
83
71
  /*#__PURE__*/ _jsx(Dialog.PrimaryButton, {
84
72
  onClick: ()=>{
85
- return dialog.onSaveChanges(saveDefaultTimeRange, saveDefaultVariables, saveDefaultTimeZone);
73
+ return dialog.onSaveChanges(saveDefaultTimeRange, saveDefaultVariables);
86
74
  },
87
75
  children: "Save Changes"
88
76
  }),
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/SaveChangesConfirmationDialog/SaveChangesConfirmationDialog.tsx"],"sourcesContent":["// Copyright 2024 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { ReactElement, useState } from 'react';\nimport { Checkbox, FormGroup, FormControlLabel, Typography } from '@mui/material';\nimport { useTimeRange, useTimeZone } from '@perses-dev/plugin-system';\nimport { isRelativeTimeRange, SAVE_DEFAULTS_DIALOG_TEXT } from '@perses-dev/core';\nimport { Dialog } from '@perses-dev/components';\nimport { useSaveChangesConfirmationDialog, useVariableDefinitionActions } from '../../context';\n\nexport const SaveChangesConfirmationDialog = (): ReactElement => {\n const { saveChangesConfirmationDialog: dialog } = useSaveChangesConfirmationDialog();\n const isSavedDurationModified = dialog?.isSavedDurationModified ?? true;\n const isSavedVariableModified = dialog?.isSavedVariableModified ?? true;\n const isSavedTimeZoneModified = dialog?.isSavedTimeZoneModified ?? true;\n const [saveDefaultTimeRange, setSaveDefaultTimeRange] = useState(isSavedDurationModified);\n const [saveDefaultVariables, setSaveDefaultVariables] = useState(isSavedVariableModified);\n const [saveDefaultTimeZone, setSaveDefaultTimeZone] = useState(isSavedTimeZoneModified);\n\n const { timeZone } = useTimeZone();\n const { getSavedVariablesStatus } = useVariableDefinitionActions();\n const { modifiedVariableNames } = getSavedVariablesStatus();\n\n const isOpen = dialog !== undefined;\n\n const { timeRange } = useTimeRange();\n const currentTimeRangeText = isRelativeTimeRange(timeRange)\n ? `(Last ${timeRange.pastDuration})`\n : '(Absolute time ranges can not be saved)';\n\n const saveTimeRangeText = `Save current time range as new default ${currentTimeRangeText}`;\n\n const saveVariablesText = `Save current variable values as new default (${\n modifiedVariableNames.length > 0 ? modifiedVariableNames.join(', ') : 'No modified variables'\n })`;\n\n const saveTimeZoneText = `Save time zone as \"${timeZone}\" time`;\n\n return (\n <Dialog open={isOpen}>\n {dialog !== undefined && (\n <>\n <Dialog.Header onClose={() => dialog.onCancel()}>Save Dashboard</Dialog.Header>\n\n <Dialog.Content>\n <Typography marginBottom={2}>{dialog.description || SAVE_DEFAULTS_DIALOG_TEXT}</Typography>\n <FormGroup>\n <FormControlLabel\n control={\n <Checkbox\n disabled={!isSavedDurationModified || !isRelativeTimeRange(timeRange)}\n checked={saveDefaultTimeRange && isSavedDurationModified && isRelativeTimeRange(timeRange)}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) => setSaveDefaultTimeRange(e.target.checked)}\n />\n }\n label={saveTimeRangeText}\n />\n <FormControlLabel\n control={\n <Checkbox\n disabled={!isSavedVariableModified}\n checked={saveDefaultVariables && isSavedVariableModified}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) => setSaveDefaultVariables(e.target.checked)}\n />\n }\n label={saveVariablesText}\n />\n <FormControlLabel\n control={\n <Checkbox\n disabled={!isSavedTimeZoneModified}\n checked={saveDefaultTimeZone && isSavedTimeZoneModified}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) => setSaveDefaultTimeZone(e.target.checked)}\n />\n }\n label={saveTimeZoneText}\n />\n </FormGroup>\n </Dialog.Content>\n\n <Dialog.Actions>\n <Dialog.PrimaryButton\n onClick={() => {\n return dialog.onSaveChanges(saveDefaultTimeRange, saveDefaultVariables, saveDefaultTimeZone);\n }}\n >\n Save Changes\n </Dialog.PrimaryButton>\n <Dialog.SecondaryButton onClick={() => dialog.onCancel()}>Cancel</Dialog.SecondaryButton>\n </Dialog.Actions>\n </>\n )}\n </Dialog>\n );\n};\n"],"names":["useState","Checkbox","FormGroup","FormControlLabel","Typography","useTimeRange","useTimeZone","isRelativeTimeRange","SAVE_DEFAULTS_DIALOG_TEXT","Dialog","useSaveChangesConfirmationDialog","useVariableDefinitionActions","SaveChangesConfirmationDialog","saveChangesConfirmationDialog","dialog","isSavedDurationModified","isSavedVariableModified","isSavedTimeZoneModified","saveDefaultTimeRange","setSaveDefaultTimeRange","saveDefaultVariables","setSaveDefaultVariables","saveDefaultTimeZone","setSaveDefaultTimeZone","timeZone","getSavedVariablesStatus","modifiedVariableNames","isOpen","undefined","timeRange","currentTimeRangeText","pastDuration","saveTimeRangeText","saveVariablesText","length","join","saveTimeZoneText","open","Header","onClose","onCancel","Content","marginBottom","description","control","disabled","checked","onChange","e","target","label","Actions","PrimaryButton","onClick","onSaveChanges","SecondaryButton"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/components/SaveChangesConfirmationDialog/SaveChangesConfirmationDialog.tsx"],"sourcesContent":["// Copyright 2024 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { ReactElement, useState } from 'react';\nimport { Checkbox, FormGroup, FormControlLabel, Typography } from '@mui/material';\nimport { useTimeRange } from '@perses-dev/plugin-system';\nimport { isRelativeTimeRange, SAVE_DEFAULTS_DIALOG_TEXT } from '@perses-dev/core';\nimport { Dialog } from '@perses-dev/components';\nimport { useSaveChangesConfirmationDialog, useVariableDefinitionActions } from '../../context';\n\nexport const SaveChangesConfirmationDialog = (): ReactElement => {\n const { saveChangesConfirmationDialog: dialog } = useSaveChangesConfirmationDialog();\n const isSavedDurationModified = dialog?.isSavedDurationModified ?? true;\n const isSavedVariableModified = dialog?.isSavedVariableModified ?? true;\n const [saveDefaultTimeRange, setSaveDefaultTimeRange] = useState(isSavedDurationModified);\n const [saveDefaultVariables, setSaveDefaultVariables] = useState(isSavedVariableModified);\n\n const { getSavedVariablesStatus } = useVariableDefinitionActions();\n const { modifiedVariableNames } = getSavedVariablesStatus();\n\n const isOpen = dialog !== undefined;\n\n const { timeRange } = useTimeRange();\n const currentTimeRangeText = isRelativeTimeRange(timeRange)\n ? `(Last ${timeRange.pastDuration})`\n : '(Absolute time ranges can not be saved)';\n\n const saveTimeRangeText = `Save current time range as new default ${currentTimeRangeText}`;\n\n const saveVariablesText = `Save current variable values as new default (${\n modifiedVariableNames.length > 0 ? modifiedVariableNames.join(', ') : 'No modified variables'\n })`;\n\n return (\n <Dialog open={isOpen}>\n {dialog !== undefined && (\n <>\n <Dialog.Header onClose={() => dialog.onCancel()}>Save Dashboard</Dialog.Header>\n\n <Dialog.Content>\n <Typography marginBottom={2}>{dialog.description || SAVE_DEFAULTS_DIALOG_TEXT}</Typography>\n <FormGroup>\n <FormControlLabel\n control={\n <Checkbox\n disabled={!isSavedDurationModified || !isRelativeTimeRange(timeRange)}\n checked={saveDefaultTimeRange && isSavedDurationModified && isRelativeTimeRange(timeRange)}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) => setSaveDefaultTimeRange(e.target.checked)}\n />\n }\n label={saveTimeRangeText}\n />\n <FormControlLabel\n control={\n <Checkbox\n disabled={!isSavedVariableModified}\n checked={saveDefaultVariables && isSavedVariableModified}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) => setSaveDefaultVariables(e.target.checked)}\n />\n }\n label={saveVariablesText}\n />\n </FormGroup>\n </Dialog.Content>\n\n <Dialog.Actions>\n <Dialog.PrimaryButton\n onClick={() => {\n return dialog.onSaveChanges(saveDefaultTimeRange, saveDefaultVariables);\n }}\n >\n Save Changes\n </Dialog.PrimaryButton>\n <Dialog.SecondaryButton onClick={() => dialog.onCancel()}>Cancel</Dialog.SecondaryButton>\n </Dialog.Actions>\n </>\n )}\n </Dialog>\n );\n};\n"],"names":["useState","Checkbox","FormGroup","FormControlLabel","Typography","useTimeRange","isRelativeTimeRange","SAVE_DEFAULTS_DIALOG_TEXT","Dialog","useSaveChangesConfirmationDialog","useVariableDefinitionActions","SaveChangesConfirmationDialog","saveChangesConfirmationDialog","dialog","isSavedDurationModified","isSavedVariableModified","saveDefaultTimeRange","setSaveDefaultTimeRange","saveDefaultVariables","setSaveDefaultVariables","getSavedVariablesStatus","modifiedVariableNames","isOpen","undefined","timeRange","currentTimeRangeText","pastDuration","saveTimeRangeText","saveVariablesText","length","join","open","Header","onClose","onCancel","Content","marginBottom","description","control","disabled","checked","onChange","e","target","label","Actions","PrimaryButton","onClick","onSaveChanges","SecondaryButton"],"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,SAAuBA,QAAQ,QAAQ,QAAQ;AAC/C,SAASC,QAAQ,EAAEC,SAAS,EAAEC,gBAAgB,EAAEC,UAAU,QAAQ,gBAAgB;AAClF,SAASC,YAAY,QAAQ,4BAA4B;AACzD,SAASC,mBAAmB,EAAEC,yBAAyB,QAAQ,mBAAmB;AAClF,SAASC,MAAM,QAAQ,yBAAyB;AAChD,SAASC,gCAAgC,EAAEC,4BAA4B,QAAQ,gBAAgB;AAE/F,OAAO,MAAMC,gCAAgC;IAC3C,MAAM,EAAEC,+BAA+BC,MAAM,EAAE,GAAGJ;IAClD,MAAMK,0BAA0BD,QAAQC,2BAA2B;IACnE,MAAMC,0BAA0BF,QAAQE,2BAA2B;IACnE,MAAM,CAACC,sBAAsBC,wBAAwB,GAAGjB,SAASc;IACjE,MAAM,CAACI,sBAAsBC,wBAAwB,GAAGnB,SAASe;IAEjE,MAAM,EAAEK,uBAAuB,EAAE,GAAGV;IACpC,MAAM,EAAEW,qBAAqB,EAAE,GAAGD;IAElC,MAAME,SAAST,WAAWU;IAE1B,MAAM,EAAEC,SAAS,EAAE,GAAGnB;IACtB,MAAMoB,uBAAuBnB,oBAAoBkB,aAC7C,CAAC,MAAM,EAAEA,UAAUE,YAAY,CAAC,CAAC,CAAC,GAClC;IAEJ,MAAMC,oBAAoB,CAAC,uCAAuC,EAAEF,sBAAsB;IAE1F,MAAMG,oBAAoB,CAAC,6CAA6C,EACtEP,sBAAsBQ,MAAM,GAAG,IAAIR,sBAAsBS,IAAI,CAAC,QAAQ,wBACvE,CAAC,CAAC;IAEH,qBACE,KAACtB;QAAOuB,MAAMT;kBACXT,WAAWU,2BACV;;8BACE,KAACf,OAAOwB,MAAM;oBAACC,SAAS,IAAMpB,OAAOqB,QAAQ;8BAAI;;8BAEjD,MAAC1B,OAAO2B,OAAO;;sCACb,KAAC/B;4BAAWgC,cAAc;sCAAIvB,OAAOwB,WAAW,IAAI9B;;sCACpD,MAACL;;8CACC,KAACC;oCACCmC,uBACE,KAACrC;wCACCsC,UAAU,CAACzB,2BAA2B,CAACR,oBAAoBkB;wCAC3DgB,SAASxB,wBAAwBF,2BAA2BR,oBAAoBkB;wCAChFiB,UAAU,CAACC,IAA2CzB,wBAAwByB,EAAEC,MAAM,CAACH,OAAO;;oCAGlGI,OAAOjB;;8CAET,KAACxB;oCACCmC,uBACE,KAACrC;wCACCsC,UAAU,CAACxB;wCACXyB,SAAStB,wBAAwBH;wCACjC0B,UAAU,CAACC,IAA2CvB,wBAAwBuB,EAAEC,MAAM,CAACH,OAAO;;oCAGlGI,OAAOhB;;;;;;8BAKb,MAACpB,OAAOqC,OAAO;;sCACb,KAACrC,OAAOsC,aAAa;4BACnBC,SAAS;gCACP,OAAOlC,OAAOmC,aAAa,CAAChC,sBAAsBE;4BACpD;sCACD;;sCAGD,KAACV,OAAOyC,eAAe;4BAACF,SAAS,IAAMlC,OAAOqB,QAAQ;sCAAI;;;;;;;AAMtE,EAAE"}
@@ -1 +1 @@
1
- {"version":3,"file":"SaveDashboardButton.d.ts","sourceRoot":"","sources":["../../../src/components/SaveDashboardButton/SaveDashboardButton.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAE,YAAY,EAAY,MAAM,OAAO,CAAC;AAC/C,OAAO,EAAU,WAAW,EAAE,MAAM,eAAe,CAAC;AAGpD,OAAO,EACL,eAAe,EAKhB,MAAM,eAAe,CAAC;AAEvB,MAAM,WAAW,wBAAyB,SAAQ,IAAI,CAAC,WAAW,EAAE,WAAW,CAAC;IAC9E,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,UAAU,CAAC;CAC7C;AAED,eAAO,MAAM,mBAAmB,qCAI7B,wBAAwB,KAAG,YAsE7B,CAAC"}
1
+ {"version":3,"file":"SaveDashboardButton.d.ts","sourceRoot":"","sources":["../../../src/components/SaveDashboardButton/SaveDashboardButton.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAE,YAAY,EAAY,MAAM,OAAO,CAAC;AAC/C,OAAO,EAAU,WAAW,EAAE,MAAM,eAAe,CAAC;AAGpD,OAAO,EACL,eAAe,EAKhB,MAAM,eAAe,CAAC;AAEvB,MAAM,WAAW,wBAAyB,SAAQ,IAAI,CAAC,WAAW,EAAE,WAAW,CAAC;IAC9E,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,UAAU,CAAC;CAC7C;AAED,eAAO,MAAM,mBAAmB,qCAI7B,wBAAwB,KAAG,YA8D7B,CAAC"}
@@ -14,7 +14,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
14
14
  import { useState } from 'react';
15
15
  import { Button } from '@mui/material';
16
16
  import { isRelativeTimeRange } from '@perses-dev/core';
17
- import { useTimeRange, useTimeZone } from '@perses-dev/plugin-system';
17
+ import { useTimeRange } from '@perses-dev/plugin-system';
18
18
  import { useDashboard, useEditMode, useSaveChangesConfirmationDialog, useVariableDefinitionActions } from '../../context';
19
19
  export const SaveDashboardButton = ({ onSave, isDisabled, variant = 'contained' })=>{
20
20
  const [isSavingDashboard, setSavingDashboard] = useState(false);
@@ -24,17 +24,14 @@ export const SaveDashboardButton = ({ onSave, isDisabled, variant = 'contained'
24
24
  const { timeRange } = useTimeRange();
25
25
  const { setEditMode } = useEditMode();
26
26
  const { openSaveChangesConfirmationDialog, closeSaveChangesConfirmationDialog } = useSaveChangesConfirmationDialog();
27
- const { timeZone: currentTimeZone } = useTimeZone();
28
27
  const onSaveButtonClick = ()=>{
29
28
  const isSavedDurationModified = isRelativeTimeRange(timeRange) && dashboard.spec.duration !== timeRange.pastDuration;
30
- const isSavedTimeZoneModified = dashboard.spec.timeZone !== currentTimeZone;
31
29
  // Save dashboard
32
30
  // - if active timeRange from plugin-system is relative and different from currently saved
33
31
  // - or if the saved variables are different from currently saved
34
- // - or if the saved timeZone are different from currently saved
35
- if (isSavedDurationModified || isSavedVariableModified || isSavedTimeZoneModified) {
32
+ if (isSavedDurationModified || isSavedVariableModified) {
36
33
  openSaveChangesConfirmationDialog({
37
- onSaveChanges: (saveDefaultTimeRange, saveDefaultVariables, isSavedTimeZone)=>{
34
+ onSaveChanges: (saveDefaultTimeRange, saveDefaultVariables)=>{
38
35
  if (isRelativeTimeRange(timeRange) && saveDefaultTimeRange === true) {
39
36
  dashboard.spec.duration = timeRange.pastDuration;
40
37
  }
@@ -42,9 +39,6 @@ export const SaveDashboardButton = ({ onSave, isDisabled, variant = 'contained'
42
39
  const variables = setVariableDefaultValues();
43
40
  dashboard.spec.variables = variables;
44
41
  }
45
- if (isSavedTimeZone) {
46
- dashboard.spec.timeZone = currentTimeZone;
47
- }
48
42
  setDashboard(dashboard);
49
43
  saveDashboard();
50
44
  },
@@ -52,8 +46,7 @@ export const SaveDashboardButton = ({ onSave, isDisabled, variant = 'contained'
52
46
  closeSaveChangesConfirmationDialog();
53
47
  },
54
48
  isSavedDurationModified,
55
- isSavedVariableModified,
56
- isSavedTimeZoneModified
49
+ isSavedVariableModified
57
50
  });
58
51
  } else {
59
52
  saveDashboard();