diff --git a/client/components/data/moderate-comment/index.jsx b/client/components/data/moderate-comment/index.jsx new file mode 100644 index 0000000000000..6500ee638c30e --- /dev/null +++ b/client/components/data/moderate-comment/index.jsx @@ -0,0 +1,110 @@ +/** @format */ +/** + * External dependencies + * + */ +import { Component } from 'react'; +import PropTypes from 'prop-types'; +import { connect } from 'react-redux'; +import { get } from 'lodash'; + +/** + * Internal dependencies + */ +import { + bumpStat, + composeAnalytics, + recordTracksEvent, + withAnalytics, +} from 'state/analytics/actions'; +import { changeCommentStatus, deleteComment } from 'state/comments/actions'; +import { getSiteComment } from 'state/selectors'; + +class ModerateComment extends Component { + static propTypes = { + siteId: PropTypes.number, + postId: PropTypes.number, + commentId: PropTypes.number.isRequired, + newStatus: PropTypes.string, + currentStatus: PropTypes.string, + updateCommentStatus: PropTypes.func.isRequired, + destroyComment: PropTypes.func.isRequired, + }; + + componentDidMount() { + this.moderate( this.props ); + } + + componentWillReceiveProps( nextProps ) { + if ( + this.props.siteId === nextProps.siteId && + this.props.postId === nextProps.postId && + this.props.commentId === nextProps.commentId && + this.props.newStatus === nextProps.newStatus + ) { + return; + } + + this.moderate( nextProps ); + } + + moderate( { + siteId, + postId, + commentId, + newStatus, + currentStatus, + updateCommentStatus, + destroyComment, + } ) { + if ( ! siteId || ! postId || ! commentId || ! newStatus || newStatus === currentStatus ) { + return; + } + + if ( 'delete' === newStatus ) { + destroyComment(); + return; + } + + updateCommentStatus(); + } + + render() { + return null; + } +} + +const mapStateToProps = ( state, { siteId, commentId } ) => { + const comment = getSiteComment( state, siteId, commentId ); + + return { + currentStatus: get( comment, 'status' ), + }; +}; + +const mapDispatchToProps = ( dispatch, { siteId, postId, commentId, newStatus } ) => ( { + updateCommentStatus: () => + dispatch( + withAnalytics( + composeAnalytics( + recordTracksEvent( 'calypso_comment_management_change_status_from_email', { + status: newStatus, + } ), + bumpStat( 'calypso_comment_management', 'comment_status_changed_to_' + newStatus ) + ), + changeCommentStatus( siteId, postId, commentId, newStatus ) + ) + ), + destroyComment: () => + dispatch( + withAnalytics( + composeAnalytics( + recordTracksEvent( 'calypso_comment_management_delete' ), + bumpStat( 'calypso_comment_management', 'comment_deleted' ) + ), + deleteComment( siteId, postId, commentId ) + ) + ), +} ); + +export default connect( mapStateToProps, mapDispatchToProps )( ModerateComment ); diff --git a/client/my-sites/comment/comment-permalink.jsx b/client/my-sites/comment/comment-permalink.jsx index 7b126fec61437..3182e20ba3430 100644 --- a/client/my-sites/comment/comment-permalink.jsx +++ b/client/my-sites/comment/comment-permalink.jsx @@ -27,7 +27,7 @@ const CommentPermalink = ( { isLoading, permaLink, translate } ) => ); CommentPermalink.propTypes = { - siteId: PropTypes.number.isRequired, + siteId: PropTypes.number, commentId: PropTypes.number.isRequired, isLoading: PropTypes.bool.isRequired, permaLink: PropTypes.string, diff --git a/client/my-sites/comment/main.jsx b/client/my-sites/comment/main.jsx index e55411f9d41bc..8f4efe5761d29 100644 --- a/client/my-sites/comment/main.jsx +++ b/client/my-sites/comment/main.jsx @@ -11,34 +11,39 @@ import { get } from 'lodash'; /** * Internal dependencies */ -import EmptyContent from 'components/empty-content'; -import getSiteId from 'state/selectors/get-site-id'; import Main from 'components/main'; -import PageViewTracker from 'lib/analytics/page-view-tracker'; +import EmptyContent from 'components/empty-content'; import DocumentHead from 'components/data/document-head'; +import ModerateComment from 'components/data/moderate-comment'; import Comment from 'my-sites/comments/comment'; import CommentPermalink from 'my-sites/comment/comment-permalink'; import CommentListHeader from 'my-sites/comments/comment-list/comment-list-header'; -import { getSiteComment, canCurrentUser } from 'state/selectors'; +import PageViewTracker from 'lib/analytics/page-view-tracker'; import { preventWidows } from 'lib/formatting'; +import { getSiteComment, canCurrentUser } from 'state/selectors'; +import getSiteId from 'state/selectors/get-site-id'; export class CommentView extends Component { static propTypes = { siteId: PropTypes.number, postId: PropTypes.number, commentId: PropTypes.number.isRequired, + action: PropTypes.string, canModerateComments: PropTypes.bool.isRequired, translate: PropTypes.func.isRequired, }; render() { - const { siteId, postId, commentId, canModerateComments, translate } = this.props; + const { siteId, postId, commentId, action, canModerateComments, translate } = this.props; return ( // eslint-disable-next-line wpcalypso/jsx-classname-namespace
+ { canModerateComments && ( + + ) } { ! canModerateComments && ( { return ! isNaN( integer ) && integer > 0 ? integer : false; }; +const sanitizeQueryAction = action => { + if ( ! action ) { + return null; + } + + const validActions = { + approve: 'approved', + unapprove: 'unapproved', + trash: 'trash', + spam: 'spam', + delete: 'delete', + }; + return validActions.hasOwnProperty( action.toLowerCase() ) + ? validActions[ action.toLowerCase() ] + : null; +}; + const changePage = path => pageNumber => { if ( window ) { window.scrollTo( 0, 0 ); @@ -97,33 +107,6 @@ export const postComments = ( { params, path, query, store } ) => { ); }; -const sanitizeQueryAction = action => { - if ( ! action ) { - return null; - } - - const validActions = { - approve: 'approved', - trash: 'trash', - spam: 'spam', - delete: 'delete', - }; - return validActions.hasOwnProperty( action.toLowerCase() ) - ? validActions[ action.toLowerCase() ] - : null; -}; - -const updateCommentStatus = ( siteId, postId, commentId, status ) => - withAnalytics( - composeAnalytics( - recordTracksEvent( 'calypso_comment_management_mail_change_status', { - status, - } ), - bumpStat( 'calypso_comment_management_mail', 'comment_status_changed_to_' + status ) - ), - changeCommentStatus( siteId, postId, commentId, status ) - ); - export const comment = ( { query, params, path, store } ) => { const siteFragment = route.getSiteFragment( path ); const commentId = sanitizeInt( params.comment ); @@ -135,22 +118,6 @@ export const comment = ( { query, params, path, store } ) => { } const action = sanitizeQueryAction( query.action ); - const siteId = sanitizeInt( query.site_id ); - const postId = sanitizeInt( query.post_id ); - - /* SECURITY WARNING - * - * we may not have user capabilities loaded onto state. - * We trust that the API will handle user capabilities for us. - */ - if ( action && siteId && postId ) { - const { dispatch } = store; - if ( 'delete' === action ) { - dispatch( deleteComment( siteId, postId, commentId, { showSuccessNotice: true } ) ); - } else { - dispatch( updateCommentStatus( siteId, postId, commentId, action ) ); - } - } renderWithReduxStore( ,