diff --git a/lib/compat/wordpress-6.8/class-gutenberg-rest-static-templates-controller.php b/lib/compat/wordpress-6.8/class-gutenberg-rest-static-templates-controller.php new file mode 100644 index 0000000000000..38282aba76858 --- /dev/null +++ b/lib/compat/wordpress-6.8/class-gutenberg-rest-static-templates-controller.php @@ -0,0 +1,250 @@ +rest_base = 'templates'; + $controller = new WP_REST_Templates_Controller( 'wp_template' ); + $wp_post_types['wp_template']->rest_base = 'wp_template'; + $controller->register_routes(); +} +add_action( 'rest_api_init', 'gutenberg_maintain_templates_routes' ); + +// 3. Even though this doesn't need to exist as a post type, we need routes to +// get that raw static templates from themes and plugins. I did not want to +// templates for back-compat. Also I registered these as a post type route +// because right now the EditorProvider assumes templates are posts. + +function gutenberg_setup_static_template() { + global $wp_post_types; + $wp_post_types['_wp_static_template'] = clone $wp_post_types['wp_template']; + $wp_post_types['_wp_static_template']->name = '_wp_static_template'; + $wp_post_types['_wp_static_template']->rest_base = '_wp_static_template'; + $wp_post_types['_wp_static_template']->rest_controller_class = 'Gutenberg_REST_Static_Templates_Controller'; + + register_setting( 'reading', 'active_templates', array( + 'type' => 'object', + 'show_in_rest' => array( + 'schema' => array( + 'type' => 'object', + 'additionalProperties' => true, + ), + ), + 'default' => array(), + ) ); +} +add_action( 'init', 'gutenberg_setup_static_template' ); + +class Gutenberg_REST_Static_Templates_Controller extends WP_REST_Templates_Controller { + public function __construct( $post_type ) { + parent::__construct( $post_type ); + } + + public function register_routes() { + // Lists all templates. + register_rest_route( + $this->namespace, + '/' . $this->rest_base, + array( + array( + 'methods' => WP_REST_Server::READABLE, + 'callback' => array( $this, 'get_items' ), + 'permission_callback' => array( $this, 'get_items_permissions_check' ), + 'args' => $this->get_collection_params(), + ), + 'schema' => array( $this, 'get_public_item_schema' ), + ) + ); + + // Lists/updates a single template based on the given id. + register_rest_route( + $this->namespace, + // The route. + sprintf( + '/%s/(?P%s%s)', + $this->rest_base, + /* + * Matches theme's directory: `/themes///` or `/themes//`. + * Excludes invalid directory name characters: `/:<>*?"|`. + */ + '([^\/:<>\*\?"\|]+(?:\/[^\/:<>\*\?"\|]+)?)', + // Matches the template name. + '[\/\w%-]+' + ), + array( + 'args' => array( + 'id' => array( + 'description' => __( 'The id of a template' ), + 'type' => 'string', + 'sanitize_callback' => array( $this, '_sanitize_template_id' ), + ), + ), + array( + 'methods' => WP_REST_Server::READABLE, + 'callback' => array( $this, 'get_item' ), + 'permission_callback' => array( $this, 'get_item_permissions_check' ), + 'args' => array( + 'context' => $this->get_context_param( array( 'default' => 'view' ) ), + ), + ), + 'schema' => array( $this, 'get_public_item_schema' ), + ) + ); + } + + public function get_item_schema() { + $schema = parent::get_item_schema(); + $schema['properties']['is_custom'] = array( + 'description' => __( 'Whether a template is a custom template.' ), + 'type' => 'bool', + 'context' => array( 'embed', 'view', 'edit' ), + 'readonly' => true, + ); + $schema['properties']['plugin'] = array( + 'type' => 'string', + 'description' => __( 'Plugin that registered the template.' ), + 'readonly' => true, + 'context' => array( 'view', 'edit', 'embed' ), + ); + return $schema; + } + + public function get_items( $request ) { + $query = array(); + if ( isset( $request['area'] ) ) { + $query['area'] = $request['area']; + } + if ( isset( $request['post_type'] ) ) { + $query['post_type'] = $request['post_type']; + } + $template_files = _get_block_templates_files( 'wp_template', $query ); + foreach ( $template_files as $template_file ) { + $query_result[] = _build_block_template_result_from_file( $template_file, 'wp_template' ); + } + + // Add templates registered in the template registry. Filtering out the ones which have a theme file. + $registered_templates = WP_Block_Templates_Registry::get_instance()->get_by_query( $query ); + $matching_registered_templates = array_filter( + $registered_templates, + function ( $registered_template ) use ( $template_files ) { + foreach ( $template_files as $template_file ) { + if ( $template_file['slug'] === $registered_template->slug ) { + return false; + } + } + return true; + } + ); + $query_result = array_merge( $query_result, $matching_registered_templates ); + + $templates = array(); + foreach ( $query_result as $template ) { + $item = $this->prepare_item_for_response( $template, $request ); + $item->data['type'] = '_wp_static_template'; + $templates[] = $this->prepare_response_for_collection( $item ); + } + + return rest_ensure_response( $templates ); + } + + public function get_item( $request ) { + $template = get_block_file_template( $request['id'], 'wp_template' ); + + if ( ! $template ) { + return new WP_Error( 'rest_template_not_found', __( 'No templates exist with that id.' ), array( 'status' => 404 ) ); + } + + $item = $this->prepare_item_for_response( $template, $request ); + // adjust the template type here instead + $item->data['type'] = '_wp_static_template'; + return rest_ensure_response( $item ); + } +} + +function gutenberg_allow_template_slugs_to_be_duplicated( $override, $slug, $post_id, $post_status, $post_type ) { + return $post_type === 'wp_template' ? $slug : $override; +} + +add_filter( 'pre_wp_unique_post_slug', 'gutenberg_allow_template_slugs_to_be_duplicated', 10, 5 ); + +function gutenberg_pre_get_block_templates( $output, $query, $template_type ) { + if ( $template_type === 'wp_template' && ! empty( $query['slug__in'] ) ) { + $active_templates = get_option( 'active_templates', array() ); + $slugs = $query['slug__in']; + $output = array(); + foreach ( $slugs as $slug ) { + if ( isset( $active_templates[ $slug ] ) ) { + if ( $active_templates[ $slug ] !== false ) { + $post = get_post( $active_templates[ $slug ] ); + if ( $post ) { + $output[] = _build_block_template_result_from_post( $post ); + } + } else { + // Deactivated template, fall back to next slug. + $output[] = array(); + } + } + } + if ( empty( $output ) ) { + $output = null; + } + } + return $output; +} + +add_filter( 'pre_get_block_templates', 'gutenberg_pre_get_block_templates', 10, 3 ); + +// Bypass the terms check in _build_block_template_result_from_post. +function gutenberg_get_the_terms( $terms, $object_id, $taxonomy ) { + if ( $taxonomy === 'wp_theme' ) { + $stylesheet = get_stylesheet(); + return array( + new WP_Term( + (object) array( + 'term_id' => 0, + 'name' => $stylesheet, + 'slug' => $stylesheet, + 'taxonomy' => 'wp_theme', + ), + ), + ); + } + return $terms; +} +add_filter( 'get_the_terms', 'gutenberg_get_the_terms', 10, 3 ); diff --git a/lib/compat/wordpress-6.8/preload.php b/lib/compat/wordpress-6.8/preload.php index aabe0d4fb574c..5d606f5f06c97 100644 --- a/lib/compat/wordpress-6.8/preload.php +++ b/lib/compat/wordpress-6.8/preload.php @@ -34,8 +34,9 @@ function gutenberg_block_editor_preload_paths_6_8( $paths, $context ) { 'url', ) ); - $paths[] = '/wp/v2/templates/lookup?slug=front-page'; - $paths[] = '/wp/v2/templates/lookup?slug=home'; + // There's an issue where preloaded data does not invalidate. + // $paths[] = '/wp/v2/templates/lookup?slug=front-page'; + // $paths[] = '/wp/v2/templates/lookup?slug=home'; } // Preload theme and global styles paths. diff --git a/lib/load.php b/lib/load.php index 100160176f391..a6b1c02b1df1d 100644 --- a/lib/load.php +++ b/lib/load.php @@ -47,6 +47,7 @@ function gutenberg_is_experiment_enabled( $name ) { require __DIR__ . '/compat/wordpress-6.7/rest-api.php'; // WordPress 6.8 compat. + require __DIR__ . '/compat/wordpress-6.8/class-gutenberg-rest-static-templates-controller.php'; require __DIR__ . '/compat/wordpress-6.8/block-comments.php'; require __DIR__ . '/compat/wordpress-6.8/class-gutenberg-rest-comment-controller-6-8.php'; require __DIR__ . '/compat/wordpress-6.8/class-gutenberg-rest-post-types-controller-6-8.php'; diff --git a/packages/core-data/src/actions.js b/packages/core-data/src/actions.js index 13cbba39e1176..cd8233face2c8 100644 --- a/packages/core-data/src/actions.js +++ b/packages/core-data/src/actions.js @@ -369,6 +369,9 @@ export const editEntityRecord = `The entity being edited (${ kind }, ${ name }) does not have a loaded config.` ); } + if ( ! select.canUser( 'update', { kind, name, id: recordId } ) ) { + return; + } const { mergedEdits = {} } = entityConfig; const record = select.getRawEntityRecord( kind, name, recordId ); const editedRecord = select.getEditedEntityRecord( @@ -673,6 +676,13 @@ export const saveEntityRecord = ), }; } + if ( + ! edits.status && + persistedRecord?.status === 'auto-draft' + ) { + edits.status = + name === 'wp_template' ? 'publish' : 'draft'; + } updatedRecord = await __unstableFetch( { path, method: recordId ? 'PUT' : 'POST', diff --git a/packages/core-data/src/private-actions.js b/packages/core-data/src/private-actions.js index df76d2693e54f..b11ef2cf08045 100644 --- a/packages/core-data/src/private-actions.js +++ b/packages/core-data/src/private-actions.js @@ -14,3 +14,7 @@ export function receiveRegisteredPostMeta( postType, registeredPostMeta ) { registeredPostMeta, }; } + +export function receiveTemplateAutoDraftId( target, id ) { + return { type: 'RECEIVE_TEMPLATE_AUTO_DRAFT_ID', target, id }; +} diff --git a/packages/core-data/src/private-selectors.ts b/packages/core-data/src/private-selectors.ts index 02fe152ed0abb..c966b6f024c76 100644 --- a/packages/core-data/src/private-selectors.ts +++ b/packages/core-data/src/private-selectors.ts @@ -253,3 +253,7 @@ export const getTemplateId = createRegistrySelector( } ); } ); + +export function getTemplateAutoDraftId( state: State, target: string ) { + return state.templateAutoDraftId[ target ]; +} diff --git a/packages/core-data/src/reducer.js b/packages/core-data/src/reducer.js index 9748355fc5caf..34070eafe1ebb 100644 --- a/packages/core-data/src/reducer.js +++ b/packages/core-data/src/reducer.js @@ -647,6 +647,12 @@ export function registeredPostMeta( state = {}, action ) { return state; } +export function templateAutoDraftId( state = {}, action ) { + return action.type === 'RECEIVE_TEMPLATE_AUTO_DRAFT_ID' + ? { ...state, [ action.target ]: action.id } + : state; +} + export default combineReducers( { terms, users, @@ -669,4 +675,5 @@ export default combineReducers( { navigationFallbackId, defaultTemplates, registeredPostMeta, + templateAutoDraftId, } ); diff --git a/packages/core-data/src/resolvers.js b/packages/core-data/src/resolvers.js index a35403c049346..723486e5c5fd3 100644 --- a/packages/core-data/src/resolvers.js +++ b/packages/core-data/src/resolvers.js @@ -66,6 +66,15 @@ export const getCurrentUser = export const getEntityRecord = ( kind, name, key = '', query ) => async ( { select, dispatch, registry, resolveSelect } ) => { + // For back-compat, we allow querying for static templates through + // wp_template. + if ( + kind === 'postType' && + name === 'wp_template' && + typeof key === 'string' + ) { + name = '_wp_static_template'; + } const configs = await resolveSelect.getEntitiesConfig( kind ); const entityConfig = configs.find( ( config ) => config.name === name && config.kind === kind @@ -211,6 +220,27 @@ export const getEntityRecord = } }; +export const getTemplateAutoDraftId = + ( target ) => + async ( { resolveSelect, dispatch } ) => { + const record = await resolveSelect.getEntityRecord( + 'postType', + '_wp_static_template', + target + ); + const autoDraft = await dispatch.saveEntityRecord( + 'postType', + 'wp_template', + { + ...record, + id: undefined, + type: 'wp_template', + status: 'auto-draft', + } + ); + await dispatch.receiveTemplateAutoDraftId( target, autoDraft.id ); + }; + /** * Requests an entity's record from the REST API. */ @@ -799,23 +829,35 @@ export const getDefaultTemplateId = // Wait for the the entities config to be loaded, otherwise receiving // the template as an entity will not work. await resolveSelect.getEntitiesConfig( 'postType' ); + const id = template?.wp_id || template?.id; // Endpoint may return an empty object if no template is found. - if ( template?.id ) { + if ( id ) { + template.id = id; + template.type = + typeof id === 'string' ? '_wp_static_template' : 'wp_template'; registry.batch( () => { - dispatch.receiveDefaultTemplateId( query, template.id ); - dispatch.receiveEntityRecords( 'postType', 'wp_template', [ + dispatch.receiveDefaultTemplateId( query, id ); + dispatch.receiveEntityRecords( 'postType', template.type, [ template, ] ); // Avoid further network requests. dispatch.finishResolution( 'getEntityRecord', [ 'postType', - 'wp_template', - template.id, + template.type, + id, ] ); } ); } }; +getDefaultTemplateId.shouldInvalidate = ( action ) => { + return ( + action.type === 'EDIT_ENTITY_RECORD' && + action.kind === 'root' && + action.name === 'site' + ); +}; + /** * Requests an entity's revisions from the REST API. * diff --git a/packages/core-data/src/selectors.ts b/packages/core-data/src/selectors.ts index 7ea8c2f7f26d5..a8a6408bc5c08 100644 --- a/packages/core-data/src/selectors.ts +++ b/packages/core-data/src/selectors.ts @@ -48,6 +48,7 @@ export interface State { userPatternCategories: Array< UserPatternCategory >; defaultTemplates: Record< string, string >; registeredPostMeta: Record< string, Object >; + templateAutoDraftId: Record< string, number | null >; } type EntityRecordKey = string | number; @@ -353,6 +354,15 @@ export const getEntityRecord = createSelector( key: EntityRecordKey, query?: GetRecordsHttpQuery ): EntityRecord | undefined => { + // For back-compat, we allow querying for static templates through + // wp_template. + if ( + kind === 'postType' && + name === 'wp_template' && + typeof key === 'string' + ) { + name = '_wp_static_template'; + } const queriedState = state.entities.records?.[ kind ]?.[ name ]?.queriedData; if ( ! queriedState ) { diff --git a/packages/edit-post/src/components/layout/index.js b/packages/edit-post/src/components/layout/index.js index aec14eab989f0..38aa1e487f613 100644 --- a/packages/edit-post/src/components/layout/index.js +++ b/packages/edit-post/src/components/layout/index.js @@ -85,6 +85,7 @@ const DESIGN_POST_TYPES = [ 'wp_template_part', 'wp_block', 'wp_navigation', + '_wp_static_template', ]; function useEditorStyles( ...additionalStyles ) { diff --git a/packages/edit-site/src/components/add-new-template/index.js b/packages/edit-site/src/components/add-new-template/index.js index 1a2d9ea727fa8..cfe03835c2b7a 100644 --- a/packages/edit-site/src/components/add-new-template/index.js +++ b/packages/edit-site/src/components/add-new-template/index.js @@ -52,7 +52,6 @@ import { TEMPLATE_POST_TYPE } from '../../utils/constants'; */ import AddCustomTemplateModalContent from './add-custom-template-modal-content'; import { - useExistingTemplates, useDefaultTemplateTypes, useTaxonomiesMenuItems, usePostTypeMenuItems, @@ -367,15 +366,9 @@ function NewTemplate() { } function useMissingTemplates( setEntityForSuggestions, onClick ) { - const existingTemplates = useExistingTemplates(); const defaultTemplateTypes = useDefaultTemplateTypes(); - const existingTemplateSlugs = ( existingTemplates || [] ).map( - ( { slug } ) => slug - ); const missingDefaultTemplates = ( defaultTemplateTypes || [] ).filter( - ( template ) => - DEFAULT_TEMPLATE_SLUGS.includes( template.slug ) && - ! existingTemplateSlugs.includes( template.slug ) + ( template ) => DEFAULT_TEMPLATE_SLUGS.includes( template.slug ) ); const onClickMenuItem = ( _entityForSuggestions ) => { onClick?.(); diff --git a/packages/edit-site/src/components/dataviews-actions/index.js b/packages/edit-site/src/components/dataviews-actions/index.js index 09b7597c6cb34..1b1e8cfa076f9 100644 --- a/packages/edit-site/src/components/dataviews-actions/index.js +++ b/packages/edit-site/src/components/dataviews-actions/index.js @@ -5,6 +5,8 @@ import { __ } from '@wordpress/i18n'; import { edit } from '@wordpress/icons'; import { useMemo } from '@wordpress/element'; import { privateApis as routerPrivateApis } from '@wordpress/router'; +import { useDispatch, useSelect } from '@wordpress/data'; +import { store as coreStore } from '@wordpress/core-data'; /** * Internal dependencies @@ -14,6 +16,44 @@ import { unlock } from '../../lock-unlock'; const { useHistory } = unlock( routerPrivateApis ); +export const useSetActiveTemplateAction = () => { + const { getEntityRecord } = useSelect( coreStore ); + const { editEntityRecord, saveEditedEntityRecord } = + useDispatch( coreStore ); + return useMemo( + () => ( { + id: 'set-active-template', + label( items ) { + return items.some( ( item ) => item._isActive ) + ? __( 'Deactivate' ) + : __( 'Activate' ); + }, + isPrimary: true, + icon: edit, + async callback( items ) { + const deactivate = items.some( ( item ) => item._isActive ); + // current active templates + const activeTemplates = { + ...( ( await getEntityRecord( 'root', 'site' ) + .active_templates ) ?? {} ), + }; + for ( const item of items ) { + if ( deactivate ) { + activeTemplates[ item.slug ] = false; + } else { + activeTemplates[ item.slug ] = item.id; + } + } + await editEntityRecord( 'root', 'site', undefined, { + active_templates: activeTemplates, + } ); + await saveEditedEntityRecord( 'root', 'site' ); + }, + } ), + [ editEntityRecord, saveEditedEntityRecord, getEntityRecord ] + ); +}; + export const useEditPostAction = () => { const history = useHistory(); return useMemo( diff --git a/packages/edit-site/src/components/editor/use-resolve-edited-entity.js b/packages/edit-site/src/components/editor/use-resolve-edited-entity.js index 4f87373870414..971635de30bce 100644 --- a/packages/edit-site/src/components/editor/use-resolve-edited-entity.js +++ b/packages/edit-site/src/components/editor/use-resolve-edited-entity.js @@ -25,18 +25,33 @@ const postTypesWithoutParentTemplate = [ TEMPLATE_PART_POST_TYPE, NAVIGATION_POST_TYPE, PATTERN_TYPES.user, + '_wp_static_template', ]; const authorizedPostTypes = [ 'page', 'post' ]; export function useResolveEditedEntity() { const { params = {} } = useLocation(); - const { postId, postType } = params; const homePage = useSelect( ( select ) => { const { getHomePage } = unlock( select( coreDataStore ) ); return getHomePage(); }, [] ); + const [ postType, postId ] = useSelect( + ( select ) => { + if ( params.postType !== '_wp_static_template' ) { + return [ params.postType, params.postId ]; + } + return [ + TEMPLATE_POST_TYPE, + unlock( select( coreDataStore ) ).getTemplateAutoDraftId( + params.postId + ), + ]; + }, + [ params.postType, params.postId ] + ); + /** * This is a hook that recreates the logic to resolve a template for a given WordPress postID postTypeId * in order to match the frontend as closely as possible in the site editor. @@ -83,6 +98,18 @@ export function useResolveEditedEntity() { [ homePage, postId, postType ] ); + const editableResolvedTemplateId = useSelect( + ( select ) => { + if ( typeof resolvedTemplateId !== 'string' ) { + return resolvedTemplateId; + } + return unlock( select( coreDataStore ) ).getTemplateAutoDraftId( + resolvedTemplateId + ); + }, + [ resolvedTemplateId ] + ); + const context = useMemo( () => { if ( postTypesWithoutParentTemplate.includes( postType ) && postId ) { return {}; @@ -106,9 +133,9 @@ export function useResolveEditedEntity() { if ( !! homePage ) { return { - isReady: resolvedTemplateId !== undefined, + isReady: editableResolvedTemplateId !== undefined, postType: TEMPLATE_POST_TYPE, - postId: resolvedTemplateId, + postId: editableResolvedTemplateId, context, }; } diff --git a/packages/edit-site/src/components/page-templates/fields.js b/packages/edit-site/src/components/page-templates/fields.js index 69e0596bf49d4..46a372faa085a 100644 --- a/packages/edit-site/src/components/page-templates/fields.js +++ b/packages/edit-site/src/components/page-templates/fields.js @@ -22,6 +22,7 @@ import { EditorProvider } from '@wordpress/editor'; */ import { default as Link, useLink } from '../routes/link'; import { useAddedBy } from './hooks'; +import { useDefaultTemplateTypes } from '../add-new-template/utils'; import usePatternSettings from '../page-patterns/use-pattern-settings'; import { unlock } from '../../lock-unlock'; @@ -154,3 +155,30 @@ export const authorField = { getValue: ( { item } ) => item.author_text, render: AuthorField, }; + +export const activeField = { + label: __( 'Active' ), + id: 'active', + getValue: ( { item } ) => item._isActive, + render: function Render( { item } ) { + const isActive = item._isActive; + return ( + + { isActive ? __( 'Active' ) : __( 'Inactive' ) } + + ); + }, +}; + +export const slugField = { + label: __( 'Template Type' ), + id: 'slug', + getValue: ( { item } ) => item.slug, + render: function Render( { item } ) { + const defaultTemplateTypes = useDefaultTemplateTypes(); + const defaultTemplateType = defaultTemplateTypes.find( + ( type ) => type.slug === item.slug + ); + return defaultTemplateType?.title || item.slug; + }, +}; diff --git a/packages/edit-site/src/components/page-templates/hooks.js b/packages/edit-site/src/components/page-templates/hooks.js index 3cf2d78a59ee9..e02a7f7059566 100644 --- a/packages/edit-site/src/components/page-templates/hooks.js +++ b/packages/edit-site/src/components/page-templates/hooks.js @@ -89,7 +89,7 @@ export function useAddedBy( postType, postId ) { type: 'user', icon: authorIcon, imageUrl: user?.avatar_urls?.[ 48 ], - text: authorText, + text: authorText ?? user?.name, isCustomized: false, }; } diff --git a/packages/edit-site/src/components/page-templates/index.js b/packages/edit-site/src/components/page-templates/index.js index ea026ca53566e..6a96424078d87 100644 --- a/packages/edit-site/src/components/page-templates/index.js +++ b/packages/edit-site/src/components/page-templates/index.js @@ -3,10 +3,14 @@ */ import { __ } from '@wordpress/i18n'; import { useState, useMemo, useCallback, useEffect } from '@wordpress/element'; -import { privateApis as corePrivateApis } from '@wordpress/core-data'; +import { + privateApis as corePrivateApis, + store as coreStore, +} from '@wordpress/core-data'; import { DataViews, filterSortAndPaginate } from '@wordpress/dataviews'; import { privateApis as routerPrivateApis } from '@wordpress/router'; import { privateApis as editorPrivateApis } from '@wordpress/editor'; +import { useSelect } from '@wordpress/data'; /** * Internal dependencies @@ -21,13 +25,19 @@ import { LAYOUT_LIST, } from '../../utils/constants'; import { unlock } from '../../lock-unlock'; -import { useEditPostAction } from '../dataviews-actions'; +import { + useEditPostAction, + useSetActiveTemplateAction, +} from '../dataviews-actions'; import { authorField, descriptionField, previewField, titleField, + activeField, + slugField, } from './fields'; +import { useDefaultTemplateTypes } from '../add-new-template/utils'; const { usePostActions } = unlock( editorPrivateApis ); const { useHistory, useLocation } = unlock( routerPrivateApis ); @@ -37,7 +47,7 @@ const EMPTY_ARRAY = []; const defaultLayouts = { [ LAYOUT_TABLE ]: { - fields: [ 'template', 'author' ], + fields: [ 'template', 'author', 'active', 'slug' ], layout: { primaryField: 'title', combinedFields: [ @@ -63,15 +73,16 @@ const defaultLayouts = { }, }, [ LAYOUT_GRID ]: { - fields: [ 'title', 'description', 'author' ], + fields: [ 'title', 'description', 'author', 'active', 'slug' ], layout: { mediaField: 'preview', primaryField: 'title', columnFields: [ 'description' ], + badgeFields: [ 'active', 'slug' ], }, }, [ LAYOUT_LIST ]: { - fields: [ 'title', 'description', 'author' ], + fields: [ 'title', 'description', 'author', 'active', 'slug' ], layout: { primaryField: 'title', }, @@ -94,9 +105,8 @@ const DEFAULT_VIEW = { export default function PageTemplates() { const { params } = useLocation(); - const { activeView = 'all', layout, postId } = params; + const { activeView = 'active', layout, postId } = params; const [ selection, setSelection ] = useState( [ postId ] ); - const defaultView = useMemo( () => { const usedType = layout ?? DEFAULT_VIEW.type; return { @@ -104,39 +114,136 @@ export default function PageTemplates() { type: usedType, layout: defaultLayouts[ usedType ].layout, fields: defaultLayouts[ usedType ].fields, - filters: - activeView !== 'all' - ? [ - { - field: 'author', - operator: 'isAny', - value: [ activeView ], - }, - ] - : [], + filters: ! [ 'active', 'user' ].includes( activeView ) + ? [ + { + field: 'author', + operator: 'isAny', + value: [ activeView ], + }, + ] + : [], }; }, [ layout, activeView ] ); const [ view, setView ] = useState( defaultView ); useEffect( () => { setView( ( currentView ) => ( { ...currentView, - filters: - activeView !== 'all' - ? [ - { - field: 'author', - operator: OPERATOR_IS_ANY, - value: [ activeView ], - }, - ] - : [], + filters: ! [ 'active', 'user' ].includes( activeView ) + ? [ + { + field: 'author', + operator: OPERATOR_IS_ANY, + value: [ activeView ], + }, + ] + : [], } ) ); }, [ activeView ] ); - const { records, isResolving: isLoadingData } = + const activeTemplatesOption = useSelect( + ( select ) => + select( coreStore ).getEntityRecord( 'root', 'site' ) + ?.active_templates + ); + const defaultTemplateTypes = useDefaultTemplateTypes(); + // Todo: this will have to be better so that we're not fetching all the + // records all the time. Active templates query will need to move server + // side. + const { records: userRecords, isResolving: isLoadingUserRecords } = useEntityRecordsWithPermissions( 'postType', TEMPLATE_POST_TYPE, { per_page: -1, } ); + const { records: staticRecords, isResolving: isLoadingStaticData } = + useEntityRecordsWithPermissions( 'postType', '_wp_static_template', { + per_page: -1, + } ); + + const activeTemplates = useMemo( () => { + const _active = [ ...staticRecords ]; + if ( activeTemplatesOption ) { + for ( const activeSlug in activeTemplatesOption ) { + const activeId = activeTemplatesOption[ activeSlug ]; + if ( activeId === false ) { + // Remove the template from the array. + const index = _active.findIndex( + ( template ) => template.slug === activeSlug + ); + if ( index !== -1 ) { + _active.splice( index, 1 ); + } + } else { + // Replace the template in the array. + const template = userRecords.find( + ( { id } ) => id === activeId + ); + if ( template ) { + const index = _active.findIndex( + ( { slug } ) => slug === template.slug + ); + if ( index !== -1 ) { + _active[ index ] = template; + } else { + _active.push( template ); + } + } + } + } + + // for ( const template of userRecords ) { + // if ( activeTemplatesOption[ template.slug ] === template.id ) { + // // replace the static template with the user template in the array + // const index = _active.findIndex( + // ( record ) => record.slug === template.slug + // ); + // if ( index !== -1 ) { + // _active[ index ] = template; + // } else { + // _active.push( template ); + // } + // } + // } + } + const defaultSlugs = defaultTemplateTypes.map( ( type ) => type.slug ); + return _active.filter( ( template ) => + defaultSlugs.includes( template.slug ) + ); + }, [ + defaultTemplateTypes, + userRecords, + staticRecords, + activeTemplatesOption, + ] ); + + let _records; + let isLoadingData; + if ( activeView === 'active' ) { + _records = activeTemplates; + isLoadingData = isLoadingUserRecords || isLoadingStaticData; + } else if ( activeView === 'user' ) { + _records = userRecords; + isLoadingData = isLoadingUserRecords; + } else { + _records = staticRecords; + isLoadingData = isLoadingStaticData; + } + + const records = useMemo( () => { + return _records.map( ( record ) => ( { + ...record, + _isActive: + typeof record.id === 'string' + ? activeTemplatesOption[ record.slug ] === record.id || + ( activeTemplatesOption[ record.slug ] === undefined && + defaultTemplateTypes.find( + ( { slug } ) => slug === record.slug + ) ) + : Object.values( activeTemplatesOption ).includes( + record.id + ), + } ) ); + }, [ _records, activeTemplatesOption, defaultTemplateTypes ] ); + const history = useHistory(); const onChangeSelection = useCallback( ( items ) => { @@ -165,8 +272,8 @@ export default function PageTemplates() { } ) ); }, [ records ] ); - const fields = useMemo( - () => [ + const fields = useMemo( () => { + const _fields = [ previewField, titleField, descriptionField, @@ -174,9 +281,11 @@ export default function PageTemplates() { ...authorField, elements: authors, }, - ], - [ authors ] - ); + activeField, + slugField, + ]; + return _fields; + }, [ authors ] ); const { data, paginationInfo } = useMemo( () => { return filterSortAndPaginate( records, view, fields ); @@ -187,9 +296,13 @@ export default function PageTemplates() { context: 'list', } ); const editAction = useEditPostAction(); + const setActiveTemplateAction = useSetActiveTemplateAction(); const actions = useMemo( - () => [ editAction, ...postTypeActions ], - [ postTypeActions, editAction ] + () => + activeView === 'user' + ? [ setActiveTemplateAction, editAction, ...postTypeActions ] + : [ setActiveTemplateAction, ...postTypeActions ], + [ postTypeActions, setActiveTemplateAction, editAction, activeView ] ); const onChangeView = useCallback( diff --git a/packages/edit-site/src/components/page-templates/style.scss b/packages/edit-site/src/components/page-templates/style.scss index 6a753921f6f40..681a8e63e7d8e 100644 --- a/packages/edit-site/src/components/page-templates/style.scss +++ b/packages/edit-site/src/components/page-templates/style.scss @@ -67,6 +67,12 @@ .dataviews-pagination { z-index: z-index(".edit-site-templates__dataviews-list-pagination"); } + .dataviews-view-grid__badge-fields { + .dataviews-view-grid__field-value:has(.is-active) { + background: var(--wp-admin-theme-color); + color: $white; + } + } } diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-templates-browse/content.js b/packages/edit-site/src/components/sidebar-navigation-screen-templates-browse/content.js index 5a07adf62d9b3..cadb335363c95 100644 --- a/packages/edit-site/src/components/sidebar-navigation-screen-templates-browse/content.js +++ b/packages/edit-site/src/components/sidebar-navigation-screen-templates-browse/content.js @@ -4,6 +4,7 @@ import { useEntityRecords } from '@wordpress/core-data'; import { useMemo } from '@wordpress/element'; import { __experimentalItemGroup as ItemGroup } from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; /** * Internal dependencies @@ -11,7 +12,6 @@ import { __experimentalItemGroup as ItemGroup } from '@wordpress/components'; import DataViewItem from '../sidebar-dataviews/dataview-item'; import { useAddedBy } from '../page-templates/hooks'; import { layout } from '@wordpress/icons'; -import { TEMPLATE_POST_TYPE } from '../../utils/constants'; const EMPTY_ARRAY = []; @@ -29,11 +29,8 @@ function TemplateDataviewItem( { template, isActive } ) { ); } -export default function DataviewsTemplatesSidebarContent( { - activeView, - title, -} ) { - const { records } = useEntityRecords( 'postType', TEMPLATE_POST_TYPE, { +export default function DataviewsTemplatesSidebarContent( { activeView } ) { + const { records } = useEntityRecords( 'postType', '_wp_static_template', { per_page: -1, } ); const firstItemPerAuthorText = useMemo( () => { @@ -53,10 +50,17 @@ export default function DataviewsTemplatesSidebarContent( { return ( + { firstItemPerAuthorText.map( ( template ) => { diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-templates-browse/index.js b/packages/edit-site/src/components/sidebar-navigation-screen-templates-browse/index.js index 8e7946390a364..f203e024a4ea5 100644 --- a/packages/edit-site/src/components/sidebar-navigation-screen-templates-browse/index.js +++ b/packages/edit-site/src/components/sidebar-navigation-screen-templates-browse/index.js @@ -15,7 +15,7 @@ const { useLocation } = unlock( routerPrivateApis ); export default function SidebarNavigationScreenTemplatesBrowse( { backPath } ) { const { - params: { activeView = 'all' }, + params: { activeView = 'active' }, } = useLocation(); return ( diff --git a/packages/editor/src/components/post-excerpt/panel.js b/packages/editor/src/components/post-excerpt/panel.js index 9c09796f46704..4c1eba161ff00 100644 --- a/packages/editor/src/components/post-excerpt/panel.js +++ b/packages/editor/src/components/post-excerpt/panel.js @@ -109,6 +109,7 @@ function PrivateExcerpt() { getCurrentPostId, getEditedPostAttribute, isEditorPanelEnabled, + __experimentalGetDefaultTemplateType, } = select( editorStore ); const postType = getCurrentPostType(); const isTemplateOrTemplatePart = [ @@ -131,13 +132,17 @@ function PrivateExcerpt() { postType, getCurrentPostId() ); + const fallback = isTemplateOrTemplatePart + ? __experimentalGetDefaultTemplateType( template.slug ) + .description + : undefined; // For post types that use excerpt as description, we do not abide // by the `isEnabled` panel flag in order to render them as text. const _shouldRender = isEditorPanelEnabled( PANEL_NAME ) || _shouldBeUsedAsDescription; return { - excerpt: getEditedPostAttribute( _usedAttribute ), + excerpt: getEditedPostAttribute( _usedAttribute ) ?? fallback, shouldRender: _shouldRender, shouldBeUsedAsDescription: _shouldBeUsedAsDescription, // If we should render, allow editing for all post types that are not used as description. diff --git a/packages/editor/src/components/post-template/hooks.js b/packages/editor/src/components/post-template/hooks.js index c9668cd144333..167f18fa2a1f4 100644 --- a/packages/editor/src/components/post-template/hooks.js +++ b/packages/editor/src/components/post-template/hooks.js @@ -48,14 +48,30 @@ export function useAllowSwitchingTemplates() { } function useTemplates( postType ) { - return useSelect( - ( select ) => - select( coreStore ).getEntityRecords( 'postType', 'wp_template', { - per_page: -1, - post_type: postType, - } ), + // To do: create a new selector to checks if templates exist at all instead + // of and unbound request. In the modal, the user templates should be + // paginated and we should not make an unbound request. + const { staticTemplates, templates } = useSelect( + ( select ) => { + return { + staticTemplates: select( coreStore ).getEntityRecords( + 'postType', + '_wp_static_template', + { per_page: -1, post_type: postType } + ), + templates: select( coreStore ).getEntityRecords( + 'postType', + 'wp_template', + { per_page: -1, post_type: postType } + ), + }; + }, [ postType ] ); + return useMemo( + () => [ ...( staticTemplates || [] ), ...( templates || [] ) ], + [ staticTemplates, templates ] + ); } export function useAvailableTemplates( postType ) { diff --git a/packages/editor/src/components/provider/index.js b/packages/editor/src/components/provider/index.js index 6c05e5b58235b..8a965395f6b93 100644 --- a/packages/editor/src/components/provider/index.js +++ b/packages/editor/src/components/provider/index.js @@ -210,7 +210,10 @@ export const ExperimentalEditorProvider = withRegistryProvider( const defaultBlockContext = useMemo( () => { const postContext = {}; // If it is a template, try to inherit the post type from the name. - if ( post.type === 'wp_template' ) { + if ( + post.type === 'wp_template' || + post.type === '_wp_static_template' + ) { if ( post.slug === 'page' ) { postContext.postType = 'page'; } else if ( post.slug === 'single' ) { diff --git a/packages/editor/src/dataviews/store/private-actions.ts b/packages/editor/src/dataviews/store/private-actions.ts index 10f2b9ce872d5..1dd847c187f03 100644 --- a/packages/editor/src/dataviews/store/private-actions.ts +++ b/packages/editor/src/dataviews/store/private-actions.ts @@ -22,7 +22,6 @@ import { restorePost, trashPost, renamePost, - resetPost, deletePost, } from '@wordpress/fields'; import duplicateTemplatePart from '../actions/duplicate-template-part'; @@ -98,7 +97,7 @@ export const registerPostTypeActions = : undefined, // @ts-ignore globalThis.IS_GUTENBERG_PLUGIN - ? ! [ 'wp_template', 'wp_block', 'wp_template_part' ].includes( + ? ! [ 'wp_block', 'wp_template_part' ].includes( postTypeConfig.slug ) && canCreate && @@ -118,7 +117,6 @@ export const registerPostTypeActions = : undefined, postTypeConfig.slug === 'wp_block' ? exportPattern : undefined, restorePost, - resetPost, deletePost, trashPost, permanentlyDeletePost, diff --git a/packages/fields/README.md b/packages/fields/README.md index e6cf6d3007ed9..1c237513a2f02 100644 --- a/packages/fields/README.md +++ b/packages/fields/README.md @@ -82,10 +82,6 @@ Undocumented declaration. Undocumented declaration. -### resetPost - -Undocumented declaration. - ### restorePost Undocumented declaration. diff --git a/packages/fields/src/actions/duplicate-post.tsx b/packages/fields/src/actions/duplicate-post.tsx index fd7e0ae9de4ad..6c75761e9dba2 100644 --- a/packages/fields/src/actions/duplicate-post.tsx +++ b/packages/fields/src/actions/duplicate-post.tsx @@ -55,10 +55,14 @@ const duplicatePost: Action< BasePost > = { return; } + const isTemplate = + item.type === 'wp_template' || + item.type === '_wp_static_template'; + const newItemOject = { - status: 'draft', + status: isTemplate ? 'publish' : 'draft', title: item.title, - slug: item.title || __( 'No title' ), + slug: isTemplate ? item.slug : item.title || __( 'No title' ), comment_status: item.comment_status, content: typeof item.content === 'string' @@ -97,7 +101,9 @@ const duplicatePost: Action< BasePost > = { try { const newItem = await saveEntityRecord( 'postType', - item.type, + item.type === '_wp_static_template' + ? 'wp_template' + : item.type, newItemOject, { throwOnError: true } ); diff --git a/packages/fields/src/actions/index.ts b/packages/fields/src/actions/index.ts index 08e22836e68fd..cfaf890f17923 100644 --- a/packages/fields/src/actions/index.ts +++ b/packages/fields/src/actions/index.ts @@ -4,7 +4,6 @@ export { default as reorderPageNative } from './reorder-page.native'; export { default as duplicatePost } from './duplicate-post'; export { default as duplicatePostNative } from './duplicate-post.native'; export { default as renamePost } from './rename-post'; -export { default as resetPost } from './reset-post'; export { default as duplicatePattern } from './duplicate-pattern'; export { default as exportPattern } from './export-pattern'; export { default as exportPatternNative } from './export-pattern.native'; diff --git a/packages/fields/src/actions/reset-post.tsx b/packages/fields/src/actions/reset-post.tsx deleted file mode 100644 index 105d7b283b833..0000000000000 --- a/packages/fields/src/actions/reset-post.tsx +++ /dev/null @@ -1,300 +0,0 @@ -/** - * WordPress dependencies - */ -import { backup } from '@wordpress/icons'; -import { dispatch, select, useDispatch } from '@wordpress/data'; -import { store as coreStore } from '@wordpress/core-data'; -import { __, sprintf } from '@wordpress/i18n'; -import { store as noticesStore } from '@wordpress/notices'; -import { useState } from '@wordpress/element'; -// @ts-ignore -import { parse, __unstableSerializeAndClean } from '@wordpress/blocks'; -import { - Button, - __experimentalText as Text, - __experimentalHStack as HStack, - __experimentalVStack as VStack, -} from '@wordpress/components'; -import type { Action } from '@wordpress/dataviews'; -import { addQueryArgs } from '@wordpress/url'; -import apiFetch from '@wordpress/api-fetch'; - -/** - * Internal dependencies - */ -import { - getItemTitle, - isTemplateOrTemplatePart, - TEMPLATE_ORIGINS, - TEMPLATE_POST_TYPE, -} from './utils'; -import type { CoreDataError, Template, TemplatePart } from '../types'; - -const isTemplateRevertable = ( - templateOrTemplatePart: Template | TemplatePart -) => { - if ( ! templateOrTemplatePart ) { - return false; - } - - return ( - templateOrTemplatePart.source === TEMPLATE_ORIGINS.custom && - ( Boolean( templateOrTemplatePart?.plugin ) || - templateOrTemplatePart?.has_theme_file ) - ); -}; - -/** - * Copied - pasted from https://github.com/WordPress/gutenberg/blob/bf1462ad37d4637ebbf63270b9c244b23c69e2a8/packages/editor/src/store/private-actions.js#L233-L365 - * - * @param {Object} template The template to revert. - * @param {Object} [options] - * @param {boolean} [options.allowUndo] Whether to allow the user to undo - * reverting the template. Default true. - */ -const revertTemplate = async ( - template: TemplatePart | Template, - { allowUndo = true } = {} -) => { - const noticeId = 'edit-site-template-reverted'; - dispatch( noticesStore ).removeNotice( noticeId ); - if ( ! isTemplateRevertable( template ) ) { - dispatch( noticesStore ).createErrorNotice( - __( 'This template is not revertable.' ), - { - type: 'snackbar', - } - ); - return; - } - - try { - const templateEntityConfig = select( coreStore ).getEntityConfig( - 'postType', - template.type - ); - - if ( ! templateEntityConfig ) { - dispatch( noticesStore ).createErrorNotice( - __( - 'The editor has encountered an unexpected error. Please reload.' - ), - { type: 'snackbar' } - ); - return; - } - - const fileTemplatePath = addQueryArgs( - `${ templateEntityConfig.baseURL }/${ template.id }`, - { context: 'edit', source: template.origin } - ); - - const fileTemplate = ( await apiFetch( { - path: fileTemplatePath, - } ) ) as any; - if ( ! fileTemplate ) { - dispatch( noticesStore ).createErrorNotice( - __( - 'The editor has encountered an unexpected error. Please reload.' - ), - { type: 'snackbar' } - ); - return; - } - - const serializeBlocks = ( { blocks: blocksForSerialization = [] } ) => - __unstableSerializeAndClean( blocksForSerialization ); - - const edited = select( coreStore ).getEditedEntityRecord( - 'postType', - template.type, - template.id - ) as any; - - // We are fixing up the undo level here to make sure we can undo - // the revert in the header toolbar correctly. - dispatch( coreStore ).editEntityRecord( - 'postType', - template.type, - template.id, - { - content: serializeBlocks, // Required to make the `undo` behave correctly. - blocks: edited.blocks, // Required to revert the blocks in the editor. - source: 'custom', // required to avoid turning the editor into a dirty state - }, - { - undoIgnore: true, // Required to merge this edit with the last undo level. - } - ); - - const blocks = parse( fileTemplate?.content?.raw ); - - dispatch( coreStore ).editEntityRecord( - 'postType', - template.type, - fileTemplate.id, - { - content: serializeBlocks, - blocks, - source: 'theme', - } - ); - - if ( allowUndo ) { - const undoRevert = () => { - dispatch( coreStore ).editEntityRecord( - 'postType', - template.type, - edited.id, - { - content: serializeBlocks, - blocks: edited.blocks, - source: 'custom', - } - ); - }; - - dispatch( noticesStore ).createSuccessNotice( - __( 'Template reset.' ), - { - type: 'snackbar', - id: noticeId, - actions: [ - { - label: __( 'Undo' ), - onClick: undoRevert, - }, - ], - } - ); - } - } catch ( error: any ) { - const errorMessage = - error.message && error.code !== 'unknown_error' - ? error.message - : __( 'Template revert failed. Please reload.' ); - - dispatch( noticesStore ).createErrorNotice( errorMessage, { - type: 'snackbar', - } ); - } -}; - -const resetPostAction: Action< Template | TemplatePart > = { - id: 'reset-post', - label: __( 'Reset' ), - isEligible: ( item ) => { - return ( - isTemplateOrTemplatePart( item ) && - item?.source === TEMPLATE_ORIGINS.custom && - ( Boolean( item.type === 'wp_template' && item?.plugin ) || - item?.has_theme_file ) - ); - }, - icon: backup, - supportsBulk: true, - hideModalHeader: true, - RenderModal: ( { items, closeModal, onActionPerformed } ) => { - const [ isBusy, setIsBusy ] = useState( false ); - - const { saveEditedEntityRecord } = useDispatch( coreStore ); - const { createSuccessNotice, createErrorNotice } = - useDispatch( noticesStore ); - const onConfirm = async () => { - try { - for ( const template of items ) { - await revertTemplate( template, { - allowUndo: false, - } ); - await saveEditedEntityRecord( - 'postType', - template.type, - template.id - ); - } - createSuccessNotice( - items.length > 1 - ? sprintf( - /* translators: The number of items. */ - __( '%s items reset.' ), - items.length - ) - : sprintf( - /* translators: The template/part's name. */ - __( '"%s" reset.' ), - getItemTitle( items[ 0 ] ) - ), - { - type: 'snackbar', - id: 'revert-template-action', - } - ); - } catch ( error ) { - let fallbackErrorMessage; - if ( items[ 0 ].type === TEMPLATE_POST_TYPE ) { - fallbackErrorMessage = - items.length === 1 - ? __( - 'An error occurred while reverting the template.' - ) - : __( - 'An error occurred while reverting the templates.' - ); - } else { - fallbackErrorMessage = - items.length === 1 - ? __( - 'An error occurred while reverting the template part.' - ) - : __( - 'An error occurred while reverting the template parts.' - ); - } - - const typedError = error as CoreDataError; - const errorMessage = - typedError.message && typedError.code !== 'unknown_error' - ? typedError.message - : fallbackErrorMessage; - - createErrorNotice( errorMessage, { type: 'snackbar' } ); - } - }; - return ( - - - { __( 'Reset to default and clear all customizations?' ) } - - - - - - - ); - }, -}; - -export default resetPostAction; diff --git a/packages/fields/src/actions/trash-post.tsx b/packages/fields/src/actions/trash-post.tsx index befbfb0ee7ffb..e685b557acf3f 100644 --- a/packages/fields/src/actions/trash-post.tsx +++ b/packages/fields/src/actions/trash-post.tsx @@ -18,7 +18,7 @@ import type { Action } from '@wordpress/dataviews'; /** * Internal dependencies */ -import { getItemTitle, isTemplateOrTemplatePart } from './utils'; +import { getItemTitle } from './utils'; import type { CoreDataError, PostWithPermissions } from '../types'; const trashPost: Action< PostWithPermissions > = { @@ -27,7 +27,7 @@ const trashPost: Action< PostWithPermissions > = { isPrimary: true, icon: trash, isEligible( item ) { - if ( isTemplateOrTemplatePart( item ) || item.type === 'wp_block' ) { + if ( item.type === 'wp_block' ) { return false; } diff --git a/test/e2e/specs/editor/blocks/image.spec.js b/test/e2e/specs/editor/blocks/image.spec.js index b2195f2c67688..f87d7daddfd91 100644 --- a/test/e2e/specs/editor/blocks/image.spec.js +++ b/test/e2e/specs/editor/blocks/image.spec.js @@ -1013,7 +1013,7 @@ test.describe( 'Image - Site editor', () => { test.beforeEach( async ( { admin } ) => { await admin.visitSiteEditor( { postId: 'emptytheme//index', - postType: 'wp_template', + postType: '_wp_static_template', canvas: 'edit', } ); } ); diff --git a/test/e2e/specs/editor/blocks/post-comments-form.spec.js b/test/e2e/specs/editor/blocks/post-comments-form.spec.js index db75771dc0915..ac6e3dd95fb42 100644 --- a/test/e2e/specs/editor/blocks/post-comments-form.spec.js +++ b/test/e2e/specs/editor/blocks/post-comments-form.spec.js @@ -33,7 +33,7 @@ test.describe( 'Comments Form', () => { // Navigate to "Singular" post template await admin.visitSiteEditor( { postId: 'emptytheme//singular', - postType: 'wp_template', + postType: '_wp_static_template', canvas: 'edit', } ); diff --git a/test/e2e/specs/editor/various/block-bindings/post-meta.spec.js b/test/e2e/specs/editor/various/block-bindings/post-meta.spec.js index 32334bfc777f2..30e48c664f434 100644 --- a/test/e2e/specs/editor/various/block-bindings/post-meta.spec.js +++ b/test/e2e/specs/editor/various/block-bindings/post-meta.spec.js @@ -25,7 +25,7 @@ test.describe( 'Post Meta source', () => { test.beforeEach( async ( { admin, editor } ) => { await admin.visitSiteEditor( { postId: 'gutenberg-test-themes/block-bindings//single-movie', - postType: 'wp_template', + postType: '_wp_static_template', canvas: 'edit', } ); await editor.openDocumentSettingsSidebar(); @@ -283,7 +283,7 @@ test.describe( 'Post Meta source', () => { test.beforeEach( async ( { admin, editor } ) => { await admin.visitSiteEditor( { postId: 'gutenberg-test-themes/block-bindings//custom-template', - postType: 'wp_template', + postType: '_wp_static_template', canvas: 'edit', } ); await editor.openDocumentSettingsSidebar(); diff --git a/test/e2e/specs/editor/various/write-design-mode.spec.js b/test/e2e/specs/editor/various/write-design-mode.spec.js index 2116f9042685a..781ccc854dbce 100644 --- a/test/e2e/specs/editor/various/write-design-mode.spec.js +++ b/test/e2e/specs/editor/various/write-design-mode.spec.js @@ -11,7 +11,7 @@ test.describe( 'Write/Design mode', () => { test.beforeEach( async ( { admin } ) => { await admin.visitSiteEditor( { postId: 'emptytheme//index', - postType: 'wp_template', + postType: '_wp_static_template', canvas: 'edit', } ); } ); diff --git a/test/e2e/specs/site-editor/block-removal.spec.js b/test/e2e/specs/site-editor/block-removal.spec.js index 7fc547c19e59e..9eb8053049a2b 100644 --- a/test/e2e/specs/site-editor/block-removal.spec.js +++ b/test/e2e/specs/site-editor/block-removal.spec.js @@ -15,7 +15,7 @@ test.describe( 'Site editor block removal prompt', () => { test.beforeEach( async ( { admin } ) => { await admin.visitSiteEditor( { postId: 'emptytheme//index', - postType: 'wp_template', + postType: '_wp_static_template', canvas: 'edit', } ); } ); diff --git a/test/e2e/specs/site-editor/font-library.spec.js b/test/e2e/specs/site-editor/font-library.spec.js index 7928ef8f71c53..1f811e7da25db 100644 --- a/test/e2e/specs/site-editor/font-library.spec.js +++ b/test/e2e/specs/site-editor/font-library.spec.js @@ -12,7 +12,7 @@ test.describe( 'Font Library', () => { test.beforeEach( async ( { admin } ) => { await admin.visitSiteEditor( { postId: 'emptytheme//index', - postType: 'wp_template', + postType: '_wp_static_template', canvas: 'edit', } ); } ); @@ -57,7 +57,7 @@ test.describe( 'Font Library', () => { test.beforeEach( async ( { admin } ) => { await admin.visitSiteEditor( { postId: 'twentytwentythree//index', - postType: 'wp_template', + postType: '_wp_static_template', canvas: 'edit', } ); } ); @@ -137,7 +137,7 @@ test.describe( 'Font Library', () => { test.beforeEach( async ( { admin } ) => { await admin.visitSiteEditor( { postId: 'emptytheme//index', - postType: 'wp_template', + postType: '_wp_static_template', canvas: 'edit', } ); } ); @@ -218,7 +218,7 @@ test.describe( 'Font Library', () => { test.beforeEach( async ( { admin } ) => { await admin.visitSiteEditor( { postId: 'twentytwentyfour//home', - postType: 'wp_template', + postType: '_wp_static_template', canvas: 'edit', } ); } ); diff --git a/test/e2e/specs/site-editor/iframe-rendering.spec.js b/test/e2e/specs/site-editor/iframe-rendering.spec.js index 9c25ef504637e..b01ffeb0ad19c 100644 --- a/test/e2e/specs/site-editor/iframe-rendering.spec.js +++ b/test/e2e/specs/site-editor/iframe-rendering.spec.js @@ -18,7 +18,7 @@ test.describe( 'Site editor iframe rendering mode', () => { } ) => { await admin.visitSiteEditor( { postId: 'emptytheme//index', - postType: 'wp_template', + postType: '_wp_static_template', canvas: 'edit', } ); const compatMode = await editor.canvas diff --git a/test/e2e/specs/site-editor/multi-entity-saving.spec.js b/test/e2e/specs/site-editor/multi-entity-saving.spec.js index cbc3bfde457a1..755484a53d110 100644 --- a/test/e2e/specs/site-editor/multi-entity-saving.spec.js +++ b/test/e2e/specs/site-editor/multi-entity-saving.spec.js @@ -21,7 +21,7 @@ test.describe( 'Site Editor - Multi-entity save flow', () => { test.beforeEach( async ( { admin } ) => { await admin.visitSiteEditor( { postId: 'emptytheme//index', - postType: 'wp_template', + postType: '_wp_static_template', canvas: 'edit', } ); } ); diff --git a/test/e2e/specs/site-editor/push-to-global-styles.spec.js b/test/e2e/specs/site-editor/push-to-global-styles.spec.js index 3e30f764811b1..178b01e7dc394 100644 --- a/test/e2e/specs/site-editor/push-to-global-styles.spec.js +++ b/test/e2e/specs/site-editor/push-to-global-styles.spec.js @@ -15,7 +15,7 @@ test.describe( 'Push to Global Styles button', () => { test.beforeEach( async ( { admin } ) => { await admin.visitSiteEditor( { postId: 'emptytheme//index', - postType: 'wp_template', + postType: '_wp_static_template', canvas: 'edit', } ); } ); diff --git a/test/e2e/specs/site-editor/settings-sidebar.spec.js b/test/e2e/specs/site-editor/settings-sidebar.spec.js index 87e9023401109..e086276c3d456 100644 --- a/test/e2e/specs/site-editor/settings-sidebar.spec.js +++ b/test/e2e/specs/site-editor/settings-sidebar.spec.js @@ -15,7 +15,7 @@ test.describe( 'Settings sidebar', () => { test.beforeEach( async ( { admin } ) => { await admin.visitSiteEditor( { postId: 'emptytheme//index', - postType: 'wp_template', + postType: '_wp_static_template', canvas: 'edit', } ); } ); @@ -63,7 +63,7 @@ test.describe( 'Settings sidebar', () => { await admin.visitSiteEditor( { postId: 'emptytheme//singular', - postType: 'wp_template', + postType: '_wp_static_template', canvas: 'edit', } ); diff --git a/test/e2e/specs/site-editor/site-editor-export.spec.js b/test/e2e/specs/site-editor/site-editor-export.spec.js index a0a56c18089cc..db85a4c066f04 100644 --- a/test/e2e/specs/site-editor/site-editor-export.spec.js +++ b/test/e2e/specs/site-editor/site-editor-export.spec.js @@ -22,7 +22,7 @@ test.describe( 'Site Editor Templates Export', () => { } ) => { await admin.visitSiteEditor( { postId: 'emptytheme//index', - postType: 'wp_template', + postType: '_wp_static_template', canvas: 'edit', } ); await page diff --git a/test/e2e/specs/site-editor/style-variations.spec.js b/test/e2e/specs/site-editor/style-variations.spec.js index 9c4243b0d171f..949dd87371003 100644 --- a/test/e2e/specs/site-editor/style-variations.spec.js +++ b/test/e2e/specs/site-editor/style-variations.spec.js @@ -36,7 +36,7 @@ test.describe( 'Global styles variations', () => { } ) => { await admin.visitSiteEditor( { postId: 'gutenberg-test-themes/style-variations//index', - postType: 'wp_template', + postType: '_wp_static_template', canvas: 'edit', } ); @@ -72,7 +72,7 @@ test.describe( 'Global styles variations', () => { } ) => { await admin.visitSiteEditor( { postId: 'gutenberg-test-themes/style-variations//index', - postType: 'wp_template', + postType: '_wp_static_template', canvas: 'edit', } ); await siteEditorStyleVariations.browseStyles(); @@ -108,7 +108,7 @@ test.describe( 'Global styles variations', () => { } ) => { await admin.visitSiteEditor( { postId: 'gutenberg-test-themes/style-variations//index', - postType: 'wp_template', + postType: '_wp_static_template', canvas: 'edit', } ); await siteEditorStyleVariations.browseStyles(); @@ -150,7 +150,7 @@ test.describe( 'Global styles variations', () => { } ) => { await admin.visitSiteEditor( { postId: 'gutenberg-test-themes/style-variations//index', - postType: 'wp_template', + postType: '_wp_static_template', canvas: 'edit', } ); await siteEditorStyleVariations.browseStyles(); @@ -180,7 +180,7 @@ test.describe( 'Global styles variations', () => { } ) => { await admin.visitSiteEditor( { postId: 'gutenberg-test-themes/style-variations//index', - postType: 'wp_template', + postType: '_wp_static_template', canvas: 'edit', } ); await siteEditorStyleVariations.browseStyles(); diff --git a/test/e2e/specs/site-editor/title.spec.js b/test/e2e/specs/site-editor/title.spec.js index 8f6c5252c9f41..75ae0ffa9efe2 100644 --- a/test/e2e/specs/site-editor/title.spec.js +++ b/test/e2e/specs/site-editor/title.spec.js @@ -19,7 +19,7 @@ test.describe( 'Site editor title', () => { // Navigate to a template. await admin.visitSiteEditor( { postId: 'emptytheme//index', - postType: 'wp_template', + postType: '_wp_static_template', canvas: 'edit', } ); const title = page diff --git a/test/e2e/specs/site-editor/zoom-out.spec.js b/test/e2e/specs/site-editor/zoom-out.spec.js index 464bd4a4a4efa..5b96e72251eba 100644 --- a/test/e2e/specs/site-editor/zoom-out.spec.js +++ b/test/e2e/specs/site-editor/zoom-out.spec.js @@ -15,7 +15,7 @@ test.describe( 'Zoom Out', () => { test.beforeEach( async ( { admin } ) => { await admin.visitSiteEditor( { postId: 'twentytwentyfour//index', - postType: 'wp_template', + postType: '_wp_static_template', canvas: 'edit', } ); } ); diff --git a/test/performance/specs/site-editor.spec.js b/test/performance/specs/site-editor.spec.js index e72d83fa8b3aa..8536aa1993e1a 100644 --- a/test/performance/specs/site-editor.spec.js +++ b/test/performance/specs/site-editor.spec.js @@ -217,6 +217,7 @@ test.describe( 'Site Editor Performance', () => { await admin.visitSiteEditor( { // The old URL is supported in both previous versions and new versions. path: '/wp_template', + activeView: 'Twenty Twenty-Four', } ); // The Templates index page has changed, so we need to know which UI is in use in the branch. @@ -287,11 +288,7 @@ test.describe( 'Site Editor Performance', () => { for ( let i = 1; i <= samples; i++ ) { // We want to start from a fresh state each time, without // queries or patterns already cached. - await admin.visitSiteEditor( { - postId: 'twentytwentyfour//home', - postType: 'wp_template', - canvas: 'edit', - } ); + await admin.visitSiteEditor( { canvas: 'edit' } ); await editor.openDocumentSettingsSidebar(); /*