Skip to content

Commit 0f04bdf

Browse files
ramonjdMamadukatalldan
authored andcommitted
Template parts: make 'Detach' context menu item consistent across patterns and template parts (#77581)
Co-authored-by: ramonjd <[email protected]> Co-authored-by: Mamaduka <[email protected]> Co-authored-by: talldan <[email protected]>
1 parent c358891 commit 0f04bdf

5 files changed

Lines changed: 94 additions & 37 deletions

File tree

packages/editor/src/components/template-part-menu-items/convert-to-regular.js

Lines changed: 74 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,30 +3,92 @@
33
*/
44
import { useSelect, useDispatch } from '@wordpress/data';
55
import { store as blockEditorStore } from '@wordpress/block-editor';
6-
import { MenuItem } from '@wordpress/components';
7-
import { __ } from '@wordpress/i18n';
6+
import { store as coreStore } from '@wordpress/core-data';
7+
import {
8+
MenuItem,
9+
__experimentalConfirmDialog as ConfirmDialog,
10+
} from '@wordpress/components';
11+
import { __, sprintf } from '@wordpress/i18n';
12+
import { decodeEntities } from '@wordpress/html-entities';
13+
import { useState } from '@wordpress/element';
814

915
export default function ConvertToRegularBlocks( { clientId, onClose } ) {
16+
const [ showConfirmDialog, setShowConfirmDialog ] = useState( false );
17+
1018
const { getBlocks } = useSelect( blockEditorStore );
1119
const { replaceBlocks } = useDispatch( blockEditorStore );
1220

13-
const canRemove = useSelect(
14-
( select ) => select( blockEditorStore ).canRemoveBlock( clientId ),
21+
const { canRemove, templatePartTitle } = useSelect(
22+
( select ) => {
23+
const { canRemoveBlock, getBlock } = select( blockEditorStore );
24+
const { getEntityRecord, getCurrentTheme } = select( coreStore );
25+
26+
const block = getBlock( clientId );
27+
const { slug, theme } = block?.attributes ?? {};
28+
const themeSlug = theme || getCurrentTheme()?.stylesheet;
29+
const templatePartId =
30+
themeSlug && slug ? `${ themeSlug }//${ slug }` : null;
31+
const entity = templatePartId
32+
? getEntityRecord(
33+
'postType',
34+
'wp_template_part',
35+
templatePartId
36+
)
37+
: null;
38+
39+
return {
40+
canRemove: canRemoveBlock( clientId ),
41+
templatePartTitle: entity?.title?.rendered
42+
? decodeEntities( entity.title.rendered )
43+
: null,
44+
};
45+
},
1546
[ clientId ]
1647
);
1748

1849
if ( ! canRemove ) {
1950
return null;
2051
}
2152

53+
const title = templatePartTitle
54+
? sprintf(
55+
/* translators: %s: template part title, e.g. "Header" */
56+
__( 'Detach %s?' ),
57+
templatePartTitle
58+
)
59+
: __( 'Detach template part?' );
60+
61+
const message = templatePartTitle
62+
? sprintf(
63+
/* translators: %s: template part title, e.g. "Header" */
64+
__(
65+
'The blocks will be separated from the original template part and will be fully editable. Future changes to the %s template part will not apply here.'
66+
),
67+
templatePartTitle
68+
)
69+
: __(
70+
'The blocks will be separated from the original template part and will be fully editable. Future changes to the template part will not apply here.'
71+
);
72+
2273
return (
23-
<MenuItem
24-
onClick={ () => {
25-
replaceBlocks( clientId, getBlocks( clientId ) );
26-
onClose();
27-
} }
28-
>
29-
{ __( 'Detach' ) }
30-
</MenuItem>
74+
<>
75+
<MenuItem onClick={ () => setShowConfirmDialog( true ) }>
76+
{ __( 'Detach' ) }
77+
</MenuItem>
78+
<ConfirmDialog
79+
isOpen={ showConfirmDialog }
80+
onConfirm={ () => {
81+
replaceBlocks( clientId, getBlocks( clientId ) );
82+
onClose();
83+
} }
84+
onCancel={ () => setShowConfirmDialog( false ) }
85+
confirmButtonText={ __( 'Detach' ) }
86+
size="medium"
87+
title={ title }
88+
__experimentalHideHeader={ false }
89+
>
90+
{ message }
91+
</ConfirmDialog>
92+
</>
3193
);
3294
}

packages/patterns/src/components/patterns-manage-button.js

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -112,25 +112,15 @@ function PatternsManageButton( { clientId, onClose } ) {
112112
{ canDetach && (
113113
<>
114114
<MenuItem onClick={ () => setShowConfirmDialog( true ) }>
115-
{ isSyncedPattern
116-
? __( 'Disconnect pattern' )
117-
: __( 'Detach pattern' ) }
115+
{ __( 'Detach' ) }
118116
</MenuItem>
119117
<ConfirmDialog
120118
isOpen={ showConfirmDialog }
121119
onConfirm={ handleDetach }
122120
onCancel={ () => setShowConfirmDialog( false ) }
123-
confirmButtonText={
124-
isSyncedPattern
125-
? __( 'Disconnect' )
126-
: __( 'Detach' )
127-
}
121+
confirmButtonText={ __( 'Detach' ) }
128122
size="medium"
129-
title={
130-
isSyncedPattern
131-
? __( 'Disconnect pattern?' )
132-
: __( 'Detach pattern?' )
133-
}
123+
title={ __( 'Detach pattern?' ) }
134124
__experimentalHideHeader={ false }
135125
>
136126
{ isSyncedPattern

test/e2e/specs/editor/various/pattern-overrides.spec.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -698,10 +698,10 @@ test.describe( 'Pattern Overrides', () => {
698698
editor.canvas.getByRole( 'document', { name: 'Block: Pattern' } )
699699
);
700700
await editor.showBlockToolbar();
701-
await editor.clickBlockOptionsMenuItem( 'Disconnect pattern' );
701+
await editor.clickBlockOptionsMenuItem( 'Detach' );
702702
await page
703703
.getByRole( 'dialog' )
704-
.getByRole( 'button', { name: 'Disconnect' } )
704+
.getByRole( 'button', { name: 'Detach' } )
705705
.click();
706706

707707
// Check that the overrides remain.
@@ -744,10 +744,10 @@ test.describe( 'Pattern Overrides', () => {
744744
editor.canvas.getByRole( 'document', { name: 'Block: Pattern' } )
745745
);
746746
await editor.showBlockToolbar();
747-
await editor.clickBlockOptionsMenuItem( 'Disconnect pattern' );
747+
await editor.clickBlockOptionsMenuItem( 'Detach' );
748748
await page
749749
.getByRole( 'dialog' )
750-
.getByRole( 'button', { name: 'Disconnect' } )
750+
.getByRole( 'button', { name: 'Detach' } )
751751
.click();
752752

753753
// Check that the overrides remain.

test/e2e/specs/editor/various/patterns.spec.js

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -479,8 +479,8 @@ test.describe( 'Unsynced pattern', () => {
479479
editor.canvas.getByRole( 'document', { name: 'Block: Paragraph' } )
480480
);
481481

482-
// Open the block options menu and click "Detach pattern".
483-
await editor.clickBlockOptionsMenuItem( 'Detach pattern' );
482+
// Open the block options menu and click "Detach".
483+
await editor.clickBlockOptionsMenuItem( 'Detach' );
484484
await page
485485
.getByRole( 'dialog' )
486486
.getByRole( 'button', { name: 'Detach' } )
@@ -838,10 +838,10 @@ test.describe( 'Synced pattern', () => {
838838
await editor.selectBlocks(
839839
editor.canvas.getByRole( 'document', { name: 'Block: Pattern' } )
840840
);
841-
await editor.clickBlockOptionsMenuItem( 'Disconnect pattern' );
841+
await editor.clickBlockOptionsMenuItem( 'Detach' );
842842
await page
843843
.getByRole( 'dialog' )
844-
.getByRole( 'button', { name: 'Disconnect' } )
844+
.getByRole( 'button', { name: 'Detach' } )
845845
.click();
846846

847847
await expect.poll( editor.getBlocks ).toMatchObject( [
@@ -878,10 +878,10 @@ test.describe( 'Synced pattern', () => {
878878
await editor.selectBlocks(
879879
editor.canvas.getByRole( 'document', { name: 'Block: Pattern' } )
880880
);
881-
await editor.clickBlockOptionsMenuItem( 'Disconnect pattern' );
881+
await editor.clickBlockOptionsMenuItem( 'Detach' );
882882
await page
883883
.getByRole( 'dialog' )
884-
.getByRole( 'button', { name: 'Disconnect' } )
884+
.getByRole( 'button', { name: 'Detach' } )
885885
.click();
886886

887887
await expect.poll( editor.getBlocks ).toMatchObject( [
@@ -984,10 +984,10 @@ test.describe( 'Synced pattern', () => {
984984
await editor.selectBlocks(
985985
editor.canvas.getByRole( 'document', { name: 'Block: Pattern' } )
986986
);
987-
await editor.clickBlockOptionsMenuItem( 'Disconnect pattern' );
987+
await editor.clickBlockOptionsMenuItem( 'Detach' );
988988
await page
989989
.getByRole( 'dialog' )
990-
.getByRole( 'button', { name: 'Disconnect' } )
990+
.getByRole( 'button', { name: 'Detach' } )
991991
.click();
992992

993993
await expect.poll( editor.getBlocks ).toMatchObject( [

test/e2e/specs/site-editor/template-part.spec.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ test.describe( 'Template Part', () => {
176176
test( 'can detach blocks from a template part', async ( {
177177
admin,
178178
editor,
179+
page,
179180
} ) => {
180181
const paragraphText = 'Test 3';
181182

@@ -210,6 +211,10 @@ test.describe( 'Template Part', () => {
210211
// Detach the paragraph from the header template part.
211212
await editor.selectBlocks( templatePartWithParagraph );
212213
await editor.clickBlockOptionsMenuItem( 'Detach' );
214+
await page
215+
.getByRole( 'dialog' )
216+
.getByRole( 'button', { name: 'Detach' } )
217+
.click();
213218

214219
// There should be a paragraph but no header template part.
215220
await expect( paragraph ).toBeVisible();

0 commit comments

Comments
 (0)