@perses-dev/dashboards 0.54.0-beta.1 → 0.54.0-beta.3

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 (115) hide show
  1. package/dist/cjs/components/Panel/Panel.js +4 -1
  2. package/dist/cjs/components/Variables/VariableEditor.js +51 -17
  3. package/dist/cjs/context/DatasourceStoreProvider.js +4 -1
  4. package/dist/cjs/context/VariableProvider/VariableProvider.js +10 -6
  5. package/dist/components/AddGroupButton/AddGroupButton.js +1 -1
  6. package/dist/components/AddGroupButton/AddGroupButton.js.map +1 -1
  7. package/dist/components/AddPanelButton/AddPanelButton.js +1 -1
  8. package/dist/components/AddPanelButton/AddPanelButton.js.map +1 -1
  9. package/dist/components/Dashboard/Dashboard.js +1 -1
  10. package/dist/components/Dashboard/Dashboard.js.map +1 -1
  11. package/dist/components/DashboardLinks/DashboardLinksEditor.js +1 -1
  12. package/dist/components/DashboardLinks/DashboardLinksEditor.js.map +1 -1
  13. package/dist/components/DashboardLinks/EditDashboardLinksButton.js +1 -1
  14. package/dist/components/DashboardLinks/EditDashboardLinksButton.js.map +1 -1
  15. package/dist/components/DashboardStickyToolbar/DashboardStickyToolbar.js +1 -1
  16. package/dist/components/DashboardStickyToolbar/DashboardStickyToolbar.js.map +1 -1
  17. package/dist/components/DashboardToolbar/DashboardToolbar.js +1 -1
  18. package/dist/components/DashboardToolbar/DashboardToolbar.js.map +1 -1
  19. package/dist/components/Datasources/DatasourceEditor.d.ts.map +1 -1
  20. package/dist/components/Datasources/DatasourceEditor.js +1 -1
  21. package/dist/components/Datasources/DatasourceEditor.js.map +1 -1
  22. package/dist/components/Datasources/EditDatasourcesButton.js +1 -1
  23. package/dist/components/Datasources/EditDatasourcesButton.js.map +1 -1
  24. package/dist/components/DiscardChangesConfirmationDialog/DiscardChangesConfirmationDialog.js +1 -1
  25. package/dist/components/DiscardChangesConfirmationDialog/DiscardChangesConfirmationDialog.js.map +1 -1
  26. package/dist/components/DownloadButton/DownloadButton.js +1 -1
  27. package/dist/components/DownloadButton/DownloadButton.js.map +1 -1
  28. package/dist/components/EditButton/EditButton.js +1 -1
  29. package/dist/components/EditButton/EditButton.js.map +1 -1
  30. package/dist/components/EditJsonButton/EditJsonButton.js +1 -1
  31. package/dist/components/EditJsonButton/EditJsonButton.js.map +1 -1
  32. package/dist/components/EditJsonDialog/EditJsonDialog.js +1 -1
  33. package/dist/components/EditJsonDialog/EditJsonDialog.js.map +1 -1
  34. package/dist/components/EmptyDashboard/EmptyDashboard.js +1 -1
  35. package/dist/components/EmptyDashboard/EmptyDashboard.js.map +1 -1
  36. package/dist/components/GridLayout/GridContainer.js +1 -1
  37. package/dist/components/GridLayout/GridContainer.js.map +1 -1
  38. package/dist/components/GridLayout/GridItemContent.js +1 -1
  39. package/dist/components/GridLayout/GridItemContent.js.map +1 -1
  40. package/dist/components/GridLayout/GridLayout.js +1 -1
  41. package/dist/components/GridLayout/GridLayout.js.map +1 -1
  42. package/dist/components/GridLayout/GridTitle.js +1 -1
  43. package/dist/components/GridLayout/GridTitle.js.map +1 -1
  44. package/dist/components/GridLayout/Row.js +1 -1
  45. package/dist/components/GridLayout/Row.js.map +1 -1
  46. package/dist/components/LeaveDialog/LeaveDialog.js +1 -1
  47. package/dist/components/LeaveDialog/LeaveDialog.js.map +1 -1
  48. package/dist/components/LinksDisplay/LinksDisplay.js +1 -1
  49. package/dist/components/LinksDisplay/LinksDisplay.js.map +1 -1
  50. package/dist/components/Panel/Panel.js +5 -2
  51. package/dist/components/Panel/Panel.js.map +1 -1
  52. package/dist/components/Panel/PanelActions.js +1 -1
  53. package/dist/components/Panel/PanelActions.js.map +1 -1
  54. package/dist/components/Panel/PanelContent.js +1 -1
  55. package/dist/components/Panel/PanelContent.js.map +1 -1
  56. package/dist/components/Panel/PanelHeader.js +1 -1
  57. package/dist/components/Panel/PanelHeader.js.map +1 -1
  58. package/dist/components/Panel/PanelPluginLoader.js +1 -1
  59. package/dist/components/Panel/PanelPluginLoader.js.map +1 -1
  60. package/dist/components/Panel/useSelectionItemActions.js +1 -1
  61. package/dist/components/Panel/useSelectionItemActions.js.map +1 -1
  62. package/dist/components/PanelDrawer/PanelDrawer.js +1 -1
  63. package/dist/components/PanelDrawer/PanelDrawer.js.map +1 -1
  64. package/dist/components/PanelDrawer/PanelEditorForm.js +1 -1
  65. package/dist/components/PanelDrawer/PanelEditorForm.js.map +1 -1
  66. package/dist/components/PanelDrawer/PanelPreview.js +1 -1
  67. package/dist/components/PanelDrawer/PanelPreview.js.map +1 -1
  68. package/dist/components/PanelDrawer/PanelQueriesSharedControls.js +1 -1
  69. package/dist/components/PanelDrawer/PanelQueriesSharedControls.js.map +1 -1
  70. package/dist/components/PanelGroupDialog/PanelGroupDialog.js +1 -1
  71. package/dist/components/PanelGroupDialog/PanelGroupDialog.js.map +1 -1
  72. package/dist/components/PanelGroupDialog/PanelGroupEditorForm.js +1 -1
  73. package/dist/components/PanelGroupDialog/PanelGroupEditorForm.js.map +1 -1
  74. package/dist/components/QuerySummaryTable/QuerySummaryTable.js +1 -1
  75. package/dist/components/QuerySummaryTable/QuerySummaryTable.js.map +1 -1
  76. package/dist/components/QueryViewerDialog/QueryViewerDialog.js +1 -1
  77. package/dist/components/QueryViewerDialog/QueryViewerDialog.js.map +1 -1
  78. package/dist/components/SaveChangesConfirmationDialog/SaveChangesConfirmationDialog.js +1 -1
  79. package/dist/components/SaveChangesConfirmationDialog/SaveChangesConfirmationDialog.js.map +1 -1
  80. package/dist/components/Variables/EditVariablesButton.js +1 -1
  81. package/dist/components/Variables/EditVariablesButton.js.map +1 -1
  82. package/dist/components/Variables/ListVariableListBox.js +1 -1
  83. package/dist/components/Variables/ListVariableListBox.js.map +1 -1
  84. package/dist/components/Variables/Variable.js +2 -2
  85. package/dist/components/Variables/Variable.js.map +1 -1
  86. package/dist/components/Variables/VariableEditor.d.ts.map +1 -1
  87. package/dist/components/Variables/VariableEditor.js +56 -22
  88. package/dist/components/Variables/VariableEditor.js.map +1 -1
  89. package/dist/components/Variables/VariableList.js +1 -1
  90. package/dist/components/Variables/VariableList.js.map +1 -1
  91. package/dist/context/DashboardProvider/DashboardProvider.d.ts.map +1 -1
  92. package/dist/context/DashboardProvider/DashboardProvider.js +1 -1
  93. package/dist/context/DashboardProvider/DashboardProvider.js.map +1 -1
  94. package/dist/context/DatasourceStoreProvider.d.ts +1 -1
  95. package/dist/context/DatasourceStoreProvider.d.ts.map +1 -1
  96. package/dist/context/DatasourceStoreProvider.js +5 -2
  97. package/dist/context/DatasourceStoreProvider.js.map +1 -1
  98. package/dist/context/PanelEditorProvider/PanelEditorProvider.js +1 -1
  99. package/dist/context/PanelEditorProvider/PanelEditorProvider.js.map +1 -1
  100. package/dist/context/VariableProvider/VariableProvider.d.ts +2 -1
  101. package/dist/context/VariableProvider/VariableProvider.d.ts.map +1 -1
  102. package/dist/context/VariableProvider/VariableProvider.js +12 -8
  103. package/dist/context/VariableProvider/VariableProvider.js.map +1 -1
  104. package/dist/keyboard-shortcuts/PanelFocusProvider.js +1 -1
  105. package/dist/keyboard-shortcuts/PanelFocusProvider.js.map +1 -1
  106. package/dist/test/datasource-provider.d.ts +1 -1
  107. package/dist/test/datasource-provider.d.ts.map +1 -1
  108. package/dist/test/datasource-provider.js.map +1 -1
  109. package/dist/test/render.js +1 -1
  110. package/dist/test/render.js.map +1 -1
  111. package/dist/views/ViewDashboard/DashboardApp.js +1 -1
  112. package/dist/views/ViewDashboard/DashboardApp.js.map +1 -1
  113. package/dist/views/ViewDashboard/ViewDashboard.js +1 -1
  114. package/dist/views/ViewDashboard/ViewDashboard.js.map +1 -1
  115. package/package.json +6 -9
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/GridLayout/GridTitle.tsx"],"sourcesContent":["// Copyright 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 { Box, IconButton, Stack, Typography } from '@mui/material';\nimport ExpandedIcon from 'mdi-material-ui/ChevronDown';\nimport CollapsedIcon from 'mdi-material-ui/ChevronRight';\nimport AddPanelIcon from 'mdi-material-ui/ChartBoxPlusOutline';\nimport PencilIcon from 'mdi-material-ui/PencilOutline';\nimport ArrowUpIcon from 'mdi-material-ui/ArrowUp';\nimport ArrowDownIcon from 'mdi-material-ui/ArrowDown';\nimport DeleteIcon from 'mdi-material-ui/DeleteOutline';\nimport { InfoTooltip } from '@perses-dev/components';\nimport { useReplaceVariablesInString } from '@perses-dev/plugin-system';\nimport { PanelGroupId } from '@perses-dev/spec';\nimport { ReactElement } from 'react';\nimport { ARIA_LABEL_TEXT, TOOLTIP_TEXT } from '../../constants';\nimport { usePanelGroupActions, useEditMode, useDeletePanelGroupDialog } from '../../context';\n\nexport interface GridTitleProps {\n panelGroupId: PanelGroupId;\n title: string;\n collapse?: {\n isOpen: boolean;\n onToggleOpen: () => void;\n };\n}\n\n/**\n * Renders the title for a Grid section, optionally also supporting expanding\n * and collapsing\n */\nexport function GridTitle(props: GridTitleProps): ReactElement {\n const { panelGroupId, title: rawTitle, collapse } = props;\n\n const title = useReplaceVariablesInString(rawTitle) as string;\n\n const { openAddPanel, openEditPanelGroup, moveUp, moveDown } = usePanelGroupActions(panelGroupId);\n const { openDeletePanelGroupDialog } = useDeletePanelGroupDialog();\n const { isEditMode } = useEditMode();\n\n const text = <Typography variant=\"h2\">{title}</Typography>;\n\n return (\n <Box\n onClick={collapse?.onToggleOpen}\n sx={{\n display: 'flex',\n justifyContent: 'start',\n alignItems: 'center',\n cursor: collapse ? 'pointer' : 'auto',\n backgroundColor: ({ palette }) => palette.background.paper,\n }}\n data-testid=\"panel-group-header\"\n >\n {collapse ? (\n <>\n <IconButton sx={{ marginRight: 1 }} aria-label={`${collapse.isOpen ? 'collapse' : 'expand'} group ${title}`}>\n {collapse.isOpen ? <ExpandedIcon /> : <CollapsedIcon />}\n </IconButton>\n {text}\n {isEditMode && (\n <Stack direction=\"row\" marginLeft=\"auto\">\n <InfoTooltip description={TOOLTIP_TEXT.addPanelToGroup}>\n <IconButton\n aria-label={ARIA_LABEL_TEXT.addPanelToGroup(title)}\n onClick={(e) => {\n // Don't trigger expand/collapse\n e.stopPropagation();\n openAddPanel();\n }}\n >\n <AddPanelIcon />\n </IconButton>\n </InfoTooltip>\n <InfoTooltip description={TOOLTIP_TEXT.editGroup}>\n <IconButton\n aria-label={ARIA_LABEL_TEXT.editGroup(title)}\n onClick={(e) => {\n // Don't trigger expand/collapse\n e.stopPropagation();\n openEditPanelGroup();\n }}\n >\n <PencilIcon />\n </IconButton>\n </InfoTooltip>\n <InfoTooltip description={TOOLTIP_TEXT.deleteGroup}>\n <IconButton\n aria-label={ARIA_LABEL_TEXT.deleteGroup(title)}\n onClick={(e) => {\n // Don't trigger expand/collapse\n e.stopPropagation();\n openDeletePanelGroupDialog(panelGroupId);\n }}\n >\n <DeleteIcon />\n </IconButton>\n </InfoTooltip>\n <InfoTooltip description={TOOLTIP_TEXT.moveGroupDown}>\n <IconButton\n aria-label={ARIA_LABEL_TEXT.moveGroupDown(title)}\n disabled={moveDown === undefined}\n onClick={(e) => {\n // Don't trigger expand/collapse\n e.stopPropagation();\n moveDown?.();\n }}\n >\n <ArrowDownIcon />\n </IconButton>\n </InfoTooltip>\n <InfoTooltip description={TOOLTIP_TEXT.moveGroupUp}>\n <IconButton\n aria-label={ARIA_LABEL_TEXT.moveGroupUp(title)}\n disabled={moveUp === undefined}\n onClick={(e) => {\n // Don't trigger expand/collapse\n e.stopPropagation();\n moveUp?.();\n }}\n >\n <ArrowUpIcon />\n </IconButton>\n </InfoTooltip>\n </Stack>\n )}\n </>\n ) : (\n // If we don't need expand/collapse, just render the title text\n text\n )}\n </Box>\n );\n}\n"],"names":["Box","IconButton","Stack","Typography","ExpandedIcon","CollapsedIcon","AddPanelIcon","PencilIcon","ArrowUpIcon","ArrowDownIcon","DeleteIcon","InfoTooltip","useReplaceVariablesInString","ARIA_LABEL_TEXT","TOOLTIP_TEXT","usePanelGroupActions","useEditMode","useDeletePanelGroupDialog","GridTitle","props","panelGroupId","title","rawTitle","collapse","openAddPanel","openEditPanelGroup","moveUp","moveDown","openDeletePanelGroupDialog","isEditMode","text","variant","onClick","onToggleOpen","sx","display","justifyContent","alignItems","cursor","backgroundColor","palette","background","paper","data-testid","marginRight","aria-label","isOpen","direction","marginLeft","description","addPanelToGroup","e","stopPropagation","editGroup","deleteGroup","moveGroupDown","disabled","undefined","moveGroupUp"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/components/GridLayout/GridTitle.tsx"],"sourcesContent":["// Copyright 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 { Box, IconButton, Stack, Typography } from '@mui/material';\nimport ExpandedIcon from 'mdi-material-ui/ChevronDown';\nimport CollapsedIcon from 'mdi-material-ui/ChevronRight';\nimport AddPanelIcon from 'mdi-material-ui/ChartBoxPlusOutline';\nimport PencilIcon from 'mdi-material-ui/PencilOutline';\nimport ArrowUpIcon from 'mdi-material-ui/ArrowUp';\nimport ArrowDownIcon from 'mdi-material-ui/ArrowDown';\nimport DeleteIcon from 'mdi-material-ui/DeleteOutline';\nimport { InfoTooltip } from '@perses-dev/components';\nimport { useReplaceVariablesInString } from '@perses-dev/plugin-system';\nimport { PanelGroupId } from '@perses-dev/spec';\nimport { ReactElement } from 'react';\nimport { ARIA_LABEL_TEXT, TOOLTIP_TEXT } from '../../constants';\nimport { usePanelGroupActions, useEditMode, useDeletePanelGroupDialog } from '../../context';\n\nexport interface GridTitleProps {\n panelGroupId: PanelGroupId;\n title: string;\n collapse?: {\n isOpen: boolean;\n onToggleOpen: () => void;\n };\n}\n\n/**\n * Renders the title for a Grid section, optionally also supporting expanding\n * and collapsing\n */\nexport function GridTitle(props: GridTitleProps): ReactElement {\n const { panelGroupId, title: rawTitle, collapse } = props;\n\n const title = useReplaceVariablesInString(rawTitle) as string;\n\n const { openAddPanel, openEditPanelGroup, moveUp, moveDown } = usePanelGroupActions(panelGroupId);\n const { openDeletePanelGroupDialog } = useDeletePanelGroupDialog();\n const { isEditMode } = useEditMode();\n\n const text = <Typography variant=\"h2\">{title}</Typography>;\n\n return (\n <Box\n onClick={collapse?.onToggleOpen}\n sx={{\n display: 'flex',\n justifyContent: 'start',\n alignItems: 'center',\n cursor: collapse ? 'pointer' : 'auto',\n backgroundColor: ({ palette }) => palette.background.paper,\n }}\n data-testid=\"panel-group-header\"\n >\n {collapse ? (\n <>\n <IconButton sx={{ marginRight: 1 }} aria-label={`${collapse.isOpen ? 'collapse' : 'expand'} group ${title}`}>\n {collapse.isOpen ? <ExpandedIcon /> : <CollapsedIcon />}\n </IconButton>\n {text}\n {isEditMode && (\n <Stack direction=\"row\" marginLeft=\"auto\">\n <InfoTooltip description={TOOLTIP_TEXT.addPanelToGroup}>\n <IconButton\n aria-label={ARIA_LABEL_TEXT.addPanelToGroup(title)}\n onClick={(e) => {\n // Don't trigger expand/collapse\n e.stopPropagation();\n openAddPanel();\n }}\n >\n <AddPanelIcon />\n </IconButton>\n </InfoTooltip>\n <InfoTooltip description={TOOLTIP_TEXT.editGroup}>\n <IconButton\n aria-label={ARIA_LABEL_TEXT.editGroup(title)}\n onClick={(e) => {\n // Don't trigger expand/collapse\n e.stopPropagation();\n openEditPanelGroup();\n }}\n >\n <PencilIcon />\n </IconButton>\n </InfoTooltip>\n <InfoTooltip description={TOOLTIP_TEXT.deleteGroup}>\n <IconButton\n aria-label={ARIA_LABEL_TEXT.deleteGroup(title)}\n onClick={(e) => {\n // Don't trigger expand/collapse\n e.stopPropagation();\n openDeletePanelGroupDialog(panelGroupId);\n }}\n >\n <DeleteIcon />\n </IconButton>\n </InfoTooltip>\n <InfoTooltip description={TOOLTIP_TEXT.moveGroupDown}>\n <IconButton\n aria-label={ARIA_LABEL_TEXT.moveGroupDown(title)}\n disabled={moveDown === undefined}\n onClick={(e) => {\n // Don't trigger expand/collapse\n e.stopPropagation();\n moveDown?.();\n }}\n >\n <ArrowDownIcon />\n </IconButton>\n </InfoTooltip>\n <InfoTooltip description={TOOLTIP_TEXT.moveGroupUp}>\n <IconButton\n aria-label={ARIA_LABEL_TEXT.moveGroupUp(title)}\n disabled={moveUp === undefined}\n onClick={(e) => {\n // Don't trigger expand/collapse\n e.stopPropagation();\n moveUp?.();\n }}\n >\n <ArrowUpIcon />\n </IconButton>\n </InfoTooltip>\n </Stack>\n )}\n </>\n ) : (\n // If we don't need expand/collapse, just render the title text\n text\n )}\n </Box>\n );\n}\n"],"names":["Box","IconButton","Stack","Typography","ExpandedIcon","CollapsedIcon","AddPanelIcon","PencilIcon","ArrowUpIcon","ArrowDownIcon","DeleteIcon","InfoTooltip","useReplaceVariablesInString","ARIA_LABEL_TEXT","TOOLTIP_TEXT","usePanelGroupActions","useEditMode","useDeletePanelGroupDialog","GridTitle","props","panelGroupId","title","rawTitle","collapse","openAddPanel","openEditPanelGroup","moveUp","moveDown","openDeletePanelGroupDialog","isEditMode","text","variant","onClick","onToggleOpen","sx","display","justifyContent","alignItems","cursor","backgroundColor","palette","background","paper","data-testid","marginRight","aria-label","isOpen","direction","marginLeft","description","addPanelToGroup","e","stopPropagation","editGroup","deleteGroup","moveGroupDown","disabled","undefined","moveGroupUp"],"mappings":";AAAA,+BAA+B;AAC/B,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;AAEjC,SAASA,GAAG,EAAEC,UAAU,EAAEC,KAAK,EAAEC,UAAU,QAAQ,gBAAgB;AACnE,OAAOC,kBAAkB,8BAA8B;AACvD,OAAOC,mBAAmB,+BAA+B;AACzD,OAAOC,kBAAkB,sCAAsC;AAC/D,OAAOC,gBAAgB,gCAAgC;AACvD,OAAOC,iBAAiB,0BAA0B;AAClD,OAAOC,mBAAmB,4BAA4B;AACtD,OAAOC,gBAAgB,gCAAgC;AACvD,SAASC,WAAW,QAAQ,yBAAyB;AACrD,SAASC,2BAA2B,QAAQ,4BAA4B;AAGxE,SAASC,eAAe,EAAEC,YAAY,QAAQ,kBAAkB;AAChE,SAASC,oBAAoB,EAAEC,WAAW,EAAEC,yBAAyB,QAAQ,gBAAgB;AAW7F;;;CAGC,GACD,OAAO,SAASC,UAAUC,KAAqB;IAC7C,MAAM,EAAEC,YAAY,EAAEC,OAAOC,QAAQ,EAAEC,QAAQ,EAAE,GAAGJ;IAEpD,MAAME,QAAQT,4BAA4BU;IAE1C,MAAM,EAAEE,YAAY,EAAEC,kBAAkB,EAAEC,MAAM,EAAEC,QAAQ,EAAE,GAAGZ,qBAAqBK;IACpF,MAAM,EAAEQ,0BAA0B,EAAE,GAAGX;IACvC,MAAM,EAAEY,UAAU,EAAE,GAAGb;IAEvB,MAAMc,qBAAO,KAAC3B;QAAW4B,SAAQ;kBAAMV;;IAEvC,qBACE,KAACrB;QACCgC,SAAST,UAAUU;QACnBC,IAAI;YACFC,SAAS;YACTC,gBAAgB;YAChBC,YAAY;YACZC,QAAQf,WAAW,YAAY;YAC/BgB,iBAAiB,CAAC,EAAEC,OAAO,EAAE,GAAKA,QAAQC,UAAU,CAACC,KAAK;QAC5D;QACAC,eAAY;kBAEXpB,yBACC;;8BACE,KAACtB;oBAAWiC,IAAI;wBAAEU,aAAa;oBAAE;oBAAGC,cAAY,GAAGtB,SAASuB,MAAM,GAAG,aAAa,SAAS,OAAO,EAAEzB,OAAO;8BACxGE,SAASuB,MAAM,iBAAG,KAAC1C,kCAAkB,KAACC;;gBAExCyB;gBACAD,4BACC,MAAC3B;oBAAM6C,WAAU;oBAAMC,YAAW;;sCAChC,KAACrC;4BAAYsC,aAAanC,aAAaoC,eAAe;sCACpD,cAAA,KAACjD;gCACC4C,cAAYhC,gBAAgBqC,eAAe,CAAC7B;gCAC5CW,SAAS,CAACmB;oCACR,gCAAgC;oCAChCA,EAAEC,eAAe;oCACjB5B;gCACF;0CAEA,cAAA,KAAClB;;;sCAGL,KAACK;4BAAYsC,aAAanC,aAAauC,SAAS;sCAC9C,cAAA,KAACpD;gCACC4C,cAAYhC,gBAAgBwC,SAAS,CAAChC;gCACtCW,SAAS,CAACmB;oCACR,gCAAgC;oCAChCA,EAAEC,eAAe;oCACjB3B;gCACF;0CAEA,cAAA,KAAClB;;;sCAGL,KAACI;4BAAYsC,aAAanC,aAAawC,WAAW;sCAChD,cAAA,KAACrD;gCACC4C,cAAYhC,gBAAgByC,WAAW,CAACjC;gCACxCW,SAAS,CAACmB;oCACR,gCAAgC;oCAChCA,EAAEC,eAAe;oCACjBxB,2BAA2BR;gCAC7B;0CAEA,cAAA,KAACV;;;sCAGL,KAACC;4BAAYsC,aAAanC,aAAayC,aAAa;sCAClD,cAAA,KAACtD;gCACC4C,cAAYhC,gBAAgB0C,aAAa,CAAClC;gCAC1CmC,UAAU7B,aAAa8B;gCACvBzB,SAAS,CAACmB;oCACR,gCAAgC;oCAChCA,EAAEC,eAAe;oCACjBzB;gCACF;0CAEA,cAAA,KAAClB;;;sCAGL,KAACE;4BAAYsC,aAAanC,aAAa4C,WAAW;sCAChD,cAAA,KAACzD;gCACC4C,cAAYhC,gBAAgB6C,WAAW,CAACrC;gCACxCmC,UAAU9B,WAAW+B;gCACrBzB,SAAS,CAACmB;oCACR,gCAAgC;oCAChCA,EAAEC,eAAe;oCACjB1B;gCACF;0CAEA,cAAA,KAAClB;;;;;;aAOX,+DAA+D;QAC/DsB;;AAIR"}
@@ -1,3 +1,4 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
2
  // Copyright The Perses Authors
