Skip to content

Commit

Permalink
Full Site Editing: Introduce a template edition mode inside the post …
Browse files Browse the repository at this point in the history
…editor (#26355)
  • Loading branch information
youknowriad committed Dec 3, 2020
1 parent 1145d22 commit a250e9e
Show file tree
Hide file tree
Showing 34 changed files with 848 additions and 258 deletions.
24 changes: 24 additions & 0 deletions docs/designers-developers/developers/data/data-core-edit-post.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,18 @@ _Returns_

- `boolean`: Whether there are metaboxes or not.

<a name="isEditingTemplate" href="#isEditingTemplate">#</a> **isEditingTemplate**

Returns true if the template editing mode is enabled.

_Parameters_

- _state_ `Object`: Global application state.

_Returns_

- `boolean`: Whether we're editing the template.

<a name="isEditorPanelEnabled" href="#isEditorPanelEnabled">#</a> **isEditorPanelEnabled**

Returns true if the given panel is enabled, or false otherwise. Panels are
Expand Down Expand Up @@ -381,6 +393,18 @@ _Parameters_

- _metaBoxesPerLocation_ `Object`: Meta boxes per location.

<a name="setIsEditingTemplate" href="#setIsEditingTemplate">#</a> **setIsEditingTemplate**

Returns an action object used to switch to template editing.

_Parameters_

- _value_ `boolean`: Is editing template.

_Returns_

- `Object`: Action object.

<a name="setIsInserterOpened" href="#setIsInserterOpened">#</a> **setIsInserterOpened**

Returns an action object used to open/close the inserter.
Expand Down
13 changes: 13 additions & 0 deletions lib/client-assets.php
Original file line number Diff line number Diff line change
Expand Up @@ -649,3 +649,16 @@ function gutenberg_extend_block_editor_settings_with_default_editor_styles( $set
return $settings;
}
add_filter( 'block_editor_settings', 'gutenberg_extend_block_editor_settings_with_default_editor_styles' );

/**
* Adds a flag to the editor settings to know whether we're in FSE theme or not.
*
* @param array $settings Default editor settings.
*
* @return array Filtered editor settings.
*/
function gutenberg_extend_block_editor_settings_with_fse_theme_flag( $settings ) {
$settings['isFSETheme'] = gutenberg_is_fse_theme();
return $settings;
}
add_filter( 'block_editor_settings', 'gutenberg_extend_block_editor_settings_with_fse_theme_flag' );
14 changes: 1 addition & 13 deletions packages/block-library/src/post-content/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import { useSelect } from '@wordpress/data';
import { useBlockProps } from '@wordpress/block-editor';

/**
Expand All @@ -13,19 +12,8 @@ import PostContentInnerBlocks from './inner-blocks';
export default function PostContentEdit( {
context: { postId: contextPostId, postType: contextPostType },
} ) {
const { id: currentPostId, type: currentPostType } = useSelect(
( select ) => select( 'core/editor' ).getCurrentPost() ?? {}
);
const blockProps = useBlockProps();

// Only render InnerBlocks if the context is different from the active post
// to avoid infinite recursion of post content.
if (
contextPostId &&
contextPostType &&
contextPostId !== currentPostId &&
contextPostType !== currentPostType
) {
if ( contextPostId && contextPostType ) {
return (
<div { ...blockProps }>
<PostContentInnerBlocks
Expand Down
17 changes: 17 additions & 0 deletions packages/core-data/src/controls.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
export function regularFetch( url ) {
return {
type: 'REGULAR_FETCH',
url,
};
}
const controls = {
async REGULAR_FETCH( { url } ) {
const { data } = await window
.fetch( url )
.then( ( res ) => res.json() );

return data;
},
};

export default controls;
3 changes: 2 additions & 1 deletion packages/core-data/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import * as actions from './actions';
import * as resolvers from './resolvers';
import * as locksSelectors from './locks/selectors';
import * as locksActions from './locks/actions';
import customControls from './controls';
import { defaultEntities, getMethodName } from './entities';
import { STORE_NAME } from './name';

Expand Down Expand Up @@ -58,7 +59,7 @@ const entityActions = defaultEntities.reduce( ( result, entity ) => {

const storeConfig = {
reducer,
controls,
controls: { ...customControls, ...controls },
actions: { ...actions, ...entityActions, ...locksActions },
selectors: { ...selectors, ...entitySelectors, ...locksSelectors },
resolvers: { ...resolvers, ...entityResolvers },
Expand Down
39 changes: 39 additions & 0 deletions packages/core-data/src/resolvers.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ import { addQueryArgs } from '@wordpress/url';
import deprecated from '@wordpress/deprecated';
import { controls } from '@wordpress/data';
import { apiFetch } from '@wordpress/data-controls';
/**
* Internal dependencies
*/
import { regularFetch } from './controls';

/**
* Internal dependencies
Expand Down Expand Up @@ -382,3 +386,38 @@ export function* getAutosaves( postType, postId ) {
export function* getAutosave( postType, postId ) {
yield controls.resolveSelect( 'core', 'getAutosaves', postType, postId );
}

/**
* Retrieve the frontend template used for a given link.
*
* @param {string} link Link.
*/
export function* __experimentalGetTemplateForLink( link ) {
// Ideally this should be using an apiFetch call
// We could potentially do so by adding a "filter" to the `wp_template` end point.
// Also it seems the returned object is not a regular REST API post type.
const template = yield regularFetch(
addQueryArgs( link, {
'_wp-find-template': true,
} )
);

if ( template === null ) {
return;
}

yield getEntityRecord( 'postType', 'wp_template', template.ID );
const record = yield controls.select(
'core',
'getEntityRecord',
'postType',
'wp_template',
template.ID
);

if ( record ) {
yield receiveEntityRecords( 'postType', 'wp_template', [ record ], {
'find-template': link,
} );
}
}
16 changes: 16 additions & 0 deletions packages/core-data/src/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -740,3 +740,19 @@ export const getReferenceByDistinctEdits = createSelector(
state.undo.flattenedUndo,
]
);

