mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
feat: Display error when plot fail to render
This commit is contained in:
@@ -9,6 +9,7 @@ export interface PanelProps<T = any> {
|
|||||||
renderCounter: number;
|
renderCounter: number;
|
||||||
width: number;
|
width: number;
|
||||||
height: number;
|
height: number;
|
||||||
|
onRenderError: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PanelOptionsProps<T = any> {
|
export interface PanelOptionsProps<T = any> {
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ interface GraphProps {
|
|||||||
showBars?: boolean;
|
showBars?: boolean;
|
||||||
width: number;
|
width: number;
|
||||||
height: number;
|
height: number;
|
||||||
|
onRenderError: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Graph extends PureComponent<GraphProps> {
|
export class Graph extends PureComponent<GraphProps> {
|
||||||
@@ -37,7 +38,7 @@ export class Graph extends PureComponent<GraphProps> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { width, timeSeries, timeRange, showLines, showBars, showPoints } = this.props;
|
const { width, timeSeries, timeRange, showLines, showBars, showPoints, onRenderError } = this.props;
|
||||||
|
|
||||||
if (!width) {
|
if (!width) {
|
||||||
return;
|
return;
|
||||||
@@ -98,6 +99,7 @@ export class Graph extends PureComponent<GraphProps> {
|
|||||||
$.plot(this.element, timeSeries, flotOptions);
|
$.plot(this.element, timeSeries, flotOptions);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log('Graph rendering error', err, flotOptions, timeSeries);
|
console.log('Graph rendering error', err, flotOptions, timeSeries);
|
||||||
|
onRenderError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,11 @@ import Portal from 'app/core/components/Portal/Portal';
|
|||||||
import { Manager, Popper as ReactPopper, Reference } from 'react-popper';
|
import { Manager, Popper as ReactPopper, Reference } from 'react-popper';
|
||||||
import Transition from 'react-transition-group/Transition';
|
import Transition from 'react-transition-group/Transition';
|
||||||
|
|
||||||
|
export enum Themes {
|
||||||
|
Default = 'popper__background--default',
|
||||||
|
Error = 'popper__background--error',
|
||||||
|
}
|
||||||
|
|
||||||
const defaultTransitionStyles = {
|
const defaultTransitionStyles = {
|
||||||
transition: 'opacity 200ms linear',
|
transition: 'opacity 200ms linear',
|
||||||
opacity: 0,
|
opacity: 0,
|
||||||
@@ -21,12 +26,7 @@ interface Props {
|
|||||||
placement?: any;
|
placement?: any;
|
||||||
content: string | ((props: any) => JSX.Element);
|
content: string | ((props: any) => JSX.Element);
|
||||||
refClassName?: string;
|
refClassName?: string;
|
||||||
theme?: string;
|
theme?: Themes;
|
||||||
}
|
|
||||||
|
|
||||||
export enum Themes {
|
|
||||||
Default = 'popper__background--default',
|
|
||||||
Error = 'popper__background--error',
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class Popper extends PureComponent<Props> {
|
class Popper extends PureComponent<Props> {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { Themes } from './Popper';
|
||||||
export interface UsingPopperProps {
|
export interface UsingPopperProps {
|
||||||
showPopper: (prevState: object) => void;
|
showPopper: (prevState: object) => void;
|
||||||
hidePopper: (prevState: object) => void;
|
hidePopper: (prevState: object) => void;
|
||||||
@@ -9,7 +9,7 @@ export interface UsingPopperProps {
|
|||||||
content: string | ((props: any) => JSX.Element);
|
content: string | ((props: any) => JSX.Element);
|
||||||
className?: string;
|
className?: string;
|
||||||
refClassName?: string;
|
refClassName?: string;
|
||||||
theme?: string;
|
theme?: Themes;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@@ -17,7 +17,7 @@ interface Props {
|
|||||||
className?: string;
|
className?: string;
|
||||||
refClassName?: string;
|
refClassName?: string;
|
||||||
content: string | ((props: any) => JSX.Element);
|
content: string | ((props: any) => JSX.Element);
|
||||||
theme?: string;
|
theme?: Themes;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import { Themes } from 'app/core/components/Tooltip/Popper';
|
|||||||
interface RenderProps {
|
interface RenderProps {
|
||||||
loading: LoadingState;
|
loading: LoadingState;
|
||||||
timeSeries: TimeSeries[];
|
timeSeries: TimeSeries[];
|
||||||
|
onRenderError: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
@@ -35,6 +36,7 @@ export interface Props {
|
|||||||
export interface State {
|
export interface State {
|
||||||
isFirstLoad: boolean;
|
isFirstLoad: boolean;
|
||||||
loading: LoadingState;
|
loading: LoadingState;
|
||||||
|
errorMessage: string;
|
||||||
response: DataQueryResponse;
|
response: DataQueryResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,6 +55,7 @@ export class DataPanel extends Component<Props, State> {
|
|||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
loading: LoadingState.NotStarted,
|
loading: LoadingState.NotStarted,
|
||||||
|
errorMessage: '',
|
||||||
response: {
|
response: {
|
||||||
data: [],
|
data: [],
|
||||||
},
|
},
|
||||||
@@ -92,7 +95,7 @@ export class DataPanel extends Component<Props, State> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState({ loading: LoadingState.Loading });
|
this.setState({ loading: LoadingState.Loading, errorMessage: '' });
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const ds = await this.dataSourceSrv.get(datasource);
|
const ds = await this.dataSourceSrv.get(datasource);
|
||||||
@@ -130,10 +133,24 @@ export class DataPanel extends Component<Props, State> {
|
|||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log('Loading error', err);
|
console.log('Loading error', err);
|
||||||
this.setState({ loading: LoadingState.Error, isFirstLoad: false });
|
this.onError('Request Error');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
onError = (errorMessage: string) => {
|
||||||
|
if (this.state.loading !== LoadingState.Error || this.state.errorMessage !== errorMessage) {
|
||||||
|
this.setState({
|
||||||
|
loading: LoadingState.Error,
|
||||||
|
isFirstLoad: false,
|
||||||
|
errorMessage: errorMessage
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onRenderError = () => {
|
||||||
|
this.onError('Error rendering panel');
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { queries } = this.props;
|
const { queries } = this.props;
|
||||||
const { response, loading, isFirstLoad } = this.state;
|
const { response, loading, isFirstLoad } = this.state;
|
||||||
@@ -158,13 +175,14 @@ export class DataPanel extends Component<Props, State> {
|
|||||||
{this.props.children({
|
{this.props.children({
|
||||||
timeSeries,
|
timeSeries,
|
||||||
loading,
|
loading,
|
||||||
|
onRenderError: this.onRenderError
|
||||||
})}
|
})}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private renderLoadingStates(): JSX.Element {
|
private renderLoadingStates(): JSX.Element {
|
||||||
const { loading } = this.state;
|
const { loading, errorMessage } = this.state;
|
||||||
if (loading === LoadingState.Loading) {
|
if (loading === LoadingState.Loading) {
|
||||||
return (
|
return (
|
||||||
<div className="panel-loading">
|
<div className="panel-loading">
|
||||||
@@ -174,7 +192,7 @@ export class DataPanel extends Component<Props, State> {
|
|||||||
} else if (loading === LoadingState.Error) {
|
} else if (loading === LoadingState.Error) {
|
||||||
return (
|
return (
|
||||||
<Tooltip
|
<Tooltip
|
||||||
content="Request Error"
|
content={errorMessage}
|
||||||
className="popper__manager--block"
|
className="popper__manager--block"
|
||||||
refClassName={`panel-info-corner panel-info-corner--error`}
|
refClassName={`panel-info-corner panel-info-corner--error`}
|
||||||
placement="bottom-start"
|
placement="bottom-start"
|
||||||
|
|||||||
@@ -87,7 +87,6 @@ export class PanelChrome extends PureComponent<Props, State> {
|
|||||||
const { datasource, targets, transparent } = panel;
|
const { datasource, targets, transparent } = panel;
|
||||||
const PanelComponent = plugin.exports.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>
|
||||||
{({ width, height }) => {
|
{({ width, height }) => {
|
||||||
@@ -115,7 +114,7 @@ export class PanelChrome extends PureComponent<Props, State> {
|
|||||||
widthPixels={width}
|
widthPixels={width}
|
||||||
refreshCounter={refreshCounter}
|
refreshCounter={refreshCounter}
|
||||||
>
|
>
|
||||||
{({ loading, timeSeries }) => {
|
{({ loading, timeSeries, onRenderError }) => {
|
||||||
return (
|
return (
|
||||||
<div className="panel-content">
|
<div className="panel-content">
|
||||||
<PanelComponent
|
<PanelComponent
|
||||||
@@ -126,6 +125,7 @@ export class PanelChrome extends PureComponent<Props, State> {
|
|||||||
width={width}
|
width={width}
|
||||||
height={height - PANEL_HEADER_HEIGHT}
|
height={height - PANEL_HEADER_HEIGHT}
|
||||||
renderCounter={renderCounter}
|
renderCounter={renderCounter}
|
||||||
|
onRenderError={onRenderError}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// Libraries
|
// Libraries
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import React, { PureComponent } from 'react';
|
import React, { Component } from 'react';
|
||||||
import colors from 'app/core/utils/colors';
|
import colors from 'app/core/utils/colors';
|
||||||
|
|
||||||
// Components & Types
|
// Components & Types
|
||||||
@@ -9,13 +9,13 @@ import { Options } from './types';
|
|||||||
|
|
||||||
interface Props extends PanelProps<Options> {}
|
interface Props extends PanelProps<Options> {}
|
||||||
|
|
||||||
export class GraphPanel extends PureComponent<Props> {
|
export class GraphPanel extends Component<Props> {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { timeSeries, timeRange, width, height } = this.props;
|
const { timeSeries, timeRange, width, height, onRenderError } = this.props;
|
||||||
const { showLines, showBars, showPoints } = this.props.options;
|
const { showLines, showBars, showPoints } = this.props.options;
|
||||||
|
|
||||||
const vmSeries = processTimeSeries({
|
const vmSeries = processTimeSeries({
|
||||||
@@ -33,6 +33,7 @@ export class GraphPanel extends PureComponent<Props> {
|
|||||||
showBars={showBars}
|
showBars={showBars}
|
||||||
width={width}
|
width={width}
|
||||||
height={height}
|
height={height}
|
||||||
|
onRenderError={onRenderError}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -233,7 +233,7 @@ div.flot-text {
|
|||||||
|
|
||||||
&--error {
|
&--error {
|
||||||
display: block;
|
display: block;
|
||||||
color: $text-color;
|
color: $white;
|
||||||
@include panel-corner-color($popover-error-bg);
|
@include panel-corner-color($popover-error-bg);
|
||||||
.fa:before {
|
.fa:before {
|
||||||
content: '\f12a';
|
content: '\f12a';
|
||||||
|
|||||||
Reference in New Issue
Block a user