From 8aad7448187b549c7815e3ced4bb0737abafe49f Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Tue, 27 Feb 2018 23:37:44 +0100 Subject: [PATCH] Only show highlighted comment --- .../src/tabs/stream/components/Comment.js | 640 ++++++++++-------- .../src/tabs/stream/components/Stream.js | 2 +- 2 files changed, 341 insertions(+), 301 deletions(-) diff --git a/client/coral-embed-stream/src/tabs/stream/components/Comment.js b/client/coral-embed-stream/src/tabs/stream/components/Comment.js index f0dcc1017..d75789a63 100644 --- a/client/coral-embed-stream/src/tabs/stream/components/Comment.js +++ b/client/coral-embed-stream/src/tabs/stream/components/Comment.js @@ -169,7 +169,7 @@ export default class Comment extends React.Component { postFlag: PropTypes.func.isRequired, deleteAction: PropTypes.func.isRequired, parentId: PropTypes.string, - highlighted: PropTypes.string, + highlighted: PropTypes.object, notify: PropTypes.func.isRequired, postComment: PropTypes.func.isRequired, depth: PropTypes.number.isRequired, @@ -186,28 +186,7 @@ export default class Comment extends React.Component { postDontAgree: PropTypes.func, animateEnter: PropTypes.bool, commentClassNames: PropTypes.array, - comment: PropTypes.shape({ - depth: PropTypes.number, - action_summaries: PropTypes.array.isRequired, - body: PropTypes.string.isRequired, - id: PropTypes.string.isRequired, - tags: PropTypes.arrayOf( - PropTypes.shape({ - name: PropTypes.string, - }) - ), - replies: PropTypes.object, - user: PropTypes.shape({ - id: PropTypes.string.isRequired, - username: PropTypes.string.isRequired, - }).isRequired, - editing: PropTypes.shape({ - edited: PropTypes.bool, - - // ISO8601 - editableUntil: PropTypes.string, - }), - }).isRequired, + comment: PropTypes.object.isRequired, setCommentStatus: PropTypes.func.isRequired, // edit a comment, passed (id, asset_id, { body }) @@ -301,6 +280,14 @@ export default class Comment extends React.Component { this.props.setActiveReplyBox(''); }; + undoStatus = () => + this.props.setCommentStatus({ + commentId: this.props.comment.id, + status: this.props.comment.status_history[ + this.props.comment.status_history.length - 2 + ].type, + }); + // getVisibileReplies returns a list containing comments // which were authored by current user or comes before the `idCursor`. getVisibileReplies() { @@ -329,6 +316,27 @@ export default class Comment extends React.Component { return view; } + /** + * getConditionalClassNames + * conditionalClassNames adds classNames based on condition + * classnames is an array of objects with key as classnames and value as conditions + * i.e: + * { + * 'myClassName': { tags: [STAFF]} + * } + * + * This will add myClassName to comments tagged with STAFF TAG. + **/ + getConditionalClassNames() { + const { commentClassNames = [] } = this.props; + return mapValues(merge({}, ...commentClassNames), condition => { + if (condition.tags) { + return condition.tags.some(tag => hasTag(this.props.comment.tags, tag)); + } + return false; + }); + } + componentDidMount() { this._isMounted = true; if (this.editWindowExpiryTimeout) { @@ -343,25 +351,51 @@ export default class Comment extends React.Component { }, Math.max(msLeftToEdit, 0)); } } + componentWillUnmount() { if (this.editWindowExpiryTimeout) { this.editWindowExpiryTimeout = clearTimeout(this.editWindowExpiryTimeout); } this._isMounted = false; } - render() { + + renderReplyBox() { + const { + asset, + depth, + comment, + parentId, + postComment, + currentUser, + setActiveReplyBox, + maxCharCount, + notify, + charCountEnable, + } = this.props; + return ( + + ); + } + + renderReplies(view) { const { asset, - data, - root, depth, comment, postFlag, - parentId, highlighted, postComment, currentUser, - postDontAgree, setActiveReplyBox, activeReplyBox, loadMore, @@ -372,39 +406,47 @@ export default class Comment extends React.Component { charCountEnable, showSignInDialog, liveUpdates, - animateEnter, emit, - commentClassNames = [], } = this.props; + return ( + + {view.map(reply => { + return ( + + ); + })} + + ); + } - if (!highlighted && this.commentIsRejected(comment)) { - return ( - { - this.props.setCommentStatus({ - commentId: comment.id, - status: - comment.status_history[comment.status_history.length - 2].type, - }); - }} - /> - ); - } - - if (this.commentIsIgnored(comment)) { - return ; - } - - const view = this.getVisibileReplies(); - - // Inactive comments can be viewed by moderators and admins (e.g. using permalinks). - const isActive = isCommentActive(comment.status); - + renderLoadMoreReplies(view) { + const { comment } = this.props; const { loadingState } = this.state; - const isPending = comment.id.indexOf('pending') >= 0; - const isHighlighted = highlighted === comment.id; - const hasMoreComments = comment.replies && (comment.replies.hasNextPage || @@ -412,6 +454,57 @@ export default class Comment extends React.Component { const moreRepliesCount = this.hasIgnoredReplies() ? -1 : comment.replyCount - view.length; + return ( +
+ +
+ ); + } + + renderRepliesContainer() { + const { highlighted, comment } = this.props; + + // Only render highlighted reply when we are the parent of it. + if (highlighted && highlighted.parent.id === comment.id) { + return this.renderReplies([highlighted]); + } + + // Otherwise render replies in current view and a load more button if needed. + const view = this.getVisibileReplies(); + return [this.renderReplies(view), this.renderLoadMoreReplies(view)]; + } + + renderComment() { + const { + asset, + data, + root, + depth, + comment, + postFlag, + parentId, + highlighted, + currentUser, + postDontAgree, + deleteAction, + disableReply, + maxCharCount, + notify, + charCountEnable, + showSignInDialog, + } = this.props; + + // Inactive comments can be viewed by moderators and admins (e.g. using permalinks). + const isActive = isCommentActive(comment.status); + + const isPending = comment.id.indexOf('pending') >= 0; + const isHighlighted = highlighted && highlighted.id === comment.id; const flagSummary = getActionSummary('FlagActionSummary', comment); const dontAgreeSummary = getActionSummary( 'DontAgreeActionSummary', @@ -424,38 +517,6 @@ export default class Comment extends React.Component { myFlag = dontAgreeSummary.find(s => s.current_user); } - /** - * conditionClassNames - * adds classNames based on condition - * classnames is an array of objects with key as classnames and value as conditions - * i.e: - * { - * 'myClassName': { tags: [STAFF]} - * } - * - * This will add myClassName to comments tagged with STAFF TAG. - * **/ - const conditionalClassNames = mapValues( - merge({}, ...commentClassNames), - condition => { - if (condition.tags) { - return condition.tags.some(tag => hasTag(comment.tags, tag)); - } - return false; - } - ); - - const rootClassName = cn( - 'talk-stream-comment-wrapper', - `talk-stream-comment-wrapper-level-${depth}`, - styles.root, - styles[`rootLevel${depth}`], - { - ...conditionalClassNames, - [styles.enter]: animateEnter, - } - ); - const commentClassName = cn( 'talk-stream-comment', `talk-stream-comment-level-${depth}`, @@ -482,241 +543,220 @@ export default class Comment extends React.Component { }; return ( -
-
- +
+ + +
+
+
+ -
-
+ {isStaff(comment.tags) ? Staff : null} + + +
+ + - -
- {isStaff(comment.tags) ? Staff : null} - - -
- - - - {comment.editing && comment.editing.edited ? ( - -   - ({t('comment.edited')}) - + {comment.editing && comment.editing.edited ? ( + +   + ({t('comment.edited')}) - ) : null} - -
- - - - {isActive && - (currentUser && comment.user.id === currentUser.id) && ( - /* User can edit/delete their own comment for a short window after posting */ - - {this.state.isEditable && ( - - Edit - - )} - )} - {!isActive && } + ) : null} +
-
- {this.state.isEditing ? ( - - ) : ( -
- -
- )} -
-
- {isActive && ( -
-
- - {!disableReply && ( - - - - )} -
-
- - - - -
-
+ + + {isActive && + (currentUser && comment.user.id === currentUser.id) && ( + /* User can edit/delete their own comment for a short window after posting */ + + {this.state.isEditable && ( + + Edit + + )} + )} -
+ {!isActive && }
-
- - {activeReplyBox === comment.id ? ( - - ) : null} - - - {view.map(reply => { - return ( - + {this.state.isEditing ? ( + - ); - })} - -
- + ) : ( +
+ +
+ )} +
+
+ {isActive && ( +
+
+ + + {!disableReply && ( + + + + )} +
+
+ + + + +
+
+ )} +
); } + + render() { + const { + depth, + comment, + activeReplyBox, + highlighted, + animateEnter, + } = this.props; + + if (!highlighted && this.commentIsRejected(comment)) { + return ; + } + + if (this.commentIsIgnored(comment)) { + return ; + } + + const rootClassName = cn( + 'talk-stream-comment-wrapper', + `talk-stream-comment-wrapper-level-${depth}`, + styles.root, + styles[`rootLevel${depth}`], + { + ...this.getConditionalClassNames(), + [styles.enter]: animateEnter, + } + ); + + const id = `c_${comment.id}`; + + return ( +
+ {this.renderComment()} + {activeReplyBox === comment.id && this.renderReplyBox()} + {this.renderRepliesContainer()} +
+ ); + } } // return whether the comment is editable diff --git a/client/coral-embed-stream/src/tabs/stream/components/Stream.js b/client/coral-embed-stream/src/tabs/stream/components/Stream.js index a431b1986..8a6b75be3 100644 --- a/client/coral-embed-stream/src/tabs/stream/components/Stream.js +++ b/client/coral-embed-stream/src/tabs/stream/components/Stream.js @@ -112,7 +112,7 @@ class Stream extends React.Component { postComment={postComment} asset={asset} currentUser={currentUser} - highlighted={comment.id} + highlighted={comment} postFlag={postFlag} postDontAgree={postDontAgree} loadMore={loadNewReplies}