소스 검색

added redux

Benoit Sida 3 년 전
부모
커밋
1f47cb3e60

+ 4
- 0
.babelrc 파일 보기

@@ -0,0 +1,4 @@
1
+{
2
+    "presets": ["env", "react"],
3
+    "plugins": ["transform-object-rest-spread"]
4
+}

+ 8
- 0
package.json 파일 보기

@@ -16,6 +16,7 @@
16 16
   "devDependencies": {
17 17
     "babel-core": "^6.24.1",
18 18
     "babel-loader": "^7.0.0",
19
+    "babel-plugin-transform-object-rest-spread": "^6.23.0",
19 20
     "babel-preset-env": "^1.4.0",
20 21
     "babel-preset-react": "^6.24.1",
21 22
     "css-loader": "^0.28.1",
@@ -31,9 +32,16 @@
31 32
   },
32 33
   "dependencies": {
33 34
     "@blueprintjs/core": "^1.16.0",
35
+    "classnames": "^2.2.5",
36
+    "font-awesome": "^4.7.0",
34 37
     "react": "^15.5.4",
35 38
     "react-addons-css-transition-group": "^15.5.2",
36 39
     "react-dom": "^15.5.4",
40
+    "react-fontawesome": "^1.6.1",
41
+    "react-redux": "^5.0.4",
42
+    "react-router-dom": "^4.1.1",
43
+    "redux": "^3.6.0",
44
+    "redux-actions": "^2.0.3",
37 45
     "resetcss": "^1.0.3"
38 46
   },
