Kaynağa Gözat

Added a ReactPanelPlugin as the interface that react panels export, this way react panels have clearer api, and gives us hooks to handle migrations and a way for panel to handle panel changes in the future

Torkel Ödegaard 6 yıl önce
ebeveyn
işleme
074073787d

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

@@ -1,3 +1,4 @@
+import { ComponentClass } from 'react';
 import { TimeSeries, LoadingState, TableData } from './data';
 import { TimeSeries, LoadingState, TableData } from './data';
 import { TimeRange } from './time';
 import { TimeRange } from './time';
 
 
@@ -19,11 +20,29 @@ export interface PanelData {
   tableData?: TableData;
   tableData?: TableData;
 }
 }
 
 
-export interface PanelOptionsProps<T = any> {
+export interface PanelEditorProps<T = any> {
   options: T;
   options: T;
   onChange: (options: T) => void;
   onChange: (options: T) => void;
 }
 }
 
 
+export class ReactPanelPlugin<TOptions = any> {
+  panel: ComponentClass<PanelProps<TOptions>>;
+  editor?: ComponentClass<PanelEditorProps<TOptions>>;
+  defaults?: TOptions;
+
+  constructor(panel: ComponentClass<PanelProps<TOptions>>) {
+    this.panel = panel;
+  }
+
+  setEditor(editor: ComponentClass<PanelEditorProps<TOptions>>) {
+    this.editor = editor;
+  }
+
+  setDefaults(defaults: TOptions) {
+    this.defaults = defaults;
+  }
+}
+
 export interface PanelSize {
 export interface PanelSize {
   width: number;
   width: number;
   height: number;
   height: number;

+ 2 - 4
packages/grafana-ui/src/types/plugin.ts

@@ -1,5 +1,5 @@
 import { ComponentClass } from 'react';
 import { ComponentClass } from 'react';
-import { PanelProps, PanelOptionsProps } from './panel';
+import { ReactPanelPlugin } from './panel';
 import { DataQueryOptions, DataQuery, DataQueryResponse, QueryHint, QueryFixAction } from './datasource';
 import { DataQueryOptions, DataQuery, DataQueryResponse, QueryHint, QueryFixAction } from './datasource';
 
 
 export interface DataSourceApi<TQuery extends DataQuery = DataQuery> {
 export interface DataSourceApi<TQuery extends DataQuery = DataQuery> {
@@ -81,9 +81,7 @@ export interface PluginExports {
 
 
   // Panel plugin
   // Panel plugin
   PanelCtrl?: any;
   PanelCtrl?: any;
-  Panel?: ComponentClass<PanelProps>;
-  PanelOptions?: ComponentClass<PanelOptionsProps>;
-  PanelDefaults?: any;
+  reactPanel: ReactPanelPlugin;
 }
 }
 
 
 export interface PluginMeta {
 export interface PluginMeta {

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

@@ -173,7 +173,7 @@ export class DashboardPanel extends PureComponent<Props, State> {
               onMouseLeave={this.onMouseLeave}
               onMouseLeave={this.onMouseLeave}
               style={styles}
               style={styles}
             >
             >
-              {plugin.exports.Panel && this.renderReactPanel()}
+              {plugin.exports.reactPanel && this.renderReactPanel()}
               {plugin.exports.PanelCtrl && this.renderAngularPanel()}
               {plugin.exports.PanelCtrl && this.renderAngularPanel()}
             </div>
             </div>
           )}
           )}

+ 2 - 2
public/app/features/dashboard/dashgrid/PanelChrome.tsx

@@ -139,7 +139,7 @@ export class PanelChrome extends PureComponent<Props, State> {
   renderPanelPlugin(loading: LoadingState, panelData: PanelData, width: number, height: number): JSX.Element {
   renderPanelPlugin(loading: LoadingState, panelData: PanelData, width: number, height: number): JSX.Element {
     const { panel, plugin } = this.props;
     const { panel, plugin } = this.props;
     const { timeRange, renderCounter } = this.state;
     const { timeRange, renderCounter } = this.state;
-    const PanelComponent = plugin.exports.Panel;
+    const PanelComponent = plugin.exports.reactPanel.panel;
 
 
     // This is only done to increase a counter that is used by backend
     // This is only done to increase a counter that is used by backend
     // image rendering (phantomjs/headless chrome) to know when to capture image
     // image rendering (phantomjs/headless chrome) to know when to capture image
@@ -153,7 +153,7 @@ export class PanelChrome extends PureComponent<Props, State> {
           loading={loading}
           loading={loading}
           panelData={panelData}
           panelData={panelData}
           timeRange={timeRange}
           timeRange={timeRange}
-          options={panel.getOptions(plugin.exports.PanelDefaults)}
+          options={panel.getOptions(plugin.exports.reactPanel.defaults)}
           width={width - 2 * variables.panelhorizontalpadding}
           width={width - 2 * variables.panelhorizontalpadding}
           height={height - PANEL_HEADER_HEIGHT - variables.panelverticalpadding}
           height={height - PANEL_HEADER_HEIGHT - variables.panelverticalpadding}
           renderCounter={renderCounter}
           renderCounter={renderCounter}

+ 2 - 2
public/app/features/dashboard/dashgrid/PanelPluginNotFound.tsx

@@ -3,7 +3,7 @@ import _ from 'lodash';
 import React, { PureComponent } from 'react';
 import React, { PureComponent } from 'react';
 
 
 // Types
 // Types
-import { PanelProps } from '@grafana/ui';
+import { PanelProps, ReactPanelPlugin } from '@grafana/ui';
 import { PanelPlugin } from 'app/types';
 import { PanelPlugin } from 'app/types';
 
 
 interface Props {
 interface Props {
@@ -63,7 +63,7 @@ export function getPanelPluginNotFound(id: string): PanelPlugin {
     },
     },
 
 
     exports: {
     exports: {
-      Panel: NotFound,
+      reactPanel: new ReactPanelPlugin(NotFound),
     },
     },
   };
   };
 }
 }

+ 11 - 17
public/app/features/dashboard/panel_editor/VisualizationTab.tsx

@@ -50,33 +50,27 @@ export class VisualizationTab extends PureComponent<Props, State> {
     };
     };
   }
   }
 
 
