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 ability to set templateLock = 'contentOnly' in editor settings #50082

Closed
wants to merge 3 commits into from

Conversation

noisysocks
Copy link
Member

@noisysocks noisysocks commented Apr 26, 2023

What?

Editor content locking

In #43037, the ability to content lock blocks was added. This is done by setting the templateLock attribute on any container block (e.g. Group) to 'contentOnly'. This is useful for creating patterns where the user may only edit content and not add, remove, or edit blocks. See https://richtabor.com/content-only-editing/ for a great guide on doing this.

This PR expands this functionality to work at the editor level. You can now set templateLock to 'contentOnly' in the block editor settings. Doing this results in the exact same experience as above, but applied to all blocks within the editor.

Kapture.2023-04-26.at.13.56.02.mp4

This PR also adds the ability to explicitly state which block types are considered to be "content" via the contentBlockTypes editor setting. This gives one the ability of finely control the locking. For example, to lock all editing except for the content within a Post Content block, one can specify:

templateLock: 'contentOnly',
contentBlockTypes: [ 'core/post-content' ],

Because container blocks (e.g. Post Content) can now be designated as content, the content locking functionality has been added to correctly take into account block nesting. For example it is possible to move and delete blocks within a content block.

List View changes

Currently, when a container block has templateLock = 'contentOnly', the List View hides all of that container block's children. This behaviour no longer makes sense now that the editor can have templateLock = 'contentOnly' as this would result in a completely empty List View. Therefore this PR adjusts the List View to display only the content blocks that are nested within a locked container.

Before After
Screenshot 2023-04-26 at 14 05 01 Screenshot 2023-04-26 at 14 04 37

Block inspector changes

The list of content blocks that appears in the block inspector when a locked block is selected has been updated to use a Panel component for consistency and to re-use the same List View logic.

Before After
Screenshot 2023-04-26 at 14 12 44 Screenshot 2023-04-26 at 14 13 19

API changes

The content locking APIs (selectors and actions) have been rewritten for clarity around three defined terms: content locking block, content locked block, and content block. isContentLockedBlock (formerly __unstableGetContentLockingParent) has been marked stable as it is the primary way that blocks adjust their interface in response to a lock. All other selectors and APIs have been marked private.

In addition there is a new isInsertionLocked selector which is similar in nature to canRemoveBlock, canMoveBlock, and canEditBlock. Having this lets us avoid repeating logic that checks getTemplateLock over and over.

  • isInsertionLocked( rootClientId ) (public)
  • __unstableGetContentLockingParent( clientId )isContentLockedBlock( clientId ) (public)
  • __unstableGetTemporarilyEditingAsBlocks()getTemporarilyUnlockedBlock() (private)
  • __unstableSetTemporarilyEditingAsBlocks()setTemporarilyUnlockedBlock() (private)
  • getContentClientIdsTree( clientId ) (private)
  • isContentBlock( clientId ) (private)
  • getContentLockingBlock( clientId ) (private)
  • isContentLockingBlock( clientId ) (private)

Why?

This forms the basis for how #49980 is implemented.

Testing Instructions

To test the new functionality:

  1. Edit a post, page, or template.
  2. Paste this into the DevTools console: wp.data.dispatch( 'core/block-editor' ).updateSettings( { templateLock: 'contentOnly' } ).

To test the existing functionality for regressions:

  1. Add a pattern that has a content lock, e.g. this one.
  2. Edit a post, page, or template.
  3. Insert that pattern.

