Skip to content

Commit

Permalink
Extend curated card collection to support Custom Post Types
Browse files Browse the repository at this point in the history
  • Loading branch information
ravichdev committed Apr 5, 2021
1 parent 5e87899 commit fb08096
Show file tree
Hide file tree
Showing 54 changed files with 2,362 additions and 144 deletions.
8 changes: 8 additions & 0 deletions plugin/assets/css/src/block-editor.css
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,14 @@
width: 100%;
}

.block-editor-block-list__block .material-design-block-handpicked-posts__types__list .components-radio-control__option {
display: inline-block;

& label {
margin-right: 8px;
}
}

.mdc-image-list--with-text-protection .mdc-image-list__supporting {
align-items: start;
height: auto;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@
* limitations under the License.
*/

/**
* External dependencies
*/
import { get } from 'lodash';

/**
* WordPress dependencies
*/
Expand All @@ -36,8 +41,12 @@ import HorizontalCardLayout from './horizontal-card-layout';
* @return {Function} A functional component.
*/
const SinglePost = ( { post, style, attributes } ) => {
const titleTrimmed = post.title.rendered.trim();
let excerpt = post.excerpt.rendered;
const titleTrimmed = get( post, [ 'title', 'rendered' ], '' ).trim();
let excerpt = get( post, [ 'excerpt', 'rendered' ], '' );

if ( ! excerpt ) {
excerpt = get( post, [ 'content', 'rendered' ], '' );
}

const excerptElement = document.createElement( 'div' );
excerptElement.innerHTML = excerpt;
Expand Down
168 changes: 168 additions & 0 deletions plugin/assets/src/block-editor/blocks/common-posts-list/edit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
/**
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**
* External dependencies
*/
import { get, isUndefined, pickBy } from 'lodash';

/**
* WordPress dependencies
*/
import { createHigherOrderComponent } from '@wordpress/compose';
import { withSelect } from '@wordpress/data';
import { useEffect, useState } from '@wordpress/element';

/**
* Internal dependencies
*/
import './style.css';
import NoPosts from './components/no-posts';
import PostsList from './components/posts-list';
import { getPosts } from '../../utils/api';

/**
* Edit component.
*
* @param {Object} props - Component props.
*
* @return {Function} A functional component.
*/
const Edit = props => {
const { postsToDisplay } = props;
const hasPosts = Array.isArray( postsToDisplay ) && postsToDisplay.length;

if ( ! hasPosts ) {
return <NoPosts { ...props } />;
}

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

/**
* @type {Function} A functional component.
*/
const EditWithSelect = withSelect( ( select, props ) => {
const {
category,
postsToShow,
posts,
orderby,
displayFeaturedImage,
style,
} = props.attributes;
const { name } = props;
let { fetchedPosts } = props;

const featuredImageSizeSlug = style === 'list' ? 'medium' : 'large';

const { getEntityRecords, getMedia } = select( 'core' );

let queryArgs = {
categories: category,
per_page: postsToShow,
};

if ( name === 'material/hand-picked-posts' ) {
queryArgs = {
include: posts.map( Number ),
per_page: posts.length,
orderby: 'date',
order: 'desc',
};

if ( orderby ) {
if ( orderby === 'title' ) {
queryArgs.orderby = 'title';
queryArgs.order = 'asc';
} else if ( orderby === 'popularity' ) {
queryArgs.orderby = 'comment_count';
queryArgs.order = 'desc';
}
}
}

const fetchedPostsQuery = pickBy(
queryArgs,
value => ! isUndefined( value )
);

fetchedPosts = Array.isArray( fetchedPosts )
? fetchedPosts
: getEntityRecords( 'postType', 'post', fetchedPostsQuery );

return {
postsToDisplay: ! Array.isArray( fetchedPosts )
? fetchedPosts
: fetchedPosts.map( post => {
if ( displayFeaturedImage && post.featured_media ) {
const image = getMedia( post.featured_media );
let url = get(
image,
[ 'media_details', 'sizes', featuredImageSizeSlug, 'source_url' ],
null
);
if ( ! url ) {
url = get( image, 'source_url', null );
}
return { ...post, featuredImageSourceUrl: url };
}
return post;
} ),
};
} )( Edit );

export default EditWithSelect;

const withGetPosts = createHigherOrderComponent( WrappedComponent => {
return props => {
const { category, posts, orderby, postType } = props.attributes;

const queryArgs = {
categories: category,
include: posts.map( Number ),
per_page: posts.length,
orderby: 'date',
order: 'desc',
};

if ( orderby ) {
if ( orderby === 'title' ) {
queryArgs.orderby = 'title';
queryArgs.order = 'asc';
} else if ( orderby === 'popularity' ) {
queryArgs.orderby = 'comment_count';
queryArgs.order = 'desc';
}
}

const [ postsToDisplay, setPostsToDisplay ] = useState( [] );

useEffect( () => {
getPosts( { selected: posts, postType, queryArgs } )
.then( data => {
setPostsToDisplay( data );
} )
.catch( e => {
console.error( e );
} );
}, [] ); // eslint-disable-line react-hooks/exhaustive-deps

return <WrappedComponent { ...props } fetchedPosts={ postsToDisplay } />;
};
}, 'withGetPosts' );

export const EditWithGetPosts = withGetPosts( EditWithSelect );
18 changes: 14 additions & 4 deletions plugin/assets/src/block-editor/blocks/common-posts-list/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,15 @@
padding: 16px;
}

.single-post-card .mdc-button__label {
white-space: nowrap;
.single-post-card {

& .mdc-card__action--button {
text-transform: none;
}

& .mdc-button__label {
white-space: nowrap;
}
}

/* @todo: Will need refactoring. */
Expand All @@ -36,12 +43,15 @@

.single-post-card__secondary {
padding: 0 16px 8px 16px;

& > p {
margin: 0;
}
}

/* @todo: Will need refactoring. */
.single-post-card__secondary-text-over-media,
.single-post-card__secondary-text-above-media {
padding-top: 1em !important;
padding-top: 16px;
}

.single-post-card__media.mdc-card__media--square {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@
"preview": {
"type": "boolean",
"default": false
},
"postType": {
"type": "string",
"default": "posts-pages"
}
},
"supports": {
Expand All @@ -88,4 +92,4 @@
"full"
]
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,16 @@
/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import { Placeholder, Button } from '@wordpress/components';
import { Placeholder, Button, RadioControl } from '@wordpress/components';
import { useCallback } from '@wordpress/element';
import { __ } from '@wordpress/i18n';

/**
* Internal dependencies
*/
import PostsControl from '../../../components/posts-control';
import genericAttributesSetter from '../../../utils/generic-attributes-setter';
import getConfig from '../../../utils/get-config';

/**
* Posts Picker component.
Expand All @@ -37,6 +38,7 @@ import genericAttributesSetter from '../../../utils/generic-attributes-setter';
*
* @return {Function} A functional component.
*/

const PostsPicker = ( { attributes, debouncedSpeak, setAttributes } ) => {
const setter = useCallback( genericAttributesSetter( setAttributes ) );

Expand All @@ -47,16 +49,37 @@ const PostsPicker = ( { attributes, debouncedSpeak, setAttributes } ) => {
);
};

const boldText = {
fontWeight: 'bold',
textAlign: 'left',
};

return (
<Placeholder
icon={ <i className="material-icons-outlined">library_books</i> }
label={ __( 'Curated Post Collection', 'material-design' ) }
className="material-design-block-products-grid material-design-block-handpicked-posts"
>
{ __( 'Display a selection of hand-picked posts.', 'material-design' ) }
<div className="material-design-block-handpicked-posts__types">
<p>
{ __(
'Display a selection of hand-picked posts.',
'material-design'
) }
</p>

<p style={ boldText }>{ __( 'Content', 'material-design' ) }</p>
<RadioControl
selected={ attributes.postType }
options={ getConfig( 'postTypes' ) }
onChange={ setter( 'postType' ) }
className="material-design-block-handpicked-posts__types__list"
/>
</div>
<div className="material-design-block-handpicked-posts__selection">
<PostsControl
selected={ attributes.posts }
postType={ attributes.postType }
onChange={ setter( 'posts', ( value = [] ) => {
/* istanbul ignore next */
return value.map( ( { id } ) => id );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import PostsPicker from './components/posts-picker';
import HandpickedPostBlockControls from './components/block-controls';
import InspectorControls from '../common-posts-list/components/inspector-controls';
import './editor.css';
import EditWithSelect from '../common-posts-list/edit-with-select';
import { EditWithGetPosts } from '../common-posts-list/edit';
import getConfig from '../../utils/get-config';

/**
Expand Down Expand Up @@ -60,7 +60,7 @@ const Edit = props => {
{ editMode ? (
<PostsPicker { ...props } />
) : (
<EditWithSelect { ...props } />
<EditWithGetPosts { ...props } />
) }
</>
);
Expand Down
2 changes: 1 addition & 1 deletion plugin/assets/src/block-editor/blocks/recent-posts/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
* Internal dependencies
*/
import InspectorControls from './components/inspector-controls';
import EditWithSelect from '../common-posts-list/edit-with-select';
import EditWithSelect from '../common-posts-list/edit';

/**
* Recent Posts Edit component.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,7 @@ export const withGlobalColorDefault = createHigherOrderComponent(
* @return {string} Color value.
*/
export const getColor = ( globalPropName, value ) =>
// eslint-disable-next-line
useMemo( () => {
useMemo( () => {// eslint-disable-line
const materialDesignDefaults = getConfig( 'defaults' );

if (
Expand Down
Loading

0 comments on commit fb08096

Please sign in to comment.