Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add confirm dialog before Permanently delete #67824

Merged
Merged
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading