Skip to content

Commit

Permalink
Post editor: iframe for block-based themes (#46212)
Browse files Browse the repository at this point in the history
  • Loading branch information
ellatrix authored Dec 19, 2022
1 parent 29341d6 commit 967cba4
Show file tree
Hide file tree
Showing 7 changed files with 204 additions and 52 deletions.
3 changes: 2 additions & 1 deletion lib/compat/wordpress-6.2/script-loader.php
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,8 @@ function gutenberg_resolve_assets_override() {
'block_editor_settings_all',
function( $settings ) {
// We must override what core is passing now.
$settings['__unstableResolvedAssets'] = gutenberg_resolve_assets_override();
$settings['__unstableResolvedAssets'] = gutenberg_resolve_assets_override();
$settings['__unstableIsBlockBasedTheme'] = wp_is_block_theme();
return $settings;
},
100
Expand Down
77 changes: 48 additions & 29 deletions packages/block-library/src/freeform/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,18 @@ import {
useBlockProps,
store as blockEditorStore,
} from '@wordpress/block-editor';
import { debounce } from '@wordpress/compose';
import { debounce, useRefEffect } from '@wordpress/compose';
import { useSelect } from '@wordpress/data';
import { ToolbarGroup } from '@wordpress/components';
import { useEffect, useRef } from '@wordpress/element';
import { useEffect, useRef, useState } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import { BACKSPACE, DELETE, F10, isKeyboardEvent } from '@wordpress/keycodes';

/**
* Internal dependencies
*/
import ConvertToBlocksButton from './convert-to-blocks-button';
import ModalEdit from './modal';

const { wp } = window;

Expand All @@ -36,17 +37,44 @@ function isTmceEmpty( editor ) {
return /^\n?$/.test( body.innerText || body.textContent );
}

export default function ClassicEdit( {
export default function FreeformEdit( props ) {
const { clientId } = props;
const canRemove = useSelect(
( select ) => select( blockEditorStore ).canRemoveBlock( clientId ),
[ clientId ]
);
const [ isIframed, setIsIframed ] = useState( false );
const ref = useRefEffect( ( element ) => {
setIsIframed( element.ownerDocument !== document );
}, [] );

return (
<>
{ canRemove && (
<BlockControls>
<ToolbarGroup>
<ConvertToBlocksButton clientId={ clientId } />
</ToolbarGroup>
</BlockControls>
) }
<div { ...useBlockProps( { ref } ) }>
{ isIframed ? (
<ModalEdit { ...props } />
) : (
<ClassicEdit { ...props } />
) }
</div>
</>
);
}

function ClassicEdit( {
clientId,
attributes: { content },
setAttributes,
onReplace,
} ) {
const { getMultiSelectedBlockClientIds } = useSelect( blockEditorStore );
const canRemove = useSelect(
( select ) => select( blockEditorStore ).canRemoveBlock( clientId ),
[ clientId ]
);
const didMount = useRef( false );

useEffect( () => {
Expand Down Expand Up @@ -225,28 +253,19 @@ export default function ClassicEdit( {
/* eslint-disable jsx-a11y/no-static-element-interactions */
return (
<>
{ canRemove && (
<BlockControls>
<ToolbarGroup>
<ConvertToBlocksButton clientId={ clientId } />
</ToolbarGroup>
</BlockControls>
) }
<div { ...useBlockProps() }>
<div
key="toolbar"
id={ `toolbar-${ clientId }` }
className="block-library-classic__toolbar"
onClick={ focus }
data-placeholder={ __( 'Classic' ) }
onKeyDown={ onToolbarKeyDown }
/>
<div
key="editor"
id={ `editor-${ clientId }` }
className="wp-block-freeform block-library-rich-text__tinymce"
/>
</div>
<div
key="toolbar"
id={ `toolbar-${ clientId }` }
className="block-library-classic__toolbar"
onClick={ focus }
data-placeholder={ __( 'Classic' ) }
onKeyDown={ onToolbarKeyDown }
/>
<div
key="editor"
id={ `editor-${ clientId }` }
className="wp-block-freeform block-library-rich-text__tinymce"
/>
</>
);
/* eslint-enable jsx-a11y/no-static-element-interactions */
Expand Down
111 changes: 111 additions & 0 deletions packages/block-library/src/freeform/modal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/**
* WordPress dependencies
*/
import { BlockControls, store } from '@wordpress/block-editor';
import {
ToolbarGroup,
ToolbarButton,
Modal,
Button,
} from '@wordpress/components';
import { useEffect, useState, RawHTML } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import { useSelect } from '@wordpress/data';

function ClassicEdit( props ) {
const styles = useSelect(
( select ) => select( store ).getSettings().styles
);
useEffect( () => {
const { baseURL, suffix, settings } = window.wpEditorL10n.tinymce;

window.tinymce.EditorManager.overrideDefaults( {
base_url: baseURL,
suffix,
} );

window.wp.oldEditor.initialize( props.id, {
tinymce: {
...settings,
height: 500,
setup( editor ) {
editor.on( 'init', () => {
const doc = editor.getDoc();
styles.forEach( ( { css } ) => {
const styleEl = doc.createElement( 'style' );
styleEl.innerHTML = css;
doc.head.appendChild( styleEl );
} );
} );
},
},
} );

return () => {
window.wp.oldEditor.remove( props.id );
};
}, [] );

return <textarea { ...props } />;
}

export default function ModalEdit( props ) {
const {
clientId,
attributes: { content },
setAttributes,
onReplace,
} = props;
const [ isOpen, setOpen ] = useState( false );
const id = `editor-${ clientId }`;
const label = __( 'Classic Edit' );

return (
<>
<BlockControls>
<ToolbarGroup>
<ToolbarButton onClick={ () => setOpen( true ) }>
{ label }
</ToolbarButton>
</ToolbarGroup>
</BlockControls>
{ content && <RawHTML>{ content }</RawHTML> }
{ ( isOpen || ! content ) && (
<Modal title={ label } __experimentalHideHeader={ true }>
<h2
style={ {
display: 'flex',
justifyContent: 'space-between',
} }
>
<div>{ label }</div>
<div>
<Button
onClick={ () =>
content ? setOpen( false ) : onReplace( [] )
}
>
{ __( 'Cancel' ) }
</Button>
<Button
isPrimary
onClick={ () => {
setAttributes( {
content:
window.wp.oldEditor.getContent(
id
),
} );
setOpen( false );
} }
>
{ __( 'Save' ) }
</Button>
</div>
</h2>
<ClassicEdit id={ id } defaultValue={ content } />
</Modal>
) }
</>
);
}
3 changes: 2 additions & 1 deletion packages/e2e-test-utils/src/create-reusable-block.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import { insertBlock } from './inserter';
import { clickMenuItem } from './click-menu-item';
import { clickBlockToolbarButton } from './click-block-toolbar-button';
import { canvas } from './canvas';

/**
* Creates a simple reusable block with a paragraph block.
Expand Down Expand Up @@ -33,7 +34,7 @@ export const createReusableBlock = async ( content, title ) => {
);

// Check that we have a reusable block on the page
const block = await page.waitForSelector(
const block = await canvas().waitForSelector(
'.block-editor-block-list__block[data-type="core/block"]'
);
expect( block ).not.toBeNull();
Expand Down
25 changes: 13 additions & 12 deletions packages/e2e-tests/specs/site-editor/multi-entity-saving.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
visitSiteEditor,
enterEditMode,
deleteAllTemplates,
canvas,
} from '@wordpress/e2e-test-utils';

describe( 'Multi-entity save flow', () => {
Expand Down Expand Up @@ -94,8 +95,8 @@ describe( 'Multi-entity save flow', () => {
it( 'Save flow should work as expected.', async () => {
await createNewPost();
// Edit the page some.
await page.waitForSelector( '.editor-post-title' );
await page.click( '.editor-post-title' );
await canvas().waitForSelector( '.editor-post-title' );
await canvas().click( '.editor-post-title' );
await page.keyboard.type( 'Test Post...' );
await page.keyboard.press( 'Enter' );

Expand All @@ -110,8 +111,8 @@ describe( 'Multi-entity save flow', () => {

// Add a reusable block and edit it.
await createReusableBlock( 'Hi!', 'Test' );
await page.waitForSelector( 'p[data-type="core/paragraph"]' );
await page.click( 'p[data-type="core/paragraph"]' );
await canvas().waitForSelector( 'p[data-type="core/paragraph"]' );
await canvas().click( 'p[data-type="core/paragraph"]' );
await page.keyboard.type( 'Oh!' );

// Should trigger multi-entity save button once template part edited.
Expand Down Expand Up @@ -169,7 +170,7 @@ describe( 'Multi-entity save flow', () => {
} );

// Update the post.
await page.click( '.editor-post-title' );
await canvas().click( '.editor-post-title' );
await page.keyboard.type( '...more title!' );

// Verify update button is enabled.
Expand All @@ -182,9 +183,9 @@ describe( 'Multi-entity save flow', () => {
await assertExistence( saveA11ySelector, false );

// Update reusable block again.
await page.click( 'p[data-type="core/paragraph"]' );
await canvas().click( 'p[data-type="core/paragraph"]' );
// We need to click again due to the clickthrough overlays in reusable blocks.
await page.click( 'p[data-type="core/paragraph"]' );
await canvas().click( 'p[data-type="core/paragraph"]' );
await page.keyboard.type( 'R!' );

// Multi-entity saving should be enabled.
Expand All @@ -203,19 +204,19 @@ describe( 'Multi-entity save flow', () => {
);
const editableSiteTitleSelector =
'.wp-block-site-title a[contenteditable="true"]';
await page.waitForSelector( editableSiteTitleSelector );
await page.focus( editableSiteTitleSelector );
await canvas().waitForSelector( editableSiteTitleSelector );
await canvas().focus( editableSiteTitleSelector );
await page.keyboard.type( '...' );

await insertBlock( 'Site Tagline' );
// Wait for the placeholder.
await page.waitForXPath(
await canvas().waitForXPath(
'//span[@data-rich-text-placeholder="Write site tagline…"]'
);
const editableSiteTagLineSelector =
'.wp-block-site-tagline[contenteditable="true"]';
await page.waitForSelector( editableSiteTagLineSelector );
await page.focus( editableSiteTagLineSelector );
await canvas().waitForSelector( editableSiteTagLineSelector );
await canvas().focus( editableSiteTagLineSelector );
await page.keyboard.type( 'Just another WordPress site' );

await clickButton( 'Publish' );
Expand Down
6 changes: 5 additions & 1 deletion packages/edit-post/src/components/visual-editor/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ export default function VisualEditor( { styles } ) {
editedPostTemplate = {},
wrapperBlockName,
wrapperUniqueId,
isBlockBasedTheme,
} = useSelect( ( select ) => {
const {
isFeatureActive,
Expand All @@ -137,7 +138,8 @@ export default function VisualEditor( { styles } ) {
_wrapperBlockName = 'core/post-content';
}

const supportsTemplateMode = getEditorSettings().supportsTemplateMode;
const editorSettings = getEditorSettings();
const supportsTemplateMode = editorSettings.supportsTemplateMode;
const canEditTemplate = select( coreStore ).canUser(
'create',
'templates'
Expand All @@ -155,6 +157,7 @@ export default function VisualEditor( { styles } ) {
: undefined,
wrapperBlockName: _wrapperBlockName,
wrapperUniqueId: getCurrentPostId(),
isBlockBasedTheme: editorSettings.__unstableIsBlockBasedTheme,
};
}, [] );
const { isCleanNewPost } = useSelect( editorStore );
Expand Down Expand Up @@ -336,6 +339,7 @@ export default function VisualEditor( { styles } ) {
>
<MaybeIframe
shouldIframe={
( isBlockBasedTheme && ! hasMetaBoxes ) ||
isTemplateMode ||
deviceType === 'Tablet' ||
deviceType === 'Mobile'
Expand Down
Loading

1 comment on commit 967cba4

@github-actions
Copy link

Choose a reason for hiding this comment

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

Flaky tests detected.
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/3731523353
📝 Reported issues:

Please sign in to comment.