Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Editor: Introduce the Editor component and use it in the site editor #62274

Merged
merged 3 commits into from
Jun 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
142 changes: 47 additions & 95 deletions packages/edit-site/src/components/editor/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import clsx from 'clsx';
* WordPress dependencies
*/
import { useDispatch, useSelect } from '@wordpress/data';
import { Notice } from '@wordpress/components';
import { useInstanceId } from '@wordpress/compose';
import {
EditorKeyboardShortcutsRegister,
Expand All @@ -28,11 +27,8 @@ import { store as preferencesStore } from '@wordpress/preferences';
import WelcomeGuide from '../welcome-guide';
import { store as editSiteStore } from '../../store';
import { GlobalStylesRenderer } from '../global-styles-renderer';
import useTitle from '../routes/use-title';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we remove this hook in favor of useEditorTitle?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not really, useEditorTitle is using useTitle internally. useTitle is more generic.

import CanvasLoader from '../canvas-loader';
import { unlock } from '../../lock-unlock';
import useEditedEntityRecord from '../use-edited-entity-record';
import { POST_TYPE_LABELS, TEMPLATE_POST_TYPE } from '../../utils/constants';
import TemplatePartConverter from '../template-part-converter';
import { useSpecificEditorSettings } from '../block-editor/use-site-editor-settings';
import PluginTemplateSettingPanel from '../plugin-template-setting-panel';
Expand All @@ -45,25 +41,18 @@ import {
import SaveButton from '../save-button';
import SiteEditorMoreMenu from '../more-menu';
import useEditorIframeProps from '../block-editor/use-editor-iframe-props';
import useEditorTitle from './use-editor-title';

const {
EditorInterface,
ExperimentalEditorProvider: EditorProvider,
Sidebar,
} = unlock( editorPrivateApis );
const { Editor } = unlock( editorPrivateApis );
const { useHistory } = unlock( routerPrivateApis );
const { BlockKeyboardShortcuts } = unlock( blockLibraryPrivateApis );

export default function Editor( { isLoading } ) {
export default function EditSiteEditor( { isLoading } ) {
const {
record: editedPost,
getTitle,
isLoaded: hasLoadedPost,
} = useEditedEntityRecord();
const { type: editedPostType } = editedPost;
const {
context,
contextPost,
editedPostType,
editedPostId,
contextPostType,
contextPostId,
editorMode,
canvasMode,
isEditingPage,
Expand All @@ -72,25 +61,25 @@ export default function Editor( { isLoading } ) {
editorCanvasView,
currentPostIsTrashed,
} = useSelect( ( select ) => {
const { getEditedPostContext, getCanvasMode, isPage } = unlock(
select( editSiteStore )
);
const {
getEditedPostContext,
getCanvasMode,
isPage,
getEditedPostType,
getEditedPostId,
} = unlock( select( editSiteStore ) );
const { get } = select( preferencesStore );
const { getEntityRecord, getCurrentTheme } = select( coreDataStore );
const { getCurrentTheme } = select( coreDataStore );
const { getEditorMode } = select( editorStore );
const _context = getEditedPostContext();

// The currently selected entity to display.
// Typically template or template part in the site editor.
return {
context: _context,
contextPost: _context?.postId
? getEntityRecord(
'postType',
_context.postType,
_context.postId
)
: undefined,
editedPostType: getEditedPostType(),
editedPostId: getEditedPostId(),
contextPostType: _context?.postId ? _context.postType : undefined,
contextPostId: _context?.postId ? _context.postId : undefined,
editorMode: getEditorMode(),
canvasMode: getCanvasMode(),
isEditingPage: isPage(),
Expand All @@ -104,30 +93,14 @@ export default function Editor( { isLoading } ) {
'trash',
};
}, [] );
useEditorTitle();
const _isPreviewingTheme = isPreviewingTheme();
const hasDefaultEditorCanvasView = ! useHasEditorCanvasContainer();
const iframeProps = useEditorIframeProps();

const isViewMode = canvasMode === 'view';
const isEditMode = canvasMode === 'edit';
const showVisualEditor = isViewMode || editorMode === 'visual';
const postWithTemplate = !! context?.postId;

let title;
if ( hasLoadedPost ) {
title = sprintf(
// translators: A breadcrumb trail for the Admin document title. %1$s: title of template being edited, %2$s: type of template (Template or Template Part).
__( '%1$s ‹ %2$s' ),
getTitle(),
POST_TYPE_LABELS[ editedPostType ] ??
POST_TYPE_LABELS[ TEMPLATE_POST_TYPE ]
);
}

// Only announce the title once the editor is ready to prevent "Replace"
// action in <URLQueryController> from double-announcing.
useTitle( hasLoadedPost && title );

const postWithTemplate = !! contextPostId;
const loadingProgressId = useInstanceId(
CanvasLoader,
'edit-site-editor__loading-progress'
Expand Down Expand Up @@ -202,10 +175,7 @@ export default function Editor( { isLoading } ) {
[ history, createSuccessNotice ]
);

const isReady =
! isLoading &&
( ( postWithTemplate && !! contextPost && !! editedPost ) ||
( ! postWithTemplate && !! editedPost ) );
const isReady = ! isLoading;

return (
<>
Expand All @@ -215,55 +185,37 @@ export default function Editor( { isLoading } ) {
{ showVisualEditor && <TemplatePartConverter /> }
{ ! isReady ? <CanvasLoader id={ loadingProgressId } /> : null }
{ isEditMode && <WelcomeGuide /> }
{ hasLoadedPost && ! editedPost && (
<Notice status="warning" isDismissible={ false }>
{ __(
"You attempted to edit an item that doesn't exist. Perhaps it was deleted?"
) }
</Notice>
) }
{ isReady && (
<EditorProvider
post={ postWithTemplate ? contextPost : editedPost }
__unstableTemplate={
postWithTemplate ? editedPost : undefined
<Editor
postType={
postWithTemplate ? contextPostType : editedPostType
}
postId={ postWithTemplate ? contextPostId : editedPostId }
templateId={ postWithTemplate ? editedPostId : undefined }
settings={ settings }
useSubRegistry={ false }
className={ clsx( 'edit-site-editor__editor-interface', {
'show-icon-labels': showIconLabels,
} ) }
styles={ styles }
enableRegionNavigation={ false }
customSaveButton={
_isPreviewingTheme && <SaveButton size="compact" />
}
forceDisableBlockTools={ ! hasDefaultEditorCanvasView }
title={
! hasDefaultEditorCanvasView
? getEditorCanvasContainerTitle( editorCanvasView )
: undefined
}
iframeProps={ iframeProps }
onActionPerformed={ onActionPerformed }
extraSidebarPanels={
! isEditingPage && <PluginTemplateSettingPanel.Slot />
}
>
<SiteEditorMoreMenu />
<EditorInterface
className={ clsx(
'edit-site-editor__editor-interface',
{
'show-icon-labels': showIconLabels,
}
) }
styles={ styles }
enableRegionNavigation={ false }
customSaveButton={
_isPreviewingTheme && <SaveButton size="compact" />
}
forceDisableBlockTools={ ! hasDefaultEditorCanvasView }
title={
! hasDefaultEditorCanvasView
? getEditorCanvasContainerTitle(
editorCanvasView
)
: undefined
}
iframeProps={ iframeProps }
/>
<Sidebar
onActionPerformed={ onActionPerformed }
extraPanels={
! isEditingPage && (
<PluginTemplateSettingPanel.Slot />
)
}
/>
{ supportsGlobalStyles && <GlobalStylesSidebar /> }
</EditorProvider>
</Editor>
) }
</>
);
Expand Down
35 changes: 35 additions & 0 deletions packages/edit-site/src/components/editor/use-editor-title.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* WordPress dependencies
*/
import { __, sprintf } from '@wordpress/i18n';

/**
* Internal dependencies
*/
import useEditedEntityRecord from '../use-edited-entity-record';
import useTitle from '../routes/use-title';
import { POST_TYPE_LABELS, TEMPLATE_POST_TYPE } from '../../utils/constants';

function useEditorTitle() {
const {
record: editedPost,
getTitle,
isLoaded: hasLoadedPost,
} = useEditedEntityRecord();
let title;
if ( hasLoadedPost ) {
title = sprintf(
// translators: A breadcrumb trail for the Admin document title. %1$s: title of template being edited, %2$s: type of template (Template or Template Part).
__( '%1$s ‹ %2$s' ),
getTitle(),
POST_TYPE_LABELS[ editedPost.type ] ??
POST_TYPE_LABELS[ TEMPLATE_POST_TYPE ]
);
}

// Only announce the title once the editor is ready to prevent "Replace"
// action in <URLQueryController> from double-announcing.
useTitle( hasLoadedPost && title );
}

export default useEditorTitle;
93 changes: 93 additions & 0 deletions packages/editor/src/components/editor/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/**
* WordPress dependencies
*/
import { useSelect } from '@wordpress/data';
import { store as coreStore } from '@wordpress/core-data';
import { Notice } from '@wordpress/components';
import { __ } from '@wordpress/i18n';

/**
* Internal dependencies
*/
import { TEMPLATE_POST_TYPE } from '../../store/constants';
import EditorInterface from '../editor-interface';
import { ExperimentalEditorProvider } from '../provider';
import Sidebar from '../sidebar';

function Editor( {
postType,
postId,
templateId,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The templateId can in theory be guessed from the postType, postId couple but it would require a lot more changes to how things work now in the site editor. So for now, this can work too.

settings,
children,

// 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,
extraSidebarPanels,
enableRegionNavigation = true,
} ) {
const { post, template, hasLoadedPost } = useSelect(
( select ) => {
const { getEntityRecord, hasFinishedResolution } =
select( coreStore );
return {
post: getEntityRecord( 'postType', postType, postId ),
template: templateId
? getEntityRecord(
'postType',
TEMPLATE_POST_TYPE,
templateId
)
: undefined,
hasLoadedPost: hasFinishedResolution( 'getEntityRecord', [
'postType',
postType,
postId,
] ),
};
},
[ postType, postId, templateId ]
);

return (
<ExperimentalEditorProvider
post={ post }
__unstableTemplate={ template }
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be honest, I don't really think that this EditorProvider should receive the full objects, postType, postId should suffice but it's a very old component and I didn't want to touch its API.

settings={ settings }
useSubRegistry={ false }
>
{ hasLoadedPost && ! post && (
<Notice status="warning" isDismissible={ false }>
{ __(
"You attempted to edit an item that doesn't exist. Perhaps it was deleted?"
) }
</Notice>
) }
<EditorInterface
className={ className }
styles={ styles }
enableRegionNavigation={ enableRegionNavigation }
customSaveButton={ customSaveButton }
forceDisableBlockTools={ forceDisableBlockTools }
title={ title }
iframeProps={ iframeProps }
/>
<Sidebar
onActionPerformed={ onActionPerformed }
extraPanels={ extraSidebarPanels }
/>
{ children }
</ExperimentalEditorProvider>
);
}

export default Editor;
4 changes: 3 additions & 1 deletion packages/editor/src/private-apis.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ import { EntitiesSavedStatesExtensible } from './components/entities-saved-state
import EditorContentSlotFill from './components/editor-interface/content-slot-fill';
import useBlockEditorSettings from './components/provider/use-block-editor-settings';
import BackButton from './components/header/back-button';
import EditorInterface from './components/editor-interface';
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';
Expand All @@ -34,6 +35,7 @@ lock( privateApis, {
BackButton,
ExperimentalEditorProvider,
EntitiesSavedStatesExtensible,
Editor,
EditorInterface,
EditorContentSlotFill,
GlobalStylesProvider,
Expand Down
Loading