mirror of
				https://github.com/elyby/accounts-frontend.git
				synced 2025-05-31 14:11:58 +05:30 
			
		
		
		
	Наверстал форму смены пароля и чуток отрефакторил профиль
This commit is contained in:
		| @@ -7,9 +7,10 @@ import { userShape } from 'components/user/User'; | ||||
|  | ||||
| import ProfileField from './ProfileField'; | ||||
| import styles from './profile.scss'; | ||||
| import profileForm from './profileForm.scss'; | ||||
| import messages from './Profile.messages'; | ||||
|  | ||||
| export class Profile extends Component { | ||||
| export default class Profile extends Component { | ||||
|     static displayName = 'Profile'; | ||||
|     static propTypes = { | ||||
|         user: userShape | ||||
| @@ -19,62 +20,67 @@ export class Profile extends Component { | ||||
|         const { user } = this.props; | ||||
|  | ||||
|         return ( | ||||
|             <div className={styles.container}> | ||||
|             <div> | ||||
|                 <Message {...messages.accountPreferencesTitle}> | ||||
|                     {(pageTitle) => ( | ||||
|                         <h2 className={styles.title}> | ||||
|                         <h2 className={styles.indexTitle}> | ||||
|                             <Helmet title={pageTitle} /> | ||||
|                             {pageTitle} | ||||
|                         </h2> | ||||
|                     )} | ||||
|                 </Message> | ||||
|  | ||||
|                 <div className={styles.content}> | ||||
|                     <div className={styles.description}> | ||||
|                         <Message {...messages.accountDescription} /> | ||||
|                 <div className={styles.indexContent}> | ||||
|                     <div className={styles.descriptionColumn}> | ||||
|                         <div className={styles.indexDescription}> | ||||
|                             <Message {...messages.accountDescription} /> | ||||
|                         </div> | ||||
|                     </div> | ||||
|  | ||||
|                     <div className={styles.options}> | ||||
|                         <div className={styles.item}> | ||||
|                             <h3 className={styles.optionsTitle}> | ||||
|                                 <Message {...messages.personalData} /> | ||||
|                             </h3> | ||||
|                             <p className={styles.optionsDescription}> | ||||
|                                 <Message {...messages.preferencesDescription} /> | ||||
|                             </p> | ||||
|                     <div className={styles.formColumn}> | ||||
|                         <div className={profileForm.form}> | ||||
|                             <div className={styles.item}> | ||||
|                                 <h3 className={profileForm.title}> | ||||
|                                     <Message {...messages.personalData} /> | ||||
|                                 </h3> | ||||
|                                 <p className={profileForm.description}> | ||||
|                                     <Message {...messages.preferencesDescription} /> | ||||
|                                 </p> | ||||
|                             </div> | ||||
|  | ||||
|                             <ProfileField | ||||
|                                 label={<Message {...messages.nickname} />} | ||||
|                                 value={user.username} | ||||
|                                 warningMessage={<Message {...messages.mojangPriorityWarning} />} | ||||
|                             /> | ||||
|  | ||||
|                             <ProfileField | ||||
|                                 label={'E-mail'} | ||||
|                                 value={user.email} | ||||
|                             /> | ||||
|  | ||||
|                             <ProfileField | ||||
|                                 label={<Message {...messages.password} />} | ||||
|                                 link="/profile/change-password" | ||||
|                                 value={<Message {...messages.changedAt} values={{ | ||||
|                                     at: (<Relative value={user.passwordChangedAt * 1000} />) | ||||
|                                 }} />} | ||||
|                                 warningMessage={user.shouldChangePassword ? ( | ||||
|                                     <HTMLMessage {...messages.oldHashingAlgoWarning} /> | ||||
|                                 ) : ''} | ||||
|                             /> | ||||
|  | ||||
|                             <ProfileField | ||||
|                                 label={<Message {...messages.twoFactorAuth} />} | ||||
|                                 value={<Message {...messages.disabled} />} | ||||
|                             /> | ||||
|  | ||||
|                             <ProfileField | ||||
|                                 label={'UUID'} | ||||
|                                 value={user.uuid} | ||||
|                                 readonly | ||||
|                             /> | ||||
|                         </div> | ||||
|  | ||||
|                         <ProfileField | ||||
|                             label={<Message {...messages.nickname} />} | ||||
|                             value={user.username} | ||||
|                             warningMessage={<Message {...messages.mojangPriorityWarning} />} | ||||
|                         /> | ||||
|  | ||||
|                         <ProfileField | ||||
|                             label={'E-mail'} | ||||
|                             value={user.email} | ||||
|                         /> | ||||
|  | ||||
|                         <ProfileField | ||||
|                             label={<Message {...messages.password} />} | ||||
|                             value={<Message {...messages.changedAt} values={{ | ||||
|                                 at: (<Relative value={user.passwordChangedAt * 1000} />) | ||||
|                             }} />} | ||||
|                             warningMessage={user.shouldChangePassword ? ( | ||||
|                                 <HTMLMessage {...messages.oldHashingAlgoWarning} /> | ||||
|                             ) : ''} | ||||
|                         /> | ||||
|  | ||||
|                         <ProfileField | ||||
|                             label={<Message {...messages.twoFactorAuth} />} | ||||
|                             value={<Message {...messages.disabled} />} | ||||
|                         /> | ||||
|  | ||||
|                         <ProfileField | ||||
|                             label={'UUID'} | ||||
|                             value={user.uuid} | ||||
|                             readonly | ||||
|                         /> | ||||
|                     </div> | ||||
|                 </div> | ||||
|             </div> | ||||
|   | ||||
| @@ -1,18 +1,21 @@ | ||||
| import React, { Component, PropTypes } from 'react'; | ||||
|  | ||||
| import { Link } from 'react-router'; | ||||
|  | ||||
| import styles from './profile.scss'; | ||||
|  | ||||
| export default class ProfileField extends Component { | ||||
|     static displayName = 'ProfileField'; | ||||
|     static propTypes = { | ||||
|         label: React.PropTypes.oneOfType([PropTypes.string, PropTypes.element]).isRequired, | ||||
|         link: PropTypes.string, | ||||
|         value: React.PropTypes.oneOfType([PropTypes.string, PropTypes.element]).isRequired, | ||||
|         warningMessage: React.PropTypes.oneOfType([PropTypes.string, PropTypes.element]), | ||||
|         readonly: PropTypes.bool | ||||
|     }; | ||||
|  | ||||
|     render() { | ||||
|         const {label, value, warningMessage, readonly} = this.props; | ||||
|         const {label, value, warningMessage, readonly, link = '#'} = this.props; | ||||
|  | ||||
|         return ( | ||||
|             <div className={styles.paramItem}> | ||||
| @@ -22,9 +25,9 @@ export default class ProfileField extends Component { | ||||
|  | ||||
|                     {readonly ? '' : ( | ||||
|                         <div className={styles.paramAction}> | ||||
|                             <a href="#"> | ||||
|                             <Link to={link}> | ||||
|                                 <span className={styles.paramEditIcon} /> | ||||
|                             </a> | ||||
|                             </Link> | ||||
|                         </div> | ||||
|                     )} | ||||
|                 </div> | ||||
|   | ||||
							
								
								
									
										65
									
								
								src/components/profile/changePassword/ChangePassword.jsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								src/components/profile/changePassword/ChangePassword.jsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,65 @@ | ||||
| import React, { Component } from 'react'; | ||||
|  | ||||
| import { FormattedMessage as Message } from 'react-intl'; | ||||
| import { Link } from 'react-router'; | ||||
| import Helmet from 'react-helmet'; | ||||
| import classNames from 'classnames'; | ||||
|  | ||||
| import { LabeledInput } from 'components/ui/Form'; | ||||
| import buttons from 'components/ui/buttons.scss'; | ||||
|  | ||||
| import styles from 'components/profile/profileForm.scss'; | ||||
| import messages from './ChangePassword.messages'; | ||||
|  | ||||
| export default class ChangePassword extends Component { | ||||
|     displayName = 'ChangePassword'; | ||||
|  | ||||
|     render() { | ||||
|         return ( | ||||
|             <div className={styles.contentWithBackButton}> | ||||
|                 <Link className={styles.backButton} to="/" /> | ||||
|  | ||||
|                 <div className={styles.form}> | ||||
|                     <div className={styles.formBody}> | ||||
|                         <Message {...messages.changePasswordTitle}> | ||||
|                             {(pageTitle) => ( | ||||
|                                 <h3 className={styles.title}> | ||||
|                                     <Helmet title={pageTitle} /> | ||||
|                                     {pageTitle} | ||||
|                                 </h3> | ||||
|                             )} | ||||
|                         </Message> | ||||
|  | ||||
|                         <div className={styles.formRow}> | ||||
|                             <p className={styles.description}> | ||||
|                                 <Message {...messages.changePasswordDescription} /> | ||||
|                                 <br/> | ||||
|                                 <b> | ||||
|                                     <Message {...messages.achievementLossWarning} /> | ||||
|                                 </b> | ||||
|                             </p> | ||||
|                         </div> | ||||
|  | ||||
|                         <div className={styles.formRow}> | ||||
|                             <LabeledInput skin="light" label={messages.newPasswordLabel} /> | ||||
|                         </div> | ||||
|  | ||||
|                         <div className={styles.formRow}> | ||||
|                             <p className={styles.description}> | ||||
|                                 <Message {...messages.passwordRequirements} /> | ||||
|                             </p> | ||||
|                         </div> | ||||
|  | ||||
|                         <div className={styles.formRow}> | ||||
|                             <LabeledInput skin="light" label={messages.repeatNewPasswordLabel} /> | ||||
|                         </div> | ||||
|                     </div> | ||||
|  | ||||
|                     <button className={classNames(buttons.green, buttons.block)}> | ||||
|                         <Message {...messages.changePasswordButton} /> | ||||
|                     </button> | ||||
|                 </div> | ||||
|             </div> | ||||
|         ); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,39 @@ | ||||
| import { defineMessages } from 'react-intl'; | ||||
|  | ||||
| export default defineMessages({ | ||||
|     changePasswordTitle: { | ||||
|         id: 'changePasswordTitle', | ||||
|         defaultMessage: 'Change password' | ||||
|         // defaultMessage: 'Смена пароля' | ||||
|     }, | ||||
|     changePasswordDescription: { | ||||
|         id: 'changePasswordDescription', | ||||
|         defaultMessage: 'Please take a password, that will be different from your passwords on the other sites and will not be the same you are using to enter Minecraft game servers you are playing.' | ||||
|         // defaultMessage: 'Придумайте пароль, который будет отличаться от ваших паролей на других сайтах и не будет совпадаеть с тем паролем, который вы используете для входа на различные игровые сервера Minecraft.' | ||||
|     }, | ||||
|     achievementLossWarning: { | ||||
|         id: 'achievementLossWarning', | ||||
|         defaultMessage: 'Are you cherish your game achievements, right?' | ||||
|         // defaultMessage: 'Вы ведь дорожите своими игровыми достижениями?' | ||||
|     }, | ||||
|     passwordRequirements: { | ||||
|         id: 'passwordRequirements', | ||||
|         defaultMessage: 'Password must contain at least 8 characters. It can be any symbols — do not limit yourself, create an unpredictable password!' | ||||
|         // defaultMessage: 'Пароль должен содержать не менее 8 символов. Это могут быть любым символы — не ограничивайте себя, придумайте непредсказуемый пароль!' | ||||
|     }, | ||||
|     changePasswordButton: { | ||||
|         id: 'changePasswordButton', | ||||
|         defaultMessage: 'Change password' | ||||
|         // defaultMessage: 'Сменить пароль' | ||||
|     }, | ||||
|     newPasswordLabel: { | ||||
|         id: 'newPasswordLabel', | ||||
|         defaultMessage: 'New password:' | ||||
|         // defaultMessage: 'Новый пароль:' | ||||
|     }, | ||||
|     repeatNewPasswordLabel: { | ||||
|         id: 'repeatNewPasswordLabel', | ||||
|         defaultMessage: 'Repeat the password:' | ||||
|         // defaultMessage: 'Повторите указанный пароль:' | ||||
|     } | ||||
| }); | ||||
| @@ -1,62 +1,32 @@ | ||||
| @import '~components/ui/fonts.scss'; | ||||
| @import '~components/ui/colors.scss'; | ||||
|  | ||||
| .container { | ||||
|     margin-top: 55px; | ||||
| } | ||||
|  | ||||
|  | ||||
| .title { | ||||
|     font-family: $font-family-title; | ||||
|     font-size: 30px; | ||||
|     margin-bottom: 12px; | ||||
| } | ||||
|  | ||||
| .content { | ||||
| .indexContent { | ||||
|     display: flex; | ||||
| } | ||||
|  | ||||
| .description { | ||||
|     font-size: 14px; | ||||
|     line-height: 1.4; | ||||
|     color: #9a9a9a; | ||||
|     width: 340px; | ||||
|     padding: 12px 20px 0 0; | ||||
|     box-sizing: border-box; | ||||
| } | ||||
|  | ||||
| .options { | ||||
|     background: #fff; | ||||
| .formColumn { | ||||
|     flex-grow: 1; | ||||
|     max-width: 416px; | ||||
|     border-bottom: 10px solid #ddd8ce; | ||||
| } | ||||
|  | ||||
| .optionsTitle { | ||||
|     position: relative; | ||||
|     font-size: 24px; | ||||
|     font-family: $font-family-title; | ||||
|     padding-bottom: 9px; | ||||
|  | ||||
|     &:after { | ||||
|         content: ''; | ||||
|         display: block; | ||||
|  | ||||
|         position: absolute; | ||||
|         left: 0; | ||||
|         bottom: 0; | ||||
|         height: 3px; | ||||
|         width: 86px; | ||||
|  | ||||
|         background: $green; | ||||
|     } | ||||
| .descriptionColumn { | ||||
|     width: 340px; | ||||
|     padding: 12px 20px 0 0; | ||||
|     box-sizing: border-box; | ||||
| } | ||||
|  | ||||
| .optionsDescription { | ||||
|     font-size: 13px; | ||||
| .indexTitle { | ||||
|     font-family: $font-family-title; | ||||
|     font-size: 30px; | ||||
|     margin-bottom: 12px; | ||||
| } | ||||
|  | ||||
| .indexDescription { | ||||
|     font-size: 14px; | ||||
|     line-height: 1.4; | ||||
|     color: #9a9a9a; | ||||
|     line-height: 1.25; | ||||
|     margin-top: 25px; | ||||
| } | ||||
|  | ||||
| .item { | ||||
|   | ||||
							
								
								
									
										65
									
								
								src/components/profile/profileForm.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								src/components/profile/profileForm.scss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,65 @@ | ||||
| @import '~components/ui/fonts.scss'; | ||||
| @import '~components/ui/colors.scss'; | ||||
|  | ||||
| .contentWithBackButton { | ||||
|     position: relative; | ||||
|     padding-left: 60px; | ||||
|     width: 400px; | ||||
|     margin: 0 auto; | ||||
| } | ||||
|  | ||||
| .backButton { | ||||
|     composes: arrow from 'components/ui/icons.scss'; | ||||
|  | ||||
|     position: absolute; | ||||
|     left: 0; | ||||
|     top: 15px; | ||||
|     width: 25px; | ||||
|     height: 25px; | ||||
|     padding: 15px; | ||||
|  | ||||
|     transform: rotate(90deg); | ||||
|  | ||||
|     color: #ccc; | ||||
|     font-size: 25px; | ||||
| } | ||||
|  | ||||
| .form { | ||||
|     background: #fff; | ||||
|     overflow: hidden; // disable margin collapsing | ||||
| } | ||||
|  | ||||
| .formBody { | ||||
|     margin: 30px; | ||||
| } | ||||
|  | ||||
| .formRow { | ||||
|     margin: 25px 0; | ||||
| } | ||||
|  | ||||
| .title { | ||||
|     position: relative; | ||||
|     font-size: 24px; | ||||
|     font-family: $font-family-title; | ||||
|     padding-bottom: 9px; | ||||
|  | ||||
|     &:after { | ||||
|         content: ''; | ||||
|         display: block; | ||||
|  | ||||
|         position: absolute; | ||||
|         left: 0; | ||||
|         bottom: 0; | ||||
|         height: 3px; | ||||
|         width: 86px; | ||||
|  | ||||
|         background: $green; | ||||
|     } | ||||
| } | ||||
|  | ||||
| .description { | ||||
|     font-size: 13px; | ||||
|     color: #9a9a9a; | ||||
|     line-height: 1.3; | ||||
|     margin-top: 25px; | ||||
| } | ||||
| @@ -71,3 +71,8 @@ | ||||
| @include button-theme('orange', $orange); | ||||
| @include button-theme('darkBlue', $dark_blue); | ||||
| @include button-theme('lightViolet', $light_violet); | ||||
|  | ||||
| .block { | ||||
|     display: block; | ||||
|     width: 100%; | ||||
| } | ||||
|   | ||||
| @@ -2,13 +2,18 @@ import React, { Component } from 'react'; | ||||
|  | ||||
| import { connect } from 'react-redux'; | ||||
|  | ||||
| import { Profile } from 'components/profile/Profile'; | ||||
| import ProfilePage from 'pages/profile/ProfilePage'; | ||||
| import Profile from 'components/profile/Profile'; | ||||
|  | ||||
| class IndexPage extends Component { | ||||
|     displayName = 'IndexPage'; | ||||
|  | ||||
|     render() { | ||||
|         return (<Profile {...this.props} />); | ||||
|         return ( | ||||
|             <ProfilePage> | ||||
|                 <Profile {...this.props} /> | ||||
|             </ProfilePage> | ||||
|         ); | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
							
								
								
									
										15
									
								
								src/pages/profile/ProfilePage.jsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								src/pages/profile/ProfilePage.jsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| import React, { Component } from 'react'; | ||||
|  | ||||
| import styles from './profile.scss'; | ||||
|  | ||||
| export default class ProfilePage extends Component { | ||||
|     displayName = 'ProfilePage'; | ||||
|  | ||||
|     render() { | ||||
|         return ( | ||||
|             <div className={styles.container}> | ||||
|                 {this.props.children} | ||||
|             </div> | ||||
|         ); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										3
									
								
								src/pages/profile/profile.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								src/pages/profile/profile.scss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| .container { | ||||
|     margin-top: 55px; | ||||
| } | ||||
| @@ -4,6 +4,7 @@ import { Route, IndexRoute } from 'react-router'; | ||||
| import RootPage from 'pages/root/RootPage'; | ||||
| import IndexPage from 'pages/index/IndexPage'; | ||||
| import AuthPage from 'pages/auth/AuthPage'; | ||||
| import ProfilePage from 'pages/profile/ProfilePage'; | ||||
|  | ||||
| import { authenticate } from 'components/user/actions'; | ||||
|  | ||||
| @@ -18,6 +19,8 @@ import ChangePassword from 'components/auth/changePassword/ChangePassword'; | ||||
| import ForgotPassword from 'components/auth/forgotPassword/ForgotPassword'; | ||||
| import Finish from 'components/auth/finish/Finish'; | ||||
|  | ||||
| import ProfileChangePassword from 'components/profile/changePassword/ChangePassword'; | ||||
|  | ||||
| import authFlow from 'services/authFlow'; | ||||
|  | ||||
| export default function routesFactory(store) { | ||||
| @@ -50,6 +53,10 @@ export default function routesFactory(store) { | ||||
|                 <Route path="/change-password" components={new ChangePassword()} {...onEnter} /> | ||||
|                 <Route path="/forgot-password" components={new ForgotPassword()} {...onEnter} /> | ||||
|             </Route> | ||||
|  | ||||
|             <Route path="profile" component={ProfilePage}> | ||||
|                 <Route path="change-password" component={ProfileChangePassword} /> | ||||
|             </Route> | ||||
|         </Route> | ||||
|     ); | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user