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

Use a modal for the reusable blocks creation flow #29040

Merged
merged 6 commits into from
Feb 18, 2021
Merged
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
14 changes: 12 additions & 2 deletions lib/client-assets.php
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@ function gutenberg_register_packages_styles( $styles ) {
$styles,
'wp-editor',
gutenberg_url( 'build/editor/style.css' ),
array( 'wp-components', 'wp-block-editor', 'wp-nux' ),
array( 'wp-components', 'wp-block-editor', 'wp-nux', 'wp-reusable-blocks' ),
filemtime( gutenberg_dir_path() . 'build/editor/style.css' )
);
$styles->add_data( 'wp-editor', 'rtl', 'replace' );
Expand Down Expand Up @@ -375,6 +375,7 @@ function gutenberg_register_packages_styles( $styles ) {
'wp-components',
'wp-editor',
'wp-block-library',
'wp-reusable-blocks',
// Always include visual styles so the editor never appears broken.
'wp-block-library-theme',
),
Expand Down Expand Up @@ -431,7 +432,7 @@ function gutenberg_register_packages_styles( $styles ) {
$styles,
'wp-edit-widgets',
gutenberg_url( 'build/edit-widgets/style.css' ),
array( 'wp-components', 'wp-block-editor', 'wp-edit-blocks' ),
array( 'wp-components', 'wp-block-editor', 'wp-edit-blocks', 'wp-reusable-blocks' ),
filemtime( gutenberg_dir_path() . 'build/edit-widgets/style.css' )
);
$styles->add_data( 'wp-edit-widgets', 'rtl', 'replace' );
Expand All @@ -453,6 +454,15 @@ function gutenberg_register_packages_styles( $styles ) {
filemtime( gutenberg_dir_path() . 'build/customize-widgets/style.css' )
);
$styles->add_data( 'wp-customize-widgets', 'rtl', 'replace' );

gutenberg_override_style(
$styles,
'wp-reusable-blocks',
gutenberg_url( 'build/reusable-blocks/style.css' ),
array( 'wp-components' ),
filemtime( gutenberg_dir_path() . 'build/reusable-blocks/style.css' )
);
$styles->add_data( 'wp-reusable-block', 'rtl', 'replace' );
}
add_action( 'wp_default_styles', 'gutenberg_register_packages_styles' );

Expand Down
3 changes: 3 additions & 0 deletions packages/base-styles/_z-index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,9 @@ $z-layers: (
// #adminmenuwrap { z-index: 9990 }
".components-popover": 1000000,

// Should be above the popover (dropdown)
".reusable-blocks-menu-items__convert-modal": 1000001,

// ...Except for popovers immediately beneath wp-admin menu on large breakpoints
".components-popover.block-editor-inserter__popover": 99999,
".components-popover.table-of-contents__popover": 99998,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export function ReusableBlocksTab( { rootClientId, onInsert, onHover } ) {
post_type: 'wp_block',
} ) }
>
{ __( 'Manage all reusable blocks' ) }
{ __( 'Manage Reusable blocks' ) }
</a>
</div>
</>
Expand Down
2 changes: 1 addition & 1 deletion packages/block-library/src/block/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const { name } = metadata;
export { metadata, name };

