mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2025-02-27 21:54:27 +01:00
(notif) ICS file attached to the reservation notification emails
This commit is contained in:
parent
7da62bb513
commit
fbb9367cd1
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
- Ability to define social networks for the FabLab "about page"
|
- Ability to define social networks for the FabLab "about page"
|
||||||
- Support for OpenID Connect in Sign-Sign-On authentication providers
|
- 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
|
- No longer needed to recompile the assets when switching the authentication provider
|
||||||
- Updated the documentation about the minimum docker version
|
- Updated the documentation about the minimum docker version
|
||||||
- Updated nodejs version to 16.13.2 for dev environment, to reflect production version
|
- Updated nodejs version to 16.13.2 for dev environment, to reflect production version
|
||||||
|
@ -54,7 +54,7 @@ class NotificationsMailer < NotifyWith::NotificationsMailer
|
|||||||
end
|
end
|
||||||
|
|
||||||
def notify_member_create_reservation
|
def notify_member_create_reservation
|
||||||
attachments[@attached_object]
|
attachments[@attached_object.ics_filename] = @attached_object.to_ics
|
||||||
mail(to: @recipient.email,
|
mail(to: @recipient.email,
|
||||||
subject: t('notifications_mailer.notify_member_create_reservation.subject'),
|
subject: t('notifications_mailer.notify_member_create_reservation.subject'),
|
||||||
template_name: 'notify_member_create_reservation')
|
template_name: 'notify_member_create_reservation')
|
||||||
|
42
app/models/concerns/i_calendar_concern.rb
Normal file
42
app/models/concerns/i_calendar_concern.rb
Normal file
@ -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
|
@ -5,6 +5,7 @@
|
|||||||
# Tickets are for Event reservations.
|
# Tickets are for Event reservations.
|
||||||
class Reservation < ApplicationRecord
|
class Reservation < ApplicationRecord
|
||||||
include NotifyWith::NotificationAttachedObject
|
include NotifyWith::NotificationAttachedObject
|
||||||
|
include ICalendarConcern
|
||||||
|
|
||||||
belongs_to :statistic_profile
|
belongs_to :statistic_profile
|
||||||
|
|
||||||
@ -67,10 +68,6 @@ class Reservation < ApplicationRecord
|
|||||||
.first
|
.first
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_ics
|
|
||||||
ReservationService.build_ics(self)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Group all slots related to this reservation by dates and by continuous time ranges
|
# Group all slots related to this reservation by dates and by continuous time ranges
|
||||||
def grouped_slots
|
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] } }
|
slots_by_date = slots.group_by { |slot| slot[:start_at].to_date }.transform_values { |slots| slots.sort_by { |slot| slot[:start_at] } }
|
||||||
|
@ -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
|
|
@ -252,6 +252,7 @@ en:
|
|||||||
Event: "Event"
|
Event: "Event"
|
||||||
Training: "Training"
|
Training: "Training"
|
||||||
description: "You have reserved %{COUNT} slots of %{ITEM}"
|
description: "You have reserved %{COUNT} slots of %{ITEM}"
|
||||||
|
alarm_summary: "Remind your reservation"
|
||||||
roles:
|
roles:
|
||||||
member: "Member"
|
member: "Member"
|
||||||
manager: "Manager"
|
manager: "Manager"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user