Input JSON UI with error

This commit is contained in:
Virginie Ky 2019-11-21 15:06:38 +01:00
parent b35e5b022d
commit 8174e9dae8
4 changed files with 93 additions and 121 deletions

View File

@ -21,7 +21,8 @@
"type": "string"
},
"geolocation": {
"type": "json"
"type": "json",
"required": true
},
"country": {
"model": "country"

View File

@ -2,8 +2,7 @@ import styled from 'styled-components';
const Wrapper = styled.div`
position: relative;
margin-top: 14px;
margin-bottom: -14px;
margin-bottom: 3px;
line-height: 18px;
.CodeMirror {

View File

@ -0,0 +1,32 @@
import styled from 'styled-components';
const Wrapper = styled.div`
padding-bottom: 30px;
label {
margin-bottom: 1rem;
line-height: 18px;
display: block;
}
> div {
border-radius: 4px;
border: 1px solid #090300;
}
&.bordered {
> div {
border-color: red;
}
}
> p {
width 100%;
padding-top: 14px;
font-size: 1.2rem;
line-height: normal;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
margin-bottom: -11px;
}
`;
export default Wrapper;

View File

@ -9,66 +9,13 @@ import PropTypes from 'prop-types';
import { isEmpty, isFunction } from 'lodash';
import cn from 'classnames';
// Design
import {
Label,
InputDescription,
InputErrors,
InputSpacer,
validateInput,
} from 'strapi-helper-plugin';
import { Description, ErrorMessage, Label } from '@buffetjs/styles';
import { Error } from '@buffetjs/core';
import InputJSON from '../InputJSON';
import Wrapper from './Wrapper';
class InputJSONWithErrors extends React.Component {
// eslint-disable-line react/prefer-stateless-function
state = { errors: [], hasInitialValue: false };
componentDidMount() {
const { value, errors } = this.props;
// Prevent the input from displaying an error when the user enters and leaves without filling it
if (!isEmpty(value)) {
this.setState({ hasInitialValue: true });
}
// Display input error if it already has some
if (!isEmpty(errors)) {
this.setState({ errors });
}
}
componentDidUpdate(prevProps) {
// Show required error if the input's value is received after the compo is mounted
if (!isEmpty(this.props.value) && !this.state.hasInitialValue) {
this.setInit();
}
// Check if errors have been updated during validations
if (prevProps.didCheckErrors !== this.props.didCheckErrors) {
// Remove from the state the errors that have already been set
const errors = isEmpty(this.props.errors) ? [] : this.props.errors;
this.setErrors(errors);
}
}
setErrors = errors => this.setState({ errors });
setInit = () => this.setState({ hasInitialValue: true });
/**
* Set the errors depending on the validations given to the input
* @param {Object} target
*/
handleBlur = ({ target }) => {
// Prevent from displaying error if the input is initially isEmpty
if (!isEmpty(target.value) || this.state.hasInitialValue) {
const errors = validateInput(target.value, this.props.validations);
this.setErrors(errors);
this.setInit();
}
};
handleChange = e => {
this.setState({ errors: [] });
this.props.onChange(e);
@ -80,74 +27,75 @@ class InputJSONWithErrors extends React.Component {
className,
deactivateErrorHighlight,
disabled,
errorsClassName,
errorsStyle,
error: inputError,
inputClassName,
inputDescription,
inputDescriptionClassName,
inputStyle,
label,
labelClassName,
labelStyle,
name,
noErrorsDescription,
onBlur,
placeholder,
resetProps,
tabIndex,
validations,
value,
...rest
} = this.props;
const handleBlur = isFunction(onBlur) ? onBlur : this.handleBlur;
let spacer = !isEmpty(inputDescription) ? <InputSpacer /> : <div />;
if (!noErrorsDescription && !isEmpty(this.state.errors)) {
spacer = <div />;
}
return (
<div
className={cn(!isEmpty(className) && className)}
style={{
marginBottom: '1.5rem',
fontSize: '1.3rem',
fontFamily: 'Lato',
}}
<Error
inputError={inputError}
name={name}
type="text"
validations={validations}
>
<Label
className={labelClassName}
htmlFor={name}
message={label}
style={labelStyle}
/>
<InputJSON
autoFocus={autoFocus}
className={inputClassName}
disabled={disabled}
deactivateErrorHighlight={deactivateErrorHighlight}
name={name}
onBlur={handleBlur}
onChange={this.handleChange}
placeholder={placeholder}
resetProps={resetProps}
style={inputStyle}
tabIndex={tabIndex}
value={value}
/>
<InputDescription
className={inputDescriptionClassName}
message={inputDescription}
style={{ marginTop: '2.9rem' }}
/>
<InputErrors
className={errorsClassName}
errors={(!noErrorsDescription && this.state.errors) || []}
name={name}
style={errorsStyle}
/>
{spacer}
</div>
{({ canCheck, onBlur, error, dispatch }) => {
const hasError = error && error !== null;
return (
<Wrapper
className={`${cn(!isEmpty(className) && className)} ${
hasError ? 'bordered' : ''
}`}
>
<Label htmlFor={name}>{label}</Label>
<InputJSON
{...rest}
autoFocus={autoFocus}
className={inputClassName}
disabled={disabled}
deactivateErrorHighlight={deactivateErrorHighlight}
name={name}
onBlur={isFunction(handleBlur) ? handleBlur : onBlur}
onChange={e => {
if (!canCheck) {
dispatch({
type: 'SET_CHECK',
});
}
dispatch({
type: 'SET_ERROR',
error: null,
});
this.handleChange(e);
}}
placeholder={placeholder}
resetProps={resetProps}
style={inputStyle}
tabIndex={tabIndex}
value={value}
/>
{!hasError && inputDescription && (
<Description>{inputDescription}</Description>
)}
{hasError && <ErrorMessage>{error}</ErrorMessage>}
</Wrapper>
);
}}
</Error>
);
}
}
@ -158,17 +106,13 @@ InputJSONWithErrors.defaultProps = {
deactivateErrorHighlight: false,
didCheckErrors: false,
disabled: false,
errors: [],
errorsClassName: '',
errorsStyle: {},
error: null,
inputClassName: '',
inputDescription: '',
inputDescriptionClassName: '',
inputStyle: {},
label: '',
labelClassName: '',
labelStyle: {},
noErrorsDescription: false,
onBlur: false,
placeholder: '',
resetProps: false,
@ -183,9 +127,7 @@ InputJSONWithErrors.propTypes = {
deactivateErrorHighlight: PropTypes.bool,
didCheckErrors: PropTypes.bool,
disabled: PropTypes.bool,
errors: PropTypes.array,
errorsClassName: PropTypes.string,
errorsStyle: PropTypes.object,
error: PropTypes.string,
inputClassName: PropTypes.string,
inputDescription: PropTypes.oneOfType([
PropTypes.string,
@ -195,7 +137,6 @@ InputJSONWithErrors.propTypes = {
params: PropTypes.object,
}),
]),
inputDescriptionClassName: PropTypes.string,
inputStyle: PropTypes.object,
label: PropTypes.oneOfType([
PropTypes.string,
@ -208,7 +149,6 @@ InputJSONWithErrors.propTypes = {
labelClassName: PropTypes.string,
labelStyle: PropTypes.object,
name: PropTypes.string.isRequired,
noErrorsDescription: PropTypes.bool,
onBlur: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),
onChange: PropTypes.func.isRequired,
placeholder: PropTypes.string,