@@ -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 => { | |||
dispatch(fetchAccountSuccess(values[0].data, values[1].data[0])); | |||
}).catch(error => { | |||
console.error(error); | |||
dispatch(fetchAccountFail(id, error)); | |||
}); | |||
}; | |||
@@ -61,7 +60,6 @@ export function fetchAccountTimeline(id) { | |||
api(getState).get(`/api/v1/accounts/${id}/statuses`).then(response => { | |||
dispatch(fetchAccountTimelineSuccess(id, response.data)); | |||
}).catch(error => { | |||
console.error(error); | |||
dispatch(fetchAccountTimelineFail(id, error)); | |||
}); | |||
}; | |||
@@ -76,7 +74,6 @@ export function expandAccountTimeline(id) { | |||
api(getState).get(`/api/v1/accounts/${id}/statuses?max_id=${lastId}`).then(response => { | |||
dispatch(expandAccountTimelineSuccess(id, response.data)); | |||
}).catch(error => { | |||
console.error(error); | |||
dispatch(expandAccountTimelineFail(id, error)); | |||
}); | |||
}; | |||
@@ -112,7 +109,6 @@ export function followAccount(id) { | |||
api(getState).post(`/api/v1/accounts/${id}/follow`).then(response => { | |||
dispatch(followAccountSuccess(response.data)); | |||
}).catch(error => { | |||
console.error(error); | |||
dispatch(followAccountFail(error)); | |||
}); | |||
}; | |||
@@ -125,7 +121,6 @@ export function unfollowAccount(id) { | |||
api(getState).post(`/api/v1/accounts/${id}/unfollow`).then(response => { | |||
dispatch(unfollowAccountSuccess(response.data)); | |||
}).catch(error => { | |||
console.error(error); | |||
dispatch(unfollowAccountFail(error)); | |||
}); | |||
} | |||
@@ -226,7 +221,6 @@ export function blockAccount(id) { | |||
api(getState).post(`/api/v1/accounts/${id}/block`).then(response => { | |||
dispatch(blockAccountSuccess(response.data)); | |||
}).catch(error => { | |||
console.error(error); | |||
dispatch(blockAccountFail(id, error)); | |||
}); | |||
}; | |||
@@ -239,7 +233,6 @@ export function unblockAccount(id) { | |||
api(getState).post(`/api/v1/accounts/${id}/unblock`).then(response => { | |||
dispatch(unblockAccountSuccess(response.data)); | |||
}).catch(error => { | |||
console.error(error); | |||
dispatch(unblockAccountFail(id, error)); | |||
}); | |||
}; | |||
@@ -43,7 +43,6 @@ export function submitCompose() { | |||
}).then(function (response) { | |||
dispatch(submitComposeSuccess(response.data)); | |||
}).catch(function (error) { | |||
console.error(error); | |||
dispatch(submitComposeFail(error)); | |||
}); | |||
}; | |||
@@ -83,7 +82,6 @@ export function uploadCompose(files) { | |||
}).then(function (response) { | |||
dispatch(uploadComposeSuccess(response.data)); | |||
}).catch(function (error) { | |||
console.error(error); | |||
dispatch(uploadComposeFail(error)); | |||
}); | |||
}; | |||
@@ -22,7 +22,6 @@ export function submitFollow(router) { | |||
dispatch(submitFollowSuccess(response.data)); | |||
router.push(`/accounts/${response.data.id}`); | |||
}).catch(function (error) { | |||
console.error(error); | |||
dispatch(submitFollowFail(error)); | |||
}); | |||
}; | |||
@@ -25,7 +25,6 @@ export function reblog(status) { | |||
// interested in how the original is modified, hence passing it skipping the wrapper | |||
dispatch(reblogSuccess(status, response.data.reblog)); | |||
}).catch(function (error) { | |||
console.error(error); | |||
dispatch(reblogFail(status, error)); | |||
}); | |||
}; | |||
@@ -38,7 +37,6 @@ export function unreblog(status) { | |||
api(getState).post(`/api/v1/statuses/${status.get('id')}/unreblog`).then(response => { | |||
dispatch(unreblogSuccess(status, response.data)); | |||
}).catch(error => { | |||
console.error(error); | |||
dispatch(unreblogFail(status, error)); | |||
}); | |||
}; | |||
@@ -97,7 +95,6 @@ export function favourite(status) { | |||
api(getState).post(`/api/v1/statuses/${status.get('id')}/favourite`).then(function (response) { | |||
dispatch(favouriteSuccess(status, response.data)); | |||
}).catch(function (error) { | |||
console.error(error); | |||
dispatch(favouriteFail(status, error)); | |||
}); | |||
}; | |||
@@ -110,7 +107,6 @@ export function unfavourite(status) { | |||
api(getState).post(`/api/v1/statuses/${status.get('id')}/unfavourite`).then(response => { | |||
dispatch(unfavouriteSuccess(status, response.data)); | |||
}).catch(error => { | |||
console.error(error); | |||
dispatch(unfavouriteFail(status, error)); | |||
}); | |||
}; | |||
@@ -1,3 +1,4 @@ | |||
export const NOTIFICATION_SHOW = 'NOTIFICATION_SHOW'; | |||
export const NOTIFICATION_DISMISS = 'NOTIFICATION_DISMISS'; | |||
export const NOTIFICATION_CLEAR = 'NOTIFICATION_CLEAR'; | |||
@@ -13,3 +14,11 @@ export function clearNotifications() { | |||
type: NOTIFICATION_CLEAR | |||
}; | |||
}; | |||
export function showNotification(title, message) { | |||
return { | |||
type: NOTIFICATION_SHOW, | |||
title: title, | |||
message: message | |||
}; | |||
}; |
@@ -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 => { | |||
dispatch(fetchStatusSuccess(values[0].data, values[1].data)); | |||
}).catch(error => { | |||
console.error(error); | |||
dispatch(fetchStatusFail(id, error)); | |||
}); | |||
}; | |||
@@ -54,7 +53,6 @@ export function deleteStatus(id) { | |||
api(getState).delete(`/api/v1/statuses/${id}`).then(response => { | |||
dispatch(deleteStatusSuccess(id)); | |||
}).catch(error => { | |||
console.error(error); | |||
dispatch(deleteStatusFail(id, error)); | |||
}); | |||
}; | |||
@@ -11,7 +11,6 @@ export function fetchSuggestions() { | |||
api(getState).get('/api/v1/accounts/suggestions').then(response => { | |||
dispatch(fetchSuggestionsSuccess(response.data)); | |||
}).catch(error => { | |||
console.error(error); | |||
dispatch(fetchSuggestionsFail(error)); | |||
}); | |||
}; | |||
@@ -48,7 +48,6 @@ export function refreshTimeline(timeline) { | |||
api(getState).get(`/api/v1/statuses/${timeline}`).then(function (response) { | |||
dispatch(refreshTimelineSuccess(timeline, response.data)); | |||
}).catch(function (error) { | |||
console.error(error); | |||
dispatch(refreshTimelineFail(timeline, error)); | |||
}); | |||
}; | |||
@@ -71,7 +70,6 @@ export function expandTimeline(timeline) { | |||
api(getState).get(`/api/v1/statuses/${timeline}?max_id=${lastId}`).then(response => { | |||
dispatch(expandTimelineSuccess(timeline, response.data)); | |||
}).catch(error => { | |||
console.error(error); | |||
dispatch(expandTimelineFail(timeline, error)); | |||
}); | |||
}; | |||
@@ -0,0 +1,31 @@ | |||
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); | |||
}; | |||
}; |
@@ -1,68 +1,20 @@ | |||
import { COMPOSE_SUBMIT_FAIL, COMPOSE_UPLOAD_FAIL } from '../actions/compose'; | |||
import { FOLLOW_SUBMIT_FAIL } from '../actions/follow'; | |||
import { | |||
REBLOG_FAIL, | |||
UNREBLOG_FAIL, | |||
FAVOURITE_FAIL, | |||
UNFAVOURITE_FAIL | |||
} from '../actions/interactions'; | |||
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(); | |||
NOTIFICATION_SHOW, | |||
NOTIFICATION_DISMISS, | |||
NOTIFICATION_CLEAR | |||
} from '../actions/notifications'; | |||
import Immutable from 'immutable'; | |||
function notificationFromError(state, error) { | |||
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); | |||
}; | |||
const initialState = Immutable.List([]); | |||
export default function notifications(state = initialState, action) { | |||
switch(action.type) { | |||
case COMPOSE_SUBMIT_FAIL: | |||
case COMPOSE_UPLOAD_FAIL: | |||
case FOLLOW_SUBMIT_FAIL: | |||
case REBLOG_FAIL: | |||
case FAVOURITE_FAIL: | |||
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_SHOW: | |||
return state.push(Immutable.Map({ | |||
key: state.size > 0 ? state.last().get('key') + 1 : 0, | |||
title: action.title, | |||
message: action.message | |||
})); | |||
case NOTIFICATION_DISMISS: | |||
return state.filterNot(item => item.get('key') === action.notification.key); | |||
case NOTIFICATION_CLEAR: | |||
@@ -2,9 +2,10 @@ import { createStore, applyMiddleware, compose } from 'redux'; | |||
import thunk from 'redux-thunk'; | |||
import appReducer from '../reducers'; | |||
import { loadingBarMiddleware } from 'react-redux-loading-bar'; | |||
import errorsMiddleware from '../middleware/errors'; | |||
export default function configureStore(initialState) { | |||
return createStore(appReducer, initialState, compose(applyMiddleware(thunk, loadingBarMiddleware({ | |||
promiseTypeSuffixes: ['REQUEST', 'SUCCESS', 'FAIL'], | |||
})), window.devToolsExtension ? window.devToolsExtension() : f => f)); | |||
}), errorsMiddleware()), window.devToolsExtension ? window.devToolsExtension() : f => f)); | |||
}; |