From 9514bfcabb1af685c84c8fbf4d8c750c8b17d33a Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Wed, 31 Jul 2024 11:39:37 +0200 Subject: [PATCH] DataViews Extensibility: Allow unregistering restore post action --- .../src/components/post-actions/actions.js | 110 +------------- .../editor/src/dataviews/actions/index.ts | 2 + .../src/dataviews/actions/restore-post.tsx | 134 ++++++++++++++++++ 3 files changed, 137 insertions(+), 109 deletions(-) create mode 100644 packages/editor/src/dataviews/actions/restore-post.tsx diff --git a/packages/editor/src/components/post-actions/actions.js b/packages/editor/src/components/post-actions/actions.js index 0d5ac4764c37d..92a5cd0eec87d 100644 --- a/packages/editor/src/components/post-actions/actions.js +++ b/packages/editor/src/components/post-actions/actions.js @@ -1,7 +1,7 @@ /** * WordPress dependencies */ -import { external, backup } from '@wordpress/icons'; +import { external } from '@wordpress/icons'; import { addQueryArgs } from '@wordpress/url'; import { useDispatch, useSelect } from '@wordpress/data'; import { decodeEntities } from '@wordpress/html-entities'; @@ -81,113 +81,6 @@ function isTemplateRemovable( template ) { ); } -const restorePostAction = { - id: 'restore', - label: __( 'Restore' ), - isPrimary: true, - icon: backup, - supportsBulk: true, - isEligible( { status, permissions } ) { - return status === 'trash' && permissions?.update; - }, - async callback( posts, { registry, onActionPerformed } ) { - const { createSuccessNotice, createErrorNotice } = - registry.dispatch( noticesStore ); - const { editEntityRecord, saveEditedEntityRecord } = - registry.dispatch( coreStore ); - await Promise.allSettled( - posts.map( ( post ) => { - return editEntityRecord( 'postType', post.type, post.id, { - status: 'draft', - } ); - } ) - ); - const promiseResult = await Promise.allSettled( - posts.map( ( post ) => { - return saveEditedEntityRecord( 'postType', post.type, post.id, { - throwOnError: true, - } ); - } ) - ); - - if ( promiseResult.every( ( { status } ) => status === 'fulfilled' ) ) { - let successMessage; - if ( posts.length === 1 ) { - successMessage = sprintf( - /* translators: The number of posts. */ - __( '"%s" has been restored.' ), - getItemTitle( posts[ 0 ] ) - ); - } else if ( posts[ 0 ].type === 'page' ) { - successMessage = sprintf( - /* translators: The number of posts. */ - __( '%d pages have been restored.' ), - posts.length - ); - } else { - successMessage = sprintf( - /* translators: The number of posts. */ - __( '%d posts have been restored.' ), - posts.length - ); - } - createSuccessNotice( successMessage, { - type: 'snackbar', - id: 'restore-post-action', - } ); - if ( onActionPerformed ) { - onActionPerformed( posts ); - } - } else { - // If there was at lease one failure. - let errorMessage; - // If we were trying to move a single post to the trash. - if ( promiseResult.length === 1 ) { - if ( promiseResult[ 0 ].reason?.message ) { - errorMessage = promiseResult[ 0 ].reason.message; - } else { - errorMessage = __( - 'An error occurred while restoring the post.' - ); - } - // If we were trying to move multiple posts to the trash - } else { - const errorMessages = new Set(); - const failedPromises = promiseResult.filter( - ( { status } ) => status === 'rejected' - ); - for ( const failedPromise of failedPromises ) { - if ( failedPromise.reason?.message ) { - errorMessages.add( failedPromise.reason.message ); - } - } - if ( errorMessages.size === 0 ) { - errorMessage = __( - 'An error occurred while restoring the posts.' - ); - } else if ( errorMessages.size === 1 ) { - errorMessage = sprintf( - /* translators: %s: an error message */ - __( 'An error occurred while restoring the posts: %s' ), - [ ...errorMessages ][ 0 ] - ); - } else { - errorMessage = sprintf( - /* translators: %s: a list of comma separated error messages */ - __( - 'Some errors occurred while restoring the posts: %s' - ), - [ ...errorMessages ].join( ',' ) - ); - } - } - createErrorNotice( errorMessage, { - type: 'snackbar', - } ); - } - }, -}; - const viewPostAction = { id: 'view-post', label: __( 'View' ), @@ -726,7 +619,6 @@ export function usePostActions( { postType, onActionPerformed, context } ) { isPattern && userCanCreatePostType && duplicatePatternAction, supportsTitle && renamePostAction, reorderPagesAction, - ! isTemplateOrTemplatePart && ! isPattern && restorePostAction, ...defaultActions, ].filter( Boolean ); // Filter actions based on provided context. If not provided diff --git a/packages/editor/src/dataviews/actions/index.ts b/packages/editor/src/dataviews/actions/index.ts index 6679b2d7d1b8f..04addcb1cde4d 100644 --- a/packages/editor/src/dataviews/actions/index.ts +++ b/packages/editor/src/dataviews/actions/index.ts @@ -11,6 +11,7 @@ import exportPattern from './export-pattern'; import resetPost from './reset-post'; import trashPost from './trash-post'; import permanentlyDeletePost from './permanently-delete-post'; +import restorePost from './restore-post'; // @ts-ignore import { store as editorStore } from '../../store'; @@ -23,6 +24,7 @@ export default function registerDefaultActions() { registerEntityAction( 'postType', 'wp_block', exportPattern ); registerEntityAction( 'postType', '*', resetPost ); + registerEntityAction( 'postType', '*', restorePost ); registerEntityAction( 'postType', '*', deletePost ); registerEntityAction( 'postType', '*', trashPost ); registerEntityAction( 'postType', '*', permanentlyDeletePost ); diff --git a/packages/editor/src/dataviews/actions/restore-post.tsx b/packages/editor/src/dataviews/actions/restore-post.tsx new file mode 100644 index 0000000000000..874eca91fee11 --- /dev/null +++ b/packages/editor/src/dataviews/actions/restore-post.tsx @@ -0,0 +1,134 @@ +/** + * WordPress dependencies + */ +import { backup } from '@wordpress/icons'; +import { store as coreStore } from '@wordpress/core-data'; +import { __, sprintf } from '@wordpress/i18n'; +import { store as noticesStore } from '@wordpress/notices'; +import type { Action } from '@wordpress/dataviews'; + +/** + * Internal dependencies + */ +import { getItemTitle, isTemplateOrTemplatePart } from './utils'; +import type { CoreDataError, PostWithPermissions } from '../types'; + +const restorePost: Action< PostWithPermissions > = { + id: 'restore', + label: __( 'Restore' ), + isPrimary: true, + icon: backup, + supportsBulk: true, + isEligible( item ) { + return ( + ! isTemplateOrTemplatePart( item ) && + item.type !== 'wp_block' && + item.status === 'trash' && + item.permissions?.update + ); + }, + async callback( posts, { registry, onActionPerformed } ) { + const { createSuccessNotice, createErrorNotice } = + registry.dispatch( noticesStore ); + const { editEntityRecord, saveEditedEntityRecord } = + registry.dispatch( coreStore ); + await Promise.allSettled( + posts.map( ( post ) => { + return editEntityRecord( 'postType', post.type, post.id, { + status: 'draft', + } ); + } ) + ); + const promiseResult = await Promise.allSettled( + posts.map( ( post ) => { + return saveEditedEntityRecord( 'postType', post.type, post.id, { + throwOnError: true, + } ); + } ) + ); + + if ( promiseResult.every( ( { status } ) => status === 'fulfilled' ) ) { + let successMessage; + if ( posts.length === 1 ) { + successMessage = sprintf( + /* translators: The number of posts. */ + __( '"%s" has been restored.' ), + getItemTitle( posts[ 0 ] ) + ); + } else if ( posts[ 0 ].type === 'page' ) { + successMessage = sprintf( + /* translators: The number of posts. */ + __( '%d pages have been restored.' ), + posts.length + ); + } else { + successMessage = sprintf( + /* translators: The number of posts. */ + __( '%d posts have been restored.' ), + posts.length + ); + } + createSuccessNotice( successMessage, { + type: 'snackbar', + id: 'restore-post-action', + } ); + if ( onActionPerformed ) { + onActionPerformed( posts ); + } + } else { + // If there was at lease one failure. + let errorMessage; + // If we were trying to move a single post to the trash. + 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 restoring the post.' + ); + } + // If we were trying to move multiple posts to the trash + } 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 restoring the posts.' + ); + } else if ( errorMessages.size === 1 ) { + errorMessage = sprintf( + /* translators: %s: an error message */ + __( 'An error occurred while restoring the posts: %s' ), + [ ...errorMessages ][ 0 ] + ); + } else { + errorMessage = sprintf( + /* translators: %s: a list of comma separated error messages */ + __( + 'Some errors occurred while restoring the posts: %s' + ), + [ ...errorMessages ].join( ',' ) + ); + } + } + createErrorNotice( errorMessage, { + type: 'snackbar', + } ); + } + }, +}; + +export default restorePost;