From 95443635b4793bbee31045ab61e0fbf1a77e85c4 Mon Sep 17 00:00:00 2001 From: muerwre Date: Sat, 24 Aug 2019 17:58:39 +0700 Subject: [PATCH] flow redux --- src/constants/api.ts | 1 + src/redux/flow/actions.ts | 7 +++++++ src/redux/flow/api.ts | 25 +++++++++++++++++++++++++ src/redux/flow/constants.ts | 6 ++++++ src/redux/flow/handlers.ts | 11 +++++++++++ src/redux/flow/reducer.ts | 15 +++++++++++++++ src/redux/flow/sagas.ts | 14 ++++++++++++++ src/redux/flow/selectors.ts | 4 ++++ src/redux/node/api.ts | 24 +++++++++++++++++------- src/redux/node/sagas.ts | 15 ++++++++++++--- src/redux/store.ts | 6 ++++++ 11 files changed, 118 insertions(+), 10 deletions(-) create mode 100644 src/redux/flow/actions.ts create mode 100644 src/redux/flow/api.ts create mode 100644 src/redux/flow/constants.ts create mode 100644 src/redux/flow/handlers.ts create mode 100644 src/redux/flow/reducer.ts create mode 100644 src/redux/flow/sagas.ts create mode 100644 src/redux/flow/selectors.ts diff --git a/src/constants/api.ts b/src/constants/api.ts index 46994588..04e3fb17 100644 --- a/src/constants/api.ts +++ b/src/constants/api.ts @@ -7,5 +7,6 @@ export const API = { }, NODE: { SAVE: '/node/', + GET: '/node/', }, }; diff --git a/src/redux/flow/actions.ts b/src/redux/flow/actions.ts new file mode 100644 index 00000000..4092bddb --- /dev/null +++ b/src/redux/flow/actions.ts @@ -0,0 +1,7 @@ +import { INode } from '../types'; +import { FLOW_ACTIONS } from './constants'; + +export const flowSetNodes = (nodes: INode[]) => ({ + nodes, + type: FLOW_ACTIONS.SET_NODES, +}); diff --git a/src/redux/flow/api.ts b/src/redux/flow/api.ts new file mode 100644 index 00000000..b15e5d7c --- /dev/null +++ b/src/redux/flow/api.ts @@ -0,0 +1,25 @@ +import { api, configWithToken, resultMiddleware, errorMiddleware } from '~/utils/api'; +import { INode, IResultWithStatus } from '../types'; +import { API } from '~/constants/api'; + +export const postNode = ({ + access, + node, +}: { + access: string; + node: INode; +}): Promise> => + api + .post(API.NODE.SAVE, { node }, configWithToken(access)) + .then(resultMiddleware) + .catch(errorMiddleware); + +export const getNodes = ({ + skip = 0, +}: { + skip: number; +}): Promise> => + api + .get(API.NODE.GET, { params: { skip } }) + .then(resultMiddleware) + .catch(errorMiddleware); diff --git a/src/redux/flow/constants.ts b/src/redux/flow/constants.ts new file mode 100644 index 00000000..7e8eb5a3 --- /dev/null +++ b/src/redux/flow/constants.ts @@ -0,0 +1,6 @@ +const prefix = 'FLOW.'; + +export const FLOW_ACTIONS = { + GET_FLOW: `${prefix}.GET_FLOW`, + SET_NODES: `${prefix}.SET_NODES`, +}; diff --git a/src/redux/flow/handlers.ts b/src/redux/flow/handlers.ts new file mode 100644 index 00000000..80f3b1ca --- /dev/null +++ b/src/redux/flow/handlers.ts @@ -0,0 +1,11 @@ +import assocPath from 'ramda/es/assocPath'; +import { FLOW_ACTIONS } from './constants'; +import { flowSetNodes } from './actions'; +import { IFlowState } from './reducer'; + +const setNodes = (state: IFlowState, { nodes }: ReturnType) => + assocPath(['nodes'], nodes, state); + +export const FLOW_HANDLERS = { + [FLOW_ACTIONS.SET_NODES]: setNodes, +}; diff --git a/src/redux/flow/reducer.ts b/src/redux/flow/reducer.ts new file mode 100644 index 00000000..e6ec1e1e --- /dev/null +++ b/src/redux/flow/reducer.ts @@ -0,0 +1,15 @@ +import { createReducer } from '~/utils/reducer'; +import { INode, UUID } from '../types'; +import { FLOW_HANDLERS } from './handlers'; + +export type IFlowState = Readonly<{ + is_loading: boolean; + nodes: Record; +}>; + +const INITIAL_STATE: IFlowState = { + nodes: {}, + is_loading: false, +}; + +export default createReducer(INITIAL_STATE, FLOW_HANDLERS); diff --git a/src/redux/flow/sagas.ts b/src/redux/flow/sagas.ts new file mode 100644 index 00000000..8374e965 --- /dev/null +++ b/src/redux/flow/sagas.ts @@ -0,0 +1,14 @@ +import { takeLatest, call } from 'redux-saga/effects'; +import { REHYDRATE } from 'redux-persist'; +import { FLOW_ACTIONS } from './constants'; +import { getNodes } from '../node/api'; + +function* onGetFlow() { + const { data, error } = yield call(getNodes, {}); + + console.log('flow', { data, error }); +} + +export default function* nodeSaga() { + yield takeLatest([FLOW_ACTIONS.GET_FLOW, REHYDRATE], onGetFlow); +} diff --git a/src/redux/flow/selectors.ts b/src/redux/flow/selectors.ts new file mode 100644 index 00000000..f5b591c0 --- /dev/null +++ b/src/redux/flow/selectors.ts @@ -0,0 +1,4 @@ +import { IState } from '../store'; +import { INodeState } from './reducer'; + +export const selectNode = (state: IState): INodeState => state.node; diff --git a/src/redux/node/api.ts b/src/redux/node/api.ts index 289a774f..bc977744 100644 --- a/src/redux/node/api.ts +++ b/src/redux/node/api.ts @@ -2,14 +2,24 @@ import { api, configWithToken, resultMiddleware, errorMiddleware } from '~/utils import { INode, IResultWithStatus } from '../types'; import { API } from '~/constants/api'; -export const postNode = ({ +export const postNode = ({ access, node, }: { - access: string, - node: INode, -}): Promise> => ( - api.post(API.NODE.SAVE, { node }, configWithToken(access)) + access: string; + node: INode; +}): Promise> => + api + .post(API.NODE.SAVE, { node }, configWithToken(access)) .then(resultMiddleware) - .catch(errorMiddleware) -); + .catch(errorMiddleware); + +export const getNodes = ({ + skip = 0, +}: { + skip?: number; +}): Promise> => + api + .get(API.NODE.GET, { params: { skip } }) + .then(resultMiddleware) + .catch(errorMiddleware); diff --git a/src/redux/node/sagas.ts b/src/redux/node/sagas.ts index c3f4972e..f003b008 100644 --- a/src/redux/node/sagas.ts +++ b/src/redux/node/sagas.ts @@ -1,11 +1,20 @@ -import { takeLatest, call } from 'redux-saga/effects'; +import { takeLatest, call, put } from 'redux-saga/effects'; import { NODE_ACTIONS } from './constants'; -import { nodeSave } from './actions'; +import { nodeSave, nodeSetSaveErrors } from './actions'; import { postNode } from './api'; import { reqWrapper } from '../auth/sagas'; function* onNodeSave({ node }: ReturnType) { - const { data, errors } = yield call(reqWrapper, postNode, { node }); + yield put(nodeSetSaveErrors({})); + + const { + data, + data: { errors }, + } = yield call(reqWrapper, postNode, { node }); + + if (errors && Object.values(errors).length > 0) { + return yield put(nodeSetSaveErrors(errors)); + } console.log({ data, errors }); } diff --git a/src/redux/store.ts b/src/redux/store.ts index ffaf9c48..9a4ed978 100644 --- a/src/redux/store.ts +++ b/src/redux/store.ts @@ -13,6 +13,9 @@ import authSaga from '~/redux/auth/sagas'; import nodeReducer, { INodeState } from '~/redux/node/reducer'; import nodeSaga from '~/redux/node/sagas'; +import flowReducer, { IFlowState } from '~/redux/flow/reducer'; +import flowSaga from '~/redux/flow/sagas'; + import uploadReducer, { IUploadState } from '~/redux/uploads/reducer'; import uploadSaga from '~/redux/uploads/sagas'; @@ -32,6 +35,7 @@ export interface IState { router: RouterState; node: INodeState; uploads: IUploadState; + flow: IFlowState; } export const sagaMiddleware = createSagaMiddleware(); @@ -49,6 +53,7 @@ export const store = createStore( router: connectRouter(history), node: nodeReducer, uploads: uploadReducer, + flow: flowReducer, }), composeEnhancers(applyMiddleware(routerMiddleware(history), sagaMiddleware)) ); @@ -57,6 +62,7 @@ export function configureStore(): { store: Store; persistor: Persistor } sagaMiddleware.run(authSaga); sagaMiddleware.run(nodeSaga); sagaMiddleware.run(uploadSaga); + sagaMiddleware.run(flowSaga); const persistor = persistStore(store);