@perses-dev/dashboards 0.7.1 → 0.8.0
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/Dashboard.js +1 -1
- package/dist/cjs/components/DashboardToolbar.js +3 -18
- package/dist/cjs/components/GridLayout/GridItemContent.js +3 -3
- package/dist/cjs/components/GridLayout/GridLayout.js +6 -9
- package/dist/cjs/components/GridLayout/GridTitle.js +15 -9
- package/dist/cjs/components/Panel/Panel.js +11 -6
- package/dist/cjs/components/Panel/Panel.test.js +17 -13
- package/dist/cjs/components/Panel/PanelContent.js +15 -0
- package/dist/cjs/components/Panel/index.js +29 -0
- package/dist/cjs/components/PanelDrawer/PanelDrawer.js +124 -0
- package/dist/cjs/components/PanelDrawer/PanelDrawer.test.js +111 -0
- package/dist/cjs/components/PanelDrawer/PanelOptionsEditor.js +19 -0
- package/dist/cjs/components/PanelGroupDialog/PanelGroupDialog.js +60 -0
- package/dist/cjs/components/PanelGroupDialog/PanelGroupDialog.test.js +95 -0
- package/dist/cjs/components/{TimeRangeControls.js → TimeRangeControls/TimeRangeControls.js} +20 -31
- package/dist/cjs/components/TimeRangeControls/TimeRangeControls.test.js +51 -0
- package/dist/cjs/components/TimeRangeControls/index.js +29 -0
- package/dist/cjs/components/Variables/Variable.js +57 -0
- package/dist/cjs/components/Variables/VariableList.js +27 -0
- package/dist/cjs/components/{VariableList → Variables}/index.js +1 -0
- package/dist/cjs/components/index.js +2 -3
- package/dist/cjs/context/DashboardAppSlice.js +45 -0
- package/dist/cjs/context/DashboardProvider.js +54 -36
- package/dist/cjs/context/LayoutsSlice.js +42 -0
- package/dist/cjs/context/QueryStringProvider.js +35 -0
- package/dist/cjs/context/TemplateVariableProvider.js +216 -0
- package/dist/cjs/context/TimeRangeProvider.js +66 -0
- package/dist/cjs/context/index.js +6 -3
- package/dist/cjs/css/styles.js +173 -169
- package/dist/cjs/test/plugin-registry.js +24 -17
- package/dist/cjs/test/render.js +11 -2
- package/dist/cjs/test/testDashboard.js +14 -37
- package/dist/cjs/views/DashboardApp.js +4 -4
- package/dist/cjs/views/ViewDashboard.js +30 -2
- package/dist/cjs/views/index.js +1 -1
- package/dist/components/Dashboard.d.ts.map +1 -1
- package/dist/components/Dashboard.js +1 -1
- package/dist/components/DashboardToolbar.d.ts +0 -1
- package/dist/components/DashboardToolbar.d.ts.map +1 -1
- package/dist/components/DashboardToolbar.js +1 -1
- package/dist/components/GridLayout/GridItemContent.d.ts +1 -0
- package/dist/components/GridLayout/GridItemContent.d.ts.map +1 -1
- package/dist/components/GridLayout/GridItemContent.js +1 -1
- package/dist/components/GridLayout/GridLayout.d.ts +2 -1
- package/dist/components/GridLayout/GridLayout.d.ts.map +1 -1
- package/dist/components/GridLayout/GridLayout.js +1 -1
- package/dist/components/GridLayout/GridTitle.d.ts +1 -0
- package/dist/components/GridLayout/GridTitle.d.ts.map +1 -1
- package/dist/components/GridLayout/GridTitle.js +1 -1
- package/dist/components/Panel/Panel.d.ts +2 -0
- package/dist/components/Panel/Panel.d.ts.map +1 -1
- package/dist/components/Panel/Panel.js +1 -1
- package/dist/components/Panel/Panel.test.d.ts.map +1 -1
- package/dist/components/Panel/Panel.test.js +1 -1
- package/dist/components/Panel/PanelContent.d.ts +11 -0
- package/dist/components/Panel/PanelContent.d.ts.map +1 -0
- package/dist/components/Panel/PanelContent.js +1 -0
- package/dist/components/Panel/index.d.ts +2 -0
- package/dist/components/Panel/index.d.ts.map +1 -0
- package/dist/components/Panel/index.js +1 -0
- package/dist/components/PanelDrawer/PanelDrawer.d.ts +4 -0
- package/dist/components/PanelDrawer/PanelDrawer.d.ts.map +1 -0
- package/dist/components/PanelDrawer/PanelDrawer.js +1 -0
- package/dist/components/PanelDrawer/PanelDrawer.test.d.ts +2 -0
- package/dist/components/PanelDrawer/PanelDrawer.test.d.ts.map +1 -0
- package/dist/components/PanelDrawer/PanelDrawer.test.js +1 -0
- package/dist/components/PanelDrawer/PanelOptionsEditor.d.ts +9 -0
- package/dist/components/PanelDrawer/PanelOptionsEditor.d.ts.map +1 -0
- package/dist/components/PanelDrawer/PanelOptionsEditor.js +1 -0
- package/dist/components/PanelGroupDialog/PanelGroupDialog.d.ts +4 -0
- package/dist/components/PanelGroupDialog/PanelGroupDialog.d.ts.map +1 -0
- package/dist/components/PanelGroupDialog/PanelGroupDialog.js +1 -0
- package/dist/components/PanelGroupDialog/PanelGroupDialog.test.d.ts +2 -0
- package/dist/components/PanelGroupDialog/PanelGroupDialog.test.d.ts.map +1 -0
- package/dist/components/PanelGroupDialog/PanelGroupDialog.test.js +1 -0
- package/dist/components/{TimeRangeControls.d.ts → TimeRangeControls/TimeRangeControls.d.ts} +0 -0
- package/dist/components/TimeRangeControls/TimeRangeControls.d.ts.map +1 -0
- package/dist/components/TimeRangeControls/TimeRangeControls.js +1 -0
- package/dist/components/TimeRangeControls/TimeRangeControls.test.d.ts +2 -0
- package/dist/components/TimeRangeControls/TimeRangeControls.test.d.ts.map +1 -0
- package/dist/components/TimeRangeControls/TimeRangeControls.test.js +1 -0
- package/dist/components/TimeRangeControls/index.d.ts +2 -0
- package/dist/components/TimeRangeControls/index.d.ts.map +1 -0
- package/dist/components/TimeRangeControls/index.js +1 -0
- package/dist/components/Variables/Variable.d.ts +8 -0
- package/dist/components/Variables/Variable.d.ts.map +1 -0
- package/dist/components/Variables/Variable.js +1 -0
- package/dist/components/Variables/VariableList.d.ts +3 -0
- package/dist/components/Variables/VariableList.d.ts.map +1 -0
- package/dist/components/Variables/VariableList.js +1 -0
- package/dist/components/Variables/index.d.ts +3 -0
- package/dist/components/Variables/index.d.ts.map +1 -0
- package/dist/components/Variables/index.js +1 -0
- package/dist/components/index.d.ts +2 -3
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +1 -1
- package/dist/context/DashboardAppSlice.d.ts +26 -0
- package/dist/context/DashboardAppSlice.d.ts.map +1 -0
- package/dist/context/DashboardAppSlice.js +1 -0
- package/dist/context/DashboardProvider.d.ts +8 -19
- package/dist/context/DashboardProvider.d.ts.map +1 -1
- package/dist/context/DashboardProvider.js +1 -1
- package/dist/context/LayoutsSlice.d.ts +12 -0
- package/dist/context/LayoutsSlice.d.ts.map +1 -0
- package/dist/context/LayoutsSlice.js +1 -0
- package/dist/context/QueryStringProvider.d.ts +13 -0
- package/dist/context/QueryStringProvider.d.ts.map +1 -0
- package/dist/context/QueryStringProvider.js +1 -0
- package/dist/context/TemplateVariableProvider.d.ts +25 -0
- package/dist/context/TemplateVariableProvider.d.ts.map +1 -0
- package/dist/context/TemplateVariableProvider.js +1 -0
- package/dist/context/TimeRangeProvider.d.ts +12 -0
- package/dist/context/TimeRangeProvider.d.ts.map +1 -0
- package/dist/context/TimeRangeProvider.js +1 -0
- package/dist/context/index.d.ts +5 -2
- package/dist/context/index.d.ts.map +1 -1
- package/dist/context/index.js +1 -1
- package/dist/css/styles.d.ts +7 -7
- package/dist/css/styles.d.ts.map +1 -1
- package/dist/css/styles.js +1 -1
- package/dist/test/plugin-registry.d.ts +4 -2
- package/dist/test/plugin-registry.d.ts.map +1 -1
- package/dist/test/plugin-registry.js +1 -1
- package/dist/test/render.d.ts +2 -1
- package/dist/test/render.d.ts.map +1 -1
- package/dist/test/render.js +1 -1
- package/dist/test/testDashboard.d.ts.map +1 -1
- package/dist/test/testDashboard.js +1 -1
- package/dist/views/DashboardApp.js +1 -1
- package/dist/views/ViewDashboard.d.ts.map +1 -1
- package/dist/views/ViewDashboard.js +1 -1
- package/package.json +9 -11
- package/dist/cjs/components/AddPanel/AddPanel.js +0 -75
- package/dist/cjs/components/VariableAutocomplete.js +0 -63
- package/dist/cjs/components/VariableList/VariableList.js +0 -42
- package/dist/cjs/components/VariableList/VariableList.test.js +0 -86
- package/dist/cjs/context/TemplateVariablesProvider.js +0 -142
- package/dist/cjs/context/TimeRangeStateProvider.js +0 -49
- package/dist/components/AddPanel/AddPanel.d.ts +0 -8
- package/dist/components/AddPanel/AddPanel.d.ts.map +0 -1
- package/dist/components/AddPanel/AddPanel.js +0 -1
- package/dist/components/TimeRangeControls.d.ts.map +0 -1
- package/dist/components/TimeRangeControls.js +0 -1
- package/dist/components/VariableAutocomplete.d.ts +0 -21
- package/dist/components/VariableAutocomplete.d.ts.map +0 -1
- package/dist/components/VariableAutocomplete.js +0 -1
- package/dist/components/VariableList/VariableList.d.ts +0 -11
- package/dist/components/VariableList/VariableList.d.ts.map +0 -1
- package/dist/components/VariableList/VariableList.js +0 -1
- package/dist/components/VariableList/VariableList.test.d.ts +0 -2
- package/dist/components/VariableList/VariableList.test.d.ts.map +0 -1
- package/dist/components/VariableList/VariableList.test.js +0 -1
- package/dist/components/VariableList/index.d.ts +0 -2
- package/dist/components/VariableList/index.d.ts.map +0 -1
- package/dist/components/VariableList/index.js +0 -1
- package/dist/context/TemplateVariablesProvider.d.ts +0 -23
- package/dist/context/TemplateVariablesProvider.d.ts.map +0 -1
- package/dist/context/TemplateVariablesProvider.js +0 -1
- package/dist/context/TimeRangeStateProvider.d.ts +0 -22
- package/dist/context/TimeRangeStateProvider.d.ts.map +0 -1
- package/dist/context/TimeRangeStateProvider.js +0 -1
|
@@ -22,6 +22,6 @@ const GridLayout_1 = require("./GridLayout");
|
|
|
22
22
|
*/
|
|
23
23
|
function Dashboard(props) {
|
|
24
24
|
const { spec, ...others } = props;
|
|
25
|
-
return ((0, jsx_runtime_1.jsx)(material_1.Box, { ...others, children: (0, jsx_runtime_1.jsx)(components_1.ErrorBoundary, { FallbackComponent: components_1.ErrorAlert, children: spec.layouts.map((layout, idx) => ((0, jsx_runtime_1.jsx)(GridLayout_1.GridLayout, { definition: layout, renderGridItemContent: (definition) => (0, jsx_runtime_1.jsx)(GridLayout_1.GridItemContent, { content: definition.content, spec: spec }) }, idx))) }) }));
|
|
25
|
+
return ((0, jsx_runtime_1.jsx)(material_1.Box, { ...others, children: (0, jsx_runtime_1.jsx)(components_1.ErrorBoundary, { FallbackComponent: components_1.ErrorAlert, children: spec.layouts.map((layout, idx) => ((0, jsx_runtime_1.jsx)(GridLayout_1.GridLayout, { groupIndex: idx, definition: layout, renderGridItemContent: (definition, groupIndex) => ((0, jsx_runtime_1.jsx)(GridLayout_1.GridItemContent, { content: definition.content, spec: spec, groupIndex: groupIndex })) }, `${JSON.stringify(spec.layouts)} ${idx}`))) }) }));
|
|
26
26
|
}
|
|
27
27
|
exports.Dashboard = Dashboard;
|
|
@@ -23,30 +23,15 @@ const Plus_1 = __importDefault(require("mdi-material-ui/Plus"));
|
|
|
23
23
|
const context_1 = require("../context");
|
|
24
24
|
const components_1 = require("../components");
|
|
25
25
|
const DashboardToolbar = (props) => {
|
|
26
|
-
const { dashboardName
|
|
26
|
+
const { dashboardName } = props;
|
|
27
27
|
const { isEditMode, setEditMode } = (0, context_1.useEditMode)();
|
|
28
|
+
const { openPanelDrawer, openPanelGroupDialog } = (0, context_1.useDashboardApp)();
|
|
28
29
|
const onEditButtonClick = () => {
|
|
29
30
|
setEditMode(true);
|
|
30
31
|
};
|
|
31
32
|
const onCancelButtonClick = () => {
|
|
32
33
|
setEditMode(false);
|
|
33
34
|
};
|
|
34
|
-
|
|
35
|
-
const onAddGroup = () => {
|
|
36
|
-
const newLayout = {
|
|
37
|
-
kind: 'Grid',
|
|
38
|
-
spec: {
|
|
39
|
-
display: {
|
|
40
|
-
title: 'New Group',
|
|
41
|
-
collapse: {
|
|
42
|
-
open: true,
|
|
43
|
-
},
|
|
44
|
-
},
|
|
45
|
-
items: [],
|
|
46
|
-
},
|
|
47
|
-
};
|
|
48
|
-
addLayout(newLayout);
|
|
49
|
-
};
|
|
50
|
-
return ((0, jsx_runtime_1.jsx)(material_1.Toolbar, { disableGutters: true, sx: { display: 'block', padding: (theme) => theme.spacing(2, 0) }, children: isEditMode ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)(material_1.Box, { sx: { display: 'flex', width: '100%' }, children: [(0, jsx_runtime_1.jsxs)(material_1.Typography, { variant: "h2", children: ["Edit ", dashboardName] }), (0, jsx_runtime_1.jsxs)(material_1.Stack, { direction: "row", spacing: 1, sx: { marginLeft: 'auto' }, children: [(0, jsx_runtime_1.jsx)(components_1.TimeRangeControls, {}), (0, jsx_runtime_1.jsx)(material_1.Button, { variant: "outlined", onClick: onCancelButtonClick, children: "Cancel" }), (0, jsx_runtime_1.jsx)(material_1.Button, { variant: "contained", children: "Save" })] })] }), (0, jsx_runtime_1.jsxs)(material_1.Stack, { direction: 'row', spacing: 1, sx: { display: 'flex', justifyContent: 'flex-end', width: '100%', padding: (theme) => theme.spacing(2, 0) }, children: [(0, jsx_runtime_1.jsx)(material_1.Button, { startIcon: (0, jsx_runtime_1.jsx)(Plus_1.default, {}), onClick: onAddGroup, children: "Add Group" }), (0, jsx_runtime_1.jsx)(material_1.Button, { startIcon: (0, jsx_runtime_1.jsx)(Plus_1.default, {}), onClick: onAddPanel, children: "Add Panel" })] })] })) : ((0, jsx_runtime_1.jsxs)(material_1.Box, { sx: { display: 'flex', width: '100%' }, children: [(0, jsx_runtime_1.jsx)(material_1.Typography, { variant: "h2", children: dashboardName }), (0, jsx_runtime_1.jsxs)(material_1.Stack, { direction: "row", spacing: 2, sx: { marginLeft: 'auto' }, children: [(0, jsx_runtime_1.jsx)(components_1.TimeRangeControls, {}), (0, jsx_runtime_1.jsx)(material_1.Button, { variant: "contained", startIcon: (0, jsx_runtime_1.jsx)(PencilOutline_1.default, {}), onClick: onEditButtonClick, sx: { marginLeft: 'auto' }, children: "Edit" })] })] })) }));
|
|
35
|
+
return ((0, jsx_runtime_1.jsx)(material_1.Toolbar, { disableGutters: true, sx: { display: 'block', padding: (theme) => theme.spacing(2, 0) }, children: isEditMode ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)(material_1.Box, { sx: { display: 'flex', width: '100%' }, children: [(0, jsx_runtime_1.jsxs)(material_1.Typography, { variant: "h2", children: ["Edit ", dashboardName] }), (0, jsx_runtime_1.jsxs)(material_1.Stack, { direction: "row", spacing: 1, sx: { marginLeft: 'auto' }, children: [(0, jsx_runtime_1.jsx)(components_1.TimeRangeControls, {}), (0, jsx_runtime_1.jsx)(material_1.Button, { variant: "outlined", onClick: onCancelButtonClick, children: "Cancel" }), (0, jsx_runtime_1.jsx)(material_1.Button, { variant: "contained", children: "Save" })] })] }), (0, jsx_runtime_1.jsxs)(material_1.Stack, { direction: 'row', spacing: 1, sx: { display: 'flex', justifyContent: 'flex-end', width: '100%', padding: (theme) => theme.spacing(2, 0) }, children: [(0, jsx_runtime_1.jsx)(material_1.Button, { startIcon: (0, jsx_runtime_1.jsx)(Plus_1.default, {}), onClick: () => openPanelGroupDialog(), children: "Add Group" }), (0, jsx_runtime_1.jsx)(material_1.Button, { startIcon: (0, jsx_runtime_1.jsx)(Plus_1.default, {}), onClick: () => openPanelDrawer({ groupIndex: 0 }), children: "Add Panel" })] })] })) : ((0, jsx_runtime_1.jsxs)(material_1.Box, { sx: { display: 'flex', width: '100%' }, children: [(0, jsx_runtime_1.jsx)(material_1.Typography, { variant: "h2", children: dashboardName }), (0, jsx_runtime_1.jsxs)(material_1.Stack, { direction: "row", spacing: 2, sx: { marginLeft: 'auto' }, children: [(0, jsx_runtime_1.jsx)(components_1.TimeRangeControls, {}), (0, jsx_runtime_1.jsx)(material_1.Button, { variant: "contained", startIcon: (0, jsx_runtime_1.jsx)(PencilOutline_1.default, {}), onClick: onEditButtonClick, sx: { marginLeft: 'auto' }, children: "Edit" })] })] })) }));
|
|
51
36
|
};
|
|
52
37
|
exports.DashboardToolbar = DashboardToolbar;
|
|
@@ -21,10 +21,10 @@ const Panel_1 = require("../Panel/Panel");
|
|
|
21
21
|
* Resolves the reference to panel content in a GridItemDefinition and renders the panel.
|
|
22
22
|
*/
|
|
23
23
|
function GridItemContent(props) {
|
|
24
|
-
const { content, spec } = props;
|
|
24
|
+
const { content, spec, groupIndex } = props;
|
|
25
25
|
try {
|
|
26
|
-
const
|
|
27
|
-
return (0, jsx_runtime_1.jsx)(Panel_1.Panel, { definition:
|
|
26
|
+
const { panelDefinition, panelsKey } = (0, core_1.resolvePanelRef)(spec, content);
|
|
27
|
+
return (0, jsx_runtime_1.jsx)(Panel_1.Panel, { definition: panelDefinition, groupIndex: groupIndex, panelKey: panelsKey });
|
|
28
28
|
}
|
|
29
29
|
catch (err) {
|
|
30
30
|
return (0, jsx_runtime_1.jsx)(components_1.ErrorAlert, { error: err });
|
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.GridLayout = void 0;
|
|
7
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
@@ -20,7 +17,7 @@ const jsx_runtime_1 = require("react/jsx-runtime");
|
|
|
20
17
|
const react_1 = require("react");
|
|
21
18
|
const react_grid_layout_1 = require("react-grid-layout");
|
|
22
19
|
const material_1 = require("@mui/material");
|
|
23
|
-
const styles_1 =
|
|
20
|
+
const styles_1 = require("../../css/styles");
|
|
24
21
|
const context_1 = require("../../context");
|
|
25
22
|
const GridTitle_1 = require("./GridTitle");
|
|
26
23
|
const ResponsiveGridLayout = (0, react_grid_layout_1.WidthProvider)(react_grid_layout_1.Responsive);
|
|
@@ -28,16 +25,16 @@ const ResponsiveGridLayout = (0, react_grid_layout_1.WidthProvider)(react_grid_l
|
|
|
28
25
|
* Layout component that arranges children in a Grid based on the definition.
|
|
29
26
|
*/
|
|
30
27
|
function GridLayout(props) {
|
|
31
|
-
var _a, _b
|
|
32
|
-
const { definition: { spec }, renderGridItemContent, ...others } = props;
|
|
33
|
-
const [isOpen, setIsOpen] = (0, react_1.useState)((
|
|
28
|
+
var _a, _b;
|
|
29
|
+
const { groupIndex, definition: { spec }, renderGridItemContent, ...others } = props;
|
|
30
|
+
const [isOpen, setIsOpen] = (0, react_1.useState)(!!((_b = (_a = spec.display) === null || _a === void 0 ? void 0 : _a.collapse) === null || _b === void 0 ? void 0 : _b.open));
|
|
34
31
|
const { isEditMode } = (0, context_1.useEditMode)();
|
|
35
32
|
const gridItems = [];
|
|
36
33
|
spec.items.forEach((item, idx) => {
|
|
37
34
|
const { x, y, width: w, height: h } = item;
|
|
38
|
-
gridItems.push((0, jsx_runtime_1.jsx)("div", { "data-grid": { x, y, w, h }, children: renderGridItemContent(item) }, idx));
|
|
35
|
+
gridItems.push((0, jsx_runtime_1.jsx)("div", { "data-grid": { x, y, w, h }, children: renderGridItemContent(item, groupIndex) }, idx));
|
|
39
36
|
});
|
|
40
|
-
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(material_1.GlobalStyles, { styles: styles_1.
|
|
37
|
+
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(material_1.GlobalStyles, { styles: styles_1.styles }), (0, jsx_runtime_1.jsxs)(material_1.Box, { ...others, component: "section", sx: { '& + &': { marginTop: (theme) => theme.spacing(1) } }, children: [spec.display !== undefined && ((0, jsx_runtime_1.jsx)(GridTitle_1.GridTitle, { groupIndex: groupIndex, title: spec.display.title, collapse: spec.display.collapse === undefined
|
|
41
38
|
? undefined
|
|
42
39
|
: { isOpen, onToggleOpen: () => setIsOpen((current) => !current) } })), (0, jsx_runtime_1.jsx)(material_1.Collapse, { in: isOpen, unmountOnExit: true, children: (0, jsx_runtime_1.jsx)(ResponsiveGridLayout, { className: "layout", breakpoints: { lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 }, cols: { lg: 24, md: 24, sm: 24, xs: 24, xxs: 2 }, rowHeight: 30, draggableHandle: '.drag-handle', resizeHandles: ['se'], isDraggable: isEditMode, isResizable: isEditMode, children: gridItems }) })] })] }));
|
|
43
40
|
}
|
|
@@ -20,22 +20,28 @@ const jsx_runtime_1 = require("react/jsx-runtime");
|
|
|
20
20
|
const material_1 = require("@mui/material");
|
|
21
21
|
const ChevronUp_1 = __importDefault(require("mdi-material-ui/ChevronUp"));
|
|
22
22
|
const ChevronDown_1 = __importDefault(require("mdi-material-ui/ChevronDown"));
|
|
23
|
+
const Plus_1 = __importDefault(require("mdi-material-ui/Plus"));
|
|
24
|
+
const PencilOutline_1 = __importDefault(require("mdi-material-ui/PencilOutline"));
|
|
25
|
+
const react_1 = require("react");
|
|
26
|
+
const context_1 = require("../../context");
|
|
23
27
|
/**
|
|
24
28
|
* Renders the title for a Grid section, optionally also supporting expanding
|
|
25
29
|
* and collapsing
|
|
26
30
|
*/
|
|
27
31
|
function GridTitle(props) {
|
|
28
|
-
const { title, collapse } = props;
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
// Otherwise render something clickable
|
|
35
|
-
return ((0, jsx_runtime_1.jsxs)(material_1.ButtonBase, { component: "header", sx: {
|
|
32
|
+
const { groupIndex, title, collapse } = props;
|
|
33
|
+
const [isHovered, setIsHovered] = (0, react_1.useState)(false);
|
|
34
|
+
const { openPanelDrawer, openPanelGroupDialog } = (0, context_1.useDashboardApp)();
|
|
35
|
+
const { isEditMode } = (0, context_1.useEditMode)();
|
|
36
|
+
const text = ((0, jsx_runtime_1.jsx)(material_1.Typography, { variant: "h2", sx: { marginLeft: collapse !== undefined ? 1 : undefined }, children: title }));
|
|
37
|
+
return ((0, jsx_runtime_1.jsx)(material_1.Box, { sx: {
|
|
36
38
|
display: 'flex',
|
|
37
39
|
justifyContent: 'start',
|
|
38
40
|
alignItems: 'center',
|
|
39
|
-
|
|
41
|
+
padding: (theme) => theme.spacing(1),
|
|
42
|
+
backgroundColor: (theme) => theme.palette.background.default,
|
|
43
|
+
}, onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), children: collapse ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(material_1.IconButton, { onClick: collapse.onToggleOpen, children: collapse.isOpen ? (0, jsx_runtime_1.jsx)(ChevronUp_1.default, {}) : (0, jsx_runtime_1.jsx)(ChevronDown_1.default, {}) }), text, isEditMode && isHovered && ((0, jsx_runtime_1.jsxs)(material_1.Stack, { direction: "row", sx: { marginLeft: 'auto' }, children: [(0, jsx_runtime_1.jsx)(material_1.IconButton, { onClick: () => openPanelDrawer({ groupIndex }), children: (0, jsx_runtime_1.jsx)(Plus_1.default, {}) }), (0, jsx_runtime_1.jsx)(material_1.IconButton, { onClick: () => openPanelGroupDialog(groupIndex), children: (0, jsx_runtime_1.jsx)(PencilOutline_1.default, {}) })] }))] })) : (
|
|
44
|
+
// If we don't need expand/collapse, just render the title text
|
|
45
|
+
text) }));
|
|
40
46
|
}
|
|
41
47
|
exports.GridTitle = GridTitle;
|
|
@@ -25,15 +25,16 @@ const components_1 = require("@perses-dev/components");
|
|
|
25
25
|
const material_1 = require("@mui/material");
|
|
26
26
|
const InformationOutline_1 = __importDefault(require("mdi-material-ui/InformationOutline"));
|
|
27
27
|
const Pencil_1 = __importDefault(require("mdi-material-ui/Pencil"));
|
|
28
|
-
const
|
|
29
|
-
const Drag_1 = __importDefault(require("mdi-material-ui/Drag"));
|
|
28
|
+
const DragVertical_1 = __importDefault(require("mdi-material-ui/DragVertical"));
|
|
30
29
|
const context_1 = require("../../context");
|
|
30
|
+
const PanelContent_1 = require("./PanelContent");
|
|
31
31
|
/**
|
|
32
32
|
* Renders a PanelDefinition's content inside of a Card.
|
|
33
33
|
*/
|
|
34
34
|
function Panel(props) {
|
|
35
|
-
const { definition, ...others } = props;
|
|
35
|
+
const { definition, groupIndex, panelKey, ...others } = props;
|
|
36
36
|
const [contentElement, setContentElement] = (0, react_1.useState)(null);
|
|
37
|
+
const [isHovered, setIsHovered] = (0, react_1.useState)(false);
|
|
37
38
|
const { width, height } = (0, use_resize_observer_1.default)({ ref: contentElement });
|
|
38
39
|
const contentDimensions = (0, react_1.useMemo)(() => {
|
|
39
40
|
if (width === undefined || height === undefined)
|
|
@@ -48,13 +49,17 @@ function Panel(props) {
|
|
|
48
49
|
// TODO: adjust padding for small panels, consistent way to determine isLargePanel here and in StatChart
|
|
49
50
|
const panelPadding = 1.5;
|
|
50
51
|
const { isEditMode } = (0, context_1.useEditMode)();
|
|
52
|
+
const { openPanelDrawer } = (0, context_1.useDashboardApp)();
|
|
53
|
+
const handleEditButtonClick = () => {
|
|
54
|
+
openPanelDrawer({ groupIndex, panelKey });
|
|
55
|
+
};
|
|
51
56
|
return ((0, jsx_runtime_1.jsxs)(material_1.Card, { ref: ref, sx: {
|
|
52
57
|
...others.sx,
|
|
53
58
|
width: '100%',
|
|
54
59
|
height: '100%',
|
|
55
60
|
display: 'flex',
|
|
56
61
|
flexFlow: 'column nowrap',
|
|
57
|
-
}, variant: "outlined", ...others, children: [(0, jsx_runtime_1.jsx)(material_1.CardHeader, { title: (0, jsx_runtime_1.jsxs)(material_1.Box, { sx: {
|
|
62
|
+
}, variant: "outlined", ...others, onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), children: [(0, jsx_runtime_1.jsx)(material_1.CardHeader, { title: (0, jsx_runtime_1.jsxs)(material_1.Box, { sx: {
|
|
58
63
|
display: 'flex',
|
|
59
64
|
alignItems: 'center',
|
|
60
65
|
minHeight: '24px',
|
|
@@ -62,7 +67,7 @@ function Panel(props) {
|
|
|
62
67
|
display: 'flex',
|
|
63
68
|
alignItems: 'center',
|
|
64
69
|
marginLeft: 'auto',
|
|
65
|
-
}, children: [!isEditMode && definition.display.description && ((0, jsx_runtime_1.jsx)(components_1.InfoTooltip, { id: "info-tooltip", description: definition.display.description, placement: components_1.TooltipPlacement.Bottom, children: (0, jsx_runtime_1.jsx)(InformationOutline_1.default, { "aria-describedby": "info-tooltip", "aria-hidden": false, fontSize: "small", sx: { cursor: 'pointer' } }) })), isEditMode && ((0, jsx_runtime_1.jsxs)(material_1.Stack, { direction: "row", alignItems: "center", spacing: 0.5, children: [(0, jsx_runtime_1.jsx)(IconButton, { "aria-label": "
|
|
70
|
+
}, children: [!isEditMode && isHovered && definition.display.description && ((0, jsx_runtime_1.jsx)(components_1.InfoTooltip, { id: "info-tooltip", description: definition.display.description, placement: components_1.TooltipPlacement.Bottom, children: (0, jsx_runtime_1.jsx)(InformationOutline_1.default, { "aria-describedby": "info-tooltip", "aria-hidden": false, fontSize: "small", sx: { cursor: 'pointer' } }) })), isEditMode && isHovered && ((0, jsx_runtime_1.jsxs)(material_1.Stack, { direction: "row", alignItems: "center", spacing: 0.5, children: [(0, jsx_runtime_1.jsx)(IconButton, { "aria-label": "edit panel", size: "small", onClick: handleEditButtonClick, children: (0, jsx_runtime_1.jsx)(Pencil_1.default, {}) }), (0, jsx_runtime_1.jsx)(IconButton, { "aria-label": "drag handle", size: "small", children: (0, jsx_runtime_1.jsx)(DragVertical_1.default, { className: "drag-handle", sx: { cursor: 'grab' } }) })] }))] })] }), sx: {
|
|
66
71
|
display: 'block',
|
|
67
72
|
padding: (theme) => theme.spacing(1, panelPadding),
|
|
68
73
|
borderBottom: (theme) => `solid 1px ${theme.palette.divider}`,
|
|
@@ -75,7 +80,7 @@ function Panel(props) {
|
|
|
75
80
|
':last-child': {
|
|
76
81
|
padding: (theme) => theme.spacing(panelPadding),
|
|
77
82
|
},
|
|
78
|
-
}, ref: setContentElement, children: (0, jsx_runtime_1.jsx)(plugin_system_1.PluginBoundary, { loadingFallback: "Loading...", ErrorFallbackComponent: components_1.ErrorAlert, children: inView === true && (0, jsx_runtime_1.jsx)(
|
|
83
|
+
}, ref: setContentElement, children: (0, jsx_runtime_1.jsx)(plugin_system_1.PluginBoundary, { loadingFallback: "Loading...", ErrorFallbackComponent: components_1.ErrorAlert, children: inView === true && (0, jsx_runtime_1.jsx)(PanelContent_1.PanelContent, { definition: definition, contentDimensions: contentDimensions }) }) })] }));
|
|
79
84
|
}
|
|
80
85
|
exports.Panel = Panel;
|
|
81
86
|
const IconButton = (0, material_1.styled)(material_1.IconButton)(({ theme }) => ({
|
|
@@ -4,22 +4,24 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
7
|
+
// Copyright 2022 The Perses Authors
|
|
8
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
9
|
+
// you may not use this file except in compliance with the License.
|
|
10
|
+
// You may obtain a copy of the License at
|
|
11
|
+
//
|
|
12
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
13
|
+
//
|
|
14
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
15
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
16
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
17
|
+
// See the License for the specific language governing permissions and
|
|
18
|
+
// limitations under the License.
|
|
7
19
|
const plugin_system_1 = require("@perses-dev/plugin-system");
|
|
8
20
|
require("intersection-observer");
|
|
9
21
|
const react_1 = require("@testing-library/react");
|
|
10
22
|
const test_1 = require("../../test");
|
|
11
23
|
const testDashboard_1 = __importDefault(require("../../test/testDashboard"));
|
|
12
|
-
const context_1 = require("../../context");
|
|
13
24
|
const Panel_1 = require("./Panel");
|
|
14
|
-
const FAKE_PANEL_PLUGIN = {
|
|
15
|
-
pluginType: 'Panel',
|
|
16
|
-
kind: 'FakePanel',
|
|
17
|
-
plugin: {
|
|
18
|
-
PanelComponent: () => {
|
|
19
|
-
return (0, jsx_runtime_1.jsx)("div", { role: "figure", children: "FakePanel chart" });
|
|
20
|
-
},
|
|
21
|
-
},
|
|
22
|
-
};
|
|
23
25
|
describe('Panel', () => {
|
|
24
26
|
let props;
|
|
25
27
|
let initialState;
|
|
@@ -33,6 +35,8 @@ describe('Panel', () => {
|
|
|
33
35
|
kind: 'FakePanel',
|
|
34
36
|
options: {},
|
|
35
37
|
},
|
|
38
|
+
groupIndex: 0,
|
|
39
|
+
panelKey: 'panelRef',
|
|
36
40
|
};
|
|
37
41
|
initialState = {
|
|
38
42
|
isEditMode: false,
|
|
@@ -42,11 +46,11 @@ describe('Panel', () => {
|
|
|
42
46
|
// Helper to render the panel with some context set
|
|
43
47
|
const renderPanel = (initialState) => {
|
|
44
48
|
const { addMockPlugin, pluginRegistryProps } = (0, test_1.mockPluginRegistryProps)();
|
|
45
|
-
addMockPlugin(FAKE_PANEL_PLUGIN);
|
|
46
|
-
(0, test_1.renderWithContext)((0, jsx_runtime_1.jsx)(
|
|
49
|
+
addMockPlugin('Panel', 'FakePanel', test_1.FAKE_PANEL_PLUGIN);
|
|
50
|
+
(0, test_1.renderWithContext)((0, jsx_runtime_1.jsx)(plugin_system_1.PluginRegistry, { ...pluginRegistryProps, children: (0, jsx_runtime_1.jsx)(Panel_1.Panel, { ...props }) }), initialState);
|
|
47
51
|
};
|
|
48
52
|
it('should render name and info icon', async () => {
|
|
49
|
-
renderPanel(
|
|
53
|
+
renderPanel();
|
|
50
54
|
await react_1.screen.findByText('Fake Panel');
|
|
51
55
|
react_1.screen.queryByLabelText('info-tooltip');
|
|
52
56
|
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PanelContent = void 0;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const plugin_system_1 = require("@perses-dev/plugin-system");
|
|
6
|
+
/**
|
|
7
|
+
* A small wrapper component that renders the appropriate PanelComponent from a Panel plugin based on the panel
|
|
8
|
+
* definition's kind. Used so that a PluginLoadingBoundary can be wrapped around this for fallback UI while
|
|
9
|
+
* the plugin is loading.
|
|
10
|
+
*/
|
|
11
|
+
function PanelContent(props) {
|
|
12
|
+
const { PanelComponent } = (0, plugin_system_1.usePanelPlugin)(props.definition.kind);
|
|
13
|
+
return (0, jsx_runtime_1.jsx)(PanelComponent, { ...props });
|
|
14
|
+
}
|
|
15
|
+
exports.PanelContent = PanelContent;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright 2022 The Perses Authors
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
15
|
+
if (k2 === undefined) k2 = k;
|
|
16
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
17
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
18
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
19
|
+
}
|
|
20
|
+
Object.defineProperty(o, k2, desc);
|
|
21
|
+
}) : (function(o, m, k, k2) {
|
|
22
|
+
if (k2 === undefined) k2 = k;
|
|
23
|
+
o[k2] = m[k];
|
|
24
|
+
}));
|
|
25
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
26
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
__exportStar(require("./Panel"), exports);
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
4
|
+
// Copyright 2022 The Perses Authors
|
|
5
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
// you may not use this file except in compliance with the License.
|
|
7
|
+
// You may obtain a copy of the License at
|
|
8
|
+
//
|
|
9
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
//
|
|
11
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
// See the License for the specific language governing permissions and
|
|
15
|
+
// limitations under the License.
|
|
16
|
+
const material_1 = require("@mui/material");
|
|
17
|
+
const components_1 = require("@perses-dev/components");
|
|
18
|
+
const plugin_system_1 = require("@perses-dev/plugin-system");
|
|
19
|
+
const react_1 = require("react");
|
|
20
|
+
const context_1 = require("../../context");
|
|
21
|
+
const functions_1 = require("../../utils/functions");
|
|
22
|
+
const PanelOptionsEditor_1 = require("./PanelOptionsEditor");
|
|
23
|
+
const PanelDrawer = () => {
|
|
24
|
+
var _a, _b, _c, _d;
|
|
25
|
+
const { layouts } = (0, context_1.useLayouts)();
|
|
26
|
+
const { panels, updatePanel } = (0, context_1.usePanels)();
|
|
27
|
+
const { panelDrawer, closePanelDrawer } = (0, context_1.useDashboardApp)();
|
|
28
|
+
let defaultPanelName = '';
|
|
29
|
+
let defaultDescription = '';
|
|
30
|
+
if (panelDrawer === null || panelDrawer === void 0 ? void 0 : panelDrawer.panelKey) {
|
|
31
|
+
// editing an existing panel
|
|
32
|
+
defaultPanelName = (_b = (_a = panels[panelDrawer.panelKey]) === null || _a === void 0 ? void 0 : _a.display.name) !== null && _b !== void 0 ? _b : '';
|
|
33
|
+
defaultDescription = (_d = (_c = panels[panelDrawer.panelKey]) === null || _c === void 0 ? void 0 : _c.display.description) !== null && _d !== void 0 ? _d : '';
|
|
34
|
+
}
|
|
35
|
+
const [group, setGroup] = (0, react_1.useState)(panelDrawer === null || panelDrawer === void 0 ? void 0 : panelDrawer.groupIndex);
|
|
36
|
+
const [panelName, setPanelName] = (0, react_1.useState)(defaultPanelName);
|
|
37
|
+
const [panelDescription, setPanelDescription] = (0, react_1.useState)(defaultDescription);
|
|
38
|
+
const [kind, setKind] = (0, react_1.useState)('');
|
|
39
|
+
const [options, setOptions] = (0, react_1.useState)({});
|
|
40
|
+
// TO DO: we might want to make the form a sub component we don't need this useEffect
|
|
41
|
+
// currently, we need to reset the states whenever panelDrawer is reopened
|
|
42
|
+
// since this component does not get remounted when it open/closes (otherwise we lose the animation of sliding in/out)
|
|
43
|
+
(0, react_1.useEffect)(() => {
|
|
44
|
+
var _a, _b, _c, _d;
|
|
45
|
+
setGroup(panelDrawer === null || panelDrawer === void 0 ? void 0 : panelDrawer.groupIndex);
|
|
46
|
+
if (panelDrawer === null || panelDrawer === void 0 ? void 0 : panelDrawer.panelKey) {
|
|
47
|
+
// display panel name and description in text fields when editing an existing panel
|
|
48
|
+
setPanelName((_b = (_a = panels[panelDrawer.panelKey]) === null || _a === void 0 ? void 0 : _a.display.name) !== null && _b !== void 0 ? _b : '');
|
|
49
|
+
setPanelDescription((_d = (_c = panels[panelDrawer.panelKey]) === null || _c === void 0 ? void 0 : _c.display.description) !== null && _d !== void 0 ? _d : '');
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
setPanelName('');
|
|
53
|
+
setPanelDescription('');
|
|
54
|
+
}
|
|
55
|
+
}, [panelDrawer, panels]);
|
|
56
|
+
const handleGroupChange = (e) => {
|
|
57
|
+
const { value } = e.target;
|
|
58
|
+
// Handle string (which would be empty string but shouldn't happen since we don't allow a "None" option) by
|
|
59
|
+
// just ignoring it
|
|
60
|
+
if (typeof value === 'string')
|
|
61
|
+
return;
|
|
62
|
+
setGroup(value);
|
|
63
|
+
};
|
|
64
|
+
const handlePanelNameChange = (e) => {
|
|
65
|
+
setPanelName(e.target.value);
|
|
66
|
+
};
|
|
67
|
+
const handlePanelDescriptionChange = (e) => {
|
|
68
|
+
setPanelDescription(e.target.value);
|
|
69
|
+
};
|
|
70
|
+
const handleKindChange = (e) => {
|
|
71
|
+
setKind(e.target.value);
|
|
72
|
+
};
|
|
73
|
+
const handleOptionsChange = (next) => {
|
|
74
|
+
setOptions(next);
|
|
75
|
+
};
|
|
76
|
+
const handleSubmit = (e) => {
|
|
77
|
+
e.preventDefault();
|
|
78
|
+
if ((panelDrawer === null || panelDrawer === void 0 ? void 0 : panelDrawer.groupIndex) !== undefined && !(panelDrawer === null || panelDrawer === void 0 ? void 0 : panelDrawer.panelKey)) {
|
|
79
|
+
addNewPanel();
|
|
80
|
+
}
|
|
81
|
+
else if (panelDrawer === null || panelDrawer === void 0 ? void 0 : panelDrawer.panelKey) {
|
|
82
|
+
editPanel();
|
|
83
|
+
}
|
|
84
|
+
closePanelDrawer();
|
|
85
|
+
};
|
|
86
|
+
const addNewPanel = () => {
|
|
87
|
+
if ((panelDrawer === null || panelDrawer === void 0 ? void 0 : panelDrawer.groupIndex) === undefined) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
const panelKey = (0, functions_1.removeWhiteSpacesAndSpecialCharacters)(panelName);
|
|
91
|
+
updatePanel(panelKey, {
|
|
92
|
+
kind,
|
|
93
|
+
options,
|
|
94
|
+
display: { name: panelName, description: panelDescription },
|
|
95
|
+
}, panelDrawer.groupIndex);
|
|
96
|
+
};
|
|
97
|
+
const editPanel = () => {
|
|
98
|
+
if ((panelDrawer === null || panelDrawer === void 0 ? void 0 : panelDrawer.panelKey) === undefined) {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
updatePanel(panelDrawer.panelKey, {
|
|
102
|
+
...panels[panelDrawer.panelKey],
|
|
103
|
+
kind,
|
|
104
|
+
options,
|
|
105
|
+
display: { name: panelName !== null && panelName !== void 0 ? panelName : '', description: panelDescription },
|
|
106
|
+
});
|
|
107
|
+
// TO DO: need to move panel if panel group changes
|
|
108
|
+
};
|
|
109
|
+
return ((0, jsx_runtime_1.jsx)(components_1.Drawer, { isOpen: !!panelDrawer, onClose: () => closePanelDrawer(), children: (0, jsx_runtime_1.jsxs)("form", { onSubmit: handleSubmit, children: [(0, jsx_runtime_1.jsx)(PanelDrawerHeader, { panelKey: panelDrawer === null || panelDrawer === void 0 ? void 0 : panelDrawer.panelKey, onClose: () => closePanelDrawer() }), (0, jsx_runtime_1.jsxs)(material_1.Grid, { container: true, spacing: 2, children: [(0, jsx_runtime_1.jsx)(material_1.Grid, { item: true, xs: 4, children: (0, jsx_runtime_1.jsxs)(material_1.FormControl, { children: [(0, jsx_runtime_1.jsx)(material_1.InputLabel, { id: "select-group", children: "Group" }), (0, jsx_runtime_1.jsx)(material_1.Select, { required: true, labelId: "select-group", label: "Group", value: group !== null && group !== void 0 ? group : 0, onChange: handleGroupChange, children: layouts.map((layout, index) => {
|
|
110
|
+
var _a;
|
|
111
|
+
return ((0, jsx_runtime_1.jsx)(material_1.MenuItem, { value: index, children: ((_a = layout.spec.display) === null || _a === void 0 ? void 0 : _a.title) || `Group ${index + 1}` }, index));
|
|
112
|
+
}) })] }) }), (0, jsx_runtime_1.jsx)(material_1.Grid, { item: true, xs: 8, children: (0, jsx_runtime_1.jsxs)(material_1.Stack, { spacing: 2, sx: { flexGrow: '1' }, children: [(0, jsx_runtime_1.jsx)(material_1.TextField, { required: true, label: "Panel Name", value: panelName, variant: "outlined", onChange: handlePanelNameChange }), (0, jsx_runtime_1.jsx)(material_1.TextField, { label: "Description", value: panelDescription, variant: "outlined", onChange: handlePanelDescriptionChange })] }) }), (0, jsx_runtime_1.jsx)(material_1.Grid, { item: true, xs: 4, children: (0, jsx_runtime_1.jsxs)(material_1.FormControl, { children: [(0, jsx_runtime_1.jsx)(material_1.InputLabel, { id: "panel-type-label", children: "Panel Type" }), (0, jsx_runtime_1.jsxs)(material_1.Select, { required: true, labelId: "panel-type-label", label: "Panel Type", value: kind, onChange: handleKindChange, children: [(0, jsx_runtime_1.jsx)(material_1.MenuItem, { value: "LineChart", children: "Line Chart" }), (0, jsx_runtime_1.jsx)(material_1.MenuItem, { value: "GaugeChart", children: "Gauge Chart" }), (0, jsx_runtime_1.jsx)(material_1.MenuItem, { value: "StatChart", children: "Stat Chart" })] })] }) }), (0, jsx_runtime_1.jsx)(material_1.Grid, { item: true, xs: 8, children: (0, jsx_runtime_1.jsx)(plugin_system_1.PluginBoundary, { loadingFallback: "Loading...", ErrorFallbackComponent: components_1.ErrorAlert, children: kind !== '' && (0, jsx_runtime_1.jsx)(PanelOptionsEditor_1.PanelOptionsEditor, { kind: kind, value: options, onChange: handleOptionsChange }) }) })] })] }) }));
|
|
113
|
+
};
|
|
114
|
+
const PanelDrawerHeader = ({ panelKey, onClose }) => {
|
|
115
|
+
const action = panelKey ? 'Edit' : 'Add';
|
|
116
|
+
return ((0, jsx_runtime_1.jsxs)(material_1.Box, { sx: {
|
|
117
|
+
display: 'flex',
|
|
118
|
+
alignItems: 'center',
|
|
119
|
+
marginBottom: (theme) => theme.spacing(2),
|
|
120
|
+
paddingBottom: (theme) => theme.spacing(2),
|
|
121
|
+
borderBottom: (theme) => `1px solid ${theme.palette.grey[100]}`,
|
|
122
|
+
}, children: [(0, jsx_runtime_1.jsx)(material_1.Typography, { variant: "h2", children: `${action} Panel` }), (0, jsx_runtime_1.jsxs)(material_1.Stack, { direction: "row", spacing: 1, sx: { marginLeft: 'auto' }, children: [(0, jsx_runtime_1.jsx)(material_1.Button, { type: "submit", variant: "contained", children: panelKey ? 'Apply' : 'Add' }), (0, jsx_runtime_1.jsx)(material_1.Button, { variant: "outlined", onClick: onClose, children: "Cancel" })] })] }));
|
|
123
|
+
};
|
|
124
|
+
exports.default = PanelDrawer;
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
30
|
+
// Copyright 2022 The Perses Authors
|
|
31
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
32
|
+
// you may not use this file except in compliance with the License.
|
|
33
|
+
// You may obtain a copy of the License at
|
|
34
|
+
//
|
|
35
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
36
|
+
//
|
|
37
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
38
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
39
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
40
|
+
// See the License for the specific language governing permissions and
|
|
41
|
+
// limitations under the License.
|
|
42
|
+
const plugin_system_1 = require("@perses-dev/plugin-system");
|
|
43
|
+
const react_1 = require("@testing-library/react");
|
|
44
|
+
const user_event_1 = __importDefault(require("@testing-library/user-event"));
|
|
45
|
+
const dashboardAppSlice = __importStar(require("../../context/DashboardAppSlice"));
|
|
46
|
+
const layoutsSlice = __importStar(require("../../context/LayoutsSlice"));
|
|
47
|
+
const context = __importStar(require("../../context/DashboardProvider"));
|
|
48
|
+
const test_1 = require("../../test");
|
|
49
|
+
const testDashboard_1 = __importDefault(require("../../test/testDashboard"));
|
|
50
|
+
const PanelDrawer_1 = __importDefault(require("./PanelDrawer"));
|
|
51
|
+
const updatePanel = jest.fn();
|
|
52
|
+
jest.spyOn(context, 'usePanels').mockReturnValue({
|
|
53
|
+
updatePanel,
|
|
54
|
+
panels: {},
|
|
55
|
+
});
|
|
56
|
+
const addItemToLayout = jest.fn();
|
|
57
|
+
jest.spyOn(layoutsSlice, 'useLayouts').mockReturnValue({
|
|
58
|
+
addItemToLayout,
|
|
59
|
+
updateLayout: jest.fn(),
|
|
60
|
+
layouts: testDashboard_1.default.spec.layouts,
|
|
61
|
+
});
|
|
62
|
+
const dashboardApp = {
|
|
63
|
+
panelDrawer: {
|
|
64
|
+
groupIndex: 0,
|
|
65
|
+
},
|
|
66
|
+
openPanelDrawer: jest.fn(),
|
|
67
|
+
closePanelDrawer: jest.fn(),
|
|
68
|
+
panelGroupDialog: undefined,
|
|
69
|
+
openPanelGroupDialog: jest.fn(),
|
|
70
|
+
closePanelGroupDialog: jest.fn(),
|
|
71
|
+
};
|
|
72
|
+
describe('Panel Drawer', () => {
|
|
73
|
+
beforeEach(() => {
|
|
74
|
+
jest.clearAllMocks();
|
|
75
|
+
});
|
|
76
|
+
const renderPanelDrawer = () => {
|
|
77
|
+
const { addMockPlugin, pluginRegistryProps } = (0, test_1.mockPluginRegistryProps)();
|
|
78
|
+
addMockPlugin('Panel', 'FakePanel', test_1.FAKE_PANEL_PLUGIN);
|
|
79
|
+
(0, test_1.renderWithContext)((0, jsx_runtime_1.jsxs)(plugin_system_1.PluginRegistry, { ...pluginRegistryProps, children: [(0, jsx_runtime_1.jsx)(PanelDrawer_1.default, {}), ","] }));
|
|
80
|
+
};
|
|
81
|
+
it('should add new panel', () => {
|
|
82
|
+
jest.spyOn(dashboardAppSlice, 'useDashboardApp').mockReturnValue(dashboardApp);
|
|
83
|
+
renderPanelDrawer();
|
|
84
|
+
const nameInput = react_1.screen.getByLabelText(/Panel Name/);
|
|
85
|
+
user_event_1.default.type(nameInput, 'New Panel');
|
|
86
|
+
user_event_1.default.click(react_1.screen.getByText('Add'));
|
|
87
|
+
expect(updatePanel).toHaveBeenCalledWith('NewPanel', {
|
|
88
|
+
kind: '',
|
|
89
|
+
display: { name: 'New Panel', description: '' },
|
|
90
|
+
options: {},
|
|
91
|
+
}, 0);
|
|
92
|
+
});
|
|
93
|
+
it('should edit an existing panel', () => {
|
|
94
|
+
jest.spyOn(dashboardAppSlice, 'useDashboardApp').mockReturnValue({
|
|
95
|
+
...dashboardApp,
|
|
96
|
+
panelDrawer: {
|
|
97
|
+
groupIndex: 0,
|
|
98
|
+
panelKey: 'cpu',
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
renderPanelDrawer();
|
|
102
|
+
const nameInput = react_1.screen.getByLabelText(/Panel Name/);
|
|
103
|
+
user_event_1.default.type(nameInput, 'cpu usage');
|
|
104
|
+
user_event_1.default.click(react_1.screen.getByText('Apply'));
|
|
105
|
+
expect(updatePanel).toHaveBeenCalledWith('cpu', {
|
|
106
|
+
display: { name: 'cpu usage', description: '' },
|
|
107
|
+
kind: '',
|
|
108
|
+
options: {},
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PanelOptionsEditor = void 0;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const plugin_system_1 = require("@perses-dev/plugin-system");
|
|
6
|
+
const react_1 = require("react");
|
|
7
|
+
function PanelOptionsEditor(props) {
|
|
8
|
+
const { kind, value, onChange } = props;
|
|
9
|
+
const { OptionsEditorComponent, createInitialOptions } = (0, plugin_system_1.usePanelPlugin)(kind);
|
|
10
|
+
// When the kind changes, re-init options
|
|
11
|
+
(0, react_1.useEffect)(() => {
|
|
12
|
+
onChange(createInitialOptions());
|
|
13
|
+
// TODO: See if we can switch up plugin loading so this happens as part of selecting the plugin kind so we don't
|
|
14
|
+
// need this effect at all
|
|
15
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
16
|
+
}, [kind]);
|
|
17
|
+
return (0, jsx_runtime_1.jsx)(OptionsEditorComponent, { value: value, onChange: onChange });
|
|
18
|
+
}
|
|
19
|
+
exports.PanelOptionsEditor = PanelOptionsEditor;
|