#26: refactor auth components

This commit is contained in:
SleepWalker 2016-05-14 14:26:17 +03:00
parent 5719259825
commit b0a6740751
37 changed files with 557 additions and 736 deletions

View File

@ -0,0 +1,12 @@
import React from 'react';
import Helmet from 'react-helmet';
import { FormattedMessage as Message } from 'react-intl';
export default function AuthTitle({title}) {
return (
<Message {...title}>
{(msg) => <span>{msg}<Helmet title={msg} /></span>}
</Message>
);
}

View File

@ -0,0 +1,7 @@
{
"accountActivationTitle": "Account activation",
"activationMailWasSent": "Please check {email} for the message with the last registration step",
"confirmEmail": "Confirm E-mail",
"didNotReceivedEmail": "Did not received E-mail?",
"enterTheCode": "Enter the code from E-mail here"
}

View File

@ -1,61 +1,18 @@
import React from 'react';
import { FormattedMessage as Message } from 'react-intl';
import Helmet from 'react-helmet';
import buttons from 'components/ui/buttons.scss';
import { Input } from 'components/ui/form';
import { Button } from 'components/ui/form';
import AuthTitle from 'components/auth/AuthTitle';
import BaseAuthBody from 'components/auth/BaseAuthBody';
import styles from './activation.scss';
import messages from './Activation.messages';
class Body extends BaseAuthBody {
static displayName = 'ActivationBody';
static panelId = 'activation';
autoFocusField = 'key';
render() {
return (
<div>
{this.renderErrors()}
<div className={styles.description}>
<div className={styles.descriptionImage} />
<div className={styles.descriptionText}>
<Message {...messages.activationMailWasSent} values={{
email: (<b>{this.context.user.email}</b>)
}} />
</div>
</div>
<div className={styles.formRow}>
<Input {...this.bindField('key')}
color="blue"
className={styles.activationCodeInput}
required
placeholder={messages.enterTheCode}
/>
</div>
</div>
);
}
}
import messages from './Activation.intl.json';
import Body from './ActivationBody';
export default function Activation() {
return {
Title: () => ( // TODO: separate component for PageTitle
<Message {...messages.accountActivationTitle}>
{(msg) => <span>{msg}<Helmet title={msg} /></span>}
</Message>
),
Title: () => <AuthTitle title={messages.accountActivationTitle} />,
Body,
Footer: () => (
<button className={buttons.blue}>
<Message {...messages.confirmEmail} />
</button>
),
Footer: () => <Button color="blue" label={messages.confirmEmail} />,
Links: () => (
<a href="#">
<Message {...messages.didNotReceivedEmail} />

View File

@ -1,28 +0,0 @@
import { defineMessages } from 'react-intl';
export default defineMessages({
accountActivationTitle: {
id: 'accountActivationTitle',
defaultMessage: 'Account activation'
},
activationMailWasSent: {
id: 'activationMailWasSent',
defaultMessage: 'Please check {email} for the message with the last registration step'
},
confirmEmail: {
id: 'confirmEmail',
defaultMessage: 'Confirm E-mail'
},
didNotReceivedEmail: {
id: 'didNotReceivedEmail',
defaultMessage: 'Did not received E-mail?'
},
enterTheCode: {
id: 'enterTheCode',
defaultMessage: 'Enter the code from E-mail here'
}
});

View File

@ -0,0 +1,42 @@
import React from 'react';
import { FormattedMessage as Message } from 'react-intl';
import { Input } from 'components/ui/form';
import BaseAuthBody from 'components/auth/BaseAuthBody';
import styles from './activation.scss';
import messages from './Activation.intl.json';
export default class ActivationBody extends BaseAuthBody {
static displayName = 'ActivationBody';
static panelId = 'activation';
autoFocusField = 'key';
render() {
return (
<div>
{this.renderErrors()}
<div className={styles.description}>
<div className={styles.descriptionImage} />
<div className={styles.descriptionText}>
<Message {...messages.activationMailWasSent} values={{
email: (<b>{this.context.user.email}</b>)
}} />
</div>
</div>
<div className={styles.formRow}>
<Input {...this.bindField('key')}
color="blue"
className={styles.activationCodeInput}
required
placeholder={messages.enterTheCode}
/>
</div>
</div>
);
}
}

View File

@ -0,0 +1,3 @@
{
"goToAuth": "Go to auth"
}

View File

@ -1,11 +1,9 @@
import React, { Component, PropTypes } from 'react';
import { FormattedMessage as Message } from 'react-intl';
import buttons from 'components/ui/buttons.scss';
import { Button } from 'components/ui/form';
import styles from './appInfo.scss';
import messages from './AppInfo.messages';
import messages from './AppInfo.intl.json';
export default class AppInfo extends Component {
static displayName = 'AppInfo';
@ -17,7 +15,7 @@ export default class AppInfo extends Component {
};
render() {
var { name, description, onGoToAuth } = this.props;
const { name, description, onGoToAuth } = this.props;
return (
<div className={styles.appInfo}>
@ -30,9 +28,7 @@ export default class AppInfo extends Component {
</p>
</div>
<div className={styles.goToAuth}>
<button className={buttons.green} onClick={onGoToAuth}>
<Message {...messages.goToAuth} />
</button>
<Button onClick={onGoToAuth} label={messages.goToAuth} />
</div>
</div>
);

View File

@ -1,8 +0,0 @@
import { defineMessages } from 'react-intl';
export default defineMessages({
goToAuth: {
id: 'goToAuth',
defaultMessage: 'Go to auth'
}
});

View File

@ -0,0 +1,9 @@
{
"changePasswordTitle": "Change password",
"changePasswordMessage": "To enhance the security of your account, please change your password.",
"skipThisStep": "Skip password changing",
"change": "Change",
"currentPassword": "Enter current password",
"newPassword": "Enter new password",
"newRePassword": "Repeat new password"
}

View File

@ -1,76 +1,18 @@
import React, { PropTypes } from 'react';
import { FormattedMessage as Message } from 'react-intl';
import Helmet from 'react-helmet';
import buttons from 'components/ui/buttons.scss';
import { Input } from 'components/ui/form';
import BaseAuthBody from 'components/auth/BaseAuthBody';
import icons from 'components/ui/icons.scss';
import { Button } from 'components/ui/form';
import AuthTitle from 'components/auth/AuthTitle';
import messages from './ChangePassword.messages';
import styles from './changePassword.scss';
class Body extends BaseAuthBody {
static displayName = 'ChangePasswordBody';
static panelId = 'changePassword';
autoFocusField = 'password';
render() {
return (
<div>
{this.renderErrors()}
<div className={styles.security}>
<span className={icons.lock} />
</div>
<p className={styles.descriptionText}>
<Message {...messages.changePasswordMessage} />
</p>
<Input {...this.bindField('password')}
icon="key"
color="darkBlue"
type="password"
required
placeholder={messages.currentPassword}
/>
<Input {...this.bindField('newPassword')}
icon="key"
color="darkBlue"
type="password"
required
placeholder={messages.newPassword}
/>
<Input {...this.bindField('newRePassword')}
icon="key"
color="darkBlue"
type="password"
required
placeholder={messages.newRePassword}
/>
</div>
);
}
}
import Body from './ChangePasswordBody';
import messages from './ChangePassword.intl.json';
export default function ChangePassword() {
const componentsMap = {
Title: () => ( // TODO: separate component for PageTitle
<Message {...messages.changePasswordTitle}>
{(msg) => <span>{msg}<Helmet title={msg} /></span>}
</Message>
),
Title: () => <AuthTitle title={messages.changePasswordTitle} />,
Body,
Footer: () => (
<button className={buttons.darkBlue} type="submit">
<Message {...messages.change} />
</button>
),
Footer: () => <Button color="darkBlue" label={messages.change} />,
Links: (props, context) => (
<a href="#" onClick={(event) => {
event.preventDefault();

View File

@ -1,32 +0,0 @@
import { defineMessages } from 'react-intl';
export default defineMessages({
changePasswordTitle: {
id: 'changePasswordTitle',
defaultMessage: 'Change password'
},
changePasswordMessage: {
id: 'passwordChangeMessage',
defaultMessage: 'To enhance the security of your account, please change your password.'
},
skipThisStep: {
id: 'skipThisStep',
defaultMessage: 'Skip password changing'
},
change: {
id: 'change',
defaultMessage: 'Change'
},
currentPassword: {
id: 'currentPassword',
defaultMessage: 'Enter current password'
},
newPassword: {
id: 'newPassword',
defaultMessage: 'Enter new password'
},
newRePassword: {
id: 'newRePassword',
defaultMessage: 'Repeat new password'
}
});

View File

@ -0,0 +1,57 @@
import React from 'react';
import { FormattedMessage as Message } from 'react-intl';
import { Input } from 'components/ui/form';
import icons from 'components/ui/icons.scss';
import BaseAuthBody from 'components/auth/BaseAuthBody';
import styles from './changePassword.scss';
import messages from './ChangePassword.intl.json';
export default class ChangePasswordBody extends BaseAuthBody {
static displayName = 'ChangePasswordBody';
static panelId = 'changePassword';
autoFocusField = 'password';
render() {
return (
<div>
{this.renderErrors()}
<div className={styles.security}>
<span className={icons.lock} />
</div>
<p className={styles.descriptionText}>
<Message {...messages.changePasswordMessage} />
</p>
<Input {...this.bindField('password')}
icon="key"
color="darkBlue"
type="password"
required
placeholder={messages.currentPassword}
/>
<Input {...this.bindField('newPassword')}
icon="key"
color="darkBlue"
type="password"
required
placeholder={messages.newPassword}
/>
<Input {...this.bindField('newRePassword')}
icon="key"
color="darkBlue"
type="password"
required
placeholder={messages.newRePassword}
/>
</div>
);
}
}

View File

@ -0,0 +1,7 @@
{
"authForAppSuccessful": "Authorization for {appName} was successfully completed",
"authForAppFailed": "Authorization for {appName} was failed",
"waitAppReaction": "Please, wait till your application response",
"passCodeToApp": "To complete authorization process, please, provide the following code to {appName}",
"copy": "Copy"
}

View File

@ -2,12 +2,11 @@ import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import { FormattedMessage as Message } from 'react-intl';
import classNames from 'classnames';
import Helmet from 'react-helmet';
import buttons from 'components/ui/buttons.scss';
import { Button } from 'components/ui/form';
import messages from './Finish.messages';
import messages from './Finish.intl.json';
import styles from './finish.scss';
class Finish extends Component {
@ -55,12 +54,12 @@ class Finish extends Component {
<div className={styles.code} ref={this.setCode}>{code}</div>
</div>
{isCopySupported ? (
<button
className={classNames(buttons.smallButton, buttons.green)}
<Button
color="green"
small
label={messages.copy}
onClick={this.handleCopyClick}
>
<Message {...messages.copy} />
</button>
/>
) : (
''
)}

View File

@ -1,29 +0,0 @@
import { defineMessages } from 'react-intl';
export default defineMessages({
authForAppSuccessful: {
id: 'authForAppSuccessful',
defaultMessage: 'Authorization for {appName} was successfully completed'
// defaultMessage: 'Авторизация для {appName} успешно выполнена'
},
authForAppFailed: {
id: 'authForAppFailed',
defaultMessage: 'Authorization for {appName} was failed'
// defaultMessage: 'Авторизация для {appName} не удалась'
},
waitAppReaction: {
id: 'waitAppReaction',
defaultMessage: 'Please, wait till your application response'
// defaultMessage: 'Пожалуйста, дождитесь реакции вашего приложения'
},
passCodeToApp: {
id: 'passCodeToApp',
defaultMessage: 'To complete authorization process, please, provide the following code to {appName}'
// defaultMessage: 'Чтобы завершить процесс авторизации, пожалуйста, передай {appName} этот код'
},
copy: {
id: 'copy',
defaultMessage: 'Copy'
// defaultMessage: 'Скопировать'
}
});

View File

@ -0,0 +1,7 @@
{
"forgotPasswordTitle": "Forgot password",
"contactSupport": "Contact support",
"sendMail": "Send mail",
"forgotPasswordMessage": "Specify the registration E-mail address for your account and we will send an email with instructions for further password recovery.",
"accountEmail": "Enter account E-mail"
}

View File

@ -1,64 +1,18 @@
import React from 'react';
import { FormattedMessage as Message } from 'react-intl';
import Helmet from 'react-helmet';
import buttons from 'components/ui/buttons.scss';
import { Input } from 'components/ui/form';
import { Button } from 'components/ui/form';
import AuthTitle from 'components/auth/AuthTitle';
import BaseAuthBody from 'components/auth/BaseAuthBody';
import messages from './ForgotPassword.messages';
import styles from './forgotPassword.scss';
class Body extends BaseAuthBody {
static displayName = 'ForgotPasswordBody';
static panelId = 'forgotPassword';
static hasGoBack = true;
autoFocusField = 'email';
// Если юзер вводил своё мыло во время попытки авторизации, то почему бы его сюда автоматически не подставить?
render() {
const {user} = this.context;
return (
<div>
{this.renderErrors()}
<p className={styles.descriptionText}>
<Message {...messages.forgotPasswordMessage} />
</p>
<Input {...this.bindField('email')}
icon="envelope"
color="lightViolet"
required
placeholder={messages.accountEmail}
defaultValue={user.email || user.username || ''}
/>
</div>
);
}
onFormSubmit() {
// TODO: обработчик отправки письма с инструкцией по смене пароля
}
}
import messages from './ForgotPassword.intl.json';
import Body from './ForgotPasswordBody';
export default function ForgotPassword() {
return {
Title: () => ( // TODO: separate component for PageTitle
<Message {...messages.forgotPasswordTitle}>
{(msg) => <span>{msg}<Helmet title={msg} /></span>}
</Message>
),
Title: () => <AuthTitle title={messages.forgotPasswordTitle} />,
Body,
Footer: () => (
<button className={buttons.lightViolet} type="submit">
<Message {...messages.sendMail} />
</button>
),
Footer: () => <Button color="lightViolet" label={messages.sendMail} />,
Links: () => (
<a href="/send-message">
<Message {...messages.contactSupport} />

View File

@ -1,24 +0,0 @@
import { defineMessages } from 'react-intl';
export default defineMessages({
forgotPasswordTitle: {
id: 'forgotPasswordTitle',
defaultMessage: 'Forgot password'
},
contactSupport: {
id: 'contactSupport',
defaultMessage: 'Contact support'
},
sendMail: {
id: 'sendMail',
defaultMessage: 'Send mail'
},
forgotPasswordMessage: {
id: 'forgotPasswordMessage',
defaultMessage: 'Specify the registration E-mail address for your account and we will send an email with instructions for further password recovery.'
},
accountEmail: {
id: 'accountEmail',
defaultMessage: 'Enter account E-mail'
}
});

View File

@ -0,0 +1,40 @@
import React from 'react';
import { FormattedMessage as Message } from 'react-intl';
import { Input } from 'components/ui/form';
import BaseAuthBody from 'components/auth/BaseAuthBody';
import styles from './forgotPassword.scss';
import messages from './ForgotPassword.intl.json';
export default class ForgotPasswordBody extends BaseAuthBody {
static displayName = 'ForgotPasswordBody';
static panelId = 'forgotPassword';
static hasGoBack = true;
autoFocusField = 'email';
// Если юзер вводил своё мыло во время попытки авторизации, то почему бы его сюда автоматически не подставить?
render() {
const {user} = this.context;
return (
<div>
{this.renderErrors()}
<p className={styles.descriptionText}>
<Message {...messages.forgotPasswordMessage} />
</p>
<Input {...this.bindField('email')}
icon="envelope"
color="lightViolet"
required
placeholder={messages.accountEmail}
defaultValue={user.email || user.username || ''}
/>
</div>
);
}
}

View File

@ -0,0 +1,5 @@
{
"loginTitle": "Sign in",
"emailOrUsername": "E-mail or username",
"next": "Next"
}

View File

@ -1,52 +1,17 @@
import React from 'react';
import { FormattedMessage as Message } from 'react-intl';
import Helmet from 'react-helmet';
import { Link } from 'react-router';
import { Button } from 'components/ui/form';
import AuthTitle from 'components/auth/AuthTitle';
import buttons from 'components/ui/buttons.scss';
import { Input } from 'components/ui/form';
import BaseAuthBody from 'components/auth/BaseAuthBody';
import passwordMessages from 'components/auth/password/Password.intl.json';
import messages from './Login.messages';
class Body extends BaseAuthBody {
static displayName = 'LoginBody';
static panelId = 'login';
autoFocusField = 'login';
render() {
return (
<div>
{this.renderErrors()}
<Input {...this.bindField('login')}
icon="envelope"
required
placeholder={messages.emailOrUsername}
/>
</div>
);
}
}
import Body from './LoginBody';
import messages from './Login.intl.json';
export default function Login() {
return {
Title: () => ( // TODO: separate component for PageTitle
<Message {...messages.loginTitle}>
{(msg) => <span>{msg}<Helmet title={msg} /></span>}
</Message>
),
Title: () => <AuthTitle title={messages.loginTitle} />,
Body,
Footer: () => (
<button className={buttons.green} type="submit">
<Message {...messages.next} />
</button>
),
Links: () => (
<span/>
)
Footer: () => <Button color="green" label={messages.next} />,
Links: () => null
};
}

View File

@ -1,18 +0,0 @@
import { defineMessages } from 'react-intl';
export default defineMessages({
loginTitle: {
id: 'loginTitle',
defaultMessage: 'Sign in'
},
emailOrUsername: {
id: 'emailOrUsername',
defaultMessage: 'E-mail or username'
},
next: {
id: 'next',
defaultMessage: 'Next'
}
});

View File

@ -0,0 +1,27 @@
import React from 'react';
import { Input } from 'components/ui/form';
import BaseAuthBody from 'components/auth/BaseAuthBody';
import messages from './Login.intl.json';
export default class LoginBody extends BaseAuthBody {
static displayName = 'LoginBody';
static panelId = 'login';
autoFocusField = 'login';
render() {
return (
<div>
{this.renderErrors()}
<Input {...this.bindField('login')}
icon="envelope"
required
placeholder={messages.emailOrUsername}
/>
</div>
);
}
}

View File

@ -1,71 +1,19 @@
import React from 'react';
import { FormattedMessage as Message } from 'react-intl';
import Helmet from 'react-helmet';
import { Link } from 'react-router';
import buttons from 'components/ui/buttons.scss';
import icons from 'components/ui/icons.scss';
import { Input, Checkbox } from 'components/ui/form';
import { Button } from 'components/ui/form';
import AuthTitle from 'components/auth/AuthTitle';
import BaseAuthBody from 'components/auth/BaseAuthBody';
import styles from './password.scss';
import Body from './PasswordBody';
import messages from './Password.intl.json';
class Body extends BaseAuthBody {
static displayName = 'PasswordBody';
static panelId = 'password';
static hasGoBack = true;
autoFocusField = 'password';
render() {
const {user} = this.context;
return (
<div>
{this.renderErrors()}
<div className={styles.miniProfile}>
<div className={styles.avatar}>
{user.avatar
? <img src={user.avatar} />
: <span className={icons.user} />
}
</div>
<div className={styles.email}>
{user.email || user.username}
</div>
</div>
<Input {...this.bindField('password')}
icon="key"
type="password"
required
placeholder={messages.accountPassword}
/>
<Checkbox {...this.bindField('rememberMe')}
defaultChecked={true}
label={<Message {...messages.rememberMe} />}
/>
</div>
);
}
}
export default function Password() {
return {
Title: () => ( // TODO: separate component for PageTitle
<Message {...messages.passwordTitle}>
{(msg) => <span>{msg}<Helmet title={msg} /></span>}
</Message>
),
Title: () => <AuthTitle title={messages.passwordTitle} />,
Body,
Footer: () => (
<button className={buttons.green} type="submit">
<Message {...messages.signInButton} />
</button>
),
Footer: () => <Button color="green" label={messages.signInButton} />,
Links: () => (
<Link to="/forgot-password">
<Message {...messages.forgotPassword} />

View File

@ -0,0 +1,51 @@
import React from 'react';
import { FormattedMessage as Message } from 'react-intl';
import icons from 'components/ui/icons.scss';
import { Input, Checkbox } from 'components/ui/form';
import BaseAuthBody from 'components/auth/BaseAuthBody';
import styles from './password.scss';
import messages from './Password.intl.json';
export default class PasswordBody extends BaseAuthBody {
static displayName = 'PasswordBody';
static panelId = 'password';
static hasGoBack = true;
autoFocusField = 'password';
render() {
const {user} = this.context;
return (
<div>
{this.renderErrors()}
<div className={styles.miniProfile}>
<div className={styles.avatar}>
{user.avatar
? <img src={user.avatar} />
: <span className={icons.user} />
}
</div>
<div className={styles.email}>
{user.email || user.username}
</div>
</div>
<Input {...this.bindField('password')}
icon="key"
type="password"
required
placeholder={messages.accountPassword}
/>
<Checkbox {...this.bindField('rememberMe')}
defaultChecked={true}
label={messages.rememberMe}
/>
</div>
);
}
}

View File

@ -0,0 +1,10 @@
{
"permissionsTitle": "Application permissions",
"youAuthorizedAs": "You authorized as:",
"theAppNeedsAccess1": "This application needs access",
"theAppNeedsAccess2": "to your data",
"decline": "Decline",
"approve": "Approve",
"scope_minecraft_server_session": "Authorization data for minecraft server",
"scope_offline_access": "Access to your profile data, when you offline"
}

View File

@ -1,73 +1,18 @@
import React, { PropTypes } from 'react';
import { FormattedMessage as Message } from 'react-intl';
import Helmet from 'react-helmet';
import buttons from 'components/ui/buttons.scss';
import icons from 'components/ui/icons.scss';
import { PanelBodyHeader } from 'components/ui/Panel';
import { Button } from 'components/ui/form';
import AuthTitle from 'components/auth/AuthTitle';
import BaseAuthBody from 'components/auth/BaseAuthBody';
import styles from './permissions.scss';
import messages from './Permissions.messages';
class Body extends BaseAuthBody {
static displayName = 'PermissionsBody';
static panelId = 'permissions';
render() {
const {user} = this.context;
const scopes = this.context.auth.scopes;
return (
<div>
{this.renderErrors()}
<PanelBodyHeader>
<div className={styles.authInfo}>
<div className={styles.authInfoAvatar}>
{user.avatar
? <img src={user.avatar} />
: <span className={icons.user} />
}
</div>
<div className={styles.authInfoTitle}>
<Message {...messages.youAuthorizedAs} />
</div>
<div className={styles.authInfoEmail}>
{user.email}
</div>
</div>
</PanelBodyHeader>
<div className={styles.permissionsContainer}>
<div className={styles.permissionsTitle}>
<Message {...messages.theAppNeedsAccess1} /><br />
<Message {...messages.theAppNeedsAccess2} />
</div>
<ul className={styles.permissionsList}>
{scopes.map((scope, key) => (
<li key={key}>{<Message {...messages[`scope_${scope}`]} />}</li>
))}
</ul>
</div>
</div>
);
}
}
import messages from './Permissions.intl.json';
import Body from './PermissionsBody';
export default function Permissions() {
const componentsMap = {
Title: () => ( // TODO: separate component for PageTitle
<Message {...messages.permissionsTitle}>
{(msg) => <span>{msg}<Helmet title={msg} /></span>}
</Message>
),
Title: () => <AuthTitle title={messages.permissionsTitle} />,
Body,
Footer: () => (
<button className={buttons.orange} autoFocus>
<Message {...messages.approve} />
</button>
),
Footer: () => <Button color="orange" autoFocus label={messages.approve} />,
Links: (props, context) => (
<a href="#" onClick={(event) => {
event.preventDefault();

View File

@ -1,43 +0,0 @@
import { defineMessages } from 'react-intl';
export default defineMessages({
permissionsTitle: {
id: 'permissionsTitle',
defaultMessage: 'Application permissions'
},
youAuthorizedAs: {
id: 'youAuthorizedAs',
defaultMessage: 'You authorized as:'
},
theAppNeedsAccess1: {
id: 'theAppNeedsAccess1',
defaultMessage: 'This application needs access'
},
theAppNeedsAccess2: {
id: 'theAppNeedsAccess2',
defaultMessage: 'to your data'
},
decline: {
id: 'decline',
defaultMessage: 'Decline'
},
approve: {
id: 'approve',
defaultMessage: 'Approve'
},
scope_minecraft_server_session: {
id: 'scope_minecraft_server_session',
defaultMessage: 'Authorization data for minecraft server'
},
scope_offline_access: {
id: 'scope_offline_access',
defaultMessage: 'Access to your profile data, when you offline'
}
});

View File

@ -0,0 +1,52 @@
import React from 'react';
import icons from 'components/ui/icons.scss';
import { PanelBodyHeader } from 'components/ui/Panel';
import BaseAuthBody from 'components/auth/BaseAuthBody';
import styles from './permissions.scss';
import messages from './Permissions.intl.json';
export default class PermissionsBody extends BaseAuthBody {
static displayName = 'PermissionsBody';
static panelId = 'permissions';
render() {
const {user} = this.context;
const scopes = this.context.auth.scopes;
return (
<div>
{this.renderErrors()}
<PanelBodyHeader>
<div className={styles.authInfo}>
<div className={styles.authInfoAvatar}>
{user.avatar
? <img src={user.avatar} />
: <span className={icons.user} />
}
</div>
<div className={styles.authInfoTitle}>
<Message {...messages.youAuthorizedAs} />
</div>
<div className={styles.authInfoEmail}>
{user.email}
</div>
</div>
</PanelBodyHeader>
<div className={styles.permissionsContainer}>
<div className={styles.permissionsTitle}>
<Message {...messages.theAppNeedsAccess1} /><br />
<Message {...messages.theAppNeedsAccess2} />
</div>
<ul className={styles.permissionsList}>
{scopes.map((scope, key) => (
<li key={key}>{<Message {...messages[`scope_${scope}`]} />}</li>
))}
</ul>
</div>
</div>
);
}
}

View File

@ -0,0 +1,10 @@
{
"registerTitle": "Sign Up",
"yourNickname": "Your nickname",
"yourEmail": "Your E-mail",
"accountPassword": "Account password",
"repeatPassword": "Repeat password",
"signUpButton": "Register",
"acceptRules": "I agree with {link}",
"termsOfService": "Terms of service"
}

View File

@ -1,92 +1,19 @@
import React from 'react';
import { FormattedMessage as Message } from 'react-intl';
import Helmet from 'react-helmet';
import buttons from 'components/ui/buttons.scss';
import { Input, Checkbox } from 'components/ui/form';
import { Button } from 'components/ui/form';
import AuthTitle from 'components/auth/AuthTitle';
import activationMessages from 'components/auth/activation/Activation.intl.json';
import BaseAuthBody from 'components/auth/BaseAuthBody';
import passwordMessages from 'components/auth/password/Password.intl.json';
import activationMessages from 'components/auth/activation/Activation.messages';
import messages from './Register.messages';
// TODO: password and username can be validate for length and sameness
class Body extends BaseAuthBody {
static displayName = 'RegisterBody';
static panelId = 'register';
autoFocusField = 'username';
render() {
return (
<div>
{this.renderErrors()}
<Input {...this.bindField('username')}
icon="user"
color="blue"
type="text"
required
placeholder={messages.yourNickname}
/>
<Input {...this.bindField('email')}
icon="envelope"
color="blue"
type="email"
required
placeholder={messages.yourEmail}
/>
<Input {...this.bindField('password')}
icon="key"
color="blue"
type="password"
required
placeholder={passwordMessages.accountPassword}
/>
<Input {...this.bindField('rePassword')}
icon="key"
color="blue"
type="password"
required
placeholder={messages.repeatPassword}
/>
<Checkbox {...this.bindField('rulesAgreement')}
color="blue"
required
label={
<Message {...messages.acceptRules} values={{
link: (
<a href="#">
<Message {...messages.termsOfService} />
</a>
)
}} />
}
/>
</div>
);
}
}
import messages from './Register.intl.json';
import Body from './RegisterBody';
export default function Register() {
return {
Title: () => ( // TODO: separate component for PageTitle
<Message {...messages.registerTitle}>
{(msg) => <span>{msg}<Helmet title={msg} /></span>}
</Message>
),
Title: () => <AuthTitle title={messages.registerTitle} />,
Body,
Footer: () => (
<button className={buttons.blue} type="submit">
<Message {...messages.signUpButton} />
</button>
),
Footer: () => <Button color="blue" label={messages.signUpButton} />,
Links: () => (
<a href="#">
<Message {...activationMessages.didNotReceivedEmail} />

View File

@ -1,43 +0,0 @@
import { defineMessages } from 'react-intl';
export default defineMessages({
registerTitle: {
id: 'registerTitle',
defaultMessage: 'Sign Up'
},
yourNickname: {
id: 'yourNickname',
defaultMessage: 'Your nickname'
},
yourEmail: {
id: 'yourEmail',
defaultMessage: 'Your E-mail'
},
accountPassword: {
id: 'accountPassword',
defaultMessage: 'Account password'
},
repeatPassword: {
id: 'repeatPassword',
defaultMessage: 'Repeat password'
},
signUpButton: {
id: 'signUpButton',
defaultMessage: 'Register'
},
acceptRules: {
id: 'acceptRules',
defaultMessage: 'I agree with {link}'
},
termsOfService: {
id: 'termsOfService',
defaultMessage: 'Terms of service'
}
});

View File

@ -0,0 +1,72 @@
import React from 'react';
import { FormattedMessage as Message } from 'react-intl';
import { Input, Checkbox } from 'components/ui/form';
import BaseAuthBody from 'components/auth/BaseAuthBody';
import passwordMessages from 'components/auth/password/Password.intl.json';
import messages from './Register.intl.json';
// TODO: password and username can be validate for length and sameness
export default class RegisterBody extends BaseAuthBody {
static displayName = 'RegisterBody';
static panelId = 'register';
autoFocusField = 'username';
render() {
return (
<div>
{this.renderErrors()}
<Input {...this.bindField('username')}
icon="user"
color="blue"
type="text"
required
placeholder={messages.yourNickname}
/>
<Input {...this.bindField('email')}
icon="envelope"
color="blue"
type="email"
required
placeholder={messages.yourEmail}
/>
<Input {...this.bindField('password')}
icon="key"
color="blue"
type="password"
required
placeholder={passwordMessages.accountPassword}
/>
<Input {...this.bindField('rePassword')}
icon="key"
color="blue"
type="password"
required
placeholder={messages.repeatPassword}
/>
<Checkbox {...this.bindField('rulesAgreement')}
color="blue"
required
label={
<Message {...messages.acceptRules} values={{
link: (
<a href="#">
<Message {...messages.termsOfService} />
</a>
)
}} />
}
/>
</div>
);
}
}

View File

@ -21,7 +21,7 @@ export default class Button extends FormComponent {
};
render() {
const { color = 'green', block } = this.props;
const { color = 'green', block, small } = this.props;
const props = {
...this.props
@ -31,7 +31,8 @@ export default class Button extends FormComponent {
return (
<button className={classNames(buttons[color], {
[buttons.block]: block
[buttons.block]: block,
[buttons.smallButton]: small
})} {...props}>
{props.label}
</button>

View File

@ -1,23 +1,39 @@
{
"acceptRules": "I agree with {link}",
"accountActivationTitle": "Account activation",
"accountEmail": "Enter account E-mail",
"accountPassword": "Account password",
"activationMailWasSent": "Please check {email} for the message with the last registration step",
"alreadyReceivedCode": "Already received code",
"approve": "Approve",
"authForAppFailed": "Authorization for {appName} was failed",
"authForAppSuccessful": "Authorization for {appName} was successfully completed",
"change": "Change",
"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",
"changePasswordTitle": "Change password",
"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",
"components.auth.activation.didNotReceivedEmail": "Did not received E-mail?",
"components.auth.activation.enterTheCode": "Enter the code from E-mail here",
"components.auth.appInfo.goToAuth": "Go to auth",
"components.auth.changePassword.change": "Change",
"components.auth.changePassword.changePasswordMessage": "To enhance the security of your account, please change your password.",
"components.auth.changePassword.changePasswordTitle": "Change password",
"components.auth.changePassword.currentPassword": "Enter current password",
"components.auth.changePassword.newPassword": "Enter new password",
"components.auth.changePassword.newRePassword": "Repeat new password",
"components.auth.changePassword.skipThisStep": "Skip password changing",
"components.auth.finish.authForAppFailed": "Authorization for {appName} was failed",
"components.auth.finish.authForAppSuccessful": "Authorization for {appName} was successfully completed",
"components.auth.finish.copy": "Copy",
"components.auth.finish.passCodeToApp": "To complete authorization process, please, provide the following code to {appName}",
"components.auth.finish.waitAppReaction": "Please, wait till your application response",
"components.auth.forgotPassword.accountEmail": "Enter account E-mail",
"components.auth.forgotPassword.contactSupport": "Contact support",
"components.auth.forgotPassword.forgotPasswordMessage": "Specify the registration E-mail address for your account and we will send an email with instructions for further password recovery.",
"components.auth.forgotPassword.forgotPasswordTitle": "Forgot password",
"components.auth.forgotPassword.sendMail": "Send mail",
"components.auth.login.emailOrUsername": "E-mail or username",
"components.auth.login.loginTitle": "Sign in",
"components.auth.login.next": "Next",
"components.auth.password.accountPassword": "Account password",
"components.auth.password.forgotPassword": "Forgot password",
"components.auth.password.forgotYourPassword": "forgot your password",
@ -26,6 +42,22 @@
"components.auth.password.rememberMe": "Remember me on this device",
"components.auth.password.signInButton": "Sign in",
"components.auth.password.suggestResetPassword": "Are you have {link}?",
"components.auth.permissions.approve": "Approve",
"components.auth.permissions.decline": "Decline",
"components.auth.permissions.permissionsTitle": "Application permissions",
"components.auth.permissions.scope_minecraft_server_session": "Authorization data for minecraft server",
"components.auth.permissions.scope_offline_access": "Access to your profile data, when you offline",
"components.auth.permissions.theAppNeedsAccess1": "This application needs access",
"components.auth.permissions.theAppNeedsAccess2": "to your data",
"components.auth.permissions.youAuthorizedAs": "You authorized as:",
"components.auth.register.acceptRules": "I agree with {link}",
"components.auth.register.accountPassword": "Account password",
"components.auth.register.registerTitle": "Sign Up",
"components.auth.register.repeatPassword": "Repeat password",
"components.auth.register.signUpButton": "Register",
"components.auth.register.termsOfService": "Terms of service",
"components.auth.register.yourEmail": "Your E-mail",
"components.auth.register.yourNickname": "Your nickname",
"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.changePassword.achievementLossWarning": "Are you cherish your game achievements, right?",
@ -45,71 +77,39 @@
"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",
"confirmEmail": "Confirm E-mail",
"contactSupport": "Contact support",
"copy": "Copy",
"currentAccountEmail": "Current account E-mail address:",
"currentPassword": "Enter current password",
"decline": "Decline",
"didNotReceivedEmail": "Did not received E-mail?",
"emailInvalid": "Email is invalid",
"emailIsTempmail": "Tempmail E-mail addresses is not allowed",
"emailNotAvailable": "This email is already registered.",
"emailOrUsername": "E-mail or username",
"emailRequired": "Email is required",
"emailToLong": "Email is too long",
"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.",
"enterTheCode": "Enter the code from E-mail here",
"forgotPasswordMessage": "Specify the registration E-mail address for your account and we will send an email with instructions for further password recovery.",
"forgotPasswordTitle": "Forgot password",
"forgotYourPassword": "forgot your password",
"goToAuth": "Go to auth",
"invalidPassword": "You have entered wrong account password.",
"keyNotExists": "The key is incorrect",
"keyRequired": "Please, enter an activation key",
"loginNotExist": "Sorry, Ely doesn't recognise your login.",
"loginRequired": "Please enter email or username",
"loginTitle": "Sign in",
"logout": "Logout",
"newEmailPlaceholder": "Enter new E-mail",
"newPassword": "Enter new password",
"newPasswordRequired": "Please enter new password",
"newRePassword": "Repeat new password",
"newRePasswordRequired": "Please repeat new password",
"next": "Next",
"passCodeToApp": "To complete authorization process, please, provide the following code to {appName}",
"passwordChangeMessage": "To enhance the security of your account, please change your password.",
"passwordRequired": "Please enter password",
"passwordTooShort": "Your password is too short",
"passwordsDoesNotMatch": "The passwords does not match",
"permissionsTitle": "Application permissions",
"pleaseEnterPassword": "Please, enter your current password",
"pressButtonToStart": "Press the button below to send a message with the code for E-mail change initialization.",
"rePasswordRequired": "Please retype your password",
"register": "Join",
"registerTitle": "Sign Up",
"repeatPassword": "Repeat password",
"rulesAgreementRequired": "You must accept rules in order to create an account",
"scope_minecraft_server_session": "Authorization data for minecraft server",
"scope_offline_access": "Access to your profile data, when you offline",
"sendEmailButton": "Send E-mail",
"sendMail": "Send mail",
"signUpButton": "Register",
"skipThisStep": "Skip password changing",
"suggestResetPassword": "Are you have {link}?",
"termsOfService": "Terms of service",
"theAppNeedsAccess1": "This application needs access",
"theAppNeedsAccess2": "to your data",
"title": "Confirm your action",
"usernameInvalid": "Username is invalid",
"usernameRequired": "Username is required",
"usernameTooLong": "Username is too long",
"usernameTooShort": "Username is too short",
"usernameUnavailable": "This username is already taken",
"waitAppReaction": "Please, wait till your application response",
"youAuthorizedAs": "You authorized as:",
"yourEmail": "Your E-mail",
"yourNickname": "Your nickname"
"usernameUnavailable": "This username is already taken"
}

View File

@ -1,23 +1,39 @@
{
"acceptRules": "I agree with {link}",
"accountActivationTitle": "Account activation",
"accountEmail": "Enter account E-mail",
"accountPassword": "Account password",
"activationMailWasSent": "Please check {email} for the message with the last registration step",
"alreadyReceivedCode": "Already received code",
"approve": "Approve",
"authForAppFailed": "Authorization for {appName} was failed",
"authForAppSuccessful": "Authorization for {appName} was successfully completed",
"change": "Change",
"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",
"changePasswordTitle": "Change password",
"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",
"components.auth.activation.didNotReceivedEmail": "Did not received E-mail?",
"components.auth.activation.enterTheCode": "Enter the code from E-mail here",
"components.auth.appInfo.goToAuth": "Go to auth",
"components.auth.changePassword.change": "Change",
"components.auth.changePassword.changePasswordMessage": "To enhance the security of your account, please change your password.",
"components.auth.changePassword.changePasswordTitle": "Change password",
"components.auth.changePassword.currentPassword": "Enter current password",
"components.auth.changePassword.newPassword": "Enter new password",
"components.auth.changePassword.newRePassword": "Repeat new password",
"components.auth.changePassword.skipThisStep": "Skip password changing",
"components.auth.finish.authForAppFailed": "Авторизация для {appName} не удалась",
"components.auth.finish.authForAppSuccessful": "Авторизация для {appName} успешно выполнена",
"components.auth.finish.copy": "Скопировать",
"components.auth.finish.passCodeToApp": "Чтобы завершить процесс авторизации, пожалуйста, передай {appName} этот код",
"components.auth.finish.waitAppReaction": "Пожалуйста, дождитесь реакции вашего приложения",
"components.auth.forgotPassword.accountEmail": "Enter account E-mail",
"components.auth.forgotPassword.contactSupport": "Contact support",
"components.auth.forgotPassword.forgotPasswordMessage": "Specify the registration E-mail address for your account and we will send an email with instructions for further password recovery.",
"components.auth.forgotPassword.forgotPasswordTitle": "Forgot password",
"components.auth.forgotPassword.sendMail": "Send mail",
"components.auth.login.emailOrUsername": "E-mail or username",
"components.auth.login.loginTitle": "Sign in",
"components.auth.login.next": "Next",
"components.auth.password.accountPassword": "Account password",
"components.auth.password.forgotPassword": "Forgot password",
"components.auth.password.forgotYourPassword": "forgot your password",
@ -26,6 +42,22 @@
"components.auth.password.rememberMe": "Remember me on this device",
"components.auth.password.signInButton": "Sign in",
"components.auth.password.suggestResetPassword": "Are you have {link}?",
"components.auth.permissions.approve": "Approve",
"components.auth.permissions.decline": "Decline",
"components.auth.permissions.permissionsTitle": "Application permissions",
"components.auth.permissions.scope_minecraft_server_session": "Authorization data for minecraft server",
"components.auth.permissions.scope_offline_access": "Access to your profile data, when you offline",
"components.auth.permissions.theAppNeedsAccess1": "This application needs access",
"components.auth.permissions.theAppNeedsAccess2": "to your data",
"components.auth.permissions.youAuthorizedAs": "You authorized as:",
"components.auth.register.acceptRules": "I agree with {link}",
"components.auth.register.accountPassword": "Account password",
"components.auth.register.registerTitle": "Sign Up",
"components.auth.register.repeatPassword": "Repeat password",
"components.auth.register.signUpButton": "Register",
"components.auth.register.termsOfService": "Terms of service",
"components.auth.register.yourEmail": "Your E-mail",
"components.auth.register.yourNickname": "Your nickname",
"components.profile.accountDescription": "Благодаря аккаунту Ely.by вы можете получить доступ ко многим ресурсам, связанным с Minecraft. Берегите свой аккаунт, используйте надёжный пароль и регулярно его меняйте.",
"components.profile.accountPreferencesTitle": "Настройки аккаунта Ely.by",
"components.profile.changePassword.achievementLossWarning": "Вы ведь дорожите своими игровыми достижениями?",
@ -45,71 +77,39 @@
"components.profile.personalData": "Персональные данные",
"components.profile.preferencesDescription": "Здесь вы можете сменить ключевые параметры вашего аккаунта. Обратите внимание, что для всех действий необходимо подтверждение при помощи ввода пароля.",
"components.profile.twoFactorAuth": "Двухфакторная аутентификация",
"confirmEmail": "Confirm E-mail",
"contactSupport": "Contact support",
"copy": "Copy",
"currentAccountEmail": "Current account E-mail address:",
"currentPassword": "Enter current password",
"decline": "Decline",
"didNotReceivedEmail": "Did not received E-mail?",
"emailInvalid": "Email is invalid",
"emailIsTempmail": "Tempmail E-mail addresses is not allowed",
"emailNotAvailable": "This email is already registered.",
"emailOrUsername": "E-mail or username",
"emailRequired": "Email is required",
"emailToLong": "Email is too long",
"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.",
"enterTheCode": "Enter the code from E-mail here",
"forgotPasswordMessage": "Specify the registration E-mail address for your account and we will send an email with instructions for further password recovery.",
"forgotPasswordTitle": "Forgot password",
"forgotYourPassword": "forgot your password",
"goToAuth": "Go to auth",
"invalidPassword": "You have entered wrong account password.",
"keyNotExists": "The key is incorrect",
"keyRequired": "Please, enter an activation key",
"loginNotExist": "Sorry, Ely doesn't recognise your login.",
"loginRequired": "Please enter email or username",
"loginTitle": "Sign in",
"logout": "Logout",
"newEmailPlaceholder": "Enter new E-mail",
"newPassword": "Enter new password",
"newPasswordRequired": "Please enter new password",
"newRePassword": "Repeat new password",
"newRePasswordRequired": "Please repeat new password",
"next": "Next",
"passCodeToApp": "To complete authorization process, please, provide the following code to {appName}",
"passwordChangeMessage": "To enhance the security of your account, please change your password.",
"passwordRequired": "Please enter password",
"passwordTooShort": "Your password is too short",
"passwordsDoesNotMatch": "The passwords does not match",
"permissionsTitle": "Application permissions",
"pleaseEnterPassword": "Please, enter your current password",
"pressButtonToStart": "Press the button below to send a message with the code for E-mail change initialization.",
"rePasswordRequired": "Please retype your password",
"register": "Join",
"registerTitle": "Sign Up",
"repeatPassword": "Repeat password",
"rulesAgreementRequired": "You must accept rules in order to create an account",
"scope_minecraft_server_session": "Authorization data for minecraft server",
"scope_offline_access": "Access to your profile data, when you offline",
"sendEmailButton": "Send E-mail",
"sendMail": "Send mail",
"signUpButton": "Register",
"skipThisStep": "Skip password changing",
"suggestResetPassword": "Are you have {link}?",
"termsOfService": "Terms of service",
"theAppNeedsAccess1": "This application needs access",
"theAppNeedsAccess2": "to your data",
"title": "Confirm your action",
"usernameInvalid": "Username is invalid",
"usernameRequired": "Username is required",
"usernameTooLong": "Username is too long",
"usernameTooShort": "Username is too short",
"usernameUnavailable": "This username is already taken",
"waitAppReaction": "Please, wait till your application response",
"youAuthorizedAs": "You authorized as:",
"yourEmail": "Your E-mail",
"yourNickname": "Your nickname"
"usernameUnavailable": "This username is already taken"
}

View File

@ -6,7 +6,8 @@ class ProfilePage extends Component {
displayName = 'ProfilePage';
static propTypes = {
onSubmit: PropTypes.func.isRequired
onSubmit: PropTypes.func.isRequired,
goToProfile: PropTypes.func.isRequired
};
static childContextTypes = {