Feature(settings): Update url/challenge lang onChange
This commit is contained in:
@ -9,7 +9,8 @@ import {
|
|||||||
initWindowHeight,
|
initWindowHeight,
|
||||||
updateNavHeight,
|
updateNavHeight,
|
||||||
toggleMapDrawer,
|
toggleMapDrawer,
|
||||||
toggleMainChat
|
toggleMainChat,
|
||||||
|
updateAppLang
|
||||||
} from './redux/actions';
|
} from './redux/actions';
|
||||||
|
|
||||||
import { submitChallenge } from './routes/challenges/redux/actions';
|
import { submitChallenge } from './routes/challenges/redux/actions';
|
||||||
@ -18,6 +19,16 @@ import Nav from './components/Nav';
|
|||||||
import Toasts from './toasts/Toasts.jsx';
|
import Toasts from './toasts/Toasts.jsx';
|
||||||
import { userSelector } from './redux/selectors';
|
import { userSelector } from './redux/selectors';
|
||||||
|
|
||||||
|
const bindableActions = {
|
||||||
|
initWindowHeight,
|
||||||
|
updateNavHeight,
|
||||||
|
fetchUser,
|
||||||
|
submitChallenge,
|
||||||
|
toggleMapDrawer,
|
||||||
|
toggleMainChat,
|
||||||
|
updateAppLang
|
||||||
|
};
|
||||||
|
|
||||||
const mapStateToProps = createSelector(
|
const mapStateToProps = createSelector(
|
||||||
userSelector,
|
userSelector,
|
||||||
state => state.app.shouldShowSignIn,
|
state => state.app.shouldShowSignIn,
|
||||||
@ -43,15 +54,6 @@ const mapStateToProps = createSelector(
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
const bindableActions = {
|
|
||||||
initWindowHeight,
|
|
||||||
updateNavHeight,
|
|
||||||
fetchUser,
|
|
||||||
submitChallenge,
|
|
||||||
toggleMapDrawer,
|
|
||||||
toggleMainChat
|
|
||||||
};
|
|
||||||
|
|
||||||
// export plain class for testing
|
// export plain class for testing
|
||||||
export class FreeCodeCamp extends React.Component {
|
export class FreeCodeCamp extends React.Component {
|
||||||
static displayName = 'FreeCodeCamp';
|
static displayName = 'FreeCodeCamp';
|
||||||
@ -74,9 +76,16 @@ export class FreeCodeCamp extends React.Component {
|
|||||||
toggleMainChat: PropTypes.func,
|
toggleMainChat: PropTypes.func,
|
||||||
fetchUser: PropTypes.func,
|
fetchUser: PropTypes.func,
|
||||||
shouldShowSignIn: PropTypes.bool,
|
shouldShowSignIn: PropTypes.bool,
|
||||||
params: PropTypes.object
|
params: PropTypes.object,
|
||||||
|
updateAppLang: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
|
componentWillReceiveProps(nextProps) {
|
||||||
|
if (this.props.params.lang !== nextProps.params.lang) {
|
||||||
|
this.props.updateAppLang(nextProps.params.lang);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.props.initWindowHeight();
|
this.props.initWindowHeight();
|
||||||
if (!this.props.isSignedIn) {
|
if (!this.props.isSignedIn) {
|
||||||
|
@ -40,6 +40,7 @@ export const updateUserLang = createAction(
|
|||||||
types.updateUserLang,
|
types.updateUserLang,
|
||||||
(username, lang) => ({ username, lang })
|
(username, lang) => ({ username, lang })
|
||||||
);
|
);
|
||||||
|
export const updateAppLang = createAction(types.updateAppLang);
|
||||||
// updateCompletedChallenges(username: String) => Action
|
// updateCompletedChallenges(username: String) => Action
|
||||||
export const updateCompletedChallenges = createAction(
|
export const updateCompletedChallenges = createAction(
|
||||||
types.updateCompletedChallenges
|
types.updateCompletedChallenges
|
||||||
|
@ -25,6 +25,10 @@ export default handleActions(
|
|||||||
user,
|
user,
|
||||||
shouldShowSignIn: true
|
shouldShowSignIn: true
|
||||||
}),
|
}),
|
||||||
|
[types.updateAppLang]: (state, { payload = 'en' }) =>({
|
||||||
|
...state,
|
||||||
|
lang: payload
|
||||||
|
}),
|
||||||
[types.showSignIn]: state => ({
|
[types.showSignIn]: state => ({
|
||||||
...state,
|
...state,
|
||||||
shouldShowSignIn: true
|
shouldShowSignIn: true
|
||||||
|
@ -2,6 +2,7 @@ import createTypes from '../utils/create-types';
|
|||||||
|
|
||||||
export default createTypes([
|
export default createTypes([
|
||||||
'updateTitle',
|
'updateTitle',
|
||||||
|
'updateAppLang',
|
||||||
|
|
||||||
'fetchUser',
|
'fetchUser',
|
||||||
'addUser',
|
'addUser',
|
||||||
|
@ -8,11 +8,11 @@ import { userSelector } from '../../../redux/selectors';
|
|||||||
import langs from '../../../../utils/supported-languages';
|
import langs from '../../../../utils/supported-languages';
|
||||||
|
|
||||||
const mapStateToProps = createSelector(
|
const mapStateToProps = createSelector(
|
||||||
userSelector,
|
userSelector,
|
||||||
({ user: { languageTag } }) => ({
|
({ user: { languageTag } }) => ({
|
||||||
// send null to prevent redux-form from initialize empty
|
// send null to prevent redux-form from initialize empty
|
||||||
initialValues: languageTag ? { lang: languageTag } : null
|
initialValues: languageTag ? { lang: languageTag } : null
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
const actions = { updateMyLang };
|
const actions = { updateMyLang };
|
||||||
const fields = [ 'lang' ];
|
const fields = [ 'lang' ];
|
||||||
|
@ -1,14 +1,17 @@
|
|||||||
import { Observable } from 'rx';
|
import { Observable } from 'rx';
|
||||||
|
import { push } from 'react-router-redux';
|
||||||
|
|
||||||
import { types } from './actions';
|
import { types } from './actions';
|
||||||
import combineSagas from '../../../utils/combine-sagas';
|
import combineSagas from '../../../utils/combine-sagas';
|
||||||
import { makeToast } from '../../../toasts/redux/actions';
|
import { makeToast } from '../../../toasts/redux/actions';
|
||||||
|
import { fetchChallenges } from '../../challenges/redux/actions';
|
||||||
import {
|
import {
|
||||||
updateUserFlag,
|
updateUserFlag,
|
||||||
updateUserEmail,
|
updateUserEmail,
|
||||||
updateUserLang,
|
updateUserLang,
|
||||||
doActionOnError
|
doActionOnError
|
||||||
} from '../../../redux/actions';
|
} from '../../../redux/actions';
|
||||||
|
import { userSelector } from '../../../redux/selectors';
|
||||||
import { postJSON$ } from '../../../../utils/ajax-stream';
|
import { postJSON$ } from '../../../../utils/ajax-stream';
|
||||||
import langs from '../../../../utils/supported-languages';
|
import langs from '../../../../utils/supported-languages';
|
||||||
|
|
||||||
@ -47,26 +50,33 @@ export function updateUserLangSaga(actions$, getState) {
|
|||||||
.filter(({ type, payload }) => (
|
.filter(({ type, payload }) => (
|
||||||
type === types.updateMyLang && !!langs[payload]
|
type === types.updateMyLang && !!langs[payload]
|
||||||
))
|
))
|
||||||
.map(({ payload }) => payload);
|
.map(({ payload }) => {
|
||||||
|
const state = getState();
|
||||||
|
const { user: { languageTag } } = userSelector(state);
|
||||||
|
return { lang: payload, oldLang: languageTag };
|
||||||
|
});
|
||||||
const ajaxUpdate$ = updateLang$
|
const ajaxUpdate$ = updateLang$
|
||||||
.flatMap(lang => {
|
.debounce(250)
|
||||||
const {
|
.flatMap(({ lang, oldLang }) => {
|
||||||
app: { user: username, csrfToken: _csrf },
|
const { app: { user: username, csrfToken: _csrf } } = getState();
|
||||||
entities: { user: userMap }
|
const body = { _csrf, lang };
|
||||||
} = getState();
|
|
||||||
const { languageTag: oldLang } = userMap[username] || {};
|
|
||||||
const body = {
|
|
||||||
_csrf,
|
|
||||||
lang
|
|
||||||
};
|
|
||||||
return postJSON$('/update-my-lang', body)
|
return postJSON$('/update-my-lang', body)
|
||||||
.map(({ message }) => makeToast({ message }))
|
.flatMap(({ message }) => {
|
||||||
|
return Observable.of(
|
||||||
|
// show user that we have updated their lang
|
||||||
|
makeToast({ message }),
|
||||||
|
// update url to reflect change
|
||||||
|
push(`/${lang}/settings`),
|
||||||
|
// refetch challenges in new language
|
||||||
|
fetchChallenges()
|
||||||
|
);
|
||||||
|
})
|
||||||
.catch(doActionOnError(() => {
|
.catch(doActionOnError(() => {
|
||||||
return updateUserLang(username, oldLang);
|
return updateUserLang(username, oldLang);
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
const optimistic$ = updateLang$
|
const optimistic$ = updateLang$
|
||||||
.map(lang => {
|
.map(({ lang }) => {
|
||||||
const { app: { user: username } } = getState();
|
const { app: { user: username } } = getState();
|
||||||
return updateUserLang(username, lang);
|
return updateUserLang(username, lang);
|
||||||
});
|
});
|
||||||
|
Reference in New Issue
Block a user