From f1cbb9acb8cad7f67b0e4101f1d03084e4e9930a Mon Sep 17 00:00:00 2001 From: Yomi Eluwande Date: Thu, 5 Dec 2024 15:55:10 +0100 Subject: [PATCH] Add a popover menu to the AreaGraph component --- .../src/MetricsGraph/MetricsTooltip/index.tsx | 2 +- .../MetricsGraphStrips/AreaGraph/Tooltip.tsx | 83 +++++++++++++++++++ .../MetricsGraphStrips/AreaGraph/index.tsx | 51 +++++++++++- .../profile/src/MetricsGraphStrips/index.tsx | 5 +- 4 files changed, 136 insertions(+), 5 deletions(-) create mode 100644 ui/packages/shared/profile/src/MetricsGraphStrips/AreaGraph/Tooltip.tsx diff --git a/ui/packages/shared/profile/src/MetricsGraph/MetricsTooltip/index.tsx b/ui/packages/shared/profile/src/MetricsGraph/MetricsTooltip/index.tsx index dd671ed3cae..6cfe8a7bd48 100644 --- a/ui/packages/shared/profile/src/MetricsGraph/MetricsTooltip/index.tsx +++ b/ui/packages/shared/profile/src/MetricsGraph/MetricsTooltip/index.tsx @@ -105,7 +105,7 @@ const MetricsTooltip = ({ const highlightedNameLabel: Label = nameLabel !== undefined ? nameLabel : {name: '', value: ''}; return ( -
+
(null); + const [tooltipPosition, setTooltipPosition] = useState({x, y}); + + const baseOffset = { + x: 16, + y: -8, + }; + + useEffect(() => { + if (tooltipRef.current != null) { + const tooltipWidth = tooltipRef.current.offsetWidth; + + let newX = x + baseOffset.x; + let newY = y + baseOffset.y; + + if (newX + tooltipWidth > containerWidth) { + newX = x - tooltipWidth - baseOffset.x; + } + + if (newY < 0) { + newY = y + Math.abs(baseOffset.y); + } + + setTooltipPosition({x: newX, y: newY}); + } + }, [x, y, containerWidth, baseOffset.x, baseOffset.y]); + + return ( +
+
+
+
Timestamp:
+
+ {formatDate(timestamp, timePattern(timezone), timezone)} +
+
+ +
+
Value:
+
+ {valueFormatter(value, 'nanoseconds', 2)} +
+
+
+
+ ); +} diff --git a/ui/packages/shared/profile/src/MetricsGraphStrips/AreaGraph/index.tsx b/ui/packages/shared/profile/src/MetricsGraphStrips/AreaGraph/index.tsx index 44b915280d4..556ccfd036f 100644 --- a/ui/packages/shared/profile/src/MetricsGraphStrips/AreaGraph/index.tsx +++ b/ui/packages/shared/profile/src/MetricsGraphStrips/AreaGraph/index.tsx @@ -18,6 +18,7 @@ import cx from 'classnames'; import * as d3 from 'd3'; import {NumberDuo} from '../../utils'; +import {Tooltip} from './Tooltip'; export interface DataPoint { timestamp: number; @@ -143,7 +144,7 @@ const ZoomWindow = ({
(undefined); const [dragStart, setDragStart] = useState(undefined); const [isHoveringDragHandle, setIsHoveringDragHandle] = useState(false); + const [hoverData, setHoverData] = useState<{timestamp: number; value: number} | null>(null); + const [isMouseOverGraph, setIsMouseOverGraph] = useState(false); const isDragging = dragStart !== undefined; // Declare the x (horizontal position) scale. @@ -245,12 +248,39 @@ export const AreaGraph = ({
{ - const [x, y] = d3.pointer(e); - setMousePosition([x, y]); + const [xPos, yPos] = d3.pointer(e); + + if ( + xPos >= marginLeft && + xPos <= width - marginRight && + yPos >= marginTop && + yPos <= height - marginBottom + ) { + setMousePosition([xPos, yPos]); + + // Find the closest data point + if (!isHoveringDragHandle && !isDragging) { + const xDate = x.invert(xPos); + const bisect = d3.bisector((d: DataPoint) => d.timestamp).left; + const index = bisect(data, xDate.getTime()); + const dataPoint = data[index]; + if (dataPoint !== undefined) { + setHoverData(dataPoint); + } + } + } else { + setMousePosition(undefined); + setHoverData(null); + } + }} + onMouseEnter={() => { + setIsMouseOverGraph(true); }} onMouseLeave={() => { + setIsMouseOverGraph(false); setMousePosition(undefined); setDragStart(undefined); + setHoverData(null); }} onMouseDown={e => { // only left mouse button @@ -313,6 +343,21 @@ export const AreaGraph = ({ })} >
+ {/* Update Tooltip conditional render */} + {mousePosition !== undefined && + hoverData !== null && + !isDragging && + !isHoveringDragHandle && + isMouseOverGraph && ( + + )} + diff --git a/ui/packages/shared/profile/src/MetricsGraphStrips/index.tsx b/ui/packages/shared/profile/src/MetricsGraphStrips/index.tsx index 62e9b2f60e3..fffc403efa4 100644 --- a/ui/packages/shared/profile/src/MetricsGraphStrips/index.tsx +++ b/ui/packages/shared/profile/src/MetricsGraphStrips/index.tsx @@ -95,7 +95,10 @@ export const MetricsGraphStrips = ({ return (
{ const newCollapsedIndices = [...collapsedIndices]; if (collapsedIndices.includes(i)) {