Merge branch 'next-respect' of github.com:coralproject/talk into next-respect

* 'next-respect' of github.com:coralproject/talk:
  fix: linting
  feat: initial comment count support (#1903)
This commit is contained in:
Belén Curcio
2018-09-26 16:37:51 -03:00
7 changed files with 159 additions and 14 deletions
@@ -45,7 +45,6 @@ class RespectButtonContainer extends React.Component<
this.props.comment.myActionPresence &&
this.props.comment.myActionPresence.reaction;
console.log(totalReactions);
return (
<RespectButton
onButtonClick={this.onButtonClick}
@@ -8,6 +8,7 @@ const Asset: GQLAssetTypeResolver<Asset> = {
// TODO: implement this.
isClosed: () => false,
actionCounts: asset => decodeActionCounts(asset.action_counts),
commentCounts: asset => asset.comment_counts,
};
export default Asset;
@@ -0,0 +1,14 @@
import {
GQLCOMMENT_STATUS,
GQLCommentCountsTypeResolver,
} from "talk-server/graph/tenant/schema/__generated__/types";
import { CommentStatusCounts } from "talk-server/models/asset";
const CommentCounts: GQLCommentCountsTypeResolver<CommentStatusCounts> = {
totalVisible: commentCounts =>
commentCounts[GQLCOMMENT_STATUS.ACCEPTED] +
commentCounts[GQLCOMMENT_STATUS.NONE],
statuses: commentCounts => commentCounts,
};
export default CommentCounts;
@@ -4,6 +4,7 @@ import { GQLResolver } from "talk-server/graph/tenant/schema/__generated__/types
import Asset from "./asset";
import AuthIntegrations from "./auth_integrations";
import Comment from "./comment";
import CommentCounts from "./comment_counts";
import Mutation from "./mutation";
import Profile from "./profile";
import Query from "./query";
@@ -12,6 +13,7 @@ const Resolvers: GQLResolver = {
Asset,
AuthIntegrations,
Comment,
CommentCounts,
Cursor,
Mutation,
Profile,
@@ -423,7 +423,7 @@ type KarmaThreshold {
type KarmaThresholds {
"""
flag represents karma settings in relation to how well a User's flagging
ability aligns with the moderation decicions made by moderators.
ability aligns with the moderation decisions made by moderators.
"""
flag: KarmaThreshold!
@@ -442,7 +442,7 @@ type Karma {
"""
karmaThresholds contains the currently set thresholds for triggering Trust
beheviour.
behavior.
"""
thresholds: KarmaThresholds!
}
@@ -935,6 +935,50 @@ type CommentsConnection {
pageInfo: PageInfo!
}
################################################################################
## CommentCounts
################################################################################
type CommentStatusCounts {
"""
The comment is not PREMOD, but was not applied a moderation status by a
moderator.
"""
NONE: Int!
"""
The comment has been accepted by a moderator.
"""
ACCEPTED: Int!
"""
The comment has been rejected by a moderator.
"""
REJECTED: Int!
"""
The comment was created while the asset's premoderation option was on, and
new comments that haven't been moderated yet are referred to as
"premoderated" or "premod" comments.
"""
PREMOD: Int!
"""
SYSTEM_WITHHELD represents a comment that was withheld by the system because
it was flagged by an internal process for further review.
"""
SYSTEM_WITHHELD: Int!
}
type CommentCounts {
"""
totalVisible will return the count of all visible Comments.
"""
totalVisible: Int!
statuses: CommentStatusCounts! @auth(roles: [ADMIN, MODERATOR])
}
################################################################################
## Asset
################################################################################
@@ -995,6 +1039,11 @@ type Asset {
"""
isClosed: Boolean!
"""
commentCounts stores all the counts of Comments that are left on the Comment.
"""
commentCounts: CommentCounts!
"""
createdAt is the date that the Asset was created at.
"""
@@ -1319,7 +1368,7 @@ input SettingsKarmaThresholdInput {
input SettingsKarmaThresholdsInput {
"""
flag represents karma settings in relation to how well a User's flagging
ability aligns with the moderation decicions made by moderators.
ability aligns with the moderation decisions made by moderators.
"""
flag: SettingsKarmaThresholdInput
@@ -1338,7 +1387,7 @@ input SettingsKarmaInput {
"""
karmaThresholds contains the currently set thresholds for triggering Trust
beheviour.
behavior.
"""
thresholds: SettingsKarmaThresholdsInput
}
+67 -4
View File
@@ -3,6 +3,7 @@ import uuid from "uuid";
import { Omit } from "talk-common/types";
import { dotize } from "talk-common/utils/dotize";
import { GQLCOMMENT_STATUS } from "talk-server/graph/tenant/schema/__generated__/types";
import { EncodedActionCounts } from "talk-server/models/action";
import { ModerationSettings } from "talk-server/models/settings";
import { TenantResource } from "talk-server/models/tenant";
@@ -11,12 +12,24 @@ function collection(db: Db) {
return db.collection<Readonly<Asset>>("assets");
}
// TODO: (wyattjoh) write a test to verify that this set of counts is always in sync with GQLCOMMENT_STATUS.
export interface CommentStatusCounts {
[GQLCOMMENT_STATUS.ACCEPTED]: number;
[GQLCOMMENT_STATUS.NONE]: number;
[GQLCOMMENT_STATUS.PREMOD]: number;
[GQLCOMMENT_STATUS.REJECTED]: number;
[GQLCOMMENT_STATUS.SYSTEM_WITHHELD]: number;
}
export interface Asset extends TenantResource {
readonly id: string;
url: string;
scraped?: Date;
closedAt?: Date;
closedMessage?: string;
created_at: Date;
modified_date?: Date;
title?: string;
description?: string;
image?: string;
@@ -24,8 +37,6 @@ export interface Asset extends TenantResource {
subsection?: string;
author?: string;
publication_date?: Date;
modified_date?: Date;
created_at: Date;
/**
* action_counts stores all the action counts for all Comment's on this Asset.
@@ -33,7 +44,13 @@ export interface Asset extends TenantResource {
action_counts: EncodedActionCounts;
/**
* settings provides a point where the settings can be overriden for a
* comment_counts stores the different counts for each comment on the Asset
* according to their statuses.
*/
comment_counts: CommentStatusCounts;
/**
* settings provides a point where the settings can be overridden for a
* specific Asset.
*/
settings?: Partial<ModerationSettings>;
@@ -62,13 +79,17 @@ export async function upsertAsset(
tenant_id: tenantID,
created_at: now,
action_counts: {},
comment_counts: createEmptyCommentCounts(),
},
};
// Perform the find and update operation to try and find and or create the
// asset.
const { value: asset } = await collection(db).findOneAndUpdate(
{ url },
{
url,
tenant_id: tenantID,
},
update,
{
// Create the object if it doesn't already exist.
@@ -90,6 +111,48 @@ export async function upsertAsset(
return asset;
}
/**
* updateCommentStatusCount increments the number of status counts for the
* given Asset ID.
*
* @param mongo the database handle
* @param tenantID the tenant that the Asset is on.
* @param id the ID of the Asset.
* @param commentStatusCounts the update document that contains a positive or
* negative number of comments to increment on the given Asset.
*/
export async function updateCommentStatusCount(
mongo: Db,
tenantID: string,
id: string,
commentStatusCounts: Partial<CommentStatusCounts>
) {
const { value: asset } = await collection(mongo).findOneAndUpdate(
{
id,
tenant_id: tenantID,
},
// Update all the specific comment status counts that are associated with
// each of the counts.
{ $inc: dotize({ comment_counts: commentStatusCounts }) },
// False to return the updated document instead of the original
// document.
{ returnOriginal: false }
);
return asset;
}
function createEmptyCommentCounts(): CommentStatusCounts {
return {
[GQLCOMMENT_STATUS.ACCEPTED]: 0,
[GQLCOMMENT_STATUS.NONE]: 0,
[GQLCOMMENT_STATUS.PREMOD]: 0,
[GQLCOMMENT_STATUS.REJECTED]: 0,
[GQLCOMMENT_STATUS.SYSTEM_WITHHELD]: 0,
};
}
export interface FindOrCreateAssetInput {
id?: string;
url?: string;
+22 -5
View File
@@ -2,7 +2,10 @@ import { Db } from "mongodb";
import { Omit } from "talk-common/types";
import { ACTION_ITEM_TYPE, CreateActionInput } from "talk-server/models/action";
import { retrieveAsset } from "talk-server/models/asset";
import {
retrieveAsset,
updateCommentStatusCount,
} from "talk-server/models/asset";
import {
createComment,
CreateCommentInput,
@@ -102,6 +105,11 @@ export async function create(
);
}
// Increment the status count for the particular status on the Asset.
await updateCommentStatusCount(mongo, tenant.id, asset.id, {
[status]: 1,
});
return comment;
}
@@ -118,7 +126,7 @@ export async function edit(
req?: Request
) {
// Get the comment that we're editing.
let comment = await retrieveComment(mongo, tenant.id, input.id);
const comment = await retrieveComment(mongo, tenant.id, input.id);
if (!comment) {
// TODO: replace to match error returned by the models/comments.ts
throw new Error("comment not found");
@@ -140,7 +148,7 @@ export async function edit(
req,
});
comment = await editComment(mongo, tenant.id, {
let editedComment = await editComment(mongo, tenant.id, {
id: input.id,
author_id: author.id,
body: input.body,
@@ -174,8 +182,17 @@ export async function edit(
);
// Insert and handle creating the actions.
comment = await addCommentActions(mongo, tenant, comment, inputs);
editedComment = await addCommentActions(mongo, tenant, comment, inputs);
}
return comment;
if (comment.status !== editedComment.status) {
// Increment the status count for the particular status on the Asset, and
// decrement the status on the comment's previous status.
await updateCommentStatusCount(mongo, tenant.id, asset.id, {
[comment.status]: -1,
[editedComment.status]: 1,
});
}
return editedComment;
}