UNPKG

modules-pack

Version:

JavaScript Modules for Modern Frontend & Backend Projects

121 lines (105 loc) 3.76 kB
import { API as API, HTTP_401_UNAUTHORIZED, NETWORK, NETWORK_ERROR_MESSAGES, REQUEST_TIMEOUT_MESSAGE } from 'modules-pack/api/constants' import { isApiActionTypeError, isApiActionTypeTimeout } from 'modules-pack/api/utils' import { stateAction, stateActionType, } from 'modules-pack/redux/actions' import { all, call, put, takeEvery } from 'modules-pack/saga/utils' import { ALERT, ERROR, get, hostname, isInList, LOGOUT, OPEN, SYSTEM, toList, } from 'utils-pack' import { POPUP, POPUP_ALERT, POPUP_ERROR } from './constants' /** * ASYNC TASKS ================================================================= * Actions Orchestration - for subscribing, managing and dispatching actions. * ============================================================================= */ /* Module's Combined Task to start all sagas at once */ export default function * saga () { yield all([ // List someSaga() here popupWatch() ]) } /** * WATCH TASKS (Action Subscriptions) ------------------------------------------ * ----------------------------------------------------------------------------- */ function * popupWatch () { yield all([ takeEvery(stateActionType(SYSTEM, ALERT), popupAlert), takeEvery(stateActionType(POPUP, ALERT), popupAlert), takeEvery(stateActionType(POPUP, ERROR), popupError), takeEvery(isApiActionTypeError, apiErrorFlow), takeEvery(isApiActionTypeTimeout, apiTimeoutAlert), takeEvery(stateActionType(NETWORK, ERROR), networkErrorAlert) ]) } /** * FLOW TASKS (Action Management) ---------------------------------------------- * ----------------------------------------------------------------------------- */ let lastApiErrorMessage = null function * apiErrorFlow ({payload = {}, meta: {shouldIgnoreErrorCodes, errorTitle, shouldAlertSameErrorOnce = false}}) { const {status, code, type, content, detail, message, msg} = payload const errors = toList(payload.errors || payload.error || {status, code, type, content, detail, message, msg}) const errorMessage = get(errors, '[0].message', get(errors, '[0].details[0].message', payload.message)) // Ignore any given errors if (shouldIgnoreErrorCodes && isInList(shouldIgnoreErrorCodes, status)) return // Ignore 401 Responses if (status === HTTP_401_UNAUTHORIZED) return // Dispatch LOGOUT if Error came from LOGOUT request if (type === LOGOUT) yield put(stateAction(API, LOGOUT)) // Popup Error if (!shouldAlertSameErrorOnce || lastApiErrorMessage !== errorMessage) { lastApiErrorMessage = errorMessage yield call(popupError, {payload: {title: errorTitle, errors}}) } } /** * HELPER TASKS (Action Dispatches) -------------------------------------------- * ----------------------------------------------------------------------------- */ function * apiTimeoutAlert ({payload: {url} = {}}) { // Show Popup Alert yield call(popupAlert, { payload: { items: [{ title: REQUEST_TIMEOUT_MESSAGE, content: `API request timed out for ${hostname(url)}, please try again.` }] } }) } function * networkErrorAlert () { // Show Popup Alert yield call(popupAlert, { payload: { items: [{ title: NETWORK_ERROR_MESSAGES[0], content: 'Cannot connect to the internet.' }] } }) } /** * @param {Array} items - [{title, content}] */ function * popupAlert ({payload: {items} = {}}) { yield put(stateAction(POPUP, OPEN, { activePopup: POPUP_ALERT, [POPUP_ALERT]: { items } })) } function * popupError ({payload: {title = 'Error', errors, items} = {}}) { yield put(stateAction(POPUP, OPEN, { activePopup: POPUP_ERROR, [POPUP_ERROR]: { title, items: toList(errors || items) } })) }