Skip to content

Commit

Permalink
Add confirm dialog before Permanently delete (#67824)
Browse files Browse the repository at this point in the history
Co-authored-by: karthick-murugan <[email protected]>
Co-authored-by: ntsekouras <[email protected]>
Co-authored-by: Mamaduka <[email protected]>
Co-authored-by: annezazu <[email protected]>
Co-authored-by: ammar-Mohamed-elz3eeem <[email protected]>
Co-authored-by: jameskoster <[email protected]>
Co-authored-by: afercia <[email protected]>
  • Loading branch information
8 people authored Dec 20, 2024
1 parent 5f22b7c commit 94df941
Showing 1 changed file with 157 additions and 86 deletions.
243 changes: 157 additions & 86 deletions packages/fields/src/actions/permanently-delete-post.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,19 @@
* WordPress dependencies
*/
import { store as coreStore } from '@wordpress/core-data';
import { __, sprintf } from '@wordpress/i18n';
import { __, _n, sprintf } from '@wordpress/i18n';
import { store as noticesStore } from '@wordpress/notices';
import type { Action } from '@wordpress/dataviews';
import { trash } from '@wordpress/icons';
import { useState } from '@wordpress/element';
import { useDispatch } from '@wordpress/data';
import {
Button,
__experimentalText as Text,
__experimentalHStack as HStack,
__experimentalVStack as VStack,
} from '@wordpress/components';
import { decodeEntities } from '@wordpress/html-entities';

/**
* Internal dependencies
Expand All @@ -25,93 +34,155 @@ const permanentlyDeletePost: Action< PostWithPermissions > = {
const { status, permissions } = item;
return status === 'trash' && permissions?.delete;
},
async callback( posts, { registry, onActionPerformed } ) {
hideModalHeader: true,
RenderModal: ( { items, closeModal, onActionPerformed } ) => {
const [ isBusy, setIsBusy ] = useState( false );
const { createSuccessNotice, createErrorNotice } =
registry.dispatch( noticesStore );
const { deleteEntityRecord } = registry.dispatch( coreStore );
const promiseResult = await Promise.allSettled(
posts.map( ( post ) => {
return deleteEntityRecord(
'postType',
post.type,
post.id,
{ force: true },
{ throwOnError: true }
);
} )
useDispatch( noticesStore );
const { deleteEntityRecord } = useDispatch( coreStore );

return (
<VStack spacing="5">
<Text>
{ items.length > 1
? sprintf(
// translators: %d: number of items to delete.
_n(
'Are you sure you want to permanently delete %d item?',
'Are you sure you want to permanently delete %d items?',
items.length
),
items.length
)
: sprintf(
// translators: %s: The post's title
__(
'Are you sure you want to permanently delete "%s"?'
),
decodeEntities( getItemTitle( items[ 0 ] ) )
) }
</Text>
<HStack justify="right">
<Button
variant="tertiary"
onClick={ closeModal }
disabled={ isBusy }
accessibleWhenDisabled
__next40pxDefaultSize
>
{ __( 'Cancel' ) }
</Button>
<Button
variant="primary"
onClick={ async () => {
setIsBusy( true );
const promiseResult = await Promise.allSettled(
items.map( ( post ) =>
deleteEntityRecord(
'postType',
post.type,
post.id,
{ force: true },
{ throwOnError: true }
)
)
);

// If all the promises were fulfilled with success.
if (
promiseResult.every(
( { status } ) => status === 'fulfilled'
)
) {
let successMessage;
if ( promiseResult.length === 1 ) {
successMessage = sprintf(
/* translators: The posts's title. */
__( '"%s" permanently deleted.' ),
getItemTitle( items[ 0 ] )
);
} else {
successMessage = __(
'The items were permanently deleted.'
);
}
createSuccessNotice( successMessage, {
type: 'snackbar',
id: 'permanently-delete-post-action',
} );
onActionPerformed?.( items );
} else {
// If there was at lease one failure.
let errorMessage;
// If we were trying to permanently delete a single post.
if ( promiseResult.length === 1 ) {
const typedError = promiseResult[ 0 ] as {
reason?: CoreDataError;
};
if ( typedError.reason?.message ) {
errorMessage =
typedError.reason.message;
} else {
errorMessage = __(
'An error occurred while permanently deleting the item.'
);
}
// If we were trying to permanently delete multiple posts
} else {
const errorMessages = new Set();
const failedPromises = promiseResult.filter(
( { status } ) => status === 'rejected'
);
for ( const failedPromise of failedPromises ) {
const typedError = failedPromise as {
reason?: CoreDataError;
};
if ( typedError.reason?.message ) {
errorMessages.add(
typedError.reason.message
);
}
}
if ( errorMessages.size === 0 ) {
errorMessage = __(
'An error occurred while permanently deleting the items.'
);
} else if ( errorMessages.size === 1 ) {
errorMessage = sprintf(
/* translators: %s: an error message */
__(
'An error occurred while permanently deleting the items: %s'
),
[ ...errorMessages ][ 0 ]
);
} else {
errorMessage = sprintf(
/* translators: %s: a list of comma separated error messages */
__(
'Some errors occurred while permanently deleting the items: %s'
),
[ ...errorMessages ].join( ',' )
);
}
}
createErrorNotice( errorMessage, {
type: 'snackbar',
} );
}

