diff --git a/docs/reference-guides/data/data-core.md b/docs/reference-guides/data/data-core.md
index 88db705f23f122..ba77f065584cfe 100644
--- a/docs/reference-guides/data/data-core.md
+++ b/docs/reference-guides/data/data-core.md
@@ -790,7 +790,7 @@ _Parameters_
- _kind_ `string`: Kind of the entity.
- _name_ `string`: Name of the entity.
- _recordId_ `Object`: ID of the record.
-- _options_ `Object`: Saving options.
+- _options_ `Object=`: Saving options.
### saveEntityRecord
diff --git a/packages/core-data/README.md b/packages/core-data/README.md
index 20ed0d4c660e2f..694f780dafb99d 100644
--- a/packages/core-data/README.md
+++ b/packages/core-data/README.md
@@ -299,7 +299,7 @@ _Parameters_
- _kind_ `string`: Kind of the entity.
- _name_ `string`: Name of the entity.
- _recordId_ `Object`: ID of the record.
-- _options_ `Object`: Saving options.
+- _options_ `Object=`: Saving options.
### saveEntityRecord
diff --git a/packages/core-data/src/actions.js b/packages/core-data/src/actions.js
index 36b0ba5f84c9d1..53ab935d868a37 100644
--- a/packages/core-data/src/actions.js
+++ b/packages/core-data/src/actions.js
@@ -773,10 +773,10 @@ export const __experimentalBatch =
/**
* Action triggered to save an entity record's edits.
*
- * @param {string} kind Kind of the entity.
- * @param {string} name Name of the entity.
- * @param {Object} recordId ID of the record.
- * @param {Object} options Saving options.
+ * @param {string} kind Kind of the entity.
+ * @param {string} name Name of the entity.
+ * @param {Object} recordId ID of the record.
+ * @param {Object=} options Saving options.
*/
export const saveEditedEntityRecord =
( kind, name, recordId, options ) =>
diff --git a/packages/editor/src/components/post-actions/actions.js b/packages/editor/src/components/post-actions/actions.js
index e38c64ddb3d7e6..cd1036faacdfd2 100644
--- a/packages/editor/src/components/post-actions/actions.js
+++ b/packages/editor/src/components/post-actions/actions.js
@@ -31,7 +31,6 @@ import {
} from '../../store/constants';
import { store as editorStore } from '../../store';
import { unlock } from '../../lock-unlock';
-import isTemplateRevertable from '../../store/utils/is-template-revertable';
import { exportPatternAsJSONAction } from './export-pattern-action';
import { CreateTemplatePartModalContents } from '../create-template-part-modal';
@@ -804,114 +803,6 @@ const useDuplicatePostAction = ( postType ) => {
);
};
-const resetTemplateAction = {
- id: 'reset-template',
- label: __( 'Reset' ),
- isEligible: ( item ) => {
- return isTemplateRevertable( item );
- },
- icon: backup,
- supportsBulk: true,
- hideModalHeader: true,
- RenderModal: ( { items, closeModal, onActionPerformed } ) => {
- const [ isBusy, setIsBusy ] = useState( false );
- const { revertTemplate } = unlock( useDispatch( editorStore ) );
- const { saveEditedEntityRecord } = useDispatch( coreStore );
- const { createSuccessNotice, createErrorNotice } =
- useDispatch( noticesStore );
- const onConfirm = async () => {
- try {
- for ( const template of items ) {
- await revertTemplate( template, {
- allowUndo: false,
- } );
- await saveEditedEntityRecord(
- 'postType',
- template.type,
- template.id
- );
- }
- createSuccessNotice(
- items.length > 1
- ? sprintf(
- /* translators: The number of items. */
- __( '%s items reset.' ),
- items.length
- )
- : sprintf(
- /* translators: The template/part's name. */
- __( '"%s" reset.' ),
- decodeEntities( getItemTitle( items[ 0 ] ) )
- ),
- {
- type: 'snackbar',
- id: 'revert-template-action',
- }
- );
- } catch ( error ) {
- let fallbackErrorMessage;
- if ( items[ 0 ].type === TEMPLATE_POST_TYPE ) {
- fallbackErrorMessage =
- items.length === 1
- ? __(
- 'An error occurred while reverting the template.'
- )
- : __(
- 'An error occurred while reverting the templates.'
- );
- } else {
- fallbackErrorMessage =
- items.length === 1
- ? __(
- 'An error occurred while reverting the template part.'
- )
- : __(
- 'An error occurred while reverting the template parts.'
- );
- }
- const errorMessage =
- error.message && error.code !== 'unknown_error'
- ? error.message
- : fallbackErrorMessage;
-
- createErrorNotice( errorMessage, { type: 'snackbar' } );
- }
- };
- return (
-
-
- { __( 'Reset to default and clear all customizations?' ) }
-
-
-
-
-
-
- );
- },
-};
-
export const duplicatePatternAction = {
id: 'duplicate-pattern',
label: _x( 'Duplicate', 'action label' ),
@@ -1037,9 +928,7 @@ export function usePostActions( { postType, onActionPerformed, context } ) {
isPattern && userCanCreatePostType && duplicatePatternAction,
supportsTitle && renamePostActionForPostType,
isPattern && exportPatternAsJSONAction,
- isTemplateOrTemplatePart
- ? resetTemplateAction
- : restorePostActionForPostType,
+ ! isTemplateOrTemplatePart && restorePostActionForPostType,
! isTemplateOrTemplatePart &&
! isPattern &&
trashPostActionForPostType,
diff --git a/packages/editor/src/dataviews/actions/index.ts b/packages/editor/src/dataviews/actions/index.ts
index 87589d68262f3e..7442c529f85711 100644
--- a/packages/editor/src/dataviews/actions/index.ts
+++ b/packages/editor/src/dataviews/actions/index.ts
@@ -7,6 +7,8 @@ import { type StoreDescriptor, dispatch } from '@wordpress/data';
* Internal dependencies
*/
import deletePost from './delete-post';
+import resetPost from './reset-post';
+
// @ts-ignore
import { store as editorStore } from '../../store';
import { unlock } from '../../lock-unlock';
@@ -16,5 +18,6 @@ export default function registerDefaultActions() {
dispatch( editorStore as StoreDescriptor )
);
+ registerEntityAction( 'postType', '*', resetPost );
registerEntityAction( 'postType', '*', deletePost );
}
diff --git a/packages/editor/src/dataviews/actions/reset-post.tsx b/packages/editor/src/dataviews/actions/reset-post.tsx
new file mode 100644
index 00000000000000..56440e6da33838
--- /dev/null
+++ b/packages/editor/src/dataviews/actions/reset-post.tsx
@@ -0,0 +1,144 @@
+/**
+ * WordPress dependencies
+ */
+import { backup } from '@wordpress/icons';
+import { useDispatch } from '@wordpress/data';
+import { store as coreStore } from '@wordpress/core-data';
+import { __, _n, sprintf, _x } from '@wordpress/i18n';
+import { store as noticesStore } from '@wordpress/notices';
+import { useState } from '@wordpress/element';
+import {
+ Button,
+ __experimentalText as Text,
+ __experimentalHStack as HStack,
+ __experimentalVStack as VStack,
+} from '@wordpress/components';
+import type { Action } from '@wordpress/dataviews';
+import type { StoreDescriptor } from '@wordpress/data';
+
+/**
+ * Internal dependencies
+ */
+import { TEMPLATE_POST_TYPE, TEMPLATE_ORIGINS } from '../../store/constants';
+import { store as editorStore } from '../../store';
+import { unlock } from '../../lock-unlock';
+import type { Post, CoreDataError } from '../types';
+import { isTemplateOrTemplatePart, getItemTitle } from './utils';
+
+const resetPost: Action< Post > = {
+ id: 'reset-post',
+ label: __( 'Reset' ),
+ isEligible: ( item ) => {
+ return (
+ isTemplateOrTemplatePart( item ) &&
+ item?.source === TEMPLATE_ORIGINS.custom &&
+ item?.has_theme_file
+ );
+ },
+ icon: backup,
+ supportsBulk: true,
+ hideModalHeader: true,
+ RenderModal: ( { items, closeModal, onActionPerformed } ) => {
+ const [ isBusy, setIsBusy ] = useState( false );
+ const { revertTemplate } = unlock(
+ useDispatch( editorStore as StoreDescriptor )
+ );
+ const { saveEditedEntityRecord } = useDispatch( coreStore );
+ const { createSuccessNotice, createErrorNotice } =
+ useDispatch( noticesStore );
+ const onConfirm = async () => {
+ try {
+ for ( const template of items ) {
+ await revertTemplate( template, {
+ allowUndo: false,
+ } );
+ await saveEditedEntityRecord(
+ 'postType',
+ template.type,
+ template.id
+ );
+ }
+ createSuccessNotice(
+ items.length > 1
+ ? sprintf(
+ /* translators: The number of items. */
+ __( '%s items reset.' ),
+ items.length
+ )
+ : sprintf(
+ /* translators: The template/part's name. */
+ __( '"%s" reset.' ),
+ getItemTitle( items[ 0 ] )
+ ),
+ {
+ type: 'snackbar',
+ id: 'revert-template-action',
+ }
+ );
+ } catch ( error ) {
+ let fallbackErrorMessage;
+ if ( items[ 0 ].type === TEMPLATE_POST_TYPE ) {
+ fallbackErrorMessage =
+ items.length === 1
+ ? __(
+ 'An error occurred while reverting the template.'
+ )
+ : __(
+ 'An error occurred while reverting the templates.'
+ );
+ } else {
+ fallbackErrorMessage =
+ items.length === 1
+ ? __(
+ 'An error occurred while reverting the template part.'
+ )
+ : __(
+ 'An error occurred while reverting the template parts.'
+ );
+ }
+
+ const typedError = error as CoreDataError;
+ const errorMessage =
+ typedError.message && typedError.code !== 'unknown_error'
+ ? typedError.message
+ : fallbackErrorMessage;
+
+ createErrorNotice( errorMessage, { type: 'snackbar' } );
+ }
+ };
+ return (
+
+
+ { __( 'Reset to default and clear all customizations?' ) }
+
+
+
+
+
+
+ );
+ },
+};
+
+export default resetPost;
diff --git a/packages/editor/src/dataviews/types.ts b/packages/editor/src/dataviews/types.ts
index c1771801d8ee37..29f4358456324d 100644
--- a/packages/editor/src/dataviews/types.ts
+++ b/packages/editor/src/dataviews/types.ts
@@ -11,11 +11,16 @@ export interface BasePost {
status?: PostStatus;
title: string | { rendered: string };
type: string;
+ id: string | number;
}
export interface TemplateOrTemplatePart extends BasePost {
- type: 'template' | 'template-part';
+ type: 'wp_template' | 'wp_template_part';
source: string;
has_theme_file: boolean;
+ id: string;
}
export type Post = TemplateOrTemplatePart | BasePost;
+
+// Will be unnecessary after typescript 5.0 upgrade.
+export type CoreDataError = { message?: string; code?: string };