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: Restore starter content modal #69081

Open
wants to merge 5 commits into
base: trunk
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 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
1 change: 1 addition & 0 deletions packages/base-styles/_z-index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ $z-layers: (

// Ensure modal footer actions appear above modal contents
".editor-start-template-options__modal__actions": 1,
".editor-start-page-options__modal__actions": 1,

// Ensure checkbox + actions don't overlap table header
".dataviews-view-table thead": 1,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ import { usePatternCategories } from '../block-patterns-tab/use-pattern-categori

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

const patternCategories = usePatternCategories( rootClientId );

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,7 @@ function BlockPatternsTab( {
) }
{ showPatternsExplorer && (
<PatternsExplorerModal
initialCategory={
selectedCategory?.name || categories[ 0 ]?.name
}
initialCategory={ selectedCategory || categories[ 0 ] }
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 explicitly 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 @@ -65,9 +65,7 @@ function CategoryTabs( {
key={ category.name }
tabId={ category.name }
aria-current={
category.name === selectedCategory?.name
? 'true'
: undefined
category === selectedCategory ? 'true' : undefined
}
>
{ category.label }
Expand Down
12 changes: 2 additions & 10 deletions packages/block-editor/src/hooks/use-zoom-out.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,13 @@
* WordPress dependencies
*/
import { useSelect, useDispatch } from '@wordpress/data';
import { useEffect, useRef, useContext } from '@wordpress/element';
import { useEffect, useRef } 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 @@ -20,7 +19,6 @@ import BlockContext from '../components/block-context';
* @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 @@ -39,7 +37,6 @@ 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 @@ -58,11 +55,6 @@ 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 @@ -79,5 +71,5 @@ export function useZoomOut( enabled = true ) {
resetZoomLevel();
}
};
}, [ enabled, isZoomOut, postId, resetZoomLevel, setZoomLevel ] );
}, [ enabled, isZoomOut, resetZoomLevel, setZoomLevel ] );
}
21 changes: 13 additions & 8 deletions packages/editor/src/components/preferences-modal/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ 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 @@ -72,6 +73,7 @@ function PreferencesModalContents( { extraSections = {} } ) {
const { setIsListViewOpened, setIsInserterOpened } =
useDispatch( editorStore );
const { set: setPreference } = useDispatch( preferencesStore );
const hasStarterPatterns = !! useStartPatterns().length;

const sections = useMemo(
() =>
Expand Down Expand Up @@ -112,14 +114,16 @@ function PreferencesModalContents( { extraSections = {} } ) {
'Allow right-click contextual menus'
) }
/>
<PreferenceToggleControl
scope="core"
featureName="enableChoosePatternModal"
help={ __(
'Shows starter patterns when creating a new page.'
) }
label={ __( 'Show starter patterns' ) }
/>
{ hasStarterPatterns && (
Mamaduka marked this conversation as resolved.
Show resolved Hide resolved
<PreferenceToggleControl
scope="core"
featureName="enableChoosePatternModal"
help={ __(
'Shows starter patterns when creating a new page.'
) }
label={ __( 'Show starter patterns' ) }
/>
) }
</PreferencesModalSection>
<PreferencesModalSection
title={ __( 'Document settings' ) }
Expand Down Expand Up @@ -337,6 +341,7 @@ function PreferencesModalContents( { extraSections = {} } ) {
setIsListViewOpened,
setPreference,
isLargeViewport,
hasStarterPatterns,
]
);

Expand Down
169 changes: 146 additions & 23 deletions packages/editor/src/components/start-page-options/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
/**
* WordPress dependencies
*/
import { useEffect } from '@wordpress/element';
import { Flex, FlexItem, Modal, ToggleControl } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import { useState, useMemo, useEffect } from '@wordpress/element';
import {
store as blockEditorStore,
__experimentalBlockPatternsList as BlockPatternsList,
} from '@wordpress/block-editor';
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';

Expand All @@ -11,8 +19,130 @@ import { store as interfaceStore } from '@wordpress/interface';
*/
import { store as editorStore } from '../../store';

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 [ showStartPatterns, setShowStartPatterns ] = useState( true );
const { set: setPreference } = useDispatch( preferencesStore );
const startPatterns = useStartPatterns();
const hasStartPattern = startPatterns.length > 0;

if ( ! hasStartPattern ) {
return null;
}

function handleClose() {
onClose();
setPreference( 'core', 'enableChoosePatternModal', showStartPatterns );
}

return (
<Modal
className="editor-start-page-options__modal"
title={ __( 'Choose a pattern' ) }
isFullScreen
onRequestClose={ handleClose }
>
<div className="editor-start-page-options__modal-content">
<PatternSelection
blockPatterns={ startPatterns }
onChoosePattern={ handleClose }
/>
</div>
<Flex
className="editor-start-page-options__modal__actions"
justify="flex-end"
expanded={ false }
>
<FlexItem>
<ToggleControl
__nextHasNoMarginBottom
checked={ showStartPatterns }
label={ __( 'Show starter patterns' ) }
help={ __(
'Shows starter patterns when creating a new page.'
) }
onChange={ ( newValue ) => {
setShowStartPatterns( newValue );
} }
/>
Comment on lines +125 to +135
Copy link
Member Author

Choose a reason for hiding this comment

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

I just duplicated the option from the Preferences modal. Compared to "Don't show me this modal", I like neutral labeling here.

Let me know if you prefer to change anything.

</FlexItem>
</Flex>
</Modal>
);
}

export default function StartPageOptions() {
const { postId, enabled } = useSelect( ( select ) => {
const [ isOpen, setIsOpen ] = useState( false );
const { isEditedPostDirty, isEditedPostEmpty } = useSelect( editorStore );
const { enabled, postId } = useSelect( ( select ) => {
const { getCurrentPostId, getCurrentPostType } = select( editorStore );
const preferencesModalActive =
select( interfaceStore ).isModalActive( 'editor/preferences' );
Expand All @@ -28,31 +158,24 @@ export default function StartPageOptions() {
'page' === getCurrentPostType(),
};
}, [] );
const { isEditedPostDirty, isEditedPostEmpty } = useSelect( editorStore );
const { setIsInserterOpened } = useDispatch( editorStore );

// Note: The `postId` ensures the effect re-runs when pages are switched without remounting the component.
// Examples: changing pages in the List View, creating a new page via Command Palette.
useEffect( () => {
if ( ! enabled ) {
const isFreshPage = ! isEditedPostDirty() && isEditedPostEmpty();
if ( ! enabled || ! isFreshPage ) {
return;
}

const isFreshPage = ! isEditedPostDirty() && isEditedPostEmpty();
if ( isFreshPage ) {
setIsInserterOpened( {
tab: 'patterns',
category: 'core/starter-content',
} );
}
// Open the modal after the initial render for a new page.
setIsOpen( true );

return () => setIsOpen( false );
}, [ enabled, postId, isEditedPostDirty, isEditedPostEmpty ] );

if ( ! isOpen ) {
return null;
}

// Note: The `postId` ensures the effect re-runs when pages are switched without remounting the component.
// Examples: changing pages in the List View, creating a new page via Command Palette.
}, [
postId,
enabled,
setIsInserterOpened,
isEditedPostDirty,
isEditedPostEmpty,
] );

return null;
return <StartPageOptionsModal onClose={ () => setIsOpen( false ) } />;
}
Loading
Loading