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

Commit 416d2ed

Browse files
authored
refactor(post-meta): isEdited state for posts (#306)
* refactor(article): add basic default meta map to post * refactor(post-meta): basic isEdited logic * refactor(post-meta): basic frontend(GQL) workflow * refactor(post-meta): fix update info not sync && warnings * fix(post-meta): exsiting post has no meta
1 parent a967880 commit 416d2ed

File tree

14 files changed

+236
-29
lines changed

14 files changed

+236
-29
lines changed

lib/groupher_server/cms/delegates/article_curd.ex

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do
7474
|> Multi.run(:set_community, fn _, %{create_content: content} ->
7575
ArticleOperation.set_community(community, thread, content.id)
7676
end)
77+
|> Multi.run(:set_meta, fn _, %{create_content: content} ->
78+
ArticleOperation.set_meta(thread, content.id)
79+
end)
7780
|> Multi.run(:set_topic, fn _, %{create_content: content} ->
7881
exec_set_topic(thread, content.id, attrs)
7982
end)
@@ -127,8 +130,12 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do
127130
|> Multi.run(:update_content, fn _, _ ->
128131
ORM.update(content, args)
129132
end)
133+
|> Multi.run(:update_meta, fn _, %{update_content: update_content} ->
134+
ArticleOperation.update_meta(update_content, :is_edited)
135+
end)
130136
|> Multi.run(:update_tag, fn _, _ ->
131-
exec_update_tags(content, args.tags)
137+
# TODO: move it to ArticleOperation moudel
138+
exec_update_tags(content, args)
132139
end)
133140
|> Repo.transaction()
134141
|> update_content_result()
@@ -407,6 +414,10 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do
407414
{:error, [message: "set community", code: ecode(:create_fails)]}
408415
end
409416

417+
defp create_content_result({:error, :set_meta, _result, _steps}) do
418+
{:error, [message: "set meta info", code: ecode(:create_fails)]}
419+
end
420+
410421
defp create_content_result({:error, :set_community_flag, _result, _steps}) do
411422
{:error, [message: "set community flag", code: ecode(:create_fails)]}
412423
end
@@ -423,10 +434,7 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do
423434
{:error, [message: "log action", code: ecode(:create_fails)]}
424435
end
425436

426-
# except Job, other content will just pass, should use set_tag function instead
427-
# defp exec_update_tags(_, _tags_ids), do: {:ok, :pass}
428-
429-
defp update_content_result({:ok, %{update_content: result}}), do: {:ok, result}
437+
defp update_content_result({:ok, %{update_meta: result}}), do: {:ok, result}
430438
defp update_content_result({:error, :update_content, result, _steps}), do: {:error, result}
431439
defp update_content_result({:error, :update_tag, result, _steps}), do: {:error, result}
432440

@@ -479,9 +487,12 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do
479487
{:ok, :pass}
480488
end
481489

482-
defp exec_update_tags(_content, tags_ids) when length(tags_ids) == 0, do: {:ok, :pass}
490+
# except Job, other content will just pass, should use set_tag function instead
491+
# defp exec_update_tags(_, _tags_ids), do: {:ok, :pass}
483492

484-
defp exec_update_tags(content, tags_ids) do
493+
defp exec_update_tags(_content, %{tags: tags_ids}) when tags_ids == [], do: {:ok, :pass}
494+
495+
defp exec_update_tags(content, %{tags: tags_ids}) do
485496
with {:ok, content} <- ORM.find(content.__struct__, content.id, preload: :tags) do
486497
tags =
487498
Enum.reduce(tags_ids, [], fn t, acc ->
@@ -502,4 +513,6 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do
502513
|> Repo.update()
503514
end
504515
end
516+
517+
defp exec_update_tags(_content, _), do: {:ok, :pass}
505518
end

lib/groupher_server/cms/delegates/article_operation.ex

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,22 @@ defmodule GroupherServer.CMS.Delegate.ArticleOperation do
2929
alias GroupherServer.CMS.Repo, as: CMSRepo
3030
alias GroupherServer.Repo
3131

32+
@default_article_meta %{
33+
isEdited: false,
34+
forbidComment: false,
35+
isReported: false
36+
# linkedPostsCount: 0,
37+
# linkedJobsCount: 0,
38+
# linkedWorksCount: 0,
39+
# reaction: %{
40+
# rocketCount: 0,
41+
# heartCount: 0,
42+
# }
43+
}
44+
45+
@doc "for test usage"
46+
def default_article_meta(), do: @default_article_meta
47+
3248
def pin_content(%Post{id: post_id}, %Community{id: community_id}, topic) do
3349
with {:ok, %{id: topic_id}} <- ORM.find_by(Topic, %{raw: topic}),
3450
{:ok, pined} <-
@@ -277,6 +293,24 @@ defmodule GroupherServer.CMS.Delegate.ArticleOperation do
277293

278294
def set_topic(_topic, _thread, _content_id), do: {:ok, :pass}
279295

296+
@doc "set meta info"
297+
def set_meta(:post, content_id) do
298+
ORM.update_by(Post, [id: content_id], %{meta: @default_article_meta})
299+
end
300+
301+
def set_meta(_, _), do: {:ok, :pass}
302+
303+
@doc "update isEdited meta label if needed"
304+
def update_meta(%Post{meta: %{"isEdited" => false} = meta} = content, :is_edited) do
305+
ORM.update(content, %{meta: Map.merge(meta, %{"isEdited" => true})})
306+
end
307+
308+
def update_meta(%Post{meta: nil} = content, :is_edited) do
309+
ORM.update(content, %{meta: Map.merge(@default_article_meta, %{"isEdited" => true})})
310+
end
311+
312+
def update_meta(content, _), do: {:ok, content}
313+
280314
# make sure the reuest tag is in the current community thread
281315
# example: you can't set a other thread tag to this thread's article
282316

lib/groupher_server/cms/post.ex

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ defmodule GroupherServer.CMS.Post do
2323

2424
@timestamps_opts [type: :utc_datetime_usec]
2525
@required_fields ~w(title body digest length)a
26-
@optional_fields ~w(origial_community_id link_addr copy_right link_addr link_icon)a
26+
@optional_fields ~w(origial_community_id link_addr copy_right link_addr link_icon meta)a
2727

2828
@type t :: %Post{}
2929
schema "cms_posts" do
@@ -36,6 +36,8 @@ defmodule GroupherServer.CMS.Post do
3636
field(:length, :integer)
3737
field(:views, :integer, default: 0)
3838

39+
field(:meta, :map)
40+
3941
has_many(:community_flags, {"posts_communities_flags", PostCommunityFlag})
4042

4143
# NOTE: this one is tricky, pin is dynamic changed when return by func: add_pin_contents_ifneed

lib/groupher_server_web/resolvers/cms_resolver.ex

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ defmodule GroupherServerWeb.Resolvers.CMS do
1111
alias CMS.{Post, Video, Repo, Job, Community, Category, Tag, Thread}
1212

1313
alias Helper.ORM
14+
alias Helper.Utils
15+
16+
@default_article_meta CMS.Delegate.ArticleOperation.default_article_meta()
1417

1518
# #######################
1619
# community ..
@@ -102,12 +105,8 @@ defmodule GroupherServerWeb.Resolvers.CMS do
102105
CMS.create_content(%Community{id: community_id}, thread, args, user)
103106
end
104107

105-
def update_content(_root, %{passport_source: content, tags: _tags} = args, _info) do
106-
CMS.update_content(content, args)
107-
end
108-
109108
def update_content(_root, %{passport_source: content} = args, _info) do
110-
ORM.update(content, args)
109+
CMS.update_content(content, args)
111110
end
112111

113112
def delete_content(_root, %{passport_source: content}, _info), do: ORM.delete(content)
@@ -445,4 +444,21 @@ defmodule GroupherServerWeb.Resolvers.CMS do
445444
def tags_count(root, _, _) do
446445
CMS.count(%Community{id: root.id}, :tags)
447446
end
447+
448+
@doc """
449+
covert normal map to absinthe fmt
450+
e.g:
451+
%{"exampleKey" => false } -> %{example_key: false }
452+
"""
453+
def get_article_meta(root, _, _) do
454+
# if meta is nil , means exsit article or test env (like: db_insert)
455+
meta = if is_nil(root.meta), do: @default_article_meta, else: root.meta
456+
457+
fmt_meta =
458+
meta
459+
|> Utils.snake_map_key()
460+
|> Utils.keys_to_atoms()
461+
462+
{:ok, fmt_meta}
463+
end
448464
end

lib/groupher_server_web/schema/cms/cms_types.ex

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,16 @@ defmodule GroupherServerWeb.Schema.CMS.Types do
3939
field(:communities, list_of(:community), resolve: dataloader(CMS, :communities))
4040
# field(:topic)
4141

42+
# article meta info
43+
field(:meta, :article_meta) do
44+
# NOTE: absinthe has issue with :map resolving, do it mannulay
45+
resolve(&R.CMS.get_article_meta/3)
46+
end
47+
48+
# field :meta, :article_meta do
49+
# resolve(&R.CMS.get_meta/3)
50+
# end
51+
4252
field :comments, list_of(:comment) do
4353
arg(:filter, :members_filter)
4454

@@ -448,4 +458,19 @@ defmodule GroupherServerWeb.Schema.CMS.Types do
448458
field(:entries, list_of(:thread))
449459
pagination_fields()
450460
end
461+
462+
@desc "article meta info"
463+
object :article_meta do
464+
field(:is_edited, :boolean)
465+
field(:forbid_comment, :boolean)
466+
# field(:isReported, :boolean)
467+
# field(:linked_posts_count, :integer)
468+
# field(:linked_jobs_count, :integer)
469+
# field(:linked_works_count, :integer)
470+
471+
# reaction: %{
472+
# rocketCount: 0,
473+
# heartCount: 0,
474+
# }
475+
end
451476
end

lib/helper/utils.ex

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,12 +107,13 @@ defmodule Helper.Utils do
107107
def keys_to_atoms(string) when is_binary(string), do: string
108108

109109
def reduce_keys_to_atoms({key, val}) when is_map(val),
110-
do: {String.to_existing_atom(key), keys_to_atoms(val)}
110+
# do: {String.to_existing_atom(key), keys_to_atoms(val)}
111+
do: {String.to_atom(key), keys_to_atoms(val)}
111112

112113
def reduce_keys_to_atoms({key, val}) when is_list(val),
113-
do: {String.to_existing_atom(key), Enum.map(val, &keys_to_atoms(&1))}
114+
do: {String.to_atom(key), Enum.map(val, &keys_to_atoms(&1))}
114115

115-
def reduce_keys_to_atoms({key, val}), do: {String.to_existing_atom(key), val}
116+
def reduce_keys_to_atoms({key, val}), do: {String.to_atom(key), val}
116117

117118
@doc """
118119
see https://stackoverflow.com/a/61559842/4050784
@@ -168,6 +169,28 @@ defmodule Helper.Utils do
168169

169170
defp map_to_camel({k, v}), do: {Recase.to_camel(to_string(k)), v}
170171

172+
@spec snake_map_key(map) :: map
173+
def snake_map_key(map) do
174+
map_list =
175+
Enum.map(map, fn {k, v} ->
176+
v =
177+
cond do
178+
is_datetime?(v) ->
179+
DateTime.to_iso8601(v)
180+
181+
is_map(v) ->
182+
snake_map_key(safe_map(v))
183+
184+
true ->
185+
v
186+
end
187+
188+
{Recase.to_snake(to_string(k)), v}
189+
end)
190+
191+
Enum.into(map_list, %{})
192+
end
193+
171194
def is_datetime?(%DateTime{}), do: true
172195
def is_datetime?(_), do: false
173196

mix.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ defmodule GroupherServer.Mixfile do
6262
{:plug_cowboy, "~> 2.4.1"},
6363
{:plug, "~> 1.11.0"},
6464
# GraphQl tool
65-
{:absinthe, "~> 1.6.1"},
65+
{:absinthe, "~> 1.6.2"},
6666
# Plug support for Absinthe
6767
{:absinthe_plug, "~> 1.5.4"},
6868
# Password hashing lib
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
defmodule GroupherServer.Repo.Migrations.AddMetaToPosts do
2+
use Ecto.Migration
3+
4+
def change do
5+
alter table(:cms_posts) do
6+
add(:meta, :map)
7+
end
8+
end
9+
end
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
defmodule GroupherServer.Test.CMS.PostMeta do
2+
use GroupherServer.TestTools
3+
4+
alias Helper.ORM
5+
alias GroupherServer.CMS
6+
alias Helper.Utils
7+
8+
@default_article_meta CMS.Delegate.ArticleOperation.default_article_meta()
9+
10+
setup do
11+
{:ok, user} = db_insert(:user)
12+
# {:ok, post} = db_insert(:post)
13+
{:ok, community} = db_insert(:community)
14+
15+
post_attrs = mock_attrs(:post, %{community_id: community.id})
16+
17+
{:ok, ~m(user community post_attrs)a}
18+
end
19+
20+
describe "[cms post meta info]" do
21+
alias CMS.{Author, Post}
22+
23+
@tag :wip
24+
test "can get default meta info", ~m(user community post_attrs)a do
25+
assert {:error, _} = ORM.find_by(Author, user_id: user.id)
26+
27+
{:ok, post} = CMS.create_content(community, :post, post_attrs, user)
28+
{:ok, post} = ORM.find_by(Post, id: post.id)
29+
30+
assert @default_article_meta == Utils.keys_to_atoms(post.meta)
31+
end
32+
33+
@tag :wip
34+
test "isEdited flag should set to true after post updated", ~m(user community post_attrs)a do
35+
{:ok, post} = CMS.create_content(community, :post, post_attrs, user)
36+
{:ok, post} = ORM.find_by(Post, id: post.id)
37+
38+
assert post.meta["isEdited"] == false
39+
40+
{:ok, _} = CMS.update_content(post, %{"title" => "new title"})
41+
{:ok, post} = ORM.find_by(Post, id: post.id)
42+
43+
assert post.meta["isEdited"] == true
44+
end
45+
46+
# test "post with image should have imageCount in meta" do
47+
# end
48+
49+
# test "post with video should have imageCount in meta" do
50+
# end
51+
end
52+
end

test/groupher_server/cms/post_test.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ defmodule GroupherServer.Test.CMS.Post do
6666
assert author.user_id == user.id
6767
end
6868

69-
test "create post with an exsit community fails", ~m(user)a do
69+
test "create post with an non-exsit community fails", ~m(user)a do
7070
invalid_attrs = mock_attrs(:post, %{community_id: non_exsit_id()})
7171
ivalid_community = %Community{id: non_exsit_id()}
7272

0 commit comments

Comments
 (0)