mirror of
https://github.com/kingomarnajjar/flex-template-web.git
synced 2026-07-28 20:53:24 +10:00
One image is required. Show validation msg.
This commit is contained in:
parent
f97e9f5a89
commit
447943b1bf
5 changed files with 54 additions and 42 deletions
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
.imagesContainer {
|
||||
width: 100%;
|
||||
min-height: 150px;
|
||||
min-height: 110px;
|
||||
}
|
||||
|
||||
.addImageWrapper {
|
||||
|
|
@ -59,3 +59,12 @@
|
|||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.imageRequiredWrapper {
|
||||
width: 100%;
|
||||
clear: both;
|
||||
}
|
||||
.imageRequiredError {
|
||||
composes: error;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import React, { Component, PropTypes } from 'react';
|
|||
import { Field, reduxForm, propTypes as formPropTypes } from 'redux-form';
|
||||
import { intlShape, injectIntl } from 'react-intl';
|
||||
import { isEqual } from 'lodash';
|
||||
import { maxLength, required } from '../../util/validators';
|
||||
import { noEmptyArray, maxLength, required } from '../../util/validators';
|
||||
import { Promised } from '../../components';
|
||||
import css from './EditListingForm.css';
|
||||
|
||||
|
|
@ -57,17 +57,13 @@ RenderField.propTypes = {
|
|||
|
||||
// Add image wrapper. Label is the only visible element, file input is hidden.
|
||||
const RenderAddImage = props => {
|
||||
const { accept, input, label, type, meta } = props;
|
||||
const { accept, input, label, type } = props;
|
||||
const { name, onChange } = input;
|
||||
const { touched, warning } = meta;
|
||||
const inputProps = { accept, id: name, name, onChange, type };
|
||||
return (
|
||||
<div className={css.addImageWrapper}>
|
||||
<input {...inputProps} style={{ display: 'none' }} />
|
||||
<div>
|
||||
<label htmlFor={name} className={css.addImage}>{label}</label>
|
||||
{touched && warning ? <span className={css.warning}>{warning}</span> : null}
|
||||
</div>
|
||||
<label htmlFor={name} className={css.addImage}>{label}</label>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
@ -81,10 +77,6 @@ RenderAddImage.propTypes = {
|
|||
}).isRequired,
|
||||
label: string.isRequired,
|
||||
type: string.isRequired,
|
||||
meta: shape({
|
||||
touched: bool,
|
||||
warning: string,
|
||||
}).isRequired,
|
||||
};
|
||||
|
||||
class EditListingForm extends Component {
|
||||
|
|
@ -134,6 +126,7 @@ class EditListingForm extends Component {
|
|||
},
|
||||
);
|
||||
const maxLength60 = maxLength(maxLengthStr, TITLE_MAX_LENGTH);
|
||||
const imageRequiredStr = intl.formatMessage({ id: 'EditListingForm.imageRequired' });
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit}>
|
||||
|
|
@ -159,11 +152,7 @@ class EditListingForm extends Component {
|
|||
renderFulfilled={dataURL => {
|
||||
return (
|
||||
<div className={css.thumbnail}>
|
||||
<img
|
||||
src={dataURL}
|
||||
alt={encodeURIComponent(i.file.name)}
|
||||
className={css.thumbnailImage}
|
||||
/>
|
||||
<img src={dataURL} alt={i.file.name} className={css.thumbnailImage} />
|
||||
{uploadingOverlay}
|
||||
</div>
|
||||
);
|
||||
|
|
@ -180,16 +169,24 @@ class EditListingForm extends Component {
|
|||
onChange={this.onImageUploadHandler}
|
||||
type="file"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Field
|
||||
component={props => {
|
||||
const { input, type } = props;
|
||||
return <input {...input} type={type} />;
|
||||
}}
|
||||
name="images"
|
||||
type="hidden"
|
||||
/>
|
||||
<Field
|
||||
component={props => {
|
||||
const { input, type, meta: { error, touched } } = props;
|
||||
return (
|
||||
<div className={css.imageRequiredWrapper}>
|
||||
<input {...input} type={type} />
|
||||
{touched && error
|
||||
? <span className={css.imageRequiredError}>{error}</span>
|
||||
: null}
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
name="images"
|
||||
type="hidden"
|
||||
validate={[noEmptyArray(imageRequiredStr)]}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Field
|
||||
name="description"
|
||||
|
|
|
|||
|
|
@ -37,24 +37,25 @@ exports[`EditListingForm matches snapshot 1`] = `
|
|||
}
|
||||
}
|
||||
type="file" />
|
||||
<div>
|
||||
<label
|
||||
className={undefined}
|
||||
htmlFor="addImage">
|
||||
+ Add image
|
||||
</label>
|
||||
</div>
|
||||
<label
|
||||
className={undefined}
|
||||
htmlFor="addImage">
|
||||
+ Add image
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
className={undefined}>
|
||||
<input
|
||||
name="images"
|
||||
onBlur={[Function]}
|
||||
onChange={[Function]}
|
||||
onDragStart={[Function]}
|
||||
onDrop={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="hidden"
|
||||
value="" />
|
||||
</div>
|
||||
</div>
|
||||
<input
|
||||
name="images"
|
||||
onBlur={[Function]}
|
||||
onChange={[Function]}
|
||||
onDragStart={[Function]}
|
||||
onDrop={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="hidden"
|
||||
value="" />
|
||||
<div>
|
||||
<label
|
||||
htmlFor="description">
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
"HeroSection.subTitle": "The largest online community to rent music studios",
|
||||
"HeroSection.title": "Book Studiotime anywhere",
|
||||
"EditListingForm.required": "Required",
|
||||
"EditListingForm.imageRequired": "You need to add at least one image.",
|
||||
"EditListingForm.maxLength": "Must be {maxLength} characters or less",
|
||||
"ListingPage.loadingListingData": "Loading listing data",
|
||||
"ListingPage.noListingData": "Could not find listing data",
|
||||
|
|
|
|||
|
|
@ -14,3 +14,7 @@ export const maxLength = (message, maximumLength) =>
|
|||
value => {
|
||||
return !value || value.length <= maximumLength ? VALID : message;
|
||||
};
|
||||
|
||||
export const noEmptyArray = message => value => {
|
||||
return value && Array.isArray(value) && value.length > 0 ? VALID : message;
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue