Commit 2e1d45a8 by Torkel Ödegaard

changed DataPanel from HOC to use render props

parent 0662b5f9
......@@ -9,7 +9,7 @@ import Drop from 'tether-drop';
import colors from 'app/core/utils/colors';
import { BackendSrv, setBackendSrv } from 'app/core/services/backend_srv';
import { DatasourceSrv } from 'app/features/plugins/datasource_srv';
import { AngularLoader, setAngularLoader } from 'app/core/services/angular_loader';
import { AngularLoader, setAngularLoader } from 'app/core/services/AngularLoader';
import { configureStore } from 'app/store/configureStore';
export class GrafanaCtrl {
......
import angular from 'angular';
import coreModule from 'app/core/core_module';
import _ from 'lodash';
export interface AngularComponent {
destroy();
}
export class AngularLoader {
/** @ngInject */
constructor(private $compile, private $rootScope) {}
load(elem, scopeProps, template): AngularComponent {
const scope = this.$rootScope.$new();
_.assign(scope, scopeProps);
const compiledElem = this.$compile(template)(scope);
const rootNode = angular.element(elem);
rootNode.append(compiledElem);
return {
destroy: () => {
scope.$destroy();
compiledElem.remove();
},
};
}
}
coreModule.service('angularLoader', AngularLoader);
let angularLoaderInstance: AngularLoader;
export function setAngularLoader(pl: AngularLoader) {
angularLoaderInstance = pl;
}
// away to access it from react
export function getAngularLoader(): AngularLoader {
return angularLoaderInstance;
}
......@@ -2,7 +2,7 @@ import React from 'react';
import config from 'app/core/config';
import { PanelModel } from '../panel_model';
import { DashboardModel } from '../dashboard_model';
import { getAngularLoader, AngularComponent } from 'app/core/services/angular_loader';
import { getAngularLoader, AngularComponent } from 'app/core/services/AngularLoader';
import { DashboardRow } from './DashboardRow';
import { AddPanelPanel } from './AddPanelPanel';
import { importPluginModule } from 'app/features/plugins/plugin_loader';
......
import React, { Component, ComponentClass } from 'react';
// Library
import React, { Component } from 'react';
export interface OuterProps {
type: string;
queries: any[];
isVisible: boolean;
interface RenderProps {
loading: LoadingState;
data: any;
}
export interface PanelProps extends OuterProps {
data: any[];
export interface Props {
datasource: string | null;
queries: any[];
children: (r: RenderProps) => JSX.Element;
}
export interface DataPanel extends ComponentClass<OuterProps> {}
interface State {
isLoading: boolean;
data: any[];
export interface State {
isFirstLoad: boolean;
loading: LoadingState;
data: any;
}
export const DataPanelWrapper = (ComposedComponent: ComponentClass<PanelProps>) => {
class Wrapper extends Component<OuterProps, State> {
static defaultProps = {
isVisible: true,
};
export enum LoadingState {
NotStarted = 'NotStarted',
Loading = 'Loading',
Done = 'Done',
Error = 'Error',
}
constructor(props: OuterProps) {
super(props);
export interface PanelProps extends RenderProps {}
this.state = {
isLoading: false,
data: [],
};
}
export class DataPanel extends Component<Props, State> {
constructor(props: Props) {
super(props);
componentDidMount() {
console.log('data panel mount');
this.issueQueries();
}
this.state = {
loading: LoadingState.NotStarted,
data: [],
isFirstLoad: true,
};
}
issueQueries = async () => {
const { isVisible } = this.props;
componentDidMount() {
console.log('DataPanel mount');
this.issueQueries();
}
if (!isVisible) {
return;
}
issueQueries = async () => {
this.setState({ loading: LoadingState.Loading });
await new Promise(resolve => {
setTimeout(() => {
this.setState({ loading: LoadingState.Done, data: [{ value: 10 }], isFirstLoad: false });
}, 500);
});
};
render() {
const { data, loading, isFirstLoad } = this.state;
console.log('data panel render');
if (isFirstLoad && loading === LoadingState.Loading) {
return (
<div className="loading">
<p>Loading</p>
</div>
);
}
this.setState({ isLoading: true });
return (
<>
{this.loadingSpinner}
{this.props.children({
data,
loading,
})}
</>
);
}
await new Promise(resolve => {
setTimeout(() => {
this.setState({ isLoading: false, data: [{ value: 10 }] });
}, 500);
});
};
private get loadingSpinner(): JSX.Element {
const { loading } = this.state;
render() {
const { data, isLoading } = this.state;
console.log('data panel render');
if (!data.length) {
return (
<div className="no-data">
<p>No Data</p>
</div>
);
}
if (isLoading) {
return (
<div className="loading">
<p>Loading</p>
</div>
);
}
return <ComposedComponent {...this.props} data={data} />;
if (loading === LoadingState.Loading) {
return (
<div className="panel__loading">
<i className="fa fa-spinner fa-spin" />
</div>
);
}
}
return Wrapper;
};
return null;
}
}
......@@ -2,7 +2,7 @@ import React, { ComponentClass } from 'react';
import { PanelModel } from '../panel_model';
import { DashboardModel } from '../dashboard_model';
import { PanelHeader } from './PanelHeader';
import { DataPanel, PanelProps, DataPanelWrapper } from './DataPanel';
import { DataPanel, PanelProps } from './DataPanel';
export interface Props {
panel: PanelModel;
......@@ -12,9 +12,6 @@ export interface Props {
interface State {}
// cache DataPanel wrapper components
const dataPanels: { [s: string]: DataPanel } = {};
export class PanelChrome extends React.Component<Props, State> {
panelComponent: DataPanel;
......@@ -23,20 +20,25 @@ export class PanelChrome extends React.Component<Props, State> {
}
render() {
const { type } = this.props.panel;
let PanelComponent = dataPanels[type];
const { datasource, targets } = this.props.panel;
const PanelComponent = this.props.component;
if (!PanelComponent) {
PanelComponent = dataPanels[type] = DataPanelWrapper(this.props.component);
}
// if (!PanelComponent) {
// PanelComponent = dataPanels[type] = DataPanelWrapper(this.props.component);
// }
console.log('PanelChrome render', PanelComponent);
return (
<div className="panel-container">
<PanelHeader panel={this.props.panel} dashboard={this.props.dashboard} />
<div className="panel-content">{<PanelComponent type={'test'} queries={[]} isVisible={true} />}</div>
<div className="panel-content">
<DataPanel datasource={datasource} queries={targets}>
{({ loading, data }) => {
return <PanelComponent loading={loading} data={data} />;
}}
</DataPanel>
</div>
</div>
);
}
......
import React from 'react';
import { PanelModel } from '../panel_model';
import { DashboardModel } from '../dashboard_model';
import { getAngularLoader, AngularComponent } from 'app/core/services/angular_loader';
import { getAngularLoader, AngularComponent } from 'app/core/services/AngularLoader';
interface Props {
panel: PanelModel;
......
import React, { PureComponent } from 'react';
import { PanelProps } from 'app/features/dashboard/dashgrid/DataPanel';
export class Graph2 extends PureComponent<PanelProps> {
interface Options {
showBars: boolean;
}
interface Props extends PanelProps {
options: Options;
}
export class Graph2 extends PureComponent<Props> {
constructor(props) {
super(props);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment