diff --git a/lib/groupher_server/cms/community.ex b/lib/groupher_server/cms/community.ex index f7a830b87..10c1358a6 100644 --- a/lib/groupher_server/cms/community.ex +++ b/lib/groupher_server/cms/community.ex @@ -19,12 +19,14 @@ defmodule GroupherServer.CMS.Community do CommunityCheatsheet } + @article_threads [:post, :job, :repo] @max_pinned_article_count_per_thread 2 @required_fields ~w(title desc user_id logo raw)a # @required_fields ~w(title desc user_id)a @optional_fields ~w(label geo_info index aka)a + def article_threads, do: @article_threads def max_pinned_article_count_per_thread, do: @max_pinned_article_count_per_thread schema "communities" do diff --git a/lib/groupher_server/cms/delegates/abuse_report.ex b/lib/groupher_server/cms/delegates/abuse_report.ex index 5d5f265be..e39b3912e 100644 --- a/lib/groupher_server/cms/delegates/abuse_report.ex +++ b/lib/groupher_server/cms/delegates/abuse_report.ex @@ -13,13 +13,13 @@ defmodule GroupherServer.CMS.Delegate.AbuseReport do alias GroupherServer.{Accounts, CMS, Repo} alias Accounts.User - alias CMS.{AbuseReport, ArticleComment, Embeds} + alias CMS.{Community, AbuseReport, ArticleComment, Embeds} alias Ecto.Multi @report_threshold_for_fold ArticleComment.report_threshold_for_fold() - @article_threads [:post, :job, :repo] + @article_threads Community.article_threads() @export_author_keys [:id, :login, :nickname, :avatar] @export_article_keys [:id, :title, :digest, :upvotes_count, :views] @export_report_keys [ diff --git a/lib/groupher_server/cms/delegates/article_comment.ex b/lib/groupher_server/cms/delegates/article_comment.ex index 9050ba9de..8fbf44db8 100644 --- a/lib/groupher_server/cms/delegates/article_comment.ex +++ b/lib/groupher_server/cms/delegates/article_comment.ex @@ -96,19 +96,14 @@ defmodule GroupherServer.CMS.Delegate.ArticleComment do # make sure the article exsit # author is passed by middleware, it's exsit for sure {:ok, article} <- ORM.find(info.model, article_id, preload: [author: :user]) do - IO.inspect(info, label: "bb") - Multi.new() |> Multi.run(:create_article_comment, fn _, _ -> - IO.inspect("11") do_create_comment(content, info.foreign_key, article, user) end) |> Multi.run(:update_article_comments_count, fn _, %{create_article_comment: comment} -> - IO.inspect("22") - update_article_comments_count(comment, :inc) |> IO.inspect(label: "22 after") + update_article_comments_count(comment, :inc) end) |> Multi.run(:add_participator, fn _, _ -> - IO.inspect("33") add_participator_to_article(article, user) end) |> Repo.transaction() diff --git a/lib/groupher_server/cms/delegates/article_curd.ex b/lib/groupher_server/cms/delegates/article_curd.ex index ceea9d7ca..3e6489782 100644 --- a/lib/groupher_server/cms/delegates/article_curd.ex +++ b/lib/groupher_server/cms/delegates/article_curd.ex @@ -7,7 +7,9 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do import GroupherServer.CMS.Helper.Matcher2 import GroupherServer.CMS.Helper.Matcher, only: [match_action: 2] - import Helper.Utils, only: [done: 1, pick_by: 2, integerfy: 1, strip_struct: 1] + import Helper.Utils, + only: [done: 1, pick_by: 2, integerfy: 1, strip_struct: 1, module_to_thread: 1] + import GroupherServer.CMS.Delegate.Helper, only: [mark_viewer_emotion_states: 2] import Helper.ErrorCode import ShortMaps @@ -301,19 +303,19 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do defp domain_filter_query(queryable, _filter), do: queryable defp add_pin_contents_ifneed(contents, querable, %{community: community} = filter) do - with {:ok, _} <- should_add_pin?(filter), - {:ok, info} <- match(querable), - true <- 1 == Map.get(contents, :page_number) do - {:ok, pinned_articles} = - PinnedArticle - |> join(:inner, [p], c in assoc(p, :community)) - # |> join(:inner, [p], article in assoc(p, ^filter.thread)) - |> join(:inner, [p], article in assoc(p, ^info.thread)) - |> where([p, c, article], c.raw == ^community) - |> select([p, c, article], article) - # 10 pined contents per community/thread, at most - |> ORM.find_all(%{page: 1, size: 10}) + thread = module_to_thread(querable) + with {:ok, _} <- should_add_pin?(filter), + true <- 1 == Map.get(contents, :page_number), + {:ok, pinned_articles} <- + PinnedArticle + |> join(:inner, [p], c in assoc(p, :community)) + # |> join(:inner, [p], article in assoc(p, ^filter.thread)) + |> join(:inner, [p], article in assoc(p, ^thread)) + |> where([p, c, article], c.raw == ^community) + |> select([p, c, article], article) + # 10 pined contents per community/thread, at most + |> ORM.find_all(%{page: 1, size: 10}) do concat_contents(pinned_articles, contents) else _error -> contents diff --git a/lib/groupher_server/cms/helper/matcher2.ex b/lib/groupher_server/cms/helper/matcher2.ex index badd57048..d9a9805c4 100644 --- a/lib/groupher_server/cms/helper/matcher2.ex +++ b/lib/groupher_server/cms/helper/matcher2.ex @@ -1,40 +1,109 @@ -defmodule GroupherServer.CMS.Helper.Matcher2 do +defmodule GroupherServer.CMS.Helper.Matcher2.Macros do @moduledoc """ - this module defined the matches and handy guard ... + generate match functions """ - import Ecto.Query, warn: false + alias GroupherServer.CMS + alias CMS.{ArticleComment, Community, Embeds} - alias GroupherServer.{Accounts, CMS} + @article_threads Community.article_threads() - alias Accounts.User - alias CMS.{ArticleComment, Post, Job, Repo} + @doc """ + match basic threads - def match(:article_comment) do - {:ok, - %{ - model: ArticleComment, - foreign_key: :article_comment_id, - preload: :article_comment, - default_meta: CMS.Embeds.ArticleCommentMeta.default_meta() - }} + {:ok, info} <- match(:post) + info: + %{ + model: Post, + thread: :post, + foreign_key: post_id, + preload: :post + default_meta: ... + } + """ + defmacro thread_matches() do + @article_threads + |> Enum.map(fn thread -> + quote do + def match(unquote(thread)) do + thread_module = unquote(thread) |> to_string |> Recase.to_pascal() + + {:ok, + %{ + model: Module.concat(CMS, thread_module), + thread: unquote(thread), + foreign_key: unquote(:"#{thread}_id"), + preload: unquote(thread), + default_meta: Embeds.ArticleMeta.default_meta() + }} + end + end + end) end - def match(:comment_article, %ArticleComment{post_id: post_id}) when not is_nil(post_id) do - {:ok, %{model: Post, id: post_id, foreign_key: :post_id}} - end + @doc """ + match basic thread query - def match(:comment_article, %ArticleComment{job_id: job_id}) when not is_nil(job_id) do - {:ok, %{model: Job, id: job_id, foreign_key: :job_id}} + {:ok, info} <- match(:post, :query, id) + info: + %{dynamic([c], field(c, :post_id) == ^id)} + """ + defmacro thread_query_matches() do + @article_threads + |> Enum.map(fn thread -> + quote do + def match(unquote(thread), :query, id) do + {:ok, dynamic([c], field(c, unquote(:"#{thread}_id")) == ^id)} + end + end + end) end - def match(:comment_article, %ArticleComment{repo_id: repo_id}) when not is_nil(repo_id) do - {:ok, %{model: Repo, id: repo_id, foreign_key: :repo_id}} - end + @doc """ + mapping basic article_comment -> thread - def match(:comment_article, %ArticleComment{}) do - {:error, "match error, not supported"} + {:ok, info} <- match(:comment_article, %ArticleComment{post_id: id} = comment) + info: + %{ + id: id, + model: CMS.Post, + foreign_key: :post_id, + } + """ + defmacro comment_article_matches() do + @article_threads + |> Enum.map(fn thread -> + # def match(:comment_article, %ArticleComment{post_id: id}) + quote do + # see https://elixirforum.com/t/generate-map-pattern-matching-functions/21928/2 + def match(:comment_article, %ArticleComment{unquote(:"#{thread}_id") => id}) + when not is_nil(id) do + thread_module = unquote(thread) |> to_string |> Recase.to_pascal() + + {:ok, + %{ + id: id, + model: Module.concat(CMS, thread_module), + foreign_key: unquote(:"#{thread}_id") + }} + end + end + end) end +end + +defmodule GroupherServer.CMS.Helper.Matcher2 do + @moduledoc """ + this module defined the matches and handy guard ... + """ + + import Ecto.Query, warn: false + import GroupherServer.CMS.Helper.Matcher2.Macros + + alias GroupherServer.{Accounts, CMS} + + alias Accounts.User + alias CMS.{ArticleComment} def match(:account) do {:ok, @@ -46,49 +115,17 @@ defmodule GroupherServer.CMS.Helper.Matcher2 do }} end - # used for paged pin articles - def match(Post) do - {:ok, %{thread: :post}} - end - - def match(:post) do - {:ok, - %{ - model: Post, - foreign_key: :post_id, - preload: :post, - default_meta: CMS.Embeds.ArticleMeta.default_meta() - }} - end - - def match(Job) do - {:ok, %{thread: :job}} - end - - def match(:job) do - {:ok, - %{ - model: Job, - foreign_key: :job_id, - preload: :job, - default_meta: CMS.Embeds.ArticleMeta.default_meta() - }} - end - - def match(Repo) do - {:ok, %{thread: :repo}} - end - - def match(:repo) do + def match(:article_comment) do {:ok, %{ - model: Repo, - foreign_key: :repo_id, - preload: :repo, - default_meta: CMS.Embeds.ArticleMeta.default_meta() + model: ArticleComment, + foreign_key: :article_comment_id, + preload: :article_comment, + default_meta: CMS.Embeds.ArticleCommentMeta.default_meta() }} end - def match(:post, :query, id), do: {:ok, dynamic([c], c.post_id == ^id)} - def match(:job, :query, id), do: {:ok, dynamic([c], c.job_id == ^id)} + thread_matches() + thread_query_matches() + comment_article_matches() end diff --git a/lib/helper/utils/utils.ex b/lib/helper/utils/utils.ex index 1ea595ff9..9216bf786 100644 --- a/lib/helper/utils/utils.ex +++ b/lib/helper/utils/utils.ex @@ -175,6 +175,16 @@ defmodule Helper.Utils do def strip_struct(map) when is_map(map), do: map + @doc "turn GroupherServer.CMS.Post -> :post" + def module_to_thread(module) do + module + |> to_string + |> String.split(".") + |> List.last() + |> String.downcase() + |> String.to_atom() + end + @doc "html uniq id generator for editorjs" @spec uid(:html, map) :: String.t() def uid(:html, %{"id" => id}) when g_none_empty_str(id), do: id diff --git a/priv/mock/tag_patch_seeds.exs b/priv/mock/tag_patch_seeds.exs index a162171d8..02a4f80d3 100644 --- a/priv/mock/tag_patch_seeds.exs +++ b/priv/mock/tag_patch_seeds.exs @@ -32,8 +32,6 @@ Enum.each(patch_communities, fn raw -> case community.raw not in ["cps-support"] do true -> # create_tags(community, :repo) - IO.inspect(community.raw, label: "patching community") - Enum.each(patch_tags, fn attr -> {:ok, _} = CMS.create_tag(community, :repo, attr, bot) end) diff --git a/test/groupher_server/cms/abuse_reports/post_report_test.exs b/test/groupher_server/cms/abuse_reports/post_report_test.exs index 743fd1b0d..fcd638368 100644 --- a/test/groupher_server/cms/abuse_reports/post_report_test.exs +++ b/test/groupher_server/cms/abuse_reports/post_report_test.exs @@ -79,6 +79,7 @@ defmodule GroupherServer.Test.CMS.AbuseReports.PostReport do assert user.id not in post.meta.reported_user_ids end + @tag :wip2 test "can undo a report with other user report it too", ~m(community user user2 post_attrs)a do {:ok, post} = CMS.create_content(community, :post, post_attrs, user) diff --git a/test/groupher_server_web/query/cms/flags/posts_flags_test.exs b/test/groupher_server_web/query/cms/flags/posts_flags_test.exs index 9d71db79f..90671a222 100644 --- a/test/groupher_server_web/query/cms/flags/posts_flags_test.exs +++ b/test/groupher_server_web/query/cms/flags/posts_flags_test.exs @@ -89,6 +89,7 @@ defmodule GroupherServer.Test.Query.Flags.PostsFlags do assert results["entries"] |> Enum.any?(&(&1["id"] !== random_id)) end + @tag :wip2 test "if have trashed posts, the trashed posts should not appears in result", ~m(guest_conn community)a do variables = %{filter: %{community: community.raw}}