#147: add validation errors for first stem of ChangeEmail

This commit is contained in:
SleepWalker 2016-07-28 07:25:02 +03:00
parent d6df492073
commit 6160e4a0bc
6 changed files with 80 additions and 19 deletions

View File

@ -5,7 +5,7 @@ import classNames from 'classnames';
import Helmet from 'react-helmet';
import { Motion, spring } from 'react-motion';
import { Input, Button, Form, FormModel } from 'components/ui/form';
import { Input, Button, Form, FormModel, FormError } from 'components/ui/form';
import { BackButton } from 'components/profile/ProfileForm';
import styles from 'components/profile/profileForm.scss';
import helpLinks from 'components/auth/helpLinks.scss';
@ -181,7 +181,7 @@ export default class ChangeEmail extends Component {
);
}
renderStep0({email}) {
renderStep0({email, form}) {
return (
<div className={styles.formBody}>
<div className={styles.formRow}>
@ -194,6 +194,8 @@ export default class ChangeEmail extends Component {
<h2 className={changeEmail.currentAccountEmail}>
{email}
</h2>
<FormError error={form.getError('email')} />
</div>
<div className={styles.formRow}>

View File

@ -0,0 +1,17 @@
import React, { PropTypes } from 'react';
import errorsDict from 'services/errorsDict';
import styles from './form.scss';
export default function FormError({error}) {
return error ? (
<div className={styles.fieldError}>
{errorsDict.resolve(error)}
</div>
) : null;
}
FormError.propTypes = {
error: PropTypes.string
};

View File

@ -1,9 +1,7 @@
import React, { PropTypes } from 'react';
import errorsDict from 'services/errorsDict';
import styles from './form.scss';
import FormComponent from './FormComponent';
import FormError from './FormError';
export default class FormInputComponent extends FormComponent {
static displayName = 'FormInputComponent';
@ -27,15 +25,7 @@ export default class FormInputComponent extends FormComponent {
renderError() {
const error = this.state && this.state.error || this.props.error;
if (error) {
return (
<div className={styles.fieldError}>
{errorsDict.resolve(error)}
</div>
);
}
return null;
return <FormError error={error} />;
}
setError(error) {

View File

@ -11,9 +11,9 @@ export default class FormModel {
* Usage:
* <input {...this.form.bindField('foo')} type="text" />
*
* @param {string} name - the name of field
* @param {string} name - the name of field
*
* @return {Object} ref and name props for component
* @return {object} - ref and name props for component
*/
bindField(name) {
this.fields[name] = {};
@ -36,6 +36,11 @@ export default class FormModel {
return props;
}
/**
* Focuses field
*
* @param {string} fieldId - an id of field to focus
*/
focus(fieldId) {
if (!this.fields[fieldId]) {
throw new Error(`Can not focus. The field with an id ${fieldId} does not exists`);
@ -44,6 +49,13 @@ export default class FormModel {
this.fields[fieldId].focus();
}
/**
* Get a value of field
*
* @param {string} fieldId - an id of field to get value of
*
* @return {string}
*/
value(fieldId) {
const field = this.fields[fieldId];
@ -58,6 +70,11 @@ export default class FormModel {
return field.getValue();
}
/**
* Add errors to form fields
*
* @param {object} errors - object maping {fieldId: errorMessage}
*/
setErrors(errors) {
const oldErrors = this.errors;
this.errors = errors;
@ -69,14 +86,29 @@ export default class FormModel {
});
}
/**
* Get error by id
*
* @param {string} fieldId - an id of field to get error for
*
* @return {string|null}
*/
getError(fieldId) {
return this.errors[fieldId] || null;
}
/**
* @return {bool}
*/
hasErrors() {
return Object.keys(this.errors).length > 0;
}
/**
* Convert form into key-value object representation
*
* @return {object}
*/
serialize() {
return Object.keys(this.fields).reduce((acc, fieldId) => {
acc[fieldId] = this.fields[fieldId].getValue();
@ -88,7 +120,7 @@ export default class FormModel {
/**
* Bind handler to listen for form loading state change
*
* @param {Function} fn
* @param {function} fn
*/
addLoadingListener(fn) {
this.removeLoadingListener(fn);
@ -98,22 +130,31 @@ export default class FormModel {
/**
* Remove form loading state handler
*
* @param {Function} fn
* @param {function} fn
*/
removeLoadingListener(fn) {
this.handlers = this.handlers.filter((handler) => handler !== fn);
}
/**
* Switch form in loading state
*/
beginLoading() {
this._isLoading = true;
this.notifyHandlers();
}
/**
* Disable loading state
*/
endLoading() {
this._isLoading = false;
this.notifyHandlers();
}
/**
* @api private
*/
notifyHandlers() {
this.handlers.forEach((fn) => fn(this._isLoading));
}

View File

@ -5,6 +5,7 @@ import Button from './Button';
import Form from './Form';
import FormModel from './FormModel';
import Dropdown from './Dropdown';
import FormError from './FormError';
export {
Input,
@ -13,5 +14,6 @@ export {
Checkbox,
Form,
FormModel,
Dropdown
Dropdown,
FormError
};

View File

@ -61,6 +61,15 @@ export default connect(null, {
if (resp.errors) {
Reflect.deleteProperty(resp.errors, 'password');
if (resp.errors.email && resp.data && resp.data.canRepeatIn) {
resp.errors.email = {
type: resp.errors.email,
payload: {
msLeft: resp.data.canRepeatIn * 1000
}
};
}
if (Object.keys(resp.errors).length) {
form.setErrors(resp.errors);
return Promise.reject(resp);