2
3
  // Licensed under the Apache License, Version 2.0 (the "License");
3
4
  // you may not use this file except in compliance with the License.
@@ -10,7 +11,6 @@
10
11
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
12
  // See the License for the specific language governing permissions and
12
13
  // limitations under the License.
13
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
14
14
  import { Collapse, useTheme } from '@mui/material';
15
15
  import { useViewPanelGroup } from '@perses-dev/dashboards';
16
16
  import { useEffect, useMemo, useState } from 'react';
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/GridLayout/Row.tsx"],"sourcesContent":["// Copyright 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 { Collapse, useTheme } from '@mui/material';\nimport { PanelGroupId } from '@perses-dev/spec';\nimport { PanelOptions, useViewPanelGroup } from '@perses-dev/dashboards';\nimport { ReactElement, useEffect, useMemo, useState } from 'react';\nimport { Layout, Layouts, Responsive, WidthProvider } from 'react-grid-layout';\nimport { ErrorAlert, ErrorBoundary } from '@perses-dev/components';\nimport { GRID_LAYOUT_COLS, GRID_LAYOUT_SMALL_BREAKPOINT } from '../../constants';\nimport { PanelGroupDefinition, PanelGroupItemLayout } from '../../model';\nimport { GridContainer } from './GridContainer';\nimport { GridItemContent } from './GridItemContent';\nimport { GridTitle } from './GridTitle';\n\nconst DEFAULT_MARGIN = 10;\nconst ROW_HEIGHT = 30;\n\nexport interface RowProps {\n panelGroupId: PanelGroupId;\n groupDefinition: PanelGroupDefinition;\n gridColWidth: number;\n panelFullHeight?: number;\n panelOptions?: PanelOptions;\n isEditMode?: boolean;\n onLayoutChange?: (currentLayout: Layout[], allLayouts: Layouts) => void;\n onWidthChange?: (\n containerWidth: number,\n margin: [number, number],\n cols: number,\n containerPadding: [number, number]\n ) => void;\n repeatVariable?: [string, string];\n}\n\nexport function Row({\n panelGroupId,\n groupDefinition,\n gridColWidth,\n panelFullHeight,\n panelOptions,\n isEditMode = false,\n onLayoutChange,\n onWidthChange,\n repeatVariable,\n}: RowProps): ReactElement {\n const ResponsiveGridLayout = useMemo(() => WidthProvider(Responsive), []);\n const theme = useTheme();\n const viewPanelItemId = useViewPanelGroup();\n\n const [isOpen, setIsOpen] = useState(!groupDefinition.isCollapsed);\n\n const hasViewPanel =\n viewPanelItemId?.panelGroupId === panelGroupId &&\n // Check for repeatVariable panels\n viewPanelItemId.repeatVariable?.[0] === repeatVariable?.[0] &&\n viewPanelItemId.repeatVariable?.[1] === repeatVariable?.[1];\n const itemLayoutViewed = viewPanelItemId?.panelGroupItemLayoutId;\n\n // If there is a panel in view mode, we should hide the grid if the panel is not in the current group.\n const isGridDisplayed = !viewPanelItemId || hasViewPanel;\n\n // TODO: handle it without useEffect\n useEffect(() => {\n if (hasViewPanel) {\n setIsOpen(true);\n }\n }, [hasViewPanel]);\n\n // Item layout is override if there is a panel in view mode\n const itemLayouts: PanelGroupItemLayout[] = useMemo(() => {\n if (itemLayoutViewed) {\n return groupDefinition.itemLayouts.map((itemLayout) => {\n if (itemLayout.i === itemLayoutViewed) {\n const rowTitleHeight = 40 + 8; // 40 is the height of the row title and 8 is the margin height\n return {\n h: Math.round(((panelFullHeight ?? window.innerHeight) - rowTitleHeight) / (ROW_HEIGHT + DEFAULT_MARGIN)), // Viewed panel should take the full height remaining\n i: itemLayoutViewed,\n w: 48,\n x: 0,\n y: 0,\n } as PanelGroupItemLayout;\n }\n return itemLayout;\n });\n }\n return groupDefinition.itemLayouts;\n }, [groupDefinition.itemLayouts, itemLayoutViewed, panelFullHeight]);\n\n return (\n <GridContainer\n sx={{\n display: isGridDisplayed ? 'block' : 'none',\n height: itemLayoutViewed ? `${panelFullHeight}px` : 'unset',\n overflow: itemLayoutViewed ? 'hidden' : 'unset',\n }}\n >\n {groupDefinition.title && (\n <GridTitle\n panelGroupId={panelGroupId}\n title={groupDefinition.title}\n collapse={\n groupDefinition.isCollapsed === undefined\n ? undefined\n : { isOpen: isOpen, onToggleOpen: () => setIsOpen((current) => !current) }\n }\n />\n )}\n <Collapse in={isOpen} unmountOnExit appear={false} data-testid=\"panel-group-content\">\n <ResponsiveGridLayout\n className=\"layout\"\n breakpoints={{ [GRID_LAYOUT_SMALL_BREAKPOINT]: theme.breakpoints.values.sm, xxs: 0 }}\n cols={GRID_LAYOUT_COLS}\n rowHeight={ROW_HEIGHT}\n draggableHandle=\".drag-handle\"\n resizeHandles={['se']}\n isDraggable={isEditMode && !hasViewPanel}\n isResizable={isEditMode && !hasViewPanel}\n margin={[DEFAULT_MARGIN, DEFAULT_MARGIN]}\n containerPadding={[0, 10]}\n layouts={{ sm: itemLayouts }}\n onLayoutChange={onLayoutChange}\n onWidthChange={onWidthChange}\n allowOverlap={hasViewPanel} // Enabling overlap when viewing a specific panel because panel in front of the viewed panel will add empty spaces (empty row height)\n >\n {itemLayouts.map(({ i, w }) => (\n <div\n key={i}\n style={{\n display: itemLayoutViewed ? (itemLayoutViewed === i ? 'unset' : 'none') : 'unset',\n }}\n >\n <ErrorBoundary FallbackComponent={ErrorAlert}>\n <GridItemContent\n panelOptions={panelOptions}\n panelGroupItemId={{ panelGroupId, panelGroupItemLayoutId: i, repeatVariable }}\n width={calculateGridItemWidth(w, gridColWidth)}\n />\n </ErrorBoundary>\n </div>\n ))}\n </ResponsiveGridLayout>\n </Collapse>\n </GridContainer>\n );\n}\n\nconst calculateGridItemWidth = (w: number, colWidth: number): number => {\n // 0 * Infinity === NaN, which causes problems with resize contraints\n if (!Number.isFinite(w)) return w;\n return Math.round(colWidth * w + Math.max(0, w - 1) * DEFAULT_MARGIN);\n};\n"],"names":["Collapse","useTheme","useViewPanelGroup","useEffect","useMemo","useState","Responsive","WidthProvider","ErrorAlert","ErrorBoundary","GRID_LAYOUT_COLS","GRID_LAYOUT_SMALL_BREAKPOINT","GridContainer","GridItemContent","GridTitle","DEFAULT_MARGIN","ROW_HEIGHT","Row","panelGroupId","groupDefinition","gridColWidth","panelFullHeight","panelOptions","isEditMode","onLayoutChange","onWidthChange","repeatVariable","ResponsiveGridLayout","theme","viewPanelItemId","isOpen","setIsOpen","isCollapsed","hasViewPanel","itemLayoutViewed","panelGroupItemLayoutId","isGridDisplayed","itemLayouts","map","itemLayout","i","rowTitleHeight","h","Math","round","window","innerHeight","w","x","y","sx","display","height","overflow","title","collapse","undefined","onToggleOpen","current","in","unmountOnExit","appear","data-testid","className","breakpoints","values","sm","xxs","cols","rowHeight","draggableHandle","resizeHandles","isDraggable","isResizable","margin","containerPadding","layouts","allowOverlap","div","style","FallbackComponent","panelGroupItemId","width","calculateGridItemWidth","colWidth","Number","isFinite","max"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/components/GridLayout/Row.tsx"],"sourcesContent":["// Copyright 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 { Collapse, useTheme } from '@mui/material';\nimport { PanelGroupId } from '@perses-dev/spec';\nimport { PanelOptions, useViewPanelGroup } from '@perses-dev/dashboards';\nimport { ReactElement, useEffect, useMemo, useState } from 'react';\nimport { Layout, Layouts, Responsive, WidthProvider } from 'react-grid-layout';\nimport { ErrorAlert, ErrorBoundary } from '@perses-dev/components';\nimport { GRID_LAYOUT_COLS, GRID_LAYOUT_SMALL_BREAKPOINT } from '../../constants';\nimport { PanelGroupDefinition, PanelGroupItemLayout } from '../../model';\nimport { GridContainer } from './GridContainer';\nimport { GridItemContent } from './GridItemContent';\nimport { GridTitle } from './GridTitle';\n\nconst DEFAULT_MARGIN = 10;\nconst ROW_HEIGHT = 30;\n\nexport interface RowProps {\n panelGroupId: PanelGroupId;\n groupDefinition: PanelGroupDefinition;\n gridColWidth: number;\n panelFullHeight?: number;\n panelOptions?: PanelOptions;\n isEditMode?: boolean;\n onLayoutChange?: (currentLayout: Layout[], allLayouts: Layouts) => void;\n onWidthChange?: (\n containerWidth: number,\n margin: [number, number],\n cols: number,\n containerPadding: [number, number]\n ) => void;\n repeatVariable?: [string, string];\n}\n\nexport function Row({\n panelGroupId,\n groupDefinition,\n gridColWidth,\n panelFullHeight,\n panelOptions,\n isEditMode = false,\n onLayoutChange,\n onWidthChange,\n repeatVariable,\n}: RowProps): ReactElement {\n const ResponsiveGridLayout = useMemo(() => WidthProvider(Responsive), []);\n const theme = useTheme();\n const viewPanelItemId = useViewPanelGroup();\n\n const [isOpen, setIsOpen] = useState(!groupDefinition.isCollapsed);\n\n const hasViewPanel =\n viewPanelItemId?.panelGroupId === panelGroupId &&\n // Check for repeatVariable panels\n viewPanelItemId.repeatVariable?.[0] === repeatVariable?.[0] &&\n viewPanelItemId.repeatVariable?.[1] === repeatVariable?.[1];\n const itemLayoutViewed = viewPanelItemId?.panelGroupItemLayoutId;\n\n // If there is a panel in view mode, we should hide the grid if the panel is not in the current group.\n const isGridDisplayed = !viewPanelItemId || hasViewPanel;\n\n // TODO: handle it without useEffect\n useEffect(() => {\n if (hasViewPanel) {\n setIsOpen(true);\n }\n }, [hasViewPanel]);\n\n // Item layout is override if there is a panel in view mode\n const itemLayouts: PanelGroupItemLayout[] = useMemo(() => {\n if (itemLayoutViewed) {\n return groupDefinition.itemLayouts.map((itemLayout) => {\n if (itemLayout.i === itemLayoutViewed) {\n const rowTitleHeight = 40 + 8; // 40 is the height of the row title and 8 is the margin height\n return {\n h: Math.round(((panelFullHeight ?? window.innerHeight) - rowTitleHeight) / (ROW_HEIGHT + DEFAULT_MARGIN)), // Viewed panel should take the full height remaining\n i: itemLayoutViewed,\n w: 48,\n x: 0,\n y: 0,\n } as PanelGroupItemLayout;\n }\n return itemLayout;\n });\n }\n return groupDefinition.itemLayouts;\n }, [groupDefinition.itemLayouts, itemLayoutViewed, panelFullHeight]);\n\n return (\n <GridContainer\n sx={{\n display: isGridDisplayed ? 'block' : 'none',\n height: itemLayoutViewed ? `${panelFullHeight}px` : 'unset',\n overflow: itemLayoutViewed ? 'hidden' : 'unset',\n }}\n >\n {groupDefinition.title && (\n <GridTitle\n panelGroupId={panelGroupId}\n title={groupDefinition.title}\n collapse={\n groupDefinition.isCollapsed === undefined\n ? undefined\n : { isOpen: isOpen, onToggleOpen: () => setIsOpen((current) => !current) }\n }\n />\n )}\n <Collapse in={isOpen} unmountOnExit appear={false} data-testid=\"panel-group-content\">\n <ResponsiveGridLayout\n className=\"layout\"\n breakpoints={{ [GRID_LAYOUT_SMALL_BREAKPOINT]: theme.breakpoints.values.sm, xxs: 0 }}\n cols={GRID_LAYOUT_COLS}\n rowHeight={ROW_HEIGHT}\n draggableHandle=\".drag-handle\"\n resizeHandles={['se']}\n isDraggable={isEditMode && !hasViewPanel}\n isResizable={isEditMode && !hasViewPanel}\n margin={[DEFAULT_MARGIN, DEFAULT_MARGIN]}\n containerPadding={[0, 10]}\n layouts={{ sm: itemLayouts }}\n onLayoutChange={onLayoutChange}\n onWidthChange={onWidthChange}\n allowOverlap={hasViewPanel} // Enabling overlap when viewing a specific panel because panel in front of the viewed panel will add empty spaces (empty row height)\n >\n {itemLayouts.map(({ i, w }) => (\n <div\n key={i}\n style={{\n display: itemLayoutViewed ? (itemLayoutViewed === i ? 'unset' : 'none') : 'unset',\n }}\n >\n <ErrorBoundary FallbackComponent={ErrorAlert}>\n <GridItemContent\n panelOptions={panelOptions}\n panelGroupItemId={{ panelGroupId, panelGroupItemLayoutId: i, repeatVariable }}\n width={calculateGridItemWidth(w, gridColWidth)}\n />\n </ErrorBoundary>\n </div>\n ))}\n </ResponsiveGridLayout>\n </Collapse>\n </GridContainer>\n );\n}\n\nconst calculateGridItemWidth = (w: number, colWidth: number): number => {\n // 0 * Infinity === NaN, which causes problems with resize contraints\n if (!Number.isFinite(w)) return w;\n return Math.round(colWidth * w + Math.max(0, w - 1) * DEFAULT_MARGIN);\n};\n"],"names":["Collapse","useTheme","useViewPanelGroup","useEffect","useMemo","useState","Responsive","WidthProvider","ErrorAlert","ErrorBoundary","GRID_LAYOUT_COLS","GRID_LAYOUT_SMALL_BREAKPOINT","GridContainer","GridItemContent","GridTitle","DEFAULT_MARGIN","ROW_HEIGHT","Row","panelGroupId","groupDefinition","gridColWidth","panelFullHeight","panelOptions","isEditMode","onLayoutChange","onWidthChange","repeatVariable","ResponsiveGridLayout","theme","viewPanelItemId","isOpen","setIsOpen","isCollapsed","hasViewPanel","itemLayoutViewed","panelGroupItemLayoutId","isGridDisplayed","itemLayouts","map","itemLayout","i","rowTitleHeight","h","Math","round","window","innerHeight","w","x","y","sx","display","height","overflow","title","collapse","undefined","onToggleOpen","current","in","unmountOnExit","appear","data-testid","className","breakpoints","values","sm","xxs","cols","rowHeight","draggableHandle","resizeHandles","isDraggable","isResizable","margin","containerPadding","layouts","allowOverlap","div","style","FallbackComponent","panelGroupItemId","width","calculateGridItemWidth","colWidth","Number","isFinite","max"],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
1
2
  // Copyright The Perses Authors
