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

Dataviews: Add confirmation step before deleting a page #56504

Merged
merged 2 commits into from
Nov 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
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 } ) => {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

In essence the changes are:

  1. add hideModalHeader and RenderModal
  2. RenderModal absorbs the callback
  3. use a plain object instead of a hook.

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
Loading