Commit 75022ebd by ryan

single hook

parent b933c57c
...@@ -27,26 +27,20 @@ export interface PanelEditorProps<T = any> { ...@@ -27,26 +27,20 @@ export interface PanelEditorProps<T = any> {
} }
/** /**
* This function is called with the full panelModel before * Called before a panel is initalized
* the pluginPanel is constructed. This gives you an opportunity
* to validate the panel settings before the panel loads.
*
* @param panelModel the whole panel object. including the configuration
* saved for other panels
*
* @returns the validated panel options that will be passed into the
* panel constructor
*/ */
export type PanelOptionsValidator<T = any> = (panelModel: any) => T; export type PanelTypeChangedHook<TOptions = any> = (
options: TOptions,
export type PreservePanelOptionsHandler<TOptions = any> = (pluginId: string, prevOptions: any) => Partial<TOptions>; prevPluginId?: string,
prevOptions?: any
) => 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>>;
optionsValidator?: PanelOptionsValidator<TOptions>;
defaults?: TOptions; defaults?: TOptions;
preserveOptions?: PreservePanelOptionsHandler<TOptions>;
panelTypeChangedHook?: PanelTypeChangedHook<TOptions>;
constructor(panel: ComponentClass<PanelProps<TOptions>>) { constructor(panel: ComponentClass<PanelProps<TOptions>>) {
this.panel = panel; this.panel = panel;
...@@ -56,16 +50,16 @@ export class ReactPanelPlugin<TOptions = any> { ...@@ -56,16 +50,16 @@ export class ReactPanelPlugin<TOptions = any> {
this.editor = editor; this.editor = editor;
} }
setOptionsValidator(validator: PanelOptionsValidator<TOptions>) {
this.optionsValidator = validator;
}
setDefaults(defaults: TOptions) { setDefaults(defaults: TOptions) {
this.defaults = defaults; this.defaults = defaults;
} }
setPreserveOptionsHandler(handler: PreservePanelOptionsHandler<TOptions>) { /**
this.preserveOptions = handler; * Called when the visualization changes.
* Lets you keep whatever settings made sense in the previous panel
*/
setPanelTypeChangedHook(v: PanelTypeChangedHook<TOptions>) {
this.panelTypeChangedHook = v;
} }
} }
......
...@@ -92,10 +92,7 @@ export class DashboardPanel extends PureComponent<Props, State> { ...@@ -92,10 +92,7 @@ export class DashboardPanel extends PureComponent<Props, State> {
this.props.panel.changeType(pluginId); this.props.panel.changeType(pluginId);
} else { } else {
const { reactPanel } = plugin.exports; const { reactPanel } = plugin.exports;
panel.changeType(pluginId, reactPanel.preserveOptions); panel.changeType(pluginId, reactPanel.panelTypeChangedHook);
if (reactPanel && reactPanel.optionsValidator) {
panel.options = reactPanel.optionsValidator(panel);
}
} }
} }
......
...@@ -3,7 +3,7 @@ import _ from 'lodash'; ...@@ -3,7 +3,7 @@ import _ from 'lodash';
// Types // Types
import { Emitter } from 'app/core/utils/emitter'; import { Emitter } from 'app/core/utils/emitter';
import { DataQuery, TimeSeries, Threshold, ScopedVars } from '@grafana/ui'; import { DataQuery, TimeSeries, Threshold, ScopedVars, PanelTypeChangedHook } from '@grafana/ui';
import { TableData } from '@grafana/ui/src'; import { TableData } from '@grafana/ui/src';
export interface GridPos { export interface GridPos {
...@@ -237,7 +237,7 @@ export class PanelModel { ...@@ -237,7 +237,7 @@ export class PanelModel {
}); });
} }
changeType(pluginId: string, preserveOptions?: any) { changeType(pluginId: string, hook?: PanelTypeChangedHook) {
const oldOptions: any = this.getOptionsToRemember(); const oldOptions: any = this.getOptionsToRemember();
const oldPluginId = this.type; const oldPluginId = this.type;
...@@ -255,9 +255,9 @@ export class PanelModel { ...@@ -255,9 +255,9 @@ export class PanelModel {
this.cachedPluginOptions[oldPluginId] = oldOptions; this.cachedPluginOptions[oldPluginId] = oldOptions;
this.restorePanelOptions(pluginId); this.restorePanelOptions(pluginId);
if (preserveOptions && oldOptions) { // Callback that can validate and migrate any existing settings
this.options = this.options || {}; if (hook) {
Object.assign(this.options, preserveOptions(oldPluginId, oldOptions.options)); Object.assign(this.options, hook(this.options || {}, oldPluginId, oldOptions.options));
} }
} }
......
...@@ -8,9 +8,7 @@ export const reactPanel = new ReactPanelPlugin<BarGaugeOptions>(BarGaugePanel); ...@@ -8,9 +8,7 @@ export const reactPanel = new ReactPanelPlugin<BarGaugeOptions>(BarGaugePanel);
reactPanel.setEditor(BarGaugePanelEditor); reactPanel.setEditor(BarGaugePanelEditor);
reactPanel.setDefaults(defaults); reactPanel.setDefaults(defaults);
reactPanel.setPreserveOptionsHandler((pluginId: string, prevOptions: any) => { reactPanel.setPanelTypeChangedHook((options: BarGaugeOptions, prevPluginId: string, prevOptions: any) => {
const options: Partial<BarGaugeOptions> = {};
if (prevOptions.valueOptions) { if (prevOptions.valueOptions) {
options.valueOptions = prevOptions.valueOptions; options.valueOptions = prevOptions.valueOptions;
options.thresholds = prevOptions.thresholds; options.thresholds = prevOptions.thresholds;
......
...@@ -8,9 +8,7 @@ export const reactPanel = new ReactPanelPlugin<GaugeOptions>(GaugePanel); ...@@ -8,9 +8,7 @@ export const reactPanel = new ReactPanelPlugin<GaugeOptions>(GaugePanel);
reactPanel.setEditor(GaugePanelEditor); reactPanel.setEditor(GaugePanelEditor);
reactPanel.setDefaults(defaults); reactPanel.setDefaults(defaults);
reactPanel.setPreserveOptionsHandler((pluginId: string, prevOptions: any) => { reactPanel.setPanelTypeChangedHook((options: GaugeOptions, prevPluginId: string, prevOptions: any) => {
const options: Partial<GaugeOptions> = {};
if (prevOptions.valueOptions) { if (prevOptions.valueOptions) {
options.valueOptions = prevOptions.valueOptions; options.valueOptions = prevOptions.valueOptions;
options.thresholds = prevOptions.thresholds; options.thresholds = prevOptions.thresholds;
......
...@@ -3,22 +3,15 @@ import { ReactPanelPlugin } from '@grafana/ui'; ...@@ -3,22 +3,15 @@ import { ReactPanelPlugin } from '@grafana/ui';
import { TextPanelEditor } from './TextPanelEditor'; import { TextPanelEditor } from './TextPanelEditor';
import { TextPanel } from './TextPanel'; import { TextPanel } from './TextPanel';
import { TextOptions, defaults } from './types'; import { TextOptions, defaults } from './types';
import { PanelModel } from 'app/features/dashboard/state';
import get from 'lodash/get';
import cloneDeep from 'lodash/cloneDeep';
export const reactPanel = new ReactPanelPlugin<TextOptions>(TextPanel); export const reactPanel = new ReactPanelPlugin<TextOptions>(TextPanel);
const validator = (model: PanelModel): TextOptions => {
const options = model.options as TextOptions;
if (!options) {
// Use the same settings from an existing 'text' panel
return cloneDeep(get(model, 'cachedPluginOptions.text'));
}
return options;
};
reactPanel.setEditor(TextPanelEditor); reactPanel.setEditor(TextPanelEditor);
reactPanel.setDefaults(defaults); reactPanel.setDefaults(defaults);
reactPanel.setOptionsValidator(validator); reactPanel.setPanelTypeChangedHook((options: TextOptions, prevPluginId: string, prevOptions: any) => {
if (prevPluginId === 'text') {
return prevOptions as TextOptions;
}
return options;
});
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment