diff --git a/packages/grafana-ui/src/components/Alert/Alert.tsx b/packages/grafana-ui/src/components/Alert/Alert.tsx index bc6ecca994a..81b7dab8ef4 100644 --- a/packages/grafana-ui/src/components/Alert/Alert.tsx +++ b/packages/grafana-ui/src/components/Alert/Alert.tsx @@ -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 => { - const { message, button } = props; + const { title, button, children } = props; return (
@@ -17,7 +18,8 @@ export const Alert: FC = props => {
-
{message}
+
{title}
+ {children &&
{children}
}
{button && (
diff --git a/packages/grafana-ui/src/components/Logs/LogRowContext.tsx b/packages/grafana-ui/src/components/Logs/LogRowContext.tsx index e5026477ebc..6d1dcf12697 100644 --- a/packages/grafana-ui/src/components/Logs/LogRowContext.tsx +++ b/packages/grafana-ui/src/components/Logs/LogRowContext.tsx @@ -179,7 +179,7 @@ const LogRowContextGroup: React.FunctionComponent = ({ }} /> )} - {error && } + {error && }
diff --git a/public/app/core/components/ErrorBoundary/ErrorBoundary.tsx b/public/app/core/components/ErrorBoundary/ErrorBoundary.tsx index aa4276e742f..92d2f24979a 100644 --- a/public/app/core/components/ErrorBoundary/ErrorBoundary.tsx +++ b/public/app/core/components/ErrorBoundary/ErrorBoundary.tsx @@ -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 { +export class ErrorBoundary extends PureComponent { readonly state: State = { error: null, errorInfo: null, @@ -41,4 +42,36 @@ class ErrorBoundary extends Component { } } -export default ErrorBoundary; +interface WithAlertBoxProps { + title?: string; + children: ReactNode; +} + +export class ErrorBoundaryAlert extends PureComponent { + static defaultProps: Partial = { + title: 'An unexpected error happened', + }; + + render() { + const { title, children } = this.props; + return ( + + {({ error, errorInfo }) => { + if (!errorInfo) { + return children; + } + + return ( + +
+ {error && error.toString()} +
+ {errorInfo.componentStack} +
+
+ ); + }} +
+ ); + } +} diff --git a/public/app/features/dashboard/dashgrid/PanelChrome.tsx b/public/app/features/dashboard/dashgrid/PanelChrome.tsx index dd4d4a1824e..afb0713cf83 100644 --- a/public/app/features/dashboard/dashgrid/PanelChrome.tsx +++ b/public/app/features/dashboard/dashgrid/PanelChrome.tsx @@ -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'; diff --git a/public/app/features/dashboard/panel_editor/QueryEditorRow.tsx b/public/app/features/dashboard/panel_editor/QueryEditorRow.tsx index ce4cbc4cc4d..3ba17d0dd95 100644 --- a/public/app/features/dashboard/panel_editor/QueryEditorRow.tsx +++ b/public/app/features/dashboard/panel_editor/QueryEditorRow.tsx @@ -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 { -
{this.renderPluginEditor()}
+
+ {this.renderPluginEditor()} +
); } diff --git a/public/app/features/explore/ErrorBoundary.tsx b/public/app/features/explore/ErrorBoundary.tsx index f80c9b06b8d..07b9eb1ea54 100644 --- a/public/app/features/explore/ErrorBoundary.tsx +++ b/public/app/features/explore/ErrorBoundary.tsx @@ -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 }; diff --git a/public/app/features/explore/Explore.tsx b/public/app/features/explore/Explore.tsx index 0838fae1215..1e1ab20ae3c 100644 --- a/public/app/features/explore/Explore.tsx +++ b/public/app/features/explore/Explore.tsx @@ -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 {
diff --git a/public/app/features/explore/Wrapper.tsx b/public/app/features/explore/Wrapper.tsx index 59d941acf14..7caa8e546f8 100644 --- a/public/app/features/explore/Wrapper.tsx +++ b/public/app/features/explore/Wrapper.tsx @@ -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'; diff --git a/public/app/plugins/datasource/prometheus/components/PromQueryField.tsx b/public/app/plugins/datasource/prometheus/components/PromQueryField.tsx index 37829da1022..d4e2b74b00d 100644 --- a/public/app/plugins/datasource/prometheus/components/PromQueryField.tsx +++ b/public/app/plugins/datasource/prometheus/components/PromQueryField.tsx @@ -154,7 +154,8 @@ class PromQueryField extends React.PureComponent { const { datasource, query, queryResponse } = this.props; - if (!queryResponse.series || queryResponse.series.length === 0) { + if (!queryResponse || queryResponse.series.length === 0) { this.setState({ hint: null }); return; }