Skip to content
Snippets Groups Projects
Commit f88b8ce7 authored by Eugen Rochko's avatar Eugen Rochko
Browse files

Improve how errors are displayed in the UI

parent aea151a0
No related branches found
No related tags found
No related merge requests found
Showing
with 54 additions and 80 deletions
...@@ -48,7 +48,6 @@ export function fetchAccount(id) { ...@@ -48,7 +48,6 @@ export function fetchAccount(id) {
axios.all([boundApi.get(`/api/v1/accounts/${id}`), boundApi.get(`/api/v1/accounts/relationships?id=${id}`)]).then(values => { axios.all([boundApi.get(`/api/v1/accounts/${id}`), boundApi.get(`/api/v1/accounts/relationships?id=${id}`)]).then(values => {
dispatch(fetchAccountSuccess(values[0].data, values[1].data[0])); dispatch(fetchAccountSuccess(values[0].data, values[1].data[0]));
}).catch(error => { }).catch(error => {
console.error(error);
dispatch(fetchAccountFail(id, error)); dispatch(fetchAccountFail(id, error));
}); });
}; };
...@@ -61,7 +60,6 @@ export function fetchAccountTimeline(id) { ...@@ -61,7 +60,6 @@ export function fetchAccountTimeline(id) {
api(getState).get(`/api/v1/accounts/${id}/statuses`).then(response => { api(getState).get(`/api/v1/accounts/${id}/statuses`).then(response => {
dispatch(fetchAccountTimelineSuccess(id, response.data)); dispatch(fetchAccountTimelineSuccess(id, response.data));
}).catch(error => { }).catch(error => {
console.error(error);
dispatch(fetchAccountTimelineFail(id, error)); dispatch(fetchAccountTimelineFail(id, error));
}); });
}; };
...@@ -76,7 +74,6 @@ export function expandAccountTimeline(id) { ...@@ -76,7 +74,6 @@ export function expandAccountTimeline(id) {
api(getState).get(`/api/v1/accounts/${id}/statuses?max_id=${lastId}`).then(response => { api(getState).get(`/api/v1/accounts/${id}/statuses?max_id=${lastId}`).then(response => {
dispatch(expandAccountTimelineSuccess(id, response.data)); dispatch(expandAccountTimelineSuccess(id, response.data));
}).catch(error => { }).catch(error => {
console.error(error);
dispatch(expandAccountTimelineFail(id, error)); dispatch(expandAccountTimelineFail(id, error));
}); });
}; };
...@@ -112,7 +109,6 @@ export function followAccount(id) { ...@@ -112,7 +109,6 @@ export function followAccount(id) {
api(getState).post(`/api/v1/accounts/${id}/follow`).then(response => { api(getState).post(`/api/v1/accounts/${id}/follow`).then(response => {
dispatch(followAccountSuccess(response.data)); dispatch(followAccountSuccess(response.data));
}).catch(error => { }).catch(error => {
console.error(error);
dispatch(followAccountFail(error)); dispatch(followAccountFail(error));
}); });
}; };
...@@ -125,7 +121,6 @@ export function unfollowAccount(id) { ...@@ -125,7 +121,6 @@ export function unfollowAccount(id) {
api(getState).post(`/api/v1/accounts/${id}/unfollow`).then(response => { api(getState).post(`/api/v1/accounts/${id}/unfollow`).then(response => {
dispatch(unfollowAccountSuccess(response.data)); dispatch(unfollowAccountSuccess(response.data));
}).catch(error => { }).catch(error => {
console.error(error);
dispatch(unfollowAccountFail(error)); dispatch(unfollowAccountFail(error));
}); });
} }
...@@ -226,7 +221,6 @@ export function blockAccount(id) { ...@@ -226,7 +221,6 @@ export function blockAccount(id) {
api(getState).post(`/api/v1/accounts/${id}/block`).then(response => { api(getState).post(`/api/v1/accounts/${id}/block`).then(response => {
dispatch(blockAccountSuccess(response.data)); dispatch(blockAccountSuccess(response.data));
}).catch(error => { }).catch(error => {
console.error(error);
dispatch(blockAccountFail(id, error)); dispatch(blockAccountFail(id, error));
}); });
}; };
...@@ -239,7 +233,6 @@ export function unblockAccount(id) { ...@@ -239,7 +233,6 @@ export function unblockAccount(id) {
api(getState).post(`/api/v1/accounts/${id}/unblock`).then(response => { api(getState).post(`/api/v1/accounts/${id}/unblock`).then(response => {
dispatch(unblockAccountSuccess(response.data)); dispatch(unblockAccountSuccess(response.data));
}).catch(error => { }).catch(error => {
console.error(error);
dispatch(unblockAccountFail(id, error)); dispatch(unblockAccountFail(id, error));
}); });
}; };
......
...@@ -43,7 +43,6 @@ export function submitCompose() { ...@@ -43,7 +43,6 @@ export function submitCompose() {
}).then(function (response) { }).then(function (response) {
dispatch(submitComposeSuccess(response.data)); dispatch(submitComposeSuccess(response.data));
}).catch(function (error) { }).catch(function (error) {
console.error(error);
dispatch(submitComposeFail(error)); dispatch(submitComposeFail(error));
}); });
}; };
...@@ -83,7 +82,6 @@ export function uploadCompose(files) { ...@@ -83,7 +82,6 @@ export function uploadCompose(files) {
}).then(function (response) { }).then(function (response) {
dispatch(uploadComposeSuccess(response.data)); dispatch(uploadComposeSuccess(response.data));
}).catch(function (error) { }).catch(function (error) {
console.error(error);
dispatch(uploadComposeFail(error)); dispatch(uploadComposeFail(error));
}); });
}; };
......
...@@ -22,7 +22,6 @@ export function submitFollow(router) { ...@@ -22,7 +22,6 @@ export function submitFollow(router) {
dispatch(submitFollowSuccess(response.data)); dispatch(submitFollowSuccess(response.data));
router.push(`/accounts/${response.data.id}`); router.push(`/accounts/${response.data.id}`);
}).catch(function (error) { }).catch(function (error) {
console.error(error);
dispatch(submitFollowFail(error)); dispatch(submitFollowFail(error));
}); });
}; };
......
...@@ -25,7 +25,6 @@ export function reblog(status) { ...@@ -25,7 +25,6 @@ export function reblog(status) {
// interested in how the original is modified, hence passing it skipping the wrapper // interested in how the original is modified, hence passing it skipping the wrapper
dispatch(reblogSuccess(status, response.data.reblog)); dispatch(reblogSuccess(status, response.data.reblog));
}).catch(function (error) { }).catch(function (error) {
console.error(error);
dispatch(reblogFail(status, error)); dispatch(reblogFail(status, error));
}); });
}; };
...@@ -38,7 +37,6 @@ export function unreblog(status) { ...@@ -38,7 +37,6 @@ export function unreblog(status) {
api(getState).post(`/api/v1/statuses/${status.get('id')}/unreblog`).then(response => { api(getState).post(`/api/v1/statuses/${status.get('id')}/unreblog`).then(response => {
dispatch(unreblogSuccess(status, response.data)); dispatch(unreblogSuccess(status, response.data));
}).catch(error => { }).catch(error => {
console.error(error);
dispatch(unreblogFail(status, error)); dispatch(unreblogFail(status, error));
}); });
}; };
...@@ -97,7 +95,6 @@ export function favourite(status) { ...@@ -97,7 +95,6 @@ export function favourite(status) {
api(getState).post(`/api/v1/statuses/${status.get('id')}/favourite`).then(function (response) { api(getState).post(`/api/v1/statuses/${status.get('id')}/favourite`).then(function (response) {
dispatch(favouriteSuccess(status, response.data)); dispatch(favouriteSuccess(status, response.data));
}).catch(function (error) { }).catch(function (error) {
console.error(error);
dispatch(favouriteFail(status, error)); dispatch(favouriteFail(status, error));
}); });
}; };
...@@ -110,7 +107,6 @@ export function unfavourite(status) { ...@@ -110,7 +107,6 @@ export function unfavourite(status) {
api(getState).post(`/api/v1/statuses/${status.get('id')}/unfavourite`).then(response => { api(getState).post(`/api/v1/statuses/${status.get('id')}/unfavourite`).then(response => {
dispatch(unfavouriteSuccess(status, response.data)); dispatch(unfavouriteSuccess(status, response.data));
}).catch(error => { }).catch(error => {
console.error(error);
dispatch(unfavouriteFail(status, error)); dispatch(unfavouriteFail(status, error));
}); });
}; };
......
export const NOTIFICATION_SHOW = 'NOTIFICATION_SHOW';
export const NOTIFICATION_DISMISS = 'NOTIFICATION_DISMISS'; export const NOTIFICATION_DISMISS = 'NOTIFICATION_DISMISS';
export const NOTIFICATION_CLEAR = 'NOTIFICATION_CLEAR'; export const NOTIFICATION_CLEAR = 'NOTIFICATION_CLEAR';
...@@ -13,3 +14,11 @@ export function clearNotifications() { ...@@ -13,3 +14,11 @@ export function clearNotifications() {
type: NOTIFICATION_CLEAR type: NOTIFICATION_CLEAR
}; };
}; };
export function showNotification(title, message) {
return {
type: NOTIFICATION_SHOW,
title: title,
message: message
};
};
...@@ -25,7 +25,6 @@ export function fetchStatus(id) { ...@@ -25,7 +25,6 @@ export function fetchStatus(id) {
axios.all([boundApi.get(`/api/v1/statuses/${id}`), boundApi.get(`/api/v1/statuses/${id}/context`)]).then(values => { axios.all([boundApi.get(`/api/v1/statuses/${id}`), boundApi.get(`/api/v1/statuses/${id}/context`)]).then(values => {
dispatch(fetchStatusSuccess(values[0].data, values[1].data)); dispatch(fetchStatusSuccess(values[0].data, values[1].data));
}).catch(error => { }).catch(error => {
console.error(error);
dispatch(fetchStatusFail(id, error)); dispatch(fetchStatusFail(id, error));
}); });
}; };
...@@ -54,7 +53,6 @@ export function deleteStatus(id) { ...@@ -54,7 +53,6 @@ export function deleteStatus(id) {
api(getState).delete(`/api/v1/statuses/${id}`).then(response => { api(getState).delete(`/api/v1/statuses/${id}`).then(response => {
dispatch(deleteStatusSuccess(id)); dispatch(deleteStatusSuccess(id));
}).catch(error => { }).catch(error => {
console.error(error);
dispatch(deleteStatusFail(id, error)); dispatch(deleteStatusFail(id, error));
}); });
}; };
......
...@@ -11,7 +11,6 @@ export function fetchSuggestions() { ...@@ -11,7 +11,6 @@ export function fetchSuggestions() {
api(getState).get('/api/v1/accounts/suggestions').then(response => { api(getState).get('/api/v1/accounts/suggestions').then(response => {
dispatch(fetchSuggestionsSuccess(response.data)); dispatch(fetchSuggestionsSuccess(response.data));
}).catch(error => { }).catch(error => {
console.error(error);
dispatch(fetchSuggestionsFail(error)); dispatch(fetchSuggestionsFail(error));
}); });
}; };
......
...@@ -48,7 +48,6 @@ export function refreshTimeline(timeline) { ...@@ -48,7 +48,6 @@ export function refreshTimeline(timeline) {
api(getState).get(`/api/v1/statuses/${timeline}`).then(function (response) { api(getState).get(`/api/v1/statuses/${timeline}`).then(function (response) {
dispatch(refreshTimelineSuccess(timeline, response.data)); dispatch(refreshTimelineSuccess(timeline, response.data));
}).catch(function (error) { }).catch(function (error) {
console.error(error);
dispatch(refreshTimelineFail(timeline, error)); dispatch(refreshTimelineFail(timeline, error));
}); });
}; };
...@@ -71,7 +70,6 @@ export function expandTimeline(timeline) { ...@@ -71,7 +70,6 @@ export function expandTimeline(timeline) {
api(getState).get(`/api/v1/statuses/${timeline}?max_id=${lastId}`).then(response => { api(getState).get(`/api/v1/statuses/${timeline}?max_id=${lastId}`).then(response => {
dispatch(expandTimelineSuccess(timeline, response.data)); dispatch(expandTimelineSuccess(timeline, response.data));
}).catch(error => { }).catch(error => {
console.error(error);
dispatch(expandTimelineFail(timeline, error)); dispatch(expandTimelineFail(timeline, error));
}); });
}; };
......
import { showNotification } from '../actions/notifications';
const defaultFailSuffix = 'FAIL';
export default function errorsMiddleware() {
return ({ dispatch }) => next => action => {
if (action.type) {
const isFail = new RegExp(`${defaultFailSuffix}$`, 'g');
if (action.type.match(isFail)) {
if (action.error.response) {
const { data, status, statusText } = action.error.response;
let message = statusText;
let title = `${status}`;
if (data.error) {
message = data.error;
}
dispatch(showNotification(title, message));
} else {
console.error(action.error);
dispatch(showNotification('Oops!', 'An unexpected error occurred. Inspect the console for more details'));
}
}
}
return next(action);
};
};
import { COMPOSE_SUBMIT_FAIL, COMPOSE_UPLOAD_FAIL } from '../actions/compose';
import { FOLLOW_SUBMIT_FAIL } from '../actions/follow';
import { import {
REBLOG_FAIL, NOTIFICATION_SHOW,
UNREBLOG_FAIL, NOTIFICATION_DISMISS,
FAVOURITE_FAIL, NOTIFICATION_CLEAR
UNFAVOURITE_FAIL } from '../actions/notifications';
} from '../actions/interactions'; import Immutable from 'immutable';
import {
TIMELINE_REFRESH_FAIL,
TIMELINE_EXPAND_FAIL
} from '../actions/timelines';
import { NOTIFICATION_DISMISS, NOTIFICATION_CLEAR } from '../actions/notifications';
import {
ACCOUNT_FETCH_FAIL,
ACCOUNT_FOLLOW_FAIL,
ACCOUNT_UNFOLLOW_FAIL,
ACCOUNT_TIMELINE_FETCH_FAIL,
ACCOUNT_TIMELINE_EXPAND_FAIL
} from '../actions/accounts';
import {
STATUS_FETCH_FAIL,
STATUS_DELETE_FAIL
} from '../actions/statuses';
import Immutable from 'immutable';
const initialState = Immutable.List();
function notificationFromError(state, error) { const initialState = Immutable.List([]);
let n = Immutable.Map({
key: state.size > 0 ? state.last().get('key') + 1 : 0,
message: ''
});
if (error.response) {
n = n.withMutations(map => {
map.set('message', error.response.statusText);
map.set('title', `${error.response.status}`);
});
} else {
n = n.set('message', `${error}`);
}
return state.push(n);
};
export default function notifications(state = initialState, action) { export default function notifications(state = initialState, action) {
switch(action.type) { switch(action.type) {
case COMPOSE_SUBMIT_FAIL: case NOTIFICATION_SHOW:
case COMPOSE_UPLOAD_FAIL: return state.push(Immutable.Map({
case FOLLOW_SUBMIT_FAIL: key: state.size > 0 ? state.last().get('key') + 1 : 0,
case REBLOG_FAIL: title: action.title,
case FAVOURITE_FAIL: message: action.message
case TIMELINE_REFRESH_FAIL: }));
case TIMELINE_EXPAND_FAIL:
case ACCOUNT_FETCH_FAIL:
case ACCOUNT_FOLLOW_FAIL:
case ACCOUNT_UNFOLLOW_FAIL:
case ACCOUNT_TIMELINE_FETCH_FAIL:
case ACCOUNT_TIMELINE_EXPAND_FAIL:
case STATUS_FETCH_FAIL:
case STATUS_DELETE_FAIL:
case UNREBLOG_FAIL:
case UNFAVOURITE_FAIL:
return notificationFromError(state, action.error);
case NOTIFICATION_DISMISS: case NOTIFICATION_DISMISS:
return state.filterNot(item => item.get('key') === action.notification.key); return state.filterNot(item => item.get('key') === action.notification.key);
case NOTIFICATION_CLEAR: case NOTIFICATION_CLEAR:
......
...@@ -2,9 +2,10 @@ import { createStore, applyMiddleware, compose } from 'redux'; ...@@ -2,9 +2,10 @@ import { createStore, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk'; import thunk from 'redux-thunk';
import appReducer from '../reducers'; import appReducer from '../reducers';
import { loadingBarMiddleware } from 'react-redux-loading-bar'; import { loadingBarMiddleware } from 'react-redux-loading-bar';
import errorsMiddleware from '../middleware/errors';
export default function configureStore(initialState) { export default function configureStore(initialState) {
return createStore(appReducer, initialState, compose(applyMiddleware(thunk, loadingBarMiddleware({ return createStore(appReducer, initialState, compose(applyMiddleware(thunk, loadingBarMiddleware({
promiseTypeSuffixes: ['REQUEST', 'SUCCESS', 'FAIL'], promiseTypeSuffixes: ['REQUEST', 'SUCCESS', 'FAIL'],
})), window.devToolsExtension ? window.devToolsExtension() : f => f)); }), errorsMiddleware()), window.devToolsExtension ? window.devToolsExtension() : f => f));
}; };
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment