Disable save button while update is in progress

This commit is contained in:
Kimmo Puputti 2017-08-15 11:25:48 +03:00
parent d52cbd39f6
commit 7434e1d887
21 changed files with 53 additions and 19 deletions

View file

@ -14,6 +14,7 @@ const EditListingDescriptionPanel = props => {
onChange,
submitButtonText,
panelUpdated,
updateInProgress,
errors,
} = props;
@ -31,6 +32,7 @@ const EditListingDescriptionPanel = props => {
onChange={onChange}
updated={panelUpdated}
updateError={errors.updateListingError}
updateInProgress={updateInProgress}
/>
</div>
);
@ -52,6 +54,7 @@ EditListingDescriptionPanel.propTypes = {
onChange: func.isRequired,
submitButtonText: string.isRequired,
panelUpdated: bool.isRequired,
updateInProgress: bool.isRequired,
errors: object.isRequired,
};

View file

@ -14,6 +14,7 @@ const EditListingLocationPanel = props => {
onChange,
submitButtonText,
panelUpdated,
updateInProgress,
errors,
} = props;
@ -57,6 +58,7 @@ const EditListingLocationPanel = props => {
saveActionMsg={submitButtonText}
updated={panelUpdated}
updateError={errors.updateListingError}
updateInProgress={updateInProgress}
/>
</div>
);
@ -78,6 +80,7 @@ EditListingLocationPanel.propTypes = {
onChange: func.isRequired,
submitButtonText: string.isRequired,
panelUpdated: bool.isRequired,
updateInProgress: bool.isRequired,
errors: object.isRequired,
};

View file

@ -82,6 +82,7 @@ class EditListingPhotosPanel extends Component {
onManageDisableScrolling,
submitButtonText,
panelUpdated,
updateInProgress,
onChange,
} = this.props;
@ -107,6 +108,7 @@ class EditListingPhotosPanel extends Component {
saveActionMsg={submitButtonText}
updated={panelUpdated}
updateError={errors.updateListingError}
updateInProgress={updateInProgress}
/>
<Modal
id="EditListingPhotosPanel.payoutModal"
@ -167,6 +169,7 @@ EditListingPhotosPanel.propTypes = {
submitButtonText: string.isRequired,
onManageDisableScrolling: func.isRequired,
panelUpdated: bool.isRequired,
updateInProgress: bool.isRequired,
};
export default EditListingPhotosPanel;

View file

@ -14,6 +14,7 @@ const EditListingPricingPanel = props => {
onChange,
submitButtonText,
panelUpdated,
updateInProgress,
errors,
} = props;
@ -31,6 +32,7 @@ const EditListingPricingPanel = props => {
saveActionMsg={submitButtonText}
updated={panelUpdated}
updateError={errors.updateListingError}
updateInProgress={updateInProgress}
/>
</div>
);
@ -52,6 +54,7 @@ EditListingPricingPanel.propTypes = {
onChange: func.isRequired,
submitButtonText: string.isRequired,
panelUpdated: bool.isRequired,
updateInProgress: bool.isRequired,
errors: object.isRequired,
};

View file

@ -30,6 +30,7 @@ export const NoPhotos = {
onManageDisableScrolling: noop,
onChange: noop,
errors: {},
updateInProgress: false,
},
useDefaultWrapperStyles: false,
};

View file

