mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
BarChart: fix stale bar values and x axis labels (#39188)
This commit is contained in:
parent
063160aae2
commit
df6b6e7a98
@ -210,7 +210,7 @@ export class GraphNG extends React.Component<GraphNGProps, GraphNGState> {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { width, height, children, timeRange, renderLegend } = this.props;
|
const { width, height, children, timeRange, renderLegend } = this.props;
|
||||||
const { config, alignedFrame } = this.state;
|
const { config, alignedFrame, alignedData } = this.state;
|
||||||
|
|
||||||
if (!config) {
|
if (!config) {
|
||||||
return null;
|
return null;
|
||||||
@ -220,8 +220,8 @@ export class GraphNG extends React.Component<GraphNGProps, GraphNGState> {
|
|||||||
<VizLayout width={width} height={height} legend={renderLegend(config)}>
|
<VizLayout width={width} height={height} legend={renderLegend(config)}>
|
||||||
{(vizWidth: number, vizHeight: number) => (
|
{(vizWidth: number, vizHeight: number) => (
|
||||||
<UPlotChart
|
<UPlotChart
|
||||||
config={this.state.config!}
|
config={config}
|
||||||
data={this.state.alignedData}
|
data={alignedData}
|
||||||
width={vizWidth}
|
width={vizWidth}
|
||||||
height={vizHeight}
|
height={vizHeight}
|
||||||
timeRange={timeRange}
|
timeRange={timeRange}
|
||||||
|
@ -101,6 +101,14 @@ export class UPlotChart extends React.Component<PlotProps, UPlotChartState> {
|
|||||||
this.reinitPlot();
|
this.reinitPlot();
|
||||||
} else if (!sameData(prevProps, this.props)) {
|
} else if (!sameData(prevProps, this.props)) {
|
||||||
plot?.setData(this.props.data);
|
plot?.setData(this.props.data);
|
||||||
|
|
||||||
|
// this is a uPlot cache-busting hack for bar charts in case x axis labels changed
|
||||||
|
// since the x scale's "range" doesnt change, the axis size doesnt get recomputed, which is where the tick labels are regenerated & cached
|
||||||
|
// the more expensive, more proper/thorough way to do this is to force all axes to recalc: plot?.redraw(false, true);
|
||||||
|
if (plot && typeof this.props.data[0][0] === 'string') {
|
||||||
|
//@ts-ignore
|
||||||
|
plot.axes[0]._values = this.props.data[0];
|
||||||
|
}
|
||||||
} else if (!sameTimeRange(prevProps, this.props)) {
|
} else if (!sameTimeRange(prevProps, this.props)) {
|
||||||
plot?.setScale('x', {
|
plot?.setScale('x', {
|
||||||
min: this.props.timeRange.from.valueOf(),
|
min: this.props.timeRange.from.valueOf(),
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React from 'react';
|
import React, { useRef } from 'react';
|
||||||
import { cloneDeep } from 'lodash';
|
import { cloneDeep } from 'lodash';
|
||||||
import { DataFrame, TimeRange } from '@grafana/data';
|
import { DataFrame, TimeRange } from '@grafana/data';
|
||||||
import { GraphNG, GraphNGProps, PlotLegend, UPlotConfigBuilder, usePanelContext, useTheme2 } from '@grafana/ui';
|
import { GraphNG, GraphNGProps, PlotLegend, UPlotConfigBuilder, usePanelContext, useTheme2 } from '@grafana/ui';
|
||||||
@ -27,6 +27,9 @@ export const BarChart: React.FC<BarChartProps> = (props) => {
|
|||||||
const theme = useTheme2();
|
const theme = useTheme2();
|
||||||
const { eventBus } = usePanelContext();
|
const { eventBus } = usePanelContext();
|
||||||
|
|
||||||
|
const frame0Ref = useRef<DataFrame>();
|
||||||
|
frame0Ref.current = props.frames[0];
|
||||||
|
|
||||||
const renderLegend = (config: UPlotConfigBuilder) => {
|
const renderLegend = (config: UPlotConfigBuilder) => {
|
||||||
if (!config || props.legend.displayMode === LegendDisplayMode.Hidden) {
|
if (!config || props.legend.displayMode === LegendDisplayMode.Hidden) {
|
||||||
return null;
|
return null;
|
||||||
@ -35,6 +38,8 @@ export const BarChart: React.FC<BarChartProps> = (props) => {
|
|||||||
return <PlotLegend data={props.frames} config={config} maxHeight="35%" maxWidth="60%" {...props.legend} />;
|
return <PlotLegend data={props.frames} config={config} maxHeight="35%" maxWidth="60%" {...props.legend} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const rawValue = (seriesIdx: number, valueIdx: number) => frame0Ref.current!.fields[seriesIdx].values.get(valueIdx);
|
||||||
|
|
||||||
const prepConfig = (alignedFrame: DataFrame, allFrames: DataFrame[], getTimeRange: () => TimeRange) => {
|
const prepConfig = (alignedFrame: DataFrame, allFrames: DataFrame[], getTimeRange: () => TimeRange) => {
|
||||||
const { timeZone, orientation, barWidth, showValue, groupWidth, stacking, legend, tooltip, text } = props;
|
const { timeZone, orientation, barWidth, showValue, groupWidth, stacking, legend, tooltip, text } = props;
|
||||||
|
|
||||||
@ -52,6 +57,7 @@ export const BarChart: React.FC<BarChartProps> = (props) => {
|
|||||||
legend,
|
legend,
|
||||||
tooltip,
|
tooltip,
|
||||||
text,
|
text,
|
||||||
|
rawValue,
|
||||||
allFrames: props.frames,
|
allFrames: props.frames,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -19,6 +19,7 @@ export interface BarChartOptions extends OptionsWithLegend, OptionsWithTooltip,
|
|||||||
showValue: BarValueVisibility;
|
showValue: BarValueVisibility;
|
||||||
barWidth: number;
|
barWidth: number;
|
||||||
groupWidth: number;
|
groupWidth: number;
|
||||||
|
rawValue: (seriesIdx: number, valueIdx: number) => number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -94,6 +94,7 @@ describe('BarChart utils', () => {
|
|||||||
text: {
|
text: {
|
||||||
valueSize: 10,
|
valueSize: 10,
|
||||||
},
|
},
|
||||||
|
rawValue: (seriesIdx: number, valueIdx: number) => frame.fields[seriesIdx].values.get(valueIdx),
|
||||||
};
|
};
|
||||||
|
|
||||||
it.each([VizOrientation.Auto, VizOrientation.Horizontal, VizOrientation.Vertical])('orientation', (v) => {
|
it.each([VizOrientation.Auto, VizOrientation.Horizontal, VizOrientation.Vertical])('orientation', (v) => {
|
||||||
|
@ -45,6 +45,7 @@ export const preparePlotConfigBuilder: UPlotConfigPrepFn<BarChartOptions> = ({
|
|||||||
barWidth,
|
barWidth,
|
||||||
stacking,
|
stacking,
|
||||||
text,
|
text,
|
||||||
|
rawValue,
|
||||||
}) => {
|
}) => {
|
||||||
const builder = new UPlotConfigBuilder();
|
const builder = new UPlotConfigBuilder();
|
||||||
const defaultValueFormatter = (seriesIdx: number, value: any) =>
|
const defaultValueFormatter = (seriesIdx: number, value: any) =>
|
||||||
@ -67,7 +68,7 @@ export const preparePlotConfigBuilder: UPlotConfigPrepFn<BarChartOptions> = ({
|
|||||||
groupWidth,
|
groupWidth,
|
||||||
barWidth,
|
barWidth,
|
||||||
stacking,
|
stacking,
|
||||||
rawValue: (seriesIdx: number, valueIdx: number) => frame.fields[seriesIdx].values.get(valueIdx),
|
rawValue,
|
||||||
formatValue,
|
formatValue,
|
||||||
text,
|
text,
|
||||||
showValue,
|
showValue,
|
||||||
|
Loading…
Reference in New Issue
Block a user