mirror of
https://github.com/wassname/talk.git
synced 2026-07-08 17:53:12 +08:00
@@ -48,7 +48,7 @@ class SuspendUserDialogContainer extends Component {
|
||||
SuspendUserDialogContainer.propTypes = {
|
||||
open: PropTypes.bool,
|
||||
hideSuspendUserDialog: PropTypes.func,
|
||||
username: PropTypes.object,
|
||||
username: PropTypes.string,
|
||||
};
|
||||
|
||||
const withOrganizationName = withQuery(gql`
|
||||
|
||||
@@ -111,6 +111,17 @@ class ModerationContainer extends Component {
|
||||
return this.handleCommentChange(prev, comment, notifyText);
|
||||
},
|
||||
},
|
||||
{
|
||||
document: COMMENT_RESET_SUBSCRIPTION,
|
||||
variables,
|
||||
updateQuery: (prev, {subscriptionData: {data: {commentReset: comment}}}) => {
|
||||
const user = comment.status_history[comment.status_history.length - 1].assigned_by;
|
||||
const notifyText = this.props.auth.user.id === user.id
|
||||
? ''
|
||||
: t('modqueue.notify_reset', user.username, prepareNotificationText(comment.body));
|
||||
return this.handleCommentChange(prev, comment, notifyText);
|
||||
},
|
||||
},
|
||||
{
|
||||
document: COMMENT_EDITED_SUBSCRIPTION,
|
||||
variables,
|
||||
@@ -299,6 +310,23 @@ const COMMENT_REJECTED_SUBSCRIPTION = gql`
|
||||
${Comment.fragments.comment}
|
||||
`;
|
||||
|
||||
const COMMENT_RESET_SUBSCRIPTION = gql`
|
||||
subscription CommentReset($asset_id: ID){
|
||||
commentReset(asset_id: $asset_id){
|
||||
...${getDefinitionName(Comment.fragments.comment)}
|
||||
status_history {
|
||||
type
|
||||
created_at
|
||||
assigned_by {
|
||||
id
|
||||
username
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
${Comment.fragments.comment}
|
||||
`;
|
||||
|
||||
const LOAD_MORE_QUERY = gql`
|
||||
query CoralAdmin_Moderation_LoadMore($limit: Int = 10, $cursor: Cursor, $sortOrder: SORT_ORDER, $asset_id: ID, $tags:[String!], $statuses:[COMMENT_STATUS!], $action_type: ACTION_TYPE) {
|
||||
comments(query: {limit: $limit, cursor: $cursor, asset_id: $asset_id, statuses: $statuses, sortOrder: $sortOrder, action_type: $action_type, tags: $tags}) {
|
||||
|
||||
@@ -345,7 +345,10 @@ export default class Comment extends React.Component {
|
||||
|
||||
if (!highlighted && this.commentIsRejected(comment)) {
|
||||
return <CommentTombstone action='reject' onUndo={() => {
|
||||
this.props.setCommentStatus({commentId: comment.id, status: 'NONE'});
|
||||
this.props.setCommentStatus({
|
||||
commentId: comment.id,
|
||||
status: comment.status_history[comment.status_history.length - 2].type,
|
||||
});
|
||||
}}/>;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ class CommentTombstone extends React.Component {
|
||||
<p className={styles.commentTombstone}>
|
||||
{this.getCopy()}
|
||||
{this.props.action === 'reject' &&
|
||||
<span className={styles.undo} onClick={this.props.onUndo}>Undo</span>
|
||||
<span className={styles.undo} onClick={this.props.onUndo}>{t('comment.undo_reject')}</span>
|
||||
}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -76,6 +76,9 @@ const singleCommentFragment = gql`
|
||||
id
|
||||
username
|
||||
}
|
||||
status_history {
|
||||
type
|
||||
}
|
||||
action_summaries {
|
||||
__typename
|
||||
count
|
||||
|
||||
@@ -102,6 +102,9 @@ export default {
|
||||
}
|
||||
}
|
||||
}
|
||||
status_history {
|
||||
type
|
||||
}
|
||||
action_summaries {
|
||||
count
|
||||
current_user {
|
||||
@@ -182,6 +185,7 @@ export default {
|
||||
editableUntil: new Date().toISOString(),
|
||||
edited: false,
|
||||
},
|
||||
status_history: [],
|
||||
id: `pending-${uuid()}`,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,6 +138,9 @@ export const withSetCommentStatus = withMutation(
|
||||
const fragment = gql`
|
||||
fragment Talk_SetCommentStatus on Comment {
|
||||
status
|
||||
status_history {
|
||||
type
|
||||
}
|
||||
}`;
|
||||
|
||||
const fragmentId = `Comment_${commentId}`;
|
||||
@@ -145,6 +148,8 @@ export const withSetCommentStatus = withMutation(
|
||||
const data = proxy.readFragment({fragment, id: fragmentId});
|
||||
|
||||
data.status = status;
|
||||
data.status_history = data.status_history ? data.status_history : [];
|
||||
data.status_history.push({__typename: 'CommentStatusHistory', type: status});
|
||||
|
||||
proxy.writeFragment({fragment, id: fragmentId, data});
|
||||
}
|
||||
|
||||
@@ -43,13 +43,11 @@ const RootMutation = {
|
||||
setCommentStatus: async (_, {id, status}, {mutators: {Comment}, pubsub}) => {
|
||||
const comment = await Comment.setStatus({id, status});
|
||||
if (status === 'ACCEPTED') {
|
||||
|
||||
// Publish the comment status change via the subscription.
|
||||
pubsub.publish('commentAccepted', comment);
|
||||
} else if (status === 'REJECTED') {
|
||||
|
||||
// Publish the comment status change via the subscription.
|
||||
pubsub.publish('commentRejected', comment);
|
||||
} else if (status === 'NONE') {
|
||||
pubsub.publish('commentReset', comment);
|
||||
}
|
||||
},
|
||||
addTag: async (_, {tag}, {mutators: {Tag}}) => {
|
||||
|
||||
@@ -11,6 +11,9 @@ const Subscription = {
|
||||
commentRejected(comment) {
|
||||
return comment;
|
||||
},
|
||||
commentReset(comment) {
|
||||
return comment;
|
||||
},
|
||||
commentFlagged(comment) {
|
||||
return comment;
|
||||
},
|
||||
|
||||
@@ -2,6 +2,7 @@ const {
|
||||
SUBSCRIBE_COMMENT_ACCEPTED,
|
||||
SUBSCRIBE_COMMENT_REJECTED,
|
||||
SUBSCRIBE_COMMENT_FLAGGED,
|
||||
SUBSCRIBE_COMMENT_RESET,
|
||||
SUBSCRIBE_ALL_COMMENT_EDITED,
|
||||
SUBSCRIBE_ALL_COMMENT_ADDED,
|
||||
SUBSCRIBE_ALL_USER_SUSPENDED,
|
||||
@@ -93,6 +94,16 @@ const setupFunctions = plugins.get('server', 'setupFunctions').reduce((acc, {plu
|
||||
}
|
||||
},
|
||||
}),
|
||||
commentReset: (options, args) => ({
|
||||
commentReset: {
|
||||
filter: (comment, context) => {
|
||||
if (!context.user || !context.user.can(SUBSCRIBE_COMMENT_RESET)) {
|
||||
return false;
|
||||
}
|
||||
return !args.asset_id || comment.asset_id === args.asset_id;
|
||||
}
|
||||
},
|
||||
}),
|
||||
userSuspended: (options, args) => ({
|
||||
userSuspended: {
|
||||
filter: (user, context) => {
|
||||
|
||||
@@ -1376,6 +1376,10 @@ type Subscription {
|
||||
# Requires the `ADMIN` or `MODERATOR` role.
|
||||
commentRejected(asset_id: ID): Comment
|
||||
|
||||
# Get an update whenever the status of a comment has been reset.
|
||||
# Requires the `ADMIN` or `MODERATOR` role.
|
||||
commentReset(asset_id: ID): Comment
|
||||
|
||||
# Get an update whenever a user has been suspended.
|
||||
# `user_id` must match id of current user except for
|
||||
# users with the `ADMIN` or `MODERATOR` role.
|
||||
|
||||
@@ -17,6 +17,7 @@ en:
|
||||
characters_remaining: "characters remaining"
|
||||
comment:
|
||||
anon: "Anonymous"
|
||||
undo_reject: "Undo"
|
||||
ban_user: "Ban User"
|
||||
comment: "Post a comment"
|
||||
edited: Edited
|
||||
@@ -263,6 +264,7 @@ en:
|
||||
notify_accepted: '{0} accepted comment "{1}"'
|
||||
notify_rejected: '{0} rejected comment "{1}"'
|
||||
notify_flagged: '{0} flagged comment "{1}"'
|
||||
notify_reset: '{0} reset status of comment "{1}"'
|
||||
approve: "Approve"
|
||||
approved: "Approved"
|
||||
ban_user: "Ban"
|
||||
|
||||
@@ -36,6 +36,7 @@ module.exports = {
|
||||
SUBSCRIBE_COMMENT_ACCEPTED: 'SUBSCRIBE_COMMENT_ACCEPTED',
|
||||
SUBSCRIBE_COMMENT_REJECTED: 'SUBSCRIBE_COMMENT_REJECTED',
|
||||
SUBSCRIBE_COMMENT_FLAGGED: 'SUBSCRIBE_COMMENT_FLAGGED',
|
||||
SUBSCRIBE_COMMENT_RESET: 'SUBSCRIBE_COMMENT_RESET',
|
||||
SUBSCRIBE_ALL_COMMENT_ADDED: 'SUBSCRIBE_ALL_COMMENT_ADDED',
|
||||
SUBSCRIBE_ALL_COMMENT_EDITED: 'SUBSCRIBE_ALL_COMMENT_EDITED',
|
||||
SUBSCRIBE_ALL_USER_SUSPENDED: 'SUBSCRIBE_ALL_USER_SUSPENDED',
|
||||
|
||||
@@ -9,6 +9,8 @@ module.exports = (user, perm) => {
|
||||
return check(user, ['ADMIN', 'MODERATOR']);
|
||||
case types.SUBSCRIBE_COMMENT_REJECTED:
|
||||
return check(user, ['ADMIN', 'MODERATOR']);
|
||||
case types.SUBSCRIBE_COMMENT_RESET:
|
||||
return check(user, ['ADMIN', 'MODERATOR']);
|
||||
case types.SUBSCRIBE_ALL_COMMENT_EDITED:
|
||||
return check(user, ['ADMIN', 'MODERATOR']);
|
||||
case types.SUBSCRIBE_ALL_COMMENT_ADDED:
|
||||
|
||||
@@ -33,9 +33,9 @@ const BanUserDialog = ({showBanDialog, closeBanDialog, banUser}) => (
|
||||
);
|
||||
|
||||
BanUserDialog.propTypes = {
|
||||
showBanDialog: PropTypes.func.isRequired,
|
||||
showBanDialog: PropTypes.bool.isRequired,
|
||||
closeBanDialog: PropTypes.func.isRequired,
|
||||
banUser: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default BanUserDialog;
|
||||
export default BanUserDialog;
|
||||
|
||||
Reference in New Issue
Block a user