chore(client): Move client app to /client

This commit is contained in:
Bouncey
2018-08-31 12:52:49 +01:00
committed by mrugesh mohapatra
parent 0e4f588a1c
commit e59ad6ebda
172 changed files with 13171 additions and 14 deletions

View File

@@ -0,0 +1,29 @@
import { call, put, takeEvery } from 'redux-saga/effects';
import { navigateTo } from 'gatsby';
import { acceptTermsComplete, acceptTermsError } from './';
import { createFlashMessage } from '../components/Flash/redux';
import { putUserAcceptsTerms } from '../utils/ajax';
function* acceptTermsSaga({ payload: quincyEmails }) {
try {
const { data: response } = yield call(putUserAcceptsTerms, quincyEmails);
yield put(acceptTermsComplete());
yield put(createFlashMessage(response));
} catch (e) {
yield put(acceptTermsError(e));
}
}
function* acceptCompleteSaga() {
yield call(navigateTo, '/welcome');
}
export function createAcceptTermsSaga(types) {
return [
takeEvery(types.acceptTerms, acceptTermsSaga),
takeEvery(types.acceptTermsComplete, acceptCompleteSaga)
];
}

View File

@@ -0,0 +1,28 @@
import { put, takeEvery } from 'redux-saga/effects';
import qs from 'query-string';
import { createFlashMessage } from '../components/Flash/redux';
function* parseMessagesSaga() {
const search = window.location.search.slice();
// TODO(Bouncey): Find a way to clear the search with causing a re-render
if (search) {
const { messages } = qs.parse(search, { arrayFormat: 'index' });
if (messages) {
const flashMap = qs.parse(messages, { arrayFormat: 'index' });
const flash = Object.keys(flashMap).reduce(
(acc, type) => [
...acc,
...flashMap[type].map(message => ({ type, message }))
],
[]
);
for (let i = 0; i < flash.length; i++) {
yield put(createFlashMessage(flash[i]));
}
}
}
}
export function createAppMountSaga(types) {
return [takeEvery(types.appMount, parseMessagesSaga)];
}

View File

@@ -0,0 +1,16 @@
import { createStore as reduxCreateStore, applyMiddleware } from 'redux';
import createSagaMiddleware from 'redux-saga';
import rootReducer from './rootReducer';
import rootSaga from './rootSaga';
const sagaMiddleware = createSagaMiddleware();
export const createStore = () => {
const store = reduxCreateStore(
rootReducer,
applyMiddleware(sagaMiddleware)
);
sagaMiddleware.run(rootSaga);
return store;
};

View File

@@ -0,0 +1,24 @@
import { call, put, takeEvery } from 'redux-saga/effects';
import { fetchUserComplete, fetchUserError } from './';
import { getSessionUser } from '../utils/ajax';
function* fetchSessionUser() {
console.log('fetchSessionUser');
try {
const {
data: {
user = {},
result = ''
}
} = yield call(getSessionUser);
const appUser = user[result];
yield put(fetchUserComplete({ user: appUser, username: result }));
} catch (e) {
yield put(fetchUserError(e));
}
}
export function createFetchUserSaga(types) {
return [takeEvery(types.fetchUser, fetchSessionUser)];
}

91
client/src/redux/index.js Normal file
View File

@@ -0,0 +1,91 @@
import { createAction, handleActions } from 'redux-actions';
import { createTypes, createAsyncTypes } from '../utils/createTypes';
import { createFetchUserSaga } from './fetch-user-saga';
import { createAcceptTermsSaga } from './accept-terms-saga';
import { createAppMountSaga } from './app-mount-saga';
import { createUpdateMyEmailSaga } from './update-email-saga';
const ns = 'app';
const initialState = {
appUsername: '',
fetchState: {
pending: true,
complete: false,
errored: false,
error: null
},
user: {}
};
const types = createTypes(
[
'appMount',
...createAsyncTypes('fetchUser'),
...createAsyncTypes('acceptTerms'),
...createAsyncTypes('updateMyEmail')
],
ns
);
export const sagas = [
...createAcceptTermsSaga(types),
...createAppMountSaga(types),
...createFetchUserSaga(types),
...createUpdateMyEmailSaga(types)
];
export const appMount = createAction(types.appMount);
export const acceptTerms = createAction(types.acceptTerms);
export const acceptTermsComplete = createAction(types.acceptTermsComplete);
export const acceptTermsError = createAction(types.acceptTermsError);
export const fetchUser = createAction(types.fetchUser);
export const fetchUserComplete = createAction(types.fetchUserComplete);
export const fetchUserError = createAction(types.fetchUserError);
export const updateMyEmail = createAction(types.updateMyEmail);
export const updateMyEmailComplete = createAction(types.updateMyEmailComplete);
export const updateMyEmailError = createAction(types.updateMyEmailError);
export const isSignedInSelector = state => !!Object.keys(state[ns].user).length;
export const userFetchStateSelector = state => state[ns].fetchState;
export const usernameSelector = state => state[ns].appUsername;
export const userSelector = state => state[ns].user;
export const reducer = handleActions(
{
[types.fetchUser]: state => ({
...state,
fetchState: {
pending: true,
complete: false,
errored: false,
error: null
}
}),
[types.fetchUserComplete]: (state, { payload: { user, username } }) => ({
...state,
user,
appUsername: username,
fetchState: {
pending: false,
complete: true,
errored: false,
error: null
}
}),
[types.fetchUserError]: (state, { payload }) => ({
...state,
fetchState: {
pending: false,
complete: false,
errored: true,
error: payload
}
})
},
initialState
);

View File

@@ -0,0 +1,9 @@
import { combineReducers } from 'redux';
import { reducer as app } from './';
import { reducer as flash } from '../components/Flash/redux';
export default combineReducers({
app,
flash
});

View File

@@ -0,0 +1,9 @@
import { all } from 'redux-saga/effects';
import { sagas as appSagas } from './';
export default function* rootSaga() {
yield all([
...appSagas
]);
}

View File

@@ -0,0 +1,23 @@
import { call, put, takeEvery } from 'redux-saga/effects';
import { updateMyEmailComplete, updateMyEmailError } from './';
import { createFlashMessage } from '../components/Flash/redux';
import { putUserUpdateEmail } from '../utils/ajax';
function* updateMyEmailSaga({ payload: newEmail }) {
try {
const { data: response } = yield call(putUserUpdateEmail, newEmail);
yield put(updateMyEmailComplete());
yield put(createFlashMessage(response));
} catch (e) {
yield put(updateMyEmailError(e));
}
}
export function createUpdateMyEmailSaga(types) {
return [
takeEvery(types.updateMyEmail, updateMyEmailSaga)
];
}