diff --git a/client/coral-framework/actions/auth.js b/client/coral-framework/actions/auth.js
index e25eb4174..19fa2c499 100644
--- a/client/coral-framework/actions/auth.js
+++ b/client/coral-framework/actions/auth.js
@@ -23,7 +23,10 @@ export const fetchSignIn = (formData) => dispatch => {
dispatch(signInRequest());
fetch(`${base}/auth/local`, getInit('POST', formData))
.then(handleResp)
- .then(({user}) => dispatch(signInSuccess(user)))
+ .then(({user}) => {
+ dispatch(hideSignInDialog());
+ dispatch(signInSuccess(user));
+ })
.catch(() => dispatch(signInFailure('Email and/or password combination incorrect.')));
};
@@ -49,6 +52,7 @@ export const facebookCallback = (err, data) => dispatch => {
}
try {
dispatch(signInFacebookSuccess(JSON.parse(data)));
+ dispatch(hideSignInDialog());
} catch (err) {
dispatch(signInFacebookFailure(err));
return;
@@ -65,8 +69,11 @@ export const fetchSignUp = formData => dispatch => {
dispatch(signUpRequest());
fetch(`${base}/user`, getInit('POST', formData))
.then(handleResp)
- .then(({user}) => signUpSuccess(user))
- .catch((error) => signUpFailure(error));
+ .then(({user}) => {
+ dispatch(signUpSuccess(user));
+ dispatch(hideSignInDialog());
+ })
+ .catch((error) => dispatch(signUpFailure(error)));
};
// Forgot Password Actions
diff --git a/client/coral-framework/helpers/error.js b/client/coral-framework/helpers/error.js
index 2674bc55b..735ad7a5d 100644
--- a/client/coral-framework/helpers/error.js
+++ b/client/coral-framework/helpers/error.js
@@ -1,6 +1,6 @@
export default {
email: 'Not a valid E-Mail',
password: 'Password must be at least 8 characters',
- username: 'Username is too short',
- confirmPassword: 'Passwords do not match'
+ displayName: 'Display name is too short',
+ confirmPassword: 'Passwords don`t match. Please, check again'
};
diff --git a/client/coral-framework/helpers/response.js b/client/coral-framework/helpers/response.js
index a18bd155f..bccfc5a04 100644
--- a/client/coral-framework/helpers/response.js
+++ b/client/coral-framework/helpers/response.js
@@ -20,8 +20,6 @@ export const getInit = (method, body) => {
export const handleResp = res => {
if (res.status === 401) {
throw new Error('Not Authorized to make this request');
- } else if (res.status === 500) {
- throw new Error(res.json());
} else if (res.status > 399) {
throw new Error('Error! Status ', res.status);
} else if (res.status === 204) {
diff --git a/client/coral-framework/helpers/validate.js b/client/coral-framework/helpers/validate.js
index 9fda4b1c2..8c5ebd36f 100644
--- a/client/coral-framework/helpers/validate.js
+++ b/client/coral-framework/helpers/validate.js
@@ -2,5 +2,5 @@ export default {
email: email => (/^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/.test(email)),
password: pass => (/^(?=.{8,}).*$/.test(pass)),
confirmPassword: () => true,
- username: username => (/^(?=.{3,}).*$/.test(username))
+ displayName: displayName => (/^(?=.{3,}).*$/.test(displayName))
};
diff --git a/client/coral-framework/reducers/auth.js b/client/coral-framework/reducers/auth.js
index 10ac121e7..c2bdc20db 100644
--- a/client/coral-framework/reducers/auth.js
+++ b/client/coral-framework/reducers/auth.js
@@ -25,7 +25,6 @@ const initialState = Map({
signInError: '',
signUpError: '',
emailAvailable: true,
- displayNameAvailable: true,
});
export default function auth (state = initialState, action) {
@@ -34,7 +33,14 @@ export default function auth (state = initialState, action) {
return state
.set('showSignInDialog', true);
case HIDE_SIGNIN_DIALOG :
- return initialState;
+ return state.merge(Map({
+ isLoading: false,
+ showSignInDialog: false,
+ view: 'SIGNIN',
+ signInError: '',
+ signUpError: '',
+ emailAvailable: true,
+ }));
case CHANGE_VIEW :
return state
.set('view', action.view);
@@ -43,22 +49,18 @@ export default function auth (state = initialState, action) {
case FETCH_SIGNIN_REQUEST:
return state
.set('isLoading', true);
+ case FETCH_SIGNIN_SUCCESS:
+ return state
+ .set('loggedIn', true)
+ .set('user', action.user);
case FETCH_SIGNIN_FAILURE:
return state
.set('isLoading', false)
.set('signInError', action.error);
- case FETCH_SIGNIN_SUCCESS:
- return state
- .set('signInError', '')
- .set('isLoading', false)
- .set('loggedIn', true)
- .set('user', action.user)
- .set('showSignInDialog', false);
case FETCH_SIGNIN_FACEBOOK_SUCCESS:
return state
.set('user', action.user)
- .set('loggedIn', true)
- .set('showSignInDialog', false);
+ .set('loggedIn', true);
case FETCH_SIGNIN_FACEBOOK_FAILURE:
return state
.set('error', action.error)
diff --git a/client/coral-sign-in/components/FormField.js b/client/coral-sign-in/components/FormField.js
index 62e50e637..ceb2d939e 100644
--- a/client/coral-sign-in/components/FormField.js
+++ b/client/coral-sign-in/components/FormField.js
@@ -11,7 +11,7 @@ const FormField = ({className, showErrors = false, errorMsg, label, ...props}) =
name={props.id}
{...props}
/>
- {showErrors && errorMsg && {errorMsg}}
+ {showErrors && errorMsg && !{errorMsg}}
);
diff --git a/client/coral-sign-in/components/SignInContent.js b/client/coral-sign-in/components/SignInContent.js
index 2e22c0696..8aa688133 100644
--- a/client/coral-sign-in/components/SignInContent.js
+++ b/client/coral-sign-in/components/SignInContent.js
@@ -41,14 +41,16 @@ const SignInContent = ({handleChange, formData, ...props}) => (
value={formData.password}
onChange={handleChange}
/>
- {
- !props.auth.isLoading ?
-
- :
-
- }
+
+ {
+ !props.auth.isLoading ?
+
+ :
+
+ }
+
props.changeView('FORGOT')}>{lang.t('signIn.forgotYourPass')}
diff --git a/client/coral-sign-in/components/SignUpContent.js b/client/coral-sign-in/components/SignUpContent.js
index 2ae6267dc..adc377dbf 100644
--- a/client/coral-sign-in/components/SignUpContent.js
+++ b/client/coral-sign-in/components/SignUpContent.js
@@ -32,21 +32,20 @@ const SignUpContent = ({handleChange, formData, ...props}) => (
type="email"
label={lang.t('signIn.email')}
value={formData.email}
- showErrors={props.showErrors}
- errorMsg={props.errors.email}
+ showErrors={!props.auth.emailAvailable || props.showErrors}
+ errorMsg={!props.auth.emailAvailable ? lang.t('signIn.emailInUse') : props.errors.email}
onChange={handleChange}
+ autoFocus
/>
- { !props.auth.emailAvailable &&
This email is not available. }
- { !props.auth.displayNameAvailable &&
This username is not available. }
(
showErrors={props.showErrors}
errorMsg={props.errors.password}
onChange={handleChange}
+ minLength="8"
/>
+ { !props.errors.password && Password must be at least 8 characters. }
(
showErrors={props.showErrors}
errorMsg={props.errors.confirmPassword}
onChange={handleChange}
+ minLength="8"
/>
- {
- !props.auth.isLoading ?
-
- :
-
- }
+
+ {
+ !props.auth.isLoading ?
+
+ :
+
+ }
+
diff --git a/client/coral-sign-in/components/styles.css b/client/coral-sign-in/components/styles.css
index a7c14d891..9cd7bd326 100644
--- a/client/coral-sign-in/components/styles.css
+++ b/client/coral-sign-in/components/styles.css
@@ -15,6 +15,10 @@
font-size: 1.2em;
}
+.formField {
+ margin-top: 15px;
+}
+
.formField label {
font-size: 1.08em;
font-weight: bold;
@@ -74,10 +78,10 @@
}
input.error{
- border: solid 1px #f44336;
+ border: solid 2px #f44336;
}
-.errorMsg {
+.errorMsg, .hint {
color: grey;
font-weight: 600;
padding: 3px 0 16px;
@@ -86,6 +90,7 @@ input.error{
.alert {
padding: 10px;
margin-bottom: 20px;
+ border-radius: 2px;
}
.alert--success {
@@ -103,4 +108,25 @@ input.error{
color: #2c69b6;
cursor: pointer;
margin: 0 5px;
+}
+
+.attention {
+ display: inline-block;
+ width: 15px;
+ height: 15px;
+ background: #B71C1C;
+ color: #FFEBEE;
+ font-weight: bolder;
+ padding: 4px;
+ vertical-align: middle;
+ border-radius: 20px;
+ box-sizing: border-box;
+ font-size: 9px;
+ line-height: 7px;
+ text-align: center;
+ margin-right: 5px;
+}
+
+.action {
+ margin-top: 15px;
}
\ No newline at end of file
diff --git a/client/coral-sign-in/containers/SignInContainer.js b/client/coral-sign-in/containers/SignInContainer.js
index 471c0c166..7a5ae51ac 100644
--- a/client/coral-sign-in/containers/SignInContainer.js
+++ b/client/coral-sign-in/containers/SignInContainer.js
@@ -1,11 +1,12 @@
import React, {Component} from 'react';
import {connect} from 'react-redux';
+import debounce from 'lodash.debounce';
import SignDialog from '../components/SignDialog';
import Button from 'coral-ui/components/Button';
import validate from 'coral-framework/helpers/validate';
-import error from 'coral-framework/helpers/error';
+import errorMsj from 'coral-framework/helpers/error';
import {
changeView,
@@ -23,7 +24,7 @@ class SignInContainer extends Component {
initialState = {
formData: {
email: '',
- username: '',
+ displayName: '',
password: '',
confirmPassword: ''
},
@@ -39,7 +40,7 @@ class SignInContainer extends Component {
this.handleSignIn = this.handleSignIn.bind(this);
this.handleClose = this.handleClose.bind(this);
this.cleanState = this.cleanState.bind(this);
- this.validation = this.validation.bind(this);
+ this.addError = this.addError.bind(this);
}
componentDidMount() {
@@ -52,72 +53,77 @@ class SignInContainer extends Component {
handleChange(e) {
const {name, value} = e.target;
- this.validation(name, value, this.state.formData);
-
this.setState(state => ({
...state,
formData: {
...state.formData,
[name]: value
}
+ }), () => {
+ this.validation(name, value);
+ });
+ }
+
+ addError(name, error) {
+ return this.setState(state => ({
+ errors: {
+ ...state.errors,
+ [name]: error
+ }
}));
}
validation(name, value) {
- if (!validate[name](value)) {
- this.setState(state => ({
- errors: {
- ...state.errors,
- [name]: error[name]
- }
- }));
+ const {addError} = this;
+ const {formData} = this.state;
+ const {checkAvailability} = this.props;
+
+ if (!value.length) {
+ addError(name, 'Please, fill this field');
+ } else if (name === 'confirmPassword' && formData.confirmPassword !== formData.password) {
+ addError(name, 'Passwords don`t match. Please, check again.');
+ } else if (!validate[name](value)) {
+ addError(name, errorMsj[name]);
} else {
const { [name]: prop, ...errors } = this.state.errors; // eslint-disable-line
- this.setState(state => ({
- ...state,
- errors
- }));
-
- // Check Availability
-
- if (name === 'email' || name === 'displayName') {
- this.props.checkAvailability({[name]: value});
+ // Removes Error
+ this.setState(state => ({...state, errors}));
+ // Checks Email Availability
+ if (name === 'email') {
+ debounce(checkAvailability({[name]: value}), 250);
}
-
}
}
isCompleted() {
const {formData} = this.state;
- return !Object.keys(formData).filter(prop => !formData[prop].length).length;
+ const {emailAvailable} = this.props.auth;
+ return !Object.keys(formData).filter(prop => !formData[prop].length).length && emailAvailable;
}
displayErrors(show = true) {
- this.setState({
- showErrors: show
- });
+ this.setState({showErrors: show});
}
handleSignUp(e) {
e.preventDefault();
+ const {errors} = this.state;
this.displayErrors();
- if (this.isCompleted()) {
- console.log('Is Completed!!');
- } else {
- console.log('Is not Completed!!');
+ if (this.isCompleted() && !Object.keys(errors).length) {
+ this.props.fetchSignUp(this.state.formData);
+ this.cleanState();
}
- this.props.fetchSignUp(this.state.formData);
}
handleSignIn(e) {
e.preventDefault();
- this.displayErrors();
this.props.fetchSignIn(this.state.formData);
+ this.cleanState();
}
handleClose() {
- this.cleanState();
this.props.hideSignInDialog();
+ this.cleanState();
}
changeView(view) {
@@ -127,19 +133,16 @@ class SignInContainer extends Component {
render() {
const {auth, showSignInDialog} = this.props;
- const {errors, showErrors, formData} = this.state;
return (
@@ -147,7 +150,7 @@ class SignInContainer extends Component {
}
}
-const mapStateToProps = (state) => ({
+const mapStateToProps = state => ({
auth: state.auth.toJS()
});
diff --git a/client/coral-sign-in/translations.js b/client/coral-sign-in/translations.js
index a0fd7015e..fdf7de0a0 100644
--- a/client/coral-sign-in/translations.js
+++ b/client/coral-sign-in/translations.js
@@ -13,9 +13,10 @@ export default {
register: 'Register',
signUp: 'Sign Up',
confirmPassword: 'Confirm Password',
- username: 'Username',
+ displayName: 'Display Name',
alreadyHaveAnAccount: 'Already have an account?',
- recoverPassword: 'Recover password'
+ recoverPassword: 'Recover password',
+ emailInUse: 'Email address already in use'
}
},
es: {
@@ -32,9 +33,10 @@ export default {
register: 'Regístrate',
signUp: 'Registro',
confirmPassword: 'Confirmar Contraseña',
- username: 'Usuario',
+ displayName: 'Nombre',
alreadyHaveAnAccount: 'Ya tienes una cuenta?',
- recoverPassword: 'Recuperar contraseña'
+ recoverPassword: 'Recuperar contraseña',
+ emailInUse: 'Este email se encuentra en uso'
}
}
};
diff --git a/package.json b/package.json
index 4341483af..b913aefce 100644
--- a/package.json
+++ b/package.json
@@ -53,6 +53,7 @@
"express": "^4.14.0",
"express-session": "^1.14.2",
"helmet": "^3.1.0",
+ "lodash.debounce": "^4.0.8",
"mongoose": "^4.6.5",
"morgan": "^1.7.0",
"passport": "^0.3.2",
diff --git a/routes/api/user/index.js b/routes/api/user/index.js
index 4b428be33..e8bc90ac2 100644
--- a/routes/api/user/index.js
+++ b/routes/api/user/index.js
@@ -61,7 +61,7 @@ router.get('/', (req, res, next) => {
});
router.post('/', (req, res, next) => {
- const {email, password, displayName} = req.query;
+ const {email, password, displayName} = req.body;
User
.createLocalUser(email, password, displayName)
@@ -87,14 +87,9 @@ router.post('/availability', (req, res, next) => {
})
.then(count => {
if (count) {
- res.json({
- status: 'unavailable'
- });
- } else {
- res.json({
- status: 'available'
- });
+ return res.json({status: 'unavailable'});
}
+ return res.json({status: 'available'});
})
.catch(err => {
next(err);