|
@@ -0,0 +1,97 @@
|
|
|
+import { call, put, takeEvery } from 'redux-sagas/effects'
|
|
|
+
|
|
|
+/** genStuff
|
|
|
+ * you input the name of a module (e.g. project) and the API (e.g. http://localhost/db/project)
|
|
|
+ * it outputs a state, action types, action creators, reducer, workers and watchers
|
|
|
+ * to handle a restful API.
|
|
|
+ */
|
|
|
+export function genStuff (name, api = `http://localhost/db/${name}`) {
|
|
|
+ const actionTypes = {}
|
|
|
+ const actions = {}
|
|
|
+
|
|
|
+ let actionList = ['list', 'create', 'read', 'update', 'delete']
|
|
|
+ if (!sync) {
|
|
|
+ let tmpActionList = []
|
|
|
+ actionList.forEach(action => {
|
|
|
+ tmpActionList.push(`${action}_request`)
|
|
|
+ tmpActionList.push(`${action}_success`)
|
|
|
+ tmpActionList.push(`${action}_failure`)
|
|
|
+ })
|
|
|
+ actionList = tmpActionList
|
|
|
+ }
|
|
|
+
|
|
|
+ /** Populate the actionTypes and actions */
|
|
|
+ actionList.forEach(action => {
|
|
|
+ const actionType = `${action.toUpperCase()}_${name.toUpperCase()}`
|
|
|
+ const actionName = `${action}${name[0].toUpperCase()}${name.substring(1)}`
|
|
|
+ actionTypes[actionType] = `${name}/${actionType}`
|
|
|
+ actions[actionName] = (id, data) => { return { type: `${name}/${actionType}`, id, data } }
|
|
|
+ })
|
|
|
+
|
|
|
+ const state = []
|
|
|
+
|
|
|
+ function * worker (action) {
|
|
|
+ try {
|
|
|
+ const data = yield call(api, payload)
|
|
|
+ yield put({ type: '??_SUCCESS', data })
|
|
|
+ } catch (error) {
|
|
|
+ yield put({ type: '??_FAILURE', error })
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ function * watcher (action) {
|
|
|
+ for (action in actions) {
|
|
|
+ yield takeEvery(`${action.toUpperCase()}_REQUEST`, worker)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ const reducer = (sync) ? (state = [], action) => {
|
|
|
+ let nextState
|
|
|
+ switch (action.type) {
|
|
|
+ case actionTypes[`CREATE_${name.toUpperCase()}`]:
|
|
|
+ nextState = [ ...state, action.data ]
|
|
|
+ return nextState
|
|
|
+ case actionTypes[`UPDATE_${name.toUpperCase()}`]:
|
|
|
+ nextState = [ ...state.slice(0, action.id), { ...state[action.id], ...action.data }, ...state.slice(action.id + 1) ]
|
|
|
+ return nextState
|
|
|
+ case actionTypes[`REMOVE_${name.toUpperCase()}`]:
|
|
|
+ nextState = [ ...state.slice(0, action.id), ...state.slice(action.id + 1) ]
|
|
|
+ return nextState
|
|
|
+ default:
|
|
|
+ return state
|
|
|
+ }
|
|
|
+ } : (state = [], action) => {
|
|
|
+ let nextState
|
|
|
+ switch (action.type) {
|
|
|
+ case actionTypes[`CREATE_REQUEST_${name.toUpperCase()}`]:
|
|
|
+ worker(action)
|
|
|
+ return nextState
|
|
|
+ case actionTypes[`CREATE_SUCCESS_${name.toUpperCase()}`]:
|
|
|
+ nextState = [ ...state, action.data ]
|
|
|
+ return nextState
|
|
|
+ case actionTypes[`UPDATE_REQUEST_${name.toUpperCase()}`]:
|
|
|
+ nextState = [ ...state.slice(0, action.id), { ...state[action.id], ...action.data }, ...state.slice(action.id + 1) ]
|
|
|
+ return nextState
|
|
|
+ case actionTypes[`UPDATE_SUCCESS_${name.toUpperCase()}`]:
|
|
|
+ nextState = [ ...state.slice(0, action.id), { ...state[action.id], ...action.data }, ...state.slice(action.id + 1) ]
|
|
|
+ return nextState
|
|
|
+ case actionTypes[`REMOVE_REQUEST_${name.toUpperCase()}`]:
|
|
|
+ nextState = [ ...state.slice(0, action.id), ...state.slice(action.id + 1) ]
|
|
|
+ return nextState
|
|
|
+ case actionTypes[`REMOVE_SUCCESS_${name.toUpperCase()}`]:
|
|
|
+ nextState = [ ...state.slice(0, action.id), ...state.slice(action.id + 1) ]
|
|
|
+ return nextState
|
|
|
+ default:
|
|
|
+ return state
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return {
|
|
|
+ actionTypes,
|
|
|
+ actions,
|
|
|
+ state,
|
|
|
+ reducer,
|
|
|
+ worker: (sync) ? null : worker,
|
|
|
+ watcher: (sync) ? null : watcher
|
|
|
+ }
|
|
|
+}
|