-
Notifications
You must be signed in to change notification settings - Fork 4.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add template replace flow to template inspector #54609
Merged
Merged
Changes from all commits
Commits
Show all changes
35 commits
Select commit
Hold shift + click to select a range
40299b2
Add a modal to allow template switching
scruffian d67576e
fetch template info
scruffian 49301d5
Allow switching to different patterns
scruffian 5d0c438
Allow switching to different patterns
scruffian 0e5bdaa
Add columns
scruffian accc523
move availble templates to the actions
scruffian 1947768
filter for the correct templates
scruffian 7e5e8c9
create the right data structure in the use select
scruffian ac58a31
move to a hook
scruffian e1dc6be
inject theme attribute into pattern again
scruffian 540dfbc
put the overlay over the top of the dropdown
scruffian 7c9d71a
fix the pattern to templates hook
draganescu a00363f
set the template on click
draganescu c78d255
Also set the blocks
scruffian 9b76d30
remove calls to set template with the current template, since setting…
draganescu c3a13a4
serialize blocks so that we have correctly processed template parts
scruffian 5787636
remove duplicated code
scruffian 59cbfab
Remove unnecessary mapping
scruffian 3c513a3
refactor
scruffian a3763ea
memoize the patterns
scruffian af09641
combine the useSelect
scruffian 083478b
Update packages/edit-site/src/components/sidebar-edit-mode/page-panel…
scruffian ca5935a
Fix ESLint error
Mamaduka e7226e4
Only show the button is there is more than 1 pattern
scruffian f5ef5d7
Copy update
scruffian 59c7c24
Move the hook to a subdir
scruffian 3f1fd65
check that there are patterns
scruffian dd80e09
move the check
scruffian 4b4e835
remove useCallback
scruffian 6c54a97
change condition to show the button
scruffian 0b1af45
change condition
scruffian f7a087b
move to use editEntityRecord
scruffian 7c7fdfd
combine filters
scruffian 3521d12
add comments
scruffian 03e26f3
Update packages/edit-site/src/components/sidebar-edit-mode/template-p…
scruffian File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
97 changes: 97 additions & 0 deletions
97
packages/edit-site/src/components/sidebar-edit-mode/template-panel/hooks.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
/** | ||
* WordPress dependencies | ||
*/ | ||
import { useSelect } from '@wordpress/data'; | ||
import { useMemo } from '@wordpress/element'; | ||
import { store as coreStore } from '@wordpress/core-data'; | ||
import { parse } from '@wordpress/blocks'; | ||
|
||
/** | ||
* Internal dependencies | ||
*/ | ||
import { store as editSiteStore } from '../../../store'; | ||
import { PATTERN_CORE_SOURCES, PATTERN_TYPES } from '../../../utils/constants'; | ||
import { unlock } from '../../../lock-unlock'; | ||
|
||
function injectThemeAttributeInBlockTemplateContent( | ||
block, | ||
currentThemeStylesheet | ||
) { | ||
block.innerBlocks = block.innerBlocks.map( ( innerBlock ) => { | ||
return injectThemeAttributeInBlockTemplateContent( | ||
innerBlock, | ||
currentThemeStylesheet | ||
); | ||
} ); | ||
|
||
if ( | ||
block.name === 'core/template-part' && | ||
block.attributes.theme === undefined | ||
) { | ||
block.attributes.theme = currentThemeStylesheet; | ||
} | ||
return block; | ||
} | ||
|
||
function preparePatterns( patterns, template, currentThemeStylesheet ) { | ||
// Filter out duplicates. | ||
const filterOutDuplicatesByName = ( currentItem, index, items ) => | ||
index === items.findIndex( ( item ) => currentItem.name === item.name ); | ||
|
||
// Filter out core patterns. | ||
const filterOutCorePatterns = ( pattern ) => | ||
! PATTERN_CORE_SOURCES.includes( pattern.source ); | ||
|
||
// Filter only the patterns that are compatible with the current template. | ||
const filterCompatiblePatterns = ( pattern ) => | ||
pattern.templateTypes?.includes( template.slug ); | ||
|
||
return patterns | ||
.filter( | ||
filterOutCorePatterns && | ||
filterOutDuplicatesByName && | ||
filterCompatiblePatterns | ||
) | ||
.map( ( pattern ) => ( { | ||
...pattern, | ||
keywords: pattern.keywords || [], | ||
type: PATTERN_TYPES.theme, | ||
blocks: parse( pattern.content, { | ||
__unstableSkipMigrationLogs: true, | ||
} ).map( ( block ) => | ||
injectThemeAttributeInBlockTemplateContent( | ||
block, | ||
currentThemeStylesheet | ||
) | ||
), | ||
} ) ); | ||
} | ||
|
||
export function useAvailablePatterns( template ) { | ||
const { blockPatterns, restBlockPatterns, currentThemeStylesheet } = | ||
useSelect( ( select ) => { | ||
const { getSettings } = unlock( select( editSiteStore ) ); | ||
const settings = getSettings(); | ||
|
||
return { | ||
blockPatterns: | ||
settings.__experimentalAdditionalBlockPatterns ?? | ||
settings.__experimentalBlockPatterns, | ||
restBlockPatterns: select( coreStore ).getBlockPatterns(), | ||
currentThemeStylesheet: | ||
select( coreStore ).getCurrentTheme().stylesheet, | ||
}; | ||
}, [] ); | ||
|
||
return useMemo( () => { | ||
const mergedPatterns = [ | ||
...( blockPatterns || [] ), | ||
...( restBlockPatterns || [] ), | ||
]; | ||
return preparePatterns( | ||
mergedPatterns, | ||
template, | ||
currentThemeStylesheet | ||
); | ||
}, [ blockPatterns, restBlockPatterns, template, currentThemeStylesheet ] ); | ||
} | ||
89 changes: 89 additions & 0 deletions
89
...ages/edit-site/src/components/sidebar-edit-mode/template-panel/replace-template-button.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
/** | ||
* WordPress dependencies | ||
*/ | ||
import { useSelect, useDispatch } from '@wordpress/data'; | ||
import { useState } from '@wordpress/element'; | ||
import { __experimentalBlockPatternsList as BlockPatternsList } from '@wordpress/block-editor'; | ||
import { MenuItem, Modal } from '@wordpress/components'; | ||
import { __ } from '@wordpress/i18n'; | ||
import { store as coreStore } from '@wordpress/core-data'; | ||
import { useAsyncList } from '@wordpress/compose'; | ||
import { serialize } from '@wordpress/blocks'; | ||
|
||
/** | ||
* Internal dependencies | ||
*/ | ||
import { store as editSiteStore } from '../../../store'; | ||
|
||
export default function ReplaceTemplateButton( { | ||
onClick, | ||
availableTemplates, | ||
} ) { | ||
const { editEntityRecord } = useDispatch( coreStore ); | ||
const [ showModal, setShowModal ] = useState( false ); | ||
const onClose = () => { | ||
setShowModal( false ); | ||
}; | ||
|
||
const { postId, postType } = useSelect( ( select ) => { | ||
return { | ||
postId: select( editSiteStore ).getEditedPostId(), | ||
postType: select( editSiteStore ).getEditedPostType(), | ||
}; | ||
}, [] ); | ||
|
||
const onTemplateSelect = async ( selectedTemplate ) => { | ||
onClose(); // Close the template suggestions modal first. | ||
onClick(); | ||
await editEntityRecord( 'postType', postType, postId, { | ||
blocks: selectedTemplate.blocks, | ||
content: serialize( selectedTemplate.blocks ), | ||
} ); | ||
}; | ||
|
||
if ( ! availableTemplates.length || availableTemplates.length < 1 ) { | ||
return null; | ||
} | ||
|
||
return ( | ||
<> | ||
<MenuItem | ||
info={ __( | ||
'Replace the contents of this template with another.' | ||
) } | ||
onClick={ () => setShowModal( true ) } | ||
> | ||
{ __( 'Replace template' ) } | ||
</MenuItem> | ||
|
||
{ showModal && ( | ||
<Modal | ||
title={ __( 'Choose a template' ) } | ||
onRequestClose={ onClose } | ||
overlayClassName="edit-site-template-panel__replace-template-modal" | ||
isFullScreen | ||
> | ||
<div className="edit-site-template-panel__replace-template-modal__content"> | ||
<TemplatesList | ||
availableTemplates={ availableTemplates } | ||
onSelect={ onTemplateSelect } | ||
/> | ||
</div> | ||
</Modal> | ||
) } | ||
</> | ||
); | ||
} | ||
|
||
function TemplatesList( { availableTemplates, onSelect } ) { | ||
const shownTemplates = useAsyncList( availableTemplates ); | ||
|
||
return ( | ||
<BlockPatternsList | ||
label={ __( 'Templates' ) } | ||
blockPatterns={ availableTemplates } | ||
shownPatterns={ shownTemplates } | ||
onClickPattern={ onSelect } | ||
/> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file is a bit confusing to me. It's unfortunate that we have to do all this work in order to get the available list of patterns for a given template.
We need to have more clarity in terms of APIs there. How should a developer know that he has to do all of this in order to make use of patterns?
cc @ellatrix @jsnajdr as you both worked on patterns before as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is the
getAllPatterns
selector incore/block-editor
store that could replace most of thisuseAvailablePatterns
hook. But it has one major difference: it also loads all the reusable blocks, aka user patterns, using thegetReusableBlocks
selector. But the Site Editor is apparently never interested in user patterns. Does it even make sense to use user patterns in Site Editor? Or are they intended only for the Post Editor.If we have a version of
getAllPatterns
that doesn't return user patterns, we could use it at all four places in Site Editor where the code that gathers patterns from various locations is repeated.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems to me it was needed at the time when this PR was merged -- it was adding a
theme
attribute to allcore/template-part
blocks that didn't have atheme
attribute. But then, one month later, @gziolo merged #55965 which added thetheme
fallback directly in thecore/template-part
block.Today, I believe
injectThemeAttributeInBlockTemplateContent
could be removed. From more than one place.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We would have to perform some extensive testing, but hopefully, injecting a
theme
attribute on the template level should no longer be necessary.