Browse Source

Moved from React Router 3 to React Router 4

howdoyoucode 7 years ago
parent
commit
427e119339

+ 1 - 1
frontend/.eslintrc.js

@@ -54,5 +54,5 @@ module.exports = {
 		"import/no-extraneous-dependencies": 0,
 		"import/no-unresolved": 0,
 		"import/prefer-default-export": 0
-	}
+	},
 }

+ 0 - 1
frontend/app/index.tpl.html

@@ -39,7 +39,6 @@
 		<script src="https://www.youtube.com/iframe_api"></script>
 		<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.15.0/moment.min.js"></script>
 		<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.4.8/socket.io.min.js"></script>
-		<script type="text/javascript" src="https://cdn.rawgit.com/atjonathan/lofig/master/dist/lofig.min.js"></script>
 		<script>
 			(function(i,s,o,g,r,a,m){i["GoogleAnalyticsObject"]=r;i[r]=i[r]||function(){
 						(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),

+ 10 - 19
frontend/app/js/components/Global/Menu.jsx

@@ -1,7 +1,7 @@
 import React, { Component } from "react";
 import PropTypes from "prop-types";
 import { connect } from "react-redux";
-import { IndexLink, Link } from "react-router";
+import { NavLink } from "react-router-dom";
 
 @connect(state => ({
 	loggedIn: state.user.get("loggedIn"),
@@ -12,31 +12,22 @@ export default class Menu extends Component {
 		loggedIn: PropTypes.bool,
 	}
 
+	static defaultProps = {
+		loggedIn: false,
+	}
+
 	render() {
 		return (
 			<div className="Menu">
-				<IndexLink to="/">
-					Home
-				</IndexLink>
+				<NavLink to="/">Home</NavLink>
 				{ this.props.loggedIn ?
-					<Link to="logout">
-						Logout
-					</Link> :
+					<NavLink to="logout">Logout</NavLink> :
 					<div>
-						<Link to="login">
-							Login
-						</Link>
-						<Link to="register">
-							Register
-						</Link>
+						<NavLink to="login">Login</NavLink>
+						<NavLink to="register">Register</NavLink>
 					</div>
 				}
-				<Link to="template">
-					Template
-				</Link>
-				<Link to="404">
-					404
-				</Link>
+				<NavLink to="template">Template</NavLink>
 			</div>
 		);
 	}

+ 9 - 8
frontend/app/js/index.js

@@ -2,15 +2,16 @@ import React from "react";
 import ReactDOM from "react-dom";
 import { Provider } from "react-redux";
 import { createStore, applyMiddleware, compose } from "redux";
-import { Router, browserHistory } from "react-router";
+import { BrowserRouter, Route } from "react-router-dom";
 import thunk from "redux-thunk";
 import "babel-polyfill";
 import logger from "dev/logger";
 
 import rootReducer from "reducers";
-import Routes from "routes";
 import DevTools from "dev/redux-dev-tools";
 
+import App from "views/App";
+
 import "../styles/main.scss";
 
 const isProduction = process.env.NODE_ENV === "production";
@@ -36,12 +37,12 @@ if (isProduction) {
 
 ReactDOM.render(
 	<Provider store={ store }>
-		{ isProduction ?
-			<Router history={ browserHistory } routes={ Routes } /> :
-			<div>
-				<Router history={ browserHistory } routes={ Routes } />
-				<DevTools />
-			</div> }
+		<div>
+			<BrowserRouter>
+				<Route path="/" component={ App } />
+			</BrowserRouter>
+			{ !isProduction ? <DevTools /> : "" }
+		</div>
 	</Provider>,
 	document.getElementById("root")
 );

+ 0 - 63
frontend/app/js/routes.js

@@ -1,63 +0,0 @@
-import App from "views/App";
-
-const errorLoading = error => {
-	throw new Error(`Dynamic page loading failed: ${ error }`);
-};
-
-const loadRoute = cb => {
-	return module => cb(null, module.default);
-};
-
-export default {
-	path: "/",
-	component: App,
-	indexRoute: {
-		getComponent(location, cb) {
-			System.import("views/Home")
-			.then(loadRoute(cb))
-			.catch(errorLoading);
-		},
-	},
-	childRoutes: [
-		{
-			path: "login",
-			getComponent(location, cb) {
-				System.import("views/Auth/Login")
-					.then(loadRoute(cb, false))
-					.catch(errorLoading);
-			},
-		},
-		{
-			path: "logout",
-			getComponent(location, cb) {
-				System.import("views/Auth/Logout")
-					.then(loadRoute(cb, false))
-					.catch(errorLoading);
-			},
-		},
-		{
-			path: "register",
-			getComponent(location, cb) {
-				System.import("views/Auth/Register")
-					.then(loadRoute(cb, false))
-					.catch(errorLoading);
-			},
-		},
-		{
-			path: "template",
-			getComponent(location, cb) {
-				System.import("views/Template")
-					.then(loadRoute(cb, false))
-					.catch(errorLoading);
-			},
-		},
-		{
-			path: "*",
-			getComponent(location, cb) {
-				System.import("views/NotFound")
-					.then(loadRoute(cb))
-					.catch(errorLoading);
-			},
-		},
-	],
-};

+ 72 - 5
frontend/app/js/views/App/index.jsx

@@ -1,4 +1,5 @@
 import React, { Component } from "react";
+import { Route, Switch } from "react-router-dom";
 import PropTypes from "prop-types";
 import { connect } from "react-redux";
 
@@ -8,14 +9,38 @@ import Menu from "components/Global/Menu";
 import io from "../../io";
 import config from "../../../../config/default";
 
+const asyncComponent = getComponent => {
+	return class AsyncComponent extends React.Component {
+		static Component = null;
+		state = { Component: AsyncComponent.Component };
+
+		componentWillMount() {
+			if (!this.state.Component) {
+				getComponent().then(Component => { // eslint-disable-line no-shadow
+					AsyncComponent.Component = Component;
+					this.setState({ Component });
+				});
+			}
+		}
+		render() {
+			const { Component } = this.state; // eslint-disable-line no-shadow
+			if (Component) return <Component { ...this.props } />;
+			return null;
+		}
+	};
+};
+
 @connect()
 
-export default class App extends Component {
+export default class App extends Component { // eslint-disable-line react/no-multi-comp
 	static propTypes = {
-		children: PropTypes.object,
 		dispatch: PropTypes.func,
 	}
 
+	static defaultProps = {
+		dispatch: () => {},
+	}
+
 	componentDidMount() {
 		const { dispatch } = this.props;
 
@@ -29,12 +54,54 @@ export default class App extends Component {
 	}
 
 	render() {
-		const { children } = this.props;
-
 		return (
 			<div>
 				<Menu />
-				<div>{ children }</div>
+				<div>
+					<Switch>
+						<Route
+							exact
+							path="/login"
+							component={ asyncComponent(() =>
+								System.import("views/Auth/Login").then(module => module.default)
+							) }
+						/>
+						<Route
+							exact
+							path="/logout"
+							component={ asyncComponent(() =>
+								System.import("views/Auth/Logout").then(module => module.default)
+							) }
+						/>
+						<Route
+							exact
+							path="/register"
+							component={ asyncComponent(() =>
+								System.import("views/Auth/Register").then(module => module.default)
+							) }
+						/>
+						<Route
+							exact
+							path="/template"
+							component={ asyncComponent(() =>
+								System.import("views/Template").then(module => module.default)
+							) }
+						/>
+						<Route
+							exact
+							path="/"
+							component={ asyncComponent(() =>
+								System.import("views/Home").then(module => module.default)
+							) }
+						/>
+						<Route
+							path="*"
+							component={ asyncComponent(() =>
+								System.import("views/NotFound").then(module => module.default)
+							) }
+						/>
+					</Switch>
+				</div>
 			</div>
 		);
 	}

+ 123 - 92
frontend/package-lock.json

@@ -52,8 +52,7 @@
     },
     "align-text": {
       "version": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz",
-      "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=",
-      "dev": true
+      "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc="
     },
     "amdefine": {
       "version": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
@@ -122,13 +121,11 @@
     },
     "array-union": {
       "version": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
-      "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=",
-      "dev": true
+      "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk="
     },
     "array-uniq": {
       "version": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
-      "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=",
-      "dev": true
+      "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY="
     },
     "array-unique": {
       "version": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz",
@@ -227,7 +224,8 @@
       }
     },
     "babel-eslint": {
-      "version": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-7.2.3.tgz",
+      "version": "7.2.3",
+      "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-7.2.3.tgz",
       "integrity": "sha1-sv4tgBJkcPXBlELcdXJTqJdxCCc=",
       "dev": true
     },
@@ -693,8 +691,7 @@
     },
     "balanced-match": {
       "version": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz",
-      "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=",
-      "dev": true
+      "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg="
     },
     "base16": {
       "version": "https://registry.npmjs.org/base16/-/base16-1.0.0.tgz",
@@ -779,8 +776,7 @@
     },
     "brace-expansion": {
       "version": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.7.tgz",
-      "integrity": "sha1-Pv/DxQ4ABTH7cg6v+A8K6O8jz1k=",
-      "dev": true
+      "integrity": "sha1-Pv/DxQ4ABTH7cg6v+A8K6O8jz1k="
     },
     "braces": {
       "version": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz",
@@ -899,8 +895,7 @@
     },
     "center-align": {
       "version": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz",
-      "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=",
-      "dev": true
+      "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60="
     },
     "chalk": {
       "version": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
@@ -1056,8 +1051,7 @@
     },
     "concat-map": {
       "version": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
-      "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
-      "dev": true
+      "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
     },
     "concat-stream": {
       "version": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz",
@@ -1120,8 +1114,7 @@
     },
     "core-util-is": {
       "version": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
-      "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
-      "dev": true
+      "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
     },
     "cosmiconfig": {
       "version": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-2.1.3.tgz",
@@ -1311,14 +1304,14 @@
       }
     },
     "dom-serializer": {
-      "version": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz",
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz",
       "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=",
-      "dev": true,
       "dependencies": {
         "domelementtype": {
-          "version": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz",
-          "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=",
-          "dev": true
+          "version": "1.1.3",
+          "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz",
+          "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs="
         }
       }
     },
@@ -1333,14 +1326,9 @@
       "dev": true
     },
     "domelementtype": {
-      "version": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz",
-      "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=",
-      "dev": true
-    },
-    "each-async": {
-      "version": "https://registry.npmjs.org/each-async/-/each-async-1.1.1.tgz",
-      "integrity": "sha1-3uUim98KtrogEqOV4bhpq/iBNHM=",
-      "dev": true
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz",
+      "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI="
     },
     "ecc-jsbn": {
       "version": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz",
@@ -1426,15 +1414,10 @@
       "integrity": "sha1-k3sHnwAH0Ik+xW1GyyILjLQ1Igo=",
       "dev": true
     },
-    "enhanced-resolve": {
-      "version": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-3.1.0.tgz",
-      "integrity": "sha1-n0tib1dyRe3PSyrYPYbhf09CHew=",
-      "dev": true
-    },
     "entities": {
-      "version": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz",
-      "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=",
-      "dev": true
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz",
+      "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA="
     },
     "errno": {
       "version": "https://registry.npmjs.org/errno/-/errno-0.1.4.tgz",
@@ -2649,8 +2632,7 @@
     },
     "graceful-readlink": {
       "version": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz",
-      "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=",
-      "dev": true
+      "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU="
     },
     "handle-thing": {
       "version": "https://registry.npmjs.org/handle-thing/-/handle-thing-1.2.5.tgz",
@@ -2720,8 +2702,9 @@
       "dev": true
     },
     "history": {
-      "version": "https://registry.npmjs.org/history/-/history-3.3.0.tgz",
-      "integrity": "sha1-/O3M6PEpdTcVRdc1RhAzV5ptrpw="
+      "version": "4.6.3",
+      "resolved": "https://registry.npmjs.org/history/-/history-4.6.3.tgz",
+      "integrity": "sha1-bXI6hxLFgda+836MJvSu3G64aWc="
     },
     "hmac-drbg": {
       "version": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
@@ -2861,13 +2844,11 @@
     },
     "inflight": {
       "version": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
-      "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
-      "dev": true
+      "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk="
     },
     "inherits": {
       "version": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
-      "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
-      "dev": true
+      "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
     },
     "inquirer": {
       "version": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz",
@@ -2905,8 +2886,7 @@
     },
     "is-buffer": {
       "version": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz",
-      "integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw=",
-      "dev": true
+      "integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw="
     },
     "is-builtin-module": {
       "version": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz",
@@ -3158,13 +3138,11 @@
     },
     "kind-of": {
       "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.0.tgz",
-      "integrity": "sha1-tYq+TVwEStM3JqjBUltIz4kb/wc=",
-      "dev": true
+      "integrity": "sha1-tYq+TVwEStM3JqjBUltIz4kb/wc="
     },
     "lazy-cache": {
       "version": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz",
-      "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=",
-      "dev": true
+      "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4="
     },
     "lcid": {
       "version": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz",
@@ -3237,8 +3215,7 @@
     },
     "longest": {
       "version": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz",
-      "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=",
-      "dev": true
+      "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc="
     },
     "loose-envify": {
       "version": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz",
@@ -3331,8 +3308,7 @@
     },
     "minimatch": {
       "version": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz",
-      "integrity": "sha1-Kk5AkLlrLbBqnX3wEFWmKnfJt3Q=",
-      "dev": true
+      "integrity": "sha1-Kk5AkLlrLbBqnX3wEFWmKnfJt3Q="
     },
     "minimist": {
       "version": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
@@ -3503,8 +3479,7 @@
     },
     "once": {
       "version": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
-      "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
-      "dev": true
+      "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E="
     },
     "onetime": {
       "version": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz",
@@ -3625,8 +3600,7 @@
     },
     "path-is-absolute": {
       "version": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
-      "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
-      "dev": true
+      "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
     },
     "path-is-inside": {
       "version": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz",
@@ -3865,10 +3839,6 @@
       "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=",
       "dev": true
     },
-    "query-string": {
-      "version": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz",
-      "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s="
-    },
     "querystring": {
       "version": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
       "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=",
@@ -3879,11 +3849,6 @@
       "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=",
       "dev": true
     },
-    "querystringify": {
-      "version": "https://registry.npmjs.org/querystringify/-/querystringify-0.0.4.tgz",
-      "integrity": "sha1-DPf4T5Rj/wrlHExLFC2VvjdyTZw=",
-      "dev": true
-    },
     "randomatic": {
       "version": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.6.tgz",
       "integrity": "sha1-EQ3Kv/OX6dz/fAeJzMCkmt8exbs=",
@@ -3942,8 +3907,26 @@
       "integrity": "sha1-57wd0QDotk6WrIIS2xEyObni4I8="
     },
     "react-router": {
-      "version": "https://registry.npmjs.org/react-router/-/react-router-3.0.5.tgz",
-      "integrity": "sha1-w7eHN1gEWou8lWKu9P9LyMznwTY="
+      "version": "4.1.2",
+      "resolved": "https://registry.npmjs.org/react-router/-/react-router-4.1.2.tgz",
+      "integrity": "sha512-VyM87OP+GkijVkkOXJw39A9fKtFelLoZYYDxtELhpZefjYatxI2SUxZcImo/9Tv52rR9UnNJBPSBpVRQMdvi8A==",
+      "dependencies": {
+        "isarray": {
+          "version": "0.0.1",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+          "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
+        },
+        "path-to-regexp": {
+          "version": "1.7.0",
+          "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz",
+          "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30="
+        }
+      }
+    },
+    "react-router-dom": {
+      "version": "4.1.2",
+      "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-4.1.2.tgz",
+      "integrity": "sha512-CU6pFlpfvIj/xi36rZAbUiN0x39241q+d5bAfJJLtlEqlM62F3zgyv5aERH9zesmKqyDBBp2kd85rkq9Mo/iNQ=="
     },
     "react-transform-catch-errors": {
       "version": "https://registry.npmjs.org/react-transform-catch-errors/-/react-transform-catch-errors-1.0.2.tgz",
@@ -4150,8 +4133,7 @@
     },
     "repeat-string": {
       "version": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
-      "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=",
-      "dev": true
+      "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc="
     },
     "repeating": {
       "version": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz",
@@ -4198,6 +4180,11 @@
       "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=",
       "dev": true
     },
+    "resolve-pathname": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-2.1.0.tgz",
+      "integrity": "sha1-6DWIAbhrg7F1YNTjw4LXrvIQCUQ="
+    },
     "restore-cursor": {
       "version": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz",
       "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=",
@@ -4205,8 +4192,7 @@
     },
     "right-align": {
       "version": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz",
-      "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=",
-      "dev": true
+      "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8="
     },
     "rimraf": {
       "version": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz",
@@ -4547,10 +4533,6 @@
       "integrity": "sha1-zsH047SUvEqBtFGAiXD4sgtO1fY=",
       "dev": true
     },
-    "strict-uri-encode": {
-      "version": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz",
-      "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM="
-    },
     "string_decoder": {
       "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.0.tgz",
       "integrity": "sha1-8G9BFXtmTYYGn4S9vcmw2KsoFmc=",
@@ -4860,6 +4842,11 @@
       "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=",
       "dev": true
     },
+    "value-equal": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-0.2.1.tgz",
+      "integrity": "sha1-wiCjBDYfzmmU277ao8fhobiVhx0="
+    },
     "vary": {
       "version": "https://registry.npmjs.org/vary/-/vary-1.1.1.tgz",
       "integrity": "sha1-Z1Neu2lMHVIldFeYRmUyP1h+jTc=",
@@ -4876,7 +4863,8 @@
       "dev": true
     },
     "warning": {
-      "version": "https://registry.npmjs.org/warning/-/warning-3.0.0.tgz",
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/warning/-/warning-3.0.0.tgz",
       "integrity": "sha1-MuU3fLVy3kqwR1O9+IIcAe1gW3w="
     },
     "watchpack": {
@@ -4890,33 +4878,77 @@
       "dev": true
     },
     "webpack": {
-      "version": "https://registry.npmjs.org/webpack/-/webpack-2.5.1.tgz",
-      "integrity": "sha1-YXQvDPivVVuHRgqc2Lui8ePuL84=",
+      "version": "2.7.0",
+      "resolved": "https://registry.npmjs.org/webpack/-/webpack-2.7.0.tgz",
+      "integrity": "sha512-MjAA0ZqO1ba7ZQJRnoCdbM56mmFpipOPUv/vQpwwfSI42p5PVDdoiuK2AL2FwFUVgT859Jr43bFZXRg/LNsqvg==",
       "dev": true,
       "dependencies": {
         "acorn": {
-          "version": "https://registry.npmjs.org/acorn/-/acorn-5.0.3.tgz",
-          "integrity": "sha1-xGDfCEkUY/AozLguqzcwvwEIez0=",
+          "version": "5.1.1",
+          "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.1.1.tgz",
+          "integrity": "sha512-vOk6uEMctu0vQrvuSqFdJyqj1Q0S5VTDL79qtjo+DhRr+1mmaD+tluFSCZqhvi/JUhXSzoZN2BhtstaPEeE8cw==",
+          "dev": true
+        },
+        "camelcase": {
+          "version": "1.2.1",
+          "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz",
+          "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=",
+          "dev": true
+        },
+        "cliui": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz",
+          "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=",
+          "dev": true
+        },
+        "enhanced-resolve": {
+          "version": "3.3.0",
+          "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-3.3.0.tgz",
+          "integrity": "sha512-2qbxE7ek3YxPJ1ML6V+satHkzHpJQKWkRHmRx6mfAoW59yP8YH8BFplbegSP+u2hBd6B6KCOpvJQ3dZAP+hkpg==",
           "dev": true
         },
         "source-list-map": {
-          "version": "https://registry.npmjs.org/source-list-map/-/source-list-map-1.1.2.tgz",
-          "integrity": "sha1-mIkBnRAkzOVc3AaUmDN+9hhqEaE=",
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.0.tgz",
+          "integrity": "sha512-I2UmuJSRr/T8jisiROLU3A3ltr+swpniSmNPI4Ml3ZCX6tVnDsuZzK7F2hl5jTqbZBWCEKlj5HRQiPExXLgE8A==",
           "dev": true
         },
         "source-map": {
-          "version": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
+          "version": "0.5.6",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
           "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=",
           "dev": true
         },
         "supports-color": {
-          "version": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
+          "version": "3.2.3",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
           "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
           "dev": true
         },
+        "uglify-js": {
+          "version": "2.8.29",
+          "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz",
+          "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=",
+          "dev": true,
+          "dependencies": {
+            "yargs": {
+              "version": "3.10.0",
+              "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz",
+              "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=",
+              "dev": true
+            }
+          }
+        },
         "webpack-sources": {
-          "version": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-0.2.3.tgz",
-          "integrity": "sha1-F8Yr+vE8cH+dAsR54Nzd6DgGl/s=",
+          "version": "1.0.1",
+          "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.0.1.tgz",
+          "integrity": "sha512-05tMxipUCwHqYaVS8xc7sYPTly8PzXayRCB4dTxLhWTqlKUiwH6ezmEe0OSreL1c30LAuA3Zqmc+uEBUGFJDjw==",
+          "dev": true
+        },
+        "wordwrap": {
+          "version": "0.0.2",
+          "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz",
+          "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=",
           "dev": true
         }
       }
@@ -5008,8 +5040,7 @@
     },
     "wrappy": {
       "version": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
-      "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
-      "dev": true
+      "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
     },
     "write": {
       "version": "https://registry.npmjs.org/write/-/write-0.2.1.tgz",

+ 12 - 10
frontend/package.json

@@ -13,7 +13,7 @@
   "devDependencies": {
     "autoprefixer": "^6.5.3",
     "babel-core": "^6.7.2",
-    "babel-eslint": "^7.1.0",
+    "babel-eslint": "^7.2.3",
     "babel-loader": "^6.2.4",
     "babel-plugin-syntax-decorators": "^6.13.0",
     "babel-plugin-transform-class-properties": "^6.6.0",
@@ -44,22 +44,24 @@
     "sass-loader": "^4.0.2",
     "style-loader": "^0.13.0",
     "url-loader": "^0.5.7",
-    "webpack": "^2.2.1",
+    "webpack": "^2.7.0",
     "webpack-dashboard": "^0.2.0",
     "webpack-dev-server": "^2.2.1"
   },
   "dependencies": {
-    "babel-polyfill": "^6.16.0",
-    "es6-promise": "^3.1.2",
+    "babel-polyfill": "^6.23.0",
+    "dom-serializer": "^0.1.0",
+    "domelementtype": "^1.3.0",
+    "es6-promise": "^3.3.1",
     "immutable": "^3.8.1",
     "isomorphic-fetch": "^2.2.1",
     "lodash": "^4.17.4",
     "prop-types": "^15.5.10",
-    "react": "^15.4.0",
-    "react-dom": "^15.4.0",
-    "react-redux": "^4.4.0",
-    "react-router": "^3.0.0",
-    "redux": "^3.3.1",
-    "redux-thunk": "^2.0.1"
+    "react": "^15.5.4",
+    "react-dom": "^15.5.4",
+    "react-redux": "^4.4.8",
+    "react-router-dom": "^4.1.2",
+    "redux": "^3.6.0",
+    "redux-thunk": "^2.2.0"
   }
 }

+ 6 - 6
frontend/webpack.config.js

@@ -91,15 +91,15 @@ if (nodeEnv === "production") {
 		new ExtractTextPlugin("style-[hash].css")
 	);
 
-  rules.push({
+	rules.push({
 		test: /\.scss$/,
 		loader: ExtractTextPlugin.extract({
 			fallback: "style-loader",
 			use: "css-loader!postcss-loader!sass-loader",
-		})
+		}),
 	});
 } else {
-  rules.push({
+	rules.push({
 		test: /\.scss$/,
 		exclude: /node_modules/,
 		use: [
@@ -108,7 +108,7 @@ if (nodeEnv === "production") {
 			"css-loader",
 			"postcss-loader",
 			"sass-loader?sourceMap",
-		]
+		],
 	});
 }
 
@@ -124,7 +124,7 @@ module.exports = {
 			"isomorphic-fetch",
 			"react-dom",
 			"react-redux",
-			"react-router",
+			"react-router-dom",
 			"react",
 			"redux-thunk",
 			"redux",
@@ -145,5 +145,5 @@ module.exports = {
 			path.join(__dirname, "./app/js"),
 		],
 	},
-	plugins
+	plugins,
 };