refactor: query data field for widgets (#2839)

* refactor: query data field for widgets

* fix: query key index

* fix: remove queryData fields

* fix: remove rest queryData field

* fix: remove queryData from services

* fix: remove queryData in another places

---------

Co-authored-by: Palash Gupta <palashgdev@gmail.com>
This commit is contained in:
Yevhen Shevchenko 2023-06-07 15:27:33 +03:00 committed by GitHub
parent ef1bc0beec
commit 1770e6a157
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 248 additions and 474 deletions

View File

@ -1,3 +1,4 @@
export const REACT_QUERY_KEY = { export const REACT_QUERY_KEY = {
GET_ALL_LICENCES: 'GET_ALL_LICENCES', GET_ALL_LICENCES: 'GET_ALL_LICENCES',
GET_QUERY_RANGE: 'GET_QUERY_RANGE',
}; };

View File

@ -6,11 +6,10 @@ import GridGraphComponent from 'container/GridGraphComponent';
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 { Time } from 'container/TopNav/DateTimeSelection/config'; import { Time } from 'container/TopNav/DateTimeSelection/config';
import { useGetQueryRange } from 'hooks/queryBuilder/useGetQueryRange';
import getChartData from 'lib/getChartData'; import getChartData from 'lib/getChartData';
import { useMemo } from 'react'; import { useMemo } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useQuery } from 'react-query';
import { GetMetricQueryRange } from 'store/actions/dashboard/getQueryResults';
import { Query } from 'types/api/queryBuilder/queryBuilderData'; import { Query } from 'types/api/queryBuilder/queryBuilderData';
import { EQueryType } from 'types/common/dashboard'; import { EQueryType } from 'types/common/dashboard';
@ -26,9 +25,6 @@ export interface ChartPreviewProps {
threshold?: number | undefined; threshold?: number | undefined;
userQueryKey?: string; userQueryKey?: string;
} }
interface QueryResponseError {
message?: string;
}
function ChartPreview({ function ChartPreview({
name, name,
@ -76,39 +72,38 @@ function ChartPreview({
} }
}, [query]); }, [query]);
const queryResponse = useQuery({ const queryResponse = useGetQueryRange(
queryKey: [ {
'chartPreview', query: query || {
userQueryKey || JSON.stringify(query), queryType: EQueryType.QUERY_BUILDER,
selectedInterval, promql: [],
], builder: {
queryFn: () => queryFormulas: [],
GetMetricQueryRange({ queryData: [],
query: query || {
queryType: EQueryType.QUERY_BUILDER,
promql: [],
builder: {
queryFormulas: [],
queryData: [],
},
clickhouse_sql: [],
}, },
globalSelectedInterval: selectedInterval, clickhouse_sql: [],
graphType, },
selectedTime, globalSelectedInterval: selectedInterval,
}), graphType,
retry: false, selectedTime,
enabled: canQuery, },
}); {
queryKey: [
'chartPreview',
userQueryKey || JSON.stringify(query),
selectedInterval,
],
retry: false,
enabled: canQuery,
},
);
const chartDataSet = queryResponse.isError const chartDataSet = queryResponse.isError
? null ? null
: getChartData({ : getChartData({
queryData: [ queryData: [
{ {
queryData: queryResponse?.data?.payload?.data?.result queryData: queryResponse?.data?.payload?.data?.result ?? [],
? queryResponse?.data?.payload?.data?.result
: [],
}, },
], ],
}); });
@ -119,8 +114,7 @@ function ChartPreview({
{(queryResponse?.isError || queryResponse?.error) && ( {(queryResponse?.isError || queryResponse?.error) && (
<FailedMessageContainer color="red" title="Failed to refresh the chart"> <FailedMessageContainer color="red" title="Failed to refresh the chart">
<InfoCircleOutlined />{' '} <InfoCircleOutlined />{' '}
{(queryResponse?.error as QueryResponseError).message || {queryResponse.error.message || t('preview_chart_unexpected_error')}
t('preview_chart_unexpected_error')}
</FailedMessageContainer> </FailedMessageContainer>
)} )}
{queryResponse.isLoading && <Spinner size="large" tip="Loading..." />} {queryResponse.isLoading && <Spinner size="large" tip="Loading..." />}

View File

@ -7,16 +7,13 @@ import {
timeItems, timeItems,
timePreferance, timePreferance,
} from 'container/NewWidget/RightContainer/timeItems'; } from 'container/NewWidget/RightContainer/timeItems';
import { useGetQueryRange } from 'hooks/queryBuilder/useGetQueryRange';
import { getDashboardVariables } from 'lib/dashbaordVariables/getDashboardVariables'; import { getDashboardVariables } from 'lib/dashbaordVariables/getDashboardVariables';
import getChartData from 'lib/getChartData'; import getChartData from 'lib/getChartData';
import { useCallback, useMemo, useState } from 'react'; import { useCallback, useMemo, useState } from 'react';
import { useQuery } from 'react-query';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import { GetMetricQueryRange } from 'store/actions/dashboard/getQueryResults';
import { AppState } from 'store/reducers'; import { AppState } from 'store/reducers';
import { ErrorResponse, SuccessResponse } from 'types/api';
import { Widgets } from 'types/api/dashboard/getAll'; import { Widgets } from 'types/api/dashboard/getAll';
import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange';
import { GlobalReducer } from 'types/reducer/globalTime'; import { GlobalReducer } from 'types/reducer/globalTime';
import { TimeContainer } from './styles'; import { TimeContainer } from './styles';
@ -44,18 +41,24 @@ function FullView({
name: getSelectedTime()?.name || '', name: getSelectedTime()?.name || '',
enum: widget?.timePreferance || 'GLOBAL_TIME', enum: widget?.timePreferance || 'GLOBAL_TIME',
}); });
const response = useQuery<
SuccessResponse<MetricRangePayloadProps> | ErrorResponse const queryKey = useMemo(
>(
`FullViewGetMetricsQueryRange-${selectedTime.enum}-${globalSelectedTime}-${widget.id}`,
() => () =>
GetMetricQueryRange({ `FullViewGetMetricsQueryRange-${selectedTime.enum}-${globalSelectedTime}-${widget.id}`,
selectedTime: selectedTime.enum, [selectedTime, globalSelectedTime, widget],
graphType: widget.panelTypes, );
query: widget.query,
globalSelectedInterval: globalSelectedTime, const response = useGetQueryRange(
variables: getDashboardVariables(), {
}), selectedTime: selectedTime.enum,
graphType: widget.panelTypes,
query: widget.query,
globalSelectedInterval: globalSelectedTime,
variables: getDashboardVariables(),
},
{
queryKey,
},
); );
const chartDataSet = useMemo( const chartDataSet = useMemo(

View File

@ -3,6 +3,7 @@ import { ChartData } from 'chart.js';
import Spinner from 'components/Spinner'; import Spinner from 'components/Spinner';
import GridGraphComponent from 'container/GridGraphComponent'; import GridGraphComponent from 'container/GridGraphComponent';
import { UpdateDashboard } from 'container/GridGraphLayout/utils'; import { UpdateDashboard } from 'container/GridGraphLayout/utils';
import { useGetQueryRange } from 'hooks/queryBuilder/useGetQueryRange';
import { useNotifications } from 'hooks/useNotifications'; import { useNotifications } from 'hooks/useNotifications';
import usePreviousValue from 'hooks/usePreviousValue'; import usePreviousValue from 'hooks/usePreviousValue';
import { getDashboardVariables } from 'lib/dashbaordVariables/getDashboardVariables'; import { getDashboardVariables } from 'lib/dashbaordVariables/getDashboardVariables';
@ -20,7 +21,6 @@ import {
import { Layout } from 'react-grid-layout'; import { Layout } from 'react-grid-layout';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useInView } from 'react-intersection-observer'; import { useInView } from 'react-intersection-observer';
import { useQuery } from 'react-query';
import { connect, useSelector } from 'react-redux'; import { connect, useSelector } from 'react-redux';
import { bindActionCreators } from 'redux'; import { bindActionCreators } from 'redux';
import { ThunkDispatch } from 'redux-thunk'; import { ThunkDispatch } from 'redux-thunk';
@ -28,7 +28,6 @@ import {
DeleteWidget, DeleteWidget,
DeleteWidgetProps, DeleteWidgetProps,
} from 'store/actions/dashboard/deleteWidget'; } from 'store/actions/dashboard/deleteWidget';
import { GetMetricQueryRange } from 'store/actions/dashboard/getQueryResults';
import { AppState } from 'store/reducers'; import { AppState } from 'store/reducers';
import AppActions from 'types/actions'; import AppActions from 'types/actions';
import { Widgets } from 'types/api/dashboard/getAll'; import { Widgets } from 'types/api/dashboard/getAll';
@ -81,33 +80,28 @@ function GridCardGraph({
const selectedData = selectedDashboard?.data; const selectedData = selectedDashboard?.data;
const { variables } = selectedData; const { variables } = selectedData;
const queryResponse = useQuery( const queryResponse = useGetQueryRange(
[ {
`GetMetricsQueryRange-${widget?.timePreferance}-${globalSelectedInterval}-${widget.id}`, selectedTime: widget?.timePreferance,
{ graphType: widget.panelTypes,
query: widget.query,
globalSelectedInterval,
variables: getDashboardVariables(),
},
{
queryKey: [
`GetMetricsQueryRange-${widget?.timePreferance}-${globalSelectedInterval}-${widget.id}`,
widget, widget,
maxTime, maxTime,
minTime, minTime,
globalSelectedInterval, globalSelectedInterval,
variables, variables,
}, ],
],
() =>
GetMetricQueryRange({
selectedTime: widget?.timePreferance,
graphType: widget.panelTypes,
query: widget.query,
globalSelectedInterval,
variables: getDashboardVariables(),
}),
{
keepPreviousData: true, keepPreviousData: true,
enabled: isGraphVisible, enabled: isGraphVisible,
refetchOnMount: false, refetchOnMount: false,
onError: (error) => { onError: (error) => {
if (error instanceof Error) { setErrorMessage(error.message);
setErrorMessage(error.message);
}
}, },
}, },
); );

View File

@ -50,14 +50,6 @@ export const UpdateDashboard = async (
queryData: [initialQueryBuilderFormValues], queryData: [initialQueryBuilderFormValues],
}, },
}, },
queryData: {
data: {
queryData: widgetData?.queryData.data.queryData || [],
},
error: false,
errorMessage: '',
loading: false,
},
timePreferance: widgetData?.timePreferance || 'GLOBAL_TIME', timePreferance: widgetData?.timePreferance || 'GLOBAL_TIME',
title: widgetData ? copyTitle : '', title: widgetData ? copyTitle : '',
}, },