-  getPanelDefaultOptions = () => {
+  getReactPanelOptions = () => {
     const { panel, plugin } = this.props;
     const { panel, plugin } = this.props;
-
-    if (plugin.exports.PanelDefaults) {
-      return panel.getOptions(plugin.exports.PanelDefaults.options);
-    }
-
-    return panel.getOptions(plugin.exports.PanelDefaults);
+    return panel.getOptions(plugin.exports.reactPanel.defaults);
   };
   };
 
 
   renderPanelOptions() {
   renderPanelOptions() {
     const { plugin, angularPanel } = this.props;
     const { plugin, angularPanel } = this.props;
-    const { PanelOptions } = plugin.exports;
 
 
     if (angularPanel) {
     if (angularPanel) {
       return <div ref={element => (this.element = element)} />;
       return <div ref={element => (this.element = element)} />;
     }
     }
 
 
-    return (
-      <>
-        {PanelOptions ? (
-          <PanelOptions options={this.getPanelDefaultOptions()} onChange={this.onPanelOptionsChanged} />
-        ) : (
-          <p>Visualization has no options</p>
-        )}
-      </>
-    );
+    if (plugin.exports.reactPanel) {
+      const PanelEditor = plugin.exports.reactPanel.editor;
+
+      if (PanelEditor) {
+        return <PanelEditor options={this.getReactPanelOptions()} onChange={this.onPanelOptionsChanged} />;
+      }
+    }
+
+    return <p>Visualization has no options</p>;
   }
   }
 
 
   componentDidMount() {
   componentDidMount() {

+ 7 - 2
public/app/plugins/panel/gauge/GaugeOptionsEditor.tsx → public/app/plugins/panel/gauge/GaugeOptionsBox.tsx

@@ -1,9 +1,14 @@
+// Libraries
 import React, { PureComponent } from 'react';
 import React, { PureComponent } from 'react';
-import { FormField, PanelOptionsProps, PanelOptionsGroup, Switch } from '@grafana/ui';
 
 
+// Components
+import { Switch, PanelOptionsGroup } from '@grafana/ui';
+
+// Types
+import { FormField, PanelEditorProps } from '@grafana/ui';
 import { GaugeOptions } from './types';
 import { GaugeOptions } from './types';
 
 
-export default class GaugeOptionsEditor extends PureComponent<PanelOptionsProps<GaugeOptions>> {
+export class GaugeOptionsBox extends PureComponent<PanelEditorProps<GaugeOptions>> {
   onToggleThresholdLabels = () =>
   onToggleThresholdLabels = () =>
     this.props.onChange({ ...this.props.options, showThresholdLabels: !this.props.options.showThresholdLabels });
     this.props.onChange({ ...this.props.options, showThresholdLabels: !this.props.options.showThresholdLabels });
 
 

+ 5 - 23
public/app/plugins/panel/gauge/GaugePanelOptions.tsx → public/app/plugins/panel/gauge/GaugePanelEditor.tsx

@@ -1,6 +1,6 @@
 import React, { PureComponent } from 'react';
 import React, { PureComponent } from 'react';
 import {
 import {
-  PanelOptionsProps,
+  PanelEditorProps,
   ThresholdsEditor,
   ThresholdsEditor,
   Threshold,
   Threshold,
   PanelOptionsGrid,
   PanelOptionsGrid,
@@ -8,29 +8,11 @@ import {
   ValueMapping,
   ValueMapping,
 } from '@grafana/ui';
 } from '@grafana/ui';
 
 
-import ValueOptions from 'app/plugins/panel/gauge/ValueOptions';
-import GaugeOptionsEditor from './GaugeOptionsEditor';
+import { ValueOptions } from 'app/plugins/panel/gauge/ValueOptions';
+import { GaugeOptionsBox } from './GaugeOptionsBox';
 import { GaugeOptions } from './types';
 import { GaugeOptions } from './types';
 
 
-export const defaultProps = {
-  options: {
-    minValue: 0,
-    maxValue: 100,
-    prefix: '',
-    showThresholdMarkers: true,
-    showThresholdLabels: false,
-    suffix: '',
-    decimals: 0,
-    stat: 'avg',
-    unit: 'none',
-    valueMappings: [],
-    thresholds: [],
-  },
-};
-
-export default class GaugePanelOptions extends PureComponent<PanelOptionsProps<GaugeOptions>> {
-  static defaultProps = defaultProps;
-
+export class GaugePanelEditor extends PureComponent<PanelEditorProps<GaugeOptions>> {
   onThresholdsChanged = (thresholds: Threshold[]) =>
   onThresholdsChanged = (thresholds: Threshold[]) =>
     this.props.onChange({
     this.props.onChange({
       ...this.props.options,
       ...this.props.options,
@@ -50,7 +32,7 @@ export default class GaugePanelOptions extends PureComponent<PanelOptionsProps<G
       <>
       <>
         <PanelOptionsGrid>
         <PanelOptionsGrid>
           <ValueOptions onChange={onChange} options={options} />
           <ValueOptions onChange={onChange} options={options} />
-          <GaugeOptionsEditor onChange={onChange} options={options} />
+          <GaugeOptionsBox onChange={onChange} options={options} />
           <ThresholdsEditor onChange={this.onThresholdsChanged} thresholds={options.thresholds} />
           <ThresholdsEditor onChange={this.onThresholdsChanged} thresholds={options.thresholds} />
         </PanelOptionsGrid>
         </PanelOptionsGrid>
 
 

+ 8 - 2
public/app/plugins/panel/gauge/ValueOptions.tsx

@@ -1,7 +1,13 @@
+// Libraries
 import React, { PureComponent } from 'react';
 import React, { PureComponent } from 'react';
-import { FormField, FormLabel, PanelOptionsProps, PanelOptionsGroup, Select } from '@grafana/ui';
+
+// Components
 import UnitPicker from 'app/core/components/Select/UnitPicker';
 import UnitPicker from 'app/core/components/Select/UnitPicker';
+import { FormField, FormLabel, PanelOptionsGroup, Select } from '@grafana/ui';
+
+// Types
 import { GaugeOptions } from './types';
 import { GaugeOptions } from './types';
+import { PanelEditorProps } from '@grafana/ui';
 
 
 const statOptions = [
 const statOptions = [
   { value: 'min', label: 'Min' },
   { value: 'min', label: 'Min' },
@@ -19,7 +25,7 @@ const statOptions = [
 
 
 const labelWidth = 6;
 const labelWidth = 6;
 
 
-export default class ValueOptions extends PureComponent<PanelOptionsProps<GaugeOptions>> {
+export class ValueOptions extends PureComponent<PanelEditorProps<GaugeOptions>> {
   onUnitChange = unit => this.props.onChange({ ...this.props.options, unit: unit.value });
   onUnitChange = unit => this.props.onChange({ ...this.props.options, unit: unit.value });
 
 
   onStatChange = stat => this.props.onChange({ ...this.props.options, stat: stat.value });
   onStatChange = stat => this.props.onChange({ ...this.props.options, stat: stat.value });

+ 8 - 2
public/app/plugins/panel/gauge/module.tsx

@@ -1,4 +1,10 @@
-import GaugePanelOptions, { defaultProps } from './GaugePanelOptions';
+import { ReactPanelPlugin } from '@grafana/ui';
+
+import { GaugePanelEditor } from './GaugePanelEditor';
 import { GaugePanel } from './GaugePanel';
 import { GaugePanel } from './GaugePanel';
+import { GaugeOptions, defaults } from './types';
+
+export const reactPanel = new ReactPanelPlugin<GaugeOptions>(GaugePanel);
 
 
-export { GaugePanel as Panel, GaugePanelOptions as PanelOptions, defaultProps as PanelDefaults };
+reactPanel.setEditor(GaugePanelEditor);
+reactPanel.setDefaults(defaults);

+ 14 - 0
public/app/plugins/panel/gauge/types.ts

@@ -13,3 +13,17 @@ export interface GaugeOptions {
   thresholds: Threshold[];
   thresholds: Threshold[];
   unit: string;
   unit: string;
 }
 }
+
+export const defaults: GaugeOptions = {
+  minValue: 0,
+  maxValue: 100,
+  prefix: '',
+  showThresholdMarkers: true,
+  showThresholdLabels: false,
+  suffix: '',
+  decimals: 0,
+  stat: 'avg',
+  unit: 'none',
+  valueMappings: [],
+  thresholds: [],
+};

+ 2 - 2
public/app/plugins/panel/graph2/GraphPanelOptions.tsx → public/app/plugins/panel/graph2/GraphPanelEditor.tsx

@@ -3,10 +3,10 @@ import _ from 'lodash';
 import React, { PureComponent } from 'react';
 import React, { PureComponent } from 'react';
 
 
 // Types
 // Types
-import { PanelOptionsProps, Switch } from '@grafana/ui';
+import { PanelEditorProps, Switch } from '@grafana/ui';
 import { Options } from './types';
 import { Options } from './types';
 
 
-export class GraphPanelOptions extends PureComponent<PanelOptionsProps<Options>> {
+export class GraphPanelEditor extends PureComponent<PanelEditorProps<Options>> {
   onToggleLines = () => {
   onToggleLines = () => {
     this.props.onChange({ ...this.props.options, showLines: !this.props.options.showLines });
     this.props.onChange({ ...this.props.options, showLines: !this.props.options.showLines });
   };
   };

+ 2 - 2
public/app/plugins/panel/graph2/module.tsx

@@ -1,4 +1,4 @@
 import { GraphPanel } from './GraphPanel';
 import { GraphPanel } from './GraphPanel';
-import { GraphPanelOptions } from './GraphPanelOptions';
+import { GraphPanelEditor } from './GraphPanelEditor';
 
 
-export { GraphPanel as Panel, GraphPanelOptions as PanelOptions };
+export { GraphPanel as Panel, GraphPanelEditor as PanelOptions };

+ 2 - 2
public/app/plugins/panel/text2/module.tsx

@@ -1,5 +1,5 @@
 import React, { PureComponent } from 'react';
 import React, { PureComponent } from 'react';
-import { PanelProps } from '@grafana/ui';
+import { PanelProps, ReactPanelPlugin } from '@grafana/ui';
 
 
 export class Text2 extends PureComponent<PanelProps> {
 export class Text2 extends PureComponent<PanelProps> {
   constructor(props: PanelProps) {
   constructor(props: PanelProps) {
@@ -11,4 +11,4 @@ export class Text2 extends PureComponent<PanelProps> {
   }
   }
 }
 }
 
 
-export { Text2 as Panel };
+export const reactPanel = new ReactPanelPlugin(Text2);