mirror of
https://github.com/scratchfoundation/scratch-www.git
synced 2024-11-26 17:16:11 -05:00
Add Error Boundary and Crash message
Added all the strings to general l10n as error boundary/crash message applies to all pages.
This commit is contained in:
parent
37437636ff
commit
53ca763646
6 changed files with 116 additions and 15 deletions
38
src/components/crashmessage/crashmessage.jsx
Normal file
38
src/components/crashmessage/crashmessage.jsx
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
const classNames = require('classnames');
|
||||||
|
const PropTypes = require('prop-types');
|
||||||
|
const React = require('react');
|
||||||
|
const FormattedMessage = require('react-intl').FormattedMessage;
|
||||||
|
|
||||||
|
const Button = require('../forms/button.jsx');
|
||||||
|
|
||||||
|
require('./crashmessage.scss');
|
||||||
|
|
||||||
|
const CrashMessage = props => (
|
||||||
|
<div className={classNames(['crash-container', props.className])}>
|
||||||
|
<img
|
||||||
|
className=""
|
||||||
|
src="/images/unhandled.png"
|
||||||
|
/>
|
||||||
|
<div className="crash-message">
|
||||||
|
<h2>
|
||||||
|
<FormattedMessage id="general.error" />
|
||||||
|
</h2>
|
||||||
|
<p>
|
||||||
|
<FormattedMessage id="general.unhandledError" />
|
||||||
|
</p>
|
||||||
|
<Button
|
||||||
|
className=""
|
||||||
|
onClick={props.onBack}
|
||||||
|
>
|
||||||
|
<FormattedMessage id="general.back" />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
CrashMessage.propTypes = {
|
||||||
|
className: PropTypes.string,
|
||||||
|
onBack: PropTypes.func
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = CrashMessage;
|
22
src/components/crashmessage/crashmessage.scss
Normal file
22
src/components/crashmessage/crashmessage.scss
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
.crash-container {
|
||||||
|
@import "../../colors";
|
||||||
|
@import "../../frameless";
|
||||||
|
|
||||||
|
margin: 3rem auto;
|
||||||
|
|
||||||
|
border: 1px solid $ui-border;
|
||||||
|
border-radius: 10px;
|
||||||
|
background-color: $background-color;
|
||||||
|
width: 60%;
|
||||||
|
overflow: hidden;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.crash-message {
|
||||||
|
margin: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
36
src/components/errorboundary/errorboundary.jsx
Normal file
36
src/components/errorboundary/errorboundary.jsx
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
const PropTypes = require('prop-types');
|
||||||
|
const React = require('react');
|
||||||
|
|
||||||
|
const CrashMessageComponent = require('../crashmessage/crashmessage.jsx');
|
||||||
|
import log from '../../lib/log.js';
|
||||||
|
|
||||||
|
class ErrorBoundary extends React.Component {
|
||||||
|
constructor (props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
hasError: false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidCatch (error, info) {
|
||||||
|
// Display fallback UI
|
||||||
|
this.setState({hasError: true});
|
||||||
|
log.error(`Unhandled Error: ${error}, info: ${info}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleBack () {
|
||||||
|
window.history.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
render () {
|
||||||
|
if (this.state.hasError) {
|
||||||
|
return <CrashMessageComponent onBack={this.handleBack} />;
|
||||||
|
}
|
||||||
|
return this.props.children;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ErrorBoundary.propTypes = {
|
||||||
|
children: PropTypes.node
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = ErrorBoundary;
|
|
@ -4,8 +4,10 @@ const React = require('react');
|
||||||
|
|
||||||
const Navigation = require('../../navigation/www/navigation.jsx');
|
const Navigation = require('../../navigation/www/navigation.jsx');
|
||||||
const Footer = require('../../footer/www/footer.jsx');
|
const Footer = require('../../footer/www/footer.jsx');
|
||||||
|
const ErrorBoundary = require('../../errorboundary/errorboundary.jsx');
|
||||||
|
|
||||||
const Page = props => (
|
const Page = props => (
|
||||||
|
<ErrorBoundary>
|
||||||
<div className="page">
|
<div className="page">
|
||||||
<div
|
<div
|
||||||
className={classNames({
|
className={classNames({
|
||||||
|
@ -22,6 +24,7 @@ const Page = props => (
|
||||||
<Footer />
|
<Footer />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</ErrorBoundary>
|
||||||
);
|
);
|
||||||
|
|
||||||
Page.propTypes = {
|
Page.propTypes = {
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
"general.accountSettings": "Account settings",
|
"general.accountSettings": "Account settings",
|
||||||
"general.about": "About",
|
"general.about": "About",
|
||||||
"general.aboutScratch": "About Scratch",
|
"general.aboutScratch": "About Scratch",
|
||||||
|
"general.back": "Back",
|
||||||
"general.birthMonth": "Birth Month",
|
"general.birthMonth": "Birth Month",
|
||||||
"general.birthYear": "Birth Year",
|
"general.birthYear": "Birth Year",
|
||||||
"general.donate": "Donate",
|
"general.donate": "Donate",
|
||||||
|
@ -73,6 +74,7 @@
|
||||||
"general.tips": "Tips",
|
"general.tips": "Tips",
|
||||||
"general.tipsWindow": "Tips Window",
|
"general.tipsWindow": "Tips Window",
|
||||||
"general.termsOfUse": "Terms of Use",
|
"general.termsOfUse": "Terms of Use",
|
||||||
|
"general.unhandledError": "We are so sorry, but it looks like Scratch has crashed. This bug has been automatically reported to the Scratch Team.",
|
||||||
"general.username": "Username",
|
"general.username": "Username",
|
||||||
"general.validationEmail": "Please enter a valid email address",
|
"general.validationEmail": "Please enter a valid email address",
|
||||||
"general.validationEmailMatch": "The emails do not match",
|
"general.validationEmailMatch": "The emails do not match",
|
||||||
|
|
BIN
static/images/unhandled.png
Normal file
BIN
static/images/unhandled.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 32 KiB |
Loading…
Reference in a new issue