1 |
|
2 |
|
3 |
|
4 | import { isUndefined, pickBy } from 'lodash';
|
5 | import classnames from 'classnames';
|
6 |
|
7 |
|
8 |
|
9 |
|
10 | import {
|
11 | Component,
|
12 | Fragment,
|
13 | RawHTML,
|
14 | } from '@wordpress/element';
|
15 | import {
|
16 | PanelBody,
|
17 | Placeholder,
|
18 | QueryControls,
|
19 | RangeControl,
|
20 | Spinner,
|
21 | ToggleControl,
|
22 | Toolbar,
|
23 | } from '@wordpress/components';
|
24 | import apiFetch from '@wordpress/api-fetch';
|
25 | import { addQueryArgs } from '@wordpress/url';
|
26 | import { __ } from '@wordpress/i18n';
|
27 | import { dateI18n, format, __experimentalGetSettings } from '@wordpress/date';
|
28 | import {
|
29 | InspectorControls,
|
30 | BlockAlignmentToolbar,
|
31 | BlockControls,
|
32 | } from '@wordpress/block-editor';
|
33 | import { withSelect } from '@wordpress/data';
|
34 |
|
35 |
|
36 |
|
37 |
|
38 | const CATEGORIES_LIST_QUERY = {
|
39 | per_page: -1,
|
40 | };
|
41 | const MAX_POSTS_COLUMNS = 6;
|
42 |
|
43 | class LatestPostsEdit extends Component {
|
44 | constructor() {
|
45 | super( ...arguments );
|
46 | this.state = {
|
47 | categoriesList: [],
|
48 | };
|
49 | this.toggleDisplayPostDate = this.toggleDisplayPostDate.bind( this );
|
50 | }
|
51 |
|
52 | componentWillMount() {
|
53 | this.isStillMounted = true;
|
54 | this.fetchRequest = apiFetch( {
|
55 | path: addQueryArgs( `/wp/v2/categories`, CATEGORIES_LIST_QUERY ),
|
56 | } ).then(
|
57 | ( categoriesList ) => {
|
58 | if ( this.isStillMounted ) {
|
59 | this.setState( { categoriesList } );
|
60 | }
|
61 | }
|
62 | ).catch(
|
63 | () => {
|
64 | if ( this.isStillMounted ) {
|
65 | this.setState( { categoriesList: [] } );
|
66 | }
|
67 | }
|
68 | );
|
69 | }
|
70 |
|
71 | componentWillUnmount() {
|
72 | this.isStillMounted = false;
|
73 | }
|
74 |
|
75 | toggleDisplayPostDate() {
|
76 | const { displayPostDate } = this.props.attributes;
|
77 | const { setAttributes } = this.props;
|
78 |
|
79 | setAttributes( { displayPostDate: ! displayPostDate } );
|
80 | }
|
81 |
|
82 | render() {
|
83 | const { attributes, setAttributes, latestPosts } = this.props;
|
84 | const { categoriesList } = this.state;
|
85 | const { displayPostDate, align, postLayout, columns, order, orderBy, categories, postsToShow } = attributes;
|
86 |
|
87 | const inspectorControls = (
|
88 | <InspectorControls>
|
89 | <PanelBody title={ __( 'Latest Posts Settings' ) }>
|
90 | <QueryControls
|
91 | { ...{ order, orderBy } }
|
92 | numberOfItems={ postsToShow }
|
93 | categoriesList={ categoriesList }
|
94 | selectedCategoryId={ categories }
|
95 | onOrderChange={ ( value ) => setAttributes( { order: value } ) }
|
96 | onOrderByChange={ ( value ) => setAttributes( { orderBy: value } ) }
|
97 | onCategoryChange={ ( value ) => setAttributes( { categories: '' !== value ? value : undefined } ) }
|
98 | onNumberOfItemsChange={ ( value ) => setAttributes( { postsToShow: value } ) }
|
99 | />
|
100 | <ToggleControl
|
101 | label={ __( 'Display post date' ) }
|
102 | checked={ displayPostDate }
|
103 | onChange={ this.toggleDisplayPostDate }
|
104 | />
|
105 | { postLayout === 'grid' &&
|
106 | <RangeControl
|
107 | label={ __( 'Columns' ) }
|
108 | value={ columns }
|
109 | onChange={ ( value ) => setAttributes( { columns: value } ) }
|
110 | min={ 2 }
|
111 | max={ ! hasPosts ? MAX_POSTS_COLUMNS : Math.min( MAX_POSTS_COLUMNS, latestPosts.length ) }
|
112 | required
|
113 | />
|
114 | }
|
115 | </PanelBody>
|
116 | </InspectorControls>
|
117 | );
|
118 |
|
119 | const hasPosts = Array.isArray( latestPosts ) && latestPosts.length;
|
120 | if ( ! hasPosts ) {
|
121 | return (
|
122 | <Fragment>
|
123 | { inspectorControls }
|
124 | <Placeholder
|
125 | icon="admin-post"
|
126 | label={ __( 'Latest Posts' ) }
|
127 | >
|
128 | { ! Array.isArray( latestPosts ) ?
|
129 | <Spinner /> :
|
130 | __( 'No posts found.' )
|
131 | }
|
132 | </Placeholder>
|
133 | </Fragment>
|
134 | );
|
135 | }
|
136 |
|
137 |
|
138 | const displayPosts = latestPosts.length > postsToShow ?
|
139 | latestPosts.slice( 0, postsToShow ) :
|
140 | latestPosts;
|
141 |
|
142 | const layoutControls = [
|
143 | {
|
144 | icon: 'list-view',
|
145 | title: __( 'List View' ),
|
146 | onClick: () => setAttributes( { postLayout: 'list' } ),
|
147 | isActive: postLayout === 'list',
|
148 | },
|
149 | {
|
150 | icon: 'grid-view',
|
151 | title: __( 'Grid View' ),
|
152 | onClick: () => setAttributes( { postLayout: 'grid' } ),
|
153 | isActive: postLayout === 'grid',
|
154 | },
|
155 | ];
|
156 |
|
157 | const dateFormat = __experimentalGetSettings().formats.date;
|
158 |
|
159 | return (
|
160 | <Fragment>
|
161 | { inspectorControls }
|
162 | <BlockControls>
|
163 | <BlockAlignmentToolbar
|
164 | value={ align }
|
165 | onChange={ ( nextAlign ) => {
|
166 | setAttributes( { align: nextAlign } );
|
167 | } }
|
168 | />
|
169 | <Toolbar controls={ layoutControls } />
|
170 | </BlockControls>
|
171 | <ul
|
172 | className={ classnames( this.props.className, {
|
173 | 'is-grid': postLayout === 'grid',
|
174 | 'has-dates': displayPostDate,
|
175 | [ `columns-${ columns }` ]: postLayout === 'grid',
|
176 | } ) }
|
177 | >
|
178 | { displayPosts.map( ( post, i ) => {
|
179 | const titleTrimmed = post.title.rendered.trim();
|
180 | return (
|
181 | <li key={ i }>
|
182 | <a href={ post.link } target="_blank" rel="noreferrer noopener">
|
183 | { titleTrimmed ? (
|
184 | <RawHTML>
|
185 | { titleTrimmed }
|
186 | </RawHTML>
|
187 | ) :
|
188 | __( '(Untitled)' )
|
189 | }
|
190 | </a>
|
191 | { displayPostDate && post.date_gmt &&
|
192 | <time dateTime={ format( 'c', post.date_gmt ) } className="wp-block-latest-posts__post-date">
|
193 | { dateI18n( dateFormat, post.date_gmt ) }
|
194 | </time>
|
195 | }
|
196 | </li>
|
197 | );
|
198 | } ) }
|
199 | </ul>
|
200 | </Fragment>
|
201 | );
|
202 | }
|
203 | }
|
204 |
|
205 | export default withSelect( ( select, props ) => {
|
206 | const { postsToShow, order, orderBy, categories } = props.attributes;
|
207 | const { getEntityRecords } = select( 'core' );
|
208 | const latestPostsQuery = pickBy( {
|
209 | categories,
|
210 | order,
|
211 | orderby: orderBy,
|
212 | per_page: postsToShow,
|
213 | }, ( value ) => ! isUndefined( value ) );
|
214 | return {
|
215 | latestPosts: getEntityRecords( 'postType', 'post', latestPostsQuery ),
|
216 | };
|
217 | } )( LatestPostsEdit );
|