diff --git a/.eslintignore b/.eslintignore
new file mode 100644
index 0000000..aa91c16
--- /dev/null
+++ b/.eslintignore
@@ -0,0 +1 @@
+src/**/*-test.js
diff --git a/.eslintrc b/.eslintrc
index e030fa3..4ff259b 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -1,6 +1,6 @@
{
- "extends": "eslint-config-airbnb",
"parser": "babel-eslint",
+ "extends": "eslint-config-airbnb",
"rules": {
"spaced-comment": [0],
"no-unused-vars": [0],
@@ -12,7 +12,11 @@
"react/prop-types": [0],
"arrow-body-style": [0],
"react/prefer-stateless-function": [0],
- "semi": [0]
+ "semi": [0],
+ "global-require": [0],
+ "no-shadow": [0],
+ "no-useless-computed-key": [0],
+ "no-underscore-dangle": [0]
},
"ecmaFeatures": {
"experimentalObjectRestSpread": true
diff --git a/.gitignore b/.gitignore
index 72579f9..b186605 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,14 +1,3 @@
-# Intellij
-.idea
-*.iml
-*.iws
-
-# Mac
-.DS_Store
-
-# node
-node_modules
-npm-debug.log
-
-#other
dist
+node_modules
+.DS_Store
diff --git a/.lesshintrc b/.lesshintrc
deleted file mode 100644
index 8d51d12..0000000
--- a/.lesshintrc
+++ /dev/null
@@ -1,18 +0,0 @@
-{
- "propertyOrdering": false,
- "hexLength": "short",
- "stringQuotes": false,
- "decimalZero": false,
- "importantRule": false,
- "zeroUnit": "no_unit",
- "qualifyingElement": false,
- "duplicateProperty": false,
- "importPath": false,
- "finalNewline": false,
- "spaceAroundComma": false,
-
- "fileExtensions": [".less", ".css"],
- "excludedFiles": [
- "test.less"
- ]
-}
diff --git a/.stylelintrc b/.stylelintrc
deleted file mode 100644
index 2fe96fd..0000000
--- a/.stylelintrc
+++ /dev/null
@@ -1,15 +0,0 @@
-{
- "extends": "stylelint-config-standard",
- "rules": {
- "string-quotes": "single",
- "selector-pseudo-class-no-unknown": [
- true,
- {
- "ignorePseudoClasses": [
- "global",
- "local"
- ]
- }
- ]
- }
-}
diff --git a/package.json b/package.json
index 70e0cc6..0e6ff5e 100644
--- a/package.json
+++ b/package.json
@@ -1,63 +1,30 @@
{
- "name": "antd-admin",
- "version": "1.0.0",
- "description": "React Admin Boilerplate, with React + Ant Design",
- "license": "Apache-2.0",
- "engines": {
- "node": ">=5.0 <7",
- "npm": ">=3.3 <4"
- },
- "keywords": [
- "ant",
- "react",
- "admin",
- "frontend"
- ],
- "devDependencies": {
- "antd": "1.10.0",
- "babel-core": "6.4.5",
- "babel-eslint": "6.0.0",
- "babel-loader": "6.2.1",
- "babel-plugin-antd": "0.4.0",
- "babel-polyfill": "6.9.1",
- "babel-preset-es2015": "6.3.13",
- "babel-preset-react": "6.3.13",
- "babel-preset-stage-0": "6.5.0",
- "css-loader": "^0.25.0",
- "eslint": "2.7.0",
- "eslint-config-airbnb": "6.x",
- "eslint-plugin-react": "4.x",
- "file-loader": "0.9.0",
- "html-webpack-plugin": "^2.22.0",
- "less": "2.7.1",
- "less-loader": "^2.2.3",
- "lesshint": "2.0.2",
- "react": "15.0.2",
- "react-cookie": "0.4.7",
- "react-dom": "15.0.2",
- "react-hot-loader": "1.3.0",
- "react-router": "2.0.1",
- "reqwest": "^2.0.5",
- "strip-loader": "0.1.2",
- "style-loader": "0.13.1",
- "stylelint": "6.6.0",
- "stylelint-config-standard": "9.0.0",
- "url-loader": "0.5.7",
- "webpack": "1.12.12",
- "webpack-dev-server": "1.14.1"
+ "private": true,
+ "entry": {
+ "index": "./src/index.js"
},
"dependencies": {
- "extract-text-webpack-plugin": "^1.0.1",
- "superagent": "2.0.0",
- "whatwg-fetch": "^1.0.0"
+ "dva": "^1.0.0",
+ "react": "^15.1.0",
+ "react-dom": "^15.1.0"
+ },
+ "devDependencies": {
+ "atool-build": "^0.7.6",
+ "atool-test-mocha": "^0.1.5",
+ "babel-plugin-dev-expression": "^0.2.1",
+ "babel-plugin-dva-hmr": "^0.1.0",
+ "babel-plugin-transform-runtime": "^6.9.0",
+ "babel-runtime": "^6.9.2",
+ "dora": "0.3.x",
+ "dora-plugin-proxy": "^0.7.0",
+ "dora-plugin-webpack": "0.6.x",
+ "dora-plugin-webpack-hmr": "^0.1.0",
+ "expect": "^1.20.2",
+ "redbox-react": "^1.2.10"
},
"scripts": {
- "build": "webpack --progress --colors --display-error-details",
- "prod": "set NODE_ENV=production&&webpack --progress --colors --config webpack.config.prod.js -p --display-error-details",
- "clean": "rd /s /q dist",
- "dev": "webpack-dev-server --devtool eval --progress --colors --content-base dist --hot --inline --display-error-details",
- "eslint": "eslint --ext .js,.jsx src/view",
- "stylelint": "stylelint \"src/**/*.css\"",
- "lesshint": "lesshint src/"
+ "start": "dora --plugins \"proxy,webpack,webpack-hmr\"",
+ "build": "atool-build",
+ "test": "atool-test-mocha ./src/**/*-test.js"
}
-}
\ No newline at end of file
+}
diff --git a/proxy.config.js b/proxy.config.js
new file mode 100644
index 0000000..752cfd7
--- /dev/null
+++ b/proxy.config.js
@@ -0,0 +1,10 @@
+'use strict';
+
+const mock = {};
+
+require('fs').readdirSync(require('path').join(__dirname + '/mock'))
+ .forEach(function (file) {
+ Object.assign(mock, require('./mock/' + file));
+ });
+
+module.exports = mock;
diff --git a/src/components/Example.js b/src/components/Example.js
new file mode 100644
index 0000000..a9bc7a0
--- /dev/null
+++ b/src/components/Example.js
@@ -0,0 +1,14 @@
+import React from 'react';
+
+const Example = (props) => {
+ return (
+
+ Example
+
+ );
+};
+
+Example.propTypes = {
+};
+
+export default Example;
diff --git a/src/index.html b/src/index.html
index f77f60c..f65f403 100644
--- a/src/index.html
+++ b/src/index.html
@@ -1,14 +1,16 @@
-
-
+
-
-
- Ant Design Admin
+
+ Demo
+
-
-
-
+
+
+
+
+
+
diff --git a/src/index.js b/src/index.js
index a4fc05b..2dfdcc0 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,27 +1,18 @@
-import React from 'react'
-import ReactDOM from 'react-dom'
-import {Router, Route, IndexRoute,IndexRedirect,Redirect,hashHistory} from 'react-router'
-import './utils/index.js'
+import './index.html';
+import './index.less';
+import dva from 'dva';
-import App from './view/index'
-import SignIn from './view/user/signIn'
-import List from './view/data/list'
-import Dashboard from './view/user/dashboard'
-import Error from './view/common/error'
-import './utils/lib.less'
+// 1. Initialize
+const app = dva();
-const routes = (
-
-
-
-
-
-
-
-
-
-
-
-)
+// 2. Plugins
+//app.use({});
-ReactDOM.render(routes, document.getElementById('view'))
+// 3. Model
+//app.model(require('./models/example'));
+
+// 4. Router
+app.router(require('./router'));
+
+// 5. Start
+app.start('#root');
diff --git a/src/models/example.js b/src/models/example.js
new file mode 100644
index 0000000..c54bf1c
--- /dev/null
+++ b/src/models/example.js
@@ -0,0 +1,24 @@
+
+export default {
+
+ namespace: 'example',
+
+ state: {},
+
+ subscriptions: {
+ setup({ dispatch, history }) {
+ },
+ },
+
+ effects: {
+ *fetchRemote({ payload }, { call, put }) {
+ },
+ },
+
+ reducers: {
+ fetch(state, action) {
+ return { ...state, ...action.payload };
+ },
+ },
+
+}
diff --git a/src/router.js b/src/router.js
new file mode 100644
index 0000000..13b526a
--- /dev/null
+++ b/src/router.js
@@ -0,0 +1,11 @@
+import React, { PropTypes } from 'react';
+import { Router, Route, IndexRoute, Link } from 'dva/router';
+import IndexPage from './routes/IndexPage';
+
+export default function({ history }) {
+ return (
+
+
+
+ );
+};
diff --git a/src/routes/IndexPage.js b/src/routes/IndexPage.js
new file mode 100644
index 0000000..3214e8c
--- /dev/null
+++ b/src/routes/IndexPage.js
@@ -0,0 +1,22 @@
+import React, { Component, PropTypes } from 'react';
+import { connect } from 'dva';
+import { Link } from 'dva/router';
+import styles from './IndexPage.less';
+
+function IndexPage() {
+ return (
+
+
Welcome to dva!
+
+
+ - To get started, edit
src/index.js and save to reload.
+ - Getting Started
+
+
+ );
+}
+
+IndexPage.propTypes = {
+};
+
+export default connect()(IndexPage);
diff --git a/src/routes/IndexPage.less b/src/routes/IndexPage.less
new file mode 100644
index 0000000..cc48bd6
--- /dev/null
+++ b/src/routes/IndexPage.less
@@ -0,0 +1,8 @@
+
+.normal {
+ margin: 100px;
+}
+
+.list {
+ margin-top: 20px;
+}
diff --git a/src/services/example.js b/src/services/example.js
new file mode 100644
index 0000000..bbf54e3
--- /dev/null
+++ b/src/services/example.js
@@ -0,0 +1,5 @@
+import request from '../utils/request';
+
+export async function query() {
+ return request('/api/users');
+}
diff --git a/src/tests/models/example-test.js b/src/tests/models/example-test.js
new file mode 100644
index 0000000..3b8bd44
--- /dev/null
+++ b/src/tests/models/example-test.js
@@ -0,0 +1,11 @@
+import expect from 'expect';
+import example from '../../models/example';
+
+describe('example', () => {
+
+ describe('reducer', () => {
+ it('it should save', () => {
+ expect(example.reducers['example/save']({}, { payload: { a: 1 }})).toEqual({ a: 1 });
+ });
+ })
+});
diff --git a/src/utils0/request.js b/src/utils0/request.js
new file mode 100644
index 0000000..c808422
--- /dev/null
+++ b/src/utils0/request.js
@@ -0,0 +1,30 @@
+import fetch from 'dva/fetch';
+
+function parseJSON(response) {
+ return response.json();
+}
+
+function checkStatus(response) {
+ if (response.status >= 200 && response.status < 300) {
+ return response;
+ }
+
+ const error = new Error(response.statusText);
+ error.response = response;
+ throw error;
+}
+
+/**
+ * Requests a URL, returning a promise.
+ *
+ * @param {string} url The URL we want to request
+ * @param {object} [options] The options we want to pass to "fetch"
+ * @return {object} An object containing either "data" or "err"
+ */
+export default function request(url, options) {
+ return fetch(url, options)
+ .then(checkStatus)
+ .then(parseJSON)
+ .then((data) => ({ data }))
+ .catch((err) => ({ err }));
+}
diff --git a/webpack.config.js b/webpack.config.js
index 48375ef..f861251 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -1,66 +1,41 @@
-const webpack = require('webpack')
-const HtmlWebpackPlugin = require('html-webpack-plugin')
-const ExtractTextPlugin = require("extract-text-webpack-plugin")
+const fs = require('fs');
+const path = require('path');
-const babelLoaderConfig = {
- presets: ['es2015', 'stage-0', 'react'],
- plugins: [
- ['antd', {
- 'style': true
- }]
- ],
-};
+module.exports = function(webpackConfig, env) {
+ webpackConfig.babel.plugins.push('transform-runtime');
-module.exports = {
- entry: [
- 'webpack-dev-server/client?http://0.0.0.0:8080',
- 'webpack/hot/only-dev-server',
- 'babel-polyfill',
- './src/index.js'
- ],
+ // Support hmr
+ if (env === 'development') {
+ webpackConfig.devtool = '#eval';
+ webpackConfig.babel.plugins.push(['dva-hmr', {
+ entries: [
+ './src/index.js',
+ ],
+ }]);
+ } else {
+ webpackConfig.babel.plugins.push('dev-expression');
+ }
- output: {
- path: __dirname + '/dist',
- filename: 'bundle.js',
- },
+ // Support CSS Modules
+ // Parse all less files as css module.
+ webpackConfig.module.loaders.forEach(function(loader, index) {
+ if (typeof loader.test === 'function' && loader.test.toString().indexOf('\\.less$') > -1) {
+ loader.include = /node_modules/;
+ loader.test = /\.less$/;
+ }
+ if (loader.test.toString() === '/\\.module\\.less$/') {
+ loader.exclude = /node_modules/;
+ loader.test = /\.less$/;
+ }
+ if (typeof loader.test === 'function' && loader.test.toString().indexOf('\\.css$') > -1) {
+ loader.include = /node_modules/;
+ loader.test = /\.css$/;
+ }
+ if (loader.test.toString() === '/\\.module\\.css$/') {
+ loader.exclude = /node_modules/;
+ loader.test = /\.css$/;
+ }
+ });
- resolve: {
- modulesDirectories: ['node_modules', './src'],
- extensions: ['', '.js', '.jsx'],
- alias: {
- antdcss: 'antd/dist/antd.min.css',
- },
- },
-
- module: {
- loaders: [{
- test: /\.jsx?$/,
- loaders: ['react-hot', 'babel-loader?' + JSON.stringify(babelLoaderConfig)],
- exclude: /node_modules/,
- },
- {
- test: /\.css$/,
- loader: ExtractTextPlugin.extract("style-loader", "css-loader")
- }, {
- test: /\.less$/,
- loader: ExtractTextPlugin.extract("style-loader", "css-loader!less-loader")
- },
- {
- test: /\.(png|jpg|svg)$/,
- loader: 'url?limit=25000',
- },
- ],
- },
-
- plugins: [
- new HtmlWebpackPlugin({
- title: 'Ant Design Admin',
- filename: 'index.html',
- template: './src/index.html'
- }),
- new ExtractTextPlugin("[name].css"),
- new webpack.DefinePlugin({
- __DEV__: JSON.stringify(JSON.parse(process.env.NODE_ENV === 'production' ? 'false' : 'true')),
- }),
- ],
+ return webpackConfig;
};
diff --git a/webpack.config.prod.js b/webpack.config.prod.js
deleted file mode 100644
index 7376467..0000000
--- a/webpack.config.prod.js
+++ /dev/null
@@ -1,66 +0,0 @@
-const webpack = require('webpack')
-const HtmlWebpackPlugin = require('html-webpack-plugin')
-const ExtractTextPlugin = require("extract-text-webpack-plugin")
-
-const babelLoaderConfig = {
- presets: ['es2015', 'stage-0', 'react'],
- plugins: [['antd', {'style': true}]],
-};
-
-module.exports = {
- entry: [
- './src/index.js',
- ],
-
- output: {
- path: __dirname + '/dist',
- filename: 'bundle.js',
- // publicPath: 'http://mycdn.com/',
- },
-
- resolve: {
- modulesDirectories: ['node_modules', './src'],
- extensions: ['', '.js', '.jsx'],
- },
-
- module: {
- loaders: [
- {
- test: /\.jsx?$/,
- loaders: ['babel-loader?' + JSON.stringify(babelLoaderConfig), 'strip-loader?strip[]=logger.debug,strip[]=console.log,strip[]=console.debug'],
- exclude: /node_modules/,
- },
- {
- test: /\.(png|jpg|svg)$/,
- loader: 'url?limit=25000',
- },{
- test: /\.css$/,
- loader: ExtractTextPlugin.extract("style-loader", "css-loader")
- }, {
- test: /\.less$/,
- loader: ExtractTextPlugin.extract("style-loader", "css-loader!less-loader")
- },
- ],
- },
-
- plugins: [
- new webpack.optimize.UglifyJsPlugin({
- minimize: true,
- compress: {warnings: false},
- }),
- new HtmlWebpackPlugin({
- title: 'Ant Design Admin',
- filename: 'index.html',
- template: './src/index.html'
- }),
- new ExtractTextPlugin("[name].css"),
- new webpack.optimize.DedupePlugin(),
- new webpack.optimize.OccurenceOrderPlugin(),
- new webpack.optimize.AggressiveMergingPlugin(),
- new webpack.NoErrorsPlugin(),
- new webpack.DefinePlugin({
- 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
- __DEV__: JSON.stringify(JSON.parse(process.env.NODE_ENV === 'production' ? 'false' : 'true')),
- }),
- ],
-};