From a81a2d6205390d0c6d427d9d791355354c4915c4 Mon Sep 17 00:00:00 2001 From: SleepWalker Date: Thu, 12 May 2016 07:30:10 +0300 Subject: [PATCH] Tiny refactoring of profile pages logic --- src/components/auth/PanelTransition.jsx | 10 +-- .../profile/changeEmail/ChangeEmail.jsx | 6 -- src/pages/profile/ChangePasswordPage.jsx | 67 ++++-------------- src/pages/profile/ChangeUsernamePage.jsx | 66 ++++------------- src/pages/profile/ProfileChangeEmailPage.jsx | 70 +------------------ src/pages/profile/ProfilePage.jsx | 64 ++++++++++++++++- 6 files changed, 95 insertions(+), 188 deletions(-) diff --git a/src/components/auth/PanelTransition.jsx b/src/components/auth/PanelTransition.jsx index 380e746..a21eec8 100644 --- a/src/components/auth/PanelTransition.jsx +++ b/src/components/auth/PanelTransition.jsx @@ -32,10 +32,10 @@ class PanelTransition extends Component { }) }).isRequired, user: userShape.isRequired, - setError: React.PropTypes.func.isRequired, - clearErrors: React.PropTypes.func.isRequired, - resolve: React.PropTypes.func.isRequired, - reject: React.PropTypes.func.isRequired, + setError: PropTypes.func.isRequired, + clearErrors: PropTypes.func.isRequired, + resolve: PropTypes.func.isRequired, + reject: PropTypes.func.isRequired, // local props Title: PropTypes.element, @@ -54,7 +54,7 @@ class PanelTransition extends Component { }) }), user: userShape, - clearErrors: React.PropTypes.func, + clearErrors: PropTypes.func, resolve: PropTypes.func, reject: PropTypes.func }; diff --git a/src/components/profile/changeEmail/ChangeEmail.jsx b/src/components/profile/changeEmail/ChangeEmail.jsx index 390dce8..8e41445 100644 --- a/src/components/profile/changeEmail/ChangeEmail.jsx +++ b/src/components/profile/changeEmail/ChangeEmail.jsx @@ -24,7 +24,6 @@ export default class ChangeEmail extends Component { static propTypes = { email: PropTypes.string.isRequired, form: PropTypes.instanceOf(FormModel), - onChange: PropTypes.func.isRequired, onSubmit: PropTypes.func.isRequired }; @@ -38,7 +37,6 @@ export default class ChangeEmail extends Component { activeStep: 0 }; - render() { const {form} = this.props; const {activeStep} = this.state; @@ -234,10 +232,6 @@ export default class ChangeEmail extends Component { return this.state.activeStep + 1 === STEPS_TOTAL; } - onUsernameChange = (event) => { - this.props.onChange(event.target.value); - }; - onFormSubmit = () => { this.props.onSubmit(this.props.form); }; diff --git a/src/pages/profile/ChangePasswordPage.jsx b/src/pages/profile/ChangePasswordPage.jsx index 21cfd92..7ce6c4c 100644 --- a/src/pages/profile/ChangePasswordPage.jsx +++ b/src/pages/profile/ChangePasswordPage.jsx @@ -3,13 +3,15 @@ import React, { Component, PropTypes } from 'react'; import accounts from 'services/api/accounts'; import { FormModel } from 'components/ui/form'; import ChangePassword from 'components/profile/changePassword/ChangePassword'; -import PasswordRequestForm from 'components/profile/passwordRequestForm/PasswordRequestForm'; class ChangePasswordPage extends Component { static displayName = 'ChangePasswordPage'; static propTypes = { - changePassword: PropTypes.func.isRequired + }; + + static contextTypes = { + onSubmit: PropTypes.func.isRequired }; form = new FormModel(); @@ -21,61 +23,22 @@ class ChangePasswordPage extends Component { } 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 { 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(null, { - changePassword: (form) => { - 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())); - } - }))); - }); - }; - } + updateUser })(ChangePasswordPage); diff --git a/src/pages/profile/ChangeUsernamePage.jsx b/src/pages/profile/ChangeUsernamePage.jsx index bc71f3c..751a54b 100644 --- a/src/pages/profile/ChangeUsernamePage.jsx +++ b/src/pages/profile/ChangeUsernamePage.jsx @@ -3,15 +3,17 @@ import React, { Component, PropTypes } from 'react'; import accounts from 'services/api/accounts'; import { FormModel } from 'components/ui/form'; import ChangeUsername from 'components/profile/changeUsername/ChangeUsername'; -import PasswordRequestForm from 'components/profile/passwordRequestForm/PasswordRequestForm'; class ChangeUsernamePage extends Component { static displayName = 'ChangeUsernamePage'; static propTypes = { username: PropTypes.string.isRequired, - updateUsername: PropTypes.func.isRequired, // updates username in state - changeUsername: PropTypes.func.isRequired // saves username to backend + updateUsername: PropTypes.func.isRequired + }; + + static contextTypes = { + onSubmit: PropTypes.func.isRequired }; form = new FormModel(); @@ -41,7 +43,13 @@ class ChangeUsernamePage extends Component { }; 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({ actualUsername: this.props.username }); @@ -50,62 +58,12 @@ class ChangeUsernamePage extends Component { } 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) => ({ username: state.user.username }), { 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())); - } - }))); - }); - }) - ; } })(ChangeUsernamePage); diff --git a/src/pages/profile/ProfileChangeEmailPage.jsx b/src/pages/profile/ProfileChangeEmailPage.jsx index 592c1ea..f9d3470 100644 --- a/src/pages/profile/ProfileChangeEmailPage.jsx +++ b/src/pages/profile/ProfileChangeEmailPage.jsx @@ -1,17 +1,13 @@ import React, { Component, PropTypes } from 'react'; -import accounts from 'services/api/accounts'; import { FormModel } from 'components/ui/form'; import ChangeEmail from 'components/profile/changeEmail/ChangeEmail'; -import PasswordRequestForm from 'components/profile/passwordRequestForm/PasswordRequestForm'; class ProfileChangeEmailPage extends Component { static displayName = 'ProfileChangeEmailPage'; static propTypes = { - email: PropTypes.string.isRequired, - updateUsername: PropTypes.func.isRequired, // updates username in state - changeUsername: PropTypes.func.isRequired // saves username to backend + email: PropTypes.string.isRequired }; form = new FormModel(); @@ -20,82 +16,18 @@ class ProfileChangeEmailPage extends Component { return ( ); } - onUsernameChange = (username) => { - this.props.updateUsername(username); - }; - onSubmit = () => { - this.props.changeUsername(this.form).then(() => { - this.setState({ - actualUsername: this.props.username - }); - }); }; } 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) => ({ 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); diff --git a/src/pages/profile/ProfilePage.jsx b/src/pages/profile/ProfilePage.jsx index 23c80d6..e905f2f 100644 --- a/src/pages/profile/ProfilePage.jsx +++ b/src/pages/profile/ProfilePage.jsx @@ -1,10 +1,24 @@ -import React, { Component } from 'react'; +import React, { Component, PropTypes } from 'react'; import styles from './profile.scss'; -export default class ProfilePage extends Component { +class ProfilePage extends Component { displayName = 'ProfilePage'; + static propTypes = { + onSubmit: PropTypes.func.isRequired + }; + + static childContextTypes = { + onSubmit: PropTypes.func + }; + + getChildContext() { + return { + onSubmit: this.props.onSubmit + }; + } + render() { return (
@@ -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);