mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2024-12-01 12:24:28 +01:00
Merge branch 'ics' into v5.4
This commit is contained in:
commit
249285ea51
@ -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
|
||||
@ -15,6 +16,7 @@
|
||||
- Updated typescript to v4.6.3
|
||||
- Updated react-select to v5.2.2
|
||||
- Updated sidekiq-scheduler to v4.0.0
|
||||
- Updated icalendar to 2.7.1
|
||||
- Webpack overlay will now report eslint issues
|
||||
- Linted all code according to eslint rules
|
||||
- when generating an avoir, the option "by_wallet" is not present anymore if wallet module is off
|
||||
|
@ -169,9 +169,9 @@ GEM
|
||||
httpclient (2.8.3)
|
||||
i18n (1.10.0)
|
||||
concurrent-ruby (~> 1.0)
|
||||
icalendar (2.5.3)
|
||||
icalendar (2.7.1)
|
||||
ice_cube (~> 0.16)
|
||||
ice_cube (0.16.3)
|
||||
ice_cube (0.16.4)
|
||||
ice_nine (0.11.2)
|
||||
image_processing (1.12.2)
|
||||
mini_magick (>= 4.9.5, < 5)
|
||||
|
@ -3,7 +3,7 @@ import { User } from '../models/user';
|
||||
import { supportedNetworks, SupportedSocialNetwork } from '../models/social-network';
|
||||
|
||||
export default class UserLib {
|
||||
private user: User;
|
||||
private readonly user: User;
|
||||
|
||||
constructor (user: User) {
|
||||
this.user = user;
|
||||
|
@ -52,4 +52,11 @@ class NotificationsMailer < NotifyWith::NotificationsMailer
|
||||
subject: t('notifications_mailer.notify_member_payment_schedule_ready.subject'),
|
||||
template_name: 'notify_member_payment_schedule_ready')
|
||||
end
|
||||
|
||||
def notify_member_create_reservation
|
||||
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')
|
||||
end
|
||||
end
|
||||
|
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.
|
||||
class Reservation < ApplicationRecord
|
||||
include NotifyWith::NotificationAttachedObject
|
||||
include ICalendarConcern
|
||||
|
||||
belongs_to :statistic_profile
|
||||
|
||||
@ -67,6 +68,28 @@ class Reservation < ApplicationRecord
|
||||
.first
|
||||
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] } }
|
||||
result = {}
|
||||
slots_by_date.each do |date, daily_slots|
|
||||
result[date] = { daily_slots.first[:start_at] => [daily_slots.first] }
|
||||
|
||||
daily_slots[1..].each do |slot|
|
||||
found = false
|
||||
result[date].each do |group_start, group_slots|
|
||||
if slot[:start_at] === group_slots.last[:end_at]
|
||||
result[date][group_start].push(slot)
|
||||
found = true
|
||||
break
|
||||
end
|
||||
end
|
||||
result[date][slot[:start_at]] = [slot] unless found
|
||||
end
|
||||
end
|
||||
result
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def machine_not_already_reserved
|
||||
|
@ -244,6 +244,15 @@ en:
|
||||
event: "Event"
|
||||
reservations: "Reservations"
|
||||
available_seats: "Available seats"
|
||||
reservation_ics:
|
||||
summary: "%{TYPE} reservation"
|
||||
type:
|
||||
Machine: "Machine"
|
||||
Space: "Space"
|
||||
Event: "Event"
|
||||
Training: "Training"
|
||||
description: "You have reserved %{COUNT} slots of %{ITEM}"
|
||||
alarm_summary: "Remind your reservation"
|
||||
roles:
|
||||
member: "Member"
|
||||
manager: "Manager"
|
||||
|
Loading…
Reference in New Issue
Block a user