From fe5fc75ded12f9c2fb861065136383ebb3222c06 Mon Sep 17 00:00:00 2001 From: Oscar Kilhed Date: Mon, 10 May 2021 22:25:14 +0200 Subject: [PATCH] Refactor and unify option creation between new visualizations (#33867) * Refactor and unify option creation between new visualizations * move to grafana/ui * move to grafana/ui * resolve duplicate scale config * more imports Co-authored-by: Ryan McKinley --- .../src/components/BarChart/utils.ts | 3 +- .../grafana-ui/src/components/uPlot/config.ts | 10 +- .../uPlot/config/UPlotConfigBuilder.test.ts | 2 +- .../uPlot/config/UPlotScaleBuilder.ts | 7 +- .../src/components/uPlot/models.cue | 2 +- .../src/components/uPlot/models.gen.ts | 1 + packages/grafana-ui/src/index.ts | 1 + .../grafana-ui/src/options/builder/axis.tsx | 153 ++++++++++++++++++ .../src/options/builder/hideSeries.tsx | 56 +++++++ .../grafana-ui/src/options/builder/index.ts | 3 + .../grafana-ui/src/options/builder/legend.tsx | 57 +++++++ packages/grafana-ui/src/options/index.ts | 4 + packages/grafana-ui/src/options/models.gen.ts | 7 + public/app/plugins/panel/barchart/module.tsx | 16 +- .../app/plugins/panel/histogram/Histogram.tsx | 8 +- public/app/plugins/panel/piechart/module.tsx | 57 ++----- .../timeseries/HideSeriesConfigEditor.tsx | 32 ---- .../timeseries/ScaleDistributionEditor.tsx | 63 -------- public/app/plugins/panel/timeseries/config.ts | 151 +---------------- .../app/plugins/panel/timeseries/module.tsx | 6 +- public/app/plugins/panel/timeseries/types.ts | 7 +- public/app/plugins/panel/xychart/module.tsx | 6 +- public/app/plugins/panel/xychart/types.ts | 4 +- 23 files changed, 335 insertions(+), 321 deletions(-) create mode 100644 packages/grafana-ui/src/options/builder/axis.tsx create mode 100644 packages/grafana-ui/src/options/builder/hideSeries.tsx create mode 100644 packages/grafana-ui/src/options/builder/index.ts create mode 100644 packages/grafana-ui/src/options/builder/legend.tsx create mode 100644 packages/grafana-ui/src/options/index.ts create mode 100644 packages/grafana-ui/src/options/models.gen.ts delete mode 100644 public/app/plugins/panel/timeseries/HideSeriesConfigEditor.tsx delete mode 100644 public/app/plugins/panel/timeseries/ScaleDistributionEditor.tsx diff --git a/packages/grafana-ui/src/components/BarChart/utils.ts b/packages/grafana-ui/src/components/BarChart/utils.ts index 5ae658b8d7a..7b41d50e7c9 100644 --- a/packages/grafana-ui/src/components/BarChart/utils.ts +++ b/packages/grafana-ui/src/components/BarChart/utils.ts @@ -11,10 +11,11 @@ import { VizOrientation, } from '@grafana/data'; import { BarChartFieldConfig, BarChartOptions, BarValueVisibility, defaultBarChartFieldConfig } from './types'; -import { AxisPlacement, ScaleDirection, ScaleDistribution, ScaleOrientation } from '../uPlot/config'; +import { AxisPlacement, ScaleDirection, ScaleOrientation } from '../uPlot/config'; import { BarsOptions, getConfig } from './bars'; import { FIXED_UNIT } from '../GraphNG/GraphNG'; import { Select } from 'uplot'; +import { ScaleDistribution } from '../uPlot/models.gen'; /** @alpha */ export function preparePlotConfigBuilder( diff --git a/packages/grafana-ui/src/components/uPlot/config.ts b/packages/grafana-ui/src/components/uPlot/config.ts index 24f61cf5bac..f4c61d09740 100644 --- a/packages/grafana-ui/src/components/uPlot/config.ts +++ b/packages/grafana-ui/src/components/uPlot/config.ts @@ -1,4 +1,5 @@ import { SelectableValue } from '@grafana/data'; +import { ScaleDistribution } from './models.gen'; /** * @alpha @@ -49,15 +50,6 @@ export enum BarAlignment { After = 1, } -/** - * @alpha - */ -export enum ScaleDistribution { - Linear = 'linear', - Logarithmic = 'log', - Ordinal = 'ordinal', -} - /** * @alpha */ diff --git a/packages/grafana-ui/src/components/uPlot/config/UPlotConfigBuilder.test.ts b/packages/grafana-ui/src/components/uPlot/config/UPlotConfigBuilder.test.ts index 72f7d89540e..213e3f59452 100644 --- a/packages/grafana-ui/src/components/uPlot/config/UPlotConfigBuilder.test.ts +++ b/packages/grafana-ui/src/components/uPlot/config/UPlotConfigBuilder.test.ts @@ -6,12 +6,12 @@ import { AxisPlacement, DrawStyle, PointVisibility, - ScaleDistribution, ScaleOrientation, ScaleDirection, GraphTresholdsStyleMode, } from '../config'; import { createTheme, ThresholdsMode } from '@grafana/data'; +import { ScaleDistribution } from '../models.gen'; describe('UPlotConfigBuilder', () => { const darkTheme = createTheme(); diff --git a/packages/grafana-ui/src/components/uPlot/config/UPlotScaleBuilder.ts b/packages/grafana-ui/src/components/uPlot/config/UPlotScaleBuilder.ts index b9123890cc5..8d8ec320f6b 100644 --- a/packages/grafana-ui/src/components/uPlot/config/UPlotScaleBuilder.ts +++ b/packages/grafana-ui/src/components/uPlot/config/UPlotScaleBuilder.ts @@ -1,6 +1,7 @@ import uPlot, { Scale, Range } from 'uplot'; import { PlotConfigBuilder } from '../types'; -import { ScaleDistribution, ScaleOrientation, ScaleDirection } from '../config'; +import { ScaleOrientation, ScaleDirection } from '../config'; +import { ScaleDistribution } from '../models.gen'; export interface ScaleProps { scaleKey: string; @@ -37,12 +38,12 @@ export class UPlotScaleBuilder extends PlotConfigBuilder { const distribution = !isTime ? { distr: - this.props.distribution === ScaleDistribution.Logarithmic + this.props.distribution === ScaleDistribution.Log ? 3 : this.props.distribution === ScaleDistribution.Ordinal ? 2 : 1, - log: this.props.distribution === ScaleDistribution.Logarithmic ? this.props.log || 2 : undefined, + log: this.props.distribution === ScaleDistribution.Log ? this.props.log || 2 : undefined, } : {}; diff --git a/packages/grafana-ui/src/components/uPlot/models.cue b/packages/grafana-ui/src/components/uPlot/models.cue index b03c3a6969c..a7394e56206 100644 --- a/packages/grafana-ui/src/components/uPlot/models.cue +++ b/packages/grafana-ui/src/components/uPlot/models.cue @@ -4,7 +4,7 @@ AxisPlacement: "auto" | "top" | "right" | "bottom" | "left" | "hidden" @cuetsy(t PointVisibility: "auto" | "never" | "always" @cuetsy(targetType="enum") DrawStyle: "line" | "bars" | "points" @cuetsy(targetType="enum") LineInterpolation: "linear" | "smooth" | "stepBefore" | "stepAfter" @cuetsy(targetType="enum") -ScaleDistribution: "linear" | "log" @cuetsy(targetType="enum") +ScaleDistribution: "linear" | "log" | "ordinal" @cuetsy(targetType="enum") GraphGradientMode: "none" | "opacity" | "hue" | "scheme" @cuetsy(targetType="enum") LineStyle: { diff --git a/packages/grafana-ui/src/components/uPlot/models.gen.ts b/packages/grafana-ui/src/components/uPlot/models.gen.ts index 681b403b0d2..c157e138303 100644 --- a/packages/grafana-ui/src/components/uPlot/models.gen.ts +++ b/packages/grafana-ui/src/components/uPlot/models.gen.ts @@ -30,6 +30,7 @@ export enum LineInterpolation { export enum ScaleDistribution { Linear = 'linear', Log = 'log', + Ordinal = 'ordinal', } export enum GraphGradientMode { Hue = 'hue', diff --git a/packages/grafana-ui/src/index.ts b/packages/grafana-ui/src/index.ts index bbaef99deb6..6a448ada238 100644 --- a/packages/grafana-ui/src/index.ts +++ b/packages/grafana-ui/src/index.ts @@ -7,6 +7,7 @@ export * from './components'; export * from './types'; export * from './utils'; export * from './themes'; +export * from './options'; export * from './slate-plugins'; // Exposes standard editors for registries of optionsUi config and panel options UI diff --git a/packages/grafana-ui/src/options/builder/axis.tsx b/packages/grafana-ui/src/options/builder/axis.tsx new file mode 100644 index 00000000000..b3599712571 --- /dev/null +++ b/packages/grafana-ui/src/options/builder/axis.tsx @@ -0,0 +1,153 @@ +import React from 'react'; +import { + FieldConfigEditorBuilder, + FieldOverrideEditorProps, + FieldType, + identityOverrideProcessor, + SelectableValue, +} from '@grafana/data'; +import { + AxisConfig, + AxisPlacement, + graphFieldOptions, + ScaleDistributionConfig, + Select, + HorizontalGroup, + RadioButtonGroup, +} from '../../index'; +import { ScaleDistribution } from '../../components/uPlot/models.gen'; + +/** + * @alpha + */ +export function addAxisConfig( + builder: FieldConfigEditorBuilder, + defaultConfig: AxisConfig, + hideScale?: boolean +) { + builder + .addRadio({ + path: 'axisPlacement', + name: 'Placement', + category: ['Axis'], + defaultValue: graphFieldOptions.axisPlacement[0].value, + settings: { + options: graphFieldOptions.axisPlacement, + }, + }) + .addTextInput({ + path: 'axisLabel', + name: 'Label', + category: ['Axis'], + defaultValue: '', + settings: { + placeholder: 'Optional text', + }, + showIf: (c) => c.axisPlacement !== AxisPlacement.Hidden, + // no matter what the field type is + shouldApply: () => true, + }) + .addNumberInput({ + path: 'axisWidth', + name: 'Width', + category: ['Axis'], + settings: { + placeholder: 'Auto', + }, + showIf: (c) => c.axisPlacement !== AxisPlacement.Hidden, + }) + .addNumberInput({ + path: 'axisSoftMin', + name: 'Soft min', + defaultValue: defaultConfig.axisSoftMin, + category: ['Axis'], + settings: { + placeholder: 'See: Standard options > Min', + }, + }) + .addNumberInput({ + path: 'axisSoftMax', + name: 'Soft max', + defaultValue: defaultConfig.axisSoftMax, + category: ['Axis'], + settings: { + placeholder: 'See: Standard options > Max', + }, + }); + if (!hideScale) { + builder.addCustomEditor({ + id: 'scaleDistribution', + path: 'scaleDistribution', + name: 'Scale', + category: ['Axis'], + editor: ScaleDistributionEditor, + override: ScaleDistributionEditor, + defaultValue: { type: ScaleDistribution.Linear }, + shouldApply: (f) => f.type === FieldType.number, + process: identityOverrideProcessor, + }); + } +} + +const DISTRIBUTION_OPTIONS: Array> = [ + { + label: 'Linear', + value: ScaleDistribution.Linear, + }, + { + label: 'Logarithmic', + value: ScaleDistribution.Log, + }, +]; + +const LOG_DISTRIBUTION_OPTIONS: Array> = [ + { + label: '2', + value: 2, + }, + { + label: '10', + value: 10, + }, +]; + +/** + * @alpha + */ +const ScaleDistributionEditor: React.FC> = ({ + value, + onChange, +}) => { + return ( + + { + console.log(v, value); + onChange({ + ...value, + type: v!, + log: v === ScaleDistribution.Linear ? undefined : 2, + }); + }} + /> + {value.type === ScaleDistribution.Log && ( + { - onChange({ - ...value, - log: v.value!, - }); - }} - /> - )} - - ); -}; diff --git a/public/app/plugins/panel/timeseries/config.ts b/public/app/plugins/panel/timeseries/config.ts index 423b1ede389..0f6af271d7f 100644 --- a/public/app/plugins/panel/timeseries/config.ts +++ b/public/app/plugins/panel/timeseries/config.ts @@ -4,35 +4,24 @@ import { FieldConfigProperty, FieldType, identityOverrideProcessor, - PanelOptionsEditorBuilder, SetFieldConfigOptionsArgs, - standardEditorsRegistry, - StatsPickerConfigSettings, stringOverrideProcessor, } from '@grafana/data'; import { - AxisConfig, - AxisPlacement, BarAlignment, DrawStyle, GraphFieldConfig, graphFieldOptions, GraphGradientMode, - HideableFieldConfig, - LegendDisplayMode, LineInterpolation, LineStyle, PointVisibility, - ScaleDistribution, - ScaleDistributionConfig, StackingConfig, StackingMode, + commonOptionsBuilder, } from '@grafana/ui'; -import { SeriesConfigEditor } from './HideSeriesConfigEditor'; -import { ScaleDistributionEditor } from './ScaleDistributionEditor'; import { LineStyleEditor } from './LineStyleEditor'; import { FillBellowToEditor } from './FillBelowToEditor'; -import { OptionsWithLegend } from './types'; import { SpanNullsEditor } from './SpanNullsEditor'; import { StackingEditor } from './StackingEditor'; @@ -188,8 +177,8 @@ export function getGraphFieldConfig(cfg: GraphFieldConfig): SetFieldConfigOption }); addStackingConfig(builder, cfg.stacking); - addAxisConfig(builder, cfg); - addHideFrom(builder); + commonOptionsBuilder.addAxisConfig(builder, cfg); + commonOptionsBuilder.addHideFrom(builder); builder.addSelect({ path: 'thresholdsStyle.mode', @@ -204,140 +193,6 @@ export function getGraphFieldConfig(cfg: GraphFieldConfig): SetFieldConfigOption }; } -export function addHideFrom(builder: FieldConfigEditorBuilder) { - builder.addCustomEditor({ - id: 'hideFrom', - name: 'Hide in area', - category: ['Series'], - path: 'hideFrom', - defaultValue: { - tooltip: false, - graph: false, - legend: false, - }, - editor: SeriesConfigEditor, - override: SeriesConfigEditor, - shouldApply: () => true, - hideFromDefaults: true, - hideFromOverrides: true, - process: (value) => value, - }); -} - -export function addAxisConfig( - builder: FieldConfigEditorBuilder, - defaultConfig: AxisConfig, - hideScale?: boolean -) { - builder - .addRadio({ - path: 'axisPlacement', - name: 'Placement', - category: ['Axis'], - defaultValue: graphFieldOptions.axisPlacement[0].value, - settings: { - options: graphFieldOptions.axisPlacement, - }, - }) - .addTextInput({ - path: 'axisLabel', - name: 'Label', - category: ['Axis'], - defaultValue: '', - settings: { - placeholder: 'Optional text', - }, - showIf: (c) => c.axisPlacement !== AxisPlacement.Hidden, - // no matter what the field type is - shouldApply: () => true, - }) - .addNumberInput({ - path: 'axisWidth', - name: 'Width', - category: ['Axis'], - settings: { - placeholder: 'Auto', - }, - showIf: (c) => c.axisPlacement !== AxisPlacement.Hidden, - }) - .addNumberInput({ - path: 'axisSoftMin', - name: 'Soft min', - defaultValue: defaultConfig.axisSoftMin, - category: ['Axis'], - settings: { - placeholder: 'See: Standard options > Min', - }, - }) - .addNumberInput({ - path: 'axisSoftMax', - name: 'Soft max', - defaultValue: defaultConfig.axisSoftMax, - category: ['Axis'], - settings: { - placeholder: 'See: Standard options > Max', - }, - }); - if (!hideScale) { - builder.addCustomEditor({ - id: 'scaleDistribution', - path: 'scaleDistribution', - name: 'Scale', - category: ['Axis'], - editor: ScaleDistributionEditor, - override: ScaleDistributionEditor, - defaultValue: { type: ScaleDistribution.Linear }, - shouldApply: (f) => f.type === FieldType.number, - process: identityOverrideProcessor, - }); - } -} - -export function addLegendOptions(builder: PanelOptionsEditorBuilder) { - builder - .addRadio({ - path: 'legend.displayMode', - name: 'Legend mode', - category: ['Legend'], - description: '', - defaultValue: LegendDisplayMode.List, - settings: { - options: [ - { value: LegendDisplayMode.List, label: 'List' }, - { value: LegendDisplayMode.Table, label: 'Table' }, - { value: LegendDisplayMode.Hidden, label: 'Hidden' }, - ], - }, - }) - .addRadio({ - path: 'legend.placement', - name: 'Legend placement', - category: ['Legend'], - description: '', - defaultValue: 'bottom', - settings: { - options: [ - { value: 'bottom', label: 'Bottom' }, - { value: 'right', label: 'Right' }, - ], - }, - showIf: (c) => c.legend.displayMode !== LegendDisplayMode.Hidden, - }) - .addCustomEditor({ - id: 'legend.calcs', - path: 'legend.calcs', - name: 'Legend values', - category: ['Legend'], - description: 'Select values or calculations to show in legend', - editor: standardEditorsRegistry.get('stats-picker').editor as any, - defaultValue: [], - settings: { - allowMultiple: true, - }, - showIf: (currentConfig) => currentConfig.legend.displayMode !== LegendDisplayMode.Hidden, - }); -} - export function addStackingConfig( builder: FieldConfigEditorBuilder<{ stacking: StackingConfig }>, defaultConfig?: StackingConfig diff --git a/public/app/plugins/panel/timeseries/module.tsx b/public/app/plugins/panel/timeseries/module.tsx index 02b15d59b78..bf8a753459b 100644 --- a/public/app/plugins/panel/timeseries/module.tsx +++ b/public/app/plugins/panel/timeseries/module.tsx @@ -1,9 +1,9 @@ import { PanelPlugin } from '@grafana/data'; -import { GraphFieldConfig } from '@grafana/ui'; +import { GraphFieldConfig, commonOptionsBuilder } from '@grafana/ui'; import { TimeSeriesPanel } from './TimeSeriesPanel'; import { graphPanelChangedHandler } from './migrations'; import { Options } from './types'; -import { addLegendOptions, defaultGraphConfig, getGraphFieldConfig } from './config'; +import { defaultGraphConfig, getGraphFieldConfig } from './config'; export const plugin = new PanelPlugin(TimeSeriesPanel) .setPanelChangeHandler(graphPanelChangedHandler) @@ -24,6 +24,6 @@ export const plugin = new PanelPlugin(TimeSeriesPanel }, }); - addLegendOptions(builder); + commonOptionsBuilder.addLegendOptions(builder); }) .setDataSupport({ annotations: true, alertStates: true }); diff --git a/public/app/plugins/panel/timeseries/types.ts b/public/app/plugins/panel/timeseries/types.ts index 05eeaabe597..4e852f0ace5 100644 --- a/public/app/plugins/panel/timeseries/types.ts +++ b/public/app/plugins/panel/timeseries/types.ts @@ -1,9 +1,4 @@ -import { VizLegendOptions, VizTooltipOptions } from '@grafana/ui'; - -export interface OptionsWithLegend { - legend: VizLegendOptions; -} - +import { VizTooltipOptions, OptionsWithLegend } from '@grafana/ui'; export interface Options extends OptionsWithLegend { tooltipOptions: VizTooltipOptions; } diff --git a/public/app/plugins/panel/xychart/module.tsx b/public/app/plugins/panel/xychart/module.tsx index 844afd22c5d..714c0cbf42c 100644 --- a/public/app/plugins/panel/xychart/module.tsx +++ b/public/app/plugins/panel/xychart/module.tsx @@ -1,9 +1,9 @@ import { PanelPlugin } from '@grafana/data'; -import { DrawStyle, GraphFieldConfig } from '@grafana/ui'; +import { DrawStyle, GraphFieldConfig, commonOptionsBuilder } from '@grafana/ui'; import { XYChartPanel } from './XYChartPanel'; import { Options } from './types'; import { XYDimsEditor } from './XYDimsEditor'; -import { getGraphFieldConfig, defaultGraphConfig, addLegendOptions } from '../timeseries/config'; +import { getGraphFieldConfig, defaultGraphConfig } from '../timeseries/config'; export const plugin = new PanelPlugin(XYChartPanel) .useFieldConfig( @@ -34,5 +34,5 @@ export const plugin = new PanelPlugin(XYChartPanel) }, }); - addLegendOptions(builder); + commonOptionsBuilder.addLegendOptions(builder); }); diff --git a/public/app/plugins/panel/xychart/types.ts b/public/app/plugins/panel/xychart/types.ts index f8e0bb98cbe..a02f5d4e2f1 100644 --- a/public/app/plugins/panel/xychart/types.ts +++ b/public/app/plugins/panel/xychart/types.ts @@ -1,6 +1,4 @@ -import { VizTooltipOptions } from '@grafana/ui'; -import { OptionsWithLegend } from '../timeseries/types'; - +import { VizTooltipOptions, OptionsWithLegend } from '@grafana/ui'; export interface XYDimensionConfig { frame: number; x?: string; // name | first