import { useNavigateToExplorer } from 'components/CeleryTask/useNavigateToExplorer'; import { ToggleGraphProps } from 'components/Graph/types'; import { QueryParams } from 'constants/query'; import { PANEL_TYPES } from 'constants/queryBuilder'; import { handleGraphClick } from 'container/GridCardLayout/GridCard/utils'; import { useGraphClickToShowButton } from 'container/GridCardLayout/useGraphClickToShowButton'; import useNavigateToExplorerPages from 'container/GridCardLayout/useNavigateToExplorerPages'; import PanelWrapper from 'container/PanelWrapper/PanelWrapper'; import { CustomTimeType } from 'container/TopNav/DateTimeSelectionV2/config'; import { useIsDarkMode } from 'hooks/useDarkMode'; import { useNotifications } from 'hooks/useNotifications'; import { useSafeNavigate } from 'hooks/useSafeNavigate'; import useUrlQuery from 'hooks/useUrlQuery'; import { GetQueryResultsProps } from 'lib/dashboard/getQueryResults'; import GetMinMax from 'lib/getMinMax'; import getTimeString from 'lib/getTimeString'; import { Dispatch, SetStateAction, useCallback, useEffect, useRef, useState, } from 'react'; import { UseQueryResult } from 'react-query'; import { useDispatch } from 'react-redux'; import { useLocation } from 'react-router-dom'; import { UpdateTimeInterval } from 'store/actions'; import { SuccessResponse } from 'types/api'; import { Widgets } from 'types/api/dashboard/getAll'; import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange'; import { DataSource } from 'types/common/queryBuilder'; function WidgetGraph({ selectedWidget, queryResponse, setRequestData, selectedGraph, }: WidgetGraphProps): JSX.Element { const graphRef = useRef(null); const lineChartRef = useRef(); const dispatch = useDispatch(); const urlQuery = useUrlQuery(); const location = useLocation(); const { safeNavigate } = useSafeNavigate(); // Add legend state management similar to dashboard components const [graphVisibility, setGraphVisibility] = useState( Array((queryResponse.data?.payload?.data?.result?.length || 0) + 1).fill( true, ), ); // Initialize graph visibility when data changes useEffect(() => { if (queryResponse.data?.payload?.data?.result) { setGraphVisibility( Array(queryResponse.data.payload.data.result.length + 1).fill(true), ); } }, [queryResponse.data?.payload?.data?.result]); // Apply graph visibility when lineChartRef is available useEffect(() => { if (!lineChartRef.current) return; graphVisibility.forEach((state, index) => { lineChartRef.current?.toggleGraph(index, state); }); }, [graphVisibility]); const handleBackNavigation = (): void => { const searchParams = new URLSearchParams(window.location.search); const startTime = searchParams.get(QueryParams.startTime); const endTime = searchParams.get(QueryParams.endTime); const relativeTime = searchParams.get( QueryParams.relativeTime, ) as CustomTimeType; if (relativeTime) { dispatch(UpdateTimeInterval(relativeTime)); } else if (startTime && endTime && startTime !== endTime) { dispatch( UpdateTimeInterval('custom', [ parseInt(getTimeString(startTime), 10), parseInt(getTimeString(endTime), 10), ]), ); } }; const onDragSelect = useCallback( (start: number, end: number): void => { const startTimestamp = Math.trunc(start); const endTimestamp = Math.trunc(end); if (startTimestamp !== endTimestamp) { dispatch(UpdateTimeInterval('custom', [startTimestamp, endTimestamp])); } const { maxTime, minTime } = GetMinMax('custom', [ startTimestamp, endTimestamp, ]); urlQuery.set(QueryParams.startTime, minTime.toString()); urlQuery.set(QueryParams.endTime, maxTime.toString()); const generatedUrl = `${location.pathname}?${urlQuery.toString()}`; safeNavigate(generatedUrl); }, [dispatch, location.pathname, safeNavigate, urlQuery], ); useEffect(() => { window.addEventListener('popstate', handleBackNavigation); return (): void => { window.removeEventListener('popstate', handleBackNavigation); }; // eslint-disable-next-line react-hooks/exhaustive-deps }, []); const isDarkMode = useIsDarkMode(); // context redirection to explorer pages const graphClick = useGraphClickToShowButton({ graphRef, isButtonEnabled: (selectedWidget?.query?.builder?.queryData ?? []).some( (q) => q.dataSource === DataSource.TRACES || q.dataSource === DataSource.LOGS, ), buttonClassName: 'view-onclick-show-button', }); const navigateToExplorer = useNavigateToExplorer(); const navigateToExplorerPages = useNavigateToExplorerPages(); const { notifications } = useNotifications(); const graphClickHandler = ( xValue: number, yValue: number, mouseX: number, mouseY: number, metric?: { [key: string]: string }, queryData?: { queryName: string; inFocusOrNot: boolean }, ): void => { handleGraphClick({ xValue, yValue, mouseX, mouseY, metric, queryData, widget: selectedWidget, navigateToExplorerPages, navigateToExplorer, notifications, graphClick, }); }; return (
); } interface WidgetGraphProps { selectedWidget: Widgets; queryResponse: UseQueryResult< SuccessResponse, Error >; setRequestData: Dispatch>; selectedGraph: PANEL_TYPES; } export default WidgetGraph;