@perses-dev/dashboards 0.20.0 → 0.21.1

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 (104) hide show
  1. package/dist/cjs/components/DashboardToolbar/DashboardToolbar.js +18 -5
  2. package/dist/cjs/components/DeletePanelDialog/DeletePanelDialog.js +2 -0
  3. package/dist/cjs/components/DeletePanelGroupDialog/DeletePanelGroupDialog.js +2 -0
  4. package/dist/cjs/components/DiscardChangesConfirmationDialog/DiscardChangesConfirmationDialog.js +74 -0
  5. package/dist/cjs/components/{UnsavedChangesConfirmationDialog → DiscardChangesConfirmationDialog}/index.js +1 -1
  6. package/dist/cjs/components/GridLayout/GridTitle.js +38 -22
  7. package/dist/cjs/components/Panel/PanelHeader.js +59 -26
  8. package/dist/cjs/components/PanelDrawer/PanelDrawer.js +29 -8
  9. package/dist/cjs/components/PanelDrawer/PanelEditorForm.js +11 -6
  10. package/dist/cjs/components/TimeRangeControls/TimeRangeControls.js +9 -2
  11. package/dist/cjs/components/Variables/Variable.js +5 -3
  12. package/dist/cjs/components/Variables/VariableEditor.js +115 -99
  13. package/dist/cjs/components/Variables/VariableEditorForm/VariableEditorForm.js +67 -56
  14. package/dist/cjs/components/Variables/VariableList.js +7 -20
  15. package/dist/cjs/components/Variables/variable-model.js +12 -1
  16. package/dist/cjs/components/index.js +1 -1
  17. package/dist/cjs/context/DashboardProvider/DashboardProvider.js +2 -0
  18. package/dist/cjs/context/DashboardProvider/dashboard-provider-api.js +10 -1
  19. package/dist/cjs/context/DashboardProvider/discard-changes-dialog-slice.js +33 -0
  20. package/dist/cjs/views/ViewDashboard/DashboardApp.js +14 -14
  21. package/dist/cjs/views/ViewDashboard/ViewDashboard.js +2 -1
  22. package/dist/components/DashboardToolbar/DashboardToolbar.d.ts +2 -0
  23. package/dist/components/DashboardToolbar/DashboardToolbar.d.ts.map +1 -1
  24. package/dist/components/DashboardToolbar/DashboardToolbar.js +19 -6
  25. package/dist/components/DashboardToolbar/DashboardToolbar.js.map +1 -1
  26. package/dist/components/DeletePanelDialog/DeletePanelDialog.js +2 -0
  27. package/dist/components/DeletePanelDialog/DeletePanelDialog.js.map +1 -1
  28. package/dist/components/DeletePanelGroupDialog/DeletePanelGroupDialog.d.ts.map +1 -1
  29. package/dist/components/DeletePanelGroupDialog/DeletePanelGroupDialog.js +2 -0
  30. package/dist/components/DeletePanelGroupDialog/DeletePanelGroupDialog.js.map +1 -1
  31. package/dist/components/DiscardChangesConfirmationDialog/DiscardChangesConfirmationDialog.d.ts +3 -0
  32. package/dist/components/DiscardChangesConfirmationDialog/DiscardChangesConfirmationDialog.d.ts.map +1 -0
  33. package/dist/components/DiscardChangesConfirmationDialog/DiscardChangesConfirmationDialog.js +63 -0
  34. package/dist/components/DiscardChangesConfirmationDialog/DiscardChangesConfirmationDialog.js.map +1 -0
  35. package/dist/components/DiscardChangesConfirmationDialog/index.d.ts +2 -0
  36. package/dist/components/DiscardChangesConfirmationDialog/index.d.ts.map +1 -0
  37. package/dist/components/{UnsavedChangesConfirmationDialog → DiscardChangesConfirmationDialog}/index.js +1 -1
  38. package/dist/components/{UnsavedChangesConfirmationDialog → DiscardChangesConfirmationDialog}/index.js.map +1 -1
  39. package/dist/components/GridLayout/GridTitle.d.ts.map +1 -1
  40. package/dist/components/GridLayout/GridTitle.js +38 -22
  41. package/dist/components/GridLayout/GridTitle.js.map +1 -1
  42. package/dist/components/Panel/PanelHeader.d.ts.map +1 -1
  43. package/dist/components/Panel/PanelHeader.js +61 -28
  44. package/dist/components/Panel/PanelHeader.js.map +1 -1
  45. package/dist/components/PanelDrawer/PanelDrawer.d.ts.map +1 -1
  46. package/dist/components/PanelDrawer/PanelDrawer.js +32 -11
  47. package/dist/components/PanelDrawer/PanelDrawer.js.map +1 -1
  48. package/dist/components/PanelDrawer/PanelEditorForm.d.ts +1 -1
  49. package/dist/components/PanelDrawer/PanelEditorForm.d.ts.map +1 -1
  50. package/dist/components/PanelDrawer/PanelEditorForm.js +12 -7
  51. package/dist/components/PanelDrawer/PanelEditorForm.js.map +1 -1
  52. package/dist/components/TimeRangeControls/TimeRangeControls.d.ts +5 -1
  53. package/dist/components/TimeRangeControls/TimeRangeControls.d.ts.map +1 -1
  54. package/dist/components/TimeRangeControls/TimeRangeControls.js +9 -2
  55. package/dist/components/TimeRangeControls/TimeRangeControls.js.map +1 -1
  56. package/dist/components/Variables/Variable.js +5 -3
  57. package/dist/components/Variables/Variable.js.map +1 -1
  58. package/dist/components/Variables/VariableEditor.d.ts.map +1 -1
  59. package/dist/components/Variables/VariableEditor.js +115 -99
  60. package/dist/components/Variables/VariableEditor.js.map +1 -1
  61. package/dist/components/Variables/VariableEditorForm/VariableEditorForm.d.ts.map +1 -1
  62. package/dist/components/Variables/VariableEditorForm/VariableEditorForm.js +68 -57
  63. package/dist/components/Variables/VariableEditorForm/VariableEditorForm.js.map +1 -1
  64. package/dist/components/Variables/VariableList.d.ts.map +1 -1
  65. package/dist/components/Variables/VariableList.js +7 -20
  66. package/dist/components/Variables/VariableList.js.map +1 -1
  67. package/dist/components/Variables/variable-model.d.ts +7 -0
  68. package/dist/components/Variables/variable-model.d.ts.map +1 -1
  69. package/dist/components/Variables/variable-model.js +10 -0
  70. package/dist/components/Variables/variable-model.js.map +1 -1
  71. package/dist/components/index.d.ts +1 -1
  72. package/dist/components/index.js +1 -1
  73. package/dist/components/index.js.map +1 -1
  74. package/dist/context/DashboardProvider/DashboardProvider.d.ts +2 -1
  75. package/dist/context/DashboardProvider/DashboardProvider.d.ts.map +1 -1
  76. package/dist/context/DashboardProvider/DashboardProvider.js +2 -0
  77. package/dist/context/DashboardProvider/DashboardProvider.js.map +1 -1
  78. package/dist/context/DashboardProvider/dashboard-provider-api.d.ts +5 -0
  79. package/dist/context/DashboardProvider/dashboard-provider-api.d.ts.map +1 -1
  80. package/dist/context/DashboardProvider/dashboard-provider-api.js +8 -0
  81. package/dist/context/DashboardProvider/dashboard-provider-api.js.map +1 -1
  82. package/dist/context/DashboardProvider/discard-changes-dialog-slice.d.ts +15 -0
  83. package/dist/context/DashboardProvider/discard-changes-dialog-slice.d.ts.map +1 -0
  84. package/dist/context/DashboardProvider/discard-changes-dialog-slice.js +27 -0
  85. package/dist/context/DashboardProvider/discard-changes-dialog-slice.js.map +1 -0
  86. package/dist/context/DashboardProvider/index.d.ts +1 -0
  87. package/dist/context/DashboardProvider/index.d.ts.map +1 -1
  88. package/dist/context/DashboardProvider/index.js.map +1 -1
  89. package/dist/views/ViewDashboard/DashboardApp.d.ts +1 -0
  90. package/dist/views/ViewDashboard/DashboardApp.d.ts.map +1 -1
  91. package/dist/views/ViewDashboard/DashboardApp.js +16 -16
  92. package/dist/views/ViewDashboard/DashboardApp.js.map +1 -1
  93. package/dist/views/ViewDashboard/ViewDashboard.d.ts +1 -0
  94. package/dist/views/ViewDashboard/ViewDashboard.d.ts.map +1 -1
  95. package/dist/views/ViewDashboard/ViewDashboard.js +2 -1
  96. package/dist/views/ViewDashboard/ViewDashboard.js.map +1 -1
  97. package/package.json +4 -4
  98. package/dist/cjs/components/UnsavedChangesConfirmationDialog/UnsavedChangesConfirmationDialog.js +0 -67
  99. package/dist/components/UnsavedChangesConfirmationDialog/UnsavedChangesConfirmationDialog.d.ts +0 -8
  100. package/dist/components/UnsavedChangesConfirmationDialog/UnsavedChangesConfirmationDialog.d.ts.map +0 -1
  101. package/dist/components/UnsavedChangesConfirmationDialog/UnsavedChangesConfirmationDialog.js +0 -56
  102. package/dist/components/UnsavedChangesConfirmationDialog/UnsavedChangesConfirmationDialog.js.map +0 -1
  103. package/dist/components/UnsavedChangesConfirmationDialog/index.d.ts +0 -2
  104. package/dist/components/UnsavedChangesConfirmationDialog/index.d.ts.map +0 -1
