Makes pie chart component accept data frames (#32829)

* Makes pie chart component accept dataframes
This commit is contained in:
Oscar Kilhed 2021-04-12 14:45:12 +02:00 committed by GitHub
parent 629603dd92
commit 1ed73ecef8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 147 additions and 79 deletions

View File

@ -1,8 +1,16 @@
import React from 'react';
import { object, select, number, boolean } from '@storybook/addon-knobs';
import { select, number, boolean } from '@storybook/addon-knobs';
import { PieChart, PieChartType } from '@grafana/ui';
import { withCenteredStory } from '../../utils/storybook/withCenteredStory';
import { FieldConfig } from '@grafana/data';
import {
FieldColorModeId,
FieldConfigSource,
FieldType,
InterpolateFunction,
ReduceDataOptions,
ThresholdsMode,
toDataFrame,
} from '@grafana/data';
export default {
title: 'Visualizations/PieChart',
@ -10,26 +18,38 @@ export default {
component: PieChart,
};
const fieldConfig: FieldConfig = {
displayName: '',
min: 0,
max: 10,
decimals: 10,
thresholds: {} as any,
noValue: 'no value',
unit: 'km/s',
links: {} as any,
const fieldConfig: FieldConfigSource = {
defaults: {
thresholds: {
mode: ThresholdsMode.Percentage,
steps: [{ color: 'green', value: 0 }],
},
color: {
mode: FieldColorModeId.PaletteClassic,
},
},
overrides: [],
};
const reduceOptions: ReduceDataOptions = { calcs: [] };
const replaceVariables: InterpolateFunction = (v) => v;
const datapoints = [
toDataFrame({
fields: [
{ name: 'time', type: FieldType.time, values: [1618197346845, 1618197346845] },
{ name: 'Living room', type: FieldType.number, values: [19, 21] },
],
}),
toDataFrame({
fields: [
{ name: 'time', type: FieldType.time, values: [1618197346845, 1618197346845] },
{ name: 'Cellar', type: FieldType.number, values: [5, 6] },
],
}),
];
const getKnobs = () => {
return {
datapoints: object('datapoints', [
{ field: fieldConfig, hasLinks: false, name: 'USA', display: { numeric: 100, text: '100', title: 'USA' } },
{ field: fieldConfig, hasLinks: false, name: 'Canada', display: { numeric: 200, text: '200', title: 'Canada' } },
{ field: fieldConfig, hasLinks: false, name: 'Sweden', display: { numeric: 20, text: '20', title: 'Sweden' } },
{ field: fieldConfig, hasLinks: false, name: 'Spain', display: { numeric: 50, text: '50', title: 'Spain' } },
{ field: fieldConfig, hasLinks: false, name: 'Germany', display: { numeric: 70, text: '70', title: 'Germeny' } },
]),
width: number('Width', 500),
height: number('Height', 500),
pieType: select('pieType', [PieChartType.Pie, PieChartType.Donut], PieChartType.Pie),
@ -40,13 +60,33 @@ const getKnobs = () => {
};
export const basic = () => {
const { datapoints, pieType, width, height } = getKnobs();
const { pieType, width, height } = getKnobs();
return <PieChart width={width} height={height} fieldDisplayValues={datapoints} pieType={pieType} />;
return (
<PieChart
width={width}
height={height}
replaceVariables={replaceVariables}
reduceOptions={reduceOptions}
fieldConfig={fieldConfig}
data={datapoints}
pieType={pieType}
/>
);
};
export const donut = () => {
const { datapoints, width, height } = getKnobs();
const { width, height } = getKnobs();
return <PieChart width={width} height={height} fieldDisplayValues={datapoints} pieType={PieChartType.Donut} />;
return (
<PieChart
width={width}
height={height}
replaceVariables={replaceVariables}
reduceOptions={reduceOptions}
fieldConfig={fieldConfig}
data={datapoints}
pieType={PieChartType.Donut}
/>
);
};

View File

@ -1,5 +1,12 @@
import React, { FC, ReactNode } from 'react';
import { DisplayValue, FALLBACK_COLOR, FieldDisplay, formattedValueToString, GrafanaTheme } from '@grafana/data';
import {
DisplayValue,
FALLBACK_COLOR,
FieldDisplay,
formattedValueToString,
getFieldDisplayValues,
GrafanaTheme,
} from '@grafana/data';
import { useStyles, useTheme } from '../../themes/ThemeContext';
import tinycolor from 'tinycolor2';
import Pie, { PieArcDatum, ProvidedProps } from '@visx/shape/lib/shapes/Pie';
@ -11,42 +18,17 @@ import { useComponentInstanceId } from '../../utils/useComponetInstanceId';
import { css } from '@emotion/css';
import { VizLegend, VizLegendItem } from '..';
import { VizLayout } from '../VizLayout/VizLayout';
import { LegendDisplayMode, VizLegendOptions } from '../VizLegend/models.gen';
import { LegendDisplayMode } from '../VizLegend/models.gen';
import { DataLinksContextMenu } from '../DataLinks/DataLinksContextMenu';
import { UseTooltipParams } from '@visx/tooltip/lib/hooks/useTooltip';
export enum PieChartLabels {
Name = 'name',
Value = 'value',
Percent = 'percent',
}
export enum PieChartLegendValues {
Value = 'value',
Percent = 'percent',
}
interface SvgProps {
height: number;
width: number;
fieldDisplayValues: FieldDisplay[];
pieType: PieChartType;
displayLabels?: PieChartLabels[];
useGradients?: boolean;
onSeriesColorChange?: (label: string, color: string) => void;
}
export interface Props extends SvgProps {
legendOptions?: PieChartLegendOptions;
}
export enum PieChartType {
Pie = 'pie',
Donut = 'donut',
}
export interface PieChartLegendOptions extends VizLegendOptions {
values: PieChartLegendValues[];
}
import {
PieChartLabels,
PieChartLegendOptions,
PieChartLegendValues,
PieChartProps,
PieChartSvgProps,
PieChartType,
} from './types';
const defaultLegendOptions: PieChartLegendOptions = {
displayMode: LegendDisplayMode.List,
@ -55,14 +37,20 @@ const defaultLegendOptions: PieChartLegendOptions = {
values: [PieChartLegendValues.Percent],
};
export const PieChart: FC<Props> = ({
fieldDisplayValues,
export const PieChart: FC<PieChartProps> = ({
data,
timeZone,
reduceOptions,
fieldConfig,
replaceVariables,
legendOptions = defaultLegendOptions,
onSeriesColorChange,
width,
height,
...restProps
}) => {
const theme = useTheme();
const getLegend = (fields: FieldDisplay[], legendOptions: PieChartLegendOptions) => {
if (legendOptions.displayMode === LegendDisplayMode.Hidden) {
return undefined;
@ -111,6 +99,15 @@ export const PieChart: FC<Props> = ({
);
};
const fieldDisplayValues = getFieldDisplayValues({
fieldConfig,
reduceOptions,
data,
theme,
replaceVariables,
timeZone,
});
return (
<VizLayout width={width} height={height} legend={getLegend(fieldDisplayValues, legendOptions)}>
{(vizWidth: number, vizHeight: number) => {
@ -122,7 +119,7 @@ export const PieChart: FC<Props> = ({
);
};
export const PieChartSvg: FC<SvgProps> = ({
export const PieChartSvg: FC<PieChartSvgProps> = ({
fieldDisplayValues,
pieType,
width,

View File

@ -0,0 +1,41 @@
import { DataFrame, FieldConfigSource, FieldDisplay, InterpolateFunction, ReduceDataOptions } from '@grafana/data';
import { VizLegendOptions } from '..';
export interface PieChartSvgProps {
height: number;
width: number;
fieldDisplayValues: FieldDisplay[];
pieType: PieChartType;
displayLabels?: PieChartLabels[];
useGradients?: boolean;
onSeriesColorChange?: (label: string, color: string) => void;
}
export interface PieChartProps extends Omit<PieChartSvgProps, 'fieldDisplayValues'> {
legendOptions?: PieChartLegendOptions;
reduceOptions: ReduceDataOptions;
fieldConfig: FieldConfigSource<any>;
replaceVariables: InterpolateFunction;
data: DataFrame[];
timeZone?: string;
}
export enum PieChartType {
Pie = 'pie',
Donut = 'donut',
}
export enum PieChartLegendValues {
Value = 'value',
Percent = 'percent',
}
export enum PieChartLabels {
Name = 'name',
Value = 'value',
Percent = 'percent',
}
export interface PieChartLegendOptions extends VizLegendOptions {
values: PieChartLegendValues[];
}

View File

@ -18,13 +18,8 @@ export { ColorPicker, SeriesColorPicker } from './ColorPicker/ColorPicker';
export { ColorValueEditor, ColorValueEditorProps } from './OptionsUI/color';
export { SeriesColorPickerPopover, SeriesColorPickerPopoverWithTheme } from './ColorPicker/SeriesColorPickerPopover';
export { EmptySearchResult } from './EmptySearchResult/EmptySearchResult';
export {
PieChart,
PieChartType,
PieChartLabels,
PieChartLegendOptions,
PieChartLegendValues,
} from './PieChart/PieChart';
export { PieChart } from './PieChart/PieChart';
export { PieChartType, PieChartLabels, PieChartLegendOptions, PieChartLegendValues } from './PieChart/types';
export { UnitPicker } from './UnitPicker/UnitPicker';
export { StatsPicker } from './StatsPicker/StatsPicker';
export { RefreshPicker, defaultIntervals } from './RefreshPicker/RefreshPicker';

View File

@ -1,7 +1,7 @@
import React, { useCallback } from 'react';
import { PieChart, useTheme } from '@grafana/ui';
import { PieChart } from '@grafana/ui';
import { PieChartOptions } from './types';
import { getFieldDisplayValues, PanelProps } from '@grafana/data';
import { PanelProps } from '@grafana/data';
import { changeSeriesColorConfigFactory } from '../timeseries/overrides/colorSeriesConfigFactory';
interface Props extends PanelProps<PieChartOptions> {}
@ -23,20 +23,15 @@ export const PieChartPanel: React.FC<Props> = ({
[fieldConfig, onFieldConfigChange]
);
const fieldDisplayValues = getFieldDisplayValues({
fieldConfig,
reduceOptions: options.reduceOptions,
data: data.series,
theme: useTheme(),
replaceVariables: replaceVariables,
timeZone,
});
return (
<PieChart
width={width}
height={height}
fieldDisplayValues={fieldDisplayValues}
timeZone={timeZone}
fieldConfig={fieldConfig}
reduceOptions={options.reduceOptions}
replaceVariables={replaceVariables}
data={data.series}
onSeriesColorChange={onSeriesColorChange}
pieType={options.pieType}
displayLabels={options.displayLabels}