diff --git a/client/coral-embed-stream/src/components/Comment.css b/client/coral-embed-stream/src/components/Comment.css index 713655914..32a034f51 100644 --- a/client/coral-embed-stream/src/components/Comment.css +++ b/client/coral-embed-stream/src/components/Comment.css @@ -169,5 +169,5 @@ } .footer { - + min-height: 10px; } diff --git a/client/coral-embed-stream/src/components/Comment.js b/client/coral-embed-stream/src/components/Comment.js index 54bbfea50..8bece5dc5 100644 --- a/client/coral-embed-stream/src/components/Comment.js +++ b/client/coral-embed-stream/src/components/Comment.js @@ -317,6 +317,7 @@ export default class Comment extends React.Component { } = this.props; const view = this.getVisibileReplies(); + const isActive = ['NONE', 'ACCEPTED'].indexOf(comment.status) >= 0; const {loadingState} = this.state; const isPending = comment.id.indexOf('pending') >= 0; const isHighlighted = highlighted === comment.id; @@ -422,7 +423,7 @@ export default class Comment extends React.Component { {...slotProps} /> - { (currentUser && (comment.user.id === currentUser.id)) && + { isActive && (currentUser && (comment.user.id === currentUser.id)) && /* User can edit/delete their own comment for a short window after posting */ @@ -467,44 +468,48 @@ export default class Comment extends React.Component { } -
-
- - {!disableReply && - - + {isActive && +
+
+ - } -
-
- - - - -
+ {!disableReply && + + + } +
+
+ + + + +
+
+ }
diff --git a/client/coral-embed-stream/src/components/Stream.js b/client/coral-embed-stream/src/components/Stream.js index 8e4e81274..66ffc0fc8 100644 --- a/client/coral-embed-stream/src/components/Stream.js +++ b/client/coral-embed-stream/src/components/Stream.js @@ -16,7 +16,7 @@ import QuestionBox from 'talk-plugin-questionbox/QuestionBox'; import {Button, TabBar, Tab, TabCount, TabContent, TabPane} from 'coral-ui'; import cn from 'classnames'; -import {getTopLevelParent} from '../graphql/utils'; +import {getTopLevelParent, attachCommentToParent} from '../graphql/utils'; import AllCommentsPane from './AllCommentsPane'; import styles from './Stream.css'; @@ -103,7 +103,16 @@ class Stream extends React.Component { const open = asset.closedAt === null; // even though the permalinked comment is the highlighted one, we're displaying its parent + replies - const highlightedComment = comment && getTopLevelParent(comment); + let highlightedComment = comment && getTopLevelParent(comment); + if (highlightedComment) { + const isInactive = ['NONE', 'ACCEPTED'].indexOf(comment.status) === -1; + if (comment.parent && isInactive) { + + // the highlighted comment is not active and as such not in the replies, so we + // attach it to the right parent. + highlightedComment = attachCommentToParent(highlightedComment, comment); + } + } const banned = user && user.status === 'BANNED'; const temporarilySuspended = diff --git a/client/coral-embed-stream/src/graphql/utils.js b/client/coral-embed-stream/src/graphql/utils.js index 1030a3547..ac6298616 100644 --- a/client/coral-embed-stream/src/graphql/utils.js +++ b/client/coral-embed-stream/src/graphql/utils.js @@ -185,6 +185,32 @@ export function insertFetchedCommentsIntoEmbedQuery(root, comments, parent_id) { return applyToCommentsOrigin(root, (origin) => findAndInsertFetchedComments(origin, comments, parent_id)); } +/** + * attachCommentToParent recurses through the comment tree starting at `topLevelComment` + * to find the parent of `comment` and attach it to the replies. + */ +export function attachCommentToParent(topLevelComment, comment) { + if (topLevelComment.id === comment.parent.id) { + return update(topLevelComment, { + replies: { + nodes: { + $apply: (nodes) => insertCommentsSorted(nodes, comment), + }, + }, + replyCount: { + $set: (count) => count + 1, + } + }); + } + return update(topLevelComment, { + replies: { + nodes: { + $apply: (nodes) => nodes.map((node) => attachCommentToParent(node, comment)), + }, + }, + }); +} + /** * Nest a string in itself repeatly until `level` has been reached. * diff --git a/graph/resolvers/asset.js b/graph/resolvers/asset.js index da9114c6a..fb2f6cac5 100644 --- a/graph/resolvers/asset.js +++ b/graph/resolvers/asset.js @@ -1,13 +1,21 @@ const {decorateWithTags} = require('./util'); +const { + SEARCH_NON_NULL_OR_ACCEPTED_COMMENTS, +} = require('../../perms/constants'); const Asset = { recentComments({id}, _, {loaders: {Comments}}) { return Comments.genRecentComments.load(id); }, - async comment({id}, {id: commentId}, {loaders: {Comments}}) { + async comment({id}, {id: commentId}, {loaders: {Comments}, user}) { + const statuses = user && user.can(SEARCH_NON_NULL_OR_ACCEPTED_COMMENTS) + ? ['NONE', 'ACCEPTED', 'PREMOD', 'REJECTED'] + : ['NONE', 'ACCEPTED']; + const comments = await Comments.getByQuery({ asset_id: id, - ids: commentId + ids: commentId, + statuses, }); return comments.nodes[0];