mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
changed DataPanel from HOC to use render props
This commit is contained in:
parent
0662b5f962
commit
2e1d45a875
@ -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 {
|
||||
|
@ -1,42 +0,0 @@
|
||||
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';
|
||||
|
@ -1,81 +1,92 @@
|
||||
import React, { Component, ComponentClass } from 'react';
|
||||
// Library
|
||||
import React, { Component } from 'react';
|
||||
|
||||
export interface OuterProps {
|
||||
type: string;
|
||||
interface RenderProps {
|
||||
loading: LoadingState;
|
||||
data: any;
|
||||
}
|
||||
|
||||
export interface Props {
|
||||
datasource: string | null;
|
||||
queries: any[];
|
||||
isVisible: boolean;
|
||||
children: (r: RenderProps) => JSX.Element;
|
||||
}
|
||||
|
||||
export interface PanelProps extends OuterProps {
|
||||
data: any[];
|
||||
export interface State {
|
||||
isFirstLoad: boolean;
|
||||
loading: LoadingState;
|
||||
data: any;
|
||||
}
|
||||
|
||||
export interface DataPanel extends ComponentClass<OuterProps> {}
|
||||
|
||||
interface State {
|
||||
isLoading: boolean;
|
||||
data: any[];
|
||||
export enum LoadingState {
|
||||
NotStarted = 'NotStarted',
|
||||
Loading = 'Loading',
|
||||
Done = 'Done',
|
||||
Error = 'Error',
|
||||
}
|
||||
|
||||
export const DataPanelWrapper = (ComposedComponent: ComponentClass<PanelProps>) => {
|
||||
class Wrapper extends Component<OuterProps, State> {
|
||||
static defaultProps = {
|
||||
isVisible: true,
|
||||
export interface PanelProps extends RenderProps {}
|
||||
|
||||
export class DataPanel extends Component<Props, State> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
loading: LoadingState.NotStarted,
|
||||
data: [],
|
||||
isFirstLoad: true,
|
||||
};
|
||||
|
||||
constructor(props: OuterProps) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
isLoading: false,
|
||||
data: [],
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
console.log('data panel mount');
|
||||
this.issueQueries();
|
||||
}
|
||||
|
||||
issueQueries = async () => {
|
||||
const { isVisible } = this.props;
|
||||
|
||||
if (!isVisible) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({ isLoading: true });
|
||||
|
||||
await new Promise(resolve => {
|
||||
setTimeout(() => {
|
||||
this.setState({ isLoading: false, data: [{ value: 10 }] });
|
||||
}, 500);
|
||||
});
|
||||
};
|
||||
|
||||
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} />;
|
||||
}
|
||||
}
|
||||
|
||||
return Wrapper;
|
||||
};
|
||||
componentDidMount() {
|
||||
console.log('DataPanel mount');
|
||||
this.issueQueries();
|
||||
}
|
||||
|
||||
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>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{this.loadingSpinner}
|
||||
{this.props.children({
|
||||
data,
|
||||
loading,
|
||||
})}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
private get loadingSpinner(): JSX.Element {
|
||||
const { loading } = this.state;
|
||||
|
||||
if (loading === LoadingState.Loading) {
|
||||
return (
|
||||
<div className="panel__loading">
|
||||
<i className="fa fa-spinner fa-spin" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
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;
|
||||
const { datasource, targets } = this.props.panel;
|
||||
const PanelComponent = this.props.component;
|
||||
|
||||
let PanelComponent = dataPanels[type];
|
||||
|
||||
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>
|
||||
);
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
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;
|
||||
|
@ -1,7 +1,15 @@
|
||||
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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user