From 20cb955f184126de8023bbec491937923840c76a Mon Sep 17 00:00:00 2001 From: scruffian Date: Fri, 6 Oct 2023 14:39:53 +0100 Subject: [PATCH] Template Parts: Add a replace flow to the inspector controls --- .../src/template-part/edit/index.js | 73 ++++++++++++++++++- 1 file changed, 71 insertions(+), 2 deletions(-) diff --git a/packages/block-library/src/template-part/edit/index.js b/packages/block-library/src/template-part/edit/index.js index 70078e5935836..268c3f4a64855 100644 --- a/packages/block-library/src/template-part/edit/index.js +++ b/packages/block-library/src/template-part/edit/index.js @@ -10,8 +10,11 @@ import { RecursionProvider, useHasRecursion, InspectorControls, + __experimentalBlockPatternsList as BlockPatternsList, } from '@wordpress/block-editor'; -import { Spinner, Modal, MenuItem } from '@wordpress/components'; +import { parse } from '@wordpress/blocks'; +import { PanelBody, Spinner, Modal, MenuItem } from '@wordpress/components'; +import { useAsyncList } from '@wordpress/compose'; import { __, sprintf } from '@wordpress/i18n'; import { store as coreStore } from '@wordpress/core-data'; import { useState } from '@wordpress/element'; @@ -43,7 +46,6 @@ function ReplaceButton( { templatePartId ); const blockPatterns = useAlternativeBlockPatterns( area, clientId ); - const hasReplacements = !! templateParts.length || !! blockPatterns.length; const canReplace = isEntityAvailable && @@ -67,6 +69,23 @@ function ReplaceButton( { ); } +function TemplatesList( { availableTemplates, onSelect } ) { + const shownTemplates = useAsyncList( availableTemplates ); + + if ( ! availableTemplates || availableTemplates?.length < 2 ) { + return null; + } + + return ( + + ); +} + export default function TemplatePartEdit( { attributes, setAttributes, @@ -117,12 +136,23 @@ export default function TemplatePartEdit( { [ templatePartId, attributes.area, clientId ] ); + const { templateParts } = useAlternativeTemplateParts( + area, + templatePartId + ); + const blockPatterns = useAlternativeBlockPatterns( area, clientId ); + const hasReplacements = !! templateParts.length || !! blockPatterns.length; const areaObject = useTemplatePartArea( area ); const blockProps = useBlockProps(); const isPlaceholder = ! slug; const isEntityAvailable = ! isPlaceholder && ! isMissing && isResolved; const TagName = tagName || areaObject.tagName; + const canReplace = + isEntityAvailable && + hasReplacements && + ( area === 'header' || area === 'footer' ); + // We don't want to render a missing state if we have any inner blocks. // A new template part is automatically created if we have any inner blocks but no entity. if ( @@ -154,6 +184,33 @@ export default function TemplatePartEdit( { ); } + const partsAsPatterns = templateParts.map( ( templatePart ) => ( { + name: createTemplatePartId( templatePart.theme, templatePart.slug ), + title: templatePart.title.rendered, + blocks: parse( templatePart.content.raw ), + templatePart, + } ) ); + const patternsAndParts = [ ...blockPatterns, ...partsAsPatterns ]; + + // TODO - de dupe + const onTemplatePartSelect = ( { templatePart } ) => { + setAttributes( { + slug: templatePart.slug, + theme: templatePart.theme, + area: templatePart.area, + } ); + createSuccessNotice( + sprintf( + /* translators: %s: template part title. */ + __( 'Template Part "%s" inserted.' ), + templatePart.title?.rendered || templatePart.slug + ), + { + type: 'snackbar', + } + ); + }; + return ( <> @@ -207,6 +264,18 @@ export default function TemplatePartEdit( { ); } } + + { canReplace && patternsAndParts.length && ( + + + + + + ) } + { isEntityAvailable && (