@@ -24,6 +24,7 @@ const _pencilOutline = /*#__PURE__*/ _interopRequireDefault(require("mdi-materia
24
24
  const _plusBoxOutline = /*#__PURE__*/ _interopRequireDefault(require("mdi-material-ui/PlusBoxOutline"));
25
25
  const _chartBoxPlusOutline = /*#__PURE__*/ _interopRequireDefault(require("mdi-material-ui/ChartBoxPlusOutline"));
26
26
  const _components = require("@perses-dev/components");
27
+ const _react = require("react");
27
28
  const _context = require("../../context");
28
29
  const _variables = require("../Variables");
29
30
  const _timeRangeControls = require("../TimeRangeControls");
@@ -34,16 +35,28 @@ function _interopRequireDefault(obj) {
34
35
  };
35
36
  }
36
37
  const DashboardToolbar = (props)=>{
37
- const { dashboardName , dashboardTitleComponent , initialVariableIsSticky , isReadonly , onEditButtonClick , onCancelButtonClick , } = props;
38
+ const { dashboardName , dashboardTitleComponent , initialVariableIsSticky , isReadonly , onEditButtonClick , onCancelButtonClick , onSave , } = props;
38
39
  const { isEditMode , setEditMode } = (0, _context.useEditMode)();
40
+ const [isSavingDashboard, setSavingDashboard] = (0, _react.useState)(false);
41
+ const dashboard = (0, _context.useDashboard)();
39
42
  const { openAddPanelGroup , openAddPanel } = (0, _context.useDashboardActions)();
40
43
  const isLaptopSize = (0, _material.useMediaQuery)((0, _material.useTheme)().breakpoints.up('sm'));
41
44
  const dashboardTitle = dashboardTitleComponent ? dashboardTitleComponent : /*#__PURE__*/ (0, _jsxRuntime.jsx)(_material.Typography, {
42
45
  variant: "h2",
43
46
  children: dashboardName
44
47
  });
45
- const onSave = ()=>{
46
- setEditMode(false);
48
+ const onSaveButtonClick = ()=>{
49
+ if (onSave !== undefined) {
50
+ setSavingDashboard(true);
51
+ onSave(dashboard.dashboard).then(()=>{
52
+ setSavingDashboard(false);
53
+ setEditMode(false);
54
+ }).catch(()=>{
55
+ setSavingDashboard(false);
56
+ });
57
+ } else {
58
+ setEditMode(false);
59
+ }
47
60
  };
48
61
  return /*#__PURE__*/ (0, _jsxRuntime.jsx)(_jsxRuntime.Fragment, {
49
62
  children: isEditMode ? /*#__PURE__*/ (0, _jsxRuntime.jsxs)(_material.Stack, {
@@ -72,8 +85,8 @@ const DashboardToolbar = (props)=>{
72
85
  }),
73
86
  /*#__PURE__*/ (0, _jsxRuntime.jsx)(_material.Button, {
74
87
  variant: "contained",
75
- onClick: onSave,
76
- disabled: isReadonly,
88
+ onClick: onSaveButtonClick,
89
+ disabled: isReadonly || isSavingDashboard,
77
90
  children: "Save"
78
91
  }),
79
92
  /*#__PURE__*/ (0, _jsxRuntime.jsx)(_material.Button, {
@@ -63,6 +63,7 @@ const DeletePanelForm = ({ deletePanelDialog })=>{
63
63
  onSubmit: handleDelete,
64
64
  children: [
65
65
  /*#__PURE__*/ (0, _jsxRuntime.jsxs)(_material.DialogContent, {
66
+ dividers: true,
66
67
  sx: {
67
68
  width: '500px'
68
69
  },
@@ -82,6 +83,7 @@ const DeletePanelForm = ({ deletePanelDialog })=>{
82
83
  children: "Delete"
83
84
  }),
84
85
  /*#__PURE__*/ (0, _jsxRuntime.jsx)(_material.Button, {
86
+ variant: "outlined",
85
87
  onClick: ()=>closeDeletePanelDialog(),
86
88
  children: "Cancel"
87
89
  })
@@ -59,6 +59,7 @@ const DeletePanelGroupDialog = ()=>{
59
59
  onSubmit: handleDelete,
60
60
  children: [
61
61
  /*#__PURE__*/ (0, _jsxRuntime.jsxs)(_material.DialogContent, {
62
+ dividers: true,
62
63
  sx: {
63
64
  width: '500px'
64
65
  },
@@ -76,6 +77,7 @@ const DeletePanelGroupDialog = ()=>{
76
77
  children: "Delete"
77
78
  }),
78
79
  /*#__PURE__*/ (0, _jsxRuntime.jsx)(_material.Button, {
80
+ variant: "outlined",
79
81
  onClick: ()=>closeDeletePanelGroupDialog(),
80
82
  children: "Cancel"
81
83
  })
@@ -0,0 +1,74 @@
1
+ // Copyright 2022 The Perses Authors
2
+ // Licensed under the Apache License, Version 2.0 (the "License");
3
+ // you may not use this file except in compliance with the License.
4
+ // You may obtain a copy of the License at
5
+ //
6
+ // http://www.apache.org/licenses/LICENSE-2.0
7
+ //
8
+ // Unless required by applicable law or agreed to in writing, software
9
+ // distributed under the License is distributed on an "AS IS" BASIS,
10
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ // See the License for the specific language governing permissions and
12
+ // limitations under the License.
13
+ "use strict";
14
+ Object.defineProperty(exports, "__esModule", {
15
+ value: true
16
+ });
17
+ Object.defineProperty(exports, "DiscardChangesConfirmationDialog", {
18
+ enumerable: true,
19
+ get: ()=>DiscardChangesConfirmationDialog
20
+ });
21
+ const _jsxRuntime = require("react/jsx-runtime");
22
+ const _material = require("@mui/material");
23
+ const _close = /*#__PURE__*/ _interopRequireDefault(require("mdi-material-ui/Close"));
24
+ const _context = require("../../context");
25
+ function _interopRequireDefault(obj) {
26
+ return obj && obj.__esModule ? obj : {
27
+ default: obj
28
+ };
29
+ }
30
+ const DiscardChangesConfirmationDialog = ()=>{
31
+ const { discardChangesConfirmationDialog: dialog } = (0, _context.useDiscardChangesConfirmationDialog)();
32
+ const isOpen = dialog !== undefined;
33
+ return /*#__PURE__*/ (0, _jsxRuntime.jsx)(_material.Dialog, {
34
+ open: isOpen,
35
+ children: dialog !== undefined && /*#__PURE__*/ (0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
36
+ children: [
37
+ /*#__PURE__*/ (0, _jsxRuntime.jsx)(_material.DialogTitle, {
38
+ children: "Discard Changes"
39
+ }),
40
+ /*#__PURE__*/ (0, _jsxRuntime.jsx)(_material.IconButton, {
41
+ "aria-label": "Close",
42
+ onClick: dialog.onCancel,
43
+ sx: (theme)=>({
44
+ position: 'absolute',
45
+ top: theme.spacing(0.5),
46
+ right: theme.spacing(0.5)
47
+ }),
48
+ children: /*#__PURE__*/ (0, _jsxRuntime.jsx)(_close.default, {})
49
+ }),
50
+ /*#__PURE__*/ (0, _jsxRuntime.jsx)(_material.DialogContent, {
51
+ dividers: true,
52
+ sx: {
53
+ width: '500px'
54
+ },
55
+ children: dialog.description || 'You have unsaved changes in this dashboard. Are you sure you want to discard these changes? Changes cannot be recovered.'
56
+ }),
57
+ /*#__PURE__*/ (0, _jsxRuntime.jsxs)(_material.DialogActions, {
58
+ children: [
59
+ /*#__PURE__*/ (0, _jsxRuntime.jsx)(_material.Button, {
60
+ variant: "contained",
61
+ onClick: dialog.onDiscardChanges,
62
+ children: "Discard Changes"
63
+ }),
64
+ /*#__PURE__*/ (0, _jsxRuntime.jsx)(_material.Button, {
65
+ variant: "outlined",
66
+ onClick: dialog.onCancel,
67
+ children: "Cancel"
68
+ })
69
+ ]
70
+ })
71
+ ]
72
+ })
73
+ });
74
+ };
@@ -14,7 +14,7 @@
14
14
  Object.defineProperty(exports, "__esModule", {
15
15
  value: true
16
16
  });
17
- _exportStar(require("./UnsavedChangesConfirmationDialog"), exports);
17
+ _exportStar(require("./DiscardChangesConfirmationDialog"), exports);
18
18
  function _exportStar(from, to) {
19
19
  Object.keys(from).forEach(function(k) {
20
20
  if (k !== "default" && !Object.prototype.hasOwnProperty.call(to, k)) Object.defineProperty(to, k, {
@@ -27,6 +27,7 @@ const _pencilOutline = /*#__PURE__*/ _interopRequireDefault(require("mdi-materia
27
27
  const _arrowUp = /*#__PURE__*/ _interopRequireDefault(require("mdi-material-ui/ArrowUp"));
28
28
  const _arrowDown = /*#__PURE__*/ _interopRequireDefault(require("mdi-material-ui/ArrowDown"));
29
29
  const _deleteOutline = /*#__PURE__*/ _interopRequireDefault(require("mdi-material-ui/DeleteOutline"));
30
+ const _components = require("@perses-dev/components");
30
31
  const _context = require("../../context");
31
32
  function _interopRequireDefault(obj) {
32
33
  return obj && obj.__esModule ? obj : {
@@ -64,32 +65,47 @@ function GridTitle(props) {
64
65
  direction: "row",
65
66
  marginLeft: "auto",
66
67
  children: [
67
- /*#__PURE__*/ (0, _jsxRuntime.jsx)(_material.IconButton, {
68
- "aria-label": `add panel to group ${title}`,
69
- onClick: openAddPanel,
70
- children: /*#__PURE__*/ (0, _jsxRuntime.jsx)(_chartBoxPlusOutline.default, {})
68
+ /*#__PURE__*/ (0, _jsxRuntime.jsx)(_components.InfoTooltip, {
69
+ description: `Add a new panel to ${title}`,
70
+ children: /*#__PURE__*/ (0, _jsxRuntime.jsx)(_material.IconButton, {
71
+ "aria-label": `add panel to group ${title}`,
72
+ onClick: openAddPanel,
73
+ children: /*#__PURE__*/ (0, _jsxRuntime.jsx)(_chartBoxPlusOutline.default, {})
74
+ })
71
75
  }),
72
- /*#__PURE__*/ (0, _jsxRuntime.jsx)(_material.IconButton, {
73
- "aria-label": `edit group ${title}`,
74
- onClick: openEditPanelGroup,
75
- children: /*#__PURE__*/ (0, _jsxRuntime.jsx)(_pencilOutline.default, {})
76
+ /*#__PURE__*/ (0, _jsxRuntime.jsx)(_components.InfoTooltip, {
77
+ description: "Edit",
78
+ children: /*#__PURE__*/ (0, _jsxRuntime.jsx)(_material.IconButton, {
79
+ "aria-label": `edit group ${title}`,
80
+ onClick: openEditPanelGroup,
81
+ children: /*#__PURE__*/ (0, _jsxRuntime.jsx)(_pencilOutline.default, {})
82
+ })
76
83
  }),
77
- /*#__PURE__*/ (0, _jsxRuntime.jsx)(_material.IconButton, {
78
- "aria-label": `delete group ${title}`,
79
- onClick: ()=>openDeletePanelGroupDialog(panelGroupId),
80
- children: /*#__PURE__*/ (0, _jsxRuntime.jsx)(_deleteOutline.default, {})
84
+ /*#__PURE__*/ (0, _jsxRuntime.jsx)(_components.InfoTooltip, {
85
+ description: "Delete",
86
+ children: /*#__PURE__*/ (0, _jsxRuntime.jsx)(_material.IconButton, {
87
+ "aria-label": `delete group ${title}`,
88
+ onClick: ()=>openDeletePanelGroupDialog(panelGroupId),
89
+ children: /*#__PURE__*/ (0, _jsxRuntime.jsx)(_deleteOutline.default, {})
90
+ })
81
91
  }),
82
- /*#__PURE__*/ (0, _jsxRuntime.jsx)(_material.IconButton, {
83
- "aria-label": `move group ${title} down`,
84
- disabled: moveDown === undefined,
85
- onClick: moveDown,
86
- children: /*#__PURE__*/ (0, _jsxRuntime.jsx)(_arrowDown.default, {})
92
+ /*#__PURE__*/ (0, _jsxRuntime.jsx)(_components.InfoTooltip, {
93
+ description: "Move panel group down",
94
+ children: /*#__PURE__*/ (0, _jsxRuntime.jsx)(_material.IconButton, {
95
+ "aria-label": `move group ${title} down`,
96
+ disabled: moveDown === undefined,
97
+ onClick: moveDown,
98
+ children: /*#__PURE__*/ (0, _jsxRuntime.jsx)(_arrowDown.default, {})
99
+ })
87
100
  }),
88
- /*#__PURE__*/ (0, _jsxRuntime.jsx)(_material.IconButton, {
89
- "aria-label": `move group ${title} up`,
90
- disabled: moveUp === undefined,
91
- onClick: moveUp,
92
- children: /*#__PURE__*/ (0, _jsxRuntime.jsx)(_arrowUp.default, {})
101
+ /*#__PURE__*/ (0, _jsxRuntime.jsx)(_components.InfoTooltip, {
102
+ description: "Move panel group up",
103
+ children: /*#__PURE__*/ (0, _jsxRuntime.jsx)(_material.IconButton, {
104
+ "aria-label": `move group ${title} up`,
105
+ disabled: moveUp === undefined,
106
+ onClick: moveUp,
107
+ children: /*#__PURE__*/ (0, _jsxRuntime.jsx)(_arrowUp.default, {})
108
+ })
93
109
  })
94
110
  ]
95
111
  })
@@ -33,49 +33,62 @@ function _interopRequireDefault(obj) {
33
33
  function PanelHeader({ id , title , description , editHandlers , isHovered , sx , ...rest }) {
34
34
  const titleElementId = `${id}-title`;
35
35
  const descriptionTooltipId = `${id}-description`;
36
- let action = undefined;
36
+ let actions = undefined;
37
37
  if (editHandlers !== undefined) {
38
38
  // If there are edit handlers, always just show the edit buttons
39
- action = /*#__PURE__*/ (0, _jsxRuntime.jsxs)(_material.Stack, {
40
- direction: "row",
41
- spacing: 0.5,
42
- alignItems: "center",
39
+ actions = /*#__PURE__*/ (0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
43
40
  children: [
44
- /*#__PURE__*/ (0, _jsxRuntime.jsx)(HeaderIconButton, {
45
- "aria-label": `edit panel ${title}`,
46
- size: "small",
47
- onClick: editHandlers.onEditPanelClick,
48
- children: /*#__PURE__*/ (0, _jsxRuntime.jsx)(_pencilOutline.default, {})
41
+ /*#__PURE__*/ (0, _jsxRuntime.jsx)(_components.InfoTooltip, {
42
+ description: "Edit",
43
+ children: /*#__PURE__*/ (0, _jsxRuntime.jsx)(HeaderIconButton, {
44
+ "aria-label": `edit panel ${title}`,
45
+ size: "small",
46
+ onClick: editHandlers.onEditPanelClick,
47
+ children: /*#__PURE__*/ (0, _jsxRuntime.jsx)(_pencilOutline.default, {
48
+ fontSize: "inherit"
49
+ })
50
+ })
49
51
  }),
50
- /*#__PURE__*/ (0, _jsxRuntime.jsx)(HeaderIconButton, {
51
- "aria-label": `delete panel ${title}`,
52
- size: "small",
53
- onClick: editHandlers.onDeletePanelClick,
54
- children: /*#__PURE__*/ (0, _jsxRuntime.jsx)(_deleteOutline.default, {})
52
+ /*#__PURE__*/ (0, _jsxRuntime.jsx)(_components.InfoTooltip, {
53
+ description: "Delete",
54
+ children: /*#__PURE__*/ (0, _jsxRuntime.jsx)(HeaderIconButton, {
55
+ "aria-label": `delete panel ${title}`,
56
+ size: "small",
57
+ onClick: editHandlers.onDeletePanelClick,
58
+ children: /*#__PURE__*/ (0, _jsxRuntime.jsx)(_deleteOutline.default, {
59
+ fontSize: "inherit"
60
+ })
61
+ })
55
62
  }),
56
- /*#__PURE__*/ (0, _jsxRuntime.jsx)(HeaderIconButton, {
57
- "aria-label": `move panel ${title}`,
58
- size: "small",
59
- children: /*#__PURE__*/ (0, _jsxRuntime.jsx)(_dragVertical.default, {
60
- className: "drag-handle",
61
- sx: {
62
- cursor: 'grab'
63
- }
63
+ /*#__PURE__*/ (0, _jsxRuntime.jsx)(_components.InfoTooltip, {
64
+ description: "Drag and drop panel to reorganize",
65
+ children: /*#__PURE__*/ (0, _jsxRuntime.jsx)(HeaderIconButton, {
66
+ "aria-label": `move panel ${title}`,
67
+ size: "small",
68
+ children: /*#__PURE__*/ (0, _jsxRuntime.jsx)(_dragVertical.default, {
69
+ className: "drag-handle",
70
+ sx: {
71
+ cursor: 'grab'
72
+ },
73
+ fontSize: "inherit"
74
+ })
64
75
  })
65
76
  })
66
77
  ]
67
78
  });
68
79
  } else if (description !== undefined && isHovered) {
69
80
  // If there aren't edit handlers and we have a description, show a button with a tooltip for the panel description
70
- action = /*#__PURE__*/ (0, _jsxRuntime.jsx)(_components.InfoTooltip, {
81
+ actions = /*#__PURE__*/ (0, _jsxRuntime.jsx)(_components.InfoTooltip, {
71
82
  id: descriptionTooltipId,
72
83
  description: description,
73
- placement: _components.TooltipPlacement.Bottom,
84
+ enterDelay: 100,
74
85
  children: /*#__PURE__*/ (0, _jsxRuntime.jsx)(HeaderIconButton, {
75
86
  "aria-label": "Panel Description",
87
+ size: "small",
76
88
  children: /*#__PURE__*/ (0, _jsxRuntime.jsx)(_informationOutline.default, {
77
89
  "aria-describedby": "info-tooltip",
78
90
  "aria-hidden": false,
91
+ fontSize: "inherit",
79
92
  sx: {
80
93
  color: (theme)=>theme.palette.grey[700]
81
94
  }
@@ -103,12 +116,24 @@ function PanelHeader({ id , title , description , editHandlers , isHovered , sx
103
116
  },
104
117
  children: title
105
118
  }),
106
- action: action,
119
+ action: /*#__PURE__*/ (0, _jsxRuntime.jsx)(HeaderActionWrapper, {
120
+ direction: "row",
121
+ spacing: 0.25,
122
+ alignItems: "center",
123
+ children: actions
124
+ }),
107
125
  sx: (0, _components.combineSx)((theme)=>({
108
126
  padding: theme.spacing(1),
109
127
  borderBottom: `solid 1px ${theme.palette.divider}`,
110
128
  '.MuiCardHeader-content': {
111
129
  overflow: 'hidden'
130
+ },
131
+ '.MuiCardHeader-action': {
132
+ // Overriding the negative margins from MUI's defaults, so we
133
+ // can vertically center the icons. Moving these values to a wrapper
134
+ // inside the action in `HeaderActionWrapper` below.
135
+ // https://github.com/mui/material-ui/blob/master/packages/mui-material/src/CardHeader/CardHeader.js#L56-L58
136
+ margin: 'auto'
112
137
  }
113
138
  }), sx),
114
139
  ...rest
@@ -118,3 +143,11 @@ const HeaderIconButton = (0, _material.styled)(_material.IconButton)(({ theme }
118
143
  borderRadius: theme.shape.borderRadius,
119
144
  padding: '4px'
120
145
  }));
146
+ const HeaderActionWrapper = (0, _material.styled)(_material.Stack)(()=>({
147
+ // Adding back the negative margins from MUI's defaults for actions, so we
148
+ // avoid increasing the header size when actions are present while also being
149
+ // able to vertically center the actions.
150
+ // https://github.com/mui/material-ui/blob/master/packages/mui-material/src/CardHeader/CardHeader.js#L56-L58
151
+ marginTop: -4,
152
+ marginBottom: -4
153
+ }));
@@ -1,4 +1,4 @@
1
- // Copyright 2022 The Perses Authors
1
+ /* eslint-disable @typescript-eslint/no-empty-function */ // Copyright 2022 The Perses Authors
2
2
  // Licensed under the Apache License, Version 2.0 (the "License");
3
3
  // you may not use this file except in compliance with the License.
4
4
  // You may obtain a copy of the License at
@@ -26,9 +26,27 @@ const _context = require("../../context");
26
26
  const _panelEditorForm = require("./PanelEditorForm");
27
27
  const PanelDrawer = ()=>{
28
28
  const panelEditor = (0, _context.usePanelEditor)();
29
+ const { openDiscardChangesConfirmationDialog , closeDiscardChangesConfirmationDialog } = (0, _context.useDiscardChangesConfirmationDialog)();
30
+ const [values, setValues] = (0, _react.useState)(undefined);
29
31
  // When the user clicks close, start closing but don't call the store yet to keep values stable during animtation
30
32
  const [isClosing, setIsClosing] = (0, _react.useState)(false);
31
- const handleClose = ()=>setIsClosing(true);
33
+ const handleClose = ()=>{
34
+ const isModified = JSON.stringify(panelEditor === null || panelEditor === void 0 ? void 0 : panelEditor.initialValues) !== JSON.stringify(values);
35
+ if (isModified) {
36
+ openDiscardChangesConfirmationDialog({
37
+ onDiscardChanges: ()=>{
38
+ closeDiscardChangesConfirmationDialog();
39
+ setIsClosing(true);
40
+ },
41
+ onCancel: ()=>{
42
+ closeDiscardChangesConfirmationDialog();
43
+ },
44
+ description: 'You have unapplied changes in this panel. Are you sure you want to discard these changes? Changes cannot be recovered.'
45
+ });
46
+ } else {
47
+ setIsClosing(true);
48
+ }
49
+ };
32
50
  // Don't call closeDrawer on the store until the Drawer has completely transitioned out
33
51
  const handleExited = ()=>{
34
52
  panelEditor === null || panelEditor === void 0 ? void 0 : panelEditor.close();
@@ -36,14 +54,17 @@ const PanelDrawer = ()=>{
36
54
  };
37
55
  // Drawer is open if we have a model and we're not transitioning out
38
56
  const isOpen = panelEditor !== undefined && isClosing === false;
39
- const handleSubmit = (values)=>{
57
+ const handleSubmit = ()=>{
40
58
  // This shouldn't happen since we don't render the submit button until we have a model, but check to make TS happy
41
- if (panelEditor === undefined) {
59
+ if (panelEditor === undefined || values === undefined) {
42
60
  throw new Error('Cannot apply changes');
43
61
  }
44
62
  panelEditor.applyChanges(values);
45
- handleClose();
63
+ setIsClosing(true);
46
64
  };
65
+ const handleChange = (0, _react.useCallback)((values)=>{
66
+ setValues(values);
67
+ }, []);
47
68
  return /*#__PURE__*/ (0, _jsxRuntime.jsx)(_components.Drawer, {
48
69
  isOpen: isOpen,
49
70
  onClose: handleClose,
@@ -75,7 +96,7 @@ const PanelDrawer = ()=>{
75
96
  /*#__PURE__*/ (0, _jsxRuntime.jsx)(_material.Button, {
76
97
  type: "submit",
77
98
  variant: "contained",
78
- form: _panelEditorForm.panelEditorFormId,
99
+ onClick: handleSubmit,
79
100
  children: panelEditor.mode === 'Add' ? 'Add' : 'Apply'
80
101
  }),
81
102
  /*#__PURE__*/ (0, _jsxRuntime.jsx)(_material.Button, {
@@ -89,8 +110,8 @@ const PanelDrawer = ()=>{
89
110
  ]
90
111
  }),
91
112
  /*#__PURE__*/ (0, _jsxRuntime.jsx)(_panelEditorForm.PanelEditorForm, {
92
- onSubmit: handleSubmit,
93
- initialValues: panelEditor.initialValues
113
+ initialValues: panelEditor.initialValues,
114
+ onChange: handleChange
94
115
  })
95
116
  ]
96
117
  })
@@ -33,7 +33,7 @@ const _context = require("../../context");
33
33
  const _panelPreview = require("./PanelPreview");
34
34
  function PanelEditorForm(props) {
35
35
  var ref;
36
- const { initialValues , onSubmit } = props;
36
+ const { initialValues , onChange } = props;
37
37
  const panelGroups = (0, _context.useListPanelGroups)();
38
38
  const [name, setName] = (0, _react.useState)(initialValues.name);
39
39
  const [description, setDescription] = (0, _react.useState)(initialValues.description);
@@ -60,8 +60,7 @@ function PanelEditorForm(props) {
60
60
  }
61
61
  setGroupId(value);
62
62
  };
63
- const handleSubmit = (e)=>{
64
- e.preventDefault();
63
+ (0, _react.useEffect)(()=>{
65
64
  const values = {
66
65
  name,
67
66
  description,
@@ -69,14 +68,20 @@ function PanelEditorForm(props) {
69
68
  kind,
70
69
  spec
71
70
  };
72
- onSubmit(values);
73
- };
71
+ onChange(values);
72
+ }, [
73
+ name,
74
+ description,
75
+ groupId,
76
+ kind,
77
+ spec,
78
+ onChange
79
+ ]);
74
80
  var _title, ref1;
75
81
  return(// Grid maxHeight allows user to scroll inside Drawer to see all content
76
82
  /*#__PURE__*/ (0, _jsxRuntime.jsx)(_material.Box, {
77
83
  component: "form",
78
84
  id: panelEditorFormId,
79
- onSubmit: handleSubmit,
80
85
  sx: {
81
86
  flex: 1,
82
87
  overflowY: 'scroll',
@@ -92,9 +92,12 @@ const TIME_OPTIONS = [
92
92
  display: 'Last 14 days'
93
93
  }
94
94
  ];
95
- function TimeRangeControls() {
95
+ const DEFAULT_HEIGHT = '34px';
96
+ function TimeRangeControls({ heightPx }) {
96
97
  const { timeRange , setTimeRange , refresh } = (0, _pluginSystem.useTimeRange)();
97
98
  const defaultTimeRange = (0, _context.useDefaultTimeRange)();
99
+ // Convert height as a number to height as a string, then use this value for styling
100
+ const height = heightPx === undefined ? DEFAULT_HEIGHT : `${heightPx}px`;
98
101
  // add time shortcut if one does not match duration from dashboard JSON
99
102
  if (!TIME_OPTIONS.some((option)=>option.value.pastDuration === defaultTimeRange.pastDuration)) {
100
103
  if ((0, _core.isDurationString)(defaultTimeRange.pastDuration)) {
@@ -111,11 +114,15 @@ function TimeRangeControls() {
111
114
  /*#__PURE__*/ (0, _jsxRuntime.jsx)(_components.DateTimeRangePicker, {
112
115
  timeOptions: TIME_OPTIONS,
113
116
  value: timeRange,
114
- onChange: setTimeRange
117
+ onChange: setTimeRange,
118
+ height: height
115
119
  }),
116
120
  /*#__PURE__*/ (0, _jsxRuntime.jsx)(RefreshIconButton, {
117
121
  "aria-label": "Refresh Dashboard",
118
122
  onClick: refresh,
123
+ sx: {
124
+ height
125
+ },
119
126
  children: /*#__PURE__*/ (0, _jsxRuntime.jsx)(_refresh.default, {})
120
127
  })
121
128
  ]
@@ -172,9 +172,10 @@ function ListVariable({ name }) {
172
172
  });
173
173
  }
174
174
  function TextVariable({ name }) {
175
- const { state } = (0, _context.useTemplateVariable)(name);
176
175
  var ref;
177
- const [tempValue, setTempValue] = (0, _react.useState)((ref = state === null || state === void 0 ? void 0 : state.value) !== null && ref !== void 0 ? ref : '');
176
+ const { state , definition } = (0, _context.useTemplateVariable)(name);
177
+ var ref1;
178
+ const [tempValue, setTempValue] = (0, _react.useState)((ref1 = state === null || state === void 0 ? void 0 : state.value) !== null && ref1 !== void 0 ? ref1 : '');
178
179
  const { setVariableValue } = (0, _context.useTemplateVariableActions)();
179
180
  (0, _react.useEffect)(()=>{
180
181
  var ref;
@@ -182,11 +183,12 @@ function TextVariable({ name }) {
182
183
  }, [
183
184
  state === null || state === void 0 ? void 0 : state.value
184
185
  ]);
186
+ var ref2;
185
187
  return /*#__PURE__*/ (0, _jsxRuntime.jsx)(_material.TextField, {
186
188
  value: tempValue,
187
189
  onChange: (e)=>setTempValue(e.target.value),
188
190
  onBlur: ()=>setVariableValue(name, tempValue),
189
191
  placeholder: name,
190
- label: name
192
+ label: (ref2 = (ref = definition === null || definition === void 0 ? void 0 : definition.spec.display) === null || ref === void 0 ? void 0 : ref.name) !== null && ref2 !== void 0 ? ref2 : name
191
193
  });
192
194
  }