Remove EditListingForm

This commit is contained in:
Vesa Luusua 2017-05-11 15:37:48 +03:00
parent 9ea6dc42e9
commit 5561a42568
8 changed files with 0 additions and 446 deletions

View file

@ -1,41 +0,0 @@
.addImageWrapper {
float: left;
width: 110px;
height: 110px;
margin: 5px;
&::after {
content: ".";
visibility: hidden;
display: block;
height: 0;
clear: both;
}
}
.addImage {
width: 110px;
height: 110px;
background-color: lightgrey;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
margin-top: 0;
}
.addImageInput {
display: none;
}
.imageRequiredWrapper {
width: 100%;
clear: both;
}
.imageRequiredError {
color: red;
}
.submitButton {
margin-top: 1rem;
}

View file

@ -1,18 +0,0 @@
/* eslint-disable no-console */
import EditListingForm from './EditListingForm';
export const Empty = {
component: EditListingForm,
props: {
stripeConnected: false,
onImageUpload: values => {
console.log(`onImageUpload with id (${values.id}) and file name (${values.file.name})`);
},
onSubmit: values => {
console.log('Submit EditListingForm with (unformatted) values:', values);
},
onUpdateImageOrder: imageOrder => {
console.log('onUpdateImageOrder with new imageOrder:', imageOrder);
},
},
};

View file

