Skip to content
This repository was archived by the owner on Dec 9, 2021. It is now read-only.

Commit 348424a

Browse files
author
Robert S
committed
add error Toasts
1 parent 110b2f7 commit 348424a

File tree

17 files changed

+216
-7
lines changed

17 files changed

+216
-7
lines changed

src/constants/RouteEnum.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
enum RouteEnum {
22
Home = '/',
33
Episodes = '/episodes',
4+
About = '/about',
45
}
56

67
export default RouteEnum;

src/constants/ToastStatusEnum.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
enum ToastStatusEnum {
2+
Error = 'error',
3+
Warning = 'warning',
4+
Success = 'success',
5+
}
6+
7+
export default ToastStatusEnum;

src/environments/base.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export default function(baseApi) {
99
shows: `${baseApi}/shows/:showId`,
1010
episodes: `${baseApi}/shows/:showId/episodes`,
1111
cast: `${baseApi}/shows/:showId/cast`,
12+
errorExample: 'https://httpstat.us/520',
1213
},
1314
isProduction: true,
1415
isDevelopment: false,
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import ToastStatusEnum from '../constants/ToastStatusEnum';
2+
import ToastsAction from '../stores/toasts/ToastsAction';
3+
4+
const errorToastMiddleware = () => (store) => (next) => (action) => {
5+
if (action.error) {
6+
const errorAction = action;
7+
8+
next(ToastsAction.add(errorAction.payload.message, ToastStatusEnum.Error));
9+
}
10+
11+
next(action);
12+
};
13+
14+
export default errorToastMiddleware;

src/stores/rootReducer.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@ import { connectRouter } from 'connected-react-router';
33
import RequestingReducer from './requesting/RequestingReducer';
44
import ErrorReducer from './error/ErrorReducer';
55
import ShowsReducer from './shows/ShowsReducer';
6+
import ToastsReducer from './toasts/ToastsReducer';
67

78
export default (history) => {
89
const reducerMap = {
910
error: ErrorReducer.reducer,
1011
requesting: RequestingReducer.reducer,
1112
router: connectRouter(history),
1213
shows: new ShowsReducer().reducer,
14+
toasts: new ToastsReducer().reducer,
1315
};
1416

1517
return combineReducers(reducerMap);

src/stores/rootStore.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@ import { routerMiddleware } from 'connected-react-router';
55
import reduxFreeze from 'redux-freeze';
66
import environment from 'environment';
77
import rootReducer from './rootReducer';
8+
import errorToastMiddleware from '../middlewares/errorToastMiddleware';
89

910
export default (initialState, history) => {
10-
const middleware = [environment.isDevelopment ? reduxFreeze : null, routerMiddleware(history), thunk].filter(Boolean);
11+
const middleware = [environment.isDevelopment ? reduxFreeze : null, thunk, routerMiddleware(history), errorToastMiddleware()].filter(Boolean);
1112

1213
const store = createStore(rootReducer(history), initialState, composeWithDevTools(applyMiddleware(...middleware)));
1314

src/stores/shows/ShowsAction.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ export default class ShowsAction {
1111
static REQUEST_CAST = 'ShowsAction.REQUEST_CAST';
1212
static REQUEST_CAST_FINISHED = 'ShowsAction.REQUEST_CAST_FINISHED';
1313

14+
static REQUEST_ERROR = 'ShowsAction.REQUEST_ERROR';
15+
static REQUEST_ERROR_FINISHED = 'ShowsAction.REQUEST_ERROR_FINISHED';
16+
1417
static requestShow() {
1518
return async (dispatch, getState) => {
1619
const showId = getState().shows.currentShowId;
@@ -34,4 +37,10 @@ export default class ShowsAction {
3437
await ActionUtility.createThunkEffect(dispatch, ShowsAction.REQUEST_CAST, ShowsEffect.requestCast, showId);
3538
};
3639
}
40+
41+
static requestError() {
42+
return async (dispatch, getState) => {
43+
await ActionUtility.createThunkEffect(dispatch, ShowsAction.REQUEST_ERROR, ShowsEffect.requestError);
44+
};
45+
}
3746
}

src/stores/shows/ShowsEffect.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,18 @@ export default class ShowsEffect {
3232

3333
return response.data.map((json) => new CastModel(json));
3434
}
35+
36+
/**
37+
* This is only to trigger an error api response so we can use it for an example in the AboutPage
38+
*/
39+
static async requestError() {
40+
const endpoint = environment.api.errorExample;
41+
const response = await HttpUtility.get(endpoint);
42+
43+
if (response instanceof HttpErrorResponseModel) {
44+
return response;
45+
}
46+
47+
return response.data;
48+
}
3549
}

src/stores/toasts/ToastsAction.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import ActionUtility from '../../utilities/ActionUtility';
2+
import uuid from 'uuid/v4';
3+
4+
export default class ToastsAction {
5+
static ADD_TOAST = 'ToastsAction.ADD_TOAST';
6+
static REMOVE_TOAST = 'ToastsAction.REMOVE_TOAST';
7+
8+
static add(message, type) {
9+
return ActionUtility.createAction(ToastsAction.ADD_TOAST, {
10+
message,
11+
type,
12+
id: uuid(),
13+
});
14+
}
15+
16+
static removeById(toastId) {
17+
return ActionUtility.createAction(ToastsAction.REMOVE_TOAST, toastId);
18+
}
19+
}

src/stores/toasts/ToastsReducer.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import ToastsAction from './ToastsAction';
2+
import BaseReducer from '../../utilities/BaseReducer';
3+
4+
export default class ToastsReducer extends BaseReducer {
5+
initialState = {
6+
items: [],
7+
};
8+
9+
[ToastsAction.ADD_TOAST](state, action) {
10+
return {
11+
...state,
12+
items: [...state.items, action.payload],
13+
};
14+
}
15+
16+
[ToastsAction.REMOVE_TOAST](state, action) {
17+
const toastId = action.payload;
18+
19+
return {
20+
...state,
21+
items: state.items.filter((model) => model.id !== toastId),
22+
};
23+
}
24+
}

0 commit comments

Comments
 (0)