mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Heatmap: hover legend regardless of tooltip state (#47600)
This commit is contained in:
@@ -220,7 +220,9 @@ export function calculateHeatmapFromData(frames: DataFrame[], options: HeatmapCa
|
||||
name: 'count',
|
||||
type: FieldType.number,
|
||||
values: new ArrayVector(heat2d.count),
|
||||
config: {},
|
||||
config: {
|
||||
unit: 'short', // always integer
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
import { Field, FieldType, formattedValueToString, LinkModel } from '@grafana/data';
|
||||
import { Field, FieldType, formattedValueToString, getFieldDisplayName, LinkModel } from '@grafana/data';
|
||||
|
||||
import { HeatmapHoverEvent } from './utils';
|
||||
import { BucketLayout, HeatmapData } from './fields';
|
||||
@@ -26,7 +26,7 @@ export const HeatmapHoverView = ({ data, hover, showHistogram }: Props) => {
|
||||
const dashboard = getDashboardSrv().getCurrent();
|
||||
return dashboard?.formatDate(v, tooltipTimeFormat);
|
||||
}
|
||||
return `${v}XX`;
|
||||
return `${v}`;
|
||||
};
|
||||
|
||||
const xVals = xField?.values.toArray();
|
||||
@@ -45,7 +45,7 @@ export const HeatmapHoverView = ({ data, hover, showHistogram }: Props) => {
|
||||
if (yField?.display) {
|
||||
return formattedValueToString(yField.display(v));
|
||||
}
|
||||
return `${v}YYY`;
|
||||
return `${v}`;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -170,7 +170,9 @@ export const HeatmapHoverView = ({ data, hover, showHistogram }: Props) => {
|
||||
<div>
|
||||
Bucket: {yDisp(yBucketMin)} - {yDisp(yBucketMax)}
|
||||
</div>
|
||||
<div>Count: {count}</div>
|
||||
<div>
|
||||
{getFieldDisplayName(countField!, data.heatmap)}: {count}
|
||||
</div>
|
||||
</div>
|
||||
{links.length > 0 && (
|
||||
<VerticalGroup>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useCallback, useMemo, useRef, useState } from 'react';
|
||||
import { css } from '@emotion/css';
|
||||
import { formattedValueToString, GrafanaTheme2, PanelProps, reduceField, ReducerID, TimeRange } from '@grafana/data';
|
||||
import { GrafanaTheme2, PanelProps, reduceField, ReducerID, TimeRange } from '@grafana/data';
|
||||
import {
|
||||
Portal,
|
||||
UPlotChart,
|
||||
@@ -82,7 +82,7 @@ export const HeatmapPanel: React.FC<HeatmapPanelProps> = ({
|
||||
return prepConfig({
|
||||
dataRef,
|
||||
theme,
|
||||
onhover: options.tooltip.show ? onhover : null,
|
||||
onhover: onhover,
|
||||
onclick: options.tooltip.show ? onclick : null,
|
||||
onzoom: (evt) => {
|
||||
onChangeTimeRange({ from: evt.xMin, to: evt.xMax });
|
||||
@@ -104,7 +104,6 @@ export const HeatmapPanel: React.FC<HeatmapPanelProps> = ({
|
||||
|
||||
const field = info.heatmap.fields[2];
|
||||
const { min, max } = reduceField({ field, reducers: [ReducerID.min, ReducerID.max] });
|
||||
const display = field.display ? (v: number) => formattedValueToString(field.display!(v)) : (v: number) => `${v}`;
|
||||
|
||||
let hoverValue: number | undefined = undefined;
|
||||
if (hover && info.heatmap.fields) {
|
||||
@@ -114,7 +113,7 @@ export const HeatmapPanel: React.FC<HeatmapPanelProps> = ({
|
||||
|
||||
return (
|
||||
<VizLayout.Legend placement="bottom" maxHeight="20%">
|
||||
<ColorScale hoverValue={hoverValue} colorPalette={palette} min={min} max={max} display={display} />
|
||||
<ColorScale hoverValue={hoverValue} colorPalette={palette} min={min} max={max} display={info.display} />
|
||||
</VizLayout.Legend>
|
||||
);
|
||||
};
|
||||
@@ -133,7 +132,7 @@ export const HeatmapPanel: React.FC<HeatmapPanelProps> = ({
|
||||
)}
|
||||
</VizLayout>
|
||||
<Portal>
|
||||
{hover && (
|
||||
{hover && options.tooltip.show && (
|
||||
<VizTooltipContainer
|
||||
position={{ x: hover.pageX, y: hover.pageY }}
|
||||
offset={{ x: 10, y: 10 }}
|
||||
|
||||
@@ -2,8 +2,10 @@ import {
|
||||
DataFrame,
|
||||
DataFrameType,
|
||||
FieldType,
|
||||
formattedValueToString,
|
||||
getDisplayProcessor,
|
||||
getFieldDisplayName,
|
||||
getValueFormat,
|
||||
GrafanaTheme2,
|
||||
} from '@grafana/data';
|
||||
import { calculateHeatmapFromData, bucketsToScanlines } from 'app/features/transformers/calculateHeatmap/heatmap';
|
||||
@@ -29,6 +31,9 @@ export interface HeatmapData {
|
||||
xLayout?: BucketLayout;
|
||||
yLayout?: BucketLayout;
|
||||
|
||||
// Print a heatmap cell value
|
||||
display?: (v: number) => string;
|
||||
|
||||
// Errors
|
||||
warning?: string;
|
||||
}
|
||||
@@ -84,6 +89,7 @@ const getHeatmapData = (frame: DataFrame, theme: GrafanaTheme2): HeatmapData =>
|
||||
return { heatmap: frame };
|
||||
}
|
||||
|
||||
// Y field values (display is used in the axis)
|
||||
if (!frame.fields[1].display) {
|
||||
frame.fields[1].display = getDisplayProcessor({ field: frame.fields[1], theme });
|
||||
}
|
||||
@@ -105,14 +111,19 @@ const getHeatmapData = (frame: DataFrame, theme: GrafanaTheme2): HeatmapData =>
|
||||
let yBinIncr = ys[1] - ys[0];
|
||||
let xBinIncr = xs[yBinQty] - xs[0];
|
||||
|
||||
// The "count" field
|
||||
const disp = frame.fields[2].display ?? getValueFormat('short');
|
||||
return {
|
||||
heatmap: frame,
|
||||
xBucketSize: xBinIncr,
|
||||
yBucketSize: yBinIncr,
|
||||
xBucketCount: xBinQty,
|
||||
yBucketCount: yBinQty,
|
||||
|
||||
// TODO: improve heuristic
|
||||
xLayout: frame.fields[0].name === 'xMax' ? BucketLayout.le : BucketLayout.ge,
|
||||
yLayout: frame.fields[1].name === 'yMax' ? BucketLayout.le : BucketLayout.ge,
|
||||
|
||||
display: (v) => formattedValueToString(disp(v)),
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user