Skip to content

Commit

Permalink
Dataviews: Add confirmation step before deleting a page (#56504)
Browse files Browse the repository at this point in the history
* Dataviews: Add confirmation step before deleting a page

* Update component docs for DataViews

---------

Co-authored-by: Miguel Fonseca <150562+mcsf@users.noreply.github.com>
  • Loading branch information
ntsekouras and mcsf authored Nov 28, 2023
1 parent d1e5080 commit e7ebdcf
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 58 deletions.
124 changes: 76 additions & 48 deletions packages/edit-site/src/components/actions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,62 +10,90 @@ import { __, sprintf } from '@wordpress/i18n';
import { store as noticesStore } from '@wordpress/notices';
import { useMemo } from '@wordpress/element';
import { privateApis as routerPrivateApis } from '@wordpress/router';
import {
Button,
__experimentalText as Text,
__experimentalHStack as HStack,
__experimentalVStack as VStack,
} from '@wordpress/components';

/**
* Internal dependencies
*/
import { unlock } from '../../lock-unlock';

const { useHistory } = unlock( routerPrivateApis );

export function useTrashPostAction() {
const { createSuccessNotice, createErrorNotice } =
useDispatch( noticesStore );
const { deleteEntityRecord } = useDispatch( coreStore );

return useMemo(
() => ( {
id: 'move-to-trash',
label: __( 'Move to Trash' ),
isPrimary: true,
icon: trash,
isEligible( { status } ) {
return status !== 'trash';
},
async callback( post ) {
try {
await deleteEntityRecord(
'postType',
post.type,
post.id,
{},
{ throwOnError: true }
);
createSuccessNotice(
sprintf(
/* translators: The page's title. */
__( '"%s" moved to the Trash.' ),
decodeEntities( post.title.rendered )
),
{
type: 'snackbar',
id: 'edit-site-page-trashed',
}
);
} catch ( error ) {
const errorMessage =
error.message && error.code !== 'unknown_error'
? error.message
: __(
'An error occurred while moving the page to the trash.'
);
export const trashPostAction = {
id: 'move-to-trash',
label: __( 'Move to Trash' ),
isPrimary: true,
icon: trash,
isEligible( { status } ) {
return status !== 'trash';
},
hideModalHeader: true,
RenderModal: ( { item: post, closeModal } ) => {
const { createSuccessNotice, createErrorNotice } =
useDispatch( noticesStore );
const { deleteEntityRecord } = useDispatch( coreStore );
return (
<VStack spacing="5">
<Text>
{ sprintf(
// translators: %s: The page's title.
__( 'Are you sure you want to delete "%s"?' ),
decodeEntities( post.title.rendered )
) }
</Text>
<HStack justify="right">
<Button variant="tertiary" onClick={ closeModal }>
{ __( 'Cancel' ) }
</Button>
<Button
variant="primary"
onClick={ async () => {
try {
await deleteEntityRecord(
'postType',
post.type,
post.id,
{},
{ throwOnError: true }
);
createSuccessNotice(
sprintf(
/* translators: The page's title. */
__( '"%s" moved to the Trash.' ),
decodeEntities( post.title.rendered )
),
{
type: 'snackbar',
id: 'edit-site-page-trashed',
}
);
} catch ( error ) {
const errorMessage =
error.message &&
error.code !== 'unknown_error'
? error.message
: __(
'An error occurred while moving the page to the trash.'
);

createErrorNotice( errorMessage, { type: 'snackbar' } );
}
},
} ),
[ createSuccessNotice, createErrorNotice, deleteEntityRecord ]
);
}
createErrorNotice( errorMessage, {
type: 'snackbar',
} );
}
} }
>
{ __( 'Delete' ) }
</Button>
</HStack>
</VStack>
);
},
};

export function usePermanentlyDeletePostAction() {
const { createSuccessNotice, createErrorNotice } =
Expand Down
4 changes: 2 additions & 2 deletions packages/edit-site/src/components/dataviews/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,6 @@ Array of operations that can be performed upon each record. Each action is an ob
- `icon`: icon to show for primary actions. It's required for a primary action, otherwise the action would be considered secondary.
- `isEligible`: function, optional. Whether the action can be performed for a given record. If not present, the action is considered to be eligible for all items. It takes the given record as input.
- `isDestructive`: boolean, optional. Whether the action can delete data, in which case the UI would communicate it via red color.
- `callback`: function, required. Callback function that takes the record as input and performs the required action.
- `RenderModal`: ReactElement, optional. If an action requires to render contents in a modal, can provide a component which takes as input the record and a `closeModal` function. If this prop is provided, the `callback` property would be ignored.
- `callback`: function, required unless `RenderModal` is provided. Callback function that takes the record as input and performs the required action.
- `RenderModal`: ReactElement, optional. If an action requires that some UI be rendered in a modal, it can provide a component which takes as props the record as `item` and a `closeModal` function. When this prop is provided, the `callback` property is ignored.
- `hideModalHeader`: boolean, optional. This property is used in combination with `RenderModal` and controls the visibility of the modal's header. If the action renders a modal and doesn't hide the header, the action's label is going to be used in the modal's header.
10 changes: 2 additions & 8 deletions packages/edit-site/src/components/page-pages/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import Link from '../routes/link';
import { DataViews, viewTypeSupportsMap } from '../dataviews';
import { default as DEFAULT_VIEWS } from '../sidebar-dataviews/default-views';
import {
useTrashPostAction,
trashPostAction,
usePermanentlyDeletePostAction,
useRestorePostAction,
postRevisionsAction,
Expand Down Expand Up @@ -259,7 +259,6 @@ export default function PagePages() {
[ authors ]
);

const trashPostAction = useTrashPostAction();
const permanentlyDeletePostAction = usePermanentlyDeletePostAction();
const restorePostAction = useRestorePostAction();
const editPostAction = useEditPostAction();
Expand All @@ -272,12 +271,7 @@ export default function PagePages() {
editPostAction,
postRevisionsAction,
],
[
trashPostAction,
permanentlyDeletePostAction,
restorePostAction,
editPostAction,
]
[ permanentlyDeletePostAction, restorePostAction, editPostAction ]
);
const onChangeView = useCallback(
( viewUpdater ) => {
Expand Down

0 comments on commit e7ebdcf

Please sign in to comment.