Compare commits

...

21 Commits

Author SHA1 Message Date
Srikanth Chekuri
18e856f62c Merge branch 'main' into perf/panel-rerender 2025-12-16 09:44:30 +05:30
Abhi kumar
c0bd545e26 Merge branch 'main' into perf/panel-rerender 2025-12-02 16:47:40 +05:30
Abhi kumar
346be7b7ba Merge branch 'main' into perf/panel-rerender 2025-11-19 11:19:01 +05:30
Abhi kumar
10176e3128 Merge branch 'main' into perf/panel-rerender 2025-11-19 09:57:07 +05:30
Abhi kumar
a6832d6ed0 Merge branch 'main' into perf/panel-rerender 2025-11-18 16:17:58 +05:30
Abhi kumar
5504e90620 Merge branch 'main' into perf/panel-rerender 2025-11-17 10:43:08 +05:30
Srikanth Chekuri
19cffa0165 Merge branch 'main' into perf/panel-rerender 2025-11-13 23:21:05 +05:30
Abhi kumar
4dc4a0b95e Merge branch 'main' into perf/panel-rerender 2025-11-13 11:44:04 +05:30
Srikanth Chekuri
2462f551be Merge branch 'main' into perf/panel-rerender 2025-11-11 13:15:30 +05:30
Abhi Kumar
78ab80d294 fix: removed unnessasary usememo 2025-11-06 17:59:34 +05:30
Abhi Kumar
d285b90f09 Merge branch 'main' of https://github.com/SigNoz/signoz into perf/panel-rerender 2025-11-06 17:53:45 +05:30
Abhi kumar
08e756cf5d Merge branch 'main' into perf/panel-rerender 2025-11-06 17:08:48 +05:30
Abhi Kumar
42c1ddda39 chore: removing deepcompare for all the props 2025-11-06 15:45:27 +05:30
Abhi Kumar
efb85fc205 Merge branch 'main' of https://github.com/SigNoz/signoz into perf/panel-rerender 2025-11-06 14:57:34 +05:30
Abhi Kumar
0e972257db perf: memoize click handlers and use refs for dashboard mutations 2025-11-06 11:36:01 +05:30
Abhi Kumar
f8144e3a1d perf: added deep comparision for props 2025-11-06 11:31:11 +05:30
Abhi Kumar
02a8a11976 chore: removed useMemo from clickhandler 2025-11-06 11:29:10 +05:30
Abhi Kumar
4a351e5280 perf: added changes to make onclickhandler stable 2025-11-06 11:28:27 +05:30
Abhi Kumar
311257a518 perf: memoized panelwrapper and not rerendering it when onclickhandler is changing 2025-11-06 02:31:25 +05:30
Abhi Kumar
d5c665a72a perf: only calling getUplotchartdata when the props are changing 2025-11-06 02:27:31 +05:30
Abhi Kumar
0d6c8785d9 perf: memoized certain expensive functions 2025-11-06 02:26:51 +05:30
7 changed files with 355 additions and 166 deletions

View File

