diff options
-rw-r--r-- | Makefile | 1 | ||||
-rw-r--r-- | debian/pixelated-user-agent.postinst | 9 | ||||
-rw-r--r-- | web-ui/app/account_recovery.html | 2 | ||||
-rw-r--r-- | web-ui/app/js/account_recovery.js | 12 | ||||
-rw-r--r-- | web-ui/app/js/account_recovery/i18n.js | 39 | ||||
-rw-r--r-- | web-ui/app/js/account_recovery/page.js | 28 | ||||
-rw-r--r-- | web-ui/app/locales/en_US/translation.json | 11 | ||||
-rw-r--r-- | web-ui/app/locales/pt_BR/translation.json | 11 | ||||
-rw-r--r-- | web-ui/app/scss/account_recovery/page.scss | 163 | ||||
-rw-r--r-- | web-ui/app/scss/base/_colors.scss | 1 | ||||
-rw-r--r-- | web-ui/config/loaders-webpack.js | 20 | ||||
-rw-r--r-- | web-ui/package.json | 6 | ||||
-rw-r--r-- | web-ui/test/spec/account_recovery/account_recovery.spec.js | 12 | ||||
-rw-r--r-- | web-ui/test/spec/account_recovery/page.spec.js | 12 | ||||
-rw-r--r-- | web-ui/webpack.config.js | 20 | ||||
-rw-r--r-- | web-ui/webpack.production.config.js | 13 |
16 files changed, 305 insertions, 55 deletions
@@ -27,6 +27,7 @@ requirements_js: install_js: @cd web-ui;\ + npm rebuild node-sass;\ npm run build create_virtualenv: ensure_virtualenv_installed diff --git a/debian/pixelated-user-agent.postinst b/debian/pixelated-user-agent.postinst new file mode 100644 index 00000000..1e6ee23e --- /dev/null +++ b/debian/pixelated-user-agent.postinst @@ -0,0 +1,9 @@ +#!/bin/sh + +export PATH=/bin:/usr/bin:/sbin:/usr/sbin + +if [ -d /run/systemd/system ]; then + systemctl -q is-active pixelated-server.service && systemctl restart pixelated-server.service +fi + +exit 0 diff --git a/web-ui/app/account_recovery.html b/web-ui/app/account_recovery.html index 407f5907..bd451ebc 100644 --- a/web-ui/app/account_recovery.html +++ b/web-ui/app/account_recovery.html @@ -1,6 +1,8 @@ <!DOCTYPE html> <html> <head> + <meta charset="utf-8"/> + <meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1.0, maximum-scale=1.0"/> <title>Pixelated Account Recovery</title> </head> <body> diff --git a/web-ui/app/js/account_recovery.js b/web-ui/app/js/account_recovery.js index 02183574..cd01378d 100644 --- a/web-ui/app/js/account_recovery.js +++ b/web-ui/app/js/account_recovery.js @@ -1,8 +1,18 @@ import React from 'react' import { render } from 'react-dom' +import a11y from 'react-a11y' +import { I18nextProvider } from 'react-i18next' + import Page from 'js/account_recovery/page' +import i18n from 'js/account_recovery/i18n' + +import 'font-awesome/scss/font-awesome.scss' + +if(process.env.NODE_ENV === 'development') a11y(React); render( - <Page/>, + <I18nextProvider i18n={ i18n }> + <Page/> + </I18nextProvider>, document.getElementById('root') ); diff --git a/web-ui/app/js/account_recovery/i18n.js b/web-ui/app/js/account_recovery/i18n.js new file mode 100644 index 00000000..9c6ad550 --- /dev/null +++ b/web-ui/app/js/account_recovery/i18n.js @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2017 ThoughtWorks, Inc. + * + * Pixelated is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Pixelated is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Pixelated. If not, see <http://www.gnu.org/licenses/>. + */ +import i18n from 'i18next' +import i18nBackend from 'i18nextXHRBackend' +import i18nDetector from 'i18nextBrowserLanguageDetector' + +const detector = new i18nDetector(); +const detect = detector.detect.bind(detector); + +detector.detect = function(detectionOrder) { + let result = detect(detectionOrder); + return result.replace('-', '_'); +}; + +i18n + .use(i18nBackend) + .use(detector) + .init({ + fallbackLng: 'en_US', + backend: { + loadPath: 'assets/locales/{{lng}}/{{ns}}.json' + } + }); + +export default i18n; diff --git a/web-ui/app/js/account_recovery/page.js b/web-ui/app/js/account_recovery/page.js index a6be0c6e..a94c2c45 100644 --- a/web-ui/app/js/account_recovery/page.js +++ b/web-ui/app/js/account_recovery/page.js @@ -1,12 +1,28 @@ import React from 'react' +import { translate } from 'react-i18next' import 'scss/account_recovery/page.scss' -const Page = () => ( - <div className="container"> - <img src="assets/images/forgot-my-password.svg" /> - <h1>E se você esquecer sua senha?</h1> +export const Page = ({ t }) => ( + <div className='container'> + <img src='assets/images/forgot-my-password.svg' alt={t('backup-account.image-description')}/> + <form> + <h1>{t('backup-account.title')}</h1> + <p>{t('backup-account.paragraph1')}</p> + <p>{t('backup-account.paragraph2')}</p> + <div className="field-group"> + <input type="text" name="email" className="email" required/> + <label className="animated-label" htmlFor="email">{t('backup-account.input-label')}</label> + </div> + <button>{t('backup-account.button')}</button> + <div> + <a href="/"> + <i className="fa fa-angle-left" aria-hidden="true"></i> + <span>{t('back-to-inbox')}</span> + </a> + </div> + </form> </div> -); +) -export default Page +export default translate('', { wait: true })(Page) diff --git a/web-ui/app/locales/en_US/translation.json b/web-ui/app/locales/en_US/translation.json index 6e2cef80..db018db4 100644 --- a/web-ui/app/locales/en_US/translation.json +++ b/web-ui/app/locales/en_US/translation.json @@ -73,5 +73,14 @@ "trash": "Trash", "all": "All", "tags": "Tags" - } + }, + "backup-account": { + "image-description": "Forgot my password!", + "title": "What if you forget your password?", + "paragraph1": "You will need a backup account. Choose an alternative email address you use regularly.", + "paragraph2": "Instructions to recover your password will be sent to this email address, save it.", + "input-label": "Type your backup account", + "button": "Add Account" + }, + "back-to-inbox": "Back to my inbox" } diff --git a/web-ui/app/locales/pt_BR/translation.json b/web-ui/app/locales/pt_BR/translation.json index d1ab7245..87b2655e 100644 --- a/web-ui/app/locales/pt_BR/translation.json +++ b/web-ui/app/locales/pt_BR/translation.json @@ -73,5 +73,14 @@ "trash": "Lixeira", "all": "Todas", "tags": "Etiquetas" - } + }, + "backup-account": { + "image-description": "Esqueci minha senha!", + "title": "E se você esquecer sua senha?", + "paragraph1": "Informe outro e-mail que você usa regularmente. Esse será o seu e-mail de recuperação.", + "paragraph2": "Instruções para recuperar sua senha serão enviadas para esse e-mail, guarde com carinho.", + "input-label": "Digite seu e-mail de recuperação.", + "button": "Adicionar e-mail" + }, + "back-to-inbox": "Voltar" } diff --git a/web-ui/app/scss/account_recovery/page.scss b/web-ui/app/scss/account_recovery/page.scss index b6a4c024..8bba1b5a 100644 --- a/web-ui/app/scss/account_recovery/page.scss +++ b/web-ui/app/scss/account_recovery/page.scss @@ -1,7 +1,10 @@ @import "../vendor/reset"; @import "../base/colors"; @import "../base/fonts"; -@import "../base/scaffolding"; + +html { + min-height: 100%; +} body { font-family: "Open Sans", "Microsoft YaHei", "Hiragino Sans GB", "Hiragino Sans GB W3", "微软雅黑", "Helvetica Neue", Arial, sans-serif; @@ -10,22 +13,164 @@ body { background: -o-linear-gradient(bottom right, $dark_blue, $middle_blue); /* For Opera 11.1 to 12.0 */ background: -moz-linear-gradient(bottom right, $dark_blue, $middle_blue); /* For Firefox 3.6 to 15 */ background: linear-gradient(to bottom right, $dark_blue, $middle_blue); /* Standard syntax */ + color: $dark_grey_text; + min-height: 100%; } h1 { - font-size: 4em; - color: $dark_slate_gray; + font-size: 1.3em; + font-weight: 600; +} + +p { + -webkit-margin-before: 0.5em; + -webkit-margin-after: 0.5em; + margin-before: 0.5em; + margin-after: 0.5em; +} + +a { + text-decoration: none; + color: $dark_blue; + font-style: italic; + + .fa { + font-size: 1.6em; + position: relative; + top: 3px; + margin-right: 0.3em; + } + +} + +.field-group { + position:relative; + margin: 1.5em 0; + width: 100%; + + label { + font-size: 0.9em; + margin-bottom: 10px; + display: inline-block; + } + + input { + display: block; + border: none; + border-bottom: solid 1px #4da3b6; + width: 100%; + height: auto; + padding: 0.3em 0px; + } + + input:focus { + outline:none; + border-width: 2px; + } + + input:focus ~ .animated-label, input:valid ~ .animated-label { + top:-12px; + left: 0; + font-size:0.7em; + color:#4da3b6; + } + + .animated-label { + color:#999; + position:absolute; + pointer-events:none; + left: 6px; + top:10px; + transition:0.2s ease all; + -moz-transition:0.2s ease all; + -webkit-transition:0.2s ease all; + } +} + + +button { + background: $dark_blue; + padding: 0.8em; + color: $white; + text-align: center; + border: none; + border-radius: 2px; + font-weight: 300; + width: 100%; + margin-bottom: 1em; } .container { background: $white; - width: 90%; - margin: 2% auto; - padding: 3%; + width: 84%; + margin: 3% auto; + padding: 6% 5%; + + -webkit-display: flex; + display: flex; + -webkit-align-items: flex-start; + align-items: flex-start; + -webkit-flex-direction: column; + flex-direction: column; +} + +img { + width: 50%; + -webkit-align-self: center; + align-self: center; +} + +@media only screen and (min-width : 500px) { + body { + font-size: 1.3em; + } + + form { + display: flex; + -webkit-display: flex; + -webkit-flex-direction: column; + flex-direction: column; + + .field-group, button, div { + width: 70%; + -webkit-align-self: center; + align-self: center; + } + } +} + +@media only screen and (min-width : 960px) { + .container{ + width: 60%; + padding: 3%; + -webkit-align-items: flex-start; + align-items: flex-start; + -webkit-flex-direction: row; + flex-direction: row; + max-width: 700px; + } + + form { + margin-left: 2.5em; + + .field-group, button, div { + width: 300px; + -webkit-align-self: flex-start; + align-self: flex-start; + } + + .field-group { + margin-top: 3em; + font-size: 1em; + } + } img { - display: block; - width: 50%; - margin: 0 auto; + width: 300px; + } + + button { + font-size: 0.8em; + margin-bottom: 1em; } } diff --git a/web-ui/app/scss/base/_colors.scss b/web-ui/app/scss/base/_colors.scss index f3c245a9..e79781cf 100644 --- a/web-ui/app/scss/base/_colors.scss +++ b/web-ui/app/scss/base/_colors.scss @@ -38,6 +38,7 @@ $black: #000; $top_pane: $contrast; $total_count_bg: #C0B9B9; $background_dropdown_grey: #f0f0f0; +$dark_grey_text: #4a4a4a; $background_light_grey: #F5F5F5; $border_light_grey: #D9D9D9; diff --git a/web-ui/config/loaders-webpack.js b/web-ui/config/loaders-webpack.js new file mode 100644 index 00000000..21e9a572 --- /dev/null +++ b/web-ui/config/loaders-webpack.js @@ -0,0 +1,20 @@ +module.exports = [ + { + test: /\.js$/, + exclude: /(node_modules|bower_components)/, + loader: 'babel', + query: { presets: ['es2015', 'react']} + }, + { + test: /\.scss|css$/, + loader: "style-loader!css-loader!sass-loader" + }, + { + test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, + loader: "url-loader?limit=10000&mimetype=application/font-woff" + }, + { + test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/, + loader: "file-loader" + } +] diff --git a/web-ui/package.json b/web-ui/package.json index 6f875280..ff4201c0 100644 --- a/web-ui/package.json +++ b/web-ui/package.json @@ -17,11 +17,12 @@ "dompurify": "^0.8.4", "enzyme": "^2.7.1", "expect": "^1.20.2", + "file-loader": "^0.10.0", "font-awesome": "^4.7.0", "handlebars": "^4.0.5", "he": "^1.1.0", "html-minifier": "2.1.6", - "i18next": "^4.1.4", + "i18next": "^6.1.2", "i18next-browser-languagedetector": "^1.0.1", "i18next-xhr-backend": "^1.2.1", "iframe-resizer": "^3.5.7", @@ -49,12 +50,15 @@ "node-sass": "^4.5.0", "quoted-printable": "^1.0.1", "react": "^15.4.2", + "react-a11y": "^0.3.3", "react-addons-test-utils": "^15.4.2", "react-dom": "^15.4.2", + "react-i18next": "^2.1.0", "requirejs": "2.2.0", "sass-loader": "^4.1.1", "style-loader": "^0.13.1", "typeahead.js": "^0.11.1", + "url-loader": "^0.5.7", "utf8": "^2.1.2", "watch": "0.19.1", "webpack": "^1.14.0" diff --git a/web-ui/test/spec/account_recovery/account_recovery.spec.js b/web-ui/test/spec/account_recovery/account_recovery.spec.js deleted file mode 100644 index eaff257b..00000000 --- a/web-ui/test/spec/account_recovery/account_recovery.spec.js +++ /dev/null @@ -1,12 +0,0 @@ -import {shallow} from 'enzyme' -import expect from 'expect' -import React from 'react' -import Page from '../../../app/js/account_recovery/page' - -describe('test', () => { - 'use strict'; - it('react', () => { - const page = shallow(<Page />); - expect(page.find('h1').text()).toEqual('E se você esquecer sua senha?'); - }); -}); diff --git a/web-ui/test/spec/account_recovery/page.spec.js b/web-ui/test/spec/account_recovery/page.spec.js new file mode 100644 index 00000000..3e19f244 --- /dev/null +++ b/web-ui/test/spec/account_recovery/page.spec.js @@ -0,0 +1,12 @@ +import {shallow} from 'enzyme' +import expect from 'expect' +import React from 'react' +import { Page } from '../../../app/js/account_recovery/page' + +describe('Page', () => { + it('renders backup email page title', () => { + const mockT = key => key; + const page = shallow(<Page t={mockT}/>); + expect(page.find('h1').text()).toEqual('backup-account.title'); + }); +}); diff --git a/web-ui/webpack.config.js b/web-ui/webpack.config.js index 59d2ae5b..5886154a 100644 --- a/web-ui/webpack.config.js +++ b/web-ui/webpack.config.js @@ -1,6 +1,7 @@ var path = require('path'); var webpack = require('webpack'); var copyWebpack = require('./config/copy-webpack'); +var loaders = require('./config/loaders-webpack'); var aliases = require('./config/alias-webpack'); module.exports = { @@ -20,18 +21,11 @@ module.exports = { extensions: ['', '.js'] }, module: { - loaders: [ - { - test: /\.js$/, - exclude: /(node_modules|bower_components)/, - loader: 'babel', - query: { presets: ['es2015', 'react']} - }, - { - test: /\.scss|css$/, - loader: "style-loader!css-loader!sass-loader" - } - ] + loaders: loaders }, - plugins: [copyWebpack] + plugins: [copyWebpack, new webpack.DefinePlugin({ + 'process.env': { + 'NODE_ENV': '"development"' + } + })] } diff --git a/web-ui/webpack.production.config.js b/web-ui/webpack.production.config.js index bc10b90e..cf8ab8ff 100644 --- a/web-ui/webpack.production.config.js +++ b/web-ui/webpack.production.config.js @@ -1,6 +1,7 @@ var path = require('path'); var webpack = require('webpack'); var copyWebpack = require('./config/copy-webpack'); +var loaders = require('./config/loaders-webpack'); var aliases = require('./config/alias-webpack'); module.exports = { @@ -20,17 +21,7 @@ module.exports = { extensions: ['', '.js'] }, module: { - loaders: [ - { - test: /\.js$/, - loader: 'babel', - query: { presets: ['es2015', 'react']} - }, - { - test: /\.scss|css$/, - loader: "style-loader!css-loader!sass-loader" - } - ] + loaders: loaders }, plugins: [ new webpack.optimize.UglifyJsPlugin(), |