mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
BarChart: Use new data error view component to show actions in panel edit (#42474)
This commit is contained in:
parent
a0333c1545
commit
8828d5e8d7
@ -12,6 +12,7 @@ export interface PanelDataErrorViewProps {
|
|||||||
data: PanelData;
|
data: PanelData;
|
||||||
needsTimeField?: boolean;
|
needsTimeField?: boolean;
|
||||||
needsNumberField?: boolean;
|
needsNumberField?: boolean;
|
||||||
|
needsStringField?: boolean;
|
||||||
// suggestions?: VisualizationSuggestion[]; <<< for sure optional
|
// suggestions?: VisualizationSuggestion[]; <<< for sure optional
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ export function PanelDataErrorView(props: PanelDataErrorViewProps) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getMessageFor(
|
function getMessageFor(
|
||||||
{ data, message, needsNumberField, needsTimeField }: PanelDataErrorViewProps,
|
{ data, message, needsNumberField, needsTimeField, needsStringField }: PanelDataErrorViewProps,
|
||||||
dataSummary: PanelDataSummary
|
dataSummary: PanelDataSummary
|
||||||
): string {
|
): string {
|
||||||
if (message) {
|
if (message) {
|
||||||
@ -68,6 +68,10 @@ function getMessageFor(
|
|||||||
return 'No data';
|
return 'No data';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (needsStringField && !dataSummary.hasStringField) {
|
||||||
|
return 'Data is missing a string field';
|
||||||
|
}
|
||||||
|
|
||||||
if (needsNumberField && !dataSummary.hasNumberField) {
|
if (needsNumberField && !dataSummary.hasNumberField) {
|
||||||
return 'Data is missing a number field';
|
return 'Data is missing a number field';
|
||||||
}
|
}
|
||||||
|
@ -5,16 +5,17 @@ import { measureText, TooltipPlugin, UPLOT_AXIS_FONT_SIZE, useTheme2 } from '@gr
|
|||||||
import { BarChartOptions } from './types';
|
import { BarChartOptions } from './types';
|
||||||
import { BarChart } from './BarChart';
|
import { BarChart } from './BarChart';
|
||||||
import { prepareGraphableFrames } from './utils';
|
import { prepareGraphableFrames } from './utils';
|
||||||
|
import { PanelDataErrorView } from '@grafana/runtime';
|
||||||
|
|
||||||
interface Props extends PanelProps<BarChartOptions> {}
|
interface Props extends PanelProps<BarChartOptions> {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @alpha
|
* @alpha
|
||||||
*/
|
*/
|
||||||
export const BarChartPanel: React.FunctionComponent<Props> = ({ data, options, width, height, timeZone }) => {
|
export const BarChartPanel: React.FunctionComponent<Props> = ({ data, options, width, height, timeZone, id }) => {
|
||||||
const theme = useTheme2();
|
const theme = useTheme2();
|
||||||
|
|
||||||
const { frames, warn } = useMemo(() => prepareGraphableFrames(data?.series, theme, options), [data, theme, options]);
|
const frames = useMemo(() => prepareGraphableFrames(data?.series, theme, options), [data, theme, options]);
|
||||||
const orientation = useMemo(() => {
|
const orientation = useMemo(() => {
|
||||||
if (!options.orientation || options.orientation === VizOrientation.Auto) {
|
if (!options.orientation || options.orientation === VizOrientation.Auto) {
|
||||||
return width < height ? VizOrientation.Horizontal : VizOrientation.Vertical;
|
return width < height ? VizOrientation.Horizontal : VizOrientation.Vertical;
|
||||||
@ -48,12 +49,8 @@ export const BarChartPanel: React.FunctionComponent<Props> = ({ data, options, w
|
|||||||
return options.tooltip;
|
return options.tooltip;
|
||||||
}, [options.tooltip, options.stacking]);
|
}, [options.tooltip, options.stacking]);
|
||||||
|
|
||||||
if (!frames || warn) {
|
if (!frames) {
|
||||||
return (
|
return <PanelDataErrorView panelId={id} data={data} needsStringField={true} needsNumberField={true} />;
|
||||||
<div className="panel-empty">
|
|
||||||
<p>{warn ?? 'No data found in response'}</p>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -147,7 +147,7 @@ describe('BarChart utils', () => {
|
|||||||
describe('prepareGraphableFrames', () => {
|
describe('prepareGraphableFrames', () => {
|
||||||
it('will warn when there is no data in the response', () => {
|
it('will warn when there is no data in the response', () => {
|
||||||
const result = prepareGraphableFrames([], createTheme(), { stacking: StackingMode.None } as any);
|
const result = prepareGraphableFrames([], createTheme(), { stacking: StackingMode.None } as any);
|
||||||
expect(result.warn).toEqual('No data in response');
|
expect(result).toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('will warn when there is no string field in the response', () => {
|
it('will warn when there is no string field in the response', () => {
|
||||||
@ -158,8 +158,7 @@ describe('BarChart utils', () => {
|
|||||||
],
|
],
|
||||||
});
|
});
|
||||||
const result = prepareGraphableFrames([df], createTheme(), { stacking: StackingMode.None } as any);
|
const result = prepareGraphableFrames([df], createTheme(), { stacking: StackingMode.None } as any);
|
||||||
expect(result.warn).toEqual('Bar charts requires a string field');
|
expect(result).toBeNull();
|
||||||
expect(result.frames).toBeUndefined();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('will warn when there are no numeric fields in the response', () => {
|
it('will warn when there are no numeric fields in the response', () => {
|
||||||
@ -170,8 +169,7 @@ describe('BarChart utils', () => {
|
|||||||
],
|
],
|
||||||
});
|
});
|
||||||
const result = prepareGraphableFrames([df], createTheme(), { stacking: StackingMode.None } as any);
|
const result = prepareGraphableFrames([df], createTheme(), { stacking: StackingMode.None } as any);
|
||||||
expect(result.warn).toEqual('No numeric fields found');
|
expect(result).toBeNull();
|
||||||
expect(result.frames).toBeUndefined();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('will convert NaN and Infinty to nulls', () => {
|
it('will convert NaN and Infinty to nulls', () => {
|
||||||
@ -181,9 +179,9 @@ describe('BarChart utils', () => {
|
|||||||
{ name: 'value', values: [-10, NaN, 10, -Infinity, +Infinity] },
|
{ name: 'value', values: [-10, NaN, 10, -Infinity, +Infinity] },
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
const result = prepareGraphableFrames([df], createTheme(), { stacking: StackingMode.None } as any);
|
const frames = prepareGraphableFrames([df], createTheme(), { stacking: StackingMode.None } as any)!;
|
||||||
|
|
||||||
const field = result.frames![0].fields[1];
|
const field = frames[0].fields[1];
|
||||||
expect(field!.values.toArray()).toMatchInlineSnapshot(`
|
expect(field!.values.toArray()).toMatchInlineSnapshot(`
|
||||||
Array [
|
Array [
|
||||||
-10,
|
-10,
|
||||||
@ -205,21 +203,23 @@ describe('BarChart utils', () => {
|
|||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
const resultAsc = prepareGraphableFrames([frame], createTheme(), {
|
const framesAsc = prepareGraphableFrames([frame], createTheme(), {
|
||||||
legend: { sortBy: 'Min', sortDesc: false },
|
legend: { sortBy: 'Min', sortDesc: false },
|
||||||
} as any);
|
} as any)!;
|
||||||
expect(resultAsc.frames![0].fields[0].type).toBe(FieldType.string);
|
|
||||||
expect(resultAsc.frames![0].fields[1].name).toBe('a');
|
|
||||||
expect(resultAsc.frames![0].fields[2].name).toBe('c');
|
|
||||||
expect(resultAsc.frames![0].fields[3].name).toBe('b');
|
|
||||||
|
|
||||||
const resultDesc = prepareGraphableFrames([frame], createTheme(), {
|
expect(framesAsc[0].fields[0].type).toBe(FieldType.string);
|
||||||
|
expect(framesAsc[0].fields[1].name).toBe('a');
|
||||||
|
expect(framesAsc[0].fields[2].name).toBe('c');
|
||||||
|
expect(framesAsc[0].fields[3].name).toBe('b');
|
||||||
|
|
||||||
|
const framesDesc = prepareGraphableFrames([frame], createTheme(), {
|
||||||
legend: { sortBy: 'Min', sortDesc: true },
|
legend: { sortBy: 'Min', sortDesc: true },
|
||||||
} as any);
|
} as any)!;
|
||||||
expect(resultDesc.frames![0].fields[0].type).toBe(FieldType.string);
|
|
||||||
expect(resultDesc.frames![0].fields[1].name).toBe('b');
|
expect(framesDesc[0].fields[0].type).toBe(FieldType.string);
|
||||||
expect(resultDesc.frames![0].fields[2].name).toBe('c');
|
expect(framesDesc[0].fields[1].name).toBe('b');
|
||||||
expect(resultDesc.frames![0].fields[3].name).toBe('a');
|
expect(framesDesc[0].fields[2].name).toBe('c');
|
||||||
|
expect(framesDesc[0].fields[3].name).toBe('a');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -298,24 +298,20 @@ export function prepareGraphableFrames(
|
|||||||
series: DataFrame[],
|
series: DataFrame[],
|
||||||
theme: GrafanaTheme2,
|
theme: GrafanaTheme2,
|
||||||
options: BarChartOptions
|
options: BarChartOptions
|
||||||
): { frames?: DataFrame[]; warn?: string } {
|
): DataFrame[] | null {
|
||||||
if (!series?.length) {
|
if (!series?.length) {
|
||||||
return { warn: 'No data in response' };
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const frames: DataFrame[] = [];
|
const frames: DataFrame[] = [];
|
||||||
const firstFrame = series[0];
|
const firstFrame = series[0];
|
||||||
|
|
||||||
if (!firstFrame.fields.some((f) => f.type === FieldType.string)) {
|
if (!firstFrame.fields.some((f) => f.type === FieldType.string)) {
|
||||||
return {
|
return null;
|
||||||
warn: 'Bar charts requires a string field',
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!firstFrame.fields.some((f) => f.type === FieldType.number)) {
|
if (!firstFrame.fields.some((f) => f.type === FieldType.number)) {
|
||||||
return {
|
return null;
|
||||||
warn: 'No numeric fields found',
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const legendOrdered = isLegendOrdered(options.legend);
|
const legendOrdered = isLegendOrdered(options.legend);
|
||||||
@ -384,7 +380,7 @@ export function prepareGraphableFrames(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return { frames };
|
return frames;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const isLegendOrdered = (options: VizLegendOptions) => Boolean(options?.sortBy && options.sortDesc !== null);
|
export const isLegendOrdered = (options: VizLegendOptions) => Boolean(options?.sortBy && options.sortDesc !== null);
|
||||||
|
Loading…
Reference in New Issue
Block a user