From 6cc674b68f5b00775d58b8005dc9d5bdc0a98e43 Mon Sep 17 00:00:00 2001 From: ntsekouras Date: Fri, 26 Apr 2024 11:52:02 +0300 Subject: [PATCH 1/7] Add publish flow in site editor --- packages/base-styles/_z-index.scss | 1 + .../higher-order/navigate-regions/style.scss | 6 +- .../edit-post/src/components/header/index.js | 2 +- .../edit-post/src/components/layout/index.js | 5 +- .../src/components/layout/style.scss | 80 ------ .../edit-site/src/components/editor/index.js | 39 ++- .../src/components/header-edit-mode/index.js | 32 ++- .../page-panels/page-status.js | 249 ------------------ .../page-panels/page-summary.js | 19 +- .../sidebar-edit-mode/page-panels/style.scss | 34 --- packages/edit-site/src/style.scss | 1 - .../entities-saved-states/style.scss | 7 + .../post-layout-actions-panel/index.js} | 31 +-- .../post-layout-actions-panel/style.scss | 36 +++ .../post-publish-button-or-toggle.js | 7 +- .../test/post-publish-button-or-toggle.js} | 0 .../components/post-publish-panel/style.scss | 43 +++ packages/editor/src/private-apis.js | 4 + packages/editor/src/style.scss | 1 + .../components/interface-skeleton/style.scss | 2 +- 20 files changed, 189 insertions(+), 410 deletions(-) delete mode 100644 packages/edit-site/src/components/sidebar-edit-mode/page-panels/page-status.js delete mode 100644 packages/edit-site/src/components/sidebar-edit-mode/page-panels/style.scss rename packages/{edit-post/src/components/layout/actions-panel.js => editor/src/components/post-layout-actions-panel/index.js} (75%) create mode 100644 packages/editor/src/components/post-layout-actions-panel/style.scss rename packages/{edit-post/src/components/header => editor/src/components/post-publish-button}/post-publish-button-or-toggle.js (96%) rename packages/{edit-post/src/components/header/test/index.js => editor/src/components/post-publish-button/test/post-publish-button-or-toggle.js} (100%) diff --git a/packages/base-styles/_z-index.scss b/packages/base-styles/_z-index.scss index d995ccb31bbf5..1191c16670ba1 100644 --- a/packages/base-styles/_z-index.scss +++ b/packages/base-styles/_z-index.scss @@ -88,6 +88,7 @@ $z-layers: ( // #wpadminbar { z-index: 99999 } ".interface-interface-skeleton__sidebar": 100000, ".edit-post-layout__toggle-sidebar-panel": 100000, + ".editor-layout__toggle-sidebar-panel": 100000, ".edit-widgets-sidebar": 100000, ".edit-post-layout .edit-post-post-publish-panel": 100001, // For larger views, the wp-admin navbar dropdown should be at top of diff --git a/packages/components/src/higher-order/navigate-regions/style.scss b/packages/components/src/higher-order/navigate-regions/style.scss index f146413a09dc9..b3a4a0c1a9d1b 100644 --- a/packages/components/src/higher-order/navigate-regions/style.scss +++ b/packages/components/src/higher-order/navigate-regions/style.scss @@ -29,9 +29,9 @@ // Header top bar when Distraction free mode is on. &.is-distraction-free .interface-interface-skeleton__header .edit-post-header, - .interface-interface-skeleton__sidebar .edit-post-layout__toggle-sidebar-panel, - .interface-interface-skeleton__actions .edit-post-layout__toggle-publish-panel, - .interface-interface-skeleton__actions .edit-post-layout__toggle-entities-saved-states-panel, + .interface-interface-skeleton__sidebar .editor-layout__toggle-sidebar-panel, + .interface-interface-skeleton__actions .editor-layout__toggle-publish-panel, + .interface-interface-skeleton__actions .editor-layout__toggle-entities-saved-states-panel, .editor-post-publish-panel { outline: 4px solid $components-color-accent; outline-offset: -4px; diff --git a/packages/edit-post/src/components/header/index.js b/packages/edit-post/src/components/header/index.js index 32f2cc1ccd276..ff21478307754 100644 --- a/packages/edit-post/src/components/header/index.js +++ b/packages/edit-post/src/components/header/index.js @@ -24,7 +24,6 @@ import { useState } from '@wordpress/element'; */ import FullscreenModeClose from './fullscreen-mode-close'; import PostEditorMoreMenu from './more-menu'; -import PostPublishButtonOrToggle from './post-publish-button-or-toggle'; import MainDashboardButton from './main-dashboard-button'; import { store as editPostStore } from '../../store'; import { unlock } from '../../lock-unlock'; @@ -36,6 +35,7 @@ const { PreviewDropdown, PinnedItems, MoreMenu, + PostPublishButtonOrToggle, } = unlock( editorPrivateApis ); const slideY = { diff --git a/packages/edit-post/src/components/layout/index.js b/packages/edit-post/src/components/layout/index.js index 4db2c1ebf41e7..9bfa80bfd7cd1 100644 --- a/packages/edit-post/src/components/layout/index.js +++ b/packages/edit-post/src/components/layout/index.js @@ -48,7 +48,6 @@ import Header from '../header'; import SettingsSidebar from '../sidebar/settings-sidebar'; import MetaBoxes from '../meta-boxes'; import WelcomeGuide from '../welcome-guide'; -import ActionsPanel from './actions-panel'; import { store as editPostStore } from '../../store'; import { unlock } from '../../lock-unlock'; import useCommonCommands from '../../hooks/commands/use-common-commands'; @@ -61,6 +60,7 @@ const { ListViewSidebar, ComplementaryArea, FullscreenMode, + PostLayoutActionsPanel, InterfaceSkeleton, interfaceStore, } = unlock( editorPrivateApis ); @@ -345,7 +345,7 @@ function Layout( { initialPost } ) { ) } actions={ - } shortcuts={ { diff --git a/packages/edit-post/src/components/layout/style.scss b/packages/edit-post/src/components/layout/style.scss index 229ab58a4e14b..5837a05201ba6 100644 --- a/packages/edit-post/src/components/layout/style.scss +++ b/packages/edit-post/src/components/layout/style.scss @@ -19,83 +19,3 @@ } @include editor-left(".edit-post-layout .components-editor-notices__snackbar"); - -.edit-post-layout .editor-post-publish-panel { - position: fixed; - z-index: z-index(".edit-post-layout .edit-post-post-publish-panel"); - top: $admin-bar-height-big; - bottom: 0; - right: 0; - left: 0; - overflow: auto; - - @include break-medium() { - z-index: z-index(".edit-post-layout .edit-post-post-publish-panel {greater than small}"); - top: $admin-bar-height; - left: auto; - width: $sidebar-width + $border-width; - border-left: $border-width solid $gray-300; - transform: translateX(+100%); - animation: edit-post-post-publish-panel__slide-in-animation 0.1s forwards; - @include reduce-motion("animation"); - - body.is-fullscreen-mode & { - top: 0; - } - - // Keep it open on focus to avoid conflict with navigate-regions animation. - [role="region"]:focus & { - transform: translateX(0%); - } - } -} - -@keyframes edit-post-post-publish-panel__slide-in-animation { - 100% { - transform: translateX(0%); - } -} - -.edit-post-layout .editor-post-publish-panel__header-publish-button { - justify-content: center; -} - -.edit-post-layout__toggle-publish-panel, -.edit-post-layout__toggle-sidebar-panel, -.edit-post-layout__toggle-entities-saved-states-panel { - z-index: z-index(".edit-post-layout__toggle-sidebar-panel"); - position: fixed !important; // Need to override the default relative positionning - top: -9999em; - bottom: auto; - left: auto; - right: 0; - box-sizing: border-box; - width: $sidebar-width; - background-color: $white; - border: 1px dotted $gray-300; - height: auto !important; // Need to override the default sidebar positionnings - padding: $grid-unit-30; - display: flex; - justify-content: center; -} - -.edit-post-layout__toggle-sidebar-panel { - .interface-interface-skeleton__sidebar:focus &, - .interface-interface-skeleton__sidebar:focus-within & { - top: auto; - bottom: 0; - } -} - -.edit-post-layout__toggle-entities-saved-states-panel, -.edit-post-layout__toggle-publish-panel { - .interface-interface-skeleton__actions:focus &, - .interface-interface-skeleton__actions:focus-within & { - top: auto; - bottom: 0; - } -} - -.edit-post-layout .entities-saved-states__panel-header { - height: $header-height + $border-width; -} diff --git a/packages/edit-site/src/components/editor/index.js b/packages/edit-site/src/components/editor/index.js index d6773e5a24d89..2ec8172a626b4 100644 --- a/packages/edit-site/src/components/editor/index.js +++ b/packages/edit-site/src/components/editor/index.js @@ -35,6 +35,7 @@ import { 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'; /** * Internal dependencies @@ -66,6 +67,7 @@ const { InterfaceSkeleton, ComplementaryArea, interfaceStore, + PostLayoutActionsPanel, } = unlock( editorPrivateApis ); const { BlockKeyboardShortcuts } = unlock( blockLibraryPrivateApis ); @@ -189,6 +191,22 @@ export default function Editor( { isLoading, onClick } ) { const { closeGeneralSidebar } = useDispatch( editSiteStore ); const settings = useSpecificEditorSettings(); + + // Local state for save panel. + // Note 'truthy' callback implies an open panel. + const [ entitiesSavedStatesCallback, setEntitiesSavedStatesCallback ] = + useState( false ); + + const closeEntitiesSavedStates = useCallback( + ( arg ) => { + if ( typeof entitiesSavedStatesCallback === 'function' ) { + entitiesSavedStatesCallback( arg ); + } + setEntitiesSavedStatesCallback( false ); + }, + [ entitiesSavedStatesCallback ] + ); + const isReady = ! isLoading && ( ( postWithTemplate && !! contextPost && !! editedPost ) || @@ -223,6 +241,8 @@ export default function Editor( { isLoading, onClick } ) { 'edit-site-editor__interface-skeleton', { 'show-icon-labels': showIconLabels, + 'is-entity-save-view-open': + !! entitiesSavedStatesCallback, } ) } header={ @@ -249,11 +269,28 @@ export default function Editor( { isLoading, onClick } ) { ease: [ 0.6, 0, 0.4, 1 ], } } > -
+
) } } + actions={ + + } notices={ } content={ <> diff --git a/packages/edit-site/src/components/header-edit-mode/index.js b/packages/edit-site/src/components/header-edit-mode/index.js index 1bf925a928b6e..02de04731cc78 100644 --- a/packages/edit-site/src/components/header-edit-mode/index.js +++ b/packages/edit-site/src/components/header-edit-mode/index.js @@ -14,6 +14,7 @@ import { __unstableMotion as motion } from '@wordpress/components'; import { store as preferencesStore } from '@wordpress/preferences'; import { DocumentBar, + PostSavedState, store as editorStore, privateApis as editorPrivateApis, } from '@wordpress/editor'; @@ -31,6 +32,7 @@ import { } from '../editor-canvas-container'; import { unlock } from '../../lock-unlock'; import { FOCUSABLE_ENTITIES } from '../../utils/constants'; +import { isPreviewingTheme } from '../../utils/is-previewing-theme'; const { CollapsableBlockToolbar, @@ -38,9 +40,10 @@ const { PostViewLink, PreviewDropdown, PinnedItems, + PostPublishButtonOrToggle, } = unlock( editorPrivateApis ); -export default function HeaderEditMode() { +export default function HeaderEditMode( { setEntitiesSavedStatesCallback } ) { const { templateType, isDistractionFree, @@ -48,6 +51,7 @@ export default function HeaderEditMode() { showIconLabels, editorCanvasView, isFixedToolbar, + isPublishSidebarOpened, } = useSelect( ( select ) => { const { getEditedPostType } = select( editSiteStore ); const { __unstableGetEditorMode } = select( blockEditorStore ); @@ -64,6 +68,8 @@ export default function HeaderEditMode() { ).getEditorCanvasContainerView(), isDistractionFree: getPreference( 'core', 'distractionFree' ), isFixedToolbar: getPreference( 'core', 'fixedToolbar' ), + isPublishSidebarOpened: + select( editorStore ).isPublishSidebarOpened(), }; }, [] ); @@ -94,6 +100,7 @@ export default function HeaderEditMode() { ease: 'easeOut', }; + const _isPreviewingTheme = isPreviewingTheme(); return (
) } - + { + // TODO: For now we conditionally render the Save/Publish buttons based on + // some specific site editor extra handling. Examples are when we're previewing + // a theme, handling of global styles changes or when we're in 'view' mode, + // which opens the save panel in a Modal. + } + { ! _isPreviewingTheme && ! isPublishSidebarOpened && ( + // This button isn't completely hidden by the publish sidebar. + // We can't hide the whole toolbar when the publish sidebar is open because + // we want to prevent mounting/unmounting the PostPublishButtonOrToggle DOM node. + // We track that DOM node to return focus to the PostPublishButtonOrToggle + // when the publish sidebar has been closed. + + ) } + { ! _isPreviewingTheme && ( + + ) } + { _isPreviewingTheme && } { ! isDistractionFree && } diff --git a/packages/edit-site/src/components/sidebar-edit-mode/page-panels/page-status.js b/packages/edit-site/src/components/sidebar-edit-mode/page-panels/page-status.js deleted file mode 100644 index a1c60276c7994..0000000000000 --- a/packages/edit-site/src/components/sidebar-edit-mode/page-panels/page-status.js +++ /dev/null @@ -1,249 +0,0 @@ -/** - * WordPress dependencies - */ -import { - Button, - ToggleControl, - Dropdown, - __experimentalText as Text, - __experimentalVStack as VStack, - TextControl, - RadioControl, - VisuallyHidden, -} from '@wordpress/components'; -import { __ } from '@wordpress/i18n'; -import { useDispatch } from '@wordpress/data'; -import { useState, useMemo } from '@wordpress/element'; -import { store as coreStore } from '@wordpress/core-data'; -import { store as noticesStore } from '@wordpress/notices'; -import { __experimentalInspectorPopoverHeader as InspectorPopoverHeader } from '@wordpress/block-editor'; -import { useInstanceId } from '@wordpress/compose'; -import { privateApis as editorPrivateApis } from '@wordpress/editor'; - -/** - * Internal dependencies - */ -import StatusLabel from '../../sidebar-navigation-screen-page/status-label'; -import { unlock } from '../../../lock-unlock'; - -const { PostPanelRow } = unlock( editorPrivateApis ); - -const STATUS_OPTIONS = [ - { - label: ( - <> - { __( 'Draft' ) } - { __( 'Not ready to publish.' ) } - - ), - value: 'draft', - }, - { - label: ( - <> - { __( 'Pending' ) } - - { __( 'Waiting for review before publishing.' ) } - - - ), - value: 'pending', - }, - { - label: ( - <> - { __( 'Private' ) } - - { __( 'Only visible to site admins and editors.' ) } - - - ), - value: 'private', - }, - { - label: ( - <> - { __( 'Scheduled' ) } - - { __( 'Publish automatically on a chosen date.' ) } - - - ), - value: 'future', - }, - { - label: ( - <> - { __( 'Published' ) } - { __( 'Visible to everyone.' ) } - - ), - value: 'publish', - }, -]; - -export default function PageStatus( { - postType, - postId, - status, - password, - date, -} ) { - const [ showPassword, setShowPassword ] = useState( !! password ); - const instanceId = useInstanceId( PageStatus ); - - const { editEntityRecord } = useDispatch( coreStore ); - const { createErrorNotice } = useDispatch( noticesStore ); - - const [ popoverAnchor, setPopoverAnchor ] = useState( null ); - // Memoize popoverProps to avoid returning a new object every time. - const popoverProps = useMemo( - () => ( { - // Anchor the popover to the middle of the entire row so that it doesn't - // move around when the label changes. - anchor: popoverAnchor, - 'aria-label': __( 'Change status' ), - placement: 'bottom-end', - } ), - [ popoverAnchor ] - ); - - const saveStatus = async ( { - status: newStatus = status, - password: newPassword = password, - date: newDate = date, - } ) => { - try { - await editEntityRecord( 'postType', postType, postId, { - status: newStatus, - date: newDate, - password: newPassword, - } ); - } catch ( error ) { - const errorMessage = - error.message && error.code !== 'unknown_error' - ? error.message - : __( 'An error occurred while updating the status' ); - - createErrorNotice( errorMessage, { - type: 'snackbar', - } ); - } - }; - - const handleTogglePassword = ( value ) => { - setShowPassword( value ); - if ( ! value ) { - saveStatus( { password: '' } ); - } - }; - - const handleStatus = ( value ) => { - let newDate = date; - let newPassword = password; - if ( value === 'publish' ) { - if ( new Date( date ) > new Date() ) { - newDate = null; - } - } else if ( value === 'future' ) { - if ( ! date || new Date( date ) < new Date() ) { - newDate = new Date(); - newDate.setDate( newDate.getDate() + 7 ); - } - } else if ( value === 'private' && password ) { - setShowPassword( false ); - newPassword = ''; - } - saveStatus( { - status: value, - date: newDate, - password: newPassword, - } ); - }; - - return ( - - ( - - ) } - renderContent={ ( { onClose } ) => ( - <> - -
- - - { status !== 'private' && ( -
- - { __( 'Password' ) } - - - { showPassword && ( -
- - { __( 'Create password' ) } - - - saveStatus( { - password: value, - } ) - } - value={ password } - placeholder={ __( - 'Use a secure password' - ) } - type="text" - id={ `edit-site-change-status__password-input-${ instanceId }` } - /> -
- ) } -
- ) } -
-
- - ) } - /> -
- ); -} 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 index 5b8710ac3abe4..b0bee04d0f75c 100644 --- 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 @@ -15,32 +15,19 @@ import { /** * Internal dependencies */ -import PageStatus from './page-status'; import { unlock } from '../../../lock-unlock'; -const { PrivatePostExcerptPanel } = unlock( editorPrivateApis ); +const { PrivatePostExcerptPanel, PostStatus } = unlock( editorPrivateApis ); -export default function PageSummary( { - status, - date, - password, - postId, - postType, -} ) { +export default function PageSummary() { return ( { ( fills ) => ( <> + - diff --git a/packages/edit-site/src/components/sidebar-edit-mode/page-panels/style.scss b/packages/edit-site/src/components/sidebar-edit-mode/page-panels/style.scss deleted file mode 100644 index 426bf103bb41a..0000000000000 --- a/packages/edit-site/src/components/sidebar-edit-mode/page-panels/style.scss +++ /dev/null @@ -1,34 +0,0 @@ -.edit-site-change-status__content { - .components-popover__content { - min-width: 320px; - padding: $grid-unit-20; - } - - .edit-site-change-status__options { - .components-base-control__field > .components-v-stack { - gap: $grid-unit-10; - } - - label { - .components-text { - display: block; - } - } - } - - .edit-site-change-status__password-legend { - padding: 0; - margin-bottom: $grid-unit-10; - } -} - -.edit-site-summary-field__trigger { - max-width: 100%; - - // Truncate - display: block; - text-align: left; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} diff --git a/packages/edit-site/src/style.scss b/packages/edit-site/src/style.scss index 8c0117a523350..677956c8f3fa8 100644 --- a/packages/edit-site/src/style.scss +++ b/packages/edit-site/src/style.scss @@ -13,7 +13,6 @@ @import "./components/page-templates/style.scss"; @import "./components/table/style.scss"; @import "./components/sidebar-edit-mode/style.scss"; -@import "./components/sidebar-edit-mode/page-panels/style.scss"; @import "./components/sidebar-edit-mode/settings-header/style.scss"; @import "./components/sidebar-edit-mode/template-panel/style.scss"; @import "./components/editor/style.scss"; diff --git a/packages/editor/src/components/entities-saved-states/style.scss b/packages/editor/src/components/entities-saved-states/style.scss index 981a0d92e5ff6..f4e0c9f814c24 100644 --- a/packages/editor/src/components/entities-saved-states/style.scss +++ b/packages/editor/src/components/entities-saved-states/style.scss @@ -30,3 +30,10 @@ margin-bottom: $grid-unit-05; } } + +.edit-post-layout, +.edit-site-editor__interface-skeleton { + .entities-saved-states__panel-header { + height: $header-height + $border-width; + } +} diff --git a/packages/edit-post/src/components/layout/actions-panel.js b/packages/editor/src/components/post-layout-actions-panel/index.js similarity index 75% rename from packages/edit-post/src/components/layout/actions-panel.js rename to packages/editor/src/components/post-layout-actions-panel/index.js index 6914cf6ff3c06..ad5018f41153e 100644 --- a/packages/edit-post/src/components/layout/actions-panel.js +++ b/packages/editor/src/components/post-layout-actions-panel/index.js @@ -1,13 +1,6 @@ /** * WordPress dependencies */ -import { - EntitiesSavedStates, - PostPublishPanel, - PluginPrePublishPanel, - PluginPostPublishPanel, - store as editorStore, -} from '@wordpress/editor'; import { useSelect, useDispatch } from '@wordpress/data'; import { Button, createSlotFill } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; @@ -16,28 +9,28 @@ import { useCallback } from '@wordpress/element'; /** * Internal dependencies */ -import { store as editPostStore } from '../../store'; +import EntitiesSavedStates from '../entities-saved-states'; +import PostPublishPanel from '../post-publish-panel'; +import PluginPrePublishPanel from '../plugin-pre-publish-panel'; +import PluginPostPublishPanel from '../plugin-post-publish-panel'; +import { store as editorStore } from '../../store'; const { Fill, Slot } = createSlotFill( 'ActionsPanel' ); export const ActionsPanelFill = Fill; -export default function ActionsPanel( { +export default function PostLayoutActionsPanel( { setEntitiesSavedStatesCallback, closeEntitiesSavedStates, isEntitiesSavedStatesOpen, + hasActiveMetaboxes, } ) { const { closePublishSidebar, togglePublishSidebar } = useDispatch( editorStore ); - const { - publishSidebarOpened, - hasActiveMetaboxes, - hasNonPostEntityChanges, - } = useSelect( + const { publishSidebarOpened, hasNonPostEntityChanges } = useSelect( ( select ) => ( { publishSidebarOpened: select( editorStore ).isPublishSidebarOpened(), - hasActiveMetaboxes: select( editPostStore ).hasMetaBoxes(), hasNonPostEntityChanges: select( editorStore ).hasNonPostEntityChanges(), } ), @@ -63,10 +56,10 @@ export default function ActionsPanel( { ); } else if ( hasNonPostEntityChanges ) { unmountableContent = ( -
+