#149: show bsod for 500 errors

This commit is contained in:
SleepWalker 2016-07-29 22:29:27 +03:00
parent 4394346a2a
commit ae11dbdc97
6 changed files with 50 additions and 13 deletions

View File

@ -0,0 +1,23 @@
import React from 'react';
import ReactDOM from 'react-dom';
import { bsod } from './actions';
import BSoD from 'components/ui/bsod/BSoD';
let injectedStore;
let onBsod;
export default function dispatchBsod(store = injectedStore) {
store.dispatch(bsod());
onBsod && onBsod();
ReactDOM.render(
<BSoD />,
document.getElementById('app')
);
}
export function inject(store, stopLoading) {
injectedStore = store;
onBsod = stopLoading;
}

View File

@ -0,0 +1,18 @@
import request from 'services/request';
import dispatchBsod, { inject } from './dispatchBsod';
export default function factory(store, stopLoading) {
inject(store, stopLoading);
// do bsod for 500 errors
request.addMiddleware({
catch(resp) {
if (resp && resp.originalResponse.status === 500) {
dispatchBsod();
}
return Promise.reject(resp);
}
});
}

View File

@ -10,14 +10,14 @@ import { factory as userFactory } from 'components/user/factory';
import { IntlProvider } from 'components/i18n'; import { IntlProvider } from 'components/i18n';
import routesFactory from 'routes'; import routesFactory from 'routes';
import storeFactory from 'storeFactory'; import storeFactory from 'storeFactory';
import bsodFactory from 'components/ui/bsod/factory';
const store = storeFactory(); const store = storeFactory();
bsodFactory(store, stopLoading);
userFactory(store) userFactory(store)
.then(() => { .then(() => {
// allow :active styles in mobile Safary
document.addEventListener('touchstart', () => {}, true);
ReactDOM.render( ReactDOM.render(
<ReduxProvider store={store}> <ReduxProvider store={store}>
<IntlProvider> <IntlProvider>

View File

@ -6,7 +6,6 @@ import classNames from 'classnames';
import Userbar from 'components/userbar/Userbar'; import Userbar from 'components/userbar/Userbar';
import PopupStack from 'components/ui/popup/PopupStack'; import PopupStack from 'components/ui/popup/PopupStack';
import BSoD from 'components/ui/bsod/BSoD';
import styles from './root.scss'; import styles from './root.scss';
@ -23,10 +22,6 @@ if (process.env.NODE_ENV === 'production') {
function RootPage(props) { function RootPage(props) {
const isRegisterPage = props.location.pathname === '/register'; const isRegisterPage = props.location.pathname === '/register';
if (props.bsod) {
return <BSoD />;
}
return ( return (
<div className={styles.root}> <div className={styles.root}>
<div id="view-port" className={classNames(styles.viewPort, { <div id="view-port" className={classNames(styles.viewPort, {
@ -61,7 +56,6 @@ RootPage.propTypes = {
pathname: PropTypes.string pathname: PropTypes.string
}).isRequired, }).isRequired,
children: PropTypes.element, children: PropTypes.element,
bsod: PropTypes.bool.isRequired,
logout: PropTypes.func.isRequired, logout: PropTypes.func.isRequired,
isPopupActive: PropTypes.bool.isRequired isPopupActive: PropTypes.bool.isRequired
}; };
@ -70,7 +64,6 @@ import { connect } from 'react-redux';
import { logout } from 'components/user/actions'; import { logout } from 'components/user/actions';
export default connect((state) => ({ export default connect((state) => ({
bsod: state.bsod,
user: state.user, user: state.user,
isPopupActive: state.popup.popups.length > 0 isPopupActive: state.popup.popups.length > 0
}), { }), {

View File

@ -1,2 +1,5 @@
import 'babel-polyfill'; import 'babel-polyfill';
import 'promise.prototype.finally'; import 'promise.prototype.finally';
// allow :active styles in mobile Safary
document.addEventListener('touchstart', () => {}, true);

View File

@ -54,7 +54,7 @@ export default {
* return a Promise that resolves to the new response. * return a Promise that resolves to the new response.
*/ */
addMiddleware(middleware) { addMiddleware(middleware) {
if (!middlewares.find((mdware) => mdware === middleware)) { if (!middlewares.some((mdware) => mdware === middleware)) {
middlewares.push(middleware); middlewares.push(middleware);
} }
} }
@ -62,7 +62,7 @@ export default {
const checkStatus = (resp) => Promise[resp.status >= 200 && resp.status < 300 ? 'resolve' : 'reject'](resp); const checkStatus = (resp) => Promise[resp.status >= 200 && resp.status < 300 ? 'resolve' : 'reject'](resp);
const toJSON = (resp) => resp.json(); const toJSON = (resp) => resp.json().then((json) => ({...json, originalResponse: resp}));
const rejectWithJSON = (resp) => toJSON(resp).then((resp) => {throw resp;}); const rejectWithJSON = (resp) => toJSON(resp).then((resp) => {throw resp;});
const handleResponseSuccess = (resp) => Promise[resp.success || typeof resp.success === 'undefined' ? 'resolve' : 'reject'](resp); const handleResponseSuccess = (resp) => Promise[resp.success || typeof resp.success === 'undefined' ? 'resolve' : 'reject'](resp);
@ -94,7 +94,7 @@ function runMiddlewares(action, data, restart) {
return middlewares return middlewares
.filter((middleware) => middleware[action]) .filter((middleware) => middleware[action])
.reduce( .reduce(
(promise, middleware) => promise.then((resp) => middleware[action](resp, restart)), (promise, middleware) => promise[/^catch|then$/.test(action) ? action : 'then']((resp) => middleware[action](resp, restart)),
Promise[action === 'catch' ? 'reject' : 'resolve'](data) Promise[action === 'catch' ? 'reject' : 'resolve'](data)
); );
} }