* VRFS-1860 - account screen lists by date; VRFS-1911 partially done (using proper date formatting)

This commit is contained in:
Seth Call 2014-07-11 17:21:55 -05:00
parent 55aea1109f
commit 014a423a3d
13 changed files with 265 additions and 66 deletions

View File

@ -32,8 +32,8 @@ require "jam_ruby/lib/s3_util"
require "jam_ruby/lib/s3_manager"
require "jam_ruby/lib/profanity"
require "jam_ruby/lib/json_validator"
require "jam_ruby/lib/em_helper.rb"
require "jam_ruby/lib/nav.rb"
require "jam_ruby/lib/em_helper"
require "jam_ruby/lib/nav"
require "jam_ruby/resque/audiomixer"
require "jam_ruby/resque/icecast_config_writer"
require "jam_ruby/resque/resque_hooks"
@ -64,6 +64,7 @@ require "jam_ruby/app/uploaders/mix_uploader"
require "jam_ruby/app/uploaders/music_notation_uploader"
require "jam_ruby/lib/desk_multipass"
require "jam_ruby/amqp/amqp_connection_manager"
require "jam_ruby/database"
require "jam_ruby/message_factory"
require "jam_ruby/models/feedback"
require "jam_ruby/models/feedback_observer"

View File

@ -74,6 +74,7 @@ module ValidationMessages
# music sessions
MUST_BE_A_MUSICIAN = "must be a musician"
CLAIMED_RECORDING_ALREADY_IN_PROGRESS = "already started by someone else"
MUST_BE_KNOWN_TIMEZONE = "not valid"
# notification
DIFFERENT_SOURCE_TARGET = 'can\'t be same as the sender'

View File

@ -0,0 +1,21 @@
module JamRuby
# creates messages (implementation: protocol buffer) objects cleanly
class Database
#def self.db_timezone
# @@db_timezone ||= TZInfo::Timezone.get(fetch_db_timezone)
#end
def self.db_timezone
@@db_timezone ||= ActiveSupport::TimeZone.new(fetch_db_timezone)
end
def self.fetch_db_timezone
result = ActiveRecord::Base.connection.execute('show timezone')
tz = result.getvalue(0, 0)
result.clear
tz
end
end
end

View File

