├── dev
├── chunk-manifest.json
├── index.html
└── js
│ ├── manifest.js.map
│ └── manifest.js
├── app
├── server
│ ├── model
│ │ ├── index.js
│ │ ├── users.js
│ │ └── articles.js
│ ├── config
│ │ └── index.js
│ ├── schemas
│ │ ├── users.js
│ │ └── articles.js
│ ├── api
│ │ ├── index.js
│ │ ├── logout.js
│ │ ├── register.js
│ │ ├── admin.js
│ │ └── login.js
│ ├── middlewares
│ │ └── auth.js
│ └── server.js
└── front
│ ├── js
│ ├── actions
│ │ ├── about.js
│ │ ├── index.js
│ │ ├── users.js
│ │ └── articles.js
│ ├── components
│ │ ├── Admin
│ │ │ ├── index.js
│ │ │ ├── Admin.js
│ │ │ ├── AdminLink.js
│ │ │ ├── Users.js
│ │ │ ├── EditArticle.js
│ │ │ ├── Article.js
│ │ │ └── AdminHome.js
│ │ ├── Blog
│ │ │ ├── All.js
│ │ │ ├── Auto.js
│ │ │ ├── Mongo.js
│ │ │ ├── Node.js
│ │ │ ├── Blog.js
│ │ │ ├── index.js
│ │ │ └── BlogLink.js
│ │ ├── partial
│ │ │ └── index.js
│ │ ├── Header
│ │ │ └── index.js
│ │ ├── About
│ │ │ └── index.js
│ │ ├── NotFound
│ │ │ └── index.js
│ │ ├── GetStorage
│ │ │ └── index.js
│ │ └── NavLink
│ │ │ └── index.js
│ ├── store
│ │ ├── index.js
│ │ ├── store.prod.js
│ │ └── store.dev.js
│ ├── reducers
│ │ ├── home.js
│ │ ├── about.js
│ │ ├── users.js
│ │ ├── index.js
│ │ ├── userInfo.js
│ │ └── articles.js
│ ├── constants
│ │ └── index.js
│ ├── utils
│ │ ├── enterOrLeaveRoute.js
│ │ └── request.js
│ ├── containers
│ │ ├── Home
│ │ │ └── index.js
│ │ ├── App.js
│ │ ├── Login
│ │ │ └── index.js
│ │ └── Register
│ │ │ └── index.js
│ ├── index.js
│ └── router
│ │ └── index.js
│ └── scss
│ ├── app.scss
│ ├── admin.scss
│ ├── pubilc.scss
│ ├── login.scss
│ ├── nav.scss
│ ├── header.scss
│ └── reset.scss
├── .idea
├── dictionaries
│ └── shunshun.xml
├── vcs.xml
├── jsLibraryMappings.xml
├── modules.xml
├── react-express-mongodb.iml
├── misc.xml
└── inspectionProfiles
│ └── Project_Default.xml
├── .eslintignore
├── .gitignore
├── tsconfig.json
├── webpack
├── api.js
├── config.js
└── base.js
├── .babelrc
├── README.md
├── webpack.prod.config.js
├── static
└── tpl.html
├── dev-server.js
├── package.json
├── webpack.dev.config.js
└── .eslintrc
/dev/chunk-manifest.json:
--------------------------------------------------------------------------------
1 | {"0":"app.chunk.js","1":"verdor.chunk.js"}
--------------------------------------------------------------------------------
/app/server/model/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by '苏萧' on 2017/7/14.
3 | */
4 |
--------------------------------------------------------------------------------
/app/server/config/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by '苏萧' on 2017/7/14.
3 | */
4 |
--------------------------------------------------------------------------------
/.idea/dictionaries/shunshun.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | webpack.dev.config.js
2 | webpack.prod.config.js
3 | webpack/**/*
4 | node-modules/**/*
5 | dev/**/*
6 | build/**/*
7 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.tags
2 | *.tags1
3 | */.DS_Store
4 | *.DS_Store
5 | */.idea/
6 | .idea/
7 | /node_modules/
8 | /app/js/
9 | /app/scss/
10 | /app/server/db/
11 | /dev/
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/jsLibraryMappings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/front/js/actions/about.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by '苏萧' on 2017/7/13.
3 | */
4 | import * as types from '../constants';
5 |
6 | export const receiveUserInfo = (data) => ({
7 | type: types.FETCH_USER_INFO,
8 | info: data
9 | });
10 |
--------------------------------------------------------------------------------
/app/server/model/users.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by suxiao on 2017/7/16.
3 | */
4 | const mongoose = require('mongoose');
5 | const userSchema = require('../schemas/users');
6 | // console.log(userSchema);
7 | module.exports = mongoose.model('Users', userSchema);
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: leo
3 | * @Date: 2017-08-14 10:14:53
4 | * @Last Modified by: leo
5 | * @Last Modified time: 2017-08-14 10:15:40
6 | */
7 | {
8 | "compilerOptions": {
9 | "experimentalDecorators": true,
10 | "allowJs": true
11 | }
12 | }
--------------------------------------------------------------------------------
/app/front/js/components/Admin/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by suxiao on 2017/7/19.
3 | */
4 |
5 | export { Users } from './Users'
6 | export { Admin } from './Admin'
7 | export { AdminHome } from './AdminHome'
8 | export { Article } from './Article'
9 | export { EditArticle } from './EditArticle'
--------------------------------------------------------------------------------
/app/front/js/store/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by '苏萧' on 2017/7/13.
3 | */
4 | if (process.env.NODE_ENV === 'production') {
5 | console.log(222222222222);
6 | module.exports = require('./store.prod');
7 | } else {
8 | console.log('111111');
9 | module.exports = require('./store.dev');
10 | }
--------------------------------------------------------------------------------
/app/server/schemas/users.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by suxiao on 2017/7/16.
3 | */
4 | const mongoose = require('mongoose');
5 | const Schema = mongoose.Schema;
6 | module.exports = new Schema({
7 | username: String,
8 | password: String,
9 | isAdmin: {
10 | type: Boolean,
11 | default: false
12 | }
13 | })
--------------------------------------------------------------------------------
/app/front/scss/app.scss:
--------------------------------------------------------------------------------
1 | .wraper {
2 | width: 100%;
3 | // height: 100%;
4 | // overflow: hidden;
5 | .main {
6 | width: 90%;
7 | // height: 90%;
8 | padding-top: 20px;
9 | // overflow: hidden;
10 | margin: 0 auto;
11 | .right-content {
12 | width: 87%;
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/app/server/model/articles.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: leo
3 | * @Date: 2017-08-14 16:02:13
4 | * @Last Modified by: leo
5 | * @Last Modified time: 2017-08-14 18:42:11
6 | */
7 | const mongoose = require('mongoose');
8 | const articleSchema = require('../schemas/articles');
9 | module.exports = mongoose.model('Articles', articleSchema);
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/front/js/components/Blog/All.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by '苏萧' on 2017/7/13.
3 | */
4 | import React from 'react'
5 | export class All extends React.Component {
6 | render() {
7 | return (
8 |
11 | );
12 | }
13 | }
--------------------------------------------------------------------------------
/app/front/js/components/Blog/Auto.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by '苏萧' on 2017/7/13.
3 | */
4 | import React from 'react'
5 | export class Auto extends React.Component {
6 | render() {
7 | return (
8 |
11 | );
12 | }
13 | }
--------------------------------------------------------------------------------
/app/front/js/components/Blog/Mongo.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by '苏萧' on 2017/7/13.
3 | */
4 | import React from 'react'
5 | export class Mongo extends React.Component {
6 | render() {
7 | return (
8 |
11 | );
12 | }
13 | }
--------------------------------------------------------------------------------
/app/front/js/components/Blog/Node.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by '苏萧' on 2017/7/13.
3 | */
4 | import React from 'react'
5 | export class Node extends React.Component {
6 | render() {
7 | return (
8 |
11 | );
12 | }
13 | }
--------------------------------------------------------------------------------
/webpack/api.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by "苏萧" on 2017/7/11.
3 | */
4 | /**
5 | * 定义不同环境变量下的 应用请求配置---服务器 API 配置文件
6 | * */
7 |
8 | const ip = require("ip").address();
9 |
10 | module.exports = {
11 | test: "http://www.baidu.com",// 测试环境的服务器地址
12 | development: `http://${ip}:3333`,// 开发环境的本地服务器地址
13 | production: "http://www.google.com"// 生产环境的服务器地址
14 | };
--------------------------------------------------------------------------------
/app/front/scss/admin.scss:
--------------------------------------------------------------------------------
1 | .admin {
2 |
3 | }
4 | .admin-nav {
5 | ul {
6 | display: flex;
7 | justify-content: flex-start;
8 | li {
9 | margin: 0 5px;
10 | }
11 | a {
12 | padding: 5px;
13 | }
14 | }
15 | }
16 | .active {
17 | color: #ff6600;
18 | }
19 | table {
20 | border: none !important;
21 | }
22 | th, td {
23 | text-align: center !important;
24 | border-right: none !important;
25 | }
--------------------------------------------------------------------------------
/app/front/js/components/Blog/Blog.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by '苏萧' on 2017/7/14.
3 | */
4 | import React from 'react';
5 | import BlogLink from './BlogLink';
6 |
7 | export class Blog extends React.Component {
8 | render() {
9 | return (
10 |
11 |
12 |
13 | {this.props.children}
14 |
15 |
16 | );
17 | }
18 | }
--------------------------------------------------------------------------------
/app/server/api/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by '苏萧' on 2017/7/14.
3 | */
4 | const express = require('express');
5 | const router = express.Router();
6 | // import { Router } from 'express';
7 |
8 | // const router = new Router();
9 |
10 | router.use('/login', require('./login'));
11 | router.use('/register', require('./register'));
12 | router.use('/admin', require('./admin'));
13 | router.use('/logout', require('./logout'));
14 |
15 | module.exports = router;
--------------------------------------------------------------------------------
/app/server/api/logout.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: leo
3 | * @Date: 2017-08-17 11:47:40
4 | * @Last Modified by: leo
5 | * @Last Modified time: 2017-08-17 15:56:35
6 | */
7 | const express = require('express');
8 | const router = express.Router();
9 | router.post('/', (req, res, next) => {
10 | req.session.destroy();
11 | res.clearCookie('user-token', {
12 | path: '/',
13 | domain: ''
14 | });
15 | res.redirect('/sign');
16 | })
17 |
18 | module.exports = router;
--------------------------------------------------------------------------------
/app/front/js/components/partial/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by suxiao on 2017/7/12.
3 | */
4 | import React from 'react'
5 | import { Link } from 'react-router'
6 | import { Icon } from 'antd'
7 |
8 | export default class Partial extends React.Component {
9 | render() {
10 | return (
11 |
12 | {
13 | this.props.type &&
14 | }
15 |
16 |
17 | );
18 | }
19 | }
--------------------------------------------------------------------------------
/.idea/react-express-mongodb.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/front/js/store/store.prod.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by '苏萧' on 2017/7/13.
3 | */
4 | import { compose, applyMiddleware } from 'redux';
5 | import thunkMiddleware from 'redux-thunk';
6 |
7 | import rootReducer from '../reducers'
8 |
9 | const createStoreWithMiddleware = compose(
10 | applyMiddleware(
11 | thunkMiddleware
12 | )
13 | );
14 |
15 | const configureStore = (initialState) => {
16 | const store = createStoreWithMiddleware(rootReducer, initialState);
17 | return store;
18 | }
19 |
20 | export default configureStore
--------------------------------------------------------------------------------
/app/front/js/components/Blog/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by '苏萧' on 2017/7/13.
3 | */
4 | // import React from 'react'
5 | // import NavLink from '../NavLink'
6 | // export default class Blog extends React.Component {
7 | // render() {
8 | // return (
9 | //
10 | //
11 | //
12 | // );
13 | // }
14 | // }
15 |
16 | export { All } from './All';
17 | export { Auto } from './Auto';
18 | export { Mongo } from './Mongo';
19 | export { Node } from './Node';
20 | export { Blog } from './Blog';
--------------------------------------------------------------------------------
/app/front/js/components/Admin/Admin.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by suxiao on 2017/7/19.
3 | */
4 | import React, { Component } from 'react';
5 |
6 | import AdminLink from './AdminLink'
7 | import '../../../scss/admin.scss'
8 |
9 | export class Admin extends Component {
10 | constructor (props) {
11 | super(props)
12 | }
13 |
14 | render() {
15 | return (
16 |
17 |
18 |
19 | {this.props.children}
20 |
21 |
22 | )
23 | }
24 | }
--------------------------------------------------------------------------------
/app/server/schemas/articles.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: leo
3 | * @Date: 2017-08-14 16:03:01
4 | * @Last Modified by: leo
5 | * @Last Modified time: 2017-08-14 21:42:11
6 | */
7 | const mongoose = require('mongoose');
8 | const Schema = mongoose.Schema;
9 | module.exports = new Schema({
10 | sort: String,
11 | title: String,
12 | content: String,
13 | author: {
14 | type: String,
15 | default: ''
16 | },
17 | createDate: {
18 | type: Date,
19 | default: Date.now
20 | },
21 | updateDate: {
22 | type: Date,
23 | default: Date.now
24 | }
25 | })
--------------------------------------------------------------------------------
/app/front/js/reducers/home.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by suxiao on 2017/7/15.
3 | */
4 | import * as types from '../constants';
5 | const initialState = {
6 | title: 'Home',
7 | description: '这是一个个人博客'
8 | }
9 |
10 | const homeState = (state=initialState, action) => {
11 | switch (action.type) {
12 | case types.HOME_INFO:
13 | let info = {};
14 | if (action.info !== undefined) {
15 | info = action.info
16 | }
17 | return Object.assign({}, state, { ...info });
18 | default:
19 | return state
20 | }
21 | }
22 |
23 | export default homeState
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 |
2 | {
3 | "presets": [
4 | ["es2015", { "modules": false }],
5 | "stage-2",
6 | "react"
7 | ],
8 | "plugins": [
9 | "react-hot-loader/babel",
10 | "transform-object-assign",
11 | "transform-decorators-legacy",
12 | [
13 | "transform-runtime",
14 | [
15 | "import",
16 | { "libraryName": "antd", "style": true }
17 | ],
18 | { "polyfill": false, "regenerator": true }
19 | ]
20 | ],
21 | "env": {
22 | "development": {
23 | "plugins": [
24 | "react-hot-loader/babel"
25 | ]
26 | }
27 | }
28 | }
--------------------------------------------------------------------------------
/app/front/js/reducers/about.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by '苏萧' on 2017/7/13.
3 | */
4 | import * as types from '../constants';
5 |
6 | const initialState = {
7 | info: 'about',
8 | isFetching: true
9 | };
10 |
11 | const aboutState = (state=initialState, action) => {
12 | switch (action) {
13 | case types.FETCH_USER_INFO:
14 | let info = {};
15 | if (action.info !== undefined) {
16 | info = action.info
17 | }
18 | return Object.assign({}, state, {info:info, isFetching:false});
19 | default:
20 | return state
21 | }
22 | };
23 |
24 | export default aboutState
--------------------------------------------------------------------------------
/app/front/js/components/Header/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by '苏萧' on 2017/7/13.
3 | */
4 | import React from 'react'
5 | import { Row, Col } from 'antd';
6 | import NavLink from '../NavLink'
7 | import '../../../scss/header.scss'
8 |
9 | export default class Header extends React.Component {
10 | render() {
11 | return (
12 |
13 |
14 | 小黑哥的BLOG
15 |
16 |
17 |
18 |
19 |
20 | );
21 | }
22 | }
--------------------------------------------------------------------------------
/app/front/js/components/About/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by '苏萧' on 2017/7/13.
3 | */
4 | import React from 'react'
5 | import { connect } from 'react-redux'
6 |
7 | import { receiveUserInfo } from '../../actions/about'
8 | @connect(
9 | (state) => ({about: state.about}),
10 | (dispath) => ({receiveUserInfo })
11 | )
12 |
13 | export default class About extends React.Component {
14 | render() {
15 | console.log(this.props.about.info);
16 | // let items = [1, 2, 3].map( (value, index) => {
17 | // return {value}
;
18 | // });
19 | // console.log(items);
20 | return (
21 | {this.props.about.info}
22 | );
23 | }
24 | }
--------------------------------------------------------------------------------
/app/front/js/components/NotFound/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by '苏萧' on 2017/7/13.
3 | */
4 | import React from 'react'
5 | import {browserHistory} from 'react-router';
6 |
7 | export default class NotFound extends React.Component {
8 | handleClick = () => {
9 | browserHistory.push('/home');
10 | }
11 | render() {
12 | return (
13 |
14 |
17 |
18 |
21 |
22 |
23 | )
24 | }
25 | }
--------------------------------------------------------------------------------
/app/front/js/reducers/users.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by suxiao on 2017/7/20.
3 | */
4 | import * as types from '../constants';
5 | const initialState = {
6 | users: [],
7 | isFetching: true
8 | }
9 |
10 | const usersState = (state=initialState, action) => {
11 | switch (action.type) {
12 | case types.FETCH_REQUEST:
13 | return Object({}, state, {isFetching: true})
14 | case types.FETCH_USERS:
15 | let info = {};
16 | if (action.users !== undefined) {
17 | info = action.users
18 | }
19 | return Object.assign({}, state, { users: info, isFetching: false });
20 | default:
21 | return state
22 | }
23 | }
24 |
25 | export default usersState
--------------------------------------------------------------------------------
/app/front/scss/pubilc.scss:
--------------------------------------------------------------------------------
1 | .clearfix {
2 | zoom: 1;
3 | }
4 |
5 | .clearfix:after {
6 | content: ".";
7 | width: 0;
8 | height: 0;
9 | visibility: hidden;
10 | display: block;
11 | clear: both;
12 | overflow:hidden;
13 | }
14 |
15 | .fl {
16 | float: left
17 | }
18 |
19 | .fr {
20 | float: right
21 | }
22 |
23 | .tl {
24 | text-align: left;
25 | }
26 |
27 | .tc {
28 | text-align: center
29 | }
30 |
31 | .tr {
32 | text-align: right;
33 | }
34 |
35 | .ellipse {
36 | overflow: hidden;
37 | text-overflow: ellipsis;
38 | white-space: nowrap;
39 | }
40 | .inline{
41 | display: inline-block;
42 | *display: inline;
43 | *zoom: 1;
44 | }
45 | .h100 {
46 | height: 100%;
47 | }
--------------------------------------------------------------------------------
/app/front/scss/login.scss:
--------------------------------------------------------------------------------
1 | .login {
2 | width: 100%;
3 | display: flex;
4 | flex-direction: column;
5 | align-items: center;
6 | justify-content: center;
7 | font-size: 16px;
8 | line-height: 26px;
9 | form {
10 | padding: 20px;
11 | margin: 0 auto;
12 | .input-wrapper {
13 | margin-bottom: 20px;
14 | text-align: center;
15 | }
16 | input {
17 | border: 1px solid #999;
18 | height: 26px;
19 | padding-left: 10px;
20 | }
21 | input[type='submit'] {
22 | padding: 5px 10px;
23 | }
24 | }
25 | }
26 | .login-form {
27 | max-width: 300px;
28 | }
29 | .login-form-forgot {
30 | float: right;
31 | }
32 | .login-form-button {
33 | width: 100%;
34 | }
--------------------------------------------------------------------------------
/app/front/js/reducers/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by '苏萧' on 2017/7/13.
3 | */
4 | import { combineReducers } from 'redux';
5 | import {routerReducer} from 'react-router-redux';
6 | import {reducer as reduceForm} from 'redux-form';
7 |
8 | import aboutState from './about';
9 | import homeState from './home';
10 | import usersState from './users';
11 | import userInfo from './userInfo';
12 | import articlesState from './articles';
13 |
14 | const rootReducer = combineReducers({
15 | about: aboutState,
16 | home: homeState,
17 | users: usersState,
18 | userInfo: userInfo,
19 | articles: articlesState,
20 | form: reduceForm,
21 | // 挂载redux-form 如果不挂载会报一堆的错误
22 | routing: routerReducer
23 | });
24 |
25 | export default rootReducer;
--------------------------------------------------------------------------------
/app/front/js/components/GetStorage/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: leo
3 | * @Date: 2017-10-19 17:10:11
4 | * @Last Modified by: leo
5 | * @Last Modified time: 2017-10-20 15:59:29
6 | */
7 |
8 | // 自动生成注释 control + option + i
9 | import React, { Component } from 'react';
10 |
11 | const GetStorage = (key) => (WrappedComponent) => class extends Component {
12 | componentWillMount() {
13 | const data = localStorage.getItem(key);
14 | this.setState({data});
15 | }
16 |
17 | testClick() {
18 | console.log('----test----');
19 | }
20 |
21 | render() {
22 | return
23 | }
24 | }
25 |
26 | export default GetStorage;
27 |
--------------------------------------------------------------------------------
/app/front/scss/nav.scss:
--------------------------------------------------------------------------------
1 | .left-menu {
2 | background: rgb(64, 64 ,64);
3 | width: 13%;
4 | height: 100%;
5 | h3 {
6 | height: 44px;
7 | line-height: 44px;
8 | background: #000;
9 | color: #ea8010;
10 | padding-left: 14px;
11 | font-size:18px;
12 | border-bottom: 1px solid #ea8010;
13 | }
14 | .nav {
15 | font-size: 16px;
16 | font-weigth: 400;
17 | li {
18 | height: 44px;
19 | line-height: 44px;
20 | a {
21 | display: block;
22 | padding-left: 14px;
23 | width: 100%;
24 | height: 100%;
25 | color: #fff;
26 | }
27 | .active {
28 | background: rgb(36, 35, 40);
29 | color: mediumvioletred;
30 | }
31 | }
32 | }
33 | }
--------------------------------------------------------------------------------
/app/front/js/constants/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by '苏萧' on 2017/7/13.
3 | */
4 |
5 | // import { createAction } from 'redux-actions'; 本来想用的,但是感觉更麻烦;
6 | // 同意的发起请求和请求失败
7 | export const FETCH_REQUEST = 'FETCH_REQUEST';
8 | export const FETCH_FAILURE = 'FETCH_FAILURE';
9 | // 登录后用户信息
10 | export const FETCH_USER_INFO = 'FETCH_USER_INFO';
11 | // 请求文章列表
12 | export const FETCH_ARTICLES = 'FETCH_ARTICLES';
13 | // 新增文章
14 | export const FETCH_ADD_ARTICLE = 'FETCH_ADD_ARTICLE';
15 | // 请求用户
16 | export const FETCH_USERS = 'FETCH_USERS';
17 | export const HOME_INFO = 'HOME_INFO';
18 |
19 | // 请求文章
20 | // export const fetchArticles = createAction(FETCH_ARTICLES, articles => articles);
21 | // 请求用户
22 | // export const fetchUsers = createAction(FETCH_USERS, users => users);
--------------------------------------------------------------------------------
/app/front/js/components/Blog/BlogLink.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by '苏萧' on 2017/7/13.
3 | */
4 | import React from 'react';
5 | import Partial from '../partial';
6 | import '../../../scss/nav.scss';
7 |
8 | export default class BlogLink extends React.Component {
9 | render() {
10 | return (
11 |
12 |
文章分类
13 |
21 |
22 | );
23 | }
24 | }
--------------------------------------------------------------------------------
/app/front/js/reducers/userInfo.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: leo
3 | * @Date: 2017-08-13 14:11:33
4 | * @Last Modified by: leo
5 | * @Last Modified time: 2017-08-15 11:22:14
6 | */
7 | import * as types from '../constants';
8 | const initialState = {
9 | user: {},
10 | isFetching: true
11 | }
12 |
13 | const userInfo = (state=initialState, action) => {
14 | switch (action.type) {
15 | case types.FETCH_REQUEST:
16 | return Object({}, state, {isFetching: true})
17 | case types.FETCH_USER_INFO:
18 | let info = {};
19 | if (action.user !== undefined) {
20 | info = action.user;
21 | }
22 | return Object.assign({}, state, { ...info, isFetching: false });
23 | default:
24 | return state
25 | }
26 | }
27 |
28 | export default userInfo
--------------------------------------------------------------------------------
/app/front/js/actions/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by '苏萧' on 2017/7/13.
3 | */
4 | import * as types from '../constants';
5 | import { get } from '../utils/request';
6 |
7 | const fetchRequset = () => ({
8 | type: types.FETCH_REQUEST
9 | })
10 |
11 | const fetchSuccess = (users) => ({
12 | type: types.FETCH_USERS,
13 | users
14 | })
15 |
16 | const fetchFailure = (error) => ({
17 | type: types.FETCH_FAILURE,
18 | error
19 | })
20 | // 请求用户信息
21 | export const receiveUsers = (url) => async (dispatch) => {
22 | try {
23 | await dispatch(fetchRequset())
24 | await get(url)
25 | .then( (response) => dispatch(fetchSuccess(response.message)))
26 | .cache((err) => dispatch(fetchFailure(err)))
27 | } catch (err) {
28 | dispatch( fetchFailure(err) )
29 | }
30 | };
--------------------------------------------------------------------------------
/app/front/scss/header.scss:
--------------------------------------------------------------------------------
1 | .header {
2 | height: 88px;
3 | background: #fff;
4 | border-bottom: 1px solid #eee;
5 | display: flex;
6 | justify-content: space-between;
7 | .title {
8 | height: 100%;
9 | line-height: 88px;
10 | padding-left: 16px;
11 | color: rgb(102, 102, 102);
12 | }
13 | .tabs-nav {
14 | ul {
15 | height: 100%;
16 | display: flex;
17 | justify-content: space-between;
18 | }
19 | li {
20 | height: 100%;
21 | line-height: 88px;
22 | }
23 | a {
24 | height: 100%;
25 | font-size: 16px;
26 | display: inline-block;
27 | padding: 0 5px 0 5px;
28 | margin-right: 10px;
29 | }
30 | .active {
31 | border-bottom: 2px solid #ff6600;
32 | color: #ff6600;
33 | }
34 | }
35 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ### 简介
2 | > 根据目前个人水平,搭建的一个简易的后台博客系统
3 | ---
4 | ### 技术说明
5 | > - 前台使用的技术 *react* *redux* *react-router*
6 | > - UI组件库 *antd*
7 | > - 后台技术 *node* *express* *mongodb*
8 | > - 打包工具 *webpack2*
9 | ---
10 | #### 功能会慢慢的加
11 | > - 目前前台路由搭建完毕,后台路由设计完毕,后台结合webpack启动项目。。。
12 | > - 登录注册功能能可以使用
13 | > - 后台可以新增文章,获取用户信息,获取文章信息
14 | > - 首页增加后台入口
15 | #### 每天进步一点
16 | ---
17 | > - 未完成 登录session,加密,时间格式化等,管理员权限功能
18 | > - 文章在编辑,删除功能
19 | > - 前台请求后台文章数据,展示文章
20 | > - 完成了注册加密,登录解密
21 |
22 | #### 启动项目
23 | - git clone
24 | - npm install
25 | - mongod --dbpath /xxx(项目文件目录)/react-express-mongodb/app/server/db/ 或者 直接启动mongod(自行Google)
26 | - 前端启动 npm start
27 | - 后端启动 npm run server
28 |
29 | #### 我是小黑哥( Leo ),我为自己带盐
30 |
31 |
32 | > 1. Hello world
33 | > 2. QQ: 946732383
34 | > 3. [我的博客](http://www.cnblogs.com/heigehe/ "博客地址")
35 |
36 |
37 |
--------------------------------------------------------------------------------
/app/front/js/components/Admin/AdminLink.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by suxiao on 2017/7/19.
3 | */
4 | import React from 'react';
5 | import { Row, Col } from 'antd';
6 | import Partial from '../partial';
7 |
8 | export default class AdminLink extends React.Component {
9 | render() {
10 | return (
11 |
12 |
13 | 后台管理
14 |
15 |
16 |
24 |
25 |
26 | );
27 | }
28 | }
--------------------------------------------------------------------------------
/app/front/js/components/NavLink/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by '苏萧' on 2017/7/13.
3 | */
4 | import React from 'react';
5 | // import { Icon } from 'antd';
6 | import Partial from '../partial';
7 | import '../../../scss/nav.scss';
8 |
9 | export default class NavLink extends React.Component {
10 | render() {
11 | return (
12 |
21 | );
22 | }
23 | }
--------------------------------------------------------------------------------
/app/front/js/reducers/articles.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: leo
3 | * @Date: 2017-08-14 17:04:42
4 | * @Last Modified by: leo
5 | * @Last Modified time: 2017-08-15 11:57:50
6 | */
7 | // import { handleActions } from 'redux-actions';
8 | import * as types from '../constants';
9 | const initialState = {
10 | articles: [],
11 | isFetching: true
12 | }
13 |
14 | const articlesState = (state=initialState, action) => {
15 | switch (action.type) {
16 | case types.FETCH_REQUEST:
17 | return Object({}, state, {isFetching: true})
18 | case types.FETCH_ARTICLES:
19 | let info = {};
20 | if (action.article !== undefined) {
21 | info = action.article
22 | }
23 | return Object.assign({}, state, { articles: info, isFetching: false });
24 | case types.FETCH_ADD_ARTICLE:
25 | return state;
26 | default:
27 | return state
28 | }
29 | }
30 |
31 | export default articlesState
--------------------------------------------------------------------------------
/app/front/js/utils/enterOrLeaveRoute.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: leo
3 | * @Date: 2017-08-13 14:09:04
4 | * @Last Modified by: leo
5 | * @Last Modified time: 2017-10-19 21:41:02
6 | */
7 | /*
8 | 路由 跳转 确认 集合
9 | 在这里处理组件进入和离开逻辑(通过路由的 onEnter onLeave 方法)
10 | */
11 |
12 | // login 页面 离开时逻辑
13 | export const enterHomePage = (nextState, replace, next) => {
14 | /*
15 | 此处处理 进入 /home 路由的权限控制
16 | nextState : 表示跳转后的location 信息;
17 | replace 用于 更改下一个进入的页面地址,但是不会跳转;
18 | next : 用于跳转页面,没有其他操作则显示当前路由对应页面
19 | */
20 | console.log('onEnter Home Page');
21 | // 这里做判断, 如果不是管理员,之类的操作,进行页面跳转
22 | // replace({ pathname: '/' })
23 | console.log(nextState);
24 | next();
25 | }
26 |
27 | export const leaveHomePage = (nextLocation) => {
28 | // 返回 false 会继续停留当前页面,
29 | // 否则,返回一个字符串,会显示给用户,让其自己决定
30 | console.log('leave Home Page');
31 | alert('确认离开吗');
32 | // console.log(nextLocation);
33 | }
34 |
--------------------------------------------------------------------------------
/app/front/scss/reset.scss:
--------------------------------------------------------------------------------
1 | /*公共样式--开始*/
2 | html, body, div, ul, li, h1, h2, h3, h4, h5, h6, p, dl, dt, dd, ol, form, input, textarea, th, td, select {
3 | margin: 0;
4 | padding: 0;
5 | }
6 | *{box-sizing: border-box;}
7 | html, body {
8 | height: 100%;
9 | }
10 |
11 | body {
12 | font-family: "Microsoft YaHei";
13 | font-size:14px;
14 | color:#333;
15 | background: rgb(243, 243, 243);
16 | }
17 | h1, h2, h3, h4, h5, h6{font-weight:normal;}
18 | ul,ol {
19 | list-style: none;
20 | }
21 |
22 | img {
23 | border: none;
24 | vertical-align: middle;
25 | }
26 |
27 | a {
28 | text-decoration: none;
29 | color: #232323;
30 | }
31 |
32 | a:hover,
33 | a:visited,
34 | a:active,
35 | a:focus {
36 | text-decoration: none;
37 | }
38 |
39 | table {
40 | border-collapse: collapse;
41 | table-layout: fixed;
42 | }
43 |
44 | input, textarea {
45 | outline: none;
46 | border: none;
47 | }
48 |
49 | textarea {
50 | resize: none;
51 | overflow: auto;
52 | }
--------------------------------------------------------------------------------
/app/front/js/containers/Home/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by '苏萧' on 2017/7/13.
3 | */
4 | import React, { PropTypes } from 'react'
5 | import { connect } from 'react-redux'
6 | import PureRenderMixin from 'react-addons-pure-render-mixin';
7 |
8 | import GetStorage from '../../components/GetStorage';
9 |
10 | @connect(
11 | (state) => ({home: state.home}),
12 | (dispatch) => ({})
13 | )
14 |
15 | class HomeComponent extends React.Component {
16 | constructor(props, context) {
17 | super(props, context);
18 | this.shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this);
19 | }
20 | static defaultProps = {
21 | home: {},
22 | data: ''
23 | }
24 |
25 | static propTypes = {
26 | home: PropTypes.object,
27 | data: PropTypes.string
28 | }
29 | render() {
30 | return (
31 |
32 |
{this.props.home.title}
33 |
{this.props.home.description}
34 |
{this.props.data}
35 |
编辑后台
36 |
37 | );
38 | }
39 | }
40 |
41 | const Home = GetStorage('name')(HomeComponent);
42 |
43 | export default Home;
44 |
--------------------------------------------------------------------------------
/app/front/js/store/store.dev.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by '苏萧' on 2017/7/13.
3 | */
4 | import { compose, createStore, applyMiddleware } from 'redux';
5 | import thunkMiddleware from 'redux-thunk';
6 | import { createLogger } from 'redux-logger';
7 | // import { syncHistoryWithStore } from 'react-router-redux';
8 | // import { browserHistory } from 'react-router';
9 | // import { syncHistoryWithStore, routerMiddleware, push } from 'react-router-redux'
10 |
11 | import rootReducer from '../reducers'
12 |
13 | const logger = createLogger({ collapsed: true });
14 | // const reduxRouterMiddleware = routerMiddleware(browserHistory);
15 |
16 | const createStoreWithMiddleware = compose(
17 | applyMiddleware(
18 | thunkMiddleware,
19 | // reduxRouterMiddleware,
20 | logger
21 | ),
22 | window.devToolsExtension ? window.devToolsExtension() : (f) => f)(createStore);
23 |
24 | const configureStore = (initialState) => {
25 | const store = createStoreWithMiddleware(rootReducer, initialState);
26 | if (module.hot) {
27 | module.hot.accept('../reducers', () => {
28 | const nextReducer = require('../reducers').default;
29 | store.replaceReducer(nextReducer);
30 | });
31 | }
32 | return store;
33 | };
34 |
35 | export default configureStore
--------------------------------------------------------------------------------
/app/front/js/actions/users.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by suxiao on 2017/7/20.
3 | */
4 | import { browserHistory } from 'react-router';
5 | import * as types from '../constants';
6 | import { post } from '../utils/request';
7 |
8 | const loginRequset = () => ({
9 | type: types.FETCH_REQUEST
10 | })
11 |
12 | const loginSuccess = (user) => ({
13 | type: types.FETCH_USER_INFO,
14 | user
15 | })
16 |
17 | const loginFailure = (error) => ({
18 | type: types.FETCH_FAILURE,
19 | error
20 | })
21 | // 请求register, login
22 | export const userFetch = (url, params, redirectUrl) => async (dispatch) => {
23 | try {
24 | await dispatch(loginRequset());
25 | const response = await post(url, params);
26 | dispatch(loginSuccess(response));
27 | if (response.status ==='01') {
28 | browserHistory.push(redirectUrl);
29 | }
30 | // await post(url, params)
31 | // .then( response => {
32 | // console.log(response);
33 | // dispatch(loginSuccess(response));
34 | // if (response.status ==='01') {
35 | // browserHistory.push(redirectUrl);
36 | // }
37 | // })
38 | // .cache(err => dispatch(loginFailure(err)))
39 | } catch (err) {
40 | dispatch( loginFailure(err) )
41 | }
42 | };
43 |
44 |
45 |
--------------------------------------------------------------------------------
/app/front/js/utils/request.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: leo
3 | * @Date: 2017-08-13 14:07:50
4 | * @Last Modified by: leo
5 | * @Last Modified time: 2017-08-15 10:52:20
6 | */
7 | /*
8 | 封装请求
9 | */
10 | // import fetch from 'isomorphic-fetch';
11 | // import 'babel-polyfill';
12 | require('es6-promise').polyfill();
13 | require('isomorphic-fetch');
14 |
15 | // baseUrl 由 webpack 根据 环境变量 更换
16 | // export const host = baseUrl; // 当前服务器地址
17 | const host = ''; // 当前服务器地址
18 | console.log(baseUrl);
19 |
20 | // 封装fetch 代替 ajax 请求数据
21 | const request = (method, url, body) => {
22 | method = method.toUpperCase();
23 | if (method === 'GET') {
24 | body = undefined;
25 | } else {
26 | body = body && JSON.stringify(body);
27 | }
28 |
29 | return fetch(host + url, {
30 | method,
31 | headers: {
32 | 'Content-Type': 'application/json',
33 | 'Accept': 'application/json'
34 | },
35 | body
36 | }).then((res) => {
37 | return res.json();
38 | }).then((data) => {
39 | // console.log(data)
40 | return data
41 | });
42 | }
43 |
44 | export const get = (url) => request('GET', url);
45 | export const post = (url, body) => request('POST', url, body);
46 | export const put = (url, body) => request('PUT', url, body);
47 | export const del = (url, body) => request('DELETE', url, body);
48 |
--------------------------------------------------------------------------------
/app/front/js/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by '苏萧' on 2017/7/13.
3 | */
4 |
5 | import React from 'react';
6 | import { render } from 'react-dom';
7 | import { AppContainer } from 'react-hot-loader';
8 | import { syncHistoryWithStore } from 'react-router-redux';
9 | import { Provider } from 'react-redux';
10 | // import { Router, Route, hashHistory, browserHistory, Link, IndexLink, IndexRoute } from 'react-router';
11 | import { Router, browserHistory } from 'react-router';
12 | import injectTapEventPlugin from 'react-tap-event-plugin';
13 |
14 | import routes from './router';
15 | import configureStore from './store'
16 |
17 | import '../scss/reset.scss'
18 | // import 'antd/lib/date-picker/style/css';
19 | // import { DatePicker } from 'antd';
20 | // react 的插件,提供onTouchTap()
21 | injectTapEventPlugin();
22 | // 创建一个增强版的history来结合store同步导航事件
23 | // const store = configureStore(browserHistory);
24 | const store = configureStore();
25 | const history = syncHistoryWithStore(browserHistory, store);
26 |
27 | // history.listen(location => analyticsService.track(location.pathname))
28 |
29 | console.log(process.env.NODE_ENV);
30 | render(
31 |
32 |
33 |
34 |
35 | ,
36 | document.getElementById('app')
37 | );
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | /usr/local/bin/bower
9 |
10 |
11 |
12 | true
13 |
14 | false
15 | true
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | General
26 |
27 |
28 | XPath
29 |
30 |
31 |
32 |
33 | AngularJS
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
49 |
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/app/front/js/containers/App.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by '苏萧' on 2017/7/13.
3 | */
4 | import React from 'react'
5 | // import { connect } from 'react-redux'
6 | // import { receiveUserInfo } from '../actions/about'
7 | import PureRenderMixin from 'react-addons-pure-render-mixin';
8 | import Header from '../components/Header'
9 | import 'antd/dist/antd.less';
10 | import '../../scss/app.scss';
11 | import '../../scss/pubilc.scss'
12 |
13 | // import { Button } from 'antd';
14 |
15 | // @connect(
16 | // state => ({about: state.about}),
17 | // dispatch => ({ receiveUserInfo })
18 | // )
19 |
20 | class App extends React.Component {
21 | constructor(props, context) {
22 | super(props, context);
23 | this.shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this);
24 | }
25 | render() {
26 | // console.log(this.props.about);
27 | // console.log(this.props.receiveUserInfo);
28 | return (
29 |
30 |
31 |
32 | {this.props.children}
33 |
34 |
35 | );
36 |
37 | }
38 | }
39 | export default App
40 | // //将state.counter绑定到props的counter
41 | // const mapStateToProps = (state) => {
42 | // return {
43 | // counter: state.counter
44 | // }
45 | // };
46 | // //将action的所有方法绑定到props上
47 | // const mapDispatchToProps = (dispatch, ownProps) => {
48 | // return {
49 | // increment: (...args) => dispatch(actions.increment(...args)),
50 | // decrement: (...args) => dispatch(actions.decrement(...args))
51 | // }
52 | // };
53 | //
54 | // //通过react-redux提供的connect方法将我们需要的state中的数据和actions中的方法绑定到props上
55 | // export default connect(mapStateToProps, mapDispatchToProps)(App)
56 |
--------------------------------------------------------------------------------
/app/server/middlewares/auth.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: leo
3 | * @Date: 2017-08-17 10:21:46
4 | * @Last Modified by: leo
5 | * @Last Modified time: 2017-10-24 14:35:15
6 | */
7 |
8 | // const crypto = require('crypto');
9 |
10 | /*
11 | // 加密
12 | function encrypto(str, secret) {
13 | const cipher = crypto.createCipher('ase192', secret);
14 | let enc = cipher.update(str, 'utf8', 'hex');
15 | enc += cipher.final('hex');
16 | return enc;
17 | }
18 |
19 | // 解密
20 | function decrypto(str, secret) {
21 | const decipher = crypto.createDecipher('ase192', secret);
22 | let dec = decipher.update(str, 'hex', 'utf8');
23 | dec += decipher.final('utf8');
24 | return dec;
25 | }
26 | */
27 |
28 | // 管理员权限
29 | const adminRequired = function (req, res, next) {
30 | if (!req.session.user) {
31 | return next();
32 | }
33 | if (!req.session.user.isAdmin) {
34 | return next()
35 | }
36 | }
37 |
38 | // 需要登录
39 | const loginRequired = function(req, res, next) {
40 | if (!req.session || !req.session.user || req.session.user._id) {
41 | return next()
42 | }
43 | }
44 |
45 | // 判断是否登录
46 | const authUser = async (req, res, next) => {
47 | let currUser = null;
48 | if (!req.session.user) {
49 | return next()
50 | }
51 | const cookie = req.cookies['user-token'];
52 | if (!cookie) {
53 | req.session.user = null;
54 | return next();
55 | }
56 | currUser = req.session.user;
57 | if (!currUser) {
58 |
59 | }
60 |
61 |
62 | }
63 |
64 | const noSession = (req, res) => {
65 | if(!req.session || req.session.user) {
66 | res.redirect('login');
67 | return;
68 | }
69 | }
70 |
71 | module.exports = {
72 | adminRequired: adminRequired,
73 | loginRequired: loginRequired,
74 | authUser: authUser,
75 | noSession: noSession
76 | }
--------------------------------------------------------------------------------
/app/front/js/router/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by '苏萧' on 2017/7/13.
3 | */
4 | import React from 'react';
5 | // import { Router, Route, hashHistory, browserHistory, Link, IndexLink, IndexRoute, Redirect } from 'react-router';
6 | import { Route, IndexRoute, Redirect } from 'react-router';
7 |
8 | import About from '../components/About';
9 | import Home from '../containers/Home';
10 | import Login from '../containers/Login';
11 | import Register from '../containers/Register';
12 | // import Blog from '../components/Blog';
13 | import App from '../containers/App';
14 | import NotFound from '../components/NotFound'
15 | import { All, Auto, Mongo, Node, Blog } from '../components/Blog';
16 | import { Admin, Users, AdminHome, Article, EditArticle } from '../components/Admin'
17 | import { enterHomePage, leaveHomePage } from '../utils/enterOrLeaveRoute'
18 |
19 | export default (
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 | {/*
42 |
43 | */}
44 |
45 | )
--------------------------------------------------------------------------------
/app/front/js/actions/articles.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: leo
3 | * @Date: 2017-08-14 16:53:31
4 | * @Last Modified by: leo
5 | * @Last Modified time: 2017-10-20 16:59:07
6 | */
7 | import { browserHistory } from 'react-router';
8 | import { Modal } from 'antd';
9 | import * as types from '../constants';
10 | import { get, post } from '../utils/request';
11 |
12 | const fetchRequset = () => ({
13 | type: types.FETCH_REQUEST
14 | })
15 |
16 | const fetchSuccess = (article) => ({
17 | type: types.FETCH_ARTICLES,
18 | article
19 | })
20 |
21 | const fetchAddArticle = (article) => ({
22 | type: types.FETCH_ADD_ARTICLE,
23 | article
24 | })
25 |
26 | const fetchFailure = (error) => ({
27 | type: types.FETCH_FAILURE,
28 | error
29 | })
30 |
31 | const success = () => {
32 | const modal = Modal.success({
33 | title: '添加文章提示',
34 | content: '添加文章成功'
35 | });
36 | setTimeout( () => {
37 | modal.destroy();
38 | browserHistory.push('/admin/article');
39 | }, 2500);
40 | }
41 | // 获取文章列表
42 | export const getArticles = (url) => async (dispatch) => {
43 | try {
44 | await dispatch(fetchRequset())
45 | const data = await get(url);
46 | await dispatch(fetchSuccess(data.message));
47 | } catch (err) {
48 | dispatch(fetchFailure(err));
49 | }
50 | }
51 | // 新增文章
52 | export const addArticle = (url, params) => async (dispatch) => {
53 | try {
54 | await dispatch(fetchRequset())
55 | const response = await post(url, params);
56 | if (response.status === '01') {
57 | success();
58 | }
59 | dispatch(fetchAddArticle(response.message));
60 | // await post(url, params)
61 | // .then( response => {
62 | // console.log(response);
63 | // dispatch(fetchAddArticle(response.message));
64 | // if (response.status === '01') {
65 | // browserHistory.push('/admin/article');
66 | // }
67 | // }
68 | // ).cache(err => dispatch(fetchFailure(err)))
69 | } catch (err) {
70 | dispatch( fetchFailure(err) )
71 | }
72 | };
--------------------------------------------------------------------------------
/webpack/config.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by '苏萧' on 2017/7/11.
3 | */
4 | /**
5 | * 此文件主要定义一些配置常量
6 | * */
7 | // 引入 node.js path 模块
8 | const path = require('path');
9 | // sass-loader 的 配置
10 | exports.sassLoaderSuffix = '?outputStyle=expanded&sourceMap=true&sourceMapContents=true&includePaths[]=./node_modules';
11 | exports.sassLoaderProd = '?outputStyle=expanded';
12 | // 公共文件
13 | exports.vendor = [
14 | 'react',
15 | 'react-dom',
16 | 'react-redux',
17 | 'react-router',
18 | 'react-router-redux',
19 | 'react-tap-event-plugin',
20 | 'redux',
21 | 'redux-thunk',
22 | 'isomorphic-fetch',
23 | 'es6-promise',
24 | 'pure-render-decorator',
25 | 'react-addons-css-transition-group',
26 | 'antd',
27 | 'antd/dist/antd.less'
28 | ];
29 | // css 代码自动补全配置
30 | exports.autoConfig = {
31 | browsers: [
32 | 'ie >= 9',
33 | 'ie_mob >= 10',
34 | 'ff >= 30',
35 | 'chrome >= 34',
36 | 'safari >= 7',
37 | 'opera >= 23',
38 | 'ios >= 7',
39 | 'android >= 4.4',
40 | 'bb >= 10'
41 | ],
42 | cascade: true,
43 | remove: true
44 | };
45 |
46 | // js 压缩 配置
47 | exports.uglifyJsConfig = {
48 | beautify: false, // 不美化输出
49 | compress: {
50 | warnings: false, // 不保留警告
51 | drop_debugger: true, // 不保留调试语句
52 | drop_console: true // 不保留控制台输出信息
53 | },
54 | mangle: { // 跳过这些,不改变命名
55 | except: ['$super', '$', 'exports', 'require']
56 | },
57 | space_colon: false,
58 | comments: false // 不保留注释
59 | };
60 |
61 | // 定义 文件路径 注:文件在 根目录下的 webpack 文件夹下
62 | const ROOT_PATH = path.resolve(__dirname, '../');
63 |
64 | exports.defPath = {
65 | ROOT_PATH: ROOT_PATH,
66 | APP_PATH: path.resolve(ROOT_PATH, 'app'),
67 | STATIC_PATH: path.resolve(ROOT_PATH, 'static'),
68 | DEV_PATH: path.resolve(ROOT_PATH, 'dev'),
69 | BUILD_PATH: path.resolve(ROOT_PATH, 'dist'),
70 | TPL_PATH: path.resolve(ROOT_PATH, 'static/tpl.html'),
71 | ENTRY_PATH: path.resolve(ROOT_PATH, 'app/front/js/index.js'),
72 | ESLINT_PATH: path.resolve(ROOT_PATH, './.eslintrc'),
73 | REQUEST_PATH: path.resolve(ROOT_PATH, 'app/front/js/utils/request')
74 | }
--------------------------------------------------------------------------------
/app/front/js/components/Admin/Users.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by suxiao on 2017/7/19.
3 | */
4 | import React, { Component, PropTypes } from 'react';
5 | import { Table } from 'antd';
6 | import { connect } from 'react-redux';
7 | import { bindActionCreators } from 'redux';
8 |
9 | require('es6-promise').polyfill();
10 | require('isomorphic-fetch');
11 |
12 | // const { ColumnGroup } = Table;
13 |
14 | import * as actions from '../../actions'
15 | @connect(
16 | (state) => ({users: state.users}),
17 | (dispatch) => bindActionCreators({...actions}, dispatch)
18 | )
19 |
20 | export class Users extends Component {
21 |
22 | static propTypes = {
23 | users: PropTypes.object.isRequired,
24 | receiveUsers: PropTypes.func
25 | }
26 |
27 | constructor (props) {
28 | super(props)
29 | }
30 |
31 | componentDidMount() {
32 | this.props.receiveUsers('/api/admin/users');
33 | }
34 |
35 | render() {
36 | const { isFetching, users } = this.props.users;
37 | const columns = [
38 | { title: '用户ID', dataIndex: '_id', key: '_id' },
39 | { title: '用户名', dataIndex: 'username', key: 'username' },
40 | { title: '密码', dataIndex: 'password', key: 'password' },
41 | { title: '是否是管理员', dataIndex: 'admin', key: 'admin' },
42 | { title: '操作',
43 | dataIndex: '',
44 | key: 'x',
45 | render: () =>
46 |
47 | 查看
48 |
49 | 删除
50 |
51 | }
52 | ];
53 | if (!isFetching && users) {
54 | console.log(users);
55 | for (let i=0; i {
57 | if (key !== 'admin') {
58 | users[i].admin = users[i].isAdmin ? '是' : '否';
59 | }
60 | });
61 | }
62 | }
63 | return (
64 |
65 | {
66 | (!isFetching && users) &&
users._id} style={{textAlign: 'center'}} bordered />
67 | }
68 |
69 | )
70 | }
71 | }
--------------------------------------------------------------------------------
/webpack.prod.config.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by "苏萧" on 2017/7/11.
3 | */
4 | const webpackMerge = require("webpack-merge");
5 | const webpack = require("webpack");
6 | const ChunkManifestPlugin = require("chunk-manifest-webpack-plugin");
7 | const ExtractTextPlugin = require("extract-text-webpack-plugin");// 抽取 css,生成单独文件
8 | const WebpackChunkHash = require("webpack-chunk-hash");
9 |
10 | const baseConfig = require("./webpack/base");
11 | const config = require("./webpack/config");
12 | const defPath = config.defPath;
13 | const APP_PATH = defPath.APP_PATH;
14 |
15 | module.exports = webpackMerge(baseConfig(), {
16 | entry: {
17 | app: defPath.ENTRY_PATH,
18 | vendor: config.vendor
19 | },
20 | output: {
21 | path: defPath.BUILD_PATH,
22 | filename: "js/bundle.js?[chunkhash:10]",
23 | publicPath: "http://xxx.xxx", //修改发布地址
24 | chunkFilename: "chunk.js?[chunkhash:10]"
25 | },
26 | modules: {
27 | rules: [
28 | {
29 | test: /\.(scss|sass|css)$/,
30 | include: APP_PATH,
31 | use: ExtractTextPlugin.extract({ // css 单独打包,(2.x 改变很大)
32 | fallback: "style-loader",
33 | use: "css-loader!post-loader!sass-loader" + config.sassLoaderProd
34 | })
35 | },
36 | {
37 | test: /\.(eot|woff|woff2|ttf|svg|png|jpe?g|gif|mp4|webm)(\?\S*)?$/,
38 | include: APP_PATH,
39 | loader: "url-loader?limit=8192&name=imgs/[name].[ext]?[hash:10]"
40 | }
41 | ]
42 | },
43 | plugins: [
44 | new webpack.HashedModeleIdPlugin(),
45 | new WebpackChunkHash(), // 标准webpack chunkhash
46 | new webpack.DefinePlugin({
47 | "process.env.NODE_ENV": JSON.stringify("production")
48 | }),
49 | new webpack.optimize.UglifyJsPlugin(config.uglifyJsConfig),
50 | new webpack.optimize.CommonsChunkPlugin({
51 | names: ["vendor", "manifest"],
52 | filename: "js/[name].js?[chunkhash:10]",
53 | minChunks: Infinity
54 | }),
55 | new ChunkManifestPlugin({
56 | filename: "chunk-manifest.json",
57 | manifestVariable: "webpackManifest"
58 | }),
59 | //css抽取
60 | new ExtractTextPlugin({
61 | filename: "css/styles.css?[contnethash:10]",
62 | disable: false,
63 | allChunks: true
64 | })
65 | ]
66 | });
67 |
68 |
69 |
--------------------------------------------------------------------------------
/app/server/api/register.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by suxiao on 2017/7/18.
3 | */
4 | const express = require('express');
5 | const bcrypt = require('bcrypt');
6 | const router = express.Router();
7 | // const mongoose = require('mongoose')
8 |
9 | const Users = require('../model/users');
10 |
11 | // 统一返回格式
12 |
13 | let responseData;
14 | router.use( (req, res, next) => {
15 | responseData = {
16 | status: '01',
17 | message: ''
18 | }
19 | next();
20 | })
21 |
22 | router.post('/', (req, res, next) => {
23 | console.log(req.body);
24 | try {
25 | const username = req.body.username;
26 | const password = req.body.password;
27 | const repassword = req.body.repassword;
28 | if (username === '') {
29 | responseData = {
30 | status: '02',
31 | message: '用户名不能为空'
32 | }
33 | res.json(responseData);
34 | return;
35 | }
36 | // 密码不能为空
37 | if (password === '') {
38 | responseData.status = '03';
39 | responseData.message = '请设置密码';
40 | res.json(responseData);
41 | return;
42 | }
43 | // 两次输入的密码必须一致
44 | if (password !== repassword) {
45 | responseData.status = '04';
46 | responseData.message = '两次输入的密码不一致';
47 | res.json(responseData);
48 | return;
49 | }
50 |
51 | Users.findOne({username: username}, (err, user) => {
52 | console.log(req.body);
53 | if (err) {
54 | console.log(err)
55 | } else {
56 | if (user) {
57 | responseData.status = '05';
58 | responseData.message = '用户名已经被注册了';
59 | return res.json(responseData);
60 | }
61 | const saltRounds = 10;
62 | bcrypt.genSalt(saltRounds, (err, salt) => {
63 | bcrypt.hash(password, salt, (err, hash) => {
64 | if (err) {
65 | return next(err);
66 | }
67 | const newUser = new Users({
68 | username: username,
69 | password: hash
70 | });
71 | responseData = {
72 | status: '01',
73 | message: '注册成功'
74 | }
75 | newUser.save().then(() => {
76 | res.json(responseData);
77 | });
78 | })
79 | })
80 | }
81 | })
82 | } catch (err) {
83 | next(err)
84 | }
85 |
86 | })
87 |
88 | module.exports = router;
--------------------------------------------------------------------------------
/dev/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
48 |
49 |
50 |
51 |
52 |
53 | Leo
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/app/front/js/components/Admin/EditArticle.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: leo
3 | * @Date: 2017-10-19 17:29:25
4 | * @Last Modified by: leo
5 | * @Last Modified time: 2017-10-19 22:07:56
6 | */
7 | import React from 'react';
8 | import LzEditor from 'react-lz-editor';
9 |
10 | export class EditArticle extends React.Component {
11 | constructor(props) {
12 | super(props);
13 | this.state = {
14 | htmlContent: '',
15 | markdownContent: '## HEAD 2 \n markdown examples \n ``` welcome ```',
16 | responseList: []
17 | }
18 | this.receiveHtml = this.receiveHtml.bind(this);
19 | this.submitArticle = this.submitArticle.bind(this);
20 | }
21 | receiveHtml(content) {
22 | console.log('recieved HTML content', content);
23 | // this.setState({responseList:[]});
24 | }
25 | submitArticle() {
26 | console.log(this.state.htmlContent);
27 | }
28 | render() {
29 | // let policy = '';
30 | const uploadProps = {
31 | action: 'http://v0.api.upyun.com/devopee',
32 | onChange: this.onChange,
33 | listType: 'picture',
34 | fileList: this.state.responseList,
35 | data: (file) => {
36 | // console.log(file);
37 | },
38 | multiple: true,
39 | beforeUpload: this.beforeUpload,
40 | showUploadList: true
41 | }
42 | const { htmlContent } = this.state;
43 | return (
44 |
45 |
54 | {/*
55 | * markdown 实例
56 |
57 |
66 |
67 | */}
68 |
发布
69 |
70 | )
71 | }
72 | }
--------------------------------------------------------------------------------
/static/tpl.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
48 |
49 |
50 |
51 |
52 |
53 | Leo Blog
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/app/front/js/components/Admin/Article.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: leo
3 | * @Date: 2017-08-14 11:38:37
4 | * @Last Modified by: leo
5 | * @Last Modified time: 2017-08-16 14:35:18
6 | */
7 |
8 | import React, { Component, PropTypes } from 'react';
9 | import { Table, Modal } from 'antd';
10 | import { connect } from 'react-redux';
11 | import { bindActionCreators } from 'redux';
12 |
13 | const confirm = Modal.confirm;
14 | // const { ColumnGroup } = Table;
15 |
16 | import * as actions from '../../actions/articles'
17 |
18 | const success = () => {
19 | const modal = Modal.success({
20 | title: '提示',
21 | content: '删除文章成功'
22 | });
23 | setTimeout( () => {
24 | modal.destroy();
25 | browserHistory.push('/admin/article');
26 | }, 1500);
27 | }
28 | @connect(
29 | (state) => ({articles: state.articles}),
30 | (dispatch) => bindActionCreators({...actions}, dispatch)
31 | )
32 |
33 | export class Article extends Component {
34 | constructor (props) {
35 | super(props);
36 | this.showConfirm = this.showConfirm.bind(this);
37 | }
38 |
39 | static propTypes = {
40 | getArticles: PropTypes.func,
41 | articles: PropTypes.object.isRequired
42 | }
43 |
44 | componentDidMount() {
45 | this.props.getArticles('/api/admin/article');
46 | }
47 |
48 | showConfirm() {
49 | confirm({
50 | title: '确认删除此文章?',
51 | content: '删除后无法复原',
52 | onOk() {
53 | console.log('OK');
54 | success();
55 | },
56 | onCancel() {
57 | console.log('cancle');
58 | }
59 | })
60 | }
61 |
62 | render() {
63 | const { isFetching, articles } = this.props.articles;
64 | const columns = [
65 | { title: '文章ID', dataIndex: '_id', key: '_id' },
66 | { title: '文章分类', dataIndex: 'sort', key: 'sort' },
67 | { title: '文章名称', dataIndex: 'title', key: 'title' },
68 | { title: '文章内容', dataIndex: 'content', key: 'content' },
69 | { title: '作者', dataIndex: 'author', key: 'author' },
70 | { title: '创建时间', dataIndex: 'createDate', key: 'createDate' },
71 | { title: '修改时间', dataIndex: 'updateDate', key: 'updateDate' },
72 |
73 | { title: '操作',
74 | dataIndex: '',
75 | key: 'x',
76 | render: () =>
77 |
78 | 编辑
79 |
80 | 删除
81 |
82 | }
83 | ];
84 | return (
85 |
86 |
87 | {
88 | !isFetching ?
users._id} style={{textAlign: 'center'}} bordered /> : null
89 | }
90 |
91 | )
92 | }
93 | }
--------------------------------------------------------------------------------
/app/front/js/containers/Login/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by '苏萧' on 2017/7/13.
3 | */
4 | import React from 'react';
5 | import PureRenderMixin from 'react-addons-pure-render-mixin';
6 |
7 | import '../../../scss/login.scss';
8 | // import Partial from '../partial';
9 | import { Form, Icon, Input, Button, Checkbox } from 'antd';
10 | import { connect } from 'react-redux';
11 | import { bindActionCreators } from 'redux';
12 | import { userFetch } from '../../actions/users';
13 | const FormItem = Form.Item;
14 |
15 | @connect(
16 | (state) => ({userInfo: state.userInfo}),
17 | (dispatch) => bindActionCreators({userFetch}, dispatch)
18 | )
19 | class LoginModel extends React.Component {
20 | constructor(props, context) {
21 | super(props, context);
22 | this.shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this);
23 | }
24 | componentDidMount() {
25 | // To disabled submit button at the beginning.
26 | // this.props.form.validateFields();
27 | }
28 | handleSubmit = (e) => {
29 | e.preventDefault();
30 | this.props.form.validateFields((err, values) => {
31 | if (!err) {
32 | console.log('Received values of form: ', values);
33 | this.props.userFetch('/api/login', values, '/home');
34 | }
35 | });
36 | }
37 | render() {
38 | const { getFieldDecorator } = this.props.form;
39 |
40 | return (
41 |
73 | );
74 | }
75 | }
76 | const Login = Form.create()(LoginModel);
77 | export default Login
--------------------------------------------------------------------------------
/dev-server.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: leo
3 | * @Date: 2017-10-20 17:24:33
4 | * @Last Modified by: leo
5 | * @Last Modified time: 2017-10-20 18:01:35
6 | */
7 | const express = require('express');
8 | const open = require('open');
9 | const path = require('path')
10 | const webpack = require('webpack');
11 | const WebpackDevMiddleware = require('webpack-dev-middleware');
12 | const WebpackHotMiddleware = require('webpack-hot-middleware');
13 | const bodyParser = require('body-parser');
14 | const mongoose = require('mongoose');
15 | const cookieParser = require('cookie-parser');
16 | const cors = require('cors');
17 | const session = require('express-session');
18 | const MongoStore = require('connect-mongo/es5')(session);
19 | // const passport = require('passport');
20 |
21 | const config = require('./webpack.dev.config');
22 | const api = require('./app/server/api');
23 | // const Users = require('./model/users');
24 |
25 | const compiler = webpack(config);
26 | const port = 3333;
27 | const app = express();
28 | // 结合webpack
29 | // 将这个添加到webpack配置文件的入口里面 ?reload=true 设置浏览器是否自动刷新;
30 | const hotMiddlewareScript = 'webpack-hot-middleware/client?path=/__webpack_hmr&timeout=10000&reload=true';
31 | const entries = Object.keys(config.entry);
32 | // 添加热加载信息
33 | entries.forEach((key) => {
34 | config.entry[key].push(hotMiddlewareScript);
35 | })
36 | // 添加插件信息
37 | if(config.plugins === undefined) {
38 | config.plugins = []
39 | }
40 |
41 | // 添加热加载插件
42 | config.plugins.push(
43 | new webpack.optimize.OccurrenceOrderPlugin(),
44 | new webpack.HotModuleReplacementPlugin(),
45 | new webpack.NoEmitOnErrorsPlugin()
46 | )
47 | app.use(WebpackDevMiddleware(compiler, {
48 | publicPath: config.output.publicPath,
49 | quiet: true,
50 | stats: { colors: true }
51 | }));
52 | app.use(WebpackHotMiddleware(compiler, {
53 | log: () => {}
54 | }));
55 |
56 | // 文件位置
57 | app.use(express.static('static'));
58 | app.use(express.static('dist'));
59 | app.use(bodyParser.json());
60 |
61 | // 登录验证
62 | app.use(cookieParser()); // 使用cookie-parser插件,后续代码直接使用req.cookies
63 | app.use(session({
64 | store: new MongoStore({
65 | mongooseConnection: mongoose.connection
66 | }),
67 | secret: 'leo-blog',
68 | resave: true,
69 | saveUninitialized: true,
70 | cookie: {
71 | path: '/'
72 | }
73 | }));
74 |
75 | // 设置跨域访问
76 | app.use(cors());
77 |
78 | app.use('/api', api);
79 | // 解决子路由刷新无法访问的问题
80 | app.get('/*', (req, res, next) => {
81 | // console.log(req.session);
82 | const filename = path.join(config.output.path, 'index.html')
83 | console.log(filename);
84 | compiler.outputFileSystem.readFile(filename, (err, result) => {
85 | if (err) {
86 | return next(err)
87 | }
88 | res.set('content-type', 'text/html');
89 | res.send(result);
90 | res.end();
91 | })
92 | });
93 | // 连接mongodb
94 | mongoose.Promise = global.Promise;
95 | // 使用connect 不要使用createConnection
96 | mongoose.connect('mongodb://localhost:27017/leoBlog', {useMongoClient: true}, (err) => {
97 | if (err) {
98 | console.log(err)
99 | } else {
100 | console.log('==> 数据连接成功');
101 | app.listen(port, (err) => {
102 | if (err) {
103 | console.log(err)
104 | } else {
105 | console.log(`正在打开==>http://localhost:${port}...`);
106 | open(`http://localhost:${port}`);
107 | }
108 | })
109 | }
110 | });
111 |
112 |
113 |
--------------------------------------------------------------------------------
/app/server/api/admin.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by suxiao on 2017/7/19.
3 | */
4 | const express = require('express');
5 | const router = express.Router();
6 |
7 | const Users = require('../model/users');
8 | const Articles = require('../model/articles');
9 |
10 | let responseData;
11 |
12 | router.use( (req, res, next) => {
13 | responseData = {
14 | status: '01',
15 | message: ''
16 | }
17 | next();
18 | });
19 |
20 | router.post('/', async (req, res, next) => {
21 | console.log(req.body);
22 | Users.find({}, (err, users) => {
23 | if (err) {
24 | console.log(err)
25 | } else {
26 | res.send('users')
27 | console.log(users);
28 | }
29 | })
30 | // res.json({
31 | // status: '0',
32 | // message: 'admin'
33 | // })
34 | next();
35 | })
36 |
37 | router.get('/users', async (req, res, next) => {
38 | try {
39 | Users.find({}, (err, users) => {
40 | if (err) {
41 | console.log(err)
42 | } else {
43 | responseData.message = users;
44 | res.json(responseData);
45 | // res.send('users')
46 | console.log('-------users----------');
47 | console.log(users);
48 | }
49 | // res.end();
50 | // next();
51 | })
52 | } catch (err) {
53 | console.log('-------users2222----------');
54 | next(err)
55 | }
56 |
57 | })
58 | // 获取文章
59 | router.get('/article', async (req, res, next) => {
60 | try {
61 | Articles.find({}, (error, article) => {
62 | if (error) {
63 | console.log(error)
64 | } else {
65 | responseData.message = article;
66 | res.json(responseData);
67 | console.log('-----------article-----------');
68 | console.log(article);
69 | console.log('-----------article-----------');
70 | }
71 | })
72 | } catch(err) {
73 | next(err);
74 | }
75 | })
76 | // 新增文章
77 | router.post('/article/add', async (req, res, next) => {
78 | const id = req.body._id;
79 | console.log('-----------article-----------');
80 | const newArtilce = new Articles(req.body);
81 | console.log(newArtilce);
82 | try {
83 | Articles.find({_id: id}, (err, article) => {
84 | if (err) {
85 | console.log(err)
86 | } else {
87 | if (article.length === 0) {
88 | newArtilce.save().then( (ret) => {
89 | console.log(ret);
90 | responseData.message = ret;
91 | res.json(responseData);
92 | }, (error) => {
93 | responseData.message = error;
94 | res.json(responseData)
95 | })
96 | }
97 | }
98 | })
99 | } catch(err) {
100 | next(err);
101 | }
102 | })
103 | // 更新文章
104 | router.put('/article/update/:id', async (req, res, next) => {
105 | try {
106 | Articles.findOneAndUpdate({_id: req.params.id}, req.body, (error, article) => {
107 | if (error) {
108 | console.log(error)
109 | } else {
110 | res.json(article);
111 | console.log(article);
112 | }
113 | })
114 | } catch(err) {
115 | next(err);
116 | }
117 | })
118 |
119 | // 删除文章
120 |
121 | router.post('/article/delete/:id', async (req, res, next) => {
122 | try {
123 | Articles.findOneAndRemove({_id: req.params.id}, req.body, (error, article) => {
124 | if (error) {
125 | console.log(error)
126 | } else {
127 | res.json(article);
128 | console.log(article);
129 | }
130 | })
131 | } catch(err) {
132 | next(err);
133 | }
134 | })
135 |
136 | module.exports = router;
--------------------------------------------------------------------------------
/app/front/js/components/Admin/AdminHome.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by suxiao on 2017/7/24.
3 | */
4 | import React, { Component } from 'react';
5 | import { Form, Input, Button, Select } from 'antd';
6 | const FormItem = Form.Item;
7 | const { Option } = Select;
8 | const { TextArea } = Input;
9 | import { connect } from 'react-redux';
10 | import { bindActionCreators } from 'redux';
11 |
12 | // const { ColumnGroup } = Table;
13 |
14 | import * as actions from '../../actions/articles'
15 |
16 | @connect(
17 | (state) => ({articles: state.articles}),
18 | (dispatch) => bindActionCreators({...actions}, dispatch)
19 | )
20 |
21 | class Home extends Component {
22 | constructor() {
23 | super();
24 | this.state = {
25 | formLayout: 'horizontal'
26 | };
27 | }
28 | handleSubmit = (e) => {
29 | e.preventDefault();
30 | this.props.form.validateFieldsAndScroll((err, values) => {
31 | if (!err) {
32 | console.log('Received values of form: ', values);
33 | this.props.addArticle('/api/admin/article/add', values);
34 | // if (!this.props.articles.isFetching) {
35 | // success();
36 | // }
37 | // const promise = new Promise( (respones, reject) => {
38 | // this.props.addArticle('/api/admin/article/add', values);
39 | // if (true) {
40 | // resolve(value)
41 | // }
42 | // });
43 | // // this.props.addArticle('/api/admin/article/add', values);
44 | // promise.then( (value) => {
45 | // console.log(value);
46 | // })
47 | } else {
48 | console.log(err);
49 | }
50 | });
51 | }
52 | render() {
53 | const { formLayout } = this.state;
54 | const { getFieldDecorator } = this.props.form;
55 | const formItemLayout = formLayout === 'horizontal' ? {
56 | labelCol: { span: 4 },
57 | wrapperCol: { span: 14 }
58 | } : null;
59 | const buttonItemLayout = formLayout === 'horizontal' ? {
60 | wrapperCol: { span: 14, offset: 4 }
61 | } : null;
62 | return (
63 |
64 |
65 |
107 |
108 | )
109 | }
110 | }
111 |
112 | export const AdminHome = Form.create()(Home);
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-express-mongodb",
3 | "version": "1.0.0",
4 | "description": "try first node-express-monggodb-react",
5 | "main": "index.js",
6 | "directories": {
7 | "test": "test"
8 | },
9 | "scripts": {
10 | "server": "node dev-server.js",
11 | "start": "webpack-dev-server --progress --colors --config webpack.dev.config.js",
12 | "dev": "webpack --progress --colors --config webpack.dev.config.js",
13 | "build": "cross-env NODE_ENV='production' webpack -p --progress --profile --colors --config webpack.prod.config.js",
14 | "eslint": "eslint app --ext .js --cache --fix",
15 | "test": "echo \"Error: no test specified\" && exit 1"
16 | },
17 | "pre-commit": [
18 | "eslint"
19 | ],
20 | "repository": {
21 | "type": "git",
22 | "url": "git+https://github.com/suxiaoX/react-express-mongodb.git"
23 | },
24 | "author": "leo",
25 | "license": "ISC",
26 | "devDependencies": {
27 | "autoprefixer": "^6.7.6",
28 | "babel-core": "^6.23.1",
29 | "babel-eslint": "^7.1.1",
30 | "babel-loader": "^6.4.0",
31 | "babel-plugin-transform-decorators-legacy": "^1.3.4",
32 | "babel-plugin-transform-object-assign": "^6.22.0",
33 | "babel-plugin-transform-runtime": "^6.23.0",
34 | "babel-preset-es2015": "^6.22.0",
35 | "babel-preset-react": "^6.23.0",
36 | "babel-preset-stage-2": "^6.22.0",
37 | "chunk-manifest-webpack-plugin": "^1.0.0",
38 | "cookies": "^0.7.0",
39 | "copy-webpack-plugin": "^4.2.0",
40 | "cross-env": "^3.2.3",
41 | "css-loader": "^0.26.2",
42 | "eslint": "^3.17.1",
43 | "eslint-config-airbnb": "^16.1.0",
44 | "eslint-loader": "^1.6.3",
45 | "eslint-plugin-jsdoc": "^2.4.0",
46 | "eslint-plugin-jsx-a11y": "^6.0.2",
47 | "eslint-plugin-react": "^6.10.0",
48 | "extract-text-webpack-plugin": "^2.1.0",
49 | "file-loader": "^0.10.1",
50 | "html-webpack-plugin": "^2.28.0",
51 | "imports-loader": "^0.7.1",
52 | "ip": "^1.1.5",
53 | "json-server": "^0.9.6",
54 | "less": "^2.7.2",
55 | "less-loader": "^4.0.5",
56 | "node-sass": "^4.5.0",
57 | "postcss-flexbugs-fixes": "^3.0.0",
58 | "postcss-loader": "^1.3.3",
59 | "pre-commit": "^1.2.2",
60 | "react-hot-loader": "^3.0.0-beta.6",
61 | "redux-logger": "^3.0.6",
62 | "sass-loader": "^6.0.2",
63 | "style-loader": "^0.13.2",
64 | "url-loader": "^0.5.8",
65 | "webpack": "^2.2.1",
66 | "webpack-chunk-hash": "^0.4.0",
67 | "webpack-dev-server": "^2.4.1",
68 | "webpack-hot-middleware": "^2.18.2",
69 | "webpack-md5-hash": "0.0.5",
70 | "webpack-merge": "^4.0.0"
71 | },
72 | "dependencies": {
73 | "antd": "^2.12.0",
74 | "babel-plugin-import": "^1.4.0",
75 | "babel-runtime": "^6.23.0",
76 | "bcrypt": "^1.0.2",
77 | "connect-mongo": "^1.3.2",
78 | "cookie-parser": "^1.4.3",
79 | "copy-webpack-plugin": "^4.2.0",
80 | "crypto": "^1.0.1",
81 | "es6-promise": "^4.0.5",
82 | "express-session": "^1.15.5",
83 | "isomorphic-fetch": "^2.2.1",
84 | "open": "^0.0.5",
85 | "passport": "^0.4.0",
86 | "passport-local": "^1.0.0",
87 | "pure-render-decorator": "^1.2.1",
88 | "react": "^15.4.2",
89 | "react-addons-css-transition-group": "^15.4.2",
90 | "react-addons-pure-render-mixin": "^15.6.2",
91 | "react-dom": "^15.4.2",
92 | "react-lz-editor": "^0.11.5",
93 | "react-quill": "^1.1.0",
94 | "react-redux": "^5.0.3",
95 | "react-router": "^3.0.2",
96 | "react-router-dom": "^4.1.1",
97 | "react-router-redux": "^4.0.8",
98 | "react-tap-event-plugin": "^2.0.1",
99 | "redux": "^3.6.0",
100 | "redux-actions": "^2.2.1",
101 | "redux-form": "^7.0.0",
102 | "redux-thunk": "^2.2.0",
103 | "timestamps": "^0.1.3"
104 | },
105 | "bugs": {
106 | "url": "https://github.com/suxiaoX/react-express-mongodb/issues"
107 | },
108 | "homepage": "https://github.com/suxiaoX/react-express-mongodb#readme"
109 | }
110 |
--------------------------------------------------------------------------------
/webpack.dev.config.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by "苏萧" on 2017/7/11.
3 | */
4 |
5 | const webpackMerge = require("webpack-merge");
6 | const webpack = require("webpack");
7 | const ChunkManifestPlugin = require("chunk-manifest-webpack-plugin");
8 | const CopyWebpackPlugin = require("copy-webpack-plugin"); // 拷贝文件插件
9 | const ip = require("ip").address();
10 |
11 | const baseConfig = require("./webpack/base");
12 | const config = require("./webpack/config");
13 | const defPath = config.defPath;
14 | const APP_PATH = defPath.APP_PATH;
15 |
16 | // 使用 `webpack-merge` 将基础配置和新配置合并
17 | module.exports = webpackMerge(baseConfig(), {
18 | devtool: "cheap-module-source-map",// 增强浏览器调试
19 | entry: {
20 | app: [// 热加载配置
21 | "react-hot-loader/patch",
22 | "webpack-dev-server/client?http://" + ip + ":8099/",
23 | "webpack/hot/only-dev-server",
24 | "./app/front/js/index.js"
25 | ],
26 | vendor: config.vendor // 公共文件单独打包
27 | },
28 | output: {
29 | path: defPath.DEV_PATH,// 所有输出文件的目标路径
30 | filename: "js/[name].js",
31 | publicPath: "/", // 必须写,且与 devServer 的 publicPath 保持一致
32 | chunkFilename: "[name].chunk.js" // 分块文件命名
33 | },
34 | module: {
35 | rules: [
36 | {
37 | test: /\.(scss|sass|css)$/,
38 | include: APP_PATH, // 必须匹配选项
39 | use: [ // 2.x 版本改为 use 代替 loaders,必须加 -loader
40 | "style-loader", "css-loader", "postcss-loader", "sass-loader" + config.sassLoaderSuffix
41 | ]
42 | },
43 | {
44 | test: /\.css$/,
45 | use: [
46 | "style-loader", "css-loader", "postcss-loader"
47 | ]
48 | },
49 | {
50 | test: /\.(png|jpe?g|gif|mp4|webm)$/,
51 | include: APP_PATH,
52 | loader: "url-loader?limit=8192&name=imgs/[name].[ext]"
53 | },
54 | {
55 | test: /\.(eot|woff|ttf|woff2|svg)$/,
56 | use: 'url-loader'
57 | }
58 | ]
59 | },
60 | plugins: [
61 | // 热模块替换相关插件
62 | new webpack.HotModuleReplacementPlugin(),
63 | new webpack.NamedModulesPlugin(),
64 | // 定义环境变量
65 | new webpack.DefinePlugin({
66 | "process.env.NODE_ENV": JSON.stringify("development")
67 | }),
68 |
69 | /*
70 | 公用模块单独打包,对应 入口文件 vendor,
71 | 持久化缓存配置
72 | */
73 |
74 | new webpack.optimize.CommonsChunkPlugin({
75 | names: [// 提取公共模块名称
76 | "vendor", "manifest" // manifest 用于分离 webpack runtime
77 | ],
78 | filename: "js/[name].js", // 公共模块文件名
79 | minChunks: Infinity // Infinity 表示仅仅创建公共组件块,不会把任何modules打包进去。
80 | }),
81 | // new ChunkManifestPlugin({ // 将 manifest 提取到一个单独的 JSON 文件中
82 | // filename: "chunk-manifest.json",
83 | // manifestVariable: "webpackManifest" // 全局变量的名称,webpack 将利用它查找 manifest JSON 对象
84 | // })
85 | ],
86 |
87 | devServer: { // 开启服务器
88 | contentBase: defPath.DEV_PATH,// 开启服务的路径
89 | publicPath: "/",
90 | historyApiFallback: true,// 设置可以从任意URL 访问
91 | clientLogLevel: "none",
92 | host: ip,
93 | // host: 'localhost',
94 | port: 8099,
95 | open: true,// 服务开启的时候打开页面
96 | hot: true,// 开启热替换
97 | inline: true,// 开启热加载
98 | compress: true,
99 | stats: {
100 | colors: true,
101 | errors: true,
102 | warnings: true,
103 | modules: false,
104 | chunks: false
105 | },
106 | /*
107 | overlay: { // 报错和警告在页面显示
108 | errors: true,
109 | warnings: true,
110 | },
111 | */
112 | //解决跨域
113 | proxy: {
114 | "/api/*": {
115 | target: `http://${ip}:3333`,
116 | secure: false, //接受运行在 https 上的服务
117 | changeOrigin: true
118 | }
119 | }
120 |
121 | //使用的url 必须以 / 开始 否则不会代理到指定地址
122 | /**
123 | * --实例使用方法--
124 | * fetch("/api/space").then(res => {
125 | // 被代理到 http://${ip}:3333/api/space
126 | return res.json();
127 | }).then(res => {
128 | console.log(res);
129 | })
130 | * */
131 | }
132 |
133 | });
134 |
--------------------------------------------------------------------------------
/webpack/base.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by "苏萧" on 2017/7/11.
3 | */
4 | /**
5 | * 定义公共的配置
6 | * --常用插件--
7 | * html-webpack-plugin 按照模板生成 HTML,动态添加 js 和 css,(2.x没有变化)
8 | * webpack-merge 非插件,用于将两个 webpack 配置文件合并为一个,(2.x新增)
9 | * extract-text-webpack-plugin 抽取 CSS 模块 生成单独文件,(2.x写法有变化)
10 | * chunk-manifest-webpack-plugin 配合 webpack.optimize.CommonsChunkPlugin,将 manifest 提取到一个单独的json 文件中,解决长效缓存的问题
11 | * webpack-md5-hash 使生成的 hash 值 是基于文件内容的
12 | * webpack.optimize.CommonsChunkPlugin 用于提取公共模块,单独打包成一个文件,(2.x写法略有不同)
13 | * webpack.DefinePlugin 用于定义环境变量,(2.x没有变化)
14 | * webpack.LoaderOptionsPlugin 代替 1.x 版本中 loader 的扩展配置功能,(2.x新增)
15 | * webpack.optimize.UglifyJsPlugin js 代码压缩,(2.x更改了默认配置)
16 | * webpack.HotModuleReplacementPlugin 开启全局的模块热替换(HMR)
17 | * webpack.NamedModulesPlugin 当模块热替换(HMR)时在浏览器控制台输出对用户更友好的模块名字信息
18 | * copy-webpack-plugin 文件拷贝
19 | * */
20 |
21 | const webpack = require("webpack");
22 | const autoprefixer = require("autoprefixer");// css3 前缀自动补全
23 | const HtmlWebpackPlugin = require("html-webpack-plugin");// 自动生成 HTML
24 | const CopyWebpackPlugin = require('copy-webpack-plugin');
25 |
26 | const config = require("./config");//引入配置
27 | const api = require("./api");
28 | const defPath = config.defPath;
29 | const APP_PATH = defPath.APP_PATH;//源码位置
30 |
31 | module.exports = function () {
32 | return {
33 | context: defPath.ROOT_PATH, //设置根目录为执行环境
34 | resolve: { //解析模块请求的选项
35 | //用于查找的模块目录
36 | modules: [
37 | APP_PATH,
38 | "node_modules"
39 | ],
40 | // 使用的扩展名 自动解析确定的扩展,能够使用户在引入时不带扩展
41 | extensions: [".js", ".jsx", ".json", ".css"]
42 | },
43 | cache: true, //启用缓存
44 | module: {
45 | rules: [
46 | {
47 | enforce: "pre",//前置执行 "pre"|"post" 表示 loader 的前置和后置
48 | test: /\.(js|jsx)$/,
49 | include: APP_PATH,
50 | loader: ["babel-loader", "eslint-loader"],
51 | options: {
52 | configFile: defPath.ESLINT_PATH //指定eslint的配置文件路径
53 | }
54 | },
55 | {
56 | test: /\.(js|jsx)$/, // 如果项目中只用到了JS后缀,那么就只写JS,避免文件搜索范围过大
57 | include: APP_PATH,
58 | loader: "babel-loader?cacheDirectory" // babel缓存打开,避免编译耗时过多
59 | },
60 | {
61 | test: /\.less$/,
62 | use: [
63 | require.resolve('style-loader'),
64 | require.resolve('css-loader'),
65 | {
66 | loader: require.resolve('postcss-loader'),
67 | options: {
68 | ident: 'postcss', // https://webpack.js.org/guides/migrating/#complex-options
69 | plugins: () => [
70 | require('postcss-flexbugs-fixes'),
71 | autoprefixer({
72 | browsers: [
73 | '>1%',
74 | 'last 4 versions',
75 | 'Firefox ESR',
76 | 'not ie < 9', // React doesn't support IE8 anyway
77 | ],
78 | flexbox: 'no-2009',
79 | }),
80 | ],
81 | },
82 | },
83 | {
84 | loader: require.resolve('less-loader'),
85 | options: {
86 | modifyVars: { "@primary-color": "#ff6600" },
87 | },
88 | },
89 | ],
90 | },
91 | { // 向应用特定文件中注入变量,应用中可以直接使用 baseUrl
92 | test: require.resolve(defPath.REQUEST_PATH),
93 | loader: "imports-loader?baseUrl=>" + JSON.stringify( api[process.env.NODE_ENV || "development"] )
94 | }
95 | ]
96 | },
97 | plugins: [
98 | // autoprefixer 是 postcss-loader 的 插件,需要在这里进行 autoprefixer 插件的配置
99 | new webpack.LoaderOptionsPlugin({
100 | options: {
101 | context: "/",
102 | minimize: true,
103 | postcss: [autoprefixer(config.autoConfig)]
104 | }
105 | }),
106 | new CopyWebpackPlugin([{
107 | from: defPath.STATIC_PATH
108 | }]),
109 | // 依照模板生成 html
110 | new HtmlWebpackPlugin({
111 | // favicon: '../static/favicon/favicon.ico',
112 | template: defPath.TPL_PATH,
113 | title: "LeoBlog",
114 | filename: "index.html",
115 | inject: "body",
116 | minify: {
117 | removeComments: true
118 | },
119 | cache: false
120 | })
121 | ]
122 | }
123 | };
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/app/server/api/login.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by suxiao on 2017/7/17.
3 | */
4 | const express = require('express');
5 | const bcrypt = require('bcrypt');
6 | const router = express.Router();
7 | // const passport = require('passport');
8 | // const LocalStrategy = require('passport-local').Strategy;
9 | // const crypto = require('crypto');
10 | // const bcrypt = require('bcrypt');
11 | // passport 不适合做单页面的验证,多页面适合用passport。
12 | const Users = require('../model/users');
13 | // 统一返回格式
14 | let responseData;
15 | router.use( (req, res, next) => {
16 | responseData = {
17 | status: '01',
18 | message: ''
19 | }
20 | next();
21 | })
22 | /*
23 | passport.use(new LocalStrategy({
24 | _usernameFiled: 'username',
25 | _passwordFiled: 'password',
26 | passReqToCallback: true
27 | }, (req, username, password, done) => {
28 | Users.findOne({username: username, password: password}, (err, user) => {
29 | console.log(user);
30 | if (err) {
31 | console.log(err);
32 | return done(err);
33 | } else {
34 | if (!user) {
35 | responseData = {
36 | status: '03',
37 | message: '用户名或密码错误'
38 | }
39 | return done(null, false, responseData);
40 | } else {
41 | responseData = {
42 | status: '01',
43 | message: '登录成功',
44 | userInfo: user.username
45 | }
46 | console.log(responseData);
47 | // const userObj = user.toObject();
48 | // bcrypt.compare(password, userObj.passport, (err, res) => {
49 |
50 | // })
51 | console.log(done);
52 | return done(null, user);
53 | // res.json(responseData);
54 | }
55 | }
56 | })
57 | }))
58 |
59 | passport.serializeUser((user, done) => {
60 | done(null, user)
61 | })
62 |
63 | passport.deserializeUser((user, done) => {
64 | done(user, user)
65 | })
66 |
67 | const options = {
68 | successRedirect: '/home',
69 | successFlash: true,
70 | failureRedirect: '/sign',
71 | failureFlash: true
72 | }
73 |
74 | router.post('/', passport.authenticate('local', options), (req, res, next) => {
75 | console.log(1111);
76 | res.json(responseData);
77 | })
78 | */
79 | // 登录
80 |
81 | router.post('/', (req, res, next) => {
82 | console.log(req.body);
83 | try {
84 | const username = req.body.username;
85 | const password = req.body.password;
86 |
87 | if ( username === '' || password === '' ) {
88 | responseData = {
89 | status: '02',
90 | message: '用户名或密码不能为空'
91 | }
92 | return res.json(responseData);
93 | }
94 | Users.findOne({ username: username }, (err, user) => {
95 | if (err) {
96 | console.log(err)
97 | } else {
98 | if (!user) {
99 | responseData = {
100 | status: '03',
101 | message: '用户名或密码错误'
102 | }
103 | return res.json(responseData);
104 | }
105 | bcrypt.compare(password, user.password, (err, responese) => {
106 | if (err){
107 | return next(err);
108 | }
109 | if (responese === false) {
110 | responseData = {
111 | status: '04',
112 | message: '用户名或密码错误'
113 | }
114 | return res.json(responseData);
115 | }
116 | responseData = {
117 | status: '01',
118 | message: '登录成功',
119 | userInfo: user.username
120 | }
121 | // req.session.user = {
122 | // id: user._id,
123 | // username: user.username
124 | // };
125 | // console.log(req.session);
126 | // res.cookie('userInfo', {responseData}, {
127 | // path: '/',
128 | // maxAge: 1000 * 60 * 60 * 24 * 30,
129 | // httpOnly: true
130 | // });
131 | return res.json(responseData);
132 |
133 | })
134 | // req.session.regenerate( (err) => {
135 | // if (err) {
136 | // console.log(err)
137 | // responseData = {
138 | // status: '05',
139 | // message: '登录失败'
140 | // }
141 | // return res.json({responseData})
142 | // }
143 | // responseData = {
144 | // status: '01',
145 | // message: '登录成功',
146 | // userInfo: user.username
147 | // }
148 | // req.cookies.set('userInfo', JSON.stringify({
149 | // id: user._id,
150 | // username: user.username
151 | // }))
152 | // req.session.user = {
153 | // username: user.username,
154 | // id: user._id
155 | // };
156 | // console.log(req.session.user);
157 | // return res.json(responseData);
158 |
159 | // });
160 | // res.json(responseData);
161 | }
162 | })
163 | } catch (error) {
164 | next(error)
165 | }
166 | })
167 |
168 | module.exports = router;
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | // 规则: 0 代表忽略 off 1 只警告通过校验 warning 2 报错并需要修改才能通过校验 error
2 | {
3 | // 引入轮子 Airbnb的验证规则-- 这里有冲突,暂时不引入
4 | // "extends": "airbnb",
5 | "plugins": [
6 | "react", "jsdoc"
7 | ],
8 | "parser": "babel-eslint",
9 | "parserOptions": {
10 | "ecmaVersion": 6,
11 | "ecmaFeatures": {
12 | "jsx": true,
13 | "experimentalObjectRestSpread": true
14 | }
15 | },
16 | "env": {
17 | "browser": true,
18 | "node": true,
19 | "es6": true
20 | },
21 | // 以当前目录为根目录,不在往上查找
22 | "root": true,
23 | "rules": {
24 | // Common js rules
25 | // 禁止将await写在循环里,因为这样就无法同时发送多个一部请求了
26 | "no-await-in-loop": "off",
27 | // 强制在代码块中使用一致的大括号风格
28 | "brace-style": [2, "1tbs", { "allowSingleLine": true }],
29 | // 强制使用骆驼拼写法命名约定
30 | "camelcase": 2,
31 | // 强制所有控制语句使用一致的括号风格
32 | "curly": 2,
33 | // 要求使用 === 和 !==
34 | "eqeqeq": 2,
35 | // 禁止扩展原生类型
36 | "no-extend-native": 2,
37 | // 禁用 __proto__ 属性
38 | "no-proto": 2,
39 | // 禁用 arguments.caller 或 arguments.callee
40 | "no-caller": 2,
41 | // 禁止出现未使用过的变量
42 | "no-unused-vars": [2, { "vars": "all", "args": "none" }],
43 | // 要求构造函数首字母大写
44 | "new-cap": 0,
45 | // 强制使用一致的反勾号、双引号或单引号 这里是单引号
46 | "quotes": [2, "single"],
47 | // 强制可嵌套的块的最大深度
48 | "max-depth": [2, 3],
49 | // 强制函数块最多允许的的语句数量
50 | "max-statements": [2, 45],
51 | // 强制每一行中所允许的最大语句数量
52 | "max-statements-per-line": [2, { "max": 2 }],
53 | // 强制一行的最大长度
54 | "max-len": [2, 200],
55 | // 禁止在没有类型检查操作符的情况下与 null 进行比较
56 | "no-eq-null": 2,
57 | // 强制操作符使用一致的换行符
58 | "operator-linebreak": 2,
59 | // 禁止出现多行空行
60 | "no-multiple-empty-lines": [2, { "max": 2 }],
61 | // 禁止空格和 tab 的混合缩进
62 | "no-mixed-spaces-and-tabs": 0,
63 | // 强制在一元操作符前后使用一致的空格
64 | "space-unary-ops": 2,
65 | // 禁止使用多个空格
66 | "no-multi-spaces": 2,
67 | // 强制在块之前使用一致的空格
68 | "space-before-blocks": 0,
69 | // 强制在关键字前后使用一致的空格
70 | "keyword-spacing": 0,
71 | // 要求操作符周围有空格
72 | "space-infix-ops": 0,
73 | // 强制在逗号前后使用一致的空格
74 | "comma-spacing": [2, { "before": false, "after": true }],
75 | // 要求或禁止末尾逗号
76 | "comma-dangle": 2,
77 | // 要求 IIFE 使用括号括起来
78 | "wrap-iife": 2,
79 | // 禁止不必要的分号
80 | "no-extra-semi": 2,
81 | // 强制分号之前和之后使用一致的空格
82 | "semi-spacing": 2,
83 | // 强制在注释中 // 或 /* 使用一致的空格
84 | "spaced-comment": 2,
85 | // 要求或禁止使用命名的 function 表达式
86 | "func-names": 0,
87 |
88 | // NodeJs rules
89 | "block-scoped-var": 2,
90 | // 要求 require() 出现在顶层模块作用域中
91 | "global-require": 0,
92 | // 禁止混合常规变量声明和 require 调用
93 | "no-mixed-requires": 2,
94 | // 禁止调用 require 时使用 new 操作符
95 | "no-new-require": 2,
96 | // 禁止对 __dirname 和 __filename 进行字符串连接
97 | "no-path-concat": 2,
98 | // 禁止使用console
99 | "no-console": 1,
100 | "no-alert": 0,
101 | // 要求使用 isNaN() 检查 NaN
102 | "use-isnan": 2,
103 | // 禁止 if 语句中 return 语句之后有 else 块
104 | "no-else-return": 2,
105 | // 禁止 case 语句落空
106 | "no-fallthrough": 2,
107 | // 禁止多次声明同一变量
108 | "no-redeclare": 2,
109 |
110 | // ES6 rules 上面是说明,下面是设置
111 | // 强制箭头函数的箭头前后使用一致的空格
112 | "arrow-spacing": 2,
113 | // 禁止修改 const 声明的变量
114 | "no-const-assign": 2,
115 | // 禁止修改类声明的变量
116 | "no-class-assign": 2,
117 | // 禁止类成员中出现重复的名称
118 | "no-dupe-class-members": 2,
119 | // 禁止在构造函数中,在调用 super() 之前使用 this 或 super
120 | "no-this-before-super": 2,
121 | // 要求使用 let 或 const 而不是 var
122 | "no-var": 2,
123 | // 建议使用箭头函数作为回调
124 | "prefer-arrow-callback": 1,
125 | // 要求箭头函数体使用大括号
126 | "arrow-body-style": 0,
127 | // 建议箭头函数的参数使用圆括号
128 | "arrow-parens": 1,
129 | // 要求使用模板字面量而非字符串连接
130 | "prefer-template": 2,
131 | // 要求使用 const 声明那些声明后不再被修改的变量
132 | "prefer-const": 2,
133 |
134 | // React语法规则
135 | // 强制在 JSX 属性中使用一致的单引号或双引号
136 | "jsx-quotes": [2, "prefer-double"],
137 | // style 属性的取值必须是 object
138 | "react/style-prop-object": "error",
139 | // react的PropTypes定义,一般是2
140 | "react/prop-types": [1],
141 | // 禁止使用数组的 index 作为 key
142 | "react/no-array-index-key": 0,
143 | // jsx 文件必须 import React
144 | "react/jsx-uses-react": 1,
145 | // 数组中的 jsx 必须有 key
146 | "react/jsx-key": "error",
147 | // 定义了的 jsx element 必须使用
148 | "react/jsx-uses-vars": 2,
149 | // 禁止使用未定义的 jsx elemet
150 | "react/jsx-no-undef": "error",
151 | // 禁止使用 pascal 写法的 jsx,比如
152 | "react/jsx-pascal-case": "error",
153 | // 禁止出现重复的 props
154 | "react/jsx-no-duplicate-props": "error",
155 | // 禁止在 componentDidUpdate 里面使用 setState 一般要打开
156 | "react/no-did-update-set-state": "off",
157 | // 禁止直接修改 this.state
158 | "react/no-direct-mutation-state": "error",
159 | // 禁止在 componentWillUpdate 中使用 setState 一般要打开
160 | "react/no-will-update-set-state": "off",
161 | // 必须使用 Class 的形式创建组件
162 | "react/prefer-es6-class": [
163 | "error",
164 | "always"
165 | ]
166 | }
167 | }
168 |
--------------------------------------------------------------------------------
/app/server/server.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by '苏萧' on 2017/7/13.
3 | */
4 | const express = require('express');
5 | const open = require('open');
6 | const path = require('path')
7 | const webpack = require('webpack');
8 | const WebpackDevMiddleware = require('webpack-dev-middleware');
9 | const WebpackHotMiddleware = require('webpack-hot-middleware');
10 | const bodyParser = require('body-parser');
11 | const mongoose = require('mongoose');
12 | // const Cookies = require('cookies');
13 | const cookieParser = require('cookie-parser');
14 | const cors = require('cors');
15 | const session = require('express-session');
16 | const MongoStore = require('connect-mongo/es5')(session);
17 | // const passport = require('passport');
18 |
19 | const config = require('../../webpack.dev.config');
20 | const api = require('./api');
21 | // const Users = require('./model/users');
22 |
23 | const compiler = webpack(config);
24 | const port = 3333;
25 | const app = express();
26 | // const Router = express.Router();
27 | // 结合webpack
28 | // 将这个添加到webpack配置文件的入口里面 ?reload=true 设置浏览器是否自动刷新;
29 | const hotMiddlewareScript = 'webpack-hot-middleware/client?path=/__webpack_hmr&timeout=10000&reload=true';
30 | const entries = Object.keys(config.entry);
31 | // 添加热加载信息
32 | entries.forEach((key) => {
33 | config.entry[key].push(hotMiddlewareScript);
34 | })
35 | // 添加插件信息
36 | if(config.plugins === undefined) {
37 | config.plugins = []
38 | }
39 |
40 | // 添加热加载插件
41 | config.plugins.push(
42 | new webpack.optimize.OccurrenceOrderPlugin(),
43 | new webpack.HotModuleReplacementPlugin(),
44 | new webpack.NoEmitOnErrorsPlugin()
45 | )
46 | app.use(WebpackDevMiddleware(compiler, {
47 | publicPath: config.output.publicPath,
48 | quiet: true,
49 | stats: { colors: true }
50 | }));
51 | app.use(WebpackHotMiddleware(compiler, {
52 | log: () => {}
53 | }));
54 |
55 | // 文件位置
56 | app.use(express.static('static'));
57 | app.use(express.static('dist'));
58 | app.use(bodyParser.urlencoded( {extended: true}));
59 | app.use(bodyParser.json());
60 |
61 | // 登录验证
62 | app.use(cookieParser()); // 使用cookie-parser插件,后续代码直接使用req.cookies
63 | app.use(session({
64 | store: new MongoStore({
65 | mongooseConnection: mongoose.connection
66 | }),
67 | secret: 'leo-blog',
68 | resave: true,
69 | saveUninitialized: true,
70 | cookie: {
71 | path: '/'
72 | }
73 | }));
74 | /*
75 | * 验证登录,不过passport多用于多页面验证,所以这里不适用,自己写一个中间件实现吧
76 | app.use(passport.initialize());
77 | app.use(passport.session());
78 |
79 | function isAuthenticated(req, res, next) {
80 | console.log(req.isAuthenticated());
81 | if (req.isAuthenticated()) {
82 | return next()
83 | } else {
84 | // res.json({ status: '02', message: '请先登录' });
85 | res.redirect('/sign');
86 | }
87 | }
88 | // 后台权限
89 | app.get('/admin', isAuthenticated, async (req, res) => {
90 | console.log(req.session.user);
91 |
92 | const filename = path.join(config.output.path, 'index.html')
93 | compiler.outputFileSystem.readFile(filename, (err, result) => {
94 | if (err) {
95 | return next(err)
96 | }
97 | res.set('content-type', 'text/html');
98 | res.send(result);
99 | res.end();
100 | })
101 | })
102 | */
103 | // 设置跨域访问
104 | app.use(cors());
105 | /*
106 | app.all('*', (req, res, next) => {
107 | res.header("Access-Control-Allow-Origin", "*");
108 | res.header("Access-Control-Allow-Headers", "X-Requested-With");
109 | res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
110 | res.header("X-Powered-By",' 3.2.1')
111 | res.header("Content-Type", "application/json;charset=utf-8");
112 | if ( req.method === 'OPTIONS' ) {
113 | res.send(200);
114 | } else {
115 | next();
116 | }
117 | });
118 | */
119 | // 设置cookie
120 | // app.use( (req, res, next) => {
121 | // req.cookies = new Cookies(req, res);
122 | // // console.log(req.cookies.get('userInfo'))
123 | // req.userInfo = {};
124 | // if (req.cookies.get('userInfo')) {
125 | // try {
126 | // req.userInfo = JSON.parse(req.cookies.get('userInfo'));
127 | // // 获取当前登录用户的类型,是否是管理员
128 | // // Users.findById(req.userInfo._id).then(function(userInfo) {
129 | // // req.userInfo.isAdmin = Boolean(userInfo.isAdmin);
130 | // // next();
131 | // // })
132 | // }catch(err){
133 | // console.log(err);
134 | // }
135 | // } else {
136 | // next();
137 | // }
138 | // })
139 |
140 | app.use('/api', api);
141 | // Router.route('/',(req, res) => {
142 | // res.send('hello world')
143 | // });
144 | // 解决子路由刷新无法访问的问题
145 | app.get('/*', (req, res, next) => {
146 | console.log(req.session);
147 | const filename = path.join(config.output.path, 'index.html')
148 | console.log(filename);
149 | compiler.outputFileSystem.readFile(filename, (err, result) => {
150 | if (err) {
151 | return next(err)
152 | }
153 | res.set('content-type', 'text/html');
154 | res.send(result);
155 | res.end();
156 | })
157 | // res.sendFile(path.resolve(__dirname + '/../../' + filename));
158 | });
159 | // 连接mongodb
160 | mongoose.Promise = global.Promise;
161 | // 使用connect 不要使用createConnection
162 | mongoose.connect('mongodb://localhost:27017/leoBlog', {useMongoClient: true}, (err) => {
163 | if (err) {
164 | console.log(err)
165 | } else {
166 | console.log('数据连接成功');
167 | app.listen(port, (err) => {
168 | if (err) {
169 | console.log(err)
170 | } else {
171 | console.log(`正在打开http://localhost:${port}...`);
172 | open(`http://localhost:${port}`);
173 | }
174 | })
175 | }
176 | });
177 |
178 |
179 |
--------------------------------------------------------------------------------
/app/front/js/containers/Register/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by suxiao on 2017/7/18.
3 | */
4 | import React from 'react';
5 | import PureRenderMixin from 'react-addons-pure-render-mixin';
6 |
7 | import '../../../scss/login.scss';
8 | import { Form, Input, Icon, Checkbox, Button } from 'antd';
9 | import { connect } from 'react-redux';
10 | import { bindActionCreators } from 'redux';
11 | import { userFetch } from '../../actions/users';
12 | const FormItem = Form.Item;
13 |
14 | @connect(
15 | (state) => ({userInfo: state.userInfo}),
16 | (dispatch) => bindActionCreators({userFetch}, dispatch)
17 | )
18 | class RegistrationForm extends React.Component {
19 | constructor(props, context) {
20 | super(props, context);
21 | this.shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this);
22 | }
23 | state = {
24 | confirmDirty: false
25 | };
26 | handleSubmit = (e) => {
27 | e.preventDefault();
28 | this.props.form.validateFieldsAndScroll((err, values) => {
29 | if (!err) {
30 | console.log('Received values of form: ', values);
31 | this.props.userFetch('/api/register', values, '/sign');
32 | }
33 | });
34 | }
35 | handleConfirmBlur = (e) => {
36 | const value = e.target.value;
37 | this.setState({ confirmDirty: this.state.confirmDirty || !!value });
38 | }
39 | checkPassword = (rule, value, callback) => {
40 | const form = this.props.form;
41 | if (value && value !== form.getFieldValue('password')) {
42 | callback('两次密码不一致');
43 | } else {
44 | callback();
45 | }
46 | }
47 | checkConfirm = (rule, value, callback) => {
48 | const form = this.props.form;
49 | if (value && this.state.confirmDirty) {
50 | form.validateFields(['repassword'], { force: true });
51 | }
52 | callback();
53 | }
54 |
55 |
56 | render() {
57 | const { getFieldDecorator } = this.props.form;
58 | const formItemLayout = {
59 | labelCol: {
60 | xs: { span: 24 },
61 | sm: { span: 6 }
62 | },
63 | wrapperCol: {
64 | xs: { span: 24 },
65 | sm: { span: 14 }
66 | }
67 | };
68 | const tailFormItemLayout = {
69 | wrapperCol: {
70 | xs: {
71 | span: 24,
72 | offset: 0
73 | },
74 | sm: {
75 | span: 14,
76 | offset: 6
77 | }
78 | }
79 | };
80 | return (
81 |
135 | );
136 | }
137 | }
138 |
139 | const Register = Form.create()(RegistrationForm);
140 | export default Register;
141 | /*
142 | export default class Register extends React.Component {
143 | render() {
144 | return (
145 |
164 | );
165 | }
166 | }
167 | */
--------------------------------------------------------------------------------
/dev/js/manifest.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"js/manifest.js","sources":["webpack:///webpack/bootstrap 5dd1f42380c8f4cacf46"],"sourcesContent":[" \t// install a JSONP callback for chunk loading\n \tvar parentJsonpFunction = window[\"webpackJsonp\"];\n \twindow[\"webpackJsonp\"] = function webpackJsonpCallback(chunkIds, moreModules, executeModules) {\n \t\t// add \"moreModules\" to the modules object,\n \t\t// then flag all \"chunkIds\" as loaded and fire callback\n \t\tvar moduleId, chunkId, i = 0, resolves = [], result;\n \t\tfor(;i < chunkIds.length; i++) {\n \t\t\tchunkId = chunkIds[i];\n \t\t\tif(installedChunks[chunkId]) {\n \t\t\t\tresolves.push(installedChunks[chunkId][0]);\n \t\t\t}\n \t\t\tinstalledChunks[chunkId] = 0;\n \t\t}\n \t\tfor(moduleId in moreModules) {\n \t\t\tif(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {\n \t\t\t\tmodules[moduleId] = moreModules[moduleId];\n \t\t\t}\n \t\t}\n \t\tif(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules, executeModules);\n \t\twhile(resolves.length) {\n \t\t\tresolves.shift()();\n \t\t}\n \t\tif(executeModules) {\n \t\t\tfor(i=0; i < executeModules.length; i++) {\n \t\t\t\tresult = __webpack_require__(__webpack_require__.s = executeModules[i]);\n \t\t\t}\n \t\t}\n \t\treturn result;\n \t};\n \tfunction hotDisposeChunk(chunkId) {\n \t\tdelete installedChunks[chunkId];\n \t}\n \tvar parentHotUpdateCallback = this[\"webpackHotUpdate\"];\n \tthis[\"webpackHotUpdate\"] = \r\n \tfunction webpackHotUpdateCallback(chunkId, moreModules) { // eslint-disable-line no-unused-vars\r\n \t\thotAddUpdateChunk(chunkId, moreModules);\r\n \t\tif(parentHotUpdateCallback) parentHotUpdateCallback(chunkId, moreModules);\r\n \t} ;\r\n \t\r\n \tfunction hotDownloadUpdateChunk(chunkId) { // eslint-disable-line no-unused-vars\r\n \t\tvar head = document.getElementsByTagName(\"head\")[0];\r\n \t\tvar script = document.createElement(\"script\");\r\n \t\tscript.type = \"text/javascript\";\r\n \t\tscript.charset = \"utf-8\";\r\n \t\tscript.src = __webpack_require__.p + \"\" + chunkId + \".\" + hotCurrentHash + \".hot-update.js\";\r\n \t\thead.appendChild(script);\r\n \t}\r\n \t\r\n \tfunction hotDownloadManifest() { // eslint-disable-line no-unused-vars\r\n \t\treturn new Promise(function(resolve, reject) {\r\n \t\t\tif(typeof XMLHttpRequest === \"undefined\")\r\n \t\t\t\treturn reject(new Error(\"No browser support\"));\r\n \t\t\ttry {\r\n \t\t\t\tvar request = new XMLHttpRequest();\r\n \t\t\t\tvar requestPath = __webpack_require__.p + \"\" + hotCurrentHash + \".hot-update.json\";\r\n \t\t\t\trequest.open(\"GET\", requestPath, true);\r\n \t\t\t\trequest.timeout = 10000;\r\n \t\t\t\trequest.send(null);\r\n \t\t\t} catch(err) {\r\n \t\t\t\treturn reject(err);\r\n \t\t\t}\r\n \t\t\trequest.onreadystatechange = function() {\r\n \t\t\t\tif(request.readyState !== 4) return;\r\n \t\t\t\tif(request.status === 0) {\r\n \t\t\t\t\t// timeout\r\n \t\t\t\t\treject(new Error(\"Manifest request to \" + requestPath + \" timed out.\"));\r\n \t\t\t\t} else if(request.status === 404) {\r\n \t\t\t\t\t// no update available\r\n \t\t\t\t\tresolve();\r\n \t\t\t\t} else if(request.status !== 200 && request.status !== 304) {\r\n \t\t\t\t\t// other failure\r\n \t\t\t\t\treject(new Error(\"Manifest request to \" + requestPath + \" failed.\"));\r\n \t\t\t\t} else {\r\n \t\t\t\t\t// success\r\n \t\t\t\t\ttry {\r\n \t\t\t\t\t\tvar update = JSON.parse(request.responseText);\r\n \t\t\t\t\t} catch(e) {\r\n \t\t\t\t\t\treject(e);\r\n \t\t\t\t\t\treturn;\r\n \t\t\t\t\t}\r\n \t\t\t\t\tresolve(update);\r\n \t\t\t\t}\r\n \t\t\t};\r\n \t\t});\r\n \t}\r\n\n \t\r\n \t\r\n \tvar hotApplyOnUpdate = true;\r\n \tvar hotCurrentHash = \"5dd1f42380c8f4cacf46\"; // eslint-disable-line no-unused-vars\r\n \tvar hotCurrentModuleData = {};\r\n \tvar hotCurrentChildModule; // eslint-disable-line no-unused-vars\r\n \tvar hotCurrentParents = []; // eslint-disable-line no-unused-vars\r\n \tvar hotCurrentParentsTemp = []; // eslint-disable-line no-unused-vars\r\n \t\r\n \tfunction hotCreateRequire(moduleId) { // eslint-disable-line no-unused-vars\r\n \t\tvar me = installedModules[moduleId];\r\n \t\tif(!me) return __webpack_require__;\r\n \t\tvar fn = function(request) {\r\n \t\t\tif(me.hot.active) {\r\n \t\t\t\tif(installedModules[request]) {\r\n \t\t\t\t\tif(installedModules[request].parents.indexOf(moduleId) < 0)\r\n \t\t\t\t\t\tinstalledModules[request].parents.push(moduleId);\r\n \t\t\t\t} else {\r\n \t\t\t\t\thotCurrentParents = [moduleId];\r\n \t\t\t\t\thotCurrentChildModule = request;\r\n \t\t\t\t}\r\n \t\t\t\tif(me.children.indexOf(request) < 0)\r\n \t\t\t\t\tme.children.push(request);\r\n \t\t\t} else {\r\n \t\t\t\tconsole.warn(\"[HMR] unexpected require(\" + request + \") from disposed module \" + moduleId);\r\n \t\t\t\thotCurrentParents = [];\r\n \t\t\t}\r\n \t\t\treturn __webpack_require__(request);\r\n \t\t};\r\n \t\tvar ObjectFactory = function ObjectFactory(name) {\r\n \t\t\treturn {\r\n \t\t\t\tconfigurable: true,\r\n \t\t\t\tenumerable: true,\r\n \t\t\t\tget: function() {\r\n \t\t\t\t\treturn __webpack_require__[name];\r\n \t\t\t\t},\r\n \t\t\t\tset: function(value) {\r\n \t\t\t\t\t__webpack_require__[name] = value;\r\n \t\t\t\t}\r\n \t\t\t};\r\n \t\t};\r\n \t\tfor(var name in __webpack_require__) {\r\n \t\t\tif(Object.prototype.hasOwnProperty.call(__webpack_require__, name) && name !== \"e\") {\r\n \t\t\t\tObject.defineProperty(fn, name, ObjectFactory(name));\r\n \t\t\t}\r\n \t\t}\r\n \t\tfn.e = function(chunkId) {\r\n \t\t\tif(hotStatus === \"ready\")\r\n \t\t\t\thotSetStatus(\"prepare\");\r\n \t\t\thotChunksLoading++;\r\n \t\t\treturn __webpack_require__.e(chunkId).then(finishChunkLoading, function(err) {\r\n \t\t\t\tfinishChunkLoading();\r\n \t\t\t\tthrow err;\r\n \t\t\t});\r\n \t\r\n \t\t\tfunction finishChunkLoading() {\r\n \t\t\t\thotChunksLoading--;\r\n \t\t\t\tif(hotStatus === \"prepare\") {\r\n \t\t\t\t\tif(!hotWaitingFilesMap[chunkId]) {\r\n \t\t\t\t\t\thotEnsureUpdateChunk(chunkId);\r\n \t\t\t\t\t}\r\n \t\t\t\t\tif(hotChunksLoading === 0 && hotWaitingFiles === 0) {\r\n \t\t\t\t\t\thotUpdateDownloaded();\r\n \t\t\t\t\t}\r\n \t\t\t\t}\r\n \t\t\t}\r\n \t\t};\r\n \t\treturn fn;\r\n \t}\r\n \t\r\n \tfunction hotCreateModule(moduleId) { // eslint-disable-line no-unused-vars\r\n \t\tvar hot = {\r\n \t\t\t// private stuff\r\n \t\t\t_acceptedDependencies: {},\r\n \t\t\t_declinedDependencies: {},\r\n \t\t\t_selfAccepted: false,\r\n \t\t\t_selfDeclined: false,\r\n \t\t\t_disposeHandlers: [],\r\n \t\t\t_main: hotCurrentChildModule !== moduleId,\r\n \t\r\n \t\t\t// Module API\r\n \t\t\tactive: true,\r\n \t\t\taccept: function(dep, callback) {\r\n \t\t\t\tif(typeof dep === \"undefined\")\r\n \t\t\t\t\thot._selfAccepted = true;\r\n \t\t\t\telse if(typeof dep === \"function\")\r\n \t\t\t\t\thot._selfAccepted = dep;\r\n \t\t\t\telse if(typeof dep === \"object\")\r\n \t\t\t\t\tfor(var i = 0; i < dep.length; i++)\r\n \t\t\t\t\t\thot._acceptedDependencies[dep[i]] = callback || function() {};\r\n \t\t\t\telse\r\n \t\t\t\t\thot._acceptedDependencies[dep] = callback || function() {};\r\n \t\t\t},\r\n \t\t\tdecline: function(dep) {\r\n \t\t\t\tif(typeof dep === \"undefined\")\r\n \t\t\t\t\thot._selfDeclined = true;\r\n \t\t\t\telse if(typeof dep === \"object\")\r\n \t\t\t\t\tfor(var i = 0; i < dep.length; i++)\r\n \t\t\t\t\t\thot._declinedDependencies[dep[i]] = true;\r\n \t\t\t\telse\r\n \t\t\t\t\thot._declinedDependencies[dep] = true;\r\n \t\t\t},\r\n \t\t\tdispose: function(callback) {\r\n \t\t\t\thot._disposeHandlers.push(callback);\r\n \t\t\t},\r\n \t\t\taddDisposeHandler: function(callback) {\r\n \t\t\t\thot._disposeHandlers.push(callback);\r\n \t\t\t},\r\n \t\t\tremoveDisposeHandler: function(callback) {\r\n \t\t\t\tvar idx = hot._disposeHandlers.indexOf(callback);\r\n \t\t\t\tif(idx >= 0) hot._disposeHandlers.splice(idx, 1);\r\n \t\t\t},\r\n \t\r\n \t\t\t// Management API\r\n \t\t\tcheck: hotCheck,\r\n \t\t\tapply: hotApply,\r\n \t\t\tstatus: function(l) {\r\n \t\t\t\tif(!l) return hotStatus;\r\n \t\t\t\thotStatusHandlers.push(l);\r\n \t\t\t},\r\n \t\t\taddStatusHandler: function(l) {\r\n \t\t\t\thotStatusHandlers.push(l);\r\n \t\t\t},\r\n \t\t\tremoveStatusHandler: function(l) {\r\n \t\t\t\tvar idx = hotStatusHandlers.indexOf(l);\r\n \t\t\t\tif(idx >= 0) hotStatusHandlers.splice(idx, 1);\r\n \t\t\t},\r\n \t\r\n \t\t\t//inherit from previous dispose call\r\n \t\t\tdata: hotCurrentModuleData[moduleId]\r\n \t\t};\r\n \t\thotCurrentChildModule = undefined;\r\n \t\treturn hot;\r\n \t}\r\n \t\r\n \tvar hotStatusHandlers = [];\r\n \tvar hotStatus = \"idle\";\r\n \t\r\n \tfunction hotSetStatus(newStatus) {\r\n \t\thotStatus = newStatus;\r\n \t\tfor(var i = 0; i < hotStatusHandlers.length; i++)\r\n \t\t\thotStatusHandlers[i].call(null, newStatus);\r\n \t}\r\n \t\r\n \t// while downloading\r\n \tvar hotWaitingFiles = 0;\r\n \tvar hotChunksLoading = 0;\r\n \tvar hotWaitingFilesMap = {};\r\n \tvar hotRequestedFilesMap = {};\r\n \tvar hotAvailableFilesMap = {};\r\n \tvar hotDeferred;\r\n \t\r\n \t// The update info\r\n \tvar hotUpdate, hotUpdateNewHash;\r\n \t\r\n \tfunction toModuleId(id) {\r\n \t\tvar isNumber = (+id) + \"\" === id;\r\n \t\treturn isNumber ? +id : id;\r\n \t}\r\n \t\r\n \tfunction hotCheck(apply) {\r\n \t\tif(hotStatus !== \"idle\") throw new Error(\"check() is only allowed in idle status\");\r\n \t\thotApplyOnUpdate = apply;\r\n \t\thotSetStatus(\"check\");\r\n \t\treturn hotDownloadManifest().then(function(update) {\r\n \t\t\tif(!update) {\r\n \t\t\t\thotSetStatus(\"idle\");\r\n \t\t\t\treturn null;\r\n \t\t\t}\r\n \t\t\thotRequestedFilesMap = {};\r\n \t\t\thotWaitingFilesMap = {};\r\n \t\t\thotAvailableFilesMap = update.c;\r\n \t\t\thotUpdateNewHash = update.h;\r\n \t\r\n \t\t\thotSetStatus(\"prepare\");\r\n \t\t\tvar promise = new Promise(function(resolve, reject) {\r\n \t\t\t\thotDeferred = {\r\n \t\t\t\t\tresolve: resolve,\r\n \t\t\t\t\treject: reject\r\n \t\t\t\t};\r\n \t\t\t});\r\n \t\t\thotUpdate = {};\r\n \t\t\tfor(var chunkId in installedChunks)\r\n \t\t\t{ // eslint-disable-line no-lone-blocks\r\n \t\t\t\t/*globals chunkId */\r\n \t\t\t\thotEnsureUpdateChunk(chunkId);\r\n \t\t\t}\r\n \t\t\tif(hotStatus === \"prepare\" && hotChunksLoading === 0 && hotWaitingFiles === 0) {\r\n \t\t\t\thotUpdateDownloaded();\r\n \t\t\t}\r\n \t\t\treturn promise;\r\n \t\t});\r\n \t}\r\n \t\r\n \tfunction hotAddUpdateChunk(chunkId, moreModules) { // eslint-disable-line no-unused-vars\r\n \t\tif(!hotAvailableFilesMap[chunkId] || !hotRequestedFilesMap[chunkId])\r\n \t\t\treturn;\r\n \t\thotRequestedFilesMap[chunkId] = false;\r\n \t\tfor(var moduleId in moreModules) {\r\n \t\t\tif(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {\r\n \t\t\t\thotUpdate[moduleId] = moreModules[moduleId];\r\n \t\t\t}\r\n \t\t}\r\n \t\tif(--hotWaitingFiles === 0 && hotChunksLoading === 0) {\r\n \t\t\thotUpdateDownloaded();\r\n \t\t}\r\n \t}\r\n \t\r\n \tfunction hotEnsureUpdateChunk(chunkId) {\r\n \t\tif(!hotAvailableFilesMap[chunkId]) {\r\n \t\t\thotWaitingFilesMap[chunkId] = true;\r\n \t\t} else {\r\n \t\t\thotRequestedFilesMap[chunkId] = true;\r\n \t\t\thotWaitingFiles++;\r\n \t\t\thotDownloadUpdateChunk(chunkId);\r\n \t\t}\r\n \t}\r\n \t\r\n \tfunction hotUpdateDownloaded() {\r\n \t\thotSetStatus(\"ready\");\r\n \t\tvar deferred = hotDeferred;\r\n \t\thotDeferred = null;\r\n \t\tif(!deferred) return;\r\n \t\tif(hotApplyOnUpdate) {\r\n \t\t\thotApply(hotApplyOnUpdate).then(function(result) {\r\n \t\t\t\tdeferred.resolve(result);\r\n \t\t\t}, function(err) {\r\n \t\t\t\tdeferred.reject(err);\r\n \t\t\t});\r\n \t\t} else {\r\n \t\t\tvar outdatedModules = [];\r\n \t\t\tfor(var id in hotUpdate) {\r\n \t\t\t\tif(Object.prototype.hasOwnProperty.call(hotUpdate, id)) {\r\n \t\t\t\t\toutdatedModules.push(toModuleId(id));\r\n \t\t\t\t}\r\n \t\t\t}\r\n \t\t\tdeferred.resolve(outdatedModules);\r\n \t\t}\r\n \t}\r\n \t\r\n \tfunction hotApply(options) {\r\n \t\tif(hotStatus !== \"ready\") throw new Error(\"apply() is only allowed in ready status\");\r\n \t\toptions = options || {};\r\n \t\r\n \t\tvar cb;\r\n \t\tvar i;\r\n \t\tvar j;\r\n \t\tvar module;\r\n \t\tvar moduleId;\r\n \t\r\n \t\tfunction getAffectedStuff(updateModuleId) {\r\n \t\t\tvar outdatedModules = [updateModuleId];\r\n \t\t\tvar outdatedDependencies = {};\r\n \t\r\n \t\t\tvar queue = outdatedModules.slice().map(function(id) {\r\n \t\t\t\treturn {\r\n \t\t\t\t\tchain: [id],\r\n \t\t\t\t\tid: id\r\n \t\t\t\t};\r\n \t\t\t});\r\n \t\t\twhile(queue.length > 0) {\r\n \t\t\t\tvar queueItem = queue.pop();\r\n \t\t\t\tvar moduleId = queueItem.id;\r\n \t\t\t\tvar chain = queueItem.chain;\r\n \t\t\t\tmodule = installedModules[moduleId];\r\n \t\t\t\tif(!module || module.hot._selfAccepted)\r\n \t\t\t\t\tcontinue;\r\n \t\t\t\tif(module.hot._selfDeclined) {\r\n \t\t\t\t\treturn {\r\n \t\t\t\t\t\ttype: \"self-declined\",\r\n \t\t\t\t\t\tchain: chain,\r\n \t\t\t\t\t\tmoduleId: moduleId\r\n \t\t\t\t\t};\r\n \t\t\t\t}\r\n \t\t\t\tif(module.hot._main) {\r\n \t\t\t\t\treturn {\r\n \t\t\t\t\t\ttype: \"unaccepted\",\r\n \t\t\t\t\t\tchain: chain,\r\n \t\t\t\t\t\tmoduleId: moduleId\r\n \t\t\t\t\t};\r\n \t\t\t\t}\r\n \t\t\t\tfor(var i = 0; i < module.parents.length; i++) {\r\n \t\t\t\t\tvar parentId = module.parents[i];\r\n \t\t\t\t\tvar parent = installedModules[parentId];\r\n \t\t\t\t\tif(!parent) continue;\r\n \t\t\t\t\tif(parent.hot._declinedDependencies[moduleId]) {\r\n \t\t\t\t\t\treturn {\r\n \t\t\t\t\t\t\ttype: \"declined\",\r\n \t\t\t\t\t\t\tchain: chain.concat([parentId]),\r\n \t\t\t\t\t\t\tmoduleId: moduleId,\r\n \t\t\t\t\t\t\tparentId: parentId\r\n \t\t\t\t\t\t};\r\n \t\t\t\t\t}\r\n \t\t\t\t\tif(outdatedModules.indexOf(parentId) >= 0) continue;\r\n \t\t\t\t\tif(parent.hot._acceptedDependencies[moduleId]) {\r\n \t\t\t\t\t\tif(!outdatedDependencies[parentId])\r\n \t\t\t\t\t\t\toutdatedDependencies[parentId] = [];\r\n \t\t\t\t\t\taddAllToSet(outdatedDependencies[parentId], [moduleId]);\r\n \t\t\t\t\t\tcontinue;\r\n \t\t\t\t\t}\r\n \t\t\t\t\tdelete outdatedDependencies[parentId];\r\n \t\t\t\t\toutdatedModules.push(parentId);\r\n \t\t\t\t\tqueue.push({\r\n \t\t\t\t\t\tchain: chain.concat([parentId]),\r\n \t\t\t\t\t\tid: parentId\r\n \t\t\t\t\t});\r\n \t\t\t\t}\r\n \t\t\t}\r\n \t\r\n \t\t\treturn {\r\n \t\t\t\ttype: \"accepted\",\r\n \t\t\t\tmoduleId: updateModuleId,\r\n \t\t\t\toutdatedModules: outdatedModules,\r\n \t\t\t\toutdatedDependencies: outdatedDependencies\r\n \t\t\t};\r\n \t\t}\r\n \t\r\n \t\tfunction addAllToSet(a, b) {\r\n \t\t\tfor(var i = 0; i < b.length; i++) {\r\n \t\t\t\tvar item = b[i];\r\n \t\t\t\tif(a.indexOf(item) < 0)\r\n \t\t\t\t\ta.push(item);\r\n \t\t\t}\r\n \t\t}\r\n \t\r\n \t\t// at begin all updates modules are outdated\r\n \t\t// the \"outdated\" status can propagate to parents if they don't accept the children\r\n \t\tvar outdatedDependencies = {};\r\n \t\tvar outdatedModules = [];\r\n \t\tvar appliedUpdate = {};\r\n \t\r\n \t\tvar warnUnexpectedRequire = function warnUnexpectedRequire() {\r\n \t\t\tconsole.warn(\"[HMR] unexpected require(\" + result.moduleId + \") to disposed module\");\r\n \t\t};\r\n \t\r\n \t\tfor(var id in hotUpdate) {\r\n \t\t\tif(Object.prototype.hasOwnProperty.call(hotUpdate, id)) {\r\n \t\t\t\tmoduleId = toModuleId(id);\r\n \t\t\t\tvar result;\r\n \t\t\t\tif(hotUpdate[id]) {\r\n \t\t\t\t\tresult = getAffectedStuff(moduleId);\r\n \t\t\t\t} else {\r\n \t\t\t\t\tresult = {\r\n \t\t\t\t\t\ttype: \"disposed\",\r\n \t\t\t\t\t\tmoduleId: id\r\n \t\t\t\t\t};\r\n \t\t\t\t}\r\n \t\t\t\tvar abortError = false;\r\n \t\t\t\tvar doApply = false;\r\n \t\t\t\tvar doDispose = false;\r\n \t\t\t\tvar chainInfo = \"\";\r\n \t\t\t\tif(result.chain) {\r\n \t\t\t\t\tchainInfo = \"\\nUpdate propagation: \" + result.chain.join(\" -> \");\r\n \t\t\t\t}\r\n \t\t\t\tswitch(result.type) {\r\n \t\t\t\t\tcase \"self-declined\":\r\n \t\t\t\t\t\tif(options.onDeclined)\r\n \t\t\t\t\t\t\toptions.onDeclined(result);\r\n \t\t\t\t\t\tif(!options.ignoreDeclined)\r\n \t\t\t\t\t\t\tabortError = new Error(\"Aborted because of self decline: \" + result.moduleId + chainInfo);\r\n \t\t\t\t\t\tbreak;\r\n \t\t\t\t\tcase \"declined\":\r\n \t\t\t\t\t\tif(options.onDeclined)\r\n \t\t\t\t\t\t\toptions.onDeclined(result);\r\n \t\t\t\t\t\tif(!options.ignoreDeclined)\r\n \t\t\t\t\t\t\tabortError = new Error(\"Aborted because of declined dependency: \" + result.moduleId + \" in \" + result.parentId + chainInfo);\r\n \t\t\t\t\t\tbreak;\r\n \t\t\t\t\tcase \"unaccepted\":\r\n \t\t\t\t\t\tif(options.onUnaccepted)\r\n \t\t\t\t\t\t\toptions.onUnaccepted(result);\r\n \t\t\t\t\t\tif(!options.ignoreUnaccepted)\r\n \t\t\t\t\t\t\tabortError = new Error(\"Aborted because \" + moduleId + \" is not accepted\" + chainInfo);\r\n \t\t\t\t\t\tbreak;\r\n \t\t\t\t\tcase \"accepted\":\r\n \t\t\t\t\t\tif(options.onAccepted)\r\n \t\t\t\t\t\t\toptions.onAccepted(result);\r\n \t\t\t\t\t\tdoApply = true;\r\n \t\t\t\t\t\tbreak;\r\n \t\t\t\t\tcase \"disposed\":\r\n \t\t\t\t\t\tif(options.onDisposed)\r\n \t\t\t\t\t\t\toptions.onDisposed(result);\r\n \t\t\t\t\t\tdoDispose = true;\r\n \t\t\t\t\t\tbreak;\r\n \t\t\t\t\tdefault:\r\n \t\t\t\t\t\tthrow new Error(\"Unexception type \" + result.type);\r\n \t\t\t\t}\r\n \t\t\t\tif(abortError) {\r\n \t\t\t\t\thotSetStatus(\"abort\");\r\n \t\t\t\t\treturn Promise.reject(abortError);\r\n \t\t\t\t}\r\n \t\t\t\tif(doApply) {\r\n \t\t\t\t\tappliedUpdate[moduleId] = hotUpdate[moduleId];\r\n \t\t\t\t\taddAllToSet(outdatedModules, result.outdatedModules);\r\n \t\t\t\t\tfor(moduleId in result.outdatedDependencies) {\r\n \t\t\t\t\t\tif(Object.prototype.hasOwnProperty.call(result.outdatedDependencies, moduleId)) {\r\n \t\t\t\t\t\t\tif(!outdatedDependencies[moduleId])\r\n \t\t\t\t\t\t\t\toutdatedDependencies[moduleId] = [];\r\n \t\t\t\t\t\t\taddAllToSet(outdatedDependencies[moduleId], result.outdatedDependencies[moduleId]);\r\n \t\t\t\t\t\t}\r\n \t\t\t\t\t}\r\n \t\t\t\t}\r\n \t\t\t\tif(doDispose) {\r\n \t\t\t\t\taddAllToSet(outdatedModules, [result.moduleId]);\r\n \t\t\t\t\tappliedUpdate[moduleId] = warnUnexpectedRequire;\r\n \t\t\t\t}\r\n \t\t\t}\r\n \t\t}\r\n \t\r\n \t\t// Store self accepted outdated modules to require them later by the module system\r\n \t\tvar outdatedSelfAcceptedModules = [];\r\n \t\tfor(i = 0; i < outdatedModules.length; i++) {\r\n \t\t\tmoduleId = outdatedModules[i];\r\n \t\t\tif(installedModules[moduleId] && installedModules[moduleId].hot._selfAccepted)\r\n \t\t\t\toutdatedSelfAcceptedModules.push({\r\n \t\t\t\t\tmodule: moduleId,\r\n \t\t\t\t\terrorHandler: installedModules[moduleId].hot._selfAccepted\r\n \t\t\t\t});\r\n \t\t}\r\n \t\r\n \t\t// Now in \"dispose\" phase\r\n \t\thotSetStatus(\"dispose\");\r\n \t\tObject.keys(hotAvailableFilesMap).forEach(function(chunkId) {\r\n \t\t\tif(hotAvailableFilesMap[chunkId] === false) {\r\n \t\t\t\thotDisposeChunk(chunkId);\r\n \t\t\t}\r\n \t\t});\r\n \t\r\n \t\tvar idx;\r\n \t\tvar queue = outdatedModules.slice();\r\n \t\twhile(queue.length > 0) {\r\n \t\t\tmoduleId = queue.pop();\r\n \t\t\tmodule = installedModules[moduleId];\r\n \t\t\tif(!module) continue;\r\n \t\r\n \t\t\tvar data = {};\r\n \t\r\n \t\t\t// Call dispose handlers\r\n \t\t\tvar disposeHandlers = module.hot._disposeHandlers;\r\n \t\t\tfor(j = 0; j < disposeHandlers.length; j++) {\r\n \t\t\t\tcb = disposeHandlers[j];\r\n \t\t\t\tcb(data);\r\n \t\t\t}\r\n \t\t\thotCurrentModuleData[moduleId] = data;\r\n \t\r\n \t\t\t// disable module (this disables requires from this module)\r\n \t\t\tmodule.hot.active = false;\r\n \t\r\n \t\t\t// remove module from cache\r\n \t\t\tdelete installedModules[moduleId];\r\n \t\r\n \t\t\t// remove \"parents\" references from all children\r\n \t\t\tfor(j = 0; j < module.children.length; j++) {\r\n \t\t\t\tvar child = installedModules[module.children[j]];\r\n \t\t\t\tif(!child) continue;\r\n \t\t\t\tidx = child.parents.indexOf(moduleId);\r\n \t\t\t\tif(idx >= 0) {\r\n \t\t\t\t\tchild.parents.splice(idx, 1);\r\n \t\t\t\t}\r\n \t\t\t}\r\n \t\t}\r\n \t\r\n \t\t// remove outdated dependency from module children\r\n \t\tvar dependency;\r\n \t\tvar moduleOutdatedDependencies;\r\n \t\tfor(moduleId in outdatedDependencies) {\r\n \t\t\tif(Object.prototype.hasOwnProperty.call(outdatedDependencies, moduleId)) {\r\n \t\t\t\tmodule = installedModules[moduleId];\r\n \t\t\t\tif(module) {\r\n \t\t\t\t\tmoduleOutdatedDependencies = outdatedDependencies[moduleId];\r\n \t\t\t\t\tfor(j = 0; j < moduleOutdatedDependencies.length; j++) {\r\n \t\t\t\t\t\tdependency = moduleOutdatedDependencies[j];\r\n \t\t\t\t\t\tidx = module.children.indexOf(dependency);\r\n \t\t\t\t\t\tif(idx >= 0) module.children.splice(idx, 1);\r\n \t\t\t\t\t}\r\n \t\t\t\t}\r\n \t\t\t}\r\n \t\t}\r\n \t\r\n \t\t// Not in \"apply\" phase\r\n \t\thotSetStatus(\"apply\");\r\n \t\r\n \t\thotCurrentHash = hotUpdateNewHash;\r\n \t\r\n \t\t// insert new code\r\n \t\tfor(moduleId in appliedUpdate) {\r\n \t\t\tif(Object.prototype.hasOwnProperty.call(appliedUpdate, moduleId)) {\r\n \t\t\t\tmodules[moduleId] = appliedUpdate[moduleId];\r\n \t\t\t}\r\n \t\t}\r\n \t\r\n \t\t// call accept handlers\r\n \t\tvar error = null;\r\n \t\tfor(moduleId in outdatedDependencies) {\r\n \t\t\tif(Object.prototype.hasOwnProperty.call(outdatedDependencies, moduleId)) {\r\n \t\t\t\tmodule = installedModules[moduleId];\r\n \t\t\t\tmoduleOutdatedDependencies = outdatedDependencies[moduleId];\r\n \t\t\t\tvar callbacks = [];\r\n \t\t\t\tfor(i = 0; i < moduleOutdatedDependencies.length; i++) {\r\n \t\t\t\t\tdependency = moduleOutdatedDependencies[i];\r\n \t\t\t\t\tcb = module.hot._acceptedDependencies[dependency];\r\n \t\t\t\t\tif(callbacks.indexOf(cb) >= 0) continue;\r\n \t\t\t\t\tcallbacks.push(cb);\r\n \t\t\t\t}\r\n \t\t\t\tfor(i = 0; i < callbacks.length; i++) {\r\n \t\t\t\t\tcb = callbacks[i];\r\n \t\t\t\t\ttry {\r\n \t\t\t\t\t\tcb(moduleOutdatedDependencies);\r\n \t\t\t\t\t} catch(err) {\r\n \t\t\t\t\t\tif(options.onErrored) {\r\n \t\t\t\t\t\t\toptions.onErrored({\r\n \t\t\t\t\t\t\t\ttype: \"accept-errored\",\r\n \t\t\t\t\t\t\t\tmoduleId: moduleId,\r\n \t\t\t\t\t\t\t\tdependencyId: moduleOutdatedDependencies[i],\r\n \t\t\t\t\t\t\t\terror: err\r\n \t\t\t\t\t\t\t});\r\n \t\t\t\t\t\t}\r\n \t\t\t\t\t\tif(!options.ignoreErrored) {\r\n \t\t\t\t\t\t\tif(!error)\r\n \t\t\t\t\t\t\t\terror = err;\r\n \t\t\t\t\t\t}\r\n \t\t\t\t\t}\r\n \t\t\t\t}\r\n \t\t\t}\r\n \t\t}\r\n \t\r\n \t\t// Load self accepted modules\r\n \t\tfor(i = 0; i < outdatedSelfAcceptedModules.length; i++) {\r\n \t\t\tvar item = outdatedSelfAcceptedModules[i];\r\n \t\t\tmoduleId = item.module;\r\n \t\t\thotCurrentParents = [moduleId];\r\n \t\t\ttry {\r\n \t\t\t\t__webpack_require__(moduleId);\r\n \t\t\t} catch(err) {\r\n \t\t\t\tif(typeof item.errorHandler === \"function\") {\r\n \t\t\t\t\ttry {\r\n \t\t\t\t\t\titem.errorHandler(err);\r\n \t\t\t\t\t} catch(err2) {\r\n \t\t\t\t\t\tif(options.onErrored) {\r\n \t\t\t\t\t\t\toptions.onErrored({\r\n \t\t\t\t\t\t\t\ttype: \"self-accept-error-handler-errored\",\r\n \t\t\t\t\t\t\t\tmoduleId: moduleId,\r\n \t\t\t\t\t\t\t\terror: err2,\r\n \t\t\t\t\t\t\t\torginalError: err\r\n \t\t\t\t\t\t\t});\r\n \t\t\t\t\t\t}\r\n \t\t\t\t\t\tif(!options.ignoreErrored) {\r\n \t\t\t\t\t\t\tif(!error)\r\n \t\t\t\t\t\t\t\terror = err2;\r\n \t\t\t\t\t\t}\r\n \t\t\t\t\t\tif(!error)\r\n \t\t\t\t\t\t\terror = err;\r\n \t\t\t\t\t}\r\n \t\t\t\t} else {\r\n \t\t\t\t\tif(options.onErrored) {\r\n \t\t\t\t\t\toptions.onErrored({\r\n \t\t\t\t\t\t\ttype: \"self-accept-errored\",\r\n \t\t\t\t\t\t\tmoduleId: moduleId,\r\n \t\t\t\t\t\t\terror: err\r\n \t\t\t\t\t\t});\r\n \t\t\t\t\t}\r\n \t\t\t\t\tif(!options.ignoreErrored) {\r\n \t\t\t\t\t\tif(!error)\r\n \t\t\t\t\t\t\terror = err;\r\n \t\t\t\t\t}\r\n \t\t\t\t}\r\n \t\t\t}\r\n \t\t}\r\n \t\r\n \t\t// handle errors in accept handlers and self accepted module load\r\n \t\tif(error) {\r\n \t\t\thotSetStatus(\"fail\");\r\n \t\t\treturn Promise.reject(error);\r\n \t\t}\r\n \t\r\n \t\thotSetStatus(\"idle\");\r\n \t\treturn new Promise(function(resolve) {\r\n \t\t\tresolve(outdatedModules);\r\n \t\t});\r\n \t}\r\n\n \t// The module cache\n \tvar installedModules = {};\n\n \t// objects to store loaded and loading chunks\n \tvar installedChunks = {\n \t\t2: 0\n \t};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {},\n \t\t\thot: hotCreateModule(moduleId),\n \t\t\tparents: (hotCurrentParentsTemp = hotCurrentParents, hotCurrentParents = [], hotCurrentParentsTemp),\n \t\t\tchildren: []\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, hotCreateRequire(moduleId));\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n \t// This file contains only the entry chunk.\n \t// The chunk loading function for additional chunks\n \t__webpack_require__.e = function requireEnsure(chunkId) {\n \t\tvar installedChunkData = installedChunks[chunkId];\n \t\tif(installedChunkData === 0) {\n \t\t\treturn new Promise(function(resolve) { resolve(); });\n \t\t}\n\n \t\t// a Promise means \"currently loading\".\n \t\tif(installedChunkData) {\n \t\t\treturn installedChunkData[2];\n \t\t}\n\n \t\t// setup Promise in chunk cache\n \t\tvar promise = new Promise(function(resolve, reject) {\n \t\t\tinstalledChunkData = installedChunks[chunkId] = [resolve, reject];\n \t\t});\n \t\tinstalledChunkData[2] = promise;\n\n \t\t// start chunk loading\n \t\tvar head = document.getElementsByTagName('head')[0];\n \t\tvar script = document.createElement('script');\n \t\tscript.type = 'text/javascript';\n \t\tscript.charset = 'utf-8';\n \t\tscript.async = true;\n \t\tscript.timeout = 120000;\n\n \t\tif (__webpack_require__.nc) {\n \t\t\tscript.setAttribute(\"nonce\", __webpack_require__.nc);\n \t\t}\n \t\tscript.src = __webpack_require__.p + \"\" + ({\"0\":\"app\",\"1\":\"verdor\"}[chunkId]||chunkId) + \".chunk.js\";\n \t\tvar timeout = setTimeout(onScriptComplete, 120000);\n \t\tscript.onerror = script.onload = onScriptComplete;\n \t\tfunction onScriptComplete() {\n \t\t\t// avoid mem leaks in IE.\n \t\t\tscript.onerror = script.onload = null;\n \t\t\tclearTimeout(timeout);\n \t\t\tvar chunk = installedChunks[chunkId];\n \t\t\tif(chunk !== 0) {\n \t\t\t\tif(chunk) {\n \t\t\t\t\tchunk[1](new Error('Loading chunk ' + chunkId + ' failed.'));\n \t\t\t\t}\n \t\t\t\tinstalledChunks[chunkId] = undefined;\n \t\t\t}\n \t\t};\n \t\thead.appendChild(script);\n\n \t\treturn promise;\n \t};\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// identity function for calling harmony imports with the correct context\n \t__webpack_require__.i = function(value) { return value; };\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"/\";\n\n \t// on error function for async loading\n \t__webpack_require__.oe = function(err) { console.error(err); throw err; };\n\n \t// __webpack_hash__\n \t__webpack_require__.h = function() { return hotCurrentHash; };\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap 5dd1f42380c8f4cacf46"],"mappings":";AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;A","sourceRoot":""}
--------------------------------------------------------------------------------
/dev/js/manifest.js:
--------------------------------------------------------------------------------
1 | /******/ (function(modules) { // webpackBootstrap
2 | /******/ // install a JSONP callback for chunk loading
3 | /******/ var parentJsonpFunction = window["webpackJsonp"];
4 | /******/ window["webpackJsonp"] = function webpackJsonpCallback(chunkIds, moreModules, executeModules) {
5 | /******/ // add "moreModules" to the modules object,
6 | /******/ // then flag all "chunkIds" as loaded and fire callback
7 | /******/ var moduleId, chunkId, i = 0, resolves = [], result;
8 | /******/ for(;i < chunkIds.length; i++) {
9 | /******/ chunkId = chunkIds[i];
10 | /******/ if(installedChunks[chunkId]) {
11 | /******/ resolves.push(installedChunks[chunkId][0]);
12 | /******/ }
13 | /******/ installedChunks[chunkId] = 0;
14 | /******/ }
15 | /******/ for(moduleId in moreModules) {
16 | /******/ if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {
17 | /******/ modules[moduleId] = moreModules[moduleId];
18 | /******/ }
19 | /******/ }
20 | /******/ if(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules, executeModules);
21 | /******/ while(resolves.length) {
22 | /******/ resolves.shift()();
23 | /******/ }
24 | /******/ if(executeModules) {
25 | /******/ for(i=0; i < executeModules.length; i++) {
26 | /******/ result = __webpack_require__(__webpack_require__.s = executeModules[i]);
27 | /******/ }
28 | /******/ }
29 | /******/ return result;
30 | /******/ };
31 | /******/ function hotDisposeChunk(chunkId) {
32 | /******/ delete installedChunks[chunkId];
33 | /******/ }
34 | /******/ var parentHotUpdateCallback = this["webpackHotUpdate"];
35 | /******/ this["webpackHotUpdate"] =
36 | /******/ function webpackHotUpdateCallback(chunkId, moreModules) { // eslint-disable-line no-unused-vars
37 | /******/ hotAddUpdateChunk(chunkId, moreModules);
38 | /******/ if(parentHotUpdateCallback) parentHotUpdateCallback(chunkId, moreModules);
39 | /******/ } ;
40 | /******/
41 | /******/ function hotDownloadUpdateChunk(chunkId) { // eslint-disable-line no-unused-vars
42 | /******/ var head = document.getElementsByTagName("head")[0];
43 | /******/ var script = document.createElement("script");
44 | /******/ script.type = "text/javascript";
45 | /******/ script.charset = "utf-8";
46 | /******/ script.src = __webpack_require__.p + "" + chunkId + "." + hotCurrentHash + ".hot-update.js";
47 | /******/ head.appendChild(script);
48 | /******/ }
49 | /******/
50 | /******/ function hotDownloadManifest() { // eslint-disable-line no-unused-vars
51 | /******/ return new Promise(function(resolve, reject) {
52 | /******/ if(typeof XMLHttpRequest === "undefined")
53 | /******/ return reject(new Error("No browser support"));
54 | /******/ try {
55 | /******/ var request = new XMLHttpRequest();
56 | /******/ var requestPath = __webpack_require__.p + "" + hotCurrentHash + ".hot-update.json";
57 | /******/ request.open("GET", requestPath, true);
58 | /******/ request.timeout = 10000;
59 | /******/ request.send(null);
60 | /******/ } catch(err) {
61 | /******/ return reject(err);
62 | /******/ }
63 | /******/ request.onreadystatechange = function() {
64 | /******/ if(request.readyState !== 4) return;
65 | /******/ if(request.status === 0) {
66 | /******/ // timeout
67 | /******/ reject(new Error("Manifest request to " + requestPath + " timed out."));
68 | /******/ } else if(request.status === 404) {
69 | /******/ // no update available
70 | /******/ resolve();
71 | /******/ } else if(request.status !== 200 && request.status !== 304) {
72 | /******/ // other failure
73 | /******/ reject(new Error("Manifest request to " + requestPath + " failed."));
74 | /******/ } else {
75 | /******/ // success
76 | /******/ try {
77 | /******/ var update = JSON.parse(request.responseText);
78 | /******/ } catch(e) {
79 | /******/ reject(e);
80 | /******/ return;
81 | /******/ }
82 | /******/ resolve(update);
83 | /******/ }
84 | /******/ };
85 | /******/ });
86 | /******/ }
87 | /******/
88 | /******/
89 | /******/
90 | /******/ var hotApplyOnUpdate = true;
91 | /******/ var hotCurrentHash = "5dd1f42380c8f4cacf46"; // eslint-disable-line no-unused-vars
92 | /******/ var hotCurrentModuleData = {};
93 | /******/ var hotCurrentChildModule; // eslint-disable-line no-unused-vars
94 | /******/ var hotCurrentParents = []; // eslint-disable-line no-unused-vars
95 | /******/ var hotCurrentParentsTemp = []; // eslint-disable-line no-unused-vars
96 | /******/
97 | /******/ function hotCreateRequire(moduleId) { // eslint-disable-line no-unused-vars
98 | /******/ var me = installedModules[moduleId];
99 | /******/ if(!me) return __webpack_require__;
100 | /******/ var fn = function(request) {
101 | /******/ if(me.hot.active) {
102 | /******/ if(installedModules[request]) {
103 | /******/ if(installedModules[request].parents.indexOf(moduleId) < 0)
104 | /******/ installedModules[request].parents.push(moduleId);
105 | /******/ } else {
106 | /******/ hotCurrentParents = [moduleId];
107 | /******/ hotCurrentChildModule = request;
108 | /******/ }
109 | /******/ if(me.children.indexOf(request) < 0)
110 | /******/ me.children.push(request);
111 | /******/ } else {
112 | /******/ console.warn("[HMR] unexpected require(" + request + ") from disposed module " + moduleId);
113 | /******/ hotCurrentParents = [];
114 | /******/ }
115 | /******/ return __webpack_require__(request);
116 | /******/ };
117 | /******/ var ObjectFactory = function ObjectFactory(name) {
118 | /******/ return {
119 | /******/ configurable: true,
120 | /******/ enumerable: true,
121 | /******/ get: function() {
122 | /******/ return __webpack_require__[name];
123 | /******/ },
124 | /******/ set: function(value) {
125 | /******/ __webpack_require__[name] = value;
126 | /******/ }
127 | /******/ };
128 | /******/ };
129 | /******/ for(var name in __webpack_require__) {
130 | /******/ if(Object.prototype.hasOwnProperty.call(__webpack_require__, name) && name !== "e") {
131 | /******/ Object.defineProperty(fn, name, ObjectFactory(name));
132 | /******/ }
133 | /******/ }
134 | /******/ fn.e = function(chunkId) {
135 | /******/ if(hotStatus === "ready")
136 | /******/ hotSetStatus("prepare");
137 | /******/ hotChunksLoading++;
138 | /******/ return __webpack_require__.e(chunkId).then(finishChunkLoading, function(err) {
139 | /******/ finishChunkLoading();
140 | /******/ throw err;
141 | /******/ });
142 | /******/
143 | /******/ function finishChunkLoading() {
144 | /******/ hotChunksLoading--;
145 | /******/ if(hotStatus === "prepare") {
146 | /******/ if(!hotWaitingFilesMap[chunkId]) {
147 | /******/ hotEnsureUpdateChunk(chunkId);
148 | /******/ }
149 | /******/ if(hotChunksLoading === 0 && hotWaitingFiles === 0) {
150 | /******/ hotUpdateDownloaded();
151 | /******/ }
152 | /******/ }
153 | /******/ }
154 | /******/ };
155 | /******/ return fn;
156 | /******/ }
157 | /******/
158 | /******/ function hotCreateModule(moduleId) { // eslint-disable-line no-unused-vars
159 | /******/ var hot = {
160 | /******/ // private stuff
161 | /******/ _acceptedDependencies: {},
162 | /******/ _declinedDependencies: {},
163 | /******/ _selfAccepted: false,
164 | /******/ _selfDeclined: false,
165 | /******/ _disposeHandlers: [],
166 | /******/ _main: hotCurrentChildModule !== moduleId,
167 | /******/
168 | /******/ // Module API
169 | /******/ active: true,
170 | /******/ accept: function(dep, callback) {
171 | /******/ if(typeof dep === "undefined")
172 | /******/ hot._selfAccepted = true;
173 | /******/ else if(typeof dep === "function")
174 | /******/ hot._selfAccepted = dep;
175 | /******/ else if(typeof dep === "object")
176 | /******/ for(var i = 0; i < dep.length; i++)
177 | /******/ hot._acceptedDependencies[dep[i]] = callback || function() {};
178 | /******/ else
179 | /******/ hot._acceptedDependencies[dep] = callback || function() {};
180 | /******/ },
181 | /******/ decline: function(dep) {
182 | /******/ if(typeof dep === "undefined")
183 | /******/ hot._selfDeclined = true;
184 | /******/ else if(typeof dep === "object")
185 | /******/ for(var i = 0; i < dep.length; i++)
186 | /******/ hot._declinedDependencies[dep[i]] = true;
187 | /******/ else
188 | /******/ hot._declinedDependencies[dep] = true;
189 | /******/ },
190 | /******/ dispose: function(callback) {
191 | /******/ hot._disposeHandlers.push(callback);
192 | /******/ },
193 | /******/ addDisposeHandler: function(callback) {
194 | /******/ hot._disposeHandlers.push(callback);
195 | /******/ },
196 | /******/ removeDisposeHandler: function(callback) {
197 | /******/ var idx = hot._disposeHandlers.indexOf(callback);
198 | /******/ if(idx >= 0) hot._disposeHandlers.splice(idx, 1);
199 | /******/ },
200 | /******/
201 | /******/ // Management API
202 | /******/ check: hotCheck,
203 | /******/ apply: hotApply,
204 | /******/ status: function(l) {
205 | /******/ if(!l) return hotStatus;
206 | /******/ hotStatusHandlers.push(l);
207 | /******/ },
208 | /******/ addStatusHandler: function(l) {
209 | /******/ hotStatusHandlers.push(l);
210 | /******/ },
211 | /******/ removeStatusHandler: function(l) {
212 | /******/ var idx = hotStatusHandlers.indexOf(l);
213 | /******/ if(idx >= 0) hotStatusHandlers.splice(idx, 1);
214 | /******/ },
215 | /******/
216 | /******/ //inherit from previous dispose call
217 | /******/ data: hotCurrentModuleData[moduleId]
218 | /******/ };
219 | /******/ hotCurrentChildModule = undefined;
220 | /******/ return hot;
221 | /******/ }
222 | /******/
223 | /******/ var hotStatusHandlers = [];
224 | /******/ var hotStatus = "idle";
225 | /******/
226 | /******/ function hotSetStatus(newStatus) {
227 | /******/ hotStatus = newStatus;
228 | /******/ for(var i = 0; i < hotStatusHandlers.length; i++)
229 | /******/ hotStatusHandlers[i].call(null, newStatus);
230 | /******/ }
231 | /******/
232 | /******/ // while downloading
233 | /******/ var hotWaitingFiles = 0;
234 | /******/ var hotChunksLoading = 0;
235 | /******/ var hotWaitingFilesMap = {};
236 | /******/ var hotRequestedFilesMap = {};
237 | /******/ var hotAvailableFilesMap = {};
238 | /******/ var hotDeferred;
239 | /******/
240 | /******/ // The update info
241 | /******/ var hotUpdate, hotUpdateNewHash;
242 | /******/
243 | /******/ function toModuleId(id) {
244 | /******/ var isNumber = (+id) + "" === id;
245 | /******/ return isNumber ? +id : id;
246 | /******/ }
247 | /******/
248 | /******/ function hotCheck(apply) {
249 | /******/ if(hotStatus !== "idle") throw new Error("check() is only allowed in idle status");
250 | /******/ hotApplyOnUpdate = apply;
251 | /******/ hotSetStatus("check");
252 | /******/ return hotDownloadManifest().then(function(update) {
253 | /******/ if(!update) {
254 | /******/ hotSetStatus("idle");
255 | /******/ return null;
256 | /******/ }
257 | /******/ hotRequestedFilesMap = {};
258 | /******/ hotWaitingFilesMap = {};
259 | /******/ hotAvailableFilesMap = update.c;
260 | /******/ hotUpdateNewHash = update.h;
261 | /******/
262 | /******/ hotSetStatus("prepare");
263 | /******/ var promise = new Promise(function(resolve, reject) {
264 | /******/ hotDeferred = {
265 | /******/ resolve: resolve,
266 | /******/ reject: reject
267 | /******/ };
268 | /******/ });
269 | /******/ hotUpdate = {};
270 | /******/ for(var chunkId in installedChunks)
271 | /******/ { // eslint-disable-line no-lone-blocks
272 | /******/ /*globals chunkId */
273 | /******/ hotEnsureUpdateChunk(chunkId);
274 | /******/ }
275 | /******/ if(hotStatus === "prepare" && hotChunksLoading === 0 && hotWaitingFiles === 0) {
276 | /******/ hotUpdateDownloaded();
277 | /******/ }
278 | /******/ return promise;
279 | /******/ });
280 | /******/ }
281 | /******/
282 | /******/ function hotAddUpdateChunk(chunkId, moreModules) { // eslint-disable-line no-unused-vars
283 | /******/ if(!hotAvailableFilesMap[chunkId] || !hotRequestedFilesMap[chunkId])
284 | /******/ return;
285 | /******/ hotRequestedFilesMap[chunkId] = false;
286 | /******/ for(var moduleId in moreModules) {
287 | /******/ if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {
288 | /******/ hotUpdate[moduleId] = moreModules[moduleId];
289 | /******/ }
290 | /******/ }
291 | /******/ if(--hotWaitingFiles === 0 && hotChunksLoading === 0) {
292 | /******/ hotUpdateDownloaded();
293 | /******/ }
294 | /******/ }
295 | /******/
296 | /******/ function hotEnsureUpdateChunk(chunkId) {
297 | /******/ if(!hotAvailableFilesMap[chunkId]) {
298 | /******/ hotWaitingFilesMap[chunkId] = true;
299 | /******/ } else {
300 | /******/ hotRequestedFilesMap[chunkId] = true;
301 | /******/ hotWaitingFiles++;
302 | /******/ hotDownloadUpdateChunk(chunkId);
303 | /******/ }
304 | /******/ }
305 | /******/
306 | /******/ function hotUpdateDownloaded() {
307 | /******/ hotSetStatus("ready");
308 | /******/ var deferred = hotDeferred;
309 | /******/ hotDeferred = null;
310 | /******/ if(!deferred) return;
311 | /******/ if(hotApplyOnUpdate) {
312 | /******/ hotApply(hotApplyOnUpdate).then(function(result) {
313 | /******/ deferred.resolve(result);
314 | /******/ }, function(err) {
315 | /******/ deferred.reject(err);
316 | /******/ });
317 | /******/ } else {
318 | /******/ var outdatedModules = [];
319 | /******/ for(var id in hotUpdate) {
320 | /******/ if(Object.prototype.hasOwnProperty.call(hotUpdate, id)) {
321 | /******/ outdatedModules.push(toModuleId(id));
322 | /******/ }
323 | /******/ }
324 | /******/ deferred.resolve(outdatedModules);
325 | /******/ }
326 | /******/ }
327 | /******/
328 | /******/ function hotApply(options) {
329 | /******/ if(hotStatus !== "ready") throw new Error("apply() is only allowed in ready status");
330 | /******/ options = options || {};
331 | /******/
332 | /******/ var cb;
333 | /******/ var i;
334 | /******/ var j;
335 | /******/ var module;
336 | /******/ var moduleId;
337 | /******/
338 | /******/ function getAffectedStuff(updateModuleId) {
339 | /******/ var outdatedModules = [updateModuleId];
340 | /******/ var outdatedDependencies = {};
341 | /******/
342 | /******/ var queue = outdatedModules.slice().map(function(id) {
343 | /******/ return {
344 | /******/ chain: [id],
345 | /******/ id: id
346 | /******/ };
347 | /******/ });
348 | /******/ while(queue.length > 0) {
349 | /******/ var queueItem = queue.pop();
350 | /******/ var moduleId = queueItem.id;
351 | /******/ var chain = queueItem.chain;
352 | /******/ module = installedModules[moduleId];
353 | /******/ if(!module || module.hot._selfAccepted)
354 | /******/ continue;
355 | /******/ if(module.hot._selfDeclined) {
356 | /******/ return {
357 | /******/ type: "self-declined",
358 | /******/ chain: chain,
359 | /******/ moduleId: moduleId
360 | /******/ };
361 | /******/ }
362 | /******/ if(module.hot._main) {
363 | /******/ return {
364 | /******/ type: "unaccepted",
365 | /******/ chain: chain,
366 | /******/ moduleId: moduleId
367 | /******/ };
368 | /******/ }
369 | /******/ for(var i = 0; i < module.parents.length; i++) {
370 | /******/ var parentId = module.parents[i];
371 | /******/ var parent = installedModules[parentId];
372 | /******/ if(!parent) continue;
373 | /******/ if(parent.hot._declinedDependencies[moduleId]) {
374 | /******/ return {
375 | /******/ type: "declined",
376 | /******/ chain: chain.concat([parentId]),
377 | /******/ moduleId: moduleId,
378 | /******/ parentId: parentId
379 | /******/ };
380 | /******/ }
381 | /******/ if(outdatedModules.indexOf(parentId) >= 0) continue;
382 | /******/ if(parent.hot._acceptedDependencies[moduleId]) {
383 | /******/ if(!outdatedDependencies[parentId])
384 | /******/ outdatedDependencies[parentId] = [];
385 | /******/ addAllToSet(outdatedDependencies[parentId], [moduleId]);
386 | /******/ continue;
387 | /******/ }
388 | /******/ delete outdatedDependencies[parentId];
389 | /******/ outdatedModules.push(parentId);
390 | /******/ queue.push({
391 | /******/ chain: chain.concat([parentId]),
392 | /******/ id: parentId
393 | /******/ });
394 | /******/ }
395 | /******/ }
396 | /******/
397 | /******/ return {
398 | /******/ type: "accepted",
399 | /******/ moduleId: updateModuleId,
400 | /******/ outdatedModules: outdatedModules,
401 | /******/ outdatedDependencies: outdatedDependencies
402 | /******/ };
403 | /******/ }
404 | /******/
405 | /******/ function addAllToSet(a, b) {
406 | /******/ for(var i = 0; i < b.length; i++) {
407 | /******/ var item = b[i];
408 | /******/ if(a.indexOf(item) < 0)
409 | /******/ a.push(item);
410 | /******/ }
411 | /******/ }
412 | /******/
413 | /******/ // at begin all updates modules are outdated
414 | /******/ // the "outdated" status can propagate to parents if they don't accept the children
415 | /******/ var outdatedDependencies = {};
416 | /******/ var outdatedModules = [];
417 | /******/ var appliedUpdate = {};
418 | /******/
419 | /******/ var warnUnexpectedRequire = function warnUnexpectedRequire() {
420 | /******/ console.warn("[HMR] unexpected require(" + result.moduleId + ") to disposed module");
421 | /******/ };
422 | /******/
423 | /******/ for(var id in hotUpdate) {
424 | /******/ if(Object.prototype.hasOwnProperty.call(hotUpdate, id)) {
425 | /******/ moduleId = toModuleId(id);
426 | /******/ var result;
427 | /******/ if(hotUpdate[id]) {
428 | /******/ result = getAffectedStuff(moduleId);
429 | /******/ } else {
430 | /******/ result = {
431 | /******/ type: "disposed",
432 | /******/ moduleId: id
433 | /******/ };
434 | /******/ }
435 | /******/ var abortError = false;
436 | /******/ var doApply = false;
437 | /******/ var doDispose = false;
438 | /******/ var chainInfo = "";
439 | /******/ if(result.chain) {
440 | /******/ chainInfo = "\nUpdate propagation: " + result.chain.join(" -> ");
441 | /******/ }
442 | /******/ switch(result.type) {
443 | /******/ case "self-declined":
444 | /******/ if(options.onDeclined)
445 | /******/ options.onDeclined(result);
446 | /******/ if(!options.ignoreDeclined)
447 | /******/ abortError = new Error("Aborted because of self decline: " + result.moduleId + chainInfo);
448 | /******/ break;
449 | /******/ case "declined":
450 | /******/ if(options.onDeclined)
451 | /******/ options.onDeclined(result);
452 | /******/ if(!options.ignoreDeclined)
453 | /******/ abortError = new Error("Aborted because of declined dependency: " + result.moduleId + " in " + result.parentId + chainInfo);
454 | /******/ break;
455 | /******/ case "unaccepted":
456 | /******/ if(options.onUnaccepted)
457 | /******/ options.onUnaccepted(result);
458 | /******/ if(!options.ignoreUnaccepted)
459 | /******/ abortError = new Error("Aborted because " + moduleId + " is not accepted" + chainInfo);
460 | /******/ break;
461 | /******/ case "accepted":
462 | /******/ if(options.onAccepted)
463 | /******/ options.onAccepted(result);
464 | /******/ doApply = true;
465 | /******/ break;
466 | /******/ case "disposed":
467 | /******/ if(options.onDisposed)
468 | /******/ options.onDisposed(result);
469 | /******/ doDispose = true;
470 | /******/ break;
471 | /******/ default:
472 | /******/ throw new Error("Unexception type " + result.type);
473 | /******/ }
474 | /******/ if(abortError) {
475 | /******/ hotSetStatus("abort");
476 | /******/ return Promise.reject(abortError);
477 | /******/ }
478 | /******/ if(doApply) {
479 | /******/ appliedUpdate[moduleId] = hotUpdate[moduleId];
480 | /******/ addAllToSet(outdatedModules, result.outdatedModules);
481 | /******/ for(moduleId in result.outdatedDependencies) {
482 | /******/ if(Object.prototype.hasOwnProperty.call(result.outdatedDependencies, moduleId)) {
483 | /******/ if(!outdatedDependencies[moduleId])
484 | /******/ outdatedDependencies[moduleId] = [];
485 | /******/ addAllToSet(outdatedDependencies[moduleId], result.outdatedDependencies[moduleId]);
486 | /******/ }
487 | /******/ }
488 | /******/ }
489 | /******/ if(doDispose) {
490 | /******/ addAllToSet(outdatedModules, [result.moduleId]);
491 | /******/ appliedUpdate[moduleId] = warnUnexpectedRequire;
492 | /******/ }
493 | /******/ }
494 | /******/ }
495 | /******/
496 | /******/ // Store self accepted outdated modules to require them later by the module system
497 | /******/ var outdatedSelfAcceptedModules = [];
498 | /******/ for(i = 0; i < outdatedModules.length; i++) {
499 | /******/ moduleId = outdatedModules[i];
500 | /******/ if(installedModules[moduleId] && installedModules[moduleId].hot._selfAccepted)
501 | /******/ outdatedSelfAcceptedModules.push({
502 | /******/ module: moduleId,
503 | /******/ errorHandler: installedModules[moduleId].hot._selfAccepted
504 | /******/ });
505 | /******/ }
506 | /******/
507 | /******/ // Now in "dispose" phase
508 | /******/ hotSetStatus("dispose");
509 | /******/ Object.keys(hotAvailableFilesMap).forEach(function(chunkId) {
510 | /******/ if(hotAvailableFilesMap[chunkId] === false) {
511 | /******/ hotDisposeChunk(chunkId);
512 | /******/ }
513 | /******/ });
514 | /******/
515 | /******/ var idx;
516 | /******/ var queue = outdatedModules.slice();
517 | /******/ while(queue.length > 0) {
518 | /******/ moduleId = queue.pop();
519 | /******/ module = installedModules[moduleId];
520 | /******/ if(!module) continue;
521 | /******/
522 | /******/ var data = {};
523 | /******/
524 | /******/ // Call dispose handlers
525 | /******/ var disposeHandlers = module.hot._disposeHandlers;
526 | /******/ for(j = 0; j < disposeHandlers.length; j++) {
527 | /******/ cb = disposeHandlers[j];
528 | /******/ cb(data);
529 | /******/ }
530 | /******/ hotCurrentModuleData[moduleId] = data;
531 | /******/
532 | /******/ // disable module (this disables requires from this module)
533 | /******/ module.hot.active = false;
534 | /******/
535 | /******/ // remove module from cache
536 | /******/ delete installedModules[moduleId];
537 | /******/
538 | /******/ // remove "parents" references from all children
539 | /******/ for(j = 0; j < module.children.length; j++) {
540 | /******/ var child = installedModules[module.children[j]];
541 | /******/ if(!child) continue;
542 | /******/ idx = child.parents.indexOf(moduleId);
543 | /******/ if(idx >= 0) {
544 | /******/ child.parents.splice(idx, 1);
545 | /******/ }
546 | /******/ }
547 | /******/ }
548 | /******/
549 | /******/ // remove outdated dependency from module children
550 | /******/ var dependency;
551 | /******/ var moduleOutdatedDependencies;
552 | /******/ for(moduleId in outdatedDependencies) {
553 | /******/ if(Object.prototype.hasOwnProperty.call(outdatedDependencies, moduleId)) {
554 | /******/ module = installedModules[moduleId];
555 | /******/ if(module) {
556 | /******/ moduleOutdatedDependencies = outdatedDependencies[moduleId];
557 | /******/ for(j = 0; j < moduleOutdatedDependencies.length; j++) {
558 | /******/ dependency = moduleOutdatedDependencies[j];
559 | /******/ idx = module.children.indexOf(dependency);
560 | /******/ if(idx >= 0) module.children.splice(idx, 1);
561 | /******/ }
562 | /******/ }
563 | /******/ }
564 | /******/ }
565 | /******/
566 | /******/ // Not in "apply" phase
567 | /******/ hotSetStatus("apply");
568 | /******/
569 | /******/ hotCurrentHash = hotUpdateNewHash;
570 | /******/
571 | /******/ // insert new code
572 | /******/ for(moduleId in appliedUpdate) {
573 | /******/ if(Object.prototype.hasOwnProperty.call(appliedUpdate, moduleId)) {
574 | /******/ modules[moduleId] = appliedUpdate[moduleId];
575 | /******/ }
576 | /******/ }
577 | /******/
578 | /******/ // call accept handlers
579 | /******/ var error = null;
580 | /******/ for(moduleId in outdatedDependencies) {
581 | /******/ if(Object.prototype.hasOwnProperty.call(outdatedDependencies, moduleId)) {
582 | /******/ module = installedModules[moduleId];
583 | /******/ moduleOutdatedDependencies = outdatedDependencies[moduleId];
584 | /******/ var callbacks = [];
585 | /******/ for(i = 0; i < moduleOutdatedDependencies.length; i++) {
586 | /******/ dependency = moduleOutdatedDependencies[i];
587 | /******/ cb = module.hot._acceptedDependencies[dependency];
588 | /******/ if(callbacks.indexOf(cb) >= 0) continue;
589 | /******/ callbacks.push(cb);
590 | /******/ }
591 | /******/ for(i = 0; i < callbacks.length; i++) {
592 | /******/ cb = callbacks[i];
593 | /******/ try {
594 | /******/ cb(moduleOutdatedDependencies);
595 | /******/ } catch(err) {
596 | /******/ if(options.onErrored) {
597 | /******/ options.onErrored({
598 | /******/ type: "accept-errored",
599 | /******/ moduleId: moduleId,
600 | /******/ dependencyId: moduleOutdatedDependencies[i],
601 | /******/ error: err
602 | /******/ });
603 | /******/ }
604 | /******/ if(!options.ignoreErrored) {
605 | /******/ if(!error)
606 | /******/ error = err;
607 | /******/ }
608 | /******/ }
609 | /******/ }
610 | /******/ }
611 | /******/ }
612 | /******/
613 | /******/ // Load self accepted modules
614 | /******/ for(i = 0; i < outdatedSelfAcceptedModules.length; i++) {
615 | /******/ var item = outdatedSelfAcceptedModules[i];
616 | /******/ moduleId = item.module;
617 | /******/ hotCurrentParents = [moduleId];
618 | /******/ try {
619 | /******/ __webpack_require__(moduleId);
620 | /******/ } catch(err) {
621 | /******/ if(typeof item.errorHandler === "function") {
622 | /******/ try {
623 | /******/ item.errorHandler(err);
624 | /******/ } catch(err2) {
625 | /******/ if(options.onErrored) {
626 | /******/ options.onErrored({
627 | /******/ type: "self-accept-error-handler-errored",
628 | /******/ moduleId: moduleId,
629 | /******/ error: err2,
630 | /******/ orginalError: err
631 | /******/ });
632 | /******/ }
633 | /******/ if(!options.ignoreErrored) {
634 | /******/ if(!error)
635 | /******/ error = err2;
636 | /******/ }
637 | /******/ if(!error)
638 | /******/ error = err;
639 | /******/ }
640 | /******/ } else {
641 | /******/ if(options.onErrored) {
642 | /******/ options.onErrored({
643 | /******/ type: "self-accept-errored",
644 | /******/ moduleId: moduleId,
645 | /******/ error: err
646 | /******/ });
647 | /******/ }
648 | /******/ if(!options.ignoreErrored) {
649 | /******/ if(!error)
650 | /******/ error = err;
651 | /******/ }
652 | /******/ }
653 | /******/ }
654 | /******/ }
655 | /******/
656 | /******/ // handle errors in accept handlers and self accepted module load
657 | /******/ if(error) {
658 | /******/ hotSetStatus("fail");
659 | /******/ return Promise.reject(error);
660 | /******/ }
661 | /******/
662 | /******/ hotSetStatus("idle");
663 | /******/ return new Promise(function(resolve) {
664 | /******/ resolve(outdatedModules);
665 | /******/ });
666 | /******/ }
667 | /******/
668 | /******/ // The module cache
669 | /******/ var installedModules = {};
670 | /******/
671 | /******/ // objects to store loaded and loading chunks
672 | /******/ var installedChunks = {
673 | /******/ 2: 0
674 | /******/ };
675 | /******/
676 | /******/ // The require function
677 | /******/ function __webpack_require__(moduleId) {
678 | /******/
679 | /******/ // Check if module is in cache
680 | /******/ if(installedModules[moduleId]) {
681 | /******/ return installedModules[moduleId].exports;
682 | /******/ }
683 | /******/ // Create a new module (and put it into the cache)
684 | /******/ var module = installedModules[moduleId] = {
685 | /******/ i: moduleId,
686 | /******/ l: false,
687 | /******/ exports: {},
688 | /******/ hot: hotCreateModule(moduleId),
689 | /******/ parents: (hotCurrentParentsTemp = hotCurrentParents, hotCurrentParents = [], hotCurrentParentsTemp),
690 | /******/ children: []
691 | /******/ };
692 | /******/
693 | /******/ // Execute the module function
694 | /******/ modules[moduleId].call(module.exports, module, module.exports, hotCreateRequire(moduleId));
695 | /******/
696 | /******/ // Flag the module as loaded
697 | /******/ module.l = true;
698 | /******/
699 | /******/ // Return the exports of the module
700 | /******/ return module.exports;
701 | /******/ }
702 | /******/
703 | /******/ // This file contains only the entry chunk.
704 | /******/ // The chunk loading function for additional chunks
705 | /******/ __webpack_require__.e = function requireEnsure(chunkId) {
706 | /******/ var installedChunkData = installedChunks[chunkId];
707 | /******/ if(installedChunkData === 0) {
708 | /******/ return new Promise(function(resolve) { resolve(); });
709 | /******/ }
710 | /******/
711 | /******/ // a Promise means "currently loading".
712 | /******/ if(installedChunkData) {
713 | /******/ return installedChunkData[2];
714 | /******/ }
715 | /******/
716 | /******/ // setup Promise in chunk cache
717 | /******/ var promise = new Promise(function(resolve, reject) {
718 | /******/ installedChunkData = installedChunks[chunkId] = [resolve, reject];
719 | /******/ });
720 | /******/ installedChunkData[2] = promise;
721 | /******/
722 | /******/ // start chunk loading
723 | /******/ var head = document.getElementsByTagName('head')[0];
724 | /******/ var script = document.createElement('script');
725 | /******/ script.type = 'text/javascript';
726 | /******/ script.charset = 'utf-8';
727 | /******/ script.async = true;
728 | /******/ script.timeout = 120000;
729 | /******/
730 | /******/ if (__webpack_require__.nc) {
731 | /******/ script.setAttribute("nonce", __webpack_require__.nc);
732 | /******/ }
733 | /******/ script.src = __webpack_require__.p + "" + ({"0":"app","1":"verdor"}[chunkId]||chunkId) + ".chunk.js";
734 | /******/ var timeout = setTimeout(onScriptComplete, 120000);
735 | /******/ script.onerror = script.onload = onScriptComplete;
736 | /******/ function onScriptComplete() {
737 | /******/ // avoid mem leaks in IE.
738 | /******/ script.onerror = script.onload = null;
739 | /******/ clearTimeout(timeout);
740 | /******/ var chunk = installedChunks[chunkId];
741 | /******/ if(chunk !== 0) {
742 | /******/ if(chunk) {
743 | /******/ chunk[1](new Error('Loading chunk ' + chunkId + ' failed.'));
744 | /******/ }
745 | /******/ installedChunks[chunkId] = undefined;
746 | /******/ }
747 | /******/ };
748 | /******/ head.appendChild(script);
749 | /******/
750 | /******/ return promise;
751 | /******/ };
752 | /******/
753 | /******/ // expose the modules object (__webpack_modules__)
754 | /******/ __webpack_require__.m = modules;
755 | /******/
756 | /******/ // expose the module cache
757 | /******/ __webpack_require__.c = installedModules;
758 | /******/
759 | /******/ // identity function for calling harmony imports with the correct context
760 | /******/ __webpack_require__.i = function(value) { return value; };
761 | /******/
762 | /******/ // define getter function for harmony exports
763 | /******/ __webpack_require__.d = function(exports, name, getter) {
764 | /******/ if(!__webpack_require__.o(exports, name)) {
765 | /******/ Object.defineProperty(exports, name, {
766 | /******/ configurable: false,
767 | /******/ enumerable: true,
768 | /******/ get: getter
769 | /******/ });
770 | /******/ }
771 | /******/ };
772 | /******/
773 | /******/ // getDefaultExport function for compatibility with non-harmony modules
774 | /******/ __webpack_require__.n = function(module) {
775 | /******/ var getter = module && module.__esModule ?
776 | /******/ function getDefault() { return module['default']; } :
777 | /******/ function getModuleExports() { return module; };
778 | /******/ __webpack_require__.d(getter, 'a', getter);
779 | /******/ return getter;
780 | /******/ };
781 | /******/
782 | /******/ // Object.prototype.hasOwnProperty.call
783 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
784 | /******/
785 | /******/ // __webpack_public_path__
786 | /******/ __webpack_require__.p = "/";
787 | /******/
788 | /******/ // on error function for async loading
789 | /******/ __webpack_require__.oe = function(err) { console.error(err); throw err; };
790 | /******/
791 | /******/ // __webpack_hash__
792 | /******/ __webpack_require__.h = function() { return hotCurrentHash; };
793 | /******/ })
794 | /************************************************************************/
795 | /******/ ([]);
796 | //# sourceMappingURL=manifest.js.map
--------------------------------------------------------------------------------