Introduce the group activity section

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
Thomas Citharel
2021-02-24 19:06:48 +01:00
parent d0567f783d
commit 3fe64a4389
70 changed files with 3224 additions and 70 deletions

View File

@@ -0,0 +1,148 @@
defmodule Mobilizon.Activities do
@moduledoc """
The Activities context.
"""
import Ecto.Query, warn: false
import EctoEnum
alias Mobilizon.Activities.Activity
alias Mobilizon.Actors.Member
alias Mobilizon.Storage.{Page, Repo}
defenum(Priority,
very_low: 10,
low: 20,
medium: 30,
high: 40,
very_high: 50
)
@activity_types ["event", "post", "discussion", "resource", "group", "member"]
@event_activity_subjects ["event_created", "event_updated", "event_deleted", "comment_posted"]
@post_activity_subjects ["post_created", "post_updated", "post_deleted"]
@discussion_activity_subjects [
"discussion_created",
"discussion_replied",
"discussion_renamed",
"discussion_archived",
"discussion_deleted"
]
@resource_activity_subjects [
"resource_created",
"resource_renamed",
"resource_moved",
"resource_deleted"
]
@member_activity_subjects [
"member_request",
"member_invited",
"member_accepted_invitation",
"member_rejected_invitation",
"member_added",
"member_joined",
"member_approved",
"member_updated",
"member_removed",
"member_quit"
]
@settings_activity_subjects ["group_created", "group_updated"]
@subjects @event_activity_subjects ++
@post_activity_subjects ++
@discussion_activity_subjects ++
@resource_activity_subjects ++
@member_activity_subjects ++ @settings_activity_subjects
@object_type ["event", "actor", "post", "discussion", "resource", "member", "group"]
defenum(Type, @activity_types)
defenum(Subject, @subjects)
defenum(ObjectType, @object_type)
@doc """
Returns the list of activities.
## Examples
iex> list_activities()
[%Activity{}, ...]
"""
def list_activities do
Repo.all(Activity)
end
@spec list_activities_for_group(
integer() | String.t(),
Keyword.t(),
integer() | nil,
integer() | nil
) :: Page.t()
def list_activities_for_group(
group_id,
actor_asking_id,
filters \\ [],
page \\ nil,
limit \\ nil
) do
Activity
|> where([a], a.group_id == ^group_id)
|> join(:inner, [a], m in Member,
on: m.parent_id == a.group_id and m.actor_id == ^actor_asking_id
)
|> where([a, m], a.inserted_at >= m.member_since)
|> filter_object_type(Keyword.get(filters, :type))
|> order_by(desc: :inserted_at)
|> preload([:author, :group])
|> Page.build_page(page, limit)
end
@doc """
Gets a single activity.
Raises `Ecto.NoResultsError` if the Activity does not exist.
## Examples
iex> get_activity!(123)
%Activity{}
iex> get_activity!(456)
** (Ecto.NoResultsError)
"""
def get_activity!(id), do: Repo.get!(Activity, id)
@doc """
Creates a activity.
## Examples
iex> create_activity(%{field: value})
{:ok, %Activity{}}
iex> create_activity(%{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def create_activity(attrs \\ %{}) do
%Activity{}
|> Activity.changeset(attrs)
|> Repo.insert()
end
def object_types, do: @object_type
def subjects, do: @subjects
def activity_types, do: @activity_types
@spec filter_object_type(Query.t(), atom()) :: Query.t()
defp filter_object_type(query, :type) do
where(query, [q], q.type == ^:type)
end
defp filter_object_type(query, _) do
query
end
end

View File

@@ -0,0 +1,77 @@
defmodule Mobilizon.Activities.Activity do
@moduledoc """
Any activity for users
"""
use Ecto.Schema
import Ecto.Changeset
alias Mobilizon.Activities.{ObjectType, Priority, Subject, Type}
alias Mobilizon.Actors.Actor
@required_attrs [:type, :subject, :author_id, :group_id, :inserted_at]
@optional_attrs [
:priority,
:subject_params,
:message,
:message_params,
:object_type,
:object_id
]
@attrs @required_attrs ++ @optional_attrs
@type t :: %__MODULE__{
priority: Priority.t(),
type: Type.t(),
subject: Subject.t(),
subject_params: map(),
message: String.t(),
message_params: map(),
object_type: ObjectType.t(),
object_id: String.t(),
author: Actor.t(),
group: Actor.t()
}
schema "activities" do
field(:priority, Priority, default: :medium)
field(:type, Type)
field(:subject, Subject)
field(:subject_params, :map, default: %{})
field(:message, :string)
field(:message_params, :map, default: %{})
field(:object_type, ObjectType)
field(:object_id, :string)
field(:inserted_at, :utc_datetime)
belongs_to(:author, Actor)
belongs_to(:group, Actor)
end
@doc false
def changeset(activity, attrs) do
activity
|> cast(attrs, @attrs)
|> validate_required(@required_attrs)
|> stringify_params(:subject_params)
|> stringify_params(:message_params)
end
defp stringify_params(changeset, attr) do
stringified_params =
changeset
|> get_change(attr, %{})
|> Enum.map(fn {key, value} -> {key, stringify_struct(value)} end)
|> Map.new()
put_change(changeset, attr, stringified_params)
end
defp stringify_struct(%_{} = struct) do
association_fields = struct.__struct__.__schema__(:associations)
struct
|> Map.from_struct()
|> Map.drop(association_fields ++ [:__meta__])
end
defp stringify_struct(smth), do: smth
end