mirror of
https://github.com/wassname/talk.git
synced 2026-07-19 11:28:50 +08:00
Implement indicator subscriptions for moderation
This commit is contained in:
@@ -31,10 +31,16 @@ export const storySearchChange = value => ({
|
||||
});
|
||||
|
||||
export const clearState = () => ({
|
||||
type: actions.MODERATION_CLEAR_STATE,
|
||||
type: actions.CLEAR_STATE,
|
||||
});
|
||||
|
||||
export const selectCommentId = id => ({
|
||||
type: actions.MODERATION_SELECT_COMMENT,
|
||||
type: actions.SELECT_COMMENT,
|
||||
id,
|
||||
});
|
||||
|
||||
// Enable or disable the activity indicator subscriptions.
|
||||
export const setIndicatorTrack = track => ({
|
||||
type: actions.SET_INDICATOR_TRACK,
|
||||
track,
|
||||
});
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
export const TOGGLE_MODAL = 'TOGGLE_MODAL';
|
||||
export const SINGLE_VIEW = 'SINGLE_VIEW';
|
||||
export const HIDE_SHORTCUTS_NOTE = 'HIDE_SHORTCUTS_NOTE';
|
||||
export const SET_SORT_ORDER = 'MODERATION_SET_SORT_ORDER';
|
||||
export const SHOW_STORY_SEARCH = 'SHOW_STORY_SEARCH';
|
||||
export const HIDE_STORY_SEARCH = 'HIDE_STORY_SEARCH';
|
||||
export const STORY_SEARCH_CHANGE_VALUE = 'STORY_SEARCH_CHANGE_VALUE';
|
||||
export const MODERATION_CLEAR_STATE = 'MODERATION_CLEAR_STATE';
|
||||
export const MODERATION_SELECT_COMMENT = 'MODERATION_SELECT_COMMENT';
|
||||
const prefix = `MODERATION`;
|
||||
|
||||
export const TOGGLE_MODAL = `${prefix}_TOGGLE_MODAL`;
|
||||
export const SINGLE_VIEW = `${prefix}_SINGLE_VIEW`;
|
||||
export const HIDE_SHORTCUTS_NOTE = `${prefix}_HIDE_SHORTCUTS_NOTE`;
|
||||
export const SET_SORT_ORDER = `${prefix}_SET_SORT_ORDER`;
|
||||
export const SHOW_STORY_SEARCH = `${prefix}_SHOW_STORY_SEARCH`;
|
||||
export const HIDE_STORY_SEARCH = `${prefix}_HIDE_STORY_SEARCH`;
|
||||
export const STORY_SEARCH_CHANGE_VALUE = `${prefix}_STORY_SEARCH_CHANGE_VALUE`;
|
||||
export const CLEAR_STATE = `${prefix}_CLEAR_STATE`;
|
||||
export const SELECT_COMMENT = `${prefix}_SELECT_COMMENT`;
|
||||
export const SET_INDICATOR_TRACK = `${prefix}_SET_INDICATOR_TRACK`;
|
||||
|
||||
@@ -8,14 +8,19 @@ const initialState = {
|
||||
shortcutsNoteVisible: 'show',
|
||||
sortOrder: 'DESC',
|
||||
selectedCommentId: '',
|
||||
// If true the activity indicator will turn on subscriptions
|
||||
// in order to determine queue counts. Set this to false
|
||||
// if the queue count is determined by other means.
|
||||
indicatorTrack: true,
|
||||
};
|
||||
|
||||
export default function moderation(state = initialState, action) {
|
||||
switch (action.type) {
|
||||
case actions.MODERATION_CLEAR_STATE:
|
||||
case actions.CLEAR_STATE:
|
||||
return {
|
||||
...initialState,
|
||||
shortcutsNoteVisible: state.shortcutsNoteVisible,
|
||||
indicatorTrack: state.indicatorTrack,
|
||||
};
|
||||
case actions.TOGGLE_MODAL:
|
||||
return {
|
||||
@@ -52,11 +57,16 @@ export default function moderation(state = initialState, action) {
|
||||
...state,
|
||||
sortOrder: action.order,
|
||||
};
|
||||
case actions.MODERATION_SELECT_COMMENT:
|
||||
case actions.SELECT_COMMENT:
|
||||
return {
|
||||
...state,
|
||||
selectedCommentId: action.id,
|
||||
};
|
||||
case actions.SET_INDICATOR_TRACK:
|
||||
return {
|
||||
...state,
|
||||
indicatorTrack: action.track,
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
||||
@@ -35,10 +35,6 @@ function whoFlagged(user) {
|
||||
class FlaggedAccountsContainer extends Component {
|
||||
subscriptions = [];
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
getCountWithoutDangling() {
|
||||
return this.props.root.flaggedUsers.nodes.filter(
|
||||
node => !isFlaggedUserDangling(node)
|
||||
|
||||
@@ -153,9 +153,6 @@ const enhance = compose(
|
||||
state: { status: { username: [SET, CHANGED] } }
|
||||
}
|
||||
)
|
||||
me {
|
||||
id
|
||||
}
|
||||
}
|
||||
`,
|
||||
})
|
||||
|
||||
@@ -1,11 +1,179 @@
|
||||
import React, { Component } from 'react';
|
||||
import { compose, gql } from 'react-apollo';
|
||||
import Indicator from '../../../components/Indicator';
|
||||
import { withFragments } from 'plugin-api/beta/client/hocs';
|
||||
import { branch, renderNothing } from 'recompose';
|
||||
import { handleIndicatorChange } from '../graphql';
|
||||
import PropTypes from 'prop-types';
|
||||
import { connect } from 'react-redux';
|
||||
import withQueueConfig from '../hoc/withQueueConfig';
|
||||
import baseQueueConfig from '../queueConfig';
|
||||
|
||||
const hideIfNoData = hasNoData => branch(hasNoData, renderNothing);
|
||||
class IndicatorContainer extends Component {
|
||||
subscriptions = [];
|
||||
|
||||
subscribeToUpdates() {
|
||||
const parameters = [
|
||||
{
|
||||
document: COMMENT_ADDED_SUBSCRIPTION,
|
||||
updateQuery: (
|
||||
prev,
|
||||
{ subscriptionData: { data: { commentAdded: comment } } }
|
||||
) => {
|
||||
return handleIndicatorChange(prev, comment, this.props.queueConfig);
|
||||
},
|
||||
},
|
||||
{
|
||||
document: COMMENT_FLAGGED_SUBSCRIPTION,
|
||||
updateQuery: (
|
||||
prev,
|
||||
{ subscriptionData: { data: { commentFlagged: comment } } }
|
||||
) => {
|
||||
return handleIndicatorChange(prev, comment, this.props.queueConfig);
|
||||
},
|
||||
},
|
||||
{
|
||||
document: COMMENT_ACCEPTED_SUBSCRIPTION,
|
||||
updateQuery: (
|
||||
prev,
|
||||
{ subscriptionData: { data: { commentAccepted: comment } } }
|
||||
) => {
|
||||
return handleIndicatorChange(prev, comment, this.props.queueConfig);
|
||||
},
|
||||
},
|
||||
{
|
||||
document: COMMENT_REJECTED_SUBSCRIPTION,
|
||||
updateQuery: (
|
||||
prev,
|
||||
{ subscriptionData: { data: { commentRejected: { comment } } } }
|
||||
) => {
|
||||
return handleIndicatorChange(prev, comment, this.props.queueConfig);
|
||||
},
|
||||
},
|
||||
{
|
||||
document: COMMENT_RESET_SUBSCRIPTION,
|
||||
updateQuery: (
|
||||
prev,
|
||||
{ subscriptionData: { data: { commentReset: { comment } } } }
|
||||
) => {
|
||||
return handleIndicatorChange(prev, comment, this.props.queueConfig);
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
this.subscriptions = parameters.map(param =>
|
||||
this.props.data.subscribeToMore(param)
|
||||
);
|
||||
}
|
||||
|
||||
unsubscribe() {
|
||||
this.subscriptions.forEach(unsubscribe => unsubscribe());
|
||||
this.subscriptions = [];
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
if (this.props.track) {
|
||||
this.subscribeToUpdates();
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.unsubscribe();
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (!this.props.track && nextProps.track) {
|
||||
this.subscribeToUpdates();
|
||||
}
|
||||
if (this.props.track && !nextProps.track) {
|
||||
this.unsubscribe();
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
if (
|
||||
!this.props.root ||
|
||||
(!this.props.root.premodCount && !this.props.root.reportedCount)
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return <Indicator />;
|
||||
}
|
||||
}
|
||||
|
||||
IndicatorContainer.propTypes = {
|
||||
data: PropTypes.object,
|
||||
root: PropTypes.object,
|
||||
track: PropTypes.bool,
|
||||
queueConfig: PropTypes.object,
|
||||
};
|
||||
|
||||
const fields = `
|
||||
status
|
||||
actions {
|
||||
__typename
|
||||
... on FlagAction {
|
||||
reason
|
||||
}
|
||||
user {
|
||||
id
|
||||
role
|
||||
}
|
||||
}
|
||||
status_history {
|
||||
type
|
||||
assigned_by {
|
||||
id
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const COMMENT_ADDED_SUBSCRIPTION = gql`
|
||||
subscription TalkAdmin_ModerationIndicator_CommentAdded {
|
||||
commentAdded {
|
||||
${fields}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const COMMENT_FLAGGED_SUBSCRIPTION = gql`
|
||||
subscription TalkAdmin_ModerationIndicator_CommentFlagged {
|
||||
commentFlagged {
|
||||
${fields}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const COMMENT_ACCEPTED_SUBSCRIPTION = gql`
|
||||
subscription TalkAdmin_ModerationIndicator_CommentAccepted {
|
||||
commentAccepted{
|
||||
${fields}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const COMMENT_REJECTED_SUBSCRIPTION = gql`
|
||||
subscription TalkAdmin_ModerationIndicator_CommentRejected {
|
||||
commentRejected{
|
||||
${fields}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const COMMENT_RESET_SUBSCRIPTION = gql`
|
||||
subscription TalkAdmin_ModerationIndicator_CommentReset {
|
||||
commentReset {
|
||||
${fields}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
track: state.moderation.indicatorTrack,
|
||||
});
|
||||
|
||||
const enhance = compose(
|
||||
connect(mapStateToProps),
|
||||
withFragments({
|
||||
root: gql`
|
||||
fragment TalkAdmin_Moderation_Indicator_root on RootQuery {
|
||||
@@ -19,7 +187,7 @@ const enhance = compose(
|
||||
}
|
||||
`,
|
||||
}),
|
||||
hideIfNoData(props => !props.root.premodCount && !props.root.reportedCount)
|
||||
withQueueConfig(baseQueueConfig)
|
||||
);
|
||||
|
||||
export default enhance(Indicator);
|
||||
export default enhance(IndicatorContainer);
|
||||
|
||||
@@ -27,6 +27,7 @@ import {
|
||||
storySearchChange,
|
||||
clearState,
|
||||
selectCommentId,
|
||||
setIndicatorTrack,
|
||||
} from 'actions/moderation';
|
||||
import withQueueConfig from '../hoc/withQueueConfig';
|
||||
import { notify } from 'coral-framework/actions/notification';
|
||||
@@ -198,11 +199,15 @@ class ModerationContainer extends Component {
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
// Stop activity indicator tracking, as we'll handle it here.
|
||||
this.props.setIndicatorTrack(false);
|
||||
this.props.clearState();
|
||||
this.subscribeToUpdates();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
// Restart activity indicator tracking.
|
||||
this.props.setIndicatorTrack(true);
|
||||
this.unsubscribe();
|
||||
}
|
||||
|
||||
@@ -525,6 +530,7 @@ const mapDispatchToProps = dispatch => ({
|
||||
clearState,
|
||||
notify,
|
||||
selectCommentId,
|
||||
setIndicatorTrack,
|
||||
},
|
||||
dispatch
|
||||
),
|
||||
|
||||
@@ -91,6 +91,22 @@ function getCommentQueues(comment, queueConfig) {
|
||||
return queues;
|
||||
}
|
||||
|
||||
/**
|
||||
* getPreviousCommentQueues determines queues that this comment previously belonged to.
|
||||
*/
|
||||
function getPreviousCommentQueues(comment, queueConfig) {
|
||||
return comment.status_history.length <= 1
|
||||
? []
|
||||
: getCommentQueues(
|
||||
{
|
||||
...comment,
|
||||
status:
|
||||
comment.status_history[comment.status_history.length - 2].type,
|
||||
},
|
||||
queueConfig
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether or not the comment belongs to the queue.
|
||||
*/
|
||||
@@ -203,17 +219,7 @@ export function handleCommentChange(
|
||||
let next = root;
|
||||
|
||||
// Queues that this comment previously belonged to.
|
||||
const prevQueues =
|
||||
comment.status_history.length <= 1
|
||||
? []
|
||||
: getCommentQueues(
|
||||
{
|
||||
...comment,
|
||||
status:
|
||||
comment.status_history[comment.status_history.length - 2].type,
|
||||
},
|
||||
queueConfig
|
||||
);
|
||||
const prevQueues = getPreviousCommentQueues(comment, queueConfig);
|
||||
|
||||
// Queues that this comment needs to be placed.
|
||||
const nextQueues = getCommentQueues(comment, queueConfig);
|
||||
@@ -291,3 +297,34 @@ export function handleCommentChange(
|
||||
});
|
||||
return next;
|
||||
}
|
||||
|
||||
const indicatorQueues = ['premod', 'reported'];
|
||||
|
||||
/**
|
||||
* Track indicator status
|
||||
* @param {Object} root current state of the store
|
||||
* @param {Object} comment comment that was changed
|
||||
* @return {Object} next state of the store
|
||||
*/
|
||||
export function handleIndicatorChange(root, comment, queueConfig) {
|
||||
let next = root;
|
||||
|
||||
// Queues that this comment previously belonged to.
|
||||
const prevQueues = getPreviousCommentQueues(comment, queueConfig);
|
||||
|
||||
// Queues that this comment needs to be placed.
|
||||
const nextQueues = getCommentQueues(comment, queueConfig);
|
||||
|
||||
for (const queue of indicatorQueues) {
|
||||
if (prevQueues.indexOf(queue) === -1 && nextQueues.indexOf(queue) >= 0) {
|
||||
next = increaseCommentCount(next, queue);
|
||||
} else if (
|
||||
prevQueues.indexOf(queue) >= 0 &&
|
||||
nextQueues.indexOf(queue) === -1
|
||||
) {
|
||||
next = decreaseCommentCount(next, queue);
|
||||
}
|
||||
}
|
||||
|
||||
return next;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user