Skip to content

Commit

Permalink
Merge pull request #6563 from arthur791004/add/post-featured-image-in…
Browse files Browse the repository at this point in the history
…-pre-publish-panel

Add PostFeaturedImage to PrePublishPanel
  • Loading branch information
westonruter authored Aug 30, 2021
2 parents 53666e0 + 1fb801e commit 96e76b1
Show file tree
Hide file tree
Showing 8 changed files with 4,183 additions and 666 deletions.
8 changes: 2 additions & 6 deletions assets/src/block-editor/plugins/pre-publish-panel.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,12 @@
* Internal dependencies
*/
import { PrePublishPanel } from '../../common/components';
import { getMinimumFeaturedImageDimensions } from '../../common/helpers';

export const name = 'amp-post-featured-image-pre-publish-panel';

// On clicking 'Publish,' display a notice if no featured image exists or its width is too small.
// Add the featured image selection component as a pre-publish check.
export const render = () => {
return (
<PrePublishPanel
dimensions={ getMinimumFeaturedImageDimensions() }
required={ false }
/>
<PrePublishPanel />
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,37 @@ import { isFunction } from 'lodash';
*/
import { createHigherOrderComponent } from '@wordpress/compose';
import { Notice } from '@wordpress/components';
import { __ } from '@wordpress/i18n';

/**
* Internal dependencies
*/
import { validateFeaturedImage, getMinimumFeaturedImageDimensions } from '../../helpers';

/**
* Create notice UI for featured image component.
*
* @param {string[]} messages Notices.
* @param {string} status Status type of notice.
* @return {JSX.Element} Notice component.
*/
const createNoticeUI = ( messages, status ) => {
return (
<Notice
status={ status }
isDismissible={ false }
>
{ messages.map( ( message, index ) => {
return (
<p key={ `message-${ index }` }>
{ message }
</p>
);
} ) }
</Notice>
);
};

/**
* Higher-order component that is used for filtering the PostFeaturedImage component.
*
Expand All @@ -30,29 +55,18 @@ export default createHigherOrderComponent(

const withFeaturedImageNotice = ( props ) => {
const { media } = props;
let noticeUI;

const errors = validateFeaturedImage( media, getMinimumFeaturedImageDimensions(), false );

if ( ! errors ) {
return <PostFeaturedImage { ...props } />;
if ( ! media ) {
const message = __( 'Selecting a featured image is recommended for an optimal user experience.', 'amp' );
noticeUI = createNoticeUI( [ message ], 'notice' );
} else {
const errorMessages = validateFeaturedImage( media, getMinimumFeaturedImageDimensions() );
noticeUI = errorMessages ? createNoticeUI( errorMessages, 'warning' ) : null;
}

return (
<>
<Notice
status="warning"
isDismissible={ false }
>
{ errors.map( ( errorMessage, index ) => {
return (
<p key={ `error-${ index }` }>
{ errorMessage }
</p>
);
} ) }
</Notice>
<PostFeaturedImage { ...props } />
</>
<PostFeaturedImage { ...props } noticeUI={ noticeUI } />
);
};

Expand Down
64 changes: 9 additions & 55 deletions assets/src/common/components/pre-publish-panel.js
Original file line number Diff line number Diff line change
@@ -1,73 +1,27 @@
/**
* External dependencies
*/
import PropTypes from 'prop-types';

/**
* WordPress dependencies
*/
import { Notice } from '@wordpress/components';
import { PostFeaturedImage } from '@wordpress/editor';
import { PluginPrePublishPanel } from '@wordpress/edit-post';
import { withSelect } from '@wordpress/data';
import { __ } from '@wordpress/i18n';

/**
* Internal dependencies
*/
import { validateFeaturedImage } from '../helpers';

/**
* Conditionally adds a notice to the pre-publish panel for the featured image.
* Adds a pre-publish panel containing the featured image selection component.
*
* @param {Object} props Component props.
* @param {Object} props.featuredMedia Media object.
* @param {Array} props.dimensions Required image dimensions.
* @param {boolean} props.required Whether selecting a featured image is required.
* @return {Function} Either a plain pre-publish panel, or the panel with a featured image notice.
* Note: The `PostFeaturedImage` component would have already been filtered to include
* any notices for the featured image so there is no need to recreate them here.
*
* @return {Function} A pre-publish panel containing the featured image selection component.
*/
const PrePublishPanel = ( { featuredMedia, dimensions, required } ) => {
const errors = validateFeaturedImage( featuredMedia, dimensions, required );

if ( ! errors ) {
return null;
}

const PrePublishPanel = () => {
return (
<PluginPrePublishPanel
title={ __( 'Featured Image', 'amp' ) }
initialOpen="true"
>
<Notice
status={ required ? 'warning' : 'notice' }
isDismissible={ false }
>
{ errors.map( ( errorMessage, index ) => {
return (
<p key={ `error-${ index }` }>
{ errorMessage }
</p>
);
} ) }
</Notice>
<PostFeaturedImage />
</PluginPrePublishPanel>
);
};

PrePublishPanel.propTypes = {
featuredMedia: PropTypes.object,
dimensions: PropTypes.shape( {
width: PropTypes.number.isRequired,
height: PropTypes.number.isRequired,
} ),
required: PropTypes.bool,
};

export default withSelect( ( select ) => {
const currentPost = select( 'core/editor' ).getCurrentPost();
const editedFeaturedMedia = select( 'core/editor' ).getEditedPostAttribute( 'featured_media' );
const featuredMedia = currentPost.featured_media || editedFeaturedMedia;

return {
featuredMedia: featuredMedia ? select( 'core' ).getMedia( featuredMedia ) : null,
};
} )( PrePublishPanel );
export default PrePublishPanel;
25 changes: 10 additions & 15 deletions assets/src/common/helpers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,24 +65,19 @@ export const getMinimumFeaturedImageDimensions = () => {
/**
* Validates the an image based on requirements.
*
* @param {Object} media A media object.
* @param {string} media.mime_type The media item's mime type.
* @param {Object} media.media_details A media details object with width and height values.
* @param {number} media.media_details.width Media width in pixels.
* @param {number} media.media_details.height Media height in pixels.
* @param {Object} dimensions An object with minimum required width and height values.
* @param {number} dimensions.width Minimum required width value.
* @param {number} dimensions.height Minimum required height value.
* @param {boolean} required Whether the image is required or not.
* @param {Object|null} media A media object.
* @param {string} media.mime_type The media item's mime type.
* @param {Object} media.media_details A media details object with width and height values.
* @param {number} media.media_details.width Media width in pixels.
* @param {number} media.media_details.height Media height in pixels.
* @param {Object} dimensions An object with minimum required width and height values.
* @param {number} dimensions.width Minimum required width value.
* @param {number} dimensions.height Minimum required height value.
* @return {string[]|null} Validation errors, or null if there were no errors.
*/
export const validateFeaturedImage = ( media, dimensions, required ) => {
export const validateFeaturedImage = ( media, dimensions ) => {
if ( ! media ) {
if ( required ) {
return [ __( 'Selecting a featured image is required.', 'amp' ) ];
}

return [ __( 'Selecting a featured image is recommended for an optimal user experience.', 'amp' ) ];
return [ __( 'Selecting a featured image is required.', 'amp' ) ];
}

const errors = [];
Expand Down
12 changes: 2 additions & 10 deletions assets/src/common/helpers/test/validateFeaturedImage.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,15 @@
import { validateFeaturedImage } from '../';

describe( 'validateFeaturedImage', () => {
it( 'returns an error if `media` is not an object', () => {
const isValid = validateFeaturedImage( null, {}, false );
expect( isValid ).toStrictEqual( [ 'Selecting a featured image is recommended for an optimal user experience.' ] );
} );

it( 'returns an error if the `media` object is not an object and is required', () => {
const isValid = validateFeaturedImage( null, null, true );
it( 'returns an error if the `media` is not an object', () => {
const isValid = validateFeaturedImage( null, { width: 10, height: 10 } );
expect( isValid ).toStrictEqual( [ 'Selecting a featured image is required.' ] );
} );

it( 'returns an error if the featured image is not an acceptable media format', () => {
const isValid = validateFeaturedImage(
{ mime_type: 'foo', media_details: { width: 11, height: 11 } },
{ width: 10, height: 10 },
false,
);
expect( isValid ).toStrictEqual( [ 'The featured image must be of either JPEG, PNG, GIF, WebP, or SVG format.' ] );
} );
Expand All @@ -27,7 +21,6 @@ describe( 'validateFeaturedImage', () => {
const isValid = validateFeaturedImage(
{ mime_type: 'image/png', media_details: { width: 10, height: 10 } },
{ width: 11, height: 11 },
false,
);
expect( isValid ).toStrictEqual( [ 'The featured image should have a size of at least 11 by 11 pixels.' ] );
} );
Expand All @@ -36,7 +29,6 @@ describe( 'validateFeaturedImage', () => {
const isValid = validateFeaturedImage(
{ mime_type: 'image/png', media_details: { width: 11, height: 11 } },
{ width: 10, height: 10 },
false,
);
expect( isValid ).toBeNull();
} );
Expand Down
Loading

0 comments on commit 96e76b1

Please sign in to comment.