DataPanel.tsx 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. // Library
  2. import React, { Component } from 'react';
  3. // Services
  4. import { DatasourceSrv, getDatasourceSrv } from 'app/features/plugins/datasource_srv';
  5. // Utils
  6. import kbn from 'app/core/utils/kbn';
  7. // Types
  8. import {
  9. DataQueryOptions,
  10. DataQueryResponse,
  11. LoadingState,
  12. PanelData,
  13. TableData,
  14. TimeRange,
  15. TimeSeries,
  16. } from '@grafana/ui';
  17. interface RenderProps {
  18. loading: LoadingState;
  19. panelData: PanelData;
  20. }
  21. export interface Props {
  22. datasource: string | null;
  23. queries: any[];
  24. panelId: number;
  25. dashboardId?: number;
  26. isVisible?: boolean;
  27. timeRange?: TimeRange;
  28. widthPixels: number;
  29. refreshCounter: number;
  30. minInterval?: string;
  31. maxDataPoints?: number;
  32. children: (r: RenderProps) => JSX.Element;
  33. onDataResponse?: (data: DataQueryResponse) => void;
  34. }
  35. export interface State {
  36. isFirstLoad: boolean;
  37. loading: LoadingState;
  38. response: DataQueryResponse;
  39. }
  40. export class DataPanel extends Component<Props, State> {
  41. static defaultProps = {
  42. isVisible: true,
  43. dashboardId: 1,
  44. };
  45. dataSourceSrv: DatasourceSrv = getDatasourceSrv();
  46. isUnmounted = false;
  47. constructor(props: Props) {
  48. super(props);
  49. this.state = {
  50. loading: LoadingState.NotStarted,
  51. response: {
  52. data: [],
  53. },
  54. isFirstLoad: true,
  55. };
  56. }
  57. componentDidMount() {
  58. this.issueQueries();
  59. }
  60. componentWillUnmount() {
  61. this.isUnmounted = true;
  62. }
  63. async componentDidUpdate(prevProps: Props) {
  64. if (!this.hasPropsChanged(prevProps)) {
  65. return;
  66. }
  67. this.issueQueries();
  68. }
  69. hasPropsChanged(prevProps: Props) {
  70. return this.props.refreshCounter !== prevProps.refreshCounter;
  71. }
  72. private issueQueries = async () => {
  73. const {
  74. isVisible,
  75. queries,
  76. datasource,
  77. panelId,
  78. dashboardId,
  79. timeRange,
  80. widthPixels,
  81. maxDataPoints,
  82. onDataResponse,
  83. } = this.props;
  84. if (!isVisible) {
  85. return;
  86. }
  87. if (!queries.length) {
  88. this.setState({ loading: LoadingState.Done });
  89. return;
  90. }
  91. this.setState({ loading: LoadingState.Loading });
  92. try {
  93. const ds = await this.dataSourceSrv.get(datasource);
  94. // TODO interpolate variables
  95. const minInterval = this.props.minInterval || ds.interval;
  96. const intervalRes = kbn.calculateInterval(timeRange, widthPixels, minInterval);
  97. const queryOptions: DataQueryOptions = {
  98. timezone: 'browser',
  99. panelId: panelId,
  100. dashboardId: dashboardId,
  101. range: timeRange,
  102. rangeRaw: timeRange.raw,
  103. interval: intervalRes.interval,
  104. intervalMs: intervalRes.intervalMs,
  105. targets: queries,
  106. maxDataPoints: maxDataPoints || widthPixels,
  107. scopedVars: {},
  108. cacheTimeout: null,
  109. };
  110. const resp = await ds.query(queryOptions);
  111. if (this.isUnmounted) {
  112. return;
  113. }
  114. if (onDataResponse) {
  115. onDataResponse(resp);
  116. }
  117. this.setState({
  118. loading: LoadingState.Done,
  119. response: resp,
  120. isFirstLoad: false,
  121. });
  122. } catch (err) {
  123. console.log('Loading error', err);
  124. this.setState({ isFirstLoad: false });
  125. throw new Error('Request Error');
  126. }
  127. };
  128. getPanelData = () => {
  129. const { response } = this.state;
  130. if (response.data.length > 0 && (response.data[0] as TableData).type === 'table') {
  131. return {
  132. tableData: response.data[0] as TableData,
  133. timeSeries: null,
  134. };
  135. }
  136. return {
  137. timeSeries: response.data as TimeSeries[],
  138. tableData: null,
  139. };
  140. };
  141. render() {
  142. const { queries } = this.props;
  143. const { loading, isFirstLoad } = this.state;
  144. const panelData = this.getPanelData();
  145. if (isFirstLoad && loading === LoadingState.Loading) {
  146. return (
  147. <div className="panel-loading">
  148. <i className="fa fa-spinner fa-spin" />
  149. </div>
  150. );
  151. }
  152. if (!queries.length) {
  153. return (
  154. <div className="panel-empty">
  155. <p>Add a query to get some data!</p>
  156. </div>
  157. );
  158. }
  159. return this.props.children({
  160. loading,
  161. panelData,
  162. });
  163. }
  164. }