diff --git a/packages/block-editor/src/components/block-inspector/index.js b/packages/block-editor/src/components/block-inspector/index.js index 18cd72cde057dc..9cb3b89a7bc252 100644 --- a/packages/block-editor/src/components/block-inspector/index.js +++ b/packages/block-editor/src/components/block-inspector/index.js @@ -92,7 +92,9 @@ const BlockInspector = ( { showNoBlockSelectedMessage = true } ) => { blockType: _blockType, topLevelLockedBlock: __unstableGetContentLockingParent( _selectedBlockClientId ) || - ( getTemplateLock( _selectedBlockClientId ) === 'contentOnly' + ( getTemplateLock( _selectedBlockClientId ) === 'contentOnly' || + ( _selectedBlockName === 'core/block' && + window.__experimentalPatternPartialSyncing ) ? _selectedBlockClientId : undefined ), }; diff --git a/packages/block-editor/src/components/block-list/use-in-between-inserter.js b/packages/block-editor/src/components/block-list/use-in-between-inserter.js index a60453716ff29c..bd323ed057d733 100644 --- a/packages/block-editor/src/components/block-list/use-in-between-inserter.js +++ b/packages/block-editor/src/components/block-list/use-in-between-inserter.js @@ -28,6 +28,7 @@ export function useInBetweenInserter() { getTemplateLock, __unstableIsWithinBlockOverlay, getBlockEditingMode, + getBlockName, } = useSelect( blockEditorStore ); const { showInsertionPoint, hideInsertionPoint } = useDispatch( blockEditorStore ); @@ -75,7 +76,9 @@ export function useInBetweenInserter() { if ( getTemplateLock( rootClientId ) || - getBlockEditingMode( rootClientId ) === 'disabled' + getBlockEditingMode( rootClientId ) === 'disabled' || + ( getBlockName( rootClientId ) === 'core/block' && + window.__experimentalPatternPartialSyncing ) ) { return; } diff --git a/packages/block-editor/src/components/block-lock/modal.js b/packages/block-editor/src/components/block-lock/modal.js index cfafa6c031bbd1..c08159faa05fd6 100644 --- a/packages/block-editor/src/components/block-lock/modal.js +++ b/packages/block-editor/src/components/block-lock/modal.js @@ -25,7 +25,7 @@ import useBlockDisplayInformation from '../use-block-display-information'; import { store as blockEditorStore } from '../../store'; // Entity based blocks which allow edit locking -const ALLOWS_EDIT_LOCKING = [ 'core/block', 'core/navigation' ]; +const ALLOWS_EDIT_LOCKING = [ 'core/navigation' ]; function getTemplateLockValue( lock ) { // Prevents all operations. diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index c0441cd3b3755e..0ed8a55bcd5364 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -2806,8 +2806,10 @@ export const __unstableGetContentLockingParent = createSelector( while ( state.blocks.parents.has( current ) ) { current = state.blocks.parents.get( current ); if ( - current && - getTemplateLock( state, current ) === 'contentOnly' + ( getBlockName( state, current ) === 'core/block' && + window.__experimentalPatternPartialSyncing ) || + ( current && + getTemplateLock( state, current ) === 'contentOnly' ) ) { result = current; } diff --git a/packages/block-library/src/block/block.json b/packages/block-library/src/block/block.json index aeccdbfc1051db..811c0984cf25dd 100644 --- a/packages/block-library/src/block/block.json +++ b/packages/block-library/src/block/block.json @@ -7,6 +7,7 @@ "description": "Create and save content to reuse across your site. Update the pattern, and the changes apply everywhere it’s used.", "keywords": [ "reusable" ], "textdomain": "default", + "usesContext": [ "postId" ], "attributes": { "ref": { "type": "number" diff --git a/packages/block-library/src/block/edit.js b/packages/block-library/src/block/edit.js index e86ed9b59c62b2..3c2d76d3639e6f 100644 --- a/packages/block-library/src/block/edit.js +++ b/packages/block-library/src/block/edit.js @@ -8,12 +8,12 @@ import classnames from 'classnames'; */ import { useRegistry, useSelect, useDispatch } from '@wordpress/data'; import { useRef, useMemo, useEffect } from '@wordpress/element'; -import { useEntityProp, useEntityRecord } from '@wordpress/core-data'; +import { useEntityRecord, store as coreStore } from '@wordpress/core-data'; import { Placeholder, Spinner, - TextControl, - PanelBody, + ToolbarButton, + ToolbarGroup, } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { @@ -21,13 +21,14 @@ import { __experimentalRecursionProvider as RecursionProvider, __experimentalUseHasRecursion as useHasRecursion, InnerBlocks, - InspectorControls, useBlockProps, Warning, privateApis as blockEditorPrivateApis, store as blockEditorStore, + BlockControls, } from '@wordpress/block-editor'; import { getBlockSupport, parse } from '@wordpress/blocks'; +import { addQueryArgs } from '@wordpress/url'; /** * Internal dependencies @@ -55,6 +56,16 @@ function getPartiallySyncedAttributes( block ) { const fullAlignments = [ 'full', 'wide', 'left', 'right' ]; +function setBlockEditMode( setEditMode, blocks ) { + blocks.forEach( ( block ) => { + const editMode = isPartiallySynced( block ) + ? 'contentOnly' + : 'disabled'; + setEditMode( block.clientId, editMode ); + setBlockEditMode( setEditMode, block.innerBlocks ); + } ); +} + const useInferredLayout = ( blocks, parentLayout ) => { const initialInferredAlignmentRef = useRef(); @@ -137,6 +148,7 @@ export default function ReusableBlockEdit( { attributes: { ref, overrides }, __unstableParentLayout: parentLayout, clientId: patternClientId, + context: { postId }, } ) { const registry = useRegistry(); const hasAlreadyRendered = useHasRecursion( ref ); @@ -145,6 +157,7 @@ export default function ReusableBlockEdit( { 'wp_block', ref ); + const isMissing = hasResolved && ! record; const initialOverrides = useRef( overrides ); const defaultValuesRef = useRef( {} ); @@ -153,7 +166,50 @@ export default function ReusableBlockEdit( { __unstableMarkNextChangeAsNotPersistent, setBlockEditingMode, } = useDispatch( blockEditorStore ); - const { getBlockEditingMode } = useSelect( blockEditorStore ); + + const { editUrl, innerBlocks, userCanEdit, getBlockEditingMode } = + useSelect( + ( select ) => { + const { canUser } = select( coreStore ); + const { + getSettings, + getBlocks, + getBlockEditingMode: editingMode, + } = select( blockEditorStore ); + + const blocks = getBlocks( patternClientId ); + const isBlockTheme = getSettings().__unstableIsBlockBasedTheme; + const canEdit = canUser( 'update', 'blocks', ref ); + const defaultUrl = addQueryArgs( 'post.php', { + action: 'edit', + post: ref, + } ); + const siteEditorUrl = addQueryArgs( 'site-editor.php', { + postType: 'wp_block', + postId: ref, + categoryType: 'pattern', + canvas: 'edit', + syncedPatternId: postId, + } ); + + // For editing link to the site editor if the theme and user permissions support it. + return { + innerBlocks: blocks, + editUrl: + canUser( 'read', 'templates' ) && isBlockTheme + ? siteEditorUrl + : defaultUrl, + userCanEdit: canEdit, + getBlockEditingMode: editingMode, + }; + }, + [ patternClientId, postId, ref ] + ); + + useEffect( + () => setBlockEditMode( setBlockEditingMode, innerBlocks ), + [ innerBlocks, setBlockEditingMode ] + ); useEffect( () => { if ( ! record?.content?.raw ) return; @@ -183,18 +239,6 @@ export default function ReusableBlockEdit( { setBlockEditingMode, ] ); - const innerBlocks = useSelect( - ( select ) => select( blockEditorStore ).getBlocks( patternClientId ), - [ patternClientId ] - ); - - const [ title, setTitle ] = useEntityProp( - 'postType', - 'wp_block', - 'title', - ref - ); - const { alignment, layout } = useInferredLayout( innerBlocks, parentLayout @@ -268,17 +312,15 @@ export default function ReusableBlockEdit( { return ( - - - - - + { userCanEdit && ( + + + + { __( 'Edit' ) } + + + + ) } { children === null ? (
) : ( diff --git a/packages/edit-site/src/components/block-editor/back-button.js b/packages/edit-site/src/components/block-editor/back-button.js index 924dedd4f853e1..75dc0a33d7afd8 100644 --- a/packages/edit-site/src/components/block-editor/back-button.js +++ b/packages/edit-site/src/components/block-editor/back-button.js @@ -5,6 +5,7 @@ import { Button } from '@wordpress/components'; import { arrowLeft } from '@wordpress/icons'; import { __ } from '@wordpress/i18n'; import { privateApis as routerPrivateApis } from '@wordpress/router'; +import { getQueryArgs } from '@wordpress/url'; /** * Internal dependencies @@ -24,9 +25,10 @@ function BackButton() { const isNavigationMenu = location.params.postType === NAVIGATION_POST_TYPE; const previousTemplateId = location.state?.fromTemplateId; - const isFocusMode = isTemplatePart || isNavigationMenu; + const { syncedPatternId } = getQueryArgs( window.location.href ); + const isFocusMode = isTemplatePart || isNavigationMenu || syncedPatternId; - if ( ! isFocusMode || ! previousTemplateId ) { + if ( ! isFocusMode || ( ! previousTemplateId && ! syncedPatternId ) ) { return null; }