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

Commit 543323e

Browse files
authored
refactor(pined-article): use common table (#331)
* refactor(pin-article): basic workflow * refactor(pinned-article): max_pinned_article_count_per_thread * refactor(pinned-article): add/alter is_pinned field * refactor(pinned-article): undo pin article * refactor(pinned-article): wip * refactor(pinned-article): fix pined test & re-org * refactor(pinned-article): wip * refactor(pinned-article): wip
1 parent 295704c commit 543323e

34 files changed

+304
-337
lines changed

lib/groupher_server/cms/article_comment.ex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ defmodule GroupherServer.CMS.ArticleComment do
2020

2121
@required_fields ~w(body_html author_id)a
2222
@optional_fields ~w(post_id job_id reply_to_id replies_count is_folded is_reported is_deleted floor is_article_author)a
23-
@updatable_fields ~w(is_folded is_reported is_deleted floor upvotes_count is_pined)a
23+
@updatable_fields ~w(is_folded is_reported is_deleted floor upvotes_count is_pinned)a
2424

2525
@max_participator_count 5
2626
@max_parent_replies_count 3
@@ -66,7 +66,7 @@ defmodule GroupherServer.CMS.ArticleComment do
6666
field(:upvotes_count, :integer, default: 0)
6767

6868
# 是否置顶
69-
field(:is_pined, :boolean, default: false)
69+
field(:is_pinned, :boolean, default: false)
7070

7171
belongs_to(:author, Accounts.User, foreign_key: :author_id)
7272
belongs_to(:post, Post, foreign_key: :post_id)

lib/groupher_server/cms/cms.ex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,8 @@ defmodule GroupherServer.CMS do
8686
# ArticleOperation
8787
# >> set flag on article, like: pin / unpin article
8888
defdelegate set_community_flags(community_info, queryable, attrs), to: ArticleOperation
89-
defdelegate pin_content(queryable, community_id), to: ArticleOperation
90-
defdelegate undo_pin_content(queryable, community_id), to: ArticleOperation
89+
defdelegate pin_article(thread, id, community_id), to: ArticleOperation
90+
defdelegate undo_pin_article(thread, id, community_id), to: ArticleOperation
9191

9292
defdelegate lock_article_comment(content), to: ArticleOperation
9393

lib/groupher_server/cms/community.ex

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,14 @@ defmodule GroupherServer.CMS.Community do
1919
CommunityCheatsheet
2020
}
2121

22+
@max_pinned_article_count_per_thread 2
23+
2224
@required_fields ~w(title desc user_id logo raw)a
2325
# @required_fields ~w(title desc user_id)a
2426
@optional_fields ~w(label geo_info index aka)a
2527

28+
def max_pinned_article_count_per_thread, do: @max_pinned_article_count_per_thread
29+
2630
schema "communities" do
2731
field(:title, :string)
2832
field(:aka, :string)

lib/groupher_server/cms/delegates/article_comment.ex

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ defmodule GroupherServer.CMS.Delegate.ArticleComment do
4646
def list_article_comments(thread, article_id, filters, mode, user \\ nil)
4747

4848
def list_article_comments(thread, article_id, filters, :timeline, user) do
49-
where_query = dynamic([c], not c.is_folded and not c.is_reported and not c.is_pined)
49+
where_query = dynamic([c], not c.is_folded and not c.is_reported and not c.is_pinned)
5050
do_list_article_comment(thread, article_id, filters, where_query, user)
5151
end
5252

@@ -57,19 +57,19 @@ defmodule GroupherServer.CMS.Delegate.ArticleComment do
5757
where_query =
5858
dynamic(
5959
[c],
60-
is_nil(c.reply_to_id) and not c.is_folded and not c.is_reported and not c.is_pined
60+
is_nil(c.reply_to_id) and not c.is_folded and not c.is_reported and not c.is_pinned
6161
)
6262

6363
do_list_article_comment(thread, article_id, filters, where_query, user)
6464
end
6565

6666
def list_folded_article_comments(thread, article_id, filters) do
67-
where_query = dynamic([c], c.is_folded and not c.is_reported and not c.is_pined)
67+
where_query = dynamic([c], c.is_folded and not c.is_reported and not c.is_pinned)
6868
do_list_article_comment(thread, article_id, filters, where_query, nil)
6969
end
7070

