2018-10-14 08:39:34 -05:00
|
|
|
// Libraries
|
2018-11-20 10:01:58 -06:00
|
|
|
import React, { PureComponent } from 'react';
|
2018-11-13 11:50:12 -06:00
|
|
|
import { AutoSizer } from 'react-virtualized';
|
2018-10-14 08:39:34 -05:00
|
|
|
|
|
|
|
// Services
|
2019-01-31 01:44:46 -06:00
|
|
|
import { getTimeSrv, TimeSrv } from '../services/TimeSrv';
|
2018-10-14 08:39:34 -05:00
|
|
|
|
|
|
|
// Components
|
2018-10-25 05:47:09 -05:00
|
|
|
import { PanelHeader } from './PanelHeader/PanelHeader';
|
2018-10-14 08:39:34 -05:00
|
|
|
import { DataPanel } from './DataPanel';
|
2019-02-12 09:06:02 -06:00
|
|
|
import ErrorBoundary from '../../../core/components/ErrorBoundary/ErrorBoundary';
|
2018-10-14 08:39:34 -05:00
|
|
|
|
2018-11-08 07:44:12 -06:00
|
|
|
// Utils
|
2019-02-07 14:34:50 -06:00
|
|
|
import { applyPanelTimeOverrides, snapshotDataToPanelData } from 'app/features/dashboard/utils/panel';
|
2018-11-14 06:20:19 -06:00
|
|
|
import { PANEL_HEADER_HEIGHT } from 'app/core/constants';
|
2019-02-01 01:12:58 -06:00
|
|
|
import { profiler } from 'app/core/profiler';
|
2018-11-08 07:44:12 -06:00
|
|
|
|
2018-10-14 08:39:34 -05:00
|
|
|
// Types
|
2019-01-31 07:16:06 -06:00
|
|
|
import { DashboardModel, PanelModel } from '../state';
|
2018-12-23 02:15:32 -06:00
|
|
|
import { PanelPlugin } from 'app/types';
|
2019-02-12 09:06:02 -06:00
|
|
|
import { DataQueryResponse, TimeRange, LoadingState, PanelData } from '@grafana/ui';
|
2018-06-19 07:51:57 -05:00
|
|
|
|
2019-01-14 07:47:41 -06:00
|
|
|
import variables from 'sass/_variables.scss';
|
2019-01-15 10:15:46 -06:00
|
|
|
import templateSrv from 'app/features/templating/template_srv';
|
2019-02-12 09:06:02 -06:00
|
|
|
|
|
|
|
const DEFAULT_PLUGIN_ERROR = 'Error in plugin';
|
2019-01-14 07:47:41 -06:00
|
|
|
|
2018-11-06 09:37:51 -06:00
|
|
|
export interface Props {
|
2018-06-19 07:51:57 -05:00
|
|
|
panel: PanelModel;
|
|
|
|
dashboard: DashboardModel;
|
2018-11-20 10:01:58 -06:00
|
|
|
plugin: PanelPlugin;
|
2018-06-19 07:51:57 -05:00
|
|
|
}
|
|
|
|
|
2018-11-06 09:37:51 -06:00
|
|
|
export interface State {
|
2018-10-14 08:39:34 -05:00
|
|
|
refreshCounter: number;
|
2018-11-05 10:46:09 -06:00
|
|
|
renderCounter: number;
|
2018-11-13 08:05:07 -06:00
|
|
|
timeInfo?: string;
|
2018-10-14 08:39:34 -05:00
|
|
|
timeRange?: TimeRange;
|
2019-02-12 09:06:02 -06:00
|
|
|
loading: LoadingState;
|
|
|
|
errorMessage: string;
|
2018-10-14 08:39:34 -05:00
|
|
|
}
|
2018-07-05 15:10:39 -05:00
|
|
|
|
2018-11-06 09:37:51 -06:00
|
|
|
export class PanelChrome extends PureComponent<Props, State> {
|
2018-11-08 07:44:12 -06:00
|
|
|
timeSrv: TimeSrv = getTimeSrv();
|
|
|
|
|
2018-06-19 07:51:57 -05:00
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
2018-11-06 09:37:51 -06:00
|
|
|
|
2018-10-14 08:39:34 -05:00
|
|
|
this.state = {
|
|
|
|
refreshCounter: 0,
|
2018-11-05 10:46:09 -06:00
|
|
|
renderCounter: 0,
|
2019-02-12 09:06:02 -06:00
|
|
|
loading: LoadingState.NotStarted,
|
|
|
|
errorMessage: '',
|
2018-10-14 08:39:34 -05:00
|
|
|
};
|
2018-07-05 15:10:39 -05:00
|
|
|
}
|
|
|
|
|
2018-11-06 09:37:51 -06:00
|
|
|
componentDidMount() {
|
2018-10-14 08:39:34 -05:00
|
|
|
this.props.panel.events.on('refresh', this.onRefresh);
|
2018-11-05 10:46:09 -06:00
|
|
|
this.props.panel.events.on('render', this.onRender);
|
2018-10-14 09:31:20 -05:00
|
|
|
this.props.dashboard.panelInitialized(this.props.panel);
|
2018-10-14 08:39:34 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
componentWillUnmount() {
|
|
|
|
this.props.panel.events.off('refresh', this.onRefresh);
|
|
|
|
}
|
|
|
|
|
|
|
|
onRefresh = () => {
|
2018-11-08 07:44:12 -06:00
|
|
|
console.log('onRefresh');
|
|
|
|
if (!this.isVisible) {
|
|
|
|
return;
|
|
|
|
}
|
2018-11-12 04:23:41 -06:00
|
|
|
|
2018-11-08 07:44:12 -06:00
|
|
|
const { panel } = this.props;
|
2018-11-13 08:05:07 -06:00
|
|
|
const timeData = applyPanelTimeOverrides(panel, this.timeSrv.timeRange());
|
2018-07-09 15:24:15 -05:00
|
|
|
|
2018-11-13 08:05:07 -06:00
|
|
|
this.setState({
|
2018-10-14 08:39:34 -05:00
|
|
|
refreshCounter: this.state.refreshCounter + 1,
|
2018-11-13 08:05:07 -06:00
|
|
|
timeRange: timeData.timeRange,
|
|
|
|
timeInfo: timeData.timeInfo,
|
|
|
|
});
|
2018-10-14 08:39:34 -05:00
|
|
|
};
|
2018-07-09 15:24:15 -05:00
|
|
|
|
2018-11-05 10:46:09 -06:00
|
|
|
onRender = () => {
|
2018-11-13 08:05:07 -06:00
|
|
|
this.setState({
|
2018-11-06 09:37:51 -06:00
|
|
|
renderCounter: this.state.renderCounter + 1,
|
2018-11-13 08:05:07 -06:00
|
|
|
});
|
2018-11-03 17:36:40 -05:00
|
|
|
};
|
|
|
|
|
2019-01-15 10:15:46 -06:00
|
|
|
onInterpolate = (value: string, format?: string) => {
|
|
|
|
return templateSrv.replace(value, this.props.panel.scopedVars, format);
|
|
|
|
};
|
|
|
|
|
2019-01-30 03:39:42 -06:00
|
|
|
onDataResponse = (dataQueryResponse: DataQueryResponse) => {
|
|
|
|
if (this.props.dashboard.isSnapshot()) {
|
2019-01-30 06:43:17 -06:00
|
|
|
this.props.panel.snapshotData = dataQueryResponse.data;
|
2019-01-30 03:39:42 -06:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2018-10-14 08:39:34 -05:00
|
|
|
get isVisible() {
|
2018-10-14 09:31:20 -05:00
|
|
|
return !this.props.dashboard.otherPanelInFullscreen(this.props.panel);
|
2018-10-14 08:39:34 -05:00
|
|
|
}
|
|
|
|
|
2019-02-12 05:25:10 -06:00
|
|
|
get hasPanelSnapshot() {
|
|
|
|
const { panel } = this.props;
|
|
|
|
return panel.snapshotData && panel.snapshotData.length;
|
|
|
|
}
|
|
|
|
|
2019-02-12 09:05:29 -06:00
|
|
|
get needsQueryExecution() {
|
|
|
|
return this.hasPanelSnapshot || this.props.plugin.dataFormats.length > 0;
|
2019-02-12 05:25:10 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
get getDataForPanel() {
|
2019-02-12 09:05:29 -06:00
|
|
|
return this.hasPanelSnapshot ? snapshotDataToPanelData(this.props.panel) : null;
|
2019-02-12 05:25:10 -06:00
|
|
|
}
|
|
|
|
|
2019-02-12 10:01:07 -06:00
|
|
|
onError = (errorMessage: string) => {
|
|
|
|
if (this.state.loading !== LoadingState.Error || this.state.errorMessage !== errorMessage) {
|
|
|
|
this.setState({
|
|
|
|
loading: LoadingState.Error,
|
|
|
|
errorMessage: errorMessage,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-02-07 14:34:50 -06:00
|
|
|
renderPanelPlugin(loading: LoadingState, panelData: PanelData, width: number, height: number): JSX.Element {
|
2019-01-30 03:39:42 -06:00
|
|
|
const { panel, plugin } = this.props;
|
|
|
|
const { timeRange, renderCounter } = this.state;
|
|
|
|
const PanelComponent = plugin.exports.Panel;
|
|
|
|
|
2019-02-01 01:12:58 -06:00
|
|
|
// This is only done to increase a counter that is used by backend
|
|
|
|
// image rendering (phantomjs/headless chrome) to know when to capture image
|
|
|
|
if (loading === LoadingState.Done) {
|
|
|
|
profiler.renderingCompleted(panel.id);
|
|
|
|
}
|
|
|
|
|
2019-01-30 03:39:42 -06:00
|
|
|
return (
|
|
|
|
<div className="panel-content">
|
|
|
|
<PanelComponent
|
|
|
|
loading={loading}
|
2019-02-01 03:53:58 -06:00
|
|
|
panelData={panelData}
|
2019-01-30 03:39:42 -06:00
|
|
|
timeRange={timeRange}
|
|
|
|
options={panel.getOptions(plugin.exports.PanelDefaults)}
|
2019-02-13 09:36:59 -06:00
|
|
|
width={width - 2 * variables.panelhorizontalpadding}
|
|
|
|
height={height - PANEL_HEADER_HEIGHT - variables.panelverticalpadding}
|
2019-01-30 03:39:42 -06:00
|
|
|
renderCounter={renderCounter}
|
|
|
|
onInterpolate={this.onInterpolate}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2019-02-12 05:27:49 -06:00
|
|
|
renderPanelBody = (width: number, height: number): JSX.Element => {
|
2019-02-12 05:25:10 -06:00
|
|
|
const { panel } = this.props;
|
2019-02-07 14:34:50 -06:00
|
|
|
const { refreshCounter, timeRange } = this.state;
|
|
|
|
const { datasource, targets } = panel;
|
|
|
|
return (
|
|
|
|
<>
|
2019-02-12 09:05:29 -06:00
|
|
|
{this.needsQueryExecution ? (
|
2019-02-12 05:25:10 -06:00
|
|
|
<DataPanel
|
2019-02-07 14:34:50 -06:00
|
|
|
panelId={panel.id}
|
2019-02-07 14:34:50 -06:00
|
|
|
datasource={datasource}
|
|
|
|
queries={targets}
|
|
|
|
timeRange={timeRange}
|
|
|
|
isVisible={this.isVisible}
|
|
|
|
widthPixels={width}
|
|
|
|
refreshCounter={refreshCounter}
|
|
|
|
onDataResponse={this.onDataResponse}
|
2019-02-13 08:54:10 -06:00
|
|
|
onError={this.onError}
|
2019-02-07 14:34:50 -06:00
|
|
|
>
|
|
|
|
{({ loading, panelData }) => {
|
|
|
|
return this.renderPanelPlugin(loading, panelData, width, height);
|
|
|
|
}}
|
|
|
|
</DataPanel>
|
2019-02-12 09:06:02 -06:00
|
|
|
) : (
|
2019-02-12 05:25:10 -06:00
|
|
|
this.renderPanelPlugin(LoadingState.Done, this.getDataForPanel, width, height)
|
2019-02-12 09:06:02 -06:00
|
|
|
)}
|
2019-02-07 14:34:50 -06:00
|
|
|
</>
|
|
|
|
);
|
2019-02-12 09:06:02 -06:00
|
|
|
};
|
2019-02-07 14:34:50 -06:00
|
|
|
|
2018-10-14 08:39:34 -05:00
|
|
|
render() {
|
2019-02-07 14:34:50 -06:00
|
|
|
const { dashboard, panel } = this.props;
|
2019-02-13 08:54:10 -06:00
|
|
|
const { errorMessage, timeInfo } = this.state;
|
2019-02-07 14:34:50 -06:00
|
|
|
const { transparent } = panel;
|
2018-11-06 08:03:56 -06:00
|
|
|
|
2018-12-06 03:34:27 -06:00
|
|
|
const containerClassNames = `panel-container panel-container--absolute ${transparent ? 'panel-transparent' : ''}`;
|
2018-06-19 07:51:57 -05:00
|
|
|
return (
|
2018-11-14 05:03:25 -06:00
|
|
|
<AutoSizer>
|
|
|
|
{({ width, height }) => {
|
|
|
|
if (width === 0) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (
|
2018-12-06 03:34:27 -06:00
|
|
|
<div className={containerClassNames}>
|
2018-12-05 07:57:57 -06:00
|
|
|
<PanelHeader
|
|
|
|
panel={panel}
|
|
|
|
dashboard={dashboard}
|
|
|
|
timeInfo={timeInfo}
|
|
|
|
title={panel.title}
|
|
|
|
description={panel.description}
|
|
|
|
scopedVars={panel.scopedVars}
|
|
|
|
links={panel.links}
|
2019-02-13 08:54:10 -06:00
|
|
|
error={errorMessage}
|
2018-12-05 07:57:57 -06:00
|
|
|
/>
|
2019-02-12 09:06:02 -06:00
|
|
|
<ErrorBoundary>
|
|
|
|
{({ error, errorInfo }) => {
|
|
|
|
if (errorInfo) {
|
|
|
|
this.onError(error.message || DEFAULT_PLUGIN_ERROR);
|
|
|
|
return null;
|
|
|
|
}
|
2019-02-12 09:13:15 -06:00
|
|
|
return this.renderPanelBody(width, height);
|
2019-02-12 09:06:02 -06:00
|
|
|
}}
|
|
|
|
</ErrorBoundary>
|
2018-11-14 05:03:25 -06:00
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}}
|
|
|
|
</AutoSizer>
|
2018-06-19 07:51:57 -05:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|