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