From 2ea4a36bf704dc19dca9188d70987ed761442e23 Mon Sep 17 00:00:00 2001 From: Dominik Prokop Date: Mon, 9 Nov 2020 13:11:09 +0100 Subject: [PATCH] Field color: handling color changes when switching panel types (#28875) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * FieldColor: Per panel settings to filter out supported modes * Updates * Updated solution * Update panel plugin API for standard options support * Update FieldColorConfigSettings interface * Change color mode correctly when changing plugin type * Render only applicable color modes in field color config editor * Apply field config API changes * TS fixes Co-authored-by: Torkel Ödegaard --- packages/grafana-data/src/field/fieldColor.ts | 1 + .../grafana-data/src/field/fieldOverrides.ts | 1 - .../src/field/overrides/processors.ts | 15 ++- .../src/panel/PanelPlugin.test.tsx | 26 ++-- .../grafana-data/src/panel/PanelPlugin.ts | 79 +++++++----- .../src/utils/OptionsUIBuilders.ts | 10 +- .../src/components/BarGauge/BarGauge.tsx | 2 +- .../src/components/OptionsUI/color.tsx | 6 - .../src/components/OptionsUI/fieldColor.tsx | 9 +- .../grafana-ui/src/utils/standardEditors.tsx | 8 +- .../dashboard/state/PanelModel.test.ts | 99 ++++++++++++++- .../features/dashboard/state/PanelModel.ts | 34 ++++- public/app/plugins/panel/graph/module.ts | 16 ++- public/app/plugins/panel/graph2/module.tsx | 118 +++++++++--------- public/app/plugins/panel/graph3/module.tsx | 23 ++-- public/app/plugins/panel/stat/module.tsx | 4 +- 16 files changed, 296 insertions(+), 155 deletions(-) diff --git a/packages/grafana-data/src/field/fieldColor.ts b/packages/grafana-data/src/field/fieldColor.ts index 7e893af82eb..ba7db8eae4e 100644 --- a/packages/grafana-data/src/field/fieldColor.ts +++ b/packages/grafana-data/src/field/fieldColor.ts @@ -24,6 +24,7 @@ export const fieldColorModeRegistry = new Registry(() => { { id: FieldColorModeId.Thresholds, name: 'From thresholds', + isByValue: true, description: 'Derive colors from thresholds', getCalculator: (_field, theme) => { return (_value, _percent, threshold) => { diff --git a/packages/grafana-data/src/field/fieldOverrides.ts b/packages/grafana-data/src/field/fieldOverrides.ts index f1bd357e47f..fba14e335b2 100644 --- a/packages/grafana-data/src/field/fieldOverrides.ts +++ b/packages/grafana-data/src/field/fieldOverrides.ts @@ -306,7 +306,6 @@ const processFieldConfigValue = ( const currentConfig = get(destination, fieldConfigProperty.path); if (currentConfig === null || currentConfig === undefined) { const item = context.fieldConfigRegistry.getIfExists(fieldConfigProperty.id); - // console.log(item); if (!item) { return; } diff --git a/packages/grafana-data/src/field/overrides/processors.ts b/packages/grafana-data/src/field/overrides/processors.ts index 8152659c9ff..feff3993a09 100644 --- a/packages/grafana-data/src/field/overrides/processors.ts +++ b/packages/grafana-data/src/field/overrides/processors.ts @@ -120,8 +120,15 @@ export const booleanOverrideProcessor = ( return value; // !!!! likely not !!!! }; -export interface ColorFieldConfigSettings { - allowUndefined?: boolean; - textWhenUndefined?: string; // Pick Color - disableNamedColors?: boolean; +export interface FieldColorConfigSettings { + /** + * When switching to a visualization that does not support by value coloring then Grafana will + * switch to a by series palette based color mode + */ + byValueSupport?: boolean; + /** + * When switching to a visualization that has this set to true then Grafana will change color mode + * to from thresholds if it was set to a by series palette + */ + preferThresholdsMode?: boolean; } diff --git a/packages/grafana-data/src/panel/PanelPlugin.test.tsx b/packages/grafana-data/src/panel/PanelPlugin.test.tsx index 10e76878236..e0a96b91785 100644 --- a/packages/grafana-data/src/panel/PanelPlugin.test.tsx +++ b/packages/grafana-data/src/panel/PanelPlugin.test.tsx @@ -9,11 +9,11 @@ describe('PanelPlugin', () => { standardFieldConfigEditorRegistry.setInit(() => { return [ { - id: 'min', + id: FieldConfigProperty.Min, path: 'min', }, { - id: 'max', + id: FieldConfigProperty.Max, path: 'max', }, ] as any; @@ -210,15 +210,15 @@ describe('PanelPlugin', () => { expect(panel.fieldConfigRegistry.list()).toHaveLength(2); }); - test('selected standard config', () => { + test('disabling standard config properties', () => { const panel = new PanelPlugin(() => { return
Panel
; }); panel.useFieldConfig({ - standardOptions: [FieldConfigProperty.Min, FieldConfigProperty.Max], + disableStandardOptions: [FieldConfigProperty.Min], }); - expect(panel.fieldConfigRegistry.list()).toHaveLength(2); + expect(panel.fieldConfigRegistry.list()).toHaveLength(1); }); describe('default values', () => { @@ -228,10 +228,9 @@ describe('PanelPlugin', () => { }); panel.useFieldConfig({ - standardOptions: [FieldConfigProperty.Max, FieldConfigProperty.Min], - standardOptionsDefaults: { - [FieldConfigProperty.Max]: 20, - [FieldConfigProperty.Min]: 10, + standardOptions: { + [FieldConfigProperty.Max]: { defaultValue: 20 }, + [FieldConfigProperty.Min]: { defaultValue: 10 }, }, }); @@ -247,17 +246,16 @@ describe('PanelPlugin', () => { }); }); - it('should ignore defaults that are not specified as available properties', () => { + it('should disable properties independently from the default values settings', () => { const panel = new PanelPlugin(() => { return
Panel
; }); panel.useFieldConfig({ - standardOptions: [FieldConfigProperty.Max], - standardOptionsDefaults: { - [FieldConfigProperty.Max]: 20, - [FieldConfigProperty.Min]: 10, + standardOptions: { + [FieldConfigProperty.Max]: { defaultValue: 20 }, }, + disableStandardOptions: [FieldConfigProperty.Min], }); expect(panel.fieldConfigRegistry.list()).toHaveLength(1); diff --git a/packages/grafana-data/src/panel/PanelPlugin.ts b/packages/grafana-data/src/panel/PanelPlugin.ts index fd07b8f52c7..e86a9fec18f 100644 --- a/packages/grafana-data/src/panel/PanelPlugin.ts +++ b/packages/grafana-data/src/panel/PanelPlugin.ts @@ -15,33 +15,38 @@ import set from 'lodash/set'; import { deprecationWarning } from '../utils'; import { FieldConfigOptionsRegistry, standardFieldConfigEditorRegistry } from '../field'; +type StandardOptionConfig = { + defaultValue?: any; + settings?: any; +}; + export interface SetFieldConfigOptionsArgs { /** - * Array of standard field config properties + * Configuration object of the standard field config properites * * @example * ```typescript * { - * standardOptions: [FieldConfigProperty.Min, FieldConfigProperty.Max, FieldConfigProperty.Unit] - * } - * ``` - */ - standardOptions?: FieldConfigProperty[]; - - /** - * Object specifying standard option properties default values - * - * @example - * ```typescript - * { - * standardOptionsDefaults: { - * [FieldConfigProperty.Min]: 20, - * [FieldConfigProperty.Max]: 100 + * standardOptions: { + * [FieldConfigProperty.Decimals]: { + * defaultValue: 3 + * } * } * } * ``` */ - standardOptionsDefaults?: Partial>; + standardOptions?: Partial>; + + /** + * Array of standard field config properties that should not be available in the panel + * @example + * ```typescript + * { + * disableStandardOptions: [FieldConfigProperty.Min, FieldConfigProperty.Max, FieldConfigProperty.Unit] + * } + * ``` + */ + disableStandardOptions?: FieldConfigProperty[]; /** * Function that allows custom field config properties definition. @@ -305,13 +310,13 @@ export class PanelPlugin) { + useFieldConfig(config: SetFieldConfigOptionsArgs = {}) { // builder is applied lazily when custom field configs are accessed this._initConfigRegistry = () => { const registry = new FieldConfigOptionsRegistry(); // Add custom options - if (config && config.useCustomConfig) { + if (config.useCustomConfig) { const builder = new FieldConfigEditorBuilder(); config.useCustomConfig(builder); @@ -326,20 +331,32 @@ export class PanelPlugin -1; + if (isDisabled) { + continue; + } } - } else { - for (const fieldConfigProp of standardFieldConfigEditorRegistry.list()) { - registry.register(fieldConfigProp); + if (config.standardOptions) { + const customDefault: any = config.standardOptions[fieldConfigProp.id as FieldConfigProperty]?.defaultValue; + const customSettings: any = config.standardOptions[fieldConfigProp.id as FieldConfigProperty]?.settings; + if (customDefault) { + fieldConfigProp = { + ...fieldConfigProp, + defaultValue: customDefault, + }; + } + + if (customSettings) { + fieldConfigProp = { + ...fieldConfigProp, + settings: fieldConfigProp.settings ? { ...fieldConfigProp.settings, ...customSettings } : customSettings, + }; + } } + + registry.register(fieldConfigProp); } return registry; diff --git a/packages/grafana-data/src/utils/OptionsUIBuilders.ts b/packages/grafana-data/src/utils/OptionsUIBuilders.ts index 8fa49d92b3c..d708dd0e29c 100644 --- a/packages/grafana-data/src/utils/OptionsUIBuilders.ts +++ b/packages/grafana-data/src/utils/OptionsUIBuilders.ts @@ -13,12 +13,10 @@ import { StringFieldConfigSettings, NumberFieldConfigSettings, SliderFieldConfigSettings, - ColorFieldConfigSettings, identityOverrideProcessor, UnitFieldConfigSettings, unitOverrideProcessor, } from '../field'; -import { FieldColor } from '../types'; /** * Fluent API for declarative creation of field config option editors @@ -104,9 +102,7 @@ export class FieldConfigEditorBuilder extends OptionsUIRegistryBuilder }); } - addColorPicker( - config: FieldConfigEditorConfig - ) { + addColorPicker(config: FieldConfigEditorConfig) { return this.addCustomEditor({ ...config, id: config.path, @@ -203,9 +199,7 @@ export class PanelOptionsEditorBuilder extends OptionsUIRegistryBuilde }); } - addColorPicker( - config: PanelOptionsEditorConfig - ): this { + addColorPicker(config: PanelOptionsEditorConfig): this { return this.addCustomEditor({ ...config, id: config.path, diff --git a/packages/grafana-ui/src/components/BarGauge/BarGauge.tsx b/packages/grafana-ui/src/components/BarGauge/BarGauge.tsx index 1616cab9522..f051c6e862d 100644 --- a/packages/grafana-ui/src/components/BarGauge/BarGauge.tsx +++ b/packages/grafana-ui/src/components/BarGauge/BarGauge.tsx @@ -545,7 +545,7 @@ export function getBarGradient(props: Props, maxSize: number): string { return gradient + ')'; } - if (mode.colors) { + if (mode.isContinuous && mode.colors) { const scheme = mode.colors.map(item => getColorForTheme(item, theme)); for (let i = 0; i < scheme.length; i++) { const color = scheme[i]; diff --git a/packages/grafana-ui/src/components/OptionsUI/color.tsx b/packages/grafana-ui/src/components/OptionsUI/color.tsx index 1b638a94193..eecd18dc4c6 100644 --- a/packages/grafana-ui/src/components/OptionsUI/color.tsx +++ b/packages/grafana-ui/src/components/OptionsUI/color.tsx @@ -28,12 +28,6 @@ export const ColorValueEditor: React.FC = ({ value, onChange }) => { color={value ? getColorForTheme(value, theme) : theme.colors.formInputBorder} /> - {/*
- {value ?? settings?.textWhenUndefined ?? 'Pick Color'} -
- {value && settings?.allowUndefined && ( - onChange(undefined)} /> - )} */} ); }} diff --git a/packages/grafana-ui/src/components/OptionsUI/fieldColor.tsx b/packages/grafana-ui/src/components/OptionsUI/fieldColor.tsx index 7d64f8ef0df..5a59163a07d 100644 --- a/packages/grafana-ui/src/components/OptionsUI/fieldColor.tsx +++ b/packages/grafana-ui/src/components/OptionsUI/fieldColor.tsx @@ -8,13 +8,14 @@ import { FieldColorMode, GrafanaTheme, getColorForTheme, + FieldColorConfigSettings, } from '@grafana/data'; import { Select } from '../Select/Select'; import { ColorValueEditor } from './color'; import { useStyles, useTheme } from '../../themes/ThemeContext'; import { css } from 'emotion'; -export const FieldColorEditor: React.FC> = ({ +export const FieldColorEditor: React.FC> = ({ value, onChange, item, @@ -22,7 +23,11 @@ export const FieldColorEditor: React.FC { + const availableOptions = item.settings?.byValueSupport + ? fieldColorModeRegistry.list() + : fieldColorModeRegistry.list().filter(m => !m.isByValue); + + const options = availableOptions.map(mode => { let suffix = mode.isByValue ? ' (by value)' : ''; return { diff --git a/packages/grafana-ui/src/utils/standardEditors.tsx b/packages/grafana-ui/src/utils/standardEditors.tsx index 8c45c5d0a41..85a2ee12a8a 100644 --- a/packages/grafana-ui/src/utils/standardEditors.tsx +++ b/packages/grafana-ui/src/utils/standardEditors.tsx @@ -20,6 +20,7 @@ import { identityOverrideProcessor, TimeZone, FieldColor, + FieldColorConfigSettings, } from '@grafana/data'; import { Switch } from '../components/Switch/Switch'; @@ -204,15 +205,18 @@ export const getStandardFieldConfigs = () => { getItemsCount: value => (value ? value.length : 0), }; - const color: FieldConfigPropertyItem = { + const color: FieldConfigPropertyItem = { id: 'color', path: 'color', name: 'Color scheme', - description: 'Select palette, gradient or single color', editor: standardEditorsRegistry.get('fieldColor').editor as any, override: standardEditorsRegistry.get('fieldColor').editor as any, process: identityOverrideProcessor, shouldApply: () => true, + settings: { + byValueSupport: true, + preferThresholdsMode: true, + }, category, }; diff --git a/public/app/features/dashboard/state/PanelModel.test.ts b/public/app/features/dashboard/state/PanelModel.test.ts index 5c7e04142ff..a3f10f210ae 100644 --- a/public/app/features/dashboard/state/PanelModel.test.ts +++ b/public/app/features/dashboard/state/PanelModel.test.ts @@ -8,6 +8,8 @@ import { standardFieldConfigEditorRegistry, PanelData, DataSourceInstanceSettings, + FieldColorModeId, + FieldColorConfigSettings, } from '@grafana/data'; import { ComponentClass } from 'react'; import { PanelQueryRunner } from './PanelQueryRunner'; @@ -55,7 +57,20 @@ export const mockStandardProperties = () => { shouldApply: () => true, }; - return [unit, decimals, boolean]; + const fieldColor = { + id: 'color', + path: 'color', + name: 'color', + description: '', + // @ts-ignore + editor: () => null, + // @ts-ignore + override: () => null, + process: identityOverrideProcessor, + shouldApply: () => true, + }; + + return [unit, decimals, boolean, fieldColor]; }; standardFieldConfigEditorRegistry.setInit(() => mockStandardProperties()); @@ -147,10 +162,13 @@ describe('PanelModel', () => { }); panelPlugin.useFieldConfig({ - standardOptions: [FieldConfigProperty.Unit, FieldConfigProperty.Decimals], - standardOptionsDefaults: { - [FieldConfigProperty.Unit]: 'flop', - [FieldConfigProperty.Decimals]: 2, + standardOptions: { + [FieldConfigProperty.Unit]: { + defaultValue: 'flop', + }, + [FieldConfigProperty.Decimals]: { + defaultValue: 2, + }, }, }); model.pluginLoaded(panelPlugin); @@ -239,6 +257,17 @@ describe('PanelModel', () => { describe('when changing panel type', () => { beforeEach(() => { const newPlugin = getPanelPlugin({ id: 'graph' }); + + newPlugin.useFieldConfig({ + standardOptions: { + [FieldConfigProperty.Color]: { + settings: { + byThresholdsSupport: true, + }, + }, + }, + }); + newPlugin.setPanelOptions(builder => { builder.addBooleanSwitch({ name: 'Show thresholds labels', @@ -285,6 +314,66 @@ describe('PanelModel', () => { }); }); + describe('when changing panel type to one that does not support by value color mode', () => { + beforeEach(() => { + model.fieldConfig.defaults.color = { mode: FieldColorModeId.Thresholds }; + + const newPlugin = getPanelPlugin({ id: 'graph' }); + newPlugin.useFieldConfig({ + standardOptions: { + [FieldConfigProperty.Color]: { + settings: { + byValueSupport: false, + }, + }, + }, + }); + + model.editSourceId = 1001; + model.changePlugin(newPlugin); + model.alert = { id: 2 }; + }); + + it('should change color mode', () => { + expect(model.fieldConfig.defaults.color.mode).toBe(FieldColorModeId.PaletteClassic); + }); + }); + + describe('when changing panel type from one not supporting by value color mode to one that supports it', () => { + const prepareModel = (colorOptions?: FieldColorConfigSettings) => { + const newModel = new PanelModel(modelJson); + newModel.fieldConfig.defaults.color = { mode: FieldColorModeId.PaletteClassic }; + + const newPlugin = getPanelPlugin({ id: 'graph' }); + newPlugin.useFieldConfig({ + standardOptions: { + [FieldConfigProperty.Color]: { + settings: { + byValueSupport: true, + ...colorOptions, + }, + }, + }, + }); + + newModel.editSourceId = 1001; + newModel.changePlugin(newPlugin); + newModel.alert = { id: 2 }; + return newModel; + }; + + it('should keep supported mode', () => { + const testModel = prepareModel(); + + expect(testModel.fieldConfig.defaults.color!.mode).toBe(FieldColorModeId.PaletteClassic); + }); + + it('should change to thresholds mode when it prefers to', () => { + const testModel = prepareModel({ preferThresholdsMode: true }); + expect(testModel.fieldConfig.defaults.color!.mode).toBe(FieldColorModeId.Thresholds); + }); + }); + describe('when changing to react panel from angular panel', () => { let panelQueryRunner: any; diff --git a/public/app/features/dashboard/state/PanelModel.ts b/public/app/features/dashboard/state/PanelModel.ts index b4e695daf21..c13e18c1dc3 100644 --- a/public/app/features/dashboard/state/PanelModel.ts +++ b/public/app/features/dashboard/state/PanelModel.ts @@ -12,6 +12,10 @@ import { DataQueryResponseData, DataTransformerConfig, eventFactory, + FieldColorConfigSettings, + FieldColorModeId, + fieldColorModeRegistry, + FieldConfigProperty, FieldConfigSource, PanelEvents, PanelPlugin, @@ -322,7 +326,35 @@ export class PanelModel implements DataConfigSource { } }); - this.fieldConfig = applyFieldConfigDefaults(this.fieldConfig, this.plugin!.fieldConfigDefaults); + this.fieldConfig = applyFieldConfigDefaults(this.fieldConfig, plugin.fieldConfigDefaults); + this.validateFieldColorMode(plugin); + } + + private validateFieldColorMode(plugin: PanelPlugin) { + // adjust to prefered field color setting if needed + const color = plugin.fieldConfigRegistry.getIfExists(FieldConfigProperty.Color); + + if (color && color.settings) { + const colorSettings = color.settings as FieldColorConfigSettings; + const mode = fieldColorModeRegistry.getIfExists(this.fieldConfig.defaults.color?.mode); + + // When no support fo value colors, use classic palette + if (!colorSettings.byValueSupport) { + if (!mode || mode.isByValue) { + this.fieldConfig.defaults.color = { mode: FieldColorModeId.PaletteClassic }; + return; + } + } + + // When supporting value colors and prefering thresholds, use Thresholds mode. + // Otherwise keep current mode + if (colorSettings.byValueSupport && colorSettings.preferThresholdsMode) { + if (!mode || !mode.isByValue) { + this.fieldConfig.defaults.color = { mode: FieldColorModeId.Thresholds }; + return; + } + } + } } pluginLoaded(plugin: PanelPlugin) { diff --git a/public/app/plugins/panel/graph/module.ts b/public/app/plugins/panel/graph/module.ts index 35b20f494da..195c95d55cb 100644 --- a/public/app/plugins/panel/graph/module.ts +++ b/public/app/plugins/panel/graph/module.ts @@ -12,11 +12,11 @@ import { axesEditorComponent } from './axes_editor'; import config from 'app/core/config'; import TimeSeries from 'app/core/time_series2'; import { getProcessedDataFrames } from 'app/features/dashboard/state/runRequest'; -import { PanelEvents, PanelPlugin, DataFrame, FieldConfigProperty, getColorForTheme } from '@grafana/data'; +import { DataFrame, FieldConfigProperty, getColorForTheme, PanelEvents, PanelPlugin } from '@grafana/data'; import { GraphContextMenuCtrl } from './GraphContextMenuCtrl'; import { graphPanelMigrationHandler } from './GraphMigrations'; -import { DataWarning, GraphPanelOptions, GraphFieldConfig } from './types'; +import { DataWarning, GraphFieldConfig, GraphPanelOptions } from './types'; import { auto } from 'angular'; import { AnnotationsSrv } from 'app/features/annotations/all'; @@ -388,10 +388,14 @@ export class GraphCtrl extends MetricsPanelCtrl { // Use new react style configuration export const plugin = new PanelPlugin(null) .useFieldConfig({ - standardOptions: [ - FieldConfigProperty.DisplayName, - FieldConfigProperty.Unit, - FieldConfigProperty.Links, // previously saved as dataLinks on options + disableStandardOptions: [ + FieldConfigProperty.NoValue, + FieldConfigProperty.Thresholds, + FieldConfigProperty.Max, + FieldConfigProperty.Min, + FieldConfigProperty.Decimals, + FieldConfigProperty.Color, + FieldConfigProperty.Mappings, ], }) .setMigrationHandler(graphPanelMigrationHandler); diff --git a/public/app/plugins/panel/graph2/module.tsx b/public/app/plugins/panel/graph2/module.tsx index 5e2063650a7..1eb3400183d 100644 --- a/public/app/plugins/panel/graph2/module.tsx +++ b/public/app/plugins/panel/graph2/module.tsx @@ -1,63 +1,61 @@ -import { FieldConfigProperty, PanelPlugin } from '@grafana/data'; +import { PanelPlugin } from '@grafana/data'; import { GraphPanel } from './GraphPanel'; import { Options } from './types'; -export const plugin = new PanelPlugin(GraphPanel) - .useFieldConfig({ standardOptions: [FieldConfigProperty.Unit, FieldConfigProperty.Decimals] }) - .setPanelOptions(builder => { - builder - .addBooleanSwitch({ - path: 'graph.showBars', - name: 'Show bars', - description: '', - defaultValue: false, - }) - .addBooleanSwitch({ - path: 'graph.showLines', - name: 'Show lines', - description: '', - defaultValue: true, - }) - .addBooleanSwitch({ - path: 'graph.showPoints', - name: 'Show poins', - description: '', - defaultValue: false, - }) - .addBooleanSwitch({ - path: 'legend.isVisible', - name: 'Show legend', - description: '', - defaultValue: true, - }) - .addBooleanSwitch({ - path: 'legend.asTable', - name: 'Display legend as table', - description: '', - defaultValue: false, - }) - .addRadio({ - path: 'legend.placement', - name: 'Legend placement', - description: '', - defaultValue: 'under', - settings: { - options: [ - { value: 'under', label: 'Below graph' }, - { value: 'right', label: 'Right to the graph' }, - ], - }, - }) - .addRadio({ - path: 'tooltipOptions.mode', - name: 'Tooltip mode', - description: '', - defaultValue: 'single', - settings: { - options: [ - { value: 'single', label: 'Single series' }, - { value: 'multi', label: 'All series' }, - ], - }, - }); - }); +export const plugin = new PanelPlugin(GraphPanel).useFieldConfig().setPanelOptions(builder => { + builder + .addBooleanSwitch({ + path: 'graph.showBars', + name: 'Show bars', + description: '', + defaultValue: false, + }) + .addBooleanSwitch({ + path: 'graph.showLines', + name: 'Show lines', + description: '', + defaultValue: true, + }) + .addBooleanSwitch({ + path: 'graph.showPoints', + name: 'Show poins', + description: '', + defaultValue: false, + }) + .addBooleanSwitch({ + path: 'legend.isVisible', + name: 'Show legend', + description: '', + defaultValue: true, + }) + .addBooleanSwitch({ + path: 'legend.asTable', + name: 'Display legend as table', + description: '', + defaultValue: false, + }) + .addRadio({ + path: 'legend.placement', + name: 'Legend placement', + description: '', + defaultValue: 'under', + settings: { + options: [ + { value: 'under', label: 'Below graph' }, + { value: 'right', label: 'Right to the graph' }, + ], + }, + }) + .addRadio({ + path: 'tooltipOptions.mode', + name: 'Tooltip mode', + description: '', + defaultValue: 'single', + settings: { + options: [ + { value: 'single', label: 'Single series' }, + { value: 'multi', label: 'All series' }, + ], + }, + }); +}); diff --git a/public/app/plugins/panel/graph3/module.tsx b/public/app/plugins/panel/graph3/module.tsx index 3ef328484c1..8a92941c336 100644 --- a/public/app/plugins/panel/graph3/module.tsx +++ b/public/app/plugins/panel/graph3/module.tsx @@ -1,21 +1,20 @@ -import { FieldConfigProperty, PanelPlugin } from '@grafana/data'; +import { FieldColorModeId, FieldConfigProperty, PanelPlugin } from '@grafana/data'; import { AxisSide, GraphCustomFieldConfig } from '@grafana/ui'; import { GraphPanel } from './GraphPanel'; import { Options } from './types'; export const plugin = new PanelPlugin(GraphPanel) .useFieldConfig({ - standardOptions: [ - // FieldConfigProperty.Min, - // FieldConfigProperty.Max, - FieldConfigProperty.Color, - FieldConfigProperty.Unit, - FieldConfigProperty.DisplayName, - FieldConfigProperty.Decimals, - // NOT: FieldConfigProperty.Thresholds, - FieldConfigProperty.Mappings, - ], - + standardOptions: { + [FieldConfigProperty.Color]: { + settings: { + byValueSupport: false, + }, + defaultValue: { + mode: FieldColorModeId.PaletteClassic, + }, + }, + }, useCustomConfig: builder => { builder .addBooleanSwitch({ diff --git a/public/app/plugins/panel/stat/module.tsx b/public/app/plugins/panel/stat/module.tsx index 873af89a110..73f57b2aacd 100644 --- a/public/app/plugins/panel/stat/module.tsx +++ b/public/app/plugins/panel/stat/module.tsx @@ -1,6 +1,6 @@ -import { sharedSingleStatMigrationHandler, BigValueTextMode } from '@grafana/ui'; +import { BigValueTextMode, sharedSingleStatMigrationHandler } from '@grafana/ui'; import { PanelPlugin } from '@grafana/data'; -import { StatPanelOptions, addStandardDataReduceOptions } from './types'; +import { addStandardDataReduceOptions, StatPanelOptions } from './types'; import { StatPanel } from './StatPanel'; import { statPanelChangedHandler } from './StatMigrations';