Dashboards: Unify angular auto-migration code (#63915)

This commit is contained in:
Ryan McKinley 2023-03-27 08:11:45 -07:00 committed by GitHub
parent f948482386
commit 36e8ca7f13
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 68 additions and 81 deletions

View File

@ -85,7 +85,9 @@ it('handles a default datasource in a template variable', async () => {
],
},
};
const dashboardModel = new DashboardModel(dashboard, {}, () => dashboard.templating.list);
const dashboardModel = new DashboardModel(dashboard, undefined, {
getVariablesFromState: () => dashboard.templating.list,
});
const exporter = new DashboardExporter();
const exported: any = await exporter.makeExportable(dashboardModel);
expect(exported.templating.list[0].datasource.uid).toBe('${DS_GFDB}');
@ -105,7 +107,9 @@ it('If a panel queries has no datasource prop ignore it', async () => {
},
],
};
const dashboardModel = new DashboardModel(dashboard, {}, () => []);
const dashboardModel = new DashboardModel(dashboard, undefined, {
getVariablesFromState: () => [],
});
const exporter = new DashboardExporter();
const exported: any = await exporter.makeExportable(dashboardModel);
expect(exported.panels[0].datasource).toEqual({ uid: '${DS_OTHER}', type: 'other' });
@ -230,7 +234,13 @@ describe('given dashboard with repeated panels', () => {
info: { version: '1.1.2' },
} as PanelPluginMeta;
dash = new DashboardModel(dash, {}, () => dash.templating.list);
dash = new DashboardModel(
dash,
{},
{
getVariablesFromState: () => dash.templating.list,
}
);
// init library panels
dash.getPanelById(17).initLibraryPanel({

View File

@ -16,7 +16,7 @@ import {
TimeZone,
UrlQueryValue,
} from '@grafana/data';
import { RefreshEvent, TimeRangeUpdatedEvent } from '@grafana/runtime';
import { RefreshEvent, TimeRangeUpdatedEvent, config } from '@grafana/runtime';
import { Dashboard } from '@grafana/schema';
import { DEFAULT_ANNOTATION_COLOR } from '@grafana/ui';
import { GRID_CELL_HEIGHT, GRID_CELL_VMARGIN, GRID_COLUMN_COUNT, REPEAT_DIR_VERTICAL } from 'app/core/constants';
@ -41,7 +41,7 @@ import { getTimeSrv } from '../services/TimeSrv';
import { mergePanels, PanelMergeInfo } from '../utils/panelMerge';
import { DashboardMigrator } from './DashboardMigrator';
import { GridPos, PanelModel } from './PanelModel';
import { GridPos, PanelModel, autoMigrateAngular } from './PanelModel';
import { TimeModel } from './TimeModel';
import { deleteScopeVars, isOnTheSameGridRow } from './utils';
@ -108,6 +108,7 @@ export class DashboardModel implements TimeModel {
// repeat process cycles
declare meta: DashboardMeta;
events: EventBusExtended;
private getVariablesFromState: GetVariables;
static nonPersistedProperties: { [str: string]: boolean } = {
events: true,
@ -126,7 +127,18 @@ export class DashboardModel implements TimeModel {
lastRefresh: true,
};
constructor(data: Dashboard, meta?: DashboardMeta, private getVariablesFromState: GetVariables = getVariablesByKey) {
constructor(
data: Dashboard,
meta?: DashboardMeta,
options?: {
// By default this uses variables from redux state
getVariablesFromState?: GetVariables;
// Force the loader to migrate panels
autoMigrateOldPanels?: boolean;
}
) {
this.getVariablesFromState = options?.getVariablesFromState ?? getVariablesByKey;
this.events = new EventBusSrv();
this.id = data.id || null;
// UID is not there for newly created dashboards
@ -162,6 +174,17 @@ export class DashboardModel implements TimeModel {
this.initMeta(meta);
this.updateSchema(data);
// Auto-migrate old angular panels
if (options?.autoMigrateOldPanels || !config.angularSupportEnabled || config.featureToggles.autoMigrateOldPanels) {
this.panels.forEach((p) => {
const newType = autoMigrateAngular[p.type];
if (!p.autoMigrateFrom && newType) {
p.autoMigrateFrom = p.type;
p.type = newType;
}
});
}
this.addBuiltInAnnotationQuery();
this.sortPanelsByGridPos();
this.panelsAffectedByVariableChange = null;

View File

@ -132,6 +132,19 @@ const defaults: any = {
title: '',
};
export const autoMigrateAngular: Record<string, string> = {
graph: 'timeseries',
'table-old': 'table',
singlestat: 'stat', // also automigrated if dashboard schemaVerion < 27
'grafana-singlestat-panel': 'stat',
'grafana-piechart-panel': 'piechart',
'grafana-worldmap-panel': 'geomap',
};
const autoMigratePanelType: Record<string, string> = {
'heatmap-new': 'heatmap', // this was a temporary development panel that is now standard
};
export class PanelModel implements DataConfigSource, IPanelModel {
/* persisted id, used in URL to identify a panel */
id!: number;
@ -235,23 +248,10 @@ export class PanelModel implements DataConfigSource, IPanelModel {
(this as any)[property] = model[property];
}
switch (this.type) {
case 'graph':
if (config.featureToggles?.autoMigrateOldPanels || !config.angularSupportEnabled) {
this.autoMigrateFrom = this.type;
this.type = 'timeseries';
}
break;
case 'table-old':
if (config.featureToggles?.autoMigrateOldPanels || !config.angularSupportEnabled) {
this.autoMigrateFrom = this.type;
this.type = 'table';
}
break;
case 'heatmap-new':
this.autoMigrateFrom = this.type;
this.type = 'heatmap';
break;
const newType = autoMigratePanelType[this.type];
if (newType) {
this.autoMigrateFrom = this.type;
this.type = newType;
}
// defaults
@ -427,7 +427,7 @@ export class PanelModel implements DataConfigSource, IPanelModel {
const version = getPluginVersion(plugin);
if (this.autoMigrateFrom) {
const wasAngular = this.autoMigrateFrom === 'graph' || this.autoMigrateFrom === 'table-old';
const wasAngular = autoMigrateAngular[this.autoMigrateFrom] != null;
this.callPanelTypeChangeHandler(
plugin,
this.autoMigrateFrom,

View File

@ -27,7 +27,7 @@ export function createDashboardModelFixture(
...dashboardInput,
};
return new DashboardModel(dashboardJson, meta, getVariablesFromState);
return new DashboardModel(dashboardJson, meta, { getVariablesFromState });
}
export function createPanelJSONFixture(panelInput: Partial<Panel | GraphPanel | RowPanel> = {}): Panel {

View File

@ -25,7 +25,6 @@ import {
import { StateManagerBase } from 'app/core/services/StateManagerBase';
import { dashboardLoaderSrv } from 'app/features/dashboard/services/DashboardLoaderSrv';
import { DashboardModel, PanelModel } from 'app/features/dashboard/state';
import { graphToTimeseriesOptions } from 'app/plugins/panel/timeseries/migrations';
import { DashboardDTO } from 'app/types';
import { DashboardScene } from './DashboardScene';
@ -63,7 +62,9 @@ export class DashboardLoader extends StateManagerBase<DashboardLoaderState> {
private initDashboard(rsp: DashboardDTO) {
// Just to have migrations run
const oldModel = new DashboardModel(rsp.dashboard, rsp.meta);
const oldModel = new DashboardModel(rsp.dashboard, rsp.meta, {
autoMigrateOldPanels: true,
});
const dashboard = createDashboardSceneFromDashboardModel(oldModel);
@ -262,14 +263,6 @@ export function createVizPanelFromPanelModel(panel: PanelModel) {
maxDataPoints: panel.maxDataPoints ?? undefined,
});
// Migrate graph to timeseries
if (panel.type === 'graph') {
const { fieldConfig, options } = graphToTimeseriesOptions(panel);
panel.fieldConfig = fieldConfig;
panel.options = options;
panel.type = 'timeseries';
}
return new VizPanel({
title: panel.title,
pluginId: panel.type,

View File

@ -60,13 +60,13 @@ describe('PieChart -> PieChartV2 migrations', () => {
expect(options).toMatchObject({ displayLabels: [PieChartLabels.Name, PieChartLabels.Value] });
});
it('hides the legend when no legend values are selected', () => {
it('hides the legend when show is false', () => {
const panel = { options: {} } as PanelModel;
const oldPieChartOptions = {
angular: {
legendType: 'On graph',
legend: {},
legend: { show: false },
},
};
const options = PieChartPanelChangedHandler(panel, 'grafana-piechart-panel', oldPieChartOptions);

View File

@ -102,10 +102,6 @@ export const PieChartPanelChangedHandler = (
if (angular.legend.percentage) {
options.legend.values.push(PieChartLegendValues.Percent);
}
if (!angular.legend.percentage && !angular.legend.values) {
// If you deselect both value and percentage in the old pie chart plugin, the legend is hidden.
options.legend.showLegend = false;
}
}
// Set up labels when the old piechart is using 'on graph', for the legend option.

View File

@ -3,5 +3,5 @@ import { DashboardMeta } from '../../app/types/dashboard';
export const getDashboardModel = (json: any, meta: DashboardMeta = {}) => {
const getVariablesFromState = () => json.templating.list;
return new DashboardModel(json, meta, getVariablesFromState);
return new DashboardModel(json, meta, { getVariablesFromState });
};

View File

@ -15644,45 +15644,10 @@ __metadata:
languageName: node
linkType: hard
"caniuse-lite@npm:^1.0.0, caniuse-lite@npm:^1.0.30001271, caniuse-lite@npm:^1.0.30001286, caniuse-lite@npm:^1.0.30001317":
version: 1.0.30001332
resolution: "caniuse-lite@npm:1.0.30001332"
checksum: e54182ea42ab3d2ff1440f9a6480292f7ab23c00c188df7ad65586312e4da567e8bedd5cb5fb8f0ff4193dc027a54e17e0b3c0b6db5d5a3fb61c7726ff9c45b3
languageName: node
linkType: hard
"caniuse-lite@npm:^1.0.30001109, caniuse-lite@npm:^1.0.30001449":
version: 1.0.30001467
resolution: "caniuse-lite@npm:1.0.30001467"
checksum: c7df36ddb8050fb366a4bedd278f4b639c1dde94b6ba62bacf960f26d488395632a0630b7932ebc52d3d04b57940d12dcb4a7d3bb744ff64c249b61fb3e0c238
languageName: node
linkType: hard
"caniuse-lite@npm:^1.0.30001332":
version: 1.0.30001335
resolution: "caniuse-lite@npm:1.0.30001335"
checksum: fe08b49ec6cb76cc69958ff001cf89d0a8ef9f35e0c8028b65981585046384f76e007d64dea372a34ca56d91caa83cc614c00779fe2b4d378aa0e68696374f67
languageName: node
linkType: hard
"caniuse-lite@npm:^1.0.30001335":
version: 1.0.30001341
resolution: "caniuse-lite@npm:1.0.30001341"
checksum: 7262b093fb0bf49dbc5328418f5ce4e3dbb0b13e39c015f986ba1807634c123ac214efc94df7d095a336f57f86852b4b63ee61838f18dcc3a4a35f87b390c8f5
languageName: node
linkType: hard
"caniuse-lite@npm:^1.0.30001400":
version: 1.0.30001402
resolution: "caniuse-lite@npm:1.0.30001402"
checksum: 6068ccccd64b357f75388cb2303cf351b686b20800571d0a845bff5c0e0d24f83df0133afbbdd8177a33eb087c93d39ecf359035a52b2feac5f182c946f706ee
languageName: node
linkType: hard
"caniuse-lite@npm:^1.0.30001426":
version: 1.0.30001429
resolution: "caniuse-lite@npm:1.0.30001429"
checksum: d1658080248ef5ef0f5157423b2766026e6aa45642ce3b2cc74859b6a54e39881dd902397a2368324ed30ed0cd40250f11a4a4f3773453cd57b88db5e5e5c76a
"caniuse-lite@npm:^1.0.0, caniuse-lite@npm:^1.0.30001109, caniuse-lite@npm:^1.0.30001271, caniuse-lite@npm:^1.0.30001286, caniuse-lite@npm:^1.0.30001317, caniuse-lite@npm:^1.0.30001332, caniuse-lite@npm:^1.0.30001335, caniuse-lite@npm:^1.0.30001400, caniuse-lite@npm:^1.0.30001426, caniuse-lite@npm:^1.0.30001449":
version: 1.0.30001469
resolution: "caniuse-lite@npm:1.0.30001469"
checksum: 8e496509d7e9ff189c72205675b5db0c5f1b6a09917027441e835efae0848a468a8c4e7d2b409ffc202438fcd23ae53e017f976a03c22c04d12d3c0e1e33e5de
languageName: node
linkType: hard