mirror of
https://github.com/grafana/grafana.git
synced 2025-01-16 11:42:35 -06:00
Prometheus: Fixed Prometheus query editor error (plus new ErrorBoundaryAlert component) (#18838)
* ErrorHandling: Fixed Prometheus query editor error and added error boundary * Update public/app/core/components/ErrorBoundary/ErrorBoundary.tsx Co-Authored-By: kay delaney <45561153+kaydelaney@users.noreply.github.com> * Fixed ts error
This commit is contained in:
parent
29ff8e6018
commit
fe658d7ac2
@ -1,15 +1,16 @@
|
||||
import React, { FC } from 'react';
|
||||
import React, { FC, ReactNode } from 'react';
|
||||
|
||||
interface Props {
|
||||
message: any;
|
||||
title: string;
|
||||
button?: {
|
||||
text: string;
|
||||
onClick: (event: React.MouseEvent) => void;
|
||||
};
|
||||
children?: ReactNode;
|
||||
}
|
||||
|
||||
export const Alert: FC<Props> = props => {
|
||||
const { message, button } = props;
|
||||
const { title, button, children } = props;
|
||||
return (
|
||||
<div className="alert-container">
|
||||
<div className="alert-error alert">
|
||||
@ -17,7 +18,8 @@ export const Alert: FC<Props> = props => {
|
||||
<i className="fa fa-exclamation-triangle" />
|
||||
</div>
|
||||
<div className="alert-body">
|
||||
<div className="alert-title">{message}</div>
|
||||
<div className="alert-title">{title}</div>
|
||||
{children && <div className="alert-text">{children}</div>}
|
||||
</div>
|
||||
{button && (
|
||||
<div className="alert-button">
|
||||
|
@ -179,7 +179,7 @@ const LogRowContextGroup: React.FunctionComponent<LogRowContextGroupProps> = ({
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{error && <Alert message={error} />}
|
||||
{error && <Alert title={error} />}
|
||||
</div>
|
||||
</CustomScrollbar>
|
||||
</div>
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { Component } from 'react';
|
||||
import React, { PureComponent, ReactNode } from 'react';
|
||||
import { Alert } from '@grafana/ui';
|
||||
|
||||
interface ErrorInfo {
|
||||
componentStack: string;
|
||||
@ -10,7 +11,7 @@ interface RenderProps {
|
||||
}
|
||||
|
||||
interface Props {
|
||||
children: (r: RenderProps) => JSX.Element;
|
||||
children: (r: RenderProps) => ReactNode;
|
||||
}
|
||||
|
||||
interface State {
|
||||
@ -18,7 +19,7 @@ interface State {
|
||||
errorInfo: ErrorInfo;
|
||||
}
|
||||
|
||||
class ErrorBoundary extends Component<Props, State> {
|
||||
export class ErrorBoundary extends PureComponent<Props, State> {
|
||||
readonly state: State = {
|
||||
error: null,
|
||||
errorInfo: null,
|
||||
@ -41,4 +42,36 @@ class ErrorBoundary extends Component<Props, State> {
|
||||
}
|
||||
}
|
||||
|
||||
export default ErrorBoundary;
|
||||
interface WithAlertBoxProps {
|
||||
title?: string;
|
||||
children: ReactNode;
|
||||
}
|
||||
|
||||
export class ErrorBoundaryAlert extends PureComponent<WithAlertBoxProps> {
|
||||
static defaultProps: Partial<WithAlertBoxProps> = {
|
||||
title: 'An unexpected error happened',
|
||||
};
|
||||
|
||||
render() {
|
||||
const { title, children } = this.props;
|
||||
return (
|
||||
<ErrorBoundary>
|
||||
{({ error, errorInfo }) => {
|
||||
if (!errorInfo) {
|
||||
return children;
|
||||
}
|
||||
|
||||
return (
|
||||
<Alert title={title}>
|
||||
<details style={{ whiteSpace: 'pre-wrap' }}>
|
||||
{error && error.toString()}
|
||||
<br />
|
||||
{errorInfo.componentStack}
|
||||
</details>
|
||||
</Alert>
|
||||
);
|
||||
}}
|
||||
</ErrorBoundary>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import { Unsubscribable } from 'rxjs';
|
||||
|
||||
// Components
|
||||
import { PanelHeader } from './PanelHeader/PanelHeader';
|
||||
import ErrorBoundary from 'app/core/components/ErrorBoundary/ErrorBoundary';
|
||||
import { ErrorBoundary } from 'app/core/components/ErrorBoundary/ErrorBoundary';
|
||||
|
||||
// Utils & Services
|
||||
import { getTimeSrv, TimeSrv } from '../services/TimeSrv';
|
||||
|
@ -8,6 +8,7 @@ import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
|
||||
import { AngularComponent, getAngularLoader } from '@grafana/runtime';
|
||||
import { Emitter } from 'app/core/utils/emitter';
|
||||
import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv';
|
||||
import { ErrorBoundaryAlert } from 'app/core/components/ErrorBoundary/ErrorBoundary';
|
||||
|
||||
// Types
|
||||
import { PanelModel } from '../state/PanelModel';
|
||||
@ -257,7 +258,9 @@ export class QueryEditorRow extends PureComponent<Props, State> {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className={bodyClasses}>{this.renderPluginEditor()}</div>
|
||||
<div className={bodyClasses}>
|
||||
<ErrorBoundaryAlert title="Data source query editor failed">{this.renderPluginEditor()}</ErrorBoundaryAlert>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { Component } from 'react';
|
||||
|
||||
export default class ErrorBoundary extends Component<{}, any> {
|
||||
export class ErrorBoundary extends Component<{}, any> {
|
||||
constructor(props: {}) {
|
||||
super(props);
|
||||
this.state = { error: null, errorInfo: null };
|
||||
|
@ -12,7 +12,7 @@ import store from 'app/core/store';
|
||||
|
||||
// Components
|
||||
import { Alert } from '@grafana/ui';
|
||||
import ErrorBoundary from './ErrorBoundary';
|
||||
import { ErrorBoundary } from './ErrorBoundary';
|
||||
import LogsContainer from './LogsContainer';
|
||||
import QueryRows from './QueryRows';
|
||||
import TableContainer from './TableContainer';
|
||||
@ -263,7 +263,7 @@ export class Explore extends React.PureComponent<ExploreProps> {
|
||||
<FadeIn duration={datasourceError ? 150 : 5} in={datasourceError ? true : false}>
|
||||
<div className="explore-container">
|
||||
<Alert
|
||||
message={`Error connecting to datasource: ${datasourceError}`}
|
||||
title={`Error connecting to datasource: ${datasourceError}`}
|
||||
button={{ text: 'Reconnect', onClick: this.onReconnect }}
|
||||
/>
|
||||
</div>
|
||||
|
@ -5,7 +5,7 @@ import { connect } from 'react-redux';
|
||||
import { StoreState } from 'app/types';
|
||||
import { ExploreId } from 'app/types/explore';
|
||||
|
||||
import ErrorBoundary from './ErrorBoundary';
|
||||
import { ErrorBoundary } from './ErrorBoundary';
|
||||
import Explore from './Explore';
|
||||
import { CustomScrollbar } from '@grafana/ui';
|
||||
import { resetExploreAction } from './state/actionTypes';
|
||||
|
@ -154,7 +154,8 @@ class PromQueryField extends React.PureComponent<PromQueryFieldProps, PromQueryF
|
||||
|
||||
componentDidUpdate(prevProps: PromQueryFieldProps) {
|
||||
const { queryResponse } = this.props;
|
||||
if (prevProps.queryResponse && prevProps.queryResponse.series !== queryResponse.series) {
|
||||
|
||||
if (queryResponse && prevProps.queryResponse && prevProps.queryResponse.series !== queryResponse.series) {
|
||||
this.refreshHint();
|
||||
}
|
||||
|
||||
@ -177,7 +178,7 @@ class PromQueryField extends React.PureComponent<PromQueryFieldProps, PromQueryF
|
||||
refreshHint = () => {
|
||||
const { datasource, query, queryResponse } = this.props;
|
||||
|
||||
if (!queryResponse.series || queryResponse.series.length === 0) {
|
||||
if (!queryResponse || queryResponse.series.length === 0) {
|
||||
this.setState({ hint: null });
|
||||
return;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user