diff --git a/public/app/features/dashboard/dashgrid/DashboardPanel.tsx b/public/app/features/dashboard/dashgrid/DashboardPanel.tsx index c45d3c15bf0..3d2542d63c8 100644 --- a/public/app/features/dashboard/dashgrid/DashboardPanel.tsx +++ b/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 { +export interface State { + pluginExports: PluginExports; +} + +export class DashboardPanel extends React.Component { 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 { // 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 { } 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 ( diff --git a/public/app/features/panel/DataPanel.tsx b/public/app/features/dashboard/dashgrid/DataPanel.tsx similarity index 67% rename from public/app/features/panel/DataPanel.tsx rename to public/app/features/dashboard/dashgrid/DataPanel.tsx index a1669f6603d..251bd243b90 100644 --- a/public/app/features/panel/DataPanel.tsx +++ b/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 { +} + interface State { isLoading: boolean; data: any[]; } -const DataPanel = (ComposedComponent: ComponentClass) => { +export const DataPanelWrapper = (ComposedComponent: ComponentClass) => { class Wrapper extends Component { public static defaultProps = { isVisible: true, @@ -32,26 +34,31 @@ const DataPanel = (ComposedComponent: ComponentClass) = } 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) = return Wrapper; }; -export default DataPanel; diff --git a/public/app/features/dashboard/dashgrid/PanelChrome.tsx b/public/app/features/dashboard/dashgrid/PanelChrome.tsx index 3fd9df799af..ebe25379c2d 100644 --- a/public/app/features/dashboard/dashgrid/PanelChrome.tsx +++ b/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; } -export class PanelChrome extends React.Component { +interface State { + height: number; +} + +export class PanelChrome extends React.Component { + panelComponent: DataPanel; + constructor(props) { super(props); - this.props.panel.events.on('panel-size-changed', this.triggerForceUpdate.bind(this)); - } - - triggerForceUpdate() { - this.forceUpdate(); - } - - render() { - let panelContentStyle = { + this.state = { height: this.getPanelHeight(), }; - let PanelComponent = this.props.component; + this.panelComponent = DataPanelWrapper(this.props.component); + this.props.panel.events.on('panel-size-changed', this.onPanelSizeChanged); + } + + onPanelSizeChanged = () => { + this.setState({ + height: this.getPanelHeight(), + }); + }; + + componentDidMount() { + console.log('panel chrome mounted'); + } + + render() { + let PanelComponent = this.panelComponent; return (
-
- {} +
+ {}
{this.props.panel.isEditing && } diff --git a/public/app/features/plugins/plugin_loader.ts b/public/app/features/plugins/plugin_loader.ts index f999ee7e2ff..ffcd36312fb 100644 --- a/public/app/features/plugins/plugin_loader.ts +++ b/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 { +export interface PluginExports { + PanelCtrl?; + any; + PanelComponent?: any; + Datasource?: any; + QueryCtrl?: any; + ConfigCtrl?: any; + AnnotationsQueryCtrl?: any; +} + +export function importPluginModule(path: string): Promise { let builtIn = builtInPlugins[path]; if (builtIn) { return Promise.resolve(builtIn); diff --git a/public/app/plugins/panel/text2/module.tsx b/public/app/plugins/panel/text2/module.tsx index 8987b738f0b..019cf912340 100644 --- a/public/app/plugins/panel/text2/module.tsx +++ b/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 { +export class ReactTestPanel extends PureComponent { constructor(props) { super(props); } render() { - return

I am a react panel, haha!

; + const { data } = this.props; + let value = 0; + + if (data.length) { + value = data[0].value; + } + + return

I am a react value: {value}

; } }