mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Fix: prevents the BarGauge from exploding when the datasource returns empty result. (#21791)
* Fixed issue where gauge throw error on empty result. * Some refactorings to improve the code. * Added some tests to make sure this doesn't happen again.
This commit is contained in:
parent
8aed87394d
commit
cab082438e
@ -1,5 +1,6 @@
|
||||
import { Vector } from '../types/vector';
|
||||
import { DataFrame } from '../types/dataFrame';
|
||||
import { DisplayProcessor } from '../types';
|
||||
|
||||
/**
|
||||
* This abstraction will present the contents of a DataFrame as if
|
||||
@ -55,6 +56,20 @@ export class DataFrameView<T = any> implements Vector<T> {
|
||||
return this.data.length;
|
||||
}
|
||||
|
||||
getFieldDisplayProcessor(colIndex: number): DisplayProcessor | null {
|
||||
if (!this.dataFrame || !this.dataFrame.fields) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const field = this.dataFrame.fields[colIndex];
|
||||
|
||||
if (!field || !field.display) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return field.display;
|
||||
}
|
||||
|
||||
get(idx: number) {
|
||||
this.index = idx;
|
||||
return this.obj;
|
||||
|
@ -131,7 +131,8 @@ export class BarGauge extends PureComponent<Props> {
|
||||
};
|
||||
}
|
||||
|
||||
const color = display(positionValue).color;
|
||||
const color = display ? display(positionValue).color : null;
|
||||
|
||||
if (color) {
|
||||
// if we are past real value the cell is not "on"
|
||||
if (value === null || (positionValue !== null && positionValue > value.numeric)) {
|
||||
|
59
public/app/plugins/panel/bargauge/BarGaugePanel.test.tsx
Normal file
59
public/app/plugins/panel/bargauge/BarGaugePanel.test.tsx
Normal file
@ -0,0 +1,59 @@
|
||||
import React from 'react';
|
||||
import { mount, ReactWrapper } from 'enzyme';
|
||||
import { PanelData, dateMath, TimeRange, VizOrientation, PanelProps } from '@grafana/data';
|
||||
import { BarGaugeDisplayMode } from '@grafana/ui';
|
||||
|
||||
import { BarGaugePanel } from './BarGaugePanel';
|
||||
import { BarGaugeOptions } from './types';
|
||||
|
||||
describe('BarGaugePanel', () => {
|
||||
describe('when empty result is rendered', () => {
|
||||
const wrapper = createBarGaugePanelWithData({
|
||||
series: [],
|
||||
timeRange: null,
|
||||
state: null,
|
||||
});
|
||||
|
||||
it('should render with title "No data"', () => {
|
||||
const displayValue = wrapper.find('div.bar-gauge__value').text();
|
||||
expect(displayValue).toBe('No data');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function createBarGaugePanelWithData(data: PanelData): ReactWrapper<PanelProps<BarGaugeOptions>> {
|
||||
const timeRange: TimeRange = {
|
||||
from: dateMath.parse('now-6h'),
|
||||
to: dateMath.parse('now'),
|
||||
raw: { from: 'now-6h', to: 'now' },
|
||||
};
|
||||
|
||||
const options: BarGaugeOptions = {
|
||||
displayMode: BarGaugeDisplayMode.Lcd,
|
||||
fieldOptions: {
|
||||
calcs: ['mean'],
|
||||
defaults: {},
|
||||
values: false,
|
||||
overrides: [],
|
||||
},
|
||||
orientation: VizOrientation.Horizontal,
|
||||
showUnfilled: true,
|
||||
};
|
||||
|
||||
return mount<BarGaugePanel>(
|
||||
<BarGaugePanel
|
||||
id={1}
|
||||
data={data}
|
||||
timeRange={timeRange}
|
||||
timeZone={'utc'}
|
||||
options={options}
|
||||
onOptionsChange={() => {}}
|
||||
onChangeTimeRange={() => {}}
|
||||
replaceVariables={s => s}
|
||||
renderCounter={0}
|
||||
width={532}
|
||||
transparent={false}
|
||||
height={250}
|
||||
/>
|
||||
);
|
||||
}
|
@ -24,7 +24,6 @@ export class BarGaugePanel extends PureComponent<PanelProps<BarGaugeOptions>> {
|
||||
): JSX.Element => {
|
||||
const { options } = this.props;
|
||||
const { field, display, view, colIndex } = value;
|
||||
const f = view.dataFrame.fields[colIndex];
|
||||
|
||||
return (
|
||||
<DataLinksContextMenu links={getFieldLinksSupplier(value)}>
|
||||
@ -36,7 +35,7 @@ export class BarGaugePanel extends PureComponent<PanelProps<BarGaugeOptions>> {
|
||||
height={height}
|
||||
orientation={options.orientation}
|
||||
field={field}
|
||||
display={f.display!}
|
||||
display={view?.getFieldDisplayProcessor(colIndex)}
|
||||
theme={config.theme}
|
||||
itemSpacing={this.getItemSpacing()}
|
||||
displayMode={options.displayMode}
|
||||
|
Loading…
Reference in New Issue
Block a user