summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile1
-rw-r--r--debian/pixelated-user-agent.postinst9
-rw-r--r--web-ui/app/account_recovery.html2
-rw-r--r--web-ui/app/js/account_recovery.js12
-rw-r--r--web-ui/app/js/account_recovery/i18n.js39
-rw-r--r--web-ui/app/js/account_recovery/page.js28
-rw-r--r--web-ui/app/locales/en_US/translation.json11
-rw-r--r--web-ui/app/locales/pt_BR/translation.json11
-rw-r--r--web-ui/app/scss/account_recovery/page.scss163
-rw-r--r--web-ui/app/scss/base/_colors.scss1
-rw-r--r--web-ui/config/loaders-webpack.js20
-rw-r--r--web-ui/package.json6
-rw-r--r--web-ui/test/spec/account_recovery/account_recovery.spec.js12
-rw-r--r--web-ui/test/spec/account_recovery/page.spec.js12
-rw-r--r--web-ui/webpack.config.js20
-rw-r--r--web-ui/webpack.production.config.js13
16 files changed, 305 insertions, 55 deletions
diff --git a/Makefile b/Makefile
index 5c17032e..a263ec42 100644
--- a/Makefile
+++ b/Makefile
@@ -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(),