Implement approve and live updates

This commit is contained in:
Chi Vinh Le
2017-08-02 21:34:48 +07:00
parent b6b7570bcc
commit da0d0349dd
8 changed files with 142 additions and 16 deletions
@@ -7,6 +7,7 @@ import ModerationMenu from './ModerationMenu';
import ModerationHeader from './ModerationHeader';
import ModerationKeysModal from '../../../components/ModerationKeysModal';
import StorySearch from '../containers/StorySearch';
import Slot from 'coral-framework/components/Slot';
export default class Moderation extends Component {
constructor() {
@@ -100,7 +101,7 @@ export default class Moderation extends Component {
}
render () {
const {root, moderation, settings, viewUserDetail, hideUserDetail, activeTab, getModPath, premodEnabled, ...props} = this.props;
const {root, data, moderation, settings, viewUserDetail, hideUserDetail, activeTab, getModPath, premodEnabled, ...props} = this.props;
const assetId = this.props.params.id;
const {asset} = root;
@@ -184,6 +185,14 @@ export default class Moderation extends Component {
closeSearch={this.closeSearch}
storySearchChange={this.props.storySearchChange}
/>
<Slot
data={data}
root={root}
assset={asset}
activeTab={activeTab}
fill='adminModeration'
/>
</div>
);
}
+1 -1
View File
@@ -129,7 +129,7 @@ export default (document, config = {}) => (WrappedComponent) => {
})
.catch((error) => {
this.context.eventEmitter.emit(`mutation.${name}.error`, {variables, error});
throw new error;
throw error;
});
};
return config.props({...data, mutate});
-10
View File
@@ -350,16 +350,6 @@ const setStatus = async ({user, loaders: {Comments}, pubsub}, {id, status}) => {
// adjust the affected user's karma in the next tick.
process.nextTick(adjustKarma(Comments, 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);
}
return comment;
};
+12 -2
View File
@@ -31,8 +31,18 @@ const RootMutation = {
stopIgnoringUser(_, {id}, {mutators: {User}}) {
return wrapResponse(null)(User.stopIgnoringUser({id}));
},
setCommentStatus(_, {id, status}, {mutators: {Comment}}) {
return wrapResponse(null)(Comment.setStatus({id, status}));
async setCommentStatus(_, {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);
}
return wrapResponse(null)(comment);
},
addTag(_, {tag}, {mutators: {Tag}}) {
return wrapResponse(null)(Tag.add(tag));
@@ -0,0 +1,70 @@
import React from 'react';
import {gql} from 'react-apollo';
import {connect} from 'react-redux';
import Comment from 'coral-admin/src/routes/Moderation/containers/Comment';
import {handleCommentChange} from 'coral-admin/src/graphql/utils';
import {getDefinitionName} from 'coral-framework/utils';
import truncate from 'lodash/truncate';
import t from 'coral-framework/services/i18n';
function prepareNotificationText(text) {
return truncate(text, {length: 50}).replace('\n', ' ');
}
class ModSubscription extends React.Component {
unsubscribe = null;
componentWillMount() {
this.unsubscribe = this.props.data.subscribeToMore({
document: COMMENT_FEATURED_SUBSCRIPTION,
variables: {
assetId: this.props.data.variables.asset_id,
},
updateQuery: (prev, {subscriptionData: {data: {commentFeatured: comment}}}) => {
const sort = this.props.data.variables.sort;
const user = comment.status_history[comment.status_history.length - 1].assigned_by;
const notify = {
activeQueue: this.props.activeTab,
text: t(
'talk-plugin-featured-comments.notify_featured',
user.username,
prepareNotificationText(comment.body)
),
anyQueue: true,
};
return handleCommentChange(prev, comment, sort, notify);
},
});
}
componentWillUnmount() {
this.unsubscribe();
}
render() {
return null;
}
}
const COMMENT_FEATURED_SUBSCRIPTION = gql`
subscription CommentFeatured($assetId: ID){
commentFeatured(asset_id: $assetId){
...${getDefinitionName(Comment.fragments.comment)}
status_history {
type
created_at
assigned_by {
id
username
}
}
}
}
${Comment.fragments.comment}
`;
const mapStateToProps = (state) => ({
sortOrder: state.moderation.toJS().sortOrder,
});
export default connect(mapStateToProps, null)(ModSubscription);
@@ -6,6 +6,7 @@ import translations from './translations.yml';
import update from 'immutability-helper';
import reducer from './reducer';
import ModTag from './containers/ModTag';
import ModSubscription from './containers/ModSubscription';
import {findCommentInEmbedQuery} from 'coral-embed-stream/src/graphql/utils';
import {insertCommentsSorted} from 'plugin-api/beta/client/utils';
@@ -18,7 +19,8 @@ export default {
streamTabPanes: [TabPane],
commentInfoBar: [Tag],
commentReactions: [Button],
adminCommentInfoBar: [ModTag]
adminModeration: [ModSubscription],
adminCommentInfoBar: [ModTag],
},
mutations: {
IgnoreUser: ({variables}) => ({
@@ -6,6 +6,7 @@ en:
featured_comments: Featured Comments
go_to_conversation: Go to conversation
tooltip_description: Comments selected by our team as worth reading
notify_featured: '{0} featured and approved comment "{1}"'
es:
talk-plugin-featured-comments:
un_feature: Desmarcar
@@ -13,4 +14,4 @@ es:
featured: Remarcado
featured_comments: Comentarios Remarcados
go_to_conversation: Ir al comentario
tooltip_description: Comentarios seleccionados por nuestro equipo que valen la pena ser leidos
tooltip_description: Comentarios seleccionados por nuestro equipo que valen la pena ser leidos
@@ -1,4 +1,48 @@
const {check} = require('perms/utils');
module.exports = {
typeDefs: `
type Subscription {
# Subscribe to featured comments.
commentFeatured(asset_id: ID): Comment
}
`,
resolvers: {
Subscription: {
commentFeatured: ({comment}) => {
return comment;
},
},
},
setupFunctions: {
commentFeatured: (options, args) => ({
commentFeatured: {
filter: ({comment}, {user}) => {
if (args.asset_id === null) {
return check(user, ['ADMIN', 'MODERATOR']);
}
return comment.asset_id === args.asset_id;
},
},
}),
},
hooks: {
RootMutation: {
addTag: {
async post(obj, {tag: {name, id, item_type}}, {mutators: {Comment}, pubsub}, info, result) {
if (name === 'FEATURED' && item_type === 'COMMENTS') {
const comment = await Comment.setStatus({id: id, status: 'ACCEPTED'});
if (comment) {
pubsub.publish('commentFeatured', {comment});
}
return result;
}
return result;
},
},
},
},
tags: [
{
name: 'FEATURED',