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 { 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}
/>

View File

@ -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;

View File

@ -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));
}
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 (
<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} />}

View File

@ -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);

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) {
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>;
}
}