Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add latest comments block #7941

Merged
merged 36 commits into from
Jul 19, 2018
Merged
Show file tree
Hide file tree
Changes from 35 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
f35aaa9
Start adding latest comments block.
miina Jun 11, 2018
8492bdf
Separate edit.js file. Add style
miina Jun 12, 2018
8d92df9
Fix style. Fix displaying controls.
miina Jun 12, 2018
3f6a3c3
Add tests. Remove isSelected.
miina Jun 19, 2018
e1adac3
Fix style.
miina Jun 19, 2018
eef19de
Fix alignment bar. Fix style.
miina Jun 19, 2018
f5f037b
Fix eslint.
miina Jun 19, 2018
4703249
Remove redundant attribute definition.
miina Jun 19, 2018
62b5391
Adjust style. Use PanelBody title.
miina Jun 21, 2018
e449439
Adjust style according to feedback.
miina Jun 23, 2018
614c0e5
Use RangeControl instead of TextControl
miina Jun 23, 2018
fac0325
Adjust style.
miina Jul 2, 2018
1eed90b
Style fixes.
miina Jul 2, 2018
4b11aaf
Add a wrapper around comment data to avoid issues in case of long tit…
miina Jul 2, 2018
e39bcc3
Revert adding clear.
miina Jul 2, 2018
bce62f6
Code consistency fixes.
miina Jul 5, 2018
4a88a56
Restore fixture file.
miina Jul 5, 2018
3ebb9a6
chore: Tweaks to PR; fix center-alignment by default
tofumatt Jul 11, 2018
6c2d384
chore: Final PR tweaks
tofumatt Jul 12, 2018
79650bf
chore: Final PR tweaks, sorry!
tofumatt Jul 12, 2018
4915fff
chore: Tweaks to comments and whitespace from review
tofumatt Jul 13, 2018
b280c8c
chore: More PR tweaks
tofumatt Jul 13, 2018
fd0395d
chore: Fix PHPCS spaces
tofumatt Jul 13, 2018
71be210
feat: Add no comments display
tofumatt Jul 17, 2018
8d56db8
docs: Add note about _draft_or_post_title
tofumatt Jul 17, 2018
5831208
chore: use edit,
tofumatt Jul 17, 2018
e6021be
Tweak to setCommentsToShow
tofumatt Jul 17, 2018
1b31098
chore: Do not use cross-package imports
tofumatt Jul 17, 2018
93c5a98
chore: Tidy up things and don't type-coerce
tofumatt Jul 17, 2018
8d7f46d
chore: Tiny tweaks
tofumatt Jul 17, 2018
6bc741a
Fix test fixtures
tofumatt Jul 18, 2018
a59a647
chore: Fix PHPCS error
tofumatt Jul 19, 2018
dfc09c1
chore: Improve rendering and other PR tweaks
tofumatt Jul 19, 2018
49441d7
Use validation built-in to blocks
tofumatt Jul 19, 2018
0d4e583
Oops
tofumatt Jul 19, 2018
28ac484
Sigh
tofumatt Jul 19, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions core-blocks/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import * as embed from './embed';
import * as file from './file';
import * as freeform from './freeform';
import * as html from './html';
import * as latestComments from './latest-comments';
import * as latestPosts from './latest-posts';
import * as list from './list';
import * as more from './more';
Expand Down Expand Up @@ -71,6 +72,7 @@ export const registerCoreBlocks = () => {
file,
freeform,
html,
latestComments,
latestPosts,
more,
nextpage,
Expand Down
123 changes: 123 additions & 0 deletions core-blocks/latest-comments/edit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
/**
* WordPress dependencies
*/
import { Component, Fragment } from '@wordpress/element';
import {
Disabled,
PanelBody,
RangeControl,
ToggleControl,
ServerSideRender,
} from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import {
InspectorControls,
BlockAlignmentToolbar,
BlockControls,
} from '@wordpress/editor';

/**
* Internal dependencies.
*/
import './editor.scss';

/**
* Minimum number of comments a user can show using this block.
*
* @type {number}
*/
const MIN_COMMENTS = 1;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO we should JSDoc any constant, even just to establish the convention in encouraging the practice for less-obvious constants.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm cool with that 👍

/**
* Maximum number of comments a user can show using this block.
*
* @type {number}
*/
const MAX_COMMENTS = 100;

class LatestComments extends Component {
constructor() {
super( ...arguments );

this.setAlignment = this.setAlignment.bind( this );
this.setCommentsToShow = this.setCommentsToShow.bind( this );

// Create toggles for each attribute; we create them here rather than
// passing `this.createToggleAttribute( 'displayAvatar' )` directly to
// `onChange` to avoid re-renders.
this.toggleDisplayAvatar = this.createToggleAttribute( 'displayAvatar' );
this.toggleDisplayDate = this.createToggleAttribute( 'displayDate' );
this.toggleDisplayExcerpt = this.createToggleAttribute( 'displayExcerpt' );
}

createToggleAttribute( propName ) {
return () => {
const value = this.props.attributes[ propName ];
const { setAttributes } = this.props;

setAttributes( { [ propName ]: ! value } );
};
}

setAlignment( align ) {
this.props.setAttributes( { align } );
}

setCommentsToShow( commentsToShow ) {
this.props.setAttributes( { commentsToShow } );
}

render() {
const {
align,
commentsToShow,
displayAvatar,
displayDate,
displayExcerpt,
} = this.props.attributes;

return (
<Fragment>
<BlockControls>
<BlockAlignmentToolbar
value={ align }
onChange={ this.setAlignment }
/>
</BlockControls>
<InspectorControls>
<PanelBody title={ __( 'Latest Comments Settings' ) }>
<ToggleControl
label={ __( 'Display avatar' ) }
checked={ displayAvatar }
onChange={ this.toggleDisplayAvatar }
/>
<ToggleControl
label={ __( 'Display date' ) }
checked={ displayDate }
onChange={ this.toggleDisplayDate }
/>
<ToggleControl
label={ __( 'Display excerpt' ) }
checked={ displayExcerpt }
onChange={ this.toggleDisplayExcerpt }
/>
<RangeControl
label={ __( 'Number of comments' ) }
value={ commentsToShow }
onChange={ this.setCommentsToShow }
min={ MIN_COMMENTS }
max={ MAX_COMMENTS }
/>
</PanelBody>
</InspectorControls>
<Disabled>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes me wonder: Is there any case where we want ServerSideRender to not be disabled? Should this be built-in to the render logic of that component?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wondered that too, we should probably open an issue for it. I suppose building it in and then having some escape hatch prop that doesn't disable it would be good.

<ServerSideRender
block="core/latest-comments"
attributes={ this.props.attributes }
/>
</Disabled>
</Fragment>
);
}
}

export default LatestComments;
14 changes: 14 additions & 0 deletions core-blocks/latest-comments/editor.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
.wp-block-latest-comments.has-avatars .avatar {
margin-right: 10px;
}

.wp-block-latest-comments__comment-excerpt p {
font-size: 14px;
line-height: $editor-line-height;
margin: 5px 0 20px;
padding-top: 0;
}

.wp-block-latest-comments.has-avatars .wp-block-latest-comments__comment {
min-height: 36px;
}
44 changes: 44 additions & 0 deletions core-blocks/latest-comments/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/**
* WordPress dependencies.
*/
import { __ } from '@wordpress/i18n';

/**
* Internal dependencies.
*/
import './style.scss';
import edit from './edit';

export const name = 'core/latest-comments';

export const settings = {
title: __( 'Latest Comments' ),

description: __( 'Show a list of your site’s most recent comments.' ),

icon: 'list-view',

category: 'widgets',

keywords: [ __( 'recent comments' ) ],

supports: {
html: false,
},

getEditWrapperProps( attributes ) {
const { align } = attributes;

// TODO: Use consistent values across the app;
// see: https://github.com/WordPress/gutenberg/issues/7908.
if ( [ 'left', 'center', 'right', 'wide', 'full' ].includes( align ) ) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should double check that our new ES2015 prototype member polyfills with Babel 7 useBuiltIns: 'usage' allows this to work as expected in IE11.

This is an ES2015+ method which until recently was not expected to be polyfilled and would therefore error in IE11.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tested it in IE11 and it worked; I could change the align values and nothing errored on me (it touches this code path).

return { 'data-align': align };
}
},

edit,

save() {
return null;
},
};
143 changes: 143 additions & 0 deletions core-blocks/latest-comments/index.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
<?php
/**
* Server-side rendering of the `core/latest-comments` block.
*
* @package gutenberg
*/

