1
0
mirror of https://github.com/ascribe/onion.git synced 2024-12-22 17:33:14 +01:00

Merge pull request #1 from ascribe/AD-1177-display-404-on-pieces-and-editio

AD-1177 display 404 on pieces and editio
This commit is contained in:
Tim Daubenschütz 2015-12-07 11:49:39 +01:00
commit 2b6b78310c
10 changed files with 116 additions and 9 deletions

View File

@ -7,7 +7,8 @@ import EditionFetcher from '../fetchers/edition_fetcher';
class EditionActions {
constructor() {
this.generateActions(
'updateEdition'
'updateEdition',
'editionFailed'
);
}
@ -18,6 +19,7 @@ class EditionActions {
})
.catch((err) => {
console.logGlobal(err);
this.actions.editionFailed(err.json);
});
}
}

View File

@ -8,7 +8,8 @@ class PieceActions {
constructor() {
this.generateActions(
'updatePiece',
'updateProperty'
'updateProperty',
'pieceFailed'
);
}
@ -19,6 +20,7 @@ class PieceActions {
})
.catch((err) => {
console.logGlobal(err);
this.actions.pieceFailed(err.json);
});
}
}

View File

@ -1,6 +1,10 @@
'use strict';
import React from 'react';
import { History } from 'react-router';
import ReactError from '../../mixins/react_error';
import { ResourceNotFoundError } from '../../models/errors';
import EditionActions from '../../actions/edition_actions';
import EditionStore from '../../stores/edition_store';
@ -9,6 +13,7 @@ import Edition from './edition';
import AscribeSpinner from '../ascribe_spinner';
import { getLangText } from '../../utils/lang_utils';
import { setDocumentTitle } from '../../utils/dom_utils';
@ -22,6 +27,8 @@ let EditionContainer = React.createClass({
params: React.PropTypes.object
},
mixins: [History, ReactError],
getInitialState() {
return EditionStore.getState();
},
@ -29,11 +36,11 @@ let EditionContainer = React.createClass({
componentDidMount() {
EditionStore.listen(this.onChange);
// Every time we enter the edition detail page, just reset the edition
// store as it will otherwise display wrong/old data once the user loads
// Every time we're entering the edition detail page,
// just reset the edition that is saved in the edition store
// as it will otherwise display wrong/old data once the user loads
// the edition detail a second time
EditionActions.updateEdition({});
this.loadEdition();
},
@ -46,6 +53,14 @@ let EditionContainer = React.createClass({
}
},
componentDidUpdate() {
const { editionError } = this.state;
if(editionError && editionError.status === 404) {
this.throws(new ResourceNotFoundError(getLangText("Oops, the edition you're looking for doesn't exist.")));
}
},
componentWillUnmount() {
window.clearInterval(this.state.timerId);
EditionStore.unlisten(this.onChange);

View File

@ -4,6 +4,9 @@ import React from 'react';
import { History } from 'react-router';
import Moment from 'moment';
import ReactError from '../../mixins/react_error';
import { ResourceNotFoundError } from '../../models/errors';
import PieceActions from '../../actions/piece_actions';
import PieceStore from '../../stores/piece_store';
@ -54,7 +57,7 @@ let PieceContainer = React.createClass({
params: React.PropTypes.object
},
mixins: [History],
mixins: [History, ReactError],
getDefaultProps() {
return {
@ -76,15 +79,22 @@ let PieceContainer = React.createClass({
componentDidMount() {
UserStore.listen(this.onChange);
PieceListStore.listen(this.onChange);
UserActions.fetchCurrentUser();
PieceStore.listen(this.onChange);
// Every time we enter the piece detail page, just reset the piece
// store as it will otherwise display wrong/old data once the user loads
// the piece detail a second time
PieceActions.updatePiece({});
this.loadPiece();
UserActions.fetchCurrentUser();
},
componentDidUpdate() {
const { pieceError } = this.state;
if(pieceError && pieceError.status === 404) {
this.throws(new ResourceNotFoundError(getLangText("Oops, the piece you're looking for doesn't exist.")));
}
},
componentWillUnmount() {

View File

@ -6,6 +6,16 @@ import { getLangText } from '../utils/lang_utils';
let ErrorNotFoundPage = React.createClass({
propTypes: {
message: React.PropTypes.string
},
getDefaultProps() {
return {
message: getLangText("Oops, the page you are looking for doesn't exist.")
};
},
render() {
return (
<div className="row">
@ -13,7 +23,7 @@ let ErrorNotFoundPage = React.createClass({
<div className="error-wrapper">
<h1>404</h1>
<p>
{getLangText('Ups, the page you are looking for does not exist.')}
{this.props.message}
</p>
</div>
</div>

16
js/mixins/react_error.js Normal file
View File

@ -0,0 +1,16 @@
'use strict';
import invariant from 'invariant';
const ReactError = {
throws(err) {
if(!err.handler) {
invariant(err.handler, 'Error thrown to ReactError did not have a `handler` function');
console.logGlobal('Error thrown to ReactError did not have a `handler` function');
} else {
err.handler(this, err);
}
}
};
export default ReactError;

31
js/models/errors.js Normal file
View File

@ -0,0 +1,31 @@
'use strict';
import React from 'react';
import ErrorNotFoundPage from '../components/error_not_found_page';
export class ResourceNotFoundError extends Error {
constructor(message) {
super(message);
this.name = this.constructor.name;
this.message = message;
// `captureStackTrace` might not be available in IE:
// - http://stackoverflow.com/a/8460753/1263876
if(Error.captureStackTrace) {
Error.captureStackTrace(this, this.constructor.name);
}
}
handler(component, err) {
const monkeyPatchedKey = `_${this.name}MonkeyPatched`;
if(!component.state[monkeyPatchedKey]) {
component.render = () => <ErrorNotFoundPage message={err.message} />;
component.setState({
[monkeyPatchedKey]: true
});
}
}
}

View File

@ -7,11 +7,17 @@ import EditionActions from '../actions/edition_actions';
class EditionStore {
constructor() {
this.edition = {};
this.editionError = null;
this.bindActions(EditionActions);
}
onUpdateEdition(edition) {
this.edition = edition;
this.editionError = null;
}
onEditionFailed(error) {
this.editionError = error;
}
}

View File

@ -7,11 +7,13 @@ import PieceActions from '../actions/piece_actions';
class PieceStore {
constructor() {
this.piece = {};
this.pieceError = null;
this.bindActions(PieceActions);
}
onUpdatePiece(piece) {
this.piece = piece;
this.pieceError = null;
}
onUpdateProperty({key, value}) {
@ -21,6 +23,10 @@ class PieceStore {
throw new Error('There is no piece defined in PieceStore or the piece object does not have the property you\'re looking for.');
}
}
onPieceFailed(err) {
this.pieceError = err;
}
}
export default alt.createStore(PieceStore, 'PieceStore');

View File

@ -30,6 +30,15 @@ class Requests {
reject(error);
} else if(body && body.detail) {
reject(new Error(body.detail));
} else if(!body.success) {
let error = new Error('Client Request Error');
error.json = {
status: response.status,
statusText: response.statusText,
type: response.type,
url: response.url
};
reject(error);
} else {
resolve(body);
}