2
3
  // Licensed under the Apache License, Version 2.0 (the "License");
3
4
  // you may not use this file except in compliance with the License.
@@ -10,7 +11,6 @@
10
11
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
12
  // See the License for the specific language governing permissions and
12
13
  // limitations under the License.
13
- import { jsx as _jsx } from "react/jsx-runtime";
14
14
  import { useEffect } from 'react';
15
15
  import { useBlocker } from 'react-router-dom';
16
16
  import { DiscardChangesConfirmationDialog } from '@perses-dev/components';
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/LeaveDialog/LeaveDialog.tsx"],"sourcesContent":["// Copyright 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, ReactNode, useEffect } from 'react';\nimport { useBlocker } from 'react-router-dom';\nimport { DiscardChangesConfirmationDialog } from '@perses-dev/components';\nimport type { BlockerFunction } from '@remix-run/router';\nimport { DashboardResource } from '../../model';\n\nconst handleRouteChange = (event: BeforeUnloadEvent): string => {\n event.preventDefault();\n event.returnValue = ''; // Required for Chrome\n return ''; // Required for other browsers\n};\n\nexport interface LeaveDialogProps {\n isBlocked: BlockerFunction | boolean;\n message: string;\n}\n\n/*\n * Prompt component uses the useBlocker hook to block react-router navigation when there are unsaved changes.\n * It also listens to the beforeunload event to show a browser confirmation dialog when the user tries to close the tab, refresh the page or change url manually.\n */\nexport function Prompt({ isBlocked, message }: LeaveDialogProps): ReactElement {\n const blocker = useBlocker(isBlocked);\n const isBlockedState = blocker.state === 'blocked';\n const isProceedingState = blocker.state === 'proceeding';\n\n useEffect(() => {\n if (isBlocked) {\n window.addEventListener('beforeunload', handleRouteChange);\n } else {\n window.removeEventListener('beforeunload', handleRouteChange);\n }\n\n return (): void => {\n window.removeEventListener('beforeunload', handleRouteChange);\n };\n }, [blocker, isBlocked, isBlockedState]);\n\n const handleDiscardChanges = (): void => blocker.proceed?.();\n const handleCancel = (): void => blocker.reset?.();\n\n return (\n <DiscardChangesConfirmationDialog\n description={message}\n isOpen={isBlockedState || isProceedingState}\n onDiscardChanges={handleDiscardChanges}\n onCancel={handleCancel}\n />\n );\n}\n\n/*\n * LeaveDialog prompts the user with a confirmation dialog when they attempt to leave the page with unsaved changes.\n */\nexport function LeaveDialog({\n original,\n current,\n}: {\n original: DashboardResource | undefined;\n current: DashboardResource;\n}): ReactNode {\n const handleIsBlocked: BlockerFunction = (ctx) => {\n if (JSON.stringify(original) !== JSON.stringify(current)) {\n // Only block navigation if the pathname is changing (=> ignore search params changes)\n if (ctx.currentLocation.pathname !== ctx.nextLocation.pathname) {\n return true;\n }\n }\n return false;\n };\n\n return <Prompt isBlocked={handleIsBlocked} message=\"You have unsaved changes, are you sure you want to leave?\" />;\n}\n"],"names":["useEffect","useBlocker","DiscardChangesConfirmationDialog","handleRouteChange","event","preventDefault","returnValue","Prompt","isBlocked","message","blocker","isBlockedState","state","isProceedingState","window","addEventListener","removeEventListener","handleDiscardChanges","proceed","handleCancel","reset","description","isOpen","onDiscardChanges","onCancel","LeaveDialog","original","current","handleIsBlocked","ctx","JSON","stringify","currentLocation","pathname","nextLocation"],"mappings":"AAAA,+BAA+B;AAC/B,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;;AAEjC,SAAkCA,SAAS,QAAQ,QAAQ;AAC3D,SAASC,UAAU,QAAQ,mBAAmB;AAC9C,SAASC,gCAAgC,QAAQ,yBAAyB;AAI1E,MAAMC,oBAAoB,CAACC;IACzBA,MAAMC,cAAc;IACpBD,MAAME,WAAW,GAAG,IAAI,sBAAsB;IAC9C,OAAO,IAAI,8BAA8B;AAC3C;AAOA;;;CAGC,GACD,OAAO,SAASC,OAAO,EAAEC,SAAS,EAAEC,OAAO,EAAoB;IAC7D,MAAMC,UAAUT,WAAWO;IAC3B,MAAMG,iBAAiBD,QAAQE,KAAK,KAAK;IACzC,MAAMC,oBAAoBH,QAAQE,KAAK,KAAK;IAE5CZ,UAAU;QACR,IAAIQ,WAAW;YACbM,OAAOC,gBAAgB,CAAC,gBAAgBZ;QAC1C,OAAO;YACLW,OAAOE,mBAAmB,CAAC,gBAAgBb;QAC7C;QAEA,OAAO;YACLW,OAAOE,mBAAmB,CAAC,gBAAgBb;QAC7C;IACF,GAAG;QAACO;QAASF;QAAWG;KAAe;IAEvC,MAAMM,uBAAuB,IAAYP,QAAQQ,OAAO;IACxD,MAAMC,eAAe,IAAYT,QAAQU,KAAK;IAE9C,qBACE,KAAClB;QACCmB,aAAaZ;QACba,QAAQX,kBAAkBE;QAC1BU,kBAAkBN;QAClBO,UAAUL;;AAGhB;AAEA;;CAEC,GACD,OAAO,SAASM,YAAY,EAC1BC,QAAQ,EACRC,OAAO,EAIR;IACC,MAAMC,kBAAmC,CAACC;QACxC,IAAIC,KAAKC,SAAS,CAACL,cAAcI,KAAKC,SAAS,CAACJ,UAAU;YACxD,sFAAsF;YACtF,IAAIE,IAAIG,eAAe,CAACC,QAAQ,KAAKJ,IAAIK,YAAY,CAACD,QAAQ,EAAE;gBAC9D,OAAO;YACT;QACF;QACA,OAAO;IACT;IAEA,qBAAO,KAAC1B;QAAOC,WAAWoB;QAAiBnB,SAAQ;;AACrD"}
1
+ {"version":3,"sources":["../../../src/components/LeaveDialog/LeaveDialog.tsx"],"sourcesContent":["// Copyright 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, ReactNode, useEffect } from 'react';\nimport { useBlocker } from 'react-router-dom';\nimport { DiscardChangesConfirmationDialog } from '@perses-dev/components';\nimport type { BlockerFunction } from '@remix-run/router';\nimport { DashboardResource } from '../../model';\n\nconst handleRouteChange = (event: BeforeUnloadEvent): string => {\n event.preventDefault();\n event.returnValue = ''; // Required for Chrome\n return ''; // Required for other browsers\n};\n\nexport interface LeaveDialogProps {\n isBlocked: BlockerFunction | boolean;\n message: string;\n}\n\n/*\n * Prompt component uses the useBlocker hook to block react-router navigation when there are unsaved changes.\n * It also listens to the beforeunload event to show a browser confirmation dialog when the user tries to close the tab, refresh the page or change url manually.\n */\nexport function Prompt({ isBlocked, message }: LeaveDialogProps): ReactElement {\n const blocker = useBlocker(isBlocked);\n const isBlockedState = blocker.state === 'blocked';\n const isProceedingState = blocker.state === 'proceeding';\n\n useEffect(() => {\n if (isBlocked) {\n window.addEventListener('beforeunload', handleRouteChange);\n } else {\n window.removeEventListener('beforeunload', handleRouteChange);\n }\n\n return (): void => {\n window.removeEventListener('beforeunload', handleRouteChange);\n };\n }, [blocker, isBlocked, isBlockedState]);\n\n const handleDiscardChanges = (): void => blocker.proceed?.();\n const handleCancel = (): void => blocker.reset?.();\n\n return (\n <DiscardChangesConfirmationDialog\n description={message}\n isOpen={isBlockedState || isProceedingState}\n onDiscardChanges={handleDiscardChanges}\n onCancel={handleCancel}\n />\n );\n}\n\n/*\n * LeaveDialog prompts the user with a confirmation dialog when they attempt to leave the page with unsaved changes.\n */\nexport function LeaveDialog({\n original,\n current,\n}: {\n original: DashboardResource | undefined;\n current: DashboardResource;\n}): ReactNode {\n const handleIsBlocked: BlockerFunction = (ctx) => {\n if (JSON.stringify(original) !== JSON.stringify(current)) {\n // Only block navigation if the pathname is changing (=> ignore search params changes)\n if (ctx.currentLocation.pathname !== ctx.nextLocation.pathname) {\n return true;\n }\n }\n return false;\n };\n\n return <Prompt isBlocked={handleIsBlocked} message=\"You have unsaved changes, are you sure you want to leave?\" />;\n}\n"],"names":["useEffect","useBlocker","DiscardChangesConfirmationDialog","handleRouteChange","event","preventDefault","returnValue","Prompt","isBlocked","message","blocker","isBlockedState","state","isProceedingState","window","addEventListener","removeEventListener","handleDiscardChanges","proceed","handleCancel","reset","description","isOpen","onDiscardChanges","onCancel","LeaveDialog","original","current","handleIsBlocked","ctx","JSON","stringify","currentLocation","pathname","nextLocation"],"mappings":";AAAA,+BAA+B;AAC/B,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;AAEjC,SAAkCA,SAAS,QAAQ,QAAQ;AAC3D,SAASC,UAAU,QAAQ,mBAAmB;AAC9C,SAASC,gCAAgC,QAAQ,yBAAyB;AAI1E,MAAMC,oBAAoB,CAACC;IACzBA,MAAMC,cAAc;IACpBD,MAAME,WAAW,GAAG,IAAI,sBAAsB;IAC9C,OAAO,IAAI,8BAA8B;AAC3C;AAOA;;;CAGC,GACD,OAAO,SAASC,OAAO,EAAEC,SAAS,EAAEC,OAAO,EAAoB;IAC7D,MAAMC,UAAUT,WAAWO;IAC3B,MAAMG,iBAAiBD,QAAQE,KAAK,KAAK;IACzC,MAAMC,oBAAoBH,QAAQE,KAAK,KAAK;IAE5CZ,UAAU;QACR,IAAIQ,WAAW;YACbM,OAAOC,gBAAgB,CAAC,gBAAgBZ;QAC1C,OAAO;YACLW,OAAOE,mBAAmB,CAAC,gBAAgBb;QAC7C;QAEA,OAAO;YACLW,OAAOE,mBAAmB,CAAC,gBAAgBb;QAC7C;IACF,GAAG;QAACO;QAASF;QAAWG;KAAe;IAEvC,MAAMM,uBAAuB,IAAYP,QAAQQ,OAAO;IACxD,MAAMC,eAAe,IAAYT,QAAQU,KAAK;IAE9C,qBACE,KAAClB;QACCmB,aAAaZ;QACba,QAAQX,kBAAkBE;QAC1BU,kBAAkBN;QAClBO,UAAUL;;AAGhB;AAEA;;CAEC,GACD,OAAO,SAASM,YAAY,EAC1BC,QAAQ,EACRC,OAAO,EAIR;IACC,MAAMC,kBAAmC,CAACC;QACxC,IAAIC,KAAKC,SAAS,CAACL,cAAcI,KAAKC,SAAS,CAACJ,UAAU;YACxD,sFAAsF;YACtF,IAAIE,IAAIG,eAAe,CAACC,QAAQ,KAAKJ,IAAIK,YAAY,CAACD,QAAQ,EAAE;gBAC9D,OAAO;YACT;QACF;QACA,OAAO;IACT;IAEA,qBAAO,KAAC1B;QAAOC,WAAWoB;QAAiBnB,SAAQ;;AACrD"}
@@ -1,3 +1,4 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
1
2
  // Copyright The Perses Authors
