react-panels: minor progress on data flow

This commit is contained in:
Torkel Ödegaard
2018-07-05 13:10:39 -07:00
parent 447bc3a6e0
commit c86fc6fb47
5 changed files with 84 additions and 40 deletions

View File

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

View File

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

View File

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

View File

@@ -138,11 +138,22 @@ const flotDeps = [
'jquery.flot.stackpercent', 'jquery.flot.stackpercent',
'jquery.flot.events', 'jquery.flot.events',
]; ];
for (let flotDep of flotDeps) { for (let flotDep of flotDeps) {
exposeToPlugin(flotDep, { fakeDep: 1 }); 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]; let builtIn = builtInPlugins[path];
if (builtIn) { if (builtIn) {
return Promise.resolve(builtIn); return Promise.resolve(builtIn);

View File

@@ -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) { constructor(props) {
super(props); super(props);
} }
render() { 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>;
} }
} }