From d2da28822deb57daad55fea33e0b3165ac4a878a Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Thu, 6 Jun 2024 10:58:31 +0100 Subject: [PATCH] Editor: Use the Editor component in the post editor. (#62339) Co-authored-by: youknowriad Co-authored-by: ramonjd --- .../edit-post/src/components/layout/index.js | 193 ++++++++++++------ .../src/components/welcome-guide/index.js | 30 +-- packages/edit-post/src/editor.js | 118 ----------- packages/edit-post/src/index.js | 18 +- packages/edit-post/src/store/index.js | 4 +- .../edit-post/src/store/private-selectors.js | 52 +++++ packages/edit-post/src/store/selectors.js | 71 +------ .../editor/src/components/editor/index.js | 51 +++-- packages/editor/src/private-apis.js | 6 - packages/editor/src/private-apis.native.js | 2 - 10 files changed, 241 insertions(+), 304 deletions(-) delete mode 100644 packages/edit-post/src/editor.js create mode 100644 packages/edit-post/src/store/private-selectors.js diff --git a/packages/edit-post/src/components/layout/index.js b/packages/edit-post/src/components/layout/index.js index ec79466580cede..cfaaf810b41918 100644 --- a/packages/edit-post/src/components/layout/index.js +++ b/packages/edit-post/src/components/layout/index.js @@ -12,6 +12,8 @@ import { UnsavedChangesWarning, EditorKeyboardShortcutsRegister, EditorSnackbars, + ErrorBoundary, + PostLockedModal, store as editorStore, privateApis as editorPrivateApis, } from '@wordpress/editor'; @@ -25,16 +27,22 @@ import { __, sprintf } from '@wordpress/i18n'; import { useCallback, useMemo } from '@wordpress/element'; import { store as noticesStore } from '@wordpress/notices'; import { store as preferencesStore } from '@wordpress/preferences'; -import { privateApis as commandsPrivateApis } from '@wordpress/commands'; +import { + CommandMenu, + privateApis as commandsPrivateApis, +} from '@wordpress/commands'; import { privateApis as coreCommandsPrivateApis } from '@wordpress/core-commands'; import { privateApis as blockLibraryPrivateApis } from '@wordpress/block-library'; import { addQueryArgs } from '@wordpress/url'; import { decodeEntities } from '@wordpress/html-entities'; +import { store as coreStore } from '@wordpress/core-data'; +import { SlotFillProvider } from '@wordpress/components'; /** * Internal dependencies */ import BackButton from '../back-button'; +import EditorInitialization from '../editor-initialization'; import EditPostKeyboardShortcuts from '../keyboard-shortcuts'; import InitPatternModal from '../init-pattern-modal'; import BrowserURL from '../browser-url'; @@ -46,12 +54,12 @@ import { unlock } from '../../lock-unlock'; import useEditPostCommands from '../../commands/use-commands'; import { usePaddingAppender } from './use-padding-appender'; import { useShouldIframe } from './use-should-iframe'; +import useNavigateToEntityRecord from '../../hooks/use-navigate-to-entity-record'; const { getLayoutStyles } = unlock( blockEditorPrivateApis ); const { useCommands } = unlock( coreCommandsPrivateApis ); const { useCommandContext } = unlock( commandsPrivateApis ); -const { EditorInterface, FullscreenMode, Sidebar } = - unlock( editorPrivateApis ); +const { Editor, FullscreenMode } = unlock( editorPrivateApis ); const { BlockKeyboardShortcuts } = unlock( blockLibraryPrivateApis ); const DESIGN_POST_TYPES = [ 'wp_template', @@ -92,7 +100,7 @@ function useEditorStyles() { ) ?? []; const defaultEditorStyles = [ - ...editorSettings.defaultEditorStyles, + ...( editorSettings?.defaultEditorStyles ?? [] ), ...presetStyles, ]; @@ -145,12 +153,26 @@ function useEditorStyles() { ] ); } -function Layout( { initialPost } ) { +function Layout( { + postId: initialPostId, + postType: initialPostType, + settings, + initialEdits, +} ) { useCommands(); useEditPostCommands(); const paddingAppenderRef = usePaddingAppender(); const shouldIframe = useShouldIframe(); const { createErrorNotice } = useDispatch( noticesStore ); + const { + currentPost, + onNavigateToEntityRecord, + onNavigateToPreviousEntityRecord, + } = useNavigateToEntityRecord( + initialPostId, + initialPostType, + 'post-only' + ); const { mode, isFullscreenActive, @@ -162,35 +184,61 @@ function Layout( { initialPost } ) { hasHistory, isEditingTemplate, isWelcomeGuideVisible, - } = useSelect( ( select ) => { - const { get } = select( preferencesStore ); - const { getEditorSettings } = select( editorStore ); - const { isFeatureActive } = select( editPostStore ); + templateId, + } = useSelect( + ( select ) => { + const { get } = select( preferencesStore ); + const { isFeatureActive, getEditedPostTemplateId } = unlock( + select( editPostStore ) + ); + const { canUser, getPostType } = select( coreStore ); - return { - mode: select( editorStore ).getEditorMode(), - isFullscreenActive: - select( editPostStore ).isFeatureActive( 'fullscreenMode' ), - hasActiveMetaboxes: select( editPostStore ).hasMetaBoxes(), - hasBlockSelected: - !! select( blockEditorStore ).getBlockSelectionStart(), - showIconLabels: get( 'core', 'showIconLabels' ), - isDistractionFree: get( 'core', 'distractionFree' ), - showMetaBoxes: - select( editorStore ).getRenderingMode() === 'post-only', - hasHistory: !! getEditorSettings().onNavigateToPreviousEntityRecord, - isEditingTemplate: - select( editorStore ).getCurrentPostType() === 'wp_template', - isWelcomeGuideVisible: isFeatureActive( 'welcomeGuide' ), - }; - }, [] ); + const supportsTemplateMode = settings.supportsTemplateMode; + const isViewable = + getPostType( currentPost.postType )?.viewable ?? false; + const canViewTemplate = canUser( 'read', 'templates' ); + + return { + mode: select( editorStore ).getEditorMode(), + isFullscreenActive: + select( editPostStore ).isFeatureActive( 'fullscreenMode' ), + hasActiveMetaboxes: select( editPostStore ).hasMetaBoxes(), + hasBlockSelected: + !! select( blockEditorStore ).getBlockSelectionStart(), + showIconLabels: get( 'core', 'showIconLabels' ), + isDistractionFree: get( 'core', 'distractionFree' ), + showMetaBoxes: + select( editorStore ).getRenderingMode() === 'post-only', + isEditingTemplate: + select( editorStore ).getCurrentPostType() === + 'wp_template', + isWelcomeGuideVisible: isFeatureActive( 'welcomeGuide' ), + templateId: + supportsTemplateMode && + isViewable && + canViewTemplate && + currentPost.postType !== 'wp_template' + ? getEditedPostTemplateId() + : null, + }; + }, + [ settings.supportsTemplateMode, currentPost.postType ] + ); // Set the right context for the command palette const commandContext = hasBlockSelected ? 'block-selection-edit' : 'entity-edit'; useCommandContext( commandContext ); - + const editorSettings = useMemo( + () => ( { + ...settings, + onNavigateToEntityRecord, + onNavigateToPreviousEntityRecord, + defaultRenderingMode: 'post-only', + } ), + [ settings, onNavigateToEntityRecord, onNavigateToPreviousEntityRecord ] + ); const styles = useEditorStyles(); // We need to add the show-icon-labels class to the body element so it is applied to modals. @@ -268,48 +316,63 @@ function Layout( { initialPost } ) { [ createSuccessNotice ] ); + const initialPost = useMemo( () => { + return { + type: initialPostType, + id: initialPostId, + }; + }, [ initialPostType, initialPostId ] ); return ( - <> - - - - - - - - - - - - { ! isDistractionFree && ( - + + + + } - /> - ) } - - - - - { ! isDistractionFree && showMetaBoxes && ( -
- - -
- ) } -
- + extraContent={ + ! isDistractionFree && + showMetaBoxes && ( +
+ + +
+ ) + } + > + + + + + + + + + + + + + + + +
+
+ ); } diff --git a/packages/edit-post/src/components/welcome-guide/index.js b/packages/edit-post/src/components/welcome-guide/index.js index 1bd2815466d9bc..fc7039fd7a87a3 100644 --- a/packages/edit-post/src/components/welcome-guide/index.js +++ b/packages/edit-post/src/components/welcome-guide/index.js @@ -2,7 +2,6 @@ * WordPress dependencies */ import { useSelect } from '@wordpress/data'; -import { store as editorStore } from '@wordpress/editor'; /** * Internal dependencies @@ -11,21 +10,22 @@ import WelcomeGuideDefault from './default'; import WelcomeGuideTemplate from './template'; import { store as editPostStore } from '../../store'; -export default function WelcomeGuide() { - const { isActive, isEditingTemplate } = useSelect( ( select ) => { - const { isFeatureActive } = select( editPostStore ); - const { getCurrentPostType } = select( editorStore ); - const _isEditingTemplate = getCurrentPostType() === 'wp_template'; +export default function WelcomeGuide( { postType } ) { + const { isActive, isEditingTemplate } = useSelect( + ( select ) => { + const { isFeatureActive } = select( editPostStore ); + const _isEditingTemplate = postType === 'wp_template'; + const feature = _isEditingTemplate + ? 'welcomeGuideTemplate' + : 'welcomeGuide'; - const feature = _isEditingTemplate - ? 'welcomeGuideTemplate' - : 'welcomeGuide'; - - return { - isActive: isFeatureActive( feature ), - isEditingTemplate: _isEditingTemplate, - }; - }, [] ); + return { + isActive: isFeatureActive( feature ), + isEditingTemplate: _isEditingTemplate, + }; + }, + [ postType ] + ); if ( ! isActive ) { return null; diff --git a/packages/edit-post/src/editor.js b/packages/edit-post/src/editor.js deleted file mode 100644 index 378265c1927788..00000000000000 --- a/packages/edit-post/src/editor.js +++ /dev/null @@ -1,118 +0,0 @@ -/** - * WordPress dependencies - */ -import { useSelect } from '@wordpress/data'; -import { - ErrorBoundary, - PostLockedModal, - store as editorStore, - privateApis as editorPrivateApis, -} from '@wordpress/editor'; -import { useMemo } from '@wordpress/element'; -import { SlotFillProvider } from '@wordpress/components'; -import { store as coreStore } from '@wordpress/core-data'; -import { CommandMenu } from '@wordpress/commands'; - -/** - * Internal dependencies - */ -import Layout from './components/layout'; -import EditorInitialization from './components/editor-initialization'; -import { store as editPostStore } from './store'; -import { unlock } from './lock-unlock'; -import useNavigateToEntityRecord from './hooks/use-navigate-to-entity-record'; - -const { ExperimentalEditorProvider } = unlock( editorPrivateApis ); - -function Editor( { - postId: initialPostId, - postType: initialPostType, - settings, - initialEdits, - ...props -} ) { - const { - currentPost, - onNavigateToEntityRecord, - onNavigateToPreviousEntityRecord, - } = useNavigateToEntityRecord( - initialPostId, - initialPostType, - 'post-only' - ); - - const { post, template } = useSelect( - ( select ) => { - const { getEditedPostTemplate } = select( editPostStore ); - const { getEntityRecord, getPostType, canUser } = - select( coreStore ); - const { getEditorSettings } = select( editorStore ); - - const postObject = getEntityRecord( - 'postType', - currentPost.postType, - currentPost.postId - ); - - const supportsTemplateMode = - getEditorSettings().supportsTemplateMode; - const isViewable = - getPostType( currentPost.postType )?.viewable ?? false; - const canViewTemplate = canUser( 'read', 'templates' ); - return { - template: - supportsTemplateMode && - isViewable && - canViewTemplate && - currentPost.postType !== 'wp_template' - ? getEditedPostTemplate() - : null, - post: postObject, - }; - }, - [ currentPost.postType, currentPost.postId ] - ); - - const editorSettings = useMemo( - () => ( { - ...settings, - onNavigateToEntityRecord, - onNavigateToPreviousEntityRecord, - defaultRenderingMode: 'post-only', - } ), - [ settings, onNavigateToEntityRecord, onNavigateToPreviousEntityRecord ] - ); - - const initialPost = useMemo( () => { - return { - type: initialPostType, - id: initialPostId, - }; - }, [ initialPostType, initialPostId ] ); - - if ( ! post ) { - return null; - } - - return ( - - - - - - - - - - - ); -} - -export default Editor; diff --git a/packages/edit-post/src/index.js b/packages/edit-post/src/index.js index 0ec4388a9af70e..152afc294f4283 100644 --- a/packages/edit-post/src/index.js +++ b/packages/edit-post/src/index.js @@ -7,7 +7,7 @@ import { __experimentalRegisterExperimentalCoreBlocks, } from '@wordpress/block-library'; import deprecated from '@wordpress/deprecated'; -import { createRoot } from '@wordpress/element'; +import { createRoot, StrictMode } from '@wordpress/element'; import { dispatch, select } from '@wordpress/data'; import { store as preferencesStore } from '@wordpress/preferences'; import { @@ -22,7 +22,7 @@ import { /** * Internal dependencies */ -import Editor from './editor'; +import Layout from './components/layout'; import { unlock } from './lock-unlock'; const { BackButton: __experimentalMainDashboardButton } = @@ -137,12 +137,14 @@ export function initializeEditor( window.addEventListener( 'drop', ( e ) => e.preventDefault(), false ); root.render( - + + + ); return root; diff --git a/packages/edit-post/src/store/index.js b/packages/edit-post/src/store/index.js index 567c022d2eb71b..17033b759292d7 100644 --- a/packages/edit-post/src/store/index.js +++ b/packages/edit-post/src/store/index.js @@ -9,7 +9,9 @@ import { createReduxStore, register } from '@wordpress/data'; import reducer from './reducer'; import * as actions from './actions'; import * as selectors from './selectors'; +import * as privateSelectors from './private-selectors'; import { STORE_NAME } from './constants'; +import { unlock } from '../lock-unlock'; /** * Store definition for the edit post namespace. @@ -23,5 +25,5 @@ export const store = createReduxStore( STORE_NAME, { actions, selectors, } ); - register( store ); +unlock( store ).registerPrivateSelectors( privateSelectors ); diff --git a/packages/edit-post/src/store/private-selectors.js b/packages/edit-post/src/store/private-selectors.js new file mode 100644 index 00000000000000..be23227d54a19b --- /dev/null +++ b/packages/edit-post/src/store/private-selectors.js @@ -0,0 +1,52 @@ +/** + * WordPress dependencies + */ +import { createRegistrySelector } from '@wordpress/data'; +import { store as coreStore } from '@wordpress/core-data'; +import { store as editorStore } from '@wordpress/editor'; + +export const getEditedPostTemplateId = createRegistrySelector( + ( select ) => () => { + const { + id: postId, + type: postType, + slug, + } = select( editorStore ).getCurrentPost(); + const { getSite, getEntityRecords } = select( coreStore ); + const siteSettings = getSite(); + // First check if the current page is set as the posts page. + const isPostsPage = +postId === siteSettings?.page_for_posts; + if ( isPostsPage ) { + return select( coreStore ).getDefaultTemplateId( { slug: 'home' } ); + } + const currentTemplate = + select( editorStore ).getEditedPostAttribute( 'template' ); + if ( currentTemplate ) { + const templateWithSameSlug = getEntityRecords( + 'postType', + 'wp_template', + { per_page: -1 } + )?.find( ( template ) => template.slug === currentTemplate ); + if ( ! templateWithSameSlug ) { + return templateWithSameSlug; + } + return templateWithSameSlug.id; + } + let slugToCheck; + // In `draft` status we might not have a slug available, so we use the `single` + // post type templates slug(ex page, single-post, single-product etc..). + // Pages do not need the `single` prefix in the slug to be prioritized + // through template hierarchy. + if ( slug ) { + slugToCheck = + postType === 'page' + ? `${ postType }-${ slug }` + : `single-${ postType }-${ slug }`; + } else { + slugToCheck = postType === 'page' ? 'page' : `single-${ postType }`; + } + return select( coreStore ).getDefaultTemplateId( { + slug: slugToCheck, + } ); + } +); diff --git a/packages/edit-post/src/store/selectors.js b/packages/edit-post/src/store/selectors.js index 8510cbb501955e..da1f9959e32e91 100644 --- a/packages/edit-post/src/store/selectors.js +++ b/packages/edit-post/src/store/selectors.js @@ -14,6 +14,7 @@ import deprecated from '@wordpress/deprecated'; * Internal dependencies */ import { unlock } from '../lock-unlock'; +import { getEditedPostTemplateId } from './private-selectors'; const { interfaceStore } = unlock( editorPrivateApis ); const EMPTY_ARRAY = []; @@ -555,67 +556,15 @@ export function areMetaBoxesInitialized( state ) { * @return {Object?} Post Template. */ export const getEditedPostTemplate = createRegistrySelector( - ( select ) => () => { - const { - id: postId, - type: postType, - slug, - } = select( editorStore ).getCurrentPost(); - const { getSite, getEditedEntityRecord, getEntityRecords } = - select( coreStore ); - const siteSettings = getSite(); - // First check if the current page is set as the posts page. - const isPostsPage = +postId === siteSettings?.page_for_posts; - if ( isPostsPage ) { - const defaultTemplateId = select( coreStore ).getDefaultTemplateId( - { slug: 'home' } - ); - return getEditedEntityRecord( - 'postType', - 'wp_template', - defaultTemplateId - ); - } - const currentTemplate = - select( editorStore ).getEditedPostAttribute( 'template' ); - if ( currentTemplate ) { - const templateWithSameSlug = getEntityRecords( - 'postType', - 'wp_template', - { per_page: -1 } - )?.find( ( template ) => template.slug === currentTemplate ); - if ( ! templateWithSameSlug ) { - return templateWithSameSlug; - } - return getEditedEntityRecord( - 'postType', - 'wp_template', - templateWithSameSlug.id - ); - } - let slugToCheck; - // In `draft` status we might not have a slug available, so we use the `single` - // post type templates slug(ex page, single-post, single-product etc..). - // Pages do not need the `single` prefix in the slug to be prioritized - // through template hierarchy. - if ( slug ) { - slugToCheck = - postType === 'page' - ? `${ postType }-${ slug }` - : `single-${ postType }-${ slug }`; - } else { - slugToCheck = postType === 'page' ? 'page' : `single-${ postType }`; + ( select ) => ( state ) => { + const templateId = getEditedPostTemplateId( state ); + if ( ! templateId ) { + return undefined; } - const defaultTemplateId = select( coreStore ).getDefaultTemplateId( { - slug: slugToCheck, - } ); - - return defaultTemplateId - ? select( coreStore ).getEditedEntityRecord( - 'postType', - 'wp_template', - defaultTemplateId - ) - : null; + return select( coreStore ).getEditedEntityRecord( + 'postType', + 'wp_template', + templateId + ); } ); diff --git a/packages/editor/src/components/editor/index.js b/packages/editor/src/components/editor/index.js index 5fb671f3714155..6201ca9ae17c7e 100644 --- a/packages/editor/src/components/editor/index.js +++ b/packages/editor/src/components/editor/index.js @@ -20,20 +20,16 @@ function Editor( { templateId, settings, children, + initialEdits, // This could be part of the settings. onActionPerformed, // The following abstractions are not ideal but necessary // to account for site editor and post editor differences for now. - className, - styles, - customSaveButton, - forceDisableBlockTools, - title, - iframeProps, + extraContent, extraSidebarPanels, - enableRegionNavigation = true, + ...props } ) { const { post, template, hasLoadedPost } = useSelect( ( select ) => { @@ -63,12 +59,7 @@ function Editor( { } return ( - + <> { hasLoadedPost && ! post && ( { __( @@ -76,21 +67,25 @@ function Editor( { ) } ) } - - - { children } - + { !! post && ( + + + { extraContent } + + + { children } + + ) } + ); } diff --git a/packages/editor/src/private-apis.js b/packages/editor/src/private-apis.js index 429f7ffc7f3f9b..48e43e7737fec8 100644 --- a/packages/editor/src/private-apis.js +++ b/packages/editor/src/private-apis.js @@ -6,7 +6,6 @@ import * as interfaceApis from '@wordpress/interface'; /** * Internal dependencies */ -import { ExperimentalEditorProvider } from './components/provider'; import { lock } from './lock-unlock'; import { EntitiesSavedStatesExtensible } from './components/entities-saved-states'; import EditorContentSlotFill from './components/editor-interface/content-slot-fill'; @@ -14,14 +13,12 @@ import useBlockEditorSettings from './components/provider/use-block-editor-setti import BackButton from './components/header/back-button'; import CreateTemplatePartModal from './components/create-template-part-modal'; import Editor from './components/editor'; -import EditorInterface from './components/editor-interface'; import PluginPostExcerpt from './components/post-excerpt/plugin'; import PreferencesModal from './components/preferences-modal'; import { usePostActions } from './components/post-actions/actions'; import ToolsMoreMenuGroup from './components/more-menu/tools-more-menu-group'; import ViewMoreMenuGroup from './components/more-menu/view-more-menu-group'; import ResizableEditor from './components/resizable-editor'; -import Sidebar from './components/sidebar'; import { mergeBaseAndUserConfigs, GlobalStylesProvider, @@ -33,10 +30,8 @@ export const privateApis = {}; lock( privateApis, { CreateTemplatePartModal, BackButton, - ExperimentalEditorProvider, EntitiesSavedStatesExtensible, Editor, - EditorInterface, EditorContentSlotFill, GlobalStylesProvider, mergeBaseAndUserConfigs, @@ -46,7 +41,6 @@ lock( privateApis, { ToolsMoreMenuGroup, ViewMoreMenuGroup, ResizableEditor, - Sidebar, // This is a temporary private API while we're updating the site editor to use EditorProvider. useBlockEditorSettings, diff --git a/packages/editor/src/private-apis.native.js b/packages/editor/src/private-apis.native.js index 7c302c9c87d3aa..5ba2d8e4406739 100644 --- a/packages/editor/src/private-apis.native.js +++ b/packages/editor/src/private-apis.native.js @@ -7,7 +7,6 @@ import * as interfaceApis from '@wordpress/interface'; * Internal dependencies */ import VisualEditor from './components/visual-editor'; -import { ExperimentalEditorProvider } from './components/provider'; import { lock } from './lock-unlock'; import { EntitiesSavedStatesExtensible } from './components/entities-saved-states'; import useBlockEditorSettings from './components/provider/use-block-editor-settings'; @@ -22,7 +21,6 @@ const { store: interfaceStore, ...remainingInterfaceApis } = interfaceApis; export const privateApis = {}; lock( privateApis, { VisualEditor, - ExperimentalEditorProvider, EntitiesSavedStatesExtensible, PluginPostExcerpt, PreferencesModal,