2019-03-07 22:46:15 +01:00
|
|
|
// @flow
|
2019-08-13 07:35:13 +02:00
|
|
|
import type { Node } from 'react';
|
2020-01-03 20:45:34 +01:00
|
|
|
import React from 'react';
|
2019-03-07 22:46:15 +01:00
|
|
|
import Yrbl from 'component/yrbl';
|
|
|
|
import Button from 'component/button';
|
2019-05-10 18:43:11 +02:00
|
|
|
import { withRouter } from 'react-router';
|
2019-12-19 07:33:06 +01:00
|
|
|
import analytics from 'analytics';
|
2020-01-03 20:45:34 +01:00
|
|
|
import I18nMessage from 'component/i18nMessage';
|
2019-03-07 22:46:15 +01:00
|
|
|
|
|
|
|
type Props = {
|
2019-08-13 07:35:13 +02:00
|
|
|
children: Node,
|
2019-05-10 18:43:11 +02:00
|
|
|
history: {
|
|
|
|
replace: string => void,
|
|
|
|
},
|
2019-03-07 22:46:15 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
type State = {
|
|
|
|
hasError: boolean,
|
2020-02-04 20:37:17 +01:00
|
|
|
eventId: ?string,
|
2019-03-07 22:46:15 +01:00
|
|
|
};
|
|
|
|
|
2019-05-10 18:43:11 +02:00
|
|
|
class ErrorBoundary extends React.Component<Props, State> {
|
2019-03-07 22:46:15 +01:00
|
|
|
constructor() {
|
|
|
|
super();
|
2020-02-04 20:37:17 +01:00
|
|
|
this.state = { hasError: false, eventId: undefined };
|
2019-05-10 18:43:11 +02:00
|
|
|
|
|
|
|
(this: any).refresh = this.refresh.bind(this);
|
2019-03-07 22:46:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static getDerivedStateFromError() {
|
|
|
|
return { hasError: true };
|
|
|
|
}
|
|
|
|
|
2020-02-04 20:37:17 +01:00
|
|
|
componentDidCatch(error, errorInfo) {
|
|
|
|
analytics.error(error, errorInfo).then(eventId => {
|
|
|
|
this.setState({ eventId });
|
2019-05-20 18:02:22 +02:00
|
|
|
});
|
|
|
|
}
|
2019-04-14 19:22:36 +02:00
|
|
|
|
2019-05-10 18:43:11 +02:00
|
|
|
refresh() {
|
|
|
|
const { history } = this.props;
|
2020-02-04 20:37:17 +01:00
|
|
|
|
2019-05-10 18:43:11 +02:00
|
|
|
// use history.replace instead of history.push so the user can't click back to the errored page
|
|
|
|
history.replace('');
|
|
|
|
this.setState({ hasError: false });
|
|
|
|
}
|
|
|
|
|
2019-03-07 22:46:15 +01:00
|
|
|
render() {
|
2020-02-04 20:37:17 +01:00
|
|
|
const { hasError, eventId } = this.state;
|
|
|
|
|
|
|
|
if (hasError) {
|
2019-03-07 22:46:15 +01:00
|
|
|
return (
|
2019-06-28 09:27:55 +02:00
|
|
|
<div className="main main--empty">
|
2019-03-07 22:46:15 +01:00
|
|
|
<Yrbl
|
|
|
|
type="sad"
|
|
|
|
title={__('Aw shucks!')}
|
|
|
|
subtitle={
|
2020-01-03 20:45:34 +01:00
|
|
|
<I18nMessage
|
|
|
|
tokens={{
|
|
|
|
refreshing_the_app_link: (
|
|
|
|
<Button
|
|
|
|
button="link"
|
|
|
|
className="load-screen__button"
|
|
|
|
label={__('refreshing the app')}
|
|
|
|
onClick={this.refresh}
|
|
|
|
/>
|
|
|
|
),
|
|
|
|
}}
|
|
|
|
>
|
2020-02-04 20:37:17 +01:00
|
|
|
There was an error. Try %refreshing_the_app_link% to fix it. If that doesn't work, try pressing
|
|
|
|
Ctrl+R/Cmd+R.
|
2020-01-03 20:45:34 +01:00
|
|
|
</I18nMessage>
|
2019-03-07 22:46:15 +01:00
|
|
|
}
|
|
|
|
/>
|
2020-02-04 20:37:17 +01:00
|
|
|
{eventId === null && (
|
|
|
|
<div className="error-wrapper">
|
|
|
|
<span className="error-text">
|
|
|
|
{__('You are not currently sharing diagnostic data so this error was not reported.')}
|
|
|
|
</span>
|
|
|
|
</div>
|
|
|
|
)}
|
|
|
|
{eventId && (
|
|
|
|
<div className="error-wrapper">
|
|
|
|
<span className="error-text">{__('Error ID: %eventId%', { eventId })}</span>
|
|
|
|
</div>
|
|
|
|
)}
|
2019-03-07 22:46:15 +01:00
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
return this.props.children;
|
|
|
|
}
|
|
|
|
}
|
2019-05-10 18:43:11 +02:00
|
|
|
|
|
|
|
export default withRouter(ErrorBoundary);
|