// Used to get `_draft_or_post_title`, which prevents empty-title posts from
// appearing with no title.
require_once( ABSPATH . 'wp-admin/includes/template.php' );

/**
* Renders the `core/latest-comments` block on server.
*
* @param array $attributes The block attributes.
*
* @return string Returns the post content with latest comments added.
*/
function gutenberg_render_block_core_latest_comments( $attributes = array() ) {
// This filter is documented in wp-includes/widgets/class-wp-widget-recent-comments.php.
$comments = get_comments( apply_filters( 'widget_comments_args', array(
'number' => $attributes['commentsToShow'],
'status' => 'approve',
'post_status' => 'publish',
) ) );

$list_items_markup = '';
if ( ! empty( $comments ) ) {
// Prime the cache for associated posts. This is copied from \WP_Widget_Recent_Comments::widget().
$post_ids = array_unique( wp_list_pluck( $comments, 'comment_post_ID' ) );
_prime_post_caches( $post_ids, strpos( get_option( 'permalink_structure' ), '%category%' ), false );

foreach ( $comments as $comment ) {
$list_items_markup .= '<li class="wp-block-latest-comments__comment">';
if ( $attributes['displayAvatar'] ) {
$avatar = get_avatar( $comment, 48, '', '', array(
'class' => 'wp-block-latest-comments__comment-avatar',
) );
if ( $avatar ) {
$list_items_markup .= $avatar;
}
}

$list_items_markup .= '<article>';
$list_items_markup .= '<footer class="wp-block-latest-comments__comment-meta">';
$author_url = get_comment_author_url( $comment );
if ( empty( $author_url ) && ! empty( $comment->user_id ) ) {
$author_url = get_author_posts_url( $comment->user_id );
}

$author_markup = '';
if ( $author_url ) {
$author_markup .= '<a class="wp-block-latest-comments__comment-author" href="' . esc_url( $author_url ) . '">' . get_comment_author( $comment ) . '</a>';
} else {
$author_markup .= '<span class="wp-block-latest-comments__comment-author">' . get_comment_author( $comment ) . '</span>';
}

// `_draft_or_post_title` calls `esc_html()` so we don't need to wrap that call in
// `esc_html`.
$post_title = '<a class="wp-block-latest-comments__comment-link" href="' . esc_url( get_comment_link( $comment ) ) . '">' . _draft_or_post_title( $comment->comment_post_ID ) . '</a>';

$list_items_markup .= sprintf(
/* translators: 1: author name (inside <a> or <span> tag, based on if they have a URL), 2: post title related to this comment */
__( '%1$s on %2$s', 'gutenberg' ),
$author_markup,
$post_title
);

if ( $attributes['displayDate'] ) {
$list_items_markup .= sprintf(
'<time datetime="%1$s" class="wp-block-latest-comments__comment-date">%2$s</time>',
esc_attr( get_comment_date( 'c', $comment ) ),
date_i18n( get_option( 'date_format' ), get_comment_date( 'U', $comment ) )
);
}
$list_items_markup .= '</footer>';
if ( $attributes['displayExcerpt'] ) {
$list_items_markup .= '<div class="wp-block-latest-comments__comment-excerpt">' . wpautop( get_comment_excerpt( $comment ) ) . '</div>';
}
$list_items_markup .= '</article></li>';
}
}

$class = 'wp-block-latest-comments';
if ( $attributes['align'] ) {
$class .= " align{$attributes['align']}";
}
if ( $attributes['displayAvatar'] ) {
$class .= ' has-avatars';
}
if ( $attributes['displayDate'] ) {
$class .= ' has-dates';
}
if ( $attributes['displayExcerpt'] ) {
$class .= ' has-excerpts';
}
if ( empty($comments) ) {
$class .= ' no-comments';
}
$classnames = esc_attr( $class );

$block_content = ! empty( $comments ) ? sprintf(
'<ol class="%1$s">%2$s</ol>',
$classnames,
$list_items_markup
) : sprintf( '<div class="%1$s">%2$s</div>',
$classnames,
__( 'No comments to show.', 'gutenberg' )
);

return $block_content;
}

