VRFS-3276 : Calendar manager

* Streamline logic
* Enable recurring sessions through rrule
* Implement method to create ics feed for user
* Extract a type-safe scheduled duration method on music_session for
external and internal use.
This commit is contained in:
Steven Miers 2015-06-26 13:56:56 -05:00
parent b71ad3a4cd
commit 92a2524c65
2 changed files with 73 additions and 52 deletions

View File

@ -1,43 +1,59 @@
module JamRuby
class CalendarManager
class << self
def ics_from_music_session(music_session, delete=false)
uid = "#{music_session.user_id}_#{music_session.id}@JamKazam"
text = "JamKazam Session #{music_session.description}"
case music_session.recurring_mode
when NO_RECURRING
create_ics_event(uid, text, scheduled_start, scheduled_start+scheduled_duration, delete)
when RECURRING_WEEKLY
create_ics_event(uid, text, scheduled_start, scheduled_start+scheduled_duration, delete)
else
raise ArgumentError("Recurring mode not supported: #{music_session.recurring_mode}")
end
end
# @return calendar (as ICS string) for specified user
def create_ics_feed(user)
end
def create_ics_event(uuid, summary, start_at, end_at, delete=false, sequence=0)
uuid ||= UUID.timestamp_create
event = "BEGIN:VEVENT\r\n"
event << "UID:#{uuid}\r\n"
event << "DTSTAMP:#{Time.now.utc().strftime(DATE_FORMAT)}\r\n"
event << "DTSTART:#{start_at.utc().strftime(DATE_FORMAT)}\r\n"
event << "DTEND:#{end_at.utc().strftime(DATE_FORMAT)}\r\n"
event << "SUMMARY:#{summary}\r\n"
if delete
event << "METHOD:CANCEL\r\n"
event << "STATUS:CANCELLED\r\n"
end
event << "SEQUENCE:#{sequence}\r\n" if sequence
event << "END:VEVENT"
end
def create_ics_cal(ics_events)
"BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:JamKazam\r\n#{ics_events}\r\nEND:VCALENDAR"
end
class CalendarManager < BaseManager
DATE_FORMAT="%Y%m%dT%H%M%SZ"
def initialize(options={})
super(options)
@log = Logging.logger[self]
end
end
end
# @return event (as ICS string) for a given music session
def ics_event_from_music_session(music_session, delete=false)
# Determine properties of calendar event and create:
uid = "#{music_session.id}@JamKazam"
text = "JamKazam Session #{music_session.description}"
rrule = nil
start_at = music_session.scheduled_start
stop_at = music_session.scheduled_start+music_session.safe_scheduled_duration
if !delete && music_session.recurring_mode==MusicSession::RECURRING_WEEKLY
rrule = "FREQ=WEEKLY;INTERVAL=1"
end
create_ics_event(uid, text, start_at, stop_at, delete, rrule)
end
# @return calendar (as ICS string) for specified user
def create_ics_feed(user)
ics_events = ""
MusicSession.scheduled_rsvp(user, true).each_with_index do |music_session, i|
ics_events << "\r\n" if(i > 0)
ics_events << ics_event_from_music_session(music_session)
end
create_ics_cal(ics_events)
end
# @return event (as ICS string) for given arguments
def create_ics_event(uuid, summary, start_at, end_at, delete=false, rrule=nil, sequence=nil)
uuid ||= UUID.timestamp_create
event = "BEGIN:VEVENT\r\n"
event << "UID:#{uuid}\r\n"
event << "DTSTAMP:#{Time.now.utc().strftime(DATE_FORMAT)}\r\n"
event << "DTSTART:#{start_at.utc().strftime(DATE_FORMAT)}\r\n"
event << "DTEND:#{end_at.utc().strftime(DATE_FORMAT)}\r\n"
event << "SUMMARY:#{summary}\r\n"
if delete
event << "METHOD:CANCEL\r\n"
event << "STATUS:CANCELLED\r\n"
end
if rrule
event << "RRULE:#{rrule}\r\n"
end
event << "SEQUENCE:#{sequence}\r\n" if sequence
event << "END:VEVENT"
end
# @return calendar (as ICS string) for specified events
def create_ics_cal(ics_events)
"BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:JamKazam\r\n#{ics_events}\r\nEND:VCALENDAR"
end
end # class
end # module

View File

@ -880,6 +880,21 @@ SQL
end
result
end
def safe_scheduled_duration
duration = scheduled_duration
# you can put seconds into the scheduled_duration field, but once stored, it comes back out as a string
if scheduled_duration.class == String
begin
bits = scheduled_duration.split(':')
duration = bits[0].to_i.hours + bits[1].to_i.minutes + bits[2].to_i.seconds
rescue Exception => e
duration = 1.hours
@@log.error("unable to parse duration #{scheduled_duration}")
end
end
duration
end
# should create a timestamp like:
#
# with_timezone = TRUE
@ -910,17 +925,7 @@ SQL
end
end
duration = scheduled_duration
# you can put seconds into the scheduled_duration field, but once stored, it comes back out as a string
if scheduled_duration.class == String
begin
bits = scheduled_duration.split(':')
duration = bits[0].to_i.hours + bits[1].to_i.minutes + bits[2].to_i.seconds
rescue Exception => e
duration = 1.hours
@@log.error("unable to parse duration #{scheduled_duration}")
end
end
duration = safe_scheduled_duration
end_time = start_time + duration
if with_timezone
"#{start_time.strftime("%A, %B %e")}, #{start_time.strftime("%l:%M").strip}-#{end_time.strftime("%l:%M %p").strip} #{timezone_display}"