diff --git a/packages/grafana-data/src/types/fieldOverrides.ts b/packages/grafana-data/src/types/fieldOverrides.ts index 02ab152d301..3a6757b2640 100644 --- a/packages/grafana-data/src/types/fieldOverrides.ts +++ b/packages/grafana-data/src/types/fieldOverrides.ts @@ -126,7 +126,7 @@ export enum FieldConfigProperty { Min = 'min', Max = 'max', Decimals = 'decimals', - Title = 'title', + DisplayName = 'displayName', NoValue = 'noValue', Thresholds = 'thresholds', Mappings = 'mappings', diff --git a/public/app/features/dashboard/state/PanelModel.ts b/public/app/features/dashboard/state/PanelModel.ts index c44ee68fa8e..ee7f5d189a9 100644 --- a/public/app/features/dashboard/state/PanelModel.ts +++ b/public/app/features/dashboard/state/PanelModel.ts @@ -335,7 +335,7 @@ export class PanelModel implements DataConfigSource { pluginLoaded(plugin: PanelPlugin) { this.plugin = plugin; - if (plugin.panel && plugin.onPanelMigration) { + if (plugin.onPanelMigration) { const version = getPluginVersion(plugin); if (version !== this.pluginVersion) { diff --git a/public/app/plugins/panel/graph/GraphMigrations.test.ts b/public/app/plugins/panel/graph/GraphMigrations.test.ts new file mode 100644 index 00000000000..667142f5e12 --- /dev/null +++ b/public/app/plugins/panel/graph/GraphMigrations.test.ts @@ -0,0 +1,129 @@ +import { PanelModel, FieldConfigSource } from '@grafana/data'; +import { graphPanelMigrationHandler } from './GraphMigrations'; + +describe('Graph Panel Migrations', () => { + it('from 7.0', () => { + const panel = { + aliasColors: {}, + bars: false, + dashLength: 10, + dashes: false, + fill: 1, + fillGradient: 0, + gridPos: { + h: 8, + w: 9, + x: 6, + y: 0, + }, + hiddenSeries: false, + id: 23763571993, + legend: { + avg: false, + current: false, + max: false, + min: false, + show: true, + total: false, + values: false, + }, + lines: true, + linewidth: 1, + nullPointMode: 'null', + options: { + dataLinks: [ + { + targetBlank: false, + title: 'Drill it down', + url: 'THE DRILLDOWN URL', + }, + ], + }, + percentage: false, + pointradius: 2, + points: false, + renderer: 'flot', + seriesOverrides: [ + { + alias: 'Bar datacenter {datacenter="baz", region="us-east-2"}', + yaxis: 2, + }, + ], + spaceLength: 10, + stack: false, + steppedLine: false, + targets: [ + { + alias: 'Foo datacenter', + labels: 'datacenter=foo,region=us-east-1', + refId: 'A', + scenarioId: 'random_walk', + }, + { + alias: 'Bar datacenter', + labels: 'datacenter=bar,region=us-east-2', + refId: 'B', + scenarioId: 'random_walk', + }, + { + alias: 'Bar datacenter', + labels: 'datacenter=baz,region=us-east-2', + refId: 'C', + scenarioId: 'random_walk', + }, + ], + thresholds: [], + timeFrom: null, + timeRegions: [], + timeShift: null, + title: 'Multiple series', + tooltip: { + shared: true, + sort: 0, + value_type: 'individual', + }, + type: 'graph', + xaxis: { + buckets: null, + mode: 'time', + name: null, + show: true, + values: [], + }, + yaxes: [ + { + format: 'percent', + label: null, + logBase: 1, + max: null, + min: null, + show: true, + $$hashKey: 'object:122', + }, + { + format: 'gflops', + label: null, + logBase: 1, + max: null, + min: null, + show: true, + $$hashKey: 'object:123', + }, + ], + yaxis: { + align: false, + alignLevel: null, + }, + datasource: null, + } as Omit; + + const result = graphPanelMigrationHandler(panel as PanelModel); + const fieldSource = (panel as any).fieldConfig as FieldConfigSource; + + expect(result.dataLinks).toBeUndefined(); + expect(fieldSource.defaults.links).toHaveLength(1); + + const link = fieldSource.defaults.links[0]; + expect(link.url).toEqual('THE DRILLDOWN URL'); + }); +}); diff --git a/public/app/plugins/panel/graph/GraphMigrations.ts b/public/app/plugins/panel/graph/GraphMigrations.ts new file mode 100644 index 00000000000..207c324c74f --- /dev/null +++ b/public/app/plugins/panel/graph/GraphMigrations.ts @@ -0,0 +1,24 @@ +import { PanelModel, FieldConfigSource, DataLink } from '@grafana/data'; + +/** + * Called when upgrading from a previously saved versoin + */ +export const graphPanelMigrationHandler = (panel: PanelModel): Partial => { + const fieldOptions: FieldConfigSource = { + defaults: {}, + overrides: [], + }; + + const options = panel.options || {}; + + // Move <7.1 dataLinks to the field section + if (options.dataLinks) { + fieldOptions.defaults.links = options.dataLinks as DataLink[]; + delete options.dataLinks; + } + + // Mutate the original panel state (only necessary because it is angular) + panel.options = options; + panel.fieldConfig = fieldOptions; + return options; +}; diff --git a/public/app/plugins/panel/graph/module.ts b/public/app/plugins/panel/graph/module.ts index fe2f8a8d22d..53d5fa5873a 100644 --- a/public/app/plugins/panel/graph/module.ts +++ b/public/app/plugins/panel/graph/module.ts @@ -12,21 +12,21 @@ 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 { getColorFromHexRgbOrName, PanelEvents, DataFrame, DataLink, VariableSuggestion } from '@grafana/data'; +import { getColorFromHexRgbOrName, PanelEvents, PanelPlugin, DataFrame, FieldConfigProperty } from '@grafana/data'; import { GraphContextMenuCtrl } from './GraphContextMenuCtrl'; -import { getDataLinksVariableSuggestions } from 'app/features/panel/panellinks/link_srv'; +import { graphPanelMigrationHandler } from './GraphMigrations'; +import { DataWarning, GraphPanelOptions, GraphFieldConfig } from './types'; import { auto } from 'angular'; import { AnnotationsSrv } from 'app/features/annotations/all'; import { CoreEvents } from 'app/types'; -import { DataWarning } from './types'; import { getLocationSrv } from '@grafana/runtime'; import { getDataTimeRange } from './utils'; import { changePanelPlugin } from 'app/features/dashboard/state/actions'; import { dispatch } from 'app/store/store'; -class GraphCtrl extends MetricsPanelCtrl { +export class GraphCtrl extends MetricsPanelCtrl { static template = template; renderError: boolean; @@ -43,7 +43,6 @@ class GraphCtrl extends MetricsPanelCtrl { subTabIndex: number; processor: DataProcessor; contextMenuCtrl: GraphContextMenuCtrl; - linkVariableSuggestions: VariableSuggestion[] = []; panelDefaults: any = { // datasource name, null = default datasource @@ -136,9 +135,7 @@ class GraphCtrl extends MetricsPanelCtrl { seriesOverrides: [], thresholds: [], timeRegions: [], - options: { - dataLinks: [], - }, + options: {}, }; /** @ngInject */ @@ -161,7 +158,6 @@ class GraphCtrl extends MetricsPanelCtrl { this.events.on(PanelEvents.editModeInitialized, this.onInitEditMode.bind(this)); this.events.on(PanelEvents.initPanelActions, this.onInitPanelActions.bind(this)); - this.onDataLinksChange = this.onDataLinksChange.bind(this); this.annotationsPromise = Promise.resolve({ annotations: [] }); } @@ -172,7 +168,6 @@ class GraphCtrl extends MetricsPanelCtrl { this.addEditorTab('Legend', 'public/app/plugins/panel/graph/tab_legend.html'); this.addEditorTab('Thresholds', 'public/app/plugins/panel/graph/tab_thresholds.html'); this.addEditorTab('Time regions', 'public/app/plugins/panel/graph/tab_time_regions.html'); - this.addEditorTab('Data links', 'public/app/plugins/panel/graph/tab_drilldown_links.html'); this.subTabIndex = 0; this.hiddenSeriesTainted = false; } @@ -221,8 +216,6 @@ class GraphCtrl extends MetricsPanelCtrl { range: this.range, }); - this.linkVariableSuggestions = getDataLinksVariableSuggestions(data); - this.dataWarning = this.getDataWarning(); this.annotationsPromise.then( @@ -350,13 +343,6 @@ class GraphCtrl extends MetricsPanelCtrl { this.render(); }; - onDataLinksChange(dataLinks: DataLink[]) { - this.panel.updateOptions({ - ...this.panel.options, - dataLinks, - }); - } - addSeriesOverride(override: any) { this.panel.seriesOverrides.push(override || {}); } @@ -388,4 +374,15 @@ class GraphCtrl extends MetricsPanelCtrl { }; } -export { GraphCtrl, GraphCtrl as PanelCtrl }; +// Use new react style configuration +export const plugin = new PanelPlugin(null) + .useFieldConfig({ + standardOptions: [ + FieldConfigProperty.DisplayName, + FieldConfigProperty.Links, // previously saved as dataLinks on options + ], + }) + .setMigrationHandler(graphPanelMigrationHandler); + +// Use the angular ctrt rather than a react one +plugin.angularPanelCtrl = GraphCtrl; diff --git a/public/app/plugins/panel/graph/tab_drilldown_links.html b/public/app/plugins/panel/graph/tab_drilldown_links.html deleted file mode 100644 index 15d28ee8403..00000000000 --- a/public/app/plugins/panel/graph/tab_drilldown_links.html +++ /dev/null @@ -1,5 +0,0 @@ - diff --git a/public/app/plugins/panel/graph/types.ts b/public/app/plugins/panel/graph/types.ts index 5daa308f189..0b370c39f67 100644 --- a/public/app/plugins/panel/graph/types.ts +++ b/public/app/plugins/panel/graph/types.ts @@ -1,3 +1,11 @@ +export interface GraphPanelOptions { + // Panel level options +} + +export interface GraphFieldConfig { + // Custom field properties +} + export interface DataWarning { title: string; tip: string;