Created customizable input text

This commit is contained in:
cyril lopez 2017-07-10 16:34:12 +02:00
parent 983c74b8b5
commit 3e7adff87c
5 changed files with 225 additions and 12 deletions

View File

@ -0,0 +1,138 @@
/**
*
* InputText
*
*/
import React from 'react';
import { FormattedMessage } from 'react-intl';
import messages from './messages';
import styles from './styles.scss';
/*
* InpuText
* A customizable input
* Settings :
* - deactivateErrorHighlight
* - noBootstrap // remove bootStrapClass
* - overrideBootstrapGrid
* - overrideBootstrapCol
*/
class InputText extends React.Component { // eslint-disable-line react/prefer-stateless-function
constructor(props) {
super(props);
this.state = {
errors: false,
value: '',
};
}
componentWillReceiveProps(nextProps) {
if (this.props.errors !== nextProps.errors) {
const errors = _.isEmpty(nextProps.errors) ? nextProps.errors ? [] : false : nextProps.errors;
this.setState({ errors });
}
}
handleBlur = ({ target }) => {
// validates basic string validations
// add custom logic here such as alerts...
const errors = this.validate(target.value);
this.setState({ errors });
}
// Basic string validations
validate = (value) => {
let errors = [];
const requiredError = 'Field is required';
_.mapKeys(this.props.validations, (validationValue, validationKey) => {
switch (validationKey) {
case 'maxLength':
if (value.length > validationValue) {
errors.push('Field is too long');
}
break;
case 'minLength':
if (value.length < validationValue) {
errors.push('Field is too short');
}
break;
case 'required':
if (value.length === 0) {
errors.push(requiredError);
}
break;
case 'regex':
if (!validationValue.test(value)) {
errors.push('Field is not valid');
}
break;
default:
errors = false;
}
});
if (_.isEmpty(errors)) {
errors = false;
} else if (_.includes(errors, requiredError)) {
errors = _.reject(errors, (value) => value !== requiredError);
}
return errors;
}
render() {
const inputValue = this.props.value || '';
// override default onBlur
const handleBlur = this.props.handleBlur || this.handleBlur;
// override bootStrapClass
const bootStrapClass = !this.props.noBootstrap ?
`col-${this.props.overrideBootstrapGrid || 'md'}-${this.props.overrideBootstrapCol || '6'}`
: '';
// set error class with override possibility
const bootStrapClassDanger = !this.props.noBootstrap && !this.props.deactivateErrorHighlight && this.state.errors ? 'has-danger' : '';
// use bootstrap class to display error
const formError = !this.props.noBootstrap ? 'form-control-feedback' : '';
return (
<div className={`${styles.inputText} ${bootStrapClass} ${bootStrapClassDanger}`}>
<label>{this.props.name}</label>
<input
name={this.props.name}
onBlur={handleBlur}
onFocus={this.props.onFocus}
onChange={this.props.handleChange}
value={inputValue}
type="text"
className={`form-control ${this.state.errors? 'form-control-danger' : ''}`}
placeholder={`Change ${this.props.name} field`}
/>
<small>{this.props.inputDescription}</small>
{_.map(this.state.errors, (error, key) => (
<div key={key} className={formError}>{error}</div>
))}
</div>
);
}
}
InputText.propTypes = {
errors: React.PropTypes.oneOfType([
React.PropTypes.bool,
React.PropTypes.array,
]),
deactivateErrorHighlight: React.PropTypes.bool,
handleBur: React.PropTypes.func,
handleChange: React.PropTypes.func.isRequired,
inputDescription: React.PropTypes.string,
name: React.PropTypes.string.isRequired,
noBootstrap: React.PropTypes.bool,
overrideBootstrapGrid: React.PropTypes.string,
overrideBootstrapCol: React.PropTypes.string,
placeholder: React.PropTypes.string,
value: React.PropTypes.string.isRequired,
validations: React.PropTypes.object.isRequired,
}
export default InputText;

View File

@ -0,0 +1,13 @@
/*
* InputText Messages
*
* This contains all the text for the InputText component.
*/
import { defineMessages } from 'react-intl';
export default defineMessages({
header: {
id: 'app.components.InputText.header',
defaultMessage: 'This is the InputText component !',
},
});

View File

@ -0,0 +1,11 @@
.inputText { /* stylelint-disable */
margin-top: 1.8rem;
> label {
text-transform: capitalize;
}
> small {
margin-top: .5rem;
display: block;
color: #ABAFBB;
}
}

View File

@ -0,0 +1,11 @@
// import InputText from '../index';
import expect from 'expect';
// import { shallow } from 'enzyme';
// import React from 'react';
describe('<InputText />', () => {
it('Expect to have unit tests specified', () => {
expect(true).toEqual(false);
});
});

View File

@ -8,24 +8,38 @@ import React from 'react';
import { connect } from 'react-redux';
import Helmet from 'react-helmet';
import PluginLeftMenu from 'components/PluginLeftMenu';
import InputText from 'components/InputText';
import selectHome from './selectors';
import styles from './styles.scss';
export class Home extends React.Component { // eslint-disable-line react/prefer-stateless-function
// constructor(props) {
// super(props);
// // this.leftMenuItems = [
// // {
// // header: 'global settings',
// // items: [
// // general, 'languages', 'advanced'],
// // }
// // ]
// }
constructor(props) {
super(props);
this.state = {
value: '',
}
}
handleChange = ({ target }) => {
console.log(target.value);
this.setState({ value: target.value });
}
render() {
const test = {
"name": "bame",
"slug": "name",
"target": "general.name",
"type": "text",
"value": "ExperienceApp",
"validations" : {
"maxLength": 2,
"required": true,
"regex": /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
}
};
return (
<div className={styles.home}>
<div className={styles.baseline}></div>
@ -39,7 +53,33 @@ export class Home extends React.Component { // eslint-disable-line react/prefer-
<div className="row">
<PluginLeftMenu />
<div className="col-md-9">
f
<div className="form-group">
<InputText
validations={test.validations}
name={test.name}
value={this.state.value}
handleChange={this.handleChange}
inputDescription="blabklba bka"
/>
<InputText
validations={test.validations}
name={test.name}
value={this.state.value}
handleChange={this.handleChange}
inputDescription="blabklba bka"
overrideBootstrapCol="4"
errors={false}
/>
<InputText
validations={test.validations}
name={test.name}
value={this.state.value}
handleChange={this.handleChange}
inputDescription="blabklba bka"
overrideBootstrapCol="2"
/>
</div>
</div>
</div>
</div>