7171
def list_folded_article_comments(thread, article_id, filters, user) do
72-
where_query = dynamic([c], c.is_folded and not c.is_reported and not c.is_pined)
72+
where_query = dynamic([c], c.is_folded and not c.is_reported and not c.is_pinned)
7373
do_list_article_comment(thread, article_id, filters, where_query, user)
7474
end
7575

@@ -129,7 +129,7 @@ defmodule GroupherServer.CMS.Delegate.ArticleComment do
129129
end
130130
end)
131131
|> Multi.run(:update_comment_flag, fn _, _ ->
132-
ORM.update(comment, %{is_pined: true})
132+
ORM.update(comment, %{is_pinned: true})
133133
end)
134134
|> Multi.run(:add_pined_comment, fn _, _ ->
135135
ArticlePinedComment
@@ -147,7 +147,7 @@ defmodule GroupherServer.CMS.Delegate.ArticleComment do
147147
with {:ok, comment} <- ORM.find(ArticleComment, comment_id) do
148148
Multi.new()
149149
|> Multi.run(:update_comment_flag, fn _, _ ->
150-
ORM.update(comment, %{is_pined: false})
150+
ORM.update(comment, %{is_pinned: false})
151151
end)
152152
|> Multi.run(:remove_pined_comment, fn _, _ ->
153153
ORM.findby_delete(ArticlePinedComment, %{article_comment_id: comment.id})

lib/groupher_server/cms/delegates/article_curd.ex

Lines changed: 11 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,18 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do
33
CURD operation on post/job ...
44
"""
55
import Ecto.Query, warn: false
6-
import GroupherServer.CMS.Utils.Matcher
6+
7+
import GroupherServer.CMS.Utils.Matcher2
8+
9+
import GroupherServer.CMS.Utils.Matcher, only: [match_action: 2, dynamic_where: 2]
710
import Helper.Utils, only: [done: 1, pick_by: 2, integerfy: 1]
811
import Helper.ErrorCode
912
import ShortMaps
1013

1114
alias GroupherServer.{Accounts, CMS, Delivery, Email, Repo, Statistics}
1215

1316
alias Accounts.User
14-
alias CMS.{Author, Community, Embeds, Delegate, Tag}
17+
alias CMS.{Author, Community, PinnedArticle, Embeds, Delegate, Tag}
1518

1619
alias Delegate.ArticleOperation
1720
alias Helper.{Later, ORM, QueryBuilder}
@@ -271,28 +274,22 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do
271274
end
272275

273276
defp read_state_query(queryable, %{read: false} = _filter, _user) do
274-
# queryable
275-
# |> join(:left, [content, f, c], viewers in assoc(content, :viewers))
276-
# |> where([content, f, c, viewers], viewers.user_id != ^user.id)
277-
# |> where([content, f, c, viewers], content.id != viewers.post_id)
278-
# |> IO.inspect(label: "query")
279277
queryable
280278
end
281279

282280
defp read_state_query(queryable, _, _), do: queryable
283281

284-
# only first page need pin contents
285-
# TODO: use seperate pined table, which is much more smaller
286-
defp add_pin_contents_ifneed(contents, CMS.Post, %{community: community} = filter) do
282+
defp add_pin_contents_ifneed(contents, querable, %{community: _community} = filter) do
287283
with {:ok, _} <- should_add_pin?(filter),
284+
{:ok, info} <- match(querable),
288285
{:ok, normal_contents} <- contents,
289286
true <- Map.has_key?(filter, :community),
290287
true <- 1 == Map.get(normal_contents, :page_number) do
291288
{:ok, pined_content} =
292-
CMS.PinedPost
289+
PinnedArticle
293290
|> join(:inner, [p], c in assoc(p, :community))
294-
|> join(:inner, [p], content in assoc(p, :post))
295-
|> where([p, c, content], c.raw == ^community)
291+
|> join(:inner, [p], content in assoc(p, ^info.thread))
292+
|> where([p, c, content], c.raw == ^filter.community)
296293
|> select([p, c, content], content)
297294
# 10 pined contents per community/thread, at most
298295
|> ORM.paginater(%{page: 1, size: 10})
@@ -305,38 +302,8 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do
305302
end
306303
end
307304

308-
defp add_pin_contents_ifneed(contents, CMS.Job, %{community: _community} = filter) do
309-
merge_pin_contents(contents, :job, CMS.PinedJob, filter)
310-
end
311-
312-
defp add_pin_contents_ifneed(contents, CMS.Repo, %{community: _community} = filter) do
313-
merge_pin_contents(contents, :repo, CMS.PinedRepo, filter)
314-
end
315-
316305
defp add_pin_contents_ifneed(contents, _querable, _filter), do: contents
317306

318-
defp merge_pin_contents(contents, thread, pin_schema, %{community: _community} = filter) do
319-
with {:ok, _} <- should_add_pin?(filter),
320-
{:ok, normal_contents} <- contents,
321-
true <- Map.has_key?(filter, :community),
322-
true <- 1 == Map.get(normal_contents, :page_number) do
323-
{:ok, pined_content} =
324-
pin_schema
325-
|> join(:inner, [p], c in assoc(p, :community))
326-
|> join(:inner, [p], content in assoc(p, ^thread))
327-
|> where([p, c, content], c.raw == ^filter.community)
328-
|> select([p, c, content], content)
329-
# 10 pined contents per community/thread, at most
330-
|> ORM.paginater(%{page: 1, size: 10})
331-
|> done()
332-
333-
concat_contents(pined_content, normal_contents)
334-
else
335-
_error ->
336-
contents
337-
end
338-
end
339-
340307
# if filter contains like: tags, sort.., then don't add pin content
341308
defp should_add_pin?(%{page: 1, tag: :all, sort: :desc_inserted, read: :all} = filter) do
342309
filter
@@ -356,7 +323,7 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do
356323
pind_entries =
357324
pined_content
358325
|> Map.get(:entries)
359-
|> Enum.map(&struct(&1, %{pin: true}))
326+
|> Enum.map(&struct(&1, %{is_pinned: true}))
360327

361328
normal_entries = normal_contents |> Map.get(:entries)
362329

lib/groupher_server/cms/delegates/article_operation.ex

Lines changed: 42 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,12 @@ defmodule GroupherServer.CMS.Delegate.ArticleOperation do
44
"""
55
import GroupherServer.CMS.Utils.Matcher
66
import Ecto.Query, warn: false
7-
# import Helper.ErrorCode
7+
8+
import Helper.ErrorCode
89
import ShortMaps
10+
import GroupherServer.CMS.Utils.Matcher2
911

12+
alias Helper.Types, as: T
1013
alias Helper.ORM
1114

1215
alias GroupherServer.CMS.{
@@ -18,59 +21,43 @@ defmodule GroupherServer.CMS.Delegate.ArticleOperation do
1821
JobCommunityFlag,
1922
RepoCommunityFlag,
2023
Tag,
21-
PinedPost,
22-
PinedJob,
23-
PinedRepo
24+
PinnedArticle
2425
}
2526

2627
alias GroupherServer.CMS.Repo, as: CMSRepo
2728
alias GroupherServer.Repo
2829

29-
def pin_content(%Post{id: post_id}, %Community{id: community_id}) do
30-
with {:ok, pined} <-
31-
ORM.findby_or_insert(
32-
PinedPost,
33-
~m(post_id community_id)a,
34-
~m(post_id community_id)a
35-
) do
36-
Post |> ORM.find(pined.post_id)
37-
end
38-
end
39-
40-
def pin_content(%Job{id: job_id}, %Community{id: community_id}) do
41-
attrs = ~m(job_id community_id)a
30+
@max_pinned_article_count_per_thread Community.max_pinned_article_count_per_thread()
4231

43-
with {:ok, pined} <- ORM.findby_or_insert(PinedJob, attrs, attrs) do
44-
Job |> ORM.find(pined.job_id)
32+
@spec pin_article(T.article_thread(), Integer.t(), Integer.t()) :: {:ok, PinnedArticle.t()}
33+
def pin_article(thread, article_id, community_id) do
34+
with {:ok, info} <- match(thread),
35+
args <- pack_pin_args(thread, article_id, community_id),
36+
{:ok, _} <- check_pinned_article_count(args.community_id, thread),
37+
{:ok, _} <- ORM.create(PinnedArticle, args) do
38+
ORM.find(info.model, article_id)
4539
end
4640
end
4741

48-
def pin_content(%CMSRepo{id: repo_id}, %Community{id: community_id}) do
49-
attrs = ~m(repo_id community_id)a
50-
51-
with {:ok, pined} <- ORM.findby_or_insert(PinedRepo, attrs, attrs) do
52-
CMSRepo |> ORM.find(pined.repo_id)
42+
@spec undo_pin_article(T.article_thread(), Integer.t(), Integer.t()) :: {:ok, PinnedArticle.t()}
43+
def undo_pin_article(thread, article_id, community_id) do
44+
with {:ok, info} <- match(thread),
45+
args <- pack_pin_args(thread, article_id, community_id) do
46+
ORM.findby_delete(PinnedArticle, args)
47+
ORM.find(info.model, article_id)
5348
end
5449
end
5550

56-
def undo_pin_content(%Post{id: post_id}, %Community{id: community_id}) do
57-
with {:ok, pined} <- ORM.find_by(PinedPost, ~m(post_id community_id)a),
58-
{:ok, deleted} <- ORM.delete(pined) do
59-
Post |> ORM.find(deleted.post_id)
60-
end
61-
end
51+
defp pack_pin_args(thread, article_id, community_id) do
52+
with {:ok, info} <- match(thread),
53+
{:ok, community} <- ORM.find(Community, community_id) do
54+
thread_upcase = thread |> to_string |> String.upcase()
6255

63-
def undo_pin_content(%Job{id: job_id}, %Community{id: community_id}) do
64-
with {:ok, pined} <- ORM.find_by(PinedJob, ~m(job_id community_id)a),
65-
{:ok, deleted} <- ORM.delete(pined) do
66-
Job |> ORM.find(deleted.job_id)
67-
end
68-
end
69-
70-
def undo_pin_content(%CMSRepo{id: repo_id}, %Community{id: community_id}) do
71-
with {:ok, pined} <- ORM.find_by(PinedRepo, ~m(repo_id community_id)a),
72-
{:ok, deleted} <- ORM.delete(pined) do
73-
CMSRepo |> ORM.find(deleted.repo_id)
56+
Map.put(
57+
%{community_id: community.id, thread: thread_upcase},
58+
info.foreign_key,
59+
article_id
60+
)
7461
end
7562
end
7663

@@ -255,18 +242,20 @@ defmodule GroupherServer.CMS.Delegate.ArticleOperation do
255242
|> Repo.update()
256243
end
257244

258-
# make sure the reuest tag is in the current community thread
259-
# example: you can't set a other thread tag to this thread's article
245+
# check if the thread has aready enough pined articles
246+
defp check_pinned_article_count(community_id, thread) do
247+
thread_upcase = thread |> to_string |> String.upcase()
260248

261-
# defp tag_in_community_thread?(%Community{id: communityId}, thread, tag) do
262-
# with {:ok, community} <- ORM.find(Community, communityId) do
263-
# matched_tags =
264-
# Tag
265-
# |> where([t], t.community_id == ^community.id)
266-
# |> where([t], t.thread == ^to_string(thread))
267-
# |> Repo.all()
249+
query =
250+
from(p in PinnedArticle,
251+
where: p.community_id == ^community_id and p.thread == ^thread_upcase
252+
)
268253

269-
# tag in matched_tags
270-
# end
271-
# end
254+
pinned_articles = query |> Repo.all()
255+
256+
case length(pinned_articles) >= @max_pinned_article_count_per_thread do
257+
true -> raise_error(:too_much_pinned_article, "too much pinned article")
258+
_ -> {:ok, :pass}
259+
end
260+
end
272261
end

lib/groupher_server/cms/job.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ defmodule GroupherServer.CMS.Job do
5656
has_many(:community_flags, {"jobs_communities_flags", JobCommunityFlag})
5757

5858
# NOTE: this one is tricky, pin is dynamic changed when return by func: add_pin_contents_ifneed
59-
field(:pin, :boolean, default_value: false, virtual: true)
59+
field(:is_pinned, :boolean, default: false, virtual: true)
6060
field(:trash, :boolean, default_value: false, virtual: true)
6161

6262
has_many(:article_comments, {"articles_comments", ArticleComment})

lib/groupher_server/cms/pined_job.ex

Lines changed: 0 additions & 30 deletions
This file was deleted.

lib/groupher_server/cms/pined_post.ex

Lines changed: 0 additions & 30 deletions
This file was deleted.

0 commit comments

Comments
 (0)