Skip to content

Commit

Permalink
Fix the AMP Preview button not being shown in the block editor (#5441)
Browse files Browse the repository at this point in the history
  • Loading branch information
pierlon authored and westonruter committed Oct 5, 2020
1 parent 7d9f743 commit 422a70d
Show file tree
Hide file tree
Showing 13 changed files with 214 additions and 130 deletions.
3 changes: 2 additions & 1 deletion assets/css/src/amp-block-editor.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@
}

/* AMP preview button wrapper */
.wp-core-ui #amp-wrapper-post-preview {
.wp-core-ui .amp-wrapper-post-preview {
margin-left: -6px;
margin-right: 6px;
}

/* AMP preview button */
.wp-core-ui .amp-editor-post-preview {
height: 34px;
margin-right: 0 !important;
padding: 6px 12px;
border-top-left-radius: 0;
border-bottom-left-radius: 0;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,24 @@
/**
* External dependencies
*/
import { get } from 'lodash';
import PropTypes from 'prop-types';

/**
* WordPress dependencies
*/
import { Component, createRef, renderToString } from '@wordpress/element';
import { Button, Icon } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import { withSelect, withDispatch } from '@wordpress/data';
import { compose } from '@wordpress/compose';
import { withDispatch, withSelect } from '@wordpress/data';
import { Component, createRef, renderToString } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import { addQueryArgs } from '@wordpress/url';

/**
* Internal dependencies
*/
import ampBlackIcon from '../../../images/amp-black-icon.svg';
import ampFilledIcon from '../../../images/amp-icon.svg';
import { isAMPEnabled } from '../helpers';
import { POST_PREVIEW_CLASS } from '../constants';
import ampFilledIcon from '../../../images/amp-icon.svg';
import ampBlackIcon from '../../../images/amp-black-icon.svg';

/**
* Writes the message and graphic in the new preview window that was opened.
Expand Down Expand Up @@ -105,22 +103,19 @@ function writeInterstitialMessage( targetDocument ) {
/**
* A 'Preview AMP' button, forked from the Core 'Preview' button: <PostPreviewButton>.
*
* Rendered into the DOM with renderPreviewButton() in helpers/index.js.
* This also moves the (non-AMP) 'Preview' button to before this, if it's not already there.
*
* @see https://github.com/WordPress/gutenberg/blob/95e769df1f82f6b0ef587d81af65dd2f48cd1c38/packages/editor/src/components/post-preview-button/index.js#L95-L200
*/
class AMPPreview extends Component {
class AmpPreviewButton extends Component {
/**
* Constructs the class.
*
* @param {*} args Constructor arguments.
*/
constructor( ...args ) {
super( ...args );
this.moveButton = this.moveButton.bind( this );
this.openPreviewWindow = this.openPreviewWindow.bind( this );

this.buttonRef = createRef();
this.openPreviewWindow = this.openPreviewWindow.bind( this );
}

/**
Expand All @@ -137,25 +132,6 @@ class AMPPreview extends Component {
if ( previewLink && ! prevProps.previewLink ) {
this.setPreviewWindowLink( previewLink );
}

this.moveButton();
}

/**
* Moves the (non-AMP) 'Preview' button to before this 'Preview AMP' button, if it's not there already.
*/
moveButton() {
const buttonWrapper = get( this, [ 'buttonRef', 'current', 'parentNode' ], false );
if ( ! buttonWrapper ) {
return;
}

if ( ! buttonWrapper.previousSibling || ! buttonWrapper.previousSibling.classList.contains( POST_PREVIEW_CLASS ) ) {
const postPreviewButton = document.querySelector( `.${ POST_PREVIEW_CLASS }` );
if ( get( postPreviewButton, 'nextSibling' ) ) {
buttonWrapper.parentNode.insertBefore( buttonWrapper, postPreviewButton.nextSibling );
}
}
}

/**
Expand All @@ -169,6 +145,9 @@ class AMPPreview extends Component {

if ( previewWindow && ! previewWindow.closed ) {
previewWindow.location = url;
if ( this.buttonRef.current ) {
this.buttonRef.current.focus();
}
}
}

Expand Down Expand Up @@ -234,31 +213,29 @@ class AMPPreview extends Component {
// just link to the post's URL.
const href = previewLink || currentPostLink;

return (
isEnabled && ! errorMessages.length && ! isStandardMode && (
<Button
className="amp-editor-post-preview"
href={ href }
title={ __( 'Preview AMP', 'amp' ) }
isSecondary
disabled={ ! isSaveable }
onClick={ this.openPreviewWindow }
ref={ this.buttonRef }
>
{ ampFilledIcon( { viewBox: '0 0 62 62', width: 18, height: 18 } ) }
<span className="screen-reader-text">
{
/* translators: accessibility text */
__( '(opens in a new tab)', 'amp' )
}
</span>
</Button>
)
return isEnabled && ! errorMessages.length && ! isStandardMode && (
<Button
className="amp-editor-post-preview"
href={ href }
title={ __( 'Preview AMP', 'amp' ) }
isSecondary
disabled={ ! isSaveable }
onClick={ this.openPreviewWindow }
ref={ this.buttonRef }
>
{ ampFilledIcon( { viewBox: '0 0 62 62', width: 18, height: 18 } ) }
<span className="screen-reader-text">
{
/* translators: accessibility text */
__( '(opens in a new tab)', 'amp' )
}
</span>
</Button>
);
}
}

