Skip to content

Commit

Permalink
Fix/unsaved prompt (woocommerce#35657)
Browse files Browse the repository at this point in the history
* Set initial values prop from reset form function as optional

* Fix unsaved modal propmt to not be shown during form submission

* Reset form on save draft and before navigation starts

* Add comments ssuggestions
  • Loading branch information
mdperez86 authored Nov 22, 2022
1 parent 995b587 commit 29b9c69
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 37 deletions.
4 changes: 4 additions & 0 deletions packages/js/components/changelog/fix-unsaved-prompt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: fix

Set initial values prop from reset form function as optional
2 changes: 1 addition & 1 deletion packages/js/components/src/form/form-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export type FormContext< Values extends Record< string, any > > = {
): InputProps< Values, Value >;
isValidForm: boolean;
resetForm: (
initialValues: Values,
initialValues?: Values,
touchedFields?: { [ P in keyof Values ]?: boolean | undefined },
errors?: FormErrors< Values >
) => void;
Expand Down
12 changes: 6 additions & 6 deletions packages/js/components/src/form/form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -166,11 +166,11 @@ function FormComponent< Values extends Record< string, any > >(
validate( values );
}, [] );

const resetForm = (
newInitialValues = {} as Values,
newTouchedFields = {},
newErrors = {}
) => {
const resetForm: (
newInitialValues?: Values,
newTouchedFields?: { [ P in keyof Values ]?: boolean | undefined },
newErrors?: FormErrors< Values >
) => void = ( newInitialValues, newTouchedFields = {}, newErrors = {} ) => {
const newValues = newInitialValues ?? initialValues.current ?? {};
initialValues.current = newValues;
setValuesInternal( newValues );
Expand All @@ -183,7 +183,7 @@ function FormComponent< Values extends Record< string, any > >(
} ) );

const isValidForm = async () => {
await validate( values );
validate( values );
return ! Object.keys( errors ).length;
};

Expand Down
27 changes: 22 additions & 5 deletions plugins/woocommerce-admin/client/products/product-form-actions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { registerPlugin } from '@wordpress/plugins';
import { useFormContext } from '@woocommerce/components';
import { Product } from '@woocommerce/data';
import { recordEvent } from '@woocommerce/tracks';
import { navigateTo } from '@woocommerce/navigation';

/**
* Internal dependencies
Expand Down Expand Up @@ -54,7 +55,13 @@ export const ProductFormActions: React.FC = () => {
...getProductDataForTracks(),
} );
if ( ! values.id ) {
createProductWithStatus( values, 'draft' );
const product = await createProductWithStatus( values, 'draft' );
if ( product?.id ) {
resetForm();
navigateTo( {
url: 'admin.php?page=wc-admin&path=/product/' + product.id,
} );
}
} else {
const product = await updateProductWithStatus(
values.id,
Expand All @@ -73,7 +80,13 @@ export const ProductFormActions: React.FC = () => {
...getProductDataForTracks(),
} );
if ( ! values.id ) {
createProductWithStatus( values, 'publish' );
const product = await createProductWithStatus( values, 'publish' );
if ( product?.id ) {
resetForm();
navigateTo( {
url: 'admin.php?page=wc-admin&path=/product/' + product.id,
} );
}
} else {
const product = await updateProductWithStatus(
values.id,
Expand All @@ -94,7 +107,7 @@ export const ProductFormActions: React.FC = () => {
if ( values.id ) {
await updateProductWithStatus( values.id, values, 'publish' );
} else {
await createProductWithStatus( values, 'publish', false, true );
await createProductWithStatus( values, 'publish', false );
}
await copyProductWithStatus( values );
};
Expand All @@ -114,13 +127,17 @@ export const ProductFormActions: React.FC = () => {
await copyProductWithStatus( values );
};

const onTrash = () => {
const onTrash = async () => {
recordEvent( 'product_delete', {
new_product_page: true,
...getProductDataForTracks(),
} );
if ( values.id ) {
deleteProductAndRedirect( values.id );
const product = await deleteProductAndRedirect( values.id );
if ( product?.id ) {
resetForm( product );
navigateTo( { url: 'edit.php?post_type=product' } );
}
}
};

Expand Down
46 changes: 21 additions & 25 deletions plugins/woocommerce-admin/client/products/use-product-helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import {
productReadOnlyProperties,
} from '@woocommerce/data';
import { recordEvent } from '@woocommerce/tracks';
import { navigateTo } from '@woocommerce/navigation';

/**
* Internal dependencies
Expand Down Expand Up @@ -66,21 +65,19 @@ export function useProductHelper() {
* @param {Product} product the product to be created.
* @param {string} status the product status.
* @param {boolean} skipNotice if the notice should be skipped (default: false).
* @param {boolean} skipRedirect if the user should skip the redirection to the new product page (default: false).
* @return {Promise<Product>} Returns a promise with the created product.
*/
const createProductWithStatus = useCallback(
async (
product: Omit< Product, ReadOnlyProperties >,
status: ProductStatus,
skipNotice = false,
skipRedirect = false
skipNotice = false
) => {
setUpdating( {
...updating,
[ status ]: true,
} );
createProduct( {
return createProduct( {
...product,
status,
} ).then(
Expand Down Expand Up @@ -109,15 +106,9 @@ export function useProductHelper() {
...updating,
[ status ]: false,
} );
if ( ! skipRedirect ) {
navigateTo( {
url:
'admin.php?page=wc-admin&path=/product/' +
newProduct.id,
} );
}
return newProduct;
},
() => {
( error ) => {
if ( ! skipNotice ) {
createNotice(
'error',
Expand All @@ -136,6 +127,7 @@ export function useProductHelper() {
...updating,
[ status ]: false,
} );
return error;
}
);
},
Expand Down Expand Up @@ -236,28 +228,32 @@ export function useProductHelper() {
* Deletes a product by given id and redirects to the product list page.
*
* @param {number} id the product id to be deleted.
* @param {string} redirectUrl the redirection url, defaults to product list ('edit.php?post_type=product').
* @return {Promise<Product>} promise with the deleted product.
*/
const deleteProductAndRedirect = useCallback(
( id: number, redirectUrl = 'edit.php?post_type=product' ) => {
setIsDeleting( true );
return deleteProduct( id ).then( () => {
const deleteProductAndRedirect = useCallback( async ( id: number ) => {
setIsDeleting( true );
return deleteProduct( id ).then(
( product ) => {
createNotice(
'success',
__(
'🎉 Successfully moved product to Trash.',
'woocommerce'
)
);
navigateTo( {
url: redirectUrl,
} );
setIsDeleting( false );
} );
},
[]
);
return product;
},
( error ) => {
createNotice(
'error',
__( 'Failed to move product to Trash.', 'woocommerce' )
);
setIsDeleting( false );
return error;
}
);
}, [] );

/**
* Sanitizes a price.
Expand Down
4 changes: 4 additions & 0 deletions plugins/woocommerce/changelog/fix-unsaved-prompt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: fix

Fix unsaved modal propmt to not be shown during form submission

0 comments on commit 29b9c69

Please sign in to comment.