瀏覽代碼

react-panels: minor progress on data flow

Torkel Ödegaard 7 年之前
父節點
當前提交
c86fc6fb47

+ 15 - 10
public/app/features/dashboard/dashgrid/DashboardPanel.tsx

@@ -5,24 +5,27 @@ import { DashboardModel } from '../dashboard_model';
 import { getAngularLoader, AngularComponent } from 'app/core/services/angular_loader';
 import { DashboardRow } from './DashboardRow';
 import { AddPanelPanel } from './AddPanelPanel';
-import { importPluginModule } from 'app/features/plugins/plugin_loader';
+import { importPluginModule, PluginExports } from 'app/features/plugins/plugin_loader';
 import { PanelChrome } from './PanelChrome';
 
-export interface DashboardPanelProps {
+export interface Props {
   panel: PanelModel;
   dashboard: DashboardModel;
 }
 
-export class DashboardPanel extends React.Component<DashboardPanelProps, any> {
+export interface State {
+  pluginExports: PluginExports;
+}
+
+export class DashboardPanel extends React.Component<Props, State> {
   element: any;
   angularPanel: AngularComponent;
   pluginInfo: any;
-  pluginExports: any;
   specialPanels = {};
 
   constructor(props) {
     super(props);
-    this.state = {};
+    this.state = { pluginExports: null };
 
     this.specialPanels['row'] = this.renderRow.bind(this);
     this.specialPanels['add-panel'] = this.renderAddPanel.bind(this);
@@ -32,8 +35,7 @@ export class DashboardPanel extends React.Component<DashboardPanelProps, any> {
 
       // load panel plugin
       importPluginModule(this.pluginInfo.module).then(pluginExports => {
-        this.pluginExports = pluginExports;
-        this.forceUpdate();
+        this.setState({ pluginExports: pluginExports });
       });
     }
   }
@@ -70,18 +72,21 @@ export class DashboardPanel extends React.Component<DashboardPanelProps, any> {
   }
 
   render() {
+    const { pluginExports } = this.state;
+
     if (this.isSpecial()) {
       return this.specialPanels[this.props.panel.type]();
     }
 
-    if (!this.pluginExports) {
+    if (!pluginExports) {
       return null;
     }
 
-    if (this.pluginExports.PanelComponent) {
+    if (pluginExports.PanelComponent) {
       return (
         <PanelChrome
-          component={this.pluginExports.PanelComponent}
+          key="asd"
+          component={pluginExports.PanelComponent}
           panel={this.props.panel}
           dashboard={this.props.dashboard}
         />

+ 17 - 11
public/app/features/panel/DataPanel.tsx → public/app/features/dashboard/dashgrid/DataPanel.tsx

@@ -1,5 +1,4 @@
 import React, { Component, ComponentClass } from 'react';
-import _ from 'lodash';
 
 export interface OuterProps {
   type: string;
@@ -7,16 +6,19 @@ export interface OuterProps {
   isVisible: boolean;
 }
 
-export interface AddedProps {
+export interface PanelProps extends OuterProps {
   data: any[];
 }
 
+export interface DataPanel extends ComponentClass<OuterProps> {
+}
+
 interface State {
   isLoading: boolean;
   data: any[];
 }
 
-const DataPanel = (ComposedComponent: ComponentClass<AddedProps & OuterProps>) => {
+export const DataPanelWrapper = (ComposedComponent: ComponentClass<PanelProps>) => {
   class Wrapper extends Component<OuterProps, State> {
     public static defaultProps = {
       isVisible: true,
@@ -32,26 +34,31 @@ const DataPanel = (ComposedComponent: ComponentClass<AddedProps & OuterProps>) =
     }
 
     public componentDidMount() {
+      console.log('data panel mount');
       this.issueQueries();
     }
 
-    public issueQueries = () => {
-      const { queries, isVisible } = this.props;
+    public issueQueries = async () => {
+      const { isVisible } = this.props;
 
       if (!isVisible) {
         return;
       }
 
-      if (!queries.length) {
-        this.setState({ data: [{ message: 'no queries' }] });
-        return;
-      }
-
       this.setState({ isLoading: true });
+
+      await new Promise(resolve => {
+        setTimeout(() => {
+
+          this.setState({ isLoading: false, data: [{value: 10}] });
+
+        }, 500);
+      });
     };
 
     public render() {
       const { data, isLoading } = this.state;
+      console.log('data panel render');
 
       if (!data.length) {
         return (
@@ -76,4 +83,3 @@ const DataPanel = (ComposedComponent: ComponentClass<AddedProps & OuterProps>) =
   return Wrapper;
 };
 
-export default DataPanel;

+ 27 - 13
public/app/features/dashboard/dashgrid/PanelChrome.tsx

@@ -1,10 +1,11 @@
-import React from 'react';
+import React, { ComponentClass } from 'react';
 import $ from 'jquery';
 import { PanelModel } from '../panel_model';
 import { DashboardModel } from '../dashboard_model';
 import { GRID_CELL_HEIGHT, GRID_CELL_VMARGIN } from 'app/core/constants';
 import { PanelHeader } from './PanelHeader';
 import { PanelEditor } from './PanelEditor';
+import { DataPanel, PanelProps, DataPanelWrapper } from './DataPanel';
 
 const TITLE_HEIGHT = 27;
 const PANEL_BORDER = 2;
@@ -12,33 +13,46 @@ const PANEL_BORDER = 2;
 export interface Props {
   panel: PanelModel;
   dashboard: DashboardModel;
-  component: any;
+  component: ComponentClass<PanelProps>;
 }
 
-export class PanelChrome extends React.Component<Props, any> {
+interface State {
+  height: number;
+}
+
+export class PanelChrome extends React.Component<Props, State> {
+  panelComponent: DataPanel;
+
   constructor(props) {
     super(props);
 
-    this.props.panel.events.on('panel-size-changed', this.triggerForceUpdate.bind(this));
-  }
+    this.state = {
+      height: this.getPanelHeight(),
+    };
 
-  triggerForceUpdate() {
-    this.forceUpdate();
+    this.panelComponent = DataPanelWrapper(this.props.component);
+    this.props.panel.events.on('panel-size-changed', this.onPanelSizeChanged);
   }
 
-  render() {
-    let panelContentStyle = {
+  onPanelSizeChanged = () => {
+    this.setState({
       height: this.getPanelHeight(),
-    };
+    });
+  };
 
-    let PanelComponent = this.props.component;
+  componentDidMount() {
+    console.log('panel chrome mounted');
+  }
+
+  render() {
+    let PanelComponent = this.panelComponent;
 
     return (
       <div className="panel-height-helper">
         <div className="panel-container">
           <PanelHeader panel={this.props.panel} dashboard={this.props.dashboard} />
-          <div className="panel-content" style={panelContentStyle}>
-            {<PanelComponent />}
+          <div className="panel-content" style={{ height: this.state.height }}>
+            {<PanelComponent type={'test'} queries={[]} isVisible={true} />}
           </div>
         </div>
         {this.props.panel.isEditing && <PanelEditor panel={this.props.panel} dashboard={this.props.dashboard} />}

+ 12 - 1
public/app/features/plugins/plugin_loader.ts

@@ -138,11 +138,22 @@ const flotDeps = [
   'jquery.flot.stackpercent',
   'jquery.flot.events',
 ];
+
 for (let flotDep of flotDeps) {
   exposeToPlugin(flotDep, { fakeDep: 1 });
 }
 
-export function importPluginModule(path: string): Promise<any> {
+export interface PluginExports {
+  PanelCtrl?;
+  any;
+  PanelComponent?: any;
+  Datasource?: any;
+  QueryCtrl?: any;
+  ConfigCtrl?: any;
+  AnnotationsQueryCtrl?: any;
+}
+
+export function importPluginModule(path: string): Promise<PluginExports> {
   let builtIn = builtInPlugins[path];
   if (builtIn) {
     return Promise.resolve(builtIn);

+ 11 - 3
public/app/plugins/panel/text2/module.tsx

@@ -1,12 +1,20 @@
-import React from 'react';
+import React, { PureComponent } from 'react';
+import { PanelProps } from 'app/features/dashboard/dashgrid/DataPanel';
 
-export class ReactTestPanel extends React.Component<any, any> {
+export class ReactTestPanel extends PureComponent<PanelProps> {
   constructor(props) {
     super(props);
   }
 
   render() {
-    return <h2>I am a react panel, haha!</h2>;
+    const { data } = this.props;
+    let value = 0;
+
+    if (data.length) {
+      value = data[0].value;
+    }
+
+    return <h2>I am a react value: {value}</h2>;
   }
 }