Added high level ErrorBoundary

This commit is contained in:
Tom Moor 2017-11-12 16:08:55 -08:00
parent 0909dc61ff
commit ee89fb852b
4 changed files with 106 additions and 52 deletions

View File

@ -15,6 +15,7 @@ type Props = {
readOnly: boolean,
component?: string,
attributes: Object,
className?: string,
};
function Heading(props: Props) {
@ -26,6 +27,7 @@ function Heading(props: Props) {
readOnly,
children,
component = 'h1',
className,
attributes,
} = props;
const parentIsDocument = parent instanceof Document;
@ -40,7 +42,7 @@ function Heading(props: Props) {
emoji && title.match(new RegExp(`^${emoji}\\s`));
return (
<Component {...attributes} id={slugish}>
<Component {...attributes} id={slugish} className={className}>
<Wrapper hasEmoji={startsWithEmojiAndSpace}>{children}</Wrapper>
{showPlaceholder && (
<Placeholder contentEditable={false}>

View File

@ -0,0 +1,42 @@
// @flow
import React, { Component } from 'react';
import { observer } from 'mobx-react';
import { observable } from 'mobx';
import CenteredContent from 'components/CenteredContent';
import PageTitle from 'components/PageTitle';
@observer
class ErrorBoundary extends Component {
@observable error: boolean = false;
componentDidCatch(error: Error, info: Object) {
this.error = true;
// Error handler is often blocked by the browser
if (window.Bugsnag) {
Bugsnag.notifyException(error, { react: info });
}
}
handleReload = () => {
window.location.reload();
};
render() {
if (this.error) {
return (
<CenteredContent>
<PageTitle title="Unknown Error" />
<h1>Something went wrong</h1>
<p>
An unrecoverable error occurred. Please try{' '}
<a onClick={this.handleReload}>reloading</a>.
</p>
</CenteredContent>
);
}
return this.props.children;
}
}
export default ErrorBoundary;

View File

@ -0,0 +1,3 @@
// @flow
import ErrorBoundary from './ErrorBoundary';
export default ErrorBoundary;

View File

@ -28,6 +28,7 @@ import Flatpage from 'scenes/Flatpage';
import ErrorAuth from 'scenes/ErrorAuth';
import Error404 from 'scenes/Error404';
import ErrorBoundary from 'components/ErrorBoundary';
import ScrollToTop from 'components/ScrollToTop';
import Layout from 'components/Layout';
import RouteSidebarHidden from 'components/RouteSidebarHidden';
@ -101,62 +102,68 @@ globalStyles();
render(
<div style={{ display: 'flex', flex: 1, height: '100%' }}>
<Provider {...stores}>
<Router>
<ScrollToTop>
<Switch>
<Route exact path="/" component={Home} />
<ErrorBoundary>
<Provider {...stores}>
<Router>
<ScrollToTop>
<Switch>
<Route exact path="/" component={Home} />
<Route exact path="/auth/slack" component={SlackAuth} />
<Route exact path="/auth/slack/commands" component={SlackAuth} />
<Route exact path="/auth/error" component={ErrorAuth} />
<Route exact path="/auth/slack" component={SlackAuth} />
<Route exact path="/auth/slack/commands" component={SlackAuth} />
<Route exact path="/auth/error" component={ErrorAuth} />
<Auth>
<Layout>
<Switch>
<Route exact path="/dashboard" component={Dashboard} />
<Route exact path="/starred" component={Starred} />
<Route exact path="/collections/:id" component={Collection} />
<Route
exact
path={`/d/${matchDocumentSlug}`}
component={RedirectDocument}
/>
<Route
exact
path={`/doc/${matchDocumentSlug}`}
component={Document}
/>
<Route
exact
path={`/doc/${matchDocumentSlug}/move`}
component={Document}
/>
<Auth>
<Layout>
<Switch>
<Route exact path="/dashboard" component={Dashboard} />
<Route exact path="/starred" component={Starred} />
<Route
exact
path="/collections/:id"
component={Collection}
/>
<Route
exact
path={`/d/${matchDocumentSlug}`}
component={RedirectDocument}
/>
<Route
exact
path={`/doc/${matchDocumentSlug}`}
component={Document}
/>
<Route
exact
path={`/doc/${matchDocumentSlug}/move`}
component={Document}
/>
<Route exact path="/search" component={Search} />
<Route exact path="/search/:query" component={Search} />
<Route exact path="/developers" component={Api} />
<Route exact path="/search" component={Search} />
<Route exact path="/search/:query" component={Search} />
<Route exact path="/developers" component={Api} />
<Route path="/404" component={Error404} />
<Route path="/404" component={Error404} />
<RouteSidebarHidden
exact
path={`/doc/${matchDocumentSlug}/edit`}
component={Document}
/>
<RouteSidebarHidden
exact
path="/collections/:id/new"
component={DocumentNew}
/>
<Route component={notFoundSearch} />
</Switch>
</Layout>
</Auth>
</Switch>
</ScrollToTop>
</Router>
</Provider>
<RouteSidebarHidden
exact
path={`/doc/${matchDocumentSlug}/edit`}
component={Document}
/>
<RouteSidebarHidden
exact
path="/collections/:id/new"
component={DocumentNew}
/>
<Route component={notFoundSearch} />
</Switch>
</Layout>
</Auth>
</Switch>
</ScrollToTop>
</Router>
</Provider>
</ErrorBoundary>
{DevTools && <DevTools position={{ bottom: 0, right: 0 }} />}
</div>,
document.getElementById('root')