Skip to content
This repository was archived by the owner on Nov 8, 2022. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion lib/groupher_server/cms/article_comment.ex
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ defmodule GroupherServer.CMS.ArticleComment do

@required_fields ~w(body_html author_id)a
@optional_fields ~w(post_id job_id reply_to_id replies_count is_folded is_reported is_deleted floor is_article_author)a
@updatable_fields ~w(is_folded is_reported is_deleted floor upvotes_count)a
@updatable_fields ~w(is_folded is_reported is_deleted floor upvotes_count is_pined)a

@max_participator_count 5
@max_parent_replies_count 3
Expand All @@ -32,6 +32,9 @@ defmodule GroupherServer.CMS.ArticleComment do
# 举报超过此数评论会被自动折叠
@report_threshold_for_fold 5

# 每篇文章最多含有置顶评论的条数
@pined_comment_limit 10

@doc "latest participators stores in article comment_participators field"
def max_participator_count(), do: @max_participator_count
@doc "latest replies stores in article_comment replies field, used for frontend display"
Expand All @@ -44,6 +47,7 @@ defmodule GroupherServer.CMS.ArticleComment do
def delete_hint(), do: @delete_hint

def report_threshold_for_fold, do: @report_threshold_for_fold
def pined_comment_limit, do: @pined_comment_limit

@type t :: %ArticleComment{}
schema "articles_comments" do
Expand All @@ -63,6 +67,9 @@ defmodule GroupherServer.CMS.ArticleComment do
field(:is_article_author, :boolean, default: false)
field(:upvotes_count, :integer, default: 0)

# 是否置顶
field(:is_pined, :boolean, default: false)

belongs_to(:author, Accounts.User, foreign_key: :author_id)
belongs_to(:post, Post, foreign_key: :post_id)
belongs_to(:job, Job, foreign_key: :job_id)
Expand Down
44 changes: 44 additions & 0 deletions lib/groupher_server/cms/article_pined_comment.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
defmodule GroupherServer.CMS.ArticlePinedComment do
@moduledoc false
alias __MODULE__

use Ecto.Schema
use Accessible

import Ecto.Changeset

alias GroupherServer.CMS

alias CMS.{
Post,
Job,
ArticleComment
}

# alias Helper.HTML

@required_fields ~w(article_comment_id)a
@optional_fields ~w(post_id job_id)a

@type t :: %ArticlePinedComment{}
schema "articles_pined_comments" do
belongs_to(:article_comment, ArticleComment, foreign_key: :article_comment_id)
belongs_to(:post, Post, foreign_key: :post_id)
belongs_to(:job, Job, foreign_key: :job_id)

timestamps(type: :utc_datetime)
end

@doc false
def changeset(%ArticlePinedComment{} = article_pined_comment, attrs) do
article_pined_comment
|> cast(attrs, @required_fields ++ @optional_fields)
|> validate_required(@required_fields)
end

# @doc false
def update_changeset(%ArticlePinedComment{} = article_pined_comment, attrs) do
article_pined_comment
|> cast(attrs, @required_fields ++ @updatable_fields)
end
end
3 changes: 3 additions & 0 deletions lib/groupher_server/cms/cms.ex
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,9 @@ defmodule GroupherServer.CMS do
defdelegate delete_article_comment(comment_id, user), to: ArticleComment
defdelegate reply_article_comment(comment_id, args, user), to: ArticleComment

defdelegate pin_article_comment(comment_id), to: ArticleComment
defdelegate undo_pin_article_comment(comment_id), to: ArticleComment

defdelegate make_emotion(comment_id, args, user), to: ArticleComment
defdelegate fold_article_comment(comment_id, user), to: ArticleComment
defdelegate unfold_article_comment(comment_id, user), to: ArticleComment
Expand Down
97 changes: 92 additions & 5 deletions lib/groupher_server/cms/delegates/article_comment.ex
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ defmodule GroupherServer.CMS.Delegate.ArticleComment do