/**
* Retrieve the frontend template used for a given link.
*
* @param {Object} state Editor state.
* @param {string} link Link.
*
* @return {Object?} The template record.
*/
export function __experimentalGetTemplateForLink( state, link ) {
const records = getEntityRecords( state, 'postType', 'wp_template', {
'find-template': link,
} );

return records?.length ? records[ 0 ] : null;
}
12 changes: 12 additions & 0 deletions packages/e2e-test-utils/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,18 @@ Clicks on the button in the header which opens Document Settings sidebar when it

Opens the global block inserter.

<a name="openPreviewPage" href="#openPreviewPage">#</a> **openPreviewPage**

Opens the preview page of an edited post.

_Parameters_

- _editorPage_ `Page`: puppeteer editor page.

_Returns_

- `Page`: preview page.

<a name="openPublishPanel" href="#openPublishPanel">#</a> **openPublishPanel**

Opens the publish panel.
Expand Down
1 change: 1 addition & 0 deletions packages/e2e-test-utils/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,5 +74,6 @@ export { uninstallPlugin } from './uninstall-plugin';
export { visitAdminPage } from './visit-admin-page';
export { waitForWindowDimensions } from './wait-for-window-dimensions';
export { showBlockToolbar } from './show-block-toolbar';
export { openPreviewPage } from './preview';

export * from './mocks';
29 changes: 29 additions & 0 deletions packages/e2e-test-utils/src/preview.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/**
* External dependencies
*/
import { last } from 'lodash';

/** @typedef {import('puppeteer').Page} Page */

/**
* Opens the preview page of an edited post.
*
* @param {Page} editorPage puppeteer editor page.
* @return {Page} preview page.
*/
export async function openPreviewPage( editorPage = page ) {
let openTabs = await browser.pages();
const expectedTabsCount = openTabs.length + 1;
await editorPage.click( '.block-editor-post-preview__button-toggle' );
await editorPage.waitFor( '.edit-post-header-preview__button-external' );
await editorPage.click( '.edit-post-header-preview__button-external' );

// Wait for the new tab to open.
while ( openTabs.length < expectedTabsCount ) {
await editorPage.waitFor( 1 );
openTabs = await browser.pages();
}

const previewPage = last( openTabs );
return previewPage;
}
28 changes: 2 additions & 26 deletions packages/e2e-tests/specs/editor/plugins/block-context.test.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
/**
* External dependencies
*/
import { last } from 'lodash';