@ -1,258 +0,0 @@
import React, { Component, PropTypes } from 'react';
import { compose } from 'redux';
import { connect } from 'react-redux';
import { Field, reduxForm, formValueSelector, propTypes as formPropTypes } from 'redux-form';
import { intlShape, injectIntl } from 'react-intl';
import { isEqual } from 'lodash';
import { arrayMove } from 'react-sortable-hoc';
import config from '../../config';
import * as propTypes from '../../util/propTypes';
import { enhancedField } from '../../util/forms';
import {
noEmptyArray,
maxLength,
required,
autocompleteSearchRequired,
autocompletePlaceSelected,
} from '../../util/validators';
import {
AddImages,
CurrencyInput,
LocationAutocompleteInput,
Button,
Input,
StripeBankAccountToken,
} from '../../components';
import css from './EditListingForm.css';
const ACCEPT_IMAGES = 'image/*';
const TITLE_MAX_LENGTH = 60;
const { bool, func, object, shape, string } = PropTypes;
// Add image wrapper. Label is the only visible element, file input is hidden.
const RenderAddImage = props => {
const { accept, input, label, type } = props;
const { name, onChange } = input;
const inputProps = { accept, id: name, name, onChange, type };
return (
<div className={css.addImageWrapper}>
<Input {...inputProps} className={css.addImageInput} />
<label htmlFor={name} className={css.addImage}>{label}</label>
</div>
);
};
RenderAddImage.propTypes = {
accept: string.isRequired,
input: shape({
value: object,
onChange: func.isRequired,
name: string.isRequired,
}).isRequired,
label: string.isRequired,
type: string.isRequired,
};
export class EditListingFormComponent extends Component {
constructor(props) {
super(props);
this.handleInitialize = this.handleInitialize.bind(this);
this.onImageUploadHandler = this.onImageUploadHandler.bind(this);
this.onSortEnd = this.onSortEnd.bind(this);
// We must create the enhanced components outside the render function
// to avoid losing focus.
// See: https://github.com/erikras/redux-form/releases/tag/v6.0.0-alpha.14
this.EnhancedInput = enhancedField('input');
this.EnhancedTextArea = enhancedField('textarea');
this.EnhancedCurrencyInput = enhancedField(CurrencyInput);
this.EnhancedLocationAutocompleteInput = enhancedField(LocationAutocompleteInput);
}
componentDidMount() {
this.handleInitialize();
}
componentWillReceiveProps(nextProps) {
if (!isEqual(this.props.images, nextProps.images)) {
nextProps.change('images', nextProps.images);
}
}
onImageUploadHandler(event) {
const file = event.target.files[0];
if (file) {
this.props.onImageUpload({ id: `${file.name}_${Date.now()}`, file });
}
}
onSortEnd({ oldIndex, newIndex }) {
const images = arrayMove(this.props.images, oldIndex, newIndex);
this.props.onUpdateImageOrder(images.map(i => i.id));
}
handleInitialize() {
const { initData = {}, initialize } = this.props;
initialize(initData);
}
render() {
const {
disabled,
handleSubmit,
images,
intl,
pristine,
saveActionMsg = 'Save listing',
submitting,
selectedPlace,
stripeConnected,
} = this.props;
const titleRequiredMessage = intl.formatMessage({ id: 'EditListingForm.titleRequired' });
const maxLengthMessage = intl.formatMessage(
{ id: 'EditListingForm.maxLength' },
{
maxLength: TITLE_MAX_LENGTH,
}
);
const maxLength60Message = maxLength(maxLengthMessage, TITLE_MAX_LENGTH);
const priceRequiredMessage = intl.formatMessage({ id: 'EditListingForm.priceRequired' });
const imageRequiredMessage = intl.formatMessage({ id: 'EditListingForm.imageRequired' });
const locationRequiredMessage = intl.formatMessage({
id: 'EditListingForm.locationRequired',
});
const locationNotRecognizedMessage = intl.formatMessage({
id: 'EditListingForm.locationNotRecognized',
});
const bankAccountNumberRequiredMessage = intl.formatMessage({
id: 'EditListingForm.bankAccountNumberRequired',
});
const descriptionRequiredMessage = intl.formatMessage({
id: 'EditListingForm.descriptionRequired',
});
const pricePlaceholderMessage = intl.formatMessage({ id: 'EditListingForm.pricePlaceholder' });
const country = selectedPlace ? selectedPlace.country : null;
const showBankAccountField = !stripeConnected && country;
const currency = config.currencyConfig.currency;
return (
<form onSubmit={handleSubmit}>
<Field
name="title"
label="Title"
placeholder="Title"
component={this.EnhancedInput}
type="text"
validate={[required(titleRequiredMessage), maxLength60Message]}
/>
<Field
name="price"
label="Price"
component={this.EnhancedCurrencyInput}
currencyConfig={config.currencyConfig}
validate={[required(priceRequiredMessage)]}
placeholder={pricePlaceholderMessage}
/>
<h3>Images</h3>
<AddImages images={images} onSortEnd={this.onSortEnd}>
<Field
accept={ACCEPT_IMAGES}
component={RenderAddImage}
label="+ Add image"
name="addImage"
onChange={this.onImageUploadHandler}
type="file"
/>
<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(imageRequiredMessage)]}
/>
</AddImages>
<Field
name="location"
label="Location"
format={null}
component={this.EnhancedLocationAutocompleteInput}
validate={[
autocompleteSearchRequired(locationRequiredMessage),
autocompletePlaceSelected(locationNotRecognizedMessage),
]}
/>
<Field
name="description"
label="Description"
placeholder="Description"
component={this.EnhancedTextArea}
validate={[required(descriptionRequiredMessage)]}
/>
{showBankAccountField
? <Field
name="bankAccountToken"
component={StripeBankAccountToken}
props={{ country, currency }}
validate={required(bankAccountNumberRequiredMessage)}
/>
: null}
<Button
className={css.submitButton}
type="submit"
disabled={pristine || submitting || disabled}
>
{saveActionMsg}
</Button>
</form>
);
}
}
EditListingFormComponent.defaultProps = { initData: {}, selectedPlace: null };
EditListingFormComponent.propTypes = {
...formPropTypes,
initData: shape({ title: string, description: string }),
selectedPlace: propTypes.place,
stripeConnected: bool.isRequired,
intl: intlShape.isRequired,
onImageUpload: func.isRequired,
onUpdateImageOrder: func.isRequired,
onSubmit: func.isRequired,
};
const formName = 'EditListingForm';
// When a field depends on the value of another field, we must connect
// to the store and select the required values to inject to the
// component.
//
// See: http://redux-form.com/6.6.1/examples/selectingFormValues/
const selector = formValueSelector(formName);
const mapStateToProps = state => {
const location = selector(state, 'location');
return {
selectedPlace: location && location.selectedPlace ? location.selectedPlace : null,
};
};
export default compose(connect(mapStateToProps), reduxForm({ form: formName }), injectIntl)(
EditListingFormComponent
);

View file

@ -1,27 +0,0 @@
// TODO: renderdeep doesn't work due to
// "Invariant Violation: getNodeFromInstance: Invalid argument."
// refs and findDOMNode are not supported by react-test-renderer
// (react-sortable-hoc uses them)
import React from 'react';
import { renderShallow } from '../../util/test-helpers';
import { fakeIntl, fakeFormProps } from '../../util/test-data';
import { EditListingFormComponent } from './EditListingForm';
const noop = () => null;
describe('EditListingForm', () => {
it('matches snapshot', () => {
const tree = renderShallow(
<EditListingFormComponent
{...fakeFormProps}
intl={fakeIntl}
dispatch={noop}
onImageUpload={v => v}
onSubmit={v => v}
onUpdateImageOrder={v => v}
stripeConnected={false}
/>
);
expect(tree).toMatchSnapshot();
});
});

