From 16f3fe7e15ed761a4ee6e617b130954ffd17c0ba Mon Sep 17 00:00:00 2001 From: Dominik Prokop Date: Fri, 13 Mar 2020 08:27:16 +0100 Subject: [PATCH] grafana/data: PanelTypeChangedHandler API update to use PanelModel instead of panel options object [BREAKING] (#22754) This changes PanelModel's API to support PanelModel API updates when changing panel type. Primary useful when changing panel type between Angular and React panels, as other migrations can be handled via DashboardMigrator. API change: https://github.com/grafana/grafana/pull/22754/files#diff-d9e3f91dc7d5697f6d85ada008003b4b (cherry picked from commit 1256d9e78d03712c6e3c0f0d05d97420e947a946) --- packages/grafana-data/src/types/panel.ts | 12 ++++-- .../SingleStatShared/SingleStatBaseOptions.ts | 39 ++++++++++--------- .../features/dashboard/state/PanelModel.ts | 2 +- public/app/plugins/panel/annolist/module.ts | 6 +-- .../plugins/panel/gauge/GaugeMigrations.ts | 4 +- public/app/plugins/panel/text2/module.tsx | 6 +-- 6 files changed, 37 insertions(+), 32 deletions(-) diff --git a/packages/grafana-data/src/types/panel.ts b/packages/grafana-data/src/types/panel.ts index a195d3fe646..93c34ed99d6 100644 --- a/packages/grafana-data/src/types/panel.ts +++ b/packages/grafana-data/src/types/panel.ts @@ -63,10 +63,10 @@ export interface PanelModel { export type PanelMigrationHandler = (panel: PanelModel) => Partial; /** - * Called before a panel is initialized + * Called before a panel is initialized. Allows panel inspection for any updates before changing the panel type. */ export type PanelTypeChangedHandler = ( - options: Partial, + panel: PanelModel, prevPluginId: string, prevOptions: any ) => Partial; @@ -117,8 +117,12 @@ export class PanelPlugin extends GrafanaPlugin } /** - * This function is called when the visualization was changed. This - * passes in the options that were used in the previous visualization + * This function is called when the visualization was changed. This + * passes in the panel model for previous visualisation options inspection + * and panel model updates. + * + * This is useful for supporting PanelModel API updates when changing + * between Angular and React panels. */ setPanelChangeHandler(handler: PanelTypeChangedHandler) { this.onPanelTypeChanged = handler; diff --git a/packages/grafana-ui/src/components/SingleStatShared/SingleStatBaseOptions.ts b/packages/grafana-ui/src/components/SingleStatShared/SingleStatBaseOptions.ts index 559279afa83..2526ac39904 100644 --- a/packages/grafana-ui/src/components/SingleStatShared/SingleStatBaseOptions.ts +++ b/packages/grafana-ui/src/components/SingleStatShared/SingleStatBaseOptions.ts @@ -27,15 +27,16 @@ export interface SingleStatBaseOptions { const optionsToKeep = ['fieldOptions', 'orientation']; export function sharedSingleStatPanelChangedHandler( - options: Partial | any, + panel: PanelModel> | any, prevPluginId: string, prevOptions: any ) { + let options = panel.options; // Migrating from angular singlestat if (prevPluginId === 'singlestat' && prevOptions.angular) { - const panel = prevOptions.angular; - const reducer = fieldReducers.getIfExists(panel.valueName); - const options = { + const prevPanel = prevOptions.angular; + const reducer = fieldReducers.getIfExists(prevPanel.valueName); + options = { fieldOptions: { defaults: {} as FieldConfig, overrides: [] as ConfigOverrideRule[], @@ -45,28 +46,28 @@ export function sharedSingleStatPanelChangedHandler( }; const defaults = options.fieldOptions.defaults; - if (panel.format) { - defaults.unit = panel.format; + if (prevPanel.format) { + defaults.unit = prevPanel.format; } - if (panel.nullPointMode) { - defaults.nullValueMode = panel.nullPointMode; + if (prevPanel.nullPointMode) { + defaults.nullValueMode = prevPanel.nullPointMode; } - if (panel.nullText) { - defaults.noValue = panel.nullText; + if (prevPanel.nullText) { + defaults.noValue = prevPanel.nullText; } - if (panel.decimals || panel.decimals === 0) { - defaults.decimals = panel.decimals; + if (prevPanel.decimals || prevPanel.decimals === 0) { + defaults.decimals = prevPanel.decimals; } // Convert thresholds and color values - if (panel.thresholds && panel.colors) { - const levels = panel.thresholds.split(',').map((strVale: string) => { + if (prevPanel.thresholds && prevPanel.colors) { + const levels = prevPanel.thresholds.split(',').map((strVale: string) => { return Number(strVale.trim()); }); // One more color than threshold const thresholds: Threshold[] = []; - for (const color of panel.colors) { + for (const color of prevPanel.colors) { const idx = thresholds.length - 1; if (idx >= 0) { thresholds.push({ value: levels[idx], color }); @@ -81,14 +82,14 @@ export function sharedSingleStatPanelChangedHandler( } // Convert value mappings - const mappings = convertOldAngularValueMapping(panel); + const mappings = convertOldAngularValueMapping(prevPanel); if (mappings && mappings.length) { defaults.mappings = mappings; } - if (panel.gauge && panel.gauge.show) { - defaults.min = panel.gauge.minValue; - defaults.max = panel.gauge.maxValue; + if (prevPanel.gauge && prevPanel.gauge.show) { + defaults.min = prevPanel.gauge.minValue; + defaults.max = prevPanel.gauge.maxValue; } return options; } diff --git a/public/app/features/dashboard/state/PanelModel.ts b/public/app/features/dashboard/state/PanelModel.ts index fd89ffaa0ce..1c36b15ce91 100644 --- a/public/app/features/dashboard/state/PanelModel.ts +++ b/public/app/features/dashboard/state/PanelModel.ts @@ -313,7 +313,7 @@ export class PanelModel { old = oldOptions.options; } this.options = this.options || {}; - Object.assign(this.options, newPlugin.onPanelTypeChanged(this.options, oldPluginId, old)); + Object.assign(this.options, newPlugin.onPanelTypeChanged(this, oldPluginId, old)); } // switch diff --git a/public/app/plugins/panel/annolist/module.ts b/public/app/plugins/panel/annolist/module.ts index f00af0ee65e..6bee00cea8e 100644 --- a/public/app/plugins/panel/annolist/module.ts +++ b/public/app/plugins/panel/annolist/module.ts @@ -1,16 +1,16 @@ import { AnnoListPanel } from './AnnoListPanel'; import { AnnoOptions, defaults } from './types'; import { AnnoListEditor } from './AnnoListEditor'; -import { PanelPlugin } from '@grafana/data'; +import { PanelModel, PanelPlugin } from '@grafana/data'; export const plugin = new PanelPlugin(AnnoListPanel) .setDefaults(defaults) .setEditor(AnnoListEditor) // TODO, we should support this directly in the plugin infrastructure - .setPanelChangeHandler((options: AnnoOptions, prevPluginId: string, prevOptions: any) => { + .setPanelChangeHandler((panel: PanelModel, prevPluginId: string, prevOptions: any) => { if (prevPluginId === 'ryantxu-annolist-panel') { return prevOptions as AnnoOptions; } - return options; + return panel.options; }); diff --git a/public/app/plugins/panel/gauge/GaugeMigrations.ts b/public/app/plugins/panel/gauge/GaugeMigrations.ts index 83e3be05f82..d4b619aa20c 100644 --- a/public/app/plugins/panel/gauge/GaugeMigrations.ts +++ b/public/app/plugins/panel/gauge/GaugeMigrations.ts @@ -9,12 +9,12 @@ export const gaugePanelMigrationHandler = (panel: PanelModel): Par // This is called when the panel changes from another panel export const gaugePanelChangedHandler = ( - options: Partial | any, + panel: PanelModel> | any, prevPluginId: string, prevOptions: any ) => { // This handles most config changes - const opts = sharedSingleStatPanelChangedHandler(options, prevPluginId, prevOptions) as GaugeOptions; + const opts = sharedSingleStatPanelChangedHandler(panel, prevPluginId, prevOptions) as GaugeOptions; // Changing from angular singlestat if (prevPluginId === 'singlestat' && prevOptions.angular) { diff --git a/public/app/plugins/panel/text2/module.tsx b/public/app/plugins/panel/text2/module.tsx index babc3713da9..ae48f013f41 100644 --- a/public/app/plugins/panel/text2/module.tsx +++ b/public/app/plugins/panel/text2/module.tsx @@ -1,4 +1,4 @@ -import { PanelPlugin } from '@grafana/data'; +import { PanelModel, PanelPlugin } from '@grafana/data'; import { TextPanelEditor } from './TextPanelEditor'; import { TextPanel } from './TextPanel'; @@ -7,9 +7,9 @@ import { TextOptions, defaults } from './types'; export const plugin = new PanelPlugin(TextPanel) .setDefaults(defaults) .setEditor(TextPanelEditor) - .setPanelChangeHandler((options: TextOptions, prevPluginId: string, prevOptions: any) => { + .setPanelChangeHandler((panel: PanelModel, prevPluginId: string, prevOptions: any) => { if (prevPluginId === 'text') { return prevOptions as TextOptions; } - return options; + return panel.options; });