summaryrefslogtreecommitdiffhomepage
path: root/app
diff options
context:
space:
mode:
authorAndrej Mihajlov <and@codeispoetry.ru>2017-06-30 19:07:25 +0300
committerAndrej Mihajlov <and@codeispoetry.ru>2017-06-30 23:58:44 +0300
commit79d46a4bcd8257d5473bae2ef2ed894829638c86 (patch)
tree100725d971d64b7d0cb321ed148584ac17e3358c /app
parent72611b83c2fb597148831b023eda8f7b05d20da9 (diff)
downloadmullvadvpn-79d46a4bcd8257d5473bae2ef2ed894829638c86.tar.xz
mullvadvpn-79d46a4bcd8257d5473bae2ef2ed894829638c86.zip
Annotate Login component
Diffstat (limited to 'app')
-rw-r--r--app/components/Login.js124
1 files changed, 61 insertions, 63 deletions
diff --git a/app/components/Login.js b/app/components/Login.js
index 72ef933082..460fa0f277 100644
--- a/app/components/Login.js
+++ b/app/components/Login.js
@@ -1,58 +1,41 @@
+// @flow
import React, { Component } from 'react';
-import PropTypes from 'prop-types';
import { If, Then } from 'react-if';
import { Layout, Container, Header } from './Layout';
import AccountInput from './AccountInput';
import ExternalLinkSVG from '../assets/images/icon-extLink.svg';
import LoginArrowSVG from '../assets/images/icon-arrow.svg';
-export default class Login extends Component {
- static propTypes = {
- user: PropTypes.object.isRequired,
- onLogin: PropTypes.func.isRequired,
- onSettings: PropTypes.func.isRequired,
- onChange: PropTypes.func.isRequired,
- onFirstChangeAfterFailure: PropTypes.func.isRequired,
- onExternalLink: PropTypes.func.isRequired,
- };
+import type { LoginState } from '../enums';
+import type { UserReduxState } from '../reducers/user';
- constructor(props) {
- super(props);
- this.state = {
- notifyOnFirstChangeAfterFailure: false,
- isActive: false
- };
- }
+export type LoginPropTypes = {
+ user: UserReduxState,
+ onLogin: (accountNumber: string) => void,
+ onSettings: ?(() => void),
+ onChange: (input: string) => void,
+ onFirstChangeAfterFailure: () => void,
+ onExternalLink: (type: string) => void,
+};
- componentWillReceiveProps(nextProps) {
- const prev = this.props.user || {};
- const next = nextProps.user || {};
-
- if(prev.status !== next.status && next.status === 'failed') {
- this.setState({ notifyOnFirstChangeAfterFailure: true });
- }
+export default class Login extends Component {
+ props: LoginPropTypes;
+ state = {
+ notifyOnFirstChangeAfterFailure: false,
+ isActive: false
}
- onLogin() {
+ onCreateAccount = () => this.props.onExternalLink('createAccount');
+ onFocus = () => this.setState({ isActive: true });
+ onBlur = () => this.setState({ isActive: false });
+ onLogin = () => {
const { account } = this.props.user;
- if(account.length > 0) {
+ if(account && account.length > 0) {
this.props.onLogin(account);
}
}
- onCreateAccount() {
- this.props.onExternalLink('createAccount');
- }
-
- onFocus() {
- this.setState({ isActive: true });
- }
-
- onBlur() {
- this.setState({ isActive: false });
- }
-
- onInputChange(val) {
+ onInputChange = (val: string) => {
// notify delegate on first change after login failure
if(this.state.notifyOnFirstChangeAfterFailure) {
this.setState({ notifyOnFirstChangeAfterFailure: false });
@@ -61,7 +44,7 @@ export default class Login extends Component {
this.props.onChange(val);
}
- formTitle(s) {
+ formTitle(s: LoginState): string {
switch(s) {
case 'connecting': return 'Logging in...';
case 'failed': return 'Login failed';
@@ -70,22 +53,22 @@ export default class Login extends Component {
}
}
- formSubtitle(s, e) {
+ formSubtitle(s: LoginState, e: ?Error): string {
switch(s) {
- case 'failed': return e.message;
+ case 'failed': return (e && e.message) || 'Unknown error';
case 'connecting': return 'Checking account number';
default: return 'Enter your account number';
}
}
- inputWrapClass(user) {
+ inputWrapClass(s: LoginState): string {
const classes = ['login-form__input-wrap'];
if(this.state.isActive) {
classes.push('login-form__input-wrap--active');
}
- switch(user.status) {
+ switch(s) {
case 'connecting':
classes.push('login-form__input-wrap--inactive');
break;
@@ -97,9 +80,9 @@ export default class Login extends Component {
return classes.join(' ');
}
- footerClass(user) {
+ footerClass(s: LoginState): string {
const classes = ['login-footer'];
- switch(user.status) {
+ switch(s) {
case 'ok':
case 'connecting':
classes.push('login-footer--invisible');
@@ -108,31 +91,46 @@ export default class Login extends Component {
return classes.join(' ');
}
- submitClass(user) {
+ submitClass(s: LoginState, account: ?string): string {
const classes = ['login-form__submit'];
- if(typeof(user.account) === 'string' && user.account.length > 0) {
+ if(account && account.length > 0) {
classes.push('login-form__submit--active');
}
- if(user.status === 'connecting') {
+ if(s === 'connecting') {
classes.push('login-form__submit--invisible');
}
return classes.join(' ');
}
- render() {
+ componentWillReceiveProps(nextProps: LoginPropTypes) {
+ const prev = this.props.user || {};
+ const next = nextProps.user || {};
+
+ if(prev.status !== next.status && next.status === 'failed') {
+ this.setState({ notifyOnFirstChangeAfterFailure: true });
+ }
+ }
+
+ render(): React.Element<*> {
const { account, status, error } = this.props.user;
const title = this.formTitle(status);
const subtitle = this.formSubtitle(status, error);
- const isConnecting = status === 'connecting';
- const isFailed = status === 'failed';
- const isLoggedIn = status === 'ok';
- const inputWrapClass = this.inputWrapClass(this.props.user);
- const footerClass = this.footerClass(this.props.user);
- const submitClass = this.submitClass(this.props.user);
+ let isConnecting = false;
+ let isFailed = false;
+ let isLoggedIn = false;
+ switch(status) {
+ case 'connecting': isConnecting = true; break;
+ case 'failed': isFailed = true; break;
+ case 'ok': isLoggedIn = true; break;
+ }
+
+ const inputWrapClass = this.inputWrapClass(status);
+ const footerClass = this.footerClass(status);
+ const submitClass = this.submitClass(status, account);
const autoFocusRef = input => {
if(isFailed && input) {
@@ -180,15 +178,15 @@ export default class Login extends Component {
<AccountInput className="login-form__input-field"
type="text"
placeholder="e.g 0000 0000 0000"
- onFocus={ ::this.onFocus }
- onBlur={ ::this.onBlur }
- onChange={ ::this.onInputChange }
- onEnter={ ::this.onLogin }
- value={ account }
+ onFocus={ this.onFocus }
+ onBlur={ this.onBlur }
+ onChange={ this.onInputChange }
+ onEnter={ this.onLogin }
+ value={ account || '' }
disabled={ isConnecting }
autoFocus={ true }
ref={ autoFocusRef } />
- <button className={ submitClass } onClick={ ::this.onLogin }>
+ <button className={ submitClass } onClick={ this.onLogin }>
<LoginArrowSVG className="login-form__submit-icon" />
</button>
</div>
@@ -196,7 +194,7 @@ export default class Login extends Component {
</div>
<div className={ footerClass }>
<div className="login-footer__prompt">Don't have an account number?</div>
- <button className="button button--primary" onClick={ ::this.onCreateAccount }>
+ <button className="button button--primary" onClick={ this.onCreateAccount }>
<span className="button-label">Create account</span>
<ExternalLinkSVG className="button-icon button-icon--16" />
</button>