mirror of
https://github.com/wassname/talk.git
synced 2026-07-02 06:48:46 +08:00
Refactor state updater
This commit is contained in:
@@ -1,62 +1,111 @@
|
||||
import update from 'immutability-helper';
|
||||
import * as notification from 'coral-admin/src/services/notification';
|
||||
|
||||
export function findCommentInModQueues(root, id, queues = ['all', 'premod', 'flagged', 'accepted', 'rejected']) {
|
||||
return queues.reduce((comment, queue) => {
|
||||
return comment ? comment : root[queue].nodes.find((c) => c.id === id);
|
||||
}, null);
|
||||
const queues = ['all', 'premod', 'flagged', 'accepted', 'rejected'];
|
||||
|
||||
const ascending = (a, b) => {
|
||||
const dateA = new Date(a.created_at);
|
||||
const dateB = new Date(b.created_at);
|
||||
if (dateA < dateB) { return -1; }
|
||||
if (dateA > dateB) { return 1; }
|
||||
return 0;
|
||||
};
|
||||
|
||||
const descending = (a, b) => -ascending(a, b);
|
||||
|
||||
function truncate(s, length = 10) {
|
||||
return (s.length > length) ? `${s.substring(0, length)}...` : s;
|
||||
}
|
||||
|
||||
export function handleCommentStatusChange(root, {id, status}, previousStatus) {
|
||||
const comment = findCommentInModQueues(root, id);
|
||||
if (!previousStatus && comment) {
|
||||
previousStatus = comment.status;
|
||||
}
|
||||
function queueHasComment(root, queue, id) {
|
||||
return root[queue].nodes.find((c) => c.id === id);
|
||||
}
|
||||
|
||||
if (status === previousStatus) {
|
||||
function removeCommentFromQueue(root, queue, id) {
|
||||
if (!queueHasComment(root, queue, id)) {
|
||||
return root;
|
||||
}
|
||||
|
||||
let acceptedNodes = root.accepted.nodes;
|
||||
let acceptedCount = root.acceptedCount;
|
||||
let rejectedNodes = root.rejected.nodes;
|
||||
let rejectedCount = root.rejectedCount;
|
||||
|
||||
if (status === 'ACCEPTED') {
|
||||
acceptedCount++;
|
||||
if (comment) {
|
||||
acceptedNodes = [{...comment, status}, ...acceptedNodes];
|
||||
}
|
||||
}
|
||||
else if (status === 'REJECTED') {
|
||||
rejectedCount++;
|
||||
if (comment) {
|
||||
rejectedNodes = [{...comment, status}, ...rejectedNodes];
|
||||
}
|
||||
}
|
||||
|
||||
const premodNodes = root.premod.nodes.filter((c) => c.id !== id);
|
||||
const flaggedNodes = root.flagged.nodes.filter((c) => c.id !== id);
|
||||
const premodCount = premodNodes.length < root.premod.nodes.length ? root.premodCount - 1 : root.premodCount;
|
||||
const flaggedCount = flaggedNodes.length < root.flagged.nodes.length ? root.flaggedCount - 1 : root.flaggedCount;
|
||||
|
||||
if (status === 'REJECTED') {
|
||||
acceptedNodes = root.accepted.nodes.filter((c) => c.id !== id);
|
||||
acceptedCount = acceptedNodes.length < root.accepted.nodes.length ? root.acceptedCount - 1 : root.acceptedCount;
|
||||
}
|
||||
else if (status === 'ACCEPTED') {
|
||||
rejectedNodes = root.rejected.nodes.filter((c) => c.id !== id);
|
||||
rejectedCount = rejectedNodes.length < root.rejected.nodes.length ? root.rejectedCount - 1 : root.rejectedCount;
|
||||
}
|
||||
|
||||
return update(root, {
|
||||
premodCount: {$set: Math.max(0, premodCount)},
|
||||
flaggedCount: {$set: Math.max(0, flaggedCount)},
|
||||
acceptedCount: {$set: Math.max(0, acceptedCount)},
|
||||
rejectedCount: {$set: Math.max(0, rejectedCount)},
|
||||
premod: {nodes: {$set: premodNodes}},
|
||||
flagged: {nodes: {$set: flaggedNodes}},
|
||||
accepted: {nodes: {$set: acceptedNodes}},
|
||||
rejected: {nodes: {$set: rejectedNodes}},
|
||||
[`${queue}Count`]: {$set: root[`${queue}Count`] - 1},
|
||||
[queue]: {
|
||||
nodes: {$apply: (nodes) => nodes.filter((c) => c.id !== id)},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function isCommentInCursor(root, queue, comment, sort) {
|
||||
const cursor = new Date(root[queue].endCursor);
|
||||
return sort === 'CHRONOLOGICAL'
|
||||
? new Date(comment.created_at) <= cursor
|
||||
: new Date(comment.created_at) >= cursor;
|
||||
}
|
||||
|
||||
function addCommentToQueue(root, queue, comment, sort) {
|
||||
if (queueHasComment(root, queue, comment.id)) {
|
||||
return root;
|
||||
}
|
||||
|
||||
const sortAlgo = sort === 'CHRONOLOGICAL' ? ascending : descending;
|
||||
const changes = {
|
||||
[`${queue}Count`]: {$set: root[`${queue}Count`] + 1},
|
||||
};
|
||||
|
||||
if (isCommentInCursor(root, queue, comment, sort)) {
|
||||
changes[queue] = {
|
||||
nodes: {$apply: (nodes) => nodes.concat(comment).sort(sortAlgo)},
|
||||
};
|
||||
}
|
||||
|
||||
return update(root, changes);
|
||||
}
|
||||
|
||||
function getCommentQueues(comment) {
|
||||
const queues = ['all'];
|
||||
if (comment.status === 'ACCEPTED') {
|
||||
queues.push('accepted');
|
||||
}
|
||||
else if (comment.status === 'REJECTED') {
|
||||
queues.push('rejected');
|
||||
}
|
||||
else if (comment.status === 'PREMOD') {
|
||||
queues.push('premod');
|
||||
}
|
||||
if (
|
||||
['NONE', 'PREMOD'].indexOf(comment.status) >= 0
|
||||
&& comment.actions && comment.actions.some((a) => a.__typename === 'FlagAction')
|
||||
) {
|
||||
queues.push('flagged');
|
||||
}
|
||||
return queues;
|
||||
}
|
||||
|
||||
function showNotification(queue, comment, user) {
|
||||
const text = `${user.username} ${comment.status.toLowerCase()} comment "${truncate(comment.body, 50)}"`;
|
||||
notification.info(text);
|
||||
}
|
||||
|
||||
export function handleCommentStatusChange(root, comment, {sort, notify, user, activeQueue}) {
|
||||
let next = root;
|
||||
const nextQueues = getCommentQueues(comment);
|
||||
|
||||
queues.forEach((queue) => {
|
||||
if (nextQueues.indexOf(queue) >= 0 && !queueHasComment(next, queue, comment.id)) {
|
||||
next = addCommentToQueue(next, queue, comment, sort);
|
||||
if (notify && activeQueue === queue && isCommentInCursor(next, queue, comment, sort)) {
|
||||
showNotification(queue, comment, user);
|
||||
}
|
||||
} else if(queueHasComment(next, queue, comment.id)){
|
||||
next = removeCommentFromQueue(next, queue, comment.id);
|
||||
if (notify && activeQueue === queue) {
|
||||
showNotification(queue, comment, user);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: All notification
|
||||
// TODO: Flagged notification
|
||||
// TODO: Edited notification
|
||||
});
|
||||
return next;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import t, {timeago} from 'coral-framework/services/i18n';
|
||||
import update from 'immutability-helper';
|
||||
|
||||
import {withSetUserStatus, withSuspendUser, withSetCommentStatus} from 'coral-framework/graphql/mutations';
|
||||
import {handleCommentStatusChange, findCommentInModQueues} from '../../../graphql/utils';
|
||||
import {handleCommentStatusChange} from '../../../graphql/utils';
|
||||
|
||||
import {fetchSettings} from 'actions/settings';
|
||||
import {updateAssets} from 'actions/assets';
|
||||
@@ -31,10 +31,6 @@ import {Spinner} from 'coral-ui';
|
||||
import Moderation from '../components/Moderation';
|
||||
import Comment from './Comment';
|
||||
|
||||
function truncate(s, length = 10) {
|
||||
return (s.length > length) ? `${s.substring(0, length)}...` : s;
|
||||
}
|
||||
|
||||
class ModerationContainer extends Component {
|
||||
unsubscribe = null;
|
||||
|
||||
@@ -47,25 +43,18 @@ class ModerationContainer extends Component {
|
||||
asset_id: this.props.data.variables.asset_id,
|
||||
},
|
||||
updateQuery: (prev, {subscriptionData: {data: {commentStatusChanged: {user, comment, previous}}}}) => {
|
||||
const activeTab = this.activeTab;
|
||||
|
||||
// Status changed was caused by a different user.
|
||||
if (user && user.id !== this.props.auth.user.id) {
|
||||
if (findCommentInModQueues(prev, comment.id) && (
|
||||
activeTab === 'all' && findCommentInModQueues(prev, comment.id, ['all'])
|
||||
|| activeTab === 'premod' && previous.status === 'PREMOD'
|
||||
|| activeTab === 'flagged' && findCommentInModQueues(prev, comment.id, ['flagged'])
|
||||
|| comment.status === 'ACCEPTED' && activeTab === 'accepted'
|
||||
|| comment.status !== 'ACCEPTED' && previous.status === 'ACCEPTED' && activeTab === 'accepted'
|
||||
|| comment.status === 'REJECTED' && activeTab === 'rejected'
|
||||
|| comment.status !== 'REJECTED' && previous.status === 'REJECTED' && activeTab === 'rejected'
|
||||
)
|
||||
) {
|
||||
const text = `${user.username} ${comment.status.toLowerCase()} comment "${truncate(comment.body, 50)}"`;
|
||||
notification.info(text);
|
||||
}
|
||||
}
|
||||
return handleCommentStatusChange(prev, comment, previous.status, user);
|
||||
const extraParams = this.props.auth.user.id === user.id
|
||||
? {}
|
||||
: {
|
||||
notify: true,
|
||||
user,
|
||||
activeQueue: this.activeTab,
|
||||
previous,
|
||||
};
|
||||
return handleCommentStatusChange(prev, comment, {
|
||||
sort: this.props.moderation.sortOrder,
|
||||
...extraParams,
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -218,6 +207,22 @@ const STATUS_CHANGED_SUBSCRIPTION = gql`
|
||||
id
|
||||
status
|
||||
body
|
||||
created_at
|
||||
action_summaries {
|
||||
count
|
||||
... on FlagActionSummary {
|
||||
reason
|
||||
}
|
||||
}
|
||||
actions {
|
||||
... on FlagAction {
|
||||
reason
|
||||
message
|
||||
user {
|
||||
username
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
previous {
|
||||
status
|
||||
|
||||
Reference in New Issue
Block a user