setIsBusy( false );
closeModal?.();
} }
isBusy={ isBusy }
disabled={ isBusy }
accessibleWhenDisabled
__next40pxDefaultSize
>
{ __( 'Delete permanently' ) }
</Button>
</HStack>
</VStack>
);
// If all the promises were fulfilled with success.
if ( promiseResult.every( ( { status } ) => status === 'fulfilled' ) ) {
let successMessage;
if ( promiseResult.length === 1 ) {
successMessage = sprintf(
/* translators: The posts's title. */
__( '"%s" permanently deleted.' ),
getItemTitle( posts[ 0 ] )
);
} else {
successMessage = __( 'The items were permanently deleted.' );
}
createSuccessNotice( successMessage, {
type: 'snackbar',
id: 'permanently-delete-post-action',
} );
onActionPerformed?.( posts );
} else {
// If there was at lease one failure.
let errorMessage;
// If we were trying to permanently delete a single post.
if ( promiseResult.length === 1 ) {
const typedError = promiseResult[ 0 ] as {
reason?: CoreDataError;
};
if ( typedError.reason?.message ) {
errorMessage = typedError.reason.message;
} else {
errorMessage = __(
'An error occurred while permanently deleting the item.'
);
}
// If we were trying to permanently delete multiple posts
} else {
const errorMessages = new Set();
const failedPromises = promiseResult.filter(
( { status } ) => status === 'rejected'
);
for ( const failedPromise of failedPromises ) {
const typedError = failedPromise as {
reason?: CoreDataError;
};
if ( typedError.reason?.message ) {
errorMessages.add( typedError.reason.message );
}
}
if ( errorMessages.size === 0 ) {
errorMessage = __(
'An error occurred while permanently deleting the items.'
);
} else if ( errorMessages.size === 1 ) {
errorMessage = sprintf(
/* translators: %s: an error message */
__(
'An error occurred while permanently deleting the items: %s'
),
[ ...errorMessages ][ 0 ]
);
} else {
errorMessage = sprintf(
/* translators: %s: a list of comma separated error messages */
__(
'Some errors occurred while permanently deleting the items: %s'
),
[ ...errorMessages ].join( ',' )
);
}
}
createErrorNotice( errorMessage, {
type: 'snackbar',
} );
}
},
};

Expand Down

1 comment on commit 94df941

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Flaky tests detected in 94df941.
Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/12429390990
📝 Reported issues:

Please sign in to comment.