Неплохой такой рефакторинг:

Образован класс для хранения цветов
Button и Input опущены в подмодуль ui, добавлена поддержка цветов
В BitmaText добавлен стиль verticalAlign:middle по умолчанию
В dev зависимости добавлен плагин для отслеживания циклических зависимостей
Компонент, что отвечает за "Нажми на кнопку или передай код" тоже выделен отдельно и немного перевёрстан
This commit is contained in:
ErickSkrauch 2016-10-02 22:16:19 +03:00
parent 7d986b1518
commit d27bceaff5
32 changed files with 316 additions and 157 deletions

View File

@ -42,6 +42,7 @@
"babel-preset-react-hmre": "^1.0.1",
"babel-preset-stage-0": "^6.3.13",
"babel-runtime": "^6.0.0",
"circular-dependency-plugin": "^2.0.0",
"eslint": "^3.1.1",
"eslint-plugin-react": "^6.0.0",
"extract-text-webpack-plugin": "^1.0.0",

View File

@ -0,0 +1,38 @@
import { PropTypes } from 'react';
import { FormattedMessage as Message } from 'react-intl';
import { colors, green } from 'components/ui/colors';
import { Button, Input } from 'components/ui';
import styles from './styles';
import messages from './messages.intl.json';
export default function Code({code, link, label, color = green}) {
return (
<div style={styles.codeWrapper}>
<div>
<a href={link}>
<Button style={styles.confirmEmailButton} color={color} label={label} />
</a>
</div>
<div style={styles.or}>
<Message {...messages.or} />
</div>
<div style={styles.codeLabel}>
<Message {...messages.pass_code_in_field} />
</div>
<div style={styles.code}>
<Input value={code} color={color} />
</div>
</div>
);
}
Code.propTypes = {
code: PropTypes.string.isRequired,
link: PropTypes.string.isRequired,
label: PropTypes.node.isRequired,
color: PropTypes.oneOf(Object.values(colors))
};

View File

@ -0,0 +1,4 @@
{
"or": "or",
"pass_code_in_field": "Use this code in an entry field of our site:"
}

View File

@ -0,0 +1,20 @@
export default {
codeWrapper: {
paddingTop: '20px',
textAlign: 'center'
},
confirmEmailButton: {
paddingLeft: '50px',
paddingRight: '50px'
},
or: {
fontSize: '12px',
paddingTop: '5px'
},
codeLabel: {
paddingTop: '1px'
},
code: {
paddingTop: '5px'
}
};

View File

@ -0,0 +1,5 @@
import Code from './code/Code';
export {
Code
};

View File

@ -1,12 +0,0 @@
import styles from './styles';
export default function Button(props) {
return (
<div style={{
...styles.button,
...props.style
}}>
{props.children}
</div>
);
}

View File

@ -1,8 +0,0 @@
export default {
button: {
backgroundColor: '#589AAA',
padding: '0 13px',
lineHeight: '50px',
display: 'inline-block'
}
};

View File

@ -1,12 +0,0 @@
import styles from './styles';
export default function Input(props) {
return (
<div style={{
...styles.input,
...props.style
}}>
{props.children}
</div>
);
}

View File

@ -1,11 +0,0 @@
export default {
input: {
backgroundColor: '#fff',
padding: '0 30px',
lineHeight: '50px',
fontSize: '18px',
display: 'inline-block',
border: '3px solid #589AAA',
color: '#568297'
}
};

View File

@ -0,0 +1,9 @@
import styles from './styles';
export default function Content(props) {
return (
<div style={styles.content}>
{props.children}
</div>
);
}

View File

@ -0,0 +1,6 @@
export default {
content: {
background: '#fff',
padding: '50px'
}
};

View File

