mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-11 21:09:09 +08:00
Feat(FE): Delete Query, Save Layout (#306)
* feat: Delete Query functionality is added * feat: save layout is updated
This commit is contained in:
parent
cc91242e9a
commit
ea5b40c7ea
@ -1,3 +1,6 @@
|
|||||||
|
/* eslint-disable react/display-name */
|
||||||
|
import { SaveFilled } from '@ant-design/icons';
|
||||||
|
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';
|
||||||
@ -10,7 +13,13 @@ import { v4 } from 'uuid';
|
|||||||
|
|
||||||
import AddWidget from './AddWidget';
|
import AddWidget from './AddWidget';
|
||||||
import Graph from './Graph';
|
import Graph from './Graph';
|
||||||
import { Card, CardContainer, ReactGridLayout } from './styles';
|
import {
|
||||||
|
Button,
|
||||||
|
ButtonContainer,
|
||||||
|
Card,
|
||||||
|
CardContainer,
|
||||||
|
ReactGridLayout,
|
||||||
|
} from './styles';
|
||||||
|
|
||||||
const GridGraph = (): JSX.Element => {
|
const GridGraph = (): JSX.Element => {
|
||||||
const { push } = useHistory();
|
const { push } = useHistory();
|
||||||
@ -19,6 +28,12 @@ const GridGraph = (): JSX.Element => {
|
|||||||
const { dashboards, loading } = useSelector<AppState, DashboardReducer>(
|
const { dashboards, loading } = useSelector<AppState, DashboardReducer>(
|
||||||
(state) => state.dashboards,
|
(state) => state.dashboards,
|
||||||
);
|
);
|
||||||
|
const [saveLayoutState, setSaveLayoutState] = useState<State>({
|
||||||
|
loading: false,
|
||||||
|
error: false,
|
||||||
|
errorMessage: '',
|
||||||
|
payload: [],
|
||||||
|
});
|
||||||
|
|
||||||
const [selectedDashboard] = dashboards;
|
const [selectedDashboard] = dashboards;
|
||||||
const { data } = selectedDashboard;
|
const { data } = selectedDashboard;
|
||||||
@ -31,16 +46,12 @@ const GridGraph = (): JSX.Element => {
|
|||||||
const isMounted = useRef(true);
|
const isMounted = useRef(true);
|
||||||
const isDeleted = useRef(false);
|
const isDeleted = useRef(false);
|
||||||
|
|
||||||
useEffect(() => {
|
const getPreLayouts: () => LayoutProps[] = useCallback(() => {
|
||||||
if (
|
|
||||||
loading === false &&
|
|
||||||
(isMounted.current === true || isDeleted.current === true)
|
|
||||||
) {
|
|
||||||
const getPreLayouts = (): LayoutProps[] => {
|
|
||||||
if (widgets === undefined) {
|
if (widgets === undefined) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data.layout === undefined) {
|
||||||
return widgets.map((e, index) => {
|
return widgets.map((e, index) => {
|
||||||
return {
|
return {
|
||||||
h: 2,
|
h: 2,
|
||||||
@ -48,16 +59,28 @@ const GridGraph = (): JSX.Element => {
|
|||||||
y: Infinity,
|
y: Infinity,
|
||||||
i: (index + 1).toString(),
|
i: (index + 1).toString(),
|
||||||
x: (index % 2) * 6,
|
x: (index % 2) * 6,
|
||||||
// eslint-disable-next-line react/display-name
|
|
||||||
Component: (): JSX.Element => (
|
Component: (): JSX.Element => (
|
||||||
<Graph isDeleted={isDeleted} widget={widgets[index]} />
|
<Graph isDeleted={isDeleted} widget={widgets[index]} />
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
};
|
} else {
|
||||||
|
return data.layout.map((e, index) => ({
|
||||||
|
...e,
|
||||||
|
y: 0,
|
||||||
|
Component: (): JSX.Element => (
|
||||||
|
<Graph isDeleted={isDeleted} widget={widgets[index]} />
|
||||||
|
),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}, [widgets, data.layout]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (
|
||||||
|
loading === false &&
|
||||||
|
(isMounted.current === true || isDeleted.current === true)
|
||||||
|
) {
|
||||||
const preLayouts = getPreLayouts();
|
const preLayouts = getPreLayouts();
|
||||||
|
|
||||||
setLayout(() => [
|
setLayout(() => [
|
||||||
...preLayouts,
|
...preLayouts,
|
||||||
{
|
{
|
||||||
@ -67,6 +90,10 @@ const GridGraph = (): JSX.Element => {
|
|||||||
w: 6,
|
w: 6,
|
||||||
h: 2,
|
h: 2,
|
||||||
Component: AddWidgetWrapper,
|
Component: AddWidgetWrapper,
|
||||||
|
maxW: 6,
|
||||||
|
isDraggable: false,
|
||||||
|
isResizable: false,
|
||||||
|
isBounded: true,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@ -74,7 +101,7 @@ const GridGraph = (): JSX.Element => {
|
|||||||
return (): void => {
|
return (): void => {
|
||||||
isMounted.current = false;
|
isMounted.current = false;
|
||||||
};
|
};
|
||||||
}, [widgets, layouts.length, AddWidgetWrapper, loading]);
|
}, [widgets, layouts.length, AddWidgetWrapper, loading, getPreLayouts]);
|
||||||
|
|
||||||
const onDropHandler = useCallback(
|
const onDropHandler = useCallback(
|
||||||
(allLayouts: Layout[], currectLayout: Layout, event: DragEvent) => {
|
(allLayouts: Layout[], currectLayout: Layout, event: DragEvent) => {
|
||||||
@ -88,11 +115,66 @@ const GridGraph = (): JSX.Element => {
|
|||||||
[pathname, push],
|
[pathname, push],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const onLayoutSaveHanlder = async (): Promise<void> => {
|
||||||
|
setSaveLayoutState((state) => ({
|
||||||
|
...state,
|
||||||
|
error: false,
|
||||||
|
errorMessage: '',
|
||||||
|
loading: true,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const response = await updateDashboardApi({
|
||||||
|
title: data.title,
|
||||||
|
uuid: selectedDashboard.uuid,
|
||||||
|
description: data.description,
|
||||||
|
name: data.name,
|
||||||
|
tags: data.tags,
|
||||||
|
widgets: data.widgets,
|
||||||
|
layout: saveLayoutState.payload.filter((e) => e.maxW === undefined),
|
||||||
|
});
|
||||||
|
if (response.statusCode === 200) {
|
||||||
|
setSaveLayoutState((state) => ({
|
||||||
|
...state,
|
||||||
|
error: false,
|
||||||
|
errorMessage: '',
|
||||||
|
loading: false,
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
setSaveLayoutState((state) => ({
|
||||||
|
...state,
|
||||||
|
error: true,
|
||||||
|
errorMessage: response.error || 'Something went wrong',
|
||||||
|
loading: false,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onLayoutChangeHandler = (layout: Layout[]): void => {
|
||||||
|
setSaveLayoutState({
|
||||||
|
loading: false,
|
||||||
|
error: false,
|
||||||
|
errorMessage: '',
|
||||||
|
payload: layout,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
if (layouts.length === 0) {
|
if (layouts.length === 0) {
|
||||||
return <Spinner height="40vh" size="large" tip="Loading..." />;
|
return <Spinner height="40vh" size="large" tip="Loading..." />;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
|
<ButtonContainer>
|
||||||
|
<Button
|
||||||
|
loading={saveLayoutState.loading}
|
||||||
|
onClick={onLayoutSaveHanlder}
|
||||||
|
icon={<SaveFilled />}
|
||||||
|
danger={saveLayoutState.error}
|
||||||
|
>
|
||||||
|
Save Layout
|
||||||
|
</Button>
|
||||||
|
</ButtonContainer>
|
||||||
|
|
||||||
<ReactGridLayout
|
<ReactGridLayout
|
||||||
isResizable
|
isResizable
|
||||||
isDraggable
|
isDraggable
|
||||||
@ -103,6 +185,7 @@ const GridGraph = (): JSX.Element => {
|
|||||||
isDroppable
|
isDroppable
|
||||||
useCSSTransforms
|
useCSSTransforms
|
||||||
onDrop={onDropHandler}
|
onDrop={onDropHandler}
|
||||||
|
onLayoutChange={onLayoutChangeHandler}
|
||||||
>
|
>
|
||||||
{layouts.map(({ Component, ...rest }, index) => {
|
{layouts.map(({ Component, ...rest }, index) => {
|
||||||
const widget = (widgets || [])[index] || {};
|
const widget = (widgets || [])[index] || {};
|
||||||
@ -120,6 +203,7 @@ const GridGraph = (): JSX.Element => {
|
|||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</ReactGridLayout>
|
</ReactGridLayout>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -127,4 +211,11 @@ interface LayoutProps extends Layout {
|
|||||||
Component: () => JSX.Element;
|
Component: () => JSX.Element;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface State {
|
||||||
|
loading: boolean;
|
||||||
|
error: boolean;
|
||||||
|
payload: Layout[];
|
||||||
|
errorMessage: string;
|
||||||
|
}
|
||||||
|
|
||||||
export default memo(GridGraph);
|
export default memo(GridGraph);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Card as CardComponent } from 'antd';
|
import { Button as ButtonComponent, Card as CardComponent } from 'antd';
|
||||||
import RGL, { WidthProvider } from 'react-grid-layout';
|
import RGL, { WidthProvider } from 'react-grid-layout';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
|
||||||
@ -40,3 +40,17 @@ export const ReactGridLayout = styled(ReactGridLayoutComponent)`
|
|||||||
margin-top: 1rem;
|
margin-top: 1rem;
|
||||||
position: relative;
|
position: relative;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const ButtonContainer = styled.div`
|
||||||
|
display: flex;
|
||||||
|
justify-content: end;
|
||||||
|
margin-top: 1rem;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const Button = styled(ButtonComponent)`
|
||||||
|
&&& {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import GridGraphLayout from 'container/GridGraphLayout';
|
import GridGraphLayout from 'container/GridGraphLayout';
|
||||||
import ComponentsSlider from 'container/NewDashboard/ComponentsSlider';
|
import ComponentsSlider from 'container/NewDashboard/ComponentsSlider';
|
||||||
import React, { useCallback, useState } from 'react';
|
import React from 'react';
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
import { AppState } from 'store/reducers';
|
import { AppState } from 'store/reducers';
|
||||||
import DashboardReducer from 'types/reducer/dashboards';
|
import DashboardReducer from 'types/reducer/dashboards';
|
||||||
|
@ -5,10 +5,10 @@ import GridGraphs from './GridGraphs';
|
|||||||
|
|
||||||
const NewDashboard = (): JSX.Element => {
|
const NewDashboard = (): JSX.Element => {
|
||||||
return (
|
return (
|
||||||
<div>
|
<>
|
||||||
<Description />
|
<Description />
|
||||||
<GridGraphs />
|
<GridGraphs />
|
||||||
</div>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Divider } from 'antd';
|
import { Button, Divider } from 'antd';
|
||||||
import Input from 'components/Input';
|
import Input from 'components/Input';
|
||||||
import { timePreferance } from 'container/NewWidget/RightContainer/timeItems';
|
import { timePreferance } from 'container/NewWidget/RightContainer/timeItems';
|
||||||
import React, { useCallback, useState } from 'react';
|
import React, { useCallback, useState } from 'react';
|
||||||
@ -6,19 +6,22 @@ import { connect } from 'react-redux';
|
|||||||
import { useLocation } from 'react-router';
|
import { useLocation } from 'react-router';
|
||||||
import { bindActionCreators, Dispatch } from 'redux';
|
import { bindActionCreators, Dispatch } from 'redux';
|
||||||
import { ThunkDispatch } from 'redux-thunk';
|
import { ThunkDispatch } from 'redux-thunk';
|
||||||
|
import { DeleteQuery } from 'store/actions';
|
||||||
import {
|
import {
|
||||||
UpdateQuery,
|
UpdateQuery,
|
||||||
UpdateQueryProps,
|
UpdateQueryProps,
|
||||||
} from 'store/actions/dashboard/updateQuery';
|
} from 'store/actions/dashboard/updateQuery';
|
||||||
import AppActions from 'types/actions';
|
import AppActions from 'types/actions';
|
||||||
|
import { DeleteQueryProps } from 'types/actions/dashboard';
|
||||||
|
|
||||||
import { Container, InputContainer } from './styles';
|
import { Container, InputContainer, QueryWrapper } from './styles';
|
||||||
|
|
||||||
const Query = ({
|
const Query = ({
|
||||||
currentIndex,
|
currentIndex,
|
||||||
preLegend,
|
preLegend,
|
||||||
preQuery,
|
preQuery,
|
||||||
updateQuery,
|
updateQuery,
|
||||||
|
deleteQuery,
|
||||||
}: QueryProps): JSX.Element => {
|
}: QueryProps): JSX.Element => {
|
||||||
const [promqlQuery, setPromqlQuery] = useState(preQuery);
|
const [promqlQuery, setPromqlQuery] = useState(preQuery);
|
||||||
const [legendFormat, setLegendFormat] = useState(preLegend);
|
const [legendFormat, setLegendFormat] = useState(preLegend);
|
||||||
@ -43,8 +46,17 @@ const Query = ({
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onDeleteQueryHandler = (): void => {
|
||||||
|
deleteQuery({
|
||||||
|
widgetId: widgetId,
|
||||||
|
currentIndex,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
<Container>
|
<Container>
|
||||||
|
<QueryWrapper>
|
||||||
<InputContainer>
|
<InputContainer>
|
||||||
<Input
|
<Input
|
||||||
onChangeHandler={(event): void =>
|
onChangeHandler={(event): void =>
|
||||||
@ -68,8 +80,13 @@ const Query = ({
|
|||||||
onBlur={(): void => onBlurHandler()}
|
onBlur={(): void => onBlurHandler()}
|
||||||
/>
|
/>
|
||||||
</InputContainer>
|
</InputContainer>
|
||||||
<Divider />
|
</QueryWrapper>
|
||||||
|
|
||||||
|
<Button onClick={onDeleteQueryHandler}>Delete</Button>
|
||||||
</Container>
|
</Container>
|
||||||
|
|
||||||
|
<Divider />
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -77,12 +94,16 @@ interface DispatchProps {
|
|||||||
updateQuery: (
|
updateQuery: (
|
||||||
props: UpdateQueryProps,
|
props: UpdateQueryProps,
|
||||||
) => (dispatch: Dispatch<AppActions>) => void;
|
) => (dispatch: Dispatch<AppActions>) => void;
|
||||||
|
deleteQuery: (
|
||||||
|
props: DeleteQueryProps,
|
||||||
|
) => (dispatch: Dispatch<AppActions>) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapDispatchToProps = (
|
const mapDispatchToProps = (
|
||||||
dispatch: ThunkDispatch<unknown, unknown, AppActions>,
|
dispatch: ThunkDispatch<unknown, unknown, AppActions>,
|
||||||
): DispatchProps => ({
|
): DispatchProps => ({
|
||||||
updateQuery: bindActionCreators(UpdateQuery, dispatch),
|
updateQuery: bindActionCreators(UpdateQuery, dispatch),
|
||||||
|
deleteQuery: bindActionCreators(DeleteQuery, dispatch),
|
||||||
});
|
});
|
||||||
|
|
||||||
interface QueryProps extends DispatchProps {
|
interface QueryProps extends DispatchProps {
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { PlusOutlined } from '@ant-design/icons';
|
import { PlusOutlined } from '@ant-design/icons';
|
||||||
import Spinner from 'components/Spinner';
|
|
||||||
import { timePreferance } from 'container/NewWidget/RightContainer/timeItems';
|
import { timePreferance } from 'container/NewWidget/RightContainer/timeItems';
|
||||||
import React, { useCallback, useMemo } from 'react';
|
import React, { useCallback, useMemo } from 'react';
|
||||||
import { connect, useSelector } from 'react-redux';
|
import { connect, useSelector } from 'react-redux';
|
||||||
@ -47,12 +46,8 @@ const QuerySection = ({
|
|||||||
});
|
});
|
||||||
}, [createQuery, urlQuery]);
|
}, [createQuery, urlQuery]);
|
||||||
|
|
||||||
if (query.length === 0) {
|
|
||||||
return <Spinner size="small" height="30vh" tip="Loading..." />;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<>
|
||||||
{query.map((e, index) => (
|
{query.map((e, index) => (
|
||||||
<Query
|
<Query
|
||||||
currentIndex={index}
|
currentIndex={index}
|
||||||
@ -66,7 +61,7 @@ const QuerySection = ({
|
|||||||
<QueryButton onClick={queryOnClickHandler} icon={<PlusOutlined />}>
|
<QueryButton onClick={queryOnClickHandler} icon={<PlusOutlined />}>
|
||||||
Query
|
Query
|
||||||
</QueryButton>
|
</QueryButton>
|
||||||
</div>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ export const InputContainer = styled.div`
|
|||||||
|
|
||||||
export const Container = styled.div`
|
export const Container = styled.div`
|
||||||
margin-top: 1rem;
|
margin-top: 1rem;
|
||||||
|
display: flex;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const QueryButton = styled(Button)`
|
export const QueryButton = styled(Button)`
|
||||||
@ -15,3 +16,11 @@ export const QueryButton = styled(Button)`
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const QueryWrapper = styled.div`
|
||||||
|
width: 100%; // parent need to 100%
|
||||||
|
|
||||||
|
> div {
|
||||||
|
width: 95%; // each child is taking 95% of the parent
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
17
frontend/src/store/actions/dashboard/deleteQuery.ts
Normal file
17
frontend/src/store/actions/dashboard/deleteQuery.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { Dispatch } from 'redux';
|
||||||
|
import AppActions from 'types/actions';
|
||||||
|
import { DeleteQueryProps } from 'types/actions/dashboard';
|
||||||
|
|
||||||
|
export const DeleteQuery = (
|
||||||
|
props: DeleteQueryProps,
|
||||||
|
): ((dispatch: Dispatch<AppActions>) => void) => {
|
||||||
|
return (dispatch: Dispatch<AppActions>): void => {
|
||||||
|
dispatch({
|
||||||
|
type: 'DELETE_QUERY',
|
||||||
|
payload: {
|
||||||
|
currentIndex: props.currentIndex,
|
||||||
|
widgetId: props.widgetId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
};
|
@ -1,6 +1,7 @@
|
|||||||
export * from './applySettingsToPanel';
|
export * from './applySettingsToPanel';
|
||||||
export * from './createQuery';
|
export * from './createQuery';
|
||||||
export * from './deleteDashboard';
|
export * from './deleteDashboard';
|
||||||
|
export * from './deleteQuery';
|
||||||
export * from './getAllDashboard';
|
export * from './getAllDashboard';
|
||||||
export * from './getDashboard';
|
export * from './getDashboard';
|
||||||
export * from './toggleEditMode';
|
export * from './toggleEditMode';
|
||||||
|
@ -4,6 +4,7 @@ import {
|
|||||||
CREATE_NEW_QUERY,
|
CREATE_NEW_QUERY,
|
||||||
DashboardActions,
|
DashboardActions,
|
||||||
DELETE_DASHBOARD_SUCCESS,
|
DELETE_DASHBOARD_SUCCESS,
|
||||||
|
DELETE_QUERY,
|
||||||
DELETE_WIDGET_SUCCESS,
|
DELETE_WIDGET_SUCCESS,
|
||||||
GET_ALL_DASHBOARD_ERROR,
|
GET_ALL_DASHBOARD_ERROR,
|
||||||
GET_ALL_DASHBOARD_LOADING_START,
|
GET_ALL_DASHBOARD_LOADING_START,
|
||||||
@ -438,6 +439,50 @@ const dashboard = (
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case DELETE_QUERY: {
|
||||||
|
const { currentIndex, widgetId } = action.payload;
|
||||||
|
const { dashboards } = state;
|
||||||
|
const [selectedDashboard] = dashboards;
|
||||||
|
const { data } = selectedDashboard;
|
||||||
|
const { widgets = [] } = data;
|
||||||
|
|
||||||
|
const selectedWidgetIndex = widgets.findIndex((e) => e.id === widgetId) || 0;
|
||||||
|
|
||||||
|
const preWidget = widgets?.slice(0, selectedWidgetIndex) || [];
|
||||||
|
const afterWidget =
|
||||||
|
widgets?.slice(
|
||||||
|
selectedWidgetIndex + 1, // this is never undefined
|
||||||
|
widgets.length,
|
||||||
|
) || [];
|
||||||
|
|
||||||
|
const selectedWidget = widgets[selectedWidgetIndex];
|
||||||
|
|
||||||
|
const query = selectedWidget.query;
|
||||||
|
|
||||||
|
const preQuery = query.slice(0, currentIndex);
|
||||||
|
const postQuery = query.slice(currentIndex + 1, query.length);
|
||||||
|
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
dashboards: [
|
||||||
|
{
|
||||||
|
...selectedDashboard,
|
||||||
|
data: {
|
||||||
|
...data,
|
||||||
|
widgets: [
|
||||||
|
...preWidget,
|
||||||
|
{
|
||||||
|
...selectedWidget,
|
||||||
|
query: [...preQuery, ...postQuery],
|
||||||
|
},
|
||||||
|
...afterWidget,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,8 @@ export const DELETE_WIDGET_ERROR = 'DELETE_WIDGET_ERROR';
|
|||||||
|
|
||||||
export const IS_ADD_WIDGET = 'IS_ADD_WIDGET';
|
export const IS_ADD_WIDGET = 'IS_ADD_WIDGET';
|
||||||
|
|
||||||
|
export const DELETE_QUERY = 'DELETE_QUERY';
|
||||||
|
|
||||||
interface GetDashboard {
|
interface GetDashboard {
|
||||||
type: typeof GET_DASHBOARD;
|
type: typeof GET_DASHBOARD;
|
||||||
payload: Dashboard;
|
payload: Dashboard;
|
||||||
@ -159,6 +161,16 @@ interface WidgetDeleteSuccess {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface DeleteQueryProps {
|
||||||
|
widgetId: string;
|
||||||
|
currentIndex: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DeleteQuery {
|
||||||
|
type: typeof DELETE_QUERY;
|
||||||
|
payload: DeleteQueryProps;
|
||||||
|
}
|
||||||
|
|
||||||
export type DashboardActions =
|
export type DashboardActions =
|
||||||
| GetDashboard
|
| GetDashboard
|
||||||
| UpdateDashboard
|
| UpdateDashboard
|
||||||
@ -177,4 +189,5 @@ export type DashboardActions =
|
|||||||
| SaveDashboardSuccess
|
| SaveDashboardSuccess
|
||||||
| WidgetDeleteSuccess
|
| WidgetDeleteSuccess
|
||||||
| IsAddWidget
|
| IsAddWidget
|
||||||
| UpdateQuery;
|
| UpdateQuery
|
||||||
|
| DeleteQuery;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { GRAPH_TYPES } from 'container/NewDashboard/ComponentsSlider';
|
import { GRAPH_TYPES } from 'container/NewDashboard/ComponentsSlider';
|
||||||
import { timePreferenceType } from 'container/NewWidget/RightContainer/timeItems';
|
import { timePreferenceType } from 'container/NewWidget/RightContainer/timeItems';
|
||||||
|
import { Layout } from 'react-grid-layout';
|
||||||
|
|
||||||
import { QueryData } from '../widgets/getQuery';
|
import { QueryData } from '../widgets/getQuery';
|
||||||
|
|
||||||
@ -19,6 +20,7 @@ export interface DashboardData {
|
|||||||
name?: string;
|
name?: string;
|
||||||
widgets?: Widgets[];
|
widgets?: Widgets[];
|
||||||
title: string;
|
title: string;
|
||||||
|
layout?: Layout[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Widgets {
|
export interface Widgets {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user