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

Replace Starter Content modal with inserter panel #66836

Merged
merged 17 commits into from
Dec 20, 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
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,8 @@ import { usePatternCategories } from '../block-patterns-tab/use-pattern-categori

function PatternsExplorer( { initialCategory, rootClientId } ) {
const [ searchValue, setSearchValue ] = useState( '' );
const [ selectedCategory, setSelectedCategory ] = useState(
initialCategory?.name
);
const [ selectedCategory, setSelectedCategory ] =
useState( initialCategory );

const patternCategories = usePatternCategories( rootClientId );

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,9 @@ function BlockPatternsTab( {
) }
{ showPatternsExplorer && (
<PatternsExplorerModal
initialCategory={ selectedCategory || categories[ 0 ] }
initialCategory={
selectedCategory?.name || categories[ 0 ]?.name
}
patternCategories={ categories }
onModalClose={ () => setShowPatternsExplorer( false ) }
rootClientId={ rootClientId }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,19 +69,19 @@ export function PatternCategoryPreviews( {
return false;
}

if ( category.name === allPatternsCategory.name ) {
if ( category.name === allPatternsCategory?.name ) {
return true;
}

if (
category.name === myPatternsCategory.name &&
category.name === myPatternsCategory?.name &&
pattern.type === INSERTER_PATTERN_TYPES.user
) {
return true;
}

if (
category.name === starterPatternsCategory.name &&
category.name === starterPatternsCategory?.name &&
pattern.blockTypes?.includes( 'core/post-content' )
) {
return true;
Expand Down Expand Up @@ -149,7 +149,7 @@ export function PatternCategoryPreviews( {
level={ 4 }
as="div"
>
{ category.label }
{ category?.label }
</Heading>
</FlexBlock>
<PatternsFilter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import {
const getShouldDisableSyncFilter = ( sourceFilter ) =>
sourceFilter !== 'all' && sourceFilter !== 'user';
const getShouldHideSourcesFilter = ( category ) => {
return category.name === myPatternsCategory.name;
return category?.name === myPatternsCategory.name;
};

const PATTERN_SOURCE_MENU_OPTIONS = [
Expand Down Expand Up @@ -60,7 +60,7 @@ export function PatternsFilter( {
// the user may be confused when switching to another category if the haven't explicity set
// this filter themselves.
const currentPatternSourceFilter =
category.name === myPatternsCategory.name
category?.name === myPatternsCategory.name
? INSERTER_PATTERN_TYPES.user
: patternSourceFilter;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,9 @@ function CategoryTabs( {
tabId={ category.name }
aria-label={ category.label }
aria-current={
category === selectedCategory ? 'true' : undefined
category.name === selectedCategory?.name
? 'true'
: undefined
}
>
{ category.label }
Expand Down
12 changes: 10 additions & 2 deletions packages/block-editor/src/hooks/use-zoom-out.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@
* WordPress dependencies
*/
import { useSelect, useDispatch } from '@wordpress/data';
import { useEffect, useRef } from '@wordpress/element';
import { useEffect, useRef, useContext } from '@wordpress/element';

/**
* Internal dependencies
*/
import { store as blockEditorStore } from '../store';
import { unlock } from '../lock-unlock';
import BlockContext from '../components/block-context';

/**
* A hook used to set the editor mode to zoomed out mode, invoking the hook sets the mode.
Expand All @@ -19,6 +20,7 @@ import { unlock } from '../lock-unlock';
* @param {boolean} enabled If we should enter into zoomOut mode or not
*/
export function useZoomOut( enabled = true ) {
const { postId } = useContext( BlockContext );
const { setZoomLevel, resetZoomLevel } = unlock(
useDispatch( blockEditorStore )
);
Expand All @@ -37,6 +39,7 @@ export function useZoomOut( enabled = true ) {

const controlZoomLevelRef = useRef( false );
const isEnabledRef = useRef( enabled );
const postIdRef = useRef( postId );

/**
* This hook tracks if the zoom state was changed manually by the user via clicking
Expand All @@ -55,6 +58,11 @@ export function useZoomOut( enabled = true ) {
useEffect( () => {
isEnabledRef.current = enabled;

// If the user created a new post/page, we should take control of the zoom level.
if ( postIdRef.current !== postId ) {
controlZoomLevelRef.current = true;
}

if ( enabled !== isZoomOut() ) {
controlZoomLevelRef.current = true;

Expand All @@ -71,5 +79,5 @@ export function useZoomOut( enabled = true ) {
resetZoomLevel();
}
};
}, [ enabled, isZoomOut, resetZoomLevel, setZoomLevel ] );
}, [ enabled, isZoomOut, postId, resetZoomLevel, setZoomLevel ] );
}
21 changes: 8 additions & 13 deletions packages/editor/src/components/preferences-modal/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import PageAttributesCheck from '../page-attributes/check';
import PostTypeSupportCheck from '../post-type-support-check';
import { store as editorStore } from '../../store';
import { unlock } from '../../lock-unlock';
import { useStartPatterns } from '../start-page-options';

const {
PreferencesModal,
Expand Down Expand Up @@ -73,7 +72,6 @@ function PreferencesModalContents( { extraSections = {} } ) {
const { setIsListViewOpened, setIsInserterOpened } =
useDispatch( editorStore );
const { set: setPreference } = useDispatch( preferencesStore );
const hasStarterPatterns = !! useStartPatterns().length;

const sections = useMemo(
() =>
Expand Down Expand Up @@ -114,16 +112,14 @@ function PreferencesModalContents( { extraSections = {} } ) {
'Allow right-click contextual menus'
) }
/>
{ hasStarterPatterns && (
<PreferenceToggleControl
scope="core"
featureName="enableChoosePatternModal"
help={ __(
'Shows starter patterns when creating a new page.'
) }
label={ __( 'Show starter patterns' ) }
/>
) }
<PreferenceToggleControl
scope="core"
featureName="enableChoosePatternModal"
help={ __(
'Shows starter patterns when creating a new page.'
) }
label={ __( 'Show starter patterns' ) }
/>
Copy link
Contributor

Choose a reason for hiding this comment

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

Why did we remove the condition?

Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe because we want this setting to persist across themes, even if they don't have starter patterns?

</PreferencesModalSection>
<PreferencesModalSection
title={ __( 'Document settings' ) }
Expand Down Expand Up @@ -341,7 +337,6 @@ function PreferencesModalContents( { extraSections = {} } ) {
setIsListViewOpened,
setPreference,
isLargeViewport,
hasStarterPatterns,
]
);

Expand Down
147 changes: 28 additions & 119 deletions packages/editor/src/components/start-page-options/index.js
Original file line number Diff line number Diff line change
@@ -1,141 +1,50 @@
/**
* WordPress dependencies
*/
import { Modal } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import { useState, useMemo } from '@wordpress/element';
import {
store as blockEditorStore,
__experimentalBlockPatternsList as BlockPatternsList,
} from '@wordpress/block-editor';
import { useEffect } from '@wordpress/element';
import { useSelect, useDispatch } from '@wordpress/data';
import { store as coreStore } from '@wordpress/core-data';
import { __unstableSerializeAndClean } from '@wordpress/blocks';
import { store as preferencesStore } from '@wordpress/preferences';
import { store as interfaceStore } from '@wordpress/interface';

/**
* Internal dependencies
*/
import { store as editorStore } from '../../store';
import { TEMPLATE_POST_TYPE } from '../../store/constants';

export function useStartPatterns() {
// A pattern is a start pattern if it includes 'core/post-content' in its blockTypes,
// and it has no postTypes declared and the current post type is page or if
// the current post type is part of the postTypes declared.
const { blockPatternsWithPostContentBlockType, postType } = useSelect(
( select ) => {
const { getPatternsByBlockTypes, getBlocksByName } =
select( blockEditorStore );
const { getCurrentPostType, getRenderingMode } =
select( editorStore );
const rootClientId =
getRenderingMode() === 'post-only'
? ''
: getBlocksByName( 'core/post-content' )?.[ 0 ];
return {
blockPatternsWithPostContentBlockType: getPatternsByBlockTypes(
'core/post-content',
rootClientId
),
postType: getCurrentPostType(),
};
},
[]
);

return useMemo( () => {
if ( ! blockPatternsWithPostContentBlockType?.length ) {
return [];
}

/*
* Filter patterns without postTypes declared if the current postType is page
* or patterns that declare the current postType in its post type array.
*/
return blockPatternsWithPostContentBlockType.filter( ( pattern ) => {
return (
( postType === 'page' && ! pattern.postTypes ) ||
( Array.isArray( pattern.postTypes ) &&
pattern.postTypes.includes( postType ) )
);
} );
}, [ postType, blockPatternsWithPostContentBlockType ] );
}

function PatternSelection( { blockPatterns, onChoosePattern } ) {
const { editEntityRecord } = useDispatch( coreStore );
const { postType, postId } = useSelect( ( select ) => {
const { getCurrentPostType, getCurrentPostId } = select( editorStore );

return {
postType: getCurrentPostType(),
postId: getCurrentPostId(),
};
}, [] );
return (
<BlockPatternsList
blockPatterns={ blockPatterns }
onClickPattern={ ( _pattern, blocks ) => {
editEntityRecord( 'postType', postType, postId, {
blocks,
content: ( { blocks: blocksForSerialization = [] } ) =>
__unstableSerializeAndClean( blocksForSerialization ),
} );
onChoosePattern();
} }
/>
);
}

function StartPageOptionsModal( { onClose } ) {
const startPatterns = useStartPatterns();
const hasStartPattern = startPatterns.length > 0;

if ( ! hasStartPattern ) {
return null;
}

return (
<Modal
title={ __( 'Choose a pattern' ) }
isFullScreen
onRequestClose={ onClose }
>
<div className="editor-start-page-options__modal-content">
<PatternSelection
blockPatterns={ startPatterns }
onChoosePattern={ onClose }
/>
</div>
</Modal>
);
}

export default function StartPageOptions() {
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we just remove this component and transform it into a hook?

const [ isClosed, setIsClosed ] = useState( false );
const shouldEnableModal = useSelect( ( select ) => {
const { isEditedPostDirty, isEditedPostEmpty, getCurrentPostType } =
select( editorStore );
const { postId, shouldEnable } = useSelect( ( select ) => {
const {
isEditedPostDirty,
isEditedPostEmpty,
getCurrentPostId,
getCurrentPostType,
} = select( editorStore );
const preferencesModalActive =
select( interfaceStore ).isModalActive( 'editor/preferences' );
const choosePatternModalEnabled = select( preferencesStore ).get(
'core',
'enableChoosePatternModal'
);
return (
choosePatternModalEnabled &&
! preferencesModalActive &&
! isEditedPostDirty() &&
isEditedPostEmpty() &&
TEMPLATE_POST_TYPE !== getCurrentPostType()
);
return {
postId: getCurrentPostId(),
shouldEnable:
choosePatternModalEnabled &&
! preferencesModalActive &&
! isEditedPostDirty() &&
isEditedPostEmpty() &&
'page' === getCurrentPostType(),
};
}, [] );
const { setIsInserterOpened } = useDispatch( editorStore );

useEffect( () => {
if ( shouldEnable ) {
setIsInserterOpened( {
tab: 'patterns',
category: 'core/starter-content',
} );
}
}, [ postId, shouldEnable, setIsInserterOpened ] );

if ( ! shouldEnableModal || isClosed ) {
return null;
}

return <StartPageOptionsModal onClose={ () => setIsClosed( true ) } />;
return null;
}
3 changes: 0 additions & 3 deletions test/e2e/specs/editor/blocks/image.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -424,9 +424,6 @@ test.describe( 'Image', () => {
page,
editor,
} ) => {
// This is a temp workaround for dragging and dropping images from the inserter.
// This should be removed when we have the zoom out view for media categories.
await page.setViewportSize( { width: 1400, height: 800 } );
Comment on lines -427 to -429
Copy link
Member

Choose a reason for hiding this comment

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

It looks like this isn't needed anymore so I went ahead and removed it.

await editor.insertBlock( { name: 'core/image' } );
const imageBlock = editor.canvas.getByRole( 'document', {
name: 'Block: Image',
Expand Down
4 changes: 4 additions & 0 deletions test/e2e/specs/editor/various/template-resolution.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,15 @@ test.describe( 'Template resolution', () => {
status: 'publish',
} );
await admin.editPost( newPage.id );
await page.locator( 'role=button[name="Block Inserter"i]' ).click();
await editor.openDocumentSettingsSidebar();
await expect(
page.getByRole( 'button', { name: 'Template options' } )
).toHaveText( 'Single Entries' );
await updateSiteSettings( { requestUtils, pageId: newPage.id } );
await page.reload();
await page.locator( 'role=button[name="Block Inserter"i]' ).click();
await editor.openDocumentSettingsSidebar();
await expect(
page.getByRole( 'button', { name: 'Template options' } )
).toHaveText( 'Index' );
Expand All @@ -81,6 +84,7 @@ test.describe( 'Template resolution', () => {
postType: 'page',
canvas: 'edit',
} );
await page.locator( 'role=button[name="Block Inserter"i]' ).click();
await editor.openDocumentSettingsSidebar();
await expect(
page.getByRole( 'button', { name: 'Template options' } )
Expand Down
4 changes: 1 addition & 3 deletions test/e2e/specs/site-editor/block-style-variations.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -317,9 +317,7 @@ async function draftNewPage( page ) {

// Create a Group block with 2 nested Group blocks.
async function addPageContent( editor, page ) {
const inserterButton = page.locator(
'role=button[name="Block Inserter"i]'
);
const inserterButton = page.locator( 'role=tab[name="Blocks"i]' );
await inserterButton.click();
await page.type( 'role=searchbox[name="Search"i]', 'Group' );
await page.click(
Expand Down
Loading
Loading