Merge pull request #812 from coralproject/view-context-non-public

Allow admins / mods to view context of rejected and premod comments
This commit is contained in:
Kim Gardner
2017-07-28 11:04:30 -04:00
committed by GitHub
5 changed files with 91 additions and 43 deletions
@@ -169,5 +169,5 @@
}
.footer {
min-height: 10px;
}
@@ -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 */
<span className={cn(styles.topRight)}>
@@ -467,44 +468,48 @@ export default class Comment extends React.Component {
</div>
}
</div>
<div className={styles.footer}>
<div className="commentActionsLeft comment__action-container">
<Slot
fill="commentReactions"
{...slotProps}
inline
/>
{!disableReply &&
<ActionButton>
<ReplyButton
onClick={this.showReplyBox}
parentCommentId={parentId || comment.id}
currentUserId={currentUser && currentUser.id}
<div className={cn(styles.footer, 'talk-stream-comment-footer')}>
{isActive &&
<div className={'talk-stream-comment-actions-container'}>
<div className="commentActionsLeft comment__action-container">
<Slot
fill="commentReactions"
{...slotProps}
inline
/>
</ActionButton>}
</div>
<div className="commentActionsRight comment__action-container">
<Slot
fill="commentActions"
wrapperComponent={ActionButton}
{...slotProps}
inline
/>
<ActionButton>
<FlagComment
flaggedByCurrentUser={!!myFlag}
flag={myFlag}
id={comment.id}
author_id={comment.user.id}
postFlag={postFlag}
addNotification={addNotification}
postDontAgree={postDontAgree}
deleteAction={deleteAction}
showSignInDialog={showSignInDialog}
currentUser={currentUser}
/>
</ActionButton>
</div>
{!disableReply &&
<ActionButton>
<ReplyButton
onClick={this.showReplyBox}
parentCommentId={parentId || comment.id}
currentUserId={currentUser && currentUser.id}
/>
</ActionButton>}
</div>
<div className="commentActionsRight comment__action-container">
<Slot
fill="commentActions"
wrapperComponent={ActionButton}
{...slotProps}
inline
/>
<ActionButton>
<FlagComment
flaggedByCurrentUser={!!myFlag}
flag={myFlag}
id={comment.id}
author_id={comment.user.id}
postFlag={postFlag}
addNotification={addNotification}
postDontAgree={postDontAgree}
deleteAction={deleteAction}
showSignInDialog={showSignInDialog}
currentUser={currentUser}
/>
</ActionButton>
</div>
</div>
}
</div>
</div>
</div>
@@ -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 =
@@ -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.
*
+10 -2
View File
@@ -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];