From 661e17108122676fa985bf09c9b44b7a4fa3cd38 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Wed, 8 May 2024 21:07:14 +0100 Subject: [PATCH] Editor: Unify the sidebar between the post and site editors --- .../edit-post/src/components/layout/index.js | 53 ++++++ .../edit-site/src/components/editor/index.js | 86 +++++++-- .../default-sidebar.js | 0 .../index.js} | 2 +- .../style.scss | 0 .../src/components/sidebar-edit-mode/index.js | 173 ------------------ .../sidebar-edit-mode/page-panels/index.js | 133 -------------- .../page-panels/page-summary.js | 61 ------ .../settings-header/index.js | 43 ----- .../settings-header/style.scss | 13 -- .../sidebar-edit-mode/template-panel/index.js | 134 -------------- .../template-panel/style.scss | 16 -- .../components/post-transform-panel}/hooks.js | 43 ++--- .../components/post-transform-panel/index.js | 100 ++++++++++ .../editor/src/components/sidebar/index.js | 75 ++------ .../template-content-panel/index.js} | 13 +- 16 files changed, 271 insertions(+), 674 deletions(-) rename packages/edit-site/src/components/{sidebar-edit-mode => global-styles-sidebar}/default-sidebar.js (100%) rename packages/edit-site/src/components/{sidebar-edit-mode/global-styles-sidebar.js => global-styles-sidebar/index.js} (100%) rename packages/edit-site/src/components/{sidebar-edit-mode => global-styles-sidebar}/style.scss (100%) delete mode 100644 packages/edit-site/src/components/sidebar-edit-mode/index.js delete mode 100644 packages/edit-site/src/components/sidebar-edit-mode/page-panels/index.js delete mode 100644 packages/edit-site/src/components/sidebar-edit-mode/page-panels/page-summary.js delete mode 100644 packages/edit-site/src/components/sidebar-edit-mode/settings-header/index.js delete mode 100644 packages/edit-site/src/components/sidebar-edit-mode/settings-header/style.scss delete mode 100644 packages/edit-site/src/components/sidebar-edit-mode/template-panel/index.js delete mode 100644 packages/edit-site/src/components/sidebar-edit-mode/template-panel/style.scss rename packages/{edit-site/src/components/sidebar-edit-mode/template-panel => editor/src/components/post-transform-panel}/hooks.js (70%) create mode 100644 packages/editor/src/components/post-transform-panel/index.js rename packages/{edit-site/src/components/sidebar-edit-mode/page-panels/page-content.js => editor/src/components/template-content-panel/index.js} (64%) diff --git a/packages/edit-post/src/components/layout/index.js b/packages/edit-post/src/components/layout/index.js index 344f73dd6fa043..dc081121546c33 100644 --- a/packages/edit-post/src/components/layout/index.js +++ b/packages/edit-post/src/components/layout/index.js @@ -35,6 +35,7 @@ import { store as preferencesStore } from '@wordpress/preferences'; import { 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'; /** * Internal dependencies @@ -287,6 +288,57 @@ function Layout( { initialPost } ) { ); } + const { createSuccessNotice } = useDispatch( noticesStore ); + + const onActionPerformed = useCallback( + ( actionId, items ) => { + switch ( actionId ) { + case 'move-to-trash': + { + const postType = items[ 0 ].type; + document.location.href = addQueryArgs( 'edit.php', { + post_type: postType, + } ); + } + break; + case 'duplicate-post': + { + const newItem = items[ 0 ]; + const title = + typeof newItem.title === 'string' + ? newItem.title + : newItem.title?.rendered; + createSuccessNotice( + sprintf( + // translators: %s: Title of the created post e.g: "Post 1". + __( '"%s" successfully created.' ), + title + ), + { + type: 'snackbar', + id: 'duplicate-post-action', + actions: [ + { + label: __( 'Edit' ), + onClick: () => { + const postId = newItem.id; + document.location.href = + addQueryArgs( 'post.php', { + post: postId, + action: 'edit', + } ); + }, + }, + ], + } + ); + } + break; + } + }, + [ createSuccessNotice ] + ); + return ( <> @@ -377,6 +429,7 @@ function Layout( { initialPost } ) { { ! isDistractionFree && ( } diff --git a/packages/edit-site/src/components/editor/index.js b/packages/edit-site/src/components/editor/index.js index dbe268fe6adb1e..0f6cbc011c4acc 100644 --- a/packages/edit-site/src/components/editor/index.js +++ b/packages/edit-site/src/components/editor/index.js @@ -22,7 +22,6 @@ import { BlockBreadcrumb, BlockToolbar, store as blockEditorStore, - BlockInspector, } from '@wordpress/block-editor'; import { EditorKeyboardShortcutsRegister, @@ -36,14 +35,12 @@ import { __, sprintf } from '@wordpress/i18n'; import { store as coreDataStore } from '@wordpress/core-data'; import { privateApis as blockLibraryPrivateApis } from '@wordpress/block-library'; import { useState, useCallback } from '@wordpress/element'; +import { store as noticesStore } from '@wordpress/notices'; +import { privateApis as routerPrivateApis } from '@wordpress/router'; /** * Internal dependencies */ -import { - SidebarComplementaryAreaFills, - SidebarInspectorFill, -} from '../sidebar-edit-mode'; import CodeEditor from '../code-editor'; import Header from '../header-edit-mode'; import WelcomeGuide from '../welcome-guide'; @@ -59,6 +56,8 @@ import { POST_TYPE_LABELS, TEMPLATE_POST_TYPE } from '../../utils/constants'; import SiteEditorCanvas from '../block-editor/site-editor-canvas'; import TemplatePartConverter from '../template-part-converter'; import { useSpecificEditorSettings } from '../block-editor/use-site-editor-settings'; +import PluginTemplateSettingPanel from '../plugin-template-setting-panel'; +import GlobalStylesSidebar from '../global-styles-sidebar'; const { ExperimentalEditorProvider: EditorProvider, @@ -68,8 +67,9 @@ const { ComplementaryArea, interfaceStore, SavePublishPanels, + Sidebar, } = unlock( editorPrivateApis ); - +const { useHistory } = unlock( routerPrivateApis ); const { BlockKeyboardShortcuts } = unlock( blockLibraryPrivateApis ); const interfaceLabels = { @@ -112,14 +112,16 @@ export default function Editor( { isLoading, onClick } ) { showIconLabels, showBlockBreadcrumbs, postTypeLabel, + isEditingPage, + supportsGlobalStyles, } = useSelect( ( select ) => { const { get } = select( preferencesStore ); - const { getEditedPostContext, getCanvasMode } = unlock( + const { getEditedPostContext, getCanvasMode, isPage } = unlock( select( editSiteStore ) ); const { __unstableGetEditorMode } = select( blockEditorStore ); const { getActiveComplementaryArea } = select( interfaceStore ); - const { getEntityRecord } = select( coreDataStore ); + const { getEntityRecord, getCurrentTheme } = select( coreDataStore ); const { isInserterOpened, isListViewOpened, @@ -149,6 +151,8 @@ export default function Editor( { isLoading, onClick } ) { showBlockBreadcrumbs: get( 'core', 'showBlockBreadcrumbs' ), showIconLabels: get( 'core', 'showIconLabels' ), postTypeLabel: getPostTypeLabel(), + isEditingPage: isPage(), + supportsGlobalStyles: getCurrentTheme()?.is_block_theme, }; }, [] ); @@ -207,6 +211,59 @@ export default function Editor( { isLoading, onClick } ) { [ entitiesSavedStatesCallback ] ); + const { createSuccessNotice } = useDispatch( noticesStore ); + const history = useHistory(); + const onActionPerformed = useCallback( + ( actionId, items ) => { + switch ( actionId ) { + case 'move-to-trash': + { + history.push( { + path: '/' + items[ 0 ].type, + postId: undefined, + postType: undefined, + canvas: 'view', + } ); + } + break; + case 'duplicate-post': + { + const newItem = items[ 0 ]; + const _title = + typeof newItem.title === 'string' + ? newItem.title + : newItem.title?.rendered; + createSuccessNotice( + sprintf( + // translators: %s: Title of the created post e.g: "Post 1". + __( '"%s" successfully created.' ), + _title + ), + { + type: 'snackbar', + id: 'duplicate-post-action', + actions: [ + { + label: __( 'Edit' ), + onClick: () => { + history.push( { + path: undefined, + postId: newItem.id, + postType: newItem.type, + canvas: 'edit', + } ); + }, + }, + ], + } + ); + } + break; + } + }, + [ history, createSuccessNotice ] + ); + const isReady = ! isLoading && ( ( postWithTemplate && !! contextPost && !! editedPost ) || @@ -232,7 +289,6 @@ export default function Editor( { isLoading, onClick } ) { settings={ settings } useSubRegistry={ false } > - { isEditMode && } - - - { ! isLargeViewport && ( ) } @@ -349,6 +402,15 @@ export default function Editor( { isLoading, onClick } ) { secondarySidebar: secondarySidebarLabel, } } /> + + ) + } + /> + { supportsGlobalStyles && } ) } diff --git a/packages/edit-site/src/components/sidebar-edit-mode/default-sidebar.js b/packages/edit-site/src/components/global-styles-sidebar/default-sidebar.js similarity index 100% rename from packages/edit-site/src/components/sidebar-edit-mode/default-sidebar.js rename to packages/edit-site/src/components/global-styles-sidebar/default-sidebar.js diff --git a/packages/edit-site/src/components/sidebar-edit-mode/global-styles-sidebar.js b/packages/edit-site/src/components/global-styles-sidebar/index.js similarity index 100% rename from packages/edit-site/src/components/sidebar-edit-mode/global-styles-sidebar.js rename to packages/edit-site/src/components/global-styles-sidebar/index.js index 3254f594632c4d..436762d6bcf94f 100644 --- a/packages/edit-site/src/components/sidebar-edit-mode/global-styles-sidebar.js +++ b/packages/edit-site/src/components/global-styles-sidebar/index.js @@ -21,12 +21,12 @@ import { /** * Internal dependencies */ -import DefaultSidebar from './default-sidebar'; import { GlobalStylesUI } from '../global-styles'; import { store as editSiteStore } from '../../store'; import { GlobalStylesMenuSlot } from '../global-styles/ui'; import { unlock } from '../../lock-unlock'; import { store as coreStore } from '@wordpress/core-data'; +import DefaultSidebar from './default-sidebar'; const { interfaceStore } = unlock( editorPrivateApis ); diff --git a/packages/edit-site/src/components/sidebar-edit-mode/style.scss b/packages/edit-site/src/components/global-styles-sidebar/style.scss similarity index 100% rename from packages/edit-site/src/components/sidebar-edit-mode/style.scss rename to packages/edit-site/src/components/global-styles-sidebar/style.scss diff --git a/packages/edit-site/src/components/sidebar-edit-mode/index.js b/packages/edit-site/src/components/sidebar-edit-mode/index.js deleted file mode 100644 index 8541f952abbf41..00000000000000 --- a/packages/edit-site/src/components/sidebar-edit-mode/index.js +++ /dev/null @@ -1,173 +0,0 @@ -/** - * WordPress dependencies - */ -import { - createSlotFill, - privateApis as componentsPrivateApis, -} from '@wordpress/components'; -import { isRTL, __ } from '@wordpress/i18n'; -import { drawerLeft, drawerRight } from '@wordpress/icons'; -import { useCallback, useContext, useEffect, useRef } from '@wordpress/element'; -import { useSelect, useDispatch } from '@wordpress/data'; -import { store as blockEditorStore } from '@wordpress/block-editor'; -import { store as coreStore } from '@wordpress/core-data'; -import { - PageAttributesPanel, - PostDiscussionPanel, - PostLastRevisionPanel, - PostTaxonomiesPanel, - privateApis as editorPrivateApis, -} from '@wordpress/editor'; - -/** - * Internal dependencies - */ -import DefaultSidebar from './default-sidebar'; -import GlobalStylesSidebar from './global-styles-sidebar'; -import SettingsHeader from './settings-header'; -import PagePanels from './page-panels'; -import TemplatePanel from './template-panel'; -import { store as editSiteStore } from '../../store'; -import { unlock } from '../../lock-unlock'; - -const { Tabs } = unlock( componentsPrivateApis ); -const { interfaceStore, useAutoSwitchEditorSidebars, PatternOverridesPanel } = - unlock( editorPrivateApis ); -const { Slot: InspectorSlot, Fill: InspectorFill } = createSlotFill( - 'EditSiteSidebarInspector' -); -export const SidebarInspectorFill = InspectorFill; - -const FillContents = ( { tabName, isEditingPage, supportsGlobalStyles } ) => { - const tabListRef = useRef( null ); - // Because `DefaultSidebar` renders a `ComplementaryArea`, we - // need to forward the `Tabs` context so it can be passed through the - // underlying slot/fill. - const tabsContextValue = useContext( Tabs.Context ); - - // This effect addresses a race condition caused by tabbing from the last - // block in the editor into the settings sidebar. Without this effect, the - // selected tab and browser focus can become separated in an unexpected way. - // (e.g the "block" tab is focused, but the "post" tab is selected). - useEffect( () => { - const tabsElements = Array.from( - tabListRef.current?.querySelectorAll( '[role="tab"]' ) || [] - ); - const selectedTabElement = tabsElements.find( - // We are purposefully using a custom `data-tab-id` attribute here - // because we don't want rely on any assumptions about `Tabs` - // component internals. - ( element ) => element.getAttribute( 'data-tab-id' ) === tabName - ); - const activeElement = selectedTabElement?.ownerDocument.activeElement; - const tabsHasFocus = tabsElements.some( ( element ) => { - return activeElement && activeElement.id === element.id; - } ); - if ( - tabsHasFocus && - selectedTabElement && - selectedTabElement.id !== activeElement?.id - ) { - selectedTabElement?.focus(); - } - }, [ tabName ] ); - - return ( - <> - - - - } - headerClassName="edit-site-sidebar-edit-mode__panel-tabs" - // This classname is added so we can apply a corrective negative - // margin to the panel. - // see https://github.com/WordPress/gutenberg/pull/55360#pullrequestreview-1737671049 - className="edit-site-sidebar__panel" - isActiveByDefault - > - - - { isEditingPage ? : } - - - - - - - - - - - - { supportsGlobalStyles && } - - ); -}; - -export function SidebarComplementaryAreaFills() { - useAutoSwitchEditorSidebars(); - const { tabName, supportsGlobalStyles, isEditingPage } = useSelect( - ( select ) => { - const sidebar = - select( interfaceStore ).getActiveComplementaryArea( 'core' ); - - const _isEditorSidebarOpened = [ - 'edit-post/block', - 'edit-post/document', - ].includes( sidebar ); - let _tabName = sidebar; - if ( ! _isEditorSidebarOpened ) { - _tabName = !! select( - blockEditorStore - ).getBlockSelectionStart() - ? 'edit-post/block' - : 'edit-post/document'; - } - - return { - tabName: _tabName, - supportsGlobalStyles: - select( coreStore ).getCurrentTheme()?.is_block_theme, - isEditingPage: select( editSiteStore ).isPage(), - }; - }, - [] - ); - const { enableComplementaryArea } = useDispatch( interfaceStore ); - - // `newSelectedTabId` could technically be falsey if no tab is selected (i.e. - // the initial render) or when we don't want a tab displayed (i.e. the - // sidebar is closed). These cases should both be covered by the `!!` check - // below, so we shouldn't need any additional falsey handling. - const onTabSelect = useCallback( - ( newSelectedTabId ) => { - if ( !! newSelectedTabId ) { - enableComplementaryArea( 'core', newSelectedTabId ); - } - }, - [ enableComplementaryArea ] - ); - - return ( - - - - ); -} diff --git a/packages/edit-site/src/components/sidebar-edit-mode/page-panels/index.js b/packages/edit-site/src/components/sidebar-edit-mode/page-panels/index.js deleted file mode 100644 index f4fc2af178e08f..00000000000000 --- a/packages/edit-site/src/components/sidebar-edit-mode/page-panels/index.js +++ /dev/null @@ -1,133 +0,0 @@ -/** - * WordPress dependencies - */ -import { PanelBody } from '@wordpress/components'; -import { __, sprintf } from '@wordpress/i18n'; -import { useSelect, useDispatch } from '@wordpress/data'; -import { store as coreStore } from '@wordpress/core-data'; -import { - PluginDocumentSettingPanel, - store as editorStore, - privateApis as editorPrivateApis, -} from '@wordpress/editor'; -import { privateApis as routerPrivateApis } from '@wordpress/router'; -import { useCallback } from '@wordpress/element'; -import { store as noticesStore } from '@wordpress/notices'; - -/** - * Internal dependencies - */ -import { store as editSiteStore } from '../../../store'; -import PageContent from './page-content'; -import PageSummary from './page-summary'; - -import { unlock } from '../../../lock-unlock'; - -const { PostCardPanel, PostActions } = unlock( editorPrivateApis ); -const { useHistory } = unlock( routerPrivateApis ); - -export default function PagePanels() { - const { id, type, hasResolved, status, date, password, renderingMode } = - useSelect( ( select ) => { - const { getEditedPostContext } = select( editSiteStore ); - const { getEditedEntityRecord, hasFinishedResolution } = - select( coreStore ); - const { getRenderingMode } = select( editorStore ); - const context = getEditedPostContext(); - const queryArgs = [ 'postType', context.postType, context.postId ]; - const page = getEditedEntityRecord( ...queryArgs ); - return { - hasResolved: hasFinishedResolution( - 'getEditedEntityRecord', - queryArgs - ), - id: page?.id, - type: page?.type, - status: page?.status, - date: page?.date, - password: page?.password, - renderingMode: getRenderingMode(), - }; - }, [] ); - const { createSuccessNotice } = useDispatch( noticesStore ); - const history = useHistory(); - const onActionPerformed = useCallback( - ( actionId, items ) => { - switch ( actionId ) { - case 'move-to-trash': - { - history.push( { - path: '/' + items[ 0 ].type, - postId: undefined, - postType: undefined, - canvas: 'view', - } ); - } - break; - case 'duplicate-post': - { - const newItem = items[ 0 ]; - const title = - typeof newItem.title === 'string' - ? newItem.title - : newItem.title?.rendered; - createSuccessNotice( - sprintf( - // translators: %s: Title of the created post e.g: "Post 1". - __( '"%s" successfully created.' ), - title - ), - { - type: 'snackbar', - id: 'duplicate-post-action', - actions: [ - { - label: __( 'Edit' ), - onClick: () => { - history.push( { - path: undefined, - postId: newItem.id, - postType: newItem.type, - canvas: 'edit', - } ); - }, - }, - ], - } - ); - } - break; - } - }, - [ history, createSuccessNotice ] - ); - - if ( ! hasResolved ) { - return null; - } - - return ( - <> - - } - /> - - - - - { renderingMode !== 'post-only' && ( - - - - ) } - - ); -} diff --git a/packages/edit-site/src/components/sidebar-edit-mode/page-panels/page-summary.js b/packages/edit-site/src/components/sidebar-edit-mode/page-panels/page-summary.js deleted file mode 100644 index 0830ff8364c8aa..00000000000000 --- a/packages/edit-site/src/components/sidebar-edit-mode/page-panels/page-summary.js +++ /dev/null @@ -1,61 +0,0 @@ -/** - * WordPress dependencies - */ -import { __experimentalVStack as VStack } from '@wordpress/components'; -import { - PluginPostStatusInfo, - PostAuthorPanel, - PostURLPanel, - PostSchedulePanel, - PostTemplatePanel, - PostFeaturedImagePanel, - privateApis as editorPrivateApis, -} from '@wordpress/editor'; - -/** - * Internal dependencies - */ -import { unlock } from '../../../lock-unlock'; - -const { - PrivatePostExcerptPanel, - PostStatus, - PostContentInformation, - PostLastEditedPanel, -} = unlock( editorPrivateApis ); - -export default function PageSummary() { - return ( - - - { ( fills ) => ( - <> - - - - - - - - - - - - - - - - { fills } - - ) } - - - ); -} diff --git a/packages/edit-site/src/components/sidebar-edit-mode/settings-header/index.js b/packages/edit-site/src/components/sidebar-edit-mode/settings-header/index.js deleted file mode 100644 index 054952077a4910..00000000000000 --- a/packages/edit-site/src/components/sidebar-edit-mode/settings-header/index.js +++ /dev/null @@ -1,43 +0,0 @@ -/** - * WordPress dependencies - */ -import { privateApis as componentsPrivateApis } from '@wordpress/components'; -import { __ } from '@wordpress/i18n'; -import { useSelect } from '@wordpress/data'; -import { store as editorStore } from '@wordpress/editor'; -import { forwardRef } from '@wordpress/element'; - -/** - * Internal dependencies - */ -import { unlock } from '../../../lock-unlock'; - -const { Tabs } = unlock( componentsPrivateApis ); - -const SettingsHeader = ( _, ref ) => { - const postTypeLabel = useSelect( - ( select ) => select( editorStore ).getPostTypeLabel(), - [] - ); - - return ( - - - { postTypeLabel } - - - { __( 'Block' ) } - - - ); -}; - -export default forwardRef( SettingsHeader ); diff --git a/packages/edit-site/src/components/sidebar-edit-mode/settings-header/style.scss b/packages/edit-site/src/components/sidebar-edit-mode/settings-header/style.scss deleted file mode 100644 index c6157519526162..00000000000000 --- a/packages/edit-site/src/components/sidebar-edit-mode/settings-header/style.scss +++ /dev/null @@ -1,13 +0,0 @@ -.components-panel__header.edit-site-sidebar-edit-mode__panel-tabs { - padding-left: 0; - - .components-button.has-icon { - padding: 0; - min-width: $icon-size; - height: $icon-size; - - @include break-medium() { - display: flex; - } - } -} diff --git a/packages/edit-site/src/components/sidebar-edit-mode/template-panel/index.js b/packages/edit-site/src/components/sidebar-edit-mode/template-panel/index.js deleted file mode 100644 index f0abc9aed09d00..00000000000000 --- a/packages/edit-site/src/components/sidebar-edit-mode/template-panel/index.js +++ /dev/null @@ -1,134 +0,0 @@ -/** - * WordPress dependencies - */ -import { useSelect, useDispatch } from '@wordpress/data'; -import { PanelBody, PanelRow } from '@wordpress/components'; -import { - PluginDocumentSettingPanel, - privateApis as editorPrivateApis, - store as editorStore, -} from '@wordpress/editor'; -import { store as coreStore } from '@wordpress/core-data'; -import { __ } from '@wordpress/i18n'; -import { useAsyncList } from '@wordpress/compose'; -import { serialize } from '@wordpress/blocks'; -import { __experimentalBlockPatternsList as BlockPatternsList } from '@wordpress/block-editor'; -import { privateApis as routerPrivateApis } from '@wordpress/router'; - -/** - * Internal dependencies - */ -import { store as editSiteStore } from '../../../store'; -import TemplateActions from '../../template-actions'; -import PluginTemplateSettingPanel from '../../plugin-template-setting-panel'; -import { useAvailablePatterns } from './hooks'; -import { TEMPLATE_PART_POST_TYPE } from '../../../utils/constants'; -import { unlock } from '../../../lock-unlock'; - -const { PostCardPanel } = unlock( editorPrivateApis ); -const { useHistory } = unlock( routerPrivateApis ); - -function TemplatesList( { availableTemplates, onSelect } ) { - const shownTemplates = useAsyncList( availableTemplates ); - if ( ! availableTemplates || availableTemplates?.length === 0 ) { - return null; - } - - return ( - - ); -} - -const POST_TYPE_PATH = { - wp_template: '/wp_template', - wp_template_part: '/patterns', -}; - -export default function TemplatePanel() { - const { title, description, record, postType, postId } = useSelect( - ( select ) => { - const { getEditedPostType, getEditedPostId } = - select( editSiteStore ); - const { getEditedEntityRecord } = select( coreStore ); - const { __experimentalGetTemplateInfo: getTemplateInfo } = - select( editorStore ); - - const type = getEditedPostType(); - const _postId = getEditedPostId(); - const _record = getEditedEntityRecord( 'postType', type, _postId ); - const info = getTemplateInfo( _record ); - - return { - title: info.title, - description: info.description, - icon: info.icon, - record: _record, - postType: type, - postId: _postId, - }; - }, - [] - ); - const history = useHistory(); - const availablePatterns = useAvailablePatterns( record ); - const { editEntityRecord } = useDispatch( coreStore ); - - if ( ! title && ! description ) { - return null; - } - - const onTemplateSelect = async ( selectedTemplate ) => { - await editEntityRecord( 'postType', postType, postId, { - blocks: selectedTemplate.blocks, - content: serialize( selectedTemplate.blocks ), - } ); - }; - - return ( - <> - { - history.push( { - path: POST_TYPE_PATH[ postType ], - } ); - } } - /> - } - /> - - - { availablePatterns?.length > 0 && ( - - -

- { __( - 'Choose a predefined pattern to switch up the look of your template.' // TODO - make this dynamic? - ) } -

-
- - -
- ) } - - ); -} diff --git a/packages/edit-site/src/components/sidebar-edit-mode/template-panel/style.scss b/packages/edit-site/src/components/sidebar-edit-mode/template-panel/style.scss deleted file mode 100644 index 15a0541672b1dd..00000000000000 --- a/packages/edit-site/src/components/sidebar-edit-mode/template-panel/style.scss +++ /dev/null @@ -1,16 +0,0 @@ -.edit-site-template-card { - &__actions { - line-height: 0; - > .components-button.is-small.has-icon { - padding: 0; - min-width: auto; - } - flex-shrink: 0; - } -} - - -.edit-site-template-panel .block-editor-block-preview__container { - border-radius: 2px; - box-shadow: none; -} diff --git a/packages/edit-site/src/components/sidebar-edit-mode/template-panel/hooks.js b/packages/editor/src/components/post-transform-panel/hooks.js similarity index 70% rename from packages/edit-site/src/components/sidebar-edit-mode/template-panel/hooks.js rename to packages/editor/src/components/post-transform-panel/hooks.js index 128a74da39070c..6ce89a1b67a2d7 100644 --- a/packages/edit-site/src/components/sidebar-edit-mode/template-panel/hooks.js +++ b/packages/editor/src/components/post-transform-panel/hooks.js @@ -5,16 +5,16 @@ import { useSelect } from '@wordpress/data'; import { useMemo } from '@wordpress/element'; import { store as coreStore } from '@wordpress/core-data'; import { parse } from '@wordpress/blocks'; +import { store as blockEditorStore } from '@wordpress/block-editor'; +import { privateApis as patternsPrivateApis } from '@wordpress/patterns'; /** * Internal dependencies */ -import { store as editSiteStore } from '../../../store'; -import { - EXCLUDED_PATTERN_SOURCES, - PATTERN_TYPES, -} from '../../../utils/constants'; -import { unlock } from '../../../lock-unlock'; +import { unlock } from '../../lock-unlock'; + +const { EXCLUDED_PATTERN_SOURCES, PATTERN_TYPES } = + unlock( patternsPrivateApis ); function injectThemeAttributeInBlockTemplateContent( block, @@ -67,7 +67,7 @@ function filterPatterns( patterns, template ) { } ); } -function preparePatterns( patterns, template, currentThemeStylesheet ) { +function preparePatterns( patterns, currentThemeStylesheet ) { return patterns.map( ( pattern ) => ( { ...pattern, keywords: pattern.keywords || [], @@ -84,31 +84,22 @@ function preparePatterns( patterns, template, currentThemeStylesheet ) { } export function useAvailablePatterns( template ) { - const { blockPatterns, restBlockPatterns, currentThemeStylesheet } = - useSelect( ( select ) => { - const { getSettings } = unlock( select( editSiteStore ) ); - const settings = getSettings(); + const { blockPatterns, currentThemeStylesheet } = useSelect( ( select ) => { + const { getSettings } = select( blockEditorStore ); - return { - blockPatterns: - settings.__experimentalAdditionalBlockPatterns ?? - settings.__experimentalBlockPatterns, - restBlockPatterns: select( coreStore ).getBlockPatterns(), - currentThemeStylesheet: - select( coreStore ).getCurrentTheme().stylesheet, - }; - }, [] ); + return { + blockPatterns: getSettings().__experimentalBlockPatterns, + currentThemeStylesheet: + select( coreStore ).getCurrentTheme().stylesheet, + }; + }, [] ); return useMemo( () => { - const mergedPatterns = [ - ...( blockPatterns || [] ), - ...( restBlockPatterns || [] ), - ]; - const filteredPatterns = filterPatterns( mergedPatterns, template ); + const filteredPatterns = filterPatterns( blockPatterns, template ); return preparePatterns( filteredPatterns, template, currentThemeStylesheet ); - }, [ blockPatterns, restBlockPatterns, template, currentThemeStylesheet ] ); + }, [ blockPatterns, template, currentThemeStylesheet ] ); } diff --git a/packages/editor/src/components/post-transform-panel/index.js b/packages/editor/src/components/post-transform-panel/index.js new file mode 100644 index 00000000000000..f70dc0f4f48cbb --- /dev/null +++ b/packages/editor/src/components/post-transform-panel/index.js @@ -0,0 +1,100 @@ +/** + * WordPress dependencies + */ +import { useSelect, useDispatch } from '@wordpress/data'; +import { store as coreStore } from '@wordpress/core-data'; +import { PanelBody, PanelRow } from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; +import { useAsyncList } from '@wordpress/compose'; +import { __experimentalBlockPatternsList as BlockPatternsList } from '@wordpress/block-editor'; +import { serialize } from '@wordpress/blocks'; + +/** + * Internal dependencies + */ +import { store as editorStore } from '../../store'; +import { useAvailablePatterns } from './hooks'; +import { + TEMPLATE_POST_TYPE, + TEMPLATE_PART_POST_TYPE, +} from '../../store/constants'; + +function TemplatesList( { availableTemplates, onSelect } ) { + const shownTemplates = useAsyncList( availableTemplates ); + if ( ! availableTemplates || availableTemplates?.length === 0 ) { + return null; + } + + return ( + + ); +} + +function PostTransform() { + const { record, postType, postId } = useSelect( ( select ) => { + const { getCurrentPostType, getCurrentPostId } = select( editorStore ); + const { getEditedEntityRecord } = select( coreStore ); + const type = getCurrentPostType(); + const id = getCurrentPostId(); + return { + postType: type, + postId: id, + record: getEditedEntityRecord( 'postType', type, id ), + }; + }, [] ); + const { editEntityRecord } = useDispatch( coreStore ); + const availablePatterns = useAvailablePatterns( record ); + const onTemplateSelect = async ( selectedTemplate ) => { + await editEntityRecord( 'postType', postType, postId, { + blocks: selectedTemplate.blocks, + content: serialize( selectedTemplate.blocks ), + } ); + }; + + if ( ! availablePatterns?.length ) { + return null; + } + + return ( + + +

+ { __( + 'Choose a predefined pattern to switch up the look of your template.' // TODO - make this dynamic? + ) } +

+
+ + +
+ ); +} + +export default function PostTransformPanel() { + const { postType } = useSelect( ( select ) => { + const { getCurrentPostType } = select( editorStore ); + return { + postType: getCurrentPostType(), + }; + }, [] ); + + if ( + [ TEMPLATE_PART_POST_TYPE, TEMPLATE_POST_TYPE ].includes( postType ) + ) { + return null; + } + + return ; +} diff --git a/packages/editor/src/components/sidebar/index.js b/packages/editor/src/components/sidebar/index.js index 4aa4d03569e116..7382a3a61f6b08 100644 --- a/packages/editor/src/components/sidebar/index.js +++ b/packages/editor/src/components/sidebar/index.js @@ -13,11 +13,9 @@ import { useEffect, useRef, } from '@wordpress/element'; -import { isRTL, __, sprintf } from '@wordpress/i18n'; +import { isRTL, __ } from '@wordpress/i18n'; import { drawerLeft, drawerRight } from '@wordpress/icons'; import { store as keyboardShortcutsStore } from '@wordpress/keyboard-shortcuts'; -import { addQueryArgs } from '@wordpress/url'; -import { store as noticesStore } from '@wordpress/notices'; import { privateApis as componentsPrivateApis } from '@wordpress/components'; import { store as interfaceStore } from '@wordpress/interface'; @@ -39,6 +37,8 @@ import useAutoSwitchEditorSidebars from '../provider/use-auto-switch-editor-side import { sidebars } from './constants'; import { unlock } from '../../lock-unlock'; import { store as editorStore } from '../../store'; +import PostTransformPanel from '../post-transform-panel'; +import TemplateContentPanel from '../template-content-panel'; const { Tabs } = unlock( componentsPrivateApis ); @@ -51,6 +51,8 @@ const SidebarContent = ( { tabName, keyboardShortcut, isEditingTemplate, + renderingMode, + onActionPerformed, extraPanels, } ) => { const tabListRef = useRef( null ); @@ -85,56 +87,6 @@ const SidebarContent = ( { selectedTabElement?.focus(); } }, [ tabName ] ); - const { createSuccessNotice } = useDispatch( noticesStore ); - - const onActionPerformed = useCallback( - ( actionId, items ) => { - switch ( actionId ) { - case 'move-to-trash': - { - const postType = items[ 0 ].type; - document.location.href = addQueryArgs( 'edit.php', { - post_type: postType, - } ); - } - break; - case 'duplicate-post': - { - const newItem = items[ 0 ]; - const title = - typeof newItem.title === 'string' - ? newItem.title - : newItem.title?.rendered; - createSuccessNotice( - sprintf( - // translators: %s: Title of the created post e.g: "Post 1". - __( '"%s" successfully created.' ), - title - ), - { - type: 'snackbar', - id: 'duplicate-post-action', - actions: [ - { - label: __( 'Edit' ), - onClick: () => { - const postId = newItem.id; - document.location.href = - addQueryArgs( 'post.php', { - post: postId, - action: 'edit', - } ); - }, - }, - ], - } - ); - } - break; - } - }, - [ createSuccessNotice ] - ); return ( { ! isEditingTemplate && } + { renderingMode !== 'post-only' && ( + + ) } + @@ -182,10 +138,10 @@ const SidebarContent = ( { ); }; -const Sidebar = ( { extraPanels } ) => { +const Sidebar = ( { extraPanels, onActionPerformed } ) => { useAutoSwitchEditorSidebars(); - const { tabName, keyboardShortcut, isEditingTemplate } = useSelect( - ( select ) => { + const { tabName, keyboardShortcut, isEditingTemplate, renderingMode } = + useSelect( ( select ) => { const shortcut = select( keyboardShortcutsStore ).getShortcutRepresentation( 'core/editor/toggle-sidebar' ); @@ -211,10 +167,9 @@ const Sidebar = ( { extraPanels } ) => { isEditingTemplate: select( editorStore ).getCurrentPostType() === 'wp_template', + renderingMode: select( editorStore ).getRenderingMode(), }; - }, - [] - ); + }, [] ); const { enableComplementaryArea } = useDispatch( interfaceStore ); @@ -237,6 +192,8 @@ const Sidebar = ( { extraPanels } ) => { tabName={ tabName } keyboardShortcut={ keyboardShortcut } isEditingTemplate={ isEditingTemplate } + renderingMode={ renderingMode } + onActionPerformed={ onActionPerformed } extraPanels={ extraPanels } /> diff --git a/packages/edit-site/src/components/sidebar-edit-mode/page-panels/page-content.js b/packages/editor/src/components/template-content-panel/index.js similarity index 64% rename from packages/edit-site/src/components/sidebar-edit-mode/page-panels/page-content.js rename to packages/editor/src/components/template-content-panel/index.js index 18a742add41b2a..e0f131f27feb5d 100644 --- a/packages/edit-site/src/components/sidebar-edit-mode/page-panels/page-content.js +++ b/packages/editor/src/components/template-content-panel/index.js @@ -6,11 +6,13 @@ import { store as blockEditorStore, privateApis as blockEditorPrivateApis, } from '@wordpress/block-editor'; +import { PanelBody } from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; /** * Internal dependencies */ -import { unlock } from '../../../lock-unlock'; +import { unlock } from '../../lock-unlock'; const { BlockQuickNavigation } = unlock( blockEditorPrivateApis ); @@ -20,10 +22,15 @@ const PAGE_CONTENT_BLOCKS = [ 'core/post-title', ]; -export default function PageContent() { +export default function TemplateContentPanel() { const clientIds = useSelect( ( select ) => { const { getBlocksByName } = select( blockEditorStore ); return getBlocksByName( PAGE_CONTENT_BLOCKS ); }, [] ); - return ; + + return ( + + + + ); }