/**
* WordPress dependencies
*/
Expand All @@ -12,29 +7,9 @@ import {
deactivatePlugin,
insertBlock,
saveDraft,
openPreviewPage,
} from '@wordpress/e2e-test-utils';

async function openPreviewPage( editorPage ) {
let openTabs = await browser.pages();
const expectedTabsCount = openTabs.length + 1;
await editorPage.click( '.block-editor-post-preview__button-toggle' );
await editorPage.waitFor( '.edit-post-header-preview__button-external' );
await editorPage.click( '.edit-post-header-preview__button-external' );

// Wait for the new tab to open.
while ( openTabs.length < expectedTabsCount ) {
await editorPage.waitFor( 1 );
openTabs = await browser.pages();
}

const previewPage = last( openTabs );
// Wait for the preview to load. We can't do interstitial detection here,
// because it might load too quickly for us to pick up, so we wait for
// the preview to load by waiting for the content to appear.
await previewPage.waitForSelector( '.entry-content' );
return previewPage;
}

describe( 'Block context', () => {
beforeAll( async () => {
await activatePlugin( 'gutenberg-test-block-context' );
Expand Down Expand Up @@ -74,6 +49,7 @@ describe( 'Block context', () => {
await insertBlock( 'Test Context Provider' );
const editorPage = page;
const previewPage = await openPreviewPage( editorPage );
await previewPage.waitForSelector( '.entry-content' );

// Check default context values are populated.
let content = await previewPage.$eval(
Expand Down
30 changes: 4 additions & 26 deletions packages/e2e-tests/specs/editor/various/preview.test.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
/**
* External dependencies
*/
import { last } from 'lodash';

/**
* WordPress dependencies
*/
Expand All @@ -15,31 +10,11 @@ import {
deactivatePlugin,
publishPost,
saveDraft,
openPreviewPage,
} from '@wordpress/e2e-test-utils';

/** @typedef {import('puppeteer').Page} Page */

async function openPreviewPage( editorPage ) {
let openTabs = await browser.pages();
const expectedTabsCount = openTabs.length + 1;
await editorPage.click( '.block-editor-post-preview__button-toggle' );
await editorPage.waitFor( '.edit-post-header-preview__button-external' );
await editorPage.click( '.edit-post-header-preview__button-external' );

// Wait for the new tab to open.
while ( openTabs.length < expectedTabsCount ) {
await editorPage.waitFor( 1 );
openTabs = await browser.pages();
}

const previewPage = last( openTabs );
// Wait for the preview to load. We can't do interstitial detection here,
// because it might load too quickly for us to pick up, so we wait for
// the preview to load by waiting for the title to appear.
await previewPage.waitForSelector( '.entry-title' );
return previewPage;
}

/**
* Given the Page instance for the editor, opens preview drodpdown, and
* awaits the presence of the external preview selector.
Expand Down Expand Up @@ -123,6 +98,7 @@ describe( 'Preview', () => {
await editorPage.type( '.editor-post-title__input', 'Hello World' );

const previewPage = await openPreviewPage( editorPage );
await previewPage.waitForSelector( '.entry-title' );

// When autosave completes for a new post, the URL of the editor should
// update to include the ID. Use this to assert on preview URL.
Expand Down Expand Up @@ -222,6 +198,7 @@ describe( 'Preview', () => {

// Open the preview page.
const previewPage = await openPreviewPage( editorPage );
await previewPage.waitForSelector( '.entry-title' );

// Title in preview should match input.
let previewTitle = await previewPage.$eval(
Expand Down Expand Up @@ -282,6 +259,7 @@ describe( 'Preview with Custom Fields enabled', () => {

// Open the preview page.
const previewPage = await openPreviewPage( editorPage );
await previewPage.waitForSelector( '.entry-title' );

// Check the title and preview match.
let previewTitle = await previewPage.$eval(
Expand Down
Loading

0 comments on commit a250e9e

Please sign in to comment.