DataPanel.tsx 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  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. onError?: (errorMessage: string) => void;
  35. }
  36. export interface State {
  37. isFirstLoad: boolean;
  38. loading: LoadingState;
  39. response: DataQueryResponse;
  40. }
  41. export class DataPanel extends Component<Props, State> {
  42. static defaultProps = {
  43. isVisible: true,
  44. dashboardId: 1,
  45. };
  46. dataSourceSrv: DatasourceSrv = getDatasourceSrv();
  47. isUnmounted = false;
  48. constructor(props: Props) {
  49. super(props);
  50. this.state = {
  51. loading: LoadingState.NotStarted,
  52. response: {
  53. data: [],
  54. },
  55. isFirstLoad: true,
  56. };
  57. }
  58. componentDidMount() {
  59. this.issueQueries();
  60. }
  61. componentWillUnmount() {
  62. this.isUnmounted = true;
  63. }
  64. async componentDidUpdate(prevProps: Props) {
  65. if (!this.hasPropsChanged(prevProps)) {
  66. return;
  67. }
  68. this.issueQueries();
  69. }
  70. hasPropsChanged(prevProps: Props) {
  71. return this.props.refreshCounter !== prevProps.refreshCounter;
  72. }
  73. private issueQueries = async () => {
  74. const {
  75. isVisible,
  76. queries,
  77. datasource,
  78. panelId,
  79. dashboardId,
  80. timeRange,
  81. widthPixels,
  82. maxDataPoints,
  83. onDataResponse,
  84. } = this.props;
  85. if (!isVisible) {
  86. return;
  87. }
  88. if (!queries.length) {
  89. this.setState({ loading: LoadingState.Done });
  90. return;
  91. }
  92. this.setState({ loading: LoadingState.Loading });
  93. try {
  94. const ds = await this.dataSourceSrv.get(datasource);
  95. // TODO interpolate variables
  96. const minInterval = this.props.minInterval || ds.interval;
  97. const intervalRes = kbn.calculateInterval(timeRange, widthPixels, minInterval);
  98. const queryOptions: DataQueryOptions = {
  99. timezone: 'browser',
  100. panelId: panelId,
  101. dashboardId: dashboardId,
  102. range: timeRange,
  103. rangeRaw: timeRange.raw,
  104. interval: intervalRes.interval,
  105. intervalMs: intervalRes.intervalMs,
  106. targets: queries,
  107. maxDataPoints: maxDataPoints || widthPixels,
  108. scopedVars: {},
  109. cacheTimeout: null,
  110. };
  111. const resp = await ds.query(queryOptions);
  112. if (this.isUnmounted) {
  113. return;
  114. }
  115. if (onDataResponse) {
  116. onDataResponse(resp);
  117. }
  118. this.setState({
  119. loading: LoadingState.Done,
  120. response: resp,
  121. isFirstLoad: false,
  122. });
  123. } catch (err) {
  124. console.log('Loading error', err);
  125. this.setState({ isFirstLoad: false });
  126. this.props.onError('Request Error');
  127. }
  128. };
  129. // error som callback eller renderprop?
  130. // ta bort error, bubbla till panelchrome
  131. getPanelData = () => {
  132. const { response } = this.state;
  133. if (response.data.length > 0 && (response.data[0] as TableData).type === 'table') {
  134. return {
  135. tableData: response.data[0] as TableData,
  136. timeSeries: null,
  137. };
  138. }
  139. return {
  140. timeSeries: response.data as TimeSeries[],
  141. tableData: null,
  142. };
  143. };
  144. render() {
  145. const { queries } = this.props;
  146. const { loading, isFirstLoad } = this.state;
  147. const panelData = this.getPanelData();
  148. if (isFirstLoad && loading === LoadingState.Loading) {
  149. return (
  150. <div className="panel-loading">
  151. <i className="fa fa-spinner fa-spin" />
  152. </div>
  153. );
  154. }
  155. if (!queries.length) {
  156. return (
  157. <div className="panel-empty">
  158. <p>Add a query to get some data!</p>
  159. </div>
  160. );
  161. }
  162. return this.props.children({
  163. loading,
  164. panelData,
  165. });
  166. }
  167. }