Tiny refactoring of profile pages logic

This commit is contained in:
SleepWalker 2016-05-12 07:30:10 +03:00
parent f837613553
commit a81a2d6205
6 changed files with 95 additions and 188 deletions

View File

@ -32,10 +32,10 @@ class PanelTransition extends Component {
}) })
}).isRequired, }).isRequired,
user: userShape.isRequired, user: userShape.isRequired,
setError: React.PropTypes.func.isRequired, setError: PropTypes.func.isRequired,
clearErrors: React.PropTypes.func.isRequired, clearErrors: PropTypes.func.isRequired,
resolve: React.PropTypes.func.isRequired, resolve: PropTypes.func.isRequired,
reject: React.PropTypes.func.isRequired, reject: PropTypes.func.isRequired,
// local props // local props
Title: PropTypes.element, Title: PropTypes.element,
@ -54,7 +54,7 @@ class PanelTransition extends Component {
}) })
}), }),
user: userShape, user: userShape,
clearErrors: React.PropTypes.func, clearErrors: PropTypes.func,
resolve: PropTypes.func, resolve: PropTypes.func,
reject: PropTypes.func reject: PropTypes.func
}; };

View File

@ -24,7 +24,6 @@ export default class ChangeEmail extends Component {
static propTypes = { static propTypes = {
email: PropTypes.string.isRequired, email: PropTypes.string.isRequired,
form: PropTypes.instanceOf(FormModel), form: PropTypes.instanceOf(FormModel),
onChange: PropTypes.func.isRequired,
onSubmit: PropTypes.func.isRequired onSubmit: PropTypes.func.isRequired
}; };
@ -38,7 +37,6 @@ export default class ChangeEmail extends Component {
activeStep: 0 activeStep: 0
}; };
render() { render() {
const {form} = this.props; const {form} = this.props;
const {activeStep} = this.state; const {activeStep} = this.state;
@ -234,10 +232,6 @@ export default class ChangeEmail extends Component {
return this.state.activeStep + 1 === STEPS_TOTAL; return this.state.activeStep + 1 === STEPS_TOTAL;
} }
onUsernameChange = (event) => {
this.props.onChange(event.target.value);
};
onFormSubmit = () => { onFormSubmit = () => {
this.props.onSubmit(this.props.form); this.props.onSubmit(this.props.form);
}; };

View File

@ -3,13 +3,15 @@ import React, { Component, PropTypes } from 'react';
import accounts from 'services/api/accounts'; import accounts from 'services/api/accounts';
import { FormModel } from 'components/ui/form'; import { FormModel } from 'components/ui/form';
import ChangePassword from 'components/profile/changePassword/ChangePassword'; import ChangePassword from 'components/profile/changePassword/ChangePassword';
import PasswordRequestForm from 'components/profile/passwordRequestForm/PasswordRequestForm';
class ChangePasswordPage extends Component { class ChangePasswordPage extends Component {
static displayName = 'ChangePasswordPage'; static displayName = 'ChangePasswordPage';
static propTypes = { static propTypes = {
changePassword: PropTypes.func.isRequired };
static contextTypes = {
onSubmit: PropTypes.func.isRequired
}; };
form = new FormModel(); form = new FormModel();
@ -21,61 +23,22 @@ class ChangePasswordPage extends Component {
} }
onSubmit = () => { onSubmit = () => {
this.props.changePassword(this.form); const {form} = this;
this.context.onSubmit({
form,
sendData: () => accounts.changePassword(form.serialize())
}).then(() => {
this.props.updateUser({
passwordChangedAt: Date.now() / 1000,
shouldChangePassword: false
});
});
}; };
} }
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { routeActions } from 'react-router-redux';
import { create as createPopup } from 'components/ui/popup/actions';
import { updateUser } from 'components/user/actions'; import { updateUser } from 'components/user/actions';
function goToProfile() {
return routeActions.push('/');
}
export default connect(null, { export default connect(null, {
changePassword: (form) => { updateUser
return (dispatch) => {
accounts.changePassword(form.serialize())
.catch((resp) => {
// prevalidate user input, because requestPassword popup will block the
// entire form from input, so it must be valid
if (resp.errors) {
Reflect.deleteProperty(resp.errors, 'password');
if (Object.keys(resp.errors).length) {
form.setErrors(resp.errors);
return Promise.reject(resp);
}
}
return Promise.resolve();
})
.then(() => {
dispatch(createPopup(PasswordRequestForm, (props) => ({
form,
onSubmit: () => {
// TODO: hide this logic in action
accounts.changePassword(form.serialize())
.catch((resp) => {
if (resp.errors) {
form.setErrors(resp.errors);
}
return Promise.reject(resp);
})
.then(() => {
dispatch(updateUser({
passwordChangedAt: Date.now() / 1000,
shouldChangePassword: false
}));
})
.then(props.onClose)
.then(() => dispatch(goToProfile()));
}
})));
});
};
}
})(ChangePasswordPage); })(ChangePasswordPage);

