diff --git a/packages/editor/src/components/post-actions/actions.js b/packages/editor/src/components/post-actions/actions.js
index ff5cd7ddbb5452..0df73d1996deb5 100644
--- a/packages/editor/src/components/post-actions/actions.js
+++ b/packages/editor/src/components/post-actions/actions.js
@@ -9,7 +9,6 @@ import { store as coreStore } from '@wordpress/core-data';
import { __, sprintf, _x } from '@wordpress/i18n';
import { store as noticesStore } from '@wordpress/notices';
import { useMemo, useState, useEffect } from '@wordpress/element';
-import { parse } from '@wordpress/blocks';
import { DataForm } from '@wordpress/dataviews';
import {
Button,
@@ -27,7 +26,6 @@ import {
} from '../../store/constants';
import { store as editorStore } from '../../store';
import { unlock } from '../../lock-unlock';
-import { CreateTemplatePartModalContents } from '../create-template-part-modal';
import { getItemTitle } from '../../dataviews/actions/utils';
// TODO: this should be shared with other components (see post-fields in edit-site).
@@ -268,75 +266,14 @@ const useDuplicatePostAction = ( postType ) => {
);
};
-export const duplicateTemplatePartAction = {
- id: 'duplicate-template-part',
- label: _x( 'Duplicate', 'action label' ),
- isEligible: ( item ) => item.type === TEMPLATE_PART_POST_TYPE,
- modalHeader: _x( 'Duplicate template part', 'action label' ),
- RenderModal: ( { items, closeModal } ) => {
- const [ item ] = items;
- const blocks = useMemo( () => {
- return (
- item.blocks ??
- parse(
- typeof item.content === 'string'
- ? item.content
- : item.content.raw,
- {
- __unstableSkipMigrationLogs: true,
- }
- )
- );
- }, [ item.content, item.blocks ] );
- const { createSuccessNotice } = useDispatch( noticesStore );
- function onTemplatePartSuccess() {
- createSuccessNotice(
- sprintf(
- // translators: %s: The new template part's title e.g. 'Call to action (copy)'.
- __( '"%s" duplicated.' ),
- getItemTitle( item )
- ),
- { type: 'snackbar', id: 'edit-site-patterns-success' }
- );
- closeModal();
- }
- return (
-
- );
- },
-};
-
export function usePostActions( { postType, onActionPerformed, context } ) {
- const {
- defaultActions,
- postTypeObject,
- userCanCreatePostType,
- isBlockBasedTheme,
- } = useSelect(
+ const { defaultActions, postTypeObject } = useSelect(
( select ) => {
- const { getPostType, canUser, getCurrentTheme } =
- select( coreStore );
+ const { getPostType } = select( coreStore );
const { getEntityActions } = unlock( select( editorStore ) );
return {
postTypeObject: getPostType( postType ),
defaultActions: getEntityActions( 'postType', postType ),
- userCanCreatePostType: canUser( 'create', {
- kind: 'postType',
- name: postType,
- } ),
- isBlockBasedTheme: getCurrentTheme()?.is_block_theme,
};
},
[ postType ]
@@ -368,10 +305,6 @@ export function usePostActions( { postType, onActionPerformed, context } ) {
! isPattern &&
duplicatePostAction
: false,
- isTemplateOrTemplatePart &&
- userCanCreatePostType &&
- isBlockBasedTheme &&
- duplicateTemplatePartAction,
...defaultActions,
].filter( Boolean );
// Filter actions based on provided context. If not provided
@@ -437,7 +370,6 @@ export function usePostActions( { postType, onActionPerformed, context } ) {
return actions;
}, [
defaultActions,
- userCanCreatePostType,
isTemplateOrTemplatePart,
isPattern,
postTypeObject?.viewable,
diff --git a/packages/editor/src/dataviews/actions/duplicate-template-part.tsx b/packages/editor/src/dataviews/actions/duplicate-template-part.tsx
new file mode 100644
index 00000000000000..fa3cf39ba76268
--- /dev/null
+++ b/packages/editor/src/dataviews/actions/duplicate-template-part.tsx
@@ -0,0 +1,70 @@
+/**
+ * WordPress dependencies
+ */
+import { useDispatch } from '@wordpress/data';
+import { __, sprintf, _x } from '@wordpress/i18n';
+import { store as noticesStore } from '@wordpress/notices';
+import { useMemo } from '@wordpress/element';
+// @ts-ignore
+import { parse } from '@wordpress/blocks';
+import type { Action } from '@wordpress/dataviews';
+
+/**
+ * Internal dependencies
+ */
+import { TEMPLATE_PART_POST_TYPE } from '../../store/constants';
+import { CreateTemplatePartModalContents } from '../../components/create-template-part-modal';
+import { getItemTitle } from './utils';
+import type { TemplatePart } from '../types';
+
+const duplicateTemplatePart: Action< TemplatePart > = {
+ id: 'duplicate-template-part',
+ label: _x( 'Duplicate', 'action label' ),
+ isEligible: ( item ) => item.type === TEMPLATE_PART_POST_TYPE,
+ modalHeader: _x( 'Duplicate template part', 'action label' ),
+ RenderModal: ( { items, closeModal } ) => {
+ const [ item ] = items;
+ const blocks = useMemo( () => {
+ return (
+ item.blocks ??
+ parse(
+ typeof item.content === 'string'
+ ? item.content
+ : item.content.raw,
+ {
+ __unstableSkipMigrationLogs: true,
+ }
+ )
+ );
+ }, [ item.content, item.blocks ] );
+ const { createSuccessNotice } = useDispatch( noticesStore );
+ function onTemplatePartSuccess() {
+ createSuccessNotice(
+ sprintf(
+ // translators: %s: The new template part's title e.g. 'Call to action (copy)'.
+ __( '"%s" duplicated.' ),
+ getItemTitle( item )
+ ),
+ { type: 'snackbar', id: 'edit-site-patterns-success' }
+ );
+ closeModal?.();
+ }
+ return (
+
+ );
+ },
+};
+
+export default duplicateTemplatePart;
diff --git a/packages/editor/src/dataviews/store/private-actions.ts b/packages/editor/src/dataviews/store/private-actions.ts
index 6854c29bb0c4e4..80449d1b7a0798 100644
--- a/packages/editor/src/dataviews/store/private-actions.ts
+++ b/packages/editor/src/dataviews/store/private-actions.ts
@@ -10,6 +10,7 @@ import { doAction } from '@wordpress/hooks';
*/
import deletePost from '../actions/delete-post';
import duplicatePattern from '../actions/duplicate-pattern';
+import duplicateTemplatePart from '../actions/duplicate-template-part';
import exportPattern from '../actions/export-pattern';
import resetPost from '../actions/reset-post';
import trashPost from '../actions/trash-post';
@@ -81,8 +82,15 @@ export const registerPostTypeActions =
kind: 'postType',
name: postType,
} );
+ const currentTheme = await registry
+ .resolveSelect( coreStore )
+ .getCurrentTheme();
const actions = [
+ postTypeConfig.slug === 'wp_template_part' &&
+ canCreate &&
+ currentTheme?.is_block_theme &&
+ duplicateTemplatePart,
canCreate && postTypeConfig.slug === 'wp_block'
? duplicatePattern
: undefined,
diff --git a/packages/editor/src/dataviews/types.ts b/packages/editor/src/dataviews/types.ts
index 80b6f3c5ceb852..5750ab96eeae81 100644
--- a/packages/editor/src/dataviews/types.ts
+++ b/packages/editor/src/dataviews/types.ts
@@ -10,8 +10,10 @@ type PostStatus =
export interface BasePost {
status?: PostStatus;
title: string | { rendered: string } | { raw: string };
+ content: string | { raw: string; rendered: string };
type: string;
id: string | number;
+ blocks?: Object[];
}
export interface Template extends BasePost {
@@ -27,12 +29,12 @@ export interface TemplatePart extends BasePost {
source: string;
has_theme_file: boolean;
id: string;
+ area: string;
}
export interface Pattern extends BasePost {
slug: string;
title: { raw: string };
- content: { raw: string } | string;
wp_pattern_sync_status: string;
}