Skip to content

Commit

Permalink
Merge pull request #262 from cofacts/block-user
Browse files Browse the repository at this point in the history
Apply status filter on resources
  • Loading branch information
MrOrz authored Jan 5, 2022
2 parents d179385 + 3bf6786 commit 05b0367
Show file tree
Hide file tree
Showing 19 changed files with 252 additions and 105 deletions.
69 changes: 55 additions & 14 deletions src/graphql/models/Article.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@ import {
createFilterType,
createSortType,
createConnectionType,
filterArticleRepliesByStatus,
filterArticleCategoriesByStatus,
filterByStatuses,
timeRangeInput,
DEFAULT_ARTICLE_REPLY_STATUSES,
DEFAULT_ARTICLE_CATEGORY_STATUSES,
DEFAULT_REPLY_REQUEST_STATUSES,
} from 'graphql/util';

import Node from '../interfaces/Node';
Expand All @@ -28,6 +30,7 @@ import User, { userFieldResolver } from 'graphql/models/User';
import ArticleReplyStatusEnum from './ArticleReplyStatusEnum';
import ArticleReply from './ArticleReply';
import ArticleCategoryStatusEnum from './ArticleCategoryStatusEnum';
import ReplyRequestStatusEnum from './ReplyRequestStatusEnum';
import ArticleCategory from './ArticleCategory';
import Hyperlink from './Hyperlink';
import ReplyRequest from './ReplyRequest';
Expand All @@ -54,19 +57,28 @@ const Article = new GraphQLObjectType({
status: {
type: ArticleReplyStatusEnum,
description:
'When specified, returns only article replies with the specified status',
'Deprecated. Please use statuses instead. When specified, returns only article replies with the specified status',
},
statuses: {
type: new GraphQLList(new GraphQLNonNull(ArticleReplyStatusEnum)),
defaultValue: DEFAULT_ARTICLE_REPLY_STATUSES,
description:
'Returns only article replies with the specified statuses',
},
},
resolve: async ({ id, articleReplies = [] }, { status }) => {
resolve: async (
{ id, articleReplies = [] },
{ status, statuses = DEFAULT_ARTICLE_REPLY_STATUSES }
) => {
// Sort by usefulness (= positive - negative feedbacks)
// then use latest first
const sortedArticleReplies = filterArticleRepliesByStatus(
const sortedArticleReplies = filterByStatuses(
// Inject articleId to each articleReply
articleReplies.map(articleReply => {
articleReply.articleId = id;
return articleReply;
}),
status
status ? [status] : statuses
).sort((a, b) => {
const usefulnessDiff =
b.positiveFeedbackCount -
Expand Down Expand Up @@ -97,29 +109,36 @@ const Article = new GraphQLObjectType({

articleCategories: {
type: new GraphQLList(ArticleCategory),

args: {
status: {
type: ArticleCategoryStatusEnum,
description:
'When specified, returns only article categories with the specified status',
'Deprecated. Please use statuses instead. When specified, returns only article categories with the specified status',
},
statuses: {
type: new GraphQLList(new GraphQLNonNull(ArticleCategoryStatusEnum)),
defaultValue: DEFAULT_ARTICLE_CATEGORY_STATUSES,
description:
'Returns only article categories with the specified statuses',
},
},

resolve: async ({ id, articleCategories = [] }, { status }) => {
resolve: async (
{ id, articleCategories = [] },
{ status, statuses = DEFAULT_ARTICLE_CATEGORY_STATUSES }
) => {
// sort by created
const sortedArticleCategories = filterArticleCategoriesByStatus(
const sortedArticleCategories = filterByStatuses(
// Inject articleId to each articleCategory
articleCategories.map(articleCategory => {
articleCategory.articleId = id;
return articleCategory;
}),
status
status ? [status] : statuses
).sort((a, b) => {
return +new Date(b.createdAt) - +new Date(a.createdAt);
});

if (sortedArticleCategories.length === 0) return [];
return sortedArticleCategories;
},
},
Expand All @@ -132,10 +151,32 @@ const Article = new GraphQLObjectType({

replyRequests: {
type: new GraphQLList(ReplyRequest),
resolve: async ({ id }, args, { loaders }) =>
args: {
statuses: {
type: new GraphQLList(new GraphQLNonNull(ReplyRequestStatusEnum)),
defaultValue: DEFAULT_ARTICLE_REPLY_STATUSES,
description:
'Returns only article replies with the specified statuses',
},
},
resolve: async (
{ id },
{ statuses = DEFAULT_REPLY_REQUEST_STATUSES },
{ loaders }
) =>
loaders.searchResultLoader.load({
index: 'replyrequests',
body: { query: { term: { articleId: id } }, size: 1000 },
body: {
query: {
bool: {
must: [
{ term: { articleId: id } },
{ terms: { status: statuses } },
],
},
},
size: 1000,
},
}),
},
replyRequestCount: { type: GraphQLInt },
Expand Down
1 change: 1 addition & 0 deletions src/graphql/models/ArticleCategoryStatusEnum.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export default new GraphQLEnumType({
},
BLOCKED: {
value: 'BLOCKED',
description: 'Created by a blocked user violating terms of use.',
},
},
});
30 changes: 28 additions & 2 deletions src/graphql/models/ArticleReply.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ import ReplyTypeEnum from './ReplyTypeEnum';
import ArticleReplyFeedback from './ArticleReplyFeedback';
import ArticleReplyStatusEnum from './ArticleReplyStatusEnum';
import FeedbackVote from './FeedbackVote';
import ArticleReplyFeedbackStatusEnum from './ArticleReplyFeedbackStatusEnum';

import {
DEFAULT_ARTICLE_REPLY_FEEDBACK_STATUSES,
filterByStatuses,
} from 'graphql/util';

export default new GraphQLObjectType({
name: 'ArticleReply',
Expand Down Expand Up @@ -67,8 +73,28 @@ export default new GraphQLObjectType({

feedbacks: {
type: new GraphQLList(ArticleReplyFeedback),
resolve: ({ articleId, replyId }, args, { loaders }) =>
loaders.articleReplyFeedbacksLoader.load({ articleId, replyId }),
args: {
statuses: {
type: new GraphQLList(
new GraphQLNonNull(ArticleReplyFeedbackStatusEnum)
),
defaultValue: DEFAULT_ARTICLE_REPLY_FEEDBACK_STATUSES,
description:
'Returns only aricle reply feedbacks with the specified statuses',
},
},
resolve: async (
{ articleId, replyId },
{ statuses = DEFAULT_ARTICLE_REPLY_FEEDBACK_STATUSES },
{ loaders }
) =>
filterByStatuses(
await loaders.articleReplyFeedbacksLoader.load({
articleId,
replyId,
}),
statuses
),
},

ownVote: {
Expand Down
5 changes: 5 additions & 0 deletions src/graphql/models/ArticleReplyFeedback.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import User, { userFieldResolver } from './User';
import Article from './Article';
import Reply from './Reply';
import ArticleReply from './ArticleReply';
import ArticleReplyFeedbackStatusEnum from './ArticleReplyFeedbackStatusEnum';

export default new GraphQLObjectType({
name: 'ArticleReplyFeedback',
Expand All @@ -33,6 +34,10 @@ export default new GraphQLObjectType({
createdAt: { type: GraphQLString },
updatedAt: { type: GraphQLString },

status: {
type: new GraphQLNonNull(ArticleReplyFeedbackStatusEnum),
},

vote: {
description: "User's vote on the articleReply",
type: FeedbackVote,
Expand Down
14 changes: 14 additions & 0 deletions src/graphql/models/ArticleReplyFeedbackStatusEnum.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { GraphQLEnumType } from 'graphql';

export default new GraphQLEnumType({
name: 'ArticleReplyFeedbackStatusEnum',
values: {
NORMAL: {
value: 'NORMAL',
},
BLOCKED: {
value: 'BLOCKED',
description: 'Created by a blocked user violating terms of use.',
},
},
});
1 change: 1 addition & 0 deletions src/graphql/models/ArticleReplyStatusEnum.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export default new GraphQLEnumType({
},
BLOCKED: {
value: 'BLOCKED',
description: 'Created by a blocked user violating terms of use.',
},
},
});
18 changes: 14 additions & 4 deletions src/graphql/models/Reply.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ import {
} from 'graphql';

import {
filterArticleRepliesByStatus,
filterByStatuses,
pagingArgs,
getSortArgs,
createSortType,
createConnectionType,
DEFAULT_ARTICLE_REPLY_STATUSES,
} from 'graphql/util';
import Node from '../interfaces/Node';
import ReplyTypeEnum from './ReplyTypeEnum';
Expand Down Expand Up @@ -39,15 +40,24 @@ const Reply = new GraphQLObjectType({
args: {
status: {
type: ArticleReplyStatusEnum,
description: 'Deprecated. Please use statuses instead.',
},
statuses: {
type: new GraphQLList(new GraphQLNonNull(ArticleReplyStatusEnum)),
defaultValue: DEFAULT_ARTICLE_REPLY_STATUSES,
description:
'When specified, returns only reply connections with the specified status',
'Returns only article replies with the specified statuses',
},
},
resolve: async ({ id }, { status }, { loaders }) => {
resolve: async (
{ id },
{ status, statuses = DEFAULT_ARTICLE_REPLY_STATUSES },
{ loaders }
) => {
const articleReplies = await loaders.articleRepliesByReplyIdLoader.load(
id
);
return filterArticleRepliesByStatus(articleReplies, status);
return filterByStatuses(articleReplies, status ? [status] : statuses);
},
},
hyperlinks: {
Expand Down
14 changes: 14 additions & 0 deletions src/graphql/models/ReplyRequest.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,20 @@ import {
GraphQLNonNull,
} from 'graphql';
import User, { userFieldResolver } from './User';
import Article from './Article';
import FeedbackVote from './FeedbackVote';
import Node from '../interfaces/Node';
import ReplyRequestStatusEnum from './ReplyRequestStatusEnum';

export default new GraphQLObjectType({
name: 'ReplyRequest',
interfaces: [Node],
fields: () => ({
id: { type: new GraphQLNonNull(GraphQLID) },

articleId: {
type: new GraphQLNonNull(GraphQLID),
},
userId: { type: GraphQLString },
appId: { type: GraphQLString },

Expand Down Expand Up @@ -57,5 +63,13 @@ export default new GraphQLObjectType({
return ownFeedback.score;
},
},
article: {
type: new GraphQLNonNull(Article),
resolve: ({ articleId }, args, { loaders }) =>
loaders.docLoader.load({ index: 'articles', id: articleId }),
},
status: {
type: new GraphQLNonNull(ReplyRequestStatusEnum),
},
}),
});
14 changes: 14 additions & 0 deletions src/graphql/models/ReplyRequestStatusEnum.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { GraphQLEnumType } from 'graphql';

export default new GraphQLEnumType({
name: 'ReplyRequestStatusEnum',
values: {
NORMAL: {
value: 'NORMAL',
},
BLOCKED: {
value: 'BLOCKED',
description: 'Created by a blocked user violating terms of use.',
},
},
});
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ describe('CreateOrUpdateReplyRequest', () => {
) {
id
replyRequestCount
replyRequests {
replyRequests(statuses: [BLOCKED, NORMAL]) {
userId
reason
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,6 @@ Object {
"comment": null,
"vote": "UPVOTE",
},
Object {
"comment": "ads content",
"vote": "UPVOTE",
},
],
"negativeFeedbackCount": 0,
"ownVote": "UPVOTE",
Expand Down
20 changes: 18 additions & 2 deletions src/graphql/queries/ListArticleReplyFeedbacks.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { GraphQLString, GraphQLList } from 'graphql';
import { GraphQLString, GraphQLList, GraphQLNonNull } from 'graphql';
import {
createFilterType,
createSortType,
Expand All @@ -8,8 +8,10 @@ import {
pagingArgs,
getSortArgs,
getRangeFieldParamFromArithmeticExpression,
DEFAULT_ARTICLE_REPLY_FEEDBACK_STATUSES,
} from 'graphql/util';
import ArticleReplyFeedback from 'graphql/models/ArticleReplyFeedback';
import ArticleReplyFeedbackStatusEnum from 'graphql/models/ArticleReplyFeedbackStatusEnum';
import FeedbackVote from 'graphql/models/FeedbackVote';

export default {
Expand Down Expand Up @@ -47,6 +49,14 @@ export default {
description:
'List only the article reply feedbacks that were last updated within the specific time range.',
},
statuses: {
type: new GraphQLList(
new GraphQLNonNull(ArticleReplyFeedbackStatusEnum)
),
defaultValue: DEFAULT_ARTICLE_REPLY_FEEDBACK_STATUSES,
description:
'List only the article reply feedbacks with the selected statuses',
},
}),
},
orderBy: {
Expand All @@ -71,7 +81,13 @@ export default {
};

const shouldQueries = []; // Affects scores
const filterQueries = []; // Not affects scores
const filterQueries = [
{
terms: {
status: filter.statuses || DEFAULT_ARTICLE_REPLY_FEEDBACK_STATUSES,
},
},
]; // Not affects scores

['userId', 'appId', 'articleId', 'replyId'].forEach(field => {
if (!filter[field]) return;
Expand Down
Loading

0 comments on commit 05b0367

Please sign in to comment.