diff --git a/client/coral-admin/src/components/ActionButton.js b/client/coral-admin/src/components/ActionButton.js index 0415b2529..1d1d4d9d0 100644 --- a/client/coral-admin/src/components/ActionButton.js +++ b/client/coral-admin/src/components/ActionButton.js @@ -14,10 +14,9 @@ const ActionButton = ({type = '', user, ...props}) => { className={`${type.toLowerCase()} ${styles.actionButton}`} cStyle={type.toLowerCase()} icon={menuActionsMap[type].icon} - onClick={() => {}} + onClick={type === 'APPROVE' ? props.acceptComment : props.rejectComment} /> ); }; export default ActionButton; - diff --git a/client/coral-admin/src/containers/ModerationQueue/ModerationContainer.js b/client/coral-admin/src/containers/ModerationQueue/ModerationContainer.js index 36836ea0d..44d64219e 100644 --- a/client/coral-admin/src/containers/ModerationQueue/ModerationContainer.js +++ b/client/coral-admin/src/containers/ModerationQueue/ModerationContainer.js @@ -5,7 +5,7 @@ import key from 'keymaster'; import isEqual from 'lodash/isEqual'; import {modQueueQuery} from '../../graphql/queries'; -import {banUser} from '../../graphql/mutations'; +import {banUser, setCommentStatus} from '../../graphql/mutations'; import {fetchSettings} from 'actions/settings'; import {updateAssets} from 'actions/assets'; @@ -52,6 +52,11 @@ class ModerationContainer extends Component { return
; } + if (data.error) { + console.log(data); + return
Error
; + } + if (providedAssetId) { asset = assets.find(asset => asset.id === this.props.params.id); @@ -61,7 +66,6 @@ class ModerationContainer extends Component { } const enablePremodTab = !!data.premod.length; - console.log(props.banUser); return (
@@ -75,6 +79,8 @@ class ModerationContainer extends Component { enablePremodTab={enablePremodTab} suspectWords={settings.wordlist.suspect} showBanUserDialog={props.showBanUserDialog} + acceptComment={props.acceptComment} + rejectComment={props.rejectComment} /> ({ export default compose( connect(mapStateToProps, mapDispatchToProps), + setCommentStatus, modQueueQuery, banUser )(ModerationContainer); diff --git a/client/coral-admin/src/containers/ModerationQueue/ModerationQueue.js b/client/coral-admin/src/containers/ModerationQueue/ModerationQueue.js index 41f0f80bd..322452489 100644 --- a/client/coral-admin/src/containers/ModerationQueue/ModerationQueue.js +++ b/client/coral-admin/src/containers/ModerationQueue/ModerationQueue.js @@ -15,6 +15,8 @@ const ModerationQueue = props => { suspectWords={props.suspectWords} actions={actionsMap[comment.status]} showBanUserDialog={props.showBanUserDialog} + acceptComment={props.acceptComment} + rejectComment={props.rejectComment} {...comment} />; }) diff --git a/client/coral-admin/src/containers/ModerationQueue/components/Comment.js b/client/coral-admin/src/containers/ModerationQueue/components/Comment.js index 7467aa677..eae2f60b2 100644 --- a/client/coral-admin/src/containers/ModerationQueue/components/Comment.js +++ b/client/coral-admin/src/containers/ModerationQueue/components/Comment.js @@ -13,7 +13,7 @@ const lang = new I18n(translations); import I18n from 'coral-framework/modules/i18n/i18n'; import translations from 'coral-admin/src/translations.json'; -const Comment = props => { +const Comment = ({actions = [], ...props}) => { const links = linkify.getMatches(props.body); return ( @@ -30,8 +30,12 @@ const Comment = props => {
{links ? Contains Link : null}
- {props.actions.map((action, i) => - + props.acceptComment({commentId: props.id})} + rejectComment={() => props.rejectComment({commentId: props.id})} showBanUserDialog={() => props.showBanUserDialog(props.user, props.id)} /> )} diff --git a/client/coral-admin/src/graphql/mutations/index.js b/client/coral-admin/src/graphql/mutations/index.js index 372f87e56..5e1503062 100644 --- a/client/coral-admin/src/graphql/mutations/index.js +++ b/client/coral-admin/src/graphql/mutations/index.js @@ -2,6 +2,7 @@ // rejectComment import {graphql} from 'react-apollo'; import SET_USER_STATUS from './setUserStatus.graphql'; +import SET_COMMENT_STATUS from './setCommentStatus.graphql'; export const banUser = graphql(SET_USER_STATUS, { props: ({mutate}) => ({ @@ -14,3 +15,26 @@ export const banUser = graphql(SET_USER_STATUS, { }); }}), }); + +export const setCommentStatus = graphql(SET_COMMENT_STATUS, { + props: ({mutate}) => ({ + acceptComment: ({commentId}) => { + return mutate({ + variables: { + commentId, + status: 'ACCEPTED' + }, + refetchQueries: ['ModQueue'] + }); + }, + rejectComment: ({commentId}) => { + return mutate({ + variables: { + commentId, + status: 'REJECTED' + }, + refetchQueries: ['ModQueue'] + }); + } + }) +}); diff --git a/client/coral-admin/src/graphql/mutations/setCommentStatus.graphql b/client/coral-admin/src/graphql/mutations/setCommentStatus.graphql new file mode 100644 index 000000000..cfcc76421 --- /dev/null +++ b/client/coral-admin/src/graphql/mutations/setCommentStatus.graphql @@ -0,0 +1,3 @@ +mutation setCommentStatus($commentId: ID!, $status: COMMENT_STATUS!){ + setCommentStatus(id: $commentId, status: $status) +} diff --git a/client/coral-admin/src/graphql/queries/index.js b/client/coral-admin/src/graphql/queries/index.js index ab7d61b05..fc59f8f84 100644 --- a/client/coral-admin/src/graphql/queries/index.js +++ b/client/coral-admin/src/graphql/queries/index.js @@ -2,8 +2,7 @@ import {graphql} from 'react-apollo'; import MOD_QUEUE_QUERY from './modQueueQuery.graphql'; export const modQueueQuery = graphql(MOD_QUEUE_QUERY, { - options: (props) => { - const {id = ''} = props.params; + options: ({params: {id = ''}}) => { return { variables: { asset_id: id diff --git a/client/coral-admin/src/graphql/queries/modQueueQuery.graphql b/client/coral-admin/src/graphql/queries/modQueueQuery.graphql index a22a6c808..38ce9af23 100644 --- a/client/coral-admin/src/graphql/queries/modQueueQuery.graphql +++ b/client/coral-admin/src/graphql/queries/modQueueQuery.graphql @@ -2,7 +2,7 @@ query ModQueue ($asset_id: ID!) { all: comments(query: { - statuses: [ACCEPTED, REJECTED, PREMOD], + statuses: [REJECTED, PREMOD], asset_id: $asset_id }) { ...commentView diff --git a/graph/mutators/comment.js b/graph/mutators/comment.js index 6214c9df8..844b47d3c 100644 --- a/graph/mutators/comment.js +++ b/graph/mutators/comment.js @@ -162,22 +162,36 @@ const createPublicComment = (context, commentInput) => { })); }; +/** + * Sets the status of a comment + * @param {String} comment comment in graphql context + * @param {String} id identifier of the comment (uuid) + * @param {String} status the new status of the comment + */ + +const setCommentStatus = ({comment}, {id, status}) => { + return CommentsService.setStatus(id, status) + .then(res => res); +}; + module.exports = (context) => { // TODO: refactor to something that'll return an error in the event an attempt // is made to mutate state while not logged in. There's got to be a better way // to do this. - if (context.user && context.user.can('mutation:createComment')) { + if (context.user && context.user.can('mutation:createComment', 'mutation:setUserStatus')) { return { Comment: { - create: (comment) => createPublicComment(context, comment) + create: (comment) => createPublicComment(context, comment), + setCommentStatus: (action) => setCommentStatus(context, action) } }; } return { Comment: { - create: () => Promise.reject(errors.ErrNotAuthorized) + create: () => Promise.reject(errors.ErrNotAuthorized), + setCommentStatus: () => Promise.reject(errors.ErrNotAuthorized) } }; }; diff --git a/graph/resolvers/root_mutation.js b/graph/resolvers/root_mutation.js index dba537879..1f10d51d9 100644 --- a/graph/resolvers/root_mutation.js +++ b/graph/resolvers/root_mutation.js @@ -29,6 +29,9 @@ const RootMutation = { }, setUserStatus(_, {id, status}, {mutators: {User}}) { return User.setUserStatus({id, status}); + }, + setCommentStatus(_, {id, status}, {mutators: {Comment}}) { + return Comment.setCommentStatus({id, status}); } }; diff --git a/graph/typeDefs.graphql b/graph/typeDefs.graphql index d91dbbdd7..325fe3b5d 100644 --- a/graph/typeDefs.graphql +++ b/graph/typeDefs.graphql @@ -491,8 +491,11 @@ type RootMutation { # Delete an action based on the action id. deleteAction(id: ID!): DeleteActionResponse - # Sets user status + # Sets User status setUserStatus(id: ID!, status: USER_STATUS!): Boolean + + # Sets Comment status + setCommentStatus(id: ID!, status: COMMENT_STATUS!): Boolean } ################################################################################ diff --git a/models/user.js b/models/user.js index 0194ba5f3..bd18aa4c5 100644 --- a/models/user.js +++ b/models/user.js @@ -148,7 +148,8 @@ const USER_GRAPH_OPERATIONS = [ 'mutation:createAction', 'mutation:deleteAction', 'mutation:editName', - 'mutation:setUserStatus' + 'mutation:setUserStatus', + 'mutation:setCommentStatus' ]; /** diff --git a/services/comments.js b/services/comments.js index fc05341cb..bcc534c51 100644 --- a/services/comments.js +++ b/services/comments.js @@ -7,6 +7,12 @@ const ALLOWED_TAGS = [ {name: 'STAFF'} ]; +const STATUSES = [ + 'ACCEPTED', + 'REJECTED', + 'PREMOD', +]; + module.exports = class CommentsService { /** @@ -249,4 +255,25 @@ module.exports = class CommentsService { return CommentModel.find(query); } + + /** + * Sets Comment Status + * @param {String} id identifier of the comment (uuid) + * @param {String} status the new status of the comment + * @return {Promise} + */ + + static setStatus(id, status) { + + // Check to see if the comment status is in the allowable set of statuses. + if (STATUSES.indexOf(status) === -1) { + + // Comment status is not supported! Error out here. + return Promise.reject(new Error(`status ${status} is not supported`)); + } + + return CommentModel.update({id}, { + $set: {status} + }); + } };