diff --git a/src/graphql/models/Reply.js b/src/graphql/models/Reply.js index 4ad65256..738e4786 100644 --- a/src/graphql/models/Reply.js +++ b/src/graphql/models/Reply.js @@ -37,6 +37,21 @@ const Reply = new GraphQLObjectType({ }, text: { type: GraphQLString }, type: { type: new GraphQLNonNull(ReplyTypeEnum) }, + status: { + type: new GraphQLNonNull(ArticleReplyStatusEnum), + description: + 'The status of this reply, calculated from its author and article replies.', + async resolve(reply, args, context) { + const user = await userFieldResolver(reply, args, context); + if (user && user.blockedReason) return 'BLOCKED'; + + const articleReplies = + await context.loaders.articleRepliesByReplyIdLoader.load(reply.id); + return articleReplies.every((ar) => ar.status !== 'NORMAL') + ? 'DELETED' + : 'NORMAL'; + }, + }, reference: { type: GraphQLString }, articleReplies: { type: new GraphQLNonNull( diff --git a/src/graphql/queries/__fixtures__/GetReplyAndArticle.js b/src/graphql/queries/__fixtures__/GetReplyAndArticle.js index 6416849e..49fec541 100644 --- a/src/graphql/queries/__fixtures__/GetReplyAndArticle.js +++ b/src/graphql/queries/__fixtures__/GetReplyAndArticle.js @@ -52,7 +52,7 @@ export default { positiveFeedbackCount: 0, negativeFeedbackCount: 1, userId: 'blocked-user', - appId: 'app1', + appId: 'WEBSITE', }, ], normalArticleReplyCount: 1, @@ -166,6 +166,12 @@ export default { reference: 'barbar2', type: 'NOT_ARTICLE', }, + '/replies/doc/bar5': { + text: 'spam content', + type: 'NOT_ARTICLE', + userId: 'blocked-user', + appId: 'WEBSITE', + }, '/replies/doc/fofo': { text: 'fofo', reference: 'barfofo', @@ -247,6 +253,10 @@ export default { title: '免費訊息詐騙', description: '詐騙貼圖、假行銷手法。', }, + '/users/doc/blocked-user': { + appId: 'WEBSITE', + blockedReason: 'https://announcement.url', + }, ...Array.from(new Array(11)).reduce((mockMap, _, i) => { mockMap[`/replyrequests/doc/popular${i}`] = { diff --git a/src/graphql/queries/__tests__/GetReplyAndGetArticle.js b/src/graphql/queries/__tests__/GetReplyAndGetArticle.js index de5e4007..d62b4a2c 100644 --- a/src/graphql/queries/__tests__/GetReplyAndGetArticle.js +++ b/src/graphql/queries/__tests__/GetReplyAndGetArticle.js @@ -505,6 +505,7 @@ describe('GetReplyAndGetArticle', () => { text } } + status } } `() @@ -599,6 +600,26 @@ describe('GetReplyAndGetArticle', () => { `() ).toMatchSnapshot('similarReply sorting test'); }); + + it('sets status to BLOCKED when the author is blocked', async () => { + expect( + await gql` + { + GetReply(id: "bar5") { + status + } + } + `() + ).toMatchInlineSnapshot(` + Object { + "data": Object { + "GetReply": Object { + "status": "BLOCKED", + }, + }, + } + `); + }); }); afterAll(() => unloadFixtures(fixtures)); diff --git a/src/graphql/queries/__tests__/__snapshots__/GetReplyAndGetArticle.js.snap b/src/graphql/queries/__tests__/__snapshots__/GetReplyAndGetArticle.js.snap index f39a131c..ef4ce771 100644 --- a/src/graphql/queries/__tests__/__snapshots__/GetReplyAndGetArticle.js.snap +++ b/src/graphql/queries/__tests__/__snapshots__/GetReplyAndGetArticle.js.snap @@ -450,6 +450,7 @@ Object { }, ], "reference": "barbar", + "status": "NORMAL", "text": "bar", "type": "NOT_ARTICLE", }, @@ -464,7 +465,7 @@ Object { "similarReplies": Object { "edges": Array [ Object { - "cursor": "WzEuODg5MTY5Mywic2ltaWxhci10by1iYXIiXQ==", + "cursor": "WzIuMTE2NjU0LCJzaW1pbGFyLXRvLWJhciJd", "highlight": Object { "hyperlinks": Array [], "reference": "barbar", @@ -473,7 +474,7 @@ Object { "node": Object { "id": "similar-to-bar", }, - "score": 1.8891693, + "score": 2.116654, }, Object { "cursor": "WzAuNTY2MzE3Miwic2ltaWxhci10by1iYXIyIl0=", @@ -523,7 +524,7 @@ Object { "score": 0.5663172, }, Object { - "cursor": "WzEuODg5MTY5Mywic2ltaWxhci10by1iYXIiXQ==", + "cursor": "WzIuMTE2NjU0LCJzaW1pbGFyLXRvLWJhciJd", "highlight": Object { "hyperlinks": Array [], "reference": "barbar", @@ -532,7 +533,7 @@ Object { "node": Object { "id": "similar-to-bar", }, - "score": 1.8891693, + "score": 2.116654, }, ], },