Files
freeCodeCamp/common/app/routes/Challenges/index.js
Berkeley Martinez dced96da8e feat: react challenges (#16099)
* chore(packages): Update redux utils

* feat(Panes): Invert control of panes map creation

* feat(Modern): Add view

* feat(Panes): Decouple panes from Challenges

* fix(Challenges): Decouple challenge views from panes map

* fix(Challenge/views): PanesMap => mapStateToPanesMap

This clarifies what these functions are doing

* fix(Challenges): Add view type

* fix(Panes): Remove unneeded panes container

* feat(Panes): Invert control of pane content render

This decouples the Panes from the content they render, allowing for
greater flexibility.

* feat(Modern): Add side panel

This is common between modern and classic

* feat(seed): Array to string file content

* fix(files): Modern files should be polyvinyls

* feat(Modern): Create editors per file

* fix(seed/React): Incorrect keyfile name

* feat(Modern): Highligh jsx correctly

This adds highlighting for jsx. Unfortunately, this disables linting for
non-javascript files as jshint will only work for those

* feat(rechallenge): Add jsx ext to babel transformer

* feat(seed): Normalize challenge files head/tail/content

* refactor(rechallenge/build): Rename function

* fix(code-storage): Pull in files from localStorage

* feat(Modern/React): Add Enzyme to test runner

This enables testing of React challenges

* feat(Modern): Add submission type

* refactor(Panes): Rename panes map update action
2017-11-29 17:44:51 -06:00

66 lines
2.5 KiB
JavaScript

import _ from 'lodash';
import { isLocationAction, redirect } from 'redux-first-router';
import { types, challengeMetaSelector } from './redux';
import { mapStateToPanes as backendPanesMap } from './views/backend';
import { mapStateToPanes as classicPanesMap } from './views/classic';
import { mapStateToPanes as stepPanesMap } from './views/step';
import { mapStateToPanes as projectPanesMap } from './views/project';
import { mapStateToPanes as quizPanesMap } from './views/quiz';
import { mapStateToPanes as modernPanesMap } from './views/Modern';
import { types as app } from '../../redux';
import { locationTypeSelector } from '../../Router/redux';
export const routes = {
[types.onRouteChallengeRoot]: {
path: '/challenges',
thunk: (dispatch) =>
dispatch(redirect({ type: types.onRouteCurrentChallenge }))
},
[types.onRouteChallenges]: '/challenges/:block/:dashedName',
[types.onRouteCurrentChallenge]: '/challenges/current-challenge'
};
export function createPanesMap() {
const viewMap = {
[backendPanesMap]: backendPanesMap,
[classicPanesMap]: classicPanesMap,
[stepPanesMap]: stepPanesMap,
[projectPanesMap]: projectPanesMap,
[quizPanesMap]: quizPanesMap,
[modernPanesMap]: modernPanesMap
};
return (state, action) => {
// if a location action has dispatched then we must update the panesmap
if (isLocationAction(action)) {
let finalPanesMap = {};
// if we are on this route,
// then we must figure out the currect view we are on
// this depends on the type of challenge
if (action.type === types.onRouteChallenges) {
// location matches a panes route
const meta = challengeMetaSelector(state);
// if challenge data has not been fetched yet (as in the case of SSR)
// then we will get a pojo factory
const mapStateToPanes = viewMap[meta.viewType] || _.stubObject;
finalPanesMap = mapStateToPanes(state);
}
return finalPanesMap;
}
// This should normally happen during SSR
// here we are ensured that the challenge data has been fetched
// now we can select the appropriate panes map factory
if (
action.type === app.fetchChallenge.complete &&
locationTypeSelector(state) === types.onRouteChallenges
) {
const meta = challengeMetaSelector(state);
const mapStateToPanes = viewMap[meta.viewType] || _.stubObject;
return mapStateToPanes(state);
}
return null;
};
}
export { default } from './Show.jsx';