UNPKG

@wordpress/block-library

Version:
218 lines (202 loc) 5.61 kB
/** * External dependencies */ import { isUndefined, pickBy } from 'lodash'; import classnames from 'classnames'; /** * WordPress dependencies */ import { Component, Fragment, RawHTML, } from '@wordpress/element'; import { PanelBody, Placeholder, QueryControls, RangeControl, Spinner, ToggleControl, Toolbar, } from '@wordpress/components'; import apiFetch from '@wordpress/api-fetch'; import { addQueryArgs } from '@wordpress/url'; import { __ } from '@wordpress/i18n'; import { dateI18n, format, __experimentalGetSettings } from '@wordpress/date'; import { InspectorControls, BlockAlignmentToolbar, BlockControls, } from '@wordpress/block-editor'; import { withSelect } from '@wordpress/data'; /** * Module Constants */ const CATEGORIES_LIST_QUERY = { per_page: -1, }; const MAX_POSTS_COLUMNS = 6; class LatestPostsEdit extends Component { constructor() { super( ...arguments ); this.state = { categoriesList: [], }; this.toggleDisplayPostDate = this.toggleDisplayPostDate.bind( this ); } componentWillMount() { this.isStillMounted = true; this.fetchRequest = apiFetch( { path: addQueryArgs( `/wp/v2/categories`, CATEGORIES_LIST_QUERY ), } ).then( ( categoriesList ) => { if ( this.isStillMounted ) { this.setState( { categoriesList } ); } } ).catch( () => { if ( this.isStillMounted ) { this.setState( { categoriesList: [] } ); } } ); } componentWillUnmount() { this.isStillMounted = false; } toggleDisplayPostDate() { const { displayPostDate } = this.props.attributes; const { setAttributes } = this.props; setAttributes( { displayPostDate: ! displayPostDate } ); } render() { const { attributes, setAttributes, latestPosts } = this.props; const { categoriesList } = this.state; const { displayPostDate, align, postLayout, columns, order, orderBy, categories, postsToShow } = attributes; const inspectorControls = ( <InspectorControls> <PanelBody title={ __( 'Latest Posts Settings' ) }> <QueryControls { ...{ order, orderBy } } numberOfItems={ postsToShow } categoriesList={ categoriesList } selectedCategoryId={ categories } onOrderChange={ ( value ) => setAttributes( { order: value } ) } onOrderByChange={ ( value ) => setAttributes( { orderBy: value } ) } onCategoryChange={ ( value ) => setAttributes( { categories: '' !== value ? value : undefined } ) } onNumberOfItemsChange={ ( value ) => setAttributes( { postsToShow: value } ) } /> <ToggleControl label={ __( 'Display post date' ) } checked={ displayPostDate } onChange={ this.toggleDisplayPostDate } /> { postLayout === 'grid' && <RangeControl label={ __( 'Columns' ) } value={ columns } onChange={ ( value ) => setAttributes( { columns: value } ) } min={ 2 } max={ ! hasPosts ? MAX_POSTS_COLUMNS : Math.min( MAX_POSTS_COLUMNS, latestPosts.length ) } required /> } </PanelBody> </InspectorControls> ); const hasPosts = Array.isArray( latestPosts ) && latestPosts.length; if ( ! hasPosts ) { return ( <Fragment> { inspectorControls } <Placeholder icon="admin-post" label={ __( 'Latest Posts' ) } > { ! Array.isArray( latestPosts ) ? <Spinner /> : __( 'No posts found.' ) } </Placeholder> </Fragment> ); } // Removing posts from display should be instant. const displayPosts = latestPosts.length > postsToShow ? latestPosts.slice( 0, postsToShow ) : latestPosts; const layoutControls = [ { icon: 'list-view', title: __( 'List View' ), onClick: () => setAttributes( { postLayout: 'list' } ), isActive: postLayout === 'list', }, { icon: 'grid-view', title: __( 'Grid View' ), onClick: () => setAttributes( { postLayout: 'grid' } ), isActive: postLayout === 'grid', }, ]; const dateFormat = __experimentalGetSettings().formats.date; return ( <Fragment> { inspectorControls } <BlockControls> <BlockAlignmentToolbar value={ align } onChange={ ( nextAlign ) => { setAttributes( { align: nextAlign } ); } } /> <Toolbar controls={ layoutControls } /> </BlockControls> <ul className={ classnames( this.props.className, { 'is-grid': postLayout === 'grid', 'has-dates': displayPostDate, [ `columns-${ columns }` ]: postLayout === 'grid', } ) } > { displayPosts.map( ( post, i ) => { const titleTrimmed = post.title.rendered.trim(); return ( <li key={ i }> <a href={ post.link } target="_blank" rel="noreferrer noopener"> { titleTrimmed ? ( <RawHTML> { titleTrimmed } </RawHTML> ) : __( '(Untitled)' ) } </a> { displayPostDate && post.date_gmt && <time dateTime={ format( 'c', post.date_gmt ) } className="wp-block-latest-posts__post-date"> { dateI18n( dateFormat, post.date_gmt ) } </time> } </li> ); } ) } </ul> </Fragment> ); } } export default withSelect( ( select, props ) => { const { postsToShow, order, orderBy, categories } = props.attributes; const { getEntityRecords } = select( 'core' ); const latestPostsQuery = pickBy( { categories, order, orderby: orderBy, per_page: postsToShow, }, ( value ) => ! isUndefined( value ) ); return { latestPosts: getEntityRecords( 'postType', 'post', latestPostsQuery ), }; } )( LatestPostsEdit );