diff --git a/common/app/routes/challenges/components/Show.jsx b/common/app/routes/challenges/components/Show.jsx index 07fb075d6a..2e57dd14a9 100644 --- a/common/app/routes/challenges/components/Show.jsx +++ b/common/app/routes/challenges/components/Show.jsx @@ -10,7 +10,11 @@ import Step from './step/Step.jsx'; import Project from './project/Project.jsx'; import Video from './video/Video.jsx'; -import { fetchChallenge, fetchChallenges } from '../redux/actions'; +import { + fetchChallenge, + fetchChallenges, + replaceChallenge +} from '../redux/actions'; import { challengeSelector } from '../redux/selectors'; const views = { @@ -23,7 +27,8 @@ const views = { const bindableActions = { fetchChallenge, - fetchChallenges + fetchChallenges, + replaceChallenge }; const mapStateToProps = createSelector( @@ -47,15 +52,27 @@ const fetchOptions = { export class Challenges extends PureComponent { static displayName = 'Challenges'; + static propTypes = { isStep: PropTypes.bool, - fetchChallenges: PropTypes.func + fetchChallenges: PropTypes.func, + replaceChallenge: PropTypes.func, + params: PropTypes.object }; componentDidMount() { this.props.fetchChallenges(); } + componentWillReceiveProps(nextProps) { + if (this.props.params.dashedName !== nextProps.params.dashedName) { + this.props.replaceChallenge({ + dashedName: nextProps.params.dashedName, + block: nextProps.params.block + }); + } + } + renderView(viewType) { const View = views[viewType] || Classic; return ; diff --git a/common/app/routes/challenges/redux/actions.js b/common/app/routes/challenges/redux/actions.js index de904ac50d..27985c93de 100644 --- a/common/app/routes/challenges/redux/actions.js +++ b/common/app/routes/challenges/redux/actions.js @@ -30,6 +30,8 @@ export const fetchChallengesCompleted = createAction( export const updateCurrentChallenge = createAction( types.updateCurrentChallenge ); +// replaceChallenge(dashedname) => Action +export const replaceChallenge = createAction(types.replaceChallenge); // map export const updateFilter = createAction( diff --git a/common/app/routes/challenges/redux/fetch-challenges-saga.js b/common/app/routes/challenges/redux/fetch-challenges-saga.js index d568ab154d..b785ca2a37 100644 --- a/common/app/routes/challenges/redux/fetch-challenges-saga.js +++ b/common/app/routes/challenges/redux/fetch-challenges-saga.js @@ -1,5 +1,10 @@ import { Observable } from 'rx'; -import { fetchChallenge, fetchChallenges } from './types'; +import { challengeSelector } from './selectors'; +import { + fetchChallenge, + fetchChallenges, + replaceChallenge +} from './types'; import { delayedRedirect, createErrorObserable @@ -14,9 +19,24 @@ export default function fetchChallengesSaga(action$, getState, { services }) { return action$ .filter(({ type }) => ( type === fetchChallenges || - type === fetchChallenge + type === fetchChallenge || + type === replaceChallenge )) .flatMap(({ type, payload: { dashedName, block } = {} }) => { + const state = getState(); + if (type === replaceChallenge) { + const { challenge: newChallenge } = challengeSelector({ + ...state, + challengesApp: { + ...state.challengesApp, + challenge: dashedName + } + }); + if (state.challengesApp.challenge !== newChallenge.dashedName) { + return Observable.just(updateCurrentChallenge(newChallenge)); + } + return Observable.just(null); + } const options = { service: 'map' }; if (type === fetchChallenge) { options.params = { dashedName, block }; diff --git a/common/app/routes/challenges/redux/types.js b/common/app/routes/challenges/redux/types.js index 87e34beadf..141b96ce5f 100644 --- a/common/app/routes/challenges/redux/types.js +++ b/common/app/routes/challenges/redux/types.js @@ -11,6 +11,7 @@ export default createTypes([ 'fetchChallengeCompleted', 'fetchChallengesCompleted', 'updateCurrentChallenge', + 'replaceChallenge', 'resetUi', // map