@ -10,7 +10,7 @@ module JamRuby
RECURRING_MODES = [NO_RECURRING, RECURRING_WEEKLY]
attr_accessor :legal_terms, :language_description, :scheduled_start_time, :access_description
attr_accessor :legal_terms, :language_description, :access_description
attr_accessor :approved_rsvps, :open_slots, :pending_invitations
@ -49,10 +49,15 @@ module JamRuby
validates :is_unstructured_rsvp, :inclusion => {:in => [true, false]}
validates :legal_terms, :inclusion => {:in => [true]}, :on => :create
validates :creator, :presence => true
validates :timezone, presence: true, if: Proc.new { |session| session.scheduled_start }
validates :scheduled_duration, presence: true, if: Proc.new { |session| session.scheduled_start }
validate :creator_is_musician
validate :validate_timezone
before_create :generate_share_token
before_create :add_to_feed
#before_save :update_scheduled_start
SHARE_TOKEN_LENGTH = 8
@ -63,6 +68,15 @@ module JamRuby
feed.music_session = self
end
def update_scheduled_start
# it's very important that this only run if timezone changes, or scheduled_start changes
if self.scheduled_start && (self.scheduled_start_changed? || self.timezone_changed?)
self.scheduled_start = MusicSession.parse_scheduled_start(self.scheduled_start, self.timezone)
end
end
def comment_count
self.comments.size
end
@ -246,7 +260,7 @@ module JamRuby
where rr.user_id = '#{user.id}'
)
)}
)
).order(:scheduled_start)
end
def self.create user, options
@ -270,8 +284,7 @@ module JamRuby
ms.open_rsvps = options[:open_rsvps] if options[:open_rsvps]
ms.creator = user
ms.is_unstructured_rsvp = options[:isUnstructuredRsvp] if options[:isUnstructuredRsvp]
ms.scheduled_start = options[:start]
ms.scheduled_start = parse_scheduled_start(ms.scheduled_start, ms.timezone)
ms.scheduled_start = parse_scheduled_start(options[:start], options[:timezone]) if options[:start] && options[:timezone]
ms.save
@ -439,14 +452,6 @@ module JamRuby
tz
end
def scheduled_start_time
unless self.scheduled_start.nil?
self.scheduled_start.utc.strftime "%a %e %B %Y"
else
""
end
end
def scheduled_end_time
end
@ -708,7 +713,7 @@ module JamRuby
[music_sessions, user_scores]
end
# converts the passed scheduled_start into the UTC using the specified timezone offset.
# converts the passed scheduled_start into the database timezone using the specified timezone offset.
# timezone comes in as TIMEZONE DISPLAY, TIMEZONE ID
def self.parse_scheduled_start(scheduled_start, timezone_param)
@ -718,14 +723,94 @@ module JamRuby
index = timezone_param.rindex(',')
if index
tz_identifier = timezone_param[(index + 1)..-1]
timezone = TZInfo::Timezone.get(tz_identifier)
result = timezone.local_to_utc(scheduled_start, true)
begin
timezone = ActiveSupport::TimeZone.new(tz_identifier)
rescue Exception => e
@@log.error("unable to find timezone=#{tz_identifier}, e=#{e}")
end
if timezone
begin
# first convert the time provided, and convert to the specified timezone (local_to_utc)
# then, convert that to the system timezone, under the ASSUMPTION that the database is configured to use the system timezone
# you can get into trouble if your dev database is not using the system timezone of the web machine
result = timezone.parse(scheduled_start)
rescue Exception => e
@@log.error("unable to convert #{scheduled_start} to #{timezone}, e=#{e}")
puts "unable to convert #{scheduled_start} to #{timezone}, e=#{e}"
end
end
end
end
result
end
def scheduled_start_time
if scheduled_start
scheduled_start.utc.strftime "%a %e %B %Y"
else
""
end
end
# should create a timestamp like:
#
# with_timezone = TRUE
# Tuesday, April 29, 8:00-9:00 PM TIMEZONE (where TIMEZONE is the TIMEZONE defined in the MusicSession when it was created)
#
# with_timezone = FALSE
# Thursday, July 10 - 10:00pm
# this should be in a helper
def pretty_scheduled_start(with_timezone)
if scheduled_start &&
start_time = scheduled_start
timezone_display = 'UTC'
index = timezone.rindex(',')
if index
tz_display = timezone[0, index]
tz_identifier = timezone[(index + 1)..-1]
begin
tz = TZInfo::Timezone.get(tz_identifier)
rescue Exception => e
@@log.error("unable to find timezone=#{tz_identifier}, e=#{e}")
end
if tz
begin
start_time = tz.utc_to_local(scheduled_start.utc)
timezone_display = tz_display
rescue Exception => e
@@log.error("unable to convert #{scheduled_start} to #{tz}, e=#{e}")
puts "unable to convert #{e}"
end
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
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}"
else
"#{start_time.strftime("%A, %B %e")} - #{start_time.strftime("%l:%M%P").strip}"
end
else
"Date and time TBD"
end
end
private
def generate_share_token
@ -747,5 +832,19 @@ module JamRuby
end
end
def validate_timezone
if timezone
index = timezone.rindex(',')
if index
tz_identifier = timezone[(index + 1)..-1]
begin
TZInfo::Timezone.get(tz_identifier)
rescue Exception => e
@@log.error("unable to find timezone=#{tz_identifier}, e=#{e}")
errors.add(:timezone, ValidationMessages::MUST_BE_KNOWN_TIMEZONE)
end
end
end
end
end
end

