mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
TimeSeriesPanel: Null points no longer get tooltips (#42371)
* TimeSeriesPanel: Null points no longer get tooltips Co-authored-by: Leon Sorokin <leeoniya@gmail.com>
This commit is contained in:
parent
7c5d5c0128
commit
4855fe78f8
packages/grafana-ui/src/components
@ -344,19 +344,19 @@ export const preparePlotConfigBuilder: UPlotConfigPrepFn<{ sync: DashboardCursor
|
||||
let seriesData = self.data[seriesIdx];
|
||||
|
||||
if (seriesData[hoveredIdx] == null) {
|
||||
let nonNullLft = hoveredIdx,
|
||||
nonNullRgt = hoveredIdx,
|
||||
let nonNullLft = null,
|
||||
nonNullRgt = null,
|
||||
i;
|
||||
|
||||
i = hoveredIdx;
|
||||
while (nonNullLft === hoveredIdx && i-- > 0) {
|
||||
while (nonNullLft == null && i-- > 0) {
|
||||
if (seriesData[i] != null) {
|
||||
nonNullLft = i;
|
||||
}
|
||||
}
|
||||
|
||||
i = hoveredIdx;
|
||||
while (nonNullRgt === hoveredIdx && i++ < seriesData.length) {
|
||||
while (nonNullRgt == null && i++ < seriesData.length) {
|
||||
if (seriesData[i] != null) {
|
||||
nonNullRgt = i;
|
||||
}
|
||||
@ -365,19 +365,19 @@ export const preparePlotConfigBuilder: UPlotConfigPrepFn<{ sync: DashboardCursor
|
||||
let xVals = self.data[0];
|
||||
|
||||
let curPos = self.valToPos(cursorXVal, 'x');
|
||||
let rgtPos = self.valToPos(xVals[nonNullRgt], 'x');
|
||||
let lftPos = self.valToPos(xVals[nonNullLft], 'x');
|
||||
let rgtPos = nonNullRgt == null ? Infinity : self.valToPos(xVals[nonNullRgt], 'x');
|
||||
let lftPos = nonNullLft == null ? -Infinity : self.valToPos(xVals[nonNullLft], 'x');
|
||||
|
||||
let lftDelta = curPos - lftPos;
|
||||
let rgtDelta = rgtPos - curPos;
|
||||
|
||||
if (lftDelta <= rgtDelta) {
|
||||
if (lftDelta <= hoverProximityPx) {
|
||||
hoveredIdx = nonNullLft;
|
||||
hoveredIdx = nonNullLft!;
|
||||
}
|
||||
} else {
|
||||
if (rgtDelta <= hoverProximityPx) {
|
||||
hoveredIdx = nonNullRgt;
|
||||
hoveredIdx = nonNullRgt!;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,6 @@
|
||||
import React, { useEffect, useLayoutEffect, useRef, useState } from 'react';
|
||||
import { useMountedState } from 'react-use';
|
||||
import uPlot from 'uplot';
|
||||
import {
|
||||
CartesianCoords2D,
|
||||
DashboardCursorSync,
|
||||
@ -10,9 +13,6 @@ import {
|
||||
TimeZone,
|
||||
} from '@grafana/data';
|
||||
import { TooltipDisplayMode } from '@grafana/schema';
|
||||
import React, { useEffect, useLayoutEffect, useState } from 'react';
|
||||
import { useMountedState } from 'react-use';
|
||||
import uPlot from 'uplot';
|
||||
import { useTheme2 } from '../../../themes/ThemeContext';
|
||||
import { Portal } from '../../Portal/Portal';
|
||||
import { SeriesTable, SeriesTableRowProps, VizTooltipContainer } from '../../VizTooltip';
|
||||
@ -43,6 +43,7 @@ export const TooltipPlugin: React.FC<TooltipPluginProps> = ({
|
||||
renderTooltip,
|
||||
...otherProps
|
||||
}) => {
|
||||
const plotInstance = useRef<uPlot>();
|
||||
const theme = useTheme2();
|
||||
const [focusedSeriesIdx, setFocusedSeriesIdx] = useState<number | null>(null);
|
||||
const [focusedPointIdx, setFocusedPointIdx] = useState<number | null>(null);
|
||||
@ -60,7 +61,6 @@ export const TooltipPlugin: React.FC<TooltipPluginProps> = ({
|
||||
|
||||
// Add uPlot hooks to the config, or re-add when the config changed
|
||||
useLayoutEffect(() => {
|
||||
let plotInstance: uPlot | undefined = undefined;
|
||||
let bbox: DOMRect | undefined = undefined;
|
||||
|
||||
const plotMouseLeave = () => {
|
||||
@ -69,7 +69,7 @@ export const TooltipPlugin: React.FC<TooltipPluginProps> = ({
|
||||
}
|
||||
setCoords(null);
|
||||
setIsActive(false);
|
||||
plotInstance?.root.classList.remove('plot-active');
|
||||
plotInstance.current?.root.classList.remove('plot-active');
|
||||
};
|
||||
|
||||
const plotMouseEnter = () => {
|
||||
@ -77,16 +77,14 @@ export const TooltipPlugin: React.FC<TooltipPluginProps> = ({
|
||||
return;
|
||||
}
|
||||
setIsActive(true);
|
||||
plotInstance?.root.classList.add('plot-active');
|
||||
plotInstance.current?.root.classList.add('plot-active');
|
||||
};
|
||||
|
||||
// cache uPlot plotting area bounding box
|
||||
config.addHook('syncRect', (u, rect) => {
|
||||
bbox = rect;
|
||||
});
|
||||
config.addHook('syncRect', (u, rect) => (bbox = rect));
|
||||
|
||||
config.addHook('init', (u) => {
|
||||
plotInstance = u;
|
||||
plotInstance.current = u;
|
||||
|
||||
u.over.addEventListener('mouseleave', plotMouseLeave);
|
||||
u.over.addEventListener('mouseenter', plotMouseEnter);
|
||||
@ -155,9 +153,9 @@ export const TooltipPlugin: React.FC<TooltipPluginProps> = ({
|
||||
|
||||
return () => {
|
||||
setCoords(null);
|
||||
if (plotInstance) {
|
||||
plotInstance.over.removeEventListener('mouseleave', plotMouseLeave);
|
||||
plotInstance.over.removeEventListener('mouseenter', plotMouseEnter);
|
||||
if (plotInstance.current) {
|
||||
plotInstance.current.over.removeEventListener('mouseleave', plotMouseLeave);
|
||||
plotInstance.current.over.removeEventListener('mouseenter', plotMouseEnter);
|
||||
}
|
||||
};
|
||||
}, [config, setCoords, setIsActive, setFocusedPointIdx, setFocusedPointIdxs]);
|
||||
@ -174,7 +172,7 @@ export const TooltipPlugin: React.FC<TooltipPluginProps> = ({
|
||||
const xFieldFmt = xField.display || getDisplayProcessor({ field: xField, timeZone, theme });
|
||||
let tooltip: React.ReactNode = null;
|
||||
|
||||
const xVal = xFieldFmt(xField!.values.get(focusedPointIdx)).text;
|
||||
let xVal = xFieldFmt(xField!.values.get(focusedPointIdx)).text;
|
||||
|
||||
if (!renderTooltip) {
|
||||
// when interacting with a point in single mode
|
||||
@ -185,8 +183,10 @@ export const TooltipPlugin: React.FC<TooltipPluginProps> = ({
|
||||
return null;
|
||||
}
|
||||
|
||||
const dataIdx = focusedPointIdxs?.[focusedSeriesIdx] ?? focusedPointIdx;
|
||||
xVal = xFieldFmt(xField!.values.get(dataIdx)).text;
|
||||
const fieldFmt = field.display || getDisplayProcessor({ field, timeZone, theme });
|
||||
const display = fieldFmt(field.values.get(focusedPointIdx));
|
||||
const display = fieldFmt(field.values.get(dataIdx));
|
||||
|
||||
tooltip = (
|
||||
<SeriesTable
|
||||
@ -247,7 +247,7 @@ export const TooltipPlugin: React.FC<TooltipPluginProps> = ({
|
||||
);
|
||||
};
|
||||
|
||||
function isCursourOutsideCanvas({ left, top }: uPlot.Cursor, canvas: DOMRect) {
|
||||
function isCursorOutsideCanvas({ left, top }: uPlot.Cursor, canvas: DOMRect) {
|
||||
if (left === undefined || top === undefined) {
|
||||
return false;
|
||||
}
|
||||
@ -264,7 +264,7 @@ export function positionTooltip(u: uPlot, bbox: DOMRect) {
|
||||
const cL = u.cursor.left || 0;
|
||||
const cT = u.cursor.top || 0;
|
||||
|
||||
if (isCursourOutsideCanvas(u.cursor, bbox)) {
|
||||
if (isCursorOutsideCanvas(u.cursor, bbox)) {
|
||||
const idx = u.posToIdx(cL);
|
||||
// when cursor outside of uPlot's canvas
|
||||
if (cT < 0 || cT > bbox.height) {
|
||||
|
Loading…
Reference in New Issue
Block a user