From 1eabacbaf487c4b07eb9ffdd1364c7779debee2f Mon Sep 17 00:00:00 2001 From: dnazarenkoo <134951516+dnazarenkoo@users.noreply.github.com> Date: Wed, 28 Jun 2023 15:55:20 +0300 Subject: [PATCH] feat: add the export panel to the traces explorer (#2983) * feat: add the export panel to the traces explorer * feat: onExport dashboard widget is updated * chore: made common hook useDashboard --------- Co-authored-by: Palash Gupta --- frontend/src/constants/query.ts | 2 + .../src/container/ExportPanel/ExportPanel.tsx | 34 ++++--- frontend/src/container/ExportPanel/index.tsx | 10 +- .../hooks/dashboard/useGetAllDashboard.tsx | 16 ++++ .../hooks/dashboard/useUpdateDashboard.tsx | 14 +++ frontend/src/hooks/dashboard/utils.ts | 37 ++++++++ frontend/src/pages/TracesExplorer/index.tsx | 93 +++++++++++++++---- frontend/src/pages/TracesExplorer/styles.ts | 5 + 8 files changed, 181 insertions(+), 30 deletions(-) create mode 100644 frontend/src/hooks/dashboard/useGetAllDashboard.tsx create mode 100644 frontend/src/hooks/dashboard/useUpdateDashboard.tsx create mode 100644 frontend/src/hooks/dashboard/utils.ts diff --git a/frontend/src/constants/query.ts b/frontend/src/constants/query.ts index 35c1e2c2ca..ec8dd54e2b 100644 --- a/frontend/src/constants/query.ts +++ b/frontend/src/constants/query.ts @@ -12,4 +12,6 @@ export enum QueryParams { aggregationOption = 'aggregationOption', entity = 'entity', resourceAttributes = 'resourceAttribute', + graphType = 'graphType', + widgetId = 'widgetId', } diff --git a/frontend/src/container/ExportPanel/ExportPanel.tsx b/frontend/src/container/ExportPanel/ExportPanel.tsx index 2cd24e25d1..80092c75dc 100644 --- a/frontend/src/container/ExportPanel/ExportPanel.tsx +++ b/frontend/src/container/ExportPanel/ExportPanel.tsx @@ -1,12 +1,11 @@ import { Button, Typography } from 'antd'; import createDashboard from 'api/dashboard/create'; -import getAll from 'api/dashboard/getAll'; import axios from 'axios'; -import { REACT_QUERY_KEY } from 'constants/reactQueryKeys'; +import { useGetAllDashboard } from 'hooks/dashboard/useGetAllDashboard'; import { useNotifications } from 'hooks/useNotifications'; import { useCallback, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { useMutation, useQuery } from 'react-query'; +import { useMutation } from 'react-query'; import { ExportPanelProps } from '.'; import { @@ -18,7 +17,7 @@ import { } from './styles'; import { getSelectOptions } from './utils'; -function ExportPanel({ onExport }: ExportPanelProps): JSX.Element { +function ExportPanel({ isLoading, onExport }: ExportPanelProps): JSX.Element { const { notifications } = useNotifications(); const { t } = useTranslation(['dashboard']); @@ -26,16 +25,18 @@ function ExportPanel({ onExport }: ExportPanelProps): JSX.Element { null, ); - const { data, isLoading, refetch } = useQuery({ - queryFn: getAll, - queryKey: REACT_QUERY_KEY.GET_ALL_DASHBOARDS, - }); + const { + data, + isLoading: isAllDashboardsLoading, + refetch, + } = useGetAllDashboard(); const { mutate: createNewDashboard, isLoading: createDashboardLoading, } = useMutation(createDashboard, { - onSuccess: () => { + onSuccess: (data) => { + onExport(data?.payload || null); refetch(); }, onError: (error) => { @@ -73,6 +74,14 @@ function ExportPanel({ onExport }: ExportPanelProps): JSX.Element { }); }, [t, createNewDashboard]); + const isDashboardLoading = isAllDashboardsLoading || createDashboardLoading; + + const isDisabled = + isAllDashboardsLoading || + !options?.length || + !selectedDashboardId || + isLoading; + return ( Export Panel @@ -81,14 +90,15 @@ function ExportPanel({ onExport }: ExportPanelProps): JSX.Element { - + ); } +ExportPanel.defaultProps = { + isLoading: false, +}; + interface OnClickProps { key: string; } export interface ExportPanelProps { + isLoading?: boolean; onExport: (dashboard: Dashboard | null) => void; } diff --git a/frontend/src/hooks/dashboard/useGetAllDashboard.tsx b/frontend/src/hooks/dashboard/useGetAllDashboard.tsx new file mode 100644 index 0000000000..aced8e6e2e --- /dev/null +++ b/frontend/src/hooks/dashboard/useGetAllDashboard.tsx @@ -0,0 +1,16 @@ +import getAll from 'api/dashboard/getAll'; +import { REACT_QUERY_KEY } from 'constants/reactQueryKeys'; +import { useQuery, UseQueryResult } from 'react-query'; +import { ErrorResponse, SuccessResponse } from 'types/api'; +import { PayloadProps } from 'types/api/dashboard/getAll'; + +export const useGetAllDashboard = (): DashboardProps => + useQuery({ + queryFn: getAll, + queryKey: REACT_QUERY_KEY.GET_ALL_DASHBOARDS, + }); + +type DashboardProps = UseQueryResult< + SuccessResponse | ErrorResponse, + unknown +>; diff --git a/frontend/src/hooks/dashboard/useUpdateDashboard.tsx b/frontend/src/hooks/dashboard/useUpdateDashboard.tsx new file mode 100644 index 0000000000..b4c34974dc --- /dev/null +++ b/frontend/src/hooks/dashboard/useUpdateDashboard.tsx @@ -0,0 +1,14 @@ +import update from 'api/dashboard/update'; +import { useMutation, UseMutationResult } from 'react-query'; +import { ErrorResponse, SuccessResponse } from 'types/api'; +import { Dashboard } from 'types/api/dashboard/getAll'; +import { Props } from 'types/api/dashboard/update'; + +export const useUpdateDashboard = (): UseUpdateDashboard => useMutation(update); + +type UseUpdateDashboard = UseMutationResult< + SuccessResponse | ErrorResponse, + unknown, + Props, + unknown +>; diff --git a/frontend/src/hooks/dashboard/utils.ts b/frontend/src/hooks/dashboard/utils.ts new file mode 100644 index 0000000000..ea2457daa8 --- /dev/null +++ b/frontend/src/hooks/dashboard/utils.ts @@ -0,0 +1,37 @@ +import { PANEL_TYPES } from 'constants/queryBuilder'; +import { Dashboard } from 'types/api/dashboard/getAll'; +import { Query } from 'types/api/queryBuilder/queryBuilderData'; + +export const addEmptyWidgetInDashboardJSONWithQuery = ( + dashboard: Dashboard, + query: Query, +): Dashboard => ({ + ...dashboard, + data: { + ...dashboard.data, + layout: [ + { + i: 'empty', + w: 6, + x: 0, + h: 2, + y: 0, + }, + ...(dashboard?.data?.layout || []), + ], + widgets: [ + ...(dashboard?.data?.widgets || []), + { + id: 'empty', + query, + description: '', + isStacked: false, + nullZeroValues: '', + opacity: '', + title: '', + timePreferance: 'GLOBAL_TIME', + panelTypes: PANEL_TYPES.TIME_SERIES, + }, + ], + }, +}); diff --git a/frontend/src/pages/TracesExplorer/index.tsx b/frontend/src/pages/TracesExplorer/index.tsx index 137e3bfbf5..f1215bc1ce 100644 --- a/frontend/src/pages/TracesExplorer/index.tsx +++ b/frontend/src/pages/TracesExplorer/index.tsx @@ -1,28 +1,95 @@ import { Tabs } from 'antd'; +import axios from 'axios'; +import { QueryParams } from 'constants/query'; import { initialQueriesMap, PANEL_TYPES } from 'constants/queryBuilder'; -import { PANEL_TYPES_QUERY } from 'constants/queryBuilderQueryNames'; +import { + COMPOSITE_QUERY, + PANEL_TYPES_QUERY, +} from 'constants/queryBuilderQueryNames'; +import ROUTES from 'constants/routes'; +import ExportPanel from 'container/ExportPanel'; import { GRAPH_TYPES } from 'container/NewDashboard/ComponentsSlider'; import QuerySection from 'container/TracesExplorer/QuerySection'; +import { useUpdateDashboard } from 'hooks/dashboard/useUpdateDashboard'; +import { addEmptyWidgetInDashboardJSONWithQuery } from 'hooks/dashboard/utils'; import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder'; import { useShareBuilderUrl } from 'hooks/queryBuilder/useShareBuilderUrl'; +import { useNotifications } from 'hooks/useNotifications'; +import history from 'lib/history'; import { useCallback, useMemo } from 'react'; +import { generatePath } from 'react-router-dom'; +import { Dashboard } from 'types/api/dashboard/getAll'; import { DataSource } from 'types/common/queryBuilder'; -import { Container } from './styles'; +import { ActionsWrapper, Container } from './styles'; import { getTabsItems } from './utils'; function TracesExplorer(): JSX.Element { + const { notifications } = useNotifications(); const { + currentQuery, + stagedQuery, + panelType, updateAllQueriesOperators, redirectWithQueryBuilderData, - currentQuery, - panelType, } = useQueryBuilder(); const tabsItems = getTabsItems(); - const currentTab = panelType || PANEL_TYPES.TIME_SERIES; + const defaultQuery = useMemo( + () => + updateAllQueriesOperators( + initialQueriesMap.traces, + PANEL_TYPES.TIME_SERIES, + DataSource.TRACES, + ), + [updateAllQueriesOperators], + ); + + const exportDefaultQuery = useMemo( + () => + updateAllQueriesOperators( + stagedQuery || initialQueriesMap.traces, + PANEL_TYPES.TIME_SERIES, + DataSource.TRACES, + ), + [stagedQuery, updateAllQueriesOperators], + ); + + const { mutate: updateDashboard, isLoading } = useUpdateDashboard(); + + const handleExport = useCallback( + (dashboard: Dashboard | null): void => { + if (!dashboard) return; + + const updatedDashboard = addEmptyWidgetInDashboardJSONWithQuery( + dashboard, + exportDefaultQuery, + ); + + updateDashboard(updatedDashboard, { + onSuccess: (data) => { + const dashboardEditView = `${generatePath(ROUTES.DASHBOARD, { + dashboardId: data?.payload?.uuid, + })}/new?${QueryParams.graphType}=graph&${ + QueryParams.widgetId + }=empty&${COMPOSITE_QUERY}=${JSON.stringify(exportDefaultQuery)}`; + + history.push(dashboardEditView); + }, + onError: (error) => { + if (axios.isAxiosError(error)) { + notifications.error({ + message: error.message, + }); + } + }, + }); + }, + [exportDefaultQuery, notifications, updateDashboard], + ); + const handleTabChange = useCallback( (newPanelType: string): void => { if (panelType === newPanelType) return; @@ -43,23 +110,17 @@ function TracesExplorer(): JSX.Element { ], ); - const defaultValue = useMemo( - () => - updateAllQueriesOperators( - initialQueriesMap.traces, - PANEL_TYPES.TIME_SERIES, - DataSource.TRACES, - ), - [updateAllQueriesOperators], - ); - - useShareBuilderUrl(defaultValue); + useShareBuilderUrl(defaultQuery); return ( <> + + + +