@@ -74,7 +74,7 @@ function gutenberg_register_gutenberg_patterns() {
),
'query-grid-posts' => array(
'title' => _x( 'Grid', 'Block pattern title', 'gutenberg' ),
- 'blockTypes' => array( 'core/query' ),
+ 'blockTypes' => array( 'core/query', 'core/post-content' ),
'categories' => array( 'query' ),
'content' => '
diff --git a/packages/edit-post/src/components/layout/index.js b/packages/edit-post/src/components/layout/index.js
index 989c185943c2c6..133e423e714975 100644
--- a/packages/edit-post/src/components/layout/index.js
+++ b/packages/edit-post/src/components/layout/index.js
@@ -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 = {
@@ -286,6 +287,7 @@ function Layout( { styles } ) {
+
>
diff --git a/packages/edit-post/src/components/start-page-options/index.js b/packages/edit-post/src/components/start-page-options/index.js
new file mode 100644
index 00000000000000..092883d3654d70
--- /dev/null
+++ b/packages/edit-post/src/components/start-page-options/index.js
@@ -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 (
+
{
+ 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 (
+ {
+ 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 (
+ {
+ 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 );
+ }
+ } }
+ >
+
+ { modalState === START_PAGE_MODAL_STATES.TEMPLATE && (
+
{
+ setModalState( START_PAGE_MODAL_STATES.PATTERN );
+ } }
+ />
+ ) }
+ { modalState === START_PAGE_MODAL_STATES.PATTERN && (
+ {
+ setModalState( START_PAGE_MODAL_STATES.CLOSED );
+ } }
+ />
+ ) }
+
+
+ );
+}
diff --git a/packages/edit-post/src/components/start-page-options/style.scss b/packages/edit-post/src/components/start-page-options/style.scss
new file mode 100644
index 00000000000000..78c0011aa6f288
--- /dev/null
+++ b/packages/edit-post/src/components/start-page-options/style.scss
@@ -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;
+ }
+ }
+}
diff --git a/packages/edit-post/src/style.scss b/packages/edit-post/src/style.scss
index 8db03ae060ab78..50c848f86fff1d 100644
--- a/packages/edit-post/src/style.scss
+++ b/packages/edit-post/src/style.scss
@@ -23,6 +23,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