From fdc8536c6f362526d435525a5480244b67aed520 Mon Sep 17 00:00:00 2001 From: Thomas Citharel Date: Mon, 16 Nov 2020 18:28:52 +0100 Subject: [PATCH] Use user timezone in emails Signed-off-by: Thomas Citharel --- lib/mobilizon/events/events.ex | 10 +++- lib/web/email/event.ex | 60 ++++++++++++++++--- .../templates/email/event_updated.html.eex | 4 +- .../templates/email/event_updated.text.eex | 4 +- .../email/notification_each_week.html.eex | 4 +- .../email/notification_each_week.text.eex | 7 +-- lib/web/views/email_view.ex | 11 ++++ 7 files changed, 80 insertions(+), 20 deletions(-) diff --git a/lib/mobilizon/events/events.ex b/lib/mobilizon/events/events.ex index d5dfb9b5..38d10dcb 100644 --- a/lib/mobilizon/events/events.ex +++ b/lib/mobilizon/events/events.ex @@ -30,7 +30,7 @@ defmodule Mobilizon.Events do alias Mobilizon.Service.Workers alias Mobilizon.Share alias Mobilizon.Storage.{Page, Repo} - alias Mobilizon.Users.User + alias Mobilizon.Users.{Setting, User} alias Mobilizon.Web.Email @@ -1587,16 +1587,22 @@ defmodule Mobilizon.Events do ) end + @doc """ + List emails for local users (including anonymous ones) participating to an event + + Returns {participation, actor, user, user_settings} + """ @spec list_local_emails_user_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) + |> join(:left, [_p, _a, u], s in Setting, on: s.user_id == u.id) |> where( [p], p.event_id == ^event_id and p.role not in [^:not_approved, ^:not_confirmed, ^:rejected] ) - |> select([p, a, u], {p, a, u}) + |> select([p, a, u, s], {p, a, u, s}) end @spec list_participations_for_user_query(integer()) :: Ecto.Query.t() diff --git a/lib/web/email/event.ex b/lib/web/email/event.ex index b4cd2e0e..b7b36e48 100644 --- a/lib/web/email/event.ex +++ b/lib/web/email/event.ex @@ -13,7 +13,7 @@ defmodule Mobilizon.Web.Email.Event do alias Mobilizon.Events alias Mobilizon.Events.{Event, Participant} alias Mobilizon.Storage.Repo - alias Mobilizon.Users.User + alias Mobilizon.Users.{Setting, User} alias Mobilizon.Web.Email alias Mobilizon.Web.Gettext, as: GettextBackend @@ -28,6 +28,7 @@ defmodule Mobilizon.Web.Email.Event do %Event{} = old_event, %Event{} = event, changes, + timezone \\ "Etc/UTC", locale \\ "en" ) do GettextBackend.put_locale(locale) @@ -44,6 +45,7 @@ defmodule Mobilizon.Web.Email.Event do |> assign(:old_event, old_event) |> assign(:changes, changes) |> assign(:subject, subject) + |> assign(:timezone, timezone) |> render(:event_updated) end @@ -75,18 +77,42 @@ defmodule Mobilizon.Web.Email.Event do defp send_notification_for_event_update_to_participant( {%Participant{} = _participant, %Actor{} = actor, - %User{locale: locale, email: email} = _user}, + %User{locale: locale, email: email} = _user, %Setting{timezone: timezone}}, %Event{} = old_event, %Event{} = event, diff ) do - email - |> Email.Event.event_updated(actor, old_event, event, diff, locale) - |> Email.Mailer.deliver_later() + do_send_notification_for_event_update_to_participant( + email, + actor, + old_event, + event, + diff, + timezone, + locale + ) end defp send_notification_for_event_update_to_participant( - {%Participant{metadata: %{email: email}} = _participant, %Actor{} = actor, nil}, + {%Participant{} = _participant, %Actor{} = actor, + %User{locale: locale, email: email} = _user, nil}, + %Event{} = old_event, + %Event{} = event, + diff + ) do + do_send_notification_for_event_update_to_participant( + email, + actor, + old_event, + event, + diff, + "Etc/UTC", + locale + ) + end + + defp send_notification_for_event_update_to_participant( + {%Participant{metadata: %{email: email}} = _participant, %Actor{} = actor, nil, nil}, %Event{} = old_event, %Event{} = event, diff @@ -94,8 +120,28 @@ defmodule Mobilizon.Web.Email.Event do when not is_nil(email) do locale = Gettext.get_locale() + do_send_notification_for_event_update_to_participant( + email, + actor, + old_event, + event, + diff, + "Etc/UTC", + locale + ) + end + + defp do_send_notification_for_event_update_to_participant( + email, + actor, + old_event, + event, + diff, + timezone, + locale + ) do email - |> Email.Event.event_updated(actor, old_event, event, diff, locale) + |> Email.Event.event_updated(actor, old_event, event, diff, timezone, locale) |> Email.Mailer.deliver_later() end end diff --git a/lib/web/templates/email/event_updated.html.eex b/lib/web/templates/email/event_updated.html.eex index a58ec69b..f6539b2e 100644 --- a/lib/web/templates/email/event_updated.html.eex +++ b/lib/web/templates/email/event_updated.html.eex @@ -74,7 +74,7 @@ <%= gettext "Start" %> - <%= datetime_to_string(@event.begins_on, @locale) %> + <%= @event.begins_on |> datetime_tz_convert(@timezone) |> datetime_to_string(@locale) %> <% end %> @@ -84,7 +84,7 @@ <%= gettext "End" %> - <%= datetime_to_string(@event.ends_on, @locale) %> + <%= @event.ends_on |> datetime_tz_convert(@timezone) |> datetime_to_string(@locale) %> <% end %> diff --git a/lib/web/templates/email/event_updated.text.eex b/lib/web/templates/email/event_updated.text.eex index ae613797..d65225f1 100644 --- a/lib/web/templates/email/event_updated.text.eex +++ b/lib/web/templates/email/event_updated.text.eex @@ -15,10 +15,10 @@ <%= gettext "New title: %{title}", title: @event.title %> <% end %> <%= if MapSet.member?(@changes, :begins_on) do %> - <%= gettext "Start %{begins_on}", begins_on: datetime_to_string(@event.begins_on, @locale) %> + <%= gettext "Start %{begins_on}", begins_on: @event.begins_on |> datetime_tz_convert(@timezone) |> datetime_to_string(@locale) %> <% end %> <%= if MapSet.member?(@changes, :ends_on) && !is_nil(@event.ends_on) do %> - <%= gettext "End %{ends_on}", ends_on: datetime_to_string(@event.ends_on, @locale) %> + <%= gettext "End %{ends_on}", ends_on: @event.ends_on |> datetime_tz_convert(@timezone) |> datetime_to_string(@locale) %> <% end %> <%= gettext "Visit the updated event page: %{link}", link: page_url(Mobilizon.Web.Endpoint, :event, @event.uuid) %> <%= ngettext "Would you wish to cancel your attendance, visit the event page through the link above and click the « Attending » button.", "Would you wish to cancel your attendance to one or several events, visit the event pages through the links above and click the « Attending » button.", 1 %> diff --git a/lib/web/templates/email/notification_each_week.html.eex b/lib/web/templates/email/notification_each_week.html.eex index a1349e15..c27c2301 100644 --- a/lib/web/templates/email/notification_each_week.html.eex +++ b/lib/web/templates/email/notification_each_week.html.eex @@ -46,7 +46,7 @@ <%= for participation <- @participations do %>
  • - <%= participation.event.begins_on |> DateTime.shift_zone!(@timezone) |> datetime_to_string(@locale) %> + <%= participation.event.begins_on |> datetime_tz_convert(@timezone) |> datetime_to_string(@locale) %> <%= participation.event.title %> @@ -56,7 +56,7 @@ <% else %> - <%= @participation.event.begins_on |> DateTime.shift_zone!(@timezone) |> datetime_to_string(@locale) %> + <%= @participation.event.begins_on |> datetime_tz_convert(@timezone) |> datetime_to_string(@locale) %> <%= @participation.event.title %> diff --git a/lib/web/templates/email/notification_each_week.text.eex b/lib/web/templates/email/notification_each_week.text.eex index 2721442c..e0c2c3cb 100644 --- a/lib/web/templates/email/notification_each_week.text.eex +++ b/lib/web/templates/email/notification_each_week.text.eex @@ -1,14 +1,11 @@ <%= gettext "What's up this week?" %> == - <%= ngettext "You have one event this week:", "You have %{total} events this week:", @total, total: @total %> - <%= if @total > 1 do %> <%= for participation <- @participations do %> - - <%= participation.event.begins_on |> DateTime.shift_zone!(@timezone) |> datetime_to_string(@locale) %> - <%= participation.event.title %> <%= page_url(Mobilizon.Web.Endpoint, :event, participation.event.uuid) %> + - <%= participation.event.begins_on |> datetime_tz_convert(@timezone) |> datetime_to_string(@locale) %> - <%= participation.event.title %> <%= page_url(Mobilizon.Web.Endpoint, :event, participation.event.uuid) %> <% end %> <% else %> - <%= DateTime.shift_zone!(@participation.event.begins_on, @timezone) |> datetime_to_string(@locale) %> - <%= @participation.event.title %> <%= page_url(Mobilizon.Web.Endpoint, :event, @participation.event.uuid) %> + <%= @participation.event.begins_on |> datetime_tz_convert(@timezone) |> datetime_to_string(@locale) %> - <%= @participation.event.title %> <%= page_url(Mobilizon.Web.Endpoint, :event, @participation.event.uuid) %> <% end %> - <%= ngettext "Would you wish to cancel your attendance, visit the event page through the link above and click the « Attending » button.", "Would you wish to cancel your attendance to one or several events, visit the event pages through the links above and click the « Attending » button.", @total %> diff --git a/lib/web/views/email_view.ex b/lib/web/views/email_view.ex index 74fada64..fb3d6141 100644 --- a/lib/web/views/email_view.ex +++ b/lib/web/views/email_view.ex @@ -16,4 +16,15 @@ defmodule Mobilizon.Web.EmailView do string end end + + @spec datetime_tz_convert(DateTime.t(), String.t()) :: DateTime.t() + def datetime_tz_convert(%DateTime{} = datetime, timezone) do + case DateTime.shift_zone(datetime, timezone) do + {:ok, datetime_with_user_tz} -> + datetime_with_user_tz + + _ -> + datetime + end + end end