Skip to content
This repository was archived by the owner on Nov 8, 2022. It is now read-only.

Commit 04d3680

Browse files
committed
fix(article-comments): replies edge case & add is_reply_to_others flag
1 parent 18858b0 commit 04d3680

File tree

5 files changed

+160
-117
lines changed

5 files changed

+160
-117
lines changed

lib/groupher_server/cms/delegates/article_comment.ex

Lines changed: 43 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -355,10 +355,6 @@ defmodule GroupherServer.CMS.Delegate.ArticleComment do
355355
|> Multi.run(:add_participator, fn _, _ ->
356356
add_participator_to_article(article, user)
357357
end)
358-
# |> Multi.run(:mention_users, fn _, %{create_comment: comment} ->
359-
# Delivery.mention_from_comment(community, thread, content, comment, args, user)
360-
# {:ok, :pass}
361-
# end)
362358
|> Repo.transaction()
363359
|> upsert_comment_result()
364360
end
@@ -368,7 +364,7 @@ defmodule GroupherServer.CMS.Delegate.ArticleComment do
368364
def reply_article_comment(comment_id, content, %User{} = user) do
369365
with {:ok, target_comment} <-
370366
ORM.find_by(ArticleComment, %{id: comment_id, is_deleted: false}),
371-
replying_comment <- Repo.preload(target_comment, :reply_to),
367+
replying_comment <- Repo.preload(target_comment, reply_to: :author),
372368
{thread, article} <- get_article(replying_comment),
373369
{:ok, info} <- match(thread),
374370
parent_comment <- get_parent_comment(replying_comment) do
@@ -394,6 +390,9 @@ defmodule GroupherServer.CMS.Delegate.ArticleComment do
394390
|> Multi.run(:add_participator, fn _, _ ->
395391
add_participator_to_article(article, user)
396392
end)
393+
|> Multi.run(:set_meta_flag, fn _, %{create_reply_comment: replyed_comment} ->
394+
update_reply_to_others_state(parent_comment, replying_comment, replyed_comment)
395+
end)
397396
|> Multi.run(:add_reply_to, fn _, %{create_reply_comment: replyed_comment} ->
398397
replyed_comment
399398
|> Repo.preload(:reply_to)
@@ -467,7 +466,8 @@ defmodule GroupherServer.CMS.Delegate.ArticleComment do
467466
end
468467

469468
# update comment's parent article's comments total count
470-
defp update_article_comments_count(%ArticleComment{} = comment, opt \\ :inc) do
469+
@spec update_article_comments_count(ArticleComment.t(), :inc | :dec) :: ArticleComment.t()
470+
defp update_article_comments_count(%ArticleComment{} = comment, opt) do
471471
with {:ok, article_info} <- match(:comment_article, comment),
472472
{:ok, article} <- ORM.find(article_info.model, article_info.id) do
473473
count_query =
@@ -479,7 +479,7 @@ defmodule GroupherServer.CMS.Delegate.ArticleComment do
479479
:inc ->
480480
ORM.update(article, %{article_comments_count: cur_count - 1 + 1})
481481

482-
_ ->
482+
:dec ->
483483
ORM.update(article, %{article_comments_count: Enum.max([0, cur_count - 1])})
484484
end
485485
end
@@ -515,9 +515,9 @@ defmodule GroupherServer.CMS.Delegate.ArticleComment do
515515
comment
516516
end
517517

518-
defp get_parent_comment(%ArticleComment{reply_to_id: _} = comment) do
519-
Repo.preload(comment, :reply_to) |> Map.get(:reply_to)
520-
# get_parent_comment(Repo.preload(comment, :reply_to))
518+
defp get_parent_comment(%ArticleComment{reply_to_id: reply_to_id} = comment)
519+
when not is_nil(reply_to_id) do
520+
get_parent_comment(Repo.preload(comment.reply_to, reply_to: :author))
521521
end
522522

523523
# 如果 replies 没有达到 @max_parent_replies_count, 则添加
@@ -563,18 +563,6 @@ defmodule GroupherServer.CMS.Delegate.ArticleComment do
563563

564564
defp add_participator_to_article(_, _), do: {:ok, :pass}
565565

566-
defp get_article(%ArticleComment{post_id: post_id} = comment) when not is_nil(post_id) do
567-
with {:ok, article} <- ORM.find(Post, comment.post_id, preload: [author: :user]) do
568-
{:post, article}
569-
end
570-
end
571-
572-
defp get_article(%ArticleComment{job_id: job_id} = comment) when not is_nil(job_id) do
573-
with {:ok, article} <- ORM.find(Job, comment.job_id, preload: [author: :user]) do
574-
{:job, article}
575-
end
576-
end
577-
578566
defp user_in_logins?([], _), do: false
579567
defp user_in_logins?(ids_list, %User{login: login}), do: Enum.member?(ids_list, login)
580568

@@ -599,6 +587,18 @@ defmodule GroupherServer.CMS.Delegate.ArticleComment do
599587
%{paged_comments | entries: new_entries}
600588
end
601589

590+
defp get_article(%ArticleComment{post_id: post_id} = comment) when not is_nil(post_id) do
591+
with {:ok, article} <- ORM.find(Post, comment.post_id, preload: [author: :user]) do
592+
{:post, article}
593+
end
594+
end
595+
596+
defp get_article(%ArticleComment{job_id: job_id} = comment) when not is_nil(job_id) do
597+
with {:ok, article} <- ORM.find(Job, comment.job_id, preload: [author: :user]) do
598+
{:job, article}
599+
end
600+
end
601+
602602
@spec get_full_comment(String.t()) :: {:ok, T.article_info()} | {:error, nil}
603603
defp get_full_comment(comment_id) do
604604
query = from(c in ArticleComment, where: c.id == ^comment_id, preload: :post, preload: :job)
@@ -633,6 +633,27 @@ defmodule GroupherServer.CMS.Delegate.ArticleComment do
633633
end
634634
end
635635

636+
# used in replies mode, for those reply to other user in replies box (for frontend)
637+
# 用于回复模式,指代这条回复是回复“回复列表其他人的” (方便前端展示)
638+
defp update_reply_to_others_state(parent_comment, replying_comment, replyed_comment) do
639+
replying_comment = replying_comment |> Repo.preload(:author)
640+
parent_comment = parent_comment |> Repo.preload(:author)
641+
is_reply_to_others = parent_comment.author.id !== replying_comment.author.id
642+
643+
case is_reply_to_others do
644+
true ->
645+
new_meta =
646+
replyed_comment.meta
647+
|> Map.from_struct()
648+
|> Map.merge(%{is_reply_to_others: is_reply_to_others})
649+
650+
ORM.update(replyed_comment, %{meta: new_meta})
651+
652+
false ->
653+
{:ok, :pass}
654+
end
655+
end
656+
636657
defp upsert_comment_result({:ok, %{create_article_comment: result}}), do: {:ok, result}
637658
defp upsert_comment_result({:ok, %{add_reply_to: result}}), do: {:ok, result}
638659
defp upsert_comment_result({:ok, %{check_article_author_upvoted: result}}), do: {:ok, result}

lib/groupher_server/cms/embeds/article_comment_meta.ex

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,12 @@ defmodule GroupherServer.CMS.Embeds.ArticleCommentMeta do
55
use Ecto.Schema
66
import Ecto.Changeset
77

8-
@optional_fields ~w(is_article_author_upvoted is_solution report_count)a
8+
@optional_fields ~w(is_article_author_upvoted is_solution report_count is_reply_to_others)a
99

1010
@default_meta %{
1111
is_article_author_upvoted: false,
1212
is_solution: false,
13+
is_reply_to_others: false,
1314
report_count: 0
1415
}
1516

@@ -19,7 +20,9 @@ defmodule GroupherServer.CMS.Embeds.ArticleCommentMeta do
1920
embedded_schema do
2021
field(:is_article_author_upvoted, :boolean, default: false)
2122
field(:is_solution, :boolean, default: false)
22-
23+
# used in replies mode, for those reply to other user in replies box (for frontend)
24+
# 用于回复模式,指代这条回复是回复“回复列表其他人的” (方便前端展示)
25+
field(:is_reply_to_others, :boolean, default: false)
2326
field(:report_count, :integer, default: 0)
2427
end
2528

lib/groupher_server_web/schema/cms/cms_types.ex

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,8 @@ defmodule GroupherServerWeb.Schema.CMS.Types do
336336

337337
object :article_comment_meta do
338338
field(:is_article_author_upvoted, :boolean)
339+
field(:is_reply_to_others, :boolean)
340+
339341
# field(:report_count, :boolean)
340342
# field(:is_solution, :boolean)
341343
end

test/groupher_server/cms/article_comment_replies_test.exs

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -65,33 +65,50 @@ defmodule GroupherServer.Test.CMS.ArticleCommentReplies do
6565
assert exist_in?(replyed_comment_2, parent_comment.replies)
6666
end
6767

68-
@tag :wip
68+
@tag :wip2
6969
test "reply to reply inside a comment should belong same parent comment",
7070
~m(post user user2)a do
71-
parent_content = "parent comment"
72-
reply_content_1 = "reply comment 1"
73-
reply_content_2 = "reply comment 2"
74-
75-
{:ok, parent_comment} = CMS.create_article_comment(:post, post.id, parent_content, user)
76-
77-
{:ok, replyed_comment_1} =
78-
CMS.reply_article_comment(parent_comment.id, reply_content_1, user2)
79-
80-
{:ok, replyed_comment_2} =
81-
CMS.reply_article_comment(replyed_comment_1.id, reply_content_2, user2)
71+
{:ok, parent_comment} = CMS.create_article_comment(:post, post.id, "parent comment", user)
8272

83-
# IO.inspect(replyed_comment_2, label: "replyed_comment_2")
73+
{:ok, replyed_comment_1} = CMS.reply_article_comment(parent_comment.id, "reply 1", user2)
74+
{:ok, replyed_comment_2} = CMS.reply_article_comment(replyed_comment_1.id, "reply 2", user2)
75+
{:ok, replyed_comment_3} = CMS.reply_article_comment(replyed_comment_2.id, "reply 3", user)
8476

8577
{:ok, parent_comment} = ORM.find(ArticleComment, parent_comment.id)
8678

79+
# IO.inspect(parent_comment.replies, label: "parent_comment.replies")
80+
8781
assert exist_in?(replyed_comment_1, parent_comment.replies)
8882
assert exist_in?(replyed_comment_2, parent_comment.replies)
83+
assert exist_in?(replyed_comment_3, parent_comment.replies)
8984

9085
{:ok, replyed_comment_1} = ORM.find(ArticleComment, replyed_comment_1.id)
9186
{:ok, replyed_comment_2} = ORM.find(ArticleComment, replyed_comment_2.id)
87+
{:ok, replyed_comment_3} = ORM.find(ArticleComment, replyed_comment_3.id)
9288

9389
assert replyed_comment_1.reply_to_id == parent_comment.id
9490
assert replyed_comment_2.reply_to_id == replyed_comment_1.id
91+
assert replyed_comment_3.reply_to_id == replyed_comment_2.id
92+
end
93+
94+
@tag :wip2
95+
test "reply to reply inside a comment should have is_reply_to_others flag in meta",
96+
~m(post user user2)a do
97+
{:ok, parent_comment} = CMS.create_article_comment(:post, post.id, "parent comment", user)
98+
99+
{:ok, replyed_comment_1} = CMS.reply_article_comment(parent_comment.id, "reply 1", user2)
100+
{:ok, replyed_comment_2} = CMS.reply_article_comment(replyed_comment_1.id, "reply 2", user2)
101+
{:ok, replyed_comment_3} = CMS.reply_article_comment(replyed_comment_2.id, "reply 3", user)
102+
103+
{:ok, parent_comment} = ORM.find(ArticleComment, parent_comment.id)
104+
105+
{:ok, replyed_comment_1} = ORM.find(ArticleComment, replyed_comment_1.id)
106+
{:ok, replyed_comment_2} = ORM.find(ArticleComment, replyed_comment_2.id)
107+
{:ok, replyed_comment_3} = ORM.find(ArticleComment, replyed_comment_3.id)
108+
109+
assert not replyed_comment_1.meta.is_reply_to_others
110+
assert replyed_comment_2.meta.is_reply_to_others
111+
assert replyed_comment_3.meta.is_reply_to_others
95112
end
96113

97114
@tag :wip

test/groupher_server_web/query/cms/article_comment_test.exs

Lines changed: 80 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -17,86 +17,6 @@ defmodule GroupherServer.Test.Query.ArticleComment do
1717
{:ok, ~m(user_conn guest_conn post job user user2)a}
1818
end
1919

20-
describe "paged replies" do
21-
@query """
22-
query($id: ID!, $filter: CommentsFilter!) {
23-
pagedCommentReplies(id: $id, filter: $filter) {
24-
entries {
25-
id
26-
bodyHtml
27-
author {
28-
id
29-
nickname
30-
}
31-
upvotesCount
32-
emotions {
33-
downvoteCount
34-
latestDownvoteUsers {
35-
login
36-
nickname
37-
}
38-
viewerHasDownvoteed
39-
beerCount
40-
latestBeerUsers {
41-
login
42-
nickname
43-
}
44-
viewerHasBeered
45-
}
46-
isArticleAuthor
47-
meta {
48-
isArticleAuthorUpvoted
49-
}
50-
replyTo {
51-
id
52-
bodyHtml
53-
floor
54-
isArticleAuthor
55-
author {
56-
id
57-
login
58-
}
59-
}
60-
repliesCount
61-
viewerHasUpvoted
62-
}
63-
totalPages
64-
totalCount
65-
pageSize
66-
pageNumber
67-
}
68-
}
69-
"""
70-
@tag :wip2
71-
test "guest user can get paged replies", ~m(guest_conn post user user2)a do
72-
comment = "test comment"
73-
total_count = 2
74-
page_size = 10
75-
thread = :post
76-
77-
author_user = post.author.user
78-
{:ok, parent_comment} = CMS.create_article_comment(thread, post.id, comment, user)
79-
80-
Enum.reduce(1..total_count, [], fn i, acc ->
81-
{:ok, reply_comment} = CMS.reply_article_comment(parent_comment.id, "reply #{i}", user2)
82-
83-
acc ++ [reply_comment]
84-
end)
85-
86-
{:ok, author_reply_comment} =
87-
CMS.reply_article_comment(parent_comment.id, "author reply", author_user)
88-
89-
variables = %{id: parent_comment.id, filter: %{page: 1, size: page_size}}
90-
results = guest_conn |> query_result(@query, variables, "pagedCommentReplies")
91-
92-
author_reply_comment =
93-
Enum.find(results["entries"], &(&1["id"] == to_string(author_reply_comment.id)))
94-
95-
assert author_reply_comment["isArticleAuthor"]
96-
assert results["entries"] |> length == total_count + 1
97-
end
98-
end
99-
10020
describe "[baisc article post comment]" do
10121
@query """
10222
query($id: ID!) {
@@ -573,4 +493,84 @@ defmodule GroupherServer.Test.Query.ArticleComment do
573493
assert upvoted_comment["viewerHasUpvoted"]
574494
end
575495
end
496+
497+
describe "paged replies" do
498+
@query """
499+
query($id: ID!, $filter: CommentsFilter!) {
500+
pagedCommentReplies(id: $id, filter: $filter) {
501+
entries {
502+
id
503+
bodyHtml
504+
author {
505+
id
506+
nickname
507+
}
508+
upvotesCount
509+
emotions {
510+
downvoteCount
511+
latestDownvoteUsers {
512+
login
513+
nickname
514+
}
515+
viewerHasDownvoteed
516+
beerCount
517+
latestBeerUsers {
518+
login
519+
nickname
520+
}
521+
viewerHasBeered
522+
}
523+
isArticleAuthor
524+
meta {
525+
isArticleAuthorUpvoted
526+
}
527+
replyTo {
528+
id
529+
bodyHtml
530+
floor
531+
isArticleAuthor
532+
author {
533+
id
534+
login
535+
}
536+
}
537+
repliesCount
538+
viewerHasUpvoted
539+
}
540+
totalPages
541+
totalCount
542+
pageSize
543+
pageNumber
544+
}
545+
}
546+
"""
547+
@tag :wip
548+
test "guest user can get paged replies", ~m(guest_conn post user user2)a do
549+
comment = "test comment"
550+
total_count = 2
551+
page_size = 10
552+
thread = :post
553+
554+
author_user = post.author.user
555+
{:ok, parent_comment} = CMS.create_article_comment(thread, post.id, comment, user)
556+
557+
Enum.reduce(1..total_count, [], fn i, acc ->
558+
{:ok, reply_comment} = CMS.reply_article_comment(parent_comment.id, "reply #{i}", user2)
559+
560+
acc ++ [reply_comment]
561+
end)
562+
563+
{:ok, author_reply_comment} =
564+
CMS.reply_article_comment(parent_comment.id, "author reply", author_user)
565+
566+
variables = %{id: parent_comment.id, filter: %{page: 1, size: page_size}}
567+
results = guest_conn |> query_result(@query, variables, "pagedCommentReplies")
568+
569+
author_reply_comment =
570+
Enum.find(results["entries"], &(&1["id"] == to_string(author_reply_comment.id)))
571+
572+
assert author_reply_comment["isArticleAuthor"]
573+
assert results["entries"] |> length == total_count + 1
574+
end
575+
end
576576
end

0 commit comments

Comments
 (0)