@ -21,9 +21,7 @@ export default function Footer() {
</td>
<td style={styles.footerLogo}>
<a href="http://ely.by">
<BitmapText message={messages.footer_logo_alt} style={{
verticalAlign: 'middle'
}} />
<BitmapText message={messages.footer_logo_alt} />
</a>
</td>
</tr>

View File

@ -1,5 +1,8 @@
import {green} from 'components/ui/colors';
export default {
footer: {
borderTop: `10px solid ${green.color}`,
background: '#DDD8CE',
height: '135px'
},

View File

@ -1,9 +1,11 @@
import Userbar from './userbar/Userbar';
import Header from './header/Header';
import Content from './content/Content';
import Footer from './footer/Footer';
export {
Userbar,
Header,
Content,
Footer
};

View File

@ -1,6 +1,8 @@
import {green} from 'components/ui/colors';
export default {
userbar: {
background: '#207E5C',
background: green.color,
height: '50px'
},
marginColumn: {
@ -11,7 +13,7 @@ export default {
verticalAlign: 'middle'
},
logo: {
background: '#1A6449',
background: green.dark,
padding: '0 13px',
display: 'block',
lineHeight: '50px'

View File

@ -61,7 +61,9 @@ BitmapText.propTypes = {
BitmapText.defaultProps = {
retina: true,
style: {}
style: {
verticalAlign: 'middle'
}
};
import { injectIntl, intlShape } from 'react-intl';

View File

@ -0,0 +1,33 @@
import { Component, PropTypes } from 'react';
import styles from './styles';
import { colors, green } from 'components/ui/colors';
export default class Button extends Component {
static propTypes = {
label: PropTypes.node.isRequired,
color: PropTypes.oneOf(Object.values(colors))
};
static defaultProps = {
color: green
};
render() {
const {props} = this;
const {color, label} = props;
return (
<div style={{
...styles.button,
...styles[color],
...props.style
}}>
{label}
</div>
);
}
}

View File

@ -0,0 +1,25 @@
import { colors } from 'components/ui/colors';
/**
* @param {Color} color
* @return {{backgroundColor: *}}
*/
function generateColor(color) {
return {
backgroundColor: color.color
};
}
const styles = {
button: {
padding: '0 13px',
lineHeight: '50px',
display: 'inline-block'
}
};
Object.values(colors).forEach((color) => {
styles[color] = generateColor(color);
});
export default styles;

View File

@ -0,0 +1,48 @@
export class Color {
constructor(name, base, light, dark) {
this._name = name;
this._base = base;
this._light = light;
this._dark = dark;
}
get name() {
return this._name;
}
get color() {
return this._base;
}
get light() {
return this._light;
}
get dark() {
return this._dark;
}
toString() {
return this.name;
}
}
export const green = new Color('green', '#207e5c', '#379070', '#1a6449');
export const blue = new Color('blue', '#5b9aa9', '#71a6b2', '#568297');
export const darkBlue = new Color('darkBlue', '#28555b', '#3e6164', '#233d49');
export const violet = new Color('violet', '#6b5b8c', '#816795', '#66437a');
export const lightViolet = new Color('lightViolet', '#8b5d79', '#a16982', '#864567');
export const orange = new Color('orange', '#dd8650', '#f39259', '#d86e3e');
export const red = new Color('red', '#e66c69', '#e15457', '#fc7872');
export const colors = {
green,
blue,
darkBlue,
violet,
lightViolet,
orange,
red
};

View File

@ -0,0 +1,7 @@
import Button from './button/Button';
import Input from './input/Input';
export {
Button,
Input
};

View File

@ -0,0 +1,33 @@
import { Component, PropTypes } from 'react';
import { colors, green } from 'components/ui/colors';
import styles from './styles';
export default class Input extends Component {
static propTypes = {
value: PropTypes.string.isRequired,
color: PropTypes.oneOf(Object.values(colors))
};
static defaultProps = {
color: green
};
render() {
const {props} = this;
const {value, color, style} = props;
return (
<div style={{
...styles.input,
...styles[color],
...style
}}>
{value}
</div>
);
}
}

View File

@ -0,0 +1,30 @@
import { colors } from 'components/ui/colors';
/**
* @param {Color} color
* @return {{backgroundColor: *}}
*/
function generateColor(color) {
return {
borderColor: color.color,
color: color.dark
};
}
const styles = {
input: {
backgroundColor: '#fff',
padding: '0 30px',
lineHeight: '50px',
fontSize: '18px',
display: 'inline-block',
border: '3px solid transparent',
color: '#444'
}
};
Object.values(colors).forEach((color) => {
styles[color] = generateColor(color);
});
export default styles;

View File

@ -2,11 +2,11 @@ import { PropTypes } from 'react';
import { FormattedMessage as Message } from 'react-intl';
import { Userbar, Header, Footer } from 'components/layout';
import { Userbar, Header, Content, Footer } from 'components/layout';
import { Table } from 'components/table';
import { Button } from 'components/button';
import { Input } from 'components/input';
import { blue } from 'components/ui/colors';
import { BitmapText } from 'components/text';
import { Code } from 'components/blocks';
import styles from './styles';
import messages from './messages.intl.json';
@ -21,12 +21,10 @@ export default function Register({username, link, code}) {
<Userbar />
<Header username={username} title={
<BitmapText message={messages.welcome_image} style={{
verticalAlign: 'middle'
}} />
<BitmapText message={messages.welcome_image} />
} />
<div style={styles.content}>
<Content>
<Table>
<tr>
<td>
@ -36,41 +34,10 @@ export default function Register({username, link, code}) {
</td>
</tr>
<tr>
<td style={{
...styles.contentCenterCell,
...styles.confirmEmailCell
}}>
<a href={link}>
<Button style={styles.confirmEmailButton}>
<BitmapText message={messages.confirm_email_image} style={{
verticalAlign: 'middle'
}} />
</Button>
</a>
</td>
</tr>
<tr>
<td style={{
...styles.contentCenterCell,
...styles.orCell,
}}>
<Message {...messages.or} />
</td>
</tr>
<tr>
<td style={{
...styles.contentCenterCell,
...styles.codeLabelCell
}}>
<Message {...messages.pass_code_in_field} />
</td>
</tr>
<tr>
<td style={{
...styles.contentCenterCell,
...styles.codeCell
}}>
<Input>{code}</Input>
<td>
<Code code={code} link={link} color={blue} label={
<BitmapText message={messages.confirm_email_image} />
} />
</td>
</tr>
<tr>
@ -78,9 +45,7 @@ export default function Register({username, link, code}) {
...styles.contentCenterCell,
...styles.whatsNextText
}}>
<BitmapText message={messages.whats_next_image} style={{
verticalAlign: 'middle'
}} />
<BitmapText message={messages.whats_next_image} />
</td>
</tr>
<tr>
@ -94,9 +59,7 @@ export default function Register({username, link, code}) {
}} />
</td>
<td style={styles.todoItemContent}>
<BitmapText message={messages.choose_you_skin_image} style={{
verticalAlign: 'middle'
}} />
<BitmapText message={messages.choose_you_skin_image} />
<div style={{
...styles.paragraph,
...styles.todoItemText
@ -119,9 +82,7 @@ export default function Register({username, link, code}) {
}} />
</td>
<td style={styles.todoItemContent}>
<BitmapText message={messages.install_our_patch_image} style={{
verticalAlign: 'middle'
}} />
<BitmapText message={messages.install_our_patch_image} />
<div style={{
...styles.paragraph,
...styles.todoItemText
@ -144,9 +105,7 @@ export default function Register({username, link, code}) {
}} />
</td>
<td style={styles.todoItemContent}>
<BitmapText message={messages.use_tlauncher_image} style={{
verticalAlign: 'middle'
}} />
<BitmapText message={messages.use_tlauncher_image} />
<div style={{
...styles.paragraph,
...styles.todoItemText
@ -159,7 +118,7 @@ export default function Register({username, link, code}) {
</td>
</tr>
</Table>
</div>
</Content>
<Footer />
</div>

View File

@ -2,8 +2,6 @@
"welcome_image": "Welcome to Ely.by",
"we_glad_to_see_you": "We glad to see you among the users of Ely.by. You almost reached the final point, it remains only to confirm your E-mail address.For doing it, please push a button under the text.",
"confirm_email_image": "Confirm Email",
"or": "or",
"pass_code_in_field": "Use this code in an entry field of our site:",
"whats_next_image": "What's the next?",
"choose_you_skin_image": "Choose your skin",
"choose_you_skin_text": "In Ely.by's catalog you can find great diversity of skins, which are ready to be put up.",

View File

@ -1,10 +1,4 @@
export default {
content: {
background: '#fff',
padding: '50px',
borderBottom: '10px solid #207E5C'
},
contentCenterCell: {
textAlign: 'center'
},
@ -14,26 +8,6 @@ export default {
lineHeight: '125%'
},
confirmEmailCell: {
paddingTop: '20px'
},
confirmEmailButton: {
paddingLeft: '50px',
paddingRight: '50px'
},
orCell: {
fontSize: '12px',
paddingTop: '5px'
},
codeLabelCell: {
paddingTop: '1px'
},
codeCell: {
paddingTop: '5px'
},
whatsNextText: {
paddingTop: '30px'
},

View File

@ -1,15 +1,15 @@
{
"components.footer.footer": "Ты атрымаў гэты ліст, бо гэты Email быў пазначаны пры рэгістрацыі на сэрвісе {serviceLink}. Калі гэта быў не ты, то проста выдалі гэты ліст.",
"components.footer.footer_logo_alt": "Ely.by - Альтэрнатыўныя сэрвісы Minecraft",
"components.footer.service_name": "Акаўнты Ely.by",
"components.header.hello_username": "Прывітанне, {username}",
"components.blocks.code.or": "ці",
"components.blocks.code.pass_code_in_field": "Пазнач гэты код у поле ўводу на сайце:",
"components.layout.footer.footer": "Ты атрымаў гэты ліст, бо гэты Email быў пазначаны пры рэгістрацыі на сэрвісе {serviceLink}. Калі гэта быў не ты, то проста выдалі гэты ліст.",
"components.layout.footer.footer_logo_alt": "Ely.by - Альтэрнатыўныя сэрвісы Minecraft",
"components.layout.footer.service_name": "Акаўнты Ely.by",
"components.layout.header.hello_username": "Прывітанне, {username}",
"emails.register.choose_you_skin_image": "Выберы свой скін",
"emails.register.choose_you_skin_text": "У каталогу скіноў Ely.by ты зможаш знайсці мноства разнастайных скіноў, кожны з якіх гатовы да таго, каб быць надзетым.",
"emails.register.confirm_email_image": "Пацвердзіць Email",
"emails.register.install_our_patch_image": "Устанаві наш патч у гульню",
"emails.register.install_our_patch_text": "Для таго, каб сістема скіноў Ely.by працавала, табе патрэбна ўстанавіць наш патч. Знайсці яго можна ў раздзеле загрузак на сайце.",
"emails.register.or": "ці",
"emails.register.pass_code_in_field": "Пазнач гэты код у поле ўводу на сайце:",
"emails.register.use_tlauncher_image": "Выкарыстоўвай TLauncher",
"emails.register.use_tlauncher_text": "Усё значна лягчэй, калі ты выкарыстоўваеш правільную прыладу для сваёй задачы. TLauncher з'яўляецца лепшым альтэрнатыўным лаунчарам для Minecraft, які таксама мае ўбудаваную падтрымку Ely.by.",
"emails.register.we_glad_to_see_you": "Мы рады бачыць цябе ў шэрагах карыстальнікаў праекту Ely.by. Ты ўжо амаль у мэты, засталося толькі пацвердзіць свой Email адрас. Каб зрабіць гэта, калі ласка, націсні на кнопку, якая знаходзіцца ніжэй.",

View File

@ -1,15 +1,15 @@
{
"components.footer.footer": "You have received this message, because this Email was set during registration at the {serviceLink} service. If it wasn't you just delete the message please.",
"components.footer.footer_logo_alt": "Ely.by - Alternative Minecraft services",
"components.footer.service_name": "Accounts Ely.by",
"components.header.hello_username": "Hello, {username}",
"components.blocks.code.or": "or",
"components.blocks.code.pass_code_in_field": "Use this code in an entry field of our site:",
"components.layout.footer.footer": "You have received this message, because this Email was set during registration at the {serviceLink} service. If it wasn't you just delete the message please.",
"components.layout.footer.footer_logo_alt": "Ely.by - Alternative Minecraft services",
"components.layout.footer.service_name": "Accounts Ely.by",
"components.layout.header.hello_username": "Hello, {username}",
"emails.register.choose_you_skin_image": "Choose your skin",
"emails.register.choose_you_skin_text": "In Ely.by's catalog you can find great diversity of skins, which are ready to be put up.",
"emails.register.confirm_email_image": "Confirm Email",
"emails.register.install_our_patch_image": "Install our patch in the game",
"emails.register.install_our_patch_text": "You should install our patch to make the Ely.by's skin system working. You can find it at 'Load' section.",
"emails.register.or": "or",
"emails.register.pass_code_in_field": "Use this code in an entry field of our site:",
"emails.register.use_tlauncher_image": "Use TLauncher",
"emails.register.use_tlauncher_text": "It is much easier, when you use right tool for right purpose. TLauncher is one of the best alternative launchers for the Minecraft, that also has installed Ely.by's support system.",
"emails.register.we_glad_to_see_you": "We glad to see you among the users of Ely.by. You almost reached the final point, it remains only to confirm your E-mail address.For doing it, please push a button under the text.",

View File

@ -1,15 +1,15 @@
{
"components.footer.footer": "Ты получил это письмо, т.к. этот Email был указан при регистрации на сервисе {serviceLink}. Если это был не ты, то просто удали это письмо.",
"components.footer.footer_logo_alt": "Ely.by - Альтернативные сервисы Minecraft",
"components.footer.service_name": "Аккаунты Ely.by",
"components.header.hello_username": "Привет, {username}",
"components.blocks.code.or": "или",
"components.blocks.code.pass_code_in_field": "Укажи этот код в поле ввода на сайте:",
"components.layout.footer.footer": "Ты получил это письмо, т.к. этот Email был указан при регистрации на сервисе {serviceLink}. Если это был не ты, то просто удали это письмо.",
"components.layout.footer.footer_logo_alt": "Ely.by - Альтернативные сервисы Minecraft",
"components.layout.footer.service_name": "Аккаунты Ely.by",
"components.layout.header.hello_username": "Привет, {username}",
"emails.register.choose_you_skin_image": "Выбери свой скин",
"emails.register.choose_you_skin_text": "В каталоге скинов Ely.by ты сможешь найти множество разнообразных скинов, каждый из которых готов к тому, чтобы быть надетым.",
"emails.register.confirm_email_image": "Подтвердить Email",
"emails.register.install_our_patch_image": "Установи наш патч в игру",
"emails.register.install_our_patch_text": "Для того, чтобы система скинов Ely.by работала, тебе нужно установить наш патч. Найти его можно в разделе загрузок на сайте.",
"emails.register.or": "или",
"emails.register.pass_code_in_field": "Укажи этот код в поле ввода на сайте:",
"emails.register.use_tlauncher_image": "Используй TLauncher",
"emails.register.use_tlauncher_text": "Всё гораздо проще, когда ты используешь правильный инструмент для своей задачи. TLauncher является лучшим альтернативным лаунчером для Minecraft, который также имеет встроенную поддержку Ely.by.",
"emails.register.we_glad_to_see_you": "Мы рады видеть тебя в рядах пользователей проекта Ely.by. Ты уже почти у цели, осталось лишь подтвердить свой Email адрес. Чтобы сделать это, пожалуйста, нажми на кнопку, которая расположена ниже.",

View File

@ -1,15 +1,15 @@
{
"components.footer.footer": "Ты получил это письмо, т.к. этот Email был указан при регистрации на сервисе {serviceLink}. Если это был не ты, то просто удали это письмо.",
"components.footer.footer_logo_alt": "Ely.by - Альтернативные сервисы Minecraft",
"components.footer.service_name": "Аккаунты Ely.by",
"components.header.hello_username": "Привет, {username}",
"components.blocks.code.or": "или",
"components.blocks.code.pass_code_in_field": "Укажи этот код в поле ввода на сайте:",
"components.layout.footer.footer": "Ты получил это письмо, т.к. этот Email был указан при регистрации на сервисе {serviceLink}. Если это был не ты, то просто удали это письмо.",
"components.layout.footer.footer_logo_alt": "Ely.by - Альтернативные сервисы Minecraft",
"components.layout.footer.service_name": "Аккаунты Ely.by",
"components.layout.header.hello_username": "Привет, {username}",
"emails.register.choose_you_skin_image": "Выбери свой скин",
"emails.register.choose_you_skin_text": "В каталоге скинов Ely.by ты сможешь найти множество разнообразных скинов, каждый из которых готов к тому, чтобы быть надетым.",
"emails.register.confirm_email_image": "Подтвердить Email",
"emails.register.install_our_patch_image": "Установи наш патч в игру",
"emails.register.install_our_patch_text": "Для того, чтобы система скинов Ely.by работала, тебе нужно установить наш патч. Найти его можно в разделе загрузок на сайте.",
"emails.register.or": "или",
"emails.register.pass_code_in_field": "Укажи этот код в поле ввода на сайте:",
"emails.register.use_tlauncher_image": "Используй TLauncher",
"emails.register.use_tlauncher_text": "Всё гораздо проще, когда ты используешь правильный инструмент для своей задачи. TLauncher является лучшим альтернативным лаунчером для Minecraft, который также имеет встроенную поддержку Ely.by.",
"emails.register.we_glad_to_see_you": "Мы рады видеть тебя в рядах пользователей проекта Ely.by. Ты уже почти у цели, осталось лишь подтвердить свой Email адрес. Чтобы сделать это, пожалуйста, нажми на кнопку, которая расположена ниже.",

View File

@ -4,6 +4,7 @@ const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CircularDependencyPlugin = require('circular-dependency-plugin');
const rootPath = path.resolve('./src');
@ -95,7 +96,11 @@ const webpackConfig = {
if (!isProduction) {
webpackConfig.plugins.push(
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin()
new webpack.NoErrorsPlugin(),
new CircularDependencyPlugin({
exclude: /node_modules/,
failOnError: true
})
);
}