alias CMS.{
ArticleComment,
ArticlePinedComment,
ArticleCommentUpvote,
ArticleCommentReply,
ArticleCommentUserEmotion,
Expand All @@ -35,6 +36,7 @@ defmodule GroupherServer.CMS.Delegate.ArticleComment do
@report_threshold_for_fold ArticleComment.report_threshold_for_fold()

@default_comment_meta Embeds.ArticleCommentMeta.default_meta()
@pined_comment_limit ArticleComment.pined_comment_limit()

@doc """
list paged article comments
Expand All @@ -43,9 +45,10 @@ defmodule GroupherServer.CMS.Delegate.ArticleComment do
with {:ok, thread_query} <- match(thread, :query, article_id) do
ArticleComment
|> where(^thread_query)
|> where([c], c.is_folded == false and c.is_reported == false)
|> where([c], c.is_folded == false and c.is_reported == false and c.is_pined == false)
|> QueryBuilder.filter_pack(filters)
|> ORM.paginater(~m(page size)a)
|> add_pined_comments_ifneed(thread, article_id, filters)
|> done()
end
end
Expand All @@ -59,19 +62,53 @@ defmodule GroupherServer.CMS.Delegate.ArticleComment do
with {:ok, thread_query} <- match(thread, :query, article_id) do
ArticleComment
|> where(^thread_query)
|> where([c], c.is_folded == false and c.is_reported == false)
|> where([c], c.is_folded == false and c.is_reported == false and c.is_pined == false)
|> QueryBuilder.filter_pack(filters)
|> ORM.paginater(~m(page size)a)
|> check_viewer_has_emotioned(user)
|> add_pined_comments_ifneed(thread, article_id, filters)
|> done()
end
end

# TODO: @pined_comment_limit 10
defp add_pined_comments_ifneed(%{entries: entries} = paged_comments, thread, article_id, %{
page: 1
}) do
with {:ok, info} <- match(thread),
query <-
from(p in ArticlePinedComment,
join: c in ArticleComment,
on: p.article_comment_id == c.id,
where: field(p, ^info.foreign_key) == ^article_id,
select: c
),
{:ok, pined_comments} <- query |> Repo.all() |> done() do
case pined_comments do
[] ->
paged_comments

_ ->
updated_entries =
Enum.concat(Enum.slice(pined_comments, 0, @pined_comment_limit), entries)

pined_comment_count = length(pined_comments)

Map.merge(paged_comments, %{
entries: updated_entries,
total_count: paged_comments.total_count + pined_comment_count
})
end
end
end

defp add_pined_comments_ifneed(paged_comments, _thread, _article_id, _), do: paged_comments

def list_folded_article_comments(thread, article_id, %{page: page, size: size} = filters) do
with {:ok, thread_query} <- match(thread, :query, article_id) do
ArticleComment
|> where(^thread_query)
|> where([c], c.is_folded == true and c.is_reported == false)
|> where([c], c.is_folded == true and c.is_reported == false and c.is_pined == false)
|> QueryBuilder.filter_pack(filters)
|> ORM.paginater(~m(page size)a)
|> done()
Expand All @@ -87,7 +124,7 @@ defmodule GroupherServer.CMS.Delegate.ArticleComment do
with {:ok, thread_query} <- match(thread, :query, article_id) do
ArticleComment
|> where(^thread_query)
|> where([c], c.is_folded == true and c.is_reported == false)
|> where([c], c.is_folded == true and c.is_reported == false and c.is_pined == false)
|> QueryBuilder.filter_pack(filters)
|> ORM.paginater(~m(page size)a)
|> check_viewer_has_emotioned(user)
Expand Down Expand Up @@ -136,6 +173,55 @@ defmodule GroupherServer.CMS.Delegate.ArticleComment do
|> done()
end

@doc "pin a comment"
def pin_article_comment(comment_id) do
with {:ok, comment} <- ORM.find(ArticleComment, comment_id),
{:ok, full_comment} <- get_full_comment(comment.id),
{:ok, info} <- match(full_comment.thread) do
Multi.new()
|> Multi.run(:checked_pined_comments_count, fn _, _ ->
count_query =
from(p in ArticlePinedComment,
where: field(p, ^info.foreign_key) == ^full_comment.article.id
)

pined_comments_count = Repo.aggregate(count_query, :count)

case pined_comments_count >= @pined_comment_limit do
true -> {:error, "only support #{@pined_comment_limit} pined comment for each article"}
false -> {:ok, :pass}
end
end)
|> Multi.run(:update_comment_flag, fn _, _ ->
ORM.update(comment, %{is_pined: true})
end)
|> Multi.run(:add_pined_comment, fn _, _ ->
ArticlePinedComment
|> ORM.create(
%{article_comment_id: comment.id}
|> Map.put(info.foreign_key, full_comment.article.id)
)
end)
|> Repo.transaction()
|> upsert_comment_result()
end
end

def undo_pin_article_comment(comment_id) do
with {:ok, comment} <- ORM.find(ArticleComment, comment_id) do
Multi.new()
|> Multi.run(:update_comment_flag, fn _, _ ->
ORM.update(comment, %{is_pined: false})
end)
|> Multi.run(:remove_pined_comment, fn _, _ ->
ORM.findby_delete(ArticlePinedComment, %{article_comment_id: comment.id})
end)
|> Repo.transaction()
|> upsert_comment_result()
end
end

# TODO: remove pined record if need
def delete_article_comment(comment_id, %User{} = _user) do
with {:ok, comment} <-
ORM.find(ArticleComment, comment_id) do
Expand Down Expand Up @@ -514,7 +600,7 @@ defmodule GroupherServer.CMS.Delegate.ArticleComment do
with {:ok, article_with_author} <- Repo.preload(article, author: :user) |> done(),
article_author <- get_in(article_with_author, [:author, :user]) do
#
article_info = %{title: article.title}
article_info = %{title: article.title, id: article.id}

author_info = %{
id: article_author.id,
Expand All @@ -531,6 +617,7 @@ defmodule GroupherServer.CMS.Delegate.ArticleComment do
defp upsert_comment_result({:ok, %{check_article_author_upvoted: result}}), do: {:ok, result}
defp upsert_comment_result({:ok, %{update_report_flag: result}}), do: {:ok, result}
defp upsert_comment_result({:ok, %{update_comment_emotion: result}}), do: {:ok, result}
defp upsert_comment_result({:ok, %{update_comment_flag: result}}), do: {:ok, result}

defp upsert_comment_result({:error, :create_comment, result, _steps}) do
{:error, result}
Expand Down
2 changes: 2 additions & 0 deletions lib/groupher_server/cms/post.ex
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ defmodule GroupherServer.CMS.Post do
Embeds,
Author,
ArticleComment,
ArticlePinedComment,
Community,
PostComment,
PostCommunityFlag,
Expand Down Expand Up @@ -58,6 +59,7 @@ defmodule GroupherServer.CMS.Post do
has_many(:comments, {"posts_comments", PostComment})

has_many(:article_comments, {"articles_comments", ArticleComment})
has_many(:article_pined_comments, {"articles_pined_comments", ArticlePinedComment})

has_many(:favorites, {"posts_favorites", PostFavorite})
has_many(:stars, {"posts_stars", PostStar})
Expand Down
3 changes: 3 additions & 0 deletions lib/helper/types.ex
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ defmodule Helper.Types do
}

@type article_thread :: :post | :job
@type article_common :: %{
title: String.t()
}
@type article_info :: %{
thread: article_thread,
article: %{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
defmodule GroupherServer.Repo.Migrations.AddPinToArticleComments do
use Ecto.Migration

def change do
alter table(:articles_comments) do
add(:is_pined, :boolean, default: false)
end

create table(:articles_pined_comments) do
add(:post_id, references(:cms_posts, on_delete: :delete_all))
add(:job_id, references(:cms_jobs, on_delete: :delete_all))

add(:article_comment_id, references(:articles_comments, on_delete: :delete_all), null: false)

timestamps()
end

create(index(:articles_pined_comments, [:post_id]))
create(index(:articles_pined_comments, [:job_id]))
create(index(:articles_pined_comments, [:article_comment_id]))

create(unique_index(:articles_pined_comments, [:post_id, :job_id, :article_comment_id]))
end
end
Loading