Skip to content

Commit

Permalink
Add: Page start options (templates and patterns).
Browse files Browse the repository at this point in the history
  • Loading branch information
jorgefilipecosta committed Mar 1, 2022
1 parent 6be0679 commit 515f42b
Show file tree
Hide file tree
Showing 4 changed files with 246 additions and 0 deletions.
2 changes: 2 additions & 0 deletions packages/edit-post/src/components/layout/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import SettingsSidebar from '../sidebar/settings-sidebar';
import MetaBoxes from '../meta-boxes';
import WelcomeGuide from '../welcome-guide';
import ActionsPanel from './actions-panel';
import StartPageOptions from '../start-page-options';
import { store as editPostStore } from '../../store';

const interfaceLabels = {
Expand Down Expand Up @@ -286,6 +287,7 @@ function Layout( { styles } ) {
<PreferencesModal />
<KeyboardShortcutHelpModal />
<WelcomeGuide />
<StartPageOptions />
<Popover.Slot />
<PluginArea onError={ onPluginAreaError } />
</>
Expand Down
216 changes: 216 additions & 0 deletions packages/edit-post/src/components/start-page-options/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
/**
* WordPress dependencies
*/
import { Modal } 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 { useAsyncList } from '@wordpress/compose';
import { store as editorStore } from '@wordpress/editor';
import { store as coreStore } from '@wordpress/core-data';
import { parse } from '@wordpress/blocks';

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

function TemplateSelection( { onChooseTemplate } ) {
const { availableTemplates, fetchedTemplates, linkedTemplate } = useSelect(
( select ) => {
const {
getEditorSettings,
getCurrentPostType,
getCurrentPost,
} = select( editorStore );
const { getEntityRecords } = select( coreStore );

const currentPostType = getCurrentPostType();
const currentPostLink = getCurrentPost().link;

const templateRecords = getEntityRecords(
'postType',
'wp_template',
{
post_type: currentPostType,
per_page: -1,
}
);

const linkedTemplateRecords = getEntityRecords(
'postType',
'wp_template',
{
'find-template': currentPostLink,
per_page: 1,
}
);

return {
availableTemplates: getEditorSettings().availableTemplates,
fetchedTemplates: templateRecords,
linkedTemplate:
linkedTemplateRecords && linkedTemplateRecords[ 0 ],
};
},
[]
);
const templatesAsPatterns = useMemo( () => {
let templates = ( fetchedTemplates || [] ).filter(
( { slug } ) => !! availableTemplates[ slug ]
);
if (
linkedTemplate &&
! templates.some( ( { id } ) => id === linkedTemplate.id )
) {
templates = [ linkedTemplate, ...templates ];
}
return templates.map( ( template ) => ( {
name: template.id,
title: template.title.rendered,
blocks: parse( template.content.raw ),
template,
} ) );
}, [ availableTemplates, fetchedTemplates, linkedTemplate ] );
const shownPatterns = useAsyncList( templatesAsPatterns );
const { editPost } = useDispatch( editorStore );
useEffect( () => {
if ( availableTemplates.length <= 1 ) {
onChooseTemplate();
}
}, [ availableTemplates.length ] );
return (
<BlockPatternsList
blockPatterns={ templatesAsPatterns }
shownPatterns={ shownPatterns }
onClickPattern={ ( { template } ) => {
if ( template.id !== linkedTemplate.id ) {
editPost( { template: template.slug } );
}
onChooseTemplate();
} }
/>
);
}

function PatternSelection( { onChoosePattern } ) {
const { blockPatterns } = useSelect( ( select ) => {
const { __experimentalGetPatternsByBlockTypes } = select(
blockEditorStore
);
return {
blockPatterns: __experimentalGetPatternsByBlockTypes(
'core/post-content'
),
};
}, [] );
const shownBlockPatterns = useAsyncList( blockPatterns );
const { resetEditorBlocks } = useDispatch( editorStore );
useEffect( () => {
if ( blockPatterns.length <= 1 ) {
onChoosePattern();
}
}, [ blockPatterns.length ] );
return (
<BlockPatternsList
blockPatterns={ blockPatterns }
shownPatterns={ shownBlockPatterns }
onClickPattern={ ( _pattern, blocks ) => {
resetEditorBlocks( blocks );
onChoosePattern();
} }
/>
);
}

const START_PAGE_MODAL_STATES = {
INITIAL: 'INITIAL',
TEMPLATE: 'TEMPLATE',
PATTERN: 'PATTERN',
CLOSED: 'CLOSED',
};

export default function StartPageOptions() {
const [ modalState, setModalState ] = useState(
START_PAGE_MODAL_STATES.INITIAL
);
const shouldOpenModel = useSelect(
( select ) => {
if ( modalState !== START_PAGE_MODAL_STATES.INITIAL ) {
return false;
}
const {
getCurrentPostType,
getEditedPostContent,
getEditedPostAttribute,
isEditedPostSaveable,
} = select( editorStore );
const { isEditingTemplate, isFeatureActive } = select(
editPostStore
);
return (
getCurrentPostType() === 'page' &&
! isEditedPostSaveable() &&
'' === getEditedPostContent() &&
'' === getEditedPostAttribute( 'template' ) &&
! isEditingTemplate() &&
! isFeatureActive( 'welcomeGuide' )
);
},
[ modalState ]
);

useEffect( () => {
if ( shouldOpenModel ) {
setModalState( START_PAGE_MODAL_STATES.TEMPLATE );
}
}, [ shouldOpenModel ] );

if (
modalState === START_PAGE_MODAL_STATES.INITIAL ||
modalState === START_PAGE_MODAL_STATES.CLOSED
) {
return null;
}
return (
<Modal
className="edit-post-start-page-options__modal"
title={
modalState === START_PAGE_MODAL_STATES.TEMPLATE
? __( 'Choose a template' )
: __( 'Choose a pattern' )
}
closeLabel={ __( 'Cancel' ) }
onRequestClose={ () => {
switch ( modalState ) {
case START_PAGE_MODAL_STATES.TEMPLATE:
setModalState( START_PAGE_MODAL_STATES.PATTERN );
return;
case START_PAGE_MODAL_STATES.PATTERN:
setModalState( START_PAGE_MODAL_STATES.CLOSED );
}
} }
>
<div className="edit-post-start-page-options__modal-content">
{ modalState === START_PAGE_MODAL_STATES.TEMPLATE && (
<TemplateSelection
onChooseTemplate={ () => {
setModalState( START_PAGE_MODAL_STATES.PATTERN );
} }
/>
) }
{ modalState === START_PAGE_MODAL_STATES.PATTERN && (
<PatternSelection
onChoosePattern={ () => {
setModalState( START_PAGE_MODAL_STATES.CLOSED );
} }
/>
) }
</div>
</Modal>
);
}
27 changes: 27 additions & 0 deletions packages/edit-post/src/components/start-page-options/style.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
.edit-post-start-page-options__modal {
// To keep modal dimensions consistent as subsections are navigated, width
// and height are used instead of max-(width/height).
@include break-small() {
width: calc(100% - #{ $grid-unit-20 * 2 });
height: calc(100% - #{ $header-height * 2 });
}
@include break-medium() {
width: $break-medium - $grid-unit-20 * 2;
}
@include break-large() {
height: 70%;
}
}

.edit-post-start-page-options__modal-content .block-editor-block-patterns-list {
display: grid;
grid-template-columns: 1fr 1fr;
grid-gap: $grid-unit-10;

.block-editor-block-patterns-list__list-item {
margin-bottom: 0;
.block-editor-block-preview__container {
min-height: 100px;
}
}
}
1 change: 1 addition & 0 deletions packages/edit-post/src/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
@import "./components/text-editor/style.scss";
@import "./components/visual-editor/style.scss";
@import "./components/welcome-guide/style.scss";
@import "./components/start-page-options/style.scss";

/**
* Animations
Expand Down

0 comments on commit 515f42b

Please sign in to comment.