View File

@ -3,15 +3,17 @@ import React, { Component, PropTypes } from 'react';
import accounts from 'services/api/accounts'; import accounts from 'services/api/accounts';
import { FormModel } from 'components/ui/form'; import { FormModel } from 'components/ui/form';
import ChangeUsername from 'components/profile/changeUsername/ChangeUsername'; import ChangeUsername from 'components/profile/changeUsername/ChangeUsername';
import PasswordRequestForm from 'components/profile/passwordRequestForm/PasswordRequestForm';
class ChangeUsernamePage extends Component { class ChangeUsernamePage extends Component {
static displayName = 'ChangeUsernamePage'; static displayName = 'ChangeUsernamePage';
static propTypes = { static propTypes = {
username: PropTypes.string.isRequired, username: PropTypes.string.isRequired,
updateUsername: PropTypes.func.isRequired, // updates username in state updateUsername: PropTypes.func.isRequired
changeUsername: PropTypes.func.isRequired // saves username to backend };
static contextTypes = {
onSubmit: PropTypes.func.isRequired
}; };
form = new FormModel(); form = new FormModel();
@ -41,7 +43,13 @@ class ChangeUsernamePage extends Component {
}; };
onSubmit = () => { onSubmit = () => {
this.props.changeUsername(this.form).then(() => { const {form} = this;
this.context.onSubmit({
form,
sendData: () => accounts.changeUsername(form.serialize())
}).then(() => {
this.props.updateUsername(form.value('username'));
this.setState({ this.setState({
actualUsername: this.props.username actualUsername: this.props.username
}); });
@ -50,62 +58,12 @@ class ChangeUsernamePage extends Component {
} }
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { routeActions } from 'react-router-redux';
import { create as createPopup } from 'components/ui/popup/actions';
import { updateUser } from 'components/user/actions'; import { updateUser } from 'components/user/actions';
function goToProfile() {
return routeActions.push('/');
}
export default connect((state) => ({ export default connect((state) => ({
username: state.user.username username: state.user.username
}), { }), {
updateUsername: (username) => { updateUsername: (username) => {
return updateUser({username}); return updateUser({username});
},
changeUsername: (form) => {
return (dispatch) => accounts.changeUsername(form.serialize())
.catch((resp) => {
// prevalidate user input, because requestPassword popup will block the
// entire form from input, so it must be valid
if (resp.errors) {
Reflect.deleteProperty(resp.errors, 'password');
if (Object.keys(resp.errors).length) {
form.setErrors(resp.errors);
return Promise.reject(resp);
}
}
return Promise.resolve();
})
.then(() => {
return new Promise((resolve) => {
dispatch(createPopup(PasswordRequestForm, (props) => ({
form,
onSubmit: () => {
// TODO: hide this logic in action
accounts.changeUsername(form.serialize())
.catch((resp) => {
if (resp.errors) {
form.setErrors(resp.errors);
}
return Promise.reject(resp);
})
.then(() => {
dispatch(updateUser({
username: form.value('username')
}));
})
.then(resolve)
.then(props.onClose)
.then(() => dispatch(goToProfile()));
}
})));
});
})
;
} }
})(ChangeUsernamePage); })(ChangeUsernamePage);

View File

@ -1,17 +1,13 @@
import React, { Component, PropTypes } from 'react'; import React, { Component, PropTypes } from 'react';
import accounts from 'services/api/accounts';
import { FormModel } from 'components/ui/form'; import { FormModel } from 'components/ui/form';
import ChangeEmail from 'components/profile/changeEmail/ChangeEmail'; import ChangeEmail from 'components/profile/changeEmail/ChangeEmail';
import PasswordRequestForm from 'components/profile/passwordRequestForm/PasswordRequestForm';
class ProfileChangeEmailPage extends Component { class ProfileChangeEmailPage extends Component {
static displayName = 'ProfileChangeEmailPage'; static displayName = 'ProfileChangeEmailPage';
static propTypes = { static propTypes = {
email: PropTypes.string.isRequired, email: PropTypes.string.isRequired
updateUsername: PropTypes.func.isRequired, // updates username in state
changeUsername: PropTypes.func.isRequired // saves username to backend
}; };
form = new FormModel(); form = new FormModel();
@ -20,82 +16,18 @@ class ProfileChangeEmailPage extends Component {
return ( return (
<ChangeEmail form={this.form} <ChangeEmail form={this.form}
onSubmit={this.onSubmit} onSubmit={this.onSubmit}
onChange={this.onUsernameChange}
email={this.props.email} email={this.props.email}
/> />
); );
} }
onUsernameChange = (username) => {
this.props.updateUsername(username);
};
onSubmit = () => { onSubmit = () => {
this.props.changeUsername(this.form).then(() => {
this.setState({
actualUsername: this.props.username
});
});
}; };
} }
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { routeActions } from 'react-router-redux';
import { create as createPopup } from 'components/ui/popup/actions';
import { updateUser } from 'components/user/actions';
function goToProfile() {
return routeActions.push('/');
}
export default connect((state) => ({ export default connect((state) => ({
email: state.user.email email: state.user.email
}), { }), {
updateUsername: (username) => {
return updateUser({username});
},
changeUsername: (form) => {
return (dispatch) => accounts.changeUsername(form.serialize())
.catch((resp) => {
// prevalidate user input, because requestPassword popup will block the
// entire form from input, so it must be valid
if (resp.errors) {
Reflect.deleteProperty(resp.errors, 'password');
if (Object.keys(resp.errors).length) {
form.setErrors(resp.errors);
return Promise.reject(resp);
}
}
return Promise.resolve();
})
.then(() => {
return new Promise((resolve) => {
dispatch(createPopup(PasswordRequestForm, (props) => ({
form,
onSubmit: () => {
// TODO: hide this logic in action
accounts.changeUsername(form.serialize())
.catch((resp) => {
if (resp.errors) {
form.setErrors(resp.errors);
}
return Promise.reject(resp);
})
.then(() => {
dispatch(updateUser({
username: form.value('username')
}));
})
.then(resolve)
.then(props.onClose)
.then(() => dispatch(goToProfile()));
}
})));
});
})
;
}
})(ProfileChangeEmailPage); })(ProfileChangeEmailPage);

View File

@ -1,10 +1,24 @@
import React, { Component } from 'react'; import React, { Component, PropTypes } from 'react';
import styles from './profile.scss'; import styles from './profile.scss';
export default class ProfilePage extends Component { class ProfilePage extends Component {
displayName = 'ProfilePage'; displayName = 'ProfilePage';
static propTypes = {
onSubmit: PropTypes.func.isRequired
};
static childContextTypes = {
onSubmit: PropTypes.func
};
getChildContext() {
return {
onSubmit: this.props.onSubmit
};
}
render() { render() {
return ( return (
<div className={styles.container}> <div className={styles.container}>
@ -13,3 +27,49 @@ export default class ProfilePage extends Component {
); );
} }
} }
import { connect } from 'react-redux';
import { routeActions } from 'react-router-redux';
import { create as createPopup } from 'components/ui/popup/actions';
import PasswordRequestForm from 'components/profile/passwordRequestForm/PasswordRequestForm';
function goToProfile() {
return routeActions.push('/');
}
export default connect(null, {
onSubmit: ({form, sendData}) => (dispatch) =>
sendData()
.catch((resp) => {
// prevalidate user input, because requestPassword popup will block the
// entire form from input, so it must be valid
if (resp.errors) {
Reflect.deleteProperty(resp.errors, 'password');
if (Object.keys(resp.errors).length) {
form.setErrors(resp.errors);
return Promise.reject(resp);
}
}
return Promise.resolve();
})
.then(() => new Promise((resolve) => {
dispatch(createPopup(PasswordRequestForm, (props) => ({
form,
onSubmit: () => {
sendData()
.catch((resp) => {
if (resp.errors) {
form.setErrors(resp.errors);
}
return Promise.reject(resp);
})
.then(resolve)
.then(props.onClose)
.then(() => dispatch(goToProfile()));
}
})));
}))
})(ProfilePage);