mirror of
https://github.com/grafana/grafana.git
synced 2025-02-11 16:15:42 -06:00
Plugins: Allow async panel migrations (#73782)
* Plugins: Allow async panel migrations * comment
This commit is contained in:
parent
7543a28ae2
commit
f95405d3c3
@ -135,9 +135,12 @@ export interface PanelEditorProps<T = any> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a panel is first loaded with current panel model
|
||||
* Called when a panel is first loaded with current panel model to migrate panel options if needed.
|
||||
* Can return panel options, or a Promise that resolves to panel options for async migrations
|
||||
*/
|
||||
export type PanelMigrationHandler<TOptions = any> = (panel: PanelModel<TOptions>) => Partial<TOptions>;
|
||||
export type PanelMigrationHandler<TOptions = any> = (
|
||||
panel: PanelModel<TOptions>
|
||||
) => Partial<TOptions> | Promise<Partial<TOptions>>;
|
||||
|
||||
/**
|
||||
* Called before a panel is initialized. Allows panel inspection for any updates before changing the panel type.
|
||||
|
@ -132,14 +132,14 @@ describe('DashboardPrompt', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('Should ignore panel schema migrations', () => {
|
||||
it('Should ignore panel schema migrations', async () => {
|
||||
const { original, dash } = getTestContext();
|
||||
const plugin = getPanelPlugin({}).setMigrationHandler((panel) => {
|
||||
delete (panel as any).legend;
|
||||
return { option1: 'Aasd' };
|
||||
});
|
||||
|
||||
dash.panels[0].pluginLoaded(plugin);
|
||||
await dash.panels[0].pluginLoaded(plugin);
|
||||
expect(hasChanges(dash, original)).toBe(false);
|
||||
});
|
||||
|
||||
|
@ -8,6 +8,7 @@ import {
|
||||
standardFieldConfigEditorRegistry,
|
||||
dateTime,
|
||||
TimeRange,
|
||||
PanelMigrationHandler,
|
||||
} from '@grafana/data';
|
||||
import { getPanelPlugin } from '@grafana/data/test/__mocks__/pluginMocks';
|
||||
import { mockStandardFieldConfigOptions } from '@grafana/data/test/helpers/fieldConfig';
|
||||
@ -80,7 +81,7 @@ describe('PanelModel', () => {
|
||||
},
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
beforeEach(async () => {
|
||||
persistedOptionsMock = {
|
||||
fieldOptions: {
|
||||
thresholds: [
|
||||
@ -141,7 +142,44 @@ describe('PanelModel', () => {
|
||||
};
|
||||
|
||||
model = new PanelModel(modelJson);
|
||||
model.pluginLoaded(tablePlugin);
|
||||
await model.pluginLoaded(tablePlugin);
|
||||
});
|
||||
|
||||
describe('migrations', () => {
|
||||
let initialMigrator: PanelMigrationHandler<(typeof model)['options']> | undefined = undefined;
|
||||
|
||||
beforeEach(() => {
|
||||
initialMigrator = tablePlugin.onPanelMigration;
|
||||
});
|
||||
afterEach(() => {
|
||||
tablePlugin.onPanelMigration = initialMigrator;
|
||||
});
|
||||
|
||||
it('should run sync migrations', async () => {
|
||||
model.options.valueToMigrate = 'old-legacy';
|
||||
|
||||
tablePlugin.onPanelMigration = (p) => ({ ...p.options, valueToMigrate: 'new-version' });
|
||||
|
||||
tablePlugin.onPanelMigration = (p) => {
|
||||
p.options.valueToMigrate = 'new-version';
|
||||
return p.options;
|
||||
};
|
||||
|
||||
await model.pluginLoaded(tablePlugin);
|
||||
expect(model.options).toMatchObject({ valueToMigrate: 'new-version' });
|
||||
});
|
||||
|
||||
it('should run async migrations', async () => {
|
||||
model.options.valueToMigrate = 'old-legacy';
|
||||
|
||||
tablePlugin.onPanelMigration = async (p) =>
|
||||
new Promise((resolve) => {
|
||||
setTimeout(() => resolve({ ...p.options, valueToMigrate: 'new-version' }), 10);
|
||||
});
|
||||
|
||||
await model.pluginLoaded(tablePlugin);
|
||||
expect(model.options).toMatchObject({ valueToMigrate: 'new-version' });
|
||||
});
|
||||
});
|
||||
|
||||
it('should apply defaults', () => {
|
||||
|
@ -429,7 +429,7 @@ export class PanelModel implements DataConfigSource, IPanelModel {
|
||||
this.options = options.options;
|
||||
}
|
||||
|
||||
pluginLoaded(plugin: PanelPlugin) {
|
||||
async pluginLoaded(plugin: PanelPlugin) {
|
||||
this.plugin = plugin;
|
||||
|
||||
const version = getPluginVersion(plugin);
|
||||
@ -451,7 +451,8 @@ export class PanelModel implements DataConfigSource, IPanelModel {
|
||||
|
||||
if (plugin.onPanelMigration) {
|
||||
if (version !== this.pluginVersion) {
|
||||
this.options = plugin.onPanelMigration(this);
|
||||
const newPanelOptions = plugin.onPanelMigration(this);
|
||||
this.options = await newPanelOptions;
|
||||
this.pluginVersion = version;
|
||||
}
|
||||
}
|
||||
|
@ -83,9 +83,9 @@ describe('applyPanelTimeOverrides', () => {
|
||||
expect(height).toBe(82);
|
||||
});
|
||||
|
||||
it('Calculate panel height with panel plugin zeroChromePadding', () => {
|
||||
it('Calculate panel height with panel plugin zeroChromePadding', async () => {
|
||||
const panelModel = new PanelModel({});
|
||||
panelModel.pluginLoaded(
|
||||
await panelModel.pluginLoaded(
|
||||
getPanelPlugin({ id: 'table' }, null as unknown as ComponentClass<PanelProps>, null).setNoPadding()
|
||||
);
|
||||
|
||||
|
@ -30,7 +30,7 @@ export function initPanelState(panel: PanelModel): ThunkResult<Promise<void>> {
|
||||
}
|
||||
|
||||
if (!panel.plugin) {
|
||||
panel.pluginLoaded(plugin);
|
||||
await panel.pluginLoaded(plugin);
|
||||
}
|
||||
|
||||
dispatch(panelModelAndPluginReady({ key: panel.key, plugin }));
|
||||
@ -120,7 +120,7 @@ export function changeToLibraryPanel(panel: PanelModel, libraryPanel: LibraryEle
|
||||
plugin = await dispatch(loadPanelPlugin(newPluginId));
|
||||
}
|
||||
|
||||
panel.pluginLoaded(plugin);
|
||||
await panel.pluginLoaded(plugin);
|
||||
panel.generateNewKey();
|
||||
|
||||
await dispatch(panelModelAndPluginReady({ key: panel.key, plugin }));
|
||||
|
Loading…
Reference in New Issue
Block a user