-
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 lock feature for Reusable Blocks to protect inner blocks #32710
Changes from all commits
f133a0f
58c6f77
a3b86ce
cabf0ba
7af65ff
e5df782
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
{ | ||
// See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations. | ||
// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp | ||
|
||
// List of extensions which should be recommended for users of this workspace. | ||
"recommendations": [ | ||
|
||
], | ||
// List of extensions recommended by VS Code that should not be recommended for users of this workspace. | ||
"unwantedRecommendations": [ | ||
|
||
] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,8 +14,10 @@ import { | |
ToolbarButton, | ||
TextControl, | ||
PanelBody, | ||
Disabled, | ||
} from '@wordpress/components'; | ||
import { __ } from '@wordpress/i18n'; | ||
import { useState, useEffect } from '@wordpress/element'; | ||
import { | ||
__experimentalUseInnerBlocksProps as useInnerBlocksProps, | ||
__experimentalUseNoRecursiveRenders as useNoRecursiveRenders, | ||
|
@@ -24,6 +26,7 @@ import { | |
InspectorControls, | ||
useBlockProps, | ||
Warning, | ||
store as blockEditorStore, | ||
} from '@wordpress/block-editor'; | ||
import { store as reusableBlocksStore } from '@wordpress/reusable-blocks'; | ||
import { ungroup } from '@wordpress/icons'; | ||
|
@@ -32,7 +35,12 @@ export default function ReusableBlockEdit( { attributes: { ref }, clientId } ) { | |
const [ hasAlreadyRendered, RecursionProvider ] = useNoRecursiveRenders( | ||
ref | ||
); | ||
const { isMissing, hasResolved } = useSelect( | ||
const { | ||
isMissing, | ||
hasResolved, | ||
parentBlockName, | ||
selectedBlock, | ||
} = useSelect( | ||
( select ) => { | ||
const persistedBlock = select( coreStore ).getEntityRecord( | ||
'postType', | ||
|
@@ -46,9 +54,23 @@ export default function ReusableBlockEdit( { attributes: { ref }, clientId } ) { | |
'wp_block', | ||
ref, | ||
] ); | ||
|
||
const { | ||
getSelectedBlockClientId, | ||
getBlockName, | ||
getBlockParents, | ||
} = select( blockEditorStore ); | ||
|
||
const currentBlockId = getSelectedBlockClientId(); | ||
const parents = getBlockParents( currentBlockId ); | ||
const _firstParentClientId = parents[ parents.length - 1 ]; | ||
const _parentBlockName = getBlockName( _firstParentClientId ); | ||
|
||
return { | ||
hasResolved: hasResolvedBlock, | ||
isMissing: hasResolvedBlock && ! persistedBlock, | ||
parentBlockName: _parentBlockName, | ||
selectedBlock: currentBlockId, | ||
}; | ||
}, | ||
[ ref, clientId ] | ||
|
@@ -84,6 +106,24 @@ export default function ReusableBlockEdit( { attributes: { ref }, clientId } ) { | |
|
||
const blockProps = useBlockProps(); | ||
|
||
// state for lock | ||
const [ isLocked, setIsLocked ] = useState( true ); | ||
|
||
let innerBlocks = <div { ...innerBlocksProps } />; | ||
if ( isLocked ) { | ||
innerBlocks = <Disabled> { innerBlocks } </Disabled>; | ||
} | ||
|
||
const lockContainerClass = isLocked ? 'is-locked' : 'is-unlocked'; | ||
|
||
// lock the blocks when deselected | ||
useEffect( () => { | ||
const isInnerBlock = parentBlockName === 'core/block'; // first check if selectedblock is inner block | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We check if the block is inner block by block type and not by verifying if the specific reusable block id is the parent of the deselected block, if we have multiple reusable blocks on the page will this logic handle that case? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thank you for taking a look 😄 Yes, it does work when multiple reusable blocks are on the page because first we have to select the reusable block itself, and only after that, we can select the inner blocks. So, when multiple reusable blocks are on the page, after working on the first reusable block, we go and select the other one. Now, first, we have to select the outer block (reusable block itself) which won't have a parentBlockName of The bug I came across while testing this was when a reusable block is selected and its inner blocks are not selected right after that but another reusable block is selected. I am adding a commit to fix this bug. Once again, thank you for reviewing it! 🙏 |
||
if ( ! isInnerBlock ) { | ||
setIsLocked( true ); | ||
} | ||
}, [ parentBlockName, selectedBlock ] ); | ||
|
||
if ( hasAlreadyRendered ) { | ||
return ( | ||
<div { ...blockProps }> | ||
|
@@ -136,8 +176,21 @@ export default function ReusableBlockEdit( { attributes: { ref }, clientId } ) { | |
/> | ||
</PanelBody> | ||
</InspectorControls> | ||
<div className="block-library-block__reusable-block-container"> | ||
{ <div { ...innerBlocksProps } /> } | ||
<div | ||
className="block-library-block__reusable-block-container" | ||
role="button" | ||
tabIndex={ 0 } | ||
onClick={ () => setIsLocked( false ) } | ||
onKeyDown={ ( e ) => { | ||
if ( e.key === 85 ) { | ||
setIsLocked( false ); | ||
} | ||
} } | ||
> | ||
<div | ||
className={ `reusable-block-lock-container ${ lockContainerClass }` } | ||
></div> | ||
{ innerBlocks } | ||
</div> | ||
</div> | ||
</RecursionProvider> | ||
|
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.
I guess if the reusable block is used inside a columns block for example this logic would not work?
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.
Yes, it does work when reusable blocks are inside columns.