mirror of
https://github.com/wassname/talk.git
synced 2026-08-15 12:55:10 +08:00
Q&A Fixes (#2866)
* Fix various Q&A moderation/tagging issues - Allow Staff members to have their questions answered and appropriately tagged - Properly filter answering for only top level questions (comments) - Add documentation around various moderation phases and comment creation steps - Remove unnecessary status filter when setting the status for a comment * fix: abstracted out perspective configs * fix: reworked tag injection * Fix sorting/unused imports Co-authored-by: Wyatt Johnson <accounts+github@wyattjoh.ca>
This commit is contained in:
co-authored by
Wyatt Johnson
parent
c052d37a6f
commit
769ab2a910
@@ -1,10 +1,8 @@
|
||||
import { Db } from "mongodb";
|
||||
|
||||
import { Config } from "coral-server/config";
|
||||
import { CoralEventPublisherBroker } from "coral-server/events/publisher";
|
||||
import { Tenant } from "coral-server/models/tenant";
|
||||
import { moderate } from "coral-server/services/comments/moderation";
|
||||
import { notifyPerspectiveModerationDecision } from "coral-server/services/perspective";
|
||||
import { AugmentedRedis } from "coral-server/services/redis";
|
||||
|
||||
import { GQLCOMMENT_STATUS } from "coral-server/graph/schema/__generated__/types";
|
||||
@@ -14,7 +12,6 @@ import { publishChanges, updateAllCommentCounts } from "./helpers";
|
||||
const approveComment = async (
|
||||
mongo: Db,
|
||||
redis: AugmentedRedis,
|
||||
config: Config,
|
||||
broker: CoralEventPublisherBroker,
|
||||
tenant: Tenant,
|
||||
commentID: string,
|
||||
@@ -48,19 +45,8 @@ const approveComment = async (
|
||||
...result,
|
||||
...counts,
|
||||
moderatorID,
|
||||
});
|
||||
|
||||
// We don't want to await on this so that
|
||||
// we don't hold up the moderation flow and response
|
||||
notifyPerspectiveModerationDecision(
|
||||
mongo,
|
||||
tenant,
|
||||
config,
|
||||
tenant.integrations.perspective,
|
||||
result.after,
|
||||
commentRevisionID,
|
||||
GQLCOMMENT_STATUS.APPROVED
|
||||
);
|
||||
});
|
||||
|
||||
// Return the resulting comment.
|
||||
return result.after;
|
||||
|
||||
@@ -23,7 +23,6 @@ import {
|
||||
retrieveComment,
|
||||
} from "coral-server/models/comment";
|
||||
import {
|
||||
getLatestRevision,
|
||||
hasAncestors,
|
||||
hasPublishedStatus,
|
||||
} from "coral-server/models/comment/helpers";
|
||||
@@ -43,10 +42,6 @@ import {
|
||||
PhaseResult,
|
||||
processForModeration,
|
||||
} from "coral-server/services/comments/pipeline";
|
||||
import {
|
||||
publishCommentCreated,
|
||||
publishCommentReplyCreated,
|
||||
} from "coral-server/services/events";
|
||||
import { AugmentedRedis } from "coral-server/services/redis";
|
||||
import { updateUserLastCommentID } from "coral-server/services/users";
|
||||
import { Request } from "coral-server/types/express";
|
||||
@@ -67,7 +62,6 @@ export type CreateComment = Omit<
|
||||
const markCommentAsAnswered = async (
|
||||
mongo: Db,
|
||||
redis: AugmentedRedis,
|
||||
config: Config,
|
||||
broker: CoralEventPublisherBroker,
|
||||
tenant: Tenant,
|
||||
comment: Readonly<Comment>,
|
||||
@@ -93,16 +87,19 @@ const markCommentAsAnswered = async (
|
||||
return;
|
||||
}
|
||||
|
||||
// If we have experts and this reply is created by
|
||||
// one of them, then this is an expert's answer.
|
||||
if (story.settings.expertIDs.some(id => id === author.id)) {
|
||||
// We need to mark this question as answered now.
|
||||
// We can now remove the unanswered tag.
|
||||
if (
|
||||
// If we are the export on this story...
|
||||
story.settings.expertIDs.some(id => id === author.id) &&
|
||||
// And this is the first reply (depth of 1)...
|
||||
comment.ancestorIDs.length === 1
|
||||
) {
|
||||
// We need to mark the parent question as answered.
|
||||
// - Remove the unanswered tag.
|
||||
// - Approve it since an expert has replied to it.
|
||||
await removeTag(mongo, tenant, comment.parentID, GQLTAG.UNANSWERED);
|
||||
await approveComment(
|
||||
mongo,
|
||||
redis,
|
||||
config,
|
||||
broker,
|
||||
tenant,
|
||||
comment.parentID,
|
||||
@@ -181,7 +178,7 @@ export default async function create(
|
||||
nudge,
|
||||
story,
|
||||
tenant,
|
||||
comment: input,
|
||||
comment: { ...input, ancestorIDs },
|
||||
author,
|
||||
req,
|
||||
now,
|
||||
@@ -218,7 +215,7 @@ export default async function create(
|
||||
}
|
||||
|
||||
// Create the comment!
|
||||
const comment = await createComment(
|
||||
const { comment, revision } = await createComment(
|
||||
mongo,
|
||||
tenant.id,
|
||||
{
|
||||
@@ -234,6 +231,11 @@ export default async function create(
|
||||
now
|
||||
);
|
||||
|
||||
log = log.child(
|
||||
{ commentID: comment.id, status, revisionID: revision.id },
|
||||
true
|
||||
);
|
||||
|
||||
// Updating some associated data.
|
||||
await Promise.all([
|
||||
updateUserLastCommentID(redis, tenant, author, comment.id),
|
||||
@@ -241,7 +243,6 @@ export default async function create(
|
||||
markCommentAsAnswered(
|
||||
mongo,
|
||||
redis,
|
||||
config,
|
||||
broker,
|
||||
tenant,
|
||||
comment,
|
||||
@@ -251,14 +252,6 @@ export default async function create(
|
||||
),
|
||||
]);
|
||||
|
||||
// Pull the revision out.
|
||||
const revision = getLatestRevision(comment);
|
||||
|
||||
log = log.child(
|
||||
{ commentID: comment.id, status, revisionID: revision.id },
|
||||
true
|
||||
);
|
||||
|
||||
log.trace("comment created");
|
||||
|
||||
if (input.parentID) {
|
||||
@@ -305,17 +298,8 @@ export default async function create(
|
||||
await publishChanges(broker, {
|
||||
...counts,
|
||||
after: comment,
|
||||
commentRevisionID: revision.id,
|
||||
});
|
||||
|
||||
// If this is a reply, publish it.
|
||||
if (input.parentID) {
|
||||
publishCommentReplyCreated(broker, comment);
|
||||
}
|
||||
|
||||
// If this comment is visible (and not a reply), publish it.
|
||||
if (!input.parentID && hasPublishedStatus(comment)) {
|
||||
publishCommentCreated(broker, comment);
|
||||
}
|
||||
|
||||
return comment;
|
||||
}
|
||||
|
||||
@@ -195,6 +195,7 @@ export default async function edit(
|
||||
await publishChanges(broker, {
|
||||
...result,
|
||||
...counts,
|
||||
commentRevisionID: result.revision.id,
|
||||
});
|
||||
|
||||
// Return the resulting comment.
|
||||
|
||||
@@ -6,7 +6,9 @@ import {
|
||||
hasPublishedStatus,
|
||||
} from "coral-server/models/comment";
|
||||
import {
|
||||
publishCommentCreated,
|
||||
publishCommentReleased,
|
||||
publishCommentReplyCreated,
|
||||
publishCommentStatusChanges,
|
||||
publishModerationQueueChanges,
|
||||
} from "coral-server/services/events";
|
||||
@@ -16,6 +18,7 @@ interface PublishChangesInput {
|
||||
after: Readonly<Comment>;
|
||||
moderationQueue: CommentModerationQueueCounts;
|
||||
moderatorID?: string;
|
||||
commentRevisionID: string;
|
||||
}
|
||||
|
||||
export default async function publishChanges(
|
||||
@@ -33,11 +36,24 @@ export default async function publishChanges(
|
||||
input.before.status,
|
||||
input.after.status,
|
||||
input.after.id,
|
||||
input.commentRevisionID,
|
||||
input.moderatorID || null
|
||||
);
|
||||
|
||||
if (hasModeratorStatus(input.before) && hasPublishedStatus(input.after)) {
|
||||
publishCommentReleased(broker, input.after);
|
||||
}
|
||||
} else {
|
||||
// This block is only hit if there is no before (if this is a new comment).
|
||||
|
||||
// If this is a reply, publish it.
|
||||
if (input.after.parentID) {
|
||||
publishCommentReplyCreated(broker, input.after);
|
||||
}
|
||||
|
||||
// If this comment is visible (and not a reply), publish it.
|
||||
if (!input.after.parentID && hasPublishedStatus(input.after)) {
|
||||
publishCommentCreated(broker, input.after);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
import { Db } from "mongodb";
|
||||
|
||||
import { Config } from "coral-server/config";
|
||||
import { CoralEventPublisherBroker } from "coral-server/events/publisher";
|
||||
import { hasTag } from "coral-server/models/comment";
|
||||
import { Tenant } from "coral-server/models/tenant";
|
||||
import { removeTag } from "coral-server/services/comments";
|
||||
import { moderate } from "coral-server/services/comments/moderation";
|
||||
import { notifyPerspectiveModerationDecision } from "coral-server/services/perspective";
|
||||
import { AugmentedRedis } from "coral-server/services/redis";
|
||||
|
||||
import {
|
||||
@@ -19,7 +17,6 @@ import { publishChanges, updateAllCommentCounts } from "./helpers";
|
||||
const rejectComment = async (
|
||||
mongo: Db,
|
||||
redis: AugmentedRedis,
|
||||
config: Config,
|
||||
broker: CoralEventPublisherBroker | null,
|
||||
tenant: Tenant,
|
||||
commentID: string,
|
||||
@@ -56,6 +53,7 @@ const rejectComment = async (
|
||||
...result,
|
||||
...counts,
|
||||
moderatorID,
|
||||
commentRevisionID,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -64,18 +62,6 @@ const rejectComment = async (
|
||||
return removeTag(mongo, tenant, result.after.id, GQLTAG.FEATURED);
|
||||
}
|
||||
|
||||
// We don't want to await on this so that
|
||||
// we don't hold up the moderation flow and response
|
||||
notifyPerspectiveModerationDecision(
|
||||
mongo,
|
||||
tenant,
|
||||
config,
|
||||
tenant.integrations.perspective,
|
||||
result.after,
|
||||
commentRevisionID,
|
||||
GQLCOMMENT_STATUS.REJECTED
|
||||
);
|
||||
|
||||
// Return the resulting comment.
|
||||
return result.after;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user