View file

@ -1,89 +0,0 @@
exports[`EditListingForm matches snapshot 1`] = `
<form
onSubmit={[Function]}>
<Field
component={[Function]}
label="Title"
name="title"
placeholder="Title"
type="text"
validate={
Array [
[Function],
[Function],
]
} />
<Field
component={[Function]}
currencyConfig={
Object {
"currency": "USD",
"currencyDisplay": "symbol",
"maximumFractionDigits": 2,
"minimumFractionDigits": 2,
"style": "currency",
"subUnitDivisor": 100,
"useGrouping": true,
}
}
label="Price"
name="price"
placeholder="EditListingForm.pricePlaceholder"
validate={
Array [
[Function],
]
} />
<h3>
Images
</h3>
<AddImages
images={Array []}
onSortEnd={[Function]}>
<Field
accept="image/*"
component={[Function]}
label="+ Add image"
name="addImage"
onChange={[Function]}
type="file" />
<Field
component={[Function]}
name="images"
type="hidden"
validate={
Array [
[Function],
]
} />
</AddImages>
<Field
component={[Function]}
format={null}
label="Location"
name="location"
validate={
Array [
[Function],
[Function],
]
} />
<Field
component={[Function]}
label="Description"
name="description"
placeholder="Description"
validate={
Array [
[Function],
]
} />
<Button
className={null}
disabled={true}
rootClassName=""
type="submit">
Save listing
</Button>
</form>
`;

View file

@ -4,7 +4,6 @@ import ChangeAccountPasswordForm from './ChangeAccountPasswordForm/ChangeAccount
import ChangePasswordForm from './ChangePasswordForm/ChangePasswordForm';
import CheckoutPage from './CheckoutPage/CheckoutPage';
import ContactDetailsPage from './ContactDetailsPage/ContactDetailsPage';
import EditListingForm from './EditListingForm/EditListingForm';
import EditListingPage from './EditListingPage/EditListingPage';
import EditProfilePage from './EditProfilePage/EditProfilePage';
import SearchForm from './SearchForm/SearchForm';
@ -35,7 +34,6 @@ export {
ChangePasswordForm,
CheckoutPage,
ContactDetailsPage,
EditListingForm,
EditListingPage,
EditProfilePage,
SearchForm,

View file

@ -23,7 +23,6 @@ import * as BookingDatesForm from './containers/BookingDatesForm/BookingDatesFor
import * as ChangeAccountPasswordForm
from './containers/ChangeAccountPasswordForm/ChangeAccountPasswordForm.example';
import * as ChangePasswordForm from './containers/ChangePasswordForm/ChangePasswordForm.example';
import * as EditListingForm from './containers/EditListingForm/EditListingForm.example';
import * as SearchForm from './containers/SearchForm/SearchForm.example';
import * as LoginForm from './containers/LoginForm/LoginForm.example';
import * as PasswordForgottenForm
@ -40,7 +39,6 @@ export {
ChangePasswordForm,
CurrencyInput,
DateInput,
EditListingForm,
EditListingWizard,
ListingCard,
LocationAutocompleteInput,

View file

@ -31,15 +31,6 @@
"DateInput.closeDatePicker": "Close",
"DateInput.defaultPlaceholder": "Date input",
"DateInput.screenReaderInputMessage": "Date input",
"EditListingForm.bankAccountNumberRequired": "You need to add a bank account number.",
"EditListingForm.descriptionRequired": "You need to add a description.",
"EditListingForm.imageRequired": "You need to add at least one image.",
"EditListingForm.locationNotRecognized": "We didn't recognize this location. Please try another location.",
"EditListingForm.locationRequired": "You need to provide a location",
"EditListingForm.maxLength": "Must be {maxLength} characters or less",
"EditListingForm.pricePlaceholder": "$0.00",
"EditListingForm.priceRequired": "You need to add a valid price.",
"EditListingForm.titleRequired": "You need to add a title.",
"EditListingPage.titleCreateListing": "Create a listing",
"EditListingPage.titleEditListing": "Edit listing",
"HeroSection.subTitle": "The largest online community to rent music studios",