/**
*
* InputText
* Customization
* - deactivateErrorHighlight: bool
* allow the user to remove bootstrap class 'has-danger' on the inputText
* - customBootstrapClass : string
* overrides the default 'col-md-6' on the inputText
* - handleBlur: function
* overrides the default input validations
* - errors : array
* - noErrorsDescription : bool
* prevent from displaying errors messages
*
* Required
* - name : string
* - handleChange : function
* - value : string
* - target : string
* - validations : object
*
* Optionnal
* - description : input description
* - handleFocus : function
* - placeholder : string if set to "" nothing will display
*
* - styles are retrieved from the HOC
*/
import React from 'react';
import PropTypes from 'prop-types';
import { isEmpty, includes, mapKeys, reject, map, isObject, union, findIndex, uniqBy, size } from 'lodash';
import { FormattedMessage } from 'react-intl';
import WithInput from '../WithInput';
/* eslint-disable react/require-default-props */
class InputText extends React.Component { // eslint-disable-line react/prefer-stateless-function
constructor(props) {
super(props);
this.state = {
errors: [],
hasInitialValue: false,
};
}
componentDidMount() {
if (this.props.value && !isEmpty(this.props.value)) {
this.setState({ hasInitialValue: true });
}
}
componentWillReceiveProps(nextProps) {
if (!this.isSame(nextProps)) {
const errors = isEmpty(nextProps.errors) ? [] : uniqBy(union(this.state.errors, nextProps.errors), 'id');
// if (isEmpty(nextProps.errors)) remove(errors, (error) => error.id === 'settings-manager.request.error.database.exist');
this.setState({ errors });
}
if (isEmpty(nextProps.errors)) {
this.setState({ errors: [] });
}
}
isSame = (nextProps) => {
return size(this.props.errors) === size(nextProps.errors) && this.props.errors.every((error, index) => error.id === nextProps.errors[index].id);
}
handleBlur = ({ target }) => {
// prevent error display if input is initially empty
if (!isEmpty(target.value) || this.state.hasInitialValue) {
// validates basic string validations
// add custom logic here such as alerts...
// specific check for db
const indexErrorDbExist = findIndex(this.props.errors, ['id', 'settings-manager.request.error.database.exist']);
const errors = indexErrorDbExist !== -1 ?
uniqBy(union(this.props.errors, this.validate(target.value)), 'id') : this.validate(target.value);
this.setState({ errors, hasInitialValue: true });
}
}
// Basic string validations
validate = (value) => {
let errors = [];
// handle i18n
const requiredError = { id: 'settings-manager.request.error.validation.required' };
mapKeys(this.props.validations, (validationValue, validationKey) => {
switch (validationKey) {
case 'maxLength':
if (value.length > validationValue) {
errors.push({ id: 'settings-manager.request.error.validation.maxLength' });
}
break;
case 'minLength':
if (value.length < validationValue) {
errors.push({ id: 'settings-manager.request.error.validation.minLength' });
}
break;
case 'required':
if (value.length === 0) {
errors.push({ id: 'settings-manager.request.error.validation.required' });
}
break;
case 'regex':
if (!new RegExp(validationValue).test(value)) {
errors.push({ id: 'settings-manager.request.error.validation.regex' });
}
break;
default:
errors = [];
}
});
if (includes(errors, requiredError)) {
errors = reject(errors, (error) => error !== requiredError);
}
return errors;
}
renderErrors = () => { // eslint-disable-line consistent-return
if (!this.props.noErrorsDescription) {
return (
map(this.state.errors, (error, key) => {
const displayError = isObject(error) && error.id
?