* feat(Profile): Reactify profile page * chore(tidyup): Remove console.log * fix(timeline): Remove legacy challenges from Timeline render * fix(style): Remove underline on a:hover
		
			
				
	
	
		
			106 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			106 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| import debug from 'debug';
 | |
| import { renderToString } from 'react-dom/server';
 | |
| import createMemoryHistory from 'history/createMemoryHistory';
 | |
| import { NOT_FOUND } from 'redux-first-router';
 | |
| import devtoolsEnhancer from 'remote-redux-devtools';
 | |
| 
 | |
| import {
 | |
|   errorThrowerMiddleware
 | |
| } from '../utils/react.js';
 | |
| import { createApp, provideStore, App } from '../../common/app';
 | |
| import waitForEpics from '../../common/utils/wait-for-epics.js';
 | |
| import { titleSelector } from '../../common/app/redux';
 | |
| 
 | |
| const log = debug('fcc:react-server');
 | |
| const isDev = process.env.NODE_ENV !== 'production';
 | |
| 
 | |
| // add routes here as they slowly get reactified
 | |
| // remove their individual controllers
 | |
| const routes = [
 | |
|   '/challenges',
 | |
|   '/challenges/*',
 | |
|   '/map',
 | |
|   '/settings',
 | |
|   '/settings/*',
 | |
|   '/:username'
 | |
| ];
 | |
| 
 | |
| const devRoutes = [];
 | |
| 
 | |
| const middlewares = isDev ? [errorThrowerMiddleware] : [];
 | |
| export default function reactSubRouter(app) {
 | |
|   var router = app.loopback.Router();
 | |
| 
 | |
|   router.get('/videos', (req, res) => res.redirect('/map'));
 | |
|   router.get(
 | |
|     '/videos/:dashedName',
 | |
|     (req, res) => res.redirect(`/challenges/${req.params.dashedName}`)
 | |
|   );
 | |
| 
 | |
|   // These routes are in production
 | |
|   routes.forEach((route) => {
 | |
|     router.get(route, serveReactApp);
 | |
|   });
 | |
| 
 | |
|   if (process.env.NODE_ENV === 'development') {
 | |
|     devRoutes.forEach(function(route) {
 | |
|       router.get(route, serveReactApp);
 | |
|     });
 | |
|   }
 | |
| 
 | |
|   app.use('/:lang', router);
 | |
| 
 | |
|   function serveReactApp(req, res, next) {
 | |
|     const { lang } = req;
 | |
|     const serviceOptions = { req };
 | |
|     createApp({
 | |
|       serviceOptions,
 | |
|       middlewares,
 | |
|       enhancers: [
 | |
|         devtoolsEnhancer({ name: 'server' })
 | |
|       ],
 | |
|       history: createMemoryHistory({ initialEntries: [ req.originalUrl ] }),
 | |
|       defaultState: { app: { lang } }
 | |
|     })
 | |
|       .filter(({
 | |
|         location: {
 | |
|           type,
 | |
|           kind,
 | |
|           pathname
 | |
|         } = {}
 | |
|       }) => {
 | |
|         if (kind === 'redirect') {
 | |
|           log('react found a redirect');
 | |
|           res.redirect(pathname);
 | |
|           return false;
 | |
|         }
 | |
| 
 | |
|         if (type === NOT_FOUND) {
 | |
|           log(`react tried to find ${req.path} but got 404`);
 | |
|           next();
 | |
|           return false;
 | |
|         }
 | |
| 
 | |
|         return true;
 | |
|       })
 | |
|       .flatMap(({ store, epic }) => {
 | |
|         return waitForEpics(epic)
 | |
|           .map(() => renderToString(
 | |
|             provideStore(App, store)
 | |
|           ))
 | |
|           .map((markup) => ({ markup, store, epic }));
 | |
|       })
 | |
|       .do(({ markup, store, epic }) => {
 | |
|         log('react markup rendered, data fetched');
 | |
|         const state = store.getState();
 | |
|         const title = titleSelector(state);
 | |
|         epic.dispose();
 | |
|         res.expose(state, 'data', { isJSON: true });
 | |
|         // note(berks): we render without express-flash dumping our messages
 | |
|         // the app will query for these on load
 | |
|         res.renderWithoutFlash('layout-react', { markup, title });
 | |
|       })
 | |
|       .subscribe(() => log('html rendered and sent'), next);
 | |
|   }
 | |
| }
 |