39 47
   "babel": {

+ 33
- 11
src/App.jsx 파일 보기

@@ -1,15 +1,37 @@
1 1
 import React from 'react'
2
-import './App.scss'
2
+import { connect } from 'react-redux'
3
+import { BrowserRouter as Router } from 'react-router-dom'
4
+import { Navbar } from './Header/Navbar'
5
+import Topbar from './Header/Topbar'
6
+import Routes from './Routes'
7
+import { LOGIN } from './Store/Actions'
8
+import './assets'
3 9
 
4
-import Navbar from './Navbar'
10
+const USER = {
11
+    username: 'Coldiary',
12
+    email: 'coldiary@orange.fr',
13
+    links: {
14
+        twitter: 'coldiary'
15
+    }
16
+}
5 17
 
6
-const App = () =>
7
-    <div>
8
-        <header>
9
-            <Navbar/>
10
-        </header>
11
-        <main></main>
12
-        <footer></footer>
13
-    </div>
18
+const App = ({ user, login }) => {
19
+    if (!user)
20
+        return <a onClick={() => login(USER)}>login</a>
21
+    return (
22
+        <Router>
23
+            <div className="flex-frame">
24
+                <header><Topbar /></header>
25
+                <main><Routes /></main>
26
+                <footer><Navbar dark><span>© 2017 - Coldiary</span></Navbar></footer>
27
+            </div>
28
+        </Router>
29
+    )
30
+}
14 31
 
15
-export default App
32
+const mapStateToProps = state => ({ user: state.user })
33
+const mapDispatchToProps = dispatch => ({ login: user => dispatch(LOGIN(user)) })
34
+
35
+const AuthApp = connect(mapStateToProps, mapDispatchToProps)(App)
36
+
37
+export default AuthApp

+ 21
- 2
src/App.scss 파일 보기

@@ -1,2 +1,21 @@
1
-@import "~resetcss/reset.min.css";
2
-@import "~@blueprintjs/core/dist/blueprint.css";
1
+@import '~@blueprintjs/core/dist/variables.scss';
2
+
3
+.flex-frame {
4
+    display: flex;
5
+    flex-direction: column;
6
+    min-height: 100vh;
7
+    background: $pt-app-background-color;
8
+
9
+    main {
10
+        flex: 1;
11
+        padding: 50px;
12
+    }
13
+
14
+    footer {
15
+        nav {
16
+            display: flex;
17
+            align-items: center;
18
+            justify-content: center;
19
+        }
20
+    }
21
+}

+ 11
- 0
src/Header/NavLinkBP.jsx 파일 보기

@@ -0,0 +1,11 @@
1
+import React from 'react'
2
+import { NavLink } from 'react-router-dom'
3
+
4
+const NavLinkBP = ({path, label, icon, exact}) =>
5
+    <NavLink to={path} {...{exact}}
6
+        activeClassName="pt-active"
7
+        className={"pt-button pt-minimal pt-icon-" + icon}>
8
+        {label}
9
+    </NavLink>
10
+
11
+export default NavLinkBP

+ 9
- 0
src/Header/Navbar.jsx 파일 보기

@@ -0,0 +1,9 @@
1
+import React from 'react'
2
+import classNames from 'classnames'
3
+
4
+const Navbar = ({ dark, children }) => <nav className={classNames(['pt-navbar', { 'pt-dark': dark }])}>{children}</nav>
5
+const NavbarGroup = ({ align, children }) => <div className={"pt-navbar-group " + (align ? "pt-align-" + align : '')}>{children}</div>
6
+const NavbarDivider = () => <span className="pt-navbar-divider" />
7
+const NavbarHeading = ({ children }) => <div className="pt-navbar-heading">{children}</div>
8
+
9
+export { Navbar, NavbarGroup, NavbarDivider, NavbarHeading }

+ 5
- 0
src/Header/Notifications.jsx 파일 보기

@@ -0,0 +1,5 @@
1
+import React from 'react'
2
+
3
+const Notifications = <div>No notifications</div>
4
+
5
+export default Notifications;

+ 37
- 0
src/Header/Topbar.jsx 파일 보기

@@ -0,0 +1,37 @@
1
+import React from 'react'
2
+import { connect } from 'react-redux'
3
+import { Popover, PopoverInteractionKind, Position } from '@blueprintjs/core'
4
+import { Navbar, NavbarGroup, NavbarDivider, NavbarHeading } from './Navbar'
5
+import NavLinkBP from './NavLinkBP'
6
+import UserMenu from './UserMenu'
7
+import { LOGOUT } from '../Store/Actions'
8
+import Notifications from './Notifications'
9
+
10
+const TopbarTemplate = ({ logout }) =>
11
+    <div>
12
+        <Navbar dark>
13
+            <NavbarGroup align="left">
14
+                <NavbarHeading>Lighthouse</NavbarHeading>
15
+                <NavLinkBP path="/" label="Home" icon="home" exact/>
16
+                <NavLinkBP path="/projects" label="Projects" icon="document"/>
17
+            </NavbarGroup>
18
+            <NavbarGroup align="right">
19
+                <input className="pt-input" placeholder="Search files..." type="text" />
20
+                <NavbarDivider />
21
+                <Popover content={Notifications} position={Position.BOTTOM_RIGHT}
22
+                        popoverClassName="pt-popover-content-sizing"
23
+                        interactionKind={PopoverInteractionKind.HOVER}>
24
+                    <button className="pt-button pt-minimal pt-icon-notifications"></button>
25
+                </Popover>
26
+                <Popover content={UserMenu({logout})} position={Position.BOTTOM_RIGHT}
27
+                        interactionKind={PopoverInteractionKind.CLICK}>
28
+                    <button className="pt-button pt-minimal pt-icon-user"></button>
29
+                </Popover>
30
+            </NavbarGroup>
31
+        </Navbar>
32
+    </div>
33
+
34
+const mapDispatchToProps = dispatch => ({ logout: () => { console.log('dispatching'); dispatch(LOGOUT()) } })
35
+const Topbar = connect(null, mapDispatchToProps)(TopbarTemplate)
36
+
37
+export default Topbar

+ 19
- 0
src/Header/UserMenu.jsx 파일 보기

@@ -0,0 +1,19 @@
1
+import React from 'react'
2
+import classNames from 'classnames'
3
+import { Link } from 'react-router-dom'
4
+import { Menu, MenuItem, MenuDivider } from "@blueprintjs/core"
5
+
6
+const MenuLink = ({ to, iconName, children, ...otherProps }) => {
7
+    let classes = classNames(["pt-menu-item","pt-popover-dismiss", {[`pt-icon-${iconName}`]: iconName}]);
8
+    return <li><Link to={to} className={classes} {...otherProps}>{children}</Link></li>
9
+}
10
+
11
+const userMenu = ({ logout }) => 
12
+    <Menu>
13
+        <MenuLink to="/user" iconName="user">Profile</MenuLink>
14
+        <MenuLink to="/settings" iconName="cog">Settings</MenuLink>
15
+        <MenuDivider />
16
+        <MenuItem text="Log out" iconName="power" onClick={() => { console.log('loginout'); logout() }} />
17
+    </Menu>
18
+
19
+export default userMenu

+ 0
- 37
src/Navbar.jsx 파일 보기

@@ -1,37 +0,0 @@
1
-import React from 'react'
2
-import { Menu, MenuItem, MenuDivider } from "@blueprintjs/core";
3
-import { Popover, PopoverInteractionKind, Position } from '@blueprintjs/core';
4
-
5
-const userMenu = 
6
-    <Menu>
7
-        <MenuItem iconName="user" text="Profile" />
8
-        <MenuItem text="Settings..." iconName="cog" />
9
-        <MenuDivider />
10
-        <MenuItem text="Log out" iconName="power" />
11
-    </Menu>
12
-
13
-const Navbar = () => 
14
-    <div>
15
-        <nav className="pt-navbar pt-dark">
16
-            <div className="pt-navbar-group pt-align-left">
17
-                <div className="pt-navbar-heading">Lighthouse</div>
18
-                <button className="pt-button pt-minimal pt-icon-home">Home</button>
19
-                <button className="pt-button pt-minimal pt-icon-document">Files</button>
20
-            </div>
21
-            <div className="pt-navbar-group pt-align-right">
22
-                <input className="pt-input" placeholder="Search files..." type="text" />
23
-                <span className="pt-navbar-divider"></span>
24
-                <Popover content={<div>No notifications</div>} position={Position.BOTTOM_RIGHT}
25
-                        popoverClassName="pt-popover-content-sizing"
26
-                        interactionKind={PopoverInteractionKind.HOVER}>
27
-                    <button className="pt-button pt-minimal pt-icon-notifications"></button>
28
-                </Popover>
29
-                <Popover content={userMenu} position={Position.BOTTOM_RIGHT}
30
-                        interactionKind={PopoverInteractionKind.CLICK}>
31
-                    <button className="pt-button pt-minimal pt-icon-user"></button>
32
-                </Popover>
33
-            </div>
34
-        </nav>
35
-    </div>
36
-
37
-export default Navbar

+ 21
- 0
src/Pages/Settings/SideMenu.jsx 파일 보기

@@ -0,0 +1,21 @@
1
+import React from 'react'
2
+import { Menu, MenuItem, MenuDivider } from '@blueprintjs/core'
3
+
4
+const SideMenu = () =>
5
+    <Menu className="pt-elevation-1">
6
+        <li className="pt-menu-header"><h6>Settings</h6></li>
7
+        <MenuItem
8
+            iconName="new-text-box"
9
+            text="New text box"
10
+        />
11
+        <MenuItem
12
+            iconName="new-object"
13
+            text="New object"
14
+        />
15
+        <MenuItem
16
+            iconName="new-link"
17
+            text="New link"
18
+        />
19
+        <MenuDivider />
20
+        <MenuItem text="Settings..." iconName="cog" />
21
+    </Menu>

+ 12
- 0
src/Pages/User/User.jsx 파일 보기

@@ -0,0 +1,12 @@
1
+import React from 'react'
2
+import UserPic from './UserPic'
3
+import UserInfo from './UserInfo'
4
+import "./User.scss"
5
+
6
+const User = () => 
7
+    <div className="User">
8
+        <UserPic />
9
+        <UserInfo />
10
+    </div>
11
+
12
+export default User;

+ 41
- 0
src/Pages/User/User.scss 파일 보기

@@ -0,0 +1,41 @@
1
+.User {
2
+    display: flex;
3
+    flex-direction: row;
4
+    align-content: flex-start;
5
+    justify-content: flex-start;
6
+
7
+    .profile-pic {
8
+        width: 200px;
9
+        height: 200px;
10
+    }
11
+
12
+    .profile-info {
13
+        display: flex;
14
+        margin-left: 50px;
15
+        flex-direction: column;
16
+        justify-content: space-around;
17
+
18
+        h3 {
19
+            margin-bottom: 30px;
20
+        }
21
+
22
+        .social-columns {
23
+            display: flex;
24
+            flex-wrap: wrap;
25
+
26
+            & > h4 {
27
+                margin: 20px;
28
+            }
29
+
30
+            .fa {
31
+                margin-right: 20px;
32
+                width: 20px;
33
+            }
34
+        }
35
+
36
+
37
+        .pt-label > input.pt-input {
38
+            margin-left: 20px;
39
+        }
40
+    }
41
+}

+ 22
- 0
src/Pages/User/UserInfo.jsx 파일 보기

@@ -0,0 +1,22 @@
1
+import React from 'react'
2
+import FontAwesome from 'react-fontawesome'
3
+import { EditableText } from "@blueprintjs/core"
4
+
5
+const SocialLink = ({ iconName, ...otherProps }) => <h4><FontAwesome name={iconName} /><EditableText {...otherProps}/></h4>
6
+
7
+const UserInfo = () => 
8
+    <div className="profile-info">
9
+        <h3><EditableText placeholder="Username"/></h3>
10
+        <h3><EditableText placeholder="Email"/></h3>
11
+        <div className="social-columns">
12
+            <SocialLink iconName="twitter" placeholder="Twitter" />
13
+            <SocialLink iconName="facebook" placeholder="Facebook"/>
14
+            <SocialLink iconName="linkedin" placeholder="LinkedIn"/>
15
+            <SocialLink iconName="stack-overflow" placeholder="StackOverflow"/>
16
+            <SocialLink iconName="github" placeholder="Github"/>
17
+            <SocialLink iconName="globe" placeholder="Website"/>
18
+        </div>
19
+    </div>
20
+    
21
+
22
+export default UserInfo

+ 25
- 0
src/Pages/User/UserPic.jsx 파일 보기

@@ -0,0 +1,25 @@
1
+import React from 'react'
2
+import cl from 'classnames'
3
+
4
+const Card = ({ className, children, interactive }) => {
5
+    let classes = cl(["pt-card", className, {'pt-interactive': interactive}]);
6
+    return <div className={classes}>{children}</div>
7
+}
8
+
9
+const Placeholder = ({ iconName, title, description }) => 
10
+    <div className="pt-non-ideal-state">
11
+        <div className="pt-non-ideal-state-visual pt-non-ideal-state-icon">
12
+            <span className={`pt-icon pt-icon-${iconName}`}></span>
13
+        </div>
14
+        <h4 className="pt-non-ideal-state-title">{title}</h4>
15
+        <div className="pt-non-ideal-state-description">
16
+            {description}
17
+        </div>
18
+    </div>
19
+
20
+const UserPic = () => 
21
+    <Card className="profile-pic" interactive>
22
+        <Placeholder iconName="mugshot" title="No picture" description="Click to change"/>
23
+    </Card>
24
+
25
+export default UserPic;

+ 18
- 0
src/Routes.jsx 파일 보기

@@ -0,0 +1,18 @@
1
+import React from 'react'
2
+import { BrowserRouter as Router, Route, Link } from 'react-router-dom'
3
+
4
+import User from './Pages/User/User'
5
+
6
+const Home = () => <div>Home</div>
7
+const Projects = () => <div>Projects</div>
8
+const Settings = () => <div>Settings</div>
9
+
10
+const Routes = () => 
11
+    <div>
12
+        <Route path="/"         component={Home} exact />
13
+        <Route path="/projects"    component={Projects} />
14
+        <Route path="/user"     component={User} />
15
+        <Route path="/settings" component={Settings} />
16
+    </div>
17
+
18
+export default Routes

+ 2
- 0
src/Store/Actions/index.js 파일 보기

@@ -0,0 +1,2 @@
1
+import { LOGIN, LOGOUT } from './user'
2
+export { LOGIN, LOGOUT }

+ 3
- 0
src/Store/Actions/user.js 파일 보기

@@ -0,0 +1,3 @@
1
+import { createAction } from 'redux-actions'
2
+export const LOGIN = createAction('LOGIN');
3
+export const LOGOUT = createAction('LOGOUT');

+ 6
- 0
src/Store/Reducers/index.js 파일 보기

@@ -0,0 +1,6 @@
1
+import { combineReducers } from 'redux'
2
+import { user } from './user'
3
+
4
+const reducers = combineReducers({ user })
5
+
6
+export default reducers

+ 7
- 0
src/Store/Reducers/user.js 파일 보기

@@ -0,0 +1,7 @@
1
+import { handleActions } from 'redux-actions'
2
+import { LOGIN, LOGOUT } from '../Actions'
3
+
4
+export const user = handleActions({
5
+  [LOGIN]: (state, action) => action.payload,
6
+  [LOGOUT]: (state, action) => null
7
+}, null);

+ 4
- 0
src/assets.js 파일 보기

@@ -0,0 +1,4 @@
1
+import "resetcss/reset.min.css"
2
+import "@blueprintjs/core/dist/blueprint.css"
3
+import 'font-awesome/css/font-awesome.min.css'
4
+import './App.scss'

+ 8
- 1
src/index.js 파일 보기

@@ -1,7 +1,14 @@
1 1
 import React from 'react'
2 2
 import ReactDOM from 'react-dom'
3
+import { createStore } from 'redux'
4
+import { Provider } from 'react-redux'
5
+import reducers from './Store/Reducers'
3 6
 import App from './App'
4 7
 
5
-ReactDOM.render(<App />, document.getElementById('root'));
8
+const devToolsEnabled = window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
9
+
10
+let store = createStore(reducers, devToolsEnabled)
11
+
12
+ReactDOM.render(<Provider store={store}><App /></Provider>, document.getElementById('root'));
6 13
 
7 14
 module.hot.accept();

+ 5
- 4
webpack.config.js 파일 보기

@@ -1,4 +1,4 @@
1
-var ExtractTextPlugin = require('extract-text-webpack-plugin');
1
+var ExtractTextPlugin = require('extract-text-webpack-plugin')
2 2
 
3 3
 module.exports = {
4 4
     entry: [
@@ -22,7 +22,7 @@ module.exports = {
22 22
                 test: /\.s?css$/,
23 23
                 loader: ExtractTextPlugin.extract({
24 24
                     fallback: 'style-loader',
25
-                    use: ['sass-loader', 'css-loader']
25
+                    use: ['css-loader', 'sass-loader']
26 26
                 })
27 27
             },
28 28
             {
@@ -39,6 +39,7 @@ module.exports = {
39 39
     ],
40 40
     devServer: {
41 41
         contentBase: './dist',
42
-        hot: true
42
+        hot: true,
43
+        historyApiFallback: true
43 44
     },
44
-};
45
+}

+ 132
- 6
yarn.lock 파일 보기

@@ -398,6 +398,10 @@ babel-plugin-syntax-jsx@^6.3.13, babel-plugin-syntax-jsx@^6.8.0:
398 398
   version "6.18.0"
399 399
   resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946"
400 400
 
401
+babel-plugin-syntax-object-rest-spread@^6.8.0:
402
+  version "6.13.0"
403
+  resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5"
404
+
401 405
 babel-plugin-syntax-trailing-function-commas@^6.22.0:
402 406
   version "6.22.0"
403 407
   resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3"
@@ -593,6 +597,13 @@ babel-plugin-transform-flow-strip-types@^6.22.0:
593 597
     babel-plugin-syntax-flow "^6.18.0"
594 598
     babel-runtime "^6.22.0"
595 599
 
600
+babel-plugin-transform-object-rest-spread@^6.23.0:
601
+  version "6.23.0"
602
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.23.0.tgz#875d6bc9be761c58a2ae3feee5dc4895d8c7f921"
603
+  dependencies:
604
+    babel-plugin-syntax-object-rest-spread "^6.8.0"
605
+    babel-runtime "^6.22.0"
606
+
596 607
 babel-plugin-transform-react-display-name@^6.23.0:
597 608
   version "6.23.0"
598 609
   resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.23.0.tgz#4398910c358441dc4cef18787264d0412ed36b37"
@@ -983,7 +994,7 @@ clap@^1.0.9:
983 994
   dependencies:
984 995
     chalk "^1.1.3"
985 996
 
986
-classnames@^2.2:
997
+classnames@^2.2, classnames@^2.2.5:
987 998
   version "2.2.5"
988 999
   resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.5.tgz#fb3801d453467649ef3603c7d61a02bd129bde6d"
989 1000
 
@@ -1183,6 +1194,14 @@ create-hmac@^1.1.0, create-hmac@^1.1.2:
1183 1194
     create-hash "^1.1.0"
1184 1195
     inherits "^2.0.1"
1185 1196
 
1197
+create-react-class@^15.5.1:
1198
+  version "15.5.3"
1199
+  resolved "https://registry.yarnpkg.com/create-react-class/-/create-react-class-15.5.3.tgz#fb0f7cae79339e9a179e194ef466efa3923820fe"
1200
+  dependencies:
1201
+    fbjs "^0.8.9"
1202
+    loose-envify "^1.3.1"
1203
+    object-assign "^4.1.1"
1204
+
1186 1205
 cross-spawn@^3.0.0:
1187 1206
   version "3.0.1"
1188 1207
   resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-3.0.1.tgz#1256037ecb9f0c5f79e3d6ef135e30770184b982"
@@ -1693,6 +1712,10 @@ flatten@^1.0.2:
1693 1712
   version "1.0.2"
1694 1713
   resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782"
1695 1714
 
1715
+font-awesome@^4.7.0:
1716
+  version "4.7.0"
1717
+  resolved "https://registry.yarnpkg.com/font-awesome/-/font-awesome-4.7.0.tgz#8fa8cf0411a1a31afd07b06d2902bb9fc815a133"
1718
+
1696 1719
 for-in@^0.1.3:
1697 1720
   version "0.1.8"
1698 1721
   resolved "https://registry.yarnpkg.com/for-in/-/for-in-0.1.8.tgz#d8773908e31256109952b1fdb9b3fa867d2775e1"
@@ -1890,6 +1913,16 @@ he@1.1.x:
1890 1913
   version "1.1.1"
1891 1914
   resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd"
1892 1915
 
1916
+history@^4.5.1, history@^4.6.0:
1917
+  version "4.6.1"
1918
+  resolved "https://registry.yarnpkg.com/history/-/history-4.6.1.tgz#911cf8eb65728555a94f2b12780a0c531a14d2fd"
1919
+  dependencies:
1920
+    invariant "^2.2.1"
1921
+    loose-envify "^1.2.0"
1922
+    resolve-pathname "^2.0.0"
1923
+    value-equal "^0.2.0"
1924
+    warning "^3.0.0"
1925
+
1893 1926
 hmac-drbg@^1.0.0:
1894 1927
   version "1.0.1"
1895 1928
   resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1"
@@ -1902,6 +1935,10 @@ hoek@2.x.x:
1902 1935
   version "2.16.3"
1903 1936
   resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed"
1904 1937
 
1938
+hoist-non-react-statics@^1.0.3, hoist-non-react-statics@^1.2.0:
1939
+  version "1.2.0"
1940
+  resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-1.2.0.tgz#aa448cf0986d55cc40773b17174b7dd066cb7cfb"
1941
+
1905 1942
 home-or-tmp@^2.0.0:
1906 1943
   version "2.0.0"
1907 1944
   resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8"
@@ -2065,7 +2102,7 @@ interpret@^1.0.0:
2065 2102
   version "1.0.3"
2066 2103
   resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.0.3.tgz#cbc35c62eeee73f19ab7b10a801511401afc0f90"
2067 2104
 
2068
-invariant@^2.2.0, invariant@^2.2.2:
2105
+invariant@^2.0.0, invariant@^2.2.0, invariant@^2.2.1, invariant@^2.2.2:
2069 2106
   version "2.2.2"
2070 2107
   resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360"
2071 2108
   dependencies:
@@ -2353,6 +2390,10 @@ loader-utils@^1.0.1, loader-utils@^1.0.2:
2353 2390
     emojis-list "^2.0.0"
2354 2391
     json5 "^0.5.0"
2355 2392
 
2393
+lodash-es@^4.17.4, lodash-es@^4.2.0, lodash-es@^4.2.1:
2394
+  version "4.17.4"
2395
+  resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.4.tgz#dcc1d7552e150a0640073ba9cb31d70f032950e7"
2396
+
2356 2397
 lodash.assign@^4.2.0:
2357 2398
   version "4.2.0"
2358 2399
   resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7"
@@ -2381,7 +2422,7 @@ lodash.uniq@^4.5.0:
2381 2422
   version "4.5.0"
2382 2423
   resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
2383 2424
 
2384
-lodash@^4.0.0, lodash@^4.14.0, lodash@^4.17.2, lodash@^4.17.3, lodash@^4.2.0:
2425
+lodash@^4.0.0, lodash@^4.13.1, lodash@^4.14.0, lodash@^4.17.2, lodash@^4.17.3, lodash@^4.2.0, lodash@^4.2.1:
2385 2426
   version "4.17.4"
2386 2427
   resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
2387 2428
 
@@ -2393,7 +2434,7 @@ longest@^1.0.1:
2393 2434
   version "1.0.1"
2394 2435
   resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097"
2395 2436
 
2396
-loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1:
2437
+loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1:
2397 2438
   version "1.3.1"
2398 2439
   resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848"
2399 2440
   dependencies:
@@ -2731,7 +2772,7 @@ oauth-sign@~0.8.1:
2731 2772
   version "0.8.2"
2732 2773
   resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43"
2733 2774
 
2734
-object-assign@^4.0.1, object-assign@^4.1.0:
2775
+object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1:
2735 2776
   version "4.1.1"
2736 2777
   resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
2737 2778
 
@@ -2857,6 +2898,12 @@ path-to-regexp@0.1.7:
2857 2898
   version "0.1.7"
2858 2899
   resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
2859 2900
 
2901
+path-to-regexp@^1.5.3:
2902
+  version "1.7.0"
2903
+  resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.7.0.tgz#59fde0f435badacba103a84e9d3bc64e96b9937d"
2904
+  dependencies:
2905
+    isarray "0.0.1"
2906
+
2860 2907
 path-type@^1.0.0:
2861 2908
   version "1.1.0"
2862 2909
   resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441"
@@ -3174,7 +3221,7 @@ promise@^7.1.1:
3174 3221
   dependencies:
3175 3222
     asap "~2.0.3"
3176 3223
 
3177
-prop-types@^15.5.7, prop-types@~15.5.7:
3224
+prop-types@^15.0.0, prop-types@^15.5.4, prop-types@^15.5.6, prop-types@^15.5.7, prop-types@~15.5.7:
3178 3225
   version "15.5.9"
3179 3226
   resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.5.9.tgz#d478eef0e761396942f70c78e772f76e8be747c9"
3180 3227
   dependencies:
@@ -3291,6 +3338,12 @@ react-dom@^15.5.4:
3291 3338
     object-assign "^4.1.0"
3292 3339
     prop-types "~15.5.7"
3293 3340
 
3341
+react-fontawesome@^1.6.1:
3342
+  version "1.6.1"
3343
+  resolved "https://registry.yarnpkg.com/react-fontawesome/-/react-fontawesome-1.6.1.tgz#eddce17e7dc731aa09fd4a186688a61793a16c5c"
3344
+  dependencies:
3345
+    prop-types "^15.5.6"
3346
+
3294 3347
 react-hot-api@^0.4.5:
3295 3348
   version "0.4.7"
3296 3349
   resolved "https://registry.yarnpkg.com/react-hot-api/-/react-hot-api-0.4.7.tgz#a7e22a56d252e11abd9366b61264cf4492c58171"
@@ -3302,6 +3355,39 @@ react-hot-loader@^1.3.1:
3302 3355
     react-hot-api "^0.4.5"
3303 3356
     source-map "^0.4.4"
3304 3357
 
3358
+react-redux@^5.0.4:
3359
+  version "5.0.4"
3360
+  resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-5.0.4.tgz#1563babadcfb2672f57f9ceaa439fb16bf85d55b"
3361
+  dependencies:
3362
+    create-react-class "^15.5.1"
3363
+    hoist-non-react-statics "^1.0.3"
3364
+    invariant "^2.0.0"
3365
+    lodash "^4.2.0"
3366
+    lodash-es "^4.2.0"
3367
+    loose-envify "^1.1.0"
3368
+    prop-types "^15.0.0"
3369
+
3370
+react-router-dom@^4.1.1:
3371
+  version "4.1.1"
3372
+  resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-4.1.1.tgz#3021ade1f2c160af97cf94e25594c5f294583025"
3373
+  dependencies:
3374
+    history "^4.5.1"
3375
+    loose-envify "^1.3.1"
3376
+    prop-types "^15.5.4"
3377
+    react-router "^4.1.1"
3378
+
3379
+react-router@^4.1.1:
3380
+  version "4.1.1"
3381
+  resolved "https://registry.yarnpkg.com/react-router/-/react-router-4.1.1.tgz#d448f3b7c1b429a6fbb03395099949c606b1fe95"
3382
+  dependencies:
3383
+    history "^4.6.0"
3384
+    hoist-non-react-statics "^1.2.0"
3385
+    invariant "^2.2.2"
3386
+    loose-envify "^1.3.1"
3387
+    path-to-regexp "^1.5.3"
3388
+    prop-types "^15.5.4"
3389
+    warning "^3.0.0"
3390
+
3305 3391
 react@^15.5.4:
3306 3392
   version "15.5.4"
3307 3393
   resolved "https://registry.yarnpkg.com/react/-/react-15.5.4.tgz#fa83eb01506ab237cdc1c8c3b1cea8de012bf047"
@@ -3377,6 +3463,28 @@ reduce-function-call@^1.0.1:
3377 3463
   dependencies:
3378 3464
     balanced-match "^0.4.2"
3379 3465
 
3466
+reduce-reducers@^0.1.0:
3467
+  version "0.1.2"
3468
+  resolved "https://registry.yarnpkg.com/reduce-reducers/-/reduce-reducers-0.1.2.tgz#fa1b4718bc5292a71ddd1e5d839c9bea9770f14b"
3469
+
3470
+redux-actions@^2.0.3:
3471
+  version "2.0.3"
3472
+  resolved "https://registry.yarnpkg.com/redux-actions/-/redux-actions-2.0.3.tgz#1550aba9def179166ccd234d07672104a736d889"
3473
+  dependencies:
3474
+    invariant "^2.2.1"
3475
+    lodash "^4.13.1"
3476
+    lodash-es "^4.17.4"
3477
+    reduce-reducers "^0.1.0"
3478
+
3479
+redux@^3.6.0:
3480
+  version "3.6.0"
3481
+  resolved "https://registry.yarnpkg.com/redux/-/redux-3.6.0.tgz#887c2b3d0b9bd86eca2be70571c27654c19e188d"
3482
+  dependencies:
3483
+    lodash "^4.2.1"
3484
+    lodash-es "^4.2.1"
3485
+    loose-envify "^1.1.0"
3486
+    symbol-observable "^1.0.2"
3487
+
3380 3488
 regenerate@^1.2.1:
3381 3489
   version "1.3.2"
3382 3490
   resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.2.tgz#d1941c67bad437e1be76433add5b385f95b19260"
@@ -3501,6 +3609,10 @@ resetcss@^1.0.3:
3501 3609
   version "1.0.3"
3502 3610
   resolved "https://registry.yarnpkg.com/resetcss/-/resetcss-1.0.3.tgz#f13960be06728ba84462f0f51575dc10c8058209"
3503 3611
 
3612
+resolve-pathname@^2.0.0:
3613
+  version "2.1.0"
3614
+  resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-2.1.0.tgz#e8358801b86b83b17560d4e3c382d7aef2100944"
3615
+
3504 3616
 right-align@^0.1.1:
3505 3617
   version "0.1.3"
3506 3618
   resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef"
@@ -3851,6 +3963,10 @@ svgo@^0.7.0:
3851 3963
     sax "~1.2.1"
3852 3964
     whet.extend "~0.9.9"
3853 3965
 
3966
+symbol-observable@^1.0.2:
3967
+  version "1.0.4"
3968
+  resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.4.tgz#29bf615d4aa7121bdd898b22d4b3f9bc4e2aa03d"
3969
+
3854 3970
 tapable@^0.2.5, tapable@~0.2.5:
3855 3971
   version "0.2.6"
3856 3972
   resolved "https://registry.yarnpkg.com/tapable/-/tapable-0.2.6.tgz#206be8e188860b514425375e6f1ae89bfb01fd8d"
@@ -4038,6 +4154,10 @@ validate-npm-package-license@^3.0.1:
4038 4154
     spdx-correct "~1.0.0"
4039 4155
     spdx-expression-parse "~1.0.0"
4040 4156
 
4157
+value-equal@^0.2.0:
4158
+  version "0.2.1"
4159
+  resolved "https://registry.yarnpkg.com/value-equal/-/value-equal-0.2.1.tgz#c220a304361fce6994dbbedaa3c7e1a1b895871d"
4160
+
4041 4161
 vary@~1.1.0:
4042 4162
   version "1.1.1"
4043 4163
   resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.1.tgz#67535ebb694c1d52257457984665323f587e8d37"
@@ -4058,6 +4178,12 @@ vm-browserify@0.0.4:
4058 4178
   dependencies:
4059 4179
     indexof "0.0.1"
4060 4180
 
4181
+warning@^3.0.0:
4182
+  version "3.0.0"
4183
+  resolved "https://registry.yarnpkg.com/warning/-/warning-3.0.0.tgz#32e5377cb572de4ab04753bdf8821c01ed605b7c"
4184
+  dependencies:
4185
+    loose-envify "^1.0.0"
4186
+
4061 4187
 watchpack@^1.3.1:
4062 4188
   version "1.3.1"
4063 4189
   resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.3.1.tgz#7d8693907b28ce6013e7f3610aa2a1acf07dad87"