mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Dashboards: Unify angular auto-migration code (#63915)
This commit is contained in:
parent
f948482386
commit
36e8ca7f13
@ -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({
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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 });
|
||||
};
|
||||
|
43
yarn.lock
43
yarn.lock
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user