Merge pull request #471 from outline/jori/document-error-boundary

More detailed error boundary for Document
This commit is contained in:
Jori Lallo
2017-12-03 21:03:47 -08:00
committed by GitHub
3 changed files with 80 additions and 71 deletions

View File

@ -8,7 +8,7 @@ type Props = {
const Container = styled.div`
width: 100%;
margin: 60px;
padding: 60px;
`;
const Content = styled.div`

View File

@ -5,8 +5,13 @@ import { observable } from 'mobx';
import CenteredContent from 'components/CenteredContent';
import PageTitle from 'components/PageTitle';
type Props = {
children?: ?React.Element<any>,
};
@observer
class ErrorBoundary extends Component {
props: Props;
@observable error: boolean = false;
componentDidCatch(error: Error, info: Object) {
@ -27,9 +32,10 @@ class ErrorBoundary extends Component {
return (
<CenteredContent>
<PageTitle title="Something went wrong" />
<h1>Something went wrong</h1>
<h1>🛸 Something unexpected happened</h1>
<p>
An unrecoverable error occurred. Please try{' '}
An unrecoverable error occurred{window.Bugsnag ||
(true && ' and our engineers have been notified')}. Please try{' '}
<a onClick={this.handleReload}>reloading</a>.
</p>
</CenteredContent>

View File

@ -33,6 +33,7 @@ import CenteredContent from 'components/CenteredContent';
import PageTitle from 'components/PageTitle';
import NewDocumentIcon from 'components/Icon/NewDocumentIcon';
import Actions, { Action, Separator } from 'components/Actions';
import ErrorBoundary from 'components/ErrorBoundary';
import Search from 'scenes/Search';
const DISCARD_CHANGES = `
@ -216,75 +217,77 @@ class DocumentScene extends Component {
return (
<Container column auto>
{isMoving && document && <DocumentMove document={document} />}
{titleText && <PageTitle title={titleText} />}
{(this.isLoading || this.isSaving) && <LoadingIndicator />}
{isFetching && (
<CenteredContent>
<LoadingState />
</CenteredContent>
)}
{!isFetching &&
document && (
<Flex justify="center" auto>
<Prompt
when={document.hasPendingChanges}
message={DISCARD_CHANGES}
/>
<Editor
key={`${document.id}-${document.revision}`}
text={document.text}
emoji={document.emoji}
onImageUploadStart={this.onImageUploadStart}
onImageUploadStop={this.onImageUploadStop}
onChange={this.onChange}
onSave={this.onSave}
onCancel={this.onDiscard}
readOnly={!this.isEditing}
/>
<Actions
align="center"
justify="flex-end"
readOnly={!this.isEditing}
>
{!isNew &&
!this.isEditing && <Collaborators document={document} />}
<Action>
{this.isEditing ? (
<SaveAction
isSaving={this.isSaving}
onClick={this.onSave.bind(this, true)}
disabled={
!(this.document && this.document.allowSave) ||
this.isSaving
}
isNew={!!isNew}
/>
) : (
<a onClick={this.onClickEdit}>Edit</a>
)}
</Action>
{this.isEditing && (
<Action>
<a onClick={this.onDiscard}>Discard</a>
</Action>
)}
{!this.isEditing && (
<Action>
<DocumentMenu document={document} />
</Action>
)}
{!this.isEditing && <Separator />}
<Action>
{!this.isEditing && (
<a onClick={this.onClickNew}>
<NewDocumentIcon />
</a>
)}
</Action>
</Actions>
</Flex>
<ErrorBoundary key={this.props.location.pathname}>
{isMoving && document && <DocumentMove document={document} />}
{titleText && <PageTitle title={titleText} />}
{(this.isLoading || this.isSaving) && <LoadingIndicator />}
{isFetching && (
<CenteredContent>
<LoadingState />
</CenteredContent>
)}
{!isFetching &&
document && (
<Flex justify="center" auto>
<Prompt
when={document.hasPendingChanges}
message={DISCARD_CHANGES}
/>
<Editor
key={`${document.id}-${document.revision}`}
text={document.text}
emoji={document.emoji}
onImageUploadStart={this.onImageUploadStart}
onImageUploadStop={this.onImageUploadStop}
onChange={this.onChange}
onSave={this.onSave}
onCancel={this.onDiscard}
readOnly={!this.isEditing}
/>
<Actions
align="center"
justify="flex-end"
readOnly={!this.isEditing}
>
{!isNew &&
!this.isEditing && <Collaborators document={document} />}
<Action>
{this.isEditing ? (
<SaveAction
isSaving={this.isSaving}
onClick={this.onSave.bind(this, true)}
disabled={
!(this.document && this.document.allowSave) ||
this.isSaving
}
isNew={!!isNew}
/>
) : (
<a onClick={this.onClickEdit}>Edit</a>
)}
</Action>
{this.isEditing && (
<Action>
<a onClick={this.onDiscard}>Discard</a>
</Action>
)}
{!this.isEditing && (
<Action>
<DocumentMenu document={document} />
</Action>
)}
{!this.isEditing && <Separator />}
<Action>
{!this.isEditing && (
<a onClick={this.onClickNew}>
<NewDocumentIcon />
</a>
)}
</Action>
</Actions>
</Flex>
)}
</ErrorBoundary>
</Container>
);
}