Merge pull request #1173 from sharetribe/update-final-form

Update Final Form et al.
This commit is contained in:
Vesa Luusua 2019-08-27 15:21:16 +03:00 committed by GitHub
commit dbfb5141a4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
33 changed files with 144 additions and 100 deletions

View file

@ -14,6 +14,19 @@ way to update this template, but currently, we follow a pattern:
## Upcoming version 2019-XX-XX
- [change] Update final-form, final-form-arrays, react-final-form and react-final-form-arrays. This
forced to make some code changes:
- Old recommendation of by-passing default field formatting or parsin isn't accepted anymore
- `format={null}` => use identity function instead: `format={v => v}`
- `parse={null}` => use identity function instead: `parse={v => v}`
- Final Form passes input props (name, value, onChange, onBlur, etc. ) grouped inside input key
- those props now include `type` attribute too.
- We had old form naming pattern with prop 'form', which now conflicted with updated Final Form
(The 'form' prop was used when Redux-Form was the form library)
[#1173](https://github.com/sharetribe/flex-template-web/pull/1173)
- [change] Update `react-dates` from v18.5.0 ti v20.3.0
[#1171](https://github.com/sharetribe/flex-template-web/pull/1171)
- [change] Update Prettier to v1.18.2

View file

@ -22,8 +22,8 @@
"express": "^4.16.4",
"express-enforces-ssl": "^1.1.0",
"express-sitemap": "^1.8.0",
"final-form": "^4.11.0",
"final-form-arrays": "^1.1.0",
"final-form": "^4.18.5",
"final-form-arrays": "^3.0.0",
"helmet": "^3.18.0",
"lodash": "^4.17.14",
"mapbox-gl-multitouch": "^1.0.3",
@ -37,8 +37,8 @@
"react": "^16.8.6",
"react-dates": "^20.3.0",
"react-dom": "^16.8.6",
"react-final-form": "^4.0.2",
"react-final-form-arrays": "^2.0.1",
"react-final-form": "^6.3.0",
"react-final-form-arrays": "^3.1.1",
"react-google-maps": "^9.4.5",
"react-helmet": "^5.2.0",
"react-intl": "^2.9.0",

View file

@ -118,6 +118,7 @@ const BookingPanel = props => {
{showBookingDatesForm ? (
<BookingDatesForm
className={css.bookingForm}
formId="BookingPanel"
submitButtonWrapperClassName={css.bookingDatesSubmitButtonWrapper}
unitType={unitType}
onSubmit={onSubmit}

View file

@ -303,6 +303,7 @@ EditListingWizard.defaultProps = {
className: null,
rootClassName: null,
listing: null,
updateInProgress: false,
};
EditListingWizard.propTypes = {
@ -340,6 +341,7 @@ EditListingWizard.propTypes = {
onPayoutDetailsFormChange: func.isRequired,
onPayoutDetailsSubmit: func.isRequired,
onManageDisableScrolling: func.isRequired,
updateInProgress: bool,
// from withViewport
viewport: shape({

View file

@ -4,6 +4,8 @@ import { Form as FinalForm, FormSpy } from 'react-final-form';
import * as validators from '../../util/validators';
import FieldBirthdayInput from './FieldBirthdayInput';
const identity = v => v;
const FormComponent = props => (
<FinalForm
{...props}
@ -25,7 +27,7 @@ const FormComponent = props => (
id={`birthday`}
name="birthday"
label="Date of birth"
format={null}
format={identity}
valueFromForm={values.birthDate}
validate={validators.composeValidators(required, minAgeRequired)}
/>
@ -41,7 +43,7 @@ export const Empty = {
onChange: formState => {
const birthday = formState.values.birthday;
if (birthday) {
console.log('birthday changed to:', birthday.toUTCString());
console.log('birthday changed to:', birthday);
}
},
onSubmit: values => {

View file

@ -9,7 +9,7 @@ const formName = 'Styleguide.FieldBoolean.Form';
const FormComponent = props => (
<FinalForm
{...props}
form={formName}
formId={formName}
render={fieldRenderProps => {
const { form, handleSubmit, onChange, invalid, pristine, submitting } = props;
const required = validators.requiredBoolean('This field is required');

View file

@ -8,7 +8,7 @@ const formName = 'Styleguide.FieldCheckbox.Form';
const FormComponent = props => (
<FinalForm
{...props}
form={formName}
formId={formName}
render={fieldRenderProps => {
const { form, handleSubmit, onChange, invalid, pristine, submitting } = fieldRenderProps;

View file

@ -7,6 +7,8 @@ import { required, bookingDateRequired, composeValidators } from '../../util/val
import { createTimeSlots } from '../../util/test-data';
import FieldDateInput from './FieldDateInput';
const identity = v => v;
const createAvailableTimeSlots = (dayCount, availableDayCount) => {
const slots = createTimeSlots(new Date(), dayCount);
const availableSlotIndices = Array.from({ length: availableDayCount }, () =>
@ -64,7 +66,7 @@ export const Empty = {
id: `EmptyDateInputForm.bookingDate`,
label: 'Date',
placeholderText: moment().format('ddd, MMMM D'),
format: null,
format: identity,
validate: composeValidators(required('Required'), bookingDateRequired('Date is not valid')),
onBlur: () => console.log('onBlur called from DateInput props.'),
onFocus: () => console.log('onFocus called from DateInput props.'),
@ -91,7 +93,7 @@ export const WithAvailableTimeSlots = {
id: `AvailableTimeSlotsDateInputForm.bookingDate`,
label: 'Date',
placeholderText: moment().format('ddd, MMMM D'),
format: null,
format: identity,
timeSlots: createAvailableTimeSlots(90, 60),
validate: composeValidators(required('Required'), bookingDateRequired('Date is not valid')),
onBlur: () => console.log('onBlur called from DateInput props.'),

View file

@ -47,7 +47,7 @@ class FieldDateInputComponent extends Component {
[css.pickerError]: hasError,
});
const { onBlur, onFocus, ...restOfInput } = input;
const { onBlur, onFocus, type, ...restOfInput } = input;
const inputProps = {
onBlur: input.onBlur,
onFocus: input.onFocus,

View file

@ -5,7 +5,8 @@ import DateRangeController from './DateRangeController';
const component = props => {
const { input, controllerRef, ...rest } = props;
return <DateRangeController ref={controllerRef} {...input} {...rest} />;
const { type, ...restOfInput } = input;
return <DateRangeController ref={controllerRef} {...restOfInput} {...rest} />;
};
const FieldDateRangeController = props => {

View file

@ -8,6 +8,8 @@ import { LINE_ITEM_NIGHT, LINE_ITEM_DAY } from '../../util/types';
import { createTimeSlots } from '../../util/test-data';
import FieldDateRangeInput from './FieldDateRangeInput';
const identity = v => v;
const createAvailableTimeSlots = (dayCount, availableDayCount) => {
const slots = createTimeSlots(new Date(), dayCount);
@ -70,7 +72,7 @@ export const Empty = {
endDatePlaceholderText: moment()
.add(1, 'days')
.format('ddd, MMMM D'),
format: null,
format: identity,
validate: composeValidators(
required('Required'),
bookingDatesRequired('Start date is not valid', 'End date is not valid')
@ -101,12 +103,12 @@ export const WithAvailableTimeSlotsNighlyBooking = {
startDateId: 'WithAvailableTimeSlotsDateRangeNightly.bookingStartDate',
startDateLabel: 'Start date',
startDatePlaceholderText: moment().format('ddd, MMMM D'),
endDateId: 'WithAvailableTimeSlotsDateRangeInputForm.bookingEndDate',
endDateId: 'WithAvailableTimeSlotsDateRangeNightly.bookingEndDate',
endDateLabel: 'End date',
endDatePlaceholderText: moment()
.add(1, 'days')
.format('ddd, MMMM D'),
format: null,
format: identity,
timeSlots: createAvailableTimeSlots(90, 60),
validate: composeValidators(
required('Required'),
@ -137,12 +139,12 @@ export const WithAvailableTimeSlotsDailyBooking = {
startDateId: 'WithAvailableTimeSlotsDateRangeDaily.bookingStartDate',
startDateLabel: 'Start date',
startDatePlaceholderText: moment().format('ddd, MMMM D'),
endDateId: 'WithAvailableTimeSlotsDateRangeInputForm.bookingEndDate',
endDateId: 'WithAvailableTimeSlotsDateRangeDaily.bookingEndDate',
endDateLabel: 'End date',
endDatePlaceholderText: moment()
.add(1, 'days')
.format('ddd, MMMM D'),
format: null,
format: identity,
timeSlots: createAvailableTimeSlots(90, 60),
validate: composeValidators(
required('Required'),

View file

@ -117,7 +117,7 @@ class FieldDateRangeInputComponent extends Component {
) : null;
// eslint-disable-next-line no-unused-vars
const { onBlur, onFocus, ...restOfInput } = input;
const { onBlur, onFocus, type, ...restOfInput } = input;
const inputProps = {
unitType,
onBlur: this.handleBlur,

View file

@ -4,12 +4,9 @@ import * as validators from '../../util/validators';
import { Button } from '../../components';
import FieldPhoneNumberInput from './FieldPhoneNumberInput';
const formName = 'Styleguide.FieldPhoneNumberInput.Form';
const FormComponent = props => (
<FinalForm
{...props}
form={formName}
render={fieldRenderProps => {
const { formId, handleSubmit, onChange, invalid, pristine, submitting } = fieldRenderProps;
const required = validators.required('This field is required');
@ -41,7 +38,7 @@ const FormComponent = props => (
export const PhoneNumber = {
component: FormComponent,
props: {
formId: 'PhoneNumberExample',
formId: 'Styleguide.FieldPhoneNumberInput.Form',
onChange: formState => {
if (formState.dirty) {
console.log('form values changed to:', formState.values);

View file

@ -2,12 +2,10 @@ import React from 'react';
import { Form as FinalForm, FormSpy } from 'react-final-form';
import { Button } from '..';
import FieldRadioButton from './FieldRadioButton';
const formName = 'Styleguide.FieldRadioButton.Form';
const FormComponent = props => (
<FinalForm
{...props}
form={formName}
render={fieldRenderProps => {
const {
handleSubmit,

View file

@ -10,9 +10,9 @@ const formName = 'Styleguide.FieldReviewRating.Form';
const FormComponent = props => (
<FinalForm
{...props}
form={formName}
formId={formName}
render={fieldRenderProps => {
const { form, handleSubmit, onChange, invalid, pristine, submitting } = fieldRenderProps;
const { formId, handleSubmit, onChange, invalid, pristine, submitting } = fieldRenderProps;
const required = validators.required('This field is required');
const submitDisabled = invalid || pristine || submitting;
@ -25,7 +25,7 @@ const FormComponent = props => (
>
<FormSpy onChange={onChange} />
<FieldReviewRating
id={`${form}.rate1`}
id={`${formId}.rate1`}
name="rating"
label="Rate your experience"
validate={required}

View file

@ -18,7 +18,6 @@ class FieldTextInputComponent extends Component {
customErrorText,
id,
label,
type,
input,
meta,
onUnmount,
@ -33,7 +32,7 @@ class FieldTextInputComponent extends Component {
}
const { valid, invalid, touched, error } = meta;
const isTextarea = type === 'textarea';
const isTextarea = input.type === 'textarea';
const errorText = customErrorText || error;
@ -43,6 +42,8 @@ class FieldTextInputComponent extends Component {
const fieldMeta = { touched: hasError, error: errorText };
// Textarea doesn't need type.
const { type, ...inputWithoutType } = input;
// Uncontrolled input uses defaultValue instead of value.
const { value: defaultValue, ...inputWithoutValue } = input;
// Use inputRef if it is passed as prop.
@ -57,7 +58,15 @@ class FieldTextInputComponent extends Component {
});
const maxLength = CONTENT_MAX_LENGTH;
const inputProps = isTextarea
? { className: inputClasses, id, rows: 1, maxLength, ...refMaybe, ...input, ...rest }
? {
className: inputClasses,
id,
rows: 1,
maxLength,
...refMaybe,
...inputWithoutType,
...rest,
}
: isUncontrolled
? {
className: inputClasses,
@ -109,9 +118,6 @@ FieldTextInputComponent.propTypes = {
id: string,
label: string,
// Either 'textarea' or something that is passed to the input element
type: string.isRequired,
// Uncontrolled input uses defaultValue prop, but doesn't pass value from form to the field.
// https://reactjs.org/docs/uncontrolled-components.html#default-values
isUncontrolled: bool,
@ -121,6 +127,8 @@ FieldTextInputComponent.propTypes = {
// Generated by final-form's Field component
input: shape({
onChange: func.isRequired,
// Either 'textarea' or something that is passed to the input element
type: string.isRequired,
}).isRequired,
meta: object.isRequired,
};

View file

@ -4,6 +4,8 @@ import { propTypes } from '../../util/types';
import { Button } from '../../components';
import LocationAutocompleteInput from './LocationAutocompleteInput';
const identity = v => v;
const Form = props => {
return (
<FinalForm
@ -12,7 +14,7 @@ const Form = props => {
return (
<form onSubmit={handleSubmit}>
<label htmlFor="location">Select location:</label>
<Field name="location" format={null} component={LocationAutocompleteInput} />
<Field name="location" format={identity} component={LocationAutocompleteInput} />
<Button type="submit" style={{ marginTop: '24px' }} disabled={pristine}>
Submit
</Button>

View file

@ -244,7 +244,6 @@ class TopbarComponent extends Component {
>
<div className={css.searchContainer}>
<TopbarSearchForm
form="TopbarSearchForm"
onSubmit={this.handleSubmit}
initialValues={initialSearchFormValues}
isMobile

View file

@ -47,7 +47,6 @@ const TopbarDesktop = props => {
<TopbarSearchForm
className={css.searchLink}
desktopInputRoot={css.topbarSearchWithLeftPadding}
form="TopbarSearchFormDesktop"
onSubmit={onSearchSubmit}
initialValues={initialSearchFormValues}
/>

View file

@ -395,7 +395,7 @@ export class TransactionPanelComponent extends Component {
/>
{showSendMessageForm ? (
<SendMessageForm
form={this.sendMessageFormName}
formId={this.sendMessageFormName}
rootClassName={css.sendMessageForm}
messagePlaceholder={sendMessagePlaceholder}
inProgress={sendMessageInProgress}

View file

@ -509,7 +509,7 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor i
totalMessagePages={1}
/>
<SendMessageForm
form="TransactionPanel.SendMessageForm"
formId="TransactionPanel.SendMessageForm"
inProgress={false}
messagePlaceholder="TransactionPanel.sendMessagePlaceholder"
onBlur={[Function]}
@ -1266,7 +1266,7 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor i
totalMessagePages={1}
/>
<SendMessageForm
form="TransactionPanel.SendMessageForm"
formId="TransactionPanel.SendMessageForm"
inProgress={false}
messagePlaceholder="TransactionPanel.sendMessagePlaceholder"
onBlur={[Function]}
@ -2023,7 +2023,7 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor i
totalMessagePages={1}
/>
<SendMessageForm
form="TransactionPanel.SendMessageForm"
formId="TransactionPanel.SendMessageForm"
inProgress={false}
messagePlaceholder="TransactionPanel.sendMessagePlaceholder"
onBlur={[Function]}
@ -2780,7 +2780,7 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor i
totalMessagePages={1}
/>
<SendMessageForm
form="TransactionPanel.SendMessageForm"
formId="TransactionPanel.SendMessageForm"
inProgress={false}
messagePlaceholder="TransactionPanel.sendMessagePlaceholder"
onBlur={[Function]}
@ -3547,7 +3547,7 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor i
totalMessagePages={1}
/>
<SendMessageForm
form="TransactionPanel.SendMessageForm"
formId="TransactionPanel.SendMessageForm"
inProgress={false}
messagePlaceholder="TransactionPanel.sendMessagePlaceholder"
onBlur={[Function]}
@ -4309,7 +4309,7 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor i
totalMessagePages={1}
/>
<SendMessageForm
form="TransactionPanel.SendMessageForm"
formId="TransactionPanel.SendMessageForm"
inProgress={false}
messagePlaceholder="TransactionPanel.sendMessagePlaceholder"
onBlur={[Function]}
@ -5064,7 +5064,7 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor i
totalMessagePages={1}
/>
<SendMessageForm
form="TransactionPanel.SendMessageForm"
formId="TransactionPanel.SendMessageForm"
inProgress={false}
messagePlaceholder="TransactionPanel.sendMessagePlaceholder"
onBlur={[Function]}
@ -5821,7 +5821,7 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor i
totalMessagePages={1}
/>
<SendMessageForm
form="TransactionPanel.SendMessageForm"
formId="TransactionPanel.SendMessageForm"
inProgress={false}
messagePlaceholder="TransactionPanel.sendMessagePlaceholder"
onBlur={[Function]}
@ -6578,7 +6578,7 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor i
totalMessagePages={1}
/>
<SendMessageForm
form="TransactionPanel.SendMessageForm"
formId="TransactionPanel.SendMessageForm"
inProgress={false}
messagePlaceholder="TransactionPanel.sendMessagePlaceholder"
onBlur={[Function]}
@ -7335,7 +7335,7 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor i
totalMessagePages={1}
/>
<SendMessageForm
form="TransactionPanel.SendMessageForm"
formId="TransactionPanel.SendMessageForm"
inProgress={false}
messagePlaceholder="TransactionPanel.sendMessagePlaceholder"
onBlur={[Function]}
@ -8092,7 +8092,7 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor i
totalMessagePages={1}
/>
<SendMessageForm
form="TransactionPanel.SendMessageForm"
formId="TransactionPanel.SendMessageForm"
inProgress={false}
messagePlaceholder="TransactionPanel.sendMessagePlaceholder"
onBlur={[Function]}
@ -8849,7 +8849,7 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor i
totalMessagePages={1}
/>
<SendMessageForm
form="TransactionPanel.SendMessageForm"
formId="TransactionPanel.SendMessageForm"
inProgress={false}
messagePlaceholder="TransactionPanel.sendMessagePlaceholder"
onBlur={[Function]}
@ -9606,7 +9606,7 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor i
totalMessagePages={1}
/>
<SendMessageForm
form="TransactionPanel.SendMessageForm"
formId="TransactionPanel.SendMessageForm"
inProgress={false}
messagePlaceholder="TransactionPanel.sendMessagePlaceholder"
onBlur={[Function]}
@ -10361,7 +10361,7 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor i
totalMessagePages={1}
/>
<SendMessageForm
form="TransactionPanel.SendMessageForm"
formId="TransactionPanel.SendMessageForm"
inProgress={false}
messagePlaceholder="TransactionPanel.sendMessagePlaceholder"
onBlur={[Function]}

View file

@ -208,8 +208,15 @@ export default function reducer(state = initialState, action = {}) {
};
case PUBLISH_LISTING_SUCCESS:
return {
...state,
redirectToListing: true,
publishingListing: null,
createListingDraftError: null,
updateListingError: null,
showListingsError: null,
uploadImageError: null,
createListingDraftInProgress: false,
updateInProgress: false,
};
case PUBLISH_LISTING_ERROR: {
// eslint-disable-next-line no-console

View file

@ -14,6 +14,8 @@ import EstimatedBreakdownMaybe from './EstimatedBreakdownMaybe';
import css from './BookingDatesForm.css';
const identity = v => v;
export class BookingDatesFormComponent extends Component {
constructor(props) {
super(props);
@ -77,7 +79,7 @@ export class BookingDatesFormComponent extends Component {
const {
endDatePlaceholder,
startDatePlaceholder,
form,
formId,
handleSubmit,
intl,
isOwnListing,
@ -159,15 +161,15 @@ export class BookingDatesFormComponent extends Component {
className={css.bookingDates}
name="bookingDates"
unitType={unitType}
startDateId={`${form}.bookingStartDate`}
startDateId={`${formId}.bookingStartDate`}
startDateLabel={bookingStartLabel}
startDatePlaceholderText={startDatePlaceholderText}
endDateId={`${form}.bookingEndDate`}
endDateId={`${formId}.bookingEndDate`}
endDateLabel={bookingEndLabel}
endDatePlaceholderText={endDatePlaceholderText}
focusedInput={this.state.focusedInput}
onFocusedInputChange={this.onFocusedInputChange}
format={null}
format={identity}
timeSlots={timeSlots}
useMobileMargins
validate={composeValidators(

View file

@ -14,6 +14,8 @@ import { Form, LocationAutocompleteInputField, Button, FieldTextInput } from '..
import css from './EditListingLocationForm.css';
const identity = v => v;
export const EditListingLocationFormComponent = props => (
<FinalForm
{...props}
@ -88,7 +90,7 @@ export const EditListingLocationFormComponent = props => (
label={titleRequiredMessage}
placeholder={addressPlaceholderMessage}
useDefaultPredictions={false}
format={null}
format={identity}
valueFromForm={values.location}
validate={composeValidators(
autocompleteSearchRequired(addressRequiredMessage),

View file

@ -159,8 +159,8 @@ export class EditListingPhotosFormComponent extends Component {
disabled={imageUploadRequested}
>
{fieldprops => {
const { accept, input, label, type, disabled } = fieldprops;
const { name } = input;
const { accept, input, label, disabled } = fieldprops;
const { name, type } = input;
const onChange = e => {
const file = e.target.files[0];
form.change(`addImage`, file);
@ -185,10 +185,10 @@ export class EditListingPhotosFormComponent extends Component {
<Field
component={props => {
const { input, type, meta } = props;
const { input, meta } = props;
return (
<div className={css.imageRequiredWrapper}>
<input {...input} type={type} />
<input {...input} />
<ValidationError fieldMeta={meta} />
</div>
);

View file

@ -2,9 +2,9 @@ import React from 'react';
import FilterForm from './FilterForm';
import { FieldTextInput } from '../../components';
const field = (
const field = formId => (
<FieldTextInput
id="field"
id={`${formId}.field`}
name="field"
type="textarea"
label="Field label"
@ -29,7 +29,7 @@ export const FilterFormExample = {
console.log('onClear called');
},
label: 'Example label',
children: field,
children: field('FilterFormExample'),
},
group: 'forms',
};
@ -45,7 +45,7 @@ export const FilterFormExampleLiveEdit = {
console.log(values);
},
label: 'Example label',
children: field,
children: field('FilterFormExampleLiveEdit'),
},
group: 'forms',
};

View file

@ -7,6 +7,8 @@ import { Form, LocationAutocompleteInput } from '../../components';
import css from './LocationSearchForm.css';
const identity = v => v;
const LocationSearchFormComponent = props => {
const handleChange = location => {
if (location.selectedPlace) {
@ -32,7 +34,7 @@ const LocationSearchFormComponent = props => {
<Form className={classes} onSubmit={preventFormSubmit}>
<Field
name="location"
format={null}
format={identity}
render={({ input, meta }) => {
const { onChange, ...restInput } = input;

View file

@ -9,6 +9,8 @@ import css from './PayoutDetailsForm.css';
const MIN_STRIPE_ACCOUNT_AGE = 18;
const identity = v => v;
const PayoutDetailsPersonalDetails = props => {
const {
intl,
@ -246,7 +248,7 @@ const PayoutDetailsPersonalDetails = props => {
label={birthdayLabel}
labelForMonth={birthdayLabelMonth}
labelForYear={birthdayLabelYear}
format={null}
format={identity}
valueFromForm={values.birthDate}
validate={validators.composeValidators(birthdayRequired, birthdayMinAge)}
/>

View file

@ -198,16 +198,8 @@ class ProfileSettingsFormComponent extends Component {
disabled={uploadInProgress}
>
{fieldProps => {
const {
accept,
id,
input,
label,
type,
disabled,
uploadImageError,
} = fieldProps;
const { name } = input;
const { accept, id, input, label, disabled, uploadImageError } = fieldProps;
const { name, type } = input;
const onChange = e => {
const file = e.target.files[0];
form.change(`profileImage`, file);

View file

@ -3,6 +3,7 @@ import SendMessageForm from './SendMessageForm';
export const Empty = {
component: SendMessageForm,
props: {
formId: 'SendMessageForm.Empty.Form',
messagePlaceholder: 'Send message to Juho…',
onChange: values => {
console.log('values changed to:', values);
@ -23,6 +24,7 @@ export const Empty = {
export const InProgress = {
component: SendMessageForm,
props: {
formId: 'SendMessageForm.InProgress.Form',
messagePlaceholder: 'Send message to Juho…',
inProgress: true,
onSubmit: values => {
@ -35,6 +37,7 @@ export const InProgress = {
export const Error = {
component: SendMessageForm,
props: {
formId: 'SendMessageForm.Error.Form',
messagePlaceholder: 'Send message to Juho…',
sendMessageError: { type: 'error', name: 'ExampleError' },
onSubmit: values => {

View file

@ -66,6 +66,7 @@ class SendMessageFormComponent extends Component {
sendMessageError,
invalid,
form,
formId,
} = formRenderProps;
const classes = classNames(rootClassName || css.root, className);
@ -76,7 +77,7 @@ class SendMessageFormComponent extends Component {
<FieldTextInput
inputRootClass={css.textarea}
type="textarea"
id="message"
id={formId ? `${formId}.message` : 'message'}
name="message"
placeholder={messagePlaceholder}
onFocus={this.handleFocus}

View file

@ -7,6 +7,8 @@ import { Form, LocationAutocompleteInput } from '../../components';
import css from './TopbarSearchForm.css';
const identity = v => v;
class TopbarSearchFormComponent extends Component {
constructor(props) {
super(props);
@ -45,7 +47,7 @@ class TopbarSearchFormComponent extends Component {
<Form className={classes} onSubmit={preventFormSubmit}>
<Field
name="location"
format={null}
format={identity}
render={({ input, meta }) => {
const { onChange, ...restInput } = input;

View file

@ -756,14 +756,14 @@
"@babel/helper-plugin-utils" "^7.0.0"
"@babel/plugin-transform-typescript" "^7.3.2"
"@babel/runtime@7.5.5", "@babel/runtime@^7.0.0", "@babel/runtime@^7.3.4", "@babel/runtime@^7.4.2", "@babel/runtime@^7.4.5":
"@babel/runtime@7.5.5", "@babel/runtime@^7.0.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.3.4", "@babel/runtime@^7.4.2", "@babel/runtime@^7.4.5":
version "7.5.5"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.5.5.tgz#74fba56d35efbeca444091c7850ccd494fd2f132"
integrity sha512-28QvEGyQyNkB0/m2B4FU7IEZGK2NUrcMtT6BZEFALTguLk+AUT6ofsHtPk5QyjAdUkpMJ+/Em+quwz4HOt30AQ==
dependencies:
regenerator-runtime "^0.13.2"
"@babel/runtime@^7.1.2", "@babel/runtime@^7.3.1":
"@babel/runtime@^7.1.2":
version "7.4.4"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.4.4.tgz#dc2e34982eb236803aa27a07fea6857af1b9171d"
integrity sha512-w0+uT71b6Yi7i5SE0co4NioIpSYS6lLiXvCzWzGSKvpK5vdQtCbICHMj+gbAKAOtxiV6HsVh/MBdaF9EQ6faSg==
@ -4497,15 +4497,15 @@ fill-range@^4.0.0:
repeat-string "^1.6.1"
to-regex-range "^2.1.0"
final-form-arrays@^1.1.0:
version "1.1.2"
resolved "https://registry.yarnpkg.com/final-form-arrays/-/final-form-arrays-1.1.2.tgz#7e33eb2485419e6956310cec76a717167c88d85c"
integrity sha512-Pmq3MXI9zbSsY7WZ2eodWQAHpsw2/i5YkagzcCgqzRcSSHB8BD3yWi7YPSGTPXuG0ixcQe9VAYpQ+UEWcqf4zg==
final-form-arrays@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/final-form-arrays/-/final-form-arrays-3.0.1.tgz#862e5e946d391039ebcdfadbe55fc3a63849e559"
integrity sha512-GKXecufCNCjDcz1+3peL21LuuTlApoxCcnpOnmfeJfC3xAlFKGdytYMfifP7W1IEWTGC8twTv3zItESkej8qpg==
final-form@^4.11.0:
version "4.12.0"
resolved "https://registry.yarnpkg.com/final-form/-/final-form-4.12.0.tgz#1844e2a3bc9789d51115c76a94d0ea6a19e219c0"
integrity sha512-z1fSzDNmIBlDjRMaluM3WgDbcwCFpPm7mvopplgXGMRS49MXR+1n//lteLwPURdGQNOZhWm3GwiEJanEHCItww==
final-form@^4.18.5:
version "4.18.5"
resolved "https://registry.yarnpkg.com/final-form/-/final-form-4.18.5.tgz#e359cfaf2892ef135d92fcf22e06b475dda3a885"
integrity sha512-DH/I2W7fWxU8J8ZsbYJ5jLvUbhbatCvLhIKlsU17MvY6W3QnetPEyuX5mcxXgIGFNFKxfvqsG3pDy/1/VwOiTw==
dependencies:
"@babel/runtime" "^7.3.1"
@ -9144,20 +9144,20 @@ react-fast-compare@^2.0.2:
resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-2.0.4.tgz#e84b4d455b0fec113e0402c329352715196f81f9"
integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==
react-final-form-arrays@^2.0.1:
version "2.0.3"
resolved "https://registry.yarnpkg.com/react-final-form-arrays/-/react-final-form-arrays-2.0.3.tgz#938bd0d62741ab59c6a680968f79eac029e37333"
integrity sha512-iHGGAbOVsTlp/lhE6EUsqzhjPZSvcExLWE91Qx0remHOJvQ2wkxHe8HTA9KBlId8YJ1fkz6g417GTq/1IFnL9w==
react-final-form-arrays@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/react-final-form-arrays/-/react-final-form-arrays-3.1.1.tgz#39d23e7ede966e418cad209e8fde46da1d603e99"
integrity sha512-e6S1x9597cvI4QPniOPmllXXandDAqCCuBo4AvXstZYgcV8whsqzk8aCrmQEy6eEfy2tEhvn6f4VI1GY+JBRsg==
dependencies:
"@babel/runtime" "^7.3.4"
react-lifecycles-compat "^3.0.4"
"@babel/runtime" "^7.4.5"
react-final-form@^4.0.2:
version "4.1.0"
resolved "https://registry.yarnpkg.com/react-final-form/-/react-final-form-4.1.0.tgz#4e1b513de164771b2b824f3fb9c0548014255971"
integrity sha512-O8p1EPQ/PFWNcX3bYGsLzuo/KnGeNfGfFi2UAX8jXLXrGcGdTfZMnyo/DFHdEKA9aKso61d/PHekQ9sst0cOmw==
react-final-form@^6.3.0:
version "6.3.0"
resolved "https://registry.yarnpkg.com/react-final-form/-/react-final-form-6.3.0.tgz#b85ae123a3796b3e0c8f56033c8a5037f4497e76"
integrity sha512-jijhXR1fFGUBQwNOSqF4MK8XJO7Ynl1p8vcFsnQS0INSkGI52+4IagjUgtHj3w8EviIHPFK/Eflji6FELUl07w==
dependencies:
"@babel/runtime" "^7.3.4"
"@babel/runtime" "^7.4.5"
ts-essentials "^2.0.8"
react-google-maps@^9.4.5:
version "9.4.5"
@ -9207,7 +9207,7 @@ react-is@^16.8.1, react-is@^16.8.4, react-is@^16.8.6, react-is@^16.9.0:
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.9.0.tgz#21ca9561399aad0ff1a7701c01683e8ca981edcb"
integrity sha512-tJBzzzIgnnRfEm046qRcURvwQnZVXmuCbscxUO5RWrGTXpon2d4c8mI0D8WE6ydVIm29JiLB6+RslkIvym9Rjw==
react-lifecycles-compat@^3.0.0, react-lifecycles-compat@^3.0.4:
react-lifecycles-compat@^3.0.0:
version "3.0.4"
resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==
@ -10872,6 +10872,11 @@ tryer@^1.0.1:
resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8"
integrity sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==
ts-essentials@^2.0.8:
version "2.0.12"
resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-2.0.12.tgz#c9303f3d74f75fa7528c3d49b80e089ab09d8745"
integrity sha512-3IVX4nI6B5cc31/GFFE+i8ey/N2eA0CZDbo6n0yrz0zDX8ZJ8djmU1p+XRz7G3is0F3bB3pu2pAroFdAWQKU3w==
ts-pnp@1.1.2, ts-pnp@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.1.2.tgz#be8e4bfce5d00f0f58e0666a82260c34a57af552"