@perses-dev/dashboards 0.22.0 → 0.23.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.
- package/dist/cjs/components/DashboardToolbar/DashboardToolbar.js +3 -0
- package/dist/cjs/components/DeletePanelDialog/DeletePanelDialog.js +8 -30
- package/dist/cjs/components/DeletePanelGroupDialog/DeletePanelGroupDialog.js +1 -0
- package/dist/cjs/components/DiscardChangesConfirmationDialog/DiscardChangesConfirmationDialog.js +1 -0
- package/dist/cjs/components/GridLayout/GridItemContent.js +2 -1
- package/dist/cjs/components/GridLayout/GridLayout.js +4 -7
- package/dist/cjs/components/Panel/Panel.js +4 -5
- package/dist/cjs/components/Panel/Panel.test.js +10 -2
- package/dist/cjs/components/Panel/PanelContent.js +2 -1
- package/dist/cjs/components/Panel/PanelHeader.js +17 -0
- package/dist/cjs/components/PanelGroupDialog/PanelGroupDialog.js +1 -0
- package/dist/cjs/components/TimeRangeControls/TimeRangeControls.test.js +2 -2
- package/dist/cjs/components/Variables/EditVariablesButton.js +1 -0
- package/dist/cjs/components/Variables/VariableEditor.js +1 -1
- package/dist/cjs/components/Variables/VariableList.js +8 -2
- package/dist/cjs/{utils/functions.js → constants/grid-layout-config.js} +13 -5
- package/dist/cjs/constants/index.js +1 -0
- package/dist/cjs/constants/user-interface-text.js +2 -0
- package/dist/cjs/context/DashboardProvider/DashboardProvider.js +29 -9
- package/dist/cjs/context/DashboardProvider/dashboard-provider-api.js +6 -4
- package/dist/cjs/context/DashboardProvider/duplicate-panel-slice.js +62 -0
- package/dist/cjs/context/DashboardProvider/panel-editor-slice.js +8 -37
- package/dist/cjs/context/useDashboard.js +4 -2
- package/dist/cjs/utils/index.js +1 -1
- package/dist/cjs/utils/panelUtils.js +168 -0
- package/dist/cjs/utils/panelUtils.test.js +195 -0
- package/dist/cjs/views/ViewDashboard/DashboardApp.js +4 -1
- package/dist/cjs/views/ViewDashboard/ViewDashboard.js +4 -2
- package/dist/components/DashboardToolbar/DashboardToolbar.d.ts.map +1 -1
- package/dist/components/DashboardToolbar/DashboardToolbar.js +3 -0
- package/dist/components/DashboardToolbar/DashboardToolbar.js.map +1 -1
- package/dist/components/DeletePanelDialog/DeletePanelDialog.d.ts.map +1 -1
- package/dist/components/DeletePanelDialog/DeletePanelDialog.js +7 -24
- package/dist/components/DeletePanelDialog/DeletePanelDialog.js.map +1 -1
- package/dist/components/DeletePanelGroupDialog/DeletePanelGroupDialog.js +1 -0
- package/dist/components/DeletePanelGroupDialog/DeletePanelGroupDialog.js.map +1 -1
- package/dist/components/DiscardChangesConfirmationDialog/DiscardChangesConfirmationDialog.js +1 -0
- package/dist/components/DiscardChangesConfirmationDialog/DiscardChangesConfirmationDialog.js.map +1 -1
- package/dist/components/GridLayout/GridItemContent.d.ts.map +1 -1
- package/dist/components/GridLayout/GridItemContent.js +2 -1
- package/dist/components/GridLayout/GridItemContent.js.map +1 -1
- package/dist/components/GridLayout/GridLayout.d.ts.map +1 -1
- package/dist/components/GridLayout/GridLayout.js +4 -7
- package/dist/components/GridLayout/GridLayout.js.map +1 -1
- package/dist/components/Panel/Panel.d.ts.map +1 -1
- package/dist/components/Panel/Panel.js +5 -6
- package/dist/components/Panel/Panel.js.map +1 -1
- package/dist/components/Panel/Panel.test.js +10 -2
- package/dist/components/Panel/Panel.test.js.map +1 -1
- package/dist/components/Panel/PanelContent.d.ts.map +1 -1
- package/dist/components/Panel/PanelContent.js +2 -1
- package/dist/components/Panel/PanelContent.js.map +1 -1
- package/dist/components/Panel/PanelHeader.d.ts +1 -0
- package/dist/components/Panel/PanelHeader.d.ts.map +1 -1
- package/dist/components/Panel/PanelHeader.js +17 -0
- package/dist/components/Panel/PanelHeader.js.map +1 -1
- package/dist/components/PanelGroupDialog/PanelGroupDialog.js +1 -0
- package/dist/components/PanelGroupDialog/PanelGroupDialog.js.map +1 -1
- package/dist/components/TimeRangeControls/TimeRangeControls.test.js +2 -2
- package/dist/components/TimeRangeControls/TimeRangeControls.test.js.map +1 -1
- package/dist/components/Variables/EditVariablesButton.d.ts.map +1 -1
- package/dist/components/Variables/EditVariablesButton.js +1 -0
- package/dist/components/Variables/EditVariablesButton.js.map +1 -1
- package/dist/components/Variables/VariableEditor.js +1 -1
- package/dist/components/Variables/VariableEditor.js.map +1 -1
- package/dist/components/Variables/VariableList.d.ts.map +1 -1
- package/dist/components/Variables/VariableList.js +8 -2
- package/dist/components/Variables/VariableList.js.map +1 -1
- package/dist/constants/grid-layout-config.d.ts +6 -0
- package/dist/constants/grid-layout-config.d.ts.map +1 -0
- package/dist/{utils/functions.js → constants/grid-layout-config.js} +5 -3
- package/dist/constants/grid-layout-config.js.map +1 -0
- package/dist/constants/index.d.ts +1 -0
- package/dist/constants/index.d.ts.map +1 -1
- package/dist/constants/index.js +1 -0
- package/dist/constants/index.js.map +1 -1
- package/dist/constants/user-interface-text.d.ts +2 -0
- package/dist/constants/user-interface-text.d.ts.map +1 -1
- package/dist/constants/user-interface-text.js +2 -0
- package/dist/constants/user-interface-text.js.map +1 -1
- package/dist/context/DashboardProvider/DashboardProvider.d.ts +6 -4
- package/dist/context/DashboardProvider/DashboardProvider.d.ts.map +1 -1
- package/dist/context/DashboardProvider/DashboardProvider.js +29 -4
- package/dist/context/DashboardProvider/DashboardProvider.js.map +1 -1
- package/dist/context/DashboardProvider/dashboard-provider-api.d.ts +1 -0
- package/dist/context/DashboardProvider/dashboard-provider-api.d.ts.map +1 -1
- package/dist/context/DashboardProvider/dashboard-provider-api.js +6 -4
- package/dist/context/DashboardProvider/dashboard-provider-api.js.map +1 -1
- package/dist/context/DashboardProvider/duplicate-panel-slice.d.ts +19 -0
- package/dist/context/DashboardProvider/duplicate-panel-slice.d.ts.map +1 -0
- package/dist/context/DashboardProvider/duplicate-panel-slice.js +58 -0
- package/dist/context/DashboardProvider/duplicate-panel-slice.js.map +1 -0
- package/dist/context/DashboardProvider/index.d.ts +1 -1
- package/dist/context/DashboardProvider/index.d.ts.map +1 -1
- package/dist/context/DashboardProvider/index.js.map +1 -1
- package/dist/context/DashboardProvider/panel-editor-slice.d.ts +4 -0
- package/dist/context/DashboardProvider/panel-editor-slice.d.ts.map +1 -1
- package/dist/context/DashboardProvider/panel-editor-slice.js +6 -35
- package/dist/context/DashboardProvider/panel-editor-slice.js.map +1 -1
- package/dist/context/useDashboard.d.ts.map +1 -1
- package/dist/context/useDashboard.js +4 -2
- package/dist/context/useDashboard.js.map +1 -1
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1 -1
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/panelUtils.d.ts +27 -0
- package/dist/utils/panelUtils.d.ts.map +1 -0
- package/dist/utils/panelUtils.js +174 -0
- package/dist/utils/panelUtils.js.map +1 -0
- package/dist/utils/panelUtils.test.d.ts +2 -0
- package/dist/utils/panelUtils.test.d.ts.map +1 -0
- package/dist/utils/panelUtils.test.js +193 -0
- package/dist/utils/panelUtils.test.js.map +1 -0
- package/dist/views/ViewDashboard/DashboardApp.d.ts +1 -0
- package/dist/views/ViewDashboard/DashboardApp.d.ts.map +1 -1
- package/dist/views/ViewDashboard/DashboardApp.js +4 -1
- package/dist/views/ViewDashboard/DashboardApp.js.map +1 -1
- package/dist/views/ViewDashboard/ViewDashboard.d.ts +2 -0
- package/dist/views/ViewDashboard/ViewDashboard.d.ts.map +1 -1
- package/dist/views/ViewDashboard/ViewDashboard.js +4 -2
- package/dist/views/ViewDashboard/ViewDashboard.js.map +1 -1
- package/package.json +5 -5
- package/dist/utils/functions.d.ts +0 -2
- package/dist/utils/functions.d.ts.map +0 -1
- package/dist/utils/functions.js.map +0 -1
|
@@ -58,9 +58,11 @@ const DashboardToolbar = (props)=>{
|
|
|
58
58
|
setEditMode(false);
|
|
59
59
|
}
|
|
60
60
|
};
|
|
61
|
+
const testId = 'dashboard-toolbar';
|
|
61
62
|
return /*#__PURE__*/ (0, _jsxRuntime.jsx)(_jsxRuntime.Fragment, {
|
|
62
63
|
children: isEditMode ? /*#__PURE__*/ (0, _jsxRuntime.jsxs)(_material.Stack, {
|
|
63
64
|
spacing: 1,
|
|
65
|
+
"data-testid": testId,
|
|
64
66
|
children: [
|
|
65
67
|
/*#__PURE__*/ (0, _jsxRuntime.jsxs)(_material.Box, {
|
|
66
68
|
p: 2,
|
|
@@ -167,6 +169,7 @@ const DashboardToolbar = (props)=>{
|
|
|
167
169
|
}) : /*#__PURE__*/ (0, _jsxRuntime.jsxs)(_material.Stack, {
|
|
168
170
|
spacing: 1,
|
|
169
171
|
padding: 2,
|
|
172
|
+
"data-testid": testId,
|
|
170
173
|
children: [
|
|
171
174
|
/*#__PURE__*/ (0, _jsxRuntime.jsxs)(_material.Box, {
|
|
172
175
|
sx: {
|
|
@@ -19,32 +19,17 @@ Object.defineProperty(exports, "DeletePanelDialog", {
|
|
|
19
19
|
get: ()=>DeletePanelDialog
|
|
20
20
|
});
|
|
21
21
|
const _jsxRuntime = require("react/jsx-runtime");
|
|
22
|
-
const
|
|
23
|
-
const _close = /*#__PURE__*/ _interopRequireDefault(require("mdi-material-ui/Close"));
|
|
22
|
+
const _components = require("@perses-dev/components");
|
|
24
23
|
const _context = require("../../context");
|
|
25
|
-
function _interopRequireDefault(obj) {
|
|
26
|
-
return obj && obj.__esModule ? obj : {
|
|
27
|
-
default: obj
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
24
|
const DeletePanelDialog = ()=>{
|
|
31
25
|
const { deletePanelDialog , closeDeletePanelDialog } = (0, _context.useDeletePanelDialog)();
|
|
32
|
-
return /*#__PURE__*/ (0, _jsxRuntime.jsxs)(
|
|
26
|
+
return /*#__PURE__*/ (0, _jsxRuntime.jsxs)(_components.Dialog, {
|
|
33
27
|
open: deletePanelDialog !== undefined,
|
|
34
28
|
children: [
|
|
35
|
-
/*#__PURE__*/ (0, _jsxRuntime.jsx)(
|
|
29
|
+
/*#__PURE__*/ (0, _jsxRuntime.jsx)(_components.Dialog.Header, {
|
|
30
|
+
onClose: ()=>closeDeletePanelDialog(),
|
|
36
31
|
children: "Delete Panel"
|
|
37
32
|
}),
|
|
38
|
-
/*#__PURE__*/ (0, _jsxRuntime.jsx)(_material.IconButton, {
|
|
39
|
-
"aria-label": "Close",
|
|
40
|
-
onClick: ()=>closeDeletePanelDialog(),
|
|
41
|
-
sx: (theme)=>({
|
|
42
|
-
position: 'absolute',
|
|
43
|
-
top: theme.spacing(0.5),
|
|
44
|
-
right: theme.spacing(0.5)
|
|
45
|
-
}),
|
|
46
|
-
children: /*#__PURE__*/ (0, _jsxRuntime.jsx)(_close.default, {})
|
|
47
|
-
}),
|
|
48
33
|
deletePanelDialog && /*#__PURE__*/ (0, _jsxRuntime.jsx)(DeletePanelForm, {
|
|
49
34
|
deletePanelDialog: deletePanelDialog
|
|
50
35
|
})
|
|
@@ -62,11 +47,7 @@ const DeletePanelForm = ({ deletePanelDialog })=>{
|
|
|
62
47
|
return /*#__PURE__*/ (0, _jsxRuntime.jsxs)("form", {
|
|
63
48
|
onSubmit: handleDelete,
|
|
64
49
|
children: [
|
|
65
|
-
/*#__PURE__*/ (0, _jsxRuntime.jsxs)(
|
|
66
|
-
dividers: true,
|
|
67
|
-
sx: {
|
|
68
|
-
width: '500px'
|
|
69
|
-
},
|
|
50
|
+
/*#__PURE__*/ (0, _jsxRuntime.jsxs)(_components.Dialog.Content, {
|
|
70
51
|
children: [
|
|
71
52
|
"Are you sure you want to delete ",
|
|
72
53
|
deletePanelDialog.panelName,
|
|
@@ -75,15 +56,12 @@ const DeletePanelForm = ({ deletePanelDialog })=>{
|
|
|
75
56
|
"? This action cannot be undone."
|
|
76
57
|
]
|
|
77
58
|
}),
|
|
78
|
-
/*#__PURE__*/ (0, _jsxRuntime.jsxs)(
|
|
59
|
+
/*#__PURE__*/ (0, _jsxRuntime.jsxs)(_components.Dialog.Actions, {
|
|
79
60
|
children: [
|
|
80
|
-
/*#__PURE__*/ (0, _jsxRuntime.jsx)(
|
|
81
|
-
variant: "contained",
|
|
82
|
-
type: "submit",
|
|
61
|
+
/*#__PURE__*/ (0, _jsxRuntime.jsx)(_components.Dialog.PrimaryButton, {
|
|
83
62
|
children: "Delete"
|
|
84
63
|
}),
|
|
85
|
-
/*#__PURE__*/ (0, _jsxRuntime.jsx)(
|
|
86
|
-
variant: "outlined",
|
|
64
|
+
/*#__PURE__*/ (0, _jsxRuntime.jsx)(_components.Dialog.SecondaryButton, {
|
|
87
65
|
onClick: ()=>closeDeletePanelDialog(),
|
|
88
66
|
children: "Cancel"
|
|
89
67
|
})
|
|
@@ -25,12 +25,13 @@ function GridItemContent(props) {
|
|
|
25
25
|
const { panelGroupItemId } = props;
|
|
26
26
|
const panelDefinition = (0, _context.usePanel)(panelGroupItemId);
|
|
27
27
|
const { isEditMode } = (0, _context.useEditMode)();
|
|
28
|
-
const { openEditPanel , openDeletePanelDialog } = (0, _context.usePanelActions)(panelGroupItemId);
|
|
28
|
+
const { openEditPanel , openDeletePanelDialog , duplicatePanel } = (0, _context.usePanelActions)(panelGroupItemId);
|
|
29
29
|
// Provide actions to the panel when in edit mode
|
|
30
30
|
let editHandlers = undefined;
|
|
31
31
|
if (isEditMode) {
|
|
32
32
|
editHandlers = {
|
|
33
33
|
onEditPanelClick: openEditPanel,
|
|
34
|
+
onDuplicatePanelClick: duplicatePanel,
|
|
34
35
|
onDeletePanelClick: openDeletePanelDialog
|
|
35
36
|
};
|
|
36
37
|
}
|
|
@@ -24,11 +24,11 @@ const _reactGridLayout = require("react-grid-layout");
|
|
|
24
24
|
const _material = require("@mui/material");
|
|
25
25
|
const _components = require("@perses-dev/components");
|
|
26
26
|
const _context = require("../../context");
|
|
27
|
+
const _constants = require("../../constants");
|
|
27
28
|
const _gridTitle = require("./GridTitle");
|
|
28
29
|
const _gridItemContent = require("./GridItemContent");
|
|
29
30
|
const _gridContainer = require("./GridContainer");
|
|
30
31
|
const ResponsiveGridLayout = (0, _reactGridLayout.WidthProvider)(_reactGridLayout.Responsive);
|
|
31
|
-
const SMALL_LAYOUT_BREAKPOINT = 'sm';
|
|
32
32
|
function GridLayout(props) {
|
|
33
33
|
const { panelGroupId /*...others */ } = props;
|
|
34
34
|
const theme = (0, _material.useTheme)();
|
|
@@ -42,7 +42,7 @@ function GridLayout(props) {
|
|
|
42
42
|
// a bug in react-layout-grid where `currentLayout` does not adjust properly
|
|
43
43
|
// when going to a smaller breakpoint and then back to a larger breakpoint.
|
|
44
44
|
// https://github.com/react-grid-layout/react-grid-layout/issues/1663
|
|
45
|
-
const smallLayout = allLayouts[
|
|
45
|
+
const smallLayout = allLayouts[_constants.GRID_LAYOUT_SMALL_BREAKPOINT];
|
|
46
46
|
if (smallLayout) {
|
|
47
47
|
updatePanelGroupLayouts(smallLayout);
|
|
48
48
|
}
|
|
@@ -68,10 +68,7 @@ function GridLayout(props) {
|
|
|
68
68
|
sm: theme.breakpoints.values.sm,
|
|
69
69
|
xxs: 0
|
|
70
70
|
},
|
|
71
|
-
cols:
|
|
72
|
-
sm: 24,
|
|
73
|
-
xxs: 2
|
|
74
|
-
},
|
|
71
|
+
cols: _constants.GRID_LAYOUT_COLS,
|
|
75
72
|
rowHeight: 30,
|
|
76
73
|
draggableHandle: '.drag-handle',
|
|
77
74
|
resizeHandles: [
|
|
@@ -84,7 +81,7 @@ function GridLayout(props) {
|
|
|
84
81
|
10
|
|
85
82
|
],
|
|
86
83
|
layouts: {
|
|
87
|
-
[
|
|
84
|
+
[_constants.GRID_LAYOUT_SMALL_BREAKPOINT]: groupDefinition.itemLayouts
|
|
88
85
|
},
|
|
89
86
|
onLayoutChange: handleLayoutChange,
|
|
90
87
|
children: groupDefinition.itemLayouts.map(({ i })=>/*#__PURE__*/ (0, _jsxRuntime.jsx)("div", {
|
|
@@ -56,8 +56,7 @@ function Panel(props) {
|
|
|
56
56
|
initialInView: false,
|
|
57
57
|
triggerOnce: true
|
|
58
58
|
});
|
|
59
|
-
|
|
60
|
-
const panelPadding = 1.5;
|
|
59
|
+
const chartsTheme = (0, _components.useChartsTheme)();
|
|
61
60
|
const handleMouseEnter = (e)=>{
|
|
62
61
|
setIsHovered(true);
|
|
63
62
|
onMouseEnter === null || onMouseEnter === void 0 ? void 0 : onMouseEnter(e);
|
|
@@ -90,7 +89,7 @@ function Panel(props) {
|
|
|
90
89
|
editHandlers: editHandlers,
|
|
91
90
|
isHovered: isHovered,
|
|
92
91
|
sx: {
|
|
93
|
-
paddingX:
|
|
92
|
+
paddingX: `${chartsTheme.container.padding.default}px`
|
|
94
93
|
}
|
|
95
94
|
}),
|
|
96
95
|
/*#__PURE__*/ (0, _jsxRuntime.jsx)(_material.CardContent, {
|
|
@@ -100,10 +99,10 @@ function Panel(props) {
|
|
|
100
99
|
overflow: 'hidden',
|
|
101
100
|
flexGrow: 1,
|
|
102
101
|
margin: 0,
|
|
103
|
-
padding:
|
|
102
|
+
padding: 0,
|
|
104
103
|
// Override MUI default style for last-child
|
|
105
104
|
':last-child': {
|
|
106
|
-
padding:
|
|
105
|
+
padding: 0
|
|
107
106
|
}
|
|
108
107
|
},
|
|
109
108
|
ref: setContentElement,
|
|
@@ -97,7 +97,8 @@ describe('Panel', ()=>{
|
|
|
97
97
|
it('does not show description in edit mode', ()=>{
|
|
98
98
|
renderPanel(undefined, {
|
|
99
99
|
onEditPanelClick: jest.fn(),
|
|
100
|
-
onDeletePanelClick: jest.fn()
|
|
100
|
+
onDeletePanelClick: jest.fn(),
|
|
101
|
+
onDuplicatePanelClick: jest.fn()
|
|
101
102
|
});
|
|
102
103
|
const panel = getPanel();
|
|
103
104
|
_userEvent.default.hover(panel);
|
|
@@ -109,9 +110,11 @@ describe('Panel', ()=>{
|
|
|
109
110
|
it('can trigger panel actions in edit mode', ()=>{
|
|
110
111
|
const onEditPanelClick = jest.fn();
|
|
111
112
|
const onDeletePanelClick = jest.fn();
|
|
113
|
+
const onDuplicatePanelClick = jest.fn();
|
|
112
114
|
renderPanel(undefined, {
|
|
113
115
|
onEditPanelClick,
|
|
114
|
-
onDeletePanelClick
|
|
116
|
+
onDeletePanelClick,
|
|
117
|
+
onDuplicatePanelClick
|
|
115
118
|
});
|
|
116
119
|
const panel = getPanel();
|
|
117
120
|
_userEvent.default.hover(panel);
|
|
@@ -123,7 +126,12 @@ describe('Panel', ()=>{
|
|
|
123
126
|
name: /delete/i
|
|
124
127
|
});
|
|
125
128
|
_userEvent.default.click(deleteButton);
|
|
129
|
+
const duplicateButton = _react.screen.getByRole('button', {
|
|
130
|
+
name: /duplicate/i
|
|
131
|
+
});
|
|
132
|
+
_userEvent.default.click(duplicateButton);
|
|
126
133
|
expect(onEditPanelClick).toHaveBeenCalledTimes(1);
|
|
127
134
|
expect(onDeletePanelClick).toHaveBeenCalledTimes(1);
|
|
135
|
+
expect(onDuplicatePanelClick).toHaveBeenCalledTimes(1);
|
|
128
136
|
});
|
|
129
137
|
});
|
|
@@ -31,7 +31,8 @@ function PanelContent(props) {
|
|
|
31
31
|
return /*#__PURE__*/ (0, _jsxRuntime.jsx)(_material.Skeleton, {
|
|
32
32
|
variant: "rectangular",
|
|
33
33
|
width: contentDimensions === null || contentDimensions === void 0 ? void 0 : contentDimensions.width,
|
|
34
|
-
height: contentDimensions === null || contentDimensions === void 0 ? void 0 : contentDimensions.height
|
|
34
|
+
height: contentDimensions === null || contentDimensions === void 0 ? void 0 : contentDimensions.height,
|
|
35
|
+
"aria-label": "Loading..."
|
|
35
36
|
});
|
|
36
37
|
}
|
|
37
38
|
if (PanelComponent === undefined) {
|
|
@@ -25,6 +25,7 @@ const _informationOutline = /*#__PURE__*/ _interopRequireDefault(require("mdi-ma
|
|
|
25
25
|
const _pencilOutline = /*#__PURE__*/ _interopRequireDefault(require("mdi-material-ui/PencilOutline"));
|
|
26
26
|
const _deleteOutline = /*#__PURE__*/ _interopRequireDefault(require("mdi-material-ui/DeleteOutline"));
|
|
27
27
|
const _dragVertical = /*#__PURE__*/ _interopRequireDefault(require("mdi-material-ui/DragVertical"));
|
|
28
|
+
const _contentCopy = /*#__PURE__*/ _interopRequireDefault(require("mdi-material-ui/ContentCopy"));
|
|
28
29
|
const _constants = require("../../constants");
|
|
29
30
|
function _interopRequireDefault(obj) {
|
|
30
31
|
return obj && obj.__esModule ? obj : {
|
|
@@ -50,6 +51,22 @@ function PanelHeader({ id , title , description , editHandlers , isHovered , sx
|
|
|
50
51
|
})
|
|
51
52
|
})
|
|
52
53
|
}),
|
|
54
|
+
/*#__PURE__*/ (0, _jsxRuntime.jsx)(_components.InfoTooltip, {
|
|
55
|
+
description: _constants.TOOLTIP_TEXT.duplicatePanel,
|
|
56
|
+
children: /*#__PURE__*/ (0, _jsxRuntime.jsx)(HeaderIconButton, {
|
|
57
|
+
"aria-label": _constants.ARIA_LABEL_TEXT.duplicatePanel(title),
|
|
58
|
+
size: "small",
|
|
59
|
+
onClick: editHandlers.onDuplicatePanelClick,
|
|
60
|
+
children: /*#__PURE__*/ (0, _jsxRuntime.jsx)(_contentCopy.default, {
|
|
61
|
+
fontSize: "inherit",
|
|
62
|
+
sx: {
|
|
63
|
+
// Shrink this icon a little bit to look more consistent
|
|
64
|
+
// with the other icons in the header.
|
|
65
|
+
transform: 'scale(0.925)'
|
|
66
|
+
}
|
|
67
|
+
})
|
|
68
|
+
})
|
|
69
|
+
}),
|
|
53
70
|
/*#__PURE__*/ (0, _jsxRuntime.jsx)(_components.InfoTooltip, {
|
|
54
71
|
description: _constants.TOOLTIP_TEXT.deletePanel,
|
|
55
72
|
children: /*#__PURE__*/ (0, _jsxRuntime.jsx)(HeaderIconButton, {
|
|
@@ -61,7 +61,7 @@ describe('TimeRangeControls', ()=>{
|
|
|
61
61
|
renderTimeRangeControls(false);
|
|
62
62
|
expect(_react.screen.getByText('Last 30 minutes')).toBeInTheDocument();
|
|
63
63
|
const dateButton = _react.screen.getByRole('button', {
|
|
64
|
-
name: /
|
|
64
|
+
name: /time range/i
|
|
65
65
|
});
|
|
66
66
|
_userEvent.default.click(dateButton);
|
|
67
67
|
const firstSelected = _react.screen.getByRole('option', {
|
|
@@ -73,7 +73,7 @@ describe('TimeRangeControls', ()=>{
|
|
|
73
73
|
it('should update URL params with correct time range values', ()=>{
|
|
74
74
|
renderTimeRangeControls(true);
|
|
75
75
|
const dateButton = _react.screen.getByRole('button', {
|
|
76
|
-
name: /
|
|
76
|
+
name: /time range/i
|
|
77
77
|
});
|
|
78
78
|
_userEvent.default.click(dateButton);
|
|
79
79
|
const firstSelected = _react.screen.getByRole('option', {
|
|
@@ -195,7 +195,7 @@ function VariableEditor(props) {
|
|
|
195
195
|
sx: {
|
|
196
196
|
minWidth: 650
|
|
197
197
|
},
|
|
198
|
-
"aria-label": "
|
|
198
|
+
"aria-label": "table of variables",
|
|
199
199
|
children: [
|
|
200
200
|
/*#__PURE__*/ (0, _jsxRuntime.jsx)(_material.TableHead, {
|
|
201
201
|
children: /*#__PURE__*/ (0, _jsxRuntime.jsxs)(_material.TableRow, {
|
|
@@ -39,12 +39,17 @@ function TemplateVariableList(props) {
|
|
|
39
39
|
disableHysteresis: true
|
|
40
40
|
});
|
|
41
41
|
const isSticky = scrollTrigger && props.initialVariableIsSticky && isPin;
|
|
42
|
-
return
|
|
42
|
+
return(// marginBottom={-1} counteracts the marginBottom={1} on every variable input.
|
|
43
|
+
// The margin on the inputs is for spacing between inputs, but is not meant to add space to bottom of the container.
|
|
44
|
+
/*#__PURE__*/ (0, _jsxRuntime.jsx)(_material.Box, {
|
|
45
|
+
marginBottom: -1,
|
|
46
|
+
"data-testid": "variable-list",
|
|
43
47
|
children: /*#__PURE__*/ (0, _jsxRuntime.jsx)(_material.AppBar, {
|
|
44
48
|
color: "inherit",
|
|
45
49
|
position: isSticky ? 'fixed' : 'static',
|
|
46
50
|
elevation: isSticky ? 4 : 0,
|
|
47
51
|
sx: {
|
|
52
|
+
backgroundColor: 'inherit',
|
|
48
53
|
...props.sx
|
|
49
54
|
},
|
|
50
55
|
children: /*#__PURE__*/ (0, _jsxRuntime.jsxs)(_material.Box, {
|
|
@@ -62,6 +67,7 @@ function TemplateVariableList(props) {
|
|
|
62
67
|
maxWidth: VARIABLE_INPUT_MAX_WIDTH,
|
|
63
68
|
marginBottom: 1,
|
|
64
69
|
marginRight: 1,
|
|
70
|
+
"data-testid": "template-variable",
|
|
65
71
|
children: /*#__PURE__*/ (0, _jsxRuntime.jsx)(_variable.TemplateVariable, {
|
|
66
72
|
name: v.spec.name
|
|
67
73
|
}, v.spec.name)
|
|
@@ -74,5 +80,5 @@ function TemplateVariableList(props) {
|
|
|
74
80
|
]
|
|
75
81
|
})
|
|
76
82
|
})
|
|
77
|
-
});
|
|
83
|
+
}));
|
|
78
84
|
}
|
|
@@ -14,10 +14,18 @@
|
|
|
14
14
|
Object.defineProperty(exports, "__esModule", {
|
|
15
15
|
value: true
|
|
16
16
|
});
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
function _export(target, all) {
|
|
18
|
+
for(var name in all)Object.defineProperty(target, name, {
|
|
19
|
+
enumerable: true,
|
|
20
|
+
get: all[name]
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
_export(exports, {
|
|
24
|
+
GRID_LAYOUT_COLS: ()=>GRID_LAYOUT_COLS,
|
|
25
|
+
GRID_LAYOUT_SMALL_BREAKPOINT: ()=>GRID_LAYOUT_SMALL_BREAKPOINT
|
|
20
26
|
});
|
|
21
|
-
const
|
|
22
|
-
|
|
27
|
+
const GRID_LAYOUT_COLS = {
|
|
28
|
+
sm: 24,
|
|
29
|
+
xxs: 2
|
|
23
30
|
};
|
|
31
|
+
const GRID_LAYOUT_SMALL_BREAKPOINT = 'sm';
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
Object.defineProperty(exports, "__esModule", {
|
|
15
15
|
value: true
|
|
16
16
|
});
|
|
17
|
+
_exportStar(require("./grid-layout-config"), exports);
|
|
17
18
|
_exportStar(require("./user-interface-text"), exports);
|
|
18
19
|
function _exportStar(from, to) {
|
|
19
20
|
Object.keys(from).forEach(function(k) {
|
|
@@ -39,6 +39,7 @@ const TOOLTIP_TEXT = {
|
|
|
39
39
|
moveGroupUp: 'Move group up',
|
|
40
40
|
// Panel buttons
|
|
41
41
|
editPanel: 'Edit',
|
|
42
|
+
duplicatePanel: 'Duplicate',
|
|
42
43
|
deletePanel: 'Delete',
|
|
43
44
|
movePanel: 'Move',
|
|
44
45
|
// Variable editor buttons
|
|
@@ -54,6 +55,7 @@ const ARIA_LABEL_TEXT = {
|
|
|
54
55
|
moveGroupUp: (groupName)=>`move group ${groupName} up`,
|
|
55
56
|
// Panel buttons
|
|
56
57
|
editPanel: (panelName)=>`edit panel ${panelName}`,
|
|
58
|
+
duplicatePanel: (panelName)=>`duplicate panel ${panelName}`,
|
|
57
59
|
deletePanel: (panelName)=>`delete panel ${panelName}`,
|
|
58
60
|
movePanel: (panelName)=>`move panel ${panelName}`
|
|
59
61
|
};
|
|
@@ -29,8 +29,9 @@ const _jsxRuntime = require("react/jsx-runtime");
|
|
|
29
29
|
const _zustand = require("zustand");
|
|
30
30
|
const _middleware = require("zustand/middleware");
|
|
31
31
|
const _immer = require("zustand/middleware/immer");
|
|
32
|
-
const _shallow =
|
|
32
|
+
const _shallow = require("zustand/shallow");
|
|
33
33
|
const _react = require("react");
|
|
34
|
+
const _pluginSystem = require("@perses-dev/plugin-system");
|
|
34
35
|
const _panelGroupEditorSlice = require("./panel-group-editor-slice");
|
|
35
36
|
const _panelGroupSlice = require("./panel-group-slice");
|
|
36
37
|
const _panelEditorSlice = require("./panel-editor-slice");
|
|
@@ -38,24 +39,40 @@ const _panelSlice = require("./panel-slice");
|
|
|
38
39
|
const _deletePanelGroupSlice = require("./delete-panel-group-slice");
|
|
39
40
|
const _deletePanelSlice = require("./delete-panel-slice");
|
|
40
41
|
const _discardChangesDialogSlice = require("./discard-changes-dialog-slice");
|
|
41
|
-
|
|
42
|
-
return obj && obj.__esModule ? obj : {
|
|
43
|
-
default: obj
|
|
44
|
-
};
|
|
45
|
-
}
|
|
42
|
+
const _duplicatePanelSlice = require("./duplicate-panel-slice");
|
|
46
43
|
const DashboardContext = /*#__PURE__*/ (0, _react.createContext)(undefined);
|
|
47
44
|
function useDashboardStore(selector) {
|
|
48
45
|
const store = (0, _react.useContext)(DashboardContext);
|
|
49
46
|
if (store === undefined) {
|
|
50
47
|
throw new Error('No DashboardContext found. Did you forget a Provider?');
|
|
51
48
|
}
|
|
52
|
-
return (0, _zustand.useStore)(store, selector, _shallow.
|
|
49
|
+
return (0, _zustand.useStore)(store, selector, _shallow.shallow);
|
|
53
50
|
}
|
|
54
51
|
function DashboardProvider(props) {
|
|
55
52
|
const createDashboardStore = (0, _react.useCallback)(initStore, [
|
|
56
53
|
props
|
|
57
54
|
]);
|
|
55
|
+
// load plugin to retrieve initial spec if default panel kind is defined
|
|
56
|
+
const { defaultPluginKinds } = (0, _pluginSystem.usePluginRegistry)();
|
|
57
|
+
var ref;
|
|
58
|
+
const defaultPanelKind = (ref = defaultPluginKinds === null || defaultPluginKinds === void 0 ? void 0 : defaultPluginKinds['Panel']) !== null && ref !== void 0 ? ref : '';
|
|
59
|
+
const { data: plugin } = (0, _pluginSystem.usePlugin)('Panel', defaultPanelKind);
|
|
58
60
|
const [store] = (0, _react.useState)(createDashboardStore(props)); // prevent calling createDashboardStore every time it rerenders
|
|
61
|
+
(0, _react.useEffect)(()=>{
|
|
62
|
+
if (plugin === undefined) return;
|
|
63
|
+
const spec = plugin.createInitialOptions();
|
|
64
|
+
// set default panel kind and spec for add panel editor
|
|
65
|
+
store.setState({
|
|
66
|
+
initialValues: {
|
|
67
|
+
kind: defaultPanelKind,
|
|
68
|
+
spec
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
}, [
|
|
72
|
+
plugin,
|
|
73
|
+
store,
|
|
74
|
+
defaultPanelKind
|
|
75
|
+
]);
|
|
59
76
|
return /*#__PURE__*/ (0, _jsxRuntime.jsx)(DashboardContext.Provider, {
|
|
60
77
|
value: store,
|
|
61
78
|
children: props.children
|
|
@@ -63,7 +80,7 @@ function DashboardProvider(props) {
|
|
|
63
80
|
}
|
|
64
81
|
function initStore(props) {
|
|
65
82
|
const { initialState: { dashboardResource , isEditMode } , } = props;
|
|
66
|
-
const { spec: { layouts , panels , duration } , metadata , } = dashboardResource;
|
|
83
|
+
const { spec: { display , layouts , panels , duration } , metadata , } = dashboardResource;
|
|
67
84
|
const store = (0, _zustand.createStore)()((0, _immer.immer)((0, _middleware.devtools)((...args)=>{
|
|
68
85
|
const [set] = args;
|
|
69
86
|
return {
|
|
@@ -74,7 +91,9 @@ function initStore(props) {
|
|
|
74
91
|
...(0, _panelEditorSlice.createPanelEditorSlice)()(...args),
|
|
75
92
|
...(0, _deletePanelSlice.createDeletePanelSlice)()(...args),
|
|
76
93
|
...(0, _discardChangesDialogSlice.createDiscardChangesDialogSlice)(...args),
|
|
94
|
+
...(0, _duplicatePanelSlice.createDuplicatePanelSlice)()(...args),
|
|
77
95
|
metadata,
|
|
96
|
+
display,
|
|
78
97
|
defaultTimeRange: {
|
|
79
98
|
pastDuration: duration
|
|
80
99
|
},
|
|
@@ -82,9 +101,10 @@ function initStore(props) {
|
|
|
82
101
|
setEditMode: (isEditMode)=>set({
|
|
83
102
|
isEditMode
|
|
84
103
|
}),
|
|
85
|
-
setDashboard: ({ metadata , spec: { panels , layouts } })=>{
|
|
104
|
+
setDashboard: ({ metadata , spec: { display , panels , layouts } })=>{
|
|
86
105
|
set((state)=>{
|
|
87
106
|
state.metadata = metadata;
|
|
107
|
+
state.display = display;
|
|
88
108
|
const { panelGroups , panelGroupOrder } = (0, _panelGroupSlice.convertLayoutsToPanelGroups)(layouts);
|
|
89
109
|
state.panels = panels;
|
|
90
110
|
state.panelGroups = panelGroups;
|
|
@@ -162,15 +162,17 @@ function usePanel(panelGroupItemId) {
|
|
|
162
162
|
}
|
|
163
163
|
return panel;
|
|
164
164
|
}
|
|
165
|
-
const selectPanelActions = ({ openEditPanel , openDeletePanelDialog })=>({
|
|
165
|
+
const selectPanelActions = ({ openEditPanel , openDeletePanelDialog , duplicatePanel })=>({
|
|
166
166
|
openEditPanel,
|
|
167
|
-
openDeletePanelDialog
|
|
167
|
+
openDeletePanelDialog,
|
|
168
|
+
duplicatePanel
|
|
168
169
|
});
|
|
169
170
|
function usePanelActions(panelGroupItemId) {
|
|
170
|
-
const { openEditPanel , openDeletePanelDialog } = (0, _dashboardProvider.useDashboardStore)(selectPanelActions);
|
|
171
|
+
const { openEditPanel , openDeletePanelDialog , duplicatePanel } = (0, _dashboardProvider.useDashboardStore)(selectPanelActions);
|
|
171
172
|
return {
|
|
172
173
|
openEditPanel: ()=>openEditPanel(panelGroupItemId),
|
|
173
|
-
openDeletePanelDialog: ()=>openDeletePanelDialog(panelGroupItemId)
|
|
174
|
+
openDeletePanelDialog: ()=>openDeletePanelDialog(panelGroupItemId),
|
|
175
|
+
duplicatePanel: ()=>duplicatePanel(panelGroupItemId)
|
|
174
176
|
};
|
|
175
177
|
}
|
|
176
178
|
const selectPanelEditor = (state)=>state.panelEditor;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// Copyright 2023 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, "createDuplicatePanelSlice", {
|
|
18
|
+
enumerable: true,
|
|
19
|
+
get: ()=>createDuplicatePanelSlice
|
|
20
|
+
});
|
|
21
|
+
const _panelUtils = require("../../utils/panelUtils");
|
|
22
|
+
const _common = require("./common");
|
|
23
|
+
function createDuplicatePanelSlice() {
|
|
24
|
+
return (set)=>({
|
|
25
|
+
duplicatePanel (panelGroupItemId) {
|
|
26
|
+
set((state)=>{
|
|
27
|
+
const panels = state.panels;
|
|
28
|
+
// Figure out the panel key at that location
|
|
29
|
+
const { panelGroupId , panelGroupItemLayoutId: panelGroupLayoutId } = panelGroupItemId;
|
|
30
|
+
const group = state.panelGroups[panelGroupId];
|
|
31
|
+
if (group === undefined) {
|
|
32
|
+
throw new Error(`Missing panel group ${panelGroupId}`);
|
|
33
|
+
}
|
|
34
|
+
const panelKey = group.itemPanelKeys[panelGroupLayoutId];
|
|
35
|
+
if (panelKey === undefined) {
|
|
36
|
+
throw new Error(`Could not find Panel Group item ${panelGroupItemId}`);
|
|
37
|
+
}
|
|
38
|
+
// Find the panel to edit
|
|
39
|
+
const panelToDupe = panels[panelKey];
|
|
40
|
+
if (panelToDupe === undefined) {
|
|
41
|
+
throw new Error(`Cannot find Panel with key '${panelKey}'`);
|
|
42
|
+
}
|
|
43
|
+
// Find the layout for the item being duped
|
|
44
|
+
const matchingLayout = group.itemLayouts.find((itemLayout)=>{
|
|
45
|
+
return itemLayout.i === panelGroupLayoutId;
|
|
46
|
+
});
|
|
47
|
+
if (matchingLayout === undefined) {
|
|
48
|
+
throw new Error(`Cannot find layout for Panel with key '${panelKey}'`);
|
|
49
|
+
}
|
|
50
|
+
const dupePanelKey = (0, _panelUtils.getValidPanelKey)(panelKey, panels);
|
|
51
|
+
state.panels[dupePanelKey] = panelToDupe;
|
|
52
|
+
const duplicateLayout = {
|
|
53
|
+
i: (0, _common.generateId)().toString(),
|
|
54
|
+
w: matchingLayout.w,
|
|
55
|
+
h: matchingLayout.h
|
|
56
|
+
};
|
|
57
|
+
group.itemLayouts = (0, _panelUtils.insertPanelInLayout)(duplicateLayout, matchingLayout, group.itemLayouts);
|
|
58
|
+
group.itemPanelKeys[duplicateLayout.i] = dupePanelKey;
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
}
|