Commit 8e5147ef authored by nano's avatar nano

init

parents
# http://editorconfig.org
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
[Makefile]
indent_style = tab
{
"parser": "babel-eslint",
"extends": "airbnb",
"rules": {
"generator-star-spacing": [0],
"consistent-return": [0],
"react/forbid-prop-types": [0],
"react/jsx-filename-extension": [1, { "extensions": [".js"] }],
"global-require": [1],
"import/prefer-default-export": [0],
"react/jsx-no-bind": [0],
"react/prop-types": [0],
"react/prefer-stateless-function": [0],
"no-else-return": [0],
"no-restricted-syntax": [0],
"import/no-extraneous-dependencies": [0],
"no-use-before-define": [0],
"jsx-a11y/no-static-element-interactions": [0],
"no-nested-ternary": [0],
"arrow-body-style": [0],
"import/extensions": [0],
"no-bitwise": [0],
"no-cond-assign": [0],
"import/no-unresolved": [0],
"require-yield": [1]
},
"parserOptions": {
"ecmaFeatures": {
"experimentalObjectRestSpread": true
}
}
}
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
# production
/dist
# misc
.DS_Store
npm-debug.log*
{
"entry": "src/index.js",
"env": {
"development": {
"extraBabelPlugins": [
"dva-hmr",
"transform-runtime",
["import", { "libraryName": "antd", "style": "css" }]
]
},
"production": {
"extraBabelPlugins": [
"transform-runtime",
["import", { "libraryName": "antd", "style": "css" }]
]
}
}
}
export default {
};
{
"en": {
"Apps" : "Apps"
},
"zh": {
"Apps" : "应用"
}
}
\ No newline at end of file
{
"private": true,
"scripts": {
"start": "roadhog server",
"build": "roadhog build",
"lint": "eslint --ext .js src test",
"precommit": "npm run lint"
},
"engines": {
"install-node": "6.9.2"
},
"dependencies": {
"antd": "^2.8.2",
"babel-runtime": "^6.9.2",
"dva": "^1.2.1",
"react": "^15.4.0",
"react-dom": "^15.4.0",
"react-intl": "^2.2.3"
},
"devDependencies": {
"babel-eslint": "^7.1.1",
"babel-plugin-dva-hmr": "^0.3.2",
"babel-plugin-import": "^1.1.1",
"babel-plugin-transform-runtime": "^6.9.0",
"eslint": "^3.12.2",
"eslint-config-airbnb": "^13.0.0",
"eslint-plugin-import": "^2.2.0",
"eslint-plugin-jsx-a11y": "^2.2.3",
"eslint-plugin-react": "^6.8.0",
"expect": "^1.20.2",
"husky": "^0.12.0",
"redbox-react": "^1.3.2",
"roadhog": "^0.5.2"
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Dva Demo</title>
<link rel="stylesheet" href="index.css" />
</head>
<body>
<div id="root"></div>
<script src="index.js"></script>
</body>
</html>
import React from 'react';
const Example = () => {
return (
<div>
Example
</div>
);
};
Example.propTypes = {
};
export default Example;
import React from 'react';
import styles from './Haha.css';
function Haha() {
return (
<div className={styles.normal}>
Component: Haha
</div>
);
}
export default Haha;
export default {
apiRoot: 'http://localhost:8081',
}
\ No newline at end of file
html, body, :global(#root) {
height: 100%;
}
import dva from 'dva';
import ReactDOM from 'react-dom';
import { browserHistory } from 'dva/router'
import './index.css';
import { IntlProvider, addLocaleData } from 'react-intl';
// 1. Initialize
const app = dva({
history: browserHistory
});
app.model(require("./models/user"));
app.model(require("./models/auth"));
app.model(require("./models/haha"));
// app.model(require("./models/login"));
app.model(require("./models/common"));
// 2. Plugins
// app.use({});
// 3. Model
// app.model(require('./models/example'));
// 4. Router
app.router(require('./router'));
// 5. Start
import en from 'react-intl/locale-data/en'
import zh from 'react-intl/locale-data/zh'
import localeData from '../i18n.json'
addLocaleData([...en, ...zh])
const language = navigator.language || (navigator.languages && navigator.languages[0]) || navigator.userLanguage;
const languageWithoutRegionCode = language.toLowerCase().split(/[_-]+/)[0];
const messages = localeData[languageWithoutRegionCode] || localeData[language] || localeData.zh;
const App = app.start()
ReactDOM.render(
<IntlProvider locale={ language } messages={ messages }>
<App />
</IntlProvider>,
document.getElementById("root")
)
import { login, forgot, register, reset } from '../services/auth'
import { message } from 'antd'
export default {
namespace: 'auth',
state: {
isSubmit: false,
register:{}
},
reducers: {
change(state, action) {
return {
...state, ...action.payload
}
}
},
effects: {
*login({ payload }, { call, put }) {
const {data} = yield call(login, payload)
if(data){
yield put({ type: 'loginSuccess'})
message.info(data["message"])
} else {
yield put({ type: 'loginFail'})
message.error("登陆失败")
}
},
*forgot({ payload }, { call, put }) {
const { data } = yield call(forgot, payload)
if(data)
{
yield put({ type: 'forgotSuccess'})
message.info(data["message"])
}else {
yield put({ type: 'forgotFail' })
message.error("邮件发送失败")
}
},
*register({ payload }, { call, put }) {
const { data } = yield call(register, payload)
if(data) {
yield put({ type: 'change', payload: { register: data}})
}
// if(data){
// yield put({ type: 'registerSuccess' })
// message.info(data["message"])
// }
},
*reset({ payload }, { call, put }) {
const { data } = yield call(reset, payload)
if(data)
{
yield put({ type: 'resetSuccess' })
message.info(data["message"])
}else{
yield put({ type: 'resetFail' })
message.error("重置失败")
}
},
},
subscriptions: {},
};
export default {
namespace: 'common',
state: {
},
reducers: {
},
effects: {},
subscriptions: {},
};
export default {
namespace: 'example',
state: {},
subscriptions: {
setup({ dispatch, history }) { // eslint-disable-line
},
},
effects: {
*fetch({ payload }, { call, put }) { // eslint-disable-line
yield put({ type: 'save' });
},
},
reducers: {
save(state, action) {
return { ...state, ...action.payload };
},
},
};
export default {
namespace: 'haha',
state: {
text: '123213213'
},
reducers: {
change(state, action) {
return {
...state, ...action.payload
}
}
},
effects: {},
subscriptions: {},
};
export default {
namespace: 'user',
state: {
},
reducers: {},
effects: {
},
subscriptions: {},
};
import React from 'react';
import { Router, Route, Redirect } from 'dva/router';
import IndexPage from './routes/IndexPage';
import Login from "./routes/Login.js";
import Forgot from "./routes/Forgot.js";
import Register from "./routes/Register.js";
import Reset from "./routes/Reset.js";
import Profiles from "./routes/Profiles.js";
function RouterConfig({ history }) {
return (
<Router history={history}>
<Redirect from="/" to="/login"/>
<Route path="/">
<Route path="/login" component={Login} />
<Route path="/forgot" component={Forgot} />
<Route path="/register" component={Register} />
<Route path="/reset" component={Reset} />
<Route path="/profiles" component={Profiles} />
</Route>
</Router>
);
}
export default RouterConfig;
import React from 'react';
import { connect } from 'dva';
import { Link } from 'dva/router'
import styles from './Login.less';
import { Form, Input, Tooltip, Icon, Cascader, Select, Row, Col, Checkbox, Button } from 'antd';
const FormItem = Form.Item;
const Option = Select.Option;
const formItemLayout = {
labelCol: {
xs: { span: 24 },
sm: { span: 6 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 14 },
},
};
class Login extends React.Component {
onSubmitLogin = (e) => {
const { form, dispatch, params: { id }} = this.props
e && e.preventDefault();
form.validateFieldsAndScroll((err, values) => {
if (!err) {
console.log('Received values of form: ', values);
const {email} = values
dispatch({type: "auth/forgot", payload: {emailOrUsername: email}})
}
});
}
render() {
const { getFieldDecorator, dispatch } = this.props.form;
return (
<div style={{ display: 'flex', justifyContent:'center', alignItems: 'center', height: '100%'}}>
<Form onSubmit={this.onSubmitLogin} className="login-form">
<FormItem>
{getFieldDecorator('email', {
rules: [{ required: true, message: 'Please input your email!' }],
})(
<Input prefix={<Icon type="user" style={{ fontSize: 13 }} />} placeholder="email" />
)}
</FormItem>
<Button type="primary" htmlType="submit" className="login-form-button">
Send
</Button>
Or <Link to="/login">Sign In</Link>
</Form>
</div>
)
}
}
function mapStateToProps() {
return {};
}
const WrapperLogin = Form.create()(Login)
export default connect(mapStateToProps)(WrapperLogin);
.normal {
font-family: Georgia, sans-serif;
margin-top: 3em;
text-align: center;
}
.title {
font-size: 2.5rem;
font-weight: normal;
letter-spacing: -1px;
}
.welcome {
height: 328px;
background: url(../assets/yay.jpg) no-repeat center 0;
background-size: 388px 328px;
}
.list {
font-size: 1.2em;
margin-top: 1.8em;
list-style: none;
line-height: 1.5em;
}
.list code {
background: #f7f7f7;
}
import React from 'react';
import { connect } from 'dva';
import styles from './IndexPage.css';
function IndexPage() {
return (
<div className={styles.normal}>
<h1 className={styles.title}>Yay! Welcome to dva!</h1>
<div className={styles.welcome} />
<ul className={styles.list}>
<li>To get started, edit <code>src/index.js</code> and save to reload.</li>
<li><a href="https://github.com/dvajs/dva-docs/blob/master/v1/en-us/getting-started.md">Getting Started</a></li>
</ul>
</div>
);
}
IndexPage.propTypes = {
};
export default connect()(IndexPage);
import React from 'react';
import { connect } from 'dva';
import { Link } from 'dva/router'
import styles from './Login.less';
import { Form, Input, Tooltip, Icon, Cascader, Select, Row, Col, Checkbox, Button } from 'antd';
const FormItem = Form.Item;
const Option = Select.Option;
const formItemLayout = {
labelCol: {
xs: { span: 24 },
sm: { span: 6 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 14 },
},
};
class Login extends React.Component {
onSubmitLogin = (e) => {
const { form, dispatch, params: { id }} = this.props
e && e.preventDefault();
form.validateFieldsAndScroll((err, values) => {
if (!err) {
console.log('Received values of form: ', values);
const {username, password} = values
dispatch({type: "auth/login", payload: {emailOrUsername: username, password}})
}
});
}
render() {
const { getFieldDecorator, dispatch } = this.props.form;
return (
<div style={{ display: 'flex', justifyContent:'center', alignItems: 'center', height: '100%'}}>
<Form onSubmit={this.onSubmitLogin} className="login-form">
<FormItem>
{getFieldDecorator('username', {
rules: [{ required: true, message: 'Please input your username!' }],
})(
<Input prefix={<Icon type="user" style={{ fontSize: 13 }} />} placeholder="Username" />
)}
</FormItem>
<FormItem>
{getFieldDecorator('password', {
rules: [{ required: true, message: 'Please input your Password!' }],
})(
<Input prefix={<Icon type="lock" style={{ fontSize: 13 }} />} type="password" placeholder="Password" />
)}
</FormItem>
<FormItem>
{getFieldDecorator('remember', {
valuePropName: 'checked',
initialValue: true,
})(
<Checkbox>Remember me</Checkbox>
)}
<Link to="/forgot" className="login-form-forgot">Forgot password</Link>
<Button type="primary" htmlType="submit" className="login-form-button">
Log in
</Button>
Or <Link to="/register">register now!</Link>
</FormItem>
</Form>
</div>
)
}
}
function mapStateToProps() {
return {};
}
const WrapperLogin = Form.create()(Login)
export default connect(mapStateToProps)(WrapperLogin);
:global {
.login-form {
max-width: 300px;
}
.login-form-forgot {
float: right;
}
.login-form-button {
width: 100%;
}
}
.normal {
}
import React from 'react';
import { connect } from 'dva';
import styles from './Profiles.css';
function Profiles({ dispatch, text }) {
return (
<div className={styles.normal} onClick={() => dispatch({type: 'haha/change', payload: { text: Math.random() }})}>
Route Component: {text}
</div>
);
}
function mapStateToProps(state) {
const {
haha: {text}
} = state
return {
text
};
}
export default connect(mapStateToProps)(Profiles);
import React from 'react';
import { connect } from 'dva';
import { Link } from 'dva/router'
import styles from './Login.less';
import { Form, Input, Tooltip, Icon, Cascader, Select, Row, Col, Checkbox, Button } from 'antd';
const FormItem = Form.Item;
const Option = Select.Option;
const formItemLayout = {
labelCol: {
xs: { span: 24 },
sm: { span: 6 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 14 },
},
};
class Login extends React.Component {
onSubmitLogin = (e) => {
const { form, dispatch, isSubmit, params: { id }} = this.props
e && e.preventDefault();
form.validateFieldsAndScroll((err, values) => {
if (!err) {
console.log('Received values of form: ', values);
const {email, username, nickname, password, confirm} = values
dispatch({type: "auth/register", payload: {email, username, nickname, password, password2: confirm, submit: isSubmit}})
}
});
}
checkPassword = (rule, value, callback) => {
const form = this.props.form;
if (value && value !== form.getFieldValue('password')) {
callback('Two passwords that you enter is inconsistent!');
} else {
callback();
}
}
checkConfirm = (rule, value, callback) => {
const form = this.props.form;
if (value) {
form.validateFields(['confirm'], { force: true });
}
callback();
}
checkUsername = (rule, value, callback) => {
const { form, dispatch } = this.props
callback();
}
checkEmail= (rule, value, callback) => {
const form = this.props.form;
if (value && value !== form.getFieldValue('password')) {
callback('Two passwords that you enter is inconsistent!');
} else {
callback();
}
}
render() {
const { getFieldDecorator, dispatch } = this.props.form;
return (
<div style={{ display: 'flex', justifyContent:'center', alignItems: 'center', height: '100%'}}>
<Form onSubmit={this.onSubmitLogin} className="login-form">
<FormItem hasFeedback >
{getFieldDecorator('email', {
rules: [{ required: true, message: 'Please input your email!' }],
}, {
validator: this.checkEmail
})(
<Input placeholder="Email" />
)}
</FormItem>
<FormItem hasFeedback >
{getFieldDecorator('username', {
rules: [{ required: true, message: 'Please input your username!' }],
}, {
validator: this.checkUsername
})(
<Input placeholder="Username" />
)}
</FormItem>
<FormItem hasFeedback >
{getFieldDecorator('nickname', {
rules: [{ required: true, message: 'Please input your nickname!' }],
})(
<Input placeholder="nickname[optional]" />
)}
</FormItem>
<FormItem hasFeedback >
{getFieldDecorator('password', {
rules: [{ required: true, message: 'Please input your Password!' }],
}, {
validator: this.checkConfirm
})(
<Input prefix={<Icon type="lock" style={{ fontSize: 13 }} />} type="password" placeholder="Password" />
)}
</FormItem>
<FormItem hasFeedback >
{getFieldDecorator('confirm', {
rules: [{
required: true, message: 'Please confirm your password!',
}, {
validator: this.checkPassword,
}],
})(
<Input type="password" onBlur={this.handleConfirmBlur} placeholder="Password Again" />
)}
</FormItem>
<Button type="primary" htmlType="submit" className="login-form-button">
Register
</Button>
Or <Link to="/login">Sign in!</Link>
</Form>
</div>
)
}
}
function mapStateToProps(state) {
const {
auth: { isSubmit, register }
} = state
return {
isSubmit,
register
};
}
const WrapperLogin = Form.create()(Login)
export default connect(mapStateToProps)(WrapperLogin);
import React from 'react';
import { connect } from 'dva';
import { Link } from 'dva/router'
import styles from './Login.less';
import { Form, Input, Tooltip, Icon, Cascader, Select, Row, Col, Checkbox, Button } from 'antd';
const FormItem = Form.Item;
const Option = Select.Option;
const formItemLayout = {
labelCol: {
xs: { span: 24 },
sm: { span: 6 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 14 },
},
};
class Reset extends React.Component {
onSubmitReset = (e) => {
const { form, dispatch, location: { query: { key, user_id }}} = this.props
e && e.preventDefault();
form.validateFieldsAndScroll((err, values) => {
if (!err) {
console.log('Received values of form: ', values);
const {password} = values
console.log(this.props)
dispatch({type: "auth/reset", payload: { password, key, user_id}})
}
});
}
checkPassword = (rule, value, callback) => {
const form = this.props.form;
if (value && value !== form.getFieldValue('password')) {
callback('Two passwords that you enter is inconsistent!');
} else {
callback();
}
}
checkConfirm = (rule, value, callback) => {
const form = this.props.form;
if (value) {
form.validateFields(['confirm'], { force: true });
}
callback();
}
render() {
const { getFieldDecorator, dispatch } = this.props.form;
return (
<div style={{ display: 'flex', justifyContent:'center', alignItems: 'center', height: '100%'}}>
<Form onSubmit={this.onSubmitReset} className="login-form">
<FormItem>
{getFieldDecorator('password', {
rules: [{ required: true, message: 'Please input your Password!' }],
}, {
validator: this.checkConfirm
})(
<Input prefix={<Icon type="lock" style={{ fontSize: 13 }} />} type="password" placeholder="Password" />
)}
</FormItem>
<FormItem>
{getFieldDecorator('confirm', {
rules: [{
required: true, message: 'Please confirm your password!',
}, {
validator: this.checkPassword,
}],
})(
<Input type="password" onBlur={this.handleConfirmBlur} placeholder="Password Again" />
)}
</FormItem>
<Button type="primary" htmlType="submit" className="login-form-button">
Submit
</Button>
</Form>
</div>
)
}
}
function mapStateToProps(state, props) {
return {};
}
const WrapperReset = Form.create()(Reset)
export default connect(mapStateToProps)(WrapperReset);
import request from '../utils/request';
import config from '../config'
export async function login(params) {
return request(`/sign_in.php`, {
method: 'POST',
body: JSON.stringify(params)
})
}
export async function forgot(params) {
return request(`/forgot_password.php`, {
method: 'POST',
body: JSON.stringify(params)
})
}
export async function register(params) {
return request(`/sign_up.php`, {
method: 'POST',
body: JSON.stringify(params)
})
}
export async function reset(params) {
return request(`/reset_password.php`, {
method: 'POST',
body: JSON.stringify(params)
})
}
import request from '../utils/request';
export async function query() {
return request('/api/users');
}
import fetch from 'dva/fetch';
import config from '../config';
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) {
url = `${config.apiRoot}${url}`
if(options && !options.headers && (options.method == 'POST' || options.method == 'PATCH')) {
options.headers = {
"content-type": "application/json"
}
}
console.log(options)
return fetch(url, options)
.then(checkStatus)
.then(parseJSON)
.then(data => ({ data }))
.catch(err => ({ err }));
}
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment