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

Improve guidance to editing template when focused on editing a page #51366

Merged
merged 11 commits into from
Jun 19, 2023
16 changes: 4 additions & 12 deletions packages/edit-site/src/components/block-editor/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,29 +16,21 @@ import { ReusableBlocksMenuItems } from '@wordpress/reusable-blocks';
import TemplatePartConverter from '../template-part-converter';
import { SidebarInspectorFill } from '../sidebar-edit-mode';
import { store as editSiteStore } from '../../store';
import { unlock } from '../../lock-unlock';
import { DisableNonPageContentBlocks } from '../page-content-focus';
import SiteEditorCanvas from './site-editor-canvas';
import getBlockEditorProvider from './get-block-editor-provider';

export default function BlockEditor() {
const { entityType, hasPageContentFocus } = useSelect( ( select ) => {
const { getEditedPostType, hasPageContentFocus: _hasPageContentFocus } =
unlock( select( editSiteStore ) );

return {
entityType: getEditedPostType(),
hasPageContentFocus: _hasPageContentFocus(),
};
}, [] );
const entityType = useSelect(
( select ) => select( editSiteStore ).getEditedPostType(),
[]
);

// Choose the provider based on the entity type currently
// being edited.
const BlockEditorProvider = getBlockEditorProvider( entityType );

return (
<BlockEditorProvider>
{ hasPageContentFocus && <DisableNonPageContentBlocks /> }
<TemplatePartConverter />
<SidebarInspectorFill>
<BlockInspector />
Expand Down
101 changes: 52 additions & 49 deletions packages/edit-site/src/components/block-editor/site-editor-canvas.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ import BackButton from './back-button';
import ResizableEditor from './resizable-editor';
import EditorCanvas from './editor-canvas';
import EditorCanvasContainer from '../editor-canvas-container';
import { usePageContentFocusNotifications } from '../page-content-focus';
import useSiteEditorSettings from './use-site-editor-settings';
import { store as editSiteStore } from '../../store';
import { FOCUSABLE_ENTITIES } from './constants';
import { unlock } from '../../lock-unlock';
import PageContentFocusManager from '../page-content-focus-manager';

const LAYOUT = {
type: 'default',
Expand Down Expand Up @@ -82,7 +82,6 @@ export default function SiteEditorCanvas() {
contentRef,
useClipboardHandler(),
useTypingObserver(),
usePageContentFocusNotifications(),
] );

const isTemplateTypeNavigation = templateType === 'wp_navigation';
Expand All @@ -98,55 +97,59 @@ export default function SiteEditorCanvas() {
: undefined;

return (
<EditorCanvasContainer.Slot>
{ ( [ editorCanvasView ] ) =>
editorCanvasView ? (
<div className="edit-site-visual-editor is-focus-mode">
{ editorCanvasView }
</div>
) : (
<BlockTools
className={ classnames( 'edit-site-visual-editor', {
'is-focus-mode': isFocusMode || !! editorCanvasView,
'is-view-mode': isViewMode,
} ) }
__unstableContentRef={ contentRef }
onClick={ ( event ) => {
// Clear selected block when clicking on the gray background.
if ( event.target === event.currentTarget ) {
clearSelectedBlock();
}
} }
>
<BlockEditorKeyboardShortcuts.Register />
<BackButton />
<ResizableEditor
enableResizing={ enableResizing }
height={ sizes.height ?? '100%' }
<>
<EditorCanvasContainer.Slot>
{ ( [ editorCanvasView ] ) =>
editorCanvasView ? (
<div className="edit-site-visual-editor is-focus-mode">
{ editorCanvasView }
</div>
) : (
<BlockTools
className={ classnames( 'edit-site-visual-editor', {
'is-focus-mode':
isFocusMode || !! editorCanvasView,
'is-view-mode': isViewMode,
} ) }
__unstableContentRef={ contentRef }
onClick={ ( event ) => {
// Clear selected block when clicking on the gray background.
if ( event.target === event.currentTarget ) {
clearSelectedBlock();
}
} }
>
<EditorCanvas
<BlockEditorKeyboardShortcuts.Register />
<BackButton />
<ResizableEditor
enableResizing={ enableResizing }
settings={ settings }
contentRef={ mergedRefs }
readonly={ isViewMode }
height={ sizes.height ?? '100%' }
>
{ resizeObserver }
<BlockList
className={ classnames(
'edit-site-block-editor__block-list wp-site-blocks',
{
'is-navigation-block':
isTemplateTypeNavigation,
}
) }
layout={ LAYOUT }
renderAppender={ showBlockAppender }
/>
</EditorCanvas>
</ResizableEditor>
</BlockTools>
)
}
</EditorCanvasContainer.Slot>
<EditorCanvas
enableResizing={ enableResizing }
settings={ settings }
contentRef={ mergedRefs }
readonly={ isViewMode }
>
{ resizeObserver }
<BlockList
className={ classnames(
'edit-site-block-editor__block-list wp-site-blocks',
{
'is-navigation-block':
isTemplateTypeNavigation,
}
) }
layout={ LAYOUT }
renderAppender={ showBlockAppender }
/>
</EditorCanvas>
</ResizableEditor>
</BlockTools>
)
}
</EditorCanvasContainer.Slot>
<PageContentFocusManager contentRef={ contentRef } />
</>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/**
* WordPress dependencies
*/
import { useSelect, useDispatch } from '@wordpress/data';
import { useEffect, useRef } from '@wordpress/element';
import { store as noticesStore } from '@wordpress/notices';
import { __ } from '@wordpress/i18n';

/**
* Internal dependencies
*/
import { store as editSiteStore } from '../../store';

/**
* Component that displays a 'You are editing a template' notification when the
* user switches from focusing on editing page content to editing a template.
*/
export default function BackToPageNotification() {
useBackToPageNotification();
return null;
}

/**
* Hook that displays a 'You are editing a template' notification when the user
* switches from focusing on editing page content to editing a template.
*/
export function useBackToPageNotification() {
const hasPageContentFocus = useSelect(
( select ) => select( editSiteStore ).hasPageContentFocus(),
[]
);

const alreadySeen = useRef( false );
const prevHasPageContentFocus = useRef( false );

const { createInfoNotice } = useDispatch( noticesStore );
const { setHasPageContentFocus } = useDispatch( editSiteStore );

useEffect( () => {
if (
! alreadySeen.current &&
prevHasPageContentFocus.current &&
! hasPageContentFocus
) {
createInfoNotice( __( 'You are editing a template.' ), {
isDismissible: true,
type: 'snackbar',
actions: [
{
label: __( 'Back to page' ),
onClick: () => setHasPageContentFocus( true ),
},
],
} );
alreadySeen.current = true;
}
prevHasPageContentFocus.current = hasPageContentFocus;
}, [
alreadySeen,
prevHasPageContentFocus,
Comment on lines +59 to +60
Copy link
Member

@Mamaduka Mamaduka Jun 19, 2023

Choose a reason for hiding this comment

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

Nit: There's no need to add mutable values like refs as dependencies. When you provide them, alreadySeen.current ESLint shows a warning.

hasPageContentFocus,
createInfoNotice,
setHasPageContentFocus,
] );
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const { useBlockEditingMode } = unlock( blockEditorPrivateApis );
* Component that when rendered, makes it so that the site editor allows only
* page content to be edited.
*/
export function DisableNonPageContentBlocks() {
export default function DisableNonPageContentBlocks() {
useDisableNonPageContentBlocks();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/**
* WordPress dependencies
*/
import { useSelect, useDispatch } from '@wordpress/data';
import { useEffect, useState, useRef } from '@wordpress/element';
import { store as noticesStore } from '@wordpress/notices';
import { __ } from '@wordpress/i18n';
import { __experimentalConfirmDialog as ConfirmDialog } from '@wordpress/components';

/**
* Internal dependencies
*/
import { store as editSiteStore } from '../../store';

/**
* Component that:
*
* - Displays a 'Edit your template to edit this block' notification when the
* user is focusing on editing page content and clicks on a disabled template
* block.
* - Displays a 'Edit your template to edit this block' dialog when the user
* is focusing on editing page conetnt and double clicks on a disabled
* template block.
*
* @param {Object} props
* @param {import('react').RefObject<HTMLElement>} props.contentRef Ref to the block
* editor iframe canvas.
*/
noisysocks marked this conversation as resolved.
Show resolved Hide resolved
export default function EditTemplateNotification( { contentRef } ) {
const hasPageContentFocus = useSelect(
( select ) => select( editSiteStore ).hasPageContentFocus(),
[]
);
const { getNotices } = useSelect( noticesStore );

const { createInfoNotice, removeNotice } = useDispatch( noticesStore );
const { setHasPageContentFocus } = useDispatch( editSiteStore );

const [ isDialogOpen, setIsDialogOpen ] = useState( false );

const lastNoticeId = useRef( 0 );

useEffect( () => {
const handleClick = async ( event ) => {
if ( ! hasPageContentFocus ) {
return;
}
if ( ! event.target.classList.contains( 'is-root-container' ) ) {
return;
}
const isNoticeAlreadyShowing = getNotices().some(
noisysocks marked this conversation as resolved.
Show resolved Hide resolved
( notice ) => notice.id === lastNoticeId.current
);
if ( isNoticeAlreadyShowing ) {
return;
}
const { notice } = await createInfoNotice(
__( 'Edit your template to edit this block.' ),
{
isDismissible: true,
type: 'snackbar',
actions: [
{
label: __( 'Edit template' ),
onClick: () => setHasPageContentFocus( false ),
},
],
}
);
lastNoticeId.current = notice.id;
};

const handleDblClick = ( event ) => {
if ( ! hasPageContentFocus ) {
return;
}
if ( ! event.target.classList.contains( 'is-root-container' ) ) {
return;
}
if ( lastNoticeId.current ) {
removeNotice( lastNoticeId.current );
}
setIsDialogOpen( true );
};

const canvas = contentRef.current;
canvas?.addEventListener( 'click', handleClick );
canvas?.addEventListener( 'dblclick', handleDblClick );
return () => {
canvas?.removeEventListener( 'click', handleClick );
canvas?.removeEventListener( 'dblclick', handleDblClick );
};
}, [ lastNoticeId, hasPageContentFocus, contentRef.current ] );

return (
<ConfirmDialog
isOpen={ isDialogOpen }
confirmButtonText={ __( 'Edit template' ) }
onConfirm={ () => {
setIsDialogOpen( false );
setHasPageContentFocus( false );
} }
onCancel={ () => setIsDialogOpen( false ) }
>
{ __( 'Edit your template to edit this block.' ) }
</ConfirmDialog>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/**
* WordPress dependencies
*/
import { useSelect } from '@wordpress/data';

/**
* Internal dependencies
*/
import { store as editSiteStore } from '../../store';
import DisableNonPageContentBlocks from './disable-non-page-content-blocks';
import EditTemplateNotification from './edit-template-notification';
import BackToPageNotification from './back-to-page-notification';

export default function PageContentFocusManager( { contentRef } ) {
const hasPageContentFocus = useSelect(
( select ) => select( editSiteStore ).hasPageContentFocus(),
[]
);
return (
<>
{ hasPageContentFocus && <DisableNonPageContentBlocks /> }
<EditTemplateNotification contentRef={ contentRef } />
<BackToPageNotification />
</>
);
}
2 changes: 0 additions & 2 deletions packages/edit-site/src/components/page-content-focus/index.js

This file was deleted.

Loading