2
3
  // Licensed under the Apache License, Version 2.0 (the "License");
3
4
  // you may not use this file except in compliance with the License.
@@ -10,7 +11,6 @@
10
11
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
12
  // See the License for the specific language governing permissions and
12
13
  // limitations under the License.
13
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
14
14
  import { IconButton, Link as LinkComponent, Menu, MenuItem, Chip, capitalize, Stack } from '@mui/material';
15
15
  import LaunchIcon from 'mdi-material-ui/Launch';
16
16
  import { useState } from 'react';
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/LinksDisplay/LinksDisplay.tsx"],"sourcesContent":["// Copyright 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 { IconButton, Link as LinkComponent, Menu, MenuItem, Theme, Chip, capitalize, Stack } from '@mui/material';\nimport LaunchIcon from 'mdi-material-ui/Launch';\nimport { Link } from '@perses-dev/spec';\nimport { MouseEvent, ReactElement, useState } from 'react';\nimport { InfoTooltip } from '@perses-dev/components';\nimport { useReplaceVariablesInString } from '@perses-dev/plugin-system';\n\ntype LinksVariant = 'dashboard' | 'panel';\n\ninterface LinksProps {\n links: Link[];\n variant: LinksVariant;\n}\n\nexport function LinksDisplay({ links, variant }: LinksProps): ReactElement | null {\n const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);\n const isMenuOpened = Boolean(anchorEl);\n const handleOpenMenu = (event: MouseEvent<HTMLButtonElement>): void => {\n setAnchorEl(event.currentTarget);\n };\n\n const handleClose = (): void => {\n setAnchorEl(null);\n };\n\n if (links.length === 0) {\n return null;\n }\n\n // Panel variant: single link shows as icon button\n if (variant === 'panel' && links.length === 1 && links[0]) {\n return <LinkButton link={links[0]} />;\n }\n\n // Dashboard variant: 1-3 links show as chips\n // Max character limit for the name and url to prevent overflow\n // in the dashboard title area, but if either the name or url is too long,\n // we will fall back to showing the links in a dropdown menu\n if (variant === 'dashboard' && links.length <= 3) {\n const canRenderAsChips = links.every((link) => {\n if (link.name) {\n return link.name.length < 30;\n }\n\n if (link.url) {\n return link.url.length < 70;\n }\n\n return false;\n });\n\n if (canRenderAsChips) {\n return (\n <Stack direction=\"row\" spacing={1}>\n {links.map((link: Link) => (\n <LinkChip key={link.url} link={link} />\n ))}\n </Stack>\n );\n }\n }\n\n // Default: show dropdown menu for multiple links\n return (\n <>\n <InfoTooltip description={`${links.length} links`} enterDelay={100}>\n <IconButton\n aria-label={`${capitalize(variant)}-links`}\n id={`${variant}-links-button`}\n size=\"small\"\n onClick={handleOpenMenu}\n sx={(theme) => ({ borderRadius: theme.shape.borderRadius, padding: '4px' })}\n >\n <LaunchIcon\n aria-describedby=\"links-icon\"\n fontSize=\"inherit\"\n sx={{ color: (theme: Theme) => theme.palette.text.secondary }}\n />\n </IconButton>\n </InfoTooltip>\n\n <Menu\n anchorEl={anchorEl}\n open={isMenuOpened}\n onClose={handleClose}\n MenuListProps={{\n 'aria-labelledby': `${variant}-links-button`,\n }}\n >\n {links.map((link: Link) => (\n <LinkMenuItem key={link.url} link={link} />\n ))}\n </Menu>\n </>\n );\n}\n\nfunction LinkChip({ link }: { link: Link }): ReactElement {\n const { url, name, tooltip, targetBlank } = useLink(link);\n\n return (\n <InfoTooltip description={tooltip ?? url} enterDelay={100}>\n <Chip\n label={name ?? url}\n component=\"a\"\n href={url}\n target={targetBlank ? '_blank' : '_self'}\n clickable\n size=\"medium\"\n icon={<LaunchIcon color=\"inherit\" fontSize=\"small\" />}\n sx={(theme) => ({ height: theme.spacing(3) })}\n />\n </InfoTooltip>\n );\n}\n\nfunction LinkButton({ link }: { link: Link }): ReactElement {\n const { url, name, tooltip, targetBlank } = useLink(link);\n\n return (\n <InfoTooltip description={tooltip ?? url} enterDelay={100}>\n <IconButton\n aria-label={name ?? url}\n size=\"small\"\n href={url}\n target={targetBlank ? '_blank' : '_self'}\n sx={(theme) => ({ borderRadius: theme.shape.borderRadius, padding: '4px' })}\n >\n <LaunchIcon fontSize=\"inherit\" sx={{ color: (theme: Theme) => theme.palette.text.secondary }} />\n </IconButton>\n </InfoTooltip>\n );\n}\n\nfunction LinkMenuItem({ link }: { link: Link }): ReactElement {\n const { url, name, tooltip, targetBlank } = useLink(link);\n\n return (\n <InfoTooltip description={tooltip ?? url} enterDelay={100}>\n <MenuItem component={LinkComponent} href={url} target={targetBlank ? '_blank' : '_self'}>\n {name ?? url}\n </MenuItem>\n </InfoTooltip>\n );\n}\n\nfunction useLink(link: Link): Link {\n const url = useReplaceVariablesInString(link.url) ?? link.url;\n const name = useReplaceVariablesInString(link.name);\n const tooltip = useReplaceVariablesInString(link.tooltip);\n\n if (link.renderVariables === false) {\n return link;\n }\n\n return { ...link, url, name, tooltip };\n}\n"],"names":["IconButton","Link","LinkComponent","Menu","MenuItem","Chip","capitalize","Stack","LaunchIcon","useState","InfoTooltip","useReplaceVariablesInString","LinksDisplay","links","variant","anchorEl","setAnchorEl","isMenuOpened","Boolean","handleOpenMenu","event","currentTarget","handleClose","length","LinkButton","link","canRenderAsChips","every","name","url","direction","spacing","map","LinkChip","description","enterDelay","aria-label","id","size","onClick","sx","theme","borderRadius","shape","padding","aria-describedby","fontSize","color","palette","text","secondary","open","onClose","MenuListProps","LinkMenuItem","tooltip","targetBlank","useLink","label","component","href","target","clickable","icon","height","renderVariables"],"mappings":"AAAA,+BAA+B;AAC/B,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;;AAEjC,SAASA,UAAU,EAAEC,QAAQC,aAAa,EAAEC,IAAI,EAAEC,QAAQ,EAASC,IAAI,EAAEC,UAAU,EAAEC,KAAK,QAAQ,gBAAgB;AAClH,OAAOC,gBAAgB,yBAAyB;AAEhD,SAAmCC,QAAQ,QAAQ,QAAQ;AAC3D,SAASC,WAAW,QAAQ,yBAAyB;AACrD,SAASC,2BAA2B,QAAQ,4BAA4B;AASxE,OAAO,SAASC,aAAa,EAAEC,KAAK,EAAEC,OAAO,EAAc;IACzD,MAAM,CAACC,UAAUC,YAAY,GAAGP,SAA6B;IAC7D,MAAMQ,eAAeC,QAAQH;IAC7B,MAAMI,iBAAiB,CAACC;QACtBJ,YAAYI,MAAMC,aAAa;IACjC;IAEA,MAAMC,cAAc;QAClBN,YAAY;IACd;IAEA,IAAIH,MAAMU,MAAM,KAAK,GAAG;QACtB,OAAO;IACT;IAEA,kDAAkD;IAClD,IAAIT,YAAY,WAAWD,MAAMU,MAAM,KAAK,KAAKV,KAAK,CAAC,EAAE,EAAE;QACzD,qBAAO,KAACW;YAAWC,MAAMZ,KAAK,CAAC,EAAE;;IACnC;IAEA,6CAA6C;IAC7C,+DAA+D;IAC/D,0EAA0E;IAC1E,4DAA4D;IAC5D,IAAIC,YAAY,eAAeD,MAAMU,MAAM,IAAI,GAAG;QAChD,MAAMG,mBAAmBb,MAAMc,KAAK,CAAC,CAACF;YACpC,IAAIA,KAAKG,IAAI,EAAE;gBACb,OAAOH,KAAKG,IAAI,CAACL,MAAM,GAAG;YAC5B;YAEA,IAAIE,KAAKI,GAAG,EAAE;gBACZ,OAAOJ,KAAKI,GAAG,CAACN,MAAM,GAAG;YAC3B;YAEA,OAAO;QACT;QAEA,IAAIG,kBAAkB;YACpB,qBACE,KAACnB;gBAAMuB,WAAU;gBAAMC,SAAS;0BAC7BlB,MAAMmB,GAAG,CAAC,CAACP,qBACV,KAACQ;wBAAwBR,MAAMA;uBAAhBA,KAAKI,GAAG;;QAI/B;IACF;IAEA,iDAAiD;IACjD,qBACE;;0BACE,KAACnB;gBAAYwB,aAAa,GAAGrB,MAAMU,MAAM,CAAC,MAAM,CAAC;gBAAEY,YAAY;0BAC7D,cAAA,KAACnC;oBACCoC,cAAY,GAAG9B,WAAWQ,SAAS,MAAM,CAAC;oBAC1CuB,IAAI,GAAGvB,QAAQ,aAAa,CAAC;oBAC7BwB,MAAK;oBACLC,SAASpB;oBACTqB,IAAI,CAACC,QAAW,CAAA;4BAAEC,cAAcD,MAAME,KAAK,CAACD,YAAY;4BAAEE,SAAS;wBAAM,CAAA;8BAEzE,cAAA,KAACpC;wBACCqC,oBAAiB;wBACjBC,UAAS;wBACTN,IAAI;4BAAEO,OAAO,CAACN,QAAiBA,MAAMO,OAAO,CAACC,IAAI,CAACC,SAAS;wBAAC;;;;0BAKlE,KAAC/C;gBACCY,UAAUA;gBACVoC,MAAMlC;gBACNmC,SAAS9B;gBACT+B,eAAe;oBACb,mBAAmB,GAAGvC,QAAQ,aAAa,CAAC;gBAC9C;0BAECD,MAAMmB,GAAG,CAAC,CAACP,qBACV,KAAC6B;wBAA4B7B,MAAMA;uBAAhBA,KAAKI,GAAG;;;;AAKrC;AAEA,SAASI,SAAS,EAAER,IAAI,EAAkB;IACxC,MAAM,EAAEI,GAAG,EAAED,IAAI,EAAE2B,OAAO,EAAEC,WAAW,EAAE,GAAGC,QAAQhC;IAEpD,qBACE,KAACf;QAAYwB,aAAaqB,WAAW1B;QAAKM,YAAY;kBACpD,cAAA,KAAC9B;YACCqD,OAAO9B,QAAQC;YACf8B,WAAU;YACVC,MAAM/B;YACNgC,QAAQL,cAAc,WAAW;YACjCM,SAAS;YACTxB,MAAK;YACLyB,oBAAM,KAACvD;gBAAWuC,OAAM;gBAAUD,UAAS;;YAC3CN,IAAI,CAACC,QAAW,CAAA;oBAAEuB,QAAQvB,MAAMV,OAAO,CAAC;gBAAG,CAAA;;;AAInD;AAEA,SAASP,WAAW,EAAEC,IAAI,EAAkB;IAC1C,MAAM,EAAEI,GAAG,EAAED,IAAI,EAAE2B,OAAO,EAAEC,WAAW,EAAE,GAAGC,QAAQhC;IAEpD,qBACE,KAACf;QAAYwB,aAAaqB,WAAW1B;QAAKM,YAAY;kBACpD,cAAA,KAACnC;YACCoC,cAAYR,QAAQC;YACpBS,MAAK;YACLsB,MAAM/B;YACNgC,QAAQL,cAAc,WAAW;YACjChB,IAAI,CAACC,QAAW,CAAA;oBAAEC,cAAcD,MAAME,KAAK,CAACD,YAAY;oBAAEE,SAAS;gBAAM,CAAA;sBAEzE,cAAA,KAACpC;gBAAWsC,UAAS;gBAAUN,IAAI;oBAAEO,OAAO,CAACN,QAAiBA,MAAMO,OAAO,CAACC,IAAI,CAACC,SAAS;gBAAC;;;;AAInG;AAEA,SAASI,aAAa,EAAE7B,IAAI,EAAkB;IAC5C,MAAM,EAAEI,GAAG,EAAED,IAAI,EAAE2B,OAAO,EAAEC,WAAW,EAAE,GAAGC,QAAQhC;IAEpD,qBACE,KAACf;QAAYwB,aAAaqB,WAAW1B;QAAKM,YAAY;kBACpD,cAAA,KAAC/B;YAASuD,WAAWzD;YAAe0D,MAAM/B;YAAKgC,QAAQL,cAAc,WAAW;sBAC7E5B,QAAQC;;;AAIjB;AAEA,SAAS4B,QAAQhC,IAAU;IACzB,MAAMI,MAAMlB,4BAA4Bc,KAAKI,GAAG,KAAKJ,KAAKI,GAAG;IAC7D,MAAMD,OAAOjB,4BAA4Bc,KAAKG,IAAI;IAClD,MAAM2B,UAAU5C,4BAA4Bc,KAAK8B,OAAO;IAExD,IAAI9B,KAAKwC,eAAe,KAAK,OAAO;QAClC,OAAOxC;IACT;IAEA,OAAO;QAAE,GAAGA,IAAI;QAAEI;QAAKD;QAAM2B;IAAQ;AACvC"}
1
+ {"version":3,"sources":["../../../src/components/LinksDisplay/LinksDisplay.tsx"],"sourcesContent":["// Copyright 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 { IconButton, Link as LinkComponent, Menu, MenuItem, Theme, Chip, capitalize, Stack } from '@mui/material';\nimport LaunchIcon from 'mdi-material-ui/Launch';\nimport { Link } from '@perses-dev/spec';\nimport { MouseEvent, ReactElement, useState } from 'react';\nimport { InfoTooltip } from '@perses-dev/components';\nimport { useReplaceVariablesInString } from '@perses-dev/plugin-system';\n\ntype LinksVariant = 'dashboard' | 'panel';\n\ninterface LinksProps {\n links: Link[];\n variant: LinksVariant;\n}\n\nexport function LinksDisplay({ links, variant }: LinksProps): ReactElement | null {\n const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);\n const isMenuOpened = Boolean(anchorEl);\n const handleOpenMenu = (event: MouseEvent<HTMLButtonElement>): void => {\n setAnchorEl(event.currentTarget);\n };\n\n const handleClose = (): void => {\n setAnchorEl(null);\n };\n\n if (links.length === 0) {\n return null;\n }\n\n // Panel variant: single link shows as icon button\n if (variant === 'panel' && links.length === 1 && links[0]) {\n return <LinkButton link={links[0]} />;\n }\n\n // Dashboard variant: 1-3 links show as chips\n // Max character limit for the name and url to prevent overflow\n // in the dashboard title area, but if either the name or url is too long,\n // we will fall back to showing the links in a dropdown menu\n if (variant === 'dashboard' && links.length <= 3) {\n const canRenderAsChips = links.every((link) => {\n if (link.name) {\n return link.name.length < 30;\n }\n\n if (link.url) {\n return link.url.length < 70;\n }\n\n return false;\n });\n\n if (canRenderAsChips) {\n return (\n <Stack direction=\"row\" spacing={1}>\n {links.map((link: Link) => (\n <LinkChip key={link.url} link={link} />\n ))}\n </Stack>\n );\n }\n }\n\n // Default: show dropdown menu for multiple links\n return (\n <>\n <InfoTooltip description={`${links.length} links`} enterDelay={100}>\n <IconButton\n aria-label={`${capitalize(variant)}-links`}\n id={`${variant}-links-button`}\n size=\"small\"\n onClick={handleOpenMenu}\n sx={(theme) => ({ borderRadius: theme.shape.borderRadius, padding: '4px' })}\n >\n <LaunchIcon\n aria-describedby=\"links-icon\"\n fontSize=\"inherit\"\n sx={{ color: (theme: Theme) => theme.palette.text.secondary }}\n />\n </IconButton>\n </InfoTooltip>\n\n <Menu\n anchorEl={anchorEl}\n open={isMenuOpened}\n onClose={handleClose}\n MenuListProps={{\n 'aria-labelledby': `${variant}-links-button`,\n }}\n >\n {links.map((link: Link) => (\n <LinkMenuItem key={link.url} link={link} />\n ))}\n </Menu>\n </>\n );\n}\n\nfunction LinkChip({ link }: { link: Link }): ReactElement {\n const { url, name, tooltip, targetBlank } = useLink(link);\n\n return (\n <InfoTooltip description={tooltip ?? url} enterDelay={100}>\n <Chip\n label={name ?? url}\n component=\"a\"\n href={url}\n target={targetBlank ? '_blank' : '_self'}\n clickable\n size=\"medium\"\n icon={<LaunchIcon color=\"inherit\" fontSize=\"small\" />}\n sx={(theme) => ({ height: theme.spacing(3) })}\n />\n </InfoTooltip>\n );\n}\n\nfunction LinkButton({ link }: { link: Link }): ReactElement {\n const { url, name, tooltip, targetBlank } = useLink(link);\n\n return (\n <InfoTooltip description={tooltip ?? url} enterDelay={100}>\n <IconButton\n aria-label={name ?? url}\n size=\"small\"\n href={url}\n target={targetBlank ? '_blank' : '_self'}\n sx={(theme) => ({ borderRadius: theme.shape.borderRadius, padding: '4px' })}\n >\n <LaunchIcon fontSize=\"inherit\" sx={{ color: (theme: Theme) => theme.palette.text.secondary }} />\n </IconButton>\n </InfoTooltip>\n );\n}\n\nfunction LinkMenuItem({ link }: { link: Link }): ReactElement {\n const { url, name, tooltip, targetBlank } = useLink(link);\n\n return (\n <InfoTooltip description={tooltip ?? url} enterDelay={100}>\n <MenuItem component={LinkComponent} href={url} target={targetBlank ? '_blank' : '_self'}>\n {name ?? url}\n </MenuItem>\n </InfoTooltip>\n );\n}\n\nfunction useLink(link: Link): Link {\n const url = useReplaceVariablesInString(link.url) ?? link.url;\n const name = useReplaceVariablesInString(link.name);\n const tooltip = useReplaceVariablesInString(link.tooltip);\n\n if (link.renderVariables === false) {\n return link;\n }\n\n return { ...link, url, name, tooltip };\n}\n"],"names":["IconButton","Link","LinkComponent","Menu","MenuItem","Chip","capitalize","Stack","LaunchIcon","useState","InfoTooltip","useReplaceVariablesInString","LinksDisplay","links","variant","anchorEl","setAnchorEl","isMenuOpened","Boolean","handleOpenMenu","event","currentTarget","handleClose","length","LinkButton","link","canRenderAsChips","every","name","url","direction","spacing","map","LinkChip","description","enterDelay","aria-label","id","size","onClick","sx","theme","borderRadius","shape","padding","aria-describedby","fontSize","color","palette","text","secondary","open","onClose","MenuListProps","LinkMenuItem","tooltip","targetBlank","useLink","label","component","href","target","clickable","icon","height","renderVariables"],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
2
  // Copyright The Perses Authors
2
3
  // Licensed under the Apache License, Version 2.0 (the "License");
3
4
  // you may not use this file except in compliance with the License.
@@ -10,7 +11,6 @@
10
11
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
12
  // See the License for the specific language governing permissions and
12
13
  // limitations under the License.
13
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
14
14
  import { Card, CardContent } from '@mui/material';
15
15
  import { ErrorAlert, ErrorBoundary, ItemActionsProvider, SelectionProvider, combineSx, useId } from '@perses-dev/components';
16
16
  import { useDataQueriesContext, usePluginRegistry } from '@perses-dev/plugin-system';
@@ -71,7 +71,10 @@ import { PanelHeader } from './PanelHeader';
71
71
  return;
72
72
  }