View File

@ -89,13 +89,14 @@ FactoryGirl.define do
musician_access true
legal_terms true
language 'eng'
timezone 'utc'
timezone 'UTC,Etc/UTC'
legal_policy 'standard'
recurring_mode 'once'
genre JamRuby::Genre.first
association :creator, :factory => :user
open_rsvps true
scheduled_start Time.now
scheduled_duration 3600
factory :recurring_music_session_weekly do
recurring_mode 'weekly'

View File

@ -48,28 +48,70 @@ describe MusicSession do
end
describe "create" do
it "scheduled session" do
session = MusicSession.create(creator, {
name: "session 1",
description: "my session",
genres: ['ambient'],
musician_access: true,
fan_access: true,
approval_required: true,
fan_chat: true,
legal_policy: 'Standard',
language: 'eng',
start: "Thu Jul 10 2014 10:00 PM",
timezone: "Central Time (US & Canada),America/Chicago",
open_rsvps: true,
legal_terms: true,
recurring_mode: 'once',
isUnstructuredRsvp: true,
rsvp_slots: [{ instrument_id: "other", proficiency_level: 1, approve: true}]
})
let(:open_params) {
{
name: "session 1",
description: "my session",
genres: ['ambient'],
musician_access: true,
fan_access: true,
approval_required: true,
fan_chat: true,
legal_policy: 'Standard',
language: 'eng',
start: "Thu Jul 10 2014 10:00 PM",
duration: 30,
timezone: "Central Time (US & Canada),America/Chicago",
open_rsvps: true,
legal_terms: true,
recurring_mode: 'once',
isUnstructuredRsvp: true,
rsvp_slots: [{ instrument_id: "other", proficiency_level: 1, approve: true}]
}
}
it "wide open scheduled session" do
session = MusicSession.create(creator, open_params)
session.valid?.should be_true
# verify that scheduled_start is now 5 hours ahead of what was specified (CST during summer is -5 offset)
session.scheduled_start.utc.should == DateTime.new(2014,07,11,3,00,0)
# verify that the update_scheduled_start does not disturb scheduled_start
session.save!
session.scheduled_start.utc.should == DateTime.new(2014,07,11,3,00,0)
end
it "works with UTC timezone" do
open_params[:timezone] = 'UTC,Etc/UTC'
session = MusicSession.create(creator, open_params)
session.valid?.should be_true
# verify that scheduled_start is now 5 hours ahead of what was specified (CST during summer is -5 offset)
session.scheduled_start.should == DateTime.new(2014,07,10,22,00,0)
end
it "no scheduled_start" do
open_params[:timezone] = nil
open_params[:scheduled_start] = nil
open_params[:scheduled_duration] = nil
session = MusicSession.create(creator, open_params)
session.valid?.should be_true
session.scheduled_start.should be_nil
end
end
describe "pretty_scheduled_start" do
it "displays central time correctly" do
time = MusicSession.parse_scheduled_start("Thu Jul 10 2014 10:00 PM", "Central Time (US & Canada),America/Chicago")
music_session = FactoryGirl.create(:music_session, scheduled_start: time, timezone: "Central Time (US & Canada),America/Chicago")
music_session.pretty_scheduled_start(true).should == 'Thursday, July 10, 10:00-11:00 PM Central Time (US & Canada)'
music_session.pretty_scheduled_start(false).should == 'Thursday, July 10 - 10:00pm'
end
it "displays default correctly" do
music_session = FactoryGirl.create(:music_session, scheduled_start: nil)
music_session.pretty_scheduled_start(true).should == 'Date and time TBD'
music_session.pretty_scheduled_start(false).should == 'Date and time TBD'
end
end
@ -258,8 +300,6 @@ describe MusicSession do
creators_slot.proficiency_level = nil
creators_slot.save!
puts RsvpSlot.all.inspect
music_session = MusicSession.find(music_session1.id)
approved_rsvps = music_session.approved_rsvps
approved_rsvps.length.should == 1
@ -278,7 +318,7 @@ describe MusicSession do
approved_rsvps.length.should == 2
# find the user who made the request for 2 rsvp slots in the approved_users array
approved_some_user = approved_rsvps.find {|s| puts s.inspect; s.id == some_user.id}
approved_some_user = approved_rsvps.find {|s| s.id == some_user.id}
instrument_ids = JSON.parse(approved_some_user[:instrument_ids])
instrument_ids.should =~ rsvp_request.rsvp_slots.map {|slot| slot.instrument_id }
@ -294,17 +334,29 @@ describe MusicSession do
describe "parse_scheduled_start" do
it "converts correctly" do
it "converts central time correctly" do
# CST has -5 offset in summery
time = DateTime.new(2004,10,15,1,30,0)
time = DateTime.new(2004,10,15,1,30,0).strftime('%Y-%m-%d %H:%M:%S')
converted = MusicSession.parse_scheduled_start(time, 'Central Time (US & Canada),America/Chicago')
converted.should == DateTime.new(2004,10,15,6,30,0)
converted.should == DateTime.new(2004,10,15,6,30,0, '+0')
# CST has -6 offset in winter
time = DateTime.new(2004,11,15,1,30,0)
time = DateTime.new(2004,11,15,1,30,0).strftime('%Y-%m-%d %H:%M:%S')
converted = MusicSession.parse_scheduled_start(time, 'Central Time (US & Canada),America/Chicago')
converted.should == DateTime.new(2004,11,15,7,30,0)
converted.should == DateTime.new(2004,11,15,7,30,0, '+0')
end
it "converts UTC correctly" do
# should not shift
time = DateTime.new(2004,10,15,1,30,0, '+0').strftime('%Y-%m-%d %H:%M:%S')
converted = MusicSession.parse_scheduled_start(time, 'UTC,Etc/UTC')
converted.should == DateTime.new(2004,10,15,1,30,0, '+0')
# should not shift
time = DateTime.new(2004,11,15,1,30,0).strftime('%Y-%m-%d %H:%M:%S')
converted = MusicSession.parse_scheduled_start(time, 'UTC,Etc/UTC')
converted.should == DateTime.new(2004,11,15,1,30,0, '+0')
end
end

