diff --git a/packages/edit-site/src/components/create-template-part-modal/index.js b/packages/edit-site/src/components/create-template-part-modal/index.js index 31f12b6cab56d..cf8d9e599e34f 100644 --- a/packages/edit-site/src/components/create-template-part-modal/index.js +++ b/packages/edit-site/src/components/create-template-part-modal/index.js @@ -42,6 +42,7 @@ export default function CreateTemplatePartModal( { defaultArea = TEMPLATE_PART_AREA_DEFAULT_CATEGORY, blocks = [], confirmLabel = __( 'Create' ), + content, closeModal, modalTitle = __( 'Create template part' ), onCreate, @@ -82,7 +83,7 @@ export default function CreateTemplatePartModal( { { slug: cleanSlug, title: uniqueTitle, - content: serialize( blocks ), + content: content || serialize( blocks ), area, }, { throwOnError: true } diff --git a/packages/edit-site/src/components/duplicate-template-part-modal/index.js b/packages/edit-site/src/components/duplicate-template-part-modal/index.js new file mode 100644 index 0000000000000..cb6f5e0b4a8a1 --- /dev/null +++ b/packages/edit-site/src/components/duplicate-template-part-modal/index.js @@ -0,0 +1,54 @@ +/** + * WordPress dependencies + */ +import { useDispatch } from '@wordpress/data'; +import { __, sprintf } from '@wordpress/i18n'; +import { store as noticesStore } from '@wordpress/notices'; + +/** + * Internal dependencies + */ +import CreateTemplatePartModal from '../create-template-part-modal'; + +export default function DuplicateTemplatePartModal( { + templatePart, + onClose, + onSuccess, +} ) { + const { createSuccessNotice } = useDispatch( noticesStore ); + + function handleOnSuccess( newTemplatePart ) { + createSuccessNotice( + sprintf( + // translators: %s: The new template part's title e.g. 'Call to action (copy)'. + __( '"%s" duplicated.' ), + templatePart.title + ), + { + type: 'snackbar', + id: 'template-parts-create', + } + ); + + onSuccess?.( newTemplatePart ); + } + + return ( + + ); +} diff --git a/packages/edit-site/src/components/page-patterns/duplicate-menu-item.js b/packages/edit-site/src/components/page-patterns/duplicate-menu-item.js index 118c954a851f3..4a067465fa2f1 100644 --- a/packages/edit-site/src/components/page-patterns/duplicate-menu-item.js +++ b/packages/edit-site/src/components/page-patterns/duplicate-menu-item.js @@ -2,10 +2,8 @@ * WordPress dependencies */ import { MenuItem } from '@wordpress/components'; -import { useDispatch } from '@wordpress/data'; import { useState } from '@wordpress/element'; -import { __, sprintf } from '@wordpress/i18n'; -import { store as noticesStore } from '@wordpress/notices'; +import { __ } from '@wordpress/i18n'; import { privateApis as patternsPrivateApis } from '@wordpress/patterns'; import { privateApis as routerPrivateApis } from '@wordpress/router'; @@ -14,7 +12,7 @@ import { privateApis as routerPrivateApis } from '@wordpress/router'; */ import { TEMPLATE_PART_POST_TYPE, PATTERN_TYPES } from '../../utils/constants'; import { unlock } from '../../lock-unlock'; -import CreateTemplatePartModal from '../create-template-part-modal'; +import DuplicateTemplatePartModal from '../duplicate-template-part-modal'; const { DuplicatePatternModal } = unlock( patternsPrivateApis ); const { useHistory } = unlock( routerPrivateApis ); @@ -25,7 +23,6 @@ export default function DuplicateMenuItem( { label = __( 'Duplicate' ), onClose, } ) { - const { createSuccessNotice } = useDispatch( noticesStore ); const [ isModalOpen, setIsModalOpen ] = useState( false ); const history = useHistory(); @@ -35,18 +32,6 @@ export default function DuplicateMenuItem( { const isThemePattern = item.type === PATTERN_TYPES.theme; async function onTemplatePartSuccess( templatePart ) { - createSuccessNotice( - sprintf( - // translators: %s: The new template part's title e.g. 'Call to action (copy)'. - __( '"%s" duplicated.' ), - item.title - ), - { - type: 'snackbar', - id: 'edit-site-patterns-success', - } - ); - history.push( { postType: TEMPLATE_PART_POST_TYPE, postId: templatePart?.id, @@ -85,19 +70,10 @@ export default function DuplicateMenuItem( { /> ) } { isModalOpen && isTemplatePart && ( - ) } diff --git a/packages/edit-site/src/components/template-part-modal/duplicate.js b/packages/edit-site/src/components/template-part-modal/duplicate.js new file mode 100644 index 0000000000000..192ec93a42016 --- /dev/null +++ b/packages/edit-site/src/components/template-part-modal/duplicate.js @@ -0,0 +1,52 @@ +/** + * WordPress dependencies + */ +import { useDispatch, useSelect } from '@wordpress/data'; +import { store as interfaceStore } from '@wordpress/interface'; +import { privateApis as routerPrivateApis } from '@wordpress/router'; +import { getQueryArgs } from '@wordpress/url'; + +/** + * Internal dependencies + */ +import useEditedEntityRecord from '../use-edited-entity-record'; +import DuplicateTemplatePartModal from '../duplicate-template-part-modal'; +import { TEMPLATE_PART_MODALS } from './'; +import { unlock } from '../../lock-unlock'; +import { TEMPLATE_PART_POST_TYPE } from '../../utils/constants'; + +const { useHistory } = unlock( routerPrivateApis ); + +export default function PatternDuplicateModal() { + const { record } = useEditedEntityRecord(); + const { categoryType, categoryId } = getQueryArgs( window.location.href ); + const { closeModal } = useDispatch( interfaceStore ); + const history = useHistory(); + + const isActive = useSelect( ( select ) => + select( interfaceStore ).isModalActive( TEMPLATE_PART_MODALS.duplicate ) + ); + + if ( ! isActive ) { + return null; + } + + function onSuccess( newTemplatePart ) { + history.push( { + postType: TEMPLATE_PART_POST_TYPE, + postId: newTemplatePart.id, + categoryType, + categoryId, + } ); + + closeModal(); + } + + return ( + + ); +} diff --git a/packages/edit-site/src/components/template-part-modal/index.js b/packages/edit-site/src/components/template-part-modal/index.js index 632470483186a..aea7e909a29cc 100644 --- a/packages/edit-site/src/components/template-part-modal/index.js +++ b/packages/edit-site/src/components/template-part-modal/index.js @@ -1,6 +1,7 @@ /** * Internal dependencies */ +import TemplatePartDuplicateModal from './duplicate'; import TemplatePartRenameModal from './rename'; export const TEMPLATE_PART_MODALS = { @@ -9,11 +10,10 @@ export const TEMPLATE_PART_MODALS = { }; export default function TemplatePartModal() { - // Duplication command and modal is in separate follow-up. return ( <> - { /* */ } + ); } diff --git a/packages/edit-site/src/hooks/commands/use-edit-mode-commands.js b/packages/edit-site/src/hooks/commands/use-edit-mode-commands.js index b079c5e956121..e5e1d32cc029b 100644 --- a/packages/edit-site/src/hooks/commands/use-edit-mode-commands.js +++ b/packages/edit-site/src/hooks/commands/use-edit-mode-commands.js @@ -4,6 +4,7 @@ import { useSelect, useDispatch } from '@wordpress/data'; import { __, sprintf, isRTL } from '@wordpress/i18n'; import { + edit, trash, rotateLeft, rotateRight, @@ -398,7 +399,7 @@ function usePatternCommands() { commands.push( { name: 'core/rename-template-part', label: __( 'Rename template part' ), - icon: symbol, + icon: edit, callback: ( { close } ) => { openModal( TEMPLATE_PART_MODALS.rename ); close(); @@ -406,7 +407,15 @@ function usePatternCommands() { } ); } - // All template parts will be eligible for duplication in a follow-up. + commands.push( { + name: 'core/duplicate-template-part', + label: __( 'Duplicate template part' ), + icon: symbol, + callback: ( { close } ) => { + openModal( TEMPLATE_PART_MODALS.duplicate ); + close(); + }, + } ); } return { isLoading: false, commands };