From fbb9367cd1ce765ab5047196c542a1693445b63a Mon Sep 17 00:00:00 2001 From: Sylvain Date: Wed, 11 May 2022 10:44:57 +0200 Subject: [PATCH] (notif) ICS file attached to the reservation notification emails --- CHANGELOG.md | 1 + app/mailers/notifications_mailer.rb | 2 +- app/models/concerns/i_calendar_concern.rb | 42 +++++++++++++++++++++++ app/models/reservation.rb | 5 +-- app/services/reservation_service.rb | 25 -------------- config/locales/en.yml | 1 + 6 files changed, 46 insertions(+), 30 deletions(-) create mode 100644 app/models/concerns/i_calendar_concern.rb delete mode 100644 app/services/reservation_service.rb diff --git a/CHANGELOG.md b/CHANGELOG.md index ef3c67645..551e88d46 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - Ability to define social networks for the FabLab "about page" - Support for OpenID Connect in Sign-Sign-On authentication providers +- ICS file attached to the reservation notification email - No longer needed to recompile the assets when switching the authentication provider - Updated the documentation about the minimum docker version - Updated nodejs version to 16.13.2 for dev environment, to reflect production version diff --git a/app/mailers/notifications_mailer.rb b/app/mailers/notifications_mailer.rb index e0e3e49c9..638b125d2 100644 --- a/app/mailers/notifications_mailer.rb +++ b/app/mailers/notifications_mailer.rb @@ -54,7 +54,7 @@ class NotificationsMailer < NotifyWith::NotificationsMailer end def notify_member_create_reservation - attachments[@attached_object] + attachments[@attached_object.ics_filename] = @attached_object.to_ics mail(to: @recipient.email, subject: t('notifications_mailer.notify_member_create_reservation.subject'), template_name: 'notify_member_create_reservation') diff --git a/app/models/concerns/i_calendar_concern.rb b/app/models/concerns/i_calendar_concern.rb new file mode 100644 index 000000000..708bd99a7 --- /dev/null +++ b/app/models/concerns/i_calendar_concern.rb @@ -0,0 +1,42 @@ +# frozen_string_literal: true + +# Adds support for iCalendar formar (RFC 5545) to reservations +module ICalendarConcern + extend ActiveSupport::Concern + require 'icalendar' + require 'icalendar/tzinfo' + + included do + def to_ics + cal = Icalendar::Calendar.new + cal.add_timezone Time.zone.tzinfo.ical_timezone Time.zone.now + build_icalendar(cal) + cal.to_ical + end + + def ics_filename + "#{self.class.name.downcase}-#{id}.ics" + end + + def build_icalendar(cal) + grouped_slots.each do |_date, daily_groups| + daily_groups.each do |start_time, group_slots| + cal.event do |e| + e.dtstart = start_time + e.dtend = group_slots.last[:end_at] + e.summary = I18n.t('reservation_ics.summary', TYPE: I18n.t("reservation_ics.type.#{reservable.class.name}")) + e.description = I18n.t('reservation_ics.description', COUNT: group_slots.count, ITEM: reservable.name) + e.ip_class = 'PRIVATE' + + e.alarm do |a| + a.action = 'DISPLAY' + a.summary = I18n.t('reservation_ics.alarm_summary') + a.trigger = '-P1DT0H0M0S' + end + end + end + end + cal + end + end +end diff --git a/app/models/reservation.rb b/app/models/reservation.rb index de38630ae..0c3c3dc88 100644 --- a/app/models/reservation.rb +++ b/app/models/reservation.rb @@ -5,6 +5,7 @@ # Tickets are for Event reservations. class Reservation < ApplicationRecord include NotifyWith::NotificationAttachedObject + include ICalendarConcern belongs_to :statistic_profile @@ -67,10 +68,6 @@ class Reservation < ApplicationRecord .first end - def to_ics - ReservationService.build_ics(self) - end - # Group all slots related to this reservation by dates and by continuous time ranges def grouped_slots slots_by_date = slots.group_by { |slot| slot[:start_at].to_date }.transform_values { |slots| slots.sort_by { |slot| slot[:start_at] } } diff --git a/app/services/reservation_service.rb b/app/services/reservation_service.rb deleted file mode 100644 index a3a6ae2c9..000000000 --- a/app/services/reservation_service.rb +++ /dev/null @@ -1,25 +0,0 @@ -# frozen_string_literal: true - -# Provides methods around the Reservation objects -class ReservationService - class << self - def build_ics(reservation) - require 'icalendar' - - cal = Icalendar::Calendar.new - reservation.grouped_slots.each do |date, daily_groups| - daily_groups.each do |start_time, group_slots| - cal.event do |e| - e.dtstart = start_time - e.dtend = group_slots.last[:end_at] - e.summary = I18n.t('reservation_ics.summary', TYPE: I18n.t("reservation_ics.type.#{reservation.reservable.class.name}")) - e.description = I18n.t('reservation_ics.description', COUNT: group_slots.count, ITEM: reservation.reservable.name) - e.ip_class = "PRIVATE" - end - end - end - - cal.to_ical - end - end -end diff --git a/config/locales/en.yml b/config/locales/en.yml index c14c5af68..888e46af1 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -252,6 +252,7 @@ en: Event: "Event" Training: "Training" description: "You have reserved %{COUNT} slots of %{ITEM}" + alarm_summary: "Remind your reservation" roles: member: "Member" manager: "Manager"