Commit b007630f authored by nano's avatar nano

complete

parent 57f88105
import React from 'react';
import styles from './EmailForm.css';
import {connect} from 'react-redux'
import { Form, Input, Icon, Button } from 'antd'
import { connect } from 'react-redux'
import { Form, Input, Icon, Button, Modal } from 'antd'
const FormItem = Form.Item;
import SubmitButton from './SubmitButton'
......@@ -14,25 +14,25 @@ const formItemLayout = {
class EmailForm extends React.Component {
onSubmit = (e) => {
const { form, dispatch, data: {id} } = this.props
const { form, dispatch, data: { id } } = this.props
e && e.preventDefault();
form.validateFieldsAndScroll((err, values) => {
if (!err) {
console.log('Received values of form: ', values);
const { email, password } = values
dispatch({type: "user/updateEmail", payload: { email, password, user_id: id }})
dispatch({ type: "user/updateEmail", payload: { email, password, user_id: id } })
}
});
}
render(){
render() {
const {form, dispatch, data, checkEmail, isEmailExists} = this.props
const {getFieldDecorator} = form
const {id, email} = data
const { form, dispatch, data, checkEmail, isEmailExists, isSendEmailActive } = this.props
const { getFieldDecorator } = form;
const { id, email } = data;
const emailProps = {
fromItem: {
......@@ -43,7 +43,7 @@ class EmailForm extends React.Component {
...formItemLayout
},
decorator: {
initialValue: email
initialValue: email
},
input: {
placeholder: "email"
......@@ -52,7 +52,7 @@ class EmailForm extends React.Component {
const passwordProps = {
fromItem: {
label: "passwrod",
label: "passwrod",
...formItemLayout
},
decorator: {
......@@ -65,20 +65,14 @@ class EmailForm extends React.Component {
type: 'password'
}
}
return (
<Form onSubmit={this.onSubmit}>
<FormItem {...emailProps.fromItem}>
{getFieldDecorator(`email`, {...emailProps.decorator})(
<Input
{...emailProps.input}
onBlur = {() => dispatch({type: 'auth/checkEmail', payload: { ...form.getFieldsValue(), id} })}/>
)}
</FormItem>
<FormItem {...passwordProps.fromItem}>
{getFieldDecorator(`password`, {...passwordProps.decorator})(
<Input {...passwordProps.input} />
{getFieldDecorator('email', { ...emailProps.decorator })(
<Input
{...emailProps.input}
onBlur={() => dispatch({ type: 'auth/checkEmail', payload: { ...form.getFieldsValue(), id } })} />
)}
</FormItem>
......@@ -94,13 +88,14 @@ class EmailForm extends React.Component {
function mapStateToProps(state, props) {
const {
user: {data},
auth: {isEmailExists, checkEmail}
user: { data },
auth: { isEmailExists, checkEmail, isSendEmailActive }
} = state
return {
data,
checkEmail,
isEmailExists
isEmailExists,
isSendEmailActive
};
}
......
......@@ -2,10 +2,10 @@ import { Button } from 'antd';
import React from 'react';
import styles from './SubmitButton.css';
function SubmitButton() {
function SubmitButton(props) {
return (
<div className={styles.wrapSubmit}>
<Button type="primary" htmlType="submit" size="large">提交</Button>
<Button type="primary" htmlType="submit" size="large" {...props} >提交</Button>
</div>
);
}
......
export default {
// apiRoot: 'http://localhost:3000',
apiRoot: 'http://192.168.1.126:3000',
apiRoot: 'http://localhost:3000',
};
html, body, :global(#root) {
height: 100%;
}
import dva from 'dva';
import ReactDOM from 'react-dom';
import { browserHistory } from 'dva/router'
import { message } from 'antd'
import './index.css';
import { browserHistory } from 'dva/router';
import { message } from 'antd';
import createLoading from 'dva-loading'
import './index.less';
import { IntlProvider, addLocaleData } from 'react-intl';
......@@ -15,6 +16,8 @@ const app = dva({
history: browserHistory
});
app.use(createLoading())
app.model(require('./models/user'));
......@@ -42,14 +45,20 @@ import zh from 'react-intl/locale-data/zh'
import localeData from '../i18n.json'
addLocaleData([...en, ...zh]);
/*eslint-disable */
const language = navigator.language || (navigator.languages && navigator.languages[0]) || navigator.userLanguage;
let language = navigator.language || (navigator.languages && navigator.languages[0]) || navigator.userLanguage;
/*eslint-enable */
const languageWithoutRegionCode = language.toLowerCase().split(/[_-]+/)[0];
const messages = localeData[languageWithoutRegionCode] || localeData[language] || localeData.zh;
if(localStorage.getItem('locale')){
language = JSON.parse(localStorage.getItem('locale'))
}
const App = app.start();
ReactDOM.render(
<IntlProvider locale={ language } messages={ messages }>
......
html, body, :global(#root) {
height: 100%;
}
:global {
.example-enter {
opacity: 0.01;
}
.example-enter.example-enter-active {
opacity: 1;
transition: opacity 500ms ease-in;
}
.example-leave {
opacity: 1;
}
.example-leave.example-leave-active {
opacity: 0.01;
transition: opacity 300ms ease-in;
}
}
\ No newline at end of file
import { login, forgot, register, reset, activate, checkUserExists } from '../services/auth'
import { message } from 'antd'
import { routerRedux } from 'dva/router'
export default {
namespace: 'auth',
state: {
input:{},
activateState: false,
checkEmail: '',
checkUsername: '',
......@@ -80,7 +83,7 @@ export default {
},
loginSuccess(state, action) {
return {
...state, ...{
...state, ...action.payload, ...{
isLoginSubmit: false,
}
};
......@@ -137,37 +140,48 @@ export default {
},
effects: {
*activate({ payload }, { call, put }) {
const { data } = yield call(activate, payload)
try {
const { data } = yield call(activate, payload)
if(data) {
message.success("激活成功")
}
} catch (error) {
message.error(error.message)
}
},
*checkEmail({ payload }, { call, put }) {
const { data } = yield call(checkUserExists, payload)
console.log(data);
if(data) {
yield put({ type: 'check', payload: { isEmailExists: true , checkEmail: 'warning'}})
} else {
yield put({ type: 'check', payload: { isEmailExists: false , checkEmail: 'success'}})
try {
const { data } = yield call(checkUserExists, payload)
if (data) {
yield put({ type: 'check', payload: { isEmailExists: true, checkEmail: 'warning' } })
}
} catch (error) {
yield put({ type: 'check', payload: { isEmailExists: false, checkEmail: 'success' } })
}
},
*checkUsername({ payload }, { call, put }) {
const { data } = yield call(checkUserExists, payload)
try {
const { data } = yield call(checkUserExists, payload)
if (data) {
yield put({ type: 'check', payload: { isUserNameExists: true, checkUsername: 'warning' } })
}
} catch (error) {
yield put({ type: 'check', payload: { isUserNameExists: false, checkUsername: 'success' } })
if(data) {
yield put({ type: 'check', payload: { isUserNameExists: true , checkUsername: 'warning'}})
} else {
yield put({ type: 'check', payload: { isUserNameExists: false , checkUsername: 'success'}})
}
},
*login({ payload }, { call, put }) {
const {data} = yield call(login, payload)
if(data){
yield put({ type: 'loginSuccess' })
try {
const { data } = yield call(login, payload)
if (data) {
yield put({ type: 'loginSuccess', payload: { input: payload } })
yield put({ type: 'user/loginSuccess', payload: { data } })
message.info("登录成功")
} else {
yield put({ type: 'loginFail' })
message.error("登陆失败")
}
} catch (error) {
yield put({ type: 'loginFail' })
message.error(error.message)
}
},
*forgot({ payload }, { call, put }) {
try {
......@@ -182,26 +196,30 @@ export default {
}
},
*register({ payload }, { call, put }) {
const {data} = yield call(register, payload)
if(data) {
yield put({ type: 'registerSuccess'})
message.info("注册成功")
} else {
yield put({ type: 'registerFail' })
message.error("注册失败")
}
try {
const { data } = yield call(register, payload)
if (data) {
yield put({ type: 'registerSuccess' })
message.info("注册成功, 请验证激活邮件~", 3)
yield put(routerRedux.replace("/verify"))
}
} catch (error) {
yield put({ type: 'registerFail' })
message.error("注册失败")
}
},
*reset({ payload }, { call, put }) {
const { data } = yield call(reset, payload)
if(data){
try {
const { data } = yield call(reset, payload)
if (data) {
yield put({ type: 'resetSuccess' })
message.info("重置成功")
}else{
yield put({ type: 'resetFail' })
message.error("重置失败")
}
} catch (error) {
yield put({ type: 'resetFail' })
message.error("重置失败")
}
},
},
subscriptions: {},
......
......@@ -66,15 +66,26 @@ export default {
effects: {
*loginSuccess({ payload }, { call, put }) {
localStorage.setItem("user", JSON.stringify(payload.data))
const {data} = payload
yield put(routerRedux.replace("/profiles"))
if(!data) {
message.error("error ")
}
if(data.active) {
yield put(routerRedux.replace("/profiles"))
message.info("登录成功")
localStorage.setItem("user", JSON.stringify(payload.data))
} else {
yield put(routerRedux.replace(`/verify`))
}
},
*preLogin({ payload }, { call, put }) {
let user = localStorage.getItem("user")
if (!user) {
yield put(routerRedux.replace("/login"))
yield put(routerRedux.replace("/signin"))
}
yield put({ type: 'loginFromStorage', payload: { data: JSON.parse(user) } })
......
import { Redirect, Route, Router } from 'dva/router';
import QueueAnim from 'rc-queue-anim'
import React from 'react';
import Active from './routes/Activate.js';
......@@ -13,18 +14,21 @@ import Register from './routes/Register.js';
import Reset from './routes/Reset.js';
import Verify from "./routes/Verify.js";
function RouterConfig({ history }) {
return (
<Router history={history}>
<Redirect from="/" to="/login"/>
<Redirect from="/" to="/signin"/>
<Route path="/">
<Route path="/login" component={Login}/>
<Route path="/signin" component={Login}/>
<Route path="/forgot" component={Forgot}/>
<Route path="/register" component={Register}/>
<Route path="/reset" component={Reset}/>
<Route path="/profiles" component={Profiles}/>
</Route>
<Route path="/activate" component={Active}/>
<Route path="/verify" component={Verify} />
</Router>
);
}
......
......@@ -11,10 +11,10 @@ class Active extends React.Component {
};
render() {
const { activateState } = this.props;
const { loading } = this.props;
return (
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', minHeight: '100%' }}>
<Button type="primary" icon="poweroff" loading={activateState} onClick={this.handleClick}>
<Button type="primary" icon="poweroff" loading={loading} onClick={this.handleClick}>
激活
</Button>
</div>
......@@ -24,10 +24,12 @@ class Active extends React.Component {
function mapStateToProps(state) {
const {
auth: { activateState },
} = state;
const loading = state.loading.global || false
return {
activateState,
loading,
};
}
......
import { Button, Form, Icon, Input, Select, Spin } from 'antd';
import { Button, Form, Icon, Input, Select, Spin, Steps } from 'antd';
import { connect } from 'dva';
import { Link } from 'dva/router';
import React, { PropTypes } from 'react';
......@@ -6,6 +6,7 @@ import { FormattedMessage as Format } from 'react-intl';
const FormItem = Form.Item;
const Option = Select.Option;
const Step = Steps.Step
const formItemLayout = {
......@@ -44,12 +45,17 @@ class Login extends React.Component {
const { getFieldDecorator, dispatch } = this.props.form;
const { isForgotSubmit = false } = this.props;
const { intl: { messages } } = this.context;
return (
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100%' }}>
<Spin spinning={isForgotSubmit} delay={500}>
<Spin spinning={loading} delay={100}>
<Form onSubmit={this.onSubmitLogin} className="login-form">
<FormItem>
<Steps size="large" current={0}>
<Step title="Sent Email" icon={<Icon type="solution" />} />
<Step title="Verify Email" icon={<Icon type="mail" />} />
</Steps>
<FormItem style={{ marginTop: '28px'}}>
{getFieldDecorator('email', {
rules: [{ required: true, message: 'Please input your username or email!' }],
})(
......@@ -68,11 +74,15 @@ class Login extends React.Component {
}
}
function mapStateToProps(state) {
function mapStateToProps(state, props) {
const {
auth: { isForgotSubmit },
} = state;
const loading = state.loading.global || false
return {
loading,
isForgotSubmit,
};
}
......
......@@ -7,7 +7,6 @@ import './Login.less';
const FormItem = Form.Item;
class Login extends React.Component {
static contextTypes = {
......@@ -31,12 +30,12 @@ class Login extends React.Component {
render() {
const { getFieldDecorator } = this.props.form;
const { isLoginSubmit = false } = this.props;
const { intl: { messages } } = this.context;
const { loading } = this.props;
const { intl: { messages } } = this.context
return (
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100%' }}>
<Spin spinning={isLoginSubmit} delay={500}>
<Spin spinning={loading} delay={100}>
<Form onSubmit={this.onSubmitLogin} className="login-form">
<FormItem>
{getFieldDecorator('account', {
......@@ -75,11 +74,13 @@ class Login extends React.Component {
function mapStateToProps(state) {
const {
common: { language },
auth: { isLoginSubmit },
} = state;
const loading = state.loading.global || false
return {
loading,
language,
isLoginSubmit,
};
}
......
:global {
.login-form {
max-width: 300px;
max-width: 80vw;
min-width: 50vw;
}
.login-form-forgot {
float: right;
......
......@@ -25,7 +25,7 @@ class Profiles extends React.Component {
if (!err) {
console.log('Received values of form: ', values);
const { username, nickname, password } = values;
const { username, name, password } = values;
dispatch({type: "user/updateProfile", payload: { username, name, password, user_id: id }})
}
......@@ -33,8 +33,8 @@ class Profiles extends React.Component {
};
render() {
const { dispatch, form, data, isUpdateSubmit=false, checkUsername, isUserNameExists } = this.props
const { getFieldDecorator } = form;
const { dispatch, form, data, isUpdateSubmit=false, checkUsername, isUserNameExists, loading } = this.props
const { getFieldDecorator } = form
const { username, name, id } = data
const nameProps = {
......@@ -51,7 +51,7 @@ class Profiles extends React.Component {
}
return (
<Spin spinning={isUpdateSubmit} delay={500}>
<Spin spinning={loading} delay={100}>
<Tabs defaultActiveKey="1" className="app-detail-nav">
<TabPane tab={<span><Icon type="setting" /> 基本信息 </span>} key="1">
<Form onSubmit={this.onUpdateSubmit}>
......@@ -96,10 +96,14 @@ class Profiles extends React.Component {
function mapStateToProps(state) {
const {
user: { data, isUpdateSubmit },
auth: { checkUsername, isEmailExists, isUserNameExists, },
auth: { checkUsername, isEmailExists, isUserNameExists },
} = state;
const loading = state.loading.global || false
return {
data,
loading,
checkUsername,
isEmailExists,
isUserNameExists,
......
import { Button, Form, Icon, Input, Select, Spin } from 'antd';
import { Button, Form, Icon, Input, Select, Spin, Steps } from 'antd';
import { connect } from 'dva';
import { Link } from 'dva/router';
import React, { PropTypes } from 'react';
import { FormattedMessage as Format } from 'react-intl';
import styles from './Register.less'
const FormItem = Form.Item;
const Option = Select.Option;
const Step = Steps.Step
class Register extends React.Component {
......@@ -47,7 +49,7 @@ class Register extends React.Component {
};
render() {
const { dispatch, register, form, checkEmail, checkUsername, isEmailExists, isUserNameExists, isRegisterSubmit, } = this.props;
const { dispatch, register, form, checkEmail, checkUsername, isEmailExists, isUserNameExists, isRegisterSubmit, loading } = this.props;
const { getFieldDecorator, } = form;
const { email = {}, username = {}, password = {} } = register;
const { intl: { messages } } = this.context;
......@@ -75,9 +77,15 @@ class Register extends React.Component {
};
return (
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100%' }}>
<Spin spinning={isRegisterSubmit} delay={500}>
<Form onSubmit={this.onSubmitLogin} className="login-form">
<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', height: '100%' }}>
<Spin spinning={loading} delay={100}>
<Steps size="large" current={0}>
<Step title="register" icon={<Icon type="solution" />} />
<Step title="verify Email" icon={<Icon type="mail" />} />
</Steps>
<Form onSubmit={this.onSubmitLogin} className="login-form" style={{ marginTop: '24px'}}>
<FormItem {...emailProps} >
{getFieldDecorator('email', {
rules: [{
......@@ -152,7 +160,11 @@ function mapStateToProps(state) {
const {
auth: { register, checkEmail, checkUsername, isEmailExists, isUserNameExists, isRegisterSubmit },
} = state;
const loading = state.loading.global || false
return {
loading,
register,
checkEmail,
checkUsername,
......
......@@ -19,3 +19,8 @@
color: #666;
}
}
.action {
margin-top: 24px;
}
\ No newline at end of file
......@@ -44,7 +44,7 @@ class Reset extends React.Component {
const { isResetSubmit = false } = this.props;
return (
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100%' }}>
<Spin spinning={isResetSubmit} delay={500}>
<Spin spinning={isResetSubmit} delay={100}>
<Form onSubmit={this.onSubmitReset} className="login-form">
<FormItem>
......
import React from 'react';
import { connect } from 'dva';
import styles from './Verify.css';
import { Form, Input, Steps, Icon, Spin, Alert, Tag } from 'antd';
import { routerRedux } from 'dva/router'
const FormItem = Form.Item;
import SubmitButton from '../components/SubmitButton'
const Step = Steps.Step
class Verify extends React.Component {
state = {
isChangeEmail: false
}
onSubmit = (e) => {
const { form, dispatch, input: { password }, data: { id }} = this.props;
e && e.preventDefault();
form.validateFieldsAndScroll((err, values) => {
if (!err) {
console.log('Received values of form: ', values);
const { email } = values
dispatch({ type: 'user/updateEmail', payload: { email, password, user_id: id } });
}
});
};
onReSend = (e) => {
const { dispatch, input: { password }, data: { id, email }} = this.props;
e && e.preventDefault();
dispatch({ type: 'user/updateEmail', payload: { email, password, user_id: id } });
};
render() {
const { form, dispatch, data, checkEmail, isEmailExists, loading, input } = this.props
const { getFieldDecorator } = form;
const { id, email } = data;
const emailProps = {
fromItem: {
label: "修改邮箱",
hasFeedback: true,
validateStatus: checkEmail,
help: isEmailExists ? 'email exists' : '',
},
decorator: {
initialValue: email
},
input: {
placeholder: "email"
}
}
return (
<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', height: '100%' }}>
<Spin spinning={loading} delay={100}>
<Steps size="large" current={1}>
<Step title="Register" icon={<Icon type="solution" />} />
<Step title="Verify Email" icon={<Icon type="mail" />} />
</Steps>
{id && input["password"] ?
<Alert
style={{ marginTop: '24px' }}
message={
<div>
<span style={{marginRight: '10px'}}>验证邮件已发送,请查收~</span>
<Tag color="blue" onClick={this.onReSend}>重发</Tag>
<Tag color="orange" onClick={() => this.setState({ isChangeEmail: true })}>
修改邮箱
</Tag>
</div>
}
type="warning"
showIcon
/>
:
<Alert
style={{ marginTop: '24px' }}
message={
<div>
<span style={{marginRight: '10px'}}>您尚未登录,请先登录</span>
<Tag color="blue" onClick={ () => dispatch(routerRedux.replace("/signin"))}>登录</Tag>
</div>
}
type="warning"
showIcon
/>
}
{
this.state.isChangeEmail &&
<Form onSubmit={this.onSubmit} className="login-form" style={{ marginTop: '24px' }}>
<FormItem {...emailProps.fromItem}>
{getFieldDecorator('email', { ...emailProps.decorator })(
<Input
{...emailProps.input}
onBlur={() => dispatch({ type: 'auth/checkEmail', payload: { ...form.getFieldsValue(), id } })} />
)}
</FormItem>
<FormItem>
<SubmitButton disabled={isEmailExists} />
</FormItem>
</Form>
}
</Spin>
</div>
);
}
}
function mapStateToProps(state, props) {
const {
user: { data } ,
auth: { input, isEmailExists, checkEmail }
} = state
const loading = state.loading.global || false
return {
input,
data,
loading,
checkEmail,
isEmailExists,
};
}
const WrapperVerify = Form.create()(Verify);
export default connect(mapStateToProps)(WrapperVerify);
......@@ -1708,6 +1708,12 @@ duplexer@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1"
dva-loading@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/dva-loading/-/dva-loading-0.2.1.tgz#fad76b8eeb28c3663a2ee1874cc118702940c63c"
dependencies:
babel-runtime "^6.11.6"
dva@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/dva/-/dva-1.2.1.tgz#b9e78a4f1812b2230134d1bb7baadd1af3630138"
......@@ -4312,6 +4318,13 @@ rc-progress@~2.0.1:
version "2.0.6"
resolved "https://registry.yarnpkg.com/rc-progress/-/rc-progress-2.0.6.tgz#799af503904330d35184ab00d61ebfcbc005c486"
rc-queue-anim@^0.13.3:
version "0.13.3"
resolved "https://registry.yarnpkg.com/rc-queue-anim/-/rc-queue-anim-0.13.3.tgz#12bfa0d36764154bd52671dcc8d213ebedd5f5fb"
dependencies:
babel-runtime "6.x"
velocity-animate "~1.3.1"
rc-radio@~2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/rc-radio/-/rc-radio-2.0.0.tgz#357b2da4d46564784b85d4bb5f0edf6c207155b3"
......@@ -4462,6 +4475,13 @@ rc@^1.1.7:
minimist "^1.2.0"
strip-json-comments "~2.0.1"
react-addons-transition-group@^15.4.2:
version "15.4.2"
resolved "https://registry.yarnpkg.com/react-addons-transition-group/-/react-addons-transition-group-15.4.2.tgz#4c42fa1c2ce024acab2924316c0f11268ded1af3"
dependencies:
fbjs "^0.8.4"
object-assign "^4.1.0"
react-dev-utils@^0.4.2:
version "0.4.2"
resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-0.4.2.tgz#ba6fae581fe945a2fc402e9b27c71fda4f62f6a1"
......@@ -5411,6 +5431,10 @@ vary@~1.1.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.1.tgz#67535ebb694c1d52257457984665323f587e8d37"
velocity-animate@~1.3.1:
version "1.3.2"
resolved "https://registry.yarnpkg.com/velocity-animate/-/velocity-animate-1.3.2.tgz#eb90d4ddb5f818c35937380b4b7df59934a26c3b"
vendors@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.1.tgz#37ad73c8ee417fb3d580e785312307d274847f22"
......
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