@@ -132,34 +132,117 @@ function CeleryTaskBar({
[selectedFilters, celerySuccessStateData], [selectedFilters, celerySuccessStateData],
); );
const onGraphClick = ( const onGraphClick = useCallback(
widgetData: Widgets, (
xValue: number, widgetData: Widgets,
_yValue: number, xValue: number,
_mouseX: number, _yValue: number,
_mouseY: number, _mouseX: number,
data?: { _mouseY: number,
[key: string]: string; data?: {
[key: string]: string;
},
): void => {
const { start, end } = getStartAndEndTimesInMilliseconds(xValue);
// Extract entity and value from data
const [firstDataPoint] = Object.entries(data || {});
const [entity, value] = (firstDataPoint || ([] as unknown)) as [
string,
string,
];
if (!isEmpty(entity) || !isEmpty(value)) {
onClick?.({
entity,
value,
timeRange: [start, end],
widgetData,
});
}
}, },
): void => { [onClick],
const { start, end } = getStartAndEndTimesInMilliseconds(xValue); );
// Extract entity and value from data const onAllStateClick = useCallback(
const [firstDataPoint] = Object.entries(data || {}); (
const [entity, value] = (firstDataPoint || ([] as unknown)) as [ xValue: number,
string, yValue: number,
string, mouseX: number,
]; mouseY: number,
data?: any,
): void => {
onGraphClick(
celerySlowestTasksTableWidgetData,
xValue,
yValue,
mouseX,
mouseY,
data,
);
},
[onGraphClick],
);
if (!isEmpty(entity) || !isEmpty(value)) { const onFailedStateClick = useCallback(
onClick?.({ (
entity, xValue: number,
value, yValue: number,
timeRange: [start, end], mouseX: number,
widgetData, mouseY: number,
}); data?: any,
} ): void => {
}; onGraphClick(
celeryFailedTasksTableWidgetData,
xValue,
yValue,
mouseX,
mouseY,
data,
);
},
[onGraphClick],
);
const onRetryStateClick = useCallback(
(
xValue: number,
yValue: number,
mouseX: number,
mouseY: number,
data?: any,
): void => {
onGraphClick(
celeryRetryTasksTableWidgetData,
xValue,
yValue,
mouseX,
mouseY,
data,
);
},
[onGraphClick],
);
const onSuccessStateClick = useCallback(
(
xValue: number,
yValue: number,
mouseX: number,
mouseY: number,
data?: any,
): void => {
onGraphClick(
celerySuccessTasksTableWidgetData,
xValue,
yValue,
mouseX,
mouseY,
data,
);
},
[onGraphClick],
);
const { getCustomSeries } = useGetGraphCustomSeries({ const { getCustomSeries } = useGetGraphCustomSeries({
isDarkMode, isDarkMode,
@@ -185,16 +268,7 @@ function CeleryTaskBar({
headerMenuList={[...ViewMenuAction]} headerMenuList={[...ViewMenuAction]}
onDragSelect={onDragSelect} onDragSelect={onDragSelect}
isQueryEnabled={queryEnabled} isQueryEnabled={queryEnabled}
onClickHandler={(xValue, yValue, mouseX, mouseY, data): void => onClickHandler={onAllStateClick}
onGraphClick(
celerySlowestTasksTableWidgetData,
xValue,
yValue,
mouseX,
mouseY,
data,
)
}
customSeries={getCustomSeries} customSeries={getCustomSeries}
dataAvailable={checkIfDataExists} dataAvailable={checkIfDataExists}
/> />
@@ -205,16 +279,7 @@ function CeleryTaskBar({
headerMenuList={[...ViewMenuAction]} headerMenuList={[...ViewMenuAction]}
onDragSelect={onDragSelect} onDragSelect={onDragSelect}
isQueryEnabled={queryEnabled} isQueryEnabled={queryEnabled}
onClickHandler={(xValue, yValue, mouseX, mouseY, data): void => onClickHandler={onFailedStateClick}
onGraphClick(
celeryFailedTasksTableWidgetData,
xValue,
yValue,
mouseX,
mouseY,
data,
)
}
customSeries={getCustomSeries} customSeries={getCustomSeries}
/> />
)} )}
@@ -224,16 +289,7 @@ function CeleryTaskBar({
headerMenuList={[...ViewMenuAction]} headerMenuList={[...ViewMenuAction]}
onDragSelect={onDragSelect} onDragSelect={onDragSelect}
isQueryEnabled={queryEnabled} isQueryEnabled={queryEnabled}
onClickHandler={(xValue, yValue, mouseX, mouseY, data): void => onClickHandler={onRetryStateClick}
onGraphClick(
celeryRetryTasksTableWidgetData,
xValue,
yValue,
mouseX,
mouseY,
data,
)
}
customSeries={getCustomSeries} customSeries={getCustomSeries}
/> />
)} )}
@@ -243,16 +299,7 @@ function CeleryTaskBar({
headerMenuList={[...ViewMenuAction]} headerMenuList={[...ViewMenuAction]}
onDragSelect={onDragSelect} onDragSelect={onDragSelect}
isQueryEnabled={queryEnabled} isQueryEnabled={queryEnabled}
onClickHandler={(xValue, yValue, mouseX, mouseY, data): void => onClickHandler={onSuccessStateClick}
onGraphClick(
celerySuccessTasksTableWidgetData,
xValue,
yValue,
mouseX,
mouseY,
data,
)
}
customSeries={getCustomSeries} customSeries={getCustomSeries}
/> />
)} )}

View File

@@ -26,6 +26,7 @@ import {
SetStateAction, SetStateAction,
useCallback, useCallback,
useEffect, useEffect,
useMemo,
useRef, useRef,
useState, useState,
} from 'react'; } from 'react';
@@ -76,6 +77,7 @@ function WidgetGraphComponent({
const isFullViewOpen = params.get(QueryParams.expandedWidgetId) === widget.id; const isFullViewOpen = params.get(QueryParams.expandedWidgetId) === widget.id;
const lineChartRef = useRef<ToggleGraphProps>(); const lineChartRef = useRef<ToggleGraphProps>();
const [graphVisibility, setGraphVisibility] = useState<boolean[]>( const [graphVisibility, setGraphVisibility] = useState<boolean[]>(
Array(queryResponse.data?.payload?.data?.result?.length || 0).fill(true), Array(queryResponse.data?.payload?.data?.result?.length || 0).fill(true),
); );
@@ -110,7 +112,7 @@ function WidgetGraphComponent({
const updateDashboardMutation = useUpdateDashboard(); const updateDashboardMutation = useUpdateDashboard();
const onDeleteHandler = (): void => { const onDeleteHandler = useCallback((): void => {
if (!selectedDashboard) return; if (!selectedDashboard) return;
const updatedWidgets = selectedDashboard?.data?.widgets?.filter( const updatedWidgets = selectedDashboard?.data?.widgets?.filter(
@@ -138,9 +140,15 @@ function WidgetGraphComponent({
setDeleteModal(false); setDeleteModal(false);
}, },
}); });
}; }, [
selectedDashboard,
widget.id,
updateDashboardMutation,
setLayouts,
setSelectedDashboard,
]);
const onCloneHandler = async (): Promise<void> => { const onCloneHandler = useCallback(async (): Promise<void> => {
if (!selectedDashboard) return; if (!selectedDashboard) return;
const uuid = v4(); const uuid = v4();
@@ -204,9 +212,18 @@ function WidgetGraphComponent({
}, },
}, },
); );
}; }, [
selectedDashboard,
widget,
updateDashboardMutation,
setLayouts,
setSelectedDashboard,
notifications,
safeNavigate,
pathname,
]);
const handleOnView = (): void => { const handleOnView = useCallback((): void => {
const queryParams = { const queryParams = {
[QueryParams.expandedWidgetId]: widget.id, [QueryParams.expandedWidgetId]: widget.id,
}; };
@@ -225,17 +242,17 @@ function WidgetGraphComponent({
pathname, pathname,
search: newSearch, search: newSearch,
}); });
}; }, [widget.id, search, pathname, safeNavigate]);
const handleOnDelete = (): void => { const handleOnDelete = useCallback((): void => {
onToggleModal(setDeleteModal); onToggleModal(setDeleteModal);
}; }, [onToggleModal]);
const onDeleteModelHandler = (): void => { const onDeleteModelHandler = useCallback((): void => {
onToggleModal(setDeleteModal); onToggleModal(setDeleteModal);
}; }, [onToggleModal]);
const onToggleModelHandler = (): void => { const onToggleModelHandler = useCallback((): void => {
const existingSearchParams = new URLSearchParams(search); const existingSearchParams = new URLSearchParams(search);
existingSearchParams.delete(QueryParams.expandedWidgetId); existingSearchParams.delete(QueryParams.expandedWidgetId);
existingSearchParams.delete(QueryParams.compositeQuery); existingSearchParams.delete(QueryParams.compositeQuery);
@@ -254,63 +271,84 @@ function WidgetGraphComponent({
pathname, pathname,
search: createQueryParams(updatedQueryParams), search: createQueryParams(updatedQueryParams),
}); });
}; }, [search, queryResponse.data?.payload, widget.id, pathname, safeNavigate]);
const [searchTerm, setSearchTerm] = useState<string>(''); const [searchTerm, setSearchTerm] = useState<string>('');
// Memoize the isButtonEnabled value to prevent recalculation
const isGraphClickButtonEnabled = useMemo(
() =>
(widget?.query?.builder?.queryData &&
Array.isArray(widget.query.builder.queryData)
? widget.query.builder.queryData
: []
).some(
(q) =>
q.dataSource === DataSource.TRACES || q.dataSource === DataSource.LOGS,
),
[widget?.query?.builder?.queryData],
);
const graphClick = useGraphClickToShowButton({ const graphClick = useGraphClickToShowButton({
graphRef: currentGraphRef?.current ? currentGraphRef : graphRef, graphRef: currentGraphRef?.current ? currentGraphRef : graphRef,
isButtonEnabled: (widget?.query?.builder?.queryData && isButtonEnabled: isGraphClickButtonEnabled,
Array.isArray(widget.query.builder.queryData)
? widget.query.builder.queryData
: []
).some(
(q) =>
q.dataSource === DataSource.TRACES || q.dataSource === DataSource.LOGS,
),
buttonClassName: 'view-onclick-show-button', buttonClassName: 'view-onclick-show-button',
}); });
const navigateToExplorer = useNavigateToExplorer(); const navigateToExplorer = useNavigateToExplorer();
const graphClickHandler = ( const graphClickHandler = useCallback(
xValue: number, (
yValue: number, xValue: number,
mouseX: number, yValue: number,
mouseY: number, mouseX: number,
metric?: { [key: string]: string }, mouseY: number,
queryData?: { queryName: string; inFocusOrNot: boolean }, metric?: { [key: string]: string },
): void => { queryData?: { queryName: string; inFocusOrNot: boolean },
const customTracesTimeRange = getCustomTimeRangeWindowSweepInMS( ): void => {
const customTracesTimeRange = getCustomTimeRangeWindowSweepInMS(
customTimeRangeWindowForCoRelation,
);
const { start, end } = getStartAndEndTimesInMilliseconds(
xValue,
customTracesTimeRange,
);
handleGraphClick({
xValue,
yValue,
mouseX,
mouseY,
metric,
queryData,
widget,
navigateToExplorerPages,
navigateToExplorer,
notifications,
graphClick,
...(customTimeRangeWindowForCoRelation
? { customTracesTimeRange: { start, end } }
: {}),
});
},
[
customTimeRangeWindowForCoRelation, customTimeRangeWindowForCoRelation,
);
const { start, end } = getStartAndEndTimesInMilliseconds(
xValue,
customTracesTimeRange,
);
handleGraphClick({
xValue,
yValue,
mouseX,
mouseY,
metric,
queryData,
widget, widget,
navigateToExplorerPages, navigateToExplorerPages,
navigateToExplorer, navigateToExplorer,
notifications, notifications,
graphClick, graphClick,
...(customTimeRangeWindowForCoRelation ],
? { customTracesTimeRange: { start, end } } );
: {}),
});
};
const { truncatedText, fullText } = useGetResolvedText({ const { truncatedText, fullText } = useGetResolvedText({
text: widget.title as string, text: widget.title as string,
maxLength: 100, maxLength: 100,
}); });
// Use the provided onClickHandler if available, otherwise use the default graphClickHandler
// Both should be stable references due to useCallback
const clickHandler = onClickHandler ?? graphClickHandler;
return ( return (
<div <div
style={{ style={{
@@ -366,7 +404,7 @@ function WidgetGraphComponent({
yAxisUnit={widget.yAxisUnit} yAxisUnit={widget.yAxisUnit}
onToggleModelHandler={onToggleModelHandler} onToggleModelHandler={onToggleModelHandler}
tableProcessedDataRef={tableProcessedDataRef} tableProcessedDataRef={tableProcessedDataRef}
onClickHandler={onClickHandler ?? graphClickHandler} onClickHandler={clickHandler}
customOnDragSelect={customOnDragSelect} customOnDragSelect={customOnDragSelect}
setCurrentGraphRef={setCurrentGraphRef} setCurrentGraphRef={setCurrentGraphRef}
enableDrillDown={ enableDrillDown={
@@ -416,7 +454,7 @@ function WidgetGraphComponent({
setRequestData={setRequestData} setRequestData={setRequestData}
setGraphVisibility={setGraphVisibility} setGraphVisibility={setGraphVisibility}
graphVisibility={graphVisibility} graphVisibility={graphVisibility}
onClickHandler={onClickHandler ?? graphClickHandler} onClickHandler={clickHandler}
onDragSelect={onDragSelect} onDragSelect={onDragSelect}
tableProcessedDataRef={tableProcessedDataRef} tableProcessedDataRef={tableProcessedDataRef}
customTooltipElement={customTooltipElement} customTooltipElement={customTooltipElement}

View File

@@ -5,7 +5,7 @@ import { timePreferenceType } from 'container/NewWidget/RightContainer/timeItems
import { getDashboardVariables } from 'lib/dashbaordVariables/getDashboardVariables'; import { getDashboardVariables } from 'lib/dashbaordVariables/getDashboardVariables';
import { mapQueryDataFromApi } from 'lib/newQueryBuilder/queryBuilderMappers/mapQueryDataFromApi'; import { mapQueryDataFromApi } from 'lib/newQueryBuilder/queryBuilderMappers/mapQueryDataFromApi';
import { useDashboard } from 'providers/Dashboard/Dashboard'; import { useDashboard } from 'providers/Dashboard/Dashboard';
import { useCallback, useMemo } from 'react'; import { useCallback, useMemo, useRef } from 'react';
import { useMutation } from 'react-query'; import { useMutation } from 'react-query';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import { AppState } from 'store/reducers'; import { AppState } from 'store/reducers';
@@ -46,6 +46,11 @@ function useUpdatedQuery(): UseUpdatedQueryResult {
[selectedDashboard], [selectedDashboard],
); );
// Use ref to access latest mutateAsync without recreating the callback
// queryRangeMutation object recreates on every render, but mutateAsync is stable
const mutateAsyncRef = useRef(queryRangeMutation.mutateAsync);
mutateAsyncRef.current = queryRangeMutation.mutateAsync;
const getUpdatedQuery = useCallback( const getUpdatedQuery = useCallback(
async ({ async ({
widgetConfig, widgetConfig,
@@ -63,12 +68,12 @@ function useUpdatedQuery(): UseUpdatedQueryResult {
}); });
// Execute query and process results // Execute query and process results
const queryResult = await queryRangeMutation.mutateAsync(queryPayload); const queryResult = await mutateAsyncRef.current(queryPayload);
// Map query data from API response // Map query data from API response
return mapQueryDataFromApi(queryResult.data.compositeQuery); return mapQueryDataFromApi(queryResult.data.compositeQuery);
}, },
[dynamicVariables, globalSelectedInterval, queryRangeMutation], [dynamicVariables, globalSelectedInterval],
); );
return { return {

View File

@@ -238,6 +238,86 @@ function External(): JSX.Element {
setSelectedData, setSelectedData,
); );
const onErrorPercentageClick = useCallback(
(
xValue: number,
yValue: number,
mouseX: number,
mouseY: number,
data: any,
): void => {
onGraphClickHandler(
xValue,
yValue,
mouseX,
mouseY,
'external_call_error_percentage',
data,
);
},
[onGraphClickHandler],
);
const onDurationClick = useCallback(
(
xValue: number,
yValue: number,
mouseX: number,
mouseY: number,
data: any,
): void => {
onGraphClickHandler(
xValue,
yValue,
mouseX,
mouseY,
'external_call_duration',
data,
);
},
[onGraphClickHandler],
);
const onRPSByAddressClick = useCallback(
(
xValue: number,
yValue: number,
mouseX: number,
mouseY: number,
data: any,
): void => {
onGraphClickHandler(
xValue,
yValue,
mouseX,
mouseY,
'external_call_rps_by_address',
data,
);
},
[onGraphClickHandler],
);
const onDurationByAddressClick = useCallback(
(
xValue: number,
yValue: number,
mouseX: number,
mouseY: number,
data: any,
): void => {
onGraphClickHandler(
xValue,
yValue,
mouseX,
mouseY,
'external_call_duration_by_address',
data,
);
},
[onGraphClickHandler],
);
return ( return (
<> <>
<Row gutter={24}> <Row gutter={24}>
@@ -266,16 +346,7 @@ function External(): JSX.Element {
<Graph <Graph
headerMenuList={MENU_ITEMS} headerMenuList={MENU_ITEMS}
widget={externalCallErrorWidget} widget={externalCallErrorWidget}
onClickHandler={(xValue, yValue, mouseX, mouseY, data): void => { onClickHandler={onErrorPercentageClick}
onGraphClickHandler(
xValue,
yValue,
mouseX,
mouseY,
'external_call_error_percentage',
data,
);
}}
onDragSelect={onDragSelect} onDragSelect={onDragSelect}
version={ENTITY_VERSION_V4} version={ENTITY_VERSION_V4}
/> />
@@ -309,16 +380,7 @@ function External(): JSX.Element {
<Graph <Graph
headerMenuList={MENU_ITEMS} headerMenuList={MENU_ITEMS}
widget={externalCallDurationWidget} widget={externalCallDurationWidget}
onClickHandler={(xValue, yValue, mouseX, mouseY, data): void => { onClickHandler={onDurationClick}
onGraphClickHandler(
xValue,
yValue,
mouseX,
mouseY,
'external_call_duration',
data,
);
}}
onDragSelect={onDragSelect} onDragSelect={onDragSelect}
version={ENTITY_VERSION_V4} version={ENTITY_VERSION_V4}
/> />
@@ -353,16 +415,7 @@ function External(): JSX.Element {
<Graph <Graph
widget={externalCallRPSWidget} widget={externalCallRPSWidget}
headerMenuList={MENU_ITEMS} headerMenuList={MENU_ITEMS}
onClickHandler={(xValue, yValue, mouseX, mouseY, data): Promise<void> => onClickHandler={onRPSByAddressClick}
onGraphClickHandler(
xValue,
yValue,
mouseX,
mouseY,
'external_call_rps_by_address',
data,
)
}
onDragSelect={onDragSelect} onDragSelect={onDragSelect}
version={ENTITY_VERSION_V4} version={ENTITY_VERSION_V4}
/> />
@@ -396,16 +449,7 @@ function External(): JSX.Element {
<Graph <Graph
widget={externalCallDurationAddressWidget} widget={externalCallDurationAddressWidget}
headerMenuList={MENU_ITEMS} headerMenuList={MENU_ITEMS}
onClickHandler={(xValue, yValue, mouseX, mouseY, data): void => { onClickHandler={onDurationByAddressClick}
onGraphClickHandler(
xValue,
yValue,
mouseX,
mouseY,
'external_call_duration_by_address',
data,
);
}}
onDragSelect={onDragSelect} onDragSelect={onDragSelect}
version={ENTITY_VERSION_V4} version={ENTITY_VERSION_V4}
/> />

View File

@@ -1,4 +1,5 @@
import { FC } from 'react'; import isEqual from 'lodash-es/isEqual';
import { FC, memo } from 'react';
import { PanelTypeVsPanelWrapper } from './constants'; import { PanelTypeVsPanelWrapper } from './constants';
import { PanelWrapperProps } from './panelWrapper.types'; import { PanelWrapperProps } from './panelWrapper.types';
@@ -55,4 +56,36 @@ function PanelWrapper({
); );
} }
export default PanelWrapper; function arePropsEqual(
prevProps: PanelWrapperProps,
nextProps: PanelWrapperProps,
): boolean {
// Destructure to separate props that need deep comparison from the rest
const {
widget: prevWidget,
queryResponse: prevQueryResponse,
...prevRest
} = prevProps;
const {
widget: nextWidget,
queryResponse: nextQueryResponse,
...nextRest
} = nextProps;
// Shallow equality check for all other props (primitives, functions, refs, arrays)
const restKeys = Object.keys(prevRest) as Array<
keyof Omit<PanelWrapperProps, 'widget' | 'queryResponse'>
>;
if (restKeys.some((key) => prevRest[key] !== nextRest[key])) {
return false;
}
// Deep equality only for widget config and query response data payload
return (
isEqual(prevWidget, nextWidget) &&
isEqual(prevQueryResponse.data?.payload, nextQueryResponse.data?.payload)
);
}
export default memo(PanelWrapper, arePropsEqual);

View File

@@ -132,11 +132,21 @@ function UplotPanelWrapper({
[selectedGraph, widget?.panelTypes, widget?.stackedBarChart], [selectedGraph, widget?.panelTypes, widget?.stackedBarChart],
); );
const chartData = getUPlotChartData( // Memoize chartData to prevent unnecessary recalculations
queryResponse?.data?.payload, const chartData = useMemo(
widget.fillSpans, () =>
stackedBarChart, getUPlotChartData(
hiddenGraph, queryResponse?.data?.payload,
widget.fillSpans,
stackedBarChart,
hiddenGraph,
),
[
queryResponse?.data?.payload,
widget.fillSpans,
stackedBarChart,
hiddenGraph,
],
); );
useEffect(() => { useEffect(() => {

View File

@@ -77,6 +77,20 @@ function MessagingQueuesGraph(): JSX.Element {
}); });
} }
}; };
const onClickHandler = useCallback(
(
xValue: number,
_yValue: number,
_mouseX: number,
_mouseY: number,
data?: any,
): void => {
setSelectedTimelineQuery(urlQuery, xValue, location, history, data);
},
[urlQuery, location, history],
);
return ( return (
<Card <Card
isDarkMode={isDarkMode} isDarkMode={isDarkMode}
@@ -86,9 +100,7 @@ function MessagingQueuesGraph(): JSX.Element {
<GridCard <GridCard
widget={widgetData} widget={widgetData}
headerMenuList={[...ViewMenuAction]} headerMenuList={[...ViewMenuAction]}
onClickHandler={(xValue, _yValue, _mouseX, _mouseY, data): void => { onClickHandler={onClickHandler}
setSelectedTimelineQuery(urlQuery, xValue, location, history, data);
}}
onDragSelect={onDragSelect} onDragSelect={onDragSelect}
customTooltipElement={messagingQueueCustomTooltipText()} customTooltipElement={messagingQueueCustomTooltipText()}
dataAvailable={checkIfDataExists} dataAvailable={checkIfDataExists}