feat(username): Add Username updating
This commit is contained in:
@@ -8,6 +8,8 @@ import { createReportUserSaga } from './report-user-saga';
|
||||
import { createShowCertSaga } from './show-cert-saga';
|
||||
import { createUpdateMyEmailSaga } from './update-email-saga';
|
||||
|
||||
import { types as settingsTypes } from './settings';
|
||||
|
||||
const ns = 'app';
|
||||
|
||||
const defaultFetchState = {
|
||||
@@ -74,6 +76,9 @@ export const updateMyEmailError = createAction(types.updateMyEmailError);
|
||||
|
||||
export const isSignedInSelector = state => !!Object.keys(state[ns].user).length;
|
||||
|
||||
export const signInLoadingSelector = state =>
|
||||
userFetchStateSelector(state).pending;
|
||||
|
||||
export const showCertSelector = state => state[ns].showCert;
|
||||
export const showCertFetchStateSelector = state => state[ns].showCertFetchState;
|
||||
|
||||
@@ -83,7 +88,11 @@ export const userByNameSelector = username => state => {
|
||||
};
|
||||
export const userFetchStateSelector = state => state[ns].userFetchState;
|
||||
export const usernameSelector = state => state[ns].appUsername;
|
||||
export const userSelector = state => state[ns].user;
|
||||
export const userSelector = state => {
|
||||
const username = usernameSelector(state);
|
||||
|
||||
return state[ns].user[username] || {};
|
||||
};
|
||||
|
||||
export const reducer = handleActions(
|
||||
{
|
||||
@@ -93,7 +102,10 @@ export const reducer = handleActions(
|
||||
}),
|
||||
[types.fetchUserComplete]: (state, { payload: { user, username } }) => ({
|
||||
...state,
|
||||
user,
|
||||
user: {
|
||||
...state.user,
|
||||
[username]: user
|
||||
},
|
||||
appUsername: username,
|
||||
userFetchState: {
|
||||
pending: false,
|
||||
@@ -135,7 +147,20 @@ export const reducer = handleActions(
|
||||
errored: true,
|
||||
error: payload
|
||||
}
|
||||
})
|
||||
}),
|
||||
[settingsTypes.submitNewUsernameComplete]: (state, { payload }) =>
|
||||
payload
|
||||
? {
|
||||
...state,
|
||||
user: {
|
||||
...state.user,
|
||||
[state.appUsername]: {
|
||||
...state.user[state.appUsername],
|
||||
username: payload
|
||||
}
|
||||
}
|
||||
}
|
||||
: state
|
||||
},
|
||||
initialState
|
||||
);
|
||||
|
@@ -2,8 +2,10 @@ import { combineReducers } from 'redux';
|
||||
|
||||
import { reducer as app } from './';
|
||||
import { reducer as flash } from '../components/Flash/redux';
|
||||
import { reducer as settings } from './settings';
|
||||
|
||||
export default combineReducers({
|
||||
app,
|
||||
flash
|
||||
flash,
|
||||
settings
|
||||
});
|
||||
|
@@ -1,7 +1,8 @@
|
||||
import { all } from 'redux-saga/effects';
|
||||
|
||||
import { sagas as appSagas } from './';
|
||||
import { sagas as settingsSagas } from './settings';
|
||||
|
||||
export default function* rootSaga() {
|
||||
yield all([...appSagas]);
|
||||
yield all([...appSagas, ...settingsSagas]);
|
||||
}
|
||||
|
73
client/src/redux/settings/index.js
Normal file
73
client/src/redux/settings/index.js
Normal file
@@ -0,0 +1,73 @@
|
||||
import { createAction, handleActions } from 'redux-actions';
|
||||
|
||||
import { createTypes, createAsyncTypes } from '../../utils/createTypes';
|
||||
import { createSettingsSagas } from './settings-sagas';
|
||||
|
||||
const ns = 'settings';
|
||||
|
||||
const defaultFetchState = {
|
||||
pending: false,
|
||||
complete: false,
|
||||
errored: false,
|
||||
error: null
|
||||
};
|
||||
|
||||
const initialState = {
|
||||
usernameValidation: {
|
||||
isValidUsername: false,
|
||||
fetchState: { ...defaultFetchState }
|
||||
}
|
||||
};
|
||||
|
||||
export const types = createTypes(
|
||||
[
|
||||
...createAsyncTypes('validateUsername'),
|
||||
...createAsyncTypes('submitNewUsername')
|
||||
],
|
||||
ns
|
||||
);
|
||||
|
||||
export const sagas = [...createSettingsSagas(types)];
|
||||
|
||||
export const submitNewUsername = createAction(types.submitNewUsername);
|
||||
export const submitNewUsernameComplete = createAction(
|
||||
types.submitNewUsernameComplete,
|
||||
({ type, username }) => (type === 'success' ? username : null)
|
||||
);
|
||||
export const submitNewUsernameError = createAction(
|
||||
types.submitNewUsernameError
|
||||
);
|
||||
|
||||
export const validateUsername = createAction(types.validateUsername);
|
||||
export const validateUsernameComplete = createAction(
|
||||
types.validateUsernameComplete
|
||||
);
|
||||
export const validateUsernameError = createAction(types.validateUsernameError);
|
||||
|
||||
export const usernameValidationSelector = state => state[ns].usernameValidation;
|
||||
|
||||
export const reducer = handleActions(
|
||||
{
|
||||
[types.submitNewUsernameComplete]: state => ({
|
||||
...state,
|
||||
usernameValidation: { ...initialState.usernameValidation }
|
||||
}),
|
||||
[types.validateUsername]: state => ({
|
||||
...state,
|
||||
usernameValidation: {
|
||||
...state.usernameValidation,
|
||||
isValidUsername: false,
|
||||
fetchState: { ...defaultFetchState, pending: true }
|
||||
}
|
||||
}),
|
||||
[types.validateUsernameComplete]: (state, { payload }) => ({
|
||||
...state,
|
||||
usernameValidation: {
|
||||
...state.usernameValidation,
|
||||
isValidUsername: !payload,
|
||||
fetchState: { ...defaultFetchState, pending: false, complete: true }
|
||||
}
|
||||
})
|
||||
},
|
||||
initialState
|
||||
);
|
41
client/src/redux/settings/settings-sagas.js
Normal file
41
client/src/redux/settings/settings-sagas.js
Normal file
@@ -0,0 +1,41 @@
|
||||
import { delay } from 'redux-saga';
|
||||
import { call, put, takeLatest } from 'redux-saga/effects';
|
||||
|
||||
import {
|
||||
validateUsernameComplete,
|
||||
validateUsernameError,
|
||||
submitNewUsernameComplete,
|
||||
submitNewUsernameError
|
||||
} from './';
|
||||
|
||||
import { getUsernameExists, putUpdateMyUsername } from '../../utils/ajax';
|
||||
import { createFlashMessage } from '../../components/Flash/redux';
|
||||
|
||||
function* validateUsernameSaga({ payload }) {
|
||||
try {
|
||||
yield delay(500);
|
||||
const {
|
||||
data: { exists }
|
||||
} = yield call(getUsernameExists, payload);
|
||||
yield put(validateUsernameComplete(exists));
|
||||
} catch (e) {
|
||||
yield put(validateUsernameError(e));
|
||||
}
|
||||
}
|
||||
|
||||
function* submitNEwUswernameSaga({ payload: username }) {
|
||||
try {
|
||||
const { data: response } = yield call(putUpdateMyUsername, username);
|
||||
yield put(submitNewUsernameComplete({...response, username}));
|
||||
yield put(createFlashMessage(response));
|
||||
} catch (e) {
|
||||
yield put(submitNewUsernameError(e));
|
||||
}
|
||||
}
|
||||
|
||||
export function createSettingsSagas(types) {
|
||||
return [
|
||||
takeLatest(types.validateUsername, validateUsernameSaga),
|
||||
takeLatest(types.submitNewUsername, submitNEwUswernameSaga)
|
||||
];
|
||||
}
|
Reference in New Issue
Block a user