73
73
  try {
74
- const plugin = await getPlugin('Panel', panelPluginKind);
74
+ const plugin = await getPlugin({
75
+ kind: 'Panel',
76
+ name: panelPluginKind
77
+ });
75
78
  // More defensive checking for plugin and actions
76
79
  if (!plugin || typeof plugin !== 'object' || !plugin.actions || !Array.isArray(plugin.actions) || plugin.actions.length === 0) {
77
80
  setPluginActions([]);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/Panel/Panel.tsx"],"sourcesContent":["// Copyright 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 {\n ErrorAlert,\n ErrorBoundary,\n ItemActionsProvider,\n SelectionProvider,\n combineSx,\n useId,\n} from '@perses-dev/components';\nimport { PanelDefinition } from '@perses-dev/spec';\nimport { ActionOptions, useDataQueriesContext, usePluginRegistry } from '@perses-dev/plugin-system';\nimport { ReactNode, memo, useEffect, useMemo, useState } from 'react';\nimport useResizeObserver from 'use-resize-observer';\nimport { PanelGroupItemId } from '../../model';\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 viewQueriesHandler?: PanelHeaderProps['viewQueriesHandler'];\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 * Whether to show panel icons always, or only when hovering over the panel.\n * Default: if the dashboard is in editing mode or the panel is in fullscreen mode: 'always', otherwise 'hover'\n */\n showIcons?: 'always' | 'hover';\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 viewQueriesHandler,\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 { queryResults } = useDataQueriesContext();\n const { getPlugin } = usePluginRegistry();\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 };\n }, [definition, contentDimensions, queryResults]);\n\n // Load plugin actions from the plugin\n const [pluginActions, setPluginActions] = useState<ReactNode[]>([]);\n\n useEffect(() => {\n const loadPluginActions = async (): Promise<void> => {\n const panelPluginKind = definition.spec.plugin.kind;\n\n if (!panelPluginKind || !panelPropsForActions || !getPlugin || typeof getPlugin !== 'function') {\n setPluginActions([]);\n return;\n }\n\n try {\n const plugin = await getPlugin('Panel', panelPluginKind);\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 setPluginActions([]);\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}`} {...(panelPropsForActions 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 setPluginActions(headerActions);\n } catch (error) {\n console.warn('Failed to load plugin actions:', error);\n setPluginActions([]);\n }\n };\n\n loadPluginActions();\n }, [definition.spec.plugin.kind, panelPropsForActions, getPlugin]);\n\n const handleMouseEnter: CardProps['onMouseEnter'] = (e) => {\n onMouseEnter?.(e);\n };\n\n const handleMouseLeave: CardProps['onMouseLeave'] = (e) => {\n onMouseLeave?.(e);\n };\n\n // default value for showIcons: if the dashboard is in editing mode or the panel is in fullscreen mode: 'always', otherwise 'hover'\n const showIcons = panelOptions?.showIcons ?? (editHandlers || readHandlers?.isPanelViewed ? 'always' : 'hover');\n const itemActionsConfig = definition.spec.plugin.spec?.actions\n ? (definition.spec.plugin.spec.actions as ActionOptions)\n : undefined;\n const itemActionsListConfig =\n itemActionsConfig?.enabled && itemActionsConfig.displayInHeader ? itemActionsConfig.actionsList : [];\n\n return (\n <SelectionProvider>\n <ItemActionsProvider>\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 viewQueriesHandler={viewQueriesHandler}\n links={definition.spec.links}\n pluginActions={pluginActions}\n itemActionsListConfig={itemActionsListConfig}\n showIcons={showIcons}\n sx={{ py: '2px', pl: '8px', pr: '2px' }}\n dimension={contentDimensions}\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, queryResults]}>\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 </ItemActionsProvider>\n </SelectionProvider>\n );\n});\n"],"names":["Card","CardContent","ErrorAlert","ErrorBoundary","ItemActionsProvider","SelectionProvider","combineSx","useId","useDataQueriesContext","usePluginRegistry","memo","useEffect","useMemo","useState","useResizeObserver","PanelContent","PanelHeader","Panel","props","definition","readHandlers","editHandlers","onMouseEnter","onMouseLeave","sx","panelOptions","panelGroupItemId","viewQueriesHandler","others","generatedPanelId","headerId","contentElement","setContentElement","width","height","ref","contentDimensions","undefined","queryResults","getPlugin","panelPropsForActions","spec","plugin","map","query","data","pluginActions","setPluginActions","loadPluginActions","panelPluginKind","kind","actions","Array","isArray","length","headerActions","filter","action","location","index","ActionComponent","component","error","console","warn","item","Boolean","handleMouseEnter","e","handleMouseLeave","showIcons","isPanelViewed","itemActionsConfig","itemActionsListConfig","enabled","displayInHeader","actionsList","display","flexFlow","variant","aria-labelledby","aria-describedby","data-testid","hideHeader","extra","panelDefinition","id","title","name","description","links","py","pl","pr","dimension","position","overflow","flexGrow","margin","padding","FallbackComponent","resetKeys"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/components/Panel/Panel.tsx"],"sourcesContent":["// Copyright 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 {\n ErrorAlert,\n ErrorBoundary,\n ItemActionsProvider,\n SelectionProvider,\n combineSx,\n useId,\n} from '@perses-dev/components';\nimport { PanelDefinition } from '@perses-dev/spec';\nimport { ActionOptions, useDataQueriesContext, usePluginRegistry } from '@perses-dev/plugin-system';\nimport { ReactNode, memo, useEffect, useMemo, useState } from 'react';\nimport useResizeObserver from 'use-resize-observer';\nimport { PanelGroupItemId } from '../../model';\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 viewQueriesHandler?: PanelHeaderProps['viewQueriesHandler'];\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 * Whether to show panel icons always, or only when hovering over the panel.\n * Default: if the dashboard is in editing mode or the panel is in fullscreen mode: 'always', otherwise 'hover'\n */\n showIcons?: 'always' | 'hover';\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 viewQueriesHandler,\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 { queryResults } = useDataQueriesContext();\n const { getPlugin } = usePluginRegistry();\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 };\n }, [definition, contentDimensions, queryResults]);\n\n // Load plugin actions from the plugin\n const [pluginActions, setPluginActions] = useState<ReactNode[]>([]);\n\n useEffect(() => {\n const loadPluginActions = async (): Promise<void> => {\n const panelPluginKind = definition.spec.plugin.kind;\n\n if (!panelPluginKind || !panelPropsForActions || !getPlugin || typeof getPlugin !== 'function') {\n setPluginActions([]);\n return;\n }\n\n try {\n const plugin = await getPlugin({ kind: 'Panel', name: panelPluginKind });\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 setPluginActions([]);\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}`} {...(panelPropsForActions 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 setPluginActions(headerActions);\n } catch (error) {\n console.warn('Failed to load plugin actions:', error);\n setPluginActions([]);\n }\n };\n\n loadPluginActions();\n }, [definition.spec.plugin.kind, panelPropsForActions, getPlugin]);\n\n const handleMouseEnter: CardProps['onMouseEnter'] = (e) => {\n onMouseEnter?.(e);\n };\n\n const handleMouseLeave: CardProps['onMouseLeave'] = (e) => {\n onMouseLeave?.(e);\n };\n\n // default value for showIcons: if the dashboard is in editing mode or the panel is in fullscreen mode: 'always', otherwise 'hover'\n const showIcons = panelOptions?.showIcons ?? (editHandlers || readHandlers?.isPanelViewed ? 'always' : 'hover');\n const itemActionsConfig = definition.spec.plugin.spec?.actions\n ? (definition.spec.plugin.spec.actions as ActionOptions)\n : undefined;\n const itemActionsListConfig =\n itemActionsConfig?.enabled && itemActionsConfig.displayInHeader ? itemActionsConfig.actionsList : [];\n\n return (\n <SelectionProvider>\n <ItemActionsProvider>\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 viewQueriesHandler={viewQueriesHandler}\n links={definition.spec.links}\n pluginActions={pluginActions}\n itemActionsListConfig={itemActionsListConfig}\n showIcons={showIcons}\n sx={{ py: '2px', pl: '8px', pr: '2px' }}\n dimension={contentDimensions}\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, queryResults]}>\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 </ItemActionsProvider>\n </SelectionProvider>\n );\n});\n"],"names":["Card","CardContent","ErrorAlert","ErrorBoundary","ItemActionsProvider","SelectionProvider","combineSx","useId","useDataQueriesContext","usePluginRegistry","memo","useEffect","useMemo","useState","useResizeObserver","PanelContent","PanelHeader","Panel","props","definition","readHandlers","editHandlers","onMouseEnter","onMouseLeave","sx","panelOptions","panelGroupItemId","viewQueriesHandler","others","generatedPanelId","headerId","contentElement","setContentElement","width","height","ref","contentDimensions","undefined","queryResults","getPlugin","panelPropsForActions","spec","plugin","map","query","data","pluginActions","setPluginActions","loadPluginActions","panelPluginKind","kind","name","actions","Array","isArray","length","headerActions","filter","action","location","index","ActionComponent","component","error","console","warn","item","Boolean","handleMouseEnter","e","handleMouseLeave","showIcons","isPanelViewed","itemActionsConfig","itemActionsListConfig","enabled","displayInHeader","actionsList","display","flexFlow","variant","aria-labelledby","aria-describedby","data-testid","hideHeader","extra","panelDefinition","id","title","description","links","py","pl","pr","dimension","position","overflow","flexGrow","margin","padding","FallbackComponent","resetKeys"],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
1
2
  // Copyright The Perses Authors
2
3
  // Licensed under the Apache License, Version 2.0 (the "License");
3
4
  // you may not use this file except in compliance with the License.
@@ -10,7 +11,6 @@
10
11
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
12
  // See the License for the specific language governing permissions and
12
13
  // limitations under the License.
13
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
14
14
  import { Stack, Box, CircularProgress, styled, Popper, ClickAwayListener } from '@mui/material';
15
15
  import { isValidElement, useMemo, useState } from 'react';
16
16
  import { InfoTooltip } from '@perses-dev/components';
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/Panel/PanelActions.tsx"],"sourcesContent":["// Copyright 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, CircularProgress, styled, Popper, ClickAwayListener } from '@mui/material';\nimport { isValidElement, PropsWithChildren, ReactElement, ReactNode, useMemo, useState, MouseEvent } from 'react';\nimport { InfoTooltip } from '@perses-dev/components';\nimport { QueryData } from '@perses-dev/plugin-system';\nimport DatabaseSearch from 'mdi-material-ui/DatabaseSearch';\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 AlertCircleIcon from 'mdi-material-ui/AlertCircle';\nimport InformationOutlineIcon from 'mdi-material-ui/InformationOutline';\nimport LightningBoltIcon from 'mdi-material-ui/LightningBolt';\nimport { Link, Notice } from '@perses-dev/spec';\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 { LinksDisplay } from '../LinksDisplay';\nimport { HeaderIconButton } from './HeaderIconButton';\nimport { PanelOptions } from './Panel';\n\nconst noticeTypeToIcon: Record<Notice['type'], ReactNode> = {\n error: <AlertCircleIcon color=\"error\" />,\n warning: <AlertIcon fontSize=\"inherit\" color=\"warning\" />,\n info: <InformationOutlineIcon fontSize=\"inherit\" color=\"info\" />,\n};\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 viewQueriesHandler?: {\n onClick: () => void;\n };\n queryResults: QueryData[];\n pluginActions?: ReactNode[];\n itemActions?: ReactNode[];\n areItemActionsDisabled?: boolean;\n showIcons: PanelOptions['showIcons'];\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 viewQueriesHandler,\n extra,\n title,\n description,\n descriptionTooltipId,\n links,\n queryResults,\n pluginActions = [],\n itemActions = [],\n showIcons,\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 && <LinksDisplay links={links} variant=\"panel\" />;\n const extraActions = editHandlers === undefined && extra;\n\n const queryStateIndicator = useMemo((): ReactNode | undefined => {\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\n if (isFetching && hasData) {\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) => e.message)\n .join('\\n');\n\n return (\n <InfoTooltip description={errorTexts}>\n <HeaderIconButton aria-label=\"panel errors\" size=\"small\">\n <AlertIcon\n fontSize=\"inherit\"\n sx={{\n color: (theme) => theme.palette.error.main,\n }}\n />\n </HeaderIconButton>\n </InfoTooltip>\n );\n }\n }, [queryResults]);\n\n const noticesIndicator = useMemo(() => {\n const notices = queryResults.flatMap((q) => {\n return q.data?.metadata?.notices ?? [];\n });\n\n if (notices.length > 0) {\n const lastNotice = notices[notices.length - 1]!;\n\n return (\n <InfoTooltip description={lastNotice.message}>\n <HeaderIconButton aria-label=\"panel notices\" size=\"small\">\n {noticeTypeToIcon[lastNotice.type]}\n </HeaderIconButton>\n </InfoTooltip>\n );\n }\n }, [queryResults]);\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 viewQueryAction = useMemo(() => {\n if (!viewQueriesHandler?.onClick) return null;\n return (\n <InfoTooltip description={TOOLTIP_TEXT.queryView}>\n <HeaderIconButton\n aria-label={ARIA_LABEL_TEXT.openQueryView(title)}\n size=\"small\"\n onClick={viewQueriesHandler.onClick}\n >\n <DatabaseSearch fontSize=\"inherit\" />\n </HeaderIconButton>\n </InfoTooltip>\n );\n }, [viewQueriesHandler, title]);\n\n const editActions = useMemo((): ReactNode | undefined => {\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((): ReactNode | undefined => {\n if (editActions && !readHandlers?.isPanelViewed) {\n return (\n <Box sx={{ background: (theme) => theme.palette.background.default }}>\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 </Box>\n );\n }\n return undefined;\n }, [editActions, readHandlers, title]);\n\n const divider = <Box sx={{ flexGrow: 1 }}></Box>;\n\n // By default, the panel header shows certain icons only on hover if the panel is in non-editing, non-fullscreen mode\n const OnHover = ({ children }: PropsWithChildren): ReactNode =>\n showIcons === 'hover' ? <Box sx={{ display: 'var(--panel-hover, none)' }}>{children}</Box> : <>{children}</>;\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} {noticesIndicator} {extraActions} {viewQueryAction}\n {readActions} {pluginActions} {itemActions}\n {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 {noticesIndicator}\n <OnHover>\n {extraActions}\n {readActions}\n <OverflowMenu title={title}>\n {editActions} {viewQueryAction} {pluginActions} {itemActions}\n </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 {noticesIndicator}\n <OnHover>\n {extraActions}\n {viewQueryAction}\n {readActions} {editActions}\n {/* Show plugin actions inside a menu if it gets crowded */}\n {pluginActions.length <= 1 ? pluginActions : <OverflowMenu title={title}>{pluginActions}</OverflowMenu>}\n {itemActions.length <= 1 ? (\n itemActions\n ) : (\n <InfoTooltip description={`${itemActions.length} actions`}>\n <OverflowMenu icon={<LightningBoltIcon fontSize=\"inherit\" />} direction=\"column\" title={title}>\n {itemActions}\n </OverflowMenu>\n </InfoTooltip>\n )}\n {moveAction}\n </OnHover>\n </ConditionalBox>\n </>\n );\n};\n\nconst OverflowMenu: React.FC<\n PropsWithChildren<{\n title?: string;\n icon?: ReactElement;\n direction?: 'row' | 'column';\n placement?:\n | 'bottom'\n | 'top'\n | 'left'\n | 'right'\n | 'bottom-start'\n | 'bottom-end'\n | 'top-start'\n | 'top-end'\n | 'left-start'\n | 'left-end'\n | 'right-start'\n | 'right-end';\n offsetX?: number;\n offsetY?: number;\n }>\n> = ({ children, title, icon, direction = 'row', placement = 'bottom', offsetX = -2, offsetY = -25 }) => {\n const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);\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 null;\n }\n\n const handleClick = (event: MouseEvent<HTMLElement>): void => {\n setAnchorEl(anchorEl ? null : event.currentTarget);\n };\n\n const handleClose = (): void => {\n setAnchorEl(null);\n };\n\n const open = Boolean(anchorEl);\n const id = open ? 'actions-menu' : undefined;\n\n return (\n <Box sx={{ background: (theme) => theme.palette.background.default }}>\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 {icon ?? <MenuIcon fontSize=\"inherit\" />}\n </HeaderIconButton>\n <Popper\n id={id}\n open={open}\n anchorEl={anchorEl}\n placement={placement}\n modifiers={[\n {\n name: 'offset',\n options: {\n offset: [offsetX, offsetY],\n },\n },\n ]}\n sx={{\n backgroundColor: (theme) => theme.palette.background.paper,\n borderRadius: 1,\n boxShadow: (theme) => theme.shadows[4],\n }}\n >\n <ClickAwayListener onClickAway={handleClose}>\n <Stack direction={direction} alignItems=\"center\" sx={{ padding: 1 }} onClick={handleClose}>\n {children}\n </Stack>\n </ClickAwayListener>\n </Popper>\n </Box>\n );\n};\n"],"names":["Stack","Box","CircularProgress","styled","Popper","ClickAwayListener","isValidElement","useMemo","useState","InfoTooltip","DatabaseSearch","ArrowCollapseIcon","ArrowExpandIcon","PencilIcon","DeleteIcon","DragIcon","ContentCopyIcon","MenuIcon","AlertIcon","AlertCircleIcon","InformationOutlineIcon","LightningBoltIcon","ARIA_LABEL_TEXT","HEADER_ACTIONS_CONTAINER_NAME","HEADER_MEDIUM_WIDTH","HEADER_SMALL_WIDTH","TOOLTIP_TEXT","LinksDisplay","HeaderIconButton","noticeTypeToIcon","error","color","warning","fontSize","info","ConditionalBox","display","alignItems","flexGrow","justifyContent","PanelActions","editHandlers","readHandlers","viewQueriesHandler","extra","title","description","descriptionTooltipId","links","queryResults","pluginActions","itemActions","showIcons","descriptionAction","trim","length","id","enterDelay","aria-label","size","aria-describedby","aria-hidden","sx","theme","palette","text","secondary","undefined","linksAction","variant","extraActions","queryStateIndicator","hasData","some","q","data","isFetching","queryErrors","filter","errorTexts","map","e","message","join","main","noticesIndicator","notices","flatMap","metadata","lastNotice","type","readActions","viewPanel","onClick","onViewPanelClick","isPanelViewed","viewQueryAction","queryView","openQueryView","editActions","editPanel","onEditPanelClick","duplicatePanel","onDuplicatePanelClick","transform","deletePanel","onDeletePanelClick","moveAction","background","default","movePanel","className","cursor","divider","OnHover","children","containerQueries","between","OverflowMenu","down","icon","direction","placement","offsetX","offsetY","anchorEl","setAnchorEl","hasContent","Array","isArray","handleClick","event","currentTarget","handleClose","open","Boolean","showPanelActions","modifiers","name","options","offset","backgroundColor","paper","borderRadius","boxShadow","shadows","onClickAway","padding"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/components/Panel/PanelActions.tsx"],"sourcesContent":["// Copyright 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, CircularProgress, styled, Popper, ClickAwayListener } from '@mui/material';\nimport { isValidElement, PropsWithChildren, ReactElement, ReactNode, useMemo, useState, MouseEvent } from 'react';\nimport { InfoTooltip } from '@perses-dev/components';\nimport { QueryData } from '@perses-dev/plugin-system';\nimport DatabaseSearch from 'mdi-material-ui/DatabaseSearch';\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 AlertCircleIcon from 'mdi-material-ui/AlertCircle';\nimport InformationOutlineIcon from 'mdi-material-ui/InformationOutline';\nimport LightningBoltIcon from 'mdi-material-ui/LightningBolt';\nimport { Link, Notice } from '@perses-dev/spec';\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 { LinksDisplay } from '../LinksDisplay';\nimport { HeaderIconButton } from './HeaderIconButton';\nimport { PanelOptions } from './Panel';\n\nconst noticeTypeToIcon: Record<Notice['type'], ReactNode> = {\n error: <AlertCircleIcon color=\"error\" />,\n warning: <AlertIcon fontSize=\"inherit\" color=\"warning\" />,\n info: <InformationOutlineIcon fontSize=\"inherit\" color=\"info\" />,\n};\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 viewQueriesHandler?: {\n onClick: () => void;\n };\n queryResults: QueryData[];\n pluginActions?: ReactNode[];\n itemActions?: ReactNode[];\n areItemActionsDisabled?: boolean;\n showIcons: PanelOptions['showIcons'];\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 viewQueriesHandler,\n extra,\n title,\n description,\n descriptionTooltipId,\n links,\n queryResults,\n pluginActions = [],\n itemActions = [],\n showIcons,\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 && <LinksDisplay links={links} variant=\"panel\" />;\n const extraActions = editHandlers === undefined && extra;\n\n const queryStateIndicator = useMemo((): ReactNode | undefined => {\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\n if (isFetching && hasData) {\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) => e.message)\n .join('\\n');\n\n return (\n <InfoTooltip description={errorTexts}>\n <HeaderIconButton aria-label=\"panel errors\" size=\"small\">\n <AlertIcon\n fontSize=\"inherit\"\n sx={{\n color: (theme) => theme.palette.error.main,\n }}\n />\n </HeaderIconButton>\n </InfoTooltip>\n );\n }\n }, [queryResults]);\n\n const noticesIndicator = useMemo(() => {\n const notices = queryResults.flatMap((q) => {\n return q.data?.metadata?.notices ?? [];\n });\n\n if (notices.length > 0) {\n const lastNotice = notices[notices.length - 1]!;\n\n return (\n <InfoTooltip description={lastNotice.message}>\n <HeaderIconButton aria-label=\"panel notices\" size=\"small\">\n {noticeTypeToIcon[lastNotice.type]}\n </HeaderIconButton>\n </InfoTooltip>\n );\n }\n }, [queryResults]);\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 viewQueryAction = useMemo(() => {\n if (!viewQueriesHandler?.onClick) return null;\n return (\n <InfoTooltip description={TOOLTIP_TEXT.queryView}>\n <HeaderIconButton\n aria-label={ARIA_LABEL_TEXT.openQueryView(title)}\n size=\"small\"\n onClick={viewQueriesHandler.onClick}\n >\n <DatabaseSearch fontSize=\"inherit\" />\n </HeaderIconButton>\n </InfoTooltip>\n );\n }, [viewQueriesHandler, title]);\n\n const editActions = useMemo((): ReactNode | undefined => {\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((): ReactNode | undefined => {\n if (editActions && !readHandlers?.isPanelViewed) {\n return (\n <Box sx={{ background: (theme) => theme.palette.background.default }}>\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 </Box>\n );\n }\n return undefined;\n }, [editActions, readHandlers, title]);\n\n const divider = <Box sx={{ flexGrow: 1 }}></Box>;\n\n // By default, the panel header shows certain icons only on hover if the panel is in non-editing, non-fullscreen mode\n const OnHover = ({ children }: PropsWithChildren): ReactNode =>\n showIcons === 'hover' ? <Box sx={{ display: 'var(--panel-hover, none)' }}>{children}</Box> : <>{children}</>;\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} {noticesIndicator} {extraActions} {viewQueryAction}\n {readActions} {pluginActions} {itemActions}\n {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 {noticesIndicator}\n <OnHover>\n {extraActions}\n {readActions}\n <OverflowMenu title={title}>\n {editActions} {viewQueryAction} {pluginActions} {itemActions}\n </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 {noticesIndicator}\n <OnHover>\n {extraActions}\n {viewQueryAction}\n {readActions} {editActions}\n {/* Show plugin actions inside a menu if it gets crowded */}\n {pluginActions.length <= 1 ? pluginActions : <OverflowMenu title={title}>{pluginActions}</OverflowMenu>}\n {itemActions.length <= 1 ? (\n itemActions\n ) : (\n <InfoTooltip description={`${itemActions.length} actions`}>\n <OverflowMenu icon={<LightningBoltIcon fontSize=\"inherit\" />} direction=\"column\" title={title}>\n {itemActions}\n </OverflowMenu>\n </InfoTooltip>\n )}\n {moveAction}\n </OnHover>\n </ConditionalBox>\n </>\n );\n};\n\nconst OverflowMenu: React.FC<\n PropsWithChildren<{\n title?: string;\n icon?: ReactElement;\n direction?: 'row' | 'column';\n placement?:\n | 'bottom'\n | 'top'\n | 'left'\n | 'right'\n | 'bottom-start'\n | 'bottom-end'\n | 'top-start'\n | 'top-end'\n | 'left-start'\n | 'left-end'\n | 'right-start'\n | 'right-end';\n offsetX?: number;\n offsetY?: number;\n }>\n> = ({ children, title, icon, direction = 'row', placement = 'bottom', offsetX = -2, offsetY = -25 }) => {\n const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);\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 null;\n }\n\n const handleClick = (event: MouseEvent<HTMLElement>): void => {\n setAnchorEl(anchorEl ? null : event.currentTarget);\n };\n\n const handleClose = (): void => {\n setAnchorEl(null);\n };\n\n const open = Boolean(anchorEl);\n const id = open ? 'actions-menu' : undefined;\n\n return (\n <Box sx={{ background: (theme) => theme.palette.background.default }}>\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 {icon ?? <MenuIcon fontSize=\"inherit\" />}\n </HeaderIconButton>\n <Popper\n id={id}\n open={open}\n anchorEl={anchorEl}\n placement={placement}\n modifiers={[\n {\n name: 'offset',\n options: {\n offset: [offsetX, offsetY],\n },\n },\n ]}\n sx={{\n backgroundColor: (theme) => theme.palette.background.paper,\n borderRadius: 1,\n boxShadow: (theme) => theme.shadows[4],\n }}\n >\n <ClickAwayListener onClickAway={handleClose}>\n <Stack direction={direction} alignItems=\"center\" sx={{ padding: 1 }} onClick={handleClose}>\n {children}\n </Stack>\n </ClickAwayListener>\n </Popper>\n </Box>\n );\n};\n"],"names":["Stack","Box","CircularProgress","styled","Popper","ClickAwayListener","isValidElement","useMemo","useState","InfoTooltip","DatabaseSearch","ArrowCollapseIcon","ArrowExpandIcon","PencilIcon","DeleteIcon","DragIcon","ContentCopyIcon","MenuIcon","AlertIcon","AlertCircleIcon","InformationOutlineIcon","LightningBoltIcon","ARIA_LABEL_TEXT","HEADER_ACTIONS_CONTAINER_NAME","HEADER_MEDIUM_WIDTH","HEADER_SMALL_WIDTH","TOOLTIP_TEXT","LinksDisplay","HeaderIconButton","noticeTypeToIcon","error","color","warning","fontSize","info","ConditionalBox","display","alignItems","flexGrow","justifyContent","PanelActions","editHandlers","readHandlers","viewQueriesHandler","extra","title","description","descriptionTooltipId","links","queryResults","pluginActions","itemActions","showIcons","descriptionAction","trim","length","id","enterDelay","aria-label","size","aria-describedby","aria-hidden","sx","theme","palette","text","secondary","undefined","linksAction","variant","extraActions","queryStateIndicator","hasData","some","q","data","isFetching","queryErrors","filter","errorTexts","map","e","message","join","main","noticesIndicator","notices","flatMap","metadata","lastNotice","type","readActions","viewPanel","onClick","onViewPanelClick","isPanelViewed","viewQueryAction","queryView","openQueryView","editActions","editPanel","onEditPanelClick","duplicatePanel","onDuplicatePanelClick","transform","deletePanel","onDeletePanelClick","moveAction","background","default","movePanel","className","cursor","divider","OnHover","children","containerQueries","between","OverflowMenu","down","icon","direction","placement","offsetX","offsetY","anchorEl","setAnchorEl","hasContent","Array","isArray","handleClick","event","currentTarget","handleClose","open","Boolean","showPanelActions","modifiers","name","options","offset","backgroundColor","paper","borderRadius","boxShadow","shadows","onClickAway","padding"],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
1
2
  // Copyright The Perses Authors
2
3
  // Licensed under the Apache License, Version 2.0 (the "License");
3
4
  // you may not use this file except in compliance with the License.
@@ -10,7 +11,6 @@
10
11
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
12
  // See the License for the specific language governing permissions and
12
13
  // limitations under the License.
13
- import { jsx as _jsx } from "react/jsx-runtime";
14
14
  import { usePlugin } from '@perses-dev/plugin-system';
15
15
  import { LoadingOverlay } from '@perses-dev/components';
16
16
  import { Skeleton } from '@mui/material';
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/Panel/PanelContent.tsx"],"sourcesContent":["// Copyright 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 { usePlugin, PanelProps, QueryData, PanelPlugin } from '@perses-dev/plugin-system';\nimport { UnknownSpec, PanelDefinition, QueryDataType } from '@perses-dev/spec';\nimport { ReactElement } from 'react';\nimport { LoadingOverlay } from '@perses-dev/components';\nimport { Skeleton } from '@mui/material';\nimport { PanelPluginLoader } from './PanelPluginLoader';\n\nexport interface PanelContentProps extends Omit<PanelProps<UnknownSpec>, 'queryResults'> {\n panelPluginKind: string;\n definition?: PanelDefinition<UnknownSpec>;\n queryResults: QueryData[];\n}\n\n/**\n * Based on the status of the queries (loading, error or data available), this component renders a\n * loading overlay, throws an error, or renders the panel content.\n */\nexport function PanelContent(props: PanelContentProps): ReactElement {\n const { panelPluginKind, definition, queryResults, spec, contentDimensions } = props;\n const { data: plugin, isLoading: isPanelLoading } = usePlugin('Panel', panelPluginKind, { useErrorBoundary: true });\n\n // Show fullsize skeleton if the panel plugin is loading.\n if (isPanelLoading) {\n return (\n <Skeleton\n variant=\"rectangular\"\n width={contentDimensions?.width}\n height={contentDimensions?.height}\n aria-label=\"Loading...\"\n />\n );\n }\n\n // Render the panel if any query has data, or the panel doesn't have a query attached (for example MarkdownPanel).\n // Loading indicator or errors of other queries are shown in the panel header.\n const queryResultsWithData = queryResults.flatMap((q) =>\n q.data ? [{ data: q.data, definition: q.definition }] : []\n );\n if (queryResultsWithData.length > 0 || queryResults.length === 0) {\n return (\n <PanelPluginLoader\n kind={panelPluginKind}\n spec={spec}\n contentDimensions={contentDimensions}\n definition={definition}\n queryResults={queryResultsWithData}\n />\n );\n }\n\n // No query has data, show loading overlay if any query is fetching data.\n if (queryResults.some((q) => q.isFetching)) {\n return <PanelLoading plugin={plugin} spec={spec} definition={definition} contentDimensions={contentDimensions} />;\n }\n\n // No query has data or is loading, show the error if any query has an error.\n // The error will be catched in <ErrorBoundary> of <Panel>.\n const queryError = queryResults.find((q) => q.error);\n if (queryError) {\n throw queryError.error;\n }\n\n // At this point, one or more queries are defined, but no query has data, is loading, or has an error.\n // This can happen if all queries are disabled (e.g. dependent dashboard variables are loading, or they are not in the viewport of the browser).\n // Most likely, some query will be enabled later. Render the panel loading skeleton.\n return <PanelLoading plugin={plugin} spec={spec} definition={definition} contentDimensions={contentDimensions} />;\n}\n\ninterface PanelLoadingProps extends Pick<PanelContentProps, 'spec' | 'definition' | 'contentDimensions'> {\n plugin?: PanelPlugin<UnknownSpec, PanelProps<UnknownSpec, QueryDataType>>;\n}\n\nfunction PanelLoading({ plugin, spec, definition, contentDimensions }: PanelLoadingProps): ReactElement {\n if (plugin?.LoadingComponent) {\n return (\n <plugin.LoadingComponent\n spec={spec}\n contentDimensions={contentDimensions}\n definition={definition}\n queryResults={[]}\n />\n );\n }\n return <LoadingOverlay />;\n}\n"],"names":["usePlugin","LoadingOverlay","Skeleton","PanelPluginLoader","PanelContent","props","panelPluginKind","definition","queryResults","spec","contentDimensions","data","plugin","isLoading","isPanelLoading","useErrorBoundary","variant","width","height","aria-label","queryResultsWithData","flatMap","q","length","kind","some","isFetching","PanelLoading","queryError","find","error","LoadingComponent"],"mappings":"AAAA,+BAA+B;AAC/B,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;;AAEjC,SAASA,SAAS,QAA4C,4BAA4B;AAG1F,SAASC,cAAc,QAAQ,yBAAyB;AACxD,SAASC,QAAQ,QAAQ,gBAAgB;AACzC,SAASC,iBAAiB,QAAQ,sBAAsB;AAQxD;;;CAGC,GACD,OAAO,SAASC,aAAaC,KAAwB;IACnD,MAAM,EAAEC,eAAe,EAAEC,UAAU,EAAEC,YAAY,EAAEC,IAAI,EAAEC,iBAAiB,EAAE,GAAGL;IAC/E,MAAM,EAAEM,MAAMC,MAAM,EAAEC,WAAWC,cAAc,EAAE,GAAGd,UAAU,SAASM,iBAAiB;QAAES,kBAAkB;IAAK;IAEjH,yDAAyD;IACzD,IAAID,gBAAgB;QAClB,qBACE,KAACZ;YACCc,SAAQ;YACRC,OAAOP,mBAAmBO;YAC1BC,QAAQR,mBAAmBQ;YAC3BC,cAAW;;IAGjB;IAEA,kHAAkH;IAClH,8EAA8E;IAC9E,MAAMC,uBAAuBZ,aAAaa,OAAO,CAAC,CAACC,IACjDA,EAAEX,IAAI,GAAG;YAAC;gBAAEA,MAAMW,EAAEX,IAAI;gBAAEJ,YAAYe,EAAEf,UAAU;YAAC;SAAE,GAAG,EAAE;IAE5D,IAAIa,qBAAqBG,MAAM,GAAG,KAAKf,aAAae,MAAM,KAAK,GAAG;QAChE,qBACE,KAACpB;YACCqB,MAAMlB;YACNG,MAAMA;YACNC,mBAAmBA;YACnBH,YAAYA;YACZC,cAAcY;;IAGpB;IAEA,yEAAyE;IACzE,IAAIZ,aAAaiB,IAAI,CAAC,CAACH,IAAMA,EAAEI,UAAU,GAAG;QAC1C,qBAAO,KAACC;YAAaf,QAAQA;YAAQH,MAAMA;YAAMF,YAAYA;YAAYG,mBAAmBA;;IAC9F;IAEA,6EAA6E;IAC7E,2DAA2D;IAC3D,MAAMkB,aAAapB,aAAaqB,IAAI,CAAC,CAACP,IAAMA,EAAEQ,KAAK;IACnD,IAAIF,YAAY;QACd,MAAMA,WAAWE,KAAK;IACxB;IAEA,sGAAsG;IACtG,gJAAgJ;IAChJ,oFAAoF;IACpF,qBAAO,KAACH;QAAaf,QAAQA;QAAQH,MAAMA;QAAMF,YAAYA;QAAYG,mBAAmBA;;AAC9F;AAMA,SAASiB,aAAa,EAAEf,MAAM,EAAEH,IAAI,EAAEF,UAAU,EAAEG,iBAAiB,EAAqB;IACtF,IAAIE,QAAQmB,kBAAkB;QAC5B,qBACE,KAACnB,OAAOmB,gBAAgB;YACtBtB,MAAMA;YACNC,mBAAmBA;YACnBH,YAAYA;YACZC,cAAc,EAAE;;IAGtB;IACA,qBAAO,KAACP;AACV"}
1
+ {"version":3,"sources":["../../../src/components/Panel/PanelContent.tsx"],"sourcesContent":["// Copyright 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 { usePlugin, PanelProps, QueryData, PanelPlugin } from '@perses-dev/plugin-system';\nimport { UnknownSpec, PanelDefinition, QueryDataType } from '@perses-dev/spec';\nimport { ReactElement } from 'react';\nimport { LoadingOverlay } from '@perses-dev/components';\nimport { Skeleton } from '@mui/material';\nimport { PanelPluginLoader } from './PanelPluginLoader';\n\nexport interface PanelContentProps extends Omit<PanelProps<UnknownSpec>, 'queryResults'> {\n panelPluginKind: string;\n definition?: PanelDefinition<UnknownSpec>;\n queryResults: QueryData[];\n}\n\n/**\n * Based on the status of the queries (loading, error or data available), this component renders a\n * loading overlay, throws an error, or renders the panel content.\n */\nexport function PanelContent(props: PanelContentProps): ReactElement {\n const { panelPluginKind, definition, queryResults, spec, contentDimensions } = props;\n const { data: plugin, isLoading: isPanelLoading } = usePlugin('Panel', panelPluginKind, { useErrorBoundary: true });\n\n // Show fullsize skeleton if the panel plugin is loading.\n if (isPanelLoading) {\n return (\n <Skeleton\n variant=\"rectangular\"\n width={contentDimensions?.width}\n height={contentDimensions?.height}\n aria-label=\"Loading...\"\n />\n );\n }\n\n // Render the panel if any query has data, or the panel doesn't have a query attached (for example MarkdownPanel).\n // Loading indicator or errors of other queries are shown in the panel header.\n const queryResultsWithData = queryResults.flatMap((q) =>\n q.data ? [{ data: q.data, definition: q.definition }] : []\n );\n if (queryResultsWithData.length > 0 || queryResults.length === 0) {\n return (\n <PanelPluginLoader\n kind={panelPluginKind}\n spec={spec}\n contentDimensions={contentDimensions}\n definition={definition}\n queryResults={queryResultsWithData}\n />\n );\n }\n\n // No query has data, show loading overlay if any query is fetching data.\n if (queryResults.some((q) => q.isFetching)) {\n return <PanelLoading plugin={plugin} spec={spec} definition={definition} contentDimensions={contentDimensions} />;\n }\n\n // No query has data or is loading, show the error if any query has an error.\n // The error will be catched in <ErrorBoundary> of <Panel>.\n const queryError = queryResults.find((q) => q.error);\n if (queryError) {\n throw queryError.error;\n }\n\n // At this point, one or more queries are defined, but no query has data, is loading, or has an error.\n // This can happen if all queries are disabled (e.g. dependent dashboard variables are loading, or they are not in the viewport of the browser).\n // Most likely, some query will be enabled later. Render the panel loading skeleton.\n return <PanelLoading plugin={plugin} spec={spec} definition={definition} contentDimensions={contentDimensions} />;\n}\n\ninterface PanelLoadingProps extends Pick<PanelContentProps, 'spec' | 'definition' | 'contentDimensions'> {\n plugin?: PanelPlugin<UnknownSpec, PanelProps<UnknownSpec, QueryDataType>>;\n}\n\nfunction PanelLoading({ plugin, spec, definition, contentDimensions }: PanelLoadingProps): ReactElement {\n if (plugin?.LoadingComponent) {\n return (\n <plugin.LoadingComponent\n spec={spec}\n contentDimensions={contentDimensions}\n definition={definition}\n queryResults={[]}\n />\n );\n }\n return <LoadingOverlay />;\n}\n"],"names":["usePlugin","LoadingOverlay","Skeleton","PanelPluginLoader","PanelContent","props","panelPluginKind","definition","queryResults","spec","contentDimensions","data","plugin","isLoading","isPanelLoading","useErrorBoundary","variant","width","height","aria-label","queryResultsWithData","flatMap","q","length","kind","some","isFetching","PanelLoading","queryError","find","error","LoadingComponent"],"mappings":";AAAA,+BAA+B;AAC/B,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;AAEjC,SAASA,SAAS,QAA4C,4BAA4B;AAG1F,SAASC,cAAc,QAAQ,yBAAyB;AACxD,SAASC,QAAQ,QAAQ,gBAAgB;AACzC,SAASC,iBAAiB,QAAQ,sBAAsB;AAQxD;;;CAGC,GACD,OAAO,SAASC,aAAaC,KAAwB;IACnD,MAAM,EAAEC,eAAe,EAAEC,UAAU,EAAEC,YAAY,EAAEC,IAAI,EAAEC,iBAAiB,EAAE,GAAGL;IAC/E,MAAM,EAAEM,MAAMC,MAAM,EAAEC,WAAWC,cAAc,EAAE,GAAGd,UAAU,SAASM,iBAAiB;QAAES,kBAAkB;IAAK;IAEjH,yDAAyD;IACzD,IAAID,gBAAgB;QAClB,qBACE,KAACZ;YACCc,SAAQ;YACRC,OAAOP,mBAAmBO;YAC1BC,QAAQR,mBAAmBQ;YAC3BC,cAAW;;IAGjB;IAEA,kHAAkH;IAClH,8EAA8E;IAC9E,MAAMC,uBAAuBZ,aAAaa,OAAO,CAAC,CAACC,IACjDA,EAAEX,IAAI,GAAG;YAAC;gBAAEA,MAAMW,EAAEX,IAAI;gBAAEJ,YAAYe,EAAEf,UAAU;YAAC;SAAE,GAAG,EAAE;IAE5D,IAAIa,qBAAqBG,MAAM,GAAG,KAAKf,aAAae,MAAM,KAAK,GAAG;QAChE,qBACE,KAACpB;YACCqB,MAAMlB;YACNG,MAAMA;YACNC,mBAAmBA;YACnBH,YAAYA;YACZC,cAAcY;;IAGpB;IAEA,yEAAyE;IACzE,IAAIZ,aAAaiB,IAAI,CAAC,CAACH,IAAMA,EAAEI,UAAU,GAAG;QAC1C,qBAAO,KAACC;YAAaf,QAAQA;YAAQH,MAAMA;YAAMF,YAAYA;YAAYG,mBAAmBA;;IAC9F;IAEA,6EAA6E;IAC7E,2DAA2D;IAC3D,MAAMkB,aAAapB,aAAaqB,IAAI,CAAC,CAACP,IAAMA,EAAEQ,KAAK;IACnD,IAAIF,YAAY;QACd,MAAMA,WAAWE,KAAK;IACxB;IAEA,sGAAsG;IACtG,gJAAgJ;IAChJ,oFAAoF;IACpF,qBAAO,KAACH;QAAaf,QAAQA;QAAQH,MAAMA;QAAMF,YAAYA;QAAYG,mBAAmBA;;AAC9F;AAMA,SAASiB,aAAa,EAAEf,MAAM,EAAEH,IAAI,EAAEF,UAAU,EAAEG,iBAAiB,EAAqB;IACtF,IAAIE,QAAQmB,kBAAkB;QAC5B,qBACE,KAACnB,OAAOmB,gBAAgB;YACtBtB,MAAMA;YACNC,mBAAmBA;YACnBH,YAAYA;YACZC,cAAc,EAAE;;IAGtB;IACA,qBAAO,KAACP;AACV"}
@@ -1,3 +1,4 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
1
2
  // Copyright The Perses Authors
2
3
  // Licensed under the Apache License, Version 2.0 (the "License");
3
4
  // you may not use this file except in compliance with the License.
@@ -10,7 +11,6 @@
10
11
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
12
  // See the License for the specific language governing permissions and
12
13
  // limitations under the License.
13
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
14
14
  import { CardHeader, Stack, Typography, Tooltip } from '@mui/material';
15
15
  import { combineSx } from '@perses-dev/components';
16
16
  import { useAllVariableValues, useReplaceVariablesInString } from '@perses-dev/plugin-system';