mirror of
https://github.com/wassname/talk.git
synced 2026-08-05 13:30:26 +08:00
GraphQL Review and Responses
This commit is contained in:
@@ -72,7 +72,8 @@ class ModerationContainer extends Component {
|
||||
<ModerationMenu
|
||||
onTabClick={props.onTabClick}
|
||||
enablePremodTab={enablePremodTab}
|
||||
{...moderation} />
|
||||
activeTab={moderation.activeTab}
|
||||
/>
|
||||
<ModerationQueue
|
||||
data={data}
|
||||
activeTab={moderation.activeTab}
|
||||
|
||||
@@ -12,12 +12,12 @@ const ModerationQueue = props => {
|
||||
return <Comment
|
||||
key={i}
|
||||
index={i}
|
||||
comment={comment}
|
||||
suspectWords={props.suspectWords}
|
||||
actions={actionsMap[comment.status]}
|
||||
showBanUserDialog={props.showBanUserDialog}
|
||||
acceptComment={props.acceptComment}
|
||||
rejectComment={props.rejectComment}
|
||||
{...comment}
|
||||
/>;
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, {PropTypes} from 'react';
|
||||
import React from 'react';
|
||||
import timeago from 'timeago.js';
|
||||
import Linkify from 'react-linkify';
|
||||
import Highlighter from 'react-highlight-words';
|
||||
@@ -14,16 +14,16 @@ import I18n from 'coral-framework/modules/i18n/i18n';
|
||||
import translations from 'coral-admin/src/translations.json';
|
||||
|
||||
const Comment = ({actions = [], ...props}) => {
|
||||
const links = linkify.getMatches(props.body);
|
||||
const links = linkify.getMatches(props.comment.body);
|
||||
|
||||
return (
|
||||
<li tabIndex={props.index}
|
||||
className={`mdl-card mdl-shadow--2dp ${styles.Comment} ${styles.listItem} ${props.isActive && !props.hideActive ? styles.activeItem : ''}`}>
|
||||
<div className={styles.itemHeader}>
|
||||
<div className={styles.author}>
|
||||
<span>{props.user.name}</span>
|
||||
<span>{props.comment.user.name}</span>
|
||||
<span className={styles.created}>
|
||||
{timeago().format(props.created_at || (Date.now() - props.index * 60 * 1000), lang.getLocale().replace('-', '_'))}
|
||||
{timeago().format(props.comment.created_at || (Date.now() - props.index * 60 * 1000), lang.getLocale().replace('-', '_'))}
|
||||
</span>
|
||||
{props.flagged ? <p className={styles.flagged}>{lang.t('comment.flagged')}</p> : null}
|
||||
</div>
|
||||
@@ -33,14 +33,14 @@ const Comment = ({actions = [], ...props}) => {
|
||||
{actions.map((action, i) =>
|
||||
<ActionButton key={i}
|
||||
type={action}
|
||||
user={props.user}
|
||||
acceptComment={() => props.acceptComment({commentId: props.id})}
|
||||
rejectComment={() => props.rejectComment({commentId: props.id})}
|
||||
showBanUserDialog={() => props.showBanUserDialog(props.user, props.id)}
|
||||
user={props.comment.user}
|
||||
acceptComment={() => props.acceptComment({commentId: props.comment.id})}
|
||||
rejectComment={() => props.rejectComment({commentId: props.comment.id})}
|
||||
showBanUserDialog={() => props.showBanUserDialog(props.comment.user, props.comment.id)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
{props.user.banned === 'banned' ?
|
||||
{props.comment.user.banned === 'banned' ?
|
||||
<span className={styles.banned}>
|
||||
<Icon name='error_outline'/>
|
||||
{lang.t('comment.banned_user')}
|
||||
@@ -50,13 +50,13 @@ const Comment = ({actions = [], ...props}) => {
|
||||
</div>
|
||||
|
||||
<div className={styles.moderateArticle}>
|
||||
{props.asset.title} <Link to={`/admin/moderate/${props.asset.id}`}>Moderate Article</Link>
|
||||
{props.comment.asset.title} <Link to={`/admin/moderate/${props.comment.asset.id}`}>Moderate Article</Link>
|
||||
</div>
|
||||
|
||||
<div className={styles.itemBody}>
|
||||
<p className={styles.body}>
|
||||
<Linkify component='span' properties={{style: linkStyles}}>
|
||||
<Highlighter searchWords={props.suspectWords} textToHighlight={props.body}/>
|
||||
<Highlighter searchWords={props.suspectWords} textToHighlight={props.comment.body}/>
|
||||
</Linkify>
|
||||
</p>
|
||||
</div>
|
||||
@@ -74,9 +74,4 @@ const linkStyles = {
|
||||
padding: '1px 2px'
|
||||
};
|
||||
|
||||
Comment.propTypes = {
|
||||
user: PropTypes.object.isRequired,
|
||||
asset: PropTypes.object.isRequired
|
||||
};
|
||||
|
||||
export default Comment;
|
||||
|
||||
+11
-10
@@ -179,19 +179,20 @@ 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', 'mutation:setUserStatus')) {
|
||||
return {
|
||||
Comment: {
|
||||
create: (comment) => createPublicComment(context, comment),
|
||||
setCommentStatus: (action) => setCommentStatus(context, action)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
let mutators = {
|
||||
Comment: {
|
||||
create: () => Promise.reject(errors.ErrNotAuthorized),
|
||||
setCommentStatus: () => Promise.reject(errors.ErrNotAuthorized)
|
||||
}
|
||||
};
|
||||
|
||||
if (context.user && context.user.can('mutation:createComment')) {
|
||||
mutators.Comment.create = (comment) => createPublicComment(context, comment);
|
||||
}
|
||||
|
||||
if (context.user && context.user.can('mutation:setCommentStatus')) {
|
||||
mutators.Comment.setCommentStatus = (action) => setCommentStatus(context, action);
|
||||
}
|
||||
|
||||
return mutators;
|
||||
};
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
const errors = require('../../errors');
|
||||
const UsersService = require('../../services/users');
|
||||
|
||||
const setUserStatus = ({user}, {id, status}) => {
|
||||
@@ -20,7 +21,7 @@ module.exports = (context) => {
|
||||
|
||||
return {
|
||||
User: {
|
||||
setUserStatus: () => {},
|
||||
setUserStatus: () => Promise.reject(errors.ErrNotAuthorized)
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -28,10 +28,10 @@ const RootMutation = {
|
||||
return wrapResponse(null)(Action.delete({id}));
|
||||
},
|
||||
setUserStatus(_, {id, status}, {mutators: {User}}) {
|
||||
return User.setUserStatus({id, status});
|
||||
return wrapResponse(null)(User.setUserStatus({id, status}));
|
||||
},
|
||||
setCommentStatus(_, {id, status}, {mutators: {Comment}}) {
|
||||
return Comment.setCommentStatus({id, status});
|
||||
return wrapResponse(null)(Comment.setCommentStatus({id, status}));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+18
-2
@@ -476,6 +476,22 @@ type DeleteActionResponse implements Response {
|
||||
errors: [UserError]
|
||||
}
|
||||
|
||||
# SetUserStatusResponse is the response returned with possibly some errors
|
||||
# relating to the delete action attempt.
|
||||
type SetUserStatusResponse implements Response {
|
||||
|
||||
# An array of errors relating to the mutation that occured.
|
||||
errors: [UserError]
|
||||
}
|
||||
|
||||
# SetCommentStatusResponse is the response returned with possibly some errors
|
||||
# relating to the delete action attempt.
|
||||
type SetCommentStatusResponse implements Response {
|
||||
|
||||
# An array of errors relating to the mutation that occured.
|
||||
errors: [UserError]
|
||||
}
|
||||
|
||||
# All mutations for the application are defined on this object.
|
||||
type RootMutation {
|
||||
|
||||
@@ -492,10 +508,10 @@ type RootMutation {
|
||||
deleteAction(id: ID!): DeleteActionResponse
|
||||
|
||||
# Sets User status
|
||||
setUserStatus(id: ID!, status: USER_STATUS!): Boolean
|
||||
setUserStatus(id: ID!, status: USER_STATUS!): SetUserStatusResponse
|
||||
|
||||
# Sets Comment status
|
||||
setCommentStatus(id: ID!, status: COMMENT_STATUS!): Boolean
|
||||
setCommentStatus(id: ID!, status: COMMENT_STATUS!): SetCommentStatusResponse
|
||||
}
|
||||
|
||||
################################################################################
|
||||
|
||||
@@ -165,6 +165,10 @@ UserSchema.method('can', function(...actions) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (actions.some((action) => action === 'mutation:setUserStatus' || action === 'mutation:setCommentStatus') && !this.hasRoles('ADMIN')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user