mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-09-22 23:53:12 +08:00
fix: save layout bug is resolved (#840)
* fix: save layout bug is resolved * chore: onClick is also added in the component slider * chore: dashboard Id is added * chore: non dashboard widget is filtered out * chore: panel layout stack issue is resolved
This commit is contained in:
parent
86bdb9a5ad
commit
c00f0f159b
@ -48,7 +48,7 @@ const GridCardGraph = ({
|
|||||||
(async (): Promise<void> => {
|
(async (): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
const getMaxMinTime = GetMaxMinTime({
|
const getMaxMinTime = GetMaxMinTime({
|
||||||
graphType: widget.panelTypes,
|
graphType: widget?.panelTypes,
|
||||||
maxTime,
|
maxTime,
|
||||||
minTime,
|
minTime,
|
||||||
});
|
});
|
||||||
@ -125,7 +125,7 @@ const GridCardGraph = ({
|
|||||||
[],
|
[],
|
||||||
);
|
);
|
||||||
|
|
||||||
const getModals = () => {
|
const getModals = (): JSX.Element => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Modal
|
<Modal
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
/* eslint-disable react/display-name */
|
/* eslint-disable react/display-name */
|
||||||
import { SaveFilled } from '@ant-design/icons';
|
import { SaveFilled } from '@ant-design/icons';
|
||||||
|
import { notification } from 'antd';
|
||||||
import updateDashboardApi from 'api/dashboard/update';
|
import updateDashboardApi from 'api/dashboard/update';
|
||||||
import Spinner from 'components/Spinner';
|
import Spinner from 'components/Spinner';
|
||||||
import { GRAPH_TYPES } from 'container/NewDashboard/ComponentsSlider';
|
import { GRAPH_TYPES } from 'container/NewDashboard/ComponentsSlider';
|
||||||
import React, { memo, useCallback, useEffect, useRef, useState } from 'react';
|
import React, { memo, useCallback, useEffect, useRef, useState } from 'react';
|
||||||
import { Layout } from 'react-grid-layout';
|
import { Layout } from 'react-grid-layout';
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
import { useHistory, useLocation } from 'react-router-dom';
|
|
||||||
import { AppState } from 'store/reducers';
|
import { AppState } from 'store/reducers';
|
||||||
import DashboardReducer from 'types/reducer/dashboards';
|
import DashboardReducer from 'types/reducer/dashboards';
|
||||||
import { v4 } from 'uuid';
|
import { v4 } from 'uuid';
|
||||||
@ -20,11 +20,9 @@ import {
|
|||||||
CardContainer,
|
CardContainer,
|
||||||
ReactGridLayout,
|
ReactGridLayout,
|
||||||
} from './styles';
|
} from './styles';
|
||||||
|
import { updateDashboard } from './utils';
|
||||||
|
|
||||||
const GridGraph = (): JSX.Element => {
|
const GridGraph = (): JSX.Element => {
|
||||||
const { push } = useHistory();
|
|
||||||
const { pathname } = useLocation();
|
|
||||||
|
|
||||||
const { dashboards, loading } = useSelector<AppState, DashboardReducer>(
|
const { dashboards, loading } = useSelector<AppState, DashboardReducer>(
|
||||||
(state) => state.dashboards,
|
(state) => state.dashboards,
|
||||||
);
|
);
|
||||||
@ -50,6 +48,7 @@ const GridGraph = (): JSX.Element => {
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// when the layout is not present
|
||||||
if (data.layout === undefined) {
|
if (data.layout === undefined) {
|
||||||
return widgets.map((e, index) => {
|
return widgets.map((e, index) => {
|
||||||
return {
|
return {
|
||||||
@ -69,17 +68,24 @@ const GridGraph = (): JSX.Element => {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
return data.layout.map((e, index) => ({
|
return data.layout
|
||||||
...e,
|
.filter((_, index) => widgets[index])
|
||||||
y: 0,
|
.map((e, index) => ({
|
||||||
Component: (): JSX.Element => (
|
...e,
|
||||||
<Graph
|
Component: (): JSX.Element => {
|
||||||
name={e.i + index}
|
if (widgets[index]) {
|
||||||
isDeleted={isDeleted}
|
return (
|
||||||
widget={widgets[index]}
|
<Graph
|
||||||
/>
|
name={e.i + index}
|
||||||
),
|
isDeleted={isDeleted}
|
||||||
}));
|
widget={widgets[index]}
|
||||||
|
yAxisUnit={widgets[index].yAxisUnit}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return <></>;
|
||||||
|
},
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
}, [widgets, data.layout]);
|
}, [widgets, data.layout]);
|
||||||
|
|
||||||
@ -89,21 +95,34 @@ const GridGraph = (): JSX.Element => {
|
|||||||
(isMounted.current === true || isDeleted.current === true)
|
(isMounted.current === true || isDeleted.current === true)
|
||||||
) {
|
) {
|
||||||
const preLayouts = getPreLayouts();
|
const preLayouts = getPreLayouts();
|
||||||
setLayout(() => [
|
setLayout(() => {
|
||||||
...preLayouts,
|
const getX = (): number => {
|
||||||
{
|
if (preLayouts && preLayouts?.length > 0) {
|
||||||
i: (preLayouts.length + 1).toString(),
|
const last = preLayouts[preLayouts?.length - 1];
|
||||||
x: (preLayouts.length % 2) * 6,
|
|
||||||
y: Infinity,
|
return (last.w + last.x) % 12;
|
||||||
w: 6,
|
}
|
||||||
h: 2,
|
return 0;
|
||||||
Component: AddWidgetWrapper,
|
};
|
||||||
maxW: 6,
|
|
||||||
isDraggable: false,
|
console.log({ x: getX() });
|
||||||
isResizable: false,
|
|
||||||
isBounded: true,
|
return [
|
||||||
},
|
...preLayouts,
|
||||||
]);
|
{
|
||||||
|
i: (preLayouts.length + 1).toString(),
|
||||||
|
x: getX(),
|
||||||
|
y: Infinity,
|
||||||
|
w: 6,
|
||||||
|
h: 2,
|
||||||
|
Component: AddWidgetWrapper,
|
||||||
|
maxW: 6,
|
||||||
|
isDraggable: false,
|
||||||
|
isResizable: false,
|
||||||
|
isBounded: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return (): void => {
|
return (): void => {
|
||||||
@ -112,18 +131,39 @@ const GridGraph = (): JSX.Element => {
|
|||||||
}, [widgets, layouts.length, AddWidgetWrapper, loading, getPreLayouts]);
|
}, [widgets, layouts.length, AddWidgetWrapper, loading, getPreLayouts]);
|
||||||
|
|
||||||
const onDropHandler = useCallback(
|
const onDropHandler = useCallback(
|
||||||
(allLayouts: Layout[], currectLayout: Layout, event: DragEvent) => {
|
async (allLayouts: Layout[], currentLayout: Layout, event: DragEvent) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
if (event.dataTransfer) {
|
if (event.dataTransfer) {
|
||||||
const graphType = event.dataTransfer.getData('text') as GRAPH_TYPES;
|
try {
|
||||||
const generateWidgetId = v4();
|
const graphType = event.dataTransfer.getData('text') as GRAPH_TYPES;
|
||||||
push(`${pathname}/new?graphType=${graphType}&widgetId=${generateWidgetId}`);
|
const generateWidgetId = v4();
|
||||||
|
|
||||||
|
await updateDashboard({
|
||||||
|
data,
|
||||||
|
generateWidgetId,
|
||||||
|
graphType,
|
||||||
|
selectedDashboard: selectedDashboard,
|
||||||
|
layout: allLayouts
|
||||||
|
.map((e, index) => ({
|
||||||
|
...e,
|
||||||
|
i: index.toString(),
|
||||||
|
// when a new element drops
|
||||||
|
w: e.i === '__dropping-elem__' ? 6 : e.w,
|
||||||
|
h: e.i === '__dropping-elem__' ? 2 : e.h,
|
||||||
|
}))
|
||||||
|
.filter((e) => e.maxW === undefined),
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
notification.error({
|
||||||
|
message: error.toString() || 'Something went wrong',
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[pathname, push],
|
[data, selectedDashboard],
|
||||||
);
|
);
|
||||||
|
|
||||||
const onLayoutSaveHanlder = async (): Promise<void> => {
|
const onLayoutSaveHandler = async (): Promise<void> => {
|
||||||
setSaveLayoutState((state) => ({
|
setSaveLayoutState((state) => ({
|
||||||
...state,
|
...state,
|
||||||
error: false,
|
error: false,
|
||||||
@ -175,7 +215,7 @@ const GridGraph = (): JSX.Element => {
|
|||||||
<ButtonContainer>
|
<ButtonContainer>
|
||||||
<Button
|
<Button
|
||||||
loading={saveLayoutState.loading}
|
loading={saveLayoutState.loading}
|
||||||
onClick={onLayoutSaveHanlder}
|
onClick={onLayoutSaveHandler}
|
||||||
icon={<SaveFilled />}
|
icon={<SaveFilled />}
|
||||||
danger={saveLayoutState.error}
|
danger={saveLayoutState.error}
|
||||||
>
|
>
|
||||||
@ -198,7 +238,7 @@ const GridGraph = (): JSX.Element => {
|
|||||||
{layouts.map(({ Component, ...rest }, index) => {
|
{layouts.map(({ Component, ...rest }, index) => {
|
||||||
const widget = (widgets || [])[index] || {};
|
const widget = (widgets || [])[index] || {};
|
||||||
|
|
||||||
const type = widget.panelTypes;
|
const type = widget?.panelTypes || 'TIME_SERIES';
|
||||||
|
|
||||||
const isQueryType = type === 'VALUE';
|
const isQueryType = type === 'VALUE';
|
||||||
|
|
||||||
|
66
frontend/src/container/GridGraphLayout/utils.ts
Normal file
66
frontend/src/container/GridGraphLayout/utils.ts
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
import { notification } from 'antd';
|
||||||
|
import updateDashboardApi from 'api/dashboard/update';
|
||||||
|
import { GRAPH_TYPES } from 'container/NewDashboard/ComponentsSlider';
|
||||||
|
import history from 'lib/history';
|
||||||
|
import { Layout } from 'react-grid-layout';
|
||||||
|
import { Dashboard } from 'types/api/dashboard/getAll';
|
||||||
|
|
||||||
|
export const updateDashboard = async ({
|
||||||
|
data,
|
||||||
|
graphType,
|
||||||
|
generateWidgetId,
|
||||||
|
layout,
|
||||||
|
selectedDashboard,
|
||||||
|
}: UpdateDashboardProps): Promise<void> => {
|
||||||
|
const response = await updateDashboardApi({
|
||||||
|
title: data.title,
|
||||||
|
uuid: selectedDashboard.uuid,
|
||||||
|
description: data.description,
|
||||||
|
name: data.name,
|
||||||
|
tags: data.tags,
|
||||||
|
widgets: [
|
||||||
|
...(data.widgets || []),
|
||||||
|
{
|
||||||
|
description: '',
|
||||||
|
id: generateWidgetId,
|
||||||
|
isStacked: false,
|
||||||
|
nullZeroValues: '',
|
||||||
|
opacity: '',
|
||||||
|
panelTypes: graphType,
|
||||||
|
query: [
|
||||||
|
{
|
||||||
|
query: '',
|
||||||
|
legend: '',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
queryData: {
|
||||||
|
data: [],
|
||||||
|
error: false,
|
||||||
|
errorMessage: '',
|
||||||
|
loading: false,
|
||||||
|
},
|
||||||
|
timePreferance: 'GLOBAL_TIME',
|
||||||
|
title: '',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
layout: layout,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.statusCode === 200) {
|
||||||
|
history.push(
|
||||||
|
`${history.location.pathname}/new?graphType=${graphType}&widgetId=${generateWidgetId}`,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
notification.error({
|
||||||
|
message: response.error || 'Something went wrong',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
interface UpdateDashboardProps {
|
||||||
|
data: Dashboard['data'];
|
||||||
|
graphType: GRAPH_TYPES;
|
||||||
|
generateWidgetId: string;
|
||||||
|
layout: Layout[];
|
||||||
|
selectedDashboard: Dashboard;
|
||||||
|
}
|
@ -1,37 +1,75 @@
|
|||||||
|
import { notification } from 'antd';
|
||||||
|
import { updateDashboard } from 'container/GridGraphLayout/utils';
|
||||||
import React, { useCallback } from 'react';
|
import React, { useCallback } from 'react';
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
import { useHistory, useLocation } from 'react-router';
|
|
||||||
import { AppState } from 'store/reducers';
|
import { AppState } from 'store/reducers';
|
||||||
import AppReducer from 'types/reducer/app';
|
import AppReducer from 'types/reducer/app';
|
||||||
|
import DashboardReducer from 'types/reducer/dashboards';
|
||||||
import { v4 } from 'uuid';
|
import { v4 } from 'uuid';
|
||||||
|
|
||||||
import menuItems, { ITEMS } from './menuItems';
|
import menuItems, { ITEMS } from './menuItems';
|
||||||
import { Card, Container, Text } from './styles';
|
import { Card, Container, Text } from './styles';
|
||||||
|
|
||||||
const DashboardGraphSlider = (): JSX.Element => {
|
const DashboardGraphSlider = (): JSX.Element => {
|
||||||
|
const { dashboards } = useSelector<AppState, DashboardReducer>(
|
||||||
|
(state) => state.dashboards,
|
||||||
|
);
|
||||||
|
|
||||||
|
const [selectedDashboard] = dashboards;
|
||||||
|
const { data } = selectedDashboard;
|
||||||
|
|
||||||
const onDragStartHandler: React.DragEventHandler<HTMLDivElement> = useCallback(
|
const onDragStartHandler: React.DragEventHandler<HTMLDivElement> = useCallback(
|
||||||
(event: React.DragEvent<HTMLDivElement>) => {
|
(event: React.DragEvent<HTMLDivElement>) => {
|
||||||
event.dataTransfer.setData('text/plain', event.currentTarget.id);
|
event.dataTransfer.setData('text/plain', event.currentTarget.id);
|
||||||
},
|
},
|
||||||
[],
|
[],
|
||||||
);
|
);
|
||||||
const { push } = useHistory();
|
|
||||||
const { pathname } = useLocation();
|
|
||||||
|
|
||||||
const onClickHandler = useCallback(
|
const onClickHandler = useCallback(
|
||||||
(name: ITEMS) => {
|
async (name: ITEMS) => {
|
||||||
const generateWidgetId = v4();
|
try {
|
||||||
push(`${pathname}/new?graphType=${name}&widgetId=${generateWidgetId}`);
|
const generateWidgetId = v4();
|
||||||
|
|
||||||
|
const getX = (): number => {
|
||||||
|
if (data.layout && data.layout?.length > 0) {
|
||||||
|
const lastIndexX = data.layout[data.layout?.length - 1];
|
||||||
|
return (lastIndexX.w + lastIndexX.x) % 12;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
await updateDashboard({
|
||||||
|
data,
|
||||||
|
generateWidgetId,
|
||||||
|
graphType: name,
|
||||||
|
layout: [
|
||||||
|
...(data.layout || []),
|
||||||
|
{
|
||||||
|
h: 2,
|
||||||
|
i: ((data.layout || [])?.length + 1).toString(),
|
||||||
|
w: 6,
|
||||||
|
x: getX(),
|
||||||
|
y: 0,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
selectedDashboard,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
notification.error({
|
||||||
|
message: 'Something went wrong',
|
||||||
|
});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
[push, pathname],
|
[data, selectedDashboard],
|
||||||
);
|
);
|
||||||
const { isDarkMode } = useSelector<AppState, AppReducer>((state) => state.app);
|
const { isDarkMode } = useSelector<AppState, AppReducer>((state) => state.app);
|
||||||
const fillColor: React.CSSProperties['color'] = isDarkMode ? 'white' : 'black';
|
const fillColor: React.CSSProperties['color'] = isDarkMode ? 'white' : 'black';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
{menuItems.map(({ name, Icon, display }) => (
|
{menuItems.map(({ name, Icon, display }) => (
|
||||||
<Card
|
<Card
|
||||||
onClick={(): void => onClickHandler(name)}
|
onClick={(): Promise<void> => onClickHandler(name)}
|
||||||
id={name}
|
id={name}
|
||||||
onDragStart={onDragStartHandler}
|
onDragStart={onDragStartHandler}
|
||||||
key={name}
|
key={name}
|
||||||
|
@ -13,7 +13,7 @@ const LeftContainer = ({
|
|||||||
}: LeftContainerProps): JSX.Element => {
|
}: LeftContainerProps): JSX.Element => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<WidgetGraph selectedGraph={selectedGraph} yAxisUnit={yAxisUnit}/>
|
<WidgetGraph selectedGraph={selectedGraph} yAxisUnit={yAxisUnit} />
|
||||||
|
|
||||||
<QueryContainer>
|
<QueryContainer>
|
||||||
<QuerySection selectedTime={selectedTime} />
|
<QuerySection selectedTime={selectedTime} />
|
||||||
|
@ -23,7 +23,7 @@ import {
|
|||||||
} from 'store/actions/dashboard/updateQuery';
|
} from 'store/actions/dashboard/updateQuery';
|
||||||
import { AppState } from 'store/reducers';
|
import { AppState } from 'store/reducers';
|
||||||
import AppActions from 'types/actions';
|
import AppActions from 'types/actions';
|
||||||
import { GlobalTime } from 'types/actions/globalTime';
|
import { Widgets } from 'types/api/dashboard/getAll';
|
||||||
import DashboardReducer from 'types/reducer/dashboards';
|
import DashboardReducer from 'types/reducer/dashboards';
|
||||||
import { GlobalReducer } from 'types/reducer/globalTime';
|
import { GlobalReducer } from 'types/reducer/globalTime';
|
||||||
|
|
||||||
@ -48,7 +48,7 @@ const NewWidget = ({
|
|||||||
const { dashboards } = useSelector<AppState, DashboardReducer>(
|
const { dashboards } = useSelector<AppState, DashboardReducer>(
|
||||||
(state) => state.dashboards,
|
(state) => state.dashboards,
|
||||||
);
|
);
|
||||||
const { maxTime, minTime, selectedTime: globalSelectedInterval } = useSelector<
|
const { selectedTime: globalSelectedInterval } = useSelector<
|
||||||
AppState,
|
AppState,
|
||||||
GlobalReducer
|
GlobalReducer
|
||||||
>((state) => state.globalTime);
|
>((state) => state.globalTime);
|
||||||
@ -77,7 +77,9 @@ const NewWidget = ({
|
|||||||
const [description, setDescription] = useState<string>(
|
const [description, setDescription] = useState<string>(
|
||||||
selectedWidget?.description || '',
|
selectedWidget?.description || '',
|
||||||
);
|
);
|
||||||
const [yAxisUnit, setYAxisUnit] = useState<string>(selectedWidget?.yAxisUnit || 'none');
|
const [yAxisUnit, setYAxisUnit] = useState<string>(
|
||||||
|
selectedWidget?.yAxisUnit || 'none',
|
||||||
|
);
|
||||||
|
|
||||||
const [stacked, setStacked] = useState<boolean>(
|
const [stacked, setStacked] = useState<boolean>(
|
||||||
selectedWidget?.isStacked || false,
|
selectedWidget?.isStacked || false,
|
||||||
@ -125,9 +127,10 @@ const NewWidget = ({
|
|||||||
saveSettingOfPanel,
|
saveSettingOfPanel,
|
||||||
selectedDashboard,
|
selectedDashboard,
|
||||||
dashboardId,
|
dashboardId,
|
||||||
|
yAxisUnit,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const onClickApplyHandler = () => {
|
const onClickApplyHandler = (): void => {
|
||||||
selectedWidget?.query.forEach((element, index) => {
|
selectedWidget?.query.forEach((element, index) => {
|
||||||
updateQuery({
|
updateQuery({
|
||||||
widgetId: selectedWidget?.id || '',
|
widgetId: selectedWidget?.id || '',
|
||||||
@ -146,7 +149,7 @@ const NewWidget = ({
|
|||||||
timePreferance: selectedTime.enum,
|
timePreferance: selectedTime.enum,
|
||||||
title,
|
title,
|
||||||
widgetId: selectedWidget?.id || '',
|
widgetId: selectedWidget?.id || '',
|
||||||
yAxisUnit
|
yAxisUnit,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -167,11 +170,10 @@ const NewWidget = ({
|
|||||||
}, [
|
}, [
|
||||||
selectedWidget?.query,
|
selectedWidget?.query,
|
||||||
selectedTime.enum,
|
selectedTime.enum,
|
||||||
maxTime,
|
|
||||||
minTime,
|
|
||||||
selectedWidget?.id,
|
selectedWidget?.id,
|
||||||
selectedGraph,
|
selectedGraph,
|
||||||
getQueryResults,
|
getQueryResults,
|
||||||
|
globalSelectedInterval,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -188,7 +190,11 @@ const NewWidget = ({
|
|||||||
|
|
||||||
<PanelContainer>
|
<PanelContainer>
|
||||||
<LeftContainerWrapper flex={5}>
|
<LeftContainerWrapper flex={5}>
|
||||||
<LeftContainer selectedTime={selectedTime} selectedGraph={selectedGraph} yAxisUnit={yAxisUnit}/>
|
<LeftContainer
|
||||||
|
selectedTime={selectedTime}
|
||||||
|
selectedGraph={selectedGraph}
|
||||||
|
yAxisUnit={yAxisUnit}
|
||||||
|
/>
|
||||||
</LeftContainerWrapper>
|
</LeftContainerWrapper>
|
||||||
|
|
||||||
<RightContainerWrapper flex={1}>
|
<RightContainerWrapper flex={1}>
|
||||||
@ -219,6 +225,7 @@ const NewWidget = ({
|
|||||||
|
|
||||||
export interface NewWidgetProps {
|
export interface NewWidgetProps {
|
||||||
selectedGraph: GRAPH_TYPES;
|
selectedGraph: GRAPH_TYPES;
|
||||||
|
yAxisUnit: Widgets['yAxisUnit'];
|
||||||
}
|
}
|
||||||
|
|
||||||
interface DispatchProps {
|
interface DispatchProps {
|
||||||
|
@ -55,6 +55,7 @@ export const SaveDashboard = ({
|
|||||||
];
|
];
|
||||||
|
|
||||||
const response = await updateDashboardApi({
|
const response = await updateDashboardApi({
|
||||||
|
...selectedDashboard.data,
|
||||||
uuid,
|
uuid,
|
||||||
// this is the data for the dashboard
|
// this is the data for the dashboard
|
||||||
title: selectedDashboard.data.title,
|
title: selectedDashboard.data.title,
|
||||||
@ -122,4 +123,5 @@ export interface SaveDashboardProps {
|
|||||||
nullZeroValues: Widgets['nullZeroValues'];
|
nullZeroValues: Widgets['nullZeroValues'];
|
||||||
widgetId: Widgets['id'];
|
widgetId: Widgets['id'];
|
||||||
dashboardId: string;
|
dashboardId: string;
|
||||||
|
yAxisUnit: Widgets['yAxisUnit'];
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,7 @@ export interface Widgets {
|
|||||||
}[];
|
}[];
|
||||||
};
|
};
|
||||||
stepSize?: number;
|
stepSize?: number;
|
||||||
|
yAxisUnit?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Query {
|
export interface Query {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user