From 23fddaedf1334f895f97c3226150d8291cb78582 Mon Sep 17 00:00:00 2001 From: Thomas Citharel Date: Fri, 29 Oct 2021 10:42:37 +0200 Subject: [PATCH] [GraphQL] Expose events from followed/member group activity Signed-off-by: Thomas Citharel --- lib/graphql/resolvers/user.ex | 19 +++++++- lib/graphql/schema.ex | 2 +- lib/graphql/schema/followed_group_activity.ex | 20 +++++++++ lib/graphql/schema/user.ex | 16 +++++++ lib/mobilizon/followed_group_activity.ex | 43 +++++++++++++++++++ 5 files changed, 98 insertions(+), 2 deletions(-) create mode 100644 lib/graphql/schema/followed_group_activity.ex create mode 100644 lib/mobilizon/followed_group_activity.ex diff --git a/lib/graphql/resolvers/user.ex b/lib/graphql/resolvers/user.ex index f9eee0bac..0330cf18e 100644 --- a/lib/graphql/resolvers/user.ex +++ b/lib/graphql/resolvers/user.ex @@ -5,7 +5,7 @@ defmodule Mobilizon.GraphQL.Resolvers.User do import Mobilizon.Users.Guards - alias Mobilizon.{Actors, Admin, Config, Events, Users} + alias Mobilizon.{Actors, Admin, Config, Events, FollowedGroupActivity, Users} alias Mobilizon.Actors.Actor alias Mobilizon.Federation.ActivityPub.{Actions, Relay} alias Mobilizon.Service.Auth.Authenticator @@ -633,6 +633,23 @@ defmodule Mobilizon.GraphQL.Resolvers.User do }} end + def user_followed_group_events(%User{id: user_id}, %{page: page, limit: limit}, %{ + context: %{current_user: %User{id: logged_in_user_id}} + }) + when user_id == logged_in_user_id do + activities = FollowedGroupActivity.user_followed_group_events(user_id, page, limit) + + activities = %Page{ + activities + | elements: + Enum.map(activities.elements, fn [event, group, profile] -> + %{group: group, profile: profile, event: event} + end) + } + + {:ok, activities} + end + @spec update_user_login_information(User.t(), map()) :: {:ok, User.t()} | {:error, Ecto.Changeset.t()} defp update_user_login_information( diff --git a/lib/graphql/schema.ex b/lib/graphql/schema.ex index 5ce92d9ed..f8b143d05 100644 --- a/lib/graphql/schema.ex +++ b/lib/graphql/schema.ex @@ -49,6 +49,7 @@ defmodule Mobilizon.GraphQL.Schema do import_types(Schema.StatisticsType) import_types(Schema.Users.PushSubscription) import_types(Schema.Users.ActivitySetting) + import_types(Schema.FollowedGroupActivityType) @desc "A struct containing the id of the deleted object" object :deleted_object do @@ -157,7 +158,6 @@ defmodule Mobilizon.GraphQL.Schema do import_fields(:resource_queries) import_fields(:post_queries) import_fields(:statistics_queries) - # import_fields(:push_queries) end @desc """ diff --git a/lib/graphql/schema/followed_group_activity.ex b/lib/graphql/schema/followed_group_activity.ex new file mode 100644 index 000000000..7d45136ee --- /dev/null +++ b/lib/graphql/schema/followed_group_activity.ex @@ -0,0 +1,20 @@ +defmodule Mobilizon.GraphQL.Schema.FollowedGroupActivityType do + @moduledoc """ + Schema representation for a follow activity + """ + use Absinthe.Schema.Notation + + @desc "A paginated list of follow group events" + object :paginated_followed_group_events do + field(:elements, list_of(:followed_group_event), description: "A list of follow group events") + field(:total, :integer, description: "The total number of follow group events in the list") + end + + @desc "A follow group event" + object :followed_group_event do + field(:user, :user) + field(:profile, :person) + field(:group, :group) + field(:event, :event) + end +end diff --git a/lib/graphql/schema/user.ex b/lib/graphql/schema/user.ex index b4ccd6f0c..e954f05d6 100644 --- a/lib/graphql/schema/user.ex +++ b/lib/graphql/schema/user.ex @@ -104,6 +104,22 @@ defmodule Mobilizon.GraphQL.Schema.UserType do resolve(&User.user_drafted_events/3) end + field(:followed_group_events, :paginated_followed_group_events, + description: "The suggested events from the groups this user follows" + ) do + arg(:page, :integer, + default_value: 1, + description: "The page in the follow group events list" + ) + + arg(:limit, :integer, + default_value: 10, + description: "The limit of follow group events per page" + ) + + resolve(&User.user_followed_group_events/3) + end + field(:settings, :user_settings, description: "The list of settings for this user") do resolve(&User.user_settings/3) end diff --git a/lib/mobilizon/followed_group_activity.ex b/lib/mobilizon/followed_group_activity.ex new file mode 100644 index 000000000..0c8d5a6c6 --- /dev/null +++ b/lib/mobilizon/followed_group_activity.ex @@ -0,0 +1,43 @@ +defmodule Mobilizon.FollowedGroupActivity do + @moduledoc """ + Provide recent elements from groups that profiles follow + """ + + import Ecto.Query + alias Mobilizon.Actors.{Actor, Follower, Member} + alias Mobilizon.Events.{Event, Participant} + alias Mobilizon.Storage.Page + + def user_followed_group_events(user_id, page \\ nil, limit \\ nil) do + Event + |> distinct([e], e.id) + |> join(:left, [e], p in Participant, on: e.id == p.event_id) + |> join(:inner, [_e, p], pa in Actor, on: p.actor_id == pa.id) + |> join(:inner, [e], g in Actor, on: e.attributed_to_id == g.id) + |> join(:left, [_e, _p, _pa, g], f in Follower, on: g.id == f.target_actor_id) + |> join(:left, [_e, _p, _pa, g], m in Member, on: g.id == m.parent_id) + |> join(:inner, [_e, _p, pa, _g, f, m], a in Actor, + on: a.id == f.actor_id or a.id == m.actor_id + ) + |> where( + [e, p, pa, _g, f, m, a], + e.begins_on > ^DateTime.utc_now() and + (f.approved or m.role in ^[:member, :moderator, :administrator, :creator]) and + a.user_id == ^user_id and + pa.user_id != ^user_id + ) + |> preload([ + :organizer_actor, + :attributed_to, + :tags, + :physical_address, + :picture + ]) + |> select([e, g, _f, _m, a], [ + e, + g, + a + ]) + |> Page.build_page(page, limit) + end +end