View File

@ -71,23 +71,8 @@ function ImportJSON({
setDashboardCreating(true); setDashboardCreating(true);
const dashboardData = JSON.parse(editorValue) as DashboardData; const dashboardData = JSON.parse(editorValue) as DashboardData;
// removing the queryData
const parsedWidgets: DashboardData = {
...dashboardData,
widgets: dashboardData.widgets?.map((e) => ({
...e,
queryData: {
...e.queryData,
data: e.queryData.data,
error: false,
errorMessage: '',
loading: false,
},
})),
};
const response = await createDashboard({ const response = await createDashboard({
...parsedWidgets, ...dashboardData,
uploadedGrafana, uploadedGrafana,
}); });

View File

@ -10,12 +10,6 @@ export const getWidgetQueryBuilder = (query: Widgets['query']): Widgets => ({
opacity: '0', opacity: '0',
panelTypes: PANEL_TYPES.TIME_SERIES, panelTypes: PANEL_TYPES.TIME_SERIES,
query, query,
queryData: {
data: { queryData: [] },
error: false,
errorMessage: '',
loading: false,
},
timePreferance: 'GLOBAL_TIME', timePreferance: 'GLOBAL_TIME',
title: '', title: '',
}); });

View File

@ -6,28 +6,14 @@ import { useTranslation } from 'react-i18next';
import { useCopyToClipboard } from 'react-use'; import { useCopyToClipboard } from 'react-use';
import { DashboardData } from 'types/api/dashboard/getAll'; import { DashboardData } from 'types/api/dashboard/getAll';
import { cleardQueryData, downloadObjectAsJson } from './util'; import { downloadObjectAsJson } from './util';
function ShareModal({ function ShareModal({
isJSONModalVisible, isJSONModalVisible,
onToggleHandler, onToggleHandler,
selectedData, selectedData,
}: ShareModalProps): JSX.Element { }: ShareModalProps): JSX.Element {
const getParsedValue = (): string => { const getParsedValue = (): string => JSON.stringify(selectedData, null, 2);
const updatedData: DashboardData = {
...selectedData,
widgets: selectedData.widgets?.map((widget) => ({
...widget,
queryData: {
...widget.queryData,
loading: false,
error: false,
errorMessage: '',
},
})),
};
return JSON.stringify(updatedData, null, 2);
};
const [jsonValue, setJSONValue] = useState<string>(getParsedValue()); const [jsonValue, setJSONValue] = useState<string>(getParsedValue());
const [isViewJSON, setIsViewJSON] = useState<boolean>(false); const [isViewJSON, setIsViewJSON] = useState<boolean>(false);
@ -53,7 +39,6 @@ function ShareModal({
} }
}, [state.error, state.value, t, notifications]); }, [state.error, state.value, t, notifications]);
const selectedDataCleaned = cleardQueryData(selectedData);
const GetFooterComponent = useMemo(() => { const GetFooterComponent = useMemo(() => {
if (!isViewJSON) { if (!isViewJSON) {
return ( return (
@ -69,7 +54,7 @@ function ShareModal({
<Button <Button
type="primary" type="primary"
onClick={(): void => { onClick={(): void => {
downloadObjectAsJson(selectedDataCleaned, selectedData.title); downloadObjectAsJson(selectedData, selectedData.title);
}} }}
> >
{t('download_json')} {t('download_json')}
@ -82,7 +67,7 @@ function ShareModal({
{t('copy_to_clipboard')} {t('copy_to_clipboard')}
</Button> </Button>
); );
}, [isViewJSON, jsonValue, selectedData, selectedDataCleaned, setCopy, t]); }, [isViewJSON, jsonValue, selectedData, setCopy, t]);
return ( return (
<Modal <Modal

View File

@ -1,5 +1,3 @@
import { DashboardData } from 'types/api/dashboard/getAll';
export function downloadObjectAsJson( export function downloadObjectAsJson(
exportObj: unknown, exportObj: unknown,
exportName: string, exportName: string,
@ -14,18 +12,3 @@ export function downloadObjectAsJson(
downloadAnchorNode.click(); downloadAnchorNode.click();
downloadAnchorNode.remove(); downloadAnchorNode.remove();
} }
export function cleardQueryData(param: DashboardData): DashboardData {
return {
...param,
widgets: param.widgets?.map((widget) => ({
...widget,
queryData: {
...widget.queryData,
data: {
queryData: [],
},
},
})),
};
}

View File

@ -1,11 +1,13 @@
import { Button, Tabs, Typography } from 'antd'; import { Button, Tabs, Typography } from 'antd';
import TextToolTip from 'components/TextToolTip'; import TextToolTip from 'components/TextToolTip';
import { GRAPH_TYPES } from 'container/NewDashboard/ComponentsSlider'; import { GRAPH_TYPES } from 'container/NewDashboard/ComponentsSlider';
import { WidgetGraphProps } from 'container/NewWidget/types';
import { QueryBuilder } from 'container/QueryBuilder'; import { QueryBuilder } from 'container/QueryBuilder';
import { useGetWidgetQueryRange } from 'hooks/queryBuilder/useGetWidgetQueryRange';
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder'; import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
import { useShareBuilderUrl } from 'hooks/queryBuilder/useShareBuilderUrl'; import { useShareBuilderUrl } from 'hooks/queryBuilder/useShareBuilderUrl';
import useUrlQuery from 'hooks/useUrlQuery'; import useUrlQuery from 'hooks/useUrlQuery';
import { useCallback, useEffect, useState } from 'react'; import { useCallback } from 'react';
import { connect, useSelector } from 'react-redux'; import { connect, useSelector } from 'react-redux';
import { bindActionCreators, Dispatch } from 'redux'; import { bindActionCreators, Dispatch } from 'redux';
import { ThunkDispatch } from 'redux-thunk'; import { ThunkDispatch } from 'redux-thunk';
@ -23,16 +25,22 @@ import DashboardReducer from 'types/reducer/dashboards';
import ClickHouseQueryContainer from './QueryBuilder/clickHouse'; import ClickHouseQueryContainer from './QueryBuilder/clickHouse';
import PromQLQueryContainer from './QueryBuilder/promQL'; import PromQLQueryContainer from './QueryBuilder/promQL';
function QuerySection({ updateQuery, selectedGraph }: QueryProps): JSX.Element { function QuerySection({
updateQuery,
selectedGraph,
selectedTime,
}: QueryProps): JSX.Element {
const { currentQuery, redirectWithQueryBuilderData } = useQueryBuilder(); const { currentQuery, redirectWithQueryBuilderData } = useQueryBuilder();
const urlQuery = useUrlQuery(); const urlQuery = useUrlQuery();
const [isInit, setIsInit] = useState<boolean>(false); const { dashboards } = useSelector<AppState, DashboardReducer>(
(state) => state.dashboards,
);
const { dashboards, isLoadingQueryResult } = useSelector< const getWidgetQueryRange = useGetWidgetQueryRange({
AppState, graphType: selectedGraph,
DashboardReducer selectedTime: selectedTime.enum,
>((state) => state.dashboards); });
const [selectedDashboards] = dashboards; const [selectedDashboards] = dashboards;
const { widgets } = selectedDashboards.data; const { widgets } = selectedDashboards.data;
@ -46,23 +54,11 @@ function QuerySection({ updateQuery, selectedGraph }: QueryProps): JSX.Element {
const { query } = selectedWidget; const { query } = selectedWidget;
const { compositeQuery } = useShareBuilderUrl({ defaultValue: query }); useShareBuilderUrl({ defaultValue: query });
useEffect(() => {
if (!isInit && compositeQuery) {
setIsInit(true);
updateQuery({
updatedQuery: compositeQuery,
widgetId: urlQuery.get('widgetId') || '',
yAxisUnit: selectedWidget.yAxisUnit,
});
}
}, [isInit, compositeQuery, selectedWidget, urlQuery, updateQuery]);
const handleStageQuery = useCallback( const handleStageQuery = useCallback(
(updatedQuery: Query): void => { (updatedQuery: Query): void => {
updateQuery({ updateQuery({
updatedQuery,
widgetId: urlQuery.get('widgetId') || '', widgetId: urlQuery.get('widgetId') || '',
yAxisUnit: selectedWidget.yAxisUnit, yAxisUnit: selectedWidget.yAxisUnit,
}); });
@ -115,7 +111,7 @@ function QuerySection({ updateQuery, selectedGraph }: QueryProps): JSX.Element {
<span style={{ display: 'flex', gap: '1rem', alignItems: 'center' }}> <span style={{ display: 'flex', gap: '1rem', alignItems: 'center' }}>
<TextToolTip text="This will temporarily save the current query and graph state. This will persist across tab change" /> <TextToolTip text="This will temporarily save the current query and graph state. This will persist across tab change" />
<Button <Button
loading={isLoadingQueryResult} loading={getWidgetQueryRange.isFetching}
type="primary" type="primary"
onClick={handleRunQuery} onClick={handleRunQuery}
> >
@ -142,6 +138,7 @@ const mapDispatchToProps = (
interface QueryProps extends DispatchProps { interface QueryProps extends DispatchProps {
selectedGraph: GRAPH_TYPES; selectedGraph: GRAPH_TYPES;
selectedTime: WidgetGraphProps['selectedTime'];
} }
export default connect(null, mapDispatchToProps)(QuerySection); export default connect(null, mapDispatchToProps)(QuerySection);

View File

@ -1,6 +1,8 @@
import { Card, Typography } from 'antd'; import { Card, Typography } from 'antd';
import Spinner from 'components/Spinner';
import GridGraphComponent from 'container/GridGraphComponent'; import GridGraphComponent from 'container/GridGraphComponent';
import { NewWidgetProps } from 'container/NewWidget'; import { WidgetGraphProps } from 'container/NewWidget/types';
import { useGetWidgetQueryRange } from 'hooks/queryBuilder/useGetWidgetQueryRange';
import getChartData from 'lib/getChartData'; import getChartData from 'lib/getChartData';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import { useLocation } from 'react-router-dom'; import { useLocation } from 'react-router-dom';
@ -12,6 +14,7 @@ import { NotFoundContainer } from './styles';
function WidgetGraph({ function WidgetGraph({
selectedGraph, selectedGraph,
yAxisUnit, yAxisUnit,
selectedTime,
}: WidgetGraphProps): JSX.Element { }: WidgetGraphProps): JSX.Element {
const { dashboards } = useSelector<AppState, DashboardReducer>( const { dashboards } = useSelector<AppState, DashboardReducer>(
(state) => state.dashboards, (state) => state.dashboards,
@ -27,20 +30,28 @@ function WidgetGraph({
const selectedWidget = widgets.find((e) => e.id === widgetId); const selectedWidget = widgets.find((e) => e.id === widgetId);
const getWidgetQueryRange = useGetWidgetQueryRange({
graphType: selectedGraph,
selectedTime: selectedTime.enum,
});
if (selectedWidget === undefined) { if (selectedWidget === undefined) {
return <Card>Invalid widget</Card>; return <Card>Invalid widget</Card>;
} }
const { queryData, title, opacity, isStacked } = selectedWidget; const { title, opacity, isStacked } = selectedWidget;
if (queryData.error) { if (getWidgetQueryRange.error) {
return ( return (
<NotFoundContainer> <NotFoundContainer>
<Typography>{queryData.errorMessage}</Typography> <Typography>{getWidgetQueryRange.error.message}</Typography>
</NotFoundContainer> </NotFoundContainer>
); );
} }
if (queryData.data.queryData.length === 0) { if (getWidgetQueryRange.isLoading) {
return <Spinner size="large" tip="Loading..." />;
}
if (getWidgetQueryRange.data?.payload.data.result.length === 0) {
return ( return (
<NotFoundContainer> <NotFoundContainer>
<Typography>No Data</Typography> <Typography>No Data</Typography>
@ -49,7 +60,9 @@ function WidgetGraph({
} }
const chartDataSet = getChartData({ const chartDataSet = getChartData({
queryData: [queryData.data], queryData: [
{ queryData: getWidgetQueryRange.data?.payload.data.result ?? [] },
],
}); });
return ( return (
@ -65,6 +78,4 @@ function WidgetGraph({
); );
} }
type WidgetGraphProps = NewWidgetProps;
export default WidgetGraph; export default WidgetGraph;

View File

@ -1,24 +1,28 @@
import { InfoCircleOutlined } from '@ant-design/icons'; import { InfoCircleOutlined } from '@ant-design/icons';
import { Typography } from 'antd';
import { Card } from 'container/GridGraphLayout/styles'; import { Card } from 'container/GridGraphLayout/styles';
import { useGetWidgetQueryRange } from 'hooks/queryBuilder/useGetWidgetQueryRange';
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
import { memo } from 'react'; import { memo } from 'react';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import { useLocation } from 'react-router-dom'; import { 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 { NewWidgetProps } from '../../index'; import { WidgetGraphProps } from '../../types';
import PlotTag from './PlotTag'; import PlotTag from './PlotTag';
import { AlertIconContainer, Container, NotFoundContainer } from './styles'; import { AlertIconContainer, Container } from './styles';
import WidgetGraphComponent from './WidgetGraph'; import WidgetGraphComponent from './WidgetGraph';
function WidgetGraph({ function WidgetGraph({
selectedGraph, selectedGraph,
yAxisUnit, yAxisUnit,
selectedTime,
}: WidgetGraphProps): JSX.Element { }: WidgetGraphProps): JSX.Element {
const { dashboards, isQueryFired } = useSelector<AppState, DashboardReducer>( const { currentQuery } = useQueryBuilder();
const { dashboards } = useSelector<AppState, DashboardReducer>(
(state) => state.dashboards, (state) => state.dashboards,
); );
const [selectedDashboard] = dashboards; const [selectedDashboard] = dashboards;
const { search } = useLocation(); const { search } = useLocation();
@ -31,33 +35,31 @@ function WidgetGraph({
const selectedWidget = widgets.find((e) => e.id === widgetId); const selectedWidget = widgets.find((e) => e.id === widgetId);
const getWidgetQueryRange = useGetWidgetQueryRange({
graphType: selectedGraph,
selectedTime: selectedTime.enum,
});
if (selectedWidget === undefined) { if (selectedWidget === undefined) {
return <Card>Invalid widget</Card>; return <Card>Invalid widget</Card>;
} }
const { queryData } = selectedWidget;
return ( return (
<Container> <Container>
<PlotTag queryType={selectedWidget.query.queryType} /> <PlotTag queryType={currentQuery.queryType} />
{queryData.error && ( {getWidgetQueryRange.error && (
<AlertIconContainer color="red" title={queryData.errorMessage}> <AlertIconContainer color="red" title={getWidgetQueryRange.error.message}>
<InfoCircleOutlined /> <InfoCircleOutlined />
</AlertIconContainer> </AlertIconContainer>
)} )}
{!isQueryFired && ( <WidgetGraphComponent
<NotFoundContainer> selectedTime={selectedTime}
<Typography>No Data</Typography> selectedGraph={selectedGraph}
</NotFoundContainer> yAxisUnit={yAxisUnit}
)} />
{isQueryFired && (
<WidgetGraphComponent selectedGraph={selectedGraph} yAxisUnit={yAxisUnit} />
)}
</Container> </Container>
); );
} }
type WidgetGraphProps = NewWidgetProps;
export default memo(WidgetGraph); export default memo(WidgetGraph);

View File

@ -1,6 +1,6 @@
import { memo } from 'react'; import { memo } from 'react';
import { NewWidgetProps } from '../index'; import { WidgetGraphProps } from '../types';
import QuerySection from './QuerySection'; import QuerySection from './QuerySection';
import { QueryContainer } from './styles'; import { QueryContainer } from './styles';
import WidgetGraph from './WidgetGraph'; import WidgetGraph from './WidgetGraph';
@ -8,12 +8,17 @@ import WidgetGraph from './WidgetGraph';
function LeftContainer({ function LeftContainer({
selectedGraph, selectedGraph,
yAxisUnit, yAxisUnit,
}: NewWidgetProps): JSX.Element { selectedTime,
}: WidgetGraphProps): JSX.Element {
return ( return (
<> <>
<WidgetGraph selectedGraph={selectedGraph} yAxisUnit={yAxisUnit} /> <WidgetGraph
selectedTime={selectedTime}
selectedGraph={selectedGraph}
yAxisUnit={yAxisUnit}
/>
<QueryContainer> <QueryContainer>
<QuerySection selectedGraph={selectedGraph} /> <QuerySection selectedTime={selectedTime} selectedGraph={selectedGraph} />
</QueryContainer> </QueryContainer>
</> </>
); );

View File

@ -1,25 +1,18 @@
import { LockFilled } from '@ant-design/icons'; import { LockFilled } from '@ant-design/icons';
import { Button, Modal, Tooltip, Typography } from 'antd'; import { Button, Modal, Tooltip, Typography } from 'antd';
import { FeatureKeys } from 'constants/features'; import { FeatureKeys } from 'constants/features';
import { COMPOSITE_QUERY } from 'constants/queryBuilderQueryNames';
import ROUTES from 'constants/routes'; import ROUTES from 'constants/routes';
import { GRAPH_TYPES } from 'container/NewDashboard/ComponentsSlider';
import { ITEMS } from 'container/NewDashboard/ComponentsSlider/menuItems'; import { ITEMS } from 'container/NewDashboard/ComponentsSlider/menuItems';
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
import { MESSAGE, useIsFeatureDisabled } from 'hooks/useFeatureFlag'; import { MESSAGE, useIsFeatureDisabled } from 'hooks/useFeatureFlag';
import { useNotifications } from 'hooks/useNotifications'; import { useNotifications } from 'hooks/useNotifications';
import useUrlQuery from 'hooks/useUrlQuery';
import { getDashboardVariables } from 'lib/dashbaordVariables/getDashboardVariables';
import history from 'lib/history'; import history from 'lib/history';
import { DashboardWidgetPageParams } from 'pages/DashboardWidget'; import { DashboardWidgetPageParams } from 'pages/DashboardWidget';
import { useCallback, useEffect, useMemo, useState } from 'react'; import { useCallback, useMemo, useState } from 'react';
import { connect, useDispatch, useSelector } from 'react-redux'; import { connect, useDispatch, useSelector } from 'react-redux';
import { generatePath, useLocation, useParams } from 'react-router-dom'; import { generatePath, useLocation, useParams } from 'react-router-dom';
import { bindActionCreators, Dispatch } from 'redux'; import { bindActionCreators, Dispatch } from 'redux';
import { ThunkDispatch } from 'redux-thunk'; import { ThunkDispatch } from 'redux-thunk';
import {
GetQueryResults,
GetQueryResultsProps,
} from 'store/actions/dashboard/getQueryResults';
import { import {
SaveDashboard, SaveDashboard,
SaveDashboardProps, SaveDashboardProps,
@ -27,10 +20,8 @@ import {
import { AppState } from 'store/reducers'; import { AppState } from 'store/reducers';
import AppActions from 'types/actions'; import AppActions from 'types/actions';
import { FLUSH_DASHBOARD } from 'types/actions/dashboard'; import { FLUSH_DASHBOARD } from 'types/actions/dashboard';
import { Widgets } from 'types/api/dashboard/getAll';
import AppReducer from 'types/reducer/app'; import AppReducer from 'types/reducer/app';
import DashboardReducer from 'types/reducer/dashboards'; import DashboardReducer from 'types/reducer/dashboards';
import { GlobalReducer } from 'types/reducer/globalTime';
import LeftContainer from './LeftContainer'; import LeftContainer from './LeftContainer';
import QueryTypeTag from './LeftContainer/QueryTypeTag'; import QueryTypeTag from './LeftContainer/QueryTypeTag';
@ -43,21 +34,15 @@ import {
PanelContainer, PanelContainer,
RightContainerWrapper, RightContainerWrapper,
} from './styles'; } from './styles';
import { NewWidgetProps } from './types';
function NewWidget({ function NewWidget({ selectedGraph, saveSettingOfPanel }: Props): JSX.Element {
selectedGraph,
saveSettingOfPanel,
getQueryResults,
}: Props): JSX.Element {
const urlQuery = useUrlQuery();
const dispatch = useDispatch(); const dispatch = useDispatch();
const { dashboards } = useSelector<AppState, DashboardReducer>( const { dashboards } = useSelector<AppState, DashboardReducer>(
(state) => state.dashboards, (state) => state.dashboards,
); );
const { selectedTime: globalSelectedInterval } = useSelector<
AppState, const { currentQuery } = useQueryBuilder();
GlobalReducer
>((state) => state.globalTime);
const { featureResponse } = useSelector<AppState, AppReducer>( const { featureResponse } = useSelector<AppState, AppReducer>(
(state) => state.app, (state) => state.app,
@ -161,27 +146,6 @@ function NewWidget({
history.push(generatePath(ROUTES.DASHBOARD, { dashboardId })); history.push(generatePath(ROUTES.DASHBOARD, { dashboardId }));
}, [dashboardId, dispatch]); }, [dashboardId, dispatch]);
const getQueryResult = useCallback(() => {
const compositeQuery = urlQuery.get(COMPOSITE_QUERY);
if ((selectedWidget?.id.length !== 0 && compositeQuery) || compositeQuery) {
getQueryResults({
query: JSON.parse(compositeQuery),
selectedTime: selectedTime.enum,
widgetId: selectedWidget?.id || '',
graphType,
globalSelectedInterval,
variables: getDashboardVariables(),
});
}
}, [
selectedTime.enum,
selectedWidget?.id,
getQueryResults,
globalSelectedInterval,
graphType,
urlQuery,
]);
const setGraphHandler = (type: ITEMS): void => { const setGraphHandler = (type: ITEMS): void => {
const params = new URLSearchParams(search); const params = new URLSearchParams(search);
params.set('graphType', type); params.set('graphType', type);
@ -189,10 +153,6 @@ function NewWidget({
setGraphType(type); setGraphType(type);
}; };
useEffect(() => {
getQueryResult();
}, [getQueryResult]);
const onSaveDashboard = useCallback((): void => { const onSaveDashboard = useCallback((): void => {
setSaveModal(true); setSaveModal(true);
}, []); }, []);
@ -231,7 +191,11 @@ function NewWidget({
<PanelContainer> <PanelContainer>
<LeftContainerWrapper flex={5}> <LeftContainerWrapper flex={5}>
<LeftContainer selectedGraph={graphType} yAxisUnit={yAxisUnit} /> <LeftContainer
selectedTime={selectedTime}
selectedGraph={graphType}
yAxisUnit={yAxisUnit}
/>
</LeftContainerWrapper> </LeftContainerWrapper>
<RightContainerWrapper flex={1}> <RightContainerWrapper flex={1}>
@ -270,34 +234,24 @@ function NewWidget({
width={600} width={600}
> >
<Typography> <Typography>
Your graph built with{' '} Your graph built with <QueryTypeTag queryType={currentQuery.queryType} />{' '}
<QueryTypeTag queryType={selectedWidget?.query.queryType} /> query will be query will be saved. Press OK to confirm.
saved. Press OK to confirm.
</Typography> </Typography>
</Modal> </Modal>
</Container> </Container>
); );
} }
export interface NewWidgetProps {
selectedGraph: GRAPH_TYPES;
yAxisUnit: Widgets['yAxisUnit'];
}
interface DispatchProps { interface DispatchProps {
saveSettingOfPanel: ( saveSettingOfPanel: (
props: SaveDashboardProps, props: SaveDashboardProps,
) => (dispatch: Dispatch<AppActions>) => void; ) => (dispatch: Dispatch<AppActions>) => void;
getQueryResults: (
props: GetQueryResultsProps,
) => (dispatch: Dispatch<AppActions>) => void;
} }
const mapDispatchToProps = ( const mapDispatchToProps = (
dispatch: ThunkDispatch<unknown, unknown, AppActions>, dispatch: ThunkDispatch<unknown, unknown, AppActions>,
): DispatchProps => ({ ): DispatchProps => ({
saveSettingOfPanel: bindActionCreators(SaveDashboard, dispatch), saveSettingOfPanel: bindActionCreators(SaveDashboard, dispatch),
getQueryResults: bindActionCreators(GetQueryResults, dispatch),
}); });
type Props = DispatchProps & NewWidgetProps; type Props = DispatchProps & NewWidgetProps;

View File

@ -0,0 +1,13 @@
import { GRAPH_TYPES } from 'container/NewDashboard/ComponentsSlider';
import { Widgets } from 'types/api/dashboard/getAll';
import { timePreferance } from './RightContainer/timeItems';
export interface NewWidgetProps {
selectedGraph: GRAPH_TYPES;
yAxisUnit: Widgets['yAxisUnit'];
}
export interface WidgetGraphProps extends NewWidgetProps {
selectedTime: timePreferance;
}

View File

@ -0,0 +1,18 @@
import { REACT_QUERY_KEY } from 'constants/reactQueryKeys';
import { useQuery, UseQueryOptions, UseQueryResult } from 'react-query';
import {
GetMetricQueryRange,
GetQueryResultsProps,
} from 'store/actions/dashboard/getQueryResults';
import { SuccessResponse } from 'types/api';
import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange';
export const useGetQueryRange = (
requestData: GetQueryResultsProps,
options?: UseQueryOptions<SuccessResponse<MetricRangePayloadProps>, Error>,
): UseQueryResult<SuccessResponse<MetricRangePayloadProps>, Error> =>
useQuery<SuccessResponse<MetricRangePayloadProps>, Error>({
queryKey: [REACT_QUERY_KEY.GET_QUERY_RANGE, requestData],
queryFn: async () => GetMetricQueryRange(requestData),
...options,
});

View File

@ -0,0 +1,51 @@
import { COMPOSITE_QUERY } from 'constants/queryBuilderQueryNames';
import { REACT_QUERY_KEY } from 'constants/reactQueryKeys';
import useUrlQuery from 'hooks/useUrlQuery';
import { getDashboardVariables } from 'lib/dashbaordVariables/getDashboardVariables';
import { UseQueryOptions, UseQueryResult } from 'react-query';
import { useSelector } from 'react-redux';
import { GetQueryResultsProps } from 'store/actions/dashboard/getQueryResults';
import { AppState } from 'store/reducers';
import { SuccessResponse } from 'types/api';
import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange';
import { GlobalReducer } from 'types/reducer/globalTime';
import { useGetQueryRange } from './useGetQueryRange';
export const useGetWidgetQueryRange = (
{
graphType,
selectedTime,
}: Pick<GetQueryResultsProps, 'graphType' | 'selectedTime'>,
options?: UseQueryOptions<SuccessResponse<MetricRangePayloadProps>, Error>,
): UseQueryResult<SuccessResponse<MetricRangePayloadProps>, Error> => {
const urlQuery = useUrlQuery();
const { selectedTime: globalSelectedInterval } = useSelector<
AppState,
GlobalReducer
>((state) => state.globalTime);
const compositeQuery = urlQuery.get(COMPOSITE_QUERY);
return useGetQueryRange(
{
graphType,
selectedTime,
globalSelectedInterval,
query: JSON.parse(compositeQuery || ''),
variables: getDashboardVariables(),
},
{
enabled: !!compositeQuery,
retry: false,
queryKey: [
REACT_QUERY_KEY.GET_QUERY_RANGE,
selectedTime,
globalSelectedInterval,
compositeQuery,
],
...options,
},
);
};

View File

@ -1,6 +1,6 @@
import { ChartData } from 'chart.js'; import { ChartData } from 'chart.js';
import getLabelName from 'lib/getLabelName'; import getLabelName from 'lib/getLabelName';
import { Widgets } from 'types/api/dashboard/getAll'; import { QueryData } from 'types/api/widgets/getQuery';
import convertIntoEpoc from './covertIntoEpoc'; import convertIntoEpoc from './covertIntoEpoc';
import { colors } from './getRandomColor'; import { colors } from './getRandomColor';
@ -77,7 +77,11 @@ const getChartData = ({ queryData }: GetChartDataProps): ChartData => {
}; };
interface GetChartDataProps { interface GetChartDataProps {
queryData: Widgets['queryData']['data'][]; queryData: {
query?: string;
legend?: string;
queryData: QueryData[];
}[];
} }
export default getChartData; export default getChartData;

View File

@ -39,16 +39,6 @@ export const GetDashboard = ({
panelTypes: graphType || PANEL_TYPES.TIME_SERIES, panelTypes: graphType || PANEL_TYPES.TIME_SERIES,
timePreferance: 'GLOBAL_TIME', timePreferance: 'GLOBAL_TIME',
title: '', title: '',
queryType: 0,
queryData: {
data: {
queryData: [],
},
error: false,
errorMessage: '',
loading: false,
},
query: initialQueryWithType, query: initialQueryWithType,
}, },
}); });

View File

@ -3,9 +3,6 @@
// @ts-nocheck // @ts-nocheck
import { getMetricsQueryRange } from 'api/metrics/getQueryRange'; import { getMetricsQueryRange } from 'api/metrics/getQueryRange';
import { AxiosError } from 'axios';
import { GRAPH_TYPES } from 'container/NewDashboard/ComponentsSlider';
import { ITEMS } from 'container/NewDashboard/ComponentsSlider/menuItems';
import { timePreferenceType } from 'container/NewWidget/RightContainer/timeItems'; import { timePreferenceType } from 'container/NewWidget/RightContainer/timeItems';
import { Time } from 'container/TopNav/DateTimeSelection/config'; import { Time } from 'container/TopNav/DateTimeSelection/config';
import GetMaxMinTime from 'lib/getMaxMinTime'; import GetMaxMinTime from 'lib/getMaxMinTime';
@ -14,14 +11,11 @@ import GetStartAndEndTime from 'lib/getStartAndEndTime';
import getStep from 'lib/getStep'; import getStep from 'lib/getStep';
import { mapQueryDataToApi } from 'lib/newQueryBuilder/queryBuilderMappers/mapQueryDataToApi'; import { mapQueryDataToApi } from 'lib/newQueryBuilder/queryBuilderMappers/mapQueryDataToApi';
import { isEmpty } from 'lodash-es'; import { isEmpty } from 'lodash-es';
import { Dispatch } from 'redux';
import store from 'store'; import store from 'store';
import AppActions from 'types/actions'; import { SuccessResponse } from 'types/api';
import { ErrorResponse, SuccessResponse } from 'types/api';
import { Query } from 'types/api/queryBuilder/queryBuilderData'; import { Query } from 'types/api/queryBuilder/queryBuilderData';
import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange'; import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange';
import { EQueryType } from 'types/common/dashboard'; import { EQueryType } from 'types/common/dashboard';
import { GlobalReducer } from 'types/reducer/globalTime';
import { convertNewDataToOld } from 'lib/newQueryBuilder/convertNewDataToOld'; import { convertNewDataToOld } from 'lib/newQueryBuilder/convertNewDataToOld';
export async function GetMetricQueryRange({ export async function GetMetricQueryRange({
@ -30,13 +24,7 @@ export async function GetMetricQueryRange({
graphType, graphType,
selectedTime, selectedTime,
variables = {}, variables = {},
}: { }: GetQueryResultsProps): Promise<SuccessResponse<MetricRangePayloadProps>> {
query: Query;
graphType: GRAPH_TYPES;
selectedTime: timePreferenceType;
globalSelectedInterval: Time;
variables?: Record<string, unknown>;
}): Promise<SuccessResponse<MetricRangePayloadProps> | ErrorResponse> {
const queryData = query[query.queryType]; const queryData = query[query.queryType];
let legendMap: Record<string, string> = {}; let legendMap: Record<string, string> = {};
@ -153,66 +141,10 @@ export async function GetMetricQueryRange({
return response; return response;
} }
export const GetQueryResults = (
props: GetQueryResultsProps,
): ((dispatch: Dispatch<AppActions>) => void) => {
return async (dispatch: Dispatch<AppActions>): Promise<void> => {
try {
dispatch({
type: 'QUERY_ERROR',
payload: {
errorMessage: '',
widgetId: props.widgetId,
errorBoolean: false,
isLoadingQueryResult: true,
},
});
const response = await GetMetricQueryRange(props);
const isError = response.error;
if (isError != null) {
dispatch({
type: 'QUERY_ERROR',
payload: {
errorMessage: isError || '',
widgetId: props.widgetId,
isLoadingQueryResult: false,
},
});
return;
}
dispatch({
type: 'QUERY_SUCCESS',
payload: {
widgetId: props.widgetId,
data: {
queryData: response.payload?.data?.result
? response.payload?.data?.result
: [],
},
},
});
} catch (error) {
dispatch({
type: 'QUERY_ERROR',
payload: {
errorMessage: (error as AxiosError).toString(),
widgetId: props.widgetId,
errorBoolean: true,
isLoadingQueryResult: false,
},
});
}
};
};
export interface GetQueryResultsProps { export interface GetQueryResultsProps {
widgetId: string;
selectedTime: timePreferenceType;
query: Query; query: Query;
graphType: ITEMS; graphType: GRAPH_TYPES;
globalSelectedInterval: GlobalReducer['selectedTime']; selectedTime: timePreferenceType;
variables: Record<string, unknown>; globalSelectedInterval: Time;
variables?: Record<string, unknown>;
} }

View File

@ -1,5 +1,6 @@
import updateDashboardApi from 'api/dashboard/update'; import updateDashboardApi from 'api/dashboard/update';
import { AxiosError } from 'axios'; import { AxiosError } from 'axios';
import { COMPOSITE_QUERY } from 'constants/queryBuilderQueryNames';
import ROUTES from 'constants/routes'; import ROUTES from 'constants/routes';
import { ITEMS } from 'container/NewDashboard/ComponentsSlider/menuItems'; import { ITEMS } from 'container/NewDashboard/ComponentsSlider/menuItems';
import history from 'lib/history'; import history from 'lib/history';
@ -84,6 +85,12 @@ export const SaveDashboard = ({
]; ];
}; };
const allLayout = getAllLayout(); const allLayout = getAllLayout();
const params = new URLSearchParams(window.location.search);
const compositeQuery = params.get(COMPOSITE_QUERY);
const query = compositeQuery
? JSON.parse(compositeQuery)
: selectedWidget.query;
const response = await updateDashboardApi({ const response = await updateDashboardApi({
data: { data: {
...selectedDashboard.data, ...selectedDashboard.data,
@ -98,6 +105,7 @@ export const SaveDashboard = ({
...preWidget, ...preWidget,
{ {
...selectedWidget, ...selectedWidget,
query,
description: updatedDescription, description: updatedDescription,
id: isEmptyWidget ? newWidgetId : widgetId, id: isEmptyWidget ? newWidgetId : widgetId,
isStacked: updatedisStacked, isStacked: updatedisStacked,
@ -107,9 +115,6 @@ export const SaveDashboard = ({
timePreferance: updatedtimePreferance, timePreferance: updatedtimePreferance,
yAxisUnit: updatedYAxisUnit, yAxisUnit: updatedYAxisUnit,
panelTypes: graphType, panelTypes: graphType,
queryData: {
...selectedWidget.queryData,
},
}, },
...afterWidget, ...afterWidget,
], ],

View File

@ -1,6 +1,5 @@
import { Dispatch } from 'redux'; import { Dispatch } from 'redux';
import AppActions from 'types/actions'; import AppActions from 'types/actions';
import { Query } from 'types/api/queryBuilder/queryBuilderData';
export const UpdateQuery = ( export const UpdateQuery = (
props: UpdateQueryProps, props: UpdateQueryProps,
@ -10,7 +9,6 @@ export const UpdateQuery = (
dispatch({ dispatch({
type: 'UPDATE_QUERY', type: 'UPDATE_QUERY',
payload: { payload: {
query: props.updatedQuery,
widgetId: props.widgetId, widgetId: props.widgetId,
yAxisUnit: props.yAxisUnit, yAxisUnit: props.yAxisUnit,
}, },
@ -18,7 +16,6 @@ export const UpdateQuery = (
}; };
export interface UpdateQueryProps { export interface UpdateQueryProps {
updatedQuery: Query;
widgetId: string; widgetId: string;
yAxisUnit: string | undefined; yAxisUnit: string | undefined;
} }

View File

@ -13,8 +13,6 @@ import {
GET_DASHBOARD_LOADING_START, GET_DASHBOARD_LOADING_START,
GET_DASHBOARD_SUCCESS, GET_DASHBOARD_SUCCESS,
IS_ADD_WIDGET, IS_ADD_WIDGET,
QUERY_ERROR,
QUERY_SUCCESS,
SAVE_SETTING_TO_PANEL_SUCCESS, SAVE_SETTING_TO_PANEL_SUCCESS,
TOGGLE_EDIT_MODE, TOGGLE_EDIT_MODE,
UPDATE_DASHBOARD, UPDATE_DASHBOARD,
@ -30,9 +28,7 @@ const InitialValue: InitialValueTypes = {
error: false, error: false,
errorMessage: '', errorMessage: '',
isEditMode: false, isEditMode: false,
isQueryFired: false,
isAddWidget: false, isAddWidget: false,
isLoadingQueryResult: false,
}; };
const dashboard = ( const dashboard = (
@ -170,102 +166,6 @@ const dashboard = (
}; };
} }
case QUERY_ERROR: {
const {
widgetId,
errorMessage,
errorBoolean = true,
isLoadingQueryResult = false,
} = action.payload;
const [selectedDashboard] = state.dashboards;
const { data } = selectedDashboard;
const selectedWidgetIndex = data.widgets?.findIndex(
(e) => e.id === widgetId,
);
const { widgets } = data;
const preWidget = data.widgets?.slice(0, selectedWidgetIndex);
const afterWidget = data.widgets?.slice(
(selectedWidgetIndex || 0) + 1, // this is never undefined
widgets?.length,
);
const selectedWidget =
(selectedDashboard.data.widgets || [])[selectedWidgetIndex || 0] || {};
return {
...state,
dashboards: [
{
...selectedDashboard,
data: {
...data,
widgets: [
...(preWidget || []),
{
...selectedWidget,
queryData: {
...selectedWidget.queryData,
error: errorBoolean,
errorMessage,
},
},
...(afterWidget || []),
],
},
},
],
isQueryFired: true,
isLoadingQueryResult,
};
}
case QUERY_SUCCESS: {
const { widgetId, data: queryDataResponse } = 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];
return {
...state,
dashboards: [
{
...selectedDashboard,
data: {
...data,
widgets: [
...preWidget,
{
...selectedWidget,
queryData: {
data: queryDataResponse,
error: selectedWidget.queryData.error,
errorMessage: selectedWidget.queryData.errorMessage,
loading: false,
},
},
...afterWidget,
],
},
},
],
isQueryFired: true,
isLoadingQueryResult: false,
};
}
case APPLY_SETTINGS_TO_PANEL: { case APPLY_SETTINGS_TO_PANEL: {
const { widgetId } = action.payload; const { widgetId } = action.payload;
@ -367,7 +267,7 @@ const dashboard = (
} }
case UPDATE_QUERY: { case UPDATE_QUERY: {
const { query, widgetId, yAxisUnit } = action.payload; const { widgetId, yAxisUnit } = action.payload;
const { dashboards } = state; const { dashboards } = state;
const [selectedDashboard] = dashboards; const [selectedDashboard] = dashboards;
const { data } = selectedDashboard; const { data } = selectedDashboard;
@ -395,7 +295,6 @@ const dashboard = (
...preWidget, ...preWidget,
{ {
...selectedWidget, ...selectedWidget,
query,
yAxisUnit, yAxisUnit,
}, },
...afterWidget, ...afterWidget,

View File

@ -5,7 +5,6 @@ import {
IDashboardVariable, IDashboardVariable,
Widgets, Widgets,
} from 'types/api/dashboard/getAll'; } from 'types/api/dashboard/getAll';
import { Query } from 'types/api/queryBuilder/queryBuilderData';
import { QueryData } from 'types/api/widgets/getQuery'; import { QueryData } from 'types/api/widgets/getQuery';
export const GET_DASHBOARD = 'GET_DASHBOARD'; export const GET_DASHBOARD = 'GET_DASHBOARD';
@ -30,9 +29,6 @@ export const DELETE_DASHBOARD_ERROR = 'DELETE_DASHBOARD_ERROR';
export const CREATE_DEFAULT_WIDGET = 'CREATE_DEFAULT_WIDGET'; export const CREATE_DEFAULT_WIDGET = 'CREATE_DEFAULT_WIDGET';
export const QUERY_SUCCESS = 'QUERY_SUCCESS';
export const QUERY_ERROR = 'QUERY_ERROR';
export const UPDATE_QUERY = 'UPDATE_QUERY'; export const UPDATE_QUERY = 'UPDATE_QUERY';
export const APPLY_SETTINGS_TO_PANEL = 'APPLY_SETTINGS_TO_PANEL'; export const APPLY_SETTINGS_TO_PANEL = 'APPLY_SETTINGS_TO_PANEL';
@ -132,30 +128,15 @@ export interface QuerySuccessPayload {
// query: string // query: string
}; };
} }
interface QuerySuccess {
type: typeof QUERY_SUCCESS;
payload: QuerySuccessPayload;
}
interface UpdateQuery { interface UpdateQuery {
type: typeof UPDATE_QUERY; type: typeof UPDATE_QUERY;
payload: { payload: {
query: Query;
widgetId: string; widgetId: string;
yAxisUnit: string | undefined; yAxisUnit: string | undefined;
}; };
} }
interface QueryError {
type: typeof QUERY_ERROR;
payload: {
errorMessage: string;
widgetId: string;
errorBoolean?: boolean;
isLoadingQueryResult?: boolean;
};
}
interface SaveDashboardSuccess { interface SaveDashboardSuccess {
type: typeof SAVE_SETTING_TO_PANEL_SUCCESS; type: typeof SAVE_SETTING_TO_PANEL_SUCCESS;
payload: Dashboard; payload: Dashboard;
@ -198,8 +179,6 @@ export type DashboardActions =
| UpdateDashboardTitle | UpdateDashboardTitle
| ToggleEditMode | ToggleEditMode
| CreateDefaultWidget | CreateDefaultWidget
| QuerySuccess
| QueryError
| ApplySettingsToPanel | ApplySettingsToPanel
| SaveDashboardSuccess | SaveDashboardSuccess
| WidgetDeleteSuccess | WidgetDeleteSuccess

View File

@ -3,8 +3,6 @@ import { timePreferenceType } from 'container/NewWidget/RightContainer/timeItems
import { Layout } from 'react-grid-layout'; import { Layout } from 'react-grid-layout';
import { Query } from 'types/api/queryBuilder/queryBuilderData'; import { Query } from 'types/api/queryBuilder/queryBuilderData';
import { QueryData } from '../widgets/getQuery';
export type PayloadProps = Dashboard[]; export type PayloadProps = Dashboard[];
export const VariableQueryTypeArr = ['QUERY', 'TEXTBOX', 'CUSTOM'] as const; export const VariableQueryTypeArr = ['QUERY', 'TEXTBOX', 'CUSTOM'] as const;
@ -65,16 +63,6 @@ export interface IBaseWidget {
opacity: string; opacity: string;
nullZeroValues: string; nullZeroValues: string;
timePreferance: timePreferenceType; timePreferance: timePreferenceType;
queryData: {
loading: boolean;
error: boolean;
errorMessage: string;
data: {
query?: string;
legend?: string;
queryData: QueryData[];
};
};
stepSize?: number; stepSize?: number;
yAxisUnit?: string; yAxisUnit?: string;
} }

View File

@ -6,7 +6,5 @@ export default interface DashboardReducer {
error: boolean; error: boolean;
errorMessage: string; errorMessage: string;
isEditMode: boolean; isEditMode: boolean;
isQueryFired: boolean;
isAddWidget: boolean; isAddWidget: boolean;
isLoadingQueryResult: boolean;
} }