mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
BarChart: TooltipPlugin2 (#80920)
Co-authored-by: Adela Almasan <adela.almasan@grafana.com>
This commit is contained in:
parent
2ed8201f25
commit
2c3596854f
@ -118,8 +118,12 @@ export const getContentItems = (
|
|||||||
|
|
||||||
const v = fields[i].values[dataIdx];
|
const v = fields[i].values[dataIdx];
|
||||||
|
|
||||||
// no value -> zero?
|
if (v == null && field.config.noValue == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const display = field.display!(v); // super expensive :(
|
const display = field.display!(v); // super expensive :(
|
||||||
|
|
||||||
// sort NaN and non-numeric to bottom (regardless of sort order)
|
// sort NaN and non-numeric to bottom (regardless of sort order)
|
||||||
const numeric = !Number.isNaN(display.numeric)
|
const numeric = !Number.isNaN(display.numeric)
|
||||||
? display.numeric
|
? display.numeric
|
||||||
|
@ -12,7 +12,7 @@ import {
|
|||||||
TimeRange,
|
TimeRange,
|
||||||
VizOrientation,
|
VizOrientation,
|
||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
import { PanelDataErrorView } from '@grafana/runtime';
|
import { PanelDataErrorView, config } from '@grafana/runtime';
|
||||||
import { SortOrder } from '@grafana/schema';
|
import { SortOrder } from '@grafana/schema';
|
||||||
import {
|
import {
|
||||||
GraphGradientMode,
|
GraphGradientMode,
|
||||||
@ -28,13 +28,17 @@ import {
|
|||||||
VizLayout,
|
VizLayout,
|
||||||
VizLegend,
|
VizLegend,
|
||||||
VizTooltipContainer,
|
VizTooltipContainer,
|
||||||
|
TooltipPlugin2,
|
||||||
} from '@grafana/ui';
|
} from '@grafana/ui';
|
||||||
import { HoverEvent, addTooltipSupport } from '@grafana/ui/src/components/uPlot/config/addTooltipSupport';
|
import { HoverEvent, addTooltipSupport } from '@grafana/ui/src/components/uPlot/config/addTooltipSupport';
|
||||||
|
import { TooltipHoverMode } from '@grafana/ui/src/components/uPlot/plugins/TooltipPlugin2';
|
||||||
import { CloseButton } from 'app/core/components/CloseButton/CloseButton';
|
import { CloseButton } from 'app/core/components/CloseButton/CloseButton';
|
||||||
import { GraphNG, GraphNGProps, PropDiffFn } from 'app/core/components/GraphNG/GraphNG';
|
import { GraphNG, GraphNGProps, PropDiffFn } from 'app/core/components/GraphNG/GraphNG';
|
||||||
import { getFieldLegendItem } from 'app/core/components/TimelineChart/utils';
|
import { getFieldLegendItem } from 'app/core/components/TimelineChart/utils';
|
||||||
import { DataHoverView } from 'app/features/visualization/data-hover/DataHoverView';
|
import { DataHoverView } from 'app/features/visualization/data-hover/DataHoverView';
|
||||||
|
|
||||||
|
import { TimeSeriesTooltip } from '../timeseries/TimeSeriesTooltip';
|
||||||
|
|
||||||
import { Options } from './panelcfg.gen';
|
import { Options } from './panelcfg.gen';
|
||||||
import { prepareBarChartDisplayValues, preparePlotConfigBuilder } from './utils';
|
import { prepareBarChartDisplayValues, preparePlotConfigBuilder } from './utils';
|
||||||
|
|
||||||
@ -302,9 +306,12 @@ export const BarChartPanel = ({ data, options, fieldConfig, width, height, timeZ
|
|||||||
fillOpacity,
|
fillOpacity,
|
||||||
allFrames: info.viz,
|
allFrames: info.viz,
|
||||||
fullHighlight,
|
fullHighlight,
|
||||||
|
hoverMulti: tooltip.mode === TooltipDisplayMode.Multi,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const showNewVizTooltips = Boolean(config.featureToggles.newVizTooltips);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<GraphNG
|
<GraphNG
|
||||||
theme={theme}
|
theme={theme}
|
||||||
@ -321,7 +328,33 @@ export const BarChartPanel = ({ data, options, fieldConfig, width, height, timeZ
|
|||||||
height={height}
|
height={height}
|
||||||
>
|
>
|
||||||
{(config) => {
|
{(config) => {
|
||||||
if (oldConfig.current !== config) {
|
if (showNewVizTooltips && options.tooltip.mode !== TooltipDisplayMode.None) {
|
||||||
|
return (
|
||||||
|
<TooltipPlugin2
|
||||||
|
config={config}
|
||||||
|
hoverMode={
|
||||||
|
options.tooltip.mode === TooltipDisplayMode.Single ? TooltipHoverMode.xOne : TooltipHoverMode.xAll
|
||||||
|
}
|
||||||
|
render={(u, dataIdxs, seriesIdx, isPinned, dismiss, timeRange2) => {
|
||||||
|
return (
|
||||||
|
<TimeSeriesTooltip
|
||||||
|
frames={info.viz}
|
||||||
|
seriesFrame={info.aligned}
|
||||||
|
dataIdxs={dataIdxs}
|
||||||
|
seriesIdx={seriesIdx}
|
||||||
|
mode={options.tooltip.mode}
|
||||||
|
sortOrder={options.tooltip.sort}
|
||||||
|
isPinned={isPinned}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
maxWidth={options.tooltip.maxWidth}
|
||||||
|
maxHeight={options.tooltip.maxHeight}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!showNewVizTooltips && oldConfig.current !== config) {
|
||||||
oldConfig.current = addTooltipSupport({
|
oldConfig.current = addTooltipSupport({
|
||||||
config,
|
config,
|
||||||
onUPlotClick,
|
onUPlotClick,
|
||||||
|
@ -68,7 +68,8 @@ exports[`BarChart utils preparePlotConfigBuilder orientation 1`] = `
|
|||||||
"y": false,
|
"y": false,
|
||||||
},
|
},
|
||||||
"focus": {
|
"focus": {
|
||||||
"prox": 30,
|
"dist": [Function],
|
||||||
|
"prox": 1000,
|
||||||
},
|
},
|
||||||
"points": {
|
"points": {
|
||||||
"bbox": [Function],
|
"bbox": [Function],
|
||||||
@ -223,7 +224,8 @@ exports[`BarChart utils preparePlotConfigBuilder orientation 2`] = `
|
|||||||
"y": false,
|
"y": false,
|
||||||
},
|
},
|
||||||
"focus": {
|
"focus": {
|
||||||
"prox": 30,
|
"dist": [Function],
|
||||||
|
"prox": 1000,
|
||||||
},
|
},
|
||||||
"points": {
|
"points": {
|
||||||
"bbox": [Function],
|
"bbox": [Function],
|
||||||
@ -378,7 +380,8 @@ exports[`BarChart utils preparePlotConfigBuilder orientation 3`] = `
|
|||||||
"y": false,
|
"y": false,
|
||||||
},
|
},
|
||||||
"focus": {
|
"focus": {
|
||||||
"prox": 30,
|
"dist": [Function],
|
||||||
|
"prox": 1000,
|
||||||
},
|
},
|
||||||
"points": {
|
"points": {
|
||||||
"bbox": [Function],
|
"bbox": [Function],
|
||||||
@ -533,7 +536,8 @@ exports[`BarChart utils preparePlotConfigBuilder stacking 1`] = `
|
|||||||
"y": false,
|
"y": false,
|
||||||
},
|
},
|
||||||
"focus": {
|
"focus": {
|
||||||
"prox": 30,
|
"dist": [Function],
|
||||||
|
"prox": 1000,
|
||||||
},
|
},
|
||||||
"points": {
|
"points": {
|
||||||
"bbox": [Function],
|
"bbox": [Function],
|
||||||
@ -688,7 +692,8 @@ exports[`BarChart utils preparePlotConfigBuilder stacking 2`] = `
|
|||||||
"y": false,
|
"y": false,
|
||||||
},
|
},
|
||||||
"focus": {
|
"focus": {
|
||||||
"prox": 30,
|
"dist": [Function],
|
||||||
|
"prox": 1000,
|
||||||
},
|
},
|
||||||
"points": {
|
"points": {
|
||||||
"bbox": [Function],
|
"bbox": [Function],
|
||||||
@ -843,7 +848,8 @@ exports[`BarChart utils preparePlotConfigBuilder stacking 3`] = `
|
|||||||
"y": false,
|
"y": false,
|
||||||
},
|
},
|
||||||
"focus": {
|
"focus": {
|
||||||
"prox": 30,
|
"dist": [Function],
|
||||||
|
"prox": 1000,
|
||||||
},
|
},
|
||||||
"points": {
|
"points": {
|
||||||
"bbox": [Function],
|
"bbox": [Function],
|
||||||
@ -998,7 +1004,8 @@ exports[`BarChart utils preparePlotConfigBuilder value visibility 1`] = `
|
|||||||
"y": false,
|
"y": false,
|
||||||
},
|
},
|
||||||
"focus": {
|
"focus": {
|
||||||
"prox": 30,
|
"dist": [Function],
|
||||||
|
"prox": 1000,
|
||||||
},
|
},
|
||||||
"points": {
|
"points": {
|
||||||
"bbox": [Function],
|
"bbox": [Function],
|
||||||
@ -1153,7 +1160,8 @@ exports[`BarChart utils preparePlotConfigBuilder value visibility 2`] = `
|
|||||||
"y": false,
|
"y": false,
|
||||||
},
|
},
|
||||||
"focus": {
|
"focus": {
|
||||||
"prox": 30,
|
"dist": [Function],
|
||||||
|
"prox": 1000,
|
||||||
},
|
},
|
||||||
"points": {
|
"points": {
|
||||||
"bbox": [Function],
|
"bbox": [Function],
|
||||||
|
@ -15,7 +15,7 @@ import { formatTime } from '@grafana/ui/src/components/uPlot/config/UPlotAxisBui
|
|||||||
import { StackingGroup, preparePlotData2 } from '@grafana/ui/src/components/uPlot/utils';
|
import { StackingGroup, preparePlotData2 } from '@grafana/ui/src/components/uPlot/utils';
|
||||||
|
|
||||||
import { distribute, SPACE_BETWEEN } from './distribute';
|
import { distribute, SPACE_BETWEEN } from './distribute';
|
||||||
import { intersects, pointWithin, Quadtree, Rect } from './quadtree';
|
import { findRects, intersects, pointWithin, Quadtree, Rect } from './quadtree';
|
||||||
|
|
||||||
const groupDistr = SPACE_BETWEEN;
|
const groupDistr = SPACE_BETWEEN;
|
||||||
const barDistr = SPACE_BETWEEN;
|
const barDistr = SPACE_BETWEEN;
|
||||||
@ -56,6 +56,7 @@ export interface BarsOptions {
|
|||||||
text?: VizTextDisplayOptions;
|
text?: VizTextDisplayOptions;
|
||||||
onHover?: (seriesIdx: number, valueIdx: number) => void;
|
onHover?: (seriesIdx: number, valueIdx: number) => void;
|
||||||
onLeave?: (seriesIdx: number, valueIdx: number) => void;
|
onLeave?: (seriesIdx: number, valueIdx: number) => void;
|
||||||
|
hoverMulti?: boolean;
|
||||||
legend?: VizLegendOptions;
|
legend?: VizLegendOptions;
|
||||||
xSpacing?: number;
|
xSpacing?: number;
|
||||||
xTimeAuto?: boolean;
|
xTimeAuto?: boolean;
|
||||||
@ -128,6 +129,7 @@ export function getConfig(opts: BarsOptions, theme: GrafanaTheme2) {
|
|||||||
fillOpacity = 1,
|
fillOpacity = 1,
|
||||||
showValue,
|
showValue,
|
||||||
xSpacing = 0,
|
xSpacing = 0,
|
||||||
|
hoverMulti = false,
|
||||||
} = opts;
|
} = opts;
|
||||||
const isXHorizontal = xOri === ScaleOrientation.Horizontal;
|
const isXHorizontal = xOri === ScaleOrientation.Horizontal;
|
||||||
const hasAutoValueSize = !Boolean(opts.text?.valueSize);
|
const hasAutoValueSize = !Boolean(opts.text?.valueSize);
|
||||||
@ -141,6 +143,8 @@ export function getConfig(opts: BarsOptions, theme: GrafanaTheme2) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let qt: Quadtree;
|
let qt: Quadtree;
|
||||||
|
const numSeries = 30; // !!
|
||||||
|
const hovered: Array<Rect | null> = Array(numSeries).fill(null);
|
||||||
let hRect: Rect | null;
|
let hRect: Rect | null;
|
||||||
|
|
||||||
// for distr: 2 scales, the splits array should contain indices into data[0] rather than values
|
// for distr: 2 scales, the splits array should contain indices into data[0] rather than values
|
||||||
@ -324,7 +328,7 @@ export function getConfig(opts: BarsOptions, theme: GrafanaTheme2) {
|
|||||||
|
|
||||||
let barRect = { x: lft, y: top, w: wid, h: hgt, sidx: seriesIdx, didx: dataIdx };
|
let barRect = { x: lft, y: top, w: wid, h: hgt, sidx: seriesIdx, didx: dataIdx };
|
||||||
|
|
||||||
if (opts.fullHighlight) {
|
if (!isStacked && opts.fullHighlight) {
|
||||||
if (opts.xOri === ScaleOrientation.Horizontal) {
|
if (opts.xOri === ScaleOrientation.Horizontal) {
|
||||||
barRect.y = 0;
|
barRect.y = 0;
|
||||||
barRect.h = u.bbox.height;
|
barRect.h = u.bbox.height;
|
||||||
@ -443,8 +447,6 @@ export function getConfig(opts: BarsOptions, theme: GrafanaTheme2) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const init = (u: uPlot) => {
|
const init = (u: uPlot) => {
|
||||||
let over = u.over;
|
|
||||||
over.style.overflow = 'hidden';
|
|
||||||
u.root.querySelectorAll<HTMLDivElement>('.u-cursor-pt').forEach((el) => {
|
u.root.querySelectorAll<HTMLDivElement>('.u-cursor-pt').forEach((el) => {
|
||||||
el.style.borderRadius = '0';
|
el.style.borderRadius = '0';
|
||||||
|
|
||||||
@ -462,7 +464,8 @@ export function getConfig(opts: BarsOptions, theme: GrafanaTheme2) {
|
|||||||
y: false,
|
y: false,
|
||||||
},
|
},
|
||||||
dataIdx: (u, seriesIdx) => {
|
dataIdx: (u, seriesIdx) => {
|
||||||
if (seriesIdx === 1) {
|
if (seriesIdx === 0) {
|
||||||
|
hovered.fill(null);
|
||||||
hRect = null;
|
hRect = null;
|
||||||
|
|
||||||
let cx = u.cursor.left! * uPlot.pxRatio;
|
let cx = u.cursor.left! * uPlot.pxRatio;
|
||||||
@ -470,26 +473,37 @@ export function getConfig(opts: BarsOptions, theme: GrafanaTheme2) {
|
|||||||
|
|
||||||
qt.get(cx, cy, 1, 1, (o) => {
|
qt.get(cx, cy, 1, 1, (o) => {
|
||||||
if (pointWithin(cx, cy, o.x, o.y, o.x + o.w, o.y + o.h)) {
|
if (pointWithin(cx, cy, o.x, o.y, o.x + o.w, o.y + o.h)) {
|
||||||
hRect = o;
|
hRect = hovered[0] = o;
|
||||||
|
hovered[hRect.sidx] = hRect;
|
||||||
|
|
||||||
|
hoverMulti &&
|
||||||
|
findRects(qt, undefined, hRect.didx).forEach((r) => {
|
||||||
|
hovered[r.sidx] = r;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return hRect && seriesIdx === hRect.sidx ? hRect.didx : null;
|
return hovered[seriesIdx]?.didx;
|
||||||
},
|
},
|
||||||
points: {
|
points: {
|
||||||
fill: 'rgba(255,255,255,0.4)',
|
fill: 'rgba(255,255,255,0.4)',
|
||||||
bbox: (u, seriesIdx) => {
|
bbox: (u, seriesIdx) => {
|
||||||
let isHovered = hRect && seriesIdx === hRect.sidx;
|
let hRect2 = hovered[seriesIdx];
|
||||||
|
let isHovered = hRect2 != null;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
left: isHovered ? hRect!.x / uPlot.pxRatio : -10,
|
left: isHovered ? hRect2!.x / uPlot.pxRatio : -10,
|
||||||
top: isHovered ? hRect!.y / uPlot.pxRatio : -10,
|
top: isHovered ? hRect2!.y / uPlot.pxRatio : -10,
|
||||||
width: isHovered ? hRect!.w / uPlot.pxRatio : 0,
|
width: isHovered ? hRect2!.w / uPlot.pxRatio : 0,
|
||||||
height: isHovered ? hRect!.h / uPlot.pxRatio : 0,
|
height: isHovered ? hRect2!.h / uPlot.pxRatio : 0,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
focus: {
|
||||||
|
prox: 1e3,
|
||||||
|
dist: (u, seriesIdx) => (hRect?.sidx === seriesIdx ? 0 : Infinity),
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// Build bars
|
// Build bars
|
||||||
|
@ -225,6 +225,7 @@ export const plugin = new PanelPlugin<Options, FieldConfig>(BarChartPanel)
|
|||||||
path: 'fullHighlight',
|
path: 'fullHighlight',
|
||||||
name: 'Highlight full area on hover',
|
name: 'Highlight full area on hover',
|
||||||
defaultValue: defaultOptions.fullHighlight,
|
defaultValue: defaultOptions.fullHighlight,
|
||||||
|
showIf: (c) => c.stacking === StackingMode.None,
|
||||||
});
|
});
|
||||||
|
|
||||||
builder.addFieldNamePicker({
|
builder.addFieldNamePicker({
|
||||||
|
@ -14,24 +14,20 @@ export function pointWithin(px: number, py: number, rlft: number, rtop: number,
|
|||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
export function findRect(qt: Quadtree, sidx: number, didx: number): Rect | undefined {
|
export function findRects(qt: Quadtree, sidx?: number, didx?: number) {
|
||||||
let out: Rect | undefined;
|
let rects: Rect[] = [];
|
||||||
|
|
||||||
if (qt.o.length) {
|
if (qt.o.length) {
|
||||||
out = qt.o.find((rect) => rect.sidx === sidx && rect.didx === didx);
|
rects.push(...qt.o.filter((rect) => (sidx == null || rect.sidx === sidx) && (didx == null || rect.didx === didx)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (out == null && qt.q) {
|
if (qt.q) {
|
||||||
for (let i = 0; i < qt.q.length; i++) {
|
for (let i = 0; i < qt.q.length; i++) {
|
||||||
out = findRect(qt.q[i], sidx, didx);
|
rects.push(...findRects(qt.q[i], sidx, didx));
|
||||||
|
|
||||||
if (out) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return out;
|
return rects;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -17,6 +17,7 @@ import {
|
|||||||
getFieldDisplayName,
|
getFieldDisplayName,
|
||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
import { maybeSortFrame } from '@grafana/data/src/transformations/transformers/joinDataFrames';
|
import { maybeSortFrame } from '@grafana/data/src/transformations/transformers/joinDataFrames';
|
||||||
|
import { config as runtimeConfig } from '@grafana/runtime';
|
||||||
import {
|
import {
|
||||||
AxisColorMode,
|
AxisColorMode,
|
||||||
AxisPlacement,
|
AxisPlacement,
|
||||||
@ -33,6 +34,8 @@ import { AxisProps } from '@grafana/ui/src/components/uPlot/config/UPlotAxisBuil
|
|||||||
import { getStackingGroups } from '@grafana/ui/src/components/uPlot/utils';
|
import { getStackingGroups } from '@grafana/ui/src/components/uPlot/utils';
|
||||||
import { findField } from 'app/features/dimensions';
|
import { findField } from 'app/features/dimensions';
|
||||||
|
|
||||||
|
import { setClassicPaletteIdxs } from '../timeseries/utils';
|
||||||
|
|
||||||
import { BarsOptions, getConfig } from './bars';
|
import { BarsOptions, getConfig } from './bars';
|
||||||
import { FieldConfig, Options, defaultFieldConfig } from './panelcfg.gen';
|
import { FieldConfig, Options, defaultFieldConfig } from './panelcfg.gen';
|
||||||
import { BarChartDisplayValues, BarChartDisplayWarning } from './types';
|
import { BarChartDisplayValues, BarChartDisplayWarning } from './types';
|
||||||
@ -60,6 +63,7 @@ export interface BarChartOptionsEX extends Options {
|
|||||||
getColor?: (seriesIdx: number, valueIdx: number, value: unknown) => string | null;
|
getColor?: (seriesIdx: number, valueIdx: number, value: unknown) => string | null;
|
||||||
timeZone?: TimeZone;
|
timeZone?: TimeZone;
|
||||||
fillOpacity?: number;
|
fillOpacity?: number;
|
||||||
|
hoverMulti?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const preparePlotConfigBuilder: UPlotConfigPrepFn<BarChartOptionsEX> = ({
|
export const preparePlotConfigBuilder: UPlotConfigPrepFn<BarChartOptionsEX> = ({
|
||||||
@ -82,6 +86,7 @@ export const preparePlotConfigBuilder: UPlotConfigPrepFn<BarChartOptionsEX> = ({
|
|||||||
legend,
|
legend,
|
||||||
timeZone,
|
timeZone,
|
||||||
fullHighlight,
|
fullHighlight,
|
||||||
|
hoverMulti,
|
||||||
}) => {
|
}) => {
|
||||||
const builder = new UPlotConfigBuilder();
|
const builder = new UPlotConfigBuilder();
|
||||||
|
|
||||||
@ -122,6 +127,7 @@ export const preparePlotConfigBuilder: UPlotConfigPrepFn<BarChartOptionsEX> = ({
|
|||||||
xTimeAuto: frame.fields[0]?.type === FieldType.time && !frame.fields[0].config.unit?.startsWith('time:'),
|
xTimeAuto: frame.fields[0]?.type === FieldType.time && !frame.fields[0].config.unit?.startsWith('time:'),
|
||||||
negY: frame.fields.map((f) => f.config.custom?.transform === GraphTransform.NegativeY),
|
negY: frame.fields.map((f) => f.config.custom?.transform === GraphTransform.NegativeY),
|
||||||
fullHighlight,
|
fullHighlight,
|
||||||
|
hoverMulti,
|
||||||
};
|
};
|
||||||
|
|
||||||
const config = getConfig(opts, theme);
|
const config = getConfig(opts, theme);
|
||||||
@ -132,7 +138,8 @@ export const preparePlotConfigBuilder: UPlotConfigPrepFn<BarChartOptionsEX> = ({
|
|||||||
builder.addHook('drawClear', config.drawClear);
|
builder.addHook('drawClear', config.drawClear);
|
||||||
builder.addHook('draw', config.draw);
|
builder.addHook('draw', config.draw);
|
||||||
|
|
||||||
builder.setTooltipInterpolator(config.interpolateTooltip);
|
const showNewVizTooltips = Boolean(runtimeConfig.featureToggles.newVizTooltips);
|
||||||
|
!showNewVizTooltips && builder.setTooltipInterpolator(config.interpolateTooltip);
|
||||||
|
|
||||||
if (xTickLabelRotation !== 0) {
|
if (xTickLabelRotation !== 0) {
|
||||||
// these are the amount of space we already have available between plot edge and first label
|
// these are the amount of space we already have available between plot edge and first label
|
||||||
@ -389,7 +396,8 @@ export function prepareBarChartDisplayValues(
|
|||||||
series[0],
|
series[0],
|
||||||
series[0].fields.findIndex((f) => f.type === FieldType.time)
|
series[0].fields.findIndex((f) => f.type === FieldType.time)
|
||||||
)
|
)
|
||||||
: outerJoinDataFrames({ frames: series });
|
: outerJoinDataFrames({ frames: series, keepDisplayNames: true });
|
||||||
|
|
||||||
if (!frame) {
|
if (!frame) {
|
||||||
return { warn: 'Unable to join data' };
|
return { warn: 'Unable to join data' };
|
||||||
}
|
}
|
||||||
@ -478,6 +486,13 @@ export function prepareBarChartDisplayValues(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if both string and time fields exist, remove unused leftover time field
|
||||||
|
if (frame.fields[0].type === FieldType.time && frame.fields[0] !== firstField) {
|
||||||
|
frame.fields.shift();
|
||||||
|
}
|
||||||
|
|
||||||
|
setClassicPaletteIdxs([frame], theme, 0);
|
||||||
|
|
||||||
if (!fields.length) {
|
if (!fields.length) {
|
||||||
return {
|
return {
|
||||||
warn: 'No numeric fields found',
|
warn: 'No numeric fields found',
|
||||||
|
@ -242,7 +242,7 @@ const matchEnumColorToSeriesColor = (frames: DataFrame[], theme: GrafanaTheme2)
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const setClassicPaletteIdxs = (frames: DataFrame[], theme: GrafanaTheme2, skipFieldIdx?: number) => {
|
export const setClassicPaletteIdxs = (frames: DataFrame[], theme: GrafanaTheme2, skipFieldIdx?: number) => {
|
||||||
let seriesIndex = 0;
|
let seriesIndex = 0;
|
||||||
frames.forEach((frame) => {
|
frames.forEach((frame) => {
|
||||||
frame.fields.forEach((field, fieldIdx) => {
|
frame.fields.forEach((field, fieldIdx) => {
|
||||||
|
Loading…
Reference in New Issue
Block a user