@ -91,6 +91,7 @@ const EditListingWizard = props => {
currentUser,
onManageDisableScrolling,
updatedTab,
updateInProgress,
intl,
} = props;
@ -126,6 +127,7 @@ const EditListingWizard = props => {
tabLinkProps={tabLink(DESCRIPTION)}
selected={selectedTab === DESCRIPTION}
panelUpdated={updatedTab === DESCRIPTION}
updateInProgress={updateInProgress}
disabled={!stepsStatus[DESCRIPTION]}
errors={errors}
listing={listing}
@ -150,6 +152,7 @@ const EditListingWizard = props => {
tabLinkProps={tabLink(LOCATION)}
selected={selectedTab === LOCATION}
panelUpdated={updatedTab === LOCATION}
updateInProgress={updateInProgress}
disabled={!stepsStatus[LOCATION]}
errors={errors}
listing={listing}
@ -182,6 +185,7 @@ const EditListingWizard = props => {
tabLinkProps={tabLink(PRICING)}
selected={selectedTab === PRICING}
panelUpdated={updatedTab === PRICING}
updateInProgress={updateInProgress}
disabled={!stepsStatus[PRICING]}
errors={errors}
listing={listing}
@ -207,6 +211,7 @@ const EditListingWizard = props => {
selected={selectedTab === PHOTOS}
disabled={!stepsStatus[PHOTOS]}
panelUpdated={updatedTab === PHOTOS}
updateInProgress={updateInProgress}
errors={errors}
fetchInProgress={fetchInProgress}
listing={listing}
@ -287,6 +292,7 @@ EditListingWizard.propTypes = {
currentUser: propTypes.currentUser,
onManageDisableScrolling: func.isRequired,
updatedTab: string,
updateInProgress: bool.isRequired,
// from injectIntl
intl: intlShape.isRequired,

View file

@ -9,6 +9,7 @@ export const Empty = {
},
saveActionMsg: 'Save description',
updated: false,
updateInProgress: false,
},
group: 'forms',
};

View file

@ -22,6 +22,7 @@ const EditListingDescriptionFormComponent = props => {
submitting,
updated,
updateError,
updateInProgress,
} = props;
const titleMessage = intl.formatMessage({ id: 'EditListingDescriptionForm.title' });
@ -58,6 +59,8 @@ const EditListingDescriptionFormComponent = props => {
: saveActionMsg;
const classes = classNames(css.root, className);
const buttonDisabled = invalid || submitting || disabled || updateInProgress;
return (
<form className={classes} onSubmit={handleSubmit}>
{errorMessage}
@ -81,11 +84,7 @@ const EditListingDescriptionFormComponent = props => {
validate={[required(descriptionRequiredMessage)]}
/>
<Button
className={css.submitButton}
type="submit"
disabled={invalid || submitting || disabled}
>
<Button className={css.submitButton} type="submit" disabled={buttonDisabled}>
{buttonContent}
</Button>
</form>
@ -104,6 +103,7 @@ EditListingDescriptionFormComponent.propTypes = {
saveActionMsg: string.isRequired,
updated: bool.isRequired,
updateError: instanceOf(Error),
updateInProgress: bool.isRequired,
};
const formName = 'EditListingDescriptionForm';

View file

@ -15,6 +15,7 @@ describe('EditListingDescriptionForm', () => {
onSubmit={v => v}
saveActionMsg="Save description"
updated={false}
updateInProgress={false}
/>
);
expect(tree).toMatchSnapshot();

View file

@ -9,6 +9,7 @@ export const Empty = {
},
saveActionMsg: 'Save location',
updated: false,
updateInProgress: false,
},
group: 'forms',
};

View file

@ -22,6 +22,7 @@ export const EditListingLocationFormComponent = props => {
submitting,
updated,
updateError,
updateInProgress,
} = props;
const titleRequiredMessage = intl.formatMessage({ id: 'EditListingLocationForm.address' });
@ -47,6 +48,7 @@ export const EditListingLocationFormComponent = props => {
: null;
const classes = classNames(css.root, className);
const buttonDisabled = invalid || submitting || disabled || updateInProgress;
return (
<form className={classes} onSubmit={handleSubmit}>
@ -76,11 +78,7 @@ export const EditListingLocationFormComponent = props => {
placeholder={buildingPlaceholderMessage}
/>
<Button
className={css.submitButton}
type="submit"
disabled={invalid || submitting || disabled}
>
<Button className={css.submitButton} type="submit" disabled={buttonDisabled}>
{updated ? <FormattedMessage id="EditListingLocationForm.updated" /> : saveActionMsg}
</Button>
</form>
@ -102,6 +100,7 @@ EditListingLocationFormComponent.propTypes = {
selectedPlace: propTypes.place,
updated: bool.isRequired,
updateError: instanceOf(Error),
updateInProgress: bool.isRequired,
};
const formName = 'EditListingLocationForm';

View file

@ -16,6 +16,7 @@ describe('EditListingLocationForm', () => {
onSubmit={v => v}
saveActionMsg="Save location"
updated={false}
updateInProgress={false}
/>
);
expect(tree).toMatchSnapshot();

View file

@ -22,6 +22,7 @@ exports[`EditListingLocationForm matches snapshot 1`] = `
type="text" />
<Button
className={null}
disabled={false}
rootClassName={null}
type="submit">
Save location

View file

@ -49,6 +49,7 @@ const initialState = {
imageOrder: [],
listingDraft: null,
updatedTab: null,
updateInProgress: false,
};
export default function reducer(state = initialState, action = {}) {
@ -74,13 +75,13 @@ export default function reducer(state = initialState, action = {}) {
return { ...state, createListingsError: payload, redirectToListing: false };
case UPDATE_LISTING_REQUEST:
return { ...state, updateListingError: null };
return { ...state, updateInProgress: true, updateListingError: null };
case UPDATE_LISTING_SUCCESS:
return state;
return { ...state, updateInProgress: false };
case UPDATE_LISTING_ERROR:
// eslint-disable-next-line no-console
console.error(payload);
return { ...state, updateListingError: payload };
return { ...state, updateInProgress: false, updateListingError: payload };
case SHOW_LISTINGS_REQUEST:
return { ...state, showListingsError: null };

View file

@ -153,6 +153,7 @@ export const EditListingPageComponent = props => {
currentUser={currentUser}
onManageDisableScrolling={onManageDisableScrolling}
updatedTab={page.updatedTab}
updateInProgress={page.updateInProgress}
/>
</PageLayout>
);

View file

@ -14,6 +14,7 @@ export const Empty = {
},
saveActionMsg: 'Save photos',
updated: false,
updateInProgress: false,
onUpdateImageOrder: imageOrder => {
console.log('onUpdateImageOrder with new imageOrder:', imageOrder);
},

View file

@ -87,6 +87,7 @@ export class EditListingPhotosFormComponent extends Component {
submitting,
updated,
updateError,
updateInProgress,
} = this.props;
const chooseImageText = (
@ -134,7 +135,11 @@ export class EditListingPhotosFormComponent extends Component {
const classes = classNames(css.root, className);
const disableForm = invalid || submitting || disabled || this.state.imageUploadRequested;
const disableForm = invalid ||
submitting ||
disabled ||
this.state.imageUploadRequested ||
updateInProgress;
return (
<form className={classes} onSubmit={handleSubmit}>
@ -203,6 +208,7 @@ EditListingPhotosFormComponent.propTypes = {
saveActionMsg: string.isRequired,
updated: bool.isRequired,
updateError: instanceOf(Error),
updateInProgress: bool.isRequired,
};
const formName = 'EditListingPhotosForm';

View file

@ -23,6 +23,7 @@ describe('EditListingPhotosForm', () => {
onUpdateImageOrder={v => v}
stripeConnected={false}
updated={false}
updateInProgress={false}
/>
);
expect(tree).toMatchSnapshot();

View file

@ -9,6 +9,7 @@ export const Empty = {
},
saveActionMsg: 'Save price',
updated: false,
updateInProgress: false,
},
group: 'forms',
};

View file

@ -20,6 +20,7 @@ export const EditListingPricingFormComponent = props => {
submitting,
updated,
updateError,
updateInProgress,
} = props;
const pricePerNightMessage = intl.formatMessage({ id: 'EditListingPricingForm.pricePerNight' });
@ -35,6 +36,7 @@ export const EditListingPricingFormComponent = props => {
: null;
const classes = classNames(css.root, className);
const buttonDisabled = invalid || submitting || disabled || updateInProgress;
return (
<form className={classes} onSubmit={handleSubmit}>
@ -50,11 +52,7 @@ export const EditListingPricingFormComponent = props => {
validate={[required(priceRequiredMessage)]}
/>
<Button
className={css.submitButton}
type="submit"
disabled={invalid || submitting || disabled}
>
<Button className={css.submitButton} type="submit" disabled={buttonDisabled}>
{updated ? <FormattedMessage id="EditListingPricingForm.updated" /> : saveActionMsg}
</Button>
</form>
@ -72,6 +70,7 @@ EditListingPricingFormComponent.propTypes = {
saveActionMsg: string.isRequired,
updated: bool.isRequired,
updateError: instanceOf(Error),
updateInProgress: bool.isRequired,
};
const formName = 'EditListingPricingForm';

View file

@ -15,6 +15,7 @@ describe('EditListingPricingForm', () => {
onSubmit={v => v}
saveActionMsg="Save price"
updated={false}
updateInProgress={false}
/>
);
expect(tree).toMatchSnapshot();