From 8c1a79f24b0ea34321725538aaa71f67c4bd6eb8 Mon Sep 17 00:00:00 2001 From: Ryan McKinley Date: Fri, 22 Jan 2021 13:25:39 -0800 Subject: [PATCH] XY Chart: share legend config with timeseries (#30559) --- .../src/components/GraphNG/GraphNG.tsx | 4 ++ public/app/plugins/panel/timeseries/config.ts | 47 ++++++++++++ .../app/plugins/panel/timeseries/module.tsx | 72 +++++-------------- public/app/plugins/panel/timeseries/types.ts | 10 +-- .../plugins/panel/xychart/XYDimsEditor.tsx | 15 +--- public/app/plugins/panel/xychart/dims.ts | 13 ++-- public/app/plugins/panel/xychart/module.tsx | 32 ++------- public/app/plugins/panel/xychart/types.ts | 7 +- 8 files changed, 88 insertions(+), 112 deletions(-) diff --git a/packages/grafana-ui/src/components/GraphNG/GraphNG.tsx b/packages/grafana-ui/src/components/GraphNG/GraphNG.tsx index a2abda34649..923ee5713bc 100755 --- a/packages/grafana-ui/src/components/GraphNG/GraphNG.tsx +++ b/packages/grafana-ui/src/components/GraphNG/GraphNG.tsx @@ -259,6 +259,10 @@ export const GraphNG: React.FC = ({ label: seriesConfig.fieldName, yAxis: axisPlacement === AxisPlacement.Left ? 1 : 2, getDisplayValues: () => { + if (!legend.calcs?.length) { + return []; + } + const fmt = field.display ?? defaultFormatter; const fieldCalcs = reduceField({ field, diff --git a/public/app/plugins/panel/timeseries/config.ts b/public/app/plugins/panel/timeseries/config.ts index 9dde12d7c04..f07bcf88d08 100644 --- a/public/app/plugins/panel/timeseries/config.ts +++ b/public/app/plugins/panel/timeseries/config.ts @@ -3,7 +3,10 @@ import { FieldConfigProperty, FieldType, identityOverrideProcessor, + PanelOptionsEditorBuilder, SetFieldConfigOptionsArgs, + standardEditorsRegistry, + StatsPickerConfigSettings, stringOverrideProcessor, } from '@grafana/data'; import { @@ -17,11 +20,13 @@ import { ScaleDistribution, ScaleDistributionConfig, GraphGradientMode, + LegendDisplayMode, } from '@grafana/ui'; import { SeriesConfigEditor } from './HideSeriesConfigEditor'; import { ScaleDistributionEditor } from './ScaleDistributionEditor'; import { LineStyleEditor } from './LineStyleEditor'; import { FillBellowToEditor } from './FillBelowToEditor'; +import { OptionsWithLegend } from './types'; export const defaultGraphConfig: GraphFieldConfig = { drawStyle: DrawStyle.Line, @@ -224,3 +229,45 @@ export function getGraphFieldConfig(cfg: GraphFieldConfig): SetFieldConfigOption }, }; } + +export function addLegendOptions(builder: PanelOptionsEditorBuilder) { + builder + .addRadio({ + path: 'legend.displayMode', + name: 'Legend mode', + 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', + 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 calculations', + description: 'Choose a reducer functions / calculations to include in legend', + editor: standardEditorsRegistry.get('stats-picker').editor as any, + defaultValue: [], + settings: { + allowMultiple: true, + }, + showIf: (currentConfig) => currentConfig.legend.displayMode !== LegendDisplayMode.Hidden, + }); +} diff --git a/public/app/plugins/panel/timeseries/module.tsx b/public/app/plugins/panel/timeseries/module.tsx index 2b449d35378..3830ef30d5d 100644 --- a/public/app/plugins/panel/timeseries/module.tsx +++ b/public/app/plugins/panel/timeseries/module.tsx @@ -1,64 +1,26 @@ -import { PanelPlugin, standardEditorsRegistry, StatsPickerConfigSettings } from '@grafana/data'; -import { GraphFieldConfig, LegendDisplayMode } from '@grafana/ui'; +import { PanelPlugin } from '@grafana/data'; +import { GraphFieldConfig } from '@grafana/ui'; import { TimeSeriesPanel } from './TimeSeriesPanel'; import { graphPanelChangedHandler } from './migrations'; import { Options } from './types'; -import { defaultGraphConfig, getGraphFieldConfig } from './config'; +import { addLegendOptions, defaultGraphConfig, getGraphFieldConfig } from './config'; export const plugin = new PanelPlugin(TimeSeriesPanel) .setPanelChangeHandler(graphPanelChangedHandler) .useFieldConfig(getGraphFieldConfig(defaultGraphConfig)) .setPanelOptions((builder) => { - builder - .addRadio({ - path: 'tooltipOptions.mode', - name: 'Tooltip mode', - description: '', - defaultValue: 'single', - settings: { - options: [ - { value: 'single', label: 'Single' }, - { value: 'multi', label: 'All' }, - { value: 'none', label: 'Hidden' }, - ], - }, - }) - .addRadio({ - path: 'legend.displayMode', - name: 'Legend mode', - 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', - 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 calculations', - description: 'Choose a reducer functions / calculations to include in legend', - editor: standardEditorsRegistry.get('stats-picker').editor as any, - defaultValue: [], - settings: { - allowMultiple: true, - }, - showIf: (currentConfig) => currentConfig.legend.displayMode !== LegendDisplayMode.Hidden, - }); + builder.addRadio({ + path: 'tooltipOptions.mode', + name: 'Tooltip mode', + description: '', + defaultValue: 'single', + settings: { + options: [ + { value: 'single', label: 'Single' }, + { value: 'multi', label: 'All' }, + { value: 'none', label: 'Hidden' }, + ], + }, + }); + addLegendOptions(builder); }); diff --git a/public/app/plugins/panel/timeseries/types.ts b/public/app/plugins/panel/timeseries/types.ts index 7051250112e..f75e2afc64a 100644 --- a/public/app/plugins/panel/timeseries/types.ts +++ b/public/app/plugins/panel/timeseries/types.ts @@ -1,12 +1,14 @@ import { VizLegendOptions, GraphTooltipOptions } from '@grafana/ui'; export interface GraphOptions { - // Redraw as time passes - realTimeUpdates?: boolean; + // nothing for now } -export interface Options { - graph: GraphOptions; +export interface OptionsWithLegend { legend: VizLegendOptions; +} + +export interface Options extends OptionsWithLegend { + graph: GraphOptions; tooltipOptions: GraphTooltipOptions; } diff --git a/public/app/plugins/panel/xychart/XYDimsEditor.tsx b/public/app/plugins/panel/xychart/XYDimsEditor.tsx index 664fb61bc0d..51c38f9a38a 100644 --- a/public/app/plugins/panel/xychart/XYDimsEditor.tsx +++ b/public/app/plugins/panel/xychart/XYDimsEditor.tsx @@ -1,6 +1,6 @@ -import React, { FC, useCallback, useMemo } from 'react'; +import React, { FC, useMemo } from 'react'; import { css } from 'emotion'; -import { IconButton, Label, Select, stylesFactory, Switch, useTheme } from '@grafana/ui'; +import { IconButton, Label, Select, stylesFactory, useTheme } from '@grafana/ui'; import { SelectableValue, getFrameDisplayName, @@ -84,13 +84,6 @@ export const XYDimsEditor: FC { - onChange({ - ...value, - sort: !value?.sort, - }); - }, [value, onChange]); - const theme = useTheme(); const styles = getStyles(theme); @@ -118,10 +111,6 @@ export const XYDimsEditor: FC -
- -
  Sort field
-

diff --git a/public/app/plugins/panel/xychart/dims.ts b/public/app/plugins/panel/xychart/dims.ts index 12d30d0f335..fccbed8ffea 100644 --- a/public/app/plugins/panel/xychart/dims.ts +++ b/public/app/plugins/panel/xychart/dims.ts @@ -1,4 +1,4 @@ -import { DataFrame, Field, FieldMatcher, FieldType, getFieldDisplayName, sortDataFrame } from '@grafana/data'; +import { DataFrame, Field, FieldMatcher, FieldType, getFieldDisplayName } from '@grafana/data'; import { XYFieldMatchers } from '@grafana/ui/src/components/GraphNG/GraphNG'; import { XYDimensionConfig } from './types'; @@ -49,11 +49,6 @@ export function getXYDimensions(cfg: XYDimensionConfig, data?: DataFrame[]): XYD } } - // Optionally sort - if (cfg.sort) { - frame = sortDataFrame(frame, xIndex); - } - let hasTime = false; const x = frame.fields[xIndex]; const fields: Field[] = [x]; @@ -92,12 +87,14 @@ function getSimpleFieldMatcher(f: Field): FieldMatcher { if (!f) { return () => false; } - return (field) => f === field; + // the field may change if sorted + return (field) => f === field || !!(f.state && f.state === field.state); } function getSimpleFieldNotMatcher(f: Field): FieldMatcher { if (!f) { return () => false; } - return (field) => f !== field; + const m = getSimpleFieldMatcher(f); + return (field) => !m(field, undefined as any, undefined as any); } diff --git a/public/app/plugins/panel/xychart/module.tsx b/public/app/plugins/panel/xychart/module.tsx index 15b97dec6cb..844afd22c5d 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, LegendDisplayMode } from '@grafana/ui'; +import { DrawStyle, GraphFieldConfig } from '@grafana/ui'; import { XYChartPanel } from './XYChartPanel'; import { Options } from './types'; import { XYDimsEditor } from './XYDimsEditor'; -import { getGraphFieldConfig, defaultGraphConfig } from '../timeseries/config'; +import { getGraphFieldConfig, defaultGraphConfig, addLegendOptions } from '../timeseries/config'; export const plugin = new PanelPlugin(XYChartPanel) .useFieldConfig( @@ -32,31 +32,7 @@ export const plugin = new PanelPlugin(XYChartPanel) { value: 'none', label: 'Hidden' }, ], }, - }) - .addRadio({ - path: 'legend.displayMode', - name: 'Legend mode', - 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', - description: '', - defaultValue: 'bottom', - settings: { - options: [ - { value: 'bottom', label: 'Bottom' }, - { value: 'right', label: 'Right' }, - ], - }, - showIf: (c) => c.legend.displayMode !== LegendDisplayMode.Hidden, }); + + addLegendOptions(builder); }); diff --git a/public/app/plugins/panel/xychart/types.ts b/public/app/plugins/panel/xychart/types.ts index 21b39893944..f31f100e1db 100644 --- a/public/app/plugins/panel/xychart/types.ts +++ b/public/app/plugins/panel/xychart/types.ts @@ -1,14 +1,13 @@ -import { VizLegendOptions, GraphTooltipOptions } from '@grafana/ui'; +import { GraphTooltipOptions } from '@grafana/ui'; +import { OptionsWithLegend } from '../timeseries/types'; export interface XYDimensionConfig { frame: number; - sort?: boolean; x?: string; // name | first exclude?: string[]; // all other numbers except } -export interface Options { +export interface Options extends OptionsWithLegend { dims: XYDimensionConfig; - legend: VizLegendOptions; tooltipOptions: GraphTooltipOptions; }