@noisysocks noisysocks added [Type] Enhancement A suggestion for improvement. [Package] Block editor /packages/block-editor [Feature] Block Locking The API allowing for the ability to lock/unlock blocks labels Apr 26, 2023
Comment on lines +225 to +228
if ( selector.isRegistrySelector ) {
selector.registry = registry;
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This bit of code was missing. It's the same as what's on line 208 above. Without it you get an error when using createRegistrySelector for a private selectors.

@noisysocks noisysocks added the Needs Dev Note Requires a developer note for a major WordPress release cycle label Apr 26, 2023
@github-actions
Copy link

github-actions bot commented Apr 26, 2023

Size Change: +158 B (0%)

Total Size: 1.37 MB

Filename Size Change
build/block-editor/content-rtl.css 4.17 kB -1 B (0%)
build/block-editor/index.min.js 201 kB +199 B (0%)
build/block-editor/style-rtl.css 15.1 kB -14 B (0%)
build/block-editor/style.css 15.1 kB -13 B (0%)
build/block-library/index.min.js 204 kB -14 B (0%)
build/data/index.min.js 8.68 kB +1 B (0%)
ℹ️ View Unchanged
Filename Size
build/a11y/index.min.js 993 B
build/annotations/index.min.js 2.78 kB
build/api-fetch/index.min.js 2.27 kB
build/autop/index.min.js 2.15 kB
build/blob/index.min.js 483 B
build/block-directory/index.min.js 7.2 kB
build/block-directory/style-rtl.css 1.04 kB
build/block-directory/style.css 1.04 kB
build/block-editor/content.css 4.17 kB
build/block-editor/default-editor-styles-rtl.css 403 B
build/block-editor/default-editor-styles.css 403 B
build/block-library/blocks/archives/editor-rtl.css 61 B
build/block-library/blocks/archives/editor.css 60 B
build/block-library/blocks/archives/style-rtl.css 90 B
build/block-library/blocks/archives/style.css 90 B
build/block-library/blocks/audio/editor-rtl.css 150 B
build/block-library/blocks/audio/editor.css 150 B
build/block-library/blocks/audio/style-rtl.css 122 B
build/block-library/blocks/audio/style.css 122 B
build/block-library/blocks/audio/theme-rtl.css 138 B
build/block-library/blocks/audio/theme.css 138 B
build/block-library/blocks/avatar/editor-rtl.css 116 B
build/block-library/blocks/avatar/editor.css 116 B
build/block-library/blocks/avatar/style-rtl.css 91 B
build/block-library/blocks/avatar/style.css 91 B
build/block-library/blocks/block/editor-rtl.css 305 B
build/block-library/blocks/block/editor.css 305 B
build/block-library/blocks/button/editor-rtl.css 587 B
build/block-library/blocks/button/editor.css 587 B
build/block-library/blocks/button/style-rtl.css 628 B
build/block-library/blocks/button/style.css 627 B
build/block-library/blocks/buttons/editor-rtl.css 337 B
build/block-library/blocks/buttons/editor.css 337 B
build/block-library/blocks/buttons/style-rtl.css 332 B
build/block-library/blocks/buttons/style.css 332 B
build/block-library/blocks/calendar/style-rtl.css 239 B
build/block-library/blocks/calendar/style.css 239 B
build/block-library/blocks/categories/editor-rtl.css 113 B
build/block-library/blocks/categories/editor.css 112 B
build/block-library/blocks/categories/style-rtl.css 124 B
build/block-library/blocks/categories/style.css 124 B
build/block-library/blocks/code/editor-rtl.css 53 B
build/block-library/blocks/code/editor.css 53 B
build/block-library/blocks/code/style-rtl.css 121 B
build/block-library/blocks/code/style.css 121 B
build/block-library/blocks/code/theme-rtl.css 124 B
build/block-library/blocks/code/theme.css 124 B
build/block-library/blocks/columns/editor-rtl.css 108 B
build/block-library/blocks/columns/editor.css 108 B
build/block-library/blocks/columns/style-rtl.css 409 B
build/block-library/blocks/columns/style.css 409 B
build/block-library/blocks/comment-author-avatar/editor-rtl.css 125 B
build/block-library/blocks/comment-author-avatar/editor.css 125 B
build/block-library/blocks/comment-content/style-rtl.css 92 B
build/block-library/blocks/comment-content/style.css 92 B
build/block-library/blocks/comment-template/style-rtl.css 199 B
build/block-library/blocks/comment-template/style.css 198 B
build/block-library/blocks/comments-pagination-numbers/editor-rtl.css 123 B
build/block-library/blocks/comments-pagination-numbers/editor.css 121 B
build/block-library/blocks/comments-pagination/editor-rtl.css 222 B
build/block-library/blocks/comments-pagination/editor.css 209 B
build/block-library/blocks/comments-pagination/style-rtl.css 235 B
build/block-library/blocks/comments-pagination/style.css 231 B
build/block-library/blocks/comments-title/editor-rtl.css 75 B
build/block-library/blocks/comments-title/editor.css 75 B
build/block-library/blocks/comments/editor-rtl.css 840 B
build/block-library/blocks/comments/editor.css 839 B
build/block-library/blocks/comments/style-rtl.css 637 B
build/block-library/blocks/comments/style.css 636 B
build/block-library/blocks/cover/editor-rtl.css 647 B
build/block-library/blocks/cover/editor.css 650 B
build/block-library/blocks/cover/style-rtl.css 1.6 kB
build/block-library/blocks/cover/style.css 1.59 kB
build/block-library/blocks/details-summary/editor-rtl.css 65 B
build/block-library/blocks/details-summary/editor.css 65 B
build/block-library/blocks/details-summary/style-rtl.css 61 B
build/block-library/blocks/details-summary/style.css 61 B
build/block-library/blocks/details/style-rtl.css 54 B
build/block-library/blocks/details/style.css 54 B
build/block-library/blocks/embed/editor-rtl.css 293 B
build/block-library/blocks/embed/editor.css 293 B
build/block-library/blocks/embed/style-rtl.css 410 B
build/block-library/blocks/embed/style.css 410 B
build/block-library/blocks/embed/theme-rtl.css 138 B
build/block-library/blocks/embed/theme.css 138 B
build/block-library/blocks/file/editor-rtl.css 300 B
build/block-library/blocks/file/editor.css 300 B
build/block-library/blocks/file/style-rtl.css 269 B
build/block-library/blocks/file/style.css 270 B
build/block-library/blocks/file/view.min.js 353 B
build/block-library/blocks/freeform/editor-rtl.css 2.44 kB
build/block-library/blocks/freeform/editor.css 2.44 kB
build/block-library/blocks/gallery/editor-rtl.css 984 B
build/block-library/blocks/gallery/editor.css 988 B
build/block-library/blocks/gallery/style-rtl.css 1.55 kB
build/block-library/blocks/gallery/style.css 1.55 kB
build/block-library/blocks/gallery/theme-rtl.css 122 B
build/block-library/blocks/gallery/theme.css 122 B
build/block-library/blocks/group/editor-rtl.css 654 B
build/block-library/blocks/group/editor.css 654 B
build/block-library/blocks/group/style-rtl.css 57 B
build/block-library/blocks/group/style.css 57 B
build/block-library/blocks/group/theme-rtl.css 78 B
build/block-library/blocks/group/theme.css 78 B
build/block-library/blocks/heading/style-rtl.css 76 B
build/block-library/blocks/heading/style.css 76 B
build/block-library/blocks/html/editor-rtl.css 340 B
build/block-library/blocks/html/editor.css 341 B
build/block-library/blocks/image/editor-rtl.css 834 B
build/block-library/blocks/image/editor.css 833 B
build/block-library/blocks/image/style-rtl.css 652 B
build/block-library/blocks/image/style.css 652 B
build/block-library/blocks/image/theme-rtl.css 137 B
build/block-library/blocks/image/theme.css 137 B
build/block-library/blocks/latest-comments/style-rtl.css 357 B
build/block-library/blocks/latest-comments/style.css 357 B
build/block-library/blocks/latest-posts/editor-rtl.css 213 B
build/block-library/blocks/latest-posts/editor.css 212 B
build/block-library/blocks/latest-posts/style-rtl.css 478 B
build/block-library/blocks/latest-posts/style.css 478 B
build/block-library/blocks/list/style-rtl.css 88 B
build/block-library/blocks/list/style.css 88 B
build/block-library/blocks/media-text/editor-rtl.css 266 B
build/block-library/blocks/media-text/editor.css 263 B
build/block-library/blocks/media-text/style-rtl.css 507 B
build/block-library/blocks/media-text/style.css 505 B
build/block-library/blocks/more/editor-rtl.css 431 B
build/block-library/blocks/more/editor.css 431 B
build/block-library/blocks/navigation-link/editor-rtl.css 716 B
build/block-library/blocks/navigation-link/editor.css 715 B
build/block-library/blocks/navigation-link/style-rtl.css 115 B
build/block-library/blocks/navigation-link/style.css 115 B
build/block-library/blocks/navigation-submenu/editor-rtl.css 299 B
build/block-library/blocks/navigation-submenu/editor.css 299 B
build/block-library/blocks/navigation/editor-rtl.css 2.13 kB
build/block-library/blocks/navigation/editor.css 2.14 kB
build/block-library/blocks/navigation/style-rtl.css 2.22 kB
build/block-library/blocks/navigation/style.css 2.21 kB
build/block-library/blocks/navigation/view-modal.min.js 2.81 kB
build/block-library/blocks/navigation/view.min.js 447 B
build/block-library/blocks/nextpage/editor-rtl.css 395 B
build/block-library/blocks/nextpage/editor.css 395 B
build/block-library/blocks/page-list/editor-rtl.css 401 B
build/block-library/blocks/page-list/editor.css 401 B
build/block-library/blocks/page-list/style-rtl.css 175 B
build/block-library/blocks/page-list/style.css 175 B
build/block-library/blocks/paragraph/editor-rtl.css 174 B
build/block-library/blocks/paragraph/editor.css 174 B
build/block-library/blocks/paragraph/style-rtl.css 279 B
build/block-library/blocks/paragraph/style.css 281 B
build/block-library/blocks/post-author/style-rtl.css 175 B
build/block-library/blocks/post-author/style.css 176 B
build/block-library/blocks/post-comments-form/editor-rtl.css 96 B
build/block-library/blocks/post-comments-form/editor.css 96 B
build/block-library/blocks/post-comments-form/style-rtl.css 501 B
build/block-library/blocks/post-comments-form/style.css 501 B
build/block-library/blocks/post-date/style-rtl.css 61 B
build/block-library/blocks/post-date/style.css 61 B
build/block-library/blocks/post-excerpt/editor-rtl.css 71 B
build/block-library/blocks/post-excerpt/editor.css 71 B
build/block-library/blocks/post-excerpt/style-rtl.css 141 B
build/block-library/blocks/post-excerpt/style.css 141 B
build/block-library/blocks/post-featured-image/editor-rtl.css 588 B
build/block-library/blocks/post-featured-image/editor.css 586 B
build/block-library/blocks/post-featured-image/style-rtl.css 322 B
build/block-library/blocks/post-featured-image/style.css 322 B
build/block-library/blocks/post-navigation-link/style-rtl.css 153 B
build/block-library/blocks/post-navigation-link/style.css 153 B
build/block-library/blocks/post-template/editor-rtl.css 99 B
build/block-library/blocks/post-template/editor.css 98 B
build/block-library/blocks/post-template/style-rtl.css 281 B
build/block-library/blocks/post-template/style.css 281 B
build/block-library/blocks/post-terms/style-rtl.css 96 B
build/block-library/blocks/post-terms/style.css 96 B
build/block-library/blocks/post-time-to-read/style-rtl.css 69 B
build/block-library/blocks/post-time-to-read/style.css 69 B
build/block-library/blocks/post-title/style-rtl.css 100 B
build/block-library/blocks/post-title/style.css 100 B
build/block-library/blocks/preformatted/style-rtl.css 103 B
build/block-library/blocks/preformatted/style.css 103 B
build/block-library/blocks/pullquote/editor-rtl.css 135 B
build/block-library/blocks/pullquote/editor.css 135 B
build/block-library/blocks/pullquote/style-rtl.css 335 B
build/block-library/blocks/pullquote/style.css 335 B
build/block-library/blocks/pullquote/theme-rtl.css 167 B
build/block-library/blocks/pullquote/theme.css 167 B
build/block-library/blocks/query-pagination-numbers/editor-rtl.css 122 B
build/block-library/blocks/query-pagination-numbers/editor.css 121 B
build/block-library/blocks/query-pagination/editor-rtl.css 221 B
build/block-library/blocks/query-pagination/editor.css 211 B
build/block-library/blocks/query-pagination/style-rtl.css 288 B
build/block-library/blocks/query-pagination/style.css 284 B
build/block-library/blocks/query-title/style-rtl.css 63 B
build/block-library/blocks/query-title/style.css 63 B
build/block-library/blocks/query/editor-rtl.css 450 B
build/block-library/blocks/query/editor.css 449 B
build/block-library/blocks/quote/style-rtl.css 222 B
build/block-library/blocks/quote/style.css 222 B
build/block-library/blocks/quote/theme-rtl.css 223 B
build/block-library/blocks/quote/theme.css 226 B
build/block-library/blocks/read-more/style-rtl.css 132 B
build/block-library/blocks/read-more/style.css 132 B
build/block-library/blocks/rss/editor-rtl.css 149 B
build/block-library/blocks/rss/editor.css 149 B
build/block-library/blocks/rss/style-rtl.css 289 B
build/block-library/blocks/rss/style.css 288 B
build/block-library/blocks/search/editor-rtl.css 165 B
build/block-library/blocks/search/editor.css 165 B
build/block-library/blocks/search/style-rtl.css 408 B
build/block-library/blocks/search/style.css 406 B
build/block-library/blocks/search/theme-rtl.css 114 B
build/block-library/blocks/search/theme.css 114 B
build/block-library/blocks/separator/editor-rtl.css 146 B
build/block-library/blocks/separator/editor.css 146 B
build/block-library/blocks/separator/style-rtl.css 234 B
build/block-library/blocks/separator/style.css 234 B
build/block-library/blocks/separator/theme-rtl.css 194 B
build/block-library/blocks/separator/theme.css 194 B
build/block-library/blocks/shortcode/editor-rtl.css 329 B
build/block-library/blocks/shortcode/editor.css 329 B
build/block-library/blocks/site-logo/editor-rtl.css 756 B
build/block-library/blocks/site-logo/editor.css 756 B
build/block-library/blocks/site-logo/style-rtl.css 203 B
build/block-library/blocks/site-logo/style.css 203 B
build/block-library/blocks/site-tagline/editor-rtl.css 86 B
build/block-library/blocks/site-tagline/editor.css 86 B
build/block-library/blocks/site-title/editor-rtl.css 116 B
build/block-library/blocks/site-title/editor.css 116 B
build/block-library/blocks/site-title/style-rtl.css 57 B
build/block-library/blocks/site-title/style.css 57 B
build/block-library/blocks/social-link/editor-rtl.css 184 B
build/block-library/blocks/social-link/editor.css 184 B
build/block-library/blocks/social-links/editor-rtl.css 674 B
build/block-library/blocks/social-links/editor.css 673 B
build/block-library/blocks/social-links/style-rtl.css 1.4 kB
build/block-library/blocks/social-links/style.css 1.39 kB
build/block-library/blocks/spacer/editor-rtl.css 359 B
build/block-library/blocks/spacer/editor.css 359 B
build/block-library/blocks/spacer/style-rtl.css 48 B
build/block-library/blocks/spacer/style.css 48 B
build/block-library/blocks/table/editor-rtl.css 433 B
build/block-library/blocks/table/editor.css 433 B
build/block-library/blocks/table/style-rtl.css 651 B
build/block-library/blocks/table/style.css 650 B
build/block-library/blocks/table/theme-rtl.css 157 B
build/block-library/blocks/table/theme.css 157 B
build/block-library/blocks/tag-cloud/style-rtl.css 251 B
build/block-library/blocks/tag-cloud/style.css 253 B
build/block-library/blocks/template-part/editor-rtl.css 403 B
build/block-library/blocks/template-part/editor.css 403 B
build/block-library/blocks/template-part/theme-rtl.css 101 B
build/block-library/blocks/template-part/theme.css 101 B
build/block-library/blocks/text-columns/editor-rtl.css 95 B
build/block-library/blocks/text-columns/editor.css 95 B
build/block-library/blocks/text-columns/style-rtl.css 166 B
build/block-library/blocks/text-columns/style.css 166 B
build/block-library/blocks/verse/style-rtl.css 99 B
build/block-library/blocks/verse/style.css 99 B
build/block-library/blocks/video/editor-rtl.css 552 B
build/block-library/blocks/video/editor.css 555 B
build/block-library/blocks/video/style-rtl.css 179 B
build/block-library/blocks/video/style.css 179 B
build/block-library/blocks/video/theme-rtl.css 139 B
build/block-library/blocks/video/theme.css 139 B
build/block-library/classic-rtl.css 179 B
build/block-library/classic.css 179 B
build/block-library/common-rtl.css 1.12 kB
build/block-library/common.css 1.12 kB
build/block-library/editor-elements-rtl.css 75 B
build/block-library/editor-elements.css 75 B
build/block-library/editor-rtl.css 11.8 kB
build/block-library/editor.css 11.8 kB
build/block-library/elements-rtl.css 54 B
build/block-library/elements.css 54 B
build/block-library/reset-rtl.css 478 B
build/block-library/reset.css 478 B
build/block-library/style-rtl.css 12.8 kB
build/block-library/style.css 12.8 kB
build/block-library/theme-rtl.css 698 B
build/block-library/theme.css 703 B
build/block-serialization-default-parser/index.min.js 1.13 kB
build/block-serialization-spec-parser/index.min.js 2.83 kB
build/blocks/index.min.js 51.1 kB
build/commands/index.min.js 14.8 kB
build/commands/style-rtl.css 789 B
build/commands/style.css 786 B
build/components/index.min.js 210 kB
build/components/style-rtl.css 11.8 kB
build/components/style.css 11.8 kB
build/compose/index.min.js 12.4 kB
build/core-data/index.min.js 16.3 kB
build/customize-widgets/index.min.js 12.2 kB
build/customize-widgets/style-rtl.css 1.41 kB
build/customize-widgets/style.css 1.41 kB
build/data-controls/index.min.js 718 B
build/date/index.min.js 40.4 kB
build/deprecated/index.min.js 518 B
build/dom-ready/index.min.js 336 B
build/dom/index.min.js 4.76 kB
build/edit-post/classic-rtl.css 571 B
build/edit-post/classic.css 571 B
build/edit-post/index.min.js 35.2 kB
build/edit-post/style-rtl.css 7.84 kB
build/edit-post/style.css 7.83 kB
build/edit-site/index.min.js 64.8 kB
build/edit-site/style-rtl.css 10.2 kB
build/edit-site/style.css 10.2 kB
build/edit-widgets/index.min.js 17.3 kB
build/edit-widgets/style-rtl.css 4.56 kB
build/edit-widgets/style.css 4.56 kB
build/editor/index.min.js 45.9 kB
build/editor/style-rtl.css 3.49 kB
build/editor/style.css 3.48 kB
build/element/index.min.js 4.95 kB
build/escape-html/index.min.js 548 B
build/format-library/index.min.js 7.26 kB
build/format-library/style-rtl.css 557 B
build/format-library/style.css 556 B
build/hooks/index.min.js 1.66 kB
build/html-entities/index.min.js 454 B
build/i18n/index.min.js 3.79 kB
build/is-shallow-equal/index.min.js 535 B
build/keyboard-shortcuts/index.min.js 1.79 kB
build/keycodes/index.min.js 1.94 kB
build/list-reusable-blocks/index.min.js 2.14 kB
build/list-reusable-blocks/style-rtl.css 865 B
build/list-reusable-blocks/style.css 865 B
build/media-utils/index.min.js 2.99 kB
build/notices/index.min.js 977 B
build/plugins/index.min.js 1.94 kB
build/preferences-persistence/index.min.js 2.23 kB
build/preferences/index.min.js 1.35 kB
build/primitives/index.min.js 960 B
build/priority-queue/index.min.js 1.52 kB
build/private-apis/index.min.js 942 B
build/react-i18n/index.min.js 702 B
build/react-refresh-entry/index.min.js 8.44 kB
build/react-refresh-runtime/index.min.js 7.31 kB
build/redux-routine/index.min.js 2.75 kB
build/reusable-blocks/index.min.js 2.26 kB
build/reusable-blocks/style-rtl.css 265 B
build/reusable-blocks/style.css 265 B
build/rich-text/index.min.js 11.1 kB
build/server-side-render/index.min.js 2.09 kB
build/shortcode/index.min.js 1.52 kB
build/style-engine/index.min.js 1.55 kB
build/token-list/index.min.js 650 B
build/url/index.min.js 3.74 kB
build/vendors/inert-polyfill.min.js 2.48 kB
build/vendors/react-dom.min.js 41.8 kB
build/vendors/react.min.js 4.02 kB
build/viewport/index.min.js 1.09 kB
build/warning/index.min.js 280 B
build/widgets/index.min.js 7.3 kB
build/widgets/style-rtl.css 1.18 kB
build/widgets/style.css 1.18 kB
build/wordcount/index.min.js 1.06 kB

compressed-size-action

@noisysocks noisysocks self-assigned this Apr 26, 2023
@github-actions
Copy link

Flaky tests detected in 4fc3d10.
Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/4805724939
📝 Reported issues:

@fabiankaegy
Copy link
Member

Thank you for working on this :) I can see this also being a great API to eventually expose the template in the post editor similar to the site editor. (#27847)

@youknowriad
Copy link
Contributor

So if I'm understanding properly the long term goal of this PR, the idea is to be able to edit the post separately from the template while still rendered within the template.

It seems that you arrive to the conclusion that the locking needed for that use-case is the same that we already have to "lock" patterns (containers). Personally, I'm still wrapping my head around this assumption. Can you explain more why it's the same thing for you?

@noisysocks
Copy link
Member Author

noisysocks commented Apr 28, 2023

Yes absolutely @youknowriad!

The goal of #49980 is to improve the UX of editing page content within the site editor. You can already do this today but it's overwhelming to many users (especially new ones) because it requires knowing which blocks are a part of the template versus which blocks are a part of the page. This results in e.g. accidentally making changes to the entire site when the user just wanted to modify one page. The hope is that by locking the template blocks it will be less overwhelming.

The goal of this PR is to add locking functionality to BlockEditor that enables #49980. Note that BlockEditor is a generic package that works with a list of blocks. It doesn't know what a "template" or "page" is. Therefore our locking mechanism must be implemented in generic terms. We want to add functionality that allows a consumer of BlockEditor to lock "non-content" and make it so that only "content" is editable.

So our requirements for the locking mechanism are:

  1. Consumer can put BlockEditor into a "content only" mode.
  2. Consumer can designate particular blocks as "content".
  3. When in "content only mode", BlockEditor prevents selection and editing of non-content blocks.
  4. When in "content only mode", blocks hide non relevant functionality e.g. the Align button in BlockToolbar.

It turns out that the existing templateLock: 'contentOnly' mechanism that we have for block patterns accomplishes a lot of this already:

  1. Consumer can put BlockEditor into a "content only" mode.
    Partially. You can use 'contentOnly' to put a block into a "content only" mode, but not the whole editor. Setting templateLock: 'contentOnly' in editor settings is permitted but causes buggy behaviour.
  2. Consumer can designate particular blocks as "content".
    No. Only blocks with an attribute containing role: 'content' are treated as content.
  3. When in "content only mode", BlockEditor prevents selection and editing of non-content blocks.
    Yes, via pointer-events.
  4. When in "content only mode", blocks hide non relevant functionality e.g. the Align button in BlockToolbar.
    Yes, via individual blocks checking if there is a content lock (example).

We can address (1) by fixing the buggy behaviour and we can address (2) by adding an explicit way for BlockEditor consumers to denote which blocks are "content" e.g. a new contentBlockTypes setting. That is what this PR does.

I favour this approach because:

  • It doesn't require a lot of new APIs. We can reuse the existing templateLock API. This means less documentation, education, backwards compatibility concerns, etc.
  • It doesn't require blocks to do any more work in addition to what they already do to hide controls in response to a template lock. (Admittedly this needs to be better documented, and perhaps the API could be improved.)
  • Content locked patterns are a fairly niche feature that probably don't get a lot of testing. By consolidating it with this new functionality, we increase the likelihood that bugs will be discovered. Improving how content locking works within the site editor will also improve how content locking works within patterns, and vice versa.

The one thing I am not so keen on is the new contentBlockTypes setting. It feels a little clunky and potentially not flexible enough. Open to alternative ideas. Maybe block.json should support having role: 'content' as an attribute, or maybe the BlockEditor consumer should explicitly state which blocks to lock/unlock e.g. wp.blockEditor.lockEditing( [ clientId, clientId ] ).

I'll cut myself off here 😀 Let me know what you like, don't like, and if you have suggestions.

@talldan
Copy link
Contributor

talldan commented Apr 28, 2023

The one thing I am not so keen on is the new contentBlockTypes setting. It feels a little clunky and potentially not flexible enough. Open to alternative ideas. Maybe block.json should support having role: 'content' as an attribute, or maybe the BlockEditor consumer should explicitly state which blocks to lock/unlock e.g. wp.blockEditor.lockEditing( [ clientId, clientId ] ).

This was also the thing that stood out to me when reading the PR description. I'm also not sure about extending role: content even more, as it's still unclear to me if it was the right solution to making content editable in contentOnly mode.

Another alternative is that core/post-content has templateLock: false. That's typically the way that implementors achieve partially locked templates today, and it means that inner content can be unlocked on a per block instance basis instead of a per block type basis.

@noisysocks
Copy link
Member Author

Another alternative is that core/post-content has templateLock: false.

On the InnerBlocks component within the block or in the block's attributes?

The problem with the former is it doesn't work for Post Title and Post Featured Image which don't use InnerBlocks.

The problem with the latter is that it creates an undo level and marks the template as having unsaved changes. We would need a way to set templateLock on a block without modifying its attributes. Not against having a setTemplateLock action that allows BlockEditor consumers to override whatever is in the block list settings or attributes. WDYT?

@talldan
Copy link
Contributor

talldan commented Apr 28, 2023

Something I'd like to clarify, is the goal for post content to be completely editable (add/remove/modify blocks?), or should it still be content locked in some way?

The problem with the former is it doesn't work for Post Title and Post Featured Image

Yeah, this is an issue that has come up before with those blocks, and one of my concerns about role: content. Or perhaps I misunderstand how it's intended to work.

It feels like two different problems to me. One is that contentOnly doesn't allow inner parts to be unlocked like other template lock modes do. The other is that it's a little hazy how role: content is supposed to work for some block types (those that store content in entities).

@noisysocks
Copy link
Member Author

is the goal for post content to be completely editable (add/remove/modify blocks?)

Yes.

@talldan
Copy link
Contributor

talldan commented Apr 28, 2023

Not against having a setTemplateLock action that allows BlockEditor consumers to override whatever is in the block list settings or attributes. WDYT?

I suppose it depends really. If it's the editor initiating a mode, then it probably shouldn't be saved to block attributes, else you get issues like #49048.

There is already an updateBlockListSettings action, which I think can update templateLock.

@noisysocks
Copy link
Member Author

There is already an updateBlockListSettings action, which I think can update templateLock.

This action is unfortunately only really an InnerBlocks implementation detail. It's how the props passed to InnerBlocks end up in the block-editor store. Whatever we call it will get clobbered the next time the InnerBlocks component updates.

https://github.com/WordPress/gutenberg/blob/trunk/packages/block-editor/src/components/inner-blocks/use-nested-settings-update.js

@talldan
Copy link
Contributor

talldan commented Apr 28, 2023

Whatever we call it will get clobbered the next time the InnerBlocks component updates.

That's a shame, but it also makes sense now you say it. 😄

I guess you need another way.

@youknowriad
Copy link
Contributor

Just to be clear, I actually like the fact that this reuses an existing API instead of inventing one. I'm just trying to make sure we're not breaking the API or that the API is actually meant for that.

We want to add functionality that allows a consumer of BlockEditor to lock "non-content" and make it so that only "content" is editable.

I guess my first question here was that: are we talking about the same "content"? In other words, what does "content" really mean?

  • In the context of a block attribute (the behavior we have for patterns), it is clear to me what content means, it's all the block attributes that are not meant for "style or layout". So actual images, videos, text but nothing that relates to design/colors/layout.
  • In the context of the current PR, it's less clear. What does "a content block" mean?
    • Why is Post Featured Image a content block and not Cover Image knowing that Cover image can be used within post content so (part of the content).

I guess I'm looking at a clear definition of "content": content attributes (we have) and content blocks (less clear to me)

When in "content only mode", BlockEditor prevents selection and editing of non-content blocks.
Yes, via pointer-events.

Did you consider useDisabled (and potentially merging with the behavior we already have in useBlockProps to disable "inner blocks" in some cases. (overlay). I think useDisabled is better than pointer events in the sense that it actually disables semantically (inert HTML attribute).

When in "content only mode", blocks hide non relevant functionality e.g. the Align button in BlockToolbar.
Yes, via individual blocks checking if there is a content lock (example).

When the whole editor is "content only", does it mean all blocks are in "content only", or all blocks but the content blocks. If the "content blocks" reset the template lock for their children, does this behavior has any impact on locked patterns?

@noisysocks
Copy link
Member Author

Just to be clear, I actually like the fact that this reuses an existing API instead of inventing one. I'm just trying to make sure we're not breaking the API or that the API is actually meant for that.

👍 absolutely.

I guess I'm looking at a clear definition of "content": content attributes (we have) and content blocks (less clear to me)

"Content block" within the context of this PR refers to a block that is not affected by a templateLock set to 'contentOnly'. These blocks are editable and appear in the sidebar navigation when a locked block is selected. By default a content block is any block with an attribute that has role: 'content'. If contentBlockTypes is specified then that is used instead.

Did you consider useDisabled (and potentially merging with the behavior we already have in useBlockProps to disable "inner blocks" in some cases. (overlay). I think useDisabled is better than pointer events in the sense that it actually disables semantically (inert HTML attribute).

I'll double check but I think we may already get this for free because when there is a templateLock, useBlockProps will add a block overlay and use useDisabled. Good flag though. I'll see if it's possible. It might not be because we technically don't want to disable the entire container e.g. you need to be able to click into deeply nested content.

When the whole editor is "content only", does it mean all blocks are in "content only", or all blocks but the content blocks. If the "content blocks" reset the template lock for their children, does this behavior has any impact on locked patterns?

The latter. The toolbar buttons etc. are hidden if the block is "content locked". A block that is a descendent of a "content block" cannot be "content locked".

I've tested locked patterns and all is fine, but admittedly I haven't tested putting a locked pattern inside a content locked locked editor which probably has issues to do with contentBlockTypes being global.

@youknowriad
Copy link
Contributor

By default a content block is any block with an attribute that has role: 'content'. If contentBlockTypes is specified then that is used instead.

If I follow this definition, it means I should be able to edit the content of a paragraph within a template even if contentOnly mode because the paragraph block has an attribute with role "content". I'm assuming that's not the case and we basically have two definition of "content blocks"

  • blocks with content attributes
  • blocks that are marked as "content" (post content, post feature image)

maybe I'm wrong though?

I haven't tested putting a locked pattern inside a content locked locked editor which probably has issues to do with contentBlockTypes being global.

I haven't tested either but it feels that the behavior of a "locked pattern" that I insert within post content, shouldn't be impacted by the editor being in "contentOnly" mode.

@noisysocks
Copy link
Member Author

noisysocks commented May 1, 2023

I'm assuming that's not the case and we basically have two definition of "content blocks"

Yes you have it right. If settings.contentBlockTypes is provided then the default behaviour of treating a block as a content block if it contains an attribute with role: 'content' is completely disabled. Otherwise you'd be able to e.g. edit the paragraph block in the site footer.

https://github.com/WordPress/gutenberg/pull/50082/files#diff-23e851c3077ed95d23bb1669da8bafbae3f1e2e952897987e45b49555004dd83R105-R109

I haven't tested either but it feels that the behavior of a "locked pattern" that I insert within post content, shouldn't be impacted by the editor being in "contentOnly" mode.

Yeah. It should be possible to insert a locked pattern into the post content, but this is probably broken. I am convinced now that settings.contentBlockTypes is definitely not a good approach 😀

@noisysocks
Copy link
Member Author

I guess the two directions I can take this are:

  1. Continue using templateLock = 'contentOnly', but come up with an alternative way to denote that Post Title and Post Featured Image are "content" that doesn't require the clunky settings.contentBlockTypes array and that doesn't require confusing definitions of what a "content block" is.

    Perhaps role: 'content' in the block.json—not sure.

  2. Ditch the 'contentOnly' approach and try something more like what @talldan suggests in Add ability to set templateLock = 'contentOnly' in editor settings #50082 (comment) where we put a lock on the root and override this lock on the blocks that we want to be edible.

    Maybe we introduce a new templateLock that disables absolutely all editing (templateLock = 'static') and then put "lock": { "edit": false } (ref) on Post Title, Post Featured Image, etc. This could also be useful to pattern authors who want more precise control over what is editable than what 'contentOnly' provides.

Wdyt?

@youknowriad
Copy link
Contributor

I'm starting to feel like "contentOnly" locking is something else and that we're stretching that concept a bit too much here. What if instead of "locking" specific parts of the editor, we think about this problem in the opposite direction: we want to "enable" specific parts of the editor.

  • Can't we have a way to lock everything?
  • Some blocks need read a config (context or something else), and enable some parts of the block itself (even if the editor is locked). The "enabled part of the block" is actually dependent on the block itself and not something that is "normalized".

So what about something like that:

1- block-editor exposes a <LockBlocksProvider> and a way to consume that context
2- The block editor UI (toolbar, moving, selecting...) is all disabled when that context is true.
3- specific core blocks (only core blocks here) can consume that context and decide to do something with it:
- The post content block can decided to override it by wrapping its inner blocks with a new LockBlocksProvider (false)
- The post title block can decide to allow editing the title even LockBlocksProvider is false (this is the part that I'm unsure how to solve technically)

Pros of this approach: No impact on third-party blocks, no new public APIs
Downside: Is it even possible to implement it (specially the bart in bold)

@youknowriad
Copy link
Contributor

I guess this is very close to @talldan's proposal as well. (but I don't see this as "template locking" personally, it's more "disable editing entirely" thing.

@noisysocks
Copy link
Member Author

Something that appeals to me about re-using templateLock is that block authors don't have to implement code that hides toolbar buttons etc. twice: once for when their block is used in a locked pattern, and again for when their block is used in the locked site editor. I guess it's probably not a practical concern though since this feature possibly will never expand beyond the core "Post–" blocks. (Especially if it's a private API.)

I like your idea, I'll try it out tomorrow. The "Post Title can decide to allow editing anyway" problem can maybe be solved by having useBlockProps pass down a function via context that the block calls. The thing I'm not sure about is if the block-editor store needs to know what is editable. Would maybe need to do something like updateBlockListSettings and useBlockSync where data is transferred from the component tree to the store.

Thanks for your help @youknowriad!

@youknowriad
Copy link
Contributor

youknowriad commented May 1, 2023

Something that appeals to me about re-using templateLock is that block authors don't have to implement code that hides toolbar buttons etc. twice: once for when their block is used in a locked pattern, and again for when their block is used in the locked site editor. I guess it's probably not a practical concern though since this feature possibly will never expand beyond the core "Post–" blocks. (Especially if it's a private API.)

Indeed, I guess we need to figure out whether third-party blocks are meant to implement this or not.

@noisysocks
Copy link
Member Author

noisysocks commented May 3, 2023

I started playing with the idea of using context in this branch if you want to take a look: trunk...try/locking-v2

I don't think we can use useDisabled() / Disabled / inert because doing this completely disables the element and in this case we need to be able to click into nested blocks that are still editable e.g. Post Title, Post Content.

I haven't yet figured out how to handle hiding the parent block selector, block movers, block toolbar buttons, in-between inserter, etc. It's tricky because these components live outside of the canvas and so don't have access to the context. Will keep fiddling.

Something else I want to explore is if we can make templateLock = 'contentOnly' use DisableBlockEditing under the hood to reduce the amount of duplicated code / concepts.

@talldan
Copy link
Contributor

talldan commented May 3, 2023

I guess it's probably not a practical concern though since this feature possibly will never expand beyond the core "Post–" blocks. (Especially if it's a private API.)

There might be a situation where a user also wants to edit Site Logo / Site Title in content only mode.

It's been identified that patterns could use content only mode (see 'The wp:pattern block'), and they are useful site building blocks (particularly headers and footers).

If those two things co-exist then potentially a user will want to upload a site logo once they've chosen a header pattern and not have that block completely locked down when content only mode is active.

There's still a long way to go in exploring these things, but just saying there could be some overlap with what you're looking at with 'post' blocks.

@youknowriad
Copy link
Contributor

If those two things co-exist then potentially a user will want to upload a site logo once they've chosen a header pattern and not have that block completely locked down when content only mode is active.

I'm not clear why the user should be able to do these things in "content only" mode? Maybe it's the name "content only" that is confusing, but for me what we're trying to do here is not "content only mode" but "entity only mode" or something (editing a post vs editing everything). Now yeah, there's a question about blocks used within templates and that store things outside the templates (site logo, site title, navigation block, reusable block). What should we do about these? It's unclear to me personally and I'd love some thoughts from @jameskoster and @SaxonF but my instinct is to say that if the blocks are within the template prevent editing them, if they are within the post content block, allow editing them.

But I agree that we need clear rules and stick by them.

@jameskoster
Copy link
Contributor

Perhaps it's helpful to remind about the scenario where a user should encounter this 'mode'.

In the site editor pathways are emerging that enable users to edit their pages. In such flows it's currently way too easy to mistakenly add blocks to the template, believing you're editing a page.

So it becomes important for us to prioritise the direct manipulation of any data associated with the page, and de-prioritise everything else.

Generally speaking that means we want the templateLock:contentOnly experience, where blocks like Post Title, Post Content, Post Excerpt, Post Featured Image, and Post Terms are treated as 'content'.

In this sense I'd agree that "entity only" might be a better way to describe it. To begin with we'll need to support single posts and pages as entity sources, but it's also possible that the entity could be something like a post category.

@noisysocks
Copy link
Member Author

Will close this out. I've a new approach in #50643.

@noisysocks noisysocks closed this May 16, 2023
@noisysocks noisysocks added the [Feature] Page Content Focus Ability to toggle between focusing on editing the page and editing the template in the site editor. label Jun 25, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Block Locking The API allowing for the ability to lock/unlock blocks [Feature] Page Content Focus Ability to toggle between focusing on editing the page and editing the template in the site editor. Needs Dev Note Requires a developer note for a major WordPress release cycle [Package] Block editor /packages/block-editor [Type] Enhancement A suggestion for improvement.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants