diff --git a/packages/edit-site/src/components/editor/index.js b/packages/edit-site/src/components/editor/index.js
index ef5147c35858f..55cd4506a082c 100644
--- a/packages/edit-site/src/components/editor/index.js
+++ b/packages/edit-site/src/components/editor/index.js
@@ -50,6 +50,7 @@ import CanvasLoader from '../canvas-loader';
import { unlock } from '../../lock-unlock';
import useEditedEntityRecord from '../use-edited-entity-record';
import PatternModal from '../pattern-modal';
+import PageModal from '../page-modal';
import { POST_TYPE_LABELS, TEMPLATE_POST_TYPE } from '../../utils/constants';
import SiteEditorCanvas from '../block-editor/site-editor-canvas';
import TemplatePartConverter from '../template-part-converter';
@@ -229,6 +230,7 @@ export default function Editor( { isLoading, onClick } ) {
) }
+
>
) }
{ editorMode === 'text' && isEditMode && (
diff --git a/packages/edit-site/src/components/page-modal/index.js b/packages/edit-site/src/components/page-modal/index.js
new file mode 100644
index 0000000000000..0bb77a11ec5f7
--- /dev/null
+++ b/packages/edit-site/src/components/page-modal/index.js
@@ -0,0 +1,17 @@
+/**
+ * Internal dependencies
+ */
+import PageRenameModal from './rename';
+
+export const PAGE_MODALS = {
+ rename: 'edit-site/page-rename',
+};
+
+export default function PageModal() {
+ return (
+ <>
+ { /* Possibly more Page related commands needing modals to come, hence this wrapper */ }
+
+ >
+ );
+}
diff --git a/packages/edit-site/src/components/page-modal/rename.js b/packages/edit-site/src/components/page-modal/rename.js
new file mode 100644
index 0000000000000..f33bebb369337
--- /dev/null
+++ b/packages/edit-site/src/components/page-modal/rename.js
@@ -0,0 +1,56 @@
+/**
+ * WordPress dependencies
+ */
+import { Modal } from '@wordpress/components';
+import { useDispatch, useSelect } from '@wordpress/data';
+import {
+ store as editorStore,
+ privateApis as editorPrivateApis,
+} from '@wordpress/editor';
+import { __ } from '@wordpress/i18n';
+import { store as interfaceStore } from '@wordpress/interface';
+
+/**
+ * Internal dependencies
+ */
+import { unlock } from '../../lock-unlock';
+import { PAGE_MODALS } from './';
+import useEditedEntityRecord from '../use-edited-entity-record';
+
+const { RenamePostModalContent } = unlock( editorPrivateApis );
+
+export default function PageRenameModal() {
+ const { postId, postType } = useSelect( ( select ) => {
+ const { getCurrentPostType, getCurrentPostId } = select( editorStore );
+
+ return {
+ postId: getCurrentPostId(),
+ postType: getCurrentPostType(),
+ };
+ }, [] );
+
+ const { record: page } = useEditedEntityRecord( postType, postId );
+ const { closeModal } = useDispatch( interfaceStore );
+ const isActive = useSelect( ( select ) =>
+ select( interfaceStore ).isModalActive( PAGE_MODALS.rename )
+ );
+
+ if ( ! isActive ) {
+ return null;
+ }
+
+ return (
+
+
+
+ );
+}
diff --git a/packages/edit-site/src/components/page-pages/index.js b/packages/edit-site/src/components/page-pages/index.js
index c6b6d95e57a51..840d79083d264 100644
--- a/packages/edit-site/src/components/page-pages/index.js
+++ b/packages/edit-site/src/components/page-pages/index.js
@@ -21,6 +21,7 @@ import { privateApis as editorPrivateApis } from '@wordpress/editor';
* Internal dependencies
*/
import Page from '../page';
+import PageCommandsModal from '../page-modal';
import { default as Link, useLink } from '../routes/link';
import {
DEFAULT_VIEWS,
@@ -411,6 +412,7 @@ export default function PagePages() {
onChangeView={ onChangeView }
onSelectionChange={ onSelectionChange }
/>
+ { view?.type !== LAYOUT_LIST && }
);
}
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 a6ab867d043ec..f4b829f34d7d0 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
@@ -32,6 +32,7 @@ import isTemplateRevertable from '../../utils/is-template-revertable';
import { KEYBOARD_SHORTCUT_HELP_MODAL_NAME } from '../../components/keyboard-shortcut-help-modal';
import { PREFERENCES_MODAL_NAME } from '../../components/preferences-modal';
import { PATTERN_MODALS } from '../../components/pattern-modal';
+import { PAGE_MODALS } from '../../components/page-modal';
import { unlock } from '../../lock-unlock';
import { TEMPLATE_POST_TYPE } from '../../utils/constants';
import { useLink } from '../../components/routes/link';
@@ -99,6 +100,45 @@ function usePageContentFocusCommands() {
return { isLoading: false, commands };
}
+function useManipulateEditedDocumentCommands() {
+ const { isPage, postId, postType } = useSelect( ( select ) => {
+ const { isPage: _isPage } = unlock( select( editSiteStore ) );
+ const { getCurrentPostType, getCurrentPostId } = select( editorStore );
+
+ return {
+ isPage: _isPage(),
+ postId: getCurrentPostId(),
+ postType: getCurrentPostType(),
+ };
+ }, [] );
+
+ const { isLoaded, record } = useEditedEntityRecord( postType, postId );
+ const { openModal } = useDispatch( interfaceStore );
+
+ if ( ! isLoaded ) {
+ return { isLoading: true, commands: [] };
+ }
+
+ const commands = [];
+
+ if ( isPage && !! record ) {
+ commands.push( {
+ name: 'core/rename-page',
+ label: __( 'Rename page' ),
+ icon: edit,
+ callback: ( { close } ) => {
+ openModal( PAGE_MODALS.rename );
+ close();
+ },
+ } );
+ }
+
+ return {
+ isLoading: ! isLoaded,
+ commands,
+ };
+}
+
function useManipulateDocumentCommands() {
const { isLoaded, record: template } = useEditedEntityRecord();
const { removeTemplate, revertTemplate } = useDispatch( editSiteStore );
@@ -294,6 +334,12 @@ export function useEditModeCommands() {
hook: useManipulateDocumentCommands,
} );
+ useCommandLoader( {
+ name: 'core/edit-site/manipulate-edited-document',
+ hook: useManipulateEditedDocumentCommands,
+ context: 'site-editor-edit',
+ } );
+
useCommandLoader( {
name: 'core/edit-site/patterns',
hook: usePatternCommands,
diff --git a/packages/editor/src/components/post-actions/actions.js b/packages/editor/src/components/post-actions/actions.js
index 7d38fc93e222d..6e38b28ff6051 100644
--- a/packages/editor/src/components/post-actions/actions.js
+++ b/packages/editor/src/components/post-actions/actions.js
@@ -8,16 +8,19 @@ import { decodeEntities } from '@wordpress/html-entities';
import { store as coreStore } from '@wordpress/core-data';
import { __, _n, sprintf } from '@wordpress/i18n';
import { store as noticesStore } from '@wordpress/notices';
-import { useMemo, useState } from '@wordpress/element';
-
+import { useMemo } from '@wordpress/element';
import {
Button,
- TextControl,
__experimentalText as Text,
__experimentalHStack as HStack,
__experimentalVStack as VStack,
} from '@wordpress/components';
+/**
+ * Internal dependencies
+ */
+import RenamePostModalContent from './rename-post-modal-content';
+
function getItemTitle( item ) {
if ( typeof item.title === 'string' ) {
return decodeEntities( item.title );
@@ -420,75 +423,7 @@ export const renamePostAction = {
isEligible( post ) {
return post.status !== 'trash';
},
- RenderModal: ( { items, closeModal } ) => {
- const [ item ] = items;
- const originalTitle = decodeEntities(
- typeof item.title === 'string' ? item.title : item.title.rendered
- );
- const [ title, setTitle ] = useState( () => originalTitle );
- const { editEntityRecord, saveEditedEntityRecord } =
- useDispatch( coreStore );
- const { createSuccessNotice, createErrorNotice } =
- useDispatch( noticesStore );
-
- async function onRename( event ) {
- event.preventDefault();
- try {
- await editEntityRecord( 'postType', item.type, item.id, {
- title,
- } );
- // Update state before saving rerenders the list.
- setTitle( '' );
- closeModal();
- // Persist edited entity.
- await saveEditedEntityRecord( 'postType', item.type, item.id, {
- throwOnError: true,
- } );
- createSuccessNotice( __( 'Name updated' ), {
- type: 'snackbar',
- } );
- } catch ( error ) {
- const errorMessage =
- error.message && error.code !== 'unknown_error'
- ? error.message
- : __( 'An error occurred while updating the name' );
- createErrorNotice( errorMessage, { type: 'snackbar' } );
- }
- }
-
- return (
-
- );
- },
+ RenderModal: RenamePostModalContent,
};
export function usePostActions( onActionPerformed, actionIds = null ) {
diff --git a/packages/editor/src/components/post-actions/rename-post-modal-content.js b/packages/editor/src/components/post-actions/rename-post-modal-content.js
new file mode 100644
index 0000000000000..ff77425b22cf6
--- /dev/null
+++ b/packages/editor/src/components/post-actions/rename-post-modal-content.js
@@ -0,0 +1,86 @@
+/**
+ * WordPress dependencies
+ */
+import {
+ Button,
+ TextControl,
+ __experimentalHStack as HStack,
+ __experimentalVStack as VStack,
+} from '@wordpress/components';
+import { store as coreStore } from '@wordpress/core-data';
+import { useDispatch } from '@wordpress/data';
+import { useState } from '@wordpress/element';
+import { decodeEntities } from '@wordpress/html-entities';
+import { __ } from '@wordpress/i18n';
+import { store as noticesStore } from '@wordpress/notices';
+
+export default function RenamePostModalContent( { items, closeModal } ) {
+ const [ item ] = items;
+ const originalTitle = decodeEntities(
+ typeof item.title === 'string' ? item.title : item.title.rendered
+ );
+ const [ title, setTitle ] = useState( () => originalTitle );
+ const { editEntityRecord, saveEditedEntityRecord } =
+ useDispatch( coreStore );
+ const { createSuccessNotice, createErrorNotice } =
+ useDispatch( noticesStore );
+
+ async function onRename( event ) {
+ event.preventDefault();
+ try {
+ await editEntityRecord( 'postType', item.type, item.id, {
+ title,
+ } );
+ // Update state before saving rerenders the list.
+ setTitle( '' );
+ closeModal();
+ // Persist edited entity.
+ await saveEditedEntityRecord( 'postType', item.type, item.id, {
+ throwOnError: true,
+ } );
+ createSuccessNotice( __( 'Name updated' ), {
+ id: 'page-update',
+ type: 'snackbar',
+ } );
+ } catch ( error ) {
+ const errorMessage =
+ error.message && error.code !== 'unknown_error'
+ ? error.message
+ : __( 'An error occurred while updating the name' );
+ createErrorNotice( errorMessage, { type: 'snackbar' } );
+ }
+ }
+
+ return (
+
+ );
+}
diff --git a/packages/editor/src/private-apis.js b/packages/editor/src/private-apis.js
index ea42d6ad5fde5..47719f881e27a 100644
--- a/packages/editor/src/private-apis.js
+++ b/packages/editor/src/private-apis.js
@@ -18,6 +18,7 @@ import PreviewDropdown from './components/preview-dropdown';
import PreferencesModal from './components/preferences-modal';
import { usePostActions } from './components/post-actions/actions';
import PostCardPanel from './components/post-card-panel';
+import RenamePostModalContent from './components/post-actions/rename-post-modal-content';
export const privateApis = {};
lock( privateApis, {
@@ -36,6 +37,7 @@ lock( privateApis, {
PreferencesModal,
usePostActions,
PostCardPanel,
+ RenamePostModalContent,
// This is a temporary private API while we're updating the site editor to use EditorProvider.
useBlockEditorSettings,