add status to Comment. /comments/pending and /comments/rejected ONLY return the respective comments

This commit is contained in:
Riley Davis
2017-01-12 12:16:13 -07:00
parent 18b35e38a8
commit 3285a5ec29
4 changed files with 119 additions and 107 deletions
+42 -3
View File
@@ -6,10 +6,11 @@ import * as actionTypes from '../constants/actions';
export const fetchModerationQueueComments = () => {
return dispatch => {
dispatch({type: commentTypes.COMMENTS_MODERATION_QUEUE_FETCH_REQUEST});
return Promise.all([
coralApi('/queue/comments/pending'),
coralApi('/comments?status=rejected'),
coralApi('/comments?action_type=flag')
coralApi('/queue/comments/rejected'),
coralApi('/queue/comments/flagged')
])
.then(([pending, rejected, flagged]) => {
@@ -27,11 +28,49 @@ export const fetchModerationQueueComments = () => {
dispatch({type: commentTypes.USERS_MODERATION_QUEUE_FETCH_SUCCESS, users});
dispatch({type: commentTypes.COMMENTS_MODERATION_QUEUE_FETCH_SUCCESS, comments});
dispatch({type: actionTypes.ACTIONS_MODERATION_QUEUE_FETCH_SUCCESS, actions});
});
};
};
export const fetchPendingQueue = () => {
return dispatch => {
dispatch({type: commentTypes.COMMENTS_MODERATION_QUEUE_FETCH_REQUEST});
return coralApi('/queue/comments/pending')
.then(pending => {
dispatch({type: commentTypes.USERS_MODERATION_QUEUE_FETCH_SUCCESS, users: pending.users});
dispatch({type: commentTypes.COMMENTS_MODERATION_QUEUE_FETCH_SUCCESS, comments: pending.comments});
dispatch({type: actionTypes.ACTIONS_MODERATION_QUEUE_FETCH_SUCCESS, actions: pending.actions});
});
};
};
export const fetchRejectedQueue = () => {
return dispatch => {
dispatch({type: commentTypes.COMMENTS_MODERATION_QUEUE_FETCH_REQUEST});
return coralApi('/queue/comments/rejected')
.then(rejected => {
dispatch({type: commentTypes.USERS_MODERATION_QUEUE_FETCH_SUCCESS, users: rejected.users});
dispatch({type: commentTypes.COMMENTS_MODERATION_QUEUE_FETCH_SUCCESS, comments: rejected.comments});
dispatch({type: actionTypes.ACTIONS_MODERATION_QUEUE_FETCH_SUCCESS, actions: rejected.actions});
});
};
};
export const fetchFlaggedQueue = () => {
return dispatch => {
dispatch({type: commentTypes.COMMENTS_MODERATION_QUEUE_FETCH_REQUEST});
return coralApi('/queue/comments/flagged')
.then(flagged => {
dispatch({type: commentTypes.USERS_MODERATION_QUEUE_FETCH_SUCCESS, users: flagged.users});
dispatch({type: commentTypes.COMMENTS_MODERATION_QUEUE_FETCH_SUCCESS, comments: flagged.comments});
dispatch({type: actionTypes.ACTIONS_MODERATION_QUEUE_FETCH_SUCCESS, actions: flagged.actions});
});
};
};
// Create a new comment
export const createComment = (name, body) => {
return (dispatch) => {
@@ -6,7 +6,10 @@ import {
updateStatus,
showBanUserDialog,
hideBanUserDialog,
fetchModerationQueueComments
fetchPendingQueue,
fetchRejectedQueue,
fetchFlaggedQueue,
fetchModerationQueueComments,
} from 'actions/comments';
import {userStatusUpdate} from 'actions/users';
import {fetchSettings} from 'actions/settings';
@@ -54,6 +57,16 @@ class ModerationContainer extends React.Component {
onTabClick(activeTab) {
this.setState({activeTab});
if (activeTab === 'pending') {
this.props.fetchPendingQueue();
} else if (activeTab === 'rejected') {
this.props.fetchRejectedQueue();
} else if (activeTab === 'flagged') {
this.props.fetchFlaggedQueue();
} else {
this.props.fetchModerationQueueComments();
}
}
onClose() {
@@ -90,6 +103,9 @@ const mapDispatchToProps = dispatch => {
return {
fetchSettings: () => dispatch(fetchSettings()),
fetchModerationQueueComments: () => dispatch(fetchModerationQueueComments()),
fetchPendingQueue: () => dispatch(fetchPendingQueue()),
fetchRejectedQueue: () => dispatch(fetchRejectedQueue()),
fetchFlaggedQueue: () => dispatch(fetchFlaggedQueue()),
showBanUserDialog: (userId, userName, commentId) => dispatch(showBanUserDialog(userId, userName, commentId)),
hideBanUserDialog: () => dispatch(hideBanUserDialog(false)),
banUser: (userId, commentId) => dispatch(userStatusUpdate('banned', userId, commentId)).then(() => {
+17 -63
View File
@@ -47,6 +47,7 @@ const CommentSchema = new Schema({
asset_id: String,
author_id: String,
status_history: [StatusSchema],
status: {type: String, default: null},
parent_id: String
}, {
timestamps: {
@@ -84,24 +85,6 @@ CommentSchema.method('filterForUser', function(user = false) {
return this.toJSON();
});
/**
* Sets up a virtual getter function on a comment such that when you try and
* access the `comment.last_status` it returns the last status in the array
* of status's on the comment, or `null` if there was no status_history.
*/
CommentSchema.virtual('status').get(function() {
// Here we are taking advantage of the fact that when documents are inserted
// for the new status on a comment that they are always appended to the end
// of the list in the order that they are inserted, hence, the last status
// is always the most recent.
if (this.status_history && this.status_history.length > 0) {
return this.status_history[this.status_history.length - 1].type;
}
return null;
});
/**
* Creates a new Comment that came from a public source.
* @param {Mixed} comment either a single comment or an array of comments.
@@ -118,7 +101,7 @@ CommentSchema.statics.publicCreate = (comment) => {
body,
asset_id,
parent_id,
status = false,
status = null,
author_id
} = comment;
@@ -130,6 +113,7 @@ CommentSchema.statics.publicCreate = (comment) => {
type: status,
created_at: new Date()
}] : [],
status,
author_id
});
@@ -160,7 +144,7 @@ CommentSchema.statics.findByAssetId = (asset_id) => Comment.find({
*/
CommentSchema.statics.findAcceptedByAssetId = (asset_id) => Comment.find({
asset_id,
'status_history.type': 'accepted'
status: 'accepted'
});
/**
@@ -171,14 +155,8 @@ CommentSchema.statics.findAcceptedByAssetId = (asset_id) => Comment.find({
CommentSchema.statics.findAcceptedAndNewByAssetId = (asset_id) => Comment.find({
asset_id,
$or: [
{
'status_history.type': 'accepted'
},
{
status_history: {
$size: 0
}
}
{status: 'accepted'},
{status: null}
]
});
@@ -205,28 +183,20 @@ CommentSchema.statics.findIdsByActionType = (action_type) => Action
.then((actions) => actions.map(a => a.item_id));
/**
* Find comments by their status_history.
* @param {String} status the status of the comment to search for
* @return {Promise}
* Find comments by current status
* @param {String} status status of the comment to search for
* @return {Promise} resovles to comment array
*/
CommentSchema.statics.findByStatus = (status = false) => {
let q = {};
if (status) {
q['status_history.type'] = status;
} else {
q.status_history = {$size: 0};
}
return Comment.find(q);
CommentSchema.statics.findByStatus = (status = null) => {
return Comment.find({status});
};
/**
* Find comments that need to be moderated (aka moderation queue).
* @param {String} moderationValue pre or post moderation setting. If it is undefined then look at the settings.
* @param {String} asset_id
* @return {Promise}
*/
CommentSchema.statics.moderationQueue = (moderation, asset_id = false) => {
CommentSchema.statics.moderationQueue = (status, asset_id = null) => {
/**
* This adds the asset_id requirement to the query if the asset_id is defined.
@@ -239,25 +209,8 @@ CommentSchema.statics.moderationQueue = (moderation, asset_id = false) => {
return query;
};
// Decide on whether or not we need to load extended options for the
// moderation based on the moderation options.
let comments;
if (moderation === 'pre') {
// Pre-moderation: New comments are shown in the moderator queues immediately.
comments = assetIDWrap(CommentSchema.statics.findByStatus('premod'));
} else {
// Post-moderation: New comments do not appear in moderation queues unless they are flagged by other users.
comments = CommentSchema.statics.findIdsByActionType('flag')
.then((ids) => assetIDWrap(Comment.find({
id: {
$in: ids
}
})));
}
// Pre-moderation: New comments are shown in the moderator queues immediately.
let comments = assetIDWrap(Comment.findByStatus(status));
return comments;
};
@@ -277,7 +230,8 @@ CommentSchema.statics.pushStatus = (id, status, assigned_by = null) => Comment.u
created_at: new Date(),
assigned_by
}
}
},
$set: {status}
});
/**
+43 -40
View File
@@ -4,10 +4,22 @@ const User = require('../../../models/user');
const Action = require('../../../models/action');
const Setting = require('../../../models/setting');
const Asset = require('../../../models/asset');
const authorization = require('../../../middleware/authorization');
const _ = require('lodash');
const router = express.Router();
function gatherActionsAndUsers (comments) {
return Promise.all([
comments,
User.findByIdArray(_.uniq(comments.map((comment) => comment.author_id))),
Action.getActionSummaries(_.uniq([
...comments.map((comment) => comment.id),
...comments.map((comment) => comment.author_id)
]))
]);
}
//==============================================================================
// Get Routes
//==============================================================================
@@ -16,49 +28,40 @@ const router = express.Router();
// depending on the settings. The :moderation overwrites this settings.
// Pre-moderation: New comments are shown in the moderator queues immediately.
// Post-moderation: New comments do not appear in moderation queues unless they are flagged by other users.
router.get('/comments/pending', (req, res, next) => {
router.get('/comments/pending', authorization.needed('admin'), (req, res, next) => {
const {
asset_id
} = req.query;
const {asset_id} = req.query;
let settings = Setting.retrieve();
if (asset_id) {
// In the event that we have an asset_id, we should fetch the asset settings
// in order to actually determine if there is additional comments to parse.
settings = Promise.all([
settings,
Asset.findById(asset_id).select('settings')
]).then(([{moderation}, asset]) => {
if (asset.settings && asset.settings.moderation) {
return {moderation: asset.settings.moderation};
}
return {moderation};
});
}
settings
.then(({moderation}) => {
return Comment.moderationQueue(moderation);
}).then((comments) => {
return Promise.all([
comments,
User.findByIdArray(_.uniq(comments.map((comment) => comment.author_id))),
Action.getActionSummaries(_.uniq([
...comments.map((comment) => comment.id),
...comments.map((comment) => comment.author_id)
]))
]);
})
Comment.moderationQueue('premod', asset_id)
.then(gatherActionsAndUsers)
.then(([comments, users, actions]) => {
res.json({
comments,
users,
actions
});
res.json({comments, users, actions});
})
.catch(error => {
next(error);
});
});
router.get('/comments/rejected', /*authorization.needed('admin'),*/ (req, res, next) => {
const {asset_id} = req.query;
Comment.moderationQueue('rejected', asset_id)
.then(gatherActionsAndUsers)
.then(([comments, users, actions]) => {
res.json({comments, users, actions});
})
.catch(error => {
next(error);
});
});
router.get('/comments/flagged', authorization.needed('admin'), (req, res, next) => {
const {asset_id} = req.query;
Comment.moderationQueue('rejected', asset_id)
.then(gatherActionsAndUsers)
.then(([comments, users, actions]) => {
res.json({comments, users, actions})
})
.catch(error => {
next(error);