From 892ce6471275f75971a4bb811d7ad35e1975630c Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Sat, 4 Aug 2018 10:48:07 -0700 Subject: [PATCH 1/2] Catch errors around document rendering --- app/components/ErrorBoundary.js | 64 ++++++++++++ app/components/ErrorBoundary/ErrorBoundary.js | 52 ---------- app/components/ErrorBoundary/index.js | 3 - app/index.js | 8 +- app/scenes/Document/Document.js | 99 ++++++++++--------- 5 files changed, 119 insertions(+), 107 deletions(-) create mode 100644 app/components/ErrorBoundary.js delete mode 100644 app/components/ErrorBoundary/ErrorBoundary.js delete mode 100644 app/components/ErrorBoundary/index.js diff --git a/app/components/ErrorBoundary.js b/app/components/ErrorBoundary.js new file mode 100644 index 000000000..cdda40444 --- /dev/null +++ b/app/components/ErrorBoundary.js @@ -0,0 +1,64 @@ +// @flow +import * as React from 'react'; +import { observer } from 'mobx-react'; +import { observable } from 'mobx'; +import HelpText from 'components/HelpText'; +import Button from 'components/Button'; +import CenteredContent from 'components/CenteredContent'; +import PageTitle from 'components/PageTitle'; +import { githubIssuesUrl } from '../../shared/utils/routeHelpers'; + +type Props = { + children: React.Node, +}; + +@observer +class ErrorBoundary extends React.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(); + }; + + contactSupport = () => { + window.open(githubIssuesUrl()); + }; + + render() { + if (this.error) { + const isReported = !!window.Bugsnag; + + return ( + + +

Something Unexpected Happened

+ + Sorry, an unrecoverable error occurred{isReported && + ' – our engineers have been notified'}. Please try reloading the + page, it may have been a temporary glitch. + +

+ {' '} + {DEPLOYMENT === 'hosted' && ( + + )} +

+
+ ); + } + return this.props.children; + } +} + +export default ErrorBoundary; diff --git a/app/components/ErrorBoundary/ErrorBoundary.js b/app/components/ErrorBoundary/ErrorBoundary.js deleted file mode 100644 index 239aaf992..000000000 --- a/app/components/ErrorBoundary/ErrorBoundary.js +++ /dev/null @@ -1,52 +0,0 @@ -// @flow -import * as React from 'react'; -import { observer } from 'mobx-react'; -import { observable } from 'mobx'; -import CenteredContent from 'components/CenteredContent'; -import PageTitle from 'components/PageTitle'; - -type Props = { - children?: ?React.Node, -}; - -@observer -class ErrorBoundary extends React.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 ( - - -

- - 🛸 - {' '} - Something unexpected happened -

-

- An unrecoverable error occurred{window.Bugsnag || - (true && ' and our engineers have been notified')}. Please try{' '} - reloading. -

-
- ); - } - return this.props.children; - } -} - -export default ErrorBoundary; diff --git a/app/components/ErrorBoundary/index.js b/app/components/ErrorBoundary/index.js deleted file mode 100644 index 60fd48261..000000000 --- a/app/components/ErrorBoundary/index.js +++ /dev/null @@ -1,3 +0,0 @@ -// @flow -import ErrorBoundary from './ErrorBoundary'; -export default ErrorBoundary; diff --git a/app/index.js b/app/index.js index 8d64d53cf..d0f085aae 100644 --- a/app/index.js +++ b/app/index.js @@ -57,8 +57,8 @@ const element = document.getElementById('root'); if (element) { render( - - + + @@ -143,8 +143,8 @@ if (element) { - - + + {DevTools && } , element diff --git a/app/scenes/Document/Document.js b/app/scenes/Document/Document.js index 763a54092..5563a2e9c 100644 --- a/app/scenes/Document/Document.js +++ b/app/scenes/Document/Document.js @@ -27,6 +27,7 @@ import DocumentMove from './components/DocumentMove'; import UiStore from 'stores/UiStore'; import AuthStore from 'stores/AuthStore'; import DocumentsStore from 'stores/DocumentsStore'; +import ErrorBoundary from 'components/ErrorBoundary'; import LoadingPlaceholder from 'components/LoadingPlaceholder'; import LoadingIndicator from 'components/LoadingIndicator'; import CenteredContent from 'components/CenteredContent'; @@ -286,57 +287,59 @@ class DocumentScene extends React.Component { } return ( - - {isMoving && } - - {(this.isUploading || this.isSaving) && } + + + {isMoving && } + + {(this.isUploading || this.isSaving) && } - - {this.isEditing && ( - - + {this.isEditing && ( + + + + + )} + {!isShare && ( +
- - - )} - {!isShare && ( -
- )} - - - + )} + + + + - + ); } } From d3aeff833db813e54c7e6604c8173a9d7dad3d2d Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Sat, 4 Aug 2018 10:56:36 -0700 Subject: [PATCH 2/2] Added ability to show more error details for reporting issue --- app/components/ErrorBoundary.js | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/app/components/ErrorBoundary.js b/app/components/ErrorBoundary.js index cdda40444..81bdbecf6 100644 --- a/app/components/ErrorBoundary.js +++ b/app/components/ErrorBoundary.js @@ -1,5 +1,6 @@ // @flow import * as React from 'react'; +import styled from 'styled-components'; import { observer } from 'mobx-react'; import { observable } from 'mobx'; import HelpText from 'components/HelpText'; @@ -14,10 +15,11 @@ type Props = { @observer class ErrorBoundary extends React.Component { - @observable error: boolean = false; + @observable error: ?Error; + @observable showDetails: boolean = false; componentDidCatch(error: Error, info: Object) { - this.error = true; + this.error = error; // Error handler is often blocked by the browser if (window.Bugsnag) { @@ -29,7 +31,11 @@ class ErrorBoundary extends React.Component { window.location.reload(); }; - contactSupport = () => { + handleShowDetails = () => { + this.showDetails = true; + }; + + handleReportBug = () => { window.open(githubIssuesUrl()); }; @@ -46,11 +52,16 @@ class ErrorBoundary extends React.Component { ' – our engineers have been notified'}. Please try reloading the page, it may have been a temporary glitch. + {this.showDetails &&
{this.error.toString()}
}

{' '} - {DEPLOYMENT === 'hosted' && ( - + ) : ( + )}

@@ -61,4 +72,11 @@ class ErrorBoundary extends React.Component { } } +const Pre = styled.pre` + background: ${props => props.theme.smoke}; + padding: 16px; + border-radius: 4px; + font-size: 12px; +`; + export default ErrorBoundary;