Send Notifications when participation approval
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
@@ -504,14 +504,25 @@ defmodule Mobilizon.Federation.ActivityPub do
|
||||
Audience.calculate_to_and_cc_from_mentions(participant),
|
||||
{:ok, activity} <- create_activity(Map.merge(join_data, audience), local),
|
||||
:ok <- maybe_federate(activity) do
|
||||
if event.local && Mobilizon.Events.get_default_participant_role(event) === :participant &&
|
||||
role == :participant do
|
||||
accept(
|
||||
:join,
|
||||
participant,
|
||||
true,
|
||||
%{"actor" => event.organizer_actor.url}
|
||||
)
|
||||
if event.local do
|
||||
cond do
|
||||
Mobilizon.Events.get_default_participant_role(event) === :participant &&
|
||||
role == :participant ->
|
||||
accept(
|
||||
:join,
|
||||
participant,
|
||||
true,
|
||||
%{"actor" => event.organizer_actor.url}
|
||||
)
|
||||
|
||||
Mobilizon.Events.get_default_participant_role(event) === :not_approved &&
|
||||
role == :not_approved ->
|
||||
Scheduler.pending_participation_notification(event)
|
||||
{:ok, activity, participant}
|
||||
|
||||
true ->
|
||||
{:ok, activity, participant}
|
||||
end
|
||||
else
|
||||
{:ok, activity, participant}
|
||||
end
|
||||
|
||||
@@ -117,6 +117,17 @@ defmodule Mobilizon.GraphQL.Schema.UserType do
|
||||
field(:notification_before_event, :boolean,
|
||||
description: "Whether this user will receive a notification right before event"
|
||||
)
|
||||
|
||||
field(:notification_pending_participation, :notification_pending_participation_enum,
|
||||
description: "When does the user receives a notification about new pending participations"
|
||||
)
|
||||
end
|
||||
|
||||
enum :notification_pending_participation_enum do
|
||||
value(:none, as: :none)
|
||||
value(:direct, as: :direct)
|
||||
value(:one_hour, as: :one_hour)
|
||||
value(:one_day, as: :one_day)
|
||||
end
|
||||
|
||||
object :user_queries do
|
||||
@@ -231,6 +242,7 @@ defmodule Mobilizon.GraphQL.Schema.UserType do
|
||||
arg(:notification_on_day, :boolean)
|
||||
arg(:notification_each_week, :boolean)
|
||||
arg(:notification_before_event, :boolean)
|
||||
arg(:notification_pending_participation, :notification_pending_participation_enum)
|
||||
resolve(&User.set_user_setting/3)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -5,7 +5,7 @@ defmodule Mobilizon.Users.Setting do
|
||||
|
||||
use Ecto.Schema
|
||||
import Ecto.Changeset
|
||||
alias Mobilizon.Users.User
|
||||
alias Mobilizon.Users.{NotificationPendingNotificationDelay, User}
|
||||
|
||||
@required_attrs [:user_id]
|
||||
|
||||
@@ -13,7 +13,8 @@ defmodule Mobilizon.Users.Setting do
|
||||
:timezone,
|
||||
:notification_on_day,
|
||||
:notification_each_week,
|
||||
:notification_before_event
|
||||
:notification_before_event,
|
||||
:notification_pending_participation
|
||||
]
|
||||
|
||||
@attrs @required_attrs ++ @optional_attrs
|
||||
@@ -24,6 +25,11 @@ defmodule Mobilizon.Users.Setting do
|
||||
field(:notification_on_day, :boolean)
|
||||
field(:notification_each_week, :boolean)
|
||||
field(:notification_before_event, :boolean)
|
||||
|
||||
field(:notification_pending_participation, NotificationPendingNotificationDelay,
|
||||
default: :none
|
||||
)
|
||||
|
||||
belongs_to(:user, User, primary_key: true, type: :id, foreign_key: :id, define_field: false)
|
||||
|
||||
timestamps()
|
||||
|
||||
@@ -22,6 +22,8 @@ defmodule Mobilizon.Users do
|
||||
|
||||
defenum(UserRole, :user_role, [:administrator, :moderator, :user])
|
||||
|
||||
defenum(NotificationPendingNotificationDelay, none: 0, direct: 1, one_hour: 5, one_day: 10)
|
||||
|
||||
@doc """
|
||||
Registers an user.
|
||||
"""
|
||||
|
||||
@@ -3,10 +3,10 @@ defmodule Mobilizon.Service.Notifications.Scheduler do
|
||||
Allows to insert jobs
|
||||
"""
|
||||
|
||||
alias Mobilizon.{Actors, Users}
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.Events.{Event, Participant}
|
||||
alias Mobilizon.Service.Workers.Notification
|
||||
alias Mobilizon.Users
|
||||
alias Mobilizon.Users.{Setting, User}
|
||||
require Logger
|
||||
|
||||
@@ -129,6 +129,61 @@ defmodule Mobilizon.Service.Notifications.Scheduler do
|
||||
|
||||
def weekly_notification(_), do: {:ok, nil}
|
||||
|
||||
def pending_participation_notification(%Event{
|
||||
id: event_id,
|
||||
organizer_actor_id: organizer_actor_id,
|
||||
local: true
|
||||
}) do
|
||||
with %Actor{user_id: user_id} when not is_nil(user_id) <-
|
||||
Actors.get_actor(organizer_actor_id),
|
||||
%User{
|
||||
settings: %Setting{
|
||||
notification_pending_participation: notification_pending_participation,
|
||||
timezone: timezone
|
||||
}
|
||||
} <- Users.get_user_with_settings!(user_id) do
|
||||
send_at =
|
||||
case notification_pending_participation do
|
||||
:none ->
|
||||
nil
|
||||
|
||||
:direct ->
|
||||
:direct
|
||||
|
||||
:one_day ->
|
||||
calculate_next_day_notification(Date.utc_today(), timezone)
|
||||
|
||||
:one_hour ->
|
||||
DateTime.utc_now()
|
||||
|> DateTime.shift_zone!(timezone)
|
||||
|> (&%{&1 | minute: 0, second: 0, microsecond: {0, 0}}).()
|
||||
end
|
||||
|
||||
params = %{
|
||||
user_id: user_id,
|
||||
event_id: event_id
|
||||
}
|
||||
|
||||
cond do
|
||||
# Sending directly
|
||||
send_at == :direct ->
|
||||
Notification.enqueue(:pending_participation_notification, params)
|
||||
|
||||
# Not sending
|
||||
is_nil(send_at) ->
|
||||
{:ok, nil}
|
||||
|
||||
# Sending to calculated time
|
||||
true ->
|
||||
Notification.enqueue(:pending_participation_notification, params, scheduled_at: send_at)
|
||||
end
|
||||
else
|
||||
_ -> {:ok, nil}
|
||||
end
|
||||
end
|
||||
|
||||
def pending_participation_notification(_), do: {:ok, nil}
|
||||
|
||||
defp shift_zone(datetime, timezone) do
|
||||
case DateTime.shift_zone(datetime, timezone) do
|
||||
{:ok, shift_datetime} -> shift_datetime
|
||||
@@ -144,4 +199,15 @@ defmodule Mobilizon.Service.Notifications.Scheduler do
|
||||
do: date,
|
||||
else: calculate_first_day_of_week(Date.add(date, -1), locale)
|
||||
end
|
||||
|
||||
defp calculate_next_day_notification(%Date{} = day, timezone) do
|
||||
{:ok, send_at} = NaiveDateTime.new(day, ~T[18:00:00])
|
||||
{:ok, send_at} = DateTime.from_naive(send_at, timezone)
|
||||
|
||||
if send_at < DateTime.utc_now() do
|
||||
calculate_first_day_of_week(Date.add(day, 1), timezone)
|
||||
else
|
||||
send_at
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -80,6 +80,28 @@ defmodule Mobilizon.Service.Workers.Notification do
|
||||
end
|
||||
end
|
||||
|
||||
def perform(
|
||||
%{
|
||||
"op" => "pending_participation_notification",
|
||||
"user_id" => user_id,
|
||||
"event_id" => event_id
|
||||
},
|
||||
_job
|
||||
) do
|
||||
with %User{} = user <- Users.get_user(user_id),
|
||||
{:ok, %Event{} = event} <- Events.get_event(event_id),
|
||||
%Page{total: total} when total > 0 <-
|
||||
Events.list_participants_for_event(event_id, [:not_approved]) do
|
||||
user
|
||||
|> Notification.pending_participation_notification(event, total)
|
||||
|> Mailer.deliver_later()
|
||||
else
|
||||
err ->
|
||||
require Logger
|
||||
Logger.error(inspect(err))
|
||||
end
|
||||
end
|
||||
|
||||
defp shift_zone(datetime, timezone) do
|
||||
case DateTime.shift_zone(datetime, timezone) do
|
||||
{:ok, shift_datetime} -> shift_datetime
|
||||
|
||||
@@ -7,7 +7,7 @@ defmodule Mobilizon.Web.Email.Notification do
|
||||
import Bamboo.Phoenix
|
||||
import Mobilizon.Web.Gettext
|
||||
|
||||
alias Mobilizon.Events.Participant
|
||||
alias Mobilizon.Events.{Event, Participant}
|
||||
alias Mobilizon.Users.{Setting, User}
|
||||
alias Mobilizon.Web.{Email, Gettext}
|
||||
|
||||
@@ -80,4 +80,28 @@ defmodule Mobilizon.Web.Email.Notification do
|
||||
|> assign(:subject, subject)
|
||||
|> render(:notification_each_week)
|
||||
end
|
||||
|
||||
def pending_participation_notification(
|
||||
%User{locale: locale, email: email},
|
||||
%Event{} = event,
|
||||
total
|
||||
) do
|
||||
Gettext.put_locale(locale)
|
||||
|
||||
subject =
|
||||
ngettext(
|
||||
"One participation request for event %{title} to process",
|
||||
"%{number_participation_requests} participation requests for event %{title} to process",
|
||||
total,
|
||||
number_participation_requests: total,
|
||||
title: event.title
|
||||
)
|
||||
|
||||
Email.base_email(to: email, subject: subject)
|
||||
|> assign(:locale, locale)
|
||||
|> assign(:event, event)
|
||||
|> assign(:total, total)
|
||||
|> assign(:subject, subject)
|
||||
|> render(:pending_participation_notification)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
<!-- HERO -->
|
||||
<tr>
|
||||
<td bgcolor="#424056" align="center" style="padding: 0px 10px 0px 10px;">
|
||||
<!--[if (gte mso 9)|(IE)]>
|
||||
<table align="center" border="0" cellspacing="0" cellpadding="0" width="600">
|
||||
<tr>
|
||||
<td align="center" valign="top" width="600">
|
||||
<![endif]-->
|
||||
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="max-width: 600px;" >
|
||||
<tr>
|
||||
<td bgcolor="#ffffff" align="center" valign="top" style="padding: 40px 20px 20px 20px; border-radius: 4px 4px 0px 0px; color: #111111; font-family: 'Lato', Helvetica, Arial, sans-serif; font-size: 48px; font-weight: 400; line-height: 48px;">
|
||||
<h1 style="font-size: 48px; font-weight: 400; margin: 0;">
|
||||
<%= gettext "Pending participations to process" %>
|
||||
</h1>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<!--[if (gte mso 9)|(IE)]>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<![endif]-->
|
||||
</td>
|
||||
</tr>
|
||||
<!-- COPY BLOCK -->
|
||||
<tr>
|
||||
<td bgcolor="#f4f4f4" align="center" style="padding: 0px 10px 0px 10px;">
|
||||
<!--[if (gte mso 9)|(IE)]>
|
||||
<table align="center" border="0" cellspacing="0" cellpadding="0" width="600">
|
||||
<tr>
|
||||
<td align="center" valign="top" width="600">
|
||||
<![endif]-->
|
||||
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="max-width: 600px;" >
|
||||
<!-- COPY -->
|
||||
<tr>
|
||||
<td bgcolor="#ffffff" align="left" style="padding: 20px 30px 0px 30px; color: #666666; font-family: 'Lato', Helvetica, Arial, sans-serif; font-size: 18px; font-weight: 400; line-height: 25px;" >
|
||||
<p style="margin: 0;">
|
||||
<%= ngettext "You have one pending participation to process:", "You have %{number_participation_requests} participation requests to process:", @total, number_participation_requests: @total %>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#ffffff" align="left" style="padding: 20px 30px 0px 30px; color: #666666; font-family: 'Lato', Helvetica, Arial, sans-serif; font-size: 18px; font-weight: 400; line-height: 25px;" >
|
||||
<table width="100%" border="0" cellspacing="0" cellpadding="0">
|
||||
<tr>
|
||||
<td bgcolor="#ffffff" align="center" style="padding: 20px 30px 60px 30px;">
|
||||
<table border="0" cellspacing="0" cellpadding="0">
|
||||
<tr>
|
||||
<td align="center" style="border-radius: 3px;" bgcolor="#424056">
|
||||
<a href="<%= page_url(Mobilizon.Web.Endpoint, :event, @event.uuid) <> "/participations" %>" target="_blank" style="font-size: 20px; font-family: Helvetica, Arial, sans-serif; color: #ffffff; text-decoration: none; color: #ffffff; text-decoration: none; padding: 15px 25px; border-radius: 2px; border: 1px solid #424056; display: inline-block;">
|
||||
<%= gettext "Manage pending participation requests" %>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#ffffff" align="left" style="padding: 20px 30px 40px 30px; color: #777777; font-family: 'Lato', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: 400; line-height: 20px;" >
|
||||
<p style="margin: 0">
|
||||
<%= gettext "You receive this email because you chose to get notifications for pending participations to your events. You may disable or change the configuration for these notification in your Mobilizon user settings." %>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<!--[if (gte mso 9)|(IE)]>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<![endif]-->
|
||||
</td>
|
||||
</tr>
|
||||
@@ -0,0 +1,8 @@
|
||||
<%= gettext "Pending participations to process" %>
|
||||
==
|
||||
|
||||
<%= ngettext "You have one pending participation to process:", "You have %{number_participation_requests} participation requests to process:", @total, number_participation_requests: @total %>
|
||||
|
||||
<%= gettext "Manage pending participation requests" %> <%= page_url(Mobilizon.Web.Endpoint, :event, @event.uuid) <> "/participations" %>
|
||||
|
||||
<%= gettext "You receive this email because you chose to get notifications for pending participations to your events. You may disable or change the configuration for these notification in your Mobilizon user settings." %>
|
||||
Reference in New Issue
Block a user