mirror of
https://github.com/grafana/grafana.git
synced 2025-09-25 17:34:22 +08:00
210 lines
4.4 KiB
TypeScript
210 lines
4.4 KiB
TypeScript
// Library
|
|
import React, { Component } from 'react';
|
|
|
|
// Services
|
|
import { DatasourceSrv, getDatasourceSrv } from 'app/features/plugins/datasource_srv';
|
|
// Utils
|
|
import kbn from 'app/core/utils/kbn';
|
|
// Types
|
|
import {
|
|
DataQueryOptions,
|
|
DataQueryResponse,
|
|
DataQueryError,
|
|
LoadingState,
|
|
PanelData,
|
|
TableData,
|
|
TimeRange,
|
|
TimeSeries,
|
|
} from '@grafana/ui';
|
|
|
|
interface RenderProps {
|
|
loading: LoadingState;
|
|
panelData: PanelData;
|
|
}
|
|
|
|
export interface Props {
|
|
datasource: string | null;
|
|
queries: any[];
|
|
panelId: number;
|
|
dashboardId?: number;
|
|
isVisible?: boolean;
|
|
timeRange?: TimeRange;
|
|
widthPixels: number;
|
|
refreshCounter: number;
|
|
minInterval?: string;
|
|
maxDataPoints?: number;
|
|
children: (r: RenderProps) => JSX.Element;
|
|
onDataResponse?: (data: DataQueryResponse) => void;
|
|
onError: (message: string, error: DataQueryError) => void;
|
|
}
|
|
|
|
export interface State {
|
|
isFirstLoad: boolean;
|
|
loading: LoadingState;
|
|
response: DataQueryResponse;
|
|
}
|
|
|
|
export class DataPanel extends Component<Props, State> {
|
|
static defaultProps = {
|
|
isVisible: true,
|
|
dashboardId: 1,
|
|
};
|
|
|
|
dataSourceSrv: DatasourceSrv = getDatasourceSrv();
|
|
isUnmounted = false;
|
|
|
|
constructor(props: Props) {
|
|
super(props);
|
|
|
|
this.state = {
|
|
loading: LoadingState.NotStarted,
|
|
response: {
|
|
data: [],
|
|
},
|
|
isFirstLoad: true,
|
|
};
|
|
}
|
|
|
|
componentDidMount() {
|
|
this.issueQueries();
|
|
}
|
|
|
|
componentWillUnmount() {
|
|
this.isUnmounted = true;
|
|
}
|
|
|
|
async componentDidUpdate(prevProps: Props) {
|
|
if (!this.hasPropsChanged(prevProps)) {
|
|
return;
|
|
}
|
|
|
|
this.issueQueries();
|
|
}
|
|
|
|
hasPropsChanged(prevProps: Props) {
|
|
return this.props.refreshCounter !== prevProps.refreshCounter;
|
|
}
|
|
|
|
private issueQueries = async () => {
|
|
const {
|
|
isVisible,
|
|
queries,
|
|
datasource,
|
|
panelId,
|
|
dashboardId,
|
|
timeRange,
|
|
widthPixels,
|
|
maxDataPoints,
|
|
onDataResponse,
|
|
onError,
|
|
} = this.props;
|
|
|
|
if (!isVisible) {
|
|
return;
|
|
}
|
|
|
|
if (!queries.length) {
|
|
this.setState({ loading: LoadingState.Done });
|
|
return;
|
|
}
|
|
|
|
this.setState({ loading: LoadingState.Loading });
|
|
|
|
try {
|
|
const ds = await this.dataSourceSrv.get(datasource);
|
|
|
|
// TODO interpolate variables
|
|
const minInterval = this.props.minInterval || ds.interval;
|
|
const intervalRes = kbn.calculateInterval(timeRange, widthPixels, minInterval);
|
|
|
|
const queryOptions: DataQueryOptions = {
|
|
timezone: 'browser',
|
|
panelId: panelId,
|
|
dashboardId: dashboardId,
|
|
range: timeRange,
|
|
rangeRaw: timeRange.raw,
|
|
interval: intervalRes.interval,
|
|
intervalMs: intervalRes.intervalMs,
|
|
targets: queries,
|
|
maxDataPoints: maxDataPoints || widthPixels,
|
|
scopedVars: {},
|
|
cacheTimeout: null,
|
|
};
|
|
|
|
const resp = await ds.query(queryOptions);
|
|
|
|
if (this.isUnmounted) {
|
|
return;
|
|
}
|
|
|
|
if (onDataResponse) {
|
|
onDataResponse(resp);
|
|
}
|
|
|
|
this.setState({
|
|
loading: LoadingState.Done,
|
|
response: resp,
|
|
isFirstLoad: false,
|
|
});
|
|
} catch (err) {
|
|
console.log('DataPanel error', err);
|
|
|
|
let message = 'Query error';
|
|
|
|
if (err.message) {
|
|
message = err.message;
|
|
} else if (err.data && err.data.message) {
|
|
message = err.data.message;
|
|
} else if (err.data && err.data.error) {
|
|
message = err.data.error;
|
|
}
|
|
|
|
onError(message, err);
|
|
this.setState({ isFirstLoad: false });
|
|
}
|
|
};
|
|
|
|
getPanelData = () => {
|
|
const { response } = this.state;
|
|
|
|
if (response.data.length > 0 && (response.data[0] as TableData).type === 'table') {
|
|
return {
|
|
tableData: response.data[0] as TableData,
|
|
timeSeries: null,
|
|
};
|
|
}
|
|
|
|
return {
|
|
timeSeries: response.data as TimeSeries[],
|
|
tableData: null,
|
|
};
|
|
};
|
|
|
|
render() {
|
|
const { queries } = this.props;
|
|
const { loading, isFirstLoad } = this.state;
|
|
const panelData = this.getPanelData();
|
|
|
|
if (isFirstLoad && loading === LoadingState.Loading) {
|
|
return (
|
|
<div className="panel-loading">
|
|
<i className="fa fa-spinner fa-spin" />
|
|
</div>
|
|
);
|
|
}
|
|
|
|
if (!queries.length) {
|
|
return (
|
|
<div className="panel-empty">
|
|
<p>Add a query to get some data!</p>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return this.props.children({
|
|
loading,
|
|
panelData,
|
|
});
|
|
}
|
|
}
|