Notifications on event update
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
9
lib/mobilizon/cldr.ex
Normal file
9
lib/mobilizon/cldr.ex
Normal file
@@ -0,0 +1,9 @@
|
||||
defmodule Mobilizon.Cldr do
|
||||
@moduledoc """
|
||||
Module to define supported locales
|
||||
"""
|
||||
|
||||
use Cldr,
|
||||
locales: ["cs", "de", "en", "es", "fr", "it", "ja", "nl", "pl", "pt", "ru"],
|
||||
providers: [Cldr.Number, Cldr.Calendar, Cldr.DateTime]
|
||||
end
|
||||
@@ -262,11 +262,19 @@ defmodule Mobilizon.Events do
|
||||
Updates an event.
|
||||
"""
|
||||
@spec update_event(Event.t(), map) :: {:ok, Event.t()} | {:error, Ecto.Changeset.t()}
|
||||
def update_event(%Event{} = event, attrs) do
|
||||
event
|
||||
|> Repo.preload(:tags)
|
||||
|> Event.update_changeset(attrs)
|
||||
|> Repo.update()
|
||||
def update_event(%Event{} = old_event, attrs) do
|
||||
with %Ecto.Changeset{changes: changes} = changeset <-
|
||||
old_event |> Repo.preload(:tags) |> Event.update_changeset(attrs) do
|
||||
with {:ok, %Event{} = new_event} <- Repo.update(changeset) do
|
||||
Mobilizon.Service.Events.Tool.calculate_event_diff_and_send_notifications(
|
||||
old_event,
|
||||
new_event,
|
||||
changes
|
||||
)
|
||||
|
||||
{:ok, new_event}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
@@ -1301,6 +1309,15 @@ defmodule Mobilizon.Events do
|
||||
)
|
||||
end
|
||||
|
||||
@spec list_participants_for_event_query(String.t()) :: Ecto.Query.t()
|
||||
def list_local_emails_user_participants_for_event_query(event_id) do
|
||||
Participant
|
||||
|> join(:inner, [p], a in Actor, on: p.actor_id == a.id and is_nil(a.domain))
|
||||
|> join(:left, [_p, a], u in User, on: a.user_id == u.id)
|
||||
|> where([p], p.event_id == ^event_id)
|
||||
|> select([_p, a, u], {a, u})
|
||||
end
|
||||
|
||||
@spec list_participations_for_user_query(integer()) :: Ecto.Query.t()
|
||||
defp list_participations_for_user_query(user_id) do
|
||||
from(
|
||||
|
||||
@@ -11,7 +11,8 @@ defmodule MobilizonWeb.Email do
|
||||
def base_email(args) do
|
||||
instance = Config.instance_config()
|
||||
|
||||
new_email(args)
|
||||
args
|
||||
|> new_email()
|
||||
|> from(Config.instance_email_from())
|
||||
|> put_header("Reply-To", Config.instance_email_reply_to())
|
||||
|> assign(:instance, instance)
|
||||
|
||||
43
lib/mobilizon_web/email/event.ex
Normal file
43
lib/mobilizon_web/email/event.ex
Normal file
@@ -0,0 +1,43 @@
|
||||
defmodule MobilizonWeb.Email.Event do
|
||||
@moduledoc """
|
||||
Handles emails sent about events.
|
||||
"""
|
||||
|
||||
use Bamboo.Phoenix, view: MobilizonWeb.EmailView
|
||||
|
||||
import Bamboo.Phoenix
|
||||
|
||||
import MobilizonWeb.Gettext
|
||||
|
||||
alias Mobilizon.Events.Event
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.Users.User
|
||||
alias MobilizonWeb.Email
|
||||
|
||||
@spec event_updated(User.t(), Actor.t(), Event.t(), Event.t(), list(), String.t()) ::
|
||||
Bamboo.Email.t()
|
||||
def event_updated(
|
||||
%User{} = user,
|
||||
%Actor{} = actor,
|
||||
%Event{} = old_event,
|
||||
%Event{} = event,
|
||||
changes,
|
||||
locale \\ "en"
|
||||
) do
|
||||
Gettext.put_locale(locale)
|
||||
|
||||
subject =
|
||||
gettext(
|
||||
"Event %{title} has been updated",
|
||||
title: old_event.title
|
||||
)
|
||||
|
||||
Email.base_email(to: {Actor.display_name(actor), user.email}, subject: subject)
|
||||
|> assign(:locale, locale)
|
||||
|> assign(:event, event)
|
||||
|> assign(:old_event, old_event)
|
||||
|> assign(:changes, changes)
|
||||
|> assign(:subject, subject)
|
||||
|> render(:event_updated)
|
||||
end
|
||||
end
|
||||
@@ -35,7 +35,7 @@
|
||||
<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;">
|
||||
<%= gettext "You requested to participate in event %{title}", title: @event.title %>
|
||||
<%= gettext "You requested to participate in event %{title}.", title: @event.title %>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
110
lib/mobilizon_web/templates/email/event_updated.html.eex
Normal file
110
lib/mobilizon_web/templates/email/event_updated.html.eex
Normal file
@@ -0,0 +1,110 @@
|
||||
<!-- 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; letter-spacing: 4px; line-height: 48px;">
|
||||
<h1 style="font-size: 48px; font-weight: 400; margin: 0;">
|
||||
<%= gettext "Event updated!" %>
|
||||
</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;">
|
||||
<%= gettext "The event %{title} was updated", title: @old_event.title %>
|
||||
</p>
|
||||
</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: 18px; font-weight: 400; line-height: 25px;" >
|
||||
<table width="100%">
|
||||
<%= if MapSet.member?(@changes, :title) do %>
|
||||
<tr>
|
||||
<td bgcolor="#ffffff" align="left">
|
||||
<%= gettext "Title" %>
|
||||
</td>
|
||||
<td bgcolor="#ffffff" align="left">
|
||||
<%= @event.title %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
<%= if MapSet.member?(@changes, :begins_on) do %>
|
||||
<tr>
|
||||
<td bgcolor="#ffffff" align="left">
|
||||
<%= gettext "Start of event" %>
|
||||
</td>
|
||||
<td bgcolor="#ffffff" align="left">
|
||||
<%= datetime_to_string(@event.begins_on) %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
<%= if MapSet.member?(@changes, :ends_on) do %>
|
||||
<tr>
|
||||
<td bgcolor="#ffffff" align="left">
|
||||
<%= gettext "Ending of event" %>
|
||||
</td>
|
||||
<td bgcolor="#ffffff" align="left">
|
||||
<%= datetime_to_string(@event.ends_on) %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- BULLETPROOF BUTTON -->
|
||||
<tr>
|
||||
<td bgcolor="#ffffff" align="left">
|
||||
<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(MobilizonWeb.Endpoint, :event, @event.id) %>" 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 "Go to event page" %>
|
||||
</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 "If you need to cancel your participation, just access the event page through link above and click on the participation button." %>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<!--[if (gte mso 9)|(IE)]>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<![endif]-->
|
||||
</td>
|
||||
</tr>
|
||||
21
lib/mobilizon_web/templates/email/event_updated.text.eex
Normal file
21
lib/mobilizon_web/templates/email/event_updated.text.eex
Normal file
@@ -0,0 +1,21 @@
|
||||
<%= gettext "Event updated!" %>
|
||||
|
||||
==
|
||||
|
||||
<%= gettext "The event %{title} was just updated", title: @old_event.title %>
|
||||
|
||||
<%= if MapSet.member?(@changes, :title) do %>
|
||||
<%= gettext "New title: %{title}", title: @event.title %>
|
||||
<% end %>
|
||||
|
||||
<%= if MapSet.member?(@changes, :begins_on) do %>
|
||||
<%= gettext "New date and time for start of event: %{begins_on}", begins_on: datetime_to_string(@event.begins_on) %>
|
||||
<% end %>
|
||||
|
||||
<%= if MapSet.member?(@changes, :ends_on) do %>
|
||||
<%= gettext "New date and time for ending of event: %{ends_on}", ends_on: datetime_to_string(@event.ends_on) %>
|
||||
<% end %>
|
||||
|
||||
<%= gettext "View the updated event on: %{link}", link: page_url(MobilizonWeb.Endpoint, :event, @event.id) %>
|
||||
|
||||
<%= gettext "If you need to cancel your participation, just access the event page through link above and click on the participation button." %>
|
||||
@@ -1,3 +1,10 @@
|
||||
defmodule MobilizonWeb.EmailView do
|
||||
use MobilizonWeb, :view
|
||||
|
||||
def datetime_to_string(%DateTime{} = datetime, locale \\ "en") do
|
||||
with {:ok, string} <-
|
||||
Cldr.DateTime.to_string(datetime, Mobilizon.Cldr, format: :medium, locale: locale) do
|
||||
string
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
50
lib/service/events/tools.ex
Normal file
50
lib/service/events/tools.ex
Normal file
@@ -0,0 +1,50 @@
|
||||
defmodule Mobilizon.Service.Events.Tool do
|
||||
@moduledoc """
|
||||
Event-related tools
|
||||
"""
|
||||
alias Mobilizon.Events
|
||||
alias Mobilizon.Events.Event
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.Users.User
|
||||
alias MobilizonWeb.Email
|
||||
alias Mobilizon.Storage.Repo
|
||||
|
||||
@important_changes [:title, :begins_on, :ends_on]
|
||||
|
||||
def calculate_event_diff_and_send_notifications(
|
||||
%Event{} = old_event,
|
||||
%Event{id: event_id} = event,
|
||||
changes
|
||||
) do
|
||||
important = MapSet.new(@important_changes)
|
||||
|
||||
diff =
|
||||
changes
|
||||
|> Map.keys()
|
||||
|> MapSet.new()
|
||||
|> MapSet.intersection(important)
|
||||
|
||||
if MapSet.size(diff) > 0 do
|
||||
Repo.transaction(fn ->
|
||||
event_id
|
||||
|> Events.list_local_emails_user_participants_for_event_query()
|
||||
|> Repo.stream()
|
||||
|> Enum.to_list()
|
||||
|> Enum.each(
|
||||
&send_notification_for_event_update_to_participant(&1, old_event, event, diff)
|
||||
)
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
defp send_notification_for_event_update_to_participant(
|
||||
{%Actor{} = actor, %User{} = user},
|
||||
%Event{} = old_event,
|
||||
%Event{} = event,
|
||||
diff
|
||||
) do
|
||||
user
|
||||
|> Email.Event.event_updated(actor, old_event, event, diff)
|
||||
|> Email.Mailer.deliver_later()
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user