ryan 6 лет назад
Родитель
Сommit
75022ebd63

+ 14 - 20
packages/grafana-ui/src/types/panel.ts

@@ -27,26 +27,20 @@ export interface PanelEditorProps<T = any> {
 }
 
 /**
- * This function is called with the full panelModel before
- * 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
+ * Called before a panel is initalized
  */
-export type PanelOptionsValidator<T = any> = (panelModel: any) => T;
-
-export type PreservePanelOptionsHandler<TOptions = any> = (pluginId: string, prevOptions: any) => Partial<TOptions>;
+export type PanelTypeChangedHook<TOptions = any> = (
+  options: TOptions,
+  prevPluginId?: string,
+  prevOptions?: any
+) => TOptions;
 
 export class ReactPanelPlugin<TOptions = any> {
   panel: ComponentClass<PanelProps<TOptions>>;
   editor?: ComponentClass<PanelEditorProps<TOptions>>;
-  optionsValidator?: PanelOptionsValidator<TOptions>;
   defaults?: TOptions;
-  preserveOptions?: PreservePanelOptionsHandler<TOptions>;
+
+  panelTypeChangedHook?: PanelTypeChangedHook<TOptions>;
 
   constructor(panel: ComponentClass<PanelProps<TOptions>>) {
     this.panel = panel;
@@ -56,16 +50,16 @@ export class ReactPanelPlugin<TOptions = any> {
     this.editor = editor;
   }
 
-  setOptionsValidator(validator: PanelOptionsValidator<TOptions>) {
-    this.optionsValidator = validator;
-  }
-
   setDefaults(defaults: TOptions) {
     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;
   }
 }
 

+ 1 - 4
public/app/features/dashboard/dashgrid/DashboardPanel.tsx

@@ -92,10 +92,7 @@ export class DashboardPanel extends PureComponent<Props, State> {
           this.props.panel.changeType(pluginId);
         } else {
           const { reactPanel } = plugin.exports;
-          panel.changeType(pluginId, reactPanel.preserveOptions);
-          if (reactPanel && reactPanel.optionsValidator) {
-            panel.options = reactPanel.optionsValidator(panel);
-          }
+          panel.changeType(pluginId, reactPanel.panelTypeChangedHook);
         }
       }
 

+ 5 - 5
public/app/features/dashboard/state/PanelModel.ts

@@ -3,7 +3,7 @@ import _ from 'lodash';
 
 // Types
 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';
 
 export interface GridPos {
@@ -237,7 +237,7 @@ export class PanelModel {
     });
   }
 
-  changeType(pluginId: string, preserveOptions?: any) {
+  changeType(pluginId: string, hook?: PanelTypeChangedHook) {
     const oldOptions: any = this.getOptionsToRemember();
     const oldPluginId = this.type;
 
@@ -255,9 +255,9 @@ export class PanelModel {
     this.cachedPluginOptions[oldPluginId] = oldOptions;
     this.restorePanelOptions(pluginId);
 
-    if (preserveOptions && oldOptions) {
-      this.options = this.options || {};
-      Object.assign(this.options, preserveOptions(oldPluginId, oldOptions.options));
+    // Callback that can validate and migrate any existing settings
+    if (hook) {
+      Object.assign(this.options, hook(this.options || {}, oldPluginId, oldOptions.options));
     }
   }
 

+ 1 - 3
public/app/plugins/panel/bargauge/module.tsx

@@ -8,9 +8,7 @@ export const reactPanel = new ReactPanelPlugin<BarGaugeOptions>(BarGaugePanel);
 
 reactPanel.setEditor(BarGaugePanelEditor);
 reactPanel.setDefaults(defaults);
-reactPanel.setPreserveOptionsHandler((pluginId: string, prevOptions: any) => {
-  const options: Partial<BarGaugeOptions> = {};
-
+reactPanel.setPanelTypeChangedHook((options: BarGaugeOptions, prevPluginId: string, prevOptions: any) => {
   if (prevOptions.valueOptions) {
     options.valueOptions = prevOptions.valueOptions;
     options.thresholds = prevOptions.thresholds;

+ 1 - 3
public/app/plugins/panel/gauge/module.tsx

@@ -8,9 +8,7 @@ export const reactPanel = new ReactPanelPlugin<GaugeOptions>(GaugePanel);
 
 reactPanel.setEditor(GaugePanelEditor);
 reactPanel.setDefaults(defaults);
-reactPanel.setPreserveOptionsHandler((pluginId: string, prevOptions: any) => {
-  const options: Partial<GaugeOptions> = {};
-
+reactPanel.setPanelTypeChangedHook((options: GaugeOptions, prevPluginId: string, prevOptions: any) => {
   if (prevOptions.valueOptions) {
     options.valueOptions = prevOptions.valueOptions;
     options.thresholds = prevOptions.thresholds;

+ 7 - 14
public/app/plugins/panel/text2/module.tsx

@@ -3,22 +3,15 @@ import { ReactPanelPlugin } from '@grafana/ui';
 import { TextPanelEditor } from './TextPanelEditor';
 import { TextPanel } from './TextPanel';
 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);
 
-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.setDefaults(defaults);
-reactPanel.setOptionsValidator(validator);
+reactPanel.setPanelTypeChangedHook((options: TextOptions, prevPluginId: string, prevOptions: any) => {
+  if (prevPluginId === 'text') {
+    return prevOptions as TextOptions;
+  }
+
+  return options;
+});