mirror of
https://github.com/elyby/accounts-frontend.git
synced 2024-12-27 23:40:28 +05:30
#41: integrate change email with backend
This commit is contained in:
parent
fa5ba292cb
commit
dffc73cc6d
17
src/components/profile/changeEmail/ChangeEmail.intl.json
Normal file
17
src/components/profile/changeEmail/ChangeEmail.intl.json
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"changeEmailTitle": "Change E-mail",
|
||||
"changeEmailDescription": "To change current account E-mail you must first verify that you own the current address and then confirm the new one.",
|
||||
"currentAccountEmail": "Current account E-mail address:",
|
||||
"pressButtonToStart": "Press the button below to send a message with the code for E-mail change initialization.",
|
||||
"enterInitializationCode": "The E-mail with an initialization code for E-mail change procedure was sent to {email}. Please enter the code into the field below:",
|
||||
|
||||
"enterNewEmail": "Then provide your new E-mail address, that you want to use with this account. You will be mailed with confirmation code.",
|
||||
"finalizationCodeWasSentToEmail": "The E-mail change confirmation code was sent to {email}.",
|
||||
"enterFinalizationCode": "In order to confirm your new E-mail, please enter the code received into the field below:",
|
||||
|
||||
"newEmailPlaceholder": "Enter new E-mail",
|
||||
"codePlaceholder": "Paste the code here",
|
||||
"sendEmailButton": "Send E-mail",
|
||||
"changeEmailButton": "Change E-mail",
|
||||
"alreadyReceivedCode": "Already received code"
|
||||
}
|
@ -12,19 +12,28 @@ import helpLinks from 'components/auth/helpLinks.scss';
|
||||
import MeasureHeight from 'components/MeasureHeight';
|
||||
|
||||
import changeEmail from './changeEmail.scss';
|
||||
import messages from './ChangeEmail.messages';
|
||||
import messages from './ChangeEmail.intl.json';
|
||||
|
||||
const STEPS_TOTAL = 3;
|
||||
|
||||
// TODO: disable code field, if the code was passed through url
|
||||
|
||||
export default class ChangeEmail extends Component {
|
||||
static displayName = 'ChangeEmail';
|
||||
|
||||
static propTypes = {
|
||||
onChangeStep: PropTypes.func,
|
||||
email: PropTypes.string.isRequired,
|
||||
form: PropTypes.instanceOf(FormModel),
|
||||
stepForms: PropTypes.arrayOf((propValue, key, componentName, location, propFullName) => {
|
||||
if (propValue.length !== 3) {
|
||||
return new Error(`\`${propFullName}\` must be an array of 3 FormModel instances. Validation failed.`);
|
||||
}
|
||||
|
||||
if (!(propValue[key] instanceof FormModel)) {
|
||||
return new Error(
|
||||
`Invalid prop \`${propFullName}\` supplied to \
|
||||
\`${componentName}\`. Validation failed.`
|
||||
);
|
||||
}
|
||||
}),
|
||||
onSubmit: PropTypes.func.isRequired,
|
||||
step: PropTypes.oneOf([0, 1, 2]),
|
||||
code: PropTypes.string
|
||||
@ -32,7 +41,11 @@ export default class ChangeEmail extends Component {
|
||||
|
||||
static get defaultProps() {
|
||||
return {
|
||||
form: new FormModel(),
|
||||
stepForms: [
|
||||
new FormModel(),
|
||||
new FormModel(),
|
||||
new FormModel()
|
||||
],
|
||||
onChangeStep() {},
|
||||
step: 0
|
||||
};
|
||||
@ -45,18 +58,19 @@ export default class ChangeEmail extends Component {
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
this.setState({
|
||||
activeStep: nextProps.step || this.state.activeStep,
|
||||
activeStep: typeof nextProps.step === 'number' ? nextProps.step : this.state.activeStep,
|
||||
code: nextProps.code || ''
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const {form} = this.props;
|
||||
const {activeStep} = this.state;
|
||||
const form = this.props.stepForms[activeStep];
|
||||
|
||||
return (
|
||||
<Form onSubmit={this.onFormSubmit}
|
||||
form={form}
|
||||
<Form form={form}
|
||||
onSubmit={this.onFormSubmit}
|
||||
onInvalid={() => this.forceUpdate()}
|
||||
>
|
||||
<div className={styles.contentWithBackButton}>
|
||||
<Link className={styles.backButton} to="/" />
|
||||
@ -95,7 +109,7 @@ export default class ChangeEmail extends Component {
|
||||
color="violet"
|
||||
block
|
||||
label={this.isLastStep() ? messages.changeEmailButton : messages.sendEmailButton}
|
||||
onClick={this.onSwitchStep}
|
||||
onClick={this.onSubmit}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@ -112,9 +126,9 @@ export default class ChangeEmail extends Component {
|
||||
}
|
||||
|
||||
renderStepForms() {
|
||||
const {form, email} = this.props;
|
||||
const {email} = this.props;
|
||||
const {activeStep, code} = this.state;
|
||||
const isCodeEntered = !!this.props.code;
|
||||
const isCodeSpecified = !!this.props.code;
|
||||
|
||||
const activeStepHeight = this.state[`step${activeStep}Height`] || 0;
|
||||
|
||||
@ -138,90 +152,25 @@ export default class ChangeEmail extends Component {
|
||||
WebkitTransform: `translateX(-${interpolatingStyle.transform}%)`,
|
||||
transform: `translateX(-${interpolatingStyle.transform}%)`
|
||||
}}>
|
||||
<MeasureHeight className={changeEmail.stepForm} onMeasure={this.onStepMeasure(0)}>
|
||||
<div className={styles.formBody}>
|
||||
<div className={styles.formRow}>
|
||||
<p className={styles.description}>
|
||||
<Message {...messages.currentAccountEmail} />
|
||||
</p>
|
||||
</div>
|
||||
{(new Array(STEPS_TOTAL)).fill(0).map((_, step) => {
|
||||
const form = this.props.stepForms[step];
|
||||
|
||||
<div className={styles.formRow}>
|
||||
<h2 className={changeEmail.currentAccountEmail}>
|
||||
{email}
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div className={styles.formRow}>
|
||||
<p className={styles.description}>
|
||||
<Message {...messages.pressButtonToStart} />
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</MeasureHeight>
|
||||
|
||||
<MeasureHeight className={changeEmail.stepForm} onMeasure={this.onStepMeasure(1)}>
|
||||
<div className={styles.formBody}>
|
||||
<div className={styles.formRow}>
|
||||
<p className={styles.description}>
|
||||
<Message {...messages.enterInitializationCode} values={{
|
||||
email: (<b>{email}</b>)
|
||||
}} />
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className={styles.formRow}>
|
||||
<Input {...form.bindField('initializationCode')}
|
||||
required
|
||||
disabled={isCodeEntered}
|
||||
value={code}
|
||||
onChange={this.onCodeInput}
|
||||
skin="light"
|
||||
color="violet"
|
||||
placeholder={messages.codePlaceholder}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className={styles.formRow}>
|
||||
<p className={styles.description}>
|
||||
<Message {...messages.enterNewEmail} />
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className={styles.formRow}>
|
||||
<Input {...form.bindField('newEmail')}
|
||||
required
|
||||
skin="light"
|
||||
color="violet"
|
||||
placeholder={messages.newEmailPlaceholder}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</MeasureHeight>
|
||||
|
||||
<MeasureHeight className={changeEmail.stepForm} onMeasure={this.onStepMeasure(2)}>
|
||||
<div className={styles.formBody}>
|
||||
<div className={styles.formRow}>
|
||||
<p className={styles.description}>
|
||||
<Message {...messages.enterFinalizationCode} values={{
|
||||
email: (<b>{form.value('newEmail')}</b>)
|
||||
}} />
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className={styles.formRow}>
|
||||
<Input {...form.bindField('finalizationCode')}
|
||||
required
|
||||
disabled={isCodeEntered}
|
||||
value={code}
|
||||
onChange={this.onCodeInput}
|
||||
skin="light"
|
||||
color="violet"
|
||||
placeholder={messages.codePlaceholder}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</MeasureHeight>
|
||||
return (
|
||||
<MeasureHeight
|
||||
className={changeEmail.stepForm}
|
||||
onMeasure={this.onStepMeasure(step)}
|
||||
state={`${step}.${form.hasErrors()}`}
|
||||
key={step}
|
||||
>
|
||||
{this[`renderStep${step}`]({
|
||||
email,
|
||||
code,
|
||||
form,
|
||||
isActiveStep: step === activeStep
|
||||
})}
|
||||
</MeasureHeight>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
@ -229,15 +178,114 @@ export default class ChangeEmail extends Component {
|
||||
);
|
||||
}
|
||||
|
||||
renderStep0({email}) {
|
||||
return (
|
||||
<div className={styles.formBody}>
|
||||
<div className={styles.formRow}>
|
||||
<p className={styles.description}>
|
||||
<Message {...messages.currentAccountEmail} />
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className={styles.formRow}>
|
||||
<h2 className={changeEmail.currentAccountEmail}>
|
||||
{email}
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div className={styles.formRow}>
|
||||
<p className={styles.description}>
|
||||
<Message {...messages.pressButtonToStart} />
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
renderStep1({email, form, code, isCodeSpecified, isActiveStep}) {
|
||||
return (
|
||||
<div className={styles.formBody}>
|
||||
<div className={styles.formRow}>
|
||||
<p className={styles.description}>
|
||||
<Message {...messages.enterInitializationCode} values={{
|
||||
email: (<b>{email}</b>)
|
||||
}} />
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className={styles.formRow}>
|
||||
<Input {...form.bindField('key')}
|
||||
required={isActiveStep}
|
||||
disabled={isCodeSpecified}
|
||||
value={code}
|
||||
onChange={this.onCodeInput}
|
||||
autoComplete="off"
|
||||
skin="light"
|
||||
color="violet"
|
||||
placeholder={messages.codePlaceholder}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className={styles.formRow}>
|
||||
<p className={styles.description}>
|
||||
<Message {...messages.enterNewEmail} />
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className={styles.formRow}>
|
||||
<Input {...form.bindField('email')}
|
||||
required={isActiveStep}
|
||||
skin="light"
|
||||
color="violet"
|
||||
placeholder={messages.newEmailPlaceholder}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
renderStep2({form, code, isCodeSpecified, isActiveStep}) {
|
||||
const newEmail = this.props.stepForms[1].value('email');
|
||||
|
||||
return (
|
||||
<div className={styles.formBody}>
|
||||
<div className={styles.formRow}>
|
||||
<p className={styles.description}>
|
||||
{newEmail ? (
|
||||
<span>
|
||||
<Message {...messages.finalizationCodeWasSentToEmail} values={{
|
||||
email: (<b>{newEmail}</b>)
|
||||
}} />
|
||||
{' '}
|
||||
</span>
|
||||
) : null}
|
||||
<Message {...messages.enterFinalizationCode} />
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className={styles.formRow}>
|
||||
<Input {...form.bindField('key')}
|
||||
required={isActiveStep}
|
||||
disabled={isCodeSpecified}
|
||||
value={code}
|
||||
onChange={this.onCodeInput}
|
||||
autoComplete="off"
|
||||
skin="light"
|
||||
color="violet"
|
||||
placeholder={messages.codePlaceholder}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
onStepMeasure(step) {
|
||||
return (height) => this.setState({
|
||||
[`step${step}Height`]: height
|
||||
});
|
||||
}
|
||||
|
||||
onSwitchStep = (event) => {
|
||||
event.preventDefault();
|
||||
|
||||
nextStep() {
|
||||
const {activeStep} = this.state;
|
||||
const nextStep = activeStep + 1;
|
||||
|
||||
@ -248,6 +296,16 @@ export default class ChangeEmail extends Component {
|
||||
|
||||
this.props.onChangeStep(nextStep);
|
||||
}
|
||||
}
|
||||
|
||||
isLastStep() {
|
||||
return this.state.activeStep + 1 === STEPS_TOTAL;
|
||||
}
|
||||
|
||||
onSwitchStep = (event) => {
|
||||
event.preventDefault();
|
||||
|
||||
this.nextStep();
|
||||
};
|
||||
|
||||
onCodeInput = (event) => {
|
||||
@ -258,11 +316,14 @@ export default class ChangeEmail extends Component {
|
||||
});
|
||||
};
|
||||
|
||||
isLastStep() {
|
||||
return this.state.activeStep + 1 === STEPS_TOTAL;
|
||||
}
|
||||
|
||||
onFormSubmit = () => {
|
||||
this.props.onSubmit(this.props.form);
|
||||
const {activeStep} = this.state;
|
||||
const promise = this.props.onSubmit(activeStep, this.props.stepForms[activeStep]);
|
||||
|
||||
if (!promise || !promise.then) {
|
||||
throw new Error('Expecting promise from onSubmit');
|
||||
}
|
||||
|
||||
promise.then(() => this.nextStep(), () => this.forceUpdate());
|
||||
};
|
||||
}
|
||||
|
@ -1,66 +0,0 @@
|
||||
import { defineMessages } from 'react-intl';
|
||||
|
||||
export default defineMessages({
|
||||
changeEmailTitle: {
|
||||
id: 'changeEmailTitle',
|
||||
defaultMessage: 'Change E-mail'
|
||||
// defaultMessage: 'Смена E-mail'
|
||||
},
|
||||
changeEmailDescription: {
|
||||
id: 'changeEmailDescription',
|
||||
defaultMessage: 'To change current account E-mail you must first verify that you own the current address and then confirm the new one.'
|
||||
// defaultMessage: 'Для смены E-mail адреса аккаунта сперва необходимо подтвердить владение текущим адресом, а за тем привязать новый.'
|
||||
},
|
||||
currentAccountEmail: {
|
||||
id: 'currentAccountEmail',
|
||||
defaultMessage: 'Current account E-mail address:'
|
||||
// defaultMessage: 'Текущий E-mail адрес, привязанный к аккаунту:'
|
||||
},
|
||||
pressButtonToStart: {
|
||||
id: 'pressButtonToStart',
|
||||
defaultMessage: 'Press the button below to send a message with the code for E-mail change initialization.'
|
||||
// defaultMessage: 'Нажмите кнопку ниже, что бы отправить письмо с кодом для инциализации процесса смены E-mail адреса.'
|
||||
},
|
||||
enterInitializationCode: {
|
||||
id: 'enterInitializationCode',
|
||||
defaultMessage: 'The E-mail with an initialization code for E-mail change procedure was sent to {email}. Please enter the code into the field below:'
|
||||
// defaultMessage: 'На E-mail {email} было отправлено письмо с кодом для инициализации смены E-mail адреса. Введите его в поле ниже:'
|
||||
},
|
||||
//
|
||||
enterNewEmail: {
|
||||
id: 'enterNewEmail',
|
||||
defaultMessage: 'Then provide your new E-mail address, that you want to use with this account. You will be mailed with confirmation code.'
|
||||
// defaultMessage: 'За тем укажите новый E-mail адрес, к котором хотите привязать свой аккаунт. На него будет выслан код с подтверждением.'
|
||||
},
|
||||
enterFinalizationCode: {
|
||||
id: 'enterFinalizationCode',
|
||||
defaultMessage: 'The E-mail change confirmation code was sent to {email}. Please enter the code received into the field below:'
|
||||
// defaultMessage: 'На указанный E-mail {email} было выслано письмо с кодом для завершщения смены E-mail адреса. Введите полученный код в поле ниже:'
|
||||
},
|
||||
//
|
||||
newEmailPlaceholder: {
|
||||
id: 'newEmailPlaceholder',
|
||||
defaultMessage: 'Enter new E-mail'
|
||||
// defaultMessage: 'Введите новый E-mail'
|
||||
},
|
||||
codePlaceholder: {
|
||||
id: 'codePlaceholder',
|
||||
defaultMessage: 'Paste the code here'
|
||||
// defaultMessage: 'Вставьте код сюда'
|
||||
},
|
||||
sendEmailButton: {
|
||||
id: 'sendEmailButton',
|
||||
defaultMessage: 'Send E-mail'
|
||||
// defaultMessage: 'Отправить E-mail'
|
||||
},
|
||||
changeEmailButton: {
|
||||
id: 'changeEmailButton',
|
||||
defaultMessage: 'Change E-mail'
|
||||
// defaultMessage: 'Сменить E-mail'
|
||||
},
|
||||
alreadyReceivedCode: {
|
||||
id: 'alreadyReceivedCode',
|
||||
defaultMessage: 'Already received code'
|
||||
// defaultMessage: 'Я получил код'
|
||||
}
|
||||
});
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"changeUsernameTitle": "Change nickname",
|
||||
"changeUsernameDescription": "You can change your nickname to any arbitrary value. Remember that it is not recommended to take a nickname of already existing Mojang account.",
|
||||
"changeUsernameWarning": "Be careful: if you playing on the server with nickname binding, then after changing nickname you may lose all your progress.",
|
||||
"changeUsernameButton": "Change nickname"
|
||||
}
|
@ -7,7 +7,7 @@ import Helmet from 'react-helmet';
|
||||
import { Input, Button, Form, FormModel } from 'components/ui/form';
|
||||
import styles from 'components/profile/profileForm.scss';
|
||||
|
||||
import messages from './ChangeUsername.messages';
|
||||
import messages from './ChangeUsername.intl.json';
|
||||
|
||||
export default class ChangeUsername extends Component {
|
||||
static displayName = 'ChangeUsername';
|
||||
|
@ -1,24 +0,0 @@
|
||||
import { defineMessages } from 'react-intl';
|
||||
|
||||
export default defineMessages({
|
||||
changeUsernameTitle: {
|
||||
id: 'changeUsernameTitle',
|
||||
defaultMessage: 'Change nickname'
|
||||
// defaultMessage: 'Смена никнейма'
|
||||
},
|
||||
changeUsernameDescription: {
|
||||
id: 'changeUsernameDescription',
|
||||
defaultMessage: 'You can change your nickname to any arbitrary value. Remember that it is not recommended to take a nickname of already existing Mojang account.'
|
||||
// defaultMessage: 'Вы можете сменить свой никнейм на любое допустимое значение. Помните о том, что не рекомендуется занимать никнеймы пользователей Mojang.'
|
||||
},
|
||||
changeUsernameWarning: {
|
||||
id: 'changeUsernameWarning',
|
||||
defaultMessage: 'Be careful: if you playing on the server with nickname binding, then after changing nickname you may lose all your progress.'
|
||||
// defaultMessage: 'Будьте внимательны: если вы играли на сервере с привязкой по нику, то после смены ника вы можете утратить весь свой прогресс.'
|
||||
},
|
||||
changeUsernameButton: {
|
||||
id: 'changeUsernameButton',
|
||||
defaultMessage: 'Change nickname'
|
||||
// defaultMessage: 'Сменить никнейм'
|
||||
}
|
||||
});
|
@ -0,0 +1,4 @@
|
||||
{
|
||||
"pleaseEnterPassword": "Please, enter your current password",
|
||||
"title": "Confirm your action"
|
||||
}
|
@ -4,7 +4,7 @@ import { FormattedMessage as Message } from 'react-intl';
|
||||
|
||||
import { Form, Button, Input, FormModel } from 'components/ui/form';
|
||||
|
||||
import messages from './PasswordRequestForm.messages';
|
||||
import messages from './PasswordRequestForm.intl.json';
|
||||
|
||||
export default class PasswordRequestForm extends Component {
|
||||
static displayName = 'PasswordRequestForm';
|
||||
|
@ -1,12 +0,0 @@
|
||||
import { defineMessages } from 'react-intl';
|
||||
|
||||
export default defineMessages({
|
||||
pleaseEnterPassword: {
|
||||
id: 'pleaseEnterPassword',
|
||||
defaultMessage: 'Please, enter your current password'
|
||||
},
|
||||
title: {
|
||||
id: 'title',
|
||||
defaultMessage: 'Confirm your action'
|
||||
}
|
||||
});
|
@ -72,6 +72,10 @@ export default class FormModel {
|
||||
return this.errors[fieldId] || null;
|
||||
}
|
||||
|
||||
hasErrors() {
|
||||
return Object.keys(this.errors).length > 0;
|
||||
}
|
||||
|
||||
serialize() {
|
||||
return Object.keys(this.fields).reduce((acc, fieldId) => {
|
||||
acc[fieldId] = this.fields[fieldId].getValue();
|
||||
|
@ -140,6 +140,17 @@
|
||||
color: $red;
|
||||
font-size: 12px;
|
||||
margin: 3px 0;
|
||||
|
||||
a {
|
||||
border-bottom: 1px dotted rgba($red, 0.75);
|
||||
text-decoration: none;
|
||||
transition: .25s;
|
||||
color: $red;
|
||||
|
||||
&:hover {
|
||||
border-bottom-color: transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include input-theme('green', $green);
|
||||
|
@ -1,13 +1,4 @@
|
||||
{
|
||||
"alreadyReceivedCode": "Already received code",
|
||||
"changeEmailButton": "Change E-mail",
|
||||
"changeEmailDescription": "To change current account E-mail you must first verify that you own the current address and then confirm the new one.",
|
||||
"changeEmailTitle": "Change E-mail",
|
||||
"changeUsernameButton": "Change nickname",
|
||||
"changeUsernameDescription": "You can change your nickname to any arbitrary value. Remember that it is not recommended to take a nickname of already existing Mojang account.",
|
||||
"changeUsernameTitle": "Change nickname",
|
||||
"changeUsernameWarning": "Be careful: if you playing on the server with nickname binding, then after changing nickname you may lose all your progress.",
|
||||
"codePlaceholder": "Paste the code here",
|
||||
"components.auth.activation.accountActivationTitle": "Account activation",
|
||||
"components.auth.activation.activationMailWasSent": "Please check {email} for the message with the last registration step",
|
||||
"components.auth.activation.confirmEmail": "Confirm E-mail",
|
||||
@ -69,6 +60,19 @@
|
||||
"components.langMenu.siteLanguage": "Site language",
|
||||
"components.profile.accountDescription": "Ely.by account allows you to get access to many Minecraft resources. Please, take care of your account safety. Use secure password and change it regularly.",
|
||||
"components.profile.accountPreferencesTitle": "Ely.by account preferences",
|
||||
"components.profile.changeEmail.alreadyReceivedCode": "Already received code",
|
||||
"components.profile.changeEmail.changeEmailButton": "Change E-mail",
|
||||
"components.profile.changeEmail.changeEmailDescription": "To change current account E-mail you must first verify that you own the current address and then confirm the new one.",
|
||||
"components.profile.changeEmail.changeEmailTitle": "Change E-mail",
|
||||
"components.profile.changeEmail.codePlaceholder": "Paste the code here",
|
||||
"components.profile.changeEmail.currentAccountEmail": "Current account E-mail address:",
|
||||
"components.profile.changeEmail.enterFinalizationCode": "In order to confirm your new E-mail, please enter the code received into the field below:",
|
||||
"components.profile.changeEmail.enterInitializationCode": "The E-mail with an initialization code for E-mail change procedure was sent to {email}. Please enter the code into the field below:",
|
||||
"components.profile.changeEmail.enterNewEmail": "Then provide your new E-mail address, that you want to use with this account. You will be mailed with confirmation code.",
|
||||
"components.profile.changeEmail.finalizationCodeWasSentToEmail": "The E-mail change confirmation code was sent to {email}.",
|
||||
"components.profile.changeEmail.newEmailPlaceholder": "Enter new E-mail",
|
||||
"components.profile.changeEmail.pressButtonToStart": "Press the button below to send a message with the code for E-mail change initialization.",
|
||||
"components.profile.changeEmail.sendEmailButton": "Send E-mail",
|
||||
"components.profile.changePassword.achievementLossWarning": "Are you cherish your game achievements, right?",
|
||||
"components.profile.changePassword.changePasswordButton": "Change password",
|
||||
"components.profile.changePassword.changePasswordDescription": "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.",
|
||||
@ -77,26 +81,24 @@
|
||||
"components.profile.changePassword.newPasswordLabel": "New password:",
|
||||
"components.profile.changePassword.passwordRequirements": "Password must contain at least 8 characters. It can be any symbols — do not limit yourself, create an unpredictable password!",
|
||||
"components.profile.changePassword.repeatNewPasswordLabel": "Repeat the password:",
|
||||
"components.profile.changeUsername.changeUsernameButton": "Change nickname",
|
||||
"components.profile.changeUsername.changeUsernameDescription": "You can change your nickname to any arbitrary value. Remember that it is not recommended to take a nickname of already existing Mojang account.",
|
||||
"components.profile.changeUsername.changeUsernameTitle": "Change nickname",
|
||||
"components.profile.changeUsername.changeUsernameWarning": "Be careful: if you playing on the server with nickname binding, then after changing nickname you may lose all your progress.",
|
||||
"components.profile.changedAt": "Changed {at}",
|
||||
"components.profile.disabled": "Disabled",
|
||||
"components.profile.mojangPriorityWarning": "A Mojang account with the same nickname was found. According to project rules, account owner has the right to demand the restoration of control over nickname.",
|
||||
"components.profile.nickname": "Nickname",
|
||||
"components.profile.oldHashingAlgoWarning": "Your was hashed with an old hashing algorithm.<br />Please, change password.",
|
||||
"components.profile.password": "Password",
|
||||
"components.profile.passwordRequestForm.pleaseEnterPassword": "Please, enter your current password",
|
||||
"components.profile.passwordRequestForm.title": "Confirm your action",
|
||||
"components.profile.personalData": "Personal data",
|
||||
"components.profile.preferencesDescription": "Here you can change the key preferences of your account. Please note that all actions must be confirmed by entering a password.",
|
||||
"components.profile.twoFactorAuth": "Two factor auth",
|
||||
"currentAccountEmail": "Current account E-mail address:",
|
||||
"enterFinalizationCode": "The E-mail change confirmation code was sent to {email}. Please enter the code received into the field below:",
|
||||
"enterInitializationCode": "The E-mail with an initialization code for E-mail change procedure was sent to {email}. Please enter the code into the field below:",
|
||||
"enterNewEmail": "Then provide your new E-mail address, that you want to use with this account. You will be mailed with confirmation code.",
|
||||
"logout": "Logout",
|
||||
"newEmailPlaceholder": "Enter new E-mail",
|
||||
"pages.root.siteName": "Ely.by",
|
||||
"pleaseEnterPassword": "Please, enter your current password",
|
||||
"pressButtonToStart": "Press the button below to send a message with the code for E-mail change initialization.",
|
||||
"register": "Join",
|
||||
"sendEmailButton": "Send E-mail",
|
||||
"services.accountNotActivated": "The account is not activated",
|
||||
"services.emailFrequency": "Please cool down, you are requesting emails too often. New key can be retrieved after 30 minutes from the previous request.",
|
||||
"services.emailInvalid": "Email is invalid",
|
||||
@ -112,6 +114,7 @@
|
||||
"services.loginRequired": "Please enter email or username",
|
||||
"services.newPasswordRequired": "Please enter new password",
|
||||
"services.newRePasswordRequired": "Please repeat new password",
|
||||
"services.oldHashStrategy": "Sorry, but your account's password is too old. Please change your password in order to perform this action.",
|
||||
"services.passwordRequired": "Please enter password",
|
||||
"services.passwordTooShort": "Your password should be at least 8 characters length",
|
||||
"services.passwordsDoesNotMatch": "The passwords does not match",
|
||||
@ -122,6 +125,5 @@
|
||||
"services.usernameRequired": "Username is required",
|
||||
"services.usernameTooLong": "Username is too long",
|
||||
"services.usernameTooShort": "Username is too short",
|
||||
"services.usernameUnavailable": "This username is already taken",
|
||||
"title": "Confirm your action"
|
||||
"services.usernameUnavailable": "This username is already taken"
|
||||
}
|
||||
|
@ -1,13 +1,4 @@
|
||||
{
|
||||
"alreadyReceivedCode": "Already received code",
|
||||
"changeEmailButton": "Change E-mail",
|
||||
"changeEmailDescription": "To change current account E-mail you must first verify that you own the current address and then confirm the new one.",
|
||||
"changeEmailTitle": "Change E-mail",
|
||||
"changeUsernameButton": "Change nickname",
|
||||
"changeUsernameDescription": "You can change your nickname to any arbitrary value. Remember that it is not recommended to take a nickname of already existing Mojang account.",
|
||||
"changeUsernameTitle": "Change nickname",
|
||||
"changeUsernameWarning": "Be careful: if you playing on the server with nickname binding, then after changing nickname you may lose all your progress.",
|
||||
"codePlaceholder": "Paste the code here",
|
||||
"components.auth.activation.accountActivationTitle": "Активация аккаунта",
|
||||
"components.auth.activation.activationMailWasSent": "На {email} отправлено письмо с инструкциями по завершению регистрации",
|
||||
"components.auth.activation.confirmEmail": "Подтверждение E-mail",
|
||||
@ -69,6 +60,19 @@
|
||||
"components.langMenu.siteLanguage": "Язык сайта",
|
||||
"components.profile.accountDescription": "Благодаря аккаунту Ely.by вы можете получить доступ ко многим ресурсам, связанным с Minecraft. Берегите свой аккаунт, используйте надёжный пароль и регулярно его меняйте.",
|
||||
"components.profile.accountPreferencesTitle": "Настройки аккаунта Ely.by",
|
||||
"components.profile.changeEmail.alreadyReceivedCode": "Я уже получил код",
|
||||
"components.profile.changeEmail.changeEmailButton": "Сменить E-mail",
|
||||
"components.profile.changeEmail.changeEmailDescription": "Для смены E-mail адреса аккаунта сперва необходимо подтвердить владение текущим адресом, а за тем привязать новый.",
|
||||
"components.profile.changeEmail.changeEmailTitle": "Смена E-mail",
|
||||
"components.profile.changeEmail.codePlaceholder": "Вставьте код сюда",
|
||||
"components.profile.changeEmail.currentAccountEmail": "Текущий E-mail адрес, привязанный к аккаунту:",
|
||||
"components.profile.changeEmail.enterFinalizationCode": "Что бы подтвердить ваш новый E-mail, пожалуйста аведите полученный код в поле ниже:",
|
||||
"components.profile.changeEmail.enterInitializationCode": "На E-mail {email} было отправлено письмо с кодом для инициализации смены E-mail адреса. Введите его в поле ниже:",
|
||||
"components.profile.changeEmail.enterNewEmail": "За тем укажите новый E-mail адрес, к котором хотите привязать свой аккаунт. На него будет выслан код с подтверждением.",
|
||||
"components.profile.changeEmail.finalizationCodeWasSentToEmail": "На указанный E-mail {email} было выслано письмо с кодом для завершщения смены E-mail адреса.",
|
||||
"components.profile.changeEmail.newEmailPlaceholder": "Введите новый E-mail",
|
||||
"components.profile.changeEmail.pressButtonToStart": "Нажмите на кнопку ниже, чтобы отправить письмо с кодом для инициализации процесса смены E-mail адреса.",
|
||||
"components.profile.changeEmail.sendEmailButton": "Отправить E-mail",
|
||||
"components.profile.changePassword.achievementLossWarning": "Вы ведь дорожите своими игровыми достижениями?",
|
||||
"components.profile.changePassword.changePasswordButton": "Сменить пароль",
|
||||
"components.profile.changePassword.changePasswordDescription": "Придумайте пароль, который будет отличаться от ваших паролей на других сайтах и не будет совпадаеть с тем паролем, который вы используете для входа на различные игровые сервера Minecraft.",
|
||||
@ -77,26 +81,24 @@
|
||||
"components.profile.changePassword.newPasswordLabel": "Новый пароль:",
|
||||
"components.profile.changePassword.passwordRequirements": "Пароль должен содержать не менее 8 символов. Это могут быть любым символы — не ограничивайте себя, придумайте непредсказуемый пароль!",
|
||||
"components.profile.changePassword.repeatNewPasswordLabel": "Повторите указанный пароль:",
|
||||
"components.profile.changeUsername.changeUsernameButton": "Сменить никнейм",
|
||||
"components.profile.changeUsername.changeUsernameDescription": "Вы можете сменить свой никнейм на любое допустимое значение. Помните о том, что не рекомендуется занимать никнеймы пользователей Mojang.",
|
||||
"components.profile.changeUsername.changeUsernameTitle": "Смена никнейма",
|
||||
"components.profile.changeUsername.changeUsernameWarning": "Будьте внимательны: если вы играли на сервере с привязкой по нику, то после смены ника вы можете утратить весь свой прогресс.",
|
||||
"components.profile.changedAt": "Изменен {at}",
|
||||
"components.profile.disabled": "Не включена",
|
||||
"components.profile.mojangPriorityWarning": "Найден аккаунт Mojang с таким же ником и, по правилам проекта, его владелец вправе потребовать восстановления контроля над ником.",
|
||||
"components.profile.nickname": "Ник",
|
||||
"components.profile.oldHashingAlgoWarning": "Для пароля применяется старый алгоритм хэширования<br />Пожалуйста, смените пароль.",
|
||||
"components.profile.password": "Пароль",
|
||||
"components.profile.passwordRequestForm.pleaseEnterPassword": "Пожалуйста, введите пароль от аккаунта",
|
||||
"components.profile.passwordRequestForm.title": "Confirm your action",
|
||||
"components.profile.personalData": "Персональные данные",
|
||||
"components.profile.preferencesDescription": "Здесь вы можете сменить ключевые параметры вашего аккаунта. Обратите внимание, что для всех действий необходимо подтверждение при помощи ввода пароля.",
|
||||
"components.profile.twoFactorAuth": "Двухфакторная аутентификация",
|
||||
"currentAccountEmail": "Current account E-mail address:",
|
||||
"enterFinalizationCode": "The E-mail change confirmation code was sent to {email}. Please enter the code received into the field below:",
|
||||
"enterInitializationCode": "The E-mail with an initialization code for E-mail change procedure was sent to {email}. Please enter the code into the field below:",
|
||||
"enterNewEmail": "Then provide your new E-mail address, that you want to use with this account. You will be mailed with confirmation code.",
|
||||
"logout": "Выход",
|
||||
"newEmailPlaceholder": "Новый E-mail",
|
||||
"pages.root.siteName": "Ely.by",
|
||||
"pleaseEnterPassword": "Пожалуйста, введите пароль от аккаунта",
|
||||
"pressButtonToStart": "Нажмите на кнопку ниже, чтобы отправить письмо с кодом для инициализации процесса смены E-mail адреса.",
|
||||
"register": "Регистрация",
|
||||
"sendEmailButton": "Отправить E-mail",
|
||||
"services.accountNotActivated": "Аккаунт не активирован",
|
||||
"services.emailFrequency": "Пожалуйста, успокойтесь, вы запрашиваете E-mail слишком часто. Новый ключ можно будет заказать через 30 минут от предыдущего запроса.",
|
||||
"services.emailInvalid": "Указан неправильный E-mail",
|
||||
@ -112,6 +114,7 @@
|
||||
"services.loginRequired": "Пожалуйста, укажите E-mail или ник",
|
||||
"services.newPasswordRequired": "Пожалуйста, заполните поле пароля",
|
||||
"services.newRePasswordRequired": "Пожалуйста, введите повтор пароля",
|
||||
"services.oldHashStrategy": "Sorry, but your account's password is too old. Please change your password in order to perform this action.",
|
||||
"services.passwordRequired": "Пожалуйста, введите пароль",
|
||||
"services.passwordTooShort": "Пароль должен быть как минимум 8 символов в длинну",
|
||||
"services.passwordsDoesNotMatch": "Пароли не совпадают",
|
||||
@ -122,6 +125,5 @@
|
||||
"services.usernameRequired": "Поле ника обязательно к заполнению",
|
||||
"services.usernameTooLong": "Слишком длинный ник",
|
||||
"services.usernameTooShort": "Ник слишком короткий",
|
||||
"services.usernameUnavailable": "Этот ник уже занят",
|
||||
"title": "Confirm your action"
|
||||
"services.usernameUnavailable": "Этот ник уже занят"
|
||||
}
|
||||
|
@ -8,10 +8,12 @@ class ChangePasswordPage extends Component {
|
||||
static displayName = 'ChangePasswordPage';
|
||||
|
||||
static propTypes = {
|
||||
updateUser: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
static contextTypes = {
|
||||
onSubmit: PropTypes.func.isRequired
|
||||
onSubmit: PropTypes.func.isRequired,
|
||||
goToProfile: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
form = new FormModel();
|
||||
@ -32,6 +34,7 @@ class ChangePasswordPage extends Component {
|
||||
passwordChangedAt: Date.now() / 1000,
|
||||
shouldChangePassword: false
|
||||
});
|
||||
this.context.goToProfile();
|
||||
});
|
||||
};
|
||||
}
|
||||
|
@ -55,10 +55,7 @@ class ChangeUsernamePage extends Component {
|
||||
sendData: () => accounts.changeUsername(form.serialize())
|
||||
}).then(() => {
|
||||
this.props.updateUsername(form.value('username'));
|
||||
|
||||
this.setState({
|
||||
actualUsername: this.props.username
|
||||
});
|
||||
this.context.goToProfile();
|
||||
});
|
||||
};
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
|
||||
import { FormModel } from 'components/ui/form';
|
||||
import ChangeEmail from 'components/profile/changeEmail/ChangeEmail';
|
||||
|
||||
import accounts from 'services/api/accounts';
|
||||
|
||||
class ProfileChangeEmailPage extends Component {
|
||||
static displayName = 'ProfileChangeEmailPage';
|
||||
|
||||
@ -17,11 +18,11 @@ class ProfileChangeEmailPage extends Component {
|
||||
static contextTypes = {
|
||||
router: PropTypes.shape({
|
||||
push: PropTypes.func
|
||||
}).isRequired
|
||||
}).isRequired,
|
||||
onSubmit: PropTypes.func.isRequired,
|
||||
goToProfile: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
form = new FormModel();
|
||||
|
||||
componentWillMount() {
|
||||
const step = this.props.params.step;
|
||||
|
||||
@ -33,13 +34,13 @@ class ProfileChangeEmailPage extends Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const {params: {step, code}} = this.props;
|
||||
const {params: {step = 'step1', code}} = this.props;
|
||||
|
||||
return (
|
||||
<ChangeEmail form={this.form}
|
||||
<ChangeEmail
|
||||
onSubmit={this.onSubmit}
|
||||
email={this.props.email}
|
||||
step={step ? step.slice(-1) * 1 - 1 : step}
|
||||
step={step.slice(-1) * 1 - 1}
|
||||
onChangeStep={this.onChangeStep}
|
||||
code={code}
|
||||
/>
|
||||
@ -50,7 +51,26 @@ class ProfileChangeEmailPage extends Component {
|
||||
this.context.router.push(`/profile/change-email/step${++step}`);
|
||||
};
|
||||
|
||||
onSubmit = () => {
|
||||
onSubmit = (step, form) => {
|
||||
return this.context.onSubmit({
|
||||
form,
|
||||
sendData: () => {
|
||||
const data = form.serialize();
|
||||
|
||||
switch (step) {
|
||||
case 0:
|
||||
return accounts.requestEmailChange();
|
||||
case 1:
|
||||
return accounts.setNewEmail(data);
|
||||
case 2:
|
||||
return accounts.confirmNewEmail(data);
|
||||
default:
|
||||
throw new Error(`Unsupported step ${step}`);
|
||||
}
|
||||
}
|
||||
}).then(() => {
|
||||
step > 1 && this.context.goToProfile();
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,8 @@ class ProfilePage extends Component {
|
||||
|
||||
static propTypes = {
|
||||
onSubmit: PropTypes.func.isRequired,
|
||||
goToProfile: PropTypes.func.isRequired
|
||||
goToProfile: PropTypes.func.isRequired,
|
||||
children: PropTypes.element
|
||||
};
|
||||
|
||||
static childContextTypes = {
|
||||
@ -36,15 +37,15 @@ 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, {
|
||||
goToProfile,
|
||||
goToProfile() {
|
||||
return routeActions.push('/');
|
||||
},
|
||||
onSubmit: ({form, sendData}) => (dispatch) =>
|
||||
sendData()
|
||||
.catch((resp) => {
|
||||
const requirePassword = resp.errors && !!resp.errors.password;
|
||||
|
||||
// prevalidate user input, because requestPassword popup will block the
|
||||
// entire form from input, so it must be valid
|
||||
if (resp.errors) {
|
||||
@ -54,26 +55,29 @@ export default connect(null, {
|
||||
form.setErrors(resp.errors);
|
||||
return Promise.reject(resp);
|
||||
}
|
||||
|
||||
return Promise.resolve({requirePassword});
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
})
|
||||
.then(() => new Promise((resolve) => {
|
||||
dispatch(createPopup(PasswordRequestForm, (props) => ({
|
||||
form,
|
||||
onSubmit: () => {
|
||||
sendData()
|
||||
.catch((resp) => {
|
||||
if (resp.errors) {
|
||||
form.setErrors(resp.errors);
|
||||
}
|
||||
.then((resp) => new Promise((resolve) => {
|
||||
if (resp.requirePassword) {
|
||||
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()));
|
||||
}
|
||||
})));
|
||||
return Promise.reject(resp);
|
||||
})
|
||||
.then(resolve)
|
||||
.then(props.onClose);
|
||||
}
|
||||
})));
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
}))
|
||||
})(ProfilePage);
|
||||
|
@ -32,5 +32,28 @@ export default {
|
||||
'/api/accounts/change-lang',
|
||||
{lang}
|
||||
);
|
||||
},
|
||||
|
||||
requestEmailChange() {
|
||||
return request.post(
|
||||
'/api/accounts/change-email/initialize'
|
||||
);
|
||||
},
|
||||
|
||||
setNewEmail({
|
||||
email = '',
|
||||
key = ''
|
||||
}) {
|
||||
return request.post(
|
||||
'/api/accounts/change-email/submit-new-email',
|
||||
{email, key}
|
||||
);
|
||||
},
|
||||
|
||||
confirmNewEmail({key}) {
|
||||
return request.post(
|
||||
'/api/accounts/change-email/confirm-new-email',
|
||||
{key}
|
||||
);
|
||||
}
|
||||
};
|
||||
|
@ -24,5 +24,6 @@
|
||||
"keyRequired": "Please, enter an activation key",
|
||||
"keyNotExists": "The key is incorrect",
|
||||
"emailFrequency": "Please cool down, you are requesting emails too often. New key can be retrieved after 30 minutes from the previous request.",
|
||||
"accountNotActivated": "The account is not activated"
|
||||
"accountNotActivated": "The account is not activated",
|
||||
"oldHashStrategy": "Sorry, but your account's password is too old. Please change your password in order to perform this action."
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ const errorsMap = {
|
||||
'error.password_required': () => <Message {...messages.passwordRequired} />,
|
||||
|
||||
'error.password_invalid': () => <Message {...messages.invalidPassword} />,
|
||||
'error.old_hash_strategy': () => <Message {...messages.oldHashStrategy} />,
|
||||
'error.password_incorrect': () => (
|
||||
<span>
|
||||
<Message {...messages.invalidPassword} />
|
||||
|
@ -14,7 +14,7 @@ function convertQueryValue(value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
function buildQuery(data) {
|
||||
function buildQuery(data = {}) {
|
||||
return Object.keys(data)
|
||||
.map(
|
||||
(keyName) =>
|
||||
|
Loading…
Reference in New Issue
Block a user