@perses-dev/dashboards 0.52.0-rc.1 → 0.53.0-beta.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/DashboardStickyToolbar/DashboardStickyToolbar.js +0 -2
- package/dist/cjs/components/DeletePanelGroupDialog/DeletePanelGroupDialog.js +5 -20
- package/dist/cjs/components/GridLayout/GridItemContent.js +6 -64
- package/dist/cjs/components/LeaveDialog/LeaveDialog.js +10 -1
- package/dist/cjs/components/PanelDrawer/PanelEditorForm.js +186 -183
- package/dist/cjs/components/PanelDrawer/PanelPreview.js +3 -0
- package/dist/cjs/components/PanelGroupDialog/PanelGroupDialog.js +6 -21
- package/dist/cjs/components/QueryViewerDialog/QueryViewerDialog.js +121 -0
- package/dist/cjs/components/QueryViewerDialog/index.js +30 -0
- package/dist/cjs/components/Variables/ListVariableListBox.js +201 -0
- package/dist/cjs/components/Variables/Variable.js +130 -72
- package/dist/cjs/components/Variables/index.js +1 -0
- package/dist/cjs/components/index.js +2 -1
- package/dist/cjs/context/DashboardProvider/DashboardProviderWithQueryParams.js +5 -27
- package/dist/cjs/context/DashboardProvider/duplicate-panel-slice.js +1 -1
- package/dist/cjs/context/DashboardProvider/panel-editor-slice.js +1 -2
- package/dist/cjs/context/PanelEditorProvider/PanelEditorProvider.js +49 -0
- package/dist/cjs/context/PanelEditorProvider/index.js +23 -0
- package/dist/cjs/context/VariableProvider/query-params.js +14 -12
- package/dist/cjs/context/index.js +1 -0
- package/dist/cjs/test/render.js +8 -6
- package/dist/components/DashboardStickyToolbar/DashboardStickyToolbar.d.ts.map +1 -1
- package/dist/components/DashboardStickyToolbar/DashboardStickyToolbar.js +0 -2
- package/dist/components/DashboardStickyToolbar/DashboardStickyToolbar.js.map +1 -1
- package/dist/components/DeletePanelGroupDialog/DeletePanelGroupDialog.d.ts.map +1 -1
- package/dist/components/DeletePanelGroupDialog/DeletePanelGroupDialog.js +5 -15
- package/dist/components/DeletePanelGroupDialog/DeletePanelGroupDialog.js.map +1 -1
- package/dist/components/GridLayout/GridItemContent.d.ts.map +1 -1
- package/dist/components/GridLayout/GridItemContent.js +8 -66
- package/dist/components/GridLayout/GridItemContent.js.map +1 -1
- package/dist/components/LeaveDialog/LeaveDialog.d.ts +2 -1
- package/dist/components/LeaveDialog/LeaveDialog.d.ts.map +1 -1
- package/dist/components/LeaveDialog/LeaveDialog.js +10 -1
- package/dist/components/LeaveDialog/LeaveDialog.js.map +1 -1
- package/dist/components/PanelDrawer/PanelEditorForm.d.ts.map +1 -1
- package/dist/components/PanelDrawer/PanelEditorForm.js +186 -183
- package/dist/components/PanelDrawer/PanelEditorForm.js.map +1 -1
- package/dist/components/PanelDrawer/PanelPreview.d.ts.map +1 -1
- package/dist/components/PanelDrawer/PanelPreview.js +4 -1
- package/dist/components/PanelDrawer/PanelPreview.js.map +1 -1
- package/dist/components/PanelGroupDialog/PanelGroupDialog.d.ts.map +1 -1
- package/dist/components/PanelGroupDialog/PanelGroupDialog.js +5 -15
- package/dist/components/PanelGroupDialog/PanelGroupDialog.js.map +1 -1
- package/dist/components/QueryViewerDialog/QueryViewerDialog.d.ts +9 -0
- package/dist/components/QueryViewerDialog/QueryViewerDialog.d.ts.map +1 -0
- package/dist/components/QueryViewerDialog/QueryViewerDialog.js +72 -0
- package/dist/components/QueryViewerDialog/QueryViewerDialog.js.map +1 -0
- package/dist/components/QueryViewerDialog/index.d.ts +2 -0
- package/dist/components/QueryViewerDialog/index.d.ts.map +1 -0
- package/dist/components/QueryViewerDialog/index.js +15 -0
- package/dist/components/QueryViewerDialog/index.js.map +1 -0
- package/dist/components/Variables/ListVariableListBox.d.ts +16 -0
- package/dist/components/Variables/ListVariableListBox.d.ts.map +1 -0
- package/dist/components/Variables/ListVariableListBox.js +141 -0
- package/dist/components/Variables/ListVariableListBox.js.map +1 -0
- package/dist/components/Variables/Variable.d.ts.map +1 -1
- package/dist/components/Variables/Variable.js +134 -76
- package/dist/components/Variables/Variable.js.map +1 -1
- package/dist/components/Variables/index.d.ts +1 -0
- package/dist/components/Variables/index.d.ts.map +1 -1
- package/dist/components/Variables/index.js +1 -0
- package/dist/components/Variables/index.js.map +1 -1
- package/dist/components/index.d.ts +2 -1
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +2 -1
- package/dist/components/index.js.map +1 -1
- package/dist/context/DashboardProvider/DashboardProviderWithQueryParams.d.ts.map +1 -1
- package/dist/context/DashboardProvider/DashboardProviderWithQueryParams.js +5 -27
- package/dist/context/DashboardProvider/DashboardProviderWithQueryParams.js.map +1 -1
- package/dist/context/DashboardProvider/duplicate-panel-slice.js +2 -2
- package/dist/context/DashboardProvider/duplicate-panel-slice.js.map +1 -1
- package/dist/context/DashboardProvider/panel-editor-slice.d.ts.map +1 -1
- package/dist/context/DashboardProvider/panel-editor-slice.js +2 -3
- package/dist/context/DashboardProvider/panel-editor-slice.js.map +1 -1
- package/dist/context/PanelEditorProvider/PanelEditorProvider.d.ts +13 -0
- package/dist/context/PanelEditorProvider/PanelEditorProvider.d.ts.map +1 -0
- package/dist/context/PanelEditorProvider/PanelEditorProvider.js +33 -0
- package/dist/context/PanelEditorProvider/PanelEditorProvider.js.map +1 -0
- package/dist/context/PanelEditorProvider/index.d.ts +3 -0
- package/dist/context/PanelEditorProvider/index.d.ts.map +1 -0
- package/dist/context/PanelEditorProvider/index.js +16 -0
- package/dist/context/PanelEditorProvider/index.js.map +1 -0
- package/dist/context/VariableProvider/query-params.d.ts +3 -4
- package/dist/context/VariableProvider/query-params.d.ts.map +1 -1
- package/dist/context/VariableProvider/query-params.js +14 -9
- package/dist/context/VariableProvider/query-params.js.map +1 -1
- package/dist/context/index.d.ts +1 -0
- package/dist/context/index.d.ts.map +1 -1
- package/dist/context/index.js +1 -0
- package/dist/context/index.js.map +1 -1
- package/dist/test/render.d.ts.map +1 -1
- package/dist/test/render.js +8 -6
- package/dist/test/render.js.map +1 -1
- package/dist/utils/panelUtils.d.ts +3 -0
- package/dist/utils/panelUtils.d.ts.map +1 -1
- package/dist/utils/panelUtils.js +3 -0
- package/dist/utils/panelUtils.js.map +1 -1
- package/package.json +6 -6
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright
|
|
1
|
+
// Copyright 2025 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
|
|
@@ -21,37 +21,15 @@ Object.defineProperty(exports, "DashboardProviderWithQueryParams", {
|
|
|
21
21
|
}
|
|
22
22
|
});
|
|
23
23
|
const _jsxruntime = require("react/jsx-runtime");
|
|
24
|
-
const
|
|
25
|
-
const _react = require("react");
|
|
26
|
-
const _nuqs = require("nuqs");
|
|
24
|
+
const _usequeryparams = require("use-query-params");
|
|
27
25
|
const _DashboardProvider = require("./DashboardProvider");
|
|
28
26
|
function DashboardProviderWithQueryParams({ children, initialState }) {
|
|
29
|
-
const [viewPanelRef, setViewPanelRef] = (0,
|
|
30
|
-
ref: _zod.z.string(),
|
|
31
|
-
repeatVariable: _zod.z.tuple([
|
|
32
|
-
_zod.z.string(),
|
|
33
|
-
_zod.z.string()
|
|
34
|
-
]).optional()
|
|
35
|
-
}).optional()));
|
|
36
|
-
// nuqs returns null when the query param is not present, but our state expects undefined when not present
|
|
37
|
-
const viewPanelRefNotNull = (0, _react.useMemo)(()=>{
|
|
38
|
-
return viewPanelRef ?? undefined;
|
|
39
|
-
}, [
|
|
40
|
-
viewPanelRef
|
|
41
|
-
]);
|
|
42
|
-
const handleSetViewPanelRef = (0, _react.useCallback)((panelRef)=>{
|
|
43
|
-
if (panelRef) {
|
|
44
|
-
return setViewPanelRef(panelRef);
|
|
45
|
-
}
|
|
46
|
-
return setViewPanelRef(null);
|
|
47
|
-
}, [
|
|
48
|
-
setViewPanelRef
|
|
49
|
-
]);
|
|
27
|
+
const [viewPanelRef, setViewPanelRef] = (0, _usequeryparams.useQueryParam)('viewPanelRef', _usequeryparams.JsonParam);
|
|
50
28
|
return /*#__PURE__*/ (0, _jsxruntime.jsx)(_DashboardProvider.DashboardProvider, {
|
|
51
29
|
initialState: {
|
|
52
30
|
...initialState,
|
|
53
|
-
viewPanelRef:
|
|
54
|
-
setViewPanelRef:
|
|
31
|
+
viewPanelRef: viewPanelRef ?? undefined,
|
|
32
|
+
setViewPanelRef: setViewPanelRef
|
|
55
33
|
},
|
|
56
34
|
children: children
|
|
57
35
|
});
|
|
@@ -49,7 +49,7 @@ function createDuplicatePanelSlice() {
|
|
|
49
49
|
if (matchingLayout === undefined) {
|
|
50
50
|
throw new Error(`Cannot find layout for Panel with key '${panelKey}'`);
|
|
51
51
|
}
|
|
52
|
-
const dupePanelKey = (
|
|
52
|
+
const dupePanelKey = crypto.randomUUID().replaceAll('-', '');
|
|
53
53
|
state.panels[dupePanelKey] = panelToDupe;
|
|
54
54
|
const duplicateLayout = {
|
|
55
55
|
i: (0, _common.generateId)().toString(),
|
|
@@ -110,8 +110,7 @@ function createPanelEditorSlice() {
|
|
|
110
110
|
panelDefinition: get().initialValues?.panelDefinition ?? (0, _common.createPanelDefinition)()
|
|
111
111
|
},
|
|
112
112
|
applyChanges: (next)=>{
|
|
113
|
-
const
|
|
114
|
-
const panelKey = (0, _utils.getValidPanelKey)(name, get().panels);
|
|
113
|
+
const panelKey = crypto.randomUUID().replaceAll('-', '');
|
|
115
114
|
set((state)=>{
|
|
116
115
|
// Add a panel
|
|
117
116
|
state.panels[panelKey] = next.panelDefinition;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// Copyright 2025 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
|
+
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
|
+
PanelEditorContext: function() {
|
|
25
|
+
return PanelEditorContext;
|
|
26
|
+
},
|
|
27
|
+
PanelEditorProvider: function() {
|
|
28
|
+
return PanelEditorProvider;
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
const _jsxruntime = require("react/jsx-runtime");
|
|
32
|
+
const _react = require("react");
|
|
33
|
+
const PanelEditorContext = /*#__PURE__*/ (0, _react.createContext)(undefined);
|
|
34
|
+
const PanelEditorProvider = ({ children })=>{
|
|
35
|
+
const [previewPanelWidth, setPreviewPanelWidth] = (0, _react.useState)(undefined);
|
|
36
|
+
const ctx = (0, _react.useMemo)(()=>({
|
|
37
|
+
preview: {
|
|
38
|
+
previewPanelWidth,
|
|
39
|
+
setPreviewPanelWidth
|
|
40
|
+
}
|
|
41
|
+
}), [
|
|
42
|
+
previewPanelWidth,
|
|
43
|
+
setPreviewPanelWidth
|
|
44
|
+
]);
|
|
45
|
+
return /*#__PURE__*/ (0, _jsxruntime.jsx)(PanelEditorContext.Provider, {
|
|
46
|
+
value: ctx,
|
|
47
|
+
children: children
|
|
48
|
+
});
|
|
49
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// Copyright 2025 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, "PanelEditorContext", {
|
|
18
|
+
enumerable: true,
|
|
19
|
+
get: function() {
|
|
20
|
+
return _PanelEditorProvider.PanelEditorContext;
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
const _PanelEditorProvider = require("./PanelEditorProvider");
|
|
@@ -33,14 +33,11 @@ _export(exports, {
|
|
|
33
33
|
getURLQueryParamName: function() {
|
|
34
34
|
return getURLQueryParamName;
|
|
35
35
|
},
|
|
36
|
-
parseAsVariableValue: function() {
|
|
37
|
-
return parseAsVariableValue;
|
|
38
|
-
},
|
|
39
36
|
useVariableQueryParams: function() {
|
|
40
37
|
return useVariableQueryParams;
|
|
41
38
|
}
|
|
42
39
|
});
|
|
43
|
-
const
|
|
40
|
+
const _usequeryparams = require("use-query-params");
|
|
44
41
|
const variableQueryParameterPrefix = 'var-';
|
|
45
42
|
function getURLQueryParamName(name) {
|
|
46
43
|
return `${variableQueryParameterPrefix}${name}`;
|
|
@@ -49,7 +46,7 @@ function encodeVariableValue(value) {
|
|
|
49
46
|
if (Array.isArray(value)) {
|
|
50
47
|
return value.join(',');
|
|
51
48
|
}
|
|
52
|
-
return value
|
|
49
|
+
return value;
|
|
53
50
|
}
|
|
54
51
|
function decodeVariableValue(value) {
|
|
55
52
|
if (!value) {
|
|
@@ -61,18 +58,23 @@ function decodeVariableValue(value) {
|
|
|
61
58
|
}
|
|
62
59
|
return values;
|
|
63
60
|
}
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
61
|
+
const VariableValueParam = {
|
|
62
|
+
encode: encodeVariableValue,
|
|
63
|
+
decode: (v)=>{
|
|
64
|
+
if (typeof v === 'string') {
|
|
65
|
+
return decodeVariableValue(v);
|
|
66
|
+
}
|
|
67
|
+
return '';
|
|
68
|
+
}
|
|
69
|
+
};
|
|
68
70
|
function useVariableQueryParams(defs) {
|
|
69
71
|
const config = {};
|
|
70
72
|
defs.forEach((def)=>{
|
|
71
73
|
const name = getURLQueryParamName(def.spec.name);
|
|
72
|
-
config[name] =
|
|
74
|
+
config[name] = VariableValueParam;
|
|
73
75
|
});
|
|
74
|
-
return (0,
|
|
75
|
-
|
|
76
|
+
return (0, _usequeryparams.useQueryParams)(config, {
|
|
77
|
+
updateType: 'replaceIn'
|
|
76
78
|
});
|
|
77
79
|
}
|
|
78
80
|
function getInitalValuesFromQueryParameters(queryParamValues) {
|
|
@@ -18,6 +18,7 @@ _export_star(require("./DashboardProvider"), exports);
|
|
|
18
18
|
_export_star(require("./DatasourceStoreProvider"), exports);
|
|
19
19
|
_export_star(require("./VariableProvider"), exports);
|
|
20
20
|
_export_star(require("./useDashboard"), exports);
|
|
21
|
+
_export_star(require("./PanelEditorProvider"), exports);
|
|
21
22
|
function _export_star(from, to) {
|
|
22
23
|
Object.keys(from).forEach(function(k) {
|
|
23
24
|
if (k !== "default" && !Object.prototype.hasOwnProperty.call(to, k)) {
|
package/dist/cjs/test/render.js
CHANGED
|
@@ -28,7 +28,8 @@ const _react = require("@testing-library/react");
|
|
|
28
28
|
const _history = require("history");
|
|
29
29
|
const _react1 = require("react");
|
|
30
30
|
const _reactrouterdom = require("react-router-dom");
|
|
31
|
-
const
|
|
31
|
+
const _usequeryparams = require("use-query-params");
|
|
32
|
+
const _reactrouter6 = require("use-query-params/adapters/react-router-6");
|
|
32
33
|
const _context = require("../context");
|
|
33
34
|
const _test = require("../test");
|
|
34
35
|
const _pluginregistry = require("./plugin-registry");
|
|
@@ -62,11 +63,12 @@ function renderWithContext(ui, options, history) {
|
|
|
62
63
|
});
|
|
63
64
|
const customHistory = history ?? (0, _history.createMemoryHistory)();
|
|
64
65
|
const mockRegistry = (0, _pluginsystem.mockPluginRegistry)(..._pluginregistry.MOCK_PLUGINS);
|
|
65
|
-
const BaseRender = ()=>/*#__PURE__*/ (0, _jsxruntime.jsx)(
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
66
|
+
const BaseRender = ()=>/*#__PURE__*/ (0, _jsxruntime.jsx)(CustomRouter, {
|
|
67
|
+
history: customHistory,
|
|
68
|
+
children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_reactquery.QueryClientProvider, {
|
|
69
|
+
client: queryClient,
|
|
70
|
+
children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_usequeryparams.QueryParamProvider, {
|
|
71
|
+
adapter: _reactrouter6.ReactRouter6Adapter,
|
|
70
72
|
children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.SnackbarProvider, {
|
|
71
73
|
anchorOrigin: {
|
|
72
74
|
vertical: 'bottom',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DashboardStickyToolbar.d.ts","sourceRoot":"","sources":["../../../src/components/DashboardStickyToolbar/DashboardStickyToolbar.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAE,YAAY,EAAY,MAAM,OAAO,CAAC;AAC/C,OAAO,EAKL,OAAO,EACP,KAAK,EAIN,MAAM,eAAe,CAAC;AAMvB,UAAU,2BAA2B;IACnC,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,EAAE,CAAC,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;CACrB;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,2BAA2B,GAAG,YAAY,
|
|
1
|
+
{"version":3,"file":"DashboardStickyToolbar.d.ts","sourceRoot":"","sources":["../../../src/components/DashboardStickyToolbar/DashboardStickyToolbar.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAE,YAAY,EAAY,MAAM,OAAO,CAAC;AAC/C,OAAO,EAKL,OAAO,EACP,KAAK,EAIN,MAAM,eAAe,CAAC;AAMvB,UAAU,2BAA2B;IACnC,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,EAAE,CAAC,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;CACrB;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,2BAA2B,GAAG,YAAY,CAsEvF"}
|
|
@@ -48,8 +48,6 @@ export function DashboardStickyToolbar(props) {
|
|
|
48
48
|
display: "flex",
|
|
49
49
|
flexWrap: !isSticky && isBiggerThanMd ? 'wrap' : 'nowrap',
|
|
50
50
|
maxWidth: isSticky || !isBiggerThanMd ? '100vw' : '100%',
|
|
51
|
-
maxHeight: "150px" // Limit the vertical space used to ~3 rows of variables
|
|
52
|
-
,
|
|
53
51
|
pt: 1,
|
|
54
52
|
pl: isSticky ? 1 : 0,
|
|
55
53
|
mt: isSticky && isBiggerThanMd ? 0.5 : 0,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/DashboardStickyToolbar/DashboardStickyToolbar.tsx"],"sourcesContent":["// Copyright 2024 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { ReactElement, useState } from 'react';\nimport {\n AppBar,\n Box,\n IconButton,\n Stack,\n SxProps,\n Theme,\n useMediaQuery,\n useScrollTrigger,\n useTheme,\n} from '@mui/material';\nimport PinOutline from 'mdi-material-ui/PinOutline';\nimport PinOffOutline from 'mdi-material-ui/PinOffOutline';\nimport { TimeRangeControls } from '@perses-dev/plugin-system';\nimport { VariableList } from '../Variables';\n\ninterface DashboardStickyToolbarProps {\n initialVariableIsSticky?: boolean;\n sx?: SxProps<Theme>;\n}\n\nexport function DashboardStickyToolbar(props: DashboardStickyToolbarProps): ReactElement {\n const [isPin, setIsPin] = useState(props.initialVariableIsSticky);\n\n const scrollTrigger = useScrollTrigger({ disableHysteresis: true });\n const isSticky = scrollTrigger && props.initialVariableIsSticky && isPin;\n\n const isBiggerThanMd = useMediaQuery(useTheme().breakpoints.up('md'));\n\n return (\n // marginBottom={-1} counteracts the marginBottom={1} on every variable input.\n // The margin on the inputs is for spacing between inputs, but is not meant to add space to bottom of the container.\n <Box marginBottom={-1} data-testid=\"variable-list\">\n <AppBar\n color=\"inherit\"\n position={isSticky ? 'fixed' : 'static'}\n elevation={isSticky ? 4 : 0}\n sx={{ backgroundColor: 'inherit', ...props.sx }}\n >\n <Box\n display=\"flex\"\n justifyContent=\"space-between\"\n sx={{\n flexDirection: isBiggerThanMd ? 'row' : 'column',\n }}\n >\n <Box\n display=\"flex\"\n flexWrap={!isSticky && isBiggerThanMd ? 'wrap' : 'nowrap'}\n maxWidth={isSticky || !isBiggerThanMd ? '100vw' : '100%'}\n
|
|
1
|
+
{"version":3,"sources":["../../../src/components/DashboardStickyToolbar/DashboardStickyToolbar.tsx"],"sourcesContent":["// Copyright 2024 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { ReactElement, useState } from 'react';\nimport {\n AppBar,\n Box,\n IconButton,\n Stack,\n SxProps,\n Theme,\n useMediaQuery,\n useScrollTrigger,\n useTheme,\n} from '@mui/material';\nimport PinOutline from 'mdi-material-ui/PinOutline';\nimport PinOffOutline from 'mdi-material-ui/PinOffOutline';\nimport { TimeRangeControls } from '@perses-dev/plugin-system';\nimport { VariableList } from '../Variables';\n\ninterface DashboardStickyToolbarProps {\n initialVariableIsSticky?: boolean;\n sx?: SxProps<Theme>;\n}\n\nexport function DashboardStickyToolbar(props: DashboardStickyToolbarProps): ReactElement {\n const [isPin, setIsPin] = useState(props.initialVariableIsSticky);\n\n const scrollTrigger = useScrollTrigger({ disableHysteresis: true });\n const isSticky = scrollTrigger && props.initialVariableIsSticky && isPin;\n\n const isBiggerThanMd = useMediaQuery(useTheme().breakpoints.up('md'));\n\n return (\n // marginBottom={-1} counteracts the marginBottom={1} on every variable input.\n // The margin on the inputs is for spacing between inputs, but is not meant to add space to bottom of the container.\n <Box marginBottom={-1} data-testid=\"variable-list\">\n <AppBar\n color=\"inherit\"\n position={isSticky ? 'fixed' : 'static'}\n elevation={isSticky ? 4 : 0}\n sx={{ backgroundColor: 'inherit', ...props.sx }}\n >\n <Box\n display=\"flex\"\n justifyContent=\"space-between\"\n sx={{\n flexDirection: isBiggerThanMd ? 'row' : 'column',\n }}\n >\n <Box\n display=\"flex\"\n flexWrap={!isSticky && isBiggerThanMd ? 'wrap' : 'nowrap'}\n maxWidth={isSticky || !isBiggerThanMd ? '100vw' : '100%'}\n pt={1}\n pl={isSticky ? 1 : 0}\n mt={isSticky && isBiggerThanMd ? 0.5 : 0}\n ml={isSticky && isBiggerThanMd ? 0.5 : 0}\n sx={{\n overflowX: !isSticky && isBiggerThanMd ? 'hidden' : 'auto',\n // Firefox:\n scrollbarWidth: 'thin',\n // Safari and Chrome:\n '&::-webkit-scrollbar': {\n height: '8px',\n backgroundColor: (theme) => theme.palette.grey['300'],\n },\n '&::-webkit-scrollbar-thumb': {\n background: (theme) => theme.palette.grey['600'],\n },\n }}\n gap={1}\n >\n <VariableList />\n {props.initialVariableIsSticky && (\n <IconButton style={{ width: 'fit-content', height: 'fit-content' }} onClick={() => setIsPin(!isPin)}>\n {isPin ? <PinOutline /> : <PinOffOutline />}\n </IconButton>\n )}\n </Box>\n {isSticky && (\n <Stack\n m={isBiggerThanMd ? 1.5 : 1}\n mt={isBiggerThanMd ? 1.5 : 0}\n ml={isBiggerThanMd ? 1.5 : 'auto'}\n direction=\"row\"\n justifyContent=\"end\"\n >\n <TimeRangeControls />\n </Stack>\n )}\n </Box>\n </AppBar>\n </Box>\n );\n}\n"],"names":["useState","AppBar","Box","IconButton","Stack","useMediaQuery","useScrollTrigger","useTheme","PinOutline","PinOffOutline","TimeRangeControls","VariableList","DashboardStickyToolbar","props","isPin","setIsPin","initialVariableIsSticky","scrollTrigger","disableHysteresis","isSticky","isBiggerThanMd","breakpoints","up","marginBottom","data-testid","color","position","elevation","sx","backgroundColor","display","justifyContent","flexDirection","flexWrap","maxWidth","pt","pl","mt","ml","overflowX","scrollbarWidth","height","theme","palette","grey","background","gap","style","width","onClick","m","direction"],"mappings":"AAAA,oCAAoC;AACpC,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;;AAEjC,SAAuBA,QAAQ,QAAQ,QAAQ;AAC/C,SACEC,MAAM,EACNC,GAAG,EACHC,UAAU,EACVC,KAAK,EAGLC,aAAa,EACbC,gBAAgB,EAChBC,QAAQ,QACH,gBAAgB;AACvB,OAAOC,gBAAgB,6BAA6B;AACpD,OAAOC,mBAAmB,gCAAgC;AAC1D,SAASC,iBAAiB,QAAQ,4BAA4B;AAC9D,SAASC,YAAY,QAAQ,eAAe;AAO5C,OAAO,SAASC,uBAAuBC,KAAkC;IACvE,MAAM,CAACC,OAAOC,SAAS,GAAGf,SAASa,MAAMG,uBAAuB;IAEhE,MAAMC,gBAAgBX,iBAAiB;QAAEY,mBAAmB;IAAK;IACjE,MAAMC,WAAWF,iBAAiBJ,MAAMG,uBAAuB,IAAIF;IAEnE,MAAMM,iBAAiBf,cAAcE,WAAWc,WAAW,CAACC,EAAE,CAAC;IAE/D,OACE,8EAA8E;IAC9E,oHAAoH;kBACpH,KAACpB;QAAIqB,cAAc,CAAC;QAAGC,eAAY;kBACjC,cAAA,KAACvB;YACCwB,OAAM;YACNC,UAAUP,WAAW,UAAU;YAC/BQ,WAAWR,WAAW,IAAI;YAC1BS,IAAI;gBAAEC,iBAAiB;gBAAW,GAAGhB,MAAMe,EAAE;YAAC;sBAE9C,cAAA,MAAC1B;gBACC4B,SAAQ;gBACRC,gBAAe;gBACfH,IAAI;oBACFI,eAAeZ,iBAAiB,QAAQ;gBAC1C;;kCAEA,MAAClB;wBACC4B,SAAQ;wBACRG,UAAU,CAACd,YAAYC,iBAAiB,SAAS;wBACjDc,UAAUf,YAAY,CAACC,iBAAiB,UAAU;wBAClDe,IAAI;wBACJC,IAAIjB,WAAW,IAAI;wBACnBkB,IAAIlB,YAAYC,iBAAiB,MAAM;wBACvCkB,IAAInB,YAAYC,iBAAiB,MAAM;wBACvCQ,IAAI;4BACFW,WAAW,CAACpB,YAAYC,iBAAiB,WAAW;4BACpD,WAAW;4BACXoB,gBAAgB;4BAChB,qBAAqB;4BACrB,wBAAwB;gCACtBC,QAAQ;gCACRZ,iBAAiB,CAACa,QAAUA,MAAMC,OAAO,CAACC,IAAI,CAAC,MAAM;4BACvD;4BACA,8BAA8B;gCAC5BC,YAAY,CAACH,QAAUA,MAAMC,OAAO,CAACC,IAAI,CAAC,MAAM;4BAClD;wBACF;wBACAE,KAAK;;0CAEL,KAACnC;4BACAE,MAAMG,uBAAuB,kBAC5B,KAACb;gCAAW4C,OAAO;oCAAEC,OAAO;oCAAeP,QAAQ;gCAAc;gCAAGQ,SAAS,IAAMlC,SAAS,CAACD;0CAC1FA,sBAAQ,KAACN,gCAAgB,KAACC;;;;oBAIhCU,0BACC,KAACf;wBACC8C,GAAG9B,iBAAiB,MAAM;wBAC1BiB,IAAIjB,iBAAiB,MAAM;wBAC3BkB,IAAIlB,iBAAiB,MAAM;wBAC3B+B,WAAU;wBACVpB,gBAAe;kCAEf,cAAA,KAACrB;;;;;;AAOf"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DeletePanelGroupDialog.d.ts","sourceRoot":"","sources":["../../../src/components/DeletePanelGroupDialog/DeletePanelGroupDialog.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAa,YAAY,EAAE,MAAM,OAAO,CAAC;AAKhD,eAAO,MAAM,sBAAsB,QAAO,
|
|
1
|
+
{"version":3,"file":"DeletePanelGroupDialog.d.ts","sourceRoot":"","sources":["../../../src/components/DeletePanelGroupDialog/DeletePanelGroupDialog.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAa,YAAY,EAAE,MAAM,OAAO,CAAC;AAKhD,eAAO,MAAM,sBAAsB,QAAO,YAmCzC,CAAC"}
|
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
// See the License for the specific language governing permissions and
|
|
12
12
|
// limitations under the License.
|
|
13
13
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
14
|
-
import {
|
|
15
|
-
import
|
|
14
|
+
import { Dialog } from '@perses-dev/components';
|
|
15
|
+
import { Button } from '@mui/material';
|
|
16
16
|
import { useDeletePanelGroupDialog, useViewPanel } from '../../context';
|
|
17
17
|
export const DeletePanelGroupDialog = ()=>{
|
|
18
18
|
const { deletePanelGroupDialog, closeDeletePanelGroupDialog, deletePanelGroup } = useDeletePanelGroupDialog();
|
|
@@ -30,23 +30,13 @@ export const DeletePanelGroupDialog = ()=>{
|
|
|
30
30
|
return /*#__PURE__*/ _jsxs(Dialog, {
|
|
31
31
|
open: deletePanelGroupDialog !== undefined,
|
|
32
32
|
children: [
|
|
33
|
-
/*#__PURE__*/ _jsx(
|
|
33
|
+
/*#__PURE__*/ _jsx(Dialog.Header, {
|
|
34
34
|
children: "Delete Panel Group"
|
|
35
35
|
}),
|
|
36
|
-
/*#__PURE__*/ _jsx(IconButton, {
|
|
37
|
-
"aria-label": "Close",
|
|
38
|
-
onClick: ()=>closeDeletePanelGroupDialog(),
|
|
39
|
-
sx: (theme)=>({
|
|
40
|
-
position: 'absolute',
|
|
41
|
-
top: theme.spacing(0.5),
|
|
42
|
-
right: theme.spacing(0.5)
|
|
43
|
-
}),
|
|
44
|
-
children: /*#__PURE__*/ _jsx(CloseIcon, {})
|
|
45
|
-
}),
|
|
46
36
|
/*#__PURE__*/ _jsxs("form", {
|
|
47
37
|
onSubmit: handleDelete,
|
|
48
38
|
children: [
|
|
49
|
-
/*#__PURE__*/ _jsxs(
|
|
39
|
+
/*#__PURE__*/ _jsxs(Dialog.Content, {
|
|
50
40
|
dividers: true,
|
|
51
41
|
sx: {
|
|
52
42
|
width: '500px'
|
|
@@ -57,7 +47,7 @@ export const DeletePanelGroupDialog = ()=>{
|
|
|
57
47
|
"? This will delete all the panels within the group."
|
|
58
48
|
]
|
|
59
49
|
}),
|
|
60
|
-
/*#__PURE__*/ _jsxs(
|
|
50
|
+
/*#__PURE__*/ _jsxs(Dialog.Actions, {
|
|
61
51
|
children: [
|
|
62
52
|
/*#__PURE__*/ _jsx(Button, {
|
|
63
53
|
variant: "contained",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/DeletePanelGroupDialog/DeletePanelGroupDialog.tsx"],"sourcesContent":["// Copyright 2023 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { FormEvent, ReactElement } from 'react';\nimport {
|
|
1
|
+
{"version":3,"sources":["../../../src/components/DeletePanelGroupDialog/DeletePanelGroupDialog.tsx"],"sourcesContent":["// Copyright 2023 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { FormEvent, ReactElement } from 'react';\nimport { Dialog } from '@perses-dev/components';\nimport { Button } from '@mui/material';\nimport { useDeletePanelGroupDialog, useViewPanel } from '../../context';\n\nexport const DeletePanelGroupDialog = (): ReactElement => {\n const { deletePanelGroupDialog, closeDeletePanelGroupDialog, deletePanelGroup } = useDeletePanelGroupDialog();\n const { setViewPanel } = useViewPanel();\n const panelGroupId = deletePanelGroupDialog?.panelGroupId;\n\n const handleDelete = (e: FormEvent): void => {\n e.preventDefault();\n if (panelGroupId === undefined) {\n throw new Error('group index is undefined');\n }\n deletePanelGroup(panelGroupId);\n closeDeletePanelGroupDialog();\n setViewPanel(undefined);\n };\n\n return (\n <Dialog open={deletePanelGroupDialog !== undefined}>\n <Dialog.Header>Delete Panel Group</Dialog.Header>\n\n <form onSubmit={handleDelete}>\n <Dialog.Content dividers sx={{ width: '500px' }}>\n Are you sure you want to delete {deletePanelGroupDialog?.panelGroupName ?? 'panel group'}? This will delete\n all the panels within the group.\n </Dialog.Content>\n <Dialog.Actions>\n <Button variant=\"contained\" type=\"submit\">\n Delete\n </Button>\n <Button variant=\"outlined\" color=\"secondary\" onClick={() => closeDeletePanelGroupDialog()}>\n Cancel\n </Button>\n </Dialog.Actions>\n </form>\n </Dialog>\n );\n};\n"],"names":["Dialog","Button","useDeletePanelGroupDialog","useViewPanel","DeletePanelGroupDialog","deletePanelGroupDialog","closeDeletePanelGroupDialog","deletePanelGroup","setViewPanel","panelGroupId","handleDelete","e","preventDefault","undefined","Error","open","Header","form","onSubmit","Content","dividers","sx","width","panelGroupName","Actions","variant","type","color","onClick"],"mappings":"AAAA,oCAAoC;AACpC,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;;AAGjC,SAASA,MAAM,QAAQ,yBAAyB;AAChD,SAASC,MAAM,QAAQ,gBAAgB;AACvC,SAASC,yBAAyB,EAAEC,YAAY,QAAQ,gBAAgB;AAExE,OAAO,MAAMC,yBAAyB;IACpC,MAAM,EAAEC,sBAAsB,EAAEC,2BAA2B,EAAEC,gBAAgB,EAAE,GAAGL;IAClF,MAAM,EAAEM,YAAY,EAAE,GAAGL;IACzB,MAAMM,eAAeJ,wBAAwBI;IAE7C,MAAMC,eAAe,CAACC;QACpBA,EAAEC,cAAc;QAChB,IAAIH,iBAAiBI,WAAW;YAC9B,MAAM,IAAIC,MAAM;QAClB;QACAP,iBAAiBE;QACjBH;QACAE,aAAaK;IACf;IAEA,qBACE,MAACb;QAAOe,MAAMV,2BAA2BQ;;0BACvC,KAACb,OAAOgB,MAAM;0BAAC;;0BAEf,MAACC;gBAAKC,UAAUR;;kCACd,MAACV,OAAOmB,OAAO;wBAACC,QAAQ;wBAACC,IAAI;4BAAEC,OAAO;wBAAQ;;4BAAG;4BACdjB,wBAAwBkB,kBAAkB;4BAAc;;;kCAG3F,MAACvB,OAAOwB,OAAO;;0CACb,KAACvB;gCAAOwB,SAAQ;gCAAYC,MAAK;0CAAS;;0CAG1C,KAACzB;gCAAOwB,SAAQ;gCAAWE,OAAM;gCAAYC,SAAS,IAAMtB;0CAA+B;;;;;;;;AAOrG,EAAE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GridItemContent.d.ts","sourceRoot":"","sources":["../../../src/components/GridLayout/GridItemContent.tsx"],"names":[],"mappings":"AAgBA,OAAc,EAAE,YAAY,EAAqB,MAAM,OAAO,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAA6D,MAAM,eAAe,CAAC;AAC5G,OAAO,EAAqB,YAAY,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"GridItemContent.d.ts","sourceRoot":"","sources":["../../../src/components/GridLayout/GridItemContent.tsx"],"names":[],"mappings":"AAgBA,OAAc,EAAE,YAAY,EAAqB,MAAM,OAAO,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAA6D,MAAM,eAAe,CAAC;AAC5G,OAAO,EAAqB,YAAY,EAAE,MAAM,UAAU,CAAC;AAI3D,MAAM,WAAW,oBAAoB;IACnC,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,GAAG,YAAY,CAmGzE"}
|
|
@@ -11,13 +11,14 @@
|
|
|
11
11
|
// See the License for the specific language governing permissions and
|
|
12
12
|
// limitations under the License.
|
|
13
13
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
14
|
-
import { Box
|
|
14
|
+
import { Box } from '@mui/material';
|
|
15
15
|
import { useInView } from 'react-intersection-observer';
|
|
16
|
-
import { DataQueriesProvider,
|
|
16
|
+
import { DataQueriesProvider, usePlugin, useSuggestedStepMs } from '@perses-dev/plugin-system';
|
|
17
17
|
import React, { useMemo, useState } from 'react';
|
|
18
18
|
import { useEditMode, usePanel, usePanelActions, useViewPanelGroup } from '../../context';
|
|
19
19
|
import { Panel } from '../Panel';
|
|
20
20
|
import { isPanelGroupItemIdEqual } from '../../context/DashboardProvider/panel-group-slice';
|
|
21
|
+
import { QueryViewerDialog } from '../QueryViewerDialog';
|
|
21
22
|
/**
|
|
22
23
|
* Resolves the reference to panel content in a GridItemDefinition and renders the panel.
|
|
23
24
|
*/ export function GridItemContent(props) {
|
|
@@ -73,38 +74,6 @@ import { isPanelGroupItemIdEqual } from '../../context/DashboardProvider/panel-g
|
|
|
73
74
|
};
|
|
74
75
|
});
|
|
75
76
|
const pluginQueryOptions = typeof plugin?.queryOptions === 'function' ? plugin?.queryOptions(panelDefinition.spec.plugin.spec) : plugin?.queryOptions;
|
|
76
|
-
const queryRows = useMemo(()=>{
|
|
77
|
-
if (!queries?.length) return null;
|
|
78
|
-
const queryItems = [];
|
|
79
|
-
queries.forEach((query, index)=>{
|
|
80
|
-
if (query?.spec?.plugin?.kind && query?.kind) {
|
|
81
|
-
queryItems.push(/*#__PURE__*/ _jsxs(React.Fragment, {
|
|
82
|
-
children: [
|
|
83
|
-
/*#__PURE__*/ _jsx(PluginSpecEditor, {
|
|
84
|
-
value: query.spec.plugin.spec,
|
|
85
|
-
pluginSelection: {
|
|
86
|
-
kind: query.spec.plugin.kind,
|
|
87
|
-
type: query.kind
|
|
88
|
-
},
|
|
89
|
-
onChange: ()=>{},
|
|
90
|
-
isReadonly: true
|
|
91
|
-
}),
|
|
92
|
-
index < queries.length - 1 && /*#__PURE__*/ _jsx(Divider, {
|
|
93
|
-
sx: {
|
|
94
|
-
my: 2
|
|
95
|
-
}
|
|
96
|
-
})
|
|
97
|
-
]
|
|
98
|
-
}, `query-${index}`));
|
|
99
|
-
}
|
|
100
|
-
});
|
|
101
|
-
return queryItems;
|
|
102
|
-
}, [
|
|
103
|
-
queries
|
|
104
|
-
]);
|
|
105
|
-
const onCloseHandler = ()=>{
|
|
106
|
-
setOpenQueryViewer(false);
|
|
107
|
-
};
|
|
108
77
|
return /*#__PURE__*/ _jsxs(Box, {
|
|
109
78
|
ref: ref,
|
|
110
79
|
sx: {
|
|
@@ -112,38 +81,6 @@ import { isPanelGroupItemIdEqual } from '../../context/DashboardProvider/panel-g
|
|
|
112
81
|
height: '100%'
|
|
113
82
|
},
|
|
114
83
|
children: [
|
|
115
|
-
/*#__PURE__*/ _jsxs(Dialog, {
|
|
116
|
-
fullWidth: true,
|
|
117
|
-
PaperProps: {
|
|
118
|
-
sx: {
|
|
119
|
-
margin: '10px',
|
|
120
|
-
width: 'calc(100% - 20px)'
|
|
121
|
-
}
|
|
122
|
-
},
|
|
123
|
-
maxWidth: "lg",
|
|
124
|
-
open: openQueryViewer,
|
|
125
|
-
children: [
|
|
126
|
-
/*#__PURE__*/ _jsx(DialogTitle, {
|
|
127
|
-
children: "Query Viewer"
|
|
128
|
-
}),
|
|
129
|
-
/*#__PURE__*/ _jsx(DialogContent, {
|
|
130
|
-
children: /*#__PURE__*/ _jsx(Box, {
|
|
131
|
-
sx: {
|
|
132
|
-
padding: '5px'
|
|
133
|
-
},
|
|
134
|
-
children: queryRows
|
|
135
|
-
})
|
|
136
|
-
}),
|
|
137
|
-
/*#__PURE__*/ _jsx(DialogActions, {
|
|
138
|
-
children: /*#__PURE__*/ _jsx(Button, {
|
|
139
|
-
variant: "outlined",
|
|
140
|
-
onClick: onCloseHandler,
|
|
141
|
-
color: "primary",
|
|
142
|
-
children: "Close"
|
|
143
|
-
})
|
|
144
|
-
})
|
|
145
|
-
]
|
|
146
|
-
}),
|
|
147
84
|
/*#__PURE__*/ _jsx(DataQueriesProvider, {
|
|
148
85
|
definitions: definitions,
|
|
149
86
|
options: {
|
|
@@ -161,6 +98,11 @@ import { isPanelGroupItemIdEqual } from '../../context/DashboardProvider/panel-g
|
|
|
161
98
|
panelOptions: props.panelOptions,
|
|
162
99
|
panelGroupItemId: panelGroupItemId
|
|
163
100
|
})
|
|
101
|
+
}),
|
|
102
|
+
/*#__PURE__*/ _jsx(QueryViewerDialog, {
|
|
103
|
+
open: openQueryViewer,
|
|
104
|
+
queryDefinitions: queryDefinitions,
|
|
105
|
+
onClose: ()=>setOpenQueryViewer(false)
|
|
164
106
|
})
|
|
165
107
|
]
|
|
166
108
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/GridLayout/GridItemContent.tsx"],"sourcesContent":["// Copyright 2023 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { Box, Button, Dialog, DialogActions, DialogContent, DialogTitle, Divider } from '@mui/material';\nimport { useInView } from 'react-intersection-observer';\nimport { DataQueriesProvider, PluginSpecEditor, usePlugin, useSuggestedStepMs } from '@perses-dev/plugin-system';\nimport React, { ReactElement, useMemo, useState } from 'react';\nimport { PanelGroupItemId, useEditMode, usePanel, usePanelActions, useViewPanelGroup } from '../../context';\nimport { Panel, PanelProps, PanelOptions } from '../Panel';\nimport { isPanelGroupItemIdEqual } from '../../context/DashboardProvider/panel-group-slice';\n\nexport interface GridItemContentProps {\n panelGroupItemId: PanelGroupItemId;\n width: number; // necessary for determining the suggested step ms\n panelOptions?: PanelOptions;\n}\n\n/**\n * Resolves the reference to panel content in a GridItemDefinition and renders the panel.\n */\nexport function GridItemContent(props: GridItemContentProps): ReactElement {\n const { panelGroupItemId, width } = props;\n const panelDefinition = usePanel(panelGroupItemId);\n\n const {\n spec: { queries },\n } = panelDefinition;\n\n const { isEditMode } = useEditMode();\n const { openEditPanel, openDeletePanelDialog, duplicatePanel, viewPanel } = usePanelActions(panelGroupItemId);\n const viewPanelGroupItemId = useViewPanelGroup();\n const { ref, inView } = useInView({\n threshold: 0.2, // we have the flexibility to adjust this threshold to trigger queries slightly earlier or later based on performance\n initialInView: false,\n triggerOnce: true,\n });\n\n const [openQueryViewer, setOpenQueryViewer] = useState(false);\n\n const viewQueriesHandler = useMemo(() => {\n return isEditMode || !queries?.length\n ? undefined\n : {\n onClick: (): void => {\n setOpenQueryViewer(true);\n },\n };\n }, [isEditMode, queries]);\n\n const readHandlers = {\n isPanelViewed: isPanelGroupItemIdEqual(viewPanelGroupItemId, panelGroupItemId),\n onViewPanelClick: function (): void {\n if (viewPanelGroupItemId === undefined) {\n viewPanel(panelGroupItemId);\n } else {\n viewPanel(undefined);\n }\n },\n };\n\n // Provide actions to the panel when in edit mode\n let editHandlers: PanelProps['editHandlers'] = undefined;\n if (isEditMode) {\n editHandlers = {\n onEditPanelClick: openEditPanel,\n onDuplicatePanelClick: duplicatePanel,\n onDeletePanelClick: openDeletePanelDialog,\n };\n }\n\n // map TimeSeriesQueryDefinition to Definition<UnknownSpec>\n const suggestedStepMs = useSuggestedStepMs(width);\n\n const { data: plugin } = usePlugin('Panel', panelDefinition.spec.plugin.kind);\n\n const queryDefinitions = queries ?? [];\n const definitions = queryDefinitions.map((query) => {\n return {\n kind: query.spec.plugin.kind,\n spec: query.spec.plugin.spec,\n };\n });\n\n const pluginQueryOptions =\n typeof plugin?.queryOptions === 'function'\n ? plugin?.queryOptions(panelDefinition.spec.plugin.spec)\n : plugin?.queryOptions;\n\n const queryRows = useMemo(() => {\n if (!queries?.length) return null;\n\n const queryItems: ReactElement[] = [];\n queries.forEach((query, index) => {\n if (query?.spec?.plugin?.kind && query?.kind) {\n queryItems.push(\n <React.Fragment key={`query-${index}`}>\n <PluginSpecEditor\n value={query.spec.plugin.spec}\n pluginSelection={{ kind: query.spec.plugin.kind, type: query.kind }}\n onChange={(): void => {}}\n isReadonly\n />\n {index < queries.length - 1 && <Divider sx={{ my: 2 }} />}\n </React.Fragment>\n );\n }\n });\n\n return queryItems;\n }, [queries]);\n\n const onCloseHandler = (): void => {\n setOpenQueryViewer(false);\n };\n\n return (\n <Box\n ref={ref}\n sx={{\n width: '100%',\n height: '100%',\n }}\n >\n <Dialog\n fullWidth\n PaperProps={{\n sx: {\n margin: '10px',\n width: 'calc(100% - 20px)',\n },\n }}\n maxWidth=\"lg\"\n open={openQueryViewer}\n >\n <DialogTitle>Query Viewer</DialogTitle>\n <DialogContent>\n <Box sx={{ padding: '5px' }}>{queryRows}</Box>\n </DialogContent>\n <DialogActions>\n <Button variant=\"outlined\" onClick={onCloseHandler} color=\"primary\">\n Close\n </Button>\n </DialogActions>\n </Dialog>\n <DataQueriesProvider\n definitions={definitions}\n options={{ suggestedStepMs, ...pluginQueryOptions }}\n queryOptions={{ enabled: inView }}\n >\n {inView && (\n <Panel\n definition={panelDefinition}\n readHandlers={readHandlers}\n editHandlers={editHandlers}\n viewQueriesHandler={viewQueriesHandler}\n panelOptions={props.panelOptions}\n panelGroupItemId={panelGroupItemId}\n />\n )}\n </DataQueriesProvider>\n </Box>\n );\n}\n"],"names":["Box","Button","Dialog","DialogActions","DialogContent","DialogTitle","Divider","useInView","DataQueriesProvider","PluginSpecEditor","usePlugin","useSuggestedStepMs","React","useMemo","useState","useEditMode","usePanel","usePanelActions","useViewPanelGroup","Panel","isPanelGroupItemIdEqual","GridItemContent","props","panelGroupItemId","width","panelDefinition","spec","queries","isEditMode","openEditPanel","openDeletePanelDialog","duplicatePanel","viewPanel","viewPanelGroupItemId","ref","inView","threshold","initialInView","triggerOnce","openQueryViewer","setOpenQueryViewer","viewQueriesHandler","length","undefined","onClick","readHandlers","isPanelViewed","onViewPanelClick","editHandlers","onEditPanelClick","onDuplicatePanelClick","onDeletePanelClick","suggestedStepMs","data","plugin","kind","queryDefinitions","definitions","map","query","pluginQueryOptions","queryOptions","queryRows","queryItems","forEach","index","push","Fragment","value","pluginSelection","type","onChange","isReadonly","sx","my","onCloseHandler","height","fullWidth","PaperProps","margin","maxWidth","open","padding","variant","color","options","enabled","definition","panelOptions"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/components/GridLayout/GridItemContent.tsx"],"sourcesContent":["// Copyright 2023 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { Box } from '@mui/material';\nimport { useInView } from 'react-intersection-observer';\nimport { DataQueriesProvider, usePlugin, useSuggestedStepMs } from '@perses-dev/plugin-system';\nimport React, { ReactElement, useMemo, useState } from 'react';\nimport { PanelGroupItemId, useEditMode, usePanel, usePanelActions, useViewPanelGroup } from '../../context';\nimport { Panel, PanelProps, PanelOptions } from '../Panel';\nimport { isPanelGroupItemIdEqual } from '../../context/DashboardProvider/panel-group-slice';\nimport { QueryViewerDialog } from '../QueryViewerDialog';\n\nexport interface GridItemContentProps {\n panelGroupItemId: PanelGroupItemId;\n width: number; // necessary for determining the suggested step ms\n panelOptions?: PanelOptions;\n}\n\n/**\n * Resolves the reference to panel content in a GridItemDefinition and renders the panel.\n */\nexport function GridItemContent(props: GridItemContentProps): ReactElement {\n const { panelGroupItemId, width } = props;\n const panelDefinition = usePanel(panelGroupItemId);\n\n const {\n spec: { queries },\n } = panelDefinition;\n\n const { isEditMode } = useEditMode();\n const { openEditPanel, openDeletePanelDialog, duplicatePanel, viewPanel } = usePanelActions(panelGroupItemId);\n const viewPanelGroupItemId = useViewPanelGroup();\n const { ref, inView } = useInView({\n threshold: 0.2, // we have the flexibility to adjust this threshold to trigger queries slightly earlier or later based on performance\n initialInView: false,\n triggerOnce: true,\n });\n\n const [openQueryViewer, setOpenQueryViewer] = useState(false);\n\n const viewQueriesHandler = useMemo(() => {\n return isEditMode || !queries?.length\n ? undefined\n : {\n onClick: (): void => {\n setOpenQueryViewer(true);\n },\n };\n }, [isEditMode, queries]);\n\n const readHandlers = {\n isPanelViewed: isPanelGroupItemIdEqual(viewPanelGroupItemId, panelGroupItemId),\n onViewPanelClick: function (): void {\n if (viewPanelGroupItemId === undefined) {\n viewPanel(panelGroupItemId);\n } else {\n viewPanel(undefined);\n }\n },\n };\n\n // Provide actions to the panel when in edit mode\n let editHandlers: PanelProps['editHandlers'] = undefined;\n if (isEditMode) {\n editHandlers = {\n onEditPanelClick: openEditPanel,\n onDuplicatePanelClick: duplicatePanel,\n onDeletePanelClick: openDeletePanelDialog,\n };\n }\n\n // map TimeSeriesQueryDefinition to Definition<UnknownSpec>\n const suggestedStepMs = useSuggestedStepMs(width);\n\n const { data: plugin } = usePlugin('Panel', panelDefinition.spec.plugin.kind);\n\n const queryDefinitions = queries ?? [];\n const definitions = queryDefinitions.map((query) => {\n return {\n kind: query.spec.plugin.kind,\n spec: query.spec.plugin.spec,\n };\n });\n\n const pluginQueryOptions =\n typeof plugin?.queryOptions === 'function'\n ? plugin?.queryOptions(panelDefinition.spec.plugin.spec)\n : plugin?.queryOptions;\n\n return (\n <Box\n ref={ref}\n sx={{\n width: '100%',\n height: '100%',\n }}\n >\n <DataQueriesProvider\n definitions={definitions}\n options={{ suggestedStepMs, ...pluginQueryOptions }}\n queryOptions={{ enabled: inView }}\n >\n {inView && (\n <Panel\n definition={panelDefinition}\n readHandlers={readHandlers}\n editHandlers={editHandlers}\n viewQueriesHandler={viewQueriesHandler}\n panelOptions={props.panelOptions}\n panelGroupItemId={panelGroupItemId}\n />\n )}\n </DataQueriesProvider>\n <QueryViewerDialog\n open={openQueryViewer}\n queryDefinitions={queryDefinitions}\n onClose={() => setOpenQueryViewer(false)}\n />\n </Box>\n );\n}\n"],"names":["Box","useInView","DataQueriesProvider","usePlugin","useSuggestedStepMs","React","useMemo","useState","useEditMode","usePanel","usePanelActions","useViewPanelGroup","Panel","isPanelGroupItemIdEqual","QueryViewerDialog","GridItemContent","props","panelGroupItemId","width","panelDefinition","spec","queries","isEditMode","openEditPanel","openDeletePanelDialog","duplicatePanel","viewPanel","viewPanelGroupItemId","ref","inView","threshold","initialInView","triggerOnce","openQueryViewer","setOpenQueryViewer","viewQueriesHandler","length","undefined","onClick","readHandlers","isPanelViewed","onViewPanelClick","editHandlers","onEditPanelClick","onDuplicatePanelClick","onDeletePanelClick","suggestedStepMs","data","plugin","kind","queryDefinitions","definitions","map","query","pluginQueryOptions","queryOptions","sx","height","options","enabled","definition","panelOptions","open","onClose"],"mappings":"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"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { DashboardResource, EphemeralDashboardResource } from '@perses-dev/core';
|
|
2
2
|
import { ReactElement, ReactNode } from 'react';
|
|
3
|
+
import type { BlockerFunction } from '@remix-run/router';
|
|
3
4
|
export interface LeaveDialogProps {
|
|
4
|
-
isBlocked: boolean;
|
|
5
|
+
isBlocked: BlockerFunction | boolean;
|
|
5
6
|
message: string;
|
|
6
7
|
}
|
|
7
8
|
export declare function Prompt({ isBlocked, message }: LeaveDialogProps): ReactElement;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LeaveDialog.d.ts","sourceRoot":"","sources":["../../../src/components/LeaveDialog/LeaveDialog.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAE,iBAAiB,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,SAAS,EAAa,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"LeaveDialog.d.ts","sourceRoot":"","sources":["../../../src/components/LeaveDialog/LeaveDialog.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAE,iBAAiB,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,SAAS,EAAa,MAAM,OAAO,CAAC;AAG3D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAQzD,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,eAAe,GAAG,OAAO,CAAC;IACrC,OAAO,EAAE,MAAM,CAAC;CACjB;AAMD,wBAAgB,MAAM,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE,gBAAgB,GAAG,YAAY,CA4B7E;AAKD,wBAAgB,WAAW,CAAC,EAC1B,QAAQ,EACR,OAAO,GACR,EAAE;IACD,QAAQ,EAAE,iBAAiB,GAAG,0BAA0B,GAAG,SAAS,CAAC;IACrE,OAAO,EAAE,iBAAiB,GAAG,0BAA0B,CAAC;CACzD,GAAG,SAAS,CAYZ"}
|
|
@@ -52,8 +52,17 @@ const handleRouteChange = (event)=>{
|
|
|
52
52
|
/*
|
|
53
53
|
* LeaveDialog prompts the user with a confirmation dialog when they attempt to leave the page with unsaved changes.
|
|
54
54
|
*/ export function LeaveDialog({ original, current }) {
|
|
55
|
+
const handleIsBlocked = (ctx)=>{
|
|
56
|
+
if (JSON.stringify(original) !== JSON.stringify(current)) {
|
|
57
|
+
// Only block navigation if the pathname is changing (=> ignore search params changes)
|
|
58
|
+
if (ctx.currentLocation.pathname !== ctx.nextLocation.pathname) {
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return false;
|
|
63
|
+
};
|
|
55
64
|
return /*#__PURE__*/ _jsx(Prompt, {
|
|
56
|
-
isBlocked:
|
|
65
|
+
isBlocked: handleIsBlocked,
|
|
57
66
|
message: "You have unsaved changes, are you sure you want to leave?"
|
|
58
67
|
});
|
|
59
68
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/LeaveDialog/LeaveDialog.tsx"],"sourcesContent":["// Copyright 2025 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { DashboardResource, EphemeralDashboardResource } from '@perses-dev/core';\nimport { ReactElement, ReactNode, useEffect } from 'react';\nimport { useBlocker } from 'react-router-dom';\nimport { DiscardChangesConfirmationDialog } from '@perses-dev/components';\n\nconst handleRouteChange = (event: BeforeUnloadEvent): string => {\n event.preventDefault();\n event.returnValue = ''; // Required for Chrome\n return ''; // Required for other browsers\n};\n\nexport interface LeaveDialogProps {\n isBlocked: boolean;\n message: string;\n}\n\n/*\n * Prompt component uses the useBlocker hook to block react-router navigation when there are unsaved changes.\n * It also listens to the beforeunload event to show a browser confirmation dialog when the user tries to close the tab, refresh the page or change url manually.\n */\nexport function Prompt({ isBlocked, message }: LeaveDialogProps): ReactElement {\n const blocker = useBlocker(isBlocked);\n const isBlockedState = blocker.state === 'blocked';\n const isProceedingState = blocker.state === 'proceeding';\n\n useEffect(() => {\n if (isBlocked) {\n window.addEventListener('beforeunload', handleRouteChange);\n } else {\n window.removeEventListener('beforeunload', handleRouteChange);\n }\n\n return (): void => {\n window.removeEventListener('beforeunload', handleRouteChange);\n };\n }, [blocker, isBlocked, isBlockedState]);\n\n const handleDiscardChanges = (): void => blocker.proceed?.();\n const handleCancel = (): void => blocker.reset?.();\n\n return (\n <DiscardChangesConfirmationDialog\n description={message}\n isOpen={isBlockedState || isProceedingState}\n onDiscardChanges={handleDiscardChanges}\n onCancel={handleCancel}\n />\n );\n}\n\n/*\n * LeaveDialog prompts the user with a confirmation dialog when they attempt to leave the page with unsaved changes.\n */\nexport function LeaveDialog({\n original,\n current,\n}: {\n original: DashboardResource | EphemeralDashboardResource | undefined;\n current: DashboardResource | EphemeralDashboardResource;\n}): ReactNode {\n
|
|
1
|
+
{"version":3,"sources":["../../../src/components/LeaveDialog/LeaveDialog.tsx"],"sourcesContent":["// Copyright 2025 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { DashboardResource, EphemeralDashboardResource } from '@perses-dev/core';\nimport { ReactElement, ReactNode, useEffect } from 'react';\nimport { useBlocker } from 'react-router-dom';\nimport { DiscardChangesConfirmationDialog } from '@perses-dev/components';\nimport type { BlockerFunction } from '@remix-run/router';\n\nconst handleRouteChange = (event: BeforeUnloadEvent): string => {\n event.preventDefault();\n event.returnValue = ''; // Required for Chrome\n return ''; // Required for other browsers\n};\n\nexport interface LeaveDialogProps {\n isBlocked: BlockerFunction | boolean;\n message: string;\n}\n\n/*\n * Prompt component uses the useBlocker hook to block react-router navigation when there are unsaved changes.\n * It also listens to the beforeunload event to show a browser confirmation dialog when the user tries to close the tab, refresh the page or change url manually.\n */\nexport function Prompt({ isBlocked, message }: LeaveDialogProps): ReactElement {\n const blocker = useBlocker(isBlocked);\n const isBlockedState = blocker.state === 'blocked';\n const isProceedingState = blocker.state === 'proceeding';\n\n useEffect(() => {\n if (isBlocked) {\n window.addEventListener('beforeunload', handleRouteChange);\n } else {\n window.removeEventListener('beforeunload', handleRouteChange);\n }\n\n return (): void => {\n window.removeEventListener('beforeunload', handleRouteChange);\n };\n }, [blocker, isBlocked, isBlockedState]);\n\n const handleDiscardChanges = (): void => blocker.proceed?.();\n const handleCancel = (): void => blocker.reset?.();\n\n return (\n <DiscardChangesConfirmationDialog\n description={message}\n isOpen={isBlockedState || isProceedingState}\n onDiscardChanges={handleDiscardChanges}\n onCancel={handleCancel}\n />\n );\n}\n\n/*\n * LeaveDialog prompts the user with a confirmation dialog when they attempt to leave the page with unsaved changes.\n */\nexport function LeaveDialog({\n original,\n current,\n}: {\n original: DashboardResource | EphemeralDashboardResource | undefined;\n current: DashboardResource | EphemeralDashboardResource;\n}): ReactNode {\n const handleIsBlocked: BlockerFunction = (ctx) => {\n if (JSON.stringify(original) !== JSON.stringify(current)) {\n // Only block navigation if the pathname is changing (=> ignore search params changes)\n if (ctx.currentLocation.pathname !== ctx.nextLocation.pathname) {\n return true;\n }\n }\n return false;\n };\n\n return <Prompt isBlocked={handleIsBlocked} message=\"You have unsaved changes, are you sure you want to leave?\" />;\n}\n"],"names":["useEffect","useBlocker","DiscardChangesConfirmationDialog","handleRouteChange","event","preventDefault","returnValue","Prompt","isBlocked","message","blocker","isBlockedState","state","isProceedingState","window","addEventListener","removeEventListener","handleDiscardChanges","proceed","handleCancel","reset","description","isOpen","onDiscardChanges","onCancel","LeaveDialog","original","current","handleIsBlocked","ctx","JSON","stringify","currentLocation","pathname","nextLocation"],"mappings":"AAAA,oCAAoC;AACpC,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;;AAGjC,SAAkCA,SAAS,QAAQ,QAAQ;AAC3D,SAASC,UAAU,QAAQ,mBAAmB;AAC9C,SAASC,gCAAgC,QAAQ,yBAAyB;AAG1E,MAAMC,oBAAoB,CAACC;IACzBA,MAAMC,cAAc;IACpBD,MAAME,WAAW,GAAG,IAAI,sBAAsB;IAC9C,OAAO,IAAI,8BAA8B;AAC3C;AAOA;;;CAGC,GACD,OAAO,SAASC,OAAO,EAAEC,SAAS,EAAEC,OAAO,EAAoB;IAC7D,MAAMC,UAAUT,WAAWO;IAC3B,MAAMG,iBAAiBD,QAAQE,KAAK,KAAK;IACzC,MAAMC,oBAAoBH,QAAQE,KAAK,KAAK;IAE5CZ,UAAU;QACR,IAAIQ,WAAW;YACbM,OAAOC,gBAAgB,CAAC,gBAAgBZ;QAC1C,OAAO;YACLW,OAAOE,mBAAmB,CAAC,gBAAgBb;QAC7C;QAEA,OAAO;YACLW,OAAOE,mBAAmB,CAAC,gBAAgBb;QAC7C;IACF,GAAG;QAACO;QAASF;QAAWG;KAAe;IAEvC,MAAMM,uBAAuB,IAAYP,QAAQQ,OAAO;IACxD,MAAMC,eAAe,IAAYT,QAAQU,KAAK;IAE9C,qBACE,KAAClB;QACCmB,aAAaZ;QACba,QAAQX,kBAAkBE;QAC1BU,kBAAkBN;QAClBO,UAAUL;;AAGhB;AAEA;;CAEC,GACD,OAAO,SAASM,YAAY,EAC1BC,QAAQ,EACRC,OAAO,EAIR;IACC,MAAMC,kBAAmC,CAACC;QACxC,IAAIC,KAAKC,SAAS,CAACL,cAAcI,KAAKC,SAAS,CAACJ,UAAU;YACxD,sFAAsF;YACtF,IAAIE,IAAIG,eAAe,CAACC,QAAQ,KAAKJ,IAAIK,YAAY,CAACD,QAAQ,EAAE;gBAC9D,OAAO;YACT;QACF;QACA,OAAO;IACT;IAEA,qBAAO,KAAC1B;QAAOC,WAAWoB;QAAiBnB,SAAQ;;AACrD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PanelEditorForm.d.ts","sourceRoot":"","sources":["../../../src/components/PanelDrawer/PanelEditorForm.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAE,YAAY,EAA4C,MAAM,OAAO,CAAC;AAE/E,OAAO,EAAE,MAAM,EAA+C,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"PanelEditorForm.d.ts","sourceRoot":"","sources":["../../../src/components/PanelDrawer/PanelEditorForm.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAE,YAAY,EAA4C,MAAM,OAAO,CAAC;AAE/E,OAAO,EAAE,MAAM,EAA+C,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAqB1G,MAAM,WAAW,oBAAoB;IACnC,aAAa,EAAE,iBAAiB,CAAC;IACjC,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,CAAC,MAAM,EAAE,iBAAiB,KAAK,IAAI,CAAC;IAC5C,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,GAAG,YAAY,CAkPzE;AAED;;GAEG;AACH,eAAO,MAAM,iBAAiB,sBAAsB,CAAC"}
|