Handle comment flags

This commit is contained in:
Chi Vinh Le
2017-06-16 20:06:13 +07:00
parent 5f450adbaf
commit 2625b372e1
8 changed files with 101 additions and 48 deletions
+11 -34
View File
@@ -14,10 +14,6 @@ const ascending = (a, b) => {
const descending = (a, b) => -ascending(a, b);
function truncate(s, length = 10) {
return (s.length > length) ? `${s.substring(0, length)}...` : s;
}
function queueHasComment(root, queue, id) {
return root[queue].nodes.find((c) => c.id === id);
}
@@ -88,22 +84,16 @@ function getCommentQueues(comment) {
return queues;
}
function showNotification(queue, comment, user) {
const text = `${user.username} ${comment.status.toLowerCase()} comment "${truncate(comment.body, 50)}"`;
notification.info(text);
}
export function handleCommentStatusChange(root, comment, {sort, notify, activeQueue}) {
export function handleCommentStatusChange(root, comment, {sort, notify}) {
let next = root;
const nextQueues = getCommentQueues(comment);
let notificationShown = false;
const showNotificationOnce = (...args) => {
const showNotificationOnce = () => {
if (notificationShown) {
return;
}
const user = comment.status_history[comment.status_history.length - 1].assigned_by;
showNotification(...[...args, user]);
notification.info(notify.text);
notificationShown = true;
};
@@ -111,38 +101,25 @@ export function handleCommentStatusChange(root, comment, {sort, notify, activeQu
if (nextQueues.indexOf(queue) >= 0) {
if (!queueHasComment(next, queue, comment.id)) {
next = addCommentToQueue(next, queue, comment, sort);
if (notify && activeQueue === queue && shouldCommentBeAdded(next, queue, comment, sort)) {
showNotificationOnce(queue, comment);
if (notify && notify.activeQueue === queue && shouldCommentBeAdded(next, queue, comment, sort)) {
showNotificationOnce(comment);
}
}
} else if(queueHasComment(next, queue, comment.id)){
next = removeCommentFromQueue(next, queue, comment.id);
if (notify && activeQueue === queue) {
showNotificationOnce(queue, comment);
if (notify && notify.activeQueue === queue) {
showNotificationOnce(comment);
}
}
if (
queue === 'all'
notify
&& (queue === 'all' || notify.anyQueue)
&& queueHasComment(next, queue, comment.id)
&& notify
&& activeQueue === queue
&& notify.activeQueue === queue
) {
showNotificationOnce(queue, comment);
showNotificationOnce(comment);
}
// TODO: Flagged notification
});
return next;
}
export function handleCommentEdit(root, comment, {sort, activeQueue}) {
if (
queueHasComment(root, activeQueue, comment.id)
|| comment.status.toLowerCase() === activeQueue && shouldCommentBeAdded(root, activeQueue, comment, sort)
) {
const text = `${comment.user.username} edited comment to "${truncate(comment.body, 50)}"`;
notification.info(text);
}
return handleCommentStatusChange(root, comment, {sort, activeQueue});
}
@@ -8,9 +8,10 @@ import {getDefinitionName} from 'coral-framework/utils';
import * as notification from 'coral-admin/src/services/notification';
import t, {timeago} from 'coral-framework/services/i18n';
import update from 'immutability-helper';
import truncate from 'lodash/truncate';
import {withSetUserStatus, withSuspendUser, withSetCommentStatus} from 'coral-framework/graphql/mutations';
import {handleCommentStatusChange, handleCommentEdit} from '../../../graphql/utils';
import {handleCommentStatusChange} from '../../../graphql/utils';
import {fetchSettings} from 'actions/settings';
import {updateAssets} from 'actions/assets';
@@ -44,16 +45,16 @@ class ModerationContainer extends Component {
},
updateQuery: (prev, {subscriptionData: {data: {commentStatusChanged: comment}}}) => {
const user = comment.status_history[comment.status_history.length - 1].assigned_by;
const extraParams = this.props.auth.user.id === user.id
const notify = this.props.auth.user.id === user.id
? {}
: {
notify: true,
activeQueue: this.activeTab,
text: `${user.username} ${comment.status.toLowerCase()} comment "${truncate(comment.body, {lenght: 50})}"`,
anyQueue: false,
};
return handleCommentStatusChange(prev, comment, {
sort: this.props.moderation.sortOrder,
...extraParams,
notify,
});
},
});
@@ -63,14 +64,37 @@ class ModerationContainer extends Component {
variables: {
asset_id: this.props.data.variables.asset_id,
},
updateQuery: (prev, {subscriptionData: {data: {commentEdited}}}) => {
return handleCommentEdit(prev, commentEdited, {
activeQueue: this.activeTab,
updateQuery: (prev, {subscriptionData: {data: {commentEdited: comment}}}) => {
return handleCommentStatusChange(prev, comment, {
sort: this.props.moderation.sortOrder,
notify: {
activeQueue: this.activeTab,
text: `${comment.user.username} edited comment to "${truncate(comment.body, {lenght: 50})}"`,
anyQueue: false,
},
});
},
});
this.subscriptions.push(sub1, sub2);
const sub3 = this.props.data.subscribeToMore({
document: COMMENTS_FLAGGED_SUBSCRIPTION,
variables: {
asset_id: this.props.data.variables.asset_id,
},
updateQuery: (prev, {subscriptionData: {data: {commentFlagged: comment}}}) => {
const user = comment.actions[comment.actions.length - 1].user;
return handleCommentStatusChange(prev, comment, {
sort: this.props.moderation.sortOrder,
notify: {
activeQueue: this.activeTab,
text: `${user.username} flagged comment "${truncate(comment.body, {lenght: 50})}"`,
anyQueue: true,
},
});
},
});
this.subscriptions.push(sub1, sub2, sub3);
}
unsubscribe() {
@@ -216,6 +240,15 @@ const COMMENTS_EDITED_SUBSCRIPTION = gql`
${Comment.fragments.comment}
`;
const COMMENTS_FLAGGED_SUBSCRIPTION = gql`
subscription CommentFlagged($asset_id: ID){
commentFlagged(asset_id: $asset_id){
...${getDefinitionName(Comment.fragments.comment)}
}
}
${Comment.fragments.comment}
`;
const STATUS_CHANGED_SUBSCRIPTION = gql`
subscription CommentStatusChanged($asset_id: ID){
commentStatusChanged(asset_id: $asset_id){
+14 -1
View File
@@ -13,7 +13,16 @@ const {CREATE_ACTION, DELETE_ACTION} = require('../../perms/constants');
* @param {String} action_type type of the action
* @return {Promise} resolves to the action created
*/
const createAction = async ({user = {}}, {item_id, item_type, action_type, group_id, metadata = {}}) => {
const createAction = async ({user = {}, pubsub, loaders: {Comments}}, {item_id, item_type, action_type, group_id, metadata = {}}) => {
let comment;
if (pubsub && item_type === 'COMMENTS') {
comment = await Comments.get.load(item_id);
if (!comment) {
throw new Error('Comment not found');
}
}
let action = await ActionsService.insertUserAction({
item_id,
item_type,
@@ -29,6 +38,10 @@ const createAction = async ({user = {}}, {item_id, item_type, action_type, group
await UsersService.setStatus(item_id, 'PENDING');
}
if (pubsub && comment) {
pubsub.publish('commentFlagged', comment);
}
return action;
};
+3
View File
@@ -8,6 +8,9 @@ const Subscription = {
commentStatusChanged(comment) {
return comment;
},
commentFlagged(comment) {
return comment;
},
};
module.exports = Subscription;
+18 -1
View File
@@ -12,7 +12,9 @@ const {deserializeUser} = require('../services/subscriptions');
const {
SUBSCRIBE_COMMENT_STATUS,
SUBSCRIBE_COMMENT_FLAGS,
SUBSCRIBE_ALL_COMMENT_EDITS,
SUBSCRIBE_ALL_COMMENT_ADDITIONS,
} = require('../perms/constants');
/**
@@ -27,7 +29,12 @@ const setupFunctions = plugins.get('server', 'setupFunctions').reduce((acc, {plu
}, {
commentAdded: (options, args) => ({
commentAdded: {
filter: (comment) => comment.asset_id === args.asset_id
filter: (comment, context) => {
if (!args.asset_id && (!context.user || !context.user.can(SUBSCRIBE_ALL_COMMENT_ADDITIONS))) {
return false;
}
return !args.asset_id || comment.asset_id === args.asset_id;
}
},
}),
commentEdited: (options, args) => ({
@@ -40,6 +47,16 @@ const setupFunctions = plugins.get('server', 'setupFunctions').reduce((acc, {plu
}
},
}),
commentFlagged: (options, args) => ({
commentFlagged: {
filter: ({comment}, context) => {
if (!context.user || !context.user.can(SUBSCRIBE_COMMENT_FLAGS)) {
return false;
}
return !args.asset_id || comment.asset_id === args.asset_id;
}
},
}),
commentStatusChanged: (options, args) => ({
commentStatusChanged: {
filter: ({comment}, context) => {
+8 -1
View File
@@ -948,12 +948,19 @@ type RootMutation {
type Subscription {
# Get an update whenever a comment was added.
commentAdded(asset_id: ID!): Comment
# `asset_id` is required except for users with the `ADMIN` or `MODERATOR` role.
commentAdded(asset_id: ID): Comment
# Get an update whenever a comment was edited.
# `asset_id` is required except for users with the `ADMIN` or `MODERATOR` role.
commentEdited(asset_id: ID): Comment
# Get an update whenever a comment was flagged.
# Requires the `ADMIN` or `MODERATOR` role.
commentFlagged(asset_id: ID): Comment
# Get an update whenever the status of a comment changed due to a moderator action.
# Requires the `ADMIN` or `MODERATOR` role.
commentStatusChanged(asset_id: ID): Comment
}
+2 -1
View File
@@ -26,6 +26,7 @@ module.exports = {
// subscriptions
SUBSCRIBE_COMMENT_STATUS: 'SUBSCRIBE_COMMENT_STATUS',
SUBSCRIBE_ALL_COMMENT_FLAGS: 'SUBSCRIBE_ALL_COMMENT_FLAGS',
SUBSCRIBE_COMMENT_FLAGS: 'SUBSCRIBE_COMMENT_FLAGS',
SUBSCRIBE_ALL_COMMENT_ADDITIONS: 'SUBSCRIBE_ALL_COMMENT_ADDITIONS',
SUBSCRIBE_ALL_COMMENT_EDITS: 'SUBSCRIBE_ALL_COMMENT_EDITS',
};
+3 -1
View File
@@ -3,11 +3,13 @@ const types = require('./constants');
module.exports = (user, perm) => {
switch (perm) {
case types.SUBSCRIBE_COMMENT_FLAGS:
return check(user, ['ADMIN', 'MODERATOR']);
case types.SUBSCRIBE_COMMENT_STATUS:
return check(user, ['ADMIN', 'MODERATOR']);
case types.SUBSCRIBE_ALL_COMMENT_EDITS:
return check(user, ['ADMIN', 'MODERATOR']);
case types.SUBSCRIBE_ALL_COMMENT_FLAGS:
case types.SUBSCRIBE_ALL_COMMENT_ADDITIONS:
return check(user, ['ADMIN', 'MODERATOR']);
default:
break;