View File

@ -104,7 +104,7 @@
var options = {
id: session.id,
name: session.name,
scheduled_start: session.scheduled_start
scheduled_start: session.pretty_scheduled_start_short
};
var txt = $(context._.template($('#template-scheduled-session').html(), options, { variable: 'data' }));
$scheduledSessions.append(txt);

View File

@ -194,23 +194,22 @@ class ApiMusicSessionsController < ApiController
begin
@music_session = MusicSession.find(params[:id])
if @music_session.creator == current_user
band = Band.find(options[:band]) unless params[:band_id].nil?
@music_session.name = params[:name] unless params[:name].nil?
@music_session.description = params[:description] unless params[:description].nil?
@music_session.musician_access = params[:musician_access] unless params[:musician_access].nil?
@music_session.approval_required = params[:approval_required] unless params[:approval_required].nil?
@music_session.fan_chat = params[:fan_chat] unless params[:fan_chat].nil?
@music_session.fan_access = params[:fan_access] unless params[:fan_access].nil?
@music_session.genre = Genre.find_by_id(params[:genres][0]) if params[:genres] && params[:genres].length > 0
@music_session.legal_policy = params[:legal_policy] unless params[:legal_policy].nil?
@music_session.language = params[:language] unless params[:language].nil?
@music_session.scheduled_start = params[:start] unless params[:start].nil?
@music_session.scheduled_duration = params[:duration] + ' minutes' if params[:duration]
@music_session.timezone = params[:timezone] unless params[:timezone].nil?
@music_session.recurring_mode = params[:reoccurrence] unless params[:reoccurrence].nil?
@music_session.open_rsvps = params[:open_rsvps] ? true : false
@music_session.band = band unless band.nil?
@music_session.name = params[:name] if params.include? :name
@music_session.description = params[:description] if params.include? :description
@music_session.musician_access = params[:musician_access] if params.include? :musician_access
@music_session.approval_required = params[:approval_required] if params.include? :approval_required
@music_session.fan_chat = params[:fan_chat] if params.include? :fan_chat
@music_session.fan_access = params[:fan_access] if params.include? :fan_access
@music_session.genre = Genre.find_by_id(params[:genres][0]) if params.include?(:genres) && params[:genres] && params[:genres].length > 0
@music_session.legal_policy = params[:legal_policy] if params.include? :legal_policy
@music_session.language = params[:language] if params.include? :language
@music_session.scheduled_start = MusicSession.parse_scheduled_start(params[:start], params[:timezone]) if params.include?(:start) && params.include?(:timezone)
@music_session.scheduled_duration = params[:duration] + ' minutes' if params.include? :duration
@music_session.timezone = params[:timezone] if params.include? :timezone
@music_session.recurring_mode = params[:reoccurrence] if params.include? :reoccurrence
@music_session.open_rsvps = params[:open_rsvps] if params.include? :open_rsvps
@music_session.band = (params[:band] ? Band.find(params[:band]) : nil) if params.include? :band
@music_session.save
params[:music_notations].each do |notation_id|
@ -219,7 +218,7 @@ class ApiMusicSessionsController < ApiController
notation.save
ms.music_notations << notation
end if params[:music_notations]
end if params.include? :music_notations
if @music_session.errors.any?
response.status = :unprocessable_entity

