Commit 36a2b9c0 by Torkel Ödegaard Committed by GitHub

Merge pull request #15136 from grafana/react-snapshots

React snapshots
parents f643e2ab 4b47e857
...@@ -811,6 +811,10 @@ export class DashboardModel { ...@@ -811,6 +811,10 @@ export class DashboardModel {
return this.getTimezone() === 'utc'; return this.getTimezone() === 'utc';
} }
isSnapshot() {
return this.snapshot !== undefined;
}
getTimezone() { getTimezone() {
return this.timezone ? this.timezone : contextSrv.user.timezone; return this.timezone ? this.timezone : contextSrv.user.timezone;
} }
......
...@@ -3,15 +3,12 @@ import React, { Component } from 'react'; ...@@ -3,15 +3,12 @@ import React, { Component } from 'react';
import { Tooltip } from '@grafana/ui'; import { Tooltip } from '@grafana/ui';
import ErrorBoundary from 'app/core/components/ErrorBoundary/ErrorBoundary'; import ErrorBoundary from 'app/core/components/ErrorBoundary/ErrorBoundary';
// Services // Services
import { getDatasourceSrv, DatasourceSrv } from 'app/features/plugins/datasource_srv'; import { DatasourceSrv, getDatasourceSrv } from 'app/features/plugins/datasource_srv';
// Utils // Utils
import kbn from 'app/core/utils/kbn'; import kbn from 'app/core/utils/kbn';
// Types // Types
import { TimeRange, TimeSeries, LoadingState, DataQueryResponse, DataQueryOptions } from '@grafana/ui/src/types'; import { DataQueryOptions, DataQueryResponse, LoadingState, TimeRange, TimeSeries } from '@grafana/ui/src/types';
const DEFAULT_PLUGIN_ERROR = 'Error in plugin'; const DEFAULT_PLUGIN_ERROR = 'Error in plugin';
...@@ -32,6 +29,7 @@ export interface Props { ...@@ -32,6 +29,7 @@ export interface Props {
minInterval?: string; minInterval?: string;
maxDataPoints?: number; maxDataPoints?: number;
children: (r: RenderProps) => JSX.Element; children: (r: RenderProps) => JSX.Element;
onDataResponse?: (data: DataQueryResponse) => void;
} }
export interface State { export interface State {
...@@ -85,7 +83,17 @@ export class DataPanel extends Component<Props, State> { ...@@ -85,7 +83,17 @@ export class DataPanel extends Component<Props, State> {
} }
private issueQueries = async () => { private issueQueries = async () => {
const { isVisible, queries, datasource, panelId, dashboardId, timeRange, widthPixels, maxDataPoints } = this.props; const {
isVisible,
queries,
datasource,
panelId,
dashboardId,
timeRange,
widthPixels,
maxDataPoints,
onDataResponse,
} = this.props;
if (!isVisible) { if (!isVisible) {
return; return;
...@@ -127,6 +135,10 @@ export class DataPanel extends Component<Props, State> { ...@@ -127,6 +135,10 @@ export class DataPanel extends Component<Props, State> {
return; return;
} }
if (onDataResponse) {
onDataResponse(resp);
}
this.setState({ this.setState({
loading: LoadingState.Done, loading: LoadingState.Done,
response: resp, response: resp,
......
...@@ -21,6 +21,7 @@ import { TimeRange } from '@grafana/ui'; ...@@ -21,6 +21,7 @@ import { TimeRange } from '@grafana/ui';
import variables from 'sass/_variables.scss'; import variables from 'sass/_variables.scss';
import templateSrv from 'app/features/templating/template_srv'; import templateSrv from 'app/features/templating/template_srv';
import { DataQueryResponse } from '@grafana/ui/src';
export interface Props { export interface Props {
panel: PanelModel; panel: PanelModel;
...@@ -83,16 +84,42 @@ export class PanelChrome extends PureComponent<Props, State> { ...@@ -83,16 +84,42 @@ export class PanelChrome extends PureComponent<Props, State> {
return templateSrv.replace(value, this.props.panel.scopedVars, format); return templateSrv.replace(value, this.props.panel.scopedVars, format);
}; };
onDataResponse = (dataQueryResponse: DataQueryResponse) => {
if (this.props.dashboard.isSnapshot()) {
this.props.panel.snapshotData = dataQueryResponse.data;
}
};
get isVisible() { get isVisible() {
return !this.props.dashboard.otherPanelInFullscreen(this.props.panel); return !this.props.dashboard.otherPanelInFullscreen(this.props.panel);
} }
renderPanel(loading, timeSeries, width, height): JSX.Element {
const { panel, plugin } = this.props;
const { timeRange, renderCounter } = this.state;
const PanelComponent = plugin.exports.Panel;
return (
<div className="panel-content">
<PanelComponent
loading={loading}
timeSeries={timeSeries}
timeRange={timeRange}
options={panel.getOptions(plugin.exports.PanelDefaults)}
width={width - 2 * variables.panelHorizontalPadding}
height={height - PANEL_HEADER_HEIGHT - variables.panelVerticalPadding}
renderCounter={renderCounter}
onInterpolate={this.onInterpolate}
/>
</div>
);
}
render() { render() {
const { panel, dashboard, plugin } = this.props; const { panel, dashboard } = this.props;
const { refreshCounter, timeRange, timeInfo, renderCounter } = this.state; const { refreshCounter, timeRange, timeInfo } = this.state;
const { datasource, targets, transparent } = panel; const { datasource, targets, transparent } = panel;
const PanelComponent = plugin.exports.Panel;
const containerClassNames = `panel-container panel-container--absolute ${transparent ? 'panel-transparent' : ''}`; const containerClassNames = `panel-container panel-container--absolute ${transparent ? 'panel-transparent' : ''}`;
return ( return (
<AutoSizer> <AutoSizer>
...@@ -113,6 +140,9 @@ export class PanelChrome extends PureComponent<Props, State> { ...@@ -113,6 +140,9 @@ export class PanelChrome extends PureComponent<Props, State> {
links={panel.links} links={panel.links}
/> />
{panel.snapshotData ? (
this.renderPanel(false, panel.snapshotData, width, height)
) : (
<DataPanel <DataPanel
datasource={datasource} datasource={datasource}
queries={targets} queries={targets}
...@@ -120,24 +150,13 @@ export class PanelChrome extends PureComponent<Props, State> { ...@@ -120,24 +150,13 @@ export class PanelChrome extends PureComponent<Props, State> {
isVisible={this.isVisible} isVisible={this.isVisible}
widthPixels={width} widthPixels={width}
refreshCounter={refreshCounter} refreshCounter={refreshCounter}
onDataResponse={this.onDataResponse}
> >
{({ loading, timeSeries }) => { {({ loading, timeSeries }) => {
return ( return this.renderPanel(loading, timeSeries, width, height);
<div className="panel-content">
<PanelComponent
loading={loading}
timeSeries={timeSeries}
timeRange={timeRange}
options={panel.getOptions(plugin.exports.PanelDefaults)}
width={width - 2 * variables.panelHorizontalPadding}
height={height - PANEL_HEADER_HEIGHT - variables.panelVerticalPadding}
renderCounter={renderCounter}
onInterpolate={this.onInterpolate}
/>
</div>
);
}} }}
</DataPanel> </DataPanel>
)}
</div> </div>
); );
}} }}
......
...@@ -4,7 +4,7 @@ import _ from 'lodash'; ...@@ -4,7 +4,7 @@ import _ from 'lodash';
// Types // Types
import { Emitter } from 'app/core/utils/emitter'; import { Emitter } from 'app/core/utils/emitter';
import { PANEL_OPTIONS_KEY_PREFIX } from 'app/core/constants'; import { PANEL_OPTIONS_KEY_PREFIX } from 'app/core/constants';
import { DataQuery } from '@grafana/ui/src/types'; import { DataQuery, TimeSeries } from '@grafana/ui';
export interface GridPos { export interface GridPos {
x: number; x: number;
...@@ -87,7 +87,7 @@ export class PanelModel { ...@@ -87,7 +87,7 @@ export class PanelModel {
datasource: string; datasource: string;
thresholds?: any; thresholds?: any;
snapshotData?: any; snapshotData?: TimeSeries[];
timeFrom?: any; timeFrom?: any;
timeShift?: any; timeShift?: any;
hideTimeOverride?: any; hideTimeOverride?: any;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment