From 6d74db5a55ecc5fdd3257b7b483224682f7919b0 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Thu, 1 Apr 2021 09:52:39 +0100 Subject: [PATCH 01/12] Allow creating custom block templates in classic themes --- lib/client-assets.php | 2 +- lib/editor-settings.php | 4 +- lib/full-site-editing/page-templates.php | 20 ++-- lib/full-site-editing/template-loader.php | 8 +- lib/full-site-editing/template-parts.php | 12 +-- lib/full-site-editing/templates.php | 12 +-- package-lock.json | 3 +- packages/core-data/src/resolvers.js | 17 ++-- packages/edit-post/package.json | 3 +- .../components/sidebar/post-template/index.js | 97 +++++++++++-------- packages/edit-post/src/editor.js | 4 +- packages/edit-post/src/store/actions.js | 48 +++++++++ 12 files changed, 150 insertions(+), 80 deletions(-) diff --git a/lib/client-assets.php b/lib/client-assets.php index 6ffb733fc6a9b2..eb6cf31093047f 100644 --- a/lib/client-assets.php +++ b/lib/client-assets.php @@ -666,7 +666,7 @@ function gutenberg_extend_block_editor_styles( $settings ) { * @return array Filtered editor settings. */ function gutenberg_extend_block_editor_settings_with_fse_theme_flag( $settings ) { - $settings['isFSETheme'] = gutenberg_is_fse_theme(); + $settings['supportsTemplateMode'] = true; // gutenberg_is_fse_theme(); // Enable the new layout options for themes with a theme.json file. $settings['supportsLayout'] = WP_Theme_JSON_Resolver::theme_has_support(); diff --git a/lib/editor-settings.php b/lib/editor-settings.php index 3aff40945abf69..e9891f49609e59 100644 --- a/lib/editor-settings.php +++ b/lib/editor-settings.php @@ -39,7 +39,7 @@ function gutenberg_get_common_block_editor_settings() { }; $settings = array( - '__unstableEnableFullSiteEditingBlocks' => gutenberg_is_fse_theme(), + '__unstableEnableFullSiteEditingBlocks' => true, // gutenberg_is_fse_theme(), 'disableCustomColors' => get_theme_support( 'disable-custom-colors' ), 'disableCustomFontSizes' => get_theme_support( 'disable-custom-font-sizes' ), 'disableCustomGradients' => get_theme_support( 'disable-custom-gradients' ), @@ -81,7 +81,7 @@ function gutenberg_extend_post_editor_settings( $settings ) { $image_sizes = wp_list_pluck( $settings['imageSizes'], 'slug' ); $settings['imageDefaultSize'] = in_array( $image_default_size, $image_sizes, true ) ? $image_default_size : 'large'; - $settings['__unstableEnableFullSiteEditingBlocks'] = gutenberg_is_fse_theme(); + $settings['__unstableEnableFullSiteEditingBlocks'] = true; // gutenberg_is_fse_theme(); return $settings; } diff --git a/lib/full-site-editing/page-templates.php b/lib/full-site-editing/page-templates.php index 6c5a11c8a40e23..6044dcc68ceeb0 100644 --- a/lib/full-site-editing/page-templates.php +++ b/lib/full-site-editing/page-templates.php @@ -15,22 +15,16 @@ * @return array (Maybe) modified page templates array. */ function gutenberg_load_block_page_templates( $templates, $theme, $post, $post_type ) { - if ( ! gutenberg_is_fse_theme() ) { + /*if ( ! gutenberg_is_fse_theme() ) { return $templates; - } + }*/ - $data = WP_Theme_JSON_Resolver::get_theme_data()->get_custom_templates(); - $custom_templates = array(); - if ( isset( $data ) ) { - foreach ( $data as $key => $template ) { - if ( ( ! isset( $template['postTypes'] ) && 'page' === $post_type ) || - ( isset( $template['postTypes'] ) && in_array( $post_type, $template['postTypes'], true ) ) - ) { - $custom_templates[ $key ] = $template['title']; - } - } + $block_templates = gutenberg_get_block_templates( array(), 'wp_template' ); + foreach ( $block_templates as $template ) { + // TODO: exclude templates that are not concerned by the current post type. + $templates[ $template->slug ] = $template->title; } - return $custom_templates; + return $templates; } add_filter( 'theme_templates', 'gutenberg_load_block_page_templates', 10, 4 ); diff --git a/lib/full-site-editing/template-loader.php b/lib/full-site-editing/template-loader.php index c828a27c99a7bd..78fc262b1582ae 100644 --- a/lib/full-site-editing/template-loader.php +++ b/lib/full-site-editing/template-loader.php @@ -9,9 +9,9 @@ * Adds necessary filters to use 'wp_template' posts instead of theme template files. */ function gutenberg_add_template_loader_filters() { - if ( ! gutenberg_is_fse_theme() ) { + /* if ( ! gutenberg_is_fse_theme() ) { return; - } + } */ foreach ( gutenberg_get_template_type_slugs() as $template_type ) { if ( 'embed' === $template_type ) { // Skip 'embed' for now because it is not a regular template type. @@ -66,7 +66,7 @@ function gutenberg_override_query_template( $template, $type, array $templates = $current_template = gutenberg_resolve_template( $type, $templates ); // Allow falling back to a PHP template if it has a higher priority than the block template. - $current_template_slug = basename( $template, '.php' ); + /* $current_template_slug = basename( $template, '.php' ); $current_block_template_slug = is_object( $current_template ) ? $current_template->slug : false; foreach ( $templates as $template_item ) { $template_item_slug = gutenberg_strip_php_suffix( $template_item ); @@ -76,7 +76,7 @@ function gutenberg_override_query_template( $template, $type, array $templates = if ( $current_template_slug !== $current_block_template_slug && $current_template_slug === $template_item_slug ) { return $template; } - } + } */ if ( $current_template ) { if ( empty( $current_template->content ) && is_user_logged_in() ) { diff --git a/lib/full-site-editing/template-parts.php b/lib/full-site-editing/template-parts.php index a64416cfc39f9c..2921152faff4d3 100644 --- a/lib/full-site-editing/template-parts.php +++ b/lib/full-site-editing/template-parts.php @@ -9,9 +9,9 @@ * Registers block editor 'wp_template_part' post type. */ function gutenberg_register_template_part_post_type() { - if ( ! gutenberg_is_fse_theme() ) { + /* if ( ! gutenberg_is_fse_theme() ) { return; - } + } */ $labels = array( 'name' => __( 'Template Parts', 'gutenberg' ), @@ -64,9 +64,9 @@ function gutenberg_register_template_part_post_type() { * Registers the 'wp_template_part_area' taxonomy. */ function gutenberg_register_wp_template_part_area_taxonomy() { - if ( ! gutenberg_is_fse_theme() ) { + /* if ( ! gutenberg_is_fse_theme() ) { return; - } + } */ register_taxonomy( 'wp_template_part_area', @@ -107,9 +107,9 @@ function gutenberg_register_wp_template_part_area_taxonomy() { * Fixes the label of the 'wp_template_part' admin menu entry. */ function gutenberg_fix_template_part_admin_menu_entry() { - if ( ! gutenberg_is_fse_theme() ) { + /* if ( ! gutenberg_is_fse_theme() ) { return; - } + } */ global $submenu; if ( ! isset( $submenu['themes.php'] ) ) { diff --git a/lib/full-site-editing/templates.php b/lib/full-site-editing/templates.php index 6362d7716c3c1c..dcef8e19e0bc12 100644 --- a/lib/full-site-editing/templates.php +++ b/lib/full-site-editing/templates.php @@ -28,9 +28,9 @@ function gutenberg_get_template_paths() { * Registers block editor 'wp_template' post type. */ function gutenberg_register_template_post_type() { - if ( ! gutenberg_is_fse_theme() ) { + /* if ( ! gutenberg_is_fse_theme() ) { return; - } + } */ $labels = array( 'name' => __( 'Templates', 'gutenberg' ), @@ -84,9 +84,9 @@ function gutenberg_register_template_post_type() { * Registers block editor 'wp_theme' taxonomy. */ function gutenberg_register_wp_theme_taxonomy() { - if ( ! gutenberg_is_fse_theme() ) { + /* if ( ! gutenberg_is_fse_theme() ) { return; - } + } */ register_taxonomy( 'wp_theme', @@ -139,9 +139,9 @@ function gutenberg_grant_template_caps( array $allcaps ) { * Fixes the label of the 'wp_template' admin menu entry. */ function gutenberg_fix_template_admin_menu_entry() { - if ( ! gutenberg_is_fse_theme() ) { + /* if ( ! gutenberg_is_fse_theme() ) { return; - } + } */ global $submenu; if ( ! isset( $submenu['themes.php'] ) ) { return; diff --git a/package-lock.json b/package-lock.json index 81b7f2e4bb11da..e4f25d93b2d6b6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12783,7 +12783,8 @@ "classnames": "^2.2.5", "lodash": "^4.17.19", "memize": "^1.1.0", - "rememo": "^3.0.0" + "rememo": "^3.0.0", + "uuid": "8.3.0" } }, "@wordpress/edit-site": { diff --git a/packages/core-data/src/resolvers.js b/packages/core-data/src/resolvers.js index dcbf37d93b2b8a..28245a16e3e69b 100644 --- a/packages/core-data/src/resolvers.js +++ b/packages/core-data/src/resolvers.js @@ -385,13 +385,18 @@ export function* __experimentalGetTemplateForLink( link ) { // Ideally this should be using an apiFetch call // We could potentially do so by adding a "filter" to the `wp_template` end point. // Also it seems the returned object is not a regular REST API post type. - const template = yield regularFetch( - addQueryArgs( link, { - '_wp-find-template': true, - } ) - ); + let template; + try { + template = yield regularFetch( + addQueryArgs( link, { + '_wp-find-template': true, + } ) + ); + } catch ( e ) { + // For non-FSE themes, it is possible that this request returns an error. + } - if ( template === null ) { + if ( ! template ) { return; } diff --git a/packages/edit-post/package.json b/packages/edit-post/package.json index 2d5f7af3c145d9..7a4b71fc309dc0 100644 --- a/packages/edit-post/package.json +++ b/packages/edit-post/package.json @@ -52,7 +52,8 @@ "classnames": "^2.2.5", "lodash": "^4.17.19", "memize": "^1.1.0", - "rememo": "^3.0.0" + "rememo": "^3.0.0", + "uuid": "8.3.0" }, "publishConfig": { "access": "public" diff --git a/packages/edit-post/src/components/sidebar/post-template/index.js b/packages/edit-post/src/components/sidebar/post-template/index.js index 806f49fa04edb3..230ce552d333da 100644 --- a/packages/edit-post/src/components/sidebar/post-template/index.js +++ b/packages/edit-post/src/components/sidebar/post-template/index.js @@ -7,7 +7,6 @@ import { useSelect, useDispatch } from '@wordpress/data'; import { createInterpolateElement } from '@wordpress/element'; import { store as editorStore } from '@wordpress/editor'; import { store as coreStore } from '@wordpress/core-data'; -import { store as noticesStore } from '@wordpress/notices'; /** * Internal dependencies @@ -15,37 +14,48 @@ import { store as noticesStore } from '@wordpress/notices'; import { store as editPostStore } from '../../../store'; function PostTemplate() { - const { template, isEditing, isFSETheme } = useSelect( ( select ) => { + const { + template, + isEditing, + supportsTemplateMode, + isResolvingTemplate, + } = useSelect( ( select ) => { const { getEditedPostAttribute, getCurrentPostType, getCurrentPost, } = select( editorStore ); - const { __experimentalGetTemplateForLink, getPostType } = select( - coreStore - ); + const { + __experimentalGetTemplateForLink, + getPostType, + isResolving, + } = select( coreStore ); const { isEditingTemplate } = select( editPostStore ); const link = getEditedPostAttribute( 'link' ); - const isFSEEnabled = select( editorStore ).getEditorSettings() - .isFSETheme; + const _supportsTemplateMode = select( editorStore ).getEditorSettings() + .supportsTemplateMode; const isViewable = getPostType( getCurrentPostType() )?.viewable ?? false; + return { template: - isFSEEnabled && + supportsTemplateMode && isViewable && link && getCurrentPost().status !== 'auto-draft' ? __experimentalGetTemplateForLink( link ) : null, isEditing: isEditingTemplate(), - isFSETheme: isFSEEnabled, + supportsTemplateMode: _supportsTemplateMode, + isResolvingTemplate: isResolving( + '__experimentalGetTemplateForLink', + [ link ] + ), }; }, [] ); - const { setIsEditingTemplate } = useDispatch( editPostStore ); - const { createSuccessNotice } = useDispatch( noticesStore ); + const { __unstableSwitchToEditingMode } = useDispatch( editPostStore ); - if ( ! isFSETheme || ! template ) { + if ( ! supportsTemplateMode || isResolvingTemplate ) { return null; } @@ -54,33 +64,44 @@ function PostTemplate() { { __( 'Template' ) } { ! isEditing && ( - { createInterpolateElement( - sprintf( - /* translators: 1: Template name. */ - __( '%s (Edit)' ), - template.slug - ), - { - a: ( - + { !! template && + createInterpolateElement( + sprintf( + /* translators: 1: Template name. */ + __( '%s (Edit)' ), + template.slug ), - } - ) } + { + a: ( + + ), + } + ) } + { ! template && + createInterpolateElement( + __( 'Default ()' ), + { + create: ( + + ), + } + ) } ) } { isEditing && ( diff --git a/packages/edit-post/src/editor.js b/packages/edit-post/src/editor.js index 3f0fa4d1105c7a..4aebbed8e4d9cd 100644 --- a/packages/edit-post/src/editor.js +++ b/packages/edit-post/src/editor.js @@ -79,7 +79,7 @@ function Editor( { } else { postObject = getEntityRecord( 'postType', postType, postId ); } - const isFSETheme = getEditorSettings().isFSETheme; + const supportsTemplateMode = getEditorSettings().supportsTemplateMode; const isViewable = getPostType( postType )?.viewable ?? false; return { @@ -100,7 +100,7 @@ function Editor( { keepCaretInsideBlock: isFeatureActive( 'keepCaretInsideBlock' ), isTemplateMode: isEditingTemplate(), template: - isFSETheme && + supportsTemplateMode && isViewable && postObject && getCurrentPost().status !== 'auto-draft' diff --git a/packages/edit-post/src/store/actions.js b/packages/edit-post/src/store/actions.js index 61d481143e095c..c4edc2c20ac279 100644 --- a/packages/edit-post/src/store/actions.js +++ b/packages/edit-post/src/store/actions.js @@ -1,6 +1,7 @@ /** * External dependencies */ +import { v4 as uuid } from 'uuid'; import { castArray, reduce } from 'lodash'; /** @@ -11,6 +12,9 @@ import { apiFetch } from '@wordpress/data-controls'; import { store as interfaceStore } from '@wordpress/interface'; import { controls, dispatch, select, subscribe } from '@wordpress/data'; import { speak } from '@wordpress/a11y'; +import { store as noticesStore } from '@wordpress/notices'; +import { createBlock, serialize } from '@wordpress/blocks'; +import { store as coreStore } from '@wordpress/core-data'; /** * Internal dependencies @@ -436,3 +440,47 @@ export function setIsEditingTemplate( value ) { value, }; } + +export function* __unstableSwitchToEditingMode( shouldCreateTemplate = false ) { + if ( shouldCreateTemplate ) { + const templateContent = [ + createBlock( 'core/post-title' ), + createBlock( 'core/post-content' ), + ]; + const template = { + slug: 'custom-template-' + uuid(), + content: serialize( templateContent ), + title: 'Custom Template', + }; + const savedTemplate = yield controls.dispatch( + coreStore, + 'saveEntityRecord', + 'postType', + 'wp_template', + template + ); + const post = yield controls.select( 'core/editor', 'getCurrentPost' ); + + yield controls.dispatch( + coreStore, + 'editEntityRecord', + 'postType', + post.type, + post.id, + { + template: savedTemplate.slug, + } + ); + } + + yield setIsEditingTemplate( true ); + + const message = shouldCreateTemplate + ? __( "Custom template created. You're in template mode now." ) + : __( + 'Editing template. Changes made here affect all posts and pages that use the template.' + ); + yield controls.dispatch( noticesStore, 'createSuccessNotice', message, { + type: 'snackbar', + } ); +} From 40b15b5dd41bec229dd5f57e15dd4280b0ecfece Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Thu, 1 Apr 2021 10:46:32 +0100 Subject: [PATCH 02/12] Fix template fetching --- packages/core-data/src/resolvers.js | 9 +++ .../components/header/template-title/index.js | 13 ++-- .../components/sidebar/post-template/index.js | 65 +++++++------------ packages/edit-post/src/editor.js | 19 ++---- packages/edit-post/src/store/selectors.js | 29 +++++++++ 5 files changed, 74 insertions(+), 61 deletions(-) diff --git a/packages/core-data/src/resolvers.js b/packages/core-data/src/resolvers.js index 28245a16e3e69b..df7228676b05e9 100644 --- a/packages/core-data/src/resolvers.js +++ b/packages/core-data/src/resolvers.js @@ -415,3 +415,12 @@ export function* __experimentalGetTemplateForLink( link ) { } ); } } + +__experimentalGetTemplateForLink.shouldInvalidate = ( action ) => { + return ( + ( action.type === 'RECEIVE_ITEMS' || action.type === 'REMOVE_ITEMS' ) && + action.invalidateCache && + action.kind === 'postType' && + action.name === 'wp_template' + ); +}; diff --git a/packages/edit-post/src/components/header/template-title/index.js b/packages/edit-post/src/components/header/template-title/index.js index deb2b905ee9e34..877c48ccf50da0 100644 --- a/packages/edit-post/src/components/header/template-title/index.js +++ b/packages/edit-post/src/components/header/template-title/index.js @@ -3,8 +3,6 @@ */ import { __, sprintf } from '@wordpress/i18n'; import { useSelect } from '@wordpress/data'; -import { store as editorStore } from '@wordpress/editor'; -import { store as coreStore } from '@wordpress/core-data'; /** * Internal dependencies @@ -13,15 +11,12 @@ import { store as editPostStore } from '../../../store'; function TemplateTitle() { const { template, isEditing } = useSelect( ( select ) => { - const { getEditedPostAttribute } = select( editorStore ); - const { __experimentalGetTemplateForLink } = select( coreStore ); - const { isEditingTemplate } = select( editPostStore ); - const link = getEditedPostAttribute( 'link' ); + const { isEditingTemplate, getEditedPostTemplate } = select( + editPostStore + ); const _isEditing = isEditingTemplate(); return { - template: _isEditing - ? __experimentalGetTemplateForLink( link ) - : null, + template: _isEditing ? getEditedPostTemplate() : null, isEditing: _isEditing, }; }, [] ); diff --git a/packages/edit-post/src/components/sidebar/post-template/index.js b/packages/edit-post/src/components/sidebar/post-template/index.js index 230ce552d333da..ae2ec1459acbe8 100644 --- a/packages/edit-post/src/components/sidebar/post-template/index.js +++ b/packages/edit-post/src/components/sidebar/post-template/index.js @@ -14,48 +14,33 @@ import { store as coreStore } from '@wordpress/core-data'; import { store as editPostStore } from '../../../store'; function PostTemplate() { - const { - template, - isEditing, - supportsTemplateMode, - isResolvingTemplate, - } = useSelect( ( select ) => { - const { - getEditedPostAttribute, - getCurrentPostType, - getCurrentPost, - } = select( editorStore ); - const { - __experimentalGetTemplateForLink, - getPostType, - isResolving, - } = select( coreStore ); - const { isEditingTemplate } = select( editPostStore ); - const link = getEditedPostAttribute( 'link' ); - const _supportsTemplateMode = select( editorStore ).getEditorSettings() - .supportsTemplateMode; - const isViewable = - getPostType( getCurrentPostType() )?.viewable ?? false; + const { template, isEditing, supportsTemplateMode } = useSelect( + ( select ) => { + const { getCurrentPostType } = select( editorStore ); + const { getPostType } = select( coreStore ); + const { isEditingTemplate, getEditedPostTemplate } = select( + editPostStore + ); + const _supportsTemplateMode = select( + editorStore + ).getEditorSettings().supportsTemplateMode; + const isViewable = + getPostType( getCurrentPostType() )?.viewable ?? false; - return { - template: - supportsTemplateMode && - isViewable && - link && - getCurrentPost().status !== 'auto-draft' - ? __experimentalGetTemplateForLink( link ) - : null, - isEditing: isEditingTemplate(), - supportsTemplateMode: _supportsTemplateMode, - isResolvingTemplate: isResolving( - '__experimentalGetTemplateForLink', - [ link ] - ), - }; - }, [] ); + return { + template: + supportsTemplateMode && + isViewable && + getEditedPostTemplate(), + isEditing: isEditingTemplate(), + supportsTemplateMode: _supportsTemplateMode, + }; + }, + [] + ); const { __unstableSwitchToEditingMode } = useDispatch( editPostStore ); - if ( ! supportsTemplateMode || isResolvingTemplate ) { + if ( ! supportsTemplateMode ) { return null; } @@ -106,7 +91,7 @@ function PostTemplate() { ) } { isEditing && ( - { template.slug } + { template?.slug } ) } diff --git a/packages/edit-post/src/editor.js b/packages/edit-post/src/editor.js index 4aebbed8e4d9cd..12aabd865e5dc4 100644 --- a/packages/edit-post/src/editor.js +++ b/packages/edit-post/src/editor.js @@ -56,14 +56,12 @@ function Editor( { getPreference, __experimentalGetPreviewDeviceType, isEditingTemplate, + getEditedPostTemplate, } = select( editPostStore ); - const { - getEntityRecord, - __experimentalGetTemplateForLink, - getPostType, - getEntityRecords, - } = select( 'core' ); - const { getEditorSettings, getCurrentPost } = select( 'core/editor' ); + const { getEntityRecord, getPostType, getEntityRecords } = select( + 'core' + ); + const { getEditorSettings } = select( 'core/editor' ); const { getBlockTypes } = select( blocksStore ); const isTemplate = [ 'wp_template', 'wp_template_part' ].includes( postType @@ -100,11 +98,8 @@ function Editor( { keepCaretInsideBlock: isFeatureActive( 'keepCaretInsideBlock' ), isTemplateMode: isEditingTemplate(), template: - supportsTemplateMode && - isViewable && - postObject && - getCurrentPost().status !== 'auto-draft' - ? __experimentalGetTemplateForLink( postObject.link ) + supportsTemplateMode && isViewable + ? getEditedPostTemplate() : null, post: postObject, }; diff --git a/packages/edit-post/src/store/selectors.js b/packages/edit-post/src/store/selectors.js index 2fb6c95a8276de..940ad34517ac82 100644 --- a/packages/edit-post/src/store/selectors.js +++ b/packages/edit-post/src/store/selectors.js @@ -9,6 +9,8 @@ import { get, includes, some, flatten, values } from 'lodash'; */ import { createRegistrySelector } from '@wordpress/data'; import { store as interfaceStore } from '@wordpress/interface'; +import { store as coreStore } from '@wordpress/core-data'; +import { store as editorStore } from '@wordpress/editor'; /** * Returns the current editing mode. * @@ -335,3 +337,30 @@ export function isInserterOpened( state ) { export function isEditingTemplate( state ) { return state.isEditingTemplate; } + +/** + * Retrieves the template of the currently edited post. + * + * @return {Object?} Post Template. + */ +export const getEditedPostTemplate = createRegistrySelector( + ( select ) => () => { + const currentTemplate = select( editorStore ).getEditedPostAttribute( + 'template' + ); + if ( currentTemplate ) { + return select( coreStore ) + .getEntityRecords( 'postType', 'wp_template' ) + ?.find( ( template ) => template.slug === currentTemplate ); + } + + const post = select( editorStore ).getCurrentPost(); + if ( post.link && post.status !== 'auto-draft' ) { + return select( coreStore ).__experimentalGetTemplateForLink( + post.link + ); + } + + return null; + } +); From f691e6d47569301046616030e506f44d5bee3cba Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Thu, 1 Apr 2021 12:12:43 +0100 Subject: [PATCH 03/12] Restore PHP callback --- lib/full-site-editing/template-loader.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/full-site-editing/template-loader.php b/lib/full-site-editing/template-loader.php index 78fc262b1582ae..dffe065156758e 100644 --- a/lib/full-site-editing/template-loader.php +++ b/lib/full-site-editing/template-loader.php @@ -66,7 +66,7 @@ function gutenberg_override_query_template( $template, $type, array $templates = $current_template = gutenberg_resolve_template( $type, $templates ); // Allow falling back to a PHP template if it has a higher priority than the block template. - /* $current_template_slug = basename( $template, '.php' ); + $current_template_slug = basename( $template, '.php' ); $current_block_template_slug = is_object( $current_template ) ? $current_template->slug : false; foreach ( $templates as $template_item ) { $template_item_slug = gutenberg_strip_php_suffix( $template_item ); @@ -76,7 +76,7 @@ function gutenberg_override_query_template( $template, $type, array $templates = if ( $current_template_slug !== $current_block_template_slug && $current_template_slug === $template_item_slug ) { return $template; } - } */ + } if ( $current_template ) { if ( empty( $current_template->content ) && is_user_logged_in() ) { From 91b24b63f15ab721c0f52657bd93070b03496bc3 Mon Sep 17 00:00:00 2001 From: Ari Stathopoulos Date: Fri, 2 Apr 2021 11:32:27 +0300 Subject: [PATCH 04/12] Take into account custom templates (#30464) --- lib/full-site-editing/template-loader.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/full-site-editing/template-loader.php b/lib/full-site-editing/template-loader.php index dffe065156758e..ffc3fcbb3b7624 100644 --- a/lib/full-site-editing/template-loader.php +++ b/lib/full-site-editing/template-loader.php @@ -71,9 +71,16 @@ function gutenberg_override_query_template( $template, $type, array $templates = foreach ( $templates as $template_item ) { $template_item_slug = gutenberg_strip_php_suffix( $template_item ); + // Is this a custom template? + $is_custom_template = 0 === strpos( $current_block_template_slug, 'custom-template-' ); + // Don't override the template if we find a template matching the slug we look for // and which does not match a block template slug. - if ( $current_template_slug !== $current_block_template_slug && $current_template_slug === $template_item_slug ) { + if ( + ! $is_custom_template && + $current_template_slug !== $current_block_template_slug && + $current_template_slug === $template_item_slug + ) { return $template; } } From 5e58e001ac8ecdef48a6cfdc1687a6daf077432c Mon Sep 17 00:00:00 2001 From: Ari Stathopoulos Date: Fri, 2 Apr 2021 13:34:14 +0300 Subject: [PATCH 05/12] Change the prefix for custom templates (#30467) * Change the prefix for custom templates * Update comment --- lib/full-site-editing/template-loader.php | 4 +++- packages/edit-post/src/store/actions.js | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/full-site-editing/template-loader.php b/lib/full-site-editing/template-loader.php index ffc3fcbb3b7624..d11b5cc9b69196 100644 --- a/lib/full-site-editing/template-loader.php +++ b/lib/full-site-editing/template-loader.php @@ -72,7 +72,9 @@ function gutenberg_override_query_template( $template, $type, array $templates = $template_item_slug = gutenberg_strip_php_suffix( $template_item ); // Is this a custom template? - $is_custom_template = 0 === strpos( $current_block_template_slug, 'custom-template-' ); + // This check should be removed when merged in core. + // Instead, wp_templates should be considered valid in locate_template. + $is_custom_template = 0 === strpos( $current_block_template_slug, 'wp-custom-template-' ); // Don't override the template if we find a template matching the slug we look for // and which does not match a block template slug. diff --git a/packages/edit-post/src/store/actions.js b/packages/edit-post/src/store/actions.js index c4edc2c20ac279..51560040bc0fbe 100644 --- a/packages/edit-post/src/store/actions.js +++ b/packages/edit-post/src/store/actions.js @@ -448,7 +448,7 @@ export function* __unstableSwitchToEditingMode( shouldCreateTemplate = false ) { createBlock( 'core/post-content' ), ]; const template = { - slug: 'custom-template-' + uuid(), + slug: 'wp-custom-template-' + uuid(), content: serialize( templateContent ), title: 'Custom Template', }; From 6067b4236b28ca38ee7b92abc1c6322ad5d61270 Mon Sep 17 00:00:00 2001 From: Ari Stathopoulos Date: Fri, 2 Apr 2021 14:04:24 +0300 Subject: [PATCH 06/12] Add gutenberg_supports_block_templates (#30465) * Introduce gutenberg_is_fse_enabled * typo & reverse logic * update filter name * Remove filter * Rename function * don't use "disable"theme-supports * rename theme-support --- lib/client-assets.php | 4 ++-- lib/compat.php | 2 +- lib/editor-settings.php | 4 ++-- lib/full-site-editing/full-site-editing.php | 9 +++++++++ lib/full-site-editing/page-templates.php | 4 ++-- lib/full-site-editing/template-loader.php | 4 ++-- lib/full-site-editing/template-parts.php | 12 ++++++------ lib/full-site-editing/templates.php | 12 ++++++------ lib/global-styles.php | 4 ++-- lib/init.php | 1 + 10 files changed, 33 insertions(+), 23 deletions(-) diff --git a/lib/client-assets.php b/lib/client-assets.php index eb6cf31093047f..ed6ee3336f2a02 100644 --- a/lib/client-assets.php +++ b/lib/client-assets.php @@ -646,7 +646,7 @@ function gutenberg_extend_block_editor_styles( $settings ) { } // Remove the default font editor styles for FSE themes. - if ( gutenberg_is_fse_theme() ) { + if ( gutenberg_supports_block_templates() ) { foreach ( $settings['styles'] as $j => $style ) { if ( 0 === strpos( $style['css'], 'body { font-family:' ) ) { unset( $settings['styles'][ $j ] ); @@ -666,7 +666,7 @@ function gutenberg_extend_block_editor_styles( $settings ) { * @return array Filtered editor settings. */ function gutenberg_extend_block_editor_settings_with_fse_theme_flag( $settings ) { - $settings['supportsTemplateMode'] = true; // gutenberg_is_fse_theme(); + $settings['supportsTemplateMode'] = gutenberg_supports_block_templates(); // Enable the new layout options for themes with a theme.json file. $settings['supportsLayout'] = WP_Theme_JSON_Resolver::theme_has_support(); diff --git a/lib/compat.php b/lib/compat.php index e391b66aa1fedf..6c748f02ed76f3 100644 --- a/lib/compat.php +++ b/lib/compat.php @@ -14,7 +14,7 @@ * @return bool */ function gutenberg_should_load_separate_block_assets() { - $load_separate_styles = gutenberg_is_fse_theme(); + $load_separate_styles = gutenberg_supports_block_templates(); /** * Determine if separate styles will be loaded for blocks on-render or not. * diff --git a/lib/editor-settings.php b/lib/editor-settings.php index e9891f49609e59..c154c3cac37ae3 100644 --- a/lib/editor-settings.php +++ b/lib/editor-settings.php @@ -39,7 +39,7 @@ function gutenberg_get_common_block_editor_settings() { }; $settings = array( - '__unstableEnableFullSiteEditingBlocks' => true, // gutenberg_is_fse_theme(), + '__unstableEnableFullSiteEditingBlocks' => gutenberg_supports_block_templates(), 'disableCustomColors' => get_theme_support( 'disable-custom-colors' ), 'disableCustomFontSizes' => get_theme_support( 'disable-custom-font-sizes' ), 'disableCustomGradients' => get_theme_support( 'disable-custom-gradients' ), @@ -81,7 +81,7 @@ function gutenberg_extend_post_editor_settings( $settings ) { $image_sizes = wp_list_pluck( $settings['imageSizes'], 'slug' ); $settings['imageDefaultSize'] = in_array( $image_default_size, $image_sizes, true ) ? $image_default_size : 'large'; - $settings['__unstableEnableFullSiteEditingBlocks'] = true; // gutenberg_is_fse_theme(); + $settings['__unstableEnableFullSiteEditingBlocks'] = gutenberg_supports_block_templates(); return $settings; } diff --git a/lib/full-site-editing/full-site-editing.php b/lib/full-site-editing/full-site-editing.php index 68e6d42d2f6bf5..3737f4bb693a25 100644 --- a/lib/full-site-editing/full-site-editing.php +++ b/lib/full-site-editing/full-site-editing.php @@ -14,6 +14,15 @@ function gutenberg_is_fse_theme() { return is_readable( get_stylesheet_directory() . '/block-templates/index.html' ); } +/** + * Returns whether the current theme is FSE-enabled or not. + * + * @return boolean Whether the current theme is FSE-enabled or not. + */ +function gutenberg_supports_block_templates() { + return gutenberg_is_fse_theme() || current_theme_supports( 'block-templates' ); +} + /** * Show a notice when a Full Site Editing theme is used. */ diff --git a/lib/full-site-editing/page-templates.php b/lib/full-site-editing/page-templates.php index 6044dcc68ceeb0..e868d963e5aaf4 100644 --- a/lib/full-site-editing/page-templates.php +++ b/lib/full-site-editing/page-templates.php @@ -15,9 +15,9 @@ * @return array (Maybe) modified page templates array. */ function gutenberg_load_block_page_templates( $templates, $theme, $post, $post_type ) { - /*if ( ! gutenberg_is_fse_theme() ) { + if ( ! gutenberg_supports_block_templates() ) { return $templates; - }*/ + } $block_templates = gutenberg_get_block_templates( array(), 'wp_template' ); foreach ( $block_templates as $template ) { diff --git a/lib/full-site-editing/template-loader.php b/lib/full-site-editing/template-loader.php index d11b5cc9b69196..c02ebf78b96a19 100644 --- a/lib/full-site-editing/template-loader.php +++ b/lib/full-site-editing/template-loader.php @@ -9,9 +9,9 @@ * Adds necessary filters to use 'wp_template' posts instead of theme template files. */ function gutenberg_add_template_loader_filters() { - /* if ( ! gutenberg_is_fse_theme() ) { + if ( ! gutenberg_supports_block_templates() ) { return; - } */ + } foreach ( gutenberg_get_template_type_slugs() as $template_type ) { if ( 'embed' === $template_type ) { // Skip 'embed' for now because it is not a regular template type. diff --git a/lib/full-site-editing/template-parts.php b/lib/full-site-editing/template-parts.php index 2921152faff4d3..e264a8149ba204 100644 --- a/lib/full-site-editing/template-parts.php +++ b/lib/full-site-editing/template-parts.php @@ -9,9 +9,9 @@ * Registers block editor 'wp_template_part' post type. */ function gutenberg_register_template_part_post_type() { - /* if ( ! gutenberg_is_fse_theme() ) { + if ( ! gutenberg_supports_block_templates() ) { return; - } */ + } $labels = array( 'name' => __( 'Template Parts', 'gutenberg' ), @@ -64,9 +64,9 @@ function gutenberg_register_template_part_post_type() { * Registers the 'wp_template_part_area' taxonomy. */ function gutenberg_register_wp_template_part_area_taxonomy() { - /* if ( ! gutenberg_is_fse_theme() ) { + if ( ! gutenberg_supports_block_templates() ) { return; - } */ + } register_taxonomy( 'wp_template_part_area', @@ -107,9 +107,9 @@ function gutenberg_register_wp_template_part_area_taxonomy() { * Fixes the label of the 'wp_template_part' admin menu entry. */ function gutenberg_fix_template_part_admin_menu_entry() { - /* if ( ! gutenberg_is_fse_theme() ) { + if ( ! gutenberg_supports_block_templates() ) { return; - } */ + } global $submenu; if ( ! isset( $submenu['themes.php'] ) ) { diff --git a/lib/full-site-editing/templates.php b/lib/full-site-editing/templates.php index dcef8e19e0bc12..0ecfcc9a68d8e6 100644 --- a/lib/full-site-editing/templates.php +++ b/lib/full-site-editing/templates.php @@ -28,9 +28,9 @@ function gutenberg_get_template_paths() { * Registers block editor 'wp_template' post type. */ function gutenberg_register_template_post_type() { - /* if ( ! gutenberg_is_fse_theme() ) { + if ( ! gutenberg_supports_block_templates() ) { return; - } */ + } $labels = array( 'name' => __( 'Templates', 'gutenberg' ), @@ -84,9 +84,9 @@ function gutenberg_register_template_post_type() { * Registers block editor 'wp_theme' taxonomy. */ function gutenberg_register_wp_theme_taxonomy() { - /* if ( ! gutenberg_is_fse_theme() ) { + if ( ! gutenberg_supports_block_templates() ) { return; - } */ + } register_taxonomy( 'wp_theme', @@ -139,9 +139,9 @@ function gutenberg_grant_template_caps( array $allcaps ) { * Fixes the label of the 'wp_template' admin menu entry. */ function gutenberg_fix_template_admin_menu_entry() { - /* if ( ! gutenberg_is_fse_theme() ) { + if ( ! gutenberg_supports_block_templates() ) { return; - } */ + } global $submenu; if ( ! isset( $submenu['themes.php'] ) ) { return; diff --git a/lib/global-styles.php b/lib/global-styles.php index 9a935de29145eb..b563863330dc48 100644 --- a/lib/global-styles.php +++ b/lib/global-styles.php @@ -198,7 +198,7 @@ function gutenberg_experimental_global_styles_settings( $settings ) { $origin = 'theme'; if ( WP_Theme_JSON_Resolver::theme_has_support() && - gutenberg_is_fse_theme() + gutenberg_supports_block_templates() ) { // Only lookup for the user data if we need it. $origin = 'user'; @@ -224,7 +224,7 @@ function gutenberg_experimental_global_styles_settings( $settings ) { function_exists( 'gutenberg_is_edit_site_page' ) && gutenberg_is_edit_site_page( $screen->id ) && WP_Theme_JSON_Resolver::theme_has_support() && - gutenberg_is_fse_theme() + gutenberg_supports_block_templates() ) { $user_cpt_id = WP_Theme_JSON_Resolver::get_user_custom_post_type_id(); $base_styles = WP_Theme_JSON_Resolver::get_merged_data( $theme_support_data, 'theme' )->get_raw_data(); diff --git a/lib/init.php b/lib/init.php index d532a620e0de29..85ddae7b2cac3a 100644 --- a/lib/init.php +++ b/lib/init.php @@ -177,3 +177,4 @@ function register_site_icon_url( $response ) { add_filter( 'rest_index', 'register_site_icon_url' ); add_theme_support( 'widgets-block-editor' ); +add_theme_support( 'full-site-editing' ); From ac79f3eeaafc0cd0c4a41df9beef3527bb11391b Mon Sep 17 00:00:00 2001 From: Ari Stathopoulos Date: Fri, 2 Apr 2021 15:22:45 +0300 Subject: [PATCH 07/12] Missed renaming the theme-support --- lib/init.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/init.php b/lib/init.php index 85ddae7b2cac3a..d320d3bffaf242 100644 --- a/lib/init.php +++ b/lib/init.php @@ -177,4 +177,4 @@ function register_site_icon_url( $response ) { add_filter( 'rest_index', 'register_site_icon_url' ); add_theme_support( 'widgets-block-editor' ); -add_theme_support( 'full-site-editing' ); +add_theme_support( 'block-templates' ); From 72eeb5985c95bc72ebbc22ea4c96b7782b445069 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Mon, 5 Apr 2021 10:09:29 +0100 Subject: [PATCH 08/12] Add a modal to edit the template's title before creating it --- .../components/sidebar/post-template/index.js | 85 +++++++++++++++++-- .../sidebar/post-template/style.scss | 4 + packages/edit-post/src/store/actions.js | 22 ++--- 3 files changed, 88 insertions(+), 23 deletions(-) diff --git a/packages/edit-post/src/components/sidebar/post-template/index.js b/packages/edit-post/src/components/sidebar/post-template/index.js index ae2ec1459acbe8..a5b53b48496108 100644 --- a/packages/edit-post/src/components/sidebar/post-template/index.js +++ b/packages/edit-post/src/components/sidebar/post-template/index.js @@ -1,10 +1,22 @@ +/** + * External dependencies + */ +import { kebabCase } from 'lodash'; + /** * WordPress dependencies */ import { __, sprintf } from '@wordpress/i18n'; -import { PanelRow, Button } from '@wordpress/components'; +import { + PanelRow, + Button, + Modal, + TextControl, + Flex, + FlexItem, +} from '@wordpress/components'; import { useSelect, useDispatch } from '@wordpress/data'; -import { createInterpolateElement } from '@wordpress/element'; +import { createInterpolateElement, useState } from '@wordpress/element'; import { store as editorStore } from '@wordpress/editor'; import { store as coreStore } from '@wordpress/core-data'; @@ -12,8 +24,11 @@ import { store as coreStore } from '@wordpress/core-data'; * Internal dependencies */ import { store as editPostStore } from '../../../store'; +import { createBlock, serialize } from '@wordpress/blocks'; function PostTemplate() { + const [ isModalOpen, setIsModalOpen ] = useState( false ); + const [ title, setTitle ] = useState( '' ); const { template, isEditing, supportsTemplateMode } = useSelect( ( select ) => { const { getCurrentPostType } = select( editorStore ); @@ -38,7 +53,7 @@ function PostTemplate() { }, [] ); - const { __unstableSwitchToEditingMode } = useDispatch( editPostStore ); + const { __unstableSwitchToTemplateMode } = useDispatch( editPostStore ); if ( ! supportsTemplateMode ) { return null; @@ -61,7 +76,7 @@ function PostTemplate() { @@ -94,6 +105,62 @@ function PostTemplate() { { template?.slug } ) } + { isModalOpen && ( + { + setIsModalOpen( false ); + setTitle( '' ); + } } + > +
{ + event.preventDefault(); + const defaultTitle = __( 'Custom Template' ); + const templateContent = [ + createBlock( 'core/post-title' ), + createBlock( 'core/post-content' ), + ]; + __unstableSwitchToTemplateMode( { + slug: + 'wp-custom-template-' + + kebabCase( title ?? defaultTitle ), + content: serialize( templateContent ), + title: title ?? defaultTitle, + } ); + setIsModalOpen( false ); + } } + > + + + + + + + + + + +
+ ) } ); } diff --git a/packages/edit-post/src/components/sidebar/post-template/style.scss b/packages/edit-post/src/components/sidebar/post-template/style.scss index d625e897224368..038b7e1d75d623 100644 --- a/packages/edit-post/src/components/sidebar/post-template/style.scss +++ b/packages/edit-post/src/components/sidebar/post-template/style.scss @@ -11,3 +11,7 @@ .edit-post-post-template__value { padding-left: 6px; } + +.edit-post-post-template__modal-actions { + padding-top: $grid-unit-15; +} diff --git a/packages/edit-post/src/store/actions.js b/packages/edit-post/src/store/actions.js index 51560040bc0fbe..e8f4d1ab12d515 100644 --- a/packages/edit-post/src/store/actions.js +++ b/packages/edit-post/src/store/actions.js @@ -1,7 +1,6 @@ /** * External dependencies */ -import { v4 as uuid } from 'uuid'; import { castArray, reduce } from 'lodash'; /** @@ -13,7 +12,6 @@ import { store as interfaceStore } from '@wordpress/interface'; import { controls, dispatch, select, subscribe } from '@wordpress/data'; import { speak } from '@wordpress/a11y'; import { store as noticesStore } from '@wordpress/notices'; -import { createBlock, serialize } from '@wordpress/blocks'; import { store as coreStore } from '@wordpress/core-data'; /** @@ -441,17 +439,13 @@ export function setIsEditingTemplate( value ) { }; } -export function* __unstableSwitchToEditingMode( shouldCreateTemplate = false ) { - if ( shouldCreateTemplate ) { - const templateContent = [ - createBlock( 'core/post-title' ), - createBlock( 'core/post-content' ), - ]; - const template = { - slug: 'wp-custom-template-' + uuid(), - content: serialize( templateContent ), - title: 'Custom Template', - }; +/** + * Potentially create a block based template and switches to the template mode. + * + * @param {Object?} template template to create and assign before switching. + */ +export function* __unstableSwitchToTemplateMode( template ) { + if ( !! template ) { const savedTemplate = yield controls.dispatch( coreStore, 'saveEntityRecord', @@ -475,7 +469,7 @@ export function* __unstableSwitchToEditingMode( shouldCreateTemplate = false ) { yield setIsEditingTemplate( true ); - const message = shouldCreateTemplate + const message = !! template ? __( "Custom template created. You're in template mode now." ) : __( 'Editing template. Changes made here affect all posts and pages that use the template.' From 60dcce8231ce5a3a4cf81474697d38719825db8f Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Tue, 6 Apr 2021 10:15:54 +0100 Subject: [PATCH 09/12] Fix design and enable for FSE themes --- .../components/sidebar/post-template/index.js | 62 ++++++++----------- .../sidebar/post-template/style.scss | 9 +++ 2 files changed, 34 insertions(+), 37 deletions(-) diff --git a/packages/edit-post/src/components/sidebar/post-template/index.js b/packages/edit-post/src/components/sidebar/post-template/index.js index a5b53b48496108..953c2d2f96aca0 100644 --- a/packages/edit-post/src/components/sidebar/post-template/index.js +++ b/packages/edit-post/src/components/sidebar/post-template/index.js @@ -6,7 +6,7 @@ import { kebabCase } from 'lodash'; /** * WordPress dependencies */ -import { __, sprintf } from '@wordpress/i18n'; +import { __ } from '@wordpress/i18n'; import { PanelRow, Button, @@ -16,7 +16,7 @@ import { FlexItem, } from '@wordpress/components'; import { useSelect, useDispatch } from '@wordpress/data'; -import { createInterpolateElement, useState } from '@wordpress/element'; +import { useState } from '@wordpress/element'; import { store as editorStore } from '@wordpress/editor'; import { store as coreStore } from '@wordpress/core-data'; @@ -63,42 +63,30 @@ function PostTemplate() { { __( 'Template' ) } { ! isEditing && ( - - { !! template && - createInterpolateElement( - sprintf( - /* translators: 1: Template name. */ - __( '%s (Edit)' ), - template.slug - ), - { - a: ( - - ), - } - ) } - { ! template && - createInterpolateElement( - __( 'Default ()' ), - { - create: ( - - ), - } +
+
+ { !! template && template?.title?.raw } + { !! template && + ! template?.title?.raw && + template.slug } + { ! template && __( 'Default' ) } +
+
+ { !! template && ( + ) } - + +
+
) } { isEditing && ( diff --git a/packages/edit-post/src/components/sidebar/post-template/style.scss b/packages/edit-post/src/components/sidebar/post-template/style.scss index 038b7e1d75d623..ed36bf1ea4d941 100644 --- a/packages/edit-post/src/components/sidebar/post-template/style.scss +++ b/packages/edit-post/src/components/sidebar/post-template/style.scss @@ -1,6 +1,7 @@ .edit-post-post-template { width: 100%; justify-content: left; + align-items: baseline; span { display: block; @@ -15,3 +16,11 @@ .edit-post-post-template__modal-actions { padding-top: $grid-unit-15; } + +.edit-post-post-template__actions { + margin-top: $grid-unit-10; + + button:not(:last-child) { + margin-right: $grid-unit-10; + } +} From 5b8e20fdf576dd4eab4c2f61f7710be7d3c19f92 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Thu, 8 Apr 2021 09:00:57 +0100 Subject: [PATCH 10/12] Add e2e test --- packages/e2e-test-utils/src/preview.js | 3 + .../post-editor-template-mode.test.js.snap | 13 ++++ .../post-editor-template-mode.test.js | 77 +++++++++++++++++-- .../components/sidebar/post-template/index.js | 1 + 4 files changed, 86 insertions(+), 8 deletions(-) create mode 100644 packages/e2e-tests/specs/experiments/__snapshots__/post-editor-template-mode.test.js.snap diff --git a/packages/e2e-test-utils/src/preview.js b/packages/e2e-test-utils/src/preview.js index f1f5a8747b46bd..789ca761b6ca20 100644 --- a/packages/e2e-test-utils/src/preview.js +++ b/packages/e2e-test-utils/src/preview.js @@ -14,6 +14,9 @@ import { last } from 'lodash'; export async function openPreviewPage( editorPage = page ) { let openTabs = await browser.pages(); const expectedTabsCount = openTabs.length + 1; + await page.waitForSelector( + '.block-editor-post-preview__button-toggle:not([disabled])' + ); await editorPage.click( '.block-editor-post-preview__button-toggle' ); await editorPage.waitForSelector( '.edit-post-header-preview__button-external' diff --git a/packages/e2e-tests/specs/experiments/__snapshots__/post-editor-template-mode.test.js.snap b/packages/e2e-tests/specs/experiments/__snapshots__/post-editor-template-mode.test.js.snap new file mode 100644 index 00000000000000..58280bb08917b8 --- /dev/null +++ b/packages/e2e-tests/specs/experiments/__snapshots__/post-editor-template-mode.test.js.snap @@ -0,0 +1,13 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Post Editor Template mode Allow creating custom block templates in classic themes 1`] = ` +"

Another FSE Post

+ +
+

Hello World

+
+ + +

Just a random paragraph added to the template

+" +`; diff --git a/packages/e2e-tests/specs/experiments/post-editor-template-mode.test.js b/packages/e2e-tests/specs/experiments/post-editor-template-mode.test.js index 140f567e4d74fe..858ef67ac807ea 100644 --- a/packages/e2e-tests/specs/experiments/post-editor-template-mode.test.js +++ b/packages/e2e-tests/specs/experiments/post-editor-template-mode.test.js @@ -13,7 +13,6 @@ import { describe( 'Post Editor Template mode', () => { beforeAll( async () => { - await activateTheme( 'tt1-blocks' ); await trashAllPosts( 'wp_template' ); await trashAllPosts( 'wp_template_part' ); } ); @@ -22,11 +21,9 @@ describe( 'Post Editor Template mode', () => { await activateTheme( 'twentytwentyone' ); } ); - beforeEach( async () => { - await createNewPost(); - } ); - it( 'Allow to switch to template mode, edit the template and check the result', async () => { + await activateTheme( 'tt1-blocks' ); + await createNewPost(); // Create a random post. await page.type( '.editor-post-title__input', 'Just an FSE Post' ); await page.keyboard.press( 'Enter' ); @@ -45,9 +42,9 @@ describe( 'Post Editor Template mode', () => { // Switch to template mode. await openDocumentSettingsSidebar(); - const switchLink = await page.waitForSelector( - '.edit-post-post-template button' - ); + const editTemplateXPath = + "//*[contains(@class, 'edit-post-post-template__actions')]//button[contains(text(), 'Edit')]"; + const switchLink = await page.waitForXPath( editTemplateXPath ); await switchLink.click(); // Check that we switched properly to edit mode. @@ -82,4 +79,68 @@ describe( 'Post Editor Template mode', () => { '//p[contains(text(), "Just a random paragraph added to the template")]' ); } ); + + it( 'Allow creating custom block templates in classic themes', async () => { + await activateTheme( 'twentytwentyone' ); + await createNewPost(); + // Create a random post. + await page.type( '.editor-post-title__input', 'Another FSE Post' ); + await page.keyboard.press( 'Enter' ); + await page.keyboard.type( 'Hello World' ); + + // Unselect the blocks. + await page.evaluate( () => { + wp.data.dispatch( 'core/block-editor' ).clearSelectedBlock(); + } ); + + // Save the post + // Saving shouldn't be necessary but unfortunately, + // there's a template resolution bug forcing us to do so. + await saveDraft(); + await page.reload(); + + // Create a new custom template. + await openDocumentSettingsSidebar(); + const newTemplateXPath = + "//*[contains(@class, 'edit-post-post-template__actions')]//button[contains(text(), 'New')]"; + const newButton = await page.waitForXPath( newTemplateXPath ); + await newButton.click(); + + // Fill the template title and submit. + const templateNameInputSelector = + '.edit-post-post-template__modal .components-text-control__input'; + await page.click( templateNameInputSelector ); + await page.keyboard.type( 'Blank Template' ); + await page.keyboard.press( 'Enter' ); + + // Check that we switched properly to edit mode. + await page.waitForXPath( + '//*[contains(@class, "components-snackbar")]/*[text()="Custom template created. You\'re in template mode now."]' + ); + + // Edit the template + await insertBlock( 'Paragraph' ); + await page.keyboard.type( + 'Just a random paragraph added to the template' + ); + + // Save changes + const doneButton = await page.waitForXPath( + `//button[contains(text(), 'Apply')]` + ); + await doneButton.click(); + const saveButton = await page.waitForXPath( + `//div[contains(@class, "entities-saved-states__panel-header")]/button[contains(text(), 'Save')]` + ); + await saveButton.click(); + + // Preview changes + const previewPage = await openPreviewPage(); + await previewPage.waitForSelector( '.wp-site-blocks' ); + const content = await previewPage.evaluate( + () => document.querySelector( '.wp-site-blocks' ).innerHTML + ); + + expect( content ).toMatchSnapshot(); + } ); } ); diff --git a/packages/edit-post/src/components/sidebar/post-template/index.js b/packages/edit-post/src/components/sidebar/post-template/index.js index 953c2d2f96aca0..5791b984fc969a 100644 --- a/packages/edit-post/src/components/sidebar/post-template/index.js +++ b/packages/edit-post/src/components/sidebar/post-template/index.js @@ -101,6 +101,7 @@ function PostTemplate() { setIsModalOpen( false ); setTitle( '' ); } } + overlayClassName="edit-post-post-template__modal" >
{ From 1a730f14fbf8127ed83059ea66d6beb484bf46cf Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Thu, 8 Apr 2021 09:04:09 +0100 Subject: [PATCH 11/12] Add documentation --- docs/how-to-guides/themes/block-based-themes.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/how-to-guides/themes/block-based-themes.md b/docs/how-to-guides/themes/block-based-themes.md index 3368d80fcfff33..6eb8608b0e02fe 100644 --- a/docs/how-to-guides/themes/block-based-themes.md +++ b/docs/how-to-guides/themes/block-based-themes.md @@ -124,6 +124,16 @@ As we're still early in the process, the number of blocks specifically dedicated One of the most important aspects of themes (if not the most important) is the styling. While initially you'll be able to provide styles and enqueue them using the same hooks themes have always used, the [Global Styles](/docs/how-to-guides/themes/theme-json.md) effort will provide a scaffolding for adding many theme styles in the future. +## Classic Themes + +Users of classic themes can also build custom block templates and use theme in their Pages and Custom Post Types that supports Page Templates. + +Theme authors can opt-out of this feature by removing the `block-templates` theme support in their `functions.php` file. + +```php +remove_theme_support( 'block-templates' ); +``` + ## Resources - [Full Site Editing](https://github.com/WordPress/gutenberg/labels/%5BFeature%5D%20Full%20Site%20Editing) label. From 70063942bbe918d0a1528fb68c23a80b4b206314 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Thu, 8 Apr 2021 09:13:30 +0100 Subject: [PATCH 12/12] Add some site blocks to the default template --- .../post-editor-template-mode.test.js.snap | 10 +++++++++- .../src/components/sidebar/post-template/index.js | 3 +++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/packages/e2e-tests/specs/experiments/__snapshots__/post-editor-template-mode.test.js.snap b/packages/e2e-tests/specs/experiments/__snapshots__/post-editor-template-mode.test.js.snap index 58280bb08917b8..641ad5cc979217 100644 --- a/packages/e2e-tests/specs/experiments/__snapshots__/post-editor-template-mode.test.js.snap +++ b/packages/e2e-tests/specs/experiments/__snapshots__/post-editor-template-mode.test.js.snap @@ -1,7 +1,15 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Post Editor Template mode Allow creating custom block templates in classic themes 1`] = ` -"

Another FSE Post

+"

gutenberg

+ +

Just another WordPress site

+ + +
+ + +

Another FSE Post

Hello World

diff --git a/packages/edit-post/src/components/sidebar/post-template/index.js b/packages/edit-post/src/components/sidebar/post-template/index.js index 5791b984fc969a..05eef4febd9b8f 100644 --- a/packages/edit-post/src/components/sidebar/post-template/index.js +++ b/packages/edit-post/src/components/sidebar/post-template/index.js @@ -108,6 +108,9 @@ function PostTemplate() { event.preventDefault(); const defaultTitle = __( 'Custom Template' ); const templateContent = [ + createBlock( 'core/site-title' ), + createBlock( 'core/site-tagline' ), + createBlock( 'core/separator' ), createBlock( 'core/post-title' ), createBlock( 'core/post-content' ), ];