View File

@ -62,4 +62,12 @@ module MusicSessionHelper
def timezone_list
end
def scheduled_start_time(music_session)
music_session.scheduled_start_time
end
def pretty_scheduled_start(music_session, with_timezone)
music_session.pretty_scheduled_start(with_timezone)
end
end

View File

@ -31,10 +31,24 @@ else
[item.genre.description] # XXX: need to return single genre; not array
end
node :scheduled_start_time do |session|
scheduled_start_time(session)
end
node :scheduled_start do |history|
history.scheduled_start.utc.strftime("%a %e %B %Y %H:%M:%S") if history.scheduled_start
end
node :pretty_scheduled_start_with_timezone do |session|
pretty_scheduled_start(session, true)
end
node :pretty_scheduled_start_short do|session|
pretty_scheduled_start(session, false)
end
child(:creator => :creator) {
attributes :id, :name, :photo_url
}

View File

@ -114,7 +114,8 @@ FactoryGirl.define do
open_rsvps true
scheduled_start Time.now
recurring_mode 'once'
scheduled_duration "30 minutes"
scheduled_duration 3600
timezone "UTC,Etc/UTC"
factory :recurring_music_session_weekly do

View File

@ -27,7 +27,8 @@ describe "Active Music Session API ", :type => :api do
:genres => ["classical"], :musician_access => true, :approval_required => false,
:fan_chat => true, :fan_access => true,
:legal_policy => true, :language => 'eng',
:timezone => "utc",
:timezone => "UTC,Etc/UTC",
:duration => "60",
:rsvp_slots => [{proficiency_level: 1, instrument_id: 'other', approve:true}]
} }

View File

@ -23,7 +23,8 @@ describe "Scheduled Music Session API ", :type => :api do
:genres => ["classical"], :musician_access => true, :approval_required => false,
:fan_chat => true, :fan_access => true,
:legal_policy => true, :language => 'eng',
:timezone => "utc",
:timezone => "UTC,Etc/UTC",
:duration => "60",
:rsvp_slots => [{proficiency_level: 1, instrument_id: 'other', approve:true}] } }
before(:all) do