AMPPreview.propTypes = {
AmpPreviewButton.propTypes = {
autosave: PropTypes.func.isRequired,
currentPostLink: PropTypes.string.isRequired,
postId: PropTypes.number.isRequired,
Expand Down Expand Up @@ -291,6 +268,7 @@ export default compose( [

const queryArgs = {};
queryArgs[ getAmpSlug() ] = 1;

const initialPreviewLink = getEditedPostPreviewLink();
const previewLink = initialPreviewLink ? addQueryArgs( initialPreviewLink, queryArgs ) : undefined;

Expand All @@ -310,4 +288,4 @@ export default compose( [
autosave: dispatch( 'core/editor' ).autosave,
savePost: dispatch( 'core/editor' ).savePost,
} ) ),
] )( AMPPreview );
] )( AmpPreviewButton );
1 change: 0 additions & 1 deletion assets/src/block-editor/components/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
export { default as AMPPreview } from './amp-preview';
export { default as MediaPlaceholder } from './media-placeholder';
export { default as LayoutControls } from './layout-controls';
export { default as withMediaLibraryNotice } from './with-media-library-notice';
30 changes: 2 additions & 28 deletions assets/src/block-editor/helpers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ import { ReactElement } from 'react';
* WordPress dependencies
*/
import { __, _x } from '@wordpress/i18n';
import { cloneElement, render } from '@wordpress/element';
import { cloneElement } from '@wordpress/element';
import { TextControl, SelectControl, ToggleControl, Notice, PanelBody, FontSizePicker } from '@wordpress/components';
import { InspectorControls } from '@wordpress/block-editor';
import { select } from '@wordpress/data';

/**
* Internal dependencies
*/
import { TEXT_BLOCKS, MEDIA_BLOCKS, DEFAULT_HEIGHT, DEFAULT_WIDTH, POST_PREVIEW_CLASS } from '../constants';
import { TEXT_BLOCKS, MEDIA_BLOCKS, DEFAULT_HEIGHT, DEFAULT_WIDTH } from '../constants';
import { MIN_FONT_SIZE, MAX_FONT_SIZE } from '../../common/constants';

