From fe73ca63a09eaaf981cb25b4e88ea9b97a5ad9f9 Mon Sep 17 00:00:00 2001 From: SagarRajput-7 <162284829+SagarRajput-7@users.noreply.github.com> Date: Mon, 3 Mar 2025 11:22:14 +0530 Subject: [PATCH] fix: fixed view trace or logs button on graph not disappearing on outside click (#7177) * fix: fixed view trace or logs button on graph not disappearing on outside click * fix: removed older function --- .../CeleryTaskLatencyGraph.tsx | 13 ++++----- .../MetricsApplication/Tabs/DBCall.tsx | 8 +++--- .../MetricsApplication/Tabs/External.tsx | 12 +++++---- .../MetricsApplication/Tabs/Overview.tsx | 14 ++++------ .../container/MetricsApplication/Tabs/util.ts | 27 ++++++++++++++++--- frontend/src/hooks/useClickOutside.tsx | 6 +++-- .../OverviewRightPanelGraph.tsx | 14 ++++------ 7 files changed, 54 insertions(+), 40 deletions(-) diff --git a/frontend/src/components/CeleryTask/CeleryTaskGraph/CeleryTaskLatencyGraph.tsx b/frontend/src/components/CeleryTask/CeleryTaskGraph/CeleryTaskLatencyGraph.tsx index 5128823382..b45299093b 100644 --- a/frontend/src/components/CeleryTask/CeleryTaskGraph/CeleryTaskLatencyGraph.tsx +++ b/frontend/src/components/CeleryTask/CeleryTaskGraph/CeleryTaskLatencyGraph.tsx @@ -8,7 +8,7 @@ import { ViewMenuAction } from 'container/GridCardLayout/config'; import GridCard from 'container/GridCardLayout/GridCard'; import { Card } from 'container/GridCardLayout/styles'; import { Button } from 'container/MetricsApplication/Tabs/styles'; -import { onGraphClickHandler } from 'container/MetricsApplication/Tabs/util'; +import { useGraphClickHandler } from 'container/MetricsApplication/Tabs/util'; import { useIsDarkMode } from 'hooks/useDarkMode'; import useUrlQuery from 'hooks/useUrlQuery'; import { OnClickPluginOpts } from 'lib/uPlotLib/plugins/onClickPlugin'; @@ -122,6 +122,8 @@ function CeleryTaskLatencyGraph({ setSelectedTimeStamp(selectTime); }, []); + const onGraphClickHandler = useGraphClickHandler(handleSetTimeStamp); + const onGraphClick = useCallback( (type: string): OnClickPluginOpts['onClick'] => ( xValue, @@ -137,14 +139,9 @@ function CeleryTaskLatencyGraph({ value, }); - return onGraphClickHandler(handleSetTimeStamp)( - xValue, - yValue, - mouseX, - mouseY, - type, - ); + return onGraphClickHandler(xValue, yValue, mouseX, mouseY, type); }, + // eslint-disable-next-line react-hooks/exhaustive-deps [handleSetTimeStamp], ); diff --git a/frontend/src/container/MetricsApplication/Tabs/DBCall.tsx b/frontend/src/container/MetricsApplication/Tabs/DBCall.tsx index 277e9d7dd6..45da3bfd58 100644 --- a/frontend/src/container/MetricsApplication/Tabs/DBCall.tsx +++ b/frontend/src/container/MetricsApplication/Tabs/DBCall.tsx @@ -34,9 +34,9 @@ import { IServiceName } from './types'; import { dbSystemTags, handleNonInQueryRange, - onGraphClickHandler, onViewTracePopupClick, useGetAPMToTracesQueries, + useGraphClickHandler, } from './util'; function DBCall(): JSX.Element { @@ -160,6 +160,8 @@ function DBCall(): JSX.Element { }); const { safeNavigate } = useSafeNavigate(); + const onGraphClickHandler = useGraphClickHandler(setSelectedTimeStamp); + return ( @@ -183,7 +185,7 @@ function DBCall(): JSX.Element { { - onGraphClickHandler(setSelectedTimeStamp)( + onGraphClickHandler( xValue, yValue, mouseX, @@ -221,7 +223,7 @@ function DBCall(): JSX.Element { widget={databaseCallsAverageDurationWidget} headerMenuList={MENU_ITEMS} onClickHandler={(xValue, yValue, mouseX, mouseY): void => { - onGraphClickHandler(setSelectedTimeStamp)( + onGraphClickHandler( xValue, yValue, mouseX, diff --git a/frontend/src/container/MetricsApplication/Tabs/External.tsx b/frontend/src/container/MetricsApplication/Tabs/External.tsx index c3d86cc3b2..b17a722e54 100644 --- a/frontend/src/container/MetricsApplication/Tabs/External.tsx +++ b/frontend/src/container/MetricsApplication/Tabs/External.tsx @@ -35,9 +35,9 @@ import { Button } from './styles'; import { IServiceName } from './types'; import { handleNonInQueryRange, - onGraphClickHandler, onViewTracePopupClick, useGetAPMToTracesQueries, + useGraphClickHandler, } from './util'; function External(): JSX.Element { @@ -223,6 +223,8 @@ function External(): JSX.Element { const { safeNavigate } = useSafeNavigate(); + const onGraphClickHandler = useGraphClickHandler(setSelectedTimeStamp); + return ( <> @@ -248,7 +250,7 @@ function External(): JSX.Element { headerMenuList={MENU_ITEMS} widget={externalCallErrorWidget} onClickHandler={(xValue, yValue, mouseX, mouseY): void => { - onGraphClickHandler(setSelectedTimeStamp)( + onGraphClickHandler( xValue, yValue, mouseX, @@ -286,7 +288,7 @@ function External(): JSX.Element { headerMenuList={MENU_ITEMS} widget={externalCallDurationWidget} onClickHandler={(xValue, yValue, mouseX, mouseY): void => { - onGraphClickHandler(setSelectedTimeStamp)( + onGraphClickHandler( xValue, yValue, mouseX, @@ -325,7 +327,7 @@ function External(): JSX.Element { widget={externalCallRPSWidget} headerMenuList={MENU_ITEMS} onClickHandler={(xValue, yValue, mouseX, mouseY): Promise => - onGraphClickHandler(setSelectedTimeStamp)( + onGraphClickHandler( xValue, yValue, mouseX, @@ -363,7 +365,7 @@ function External(): JSX.Element { widget={externalCallDurationAddressWidget} headerMenuList={MENU_ITEMS} onClickHandler={(xValue, yValue, mouseX, mouseY): void => { - onGraphClickHandler(setSelectedTimeStamp)( + onGraphClickHandler( xValue, yValue, mouseX, diff --git a/frontend/src/container/MetricsApplication/Tabs/Overview.tsx b/frontend/src/container/MetricsApplication/Tabs/Overview.tsx index d96034e9af..1492924249 100644 --- a/frontend/src/container/MetricsApplication/Tabs/Overview.tsx +++ b/frontend/src/container/MetricsApplication/Tabs/Overview.tsx @@ -51,10 +51,10 @@ import { IServiceName } from './types'; import { generateExplorerPath, handleNonInQueryRange, - onGraphClickHandler, onViewTracePopupClick, useGetAPMToLogsQueries, useGetAPMToTracesQueries, + useGraphClickHandler, } from './util'; function Application(): JSX.Element { @@ -79,6 +79,8 @@ function Application(): JSX.Element { setSelectedTimeStamp(selectTime); }, []); + const onGraphClickHandler = useGraphClickHandler(handleSetTimeStamp); + const dispatch = useDispatch(); const handleGraphClick = useCallback( (type: string): OnClickPluginOpts['onClick'] => ( @@ -86,14 +88,8 @@ function Application(): JSX.Element { yValue, mouseX, mouseY, - ): Promise => - onGraphClickHandler(handleSetTimeStamp)( - xValue, - yValue, - mouseX, - mouseY, - type, - ), + ): Promise => onGraphClickHandler(xValue, yValue, mouseX, mouseY, type), + // eslint-disable-next-line react-hooks/exhaustive-deps [handleSetTimeStamp], ); diff --git a/frontend/src/container/MetricsApplication/Tabs/util.ts b/frontend/src/container/MetricsApplication/Tabs/util.ts index f48b346b46..674ba4b195 100644 --- a/frontend/src/container/MetricsApplication/Tabs/util.ts +++ b/frontend/src/container/MetricsApplication/Tabs/util.ts @@ -4,11 +4,12 @@ import ROUTES from 'constants/routes'; import { routeConfig } from 'container/SideNav/config'; import { getQueryString } from 'container/SideNav/helper'; import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder'; +import useClickOutside from 'hooks/useClickOutside'; import useResourceAttribute from 'hooks/useResourceAttribute'; import { resourceAttributesToTracesFilterItems } from 'hooks/useResourceAttribute/utils'; import { prepareQueryWithDefaultTimestamp } from 'pages/LogsExplorer/utils'; import { traceFilterKeys } from 'pages/TracesExplorer/Filter/filterUtils'; -import { Dispatch, SetStateAction, useMemo } from 'react'; +import { Dispatch, SetStateAction, useMemo, useRef } from 'react'; import { BaseAutocompleteData, DataTypes, @@ -106,9 +107,27 @@ export function onViewTracePopupClick({ }; } -export function onGraphClickHandler( +export function useGraphClickHandler( setSelectedTimeStamp: (n: number) => void | Dispatch>, -) { +): ( + xValue: number, + yValue: number, + mouseX: number, + mouseY: number, + type: string, +) => Promise { + const buttonRef = useRef(null); + + useClickOutside({ + ref: buttonRef, + onClickOutside: () => { + if (buttonRef.current) { + buttonRef.current.style.display = 'none'; + } + }, + eventType: 'mousedown', + }); + return async ( xValue: number, yValue: number, @@ -117,8 +136,8 @@ export function onGraphClickHandler( type: string, ): Promise => { const id = `${type}_button`; - const buttonElement = document.getElementById(id); + buttonRef.current = buttonElement; if (xValue) { if (buttonElement) { diff --git a/frontend/src/hooks/useClickOutside.tsx b/frontend/src/hooks/useClickOutside.tsx index d53415dbb6..3e37b93484 100644 --- a/frontend/src/hooks/useClickOutside.tsx +++ b/frontend/src/hooks/useClickOutside.tsx @@ -3,11 +3,13 @@ import { useEffect } from 'react'; type UseClickOutsideProps = { ref: React.RefObject; onClickOutside: () => void; + eventType?: 'mousedown' | 'mouseup' | 'click' | 'dblclick'; }; const useClickOutside = ({ ref, onClickOutside, + eventType, }: UseClickOutsideProps): void => { const handleClickOutside = (event: MouseEvent): void => { if (ref.current && !ref.current.contains(event.target as Node)) { @@ -16,10 +18,10 @@ const useClickOutside = ({ }; useEffect(() => { - document.addEventListener('click', handleClickOutside); + document.addEventListener(eventType ?? 'click', handleClickOutside); return (): void => { - document.removeEventListener('click', handleClickOutside); + document.removeEventListener(eventType ?? 'click', handleClickOutside); }; // eslint-disable-next-line react-hooks/exhaustive-deps }, [ref, onClickOutside]); diff --git a/frontend/src/pages/Celery/CeleryOverview/CeleryOverviewDetail/OverviewRightPanelGraph.tsx b/frontend/src/pages/Celery/CeleryOverview/CeleryOverviewDetail/OverviewRightPanelGraph.tsx index 5663d7fb4d..fb573c9bec 100644 --- a/frontend/src/pages/Celery/CeleryOverview/CeleryOverviewDetail/OverviewRightPanelGraph.tsx +++ b/frontend/src/pages/Celery/CeleryOverview/CeleryOverviewDetail/OverviewRightPanelGraph.tsx @@ -7,7 +7,7 @@ import { QueryParams } from 'constants/query'; import { ViewMenuAction } from 'container/GridCardLayout/config'; import GridCard from 'container/GridCardLayout/GridCard'; import { Button } from 'container/MetricsApplication/Tabs/styles'; -import { onGraphClickHandler } from 'container/MetricsApplication/Tabs/util'; +import { useGraphClickHandler } from 'container/MetricsApplication/Tabs/util'; import useUrlQuery from 'hooks/useUrlQuery'; import { OnClickPluginOpts } from 'lib/uPlotLib/plugins/onClickPlugin'; import { useCallback, useEffect, useMemo, useState } from 'react'; @@ -84,20 +84,16 @@ export default function OverviewRightPanelGraph({ const navigateToTraces = useNavigateToTraces(); + const onGraphClickHandler = useGraphClickHandler(handleSetTimeStamp); + const handleGraphClick = useCallback( (type: string): OnClickPluginOpts['onClick'] => ( xValue, yValue, mouseX, mouseY, - ): Promise => - onGraphClickHandler(handleSetTimeStamp)( - xValue, - yValue, - mouseX, - mouseY, - type, - ), + ): Promise => onGraphClickHandler(xValue, yValue, mouseX, mouseY, type), + // eslint-disable-next-line react-hooks/exhaustive-deps [handleSetTimeStamp], );