Make error boundary more helpful

Signed-off-by: Tejas Kumar <tejask@spotify.com>
This commit is contained in:
Tejas Kumar
2021-05-20 17:13:17 +02:00
committed by Fredrik Adelöw
parent 46d6a27eb5
commit dcb5403042
4 changed files with 72 additions and 10 deletions
@@ -14,10 +14,12 @@
* limitations under the License.
*/
import React, { ComponentClass, Component, ErrorInfo } from 'react';
import { Button, CardContent, CardHeader } from '@material-ui/core';
import React, { ComponentClass, Component, ErrorInfo, useState } from 'react';
import { slackChannel as defaultSlackChannel } from '../constants';
type Props = {
slackChannel?: string;
slackChannel?: typeof defaultSlackChannel;
onError?: (error: Error, errorInfo: string) => null;
};
@@ -28,15 +30,54 @@ type State = {
type EProps = {
error?: Error;
slackChannel?: string;
slackChannel?: typeof defaultSlackChannel;
children?: React.ReactNode;
};
const Error = ({ slackChannel }: EProps) => {
const Error = ({ slackChannel, error }: EProps) => {
const [isShowingTrace, setIsShowingTrace] = useState(false);
return (
<div role="alert">
Something went wrong here.{' '}
{slackChannel && <>Please contact {slackChannel} for help.</>}
<CardHeader title="Something Went Wrong" />
<CardContent>
<p>
<strong>Error:</strong> {error?.message ?? 'No Further Info'}
</p>
<div>
<Button
onClick={() => setIsShowingTrace(!isShowingTrace)}
variant="contained"
color="primary"
>
{isShowingTrace ? 'Hide' : 'Show'} Details
</Button>
</div>
{isShowingTrace && (
<pre style={{ overflow: 'auto' }}>
<code>
{error?.stack?.split('\n').map(line => (
<>
{line}
<br />
</>
)) ?? ''}
</code>
</pre>
)}
{slackChannel && (
<p>
Please contact{' '}
<a
href={slackChannel.href}
target="_blank"
rel="noopener noreferrer"
>
<u>{slackChannel.name}</u>
</a>{' '}
for help.
</p>
)}
</CardContent>
</div>
);
};
@@ -28,6 +28,7 @@ import {
import classNames from 'classnames';
import { ErrorBoundary } from '../ErrorBoundary';
import { BottomLink, BottomLinkProps } from '../BottomLink';
import { slackChannel as defaultSlackChannel } from '../constants';
const useStyles = makeStyles(theme => ({
noPadding: {
@@ -112,7 +113,7 @@ type Props = {
subheader?: ReactNode;
divider?: boolean;
deepLink?: BottomLinkProps;
slackChannel?: string;
slackChannel?: typeof defaultSlackChannel;
variant?: InfoCardVariants;
style?: object;
cardStyle?: object;
@@ -133,7 +134,7 @@ export const InfoCard = ({
subheader,
divider = true,
deepLink,
slackChannel = '#backstage',
slackChannel = defaultSlackChannel,
variant,
children,
headerStyle,
@@ -33,6 +33,7 @@ import {
} from '@material-ui/core';
import { BottomLink, BottomLinkProps } from '../BottomLink';
import { ErrorBoundary } from '../ErrorBoundary';
import { slackChannel as defaultSlackChannel } from '../constants';
const useTabsStyles = makeStyles(theme => ({
root: {
@@ -52,7 +53,7 @@ const BoldHeader = withStyles(theme => ({
}))(CardHeader);
type Props = {
slackChannel?: string;
slackChannel?: typeof defaultSlackChannel;
children?: ReactElement<TabProps>[];
onChange?: (event: React.ChangeEvent<{}>, value: number | string) => void;
title?: string;
@@ -61,7 +62,7 @@ type Props = {
};
const TabbedCard = ({
slackChannel = '#backstage',
slackChannel = defaultSlackChannel,
children,
title,
deepLink,
+19
View File
@@ -0,0 +1,19 @@
/*
* Copyright 2021 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export const slackChannel = {
name: '#backstage',
href: 'https://spotify.slack.com/archives/C54P1J36Z',
};