const ampLayoutOptions = [
Expand Down Expand Up @@ -719,29 +719,3 @@ export const isAMPEnabled = () => {
const { getEditedPostAttribute } = select( 'core/editor' );
return getEditedPostAttribute( 'amp_enabled' ) || false;
};

/**
* Renders the 'Preview AMP' button in the DOM right after the non-AMP 'Preview' button.
*
* @param {Object} PreviewComponent The 'Preview AMP' component to render into the DOM.
*/
export const renderPreviewButton = ( PreviewComponent ) => {
const postPreviewButton = document.querySelector( `.${ POST_PREVIEW_CLASS }` );
const ampPreviewButtonWrapperId = 'amp-wrapper-post-preview';

// Exit if the non-AMP 'Preview' button doesn't exist.
if ( ! postPreviewButton || ! postPreviewButton.nextSibling ) {
return;
}

const buttonWrapper = document.createElement( 'div' );
buttonWrapper.id = ampPreviewButtonWrapperId;

render(
<PreviewComponent />,
buttonWrapper,
);

// Insert the new AMP preview button after the non-AMP 'Preview' button.
postPreviewButton.parentNode.insertBefore( buttonWrapper, postPreviewButton.nextSibling );
};
33 changes: 0 additions & 33 deletions assets/src/block-editor/helpers/test/renderPreviewButton.js

This file was deleted.

10 changes: 2 additions & 8 deletions assets/src/block-editor/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,14 @@ import { addFilter } from '@wordpress/hooks';
import { registerPlugin } from '@wordpress/plugins';
import { registerBlockType } from '@wordpress/blocks';
import { select } from '@wordpress/data';
import domReady from '@wordpress/dom-ready';

/**
* Internal dependencies
*/
import { withFeaturedImageNotice } from '../common/components';
import { getMinimumFeaturedImageDimensions } from '../common/helpers';
import { withMediaLibraryNotice, AMPPreview } from './components';
import { addAMPAttributes, filterBlocksEdit, filterBlocksSave, renderPreviewButton } from './helpers';
import { withMediaLibraryNotice } from './components';
import { addAMPAttributes, filterBlocksEdit, filterBlocksSave } from './helpers';
import './store';

const {
Expand Down Expand Up @@ -60,8 +59,3 @@ blocks.keys().forEach( ( modulePath ) => {
registerBlockType( name, settings );
}
} );

// Render the 'Preview AMP' button, and move it to after the (non-AMP) 'Preview' button.
domReady( () => {
renderPreviewButton( AMPPreview );
} );
90 changes: 90 additions & 0 deletions assets/src/block-editor/plugins/wrapped-amp-preview-button.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/**
* External dependencies
*/
import { get } from 'lodash';

/**
* WordPress dependencies
*/
import { Component, createPortal } from '@wordpress/element';
import { withSelect } from '@wordpress/data';
import { ifCondition, compose, pure } from '@wordpress/compose';

/**
* Internal dependencies
*/
import { POST_PREVIEW_CLASS } from '../constants';
import AmpPreviewButton from '../components/amp-preview-button';

/**
* A wrapper for the AMP preview button that renders it immediately after the 'Post' preview button, when present.
*/
class WrappedAmpPreviewButton extends Component {
/**
* Constructs the class.
*
* @param {*} args Constructor arguments.
*/
constructor( ...args ) {
super( ...args );

this.root = document.createElement( 'div' );
this.root.className = 'amp-wrapper-post-preview';

this.postPreviewButton = document.querySelector( `.${ POST_PREVIEW_CLASS }` );
}

/**
* Invoked immediately after a component is mounted (inserted into the tree).
*/
componentDidMount() {
if ( ! this.postPreviewButton ) {
return;
}

// Insert the AMP preview button immediately after the post preview button.
this.postPreviewButton.parentNode.insertBefore( this.root, this.postPreviewButton.nextSibling );
}

/**
* Invoked immediately before a component is unmounted and destroyed.
*/
componentWillUnmount() {
if ( ! this.postPreviewButton ) {
return;
}

this.postPreviewButton.parentNode.removeChild( this.root );
}

/**
* Renders the component.
*/
render() {
if ( ! this.postPreviewButton ) {
return null;
}

return createPortal( <AmpPreviewButton />, this.root );
}
}

export const name = 'amp-preview-button-wrapper';

export const render = pure(
compose( [
withSelect( ( select ) => {
const { getPostType } = select( 'core' );
const { getEditedPostAttribute } = select( 'core/editor' );

const postType = getPostType( getEditedPostAttribute( 'type' ) );

return {
isViewable: get( postType, [ 'viewable' ], false ),
};
} ),
// This HOC creator renders the component only when the condition is true. At that point the 'Post' preview
// button should have already been rendered (since it also relies on the same condition for rendering).
ifCondition( ( { isViewable } ) => isViewable ),
] )( WrappedAmpPreviewButton ),
);
2 changes: 1 addition & 1 deletion assets/src/block-validation/store/selectors.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Returns general validation erroxrs.
* Returns general validation errors.
*
* @param {Object} state Editor state.
*
Expand Down
2 changes: 1 addition & 1 deletion bin/local-env/install-wordpress.sh
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ wp plugin activate amp --quiet

# Install & activate Gutenberg plugin.
echo -e $(status_message "Installing and activating Gutenberg plugin...")
wp plugin install gutenberg --activate --force --quiet --version=7.1.0
wp plugin install gutenberg --activate --force --quiet

# Set pretty permalinks.
echo -e $(status_message "Setting permalink structure...")
Expand Down
Loading

0 comments on commit 422a70d

Please sign in to comment.