From 1ed73ecef82af9ec2d0d96359034e52733468759 Mon Sep 17 00:00:00 2001 From: Oscar Kilhed Date: Mon, 12 Apr 2021 14:45:12 +0200 Subject: [PATCH] Makes pie chart component accept data frames (#32829) * Makes pie chart component accept dataframes --- .../components/PieChart/PieChart.story.tsx | 84 ++++++++++++++----- .../src/components/PieChart/PieChart.tsx | 73 ++++++++-------- .../src/components/PieChart/types.ts | 41 +++++++++ packages/grafana-ui/src/components/index.ts | 9 +- .../plugins/panel/piechart/PieChartPanel.tsx | 19 ++--- 5 files changed, 147 insertions(+), 79 deletions(-) create mode 100644 packages/grafana-ui/src/components/PieChart/types.ts diff --git a/packages/grafana-ui/src/components/PieChart/PieChart.story.tsx b/packages/grafana-ui/src/components/PieChart/PieChart.story.tsx index d021770d37c..6ba091188ac 100644 --- a/packages/grafana-ui/src/components/PieChart/PieChart.story.tsx +++ b/packages/grafana-ui/src/components/PieChart/PieChart.story.tsx @@ -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 ; + return ( + + ); }; export const donut = () => { - const { datapoints, width, height } = getKnobs(); + const { width, height } = getKnobs(); - return ; + return ( + + ); }; diff --git a/packages/grafana-ui/src/components/PieChart/PieChart.tsx b/packages/grafana-ui/src/components/PieChart/PieChart.tsx index 71d34d88225..47495e219bb 100644 --- a/packages/grafana-ui/src/components/PieChart/PieChart.tsx +++ b/packages/grafana-ui/src/components/PieChart/PieChart.tsx @@ -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 = ({ - fieldDisplayValues, +export const PieChart: FC = ({ + 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 = ({ ); }; + const fieldDisplayValues = getFieldDisplayValues({ + fieldConfig, + reduceOptions, + data, + theme, + replaceVariables, + timeZone, + }); + return ( {(vizWidth: number, vizHeight: number) => { @@ -122,7 +119,7 @@ export const PieChart: FC = ({ ); }; -export const PieChartSvg: FC = ({ +export const PieChartSvg: FC = ({ fieldDisplayValues, pieType, width, diff --git a/packages/grafana-ui/src/components/PieChart/types.ts b/packages/grafana-ui/src/components/PieChart/types.ts new file mode 100644 index 00000000000..89a1d929e19 --- /dev/null +++ b/packages/grafana-ui/src/components/PieChart/types.ts @@ -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 { + legendOptions?: PieChartLegendOptions; + reduceOptions: ReduceDataOptions; + fieldConfig: FieldConfigSource; + 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[]; +} diff --git a/packages/grafana-ui/src/components/index.ts b/packages/grafana-ui/src/components/index.ts index 2c00fe24cc3..bb04c76f3bf 100644 --- a/packages/grafana-ui/src/components/index.ts +++ b/packages/grafana-ui/src/components/index.ts @@ -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'; diff --git a/public/app/plugins/panel/piechart/PieChartPanel.tsx b/public/app/plugins/panel/piechart/PieChartPanel.tsx index 258e81d4d81..bd6b63e979d 100644 --- a/public/app/plugins/panel/piechart/PieChartPanel.tsx +++ b/public/app/plugins/panel/piechart/PieChartPanel.tsx @@ -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 {} @@ -23,20 +23,15 @@ export const PieChartPanel: React.FC = ({ [fieldConfig, onFieldConfigChange] ); - const fieldDisplayValues = getFieldDisplayValues({ - fieldConfig, - reduceOptions: options.reduceOptions, - data: data.series, - theme: useTheme(), - replaceVariables: replaceVariables, - timeZone, - }); - return (