From 21948e80e0c5ab0db4223caa555310abb1eba27c Mon Sep 17 00:00:00 2001 From: Ryan McKinley Date: Sun, 18 Aug 2019 15:01:07 -0700 Subject: [PATCH] SingleStat: add a gauge migration call to action button in the editor (#18604) --- .../SingleStatBaseOptions.test.ts | 6 +- .../SingleStatShared/SingleStatBaseOptions.ts | 119 +++++++++++++++++- .../SingleStatBaseOptions.test.ts.snap | 2 +- .../src/components/SingleStatShared/index.ts | 4 +- .../dashboard/dashgrid/DashboardPanel.tsx | 4 +- .../dashboard/panel_editor/PanelEditor.tsx | 6 +- .../panel_editor/VisualizationTab.tsx | 12 +- .../dashboard/panel_editor/VizTypePicker.tsx | 11 +- .../dashboard/state/PanelModel.test.ts | 2 +- .../features/dashboard/state/PanelModel.ts | 23 ++-- public/app/features/panel/panel_ctrl.ts | 4 + .../panel/bargauge/BarGaugeMigrations.test.ts | 4 +- .../panel/bargauge/BarGaugeMigrations.ts | 7 +- public/app/plugins/panel/bargauge/module.tsx | 8 +- .../panel/gauge/GaugeMigrations.test.ts | 28 ++++- .../plugins/panel/gauge/GaugeMigrations.ts | 28 ++++- public/app/plugins/panel/gauge/module.tsx | 7 +- .../app/plugins/panel/singlestat/editor.html | 37 ++++++ public/app/plugins/panel/singlestat/module.ts | 9 ++ .../app/plugins/panel/singlestat2/module.tsx | 6 +- 20 files changed, 267 insertions(+), 60 deletions(-) diff --git a/packages/grafana-ui/src/components/SingleStatShared/SingleStatBaseOptions.test.ts b/packages/grafana-ui/src/components/SingleStatShared/SingleStatBaseOptions.test.ts index 209953fc5fa..3a467e8ba29 100644 --- a/packages/grafana-ui/src/components/SingleStatShared/SingleStatBaseOptions.test.ts +++ b/packages/grafana-ui/src/components/SingleStatShared/SingleStatBaseOptions.test.ts @@ -1,6 +1,6 @@ -import { sharedSingleStatMigrationCheck } from './SingleStatBaseOptions'; +import { sharedSingleStatMigrationHandler } from './SingleStatBaseOptions'; -describe('sharedSingleStatMigrationCheck', () => { +describe('sharedSingleStatMigrationHandler', () => { it('from old valueOptions model without pluginVersion', () => { const panel = { options: { @@ -34,6 +34,6 @@ describe('sharedSingleStatMigrationCheck', () => { type: 'bargauge', }; - expect(sharedSingleStatMigrationCheck(panel as any)).toMatchSnapshot(); + expect(sharedSingleStatMigrationHandler(panel as any)).toMatchSnapshot(); }); }); diff --git a/packages/grafana-ui/src/components/SingleStatShared/SingleStatBaseOptions.ts b/packages/grafana-ui/src/components/SingleStatShared/SingleStatBaseOptions.ts index 3215d0c72b2..ae104fccbf1 100644 --- a/packages/grafana-ui/src/components/SingleStatShared/SingleStatBaseOptions.ts +++ b/packages/grafana-ui/src/components/SingleStatShared/SingleStatBaseOptions.ts @@ -3,7 +3,15 @@ import omit from 'lodash/omit'; import { VizOrientation, PanelModel } from '../../types/panel'; import { FieldDisplayOptions } from '../../utils/fieldDisplay'; -import { fieldReducers, Threshold, sortThresholds } from '@grafana/data'; +import { + fieldReducers, + Threshold, + sortThresholds, + FieldConfig, + ReducerID, + ValueMapping, + MappingType, +} from '@grafana/data'; export interface SingleStatBaseOptions { fieldOptions: FieldDisplayOptions; @@ -12,23 +20,82 @@ export interface SingleStatBaseOptions { const optionsToKeep = ['fieldOptions', 'orientation']; -export const sharedSingleStatOptionsCheck = ( +export function sharedSingleStatPanelChangedHandler( options: Partial | any, prevPluginId: string, prevOptions: any -) => { +) { + // Migrating from angular singlestat + if (prevPluginId === 'singlestat' && prevOptions.angular) { + const panel = prevOptions.angular; + const reducer = fieldReducers.getIfExists(panel.valueName); + const options = { + fieldOptions: { + defaults: {} as FieldConfig, + override: {} as FieldConfig, + calcs: [reducer ? reducer.id : ReducerID.mean], + }, + orientation: VizOrientation.Horizontal, + }; + + const defaults = options.fieldOptions.defaults; + if (panel.format) { + defaults.unit = panel.format; + } + if (panel.nullPointMode) { + defaults.nullValueMode = panel.nullPointMode; + } + if (panel.nullText) { + defaults.noValue = panel.nullText; + } + if (panel.decimals || panel.decimals === 0) { + defaults.decimals = panel.decimals; + } + + // Convert thresholds and color values + if (panel.thresholds && panel.colors) { + const levels = panel.thresholds.split(',').map((strVale: string) => { + return Number(strVale.trim()); + }); + + // One more color than threshold + const thresholds: Threshold[] = []; + for (const color of panel.colors) { + const idx = thresholds.length - 1; + if (idx >= 0) { + thresholds.push({ value: levels[idx], color }); + } else { + thresholds.push({ value: -Infinity, color }); + } + } + defaults.thresholds = thresholds; + } + + // Convert value mappings + const mappings = convertOldAngulrValueMapping(panel); + if (mappings && mappings.length) { + defaults.mappings = mappings; + } + + if (panel.gauge) { + defaults.min = panel.gauge.minValue; + defaults.max = panel.gauge.maxValue; + } + return options; + } + for (const k of optionsToKeep) { if (prevOptions.hasOwnProperty(k)) { options[k] = cloneDeep(prevOptions[k]); } } return options; -}; +} -export function sharedSingleStatMigrationCheck(panel: PanelModel) { +export function sharedSingleStatMigrationHandler(panel: PanelModel): SingleStatBaseOptions { if (!panel.options) { // This happens on the first load or when migrating from angular - return {}; + return {} as any; } const previousVersion = parseFloat(panel.pluginVersion || '6.1'); @@ -121,3 +188,43 @@ export function migrateOldThresholds(thresholds?: any[]): Threshold[] | undefine copy[0].value = -Infinity; return copy; } + +/** + * Convert the angular single stat mapping to new react style + */ +function convertOldAngulrValueMapping(panel: any): ValueMapping[] { + const mappings: ValueMapping[] = []; + + // Guess the right type based on options + let mappingType = panel.mappingType; + if (!panel.mappingType) { + if (panel.valueMaps && panel.valueMaps.length) { + mappingType = 1; + } else if (panel.rangeMaps && panel.rangeMaps.length) { + mappingType = 2; + } + } + + // check value to text mappings if its enabled + if (mappingType === 1) { + for (let i = 0; i < panel.valueMaps.length; i++) { + const map = panel.valueMaps[i]; + mappings.push({ + ...map, + id: i, // used for order + type: MappingType.ValueToText, + }); + } + } else if (mappingType === 2) { + for (let i = 0; i < panel.rangeMaps.length; i++) { + const map = panel.rangeMaps[i]; + mappings.push({ + ...map, + id: i, // used for order + type: MappingType.RangeToText, + }); + } + } + + return mappings; +} diff --git a/packages/grafana-ui/src/components/SingleStatShared/__snapshots__/SingleStatBaseOptions.test.ts.snap b/packages/grafana-ui/src/components/SingleStatShared/__snapshots__/SingleStatBaseOptions.test.ts.snap index 422d49bccdb..01b87fa582a 100644 --- a/packages/grafana-ui/src/components/SingleStatShared/__snapshots__/SingleStatBaseOptions.test.ts.snap +++ b/packages/grafana-ui/src/components/SingleStatShared/__snapshots__/SingleStatBaseOptions.test.ts.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`sharedSingleStatMigrationCheck from old valueOptions model without pluginVersion 1`] = ` +exports[`sharedSingleStatMigrationHandler from old valueOptions model without pluginVersion 1`] = ` Object { "fieldOptions": Object { "calcs": Array [ diff --git a/packages/grafana-ui/src/components/SingleStatShared/index.ts b/packages/grafana-ui/src/components/SingleStatShared/index.ts index 57531c93124..f6fcffd3fd2 100644 --- a/packages/grafana-ui/src/components/SingleStatShared/index.ts +++ b/packages/grafana-ui/src/components/SingleStatShared/index.ts @@ -3,6 +3,6 @@ export { FieldPropertiesEditor } from './FieldPropertiesEditor'; export { SingleStatBaseOptions, - sharedSingleStatOptionsCheck, - sharedSingleStatMigrationCheck, + sharedSingleStatPanelChangedHandler, + sharedSingleStatMigrationHandler, } from './SingleStatBaseOptions'; diff --git a/public/app/features/dashboard/dashgrid/DashboardPanel.tsx b/public/app/features/dashboard/dashgrid/DashboardPanel.tsx index 4d7b2cf8d8d..5ef3e0c5b66 100644 --- a/public/app/features/dashboard/dashgrid/DashboardPanel.tsx +++ b/public/app/features/dashboard/dashgrid/DashboardPanel.tsx @@ -61,7 +61,7 @@ export class DashboardPanel extends PureComponent { return ; } - onPluginTypeChanged = (plugin: PanelPluginMeta) => { + onPluginTypeChange = (plugin: PanelPluginMeta) => { this.loadPlugin(plugin.id); }; @@ -211,7 +211,7 @@ export class DashboardPanel extends PureComponent { plugin={plugin} dashboard={dashboard} angularPanel={angularPanel} - onTypeChanged={this.onPluginTypeChanged} + onPluginTypeChange={this.onPluginTypeChange} /> )} diff --git a/public/app/features/dashboard/panel_editor/PanelEditor.tsx b/public/app/features/dashboard/panel_editor/PanelEditor.tsx index dde5f8440c1..5a27d9e1e63 100644 --- a/public/app/features/dashboard/panel_editor/PanelEditor.tsx +++ b/public/app/features/dashboard/panel_editor/PanelEditor.tsx @@ -20,7 +20,7 @@ interface PanelEditorProps { dashboard: DashboardModel; plugin: PanelPlugin; angularPanel?: AngularComponent; - onTypeChanged: (newType: PanelPluginMeta) => void; + onPluginTypeChange: (newType: PanelPluginMeta) => void; } interface PanelEditorTab { @@ -70,7 +70,7 @@ export class PanelEditor extends PureComponent { }; renderCurrentTab(activeTab: string) { - const { panel, dashboard, onTypeChanged, plugin, angularPanel } = this.props; + const { panel, dashboard, onPluginTypeChange, plugin, angularPanel } = this.props; switch (activeTab) { case 'advanced': @@ -85,7 +85,7 @@ export class PanelEditor extends PureComponent { panel={panel} dashboard={dashboard} plugin={plugin} - onTypeChanged={onTypeChanged} + onPluginTypeChange={onPluginTypeChange} angularPanel={angularPanel} /> ); diff --git a/public/app/features/dashboard/panel_editor/VisualizationTab.tsx b/public/app/features/dashboard/panel_editor/VisualizationTab.tsx index f67532dd398..739f99bd95b 100644 --- a/public/app/features/dashboard/panel_editor/VisualizationTab.tsx +++ b/public/app/features/dashboard/panel_editor/VisualizationTab.tsx @@ -19,13 +19,14 @@ import { DashboardModel } from '../state'; import { VizPickerSearch } from './VizPickerSearch'; import PluginStateinfo from 'app/features/plugins/PluginStateInfo'; import { PanelPlugin, PanelPluginMeta } from '@grafana/ui'; +import { PanelCtrl } from 'app/plugins/sdk'; interface Props { panel: PanelModel; dashboard: DashboardModel; plugin: PanelPlugin; angularPanel?: AngularComponent; - onTypeChanged: (newType: PanelPluginMeta) => void; + onPluginTypeChange: (newType: PanelPluginMeta) => void; updateLocation: typeof updateLocation; urlOpenVizPicker: boolean; } @@ -104,8 +105,9 @@ export class VisualizationTab extends PureComponent { return; } - const panelCtrl = scope.$$childHead.ctrl; + const panelCtrl: PanelCtrl = scope.$$childHead.ctrl; panelCtrl.initEditMode(); + panelCtrl.onPluginTypeChange = this.onPluginTypeChange; let template = ''; for (let i = 0; i < panelCtrl.editorTabs.length; i++) { @@ -197,11 +199,11 @@ export class VisualizationTab extends PureComponent { } }; - onTypeChanged = (plugin: PanelPluginMeta) => { + onPluginTypeChange = (plugin: PanelPluginMeta) => { if (plugin.id === this.props.plugin.meta.id) { this.setState({ isVizPickerOpen: false }); } else { - this.props.onTypeChanged(plugin); + this.props.onPluginTypeChange(plugin); } }; @@ -235,7 +237,7 @@ export class VisualizationTab extends PureComponent { diff --git a/public/app/features/dashboard/panel_editor/VizTypePicker.tsx b/public/app/features/dashboard/panel_editor/VizTypePicker.tsx index 30da43940f9..0d0f5c2be48 100644 --- a/public/app/features/dashboard/panel_editor/VizTypePicker.tsx +++ b/public/app/features/dashboard/panel_editor/VizTypePicker.tsx @@ -6,7 +6,7 @@ import { PanelPluginMeta, EmptySearchResult } from '@grafana/ui'; export interface Props { current: PanelPluginMeta; - onTypeChanged: (newType: PanelPluginMeta) => void; + onTypeChange: (newType: PanelPluginMeta) => void; searchQuery: string; onClose: () => void; } @@ -34,16 +34,11 @@ export class VizTypePicker extends PureComponent { } renderVizPlugin = (plugin: PanelPluginMeta, index: number) => { - const { onTypeChanged } = this.props; + const { onTypeChange } = this.props; const isCurrent = plugin.id === this.props.current.id; return ( - onTypeChanged(plugin)} - /> + onTypeChange(plugin)} /> ); }; diff --git a/public/app/features/dashboard/state/PanelModel.test.ts b/public/app/features/dashboard/state/PanelModel.test.ts index b6e5c7f7586..165195583fd 100644 --- a/public/app/features/dashboard/state/PanelModel.test.ts +++ b/public/app/features/dashboard/state/PanelModel.test.ts @@ -165,7 +165,7 @@ describe('PanelModel', () => { it('should call react onPanelTypeChanged', () => { expect(onPanelTypeChanged.mock.calls.length).toBe(1); expect(onPanelTypeChanged.mock.calls[0][1]).toBe('table'); - expect(onPanelTypeChanged.mock.calls[0][2].fieldOptions).toBeDefined(); + expect(onPanelTypeChanged.mock.calls[0][2].angular).toBeDefined(); }); it('getQueryRunner() should return same instance after changing to another react panel', () => { diff --git a/public/app/features/dashboard/state/PanelModel.ts b/public/app/features/dashboard/state/PanelModel.ts index 9869c830c41..addc3073339 100644 --- a/public/app/features/dashboard/state/PanelModel.ts +++ b/public/app/features/dashboard/state/PanelModel.ts @@ -262,9 +262,10 @@ export class PanelModel { const pluginId = newPlugin.meta.id; const oldOptions: any = this.getOptionsToRemember(); const oldPluginId = this.type; + const wasAngular = !!this.plugin.angularPanelCtrl; // for angular panels we must remove all events and let angular panels do some cleanup - if (this.plugin.angularPanelCtrl) { + if (wasAngular) { this.destroy(); } @@ -280,16 +281,24 @@ export class PanelModel { this.cachedPluginOptions[oldPluginId] = oldOptions; this.restorePanelOptions(pluginId); + // Let panel plugins inspect options from previous panel and keep any that it can use + if (newPlugin.onPanelTypeChanged) { + let old: any = {}; + + if (wasAngular) { + old = { angular: oldOptions }; + } else if (oldOptions && oldOptions.options) { + old = oldOptions.options; + } + + this.options = this.options || {}; + Object.assign(this.options, newPlugin.onPanelTypeChanged(this.options, oldPluginId, old)); + } + // switch this.type = pluginId; this.plugin = newPlugin; this.applyPluginOptionDefaults(newPlugin); - // Let panel plugins inspect options from previous panel and keep any that it can use - if (newPlugin.onPanelTypeChanged) { - this.options = this.options || {}; - const old = oldOptions && oldOptions.options ? oldOptions.options : {}; - Object.assign(this.options, newPlugin.onPanelTypeChanged(this.options, oldPluginId, old)); - } if (newPlugin.onPanelMigration) { this.pluginVersion = getPluginVersion(newPlugin); diff --git a/public/app/features/panel/panel_ctrl.ts b/public/app/features/panel/panel_ctrl.ts index 0202cd595c8..185d517025e 100644 --- a/public/app/features/panel/panel_ctrl.ts +++ b/public/app/features/panel/panel_ctrl.ts @@ -19,6 +19,7 @@ import { GRID_COLUMN_COUNT } from 'app/core/constants'; import { auto } from 'angular'; import { TemplateSrv } from '../templating/template_srv'; import { LinkSrv } from './panellinks/link_srv'; +import { PanelPluginMeta } from '@grafana/ui/src/types/panel'; export class PanelCtrl { panel: any; @@ -281,4 +282,7 @@ export class PanelCtrl { html += ''; return html; } + + // overriden from react + onPluginTypeChange = (plugin: PanelPluginMeta) => {}; } diff --git a/public/app/plugins/panel/bargauge/BarGaugeMigrations.test.ts b/public/app/plugins/panel/bargauge/BarGaugeMigrations.test.ts index 540dd8ddc19..3a5a556ad57 100644 --- a/public/app/plugins/panel/bargauge/BarGaugeMigrations.test.ts +++ b/public/app/plugins/panel/bargauge/BarGaugeMigrations.test.ts @@ -1,5 +1,5 @@ import { PanelModel } from '@grafana/ui'; -import { barGaugePanelMigrationCheck } from './BarGaugeMigrations'; +import { barGaugePanelMigrationHandler } from './BarGaugeMigrations'; describe('BarGauge Panel Migrations', () => { it('from 6.2', () => { @@ -45,6 +45,6 @@ describe('BarGauge Panel Migrations', () => { type: 'bargauge', } as PanelModel; - expect(barGaugePanelMigrationCheck(panel)).toMatchSnapshot(); + expect(barGaugePanelMigrationHandler(panel)).toMatchSnapshot(); }); }); diff --git a/public/app/plugins/panel/bargauge/BarGaugeMigrations.ts b/public/app/plugins/panel/bargauge/BarGaugeMigrations.ts index c6f8c029ffc..065c8ce8c01 100644 --- a/public/app/plugins/panel/bargauge/BarGaugeMigrations.ts +++ b/public/app/plugins/panel/bargauge/BarGaugeMigrations.ts @@ -1,7 +1,6 @@ -import { PanelModel } from '@grafana/ui'; -import { sharedSingleStatMigrationCheck } from '@grafana/ui/src/components/SingleStatShared/SingleStatBaseOptions'; +import { PanelModel, sharedSingleStatMigrationHandler } from '@grafana/ui'; import { BarGaugeOptions } from './types'; -export const barGaugePanelMigrationCheck = (panel: PanelModel): Partial => { - return sharedSingleStatMigrationCheck(panel); +export const barGaugePanelMigrationHandler = (panel: PanelModel): Partial => { + return sharedSingleStatMigrationHandler(panel); }; diff --git a/public/app/plugins/panel/bargauge/module.tsx b/public/app/plugins/panel/bargauge/module.tsx index 423aef5fab4..8742ab774de 100644 --- a/public/app/plugins/panel/bargauge/module.tsx +++ b/public/app/plugins/panel/bargauge/module.tsx @@ -1,11 +1,11 @@ -import { PanelPlugin, sharedSingleStatOptionsCheck } from '@grafana/ui'; +import { PanelPlugin, sharedSingleStatPanelChangedHandler } from '@grafana/ui'; import { BarGaugePanel } from './BarGaugePanel'; import { BarGaugePanelEditor } from './BarGaugePanelEditor'; import { BarGaugeOptions, defaults } from './types'; -import { barGaugePanelMigrationCheck } from './BarGaugeMigrations'; +import { barGaugePanelMigrationHandler } from './BarGaugeMigrations'; export const plugin = new PanelPlugin(BarGaugePanel) .setDefaults(defaults) .setEditor(BarGaugePanelEditor) - .setPanelChangeHandler(sharedSingleStatOptionsCheck) - .setMigrationHandler(barGaugePanelMigrationCheck); + .setPanelChangeHandler(sharedSingleStatPanelChangedHandler) + .setMigrationHandler(barGaugePanelMigrationHandler); diff --git a/public/app/plugins/panel/gauge/GaugeMigrations.test.ts b/public/app/plugins/panel/gauge/GaugeMigrations.test.ts index 8175a051c5f..8e00a4c635b 100644 --- a/public/app/plugins/panel/gauge/GaugeMigrations.test.ts +++ b/public/app/plugins/panel/gauge/GaugeMigrations.test.ts @@ -1,5 +1,5 @@ import { PanelModel } from '@grafana/ui'; -import { gaugePanelMigrationCheck } from './GaugeMigrations'; +import { gaugePanelMigrationHandler, gaugePanelChangedHandler } from './GaugeMigrations'; describe('Gauge Panel Migrations', () => { it('from 6.1.1', () => { @@ -77,6 +77,30 @@ describe('Gauge Panel Migrations', () => { type: 'gauge', } as PanelModel; - expect(gaugePanelMigrationCheck(panel)).toMatchSnapshot(); + expect(gaugePanelMigrationHandler(panel)).toMatchSnapshot(); + }); + + it('change from angular singlestat to gauge', () => { + const old: any = { + angular: { + format: 'ms', + decimals: 7, + gauge: { + maxValue: 150, + minValue: -10, + show: true, + thresholdLabels: true, + thresholdMarkers: true, + }, + }, + }; + + const newOptions = gaugePanelChangedHandler({} as any, 'singlestat', old); + expect(newOptions.fieldOptions.defaults.unit).toBe('ms'); + expect(newOptions.fieldOptions.defaults.min).toBe(-10); + expect(newOptions.fieldOptions.defaults.max).toBe(150); + expect(newOptions.fieldOptions.defaults.decimals).toBe(7); + expect(newOptions.showThresholdMarkers).toBe(true); + expect(newOptions.showThresholdLabels).toBe(true); }); }); diff --git a/public/app/plugins/panel/gauge/GaugeMigrations.ts b/public/app/plugins/panel/gauge/GaugeMigrations.ts index d3227eaf8cb..0dceaedb038 100644 --- a/public/app/plugins/panel/gauge/GaugeMigrations.ts +++ b/public/app/plugins/panel/gauge/GaugeMigrations.ts @@ -1,7 +1,27 @@ -import { PanelModel } from '@grafana/ui'; +import { PanelModel, sharedSingleStatPanelChangedHandler, sharedSingleStatMigrationHandler } from '@grafana/ui'; import { GaugeOptions } from './types'; -import { sharedSingleStatMigrationCheck } from '@grafana/ui/src/components/SingleStatShared/SingleStatBaseOptions'; -export const gaugePanelMigrationCheck = (panel: PanelModel): Partial => { - return sharedSingleStatMigrationCheck(panel); +// This is called when the panel first loads +export const gaugePanelMigrationHandler = (panel: PanelModel): Partial => { + return sharedSingleStatMigrationHandler(panel); +}; + +// This is called when the panel changes from another panel +export const gaugePanelChangedHandler = ( + options: Partial | any, + prevPluginId: string, + prevOptions: any +) => { + // This handles most config changes + const opts = sharedSingleStatPanelChangedHandler(options, prevPluginId, prevOptions) as GaugeOptions; + + // Changing from angular singlestat + if (prevPluginId === 'singlestat' && prevOptions.angular) { + const gauge = prevOptions.angular.gauge; + if (gauge) { + opts.showThresholdMarkers = gauge.thresholdMarkers; + opts.showThresholdLabels = gauge.thresholdLabels; + } + } + return opts; }; diff --git a/public/app/plugins/panel/gauge/module.tsx b/public/app/plugins/panel/gauge/module.tsx index 6272181e566..ed014550d1f 100644 --- a/public/app/plugins/panel/gauge/module.tsx +++ b/public/app/plugins/panel/gauge/module.tsx @@ -1,10 +1,11 @@ -import { PanelPlugin, sharedSingleStatMigrationCheck, sharedSingleStatOptionsCheck } from '@grafana/ui'; +import { PanelPlugin } from '@grafana/ui'; import { GaugePanelEditor } from './GaugePanelEditor'; import { GaugePanel } from './GaugePanel'; import { GaugeOptions, defaults } from './types'; +import { gaugePanelMigrationHandler, gaugePanelChangedHandler } from './GaugeMigrations'; export const plugin = new PanelPlugin(GaugePanel) .setDefaults(defaults) .setEditor(GaugePanelEditor) - .setPanelChangeHandler(sharedSingleStatOptionsCheck) - .setMigrationHandler(sharedSingleStatMigrationCheck); + .setPanelChangeHandler(gaugePanelChangedHandler) + .setMigrationHandler(gaugePanelMigrationHandler); diff --git a/public/app/plugins/panel/singlestat/editor.html b/public/app/plugins/panel/singlestat/editor.html index 86244423ab7..efc5c0909ea 100644 --- a/public/app/plugins/panel/singlestat/editor.html +++ b/public/app/plugins/panel/singlestat/editor.html @@ -1,4 +1,41 @@
+ +
+
Gauge Migration
+

+ Gauge visualizations within the Singlestat panel are deprecated. Please + migrate this panel to use the Gauge panel + +

+ + +
+ +
+ +
+ NOTE: Sparklines are not supported in the gauge panel +
+ +
+ NOTE: Prefix will not be show in the gauge panel +
+ +
+ NOTE: Postfix will not be show in the gauge panel +
+ +
+ NOTE: Links will be in the upper left corner, rather than anywhere on the gauge +
+

+
+ +
Value
diff --git a/public/app/plugins/panel/singlestat/module.ts b/public/app/plugins/panel/singlestat/module.ts index 78d70becf27..de63a23332a 100644 --- a/public/app/plugins/panel/singlestat/module.ts +++ b/public/app/plugins/panel/singlestat/module.ts @@ -113,6 +113,15 @@ class SingleStatCtrl extends MetricsPanelCtrl { this.unitFormats = kbn.getUnitFormats(); } + migrateToGaugePanel(migrate: boolean) { + if (migrate) { + this.onPluginTypeChange(config.panels['gauge']); + } else { + this.panel.gauge.show = false; + this.render(); + } + } + setUnitFormat(subItem: { value: any }) { this.panel.format = subItem.value; this.refresh(); diff --git a/public/app/plugins/panel/singlestat2/module.tsx b/public/app/plugins/panel/singlestat2/module.tsx index abf794f02d3..a78ebdd6375 100644 --- a/public/app/plugins/panel/singlestat2/module.tsx +++ b/public/app/plugins/panel/singlestat2/module.tsx @@ -1,4 +1,4 @@ -import { PanelPlugin, sharedSingleStatMigrationCheck, sharedSingleStatOptionsCheck } from '@grafana/ui'; +import { PanelPlugin, sharedSingleStatMigrationHandler, sharedSingleStatPanelChangedHandler } from '@grafana/ui'; import { SingleStatOptions, defaults } from './types'; import { SingleStatPanel } from './SingleStatPanel'; import { SingleStatEditor } from './SingleStatEditor'; @@ -6,5 +6,5 @@ import { SingleStatEditor } from './SingleStatEditor'; export const plugin = new PanelPlugin(SingleStatPanel) .setDefaults(defaults) .setEditor(SingleStatEditor) - .setPanelChangeHandler(sharedSingleStatOptionsCheck) - .setMigrationHandler(sharedSingleStatMigrationCheck); + .setPanelChangeHandler(sharedSingleStatPanelChangedHandler) + .setMigrationHandler(sharedSingleStatMigrationHandler);