export const settings = {
title: _x( 'Reusable Block', 'block title' ),
title: _x( 'Reusable block', 'block title' ),
description: __(
'Create and save content to reuse across your site. Update the block, and the changes apply everywhere it’s used.'
),
Expand Down
62 changes: 18 additions & 44 deletions packages/e2e-tests/specs/editor/various/reusable-blocks.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import {
} from '@wordpress/e2e-test-utils';

const reusableBlockNameInputSelector =
'.reusable-blocks-menu-items__convert-modal .components-text-control__input';
const reusableBlockInspectorNameInputSelector =
'.block-editor-block-inspector .components-text-control__input';

const saveAll = async () => {
Expand Down Expand Up @@ -49,31 +51,23 @@ const createReusableBlock = async ( content, title ) => {

await clickBlockToolbarButton( 'Options' );
await clickMenuItem( 'Add to Reusable blocks' );
const nameInput = await page.waitForSelector(
reusableBlockNameInputSelector
);
await nameInput.click();
await page.keyboard.type( title );
await page.keyboard.press( 'Enter' );

// Wait for creation to finish
await page.waitForXPath(
'//*[contains(@class, "components-snackbar")]/*[text()="Block created."]'
'//*[contains(@class, "components-snackbar")]/*[text()="Reusable block created."]'
);

// Check that we have a reusable block on the page
const block = await page.waitForSelector(
'.block-editor-block-list__block[data-type="core/block"]'
);
expect( block ).not.toBeNull();

await openDocumentSettingsSidebar();
const nameInput = await page.waitForSelector(
reusableBlockNameInputSelector
);
if ( title ) {
await nameInput.click();

// Select all of the text in the title field.
await pressKeyWithModifier( 'primary', 'a' );

// Give the reusable block a title
await page.keyboard.type( title );
}
};

describe( 'Reusable blocks', () => {
Expand All @@ -85,19 +79,8 @@ describe( 'Reusable blocks', () => {
await createNewPost();
} );

it( 'can be created with no title', async () => {
await createReusableBlock( 'Hello there!' );
await openDocumentSettingsSidebar();
const title = await page.$eval(
reusableBlockNameInputSelector,
( element ) => element.value
);
expect( title ).toBe( 'Untitled Reusable Block' );
} );

it( 'can be created, inserted, edited and converted to a regular block.', async () => {
await createReusableBlock( 'Hello there!', 'Greeting block' );
await saveAll();
await clearAllBlocks();

// Insert the reusable block we created above
Expand All @@ -106,7 +89,7 @@ describe( 'Reusable blocks', () => {
// Change the block's title
await openDocumentSettingsSidebar();
const nameInput = await page.waitForSelector(
reusableBlockNameInputSelector
reusableBlockInspectorNameInputSelector
);
await nameInput.click();
await pressKeyWithModifier( 'primary', 'a' );
Expand Down Expand Up @@ -157,9 +140,6 @@ describe( 'Reusable blocks', () => {
it( 'can be inserted after refresh', async () => {
await createReusableBlock( 'Awesome Paragraph', 'Awesome block' );

// Save the reusable block
await saveAll();

// Step 2. Create new post.
await createNewPost();

Expand All @@ -169,7 +149,7 @@ describe( 'Reusable blocks', () => {
// Check the title.
await openDocumentSettingsSidebar();
const title = await page.$eval(
reusableBlockNameInputSelector,
reusableBlockInspectorNameInputSelector,
( element ) => element.value
);
expect( title ).toBe( 'Awesome block' );
Expand All @@ -192,22 +172,18 @@ describe( 'Reusable blocks', () => {
await clickBlockToolbarButton( 'Options' );
await clickMenuItem( 'Add to Reusable blocks' );

// Wait for creation to finish
await page.waitForXPath(
'//*[contains(@class, "components-snackbar")]/*[text()="Block created."]'
);

// Set title.
await openDocumentSettingsSidebar();
// Set title
const nameInput = await page.waitForSelector(
reusableBlockNameInputSelector
);
await nameInput.click();
await pressKeyWithModifier( 'primary', 'a' );
await page.keyboard.type( 'Multi-selection reusable block' );
await page.keyboard.press( 'Enter' );

// Save the reusable block
await saveAll();
// Wait for creation to finish
await page.waitForXPath(
'//*[contains(@class, "components-snackbar")]/*[text()="Reusable block created."]'
);

await clearAllBlocks();

Expand All @@ -226,7 +202,6 @@ describe( 'Reusable blocks', () => {
'Awesome Paragraph',
'Random reusable block'
);
await saveAll();
await clearAllBlocks();
await insertReusableBlock( 'Random reusable block' );

Expand Down Expand Up @@ -260,7 +235,7 @@ describe( 'Reusable blocks', () => {
// Save the reusable block
await page.click( publishButtonSelector );
await page.waitForXPath(
'//*[contains(@class, "components-snackbar")]/*[text()="Reusable Block updated."]'
'//*[contains(@class, "components-snackbar")]/*[text()="Reusable block updated."]'
Copy link
Contributor

Choose a reason for hiding this comment

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

This breaks due to this: https://github.com/WordPress/gutenberg/blob/master/lib/compat.php#L266

Since we make blocks with a lower b, should we change the other Labels as well?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It seems there's an inconsistency between Core and Gutenberg. Core menus favor capitalizing everything and Gutenberg the opposite. This is one area where the same string can be used in two different places. The issue is that at some point the guideline here should be consistent between Core and Gutenberg but it's a broader issue.

);

await createNewPost();
Expand Down Expand Up @@ -293,7 +268,6 @@ describe( 'Reusable blocks', () => {
'Awesome Paragraph',
'Duplicated reusable block'
);
await saveAll();
await clearAllBlocks();
await insertReusableBlock( 'Duplicated reusable block' );
await insertReusableBlock( 'Duplicated reusable block' );
Expand Down
2 changes: 1 addition & 1 deletion packages/edit-post/src/plugins/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ registerPlugin( 'edit-post', {
post_type: 'wp_block',
} ) }
>
{ __( 'Manage all reusable blocks' ) }
{ __( 'Manage Reusable blocks' ) }
</MenuItem>
<KeyboardShortcutsHelpMenuItem
onSelect={ onClose }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ class ImportForm extends Component {
case 'Invalid JSON file':
uiMessage = __( 'Invalid JSON file' );
break;
case 'Invalid Reusable Block JSON file':
uiMessage = __( 'Invalid Reusable Block JSON file' );
case 'Invalid Reusable block JSON file':
uiMessage = __( 'Invalid Reusable block JSON file' );
break;
default:
uiMessage = __( 'Unknown error' );
Expand Down
2 changes: 1 addition & 1 deletion packages/list-reusable-blocks/src/utils/import.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ async function importReusableBlock( file ) {
! isString( parsedContent.title ) ||
! isString( parsedContent.content )
) {
throw new Error( 'Invalid Reusable Block JSON file' );
throw new Error( 'Invalid Reusable block JSON file' );
}
const postType = await apiFetch( { path: `/wp/v2/types/wp_block` } );
const reusableBlock = await apiFetch( {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,15 @@
*/
import { hasBlockSupport, isReusableBlock } from '@wordpress/blocks';
import { BlockSettingsMenuControls } from '@wordpress/block-editor';
import { useCallback } from '@wordpress/element';
import { MenuItem } from '@wordpress/components';
import { useCallback, useState } from '@wordpress/element';
import {
MenuItem,
Modal,
Button,
TextControl,
Flex,
FlexItem,
} from '@wordpress/components';
import { reusableBlock } from '@wordpress/icons';
import { useDispatch, useSelect } from '@wordpress/data';
import { __ } from '@wordpress/i18n';
Expand All @@ -27,6 +34,8 @@ export default function ReusableBlockConvertButton( {
clientIds,
rootClientId,
} ) {
const [ isModalOpen, setIsModalOpen ] = useState( false );
const [ title, setTitle ] = useState( '' );
const canConvert = useSelect(
( select ) => {
const { canUser } = select( 'core' );
Expand Down Expand Up @@ -76,10 +85,10 @@ export default function ReusableBlockConvertButton( {
noticesStore
);
const onConvert = useCallback(
async function () {
async function ( reusableBlockTitle ) {
try {
await convertBlocksToReusable( clientIds );
createSuccessNotice( __( 'Block created.' ), {
await convertBlocksToReusable( clientIds, reusableBlockTitle );
createSuccessNotice( __( 'Reusable block created.' ), {
type: 'snackbar',
} );
} catch ( error ) {
Expand All @@ -98,15 +107,61 @@ export default function ReusableBlockConvertButton( {
return (
<BlockSettingsMenuControls>
{ ( { onClose } ) => (
<MenuItem
icon={ reusableBlock }
onClick={ () => {
onConvert();
onClose();
} }
>
{ __( 'Add to Reusable blocks' ) }
</MenuItem>
<>
<MenuItem
icon={ reusableBlock }
onClick={ () => {
setIsModalOpen( true );
} }
>
{ __( 'Add to Reusable blocks' ) }
</MenuItem>
{ isModalOpen && (
<Modal
title={ __( 'Create Reusable block' ) }
closeLabel={ __( 'Close' ) }
onRequestClose={ () => {
setIsModalOpen( false );
setTitle( '' );
} }
overlayClassName="reusable-blocks-menu-items__convert-modal"
>
<form
onSubmit={ ( event ) => {
event.preventDefault();
onConvert( title );
setIsModalOpen( false );
setTitle( '' );
onClose();
} }
>
<TextControl
label={ __( 'Name' ) }
value={ title }
onChange={ setTitle }
/>
<Flex justify="flex-end">
<FlexItem>
<Button
isSecondary
onClick={ () => {
setIsModalOpen( false );
setTitle( '' );
} }
>
{ __( 'Cancel' ) }
</Button>
</FlexItem>
<FlexItem>
<Button isPrimary type="submit">
{ __( 'Save' ) }
</Button>
</FlexItem>
</Flex>
</form>
</Modal>
) }
</>
) }
</BlockSettingsMenuControls>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.reusable-blocks-menu-items__convert-modal {
z-index: z-index(".reusable-blocks-menu-items__convert-modal");
}
5 changes: 3 additions & 2 deletions packages/reusable-blocks/src/store/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@ export function* __experimentalConvertBlockToStatic( clientId ) {
* Returns a generator converting one or more static blocks into a reusable block.
*
* @param {string[]} clientIds The client IDs of the block to detach.
* @param {string} title Reusable block title.
*/
export function* __experimentalConvertBlocksToReusable( clientIds ) {
yield convertBlocksToReusable( clientIds );
export function* __experimentalConvertBlocksToReusable( clientIds, title ) {
yield convertBlocksToReusable( clientIds, title );
}

/**
Expand Down
Loading