* 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
66 lines
2.5 KiB
JavaScript
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';
|