PanelChrome.tsx 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. // Libraries
  2. import React, { PureComponent } from 'react';
  3. import { AutoSizer } from 'react-virtualized';
  4. // Services
  5. import { getTimeSrv, TimeSrv } from '../services/TimeSrv';
  6. // Components
  7. import { PanelHeader } from './PanelHeader/PanelHeader';
  8. import { DataPanel } from './DataPanel';
  9. // Utils
  10. import { applyPanelTimeOverrides } from 'app/features/dashboard/utils/panel';
  11. import { PANEL_HEADER_HEIGHT } from 'app/core/constants';
  12. import { profiler } from 'app/core/profiler';
  13. // Types
  14. import { DashboardModel, PanelModel } from '../state';
  15. import { PanelPlugin } from 'app/types';
  16. import { TimeRange, LoadingState } from '@grafana/ui';
  17. import variables from 'sass/_variables.scss';
  18. import templateSrv from 'app/features/templating/template_srv';
  19. import { DataQueryResponse } from '@grafana/ui/src';
  20. export interface Props {
  21. panel: PanelModel;
  22. dashboard: DashboardModel;
  23. plugin: PanelPlugin;
  24. }
  25. export interface State {
  26. refreshCounter: number;
  27. renderCounter: number;
  28. timeInfo?: string;
  29. timeRange?: TimeRange;
  30. }
  31. export class PanelChrome extends PureComponent<Props, State> {
  32. timeSrv: TimeSrv = getTimeSrv();
  33. constructor(props) {
  34. super(props);
  35. this.state = {
  36. refreshCounter: 0,
  37. renderCounter: 0,
  38. };
  39. }
  40. componentDidMount() {
  41. this.props.panel.events.on('refresh', this.onRefresh);
  42. this.props.panel.events.on('render', this.onRender);
  43. this.props.dashboard.panelInitialized(this.props.panel);
  44. }
  45. componentWillUnmount() {
  46. this.props.panel.events.off('refresh', this.onRefresh);
  47. }
  48. onRefresh = () => {
  49. console.log('onRefresh');
  50. if (!this.isVisible) {
  51. return;
  52. }
  53. const { panel } = this.props;
  54. const timeData = applyPanelTimeOverrides(panel, this.timeSrv.timeRange());
  55. this.setState({
  56. refreshCounter: this.state.refreshCounter + 1,
  57. timeRange: timeData.timeRange,
  58. timeInfo: timeData.timeInfo,
  59. });
  60. };
  61. onRender = () => {
  62. this.setState({
  63. renderCounter: this.state.renderCounter + 1,
  64. });
  65. };
  66. onInterpolate = (value: string, format?: string) => {
  67. return templateSrv.replace(value, this.props.panel.scopedVars, format);
  68. };
  69. onDataResponse = (dataQueryResponse: DataQueryResponse) => {
  70. if (this.props.dashboard.isSnapshot()) {
  71. this.props.panel.snapshotData = dataQueryResponse.data;
  72. }
  73. };
  74. get isVisible() {
  75. return !this.props.dashboard.otherPanelInFullscreen(this.props.panel);
  76. }
  77. renderPanel(loading, panelData, width, height): JSX.Element {
  78. const { panel, plugin } = this.props;
  79. const { timeRange, renderCounter } = this.state;
  80. const PanelComponent = plugin.exports.Panel;
  81. // This is only done to increase a counter that is used by backend
  82. // image rendering (phantomjs/headless chrome) to know when to capture image
  83. if (loading === LoadingState.Done) {
  84. profiler.renderingCompleted(panel.id);
  85. }
  86. return (
  87. <div className="panel-content">
  88. <PanelComponent
  89. loading={loading}
  90. panelData={panelData}
  91. timeRange={timeRange}
  92. options={panel.getOptions(plugin.exports.PanelDefaults)}
  93. width={width - 2 * variables.panelHorizontalPadding}
  94. height={height - PANEL_HEADER_HEIGHT - variables.panelVerticalPadding}
  95. renderCounter={renderCounter}
  96. onInterpolate={this.onInterpolate}
  97. />
  98. </div>
  99. );
  100. }
  101. render() {
  102. const { panel, dashboard } = this.props;
  103. const { refreshCounter, timeRange, timeInfo } = this.state;
  104. const { datasource, targets, transparent } = panel;
  105. const containerClassNames = `panel-container panel-container--absolute ${transparent ? 'panel-transparent' : ''}`;
  106. return (
  107. <AutoSizer>
  108. {({ width, height }) => {
  109. if (width === 0) {
  110. return null;
  111. }
  112. return (
  113. <div className={containerClassNames}>
  114. <PanelHeader
  115. panel={panel}
  116. dashboard={dashboard}
  117. timeInfo={timeInfo}
  118. title={panel.title}
  119. description={panel.description}
  120. scopedVars={panel.scopedVars}
  121. links={panel.links}
  122. />
  123. {panel.snapshotData ? (
  124. this.renderPanel(false, panel.snapshotData, width, height)
  125. ) : (
  126. <DataPanel
  127. datasource={datasource}
  128. queries={targets}
  129. timeRange={timeRange}
  130. isVisible={this.isVisible}
  131. widthPixels={width}
  132. refreshCounter={refreshCounter}
  133. onDataResponse={this.onDataResponse}
  134. >
  135. {({ loading, panelData }) => {
  136. return this.renderPanel(loading, panelData, width, height);
  137. }}
  138. </DataPanel>
  139. )}
  140. </div>
  141. );
  142. }}
  143. </AutoSizer>
  144. );
  145. }
  146. }