Initial redux-saga is added

This commit is contained in:
Sukchan Lee 2017-06-19 19:20:39 +09:00
parent 6a5374afa8
commit c95702c0e6
9 changed files with 127 additions and 119 deletions

View File

@ -8,6 +8,7 @@
"license": "GPL-3.0",
"dependencies": {
"add": "^2.0.6",
"axios": "^0.16.2",
"babel-plugin-polished": "^1.0.3",
"babel-plugin-styled-components": "^1.1.4",
"babel-preset-stage-0": "^6.24.1",

35
webui/src/actions/crud.js Normal file
View File

@ -0,0 +1,35 @@
export const CRUD = {
FETCH: 'crud/FETCH',
FETCH_SUCCESS: 'crud/FETCH_SUCCESS',
FETCH_FAILURE: 'crud/FETCH_FAILURE',
FETCH_ONE: 'crud/FETCH_ONE',
FETCH_ONE_SUCCESS: 'crud/FETCH_ONE_SUCCESS',
FETCH_ONE_FAILURE: 'crud/FETCH_ONE_FAILURE',
CREATE: 'crud/CREATE',
CREATE_SUCCESS: 'crud/CREATE_SUCCESS',
CREATE_FAILURE: 'crud/CREATE_FAILURE',
UPDATE: 'crud/UPDATE',
UPDATE_SUCCESS: 'crud/UPDATE_SUCCESS',
UPDATE_FAILURE: 'crud/UPDATE_FAILURE',
DELETE: 'crud/DELETE',
DELETE_SUCCESS: 'crud/DELETE_SUCCESS',
DELETE_FAILURE: 'crud/DELETE_FAILURE',
};
export const fetchCollection = (model, id, url, params) => {
return {
type: CRUD.FETCH,
meta: {
success: CRUD.FETCH_SUCCESS,
failure: CRUD.FETCH_FAILURE,
model,
id,
params
},
payload: {
method: 'get',
url,
params
}
}
}

View File

@ -1,26 +1,11 @@
import {
fetchCollection, fetchRecord, createRecord, updateRecord, deleteRecord
} from 'redux-crud-store'
fetchCollection
} from 'actions/crud'
const MODEL = 'subscribers'
const PATH = '/Subscriber'
const MODEL = 'subscribers';
const ID = 'imsi';
const URL = '/Subscriber';
export function fetchSubscribers(params = {}) {
return fetchCollection(MODEL, PATH, params)
}
export function fetchSubscriber(id, params = {}) {
return fetchRecord(MODEL, id, `${PATH}/${id}`, params)
}
export function createSubscriber(data = {}) {
return createRecord(MODEL, PATH, data)
}
export function updateSubscriber(id, data = {}) {
return updateRecord(MODEL, id, `${PATH}/${id}`, data)
}
export function deleteSubscriber(id) {
return deleteRecord(MODEL, id, `${PATH}/${id}`)
export const fetchSubscribers = (params = {}) => {
return fetchCollection(MODEL, ID, URL, params)
}

View File

@ -1,7 +1,16 @@
import { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { fetchSubscribers } from 'actions/subscriber';
import { fetchCollection } from 'actions/crud';
class SubscriberContainer extends Component {
componentWillMount() {
const { crud, dispatch } = this.props
dispatch(fetchSubscribers());
}
render() {
return <div>
<p>loading...</p>
@ -9,4 +18,8 @@ class SubscriberContainer extends Component {
}
}
export default SubscriberContainer;
export default connect(
(state) => ({
crud: state.crud
})
)(SubscriberContainer);

View File

@ -0,0 +1,41 @@
import { CRUD } from 'actions/crud';
import { fromJS } from 'immutable';
const byIdInitialState = fromJS({});
export const modelInitialState = fromJS({
byId: byIdInitialState
});
const initialState = fromJS({});
export function byIdReducer(state = byIdInitialState, action) {
switch(action.type) {
case CRUD.FETCH_SUCCESS:
const data = state.toJS();
action.payload.forEach((document) => {
data[document[action.meta.id]] = {
document,
error: null
}
})
return fromJS(data);
default:
return state;
}
}
function crud(state = initialState, action) {
switch(action.type) {
case CRUD.FETCH:
case CRUD.FETCH_SUCCESS:
case CRUD.FETCH_FAILURE:
return state.updateIn([action.meta.model, "byId"],
(s) => byIdReducer(s, action));
default:
return state;
}
}
export default crud;

View File

@ -1,9 +1,11 @@
import { combineReducers } from 'redux';
import auth from './auth';
import crud from './crud';
import ui from './ui';
export default combineReducers({
auth,
crud,
ui
});

View File

@ -1,113 +1,29 @@
/* @flow */
/* global Generator */
/*
import 'regenerator-runtime/runtime'
import { takeEvery, fork, put, call } from 'redux-saga/effects'
import {
FETCH, FETCH_ONE, CREATE, UPDATE, DELETE, API_CALL, GARBAGE_COLLECT
} from './actionTypes'
// TODO: The `Effect` type is not actually defined. Because 'redux-saga' does
// not use @flow annotations, flow pretends that this import succeeds.
import type { Effect } from 'redux-saga'
import type { CrudAction } from './actionTypes'
// Generator type parameters are: Generator<+Yield,+Return,-Next>
const delay = ms => new Promise(resolve => setTimeout(resolve, ms))
function* garbageCollector() {
yield call(delay, 10 * 60 * 1000) // initial 10 minute delay
for (;;) {
yield call(delay, 5 * 60 * 1000) // every 5 minutes thereafter
yield put({ type: GARBAGE_COLLECT, meta: { now: Date.now() } })
}
}
export const apiGeneric = (apiClient: Object) =>
function* _apiGeneric(action: CrudAction<any>): Generator<Effect, void, any> {
const { method, path, params, data, fetchConfig } = action.payload
const { success, failure } = action.meta
const meta = {
...action.meta,
fetchTime: Date.now()
}
try {
const response = yield call(apiClient[method], path, { params, data, fetchConfig })
yield put({ meta, type: success, payload: response })
} catch (error) {
yield put({ meta, type: failure, payload: error, error: true })
}
}
const watchFetch = (apiClient) => function* _watchFetch() {
yield* takeEvery(FETCH, apiGeneric(apiClient))
}
const watchFetchOne = (apiClient) => function* _watchFetchOne() {
yield* takeEvery(FETCH_ONE, apiGeneric(apiClient))
}
const watchCreate = (apiClient) => function* _watchCreate() {
yield* takeEvery(CREATE, apiGeneric(apiClient))
}
const watchUpdate = (apiClient) => function* _watchUpdate() {
yield* takeEvery(UPDATE, apiGeneric(apiClient))
}
const watchDelete = (apiClient) => function* _watchDelete() {
yield* takeEvery(DELETE, apiGeneric(apiClient))
}
const watchApiCall = (apiClient) => function* _watchApiCall() {
yield* takeEvery(API_CALL, apiGeneric(apiClient))
}
export default function crudSaga(apiClient: Object) {
return function* _crudSaga(): Generator<Effect, void, any> {
yield [
fork(watchFetch(apiClient)),
fork(watchFetchOne(apiClient)),
fork(watchCreate(apiClient)),
fork(watchUpdate(apiClient)),
fork(watchDelete(apiClient)),
fork(watchApiCall(apiClient)),
fork(garbageCollector)
]
}
}
*/
import axios from 'axios';
import { all, takeEvery, put, call } from 'redux-saga/effects';
import { ApiClient } from 'redux-crud-store';
import { crudActions } from 'redux-crud-store';
import { CRUD } from 'actions/crud';
const apiClient = new ApiClient({ basePath: '/api/db' })
const crudApi = (method, url, { params, data } = {} ) => {
return axios({ baseURL: '/api/db', method, url, params, data })
.then(response => response.data);
}
function* apiGeneric(action) {
const { method, path, params, data, fetchConfig } = action.payload
const { success, failure } = action.meta
function* crudEntity(action) {
const { method, url, params, data } = action.payload;
const { success, failure } = action.meta;
const meta = {
...action.meta,
fetchTime: Date.now()
}
try {
const response = yield call(apiClient[method], path, { params, data, fetchConfig })
const response = yield call(crudApi, method, url, { params, data })
yield put({ meta, type: success, payload: response })
} catch (error) {
yield put({ meta, type: failure, payload: error, error: true })
}
}
function* watchFetch() {
yield takeEvery(crudActions.FETCH, apiGeneric)
yield takeEvery(CRUD.FETCH, crudEntity)
}
export default function* () {

View File

@ -1,8 +1,10 @@
import { all } from 'redux-saga/effects';
import auth from './auth';
import crud from './crud';
export default function* rootSaga() {
yield all([
auth(),
crud()
])
}

View File

@ -186,6 +186,13 @@ aws4@^1.2.1:
version "1.6.0"
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e"
axios@^0.16.2:
version "0.16.2"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.16.2.tgz#ba4f92f17167dfbab40983785454b9ac149c3c6d"
dependencies:
follow-redirects "^1.2.3"
is-buffer "^1.1.5"
babel-code-frame@^6.20.0, babel-code-frame@^6.22.0:
version "6.22.0"
resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.22.0.tgz#027620bee567a88c32561574e7fd0801d33118e4"
@ -1471,7 +1478,7 @@ debug@2.6.7:
dependencies:
ms "2.0.0"
debug@2.6.8, debug@^2.1.1, debug@^2.2.0:
debug@2.6.8, debug@^2.1.1, debug@^2.2.0, debug@^2.4.5:
version "2.6.8"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc"
dependencies:
@ -1844,6 +1851,12 @@ find-up@^2.1.0:
dependencies:
locate-path "^2.0.0"
follow-redirects@^1.2.3:
version "1.2.3"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.2.3.tgz#01abaeca85e3609837d9fcda3167a7e42fdaca21"
dependencies:
debug "^2.4.5"
for-in@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"