Skip to content
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

Closed
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .vscode/extensions.json
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": [

]
}
53 changes: 50 additions & 3 deletions packages/block-library/src/block/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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';
Expand All @@ -32,7 +35,7 @@ export default function ReusableBlockEdit( { attributes: { ref }, clientId } ) {
const [ hasAlreadyRendered, RecursionProvider ] = useNoRecursiveRenders(
ref
);
const { isMissing, hasResolved } = useSelect(
const { isMissing, hasResolved, parentBlockName } = useSelect(
( select ) => {
const persistedBlock = select( coreStore ).getEntityRecord(
'postType',
Expand All @@ -46,9 +49,22 @@ 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 ];
Copy link
Member

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?

Copy link
Contributor Author

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.

const _parentBlockName = getBlockName( _firstParentClientId );

return {
hasResolved: hasResolvedBlock,
isMissing: hasResolvedBlock && ! persistedBlock,
parentBlockName: _parentBlockName,
};
},
[ ref, clientId ]
Expand Down Expand Up @@ -84,6 +100,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
Copy link
Member

Choose a reason for hiding this comment

The 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?

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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 core/block thus it will lock the reusable blocks. The same logic follows in the case of the reusable blocks inside columns.

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.
In such a scenario, the previously selected reusable block remains unlocked.

I am adding a commit to fix this bug. Once again, thank you for reviewing it! 🙏

if ( ! isInnerBlock ) {
setIsLocked( true );
}
}, [ parentBlockName ] );

if ( hasAlreadyRendered ) {
return (
<div { ...blockProps }>
Expand Down Expand Up @@ -136,8 +170,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>
Expand Down
13 changes: 13 additions & 0 deletions packages/block-library/src/block/editor.scss
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,17 @@
.components-disabled .block-list-appender {
display: none;
}

.is-locked {
position: absolute;
cursor: pointer;
width: 100%;
height: 100%;
z-index: 1;
border: 0;
&:hover {
background-color: rgba(#bbffe4, 0.3);
border: 1px solid#00b06f;
}
}
}