Files
freeCodeCamp/common/app/create-app.jsx
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

101 lines
2.6 KiB
JavaScript

import { Observable } from 'rx';
import { compose, createStore, applyMiddleware } from 'redux';
import { selectLocationState, connectRoutes } from 'redux-first-router';
import { combineReducers } from 'berkeleys-redux-utils';
import { createEpic } from 'redux-epic';
import appReducer from './reducer.js';
import routesMap from './routes-map.js';
import createPanesMap from './create-panes-map.js';
import createPanesAspects from './Panes/redux';
import addLangToRoutesEnhancer from './Router/redux/add-lang-enhancer.js';
import epics from './epics';
import { onBeforeChange } from './utils/redux-first-router.js';
import servicesCreator from '../utils/services-creator';
// createApp(settings: {
// history?: History,
// defaultState?: Object|Void,
// serviceOptions?: Object,
// middlewares?: Function[],
// enhancers?: Function[],
// epics?: Function[],
// }) => Observable
//
// Either location or history must be defined
export default function createApp({
history,
defaultState,
serviceOptions = {},
middlewares: sideMiddlewares = [],
enhancers: sideEnhancers = [],
epics: sideEpics = [],
epicOptions: sideEpicOptions = {}
}) {
const epicOptions = {
...sideEpicOptions,
services: servicesCreator(serviceOptions)
};
const epicMiddleware = createEpic(
epicOptions,
...epics,
...sideEpics
);
const {
reducer: routesReducer,
middleware: routesMiddleware,
enhancer: routesEnhancer
} = connectRoutes(history, routesMap, { onBeforeChange });
routesReducer.toString = () => 'location';
const {
reducer: panesReducer,
middleware: panesMiddleware
} = createPanesAspects({ createPanesMap });
const enhancer = compose(
addLangToRoutesEnhancer(routesMap),
routesEnhancer,
applyMiddleware(
routesMiddleware,
panesMiddleware,
epicMiddleware,
...sideMiddlewares
),
// enhancers must come after middlewares
// on client side these are things like Redux DevTools
...sideEnhancers
);
const reducer = combineReducers(
appReducer,
panesReducer,
routesReducer
);
// create composed store enhancer
// use store enhancer function to enhance `createStore` function
// call enhanced createStore function with reducer and defaultState
// to create store
const store = createStore(reducer, defaultState, enhancer);
const location = selectLocationState(store.getState());
// ({
// redirect,
// props,
// reducer,
// store,
// epic: epicMiddleware
// }));
return Observable.of({
store,
epic: epicMiddleware,
location,
notFound: false
});
}