register_block_type( 'core/latest-comments', array(
'attributes' => array(
'className' => array(
'type' => 'string',
),
'commentsToShow' => array(
'type' => 'number',
'default' => 5,
'minimum' => 1,
'maximum' => 100,
),
'displayAvatar' => array(
'type' => 'boolean',
'default' => true,
),
'displayDate' => array(
'type' => 'boolean',
'default' => true,
),
'displayExcerpt' => array(
'type' => 'boolean',
'default' => true,
),
'align' => array(
'type' => 'string',
'enum' => array( 'center', 'left', 'right', 'wide', 'full', '' ),
),
),
'render_callback' => 'gutenberg_render_block_core_latest_comments',
) );
43 changes: 43 additions & 0 deletions core-blocks/latest-comments/style.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
.wp-block-latest-comments__comment {
font-size: 15px;
line-height: 1.1;
list-style: none;
margin-bottom: 1em;

.has-avatars & {
min-height: 36px;
list-style: none;

.wp-block-latest-comments__comment-meta,
.wp-block-latest-comments__comment-excerpt {
margin-left: 52px;
}
}

.has-dates &,
.has-excerpts & {
line-height: 1.5;
}
}

.wp-block-latest-comments__comment-excerpt p {
font-size: 14px;
line-height: 1.8;
margin: 5px 0 20px;
}

.wp-block-latest-comments__comment-date {
color: $dark-gray-100;
display: block;
font-size: 12px;
}

.wp-block-latest-comments .avatar,
.wp-block-latest-comments__comment-avatar {
border-radius: 24px;
display: block;
float: left;
height: 40px;
margin-right: 12px;
width: 40px;
}
1 change: 1 addition & 0 deletions core-blocks/test/fixtures/core__latest-comments.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<!-- wp:latest-comments {"displayAvatar":true,"displayExcerpt":true,"displayTimestamp":true} /-->
Loading