mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Merge pull request #16166 from ryantxu/drop-panel-plugin-setters
Refactor ReactPanelPlugin change hooks -> handler & add panel version to json
This commit is contained in:
@@ -21,27 +21,32 @@ export interface PanelEditorProps<T = any> {
|
|||||||
onOptionsChange: (options: T) => void;
|
onOptionsChange: (options: T) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface PanelModel<TOptions = any> {
|
||||||
|
id: number;
|
||||||
|
options: TOptions;
|
||||||
|
pluginVersion?: string;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when a panel is first loaded with existing options
|
* Called when a panel is first loaded with current panel model
|
||||||
*/
|
*/
|
||||||
export type PanelMigrationHook<TOptions = any> = (options: Partial<TOptions>) => Partial<TOptions>;
|
export type PanelMigrationHandler<TOptions = any> = (panel: PanelModel<TOptions>) => Partial<TOptions>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called before a panel is initalized
|
* Called before a panel is initalized
|
||||||
*/
|
*/
|
||||||
export type PanelTypeChangedHook<TOptions = any> = (
|
export type PanelTypeChangedHandler<TOptions = any> = (
|
||||||
options: Partial<TOptions>,
|
options: Partial<TOptions>,
|
||||||
prevPluginId: string,
|
prevPluginId: string,
|
||||||
prevOptions?: any
|
prevOptions: any
|
||||||
) => Partial<TOptions>;
|
) => Partial<TOptions>;
|
||||||
|
|
||||||
export class ReactPanelPlugin<TOptions = any> {
|
export class ReactPanelPlugin<TOptions = any> {
|
||||||
panel: ComponentClass<PanelProps<TOptions>>;
|
panel: ComponentClass<PanelProps<TOptions>>;
|
||||||
editor?: ComponentClass<PanelEditorProps<TOptions>>;
|
editor?: ComponentClass<PanelEditorProps<TOptions>>;
|
||||||
defaults?: TOptions;
|
defaults?: TOptions;
|
||||||
|
onPanelMigration?: PanelMigrationHandler<TOptions>;
|
||||||
panelMigrationHook?: PanelMigrationHook<TOptions>;
|
onPanelTypeChanged?: PanelTypeChangedHandler<TOptions>;
|
||||||
panelTypeChangedHook?: PanelTypeChangedHook<TOptions>;
|
|
||||||
|
|
||||||
constructor(panel: ComponentClass<PanelProps<TOptions>>) {
|
constructor(panel: ComponentClass<PanelProps<TOptions>>) {
|
||||||
this.panel = panel;
|
this.panel = panel;
|
||||||
@@ -49,25 +54,32 @@ export class ReactPanelPlugin<TOptions = any> {
|
|||||||
|
|
||||||
setEditor(editor: ComponentClass<PanelEditorProps<TOptions>>) {
|
setEditor(editor: ComponentClass<PanelEditorProps<TOptions>>) {
|
||||||
this.editor = editor;
|
this.editor = editor;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
setDefaults(defaults: TOptions) {
|
setDefaults(defaults: TOptions) {
|
||||||
this.defaults = defaults;
|
this.defaults = defaults;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the panel first loaded with
|
* This function is called before the panel first loads if
|
||||||
|
* the current version is different than the version that was saved.
|
||||||
|
*
|
||||||
|
* This is a good place to support any changes to the options model
|
||||||
*/
|
*/
|
||||||
setPanelMigrationHook(v: PanelMigrationHook<TOptions>) {
|
setMigrationHandler(handler: PanelMigrationHandler) {
|
||||||
this.panelMigrationHook = v;
|
this.onPanelMigration = handler;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the visualization changes.
|
* This function is called when the visualization was changed. This
|
||||||
* Lets you keep whatever settings made sense in the previous panel
|
* passes in the options that were used in the previous visualization
|
||||||
*/
|
*/
|
||||||
setPanelTypeChangedHook(v: PanelTypeChangedHook<TOptions>) {
|
setPanelChangeHandler(handler: PanelTypeChangedHandler) {
|
||||||
this.panelTypeChangedHook = v;
|
this.onPanelTypeChanged = handler;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ export interface PluginExports {
|
|||||||
|
|
||||||
// Panel plugin
|
// Panel plugin
|
||||||
PanelCtrl?: any;
|
PanelCtrl?: any;
|
||||||
reactPanel: ReactPanelPlugin;
|
reactPanel?: ReactPanelPlugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PluginMeta {
|
export interface PluginMeta {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { EventEmitter } from 'eventemitter3';
|
import { EventEmitter } from 'eventemitter3';
|
||||||
|
|
||||||
export class Emitter {
|
export class Emitter {
|
||||||
emitter: any;
|
private emitter: EventEmitter;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.emitter = new EventEmitter();
|
this.emitter = new EventEmitter();
|
||||||
@@ -29,4 +29,8 @@ export class Emitter {
|
|||||||
off(name, handler) {
|
off(name, handler) {
|
||||||
this.emitter.off(name, handler);
|
this.emitter.off(name, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getEventCount(): number {
|
||||||
|
return (this.emitter as any)._eventsCount;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import { PanelEditor } from '../panel_editor/PanelEditor';
|
|||||||
import { PanelModel, DashboardModel } from '../state';
|
import { PanelModel, DashboardModel } from '../state';
|
||||||
import { PanelPlugin } from 'app/types';
|
import { PanelPlugin } from 'app/types';
|
||||||
import { PanelResizer } from './PanelResizer';
|
import { PanelResizer } from './PanelResizer';
|
||||||
import { PanelTypeChangedHook } from '@grafana/ui';
|
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
panel: PanelModel;
|
panel: PanelModel;
|
||||||
@@ -71,9 +70,6 @@ export class DashboardPanel extends PureComponent<Props, State> {
|
|||||||
if (!this.state.plugin || this.state.plugin.id !== pluginId) {
|
if (!this.state.plugin || this.state.plugin.id !== pluginId) {
|
||||||
let plugin = config.panels[pluginId] || getPanelPluginNotFound(pluginId);
|
let plugin = config.panels[pluginId] || getPanelPluginNotFound(pluginId);
|
||||||
|
|
||||||
// remember if this is from an angular panel
|
|
||||||
const fromAngularPanel = this.state.angularPanel != null;
|
|
||||||
|
|
||||||
// unmount angular panel
|
// unmount angular panel
|
||||||
this.cleanUpAngularPanel();
|
this.cleanUpAngularPanel();
|
||||||
|
|
||||||
@@ -86,23 +82,9 @@ export class DashboardPanel extends PureComponent<Props, State> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (panel.type !== pluginId) {
|
if (panel.type !== pluginId) {
|
||||||
if (fromAngularPanel) {
|
panel.changePlugin(plugin);
|
||||||
// for angular panels only we need to remove all events and let angular panels do some cleanup
|
} else {
|
||||||
panel.destroy();
|
panel.pluginLoaded(plugin);
|
||||||
|
|
||||||
this.props.panel.changeType(pluginId);
|
|
||||||
} else {
|
|
||||||
let hook: PanelTypeChangedHook | null = null;
|
|
||||||
if (plugin.exports.reactPanel) {
|
|
||||||
hook = plugin.exports.reactPanel.panelTypeChangedHook;
|
|
||||||
}
|
|
||||||
panel.changeType(pluginId, hook);
|
|
||||||
}
|
|
||||||
} else if (plugin.exports && plugin.exports.reactPanel && panel.options) {
|
|
||||||
const hook = plugin.exports.reactPanel.panelMigrationHook;
|
|
||||||
if (hook) {
|
|
||||||
panel.options = hook(panel.options);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState({ plugin, angularPanel: null });
|
this.setState({ plugin, angularPanel: null });
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import { PanelModel } from './PanelModel';
|
import { PanelModel } from './PanelModel';
|
||||||
|
import { getPanelPlugin } from '../../plugins/__mocks__/pluginMocks';
|
||||||
|
import { ReactPanelPlugin } from '@grafana/ui/src/types/panel';
|
||||||
|
|
||||||
describe('PanelModel', () => {
|
describe('PanelModel', () => {
|
||||||
describe('when creating new panel model', () => {
|
describe('when creating new panel model', () => {
|
||||||
@@ -76,7 +78,7 @@ describe('PanelModel', () => {
|
|||||||
|
|
||||||
describe('when changing panel type', () => {
|
describe('when changing panel type', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
model.changeType('graph');
|
model.changePlugin(getPanelPlugin({ id: 'graph', exports: {} }));
|
||||||
model.alert = { id: 2 };
|
model.alert = { id: 2 };
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -85,16 +87,54 @@ describe('PanelModel', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should restore table properties when changing back', () => {
|
it('should restore table properties when changing back', () => {
|
||||||
model.changeType('table');
|
model.changePlugin(getPanelPlugin({ id: 'table', exports: {} }));
|
||||||
expect(model.showColumns).toBe(true);
|
expect(model.showColumns).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should remove alert rule when changing type that does not support it', () => {
|
it('should remove alert rule when changing type that does not support it', () => {
|
||||||
model.changeType('table');
|
model.changePlugin(getPanelPlugin({ id: 'table', exports: {} }));
|
||||||
expect(model.alert).toBe(undefined);
|
expect(model.alert).toBe(undefined);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('when changing from angular panel', () => {
|
||||||
|
let tearDownPublished = false;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
model.events.on('panel-teardown', () => {
|
||||||
|
tearDownPublished = true;
|
||||||
|
});
|
||||||
|
model.changePlugin(getPanelPlugin({ id: 'graph', exports: {} }));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should teardown / destroy panel so angular panels event subscriptions are removed', () => {
|
||||||
|
expect(tearDownPublished).toBe(true);
|
||||||
|
expect(model.events.getEventCount()).toBe(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when changing to react panel', () => {
|
||||||
|
const onPanelTypeChanged = jest.fn();
|
||||||
|
const reactPanel = new ReactPanelPlugin({} as any).setPanelChangeHandler(onPanelTypeChanged as any);
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
model.changePlugin(
|
||||||
|
getPanelPlugin({
|
||||||
|
id: 'react',
|
||||||
|
exports: {
|
||||||
|
reactPanel,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
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].thresholds).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('get panel options', () => {
|
describe('get panel options', () => {
|
||||||
it('should apply defaults', () => {
|
it('should apply defaults', () => {
|
||||||
model.options = { existingProp: 10 };
|
model.options = { existingProp: 10 };
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ import { Emitter } from 'app/core/utils/emitter';
|
|||||||
import { getNextRefIdChar } from 'app/core/utils/query';
|
import { getNextRefIdChar } from 'app/core/utils/query';
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
import { DataQuery, TimeSeries, Threshold, ScopedVars, PanelTypeChangedHook } from '@grafana/ui';
|
import { DataQuery, TimeSeries, Threshold, ScopedVars, TableData } from '@grafana/ui';
|
||||||
import { TableData } from '@grafana/ui/src';
|
import { PanelPlugin } from 'app/types';
|
||||||
|
|
||||||
export interface GridPos {
|
export interface GridPos {
|
||||||
x: number;
|
x: number;
|
||||||
@@ -23,6 +23,7 @@ const notPersistedProperties: { [str: string]: boolean } = {
|
|||||||
isEditing: true,
|
isEditing: true,
|
||||||
hasRefreshed: true,
|
hasRefreshed: true,
|
||||||
cachedPluginOptions: true,
|
cachedPluginOptions: true,
|
||||||
|
plugin: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
// For angular panels we need to clean up properties when changing type
|
// For angular panels we need to clean up properties when changing type
|
||||||
@@ -58,6 +59,7 @@ const mustKeepProps: { [str: string]: boolean } = {
|
|||||||
cacheTimeout: true,
|
cacheTimeout: true,
|
||||||
cachedPluginOptions: true,
|
cachedPluginOptions: true,
|
||||||
transparent: true,
|
transparent: true,
|
||||||
|
pluginVersion: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
const defaults: any = {
|
const defaults: any = {
|
||||||
@@ -87,6 +89,7 @@ export class PanelModel {
|
|||||||
targets: DataQuery[];
|
targets: DataQuery[];
|
||||||
datasource: string;
|
datasource: string;
|
||||||
thresholds?: any;
|
thresholds?: any;
|
||||||
|
pluginVersion?: string;
|
||||||
|
|
||||||
snapshotData?: TimeSeries[] | [TableData];
|
snapshotData?: TimeSeries[] | [TableData];
|
||||||
timeFrom?: any;
|
timeFrom?: any;
|
||||||
@@ -110,6 +113,7 @@ export class PanelModel {
|
|||||||
cacheTimeout?: any;
|
cacheTimeout?: any;
|
||||||
cachedPluginOptions?: any;
|
cachedPluginOptions?: any;
|
||||||
legend?: { show: boolean };
|
legend?: { show: boolean };
|
||||||
|
plugin?: PanelPlugin;
|
||||||
|
|
||||||
constructor(model: any) {
|
constructor(model: any) {
|
||||||
this.events = new Emitter();
|
this.events = new Emitter();
|
||||||
@@ -240,11 +244,27 @@ export class PanelModel {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
changeType(pluginId: string, hook?: PanelTypeChangedHook) {
|
pluginLoaded(plugin: PanelPlugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
|
||||||
|
const { reactPanel } = plugin.exports;
|
||||||
|
|
||||||
|
if (reactPanel && reactPanel.onPanelMigration) {
|
||||||
|
this.options = reactPanel.onPanelMigration(this);
|
||||||
|
this.pluginVersion = plugin.info ? plugin.info.version : '1.0.0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
changePlugin(newPlugin: PanelPlugin) {
|
||||||
|
const pluginId = newPlugin.id;
|
||||||
const oldOptions: any = this.getOptionsToRemember();
|
const oldOptions: any = this.getOptionsToRemember();
|
||||||
const oldPluginId = this.type;
|
const oldPluginId = this.type;
|
||||||
|
const reactPanel = newPlugin.exports.reactPanel;
|
||||||
|
|
||||||
this.type = pluginId;
|
// for angular panels we must remove all events and let angular panels do some cleanup
|
||||||
|
if (!reactPanel) {
|
||||||
|
this.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
// remove panel type specific options
|
// remove panel type specific options
|
||||||
for (const key of _.keys(this)) {
|
for (const key of _.keys(this)) {
|
||||||
@@ -258,12 +278,16 @@ export class PanelModel {
|
|||||||
this.cachedPluginOptions[oldPluginId] = oldOptions;
|
this.cachedPluginOptions[oldPluginId] = oldOptions;
|
||||||
this.restorePanelOptions(pluginId);
|
this.restorePanelOptions(pluginId);
|
||||||
|
|
||||||
// Callback that can validate and migrate any existing settings
|
// switch
|
||||||
if (hook) {
|
this.type = pluginId;
|
||||||
this.options = this.options || {};
|
this.plugin = newPlugin;
|
||||||
const old = oldOptions ? oldOptions.options : null;
|
|
||||||
|
|
||||||
Object.assign(this.options, hook(this.options, oldPluginId, old));
|
// Let panel plugins inspect options from previous panel and keep any that it can use
|
||||||
|
const onPanelTypeChanged = reactPanel ? reactPanel.onPanelTypeChanged : null;
|
||||||
|
if (onPanelTypeChanged) {
|
||||||
|
this.options = this.options || {};
|
||||||
|
const old = oldOptions ? oldOptions.options : {};
|
||||||
|
Object.assign(this.options, onPanelTypeChanged(this.options, oldPluginId, old));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ export const getMockPlugins = (amount: number): Plugin[] => {
|
|||||||
return plugins;
|
return plugins;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getPanelPlugin = (options: { id: string; sort?: number; hideFromList?: boolean }): PanelPlugin => {
|
export const getPanelPlugin = (options: Partial<PanelPlugin>): PanelPlugin => {
|
||||||
return {
|
return {
|
||||||
id: options.id,
|
id: options.id,
|
||||||
name: options.id,
|
name: options.id,
|
||||||
@@ -56,6 +56,7 @@ export const getPanelPlugin = (options: { id: string; sort?: number; hideFromLis
|
|||||||
hideFromList: options.hideFromList === true,
|
hideFromList: options.hideFromList === true,
|
||||||
module: '',
|
module: '',
|
||||||
baseUrl: '',
|
baseUrl: '',
|
||||||
|
exports: options.exports,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -5,8 +5,7 @@ import { BarGaugePanelEditor } from './BarGaugePanelEditor';
|
|||||||
import { BarGaugeOptions, defaults } from './types';
|
import { BarGaugeOptions, defaults } from './types';
|
||||||
import { singleStatBaseOptionsCheck } from '../singlestat2/module';
|
import { singleStatBaseOptionsCheck } from '../singlestat2/module';
|
||||||
|
|
||||||
export const reactPanel = new ReactPanelPlugin<BarGaugeOptions>(BarGaugePanel);
|
export const reactPanel = new ReactPanelPlugin<BarGaugeOptions>(BarGaugePanel)
|
||||||
|
.setDefaults(defaults)
|
||||||
reactPanel.setEditor(BarGaugePanelEditor);
|
.setEditor(BarGaugePanelEditor)
|
||||||
reactPanel.setDefaults(defaults);
|
.setPanelChangeHandler(singleStatBaseOptionsCheck);
|
||||||
reactPanel.setPanelTypeChangedHook(singleStatBaseOptionsCheck);
|
|
||||||
|
|||||||
@@ -3,10 +3,10 @@ import { ReactPanelPlugin } from '@grafana/ui';
|
|||||||
import { GaugePanelEditor } from './GaugePanelEditor';
|
import { GaugePanelEditor } from './GaugePanelEditor';
|
||||||
import { GaugePanel } from './GaugePanel';
|
import { GaugePanel } from './GaugePanel';
|
||||||
import { GaugeOptions, defaults } from './types';
|
import { GaugeOptions, defaults } from './types';
|
||||||
import { singleStatBaseOptionsCheck } from '../singlestat2/module';
|
import { singleStatBaseOptionsCheck, singleStatMigrationCheck } from '../singlestat2/module';
|
||||||
|
|
||||||
export const reactPanel = new ReactPanelPlugin<GaugeOptions>(GaugePanel);
|
export const reactPanel = new ReactPanelPlugin<GaugeOptions>(GaugePanel)
|
||||||
|
.setDefaults(defaults)
|
||||||
reactPanel.setEditor(GaugePanelEditor);
|
.setEditor(GaugePanelEditor)
|
||||||
reactPanel.setDefaults(defaults);
|
.setPanelChangeHandler(singleStatBaseOptionsCheck)
|
||||||
reactPanel.setPanelTypeChangedHook(singleStatBaseOptionsCheck);
|
.setMigrationHandler(singleStatMigrationCheck);
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
import { ReactPanelPlugin } from '@grafana/ui';
|
import { ReactPanelPlugin } from '@grafana/ui';
|
||||||
|
|
||||||
import { GraphPanelEditor } from './GraphPanelEditor';
|
import { GraphPanelEditor } from './GraphPanelEditor';
|
||||||
import { GraphPanel } from './GraphPanel';
|
import { GraphPanel } from './GraphPanel';
|
||||||
import { Options } from './types';
|
import { Options, defaults } from './types';
|
||||||
|
|
||||||
export const reactPanel = new ReactPanelPlugin<Options>(GraphPanel);
|
export const reactPanel = new ReactPanelPlugin<Options>(GraphPanel).setDefaults(defaults).setEditor(GraphPanelEditor);
|
||||||
reactPanel.setEditor(GraphPanelEditor);
|
|
||||||
|
|||||||
@@ -3,3 +3,9 @@ export interface Options {
|
|||||||
showLines: boolean;
|
showLines: boolean;
|
||||||
showPoints: boolean;
|
showPoints: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const defaults: Options = {
|
||||||
|
showBars: false,
|
||||||
|
showLines: true,
|
||||||
|
showPoints: false,
|
||||||
|
};
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { PieChartOptions } from './types';
|
|||||||
import { SingleStatValueEditor } from '../singlestat2/SingleStatValueEditor';
|
import { SingleStatValueEditor } from '../singlestat2/SingleStatValueEditor';
|
||||||
import { SingleStatValueOptions } from '../singlestat2/types';
|
import { SingleStatValueOptions } from '../singlestat2/types';
|
||||||
|
|
||||||
export default class PieChartPanelEditor extends PureComponent<PanelEditorProps<PieChartOptions>> {
|
export class PieChartPanelEditor extends PureComponent<PanelEditorProps<PieChartOptions>> {
|
||||||
onValueMappingsChanged = (valueMappings: ValueMapping[]) =>
|
onValueMappingsChanged = (valueMappings: ValueMapping[]) =>
|
||||||
this.props.onOptionsChange({
|
this.props.onOptionsChange({
|
||||||
...this.props.options,
|
...this.props.options,
|
||||||
|
|||||||
@@ -1,12 +1,8 @@
|
|||||||
import { ReactPanelPlugin } from '@grafana/ui';
|
import { ReactPanelPlugin } from '@grafana/ui';
|
||||||
|
import { PieChartPanelEditor } from './PieChartPanelEditor';
|
||||||
import PieChartPanelEditor from './PieChartPanelEditor';
|
|
||||||
import { PieChartPanel } from './PieChartPanel';
|
import { PieChartPanel } from './PieChartPanel';
|
||||||
import { PieChartOptions, defaults } from './types';
|
import { PieChartOptions, defaults } from './types';
|
||||||
import { singleStatBaseOptionsCheck } from '../singlestat2/module';
|
|
||||||
|
|
||||||
export const reactPanel = new ReactPanelPlugin<PieChartOptions>(PieChartPanel);
|
export const reactPanel = new ReactPanelPlugin<PieChartOptions>(PieChartPanel)
|
||||||
|
.setDefaults(defaults)
|
||||||
reactPanel.setEditor(PieChartPanelEditor);
|
.setEditor(PieChartPanelEditor);
|
||||||
reactPanel.setDefaults(defaults);
|
|
||||||
reactPanel.setPanelTypeChangedHook(singleStatBaseOptionsCheck);
|
|
||||||
|
|||||||
@@ -1,39 +1,39 @@
|
|||||||
import { ReactPanelPlugin, getStatsCalculators } from '@grafana/ui';
|
import { ReactPanelPlugin, getStatsCalculators, PanelModel } from '@grafana/ui';
|
||||||
import { SingleStatOptions, defaults, SingleStatBaseOptions } from './types';
|
import { SingleStatOptions, defaults, SingleStatBaseOptions } from './types';
|
||||||
import { SingleStatPanel } from './SingleStatPanel';
|
import { SingleStatPanel } from './SingleStatPanel';
|
||||||
import cloneDeep from 'lodash/cloneDeep';
|
import cloneDeep from 'lodash/cloneDeep';
|
||||||
import { SingleStatEditor } from './SingleStatEditor';
|
import { SingleStatEditor } from './SingleStatEditor';
|
||||||
|
|
||||||
export const reactPanel = new ReactPanelPlugin<SingleStatOptions>(SingleStatPanel);
|
|
||||||
|
|
||||||
const optionsToKeep = ['valueOptions', 'stat', 'maxValue', 'maxValue', 'thresholds', 'valueMappings'];
|
const optionsToKeep = ['valueOptions', 'stat', 'maxValue', 'maxValue', 'thresholds', 'valueMappings'];
|
||||||
|
|
||||||
export const singleStatBaseOptionsCheck = (
|
export const singleStatBaseOptionsCheck = (
|
||||||
options: Partial<SingleStatBaseOptions>,
|
options: Partial<SingleStatBaseOptions>,
|
||||||
prevPluginId: string,
|
prevPluginId: string,
|
||||||
prevOptions?: any
|
prevOptions: any
|
||||||
) => {
|
) => {
|
||||||
if (prevOptions) {
|
optionsToKeep.forEach(v => {
|
||||||
optionsToKeep.forEach(v => {
|
if (prevOptions.hasOwnProperty(v)) {
|
||||||
if (prevOptions.hasOwnProperty(v)) {
|
options[v] = cloneDeep(prevOptions.display);
|
||||||
options[v] = cloneDeep(prevOptions.display);
|
}
|
||||||
}
|
});
|
||||||
});
|
return options;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const singleStatMigrationCheck = (panel: PanelModel<SingleStatOptions>) => {
|
||||||
|
const options = panel.options;
|
||||||
|
if (options.valueOptions) {
|
||||||
|
// 6.1 renamed some stats, This makes sure they are up to date
|
||||||
|
// avg -> mean, current -> last, total -> sum
|
||||||
|
const { valueOptions } = options;
|
||||||
|
if (valueOptions && valueOptions.stat) {
|
||||||
|
valueOptions.stat = getStatsCalculators([valueOptions.stat]).map(s => s.id)[0];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return options;
|
return options;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const singleStatMigrationCheck = (options: Partial<SingleStatBaseOptions>) => {
|
export const reactPanel = new ReactPanelPlugin<SingleStatOptions>(SingleStatPanel)
|
||||||
// 6.1 renamed some stats, This makes sure they are up to date
|
.setDefaults(defaults)
|
||||||
// avg -> mean, current -> last, total -> sum
|
.setEditor(SingleStatEditor)
|
||||||
const { valueOptions } = options;
|
.setPanelChangeHandler(singleStatMigrationCheck)
|
||||||
if (valueOptions && valueOptions.stat) {
|
.setMigrationHandler(singleStatMigrationCheck);
|
||||||
valueOptions.stat = getStatsCalculators([valueOptions.stat]).map(s => s.id)[0];
|
|
||||||
}
|
|
||||||
return options;
|
|
||||||
};
|
|
||||||
|
|
||||||
reactPanel.setEditor(SingleStatEditor);
|
|
||||||
reactPanel.setDefaults(defaults);
|
|
||||||
reactPanel.setPanelTypeChangedHook(singleStatBaseOptionsCheck);
|
|
||||||
reactPanel.setPanelMigrationHook(singleStatMigrationCheck);
|
|
||||||
|
|||||||
@@ -4,6 +4,4 @@ import { TablePanelEditor } from './TablePanelEditor';
|
|||||||
import { TablePanel } from './TablePanel';
|
import { TablePanel } from './TablePanel';
|
||||||
import { Options, defaults } from './types';
|
import { Options, defaults } from './types';
|
||||||
|
|
||||||
export const reactPanel = new ReactPanelPlugin<Options>(TablePanel);
|
export const reactPanel = new ReactPanelPlugin<Options>(TablePanel).setDefaults(defaults).setEditor(TablePanelEditor);
|
||||||
reactPanel.setEditor(TablePanelEditor);
|
|
||||||
reactPanel.setDefaults(defaults);
|
|
||||||
|
|||||||
@@ -4,14 +4,12 @@ import { TextPanelEditor } from './TextPanelEditor';
|
|||||||
import { TextPanel } from './TextPanel';
|
import { TextPanel } from './TextPanel';
|
||||||
import { TextOptions, defaults } from './types';
|
import { TextOptions, defaults } from './types';
|
||||||
|
|
||||||
export const reactPanel = new ReactPanelPlugin<TextOptions>(TextPanel);
|
export const reactPanel = new ReactPanelPlugin<TextOptions>(TextPanel)
|
||||||
|
.setDefaults(defaults)
|
||||||
reactPanel.setEditor(TextPanelEditor);
|
.setEditor(TextPanelEditor)
|
||||||
reactPanel.setDefaults(defaults);
|
.setPanelChangeHandler((options: TextOptions, prevPluginId: string, prevOptions: any) => {
|
||||||
reactPanel.setPanelTypeChangedHook((options: TextOptions, prevPluginId: string, prevOptions: any) => {
|
if (prevPluginId === 'text') {
|
||||||
if (prevPluginId === 'text') {
|
return prevOptions as TextOptions;
|
||||||
return prevOptions as TextOptions;
|
}
|
||||||
}
|
return options;
|
||||||
|
});
|
||||||
return options;
|
|
||||||
});
|
|
||||||
|
|||||||
Reference in New Issue
Block a user