finish basic create session flow

This commit is contained in:
Bert Owen 2014-06-10 06:13:54 +08:00
commit 3ed14be60f
41 changed files with 860 additions and 316 deletions

View File

@ -169,3 +169,4 @@ periodic_emails.sql
remember_extra_scoring_data.sql
indexing_for_regions.sql
latency_tester.sql
scheduled_sessions_next_session_scheduled.sql

View File

@ -0,0 +1 @@
alter table music_sessions add column next_session_scheduled BOOLEAN default null;

View File

@ -104,7 +104,6 @@
def new_musicians(user, new_musicians, host='www.jamkazam.com')
@user, @new_musicians, @host = user, new_musicians, host
sendgrid_recipients([user.email])
sendgrid_substitute('@USERID', [user.id])
sendgrid_unique_args :type => "new_musicians"

View File

@ -7,7 +7,7 @@ Hi <%= @user.first_name %>,
<% link_style = "background-color:#ED3618; margin:0px 8px 0px 8px; border: solid 1px #F27861; outline: solid 2px #ED3618; padding:3px 10px; font-family:Raleway, Arial, Helvetica, sans-serif; font-size:12px; font-weight:300; cursor:pointer; color:#FC9; text-decoration:none;" %>
<p>
<table bgcolor="#242323" cellpadding="3px" cellspacing="5px">
<% @new_nearby.each do |user| %>
<% @new_musicians.each do |user| %>
<tr valign="top">
<td width="10%"><img src="http://<%= @host %>/assets/shared/avatar_generic.png" /></td>
<td width="20%"><font color="#ccc"><%= user.name %><br />
@ -24,7 +24,7 @@ Hi <%= @user.first_name %>,
<% end %>
</table>
</p>
<p>There are currently <%= @new_nearby.size%> musicians on JamKazam with low enough latency Internet connections to you to support a good online session. To see ALL the JamKazam musicians with whom you may want to connect and play, view our Musicians page at: <a href="http://www.jamkazam.com/client#/musicians">http://www.jamkazam.com/client#/musicians</a>.
<p>There are currently <%= @new_musicians.size%> musicians on JamKazam with low enough latency Internet connections to you to support a good online session. To see ALL the JamKazam musicians with whom you may want to connect and play, view our Musicians page at: <a href="http://www.jamkazam.com/client#/musicians">http://www.jamkazam.com/client#/musicians</a>.
</p>
<p>Best Regards,</p>

View File

@ -1,17 +1,17 @@
New JamKazam Musicians in your Area
New Musicians You Should Check Out
Hi <%= @user.first_name %>,
The following new musicians have joined JamKazam within the last week, and have Internet connections with low enough latency to you that you can have a good online session together. We'd suggest that you look through the new musicians listed below to see if any match your musical interests, and if so, click through to their profile page on the JamKazam website to send them a message or a request to connect as a JamKazam friend:
<% @new_nearby.each do |user| %>
<% @new_musicians.each do |user| %>
<%= user.name %> (http://<%= @host %>/client#/profile/<%= user.id %>)
<%= user.location %>
<% user.instruments.collect { |inst| inst.description }.join(', ') %>
<%= user.biography %>
<% end %>
There are currently <%= @new_nearby.size%> musicians on JamKazam with low enough latency Internet connections to you to support a good online session. To see ALL the JamKazam musicians with whom you may want to connect and play, view our Musicians page at: http://www.jamkazam.com/client#/musicians.
There are currently <%= @new_musicians.size%> musicians on JamKazam with low enough latency Internet connections to you to support a good online session. To see ALL the JamKazam musicians with whom you may want to connect and play, view our Musicians page at: http://www.jamkazam.com/client#/musicians.
Best Regards,
Team JamKazam

View File

@ -25,7 +25,7 @@
<tr>
<td><%= sess.genre.description %></td>
<td><%= sess.description %></td>
<td style="text-align:center"><%= sess.latency_store %></td>
<td style="text-align:center"><%= sess.latency %></td>
</tr>
<% end %>
</table>

View File

@ -11,7 +11,7 @@ Take a look through these new sessions below, and just click the RSVP button on
GENRE | DESCRIPTION | LATENCY
<% @sessions_and_latency.each do |sess| %>
<%= sess.genre.description %> | <%= sess.description %> | <%= sess.latency_store %>
<%= sess.genre.description %> | <%= sess.description %> | <%= sess.latency %>
<% end %>
To see ALL the scheduled sessions that you might be interested in joining, view our Find Session page at: http://www.jamkazam.com/client#/findSession.

View File

@ -9,7 +9,7 @@ module JamRuby
VAR_MUSICIAN_TABLE = "@MUSICIAN_TABLE"
TMP_NEW = 'tmp_new_musicians'
TMP_CAND = 'tmp_receiver_candidates'
TMP_RECEIVE = 'tmp_receivers'
TMP_PAIRS = 'tmp_receivers_new_musicians'
def self.subject
@ -21,77 +21,93 @@ module JamRuby
ActiveRecord::Base.connection.execute("DROP TABLE IF EXISTS #{TMP_NEW}")
sql =<<SQL
SELECT
users.id AS new_user_id, users.last_jam_locidispid AS last_jam_locidispid
users.id AS new_user_id,
users.last_jam_locidispid AS last_jam_locidispid,
users.created_at AS new_created_at
INTO TEMP TABLE #{TMP_NEW}
FROM users
WHERE
musician = 't' AND
last_jam_locidispid IS NOT NULL AND
users.musician = 't' AND
users.last_jam_locidispid IS NOT NULL AND
users.created_at > '#{time_since_last_batch(SINCE_DAYS)}'
SQL
ActiveRecord::Base.connection.execute(sql)
end
def _fetch_receiver_candidates
ActiveRecord::Base.connection.execute("DROP TABLE IF EXISTS #{TMP_CAND}")
# inserts eligible sessions to temp table
def _fetch_eligible_receivers
ActiveRecord::Base.connection.execute("DROP TABLE IF EXISTS #{TMP_RECEIVE}")
sql =<<SQL
SELECT
users.id AS receiver_candidate_id, users.last_jam_locidispid AS last_jam_locidispid
INTO TEMP TABLE #{TMP_CAND}
FROM users
FULL OUTER JOIN #{TMP_NEW} ON users.id = #{TMP_NEW}.new_user_id
rr.id AS receiver_id,
rr.created_at AS receiver_created_at
INTO TEMP TABLE #{TMP_RECEIVE}
FROM users rr
FULL OUTER JOIN #{TMP_NEW} ON #{TMP_NEW}.new_user_id = rr.id
WHERE
users.musician = 't' AND
users.subscribe_email = 't' AND
users.last_jam_locidispid IS NOT NULL AND
(#{TMP_NEW}.new_user_id IS NULL OR users.id IS NULL)
rr.musician = 't' AND
rr.subscribe_email = 't' AND
rr.last_jam_locidispid IS NOT NULL AND
(#{TMP_NEW}.new_user_id IS NULL OR rr.id IS NULL)
SQL
ActiveRecord::Base.connection.execute(sql)
end
def _fetch_eligible_receivers
def _fetch_pairs
ActiveRecord::Base.connection.execute("DROP TABLE IF EXISTS #{TMP_PAIRS}")
# load eligible recipients into tmp table
sql =<<SQL
SELECT
#{TMP_NEW}.new_user_id,
#{TMP_CAND}.receiver_candidate_id AS receiver_id,
receivers.id AS receiver_id,
scores.score AS latency
INTO TEMP TABLE #{TMP_PAIRS}
FROM scores
INNER JOIN #{TMP_CAND} ON #{TMP_CAND}.last_jam_locidispid = scores.alocidispid
INNER JOIN users AS receivers ON receivers.last_jam_locidispid = scores.alocidispid
INNER JOIN #{TMP_NEW} ON #{TMP_NEW}.last_jam_locidispid = scores.blocidispid
WHERE
scores.score < #{Score::MAX_YELLOW_LATENCY}
scores.score < #{Score::MAX_YELLOW_LATENCY} AND
receivers.id IN (
SELECT receiver_id
FROM #{TMP_RECEIVE}
)
SQL
ActiveRecord::Base.connection.execute(sql)
end
def fetch_recipients
def fetch_recipients(per_page=500)
objs = []
# load new musicians into tmp table
self._fetch_new_musicians
# load receiver candidates into tmp table
self._fetch_receiver_candidates
# load email receivers into tmp table
self._fetch_eligible_receivers
sql = "SELECT DISTINCT receiver_id FROM #{TMP_PAIRS} GROUP BY receiver_id"
ActiveRecord::Base.connection.execute(sql).each do |result|
receiver = User.find_by_id(result['receiver_id'])
# load receivers/musicians pairs into tmp table
self._fetch_pairs
sql = "SELECT new_user_id, latency FROM #{TMP_PAIRS} WHERE receiver_id = '#{receiver.id}'"
new_musicians = ActiveRecord::Base.connection.execute(sql).collect do |rr|
new_user = User.where(['id = ?',rr['new_user_id']])
.limit(1)
.includes([:instruments])
.first
new_user.latency_store = result['latency']
new_user
countsql = "SELECT COUNT(DISTINCT receiver_id) AS num FROM #{TMP_PAIRS}"
rr = ActiveRecord::Base.connection.execute(countsql)
num_pair = 0 < rr.count ? rr[0]['num'].to_i : 0
loops = (num_pair / per_page) + (num_pair % per_page) - 1
0.upto(loops) do |nn|
offset = nn * per_page
sql =<<SQL
SELECT DISTINCT receiver_id
FROM #{TMP_PAIRS}
ORDER BY receiver_id ASC
LIMIT #{per_page}
OFFSET #{offset}
SQL
ActiveRecord::Base.connection.execute(sql).each do |result|
receiver = User.find_by_id(result['receiver_id'])
new_musicians = User.select("users.*, #{TMP_PAIRS}.latency")
.joins("INNER JOIN #{TMP_PAIRS} ON #{TMP_PAIRS}.new_user_id = users.id")
.where(["#{TMP_PAIRS}.receiver_id = ?", receiver.id])
.includes(:instruments)
block_given? ? yield(receiver, new_musicians) : objs << [receiver, new_musicians]
end
block_given? ? yield(receiver, new_musicians) : objs << [receiver, new_musicians]
end
objs
end
@ -101,7 +117,7 @@ SQL
self.fetch_recipients do |user, new_musicians|
self.opt_in_count += 1
bset = EmailBatchSet.new_musician_set(self, user, new_musicians)
UserMailer.new_musicians(uu, new_musicians).deliver
UserMailer.new_musicians(user, new_musicians).deliver
end
self.sent_count = self.opt_in_count
self.save
@ -110,7 +126,7 @@ SQL
def self.send_new_musician_batch
oo = self.create
oo..deliver_batch
oo.deliver_batch
oo
end

View File

@ -5,8 +5,9 @@ module JamRuby
SINCE_DAYS = 2
MIN_HOURS_START = 2
TMP_SNAP = 'tmp_scheduled_session_snapshot'
TMP_USER = 'tmp_scheduled_session_user'
TMP_SESS = 'tmp_candidate_sessions'
TMP_RECIP = 'tmp_candidate_recipients'
TMP_MATCH = 'tmp_matches'
def self.subject
"New sessions have been scheduled that may be a good match for you!"
@ -14,22 +15,23 @@ module JamRuby
# inserts eligible sessions to temp table
def _collect_eligible_sessions
ActiveRecord::Base.connection.execute("DROP TABLE IF EXISTS #{TMP_SNAP}")
ActiveRecord::Base.connection.execute("DROP TABLE IF EXISTS #{TMP_SESS}")
sql =<<SQL
SELECT
rs.instrument_id AS instrument_id,
msess.id AS session_id,
msess.user_id AS creator_id,
users.last_jam_locidispid AS creator_score_idx
INTO TEMP TABLE #{TMP_SNAP}
msess.id AS session_id,
msess.user_id AS creator_id,
users.last_jam_locidispid AS creator_score_idx,
rs.instrument_id
INTO TEMP TABLE #{TMP_SESS}
FROM music_sessions msess
INNER JOIN users ON users.id = msess.user_id
INNER JOIN rsvp_slots AS rs ON rs.music_session_id = msess.id
LEFT JOIN rsvp_requests_rsvp_slots AS rrrs ON rrrs.rsvp_slot_id = rs.id
INNER JOIN users ON users.id = msess.user_id
WHERE
musician_access = 't' AND
approval_required = 'f' AND
msess.created_at > '#{time_since_last_batch(SINCE_DAYS)}' AND
msess.created_at < '#{self.created_at}' AND
scheduled_start >= '#{Time.now() + MIN_HOURS_START.hours}' AND
(rrrs.rsvp_slot_id IS NULL OR rrrs.chosen != 't')
SQL
@ -37,41 +39,64 @@ SQL
end
def _collect_eligible_recipients
ActiveRecord::Base.connection.execute("DROP TABLE IF EXISTS #{TMP_USER}")
ActiveRecord::Base.connection.execute("DROP TABLE IF EXISTS #{TMP_RECIP}")
# load eligible recipients into tmp table
sql =<<SQL
SELECT
users.id AS user_id,
users.last_jam_locidispid AS user_score_idx,
tmp.session_id AS session_id,
tmp.creator_id AS creator_id,
tmp.creator_score_idx AS creator_score_idx
INTO TEMP TABLE #{TMP_USER}
users.id AS receiver_id,
users.last_jam_locidispid AS receiver_score_idx
INTO TEMP TABLE #{TMP_RECIP}
FROM users
INNER JOIN musicians_instruments AS mi ON mi.user_id = users.id
LEFT JOIN #{TMP_SNAP} AS tmp ON tmp.instrument_id = mi.instrument_id
INNER JOIN #{TMP_SESS} ON #{TMP_SESS}.instrument_id = mi.instrument_id
WHERE
users.musician = 't' AND
users.subscribe_email = 't' AND
tmp.session_id IS NOT NULL
GROUP BY users.id, tmp.session_id, tmp.creator_id, tmp.creator_score_idx
users.subscribe_email = 't'
SQL
ActiveRecord::Base.connection.execute(sql)
end
def _collect_scored_recipients
ActiveRecord::Base.connection.execute("DROP TABLE IF EXISTS #{TMP_MATCH}")
sql =<<SQL
SELECT
DISTINCT #{TMP_RECIP}.receiver_id,
#{TMP_SESS}.session_id,
scores.score AS latency
INTO TEMP TABLE #{TMP_MATCH}
FROM scores
INNER JOIN #{TMP_SESS} ON #{TMP_SESS}.creator_score_idx = scores.alocidispid
INNER JOIN #{TMP_RECIP} ON #{TMP_RECIP}.receiver_score_idx = scores.blocidispid
WHERE
scores.score < #{Score::MAX_YELLOW_LATENCY} AND
#{TMP_RECIP}.receiver_id != #{TMP_SESS}.creator_id
GROUP BY
#{TMP_RECIP}.receiver_id,
#{TMP_SESS}.session_id,
latency
SQL
ActiveRecord::Base.connection.execute(sql)
end
# select recipients whose score is below minimum threshold
def _select_scored_recipients
sql =<<SQL
SELECT DISTINCT user_id, scores.score AS latency
FROM #{TMP_USER}
INNER JOIN scores ON scores.alocidispid = #{TMP_USER}.creator_score_idx AND scores.blocidispid = #{TMP_USER}.user_score_idx
WHERE
scores.score < #{Score::MAX_YELLOW_LATENCY}
def _select_scored_recipients(offset=0)
if 0 > offset
sql = "SELECT COUNT(DISTINCT receiver_id) AS num FROM #{TMP_MATCH}"
rr = ActiveRecord::Base.connection.execute(sql)
return 0 < rr.count ? rr[0]['num'].to_i : 0
else
sql =<<SQL
SELECT DISTINCT receiver_id
FROM #{TMP_MATCH}
ORDER BY receiver_id ASC
LIMIT #{@per_page}
OFFSET #{offset}
SQL
ActiveRecord::Base.connection.execute(sql)
return ActiveRecord::Base.connection.execute(sql)
end
end
def fetch_recipients
def fetch_recipients(per_page=500)
objs = []
# load eligible sessions into tmp table
@ -80,41 +105,43 @@ SQL
# load eligible mail recipients into tmp table
self._collect_eligible_recipients
# now just get the sessions/latency for each distinct mail recipient
_select_scored_recipients.each do |result|
user = User.find_by_id(result['user_id'])
# load mail recipients with minimum score into tmp table
self._collect_scored_recipients
sql = "SELECT session_id FROM #{TMP_USER} WHERE user_id = '#{user.id}'"
sessions = ActiveRecord::Base.connection.execute(sql).collect do |rr|
msess = MusicSession.where(['id = ?',rr['session_id']])
.limit(1)
@per_page = per_page
num_recip = _select_scored_recipients(-1)
loops = (num_recip / @per_page) + (num_recip % @per_page) - 1
0.upto(loops) do |nn|
offset = nn * @per_page
# now just get the sessions/latency for each distinct mail recipient
_select_scored_recipients(offset).each do |result|
receiver = User.find_by_id(result['receiver_id'])
sessions = MusicSession.select("music_sessions.*, #{TMP_MATCH}.latency")
.joins("INNER JOIN #{TMP_MATCH} ON #{TMP_MATCH}.session_id = music_sessions.id")
.where(["#{TMP_MATCH}.receiver_id = ?", receiver.id])
.includes([:genre, :creator])
.first
msess.latency_store = result['latency']
msess
block_given? ? yield(receiver, sessions) : objs << [receiver, sessions]
end
block_given? ? yield(user, sessions) : objs << [user, sessions]
end
objs
end
def deliver_batch_sets!
self.opt_in_count = 0
sent = 0
self.fetch_recipients do |receiver, sessions_and_latency|
self.opt_in_count += 1
sent += 1
bset = EmailBatchSet.scheduled_session_set(self, receiver, sessions_and_latency)
UserMailer.scheduled_session_daily(receiver, sessions_and_latency).deliver
end
self.sent_count = sent
self.sent_count = self.opt_in_count
self.save
self.did_batch_run!
end
def self.send_daily_session_batch
oo = self.create
oo..deliver_batch
oo.deliver_batch
oo
end

View File

@ -8,10 +8,7 @@ module JamRuby
RECURRING_MODES = [NO_RECURRING, RECURRING_WEEKLY]
attr_accessor :legal_terms, :recurring_mode, :language_description, :scheduled_start_time, :access_description
# used for temporary data store of latency between creator and some other user
attr_accessor :latency_store
attr_accessor :legal_terms, :language_description, :scheduled_start_time, :access_description
self.table_name = "music_sessions"
@ -65,6 +62,93 @@ module JamRuby
self.comments.size
end
# copies all relevant info for the recurring session
def copy
MusicSession.transaction do
# copy base music_session data
new_session = MusicSession.new
new_session.description = self.description
new_session.user_id = self.user_id
new_session.band_id = self.band_id
new_session.fan_access = self.fan_access
# TODO: confirm this logic
# new_session.scheduled_start = self.scheduled_start + self.scheduled_duration
new_session.scheduled_duration = self.scheduled_duration
new_session.musician_access = self.musician_access
new_session.approval_required = self.approval_required
new_session.fan_chat = self.fan_chat
new_session.genre_id = self.genre_id
new_session.legal_policy = self.legal_policy
new_session.language = self.language
new_session.name = self.name
new_session.recurring_mode = self.recurring_mode
new_session.timezone = self.timezone
new_session.open_rsvps = self.open_rsvps
# copy rsvp_slots, rsvp_requests, and rsvp_requests_rsvp_slots
RsvpSlot.find_each(:conditions => "music_session_id = '#{self.id}'") do |slot|
new_slot = RsvpSlot.new
new_slot.instrument_id = slot.instrument_id
new_slot.proficiency_level = slot.proficiency_level
new_session.rsvp_slots << new_slot
# get the request for this slot that was approved (should only be ONE)
rsvp_request_slot = RsvpRequestRsvpSlot.where("chosen = true AND rsvp_slot_id = ?", slot.id).first
unless rsvp_request_slot.nil?
rsvp = RsvpRequest.find_by_id(rsvp_request_slot.rsvp_request_id)
new_rsvp = RsvpRequest.new
new_rsvp.user_id = rsvp.user_id
new_rsvp_req_slot = RsvpRequestRsvpSlot.new
new_rsvp_req_slot.rsvp_request = new_rsvp
new_rsvp_req_slot.rsvp_slot = new_slot
new_rsvp_req_slot.chosen = true
# if this slot was not chosen, try to get any RSVPs that were 1-time cancellations and copy those
else
rejected_req_slots = RsvpRequestRsvpSlot.where("(chosen = false OR chosen is null) AND rsvp_slot_id = ?", slot.id).order("created_at ASC")
rejected_req_slots.each do |req_slot|
# get RsvpRequest corresponding to this RsvpRequestRsvpSlot
rsvp = RsvpRequest.find_by_id(req_slot.rsvp_request_id)
# if the RSVP was canceled (but all future sessions were NOT canceled), then copy this one and break
if rsvp.canceled && !rsvp.cancel_all
new_rsvp = RsvpRequest.new
new_rsvp.user_id = rsvp.user_id
new_rsvp_req_slot = RsvpRequestRsvpSlot.new
new_rsvp_req_slot.rsvp_request = new_rsvp
new_rsvp_req_slot.rsvp_slot = new_slot
new_rsvp_req_slot.chosen = true
break
end
end
end
end
# copy music_notations
MusicNotation.find_each(:conditions => "music_session_id = '#{self.id}'") do |notation|
new_notation = MusicNotation.new
new_notation.user_id = notation.user_id
new_notation.music_session = new_session
new_notation.file_url = notation.file_url
# new_notation.file_name = notation.file_name
new_notation.size = notation.size
new_session.music_notations << new_notation
end
new_session.save
# mark the next session as scheduled
self.next_session_scheduled = true
self.save
end
end
def grouped_tracks
tracks = []
self.music_session_user_histories.each do |msuh|

View File

@ -39,18 +39,18 @@ module JamRuby
raise StateError, "Invalid session."
end
# verify invitation exists for this user and session
invitation = Invitation.where("music_session_id = ? AND receiver_id = ?", music_session.id, user.id)
if invitation.blank? && !music_session.open_rsvps
raise PermissionError, "Only a session invitee can create an RSVP for this session."
end
# verify slot IDs exist in request
if params[:rsvp_slots].blank?
raise StateError, "You must select at least 1 slot."
end
# verify invitation exists for this user and session
invitation = Invitation.where("music_session_id = ? AND receiver_id = ?", music_session.id, user.id)
if invitation.first.nil? && !music_session.open_rsvps
raise PermissionError, "Only a session invitee can create an RSVP for this session."
end
RsvpRequest.transaction do
@rsvp = RsvpRequest.new
@rsvp.user = user

View File

@ -19,9 +19,6 @@ module JamRuby
# updating_password corresponds to a lost_password
attr_accessor :updating_password, :updating_email, :updated_email, :update_email_confirmation_url, :administratively_created, :current_password, :setting_password, :confirm_current_password, :updating_avatar, :updating_progression_field, :mods_json
# used for temporary data store of latency between self and some other user
attr_accessor :latency_store
belongs_to :icecast_server_group, class_name: "JamRuby::IcecastServerGroup", inverse_of: :users, foreign_key: 'icecast_server_group_id'
# authorizations (for facebook, etc -- omniauth)

View File

@ -0,0 +1,39 @@
require 'json'
require 'resque'
require 'resque-retry'
require 'net/http'
require 'digest/md5'
module JamRuby
class MusicSessionScheduler
extend Resque::Plugins::LonelyJob
@queue = :music_session_scheduler
@@log = Logging.logger[MusicSessionScheduler]
def self.lock_timeout
120
end
def self.perform
@@log.debug("waking up")
JamWebEventMachine.run_wait_stop do
MusicSessionScheduler.new.run
end
@@log.debug("done")
end
def run
# get all weekly sessions that have ended in the last 15 minutes
criteria = "recurring_mode = 'weekly' AND session_removed_at is not null AND next_session_scheduled = false"
MusicSession.find_each(:conditions => criteria) do |music_session|
music_session.copy
end
end
end
end

View File

@ -93,6 +93,7 @@ FactoryGirl.define do
recurring_mode 'once'
genre JamRuby::Genre.first
association :creator, :factory => :user
open_rsvps false
factory :recurring_music_session_weekly do
recurring_mode 'weekly'
@ -476,21 +477,12 @@ FactoryGirl.define do
end
factory :rsvp_slot, class: JamRuby::RsvpSlot do
association :instrument, factory: :instrument
association :music_session, factory: :music_session
# association :rsvp_request_slot, factory: :rsvp_request_slot
proficiency_level 'beginner'
end
factory :rsvp_request, class: JamRuby::RsvpRequest do
association :user, factory: :user
association :rsvp_slot, factory: :rsvp_slot
association :rsvp_request_slot, factory: :rsvp_request_slot
canceled false
end
factory :rsvp_request_slot, class: JamRuby::RsvpRequestRsvpSlot do
chosen false
cancel_all false
end
factory :latency_tester, :class => JamRuby::LatencyTester do

View File

@ -15,49 +15,93 @@ describe EmailBatchNewMusician do
let (:new_musician_batch) { FactoryGirl.create(:email_batch_new_musician) }
let (:receiver) {
let (:receiver_date) { Time.now - (EmailBatchNewMusician::SINCE_DAYS.days + 1.day) }
let (:receiver1) {
FactoryGirl.create(:user,
:created_at => Time.now - (EmailBatchNewMusician::SINCE_DAYS.days + 1.day),
:created_at => receiver_date,
:last_jam_locidispid => 1,
:last_jam_addr => 1
)
}
let (:receiver2) {
FactoryGirl.create(:user,
:created_at => receiver_date,
:last_jam_locidispid => 3,
:last_jam_addr => 3
)
}
let (:drummer) { FactoryGirl.create(:user, :last_jam_locidispid => 1, :last_jam_addr => 1) }
let (:guitarist) { FactoryGirl.create(:user, :last_jam_locidispid => 1, :last_jam_addr => 1) }
let (:bassist) { FactoryGirl.create(:user, :last_jam_locidispid => 1, :last_jam_addr => 1) }
let (:vocalist) { FactoryGirl.create(:user, :last_jam_locidispid => 1, :last_jam_addr => 1) }
let (:loser) { FactoryGirl.create(:user, :last_jam_locidispid => 2, :last_jam_addr => 2) }
let (:drummer3) { FactoryGirl.create(:user, :last_jam_locidispid => 3, :last_jam_addr => 3) }
let (:guitarist3) { FactoryGirl.create(:user, :last_jam_locidispid => 3, :last_jam_addr => 3) }
let (:bassist3) { FactoryGirl.create(:user, :last_jam_locidispid => 3, :last_jam_addr => 3) }
let (:vocalist3) { FactoryGirl.create(:user, :last_jam_locidispid => 3, :last_jam_addr => 3) }
let (:drummer) { FactoryGirl.create(:user,
:last_jam_locidispid => 1,
:last_jam_addr => 1) }
let (:guitarist) { FactoryGirl.create(:user,
:last_jam_locidispid => 1,
:last_jam_addr => 1) }
let (:bassist) { FactoryGirl.create(:user,
:last_jam_locidispid => 1,
:last_jam_addr => 1) }
let (:vocalist) { FactoryGirl.create(:user,
:last_jam_locidispid => 1,
:last_jam_addr => 1) }
let (:loser) { FactoryGirl.create(:user,
:last_jam_locidispid => 2,
:last_jam_addr => 2) }
before(:each) do
drummer; guitarist; bassist; vocalist; loser
drummer3; guitarist3; bassist3; vocalist3
receiver1; receiver2
new_musician_batch.reset!
JamRuby::Score.delete_all
JamRuby::Score.createx(1, 'a', 1, 1, 'a', 1, 10)
JamRuby::Score.createx(1, 'a', 1, 2, 'a', 2, Score::MAX_YELLOW_LATENCY + 1)
end
it 'sets up data properly' do
receiver; drummer; loser; vocalist
results = new_musician_batch.fetch_recipients
expect(results.count).to eq(1)
user, new_musicians = results[0]
expect(user.id).to eq(receiver.id)
expect(new_musicians.count).to eq(2)
expect(user.id).to eq(receiver1.id)
expect(new_musicians.count).to eq(4)
end
it 'sends email' do
pending
ebatch = new_musician_batch
ebatch.deliver_batch
expect(UserMailer.deliveries.length).to eq(3)
new_musician_batch.deliver_batch
expect(UserMailer.deliveries.length).to eq(1)
end
it 'sends email periodically' do
EmailBatchNewMusician.send_new_musician_batch
expect(UserMailer.deliveries.length).to eq(1)
end
it 'handles multiple receivers' do
JamRuby::Score.createx(1, 'a', 1, 3, 'a', 3, 10)
JamRuby::Score.createx(1, 'a', 1, 4, 'a', 4, 10)
JamRuby::Score.createx(2, 'a', 2, 4, 'a', 4, 10)
results = new_musician_batch.fetch_recipients
expect(results.count).to eq(2)
user, new_musicians = results.detect { |rr| rr[0].id == receiver1.id }
expect(new_musicians.count).to eq(8)
user, new_musicians = results.detect { |rr| rr[0].id == receiver2.id }
expect(new_musicians.count).to eq(4)
end
it 'handles large batches' do
dd = receiver_date + 1.day
20.downto(1) do |nn|
FactoryGirl.create(:user, :last_jam_locidispid => 5, :last_jam_addr => 5, :created_at => dd)
end
10.downto(1) do |nn|
FactoryGirl.create(:user, :last_jam_locidispid => 6, :last_jam_addr => 6)
end
JamRuby::Score.delete_all
JamRuby::Score.createx(5, 'a', 5, 6, 'a', 6, 10)
JamRuby::Score.createx(5, 'a', 5, 7, 'a', 7, Score::MAX_YELLOW_LATENCY + 1)
FactoryGirl.create(:user, :last_jam_locidispid => 8, :last_jam_addr => 8, :created_at => dd)
FactoryGirl.create(:user, :last_jam_locidispid => 7, :last_jam_addr => 7)
receivers = []
new_musician_batch.fetch_recipients do |uu, newm|
receivers << uu
expect(newm.count).to eq(10)
end
expect(receivers.count).to eq(User.where(["created_at <= ? AND last_jam_addr = ?",dd,5]).count)
end
end

View File

@ -20,41 +20,34 @@ describe EmailBatchScheduledSessions do
let (:bass) { FactoryGirl.create(:instrument, :description => 'bass') }
let (:vocals) { FactoryGirl.create(:instrument, :description => 'vocal') }
let (:drummer) { FactoryGirl.create(:user,
:last_jam_locidispid => 1,
:last_jam_addr => 1) }
let (:guitarist) { FactoryGirl.create(:user,
:last_jam_locidispid => 1,
:last_jam_addr => 1) }
let (:bassist) { FactoryGirl.create(:user,
:last_jam_locidispid => 1,
:last_jam_addr => 1) }
let (:vocalist) { FactoryGirl.create(:user,
:last_jam_locidispid => 1,
:last_jam_addr => 1) }
let (:loser) { FactoryGirl.create(:user,
:last_jam_locidispid => 2,
:last_jam_addr => 2) }
let (:drummer) { FactoryGirl.create(:user, :last_jam_locidispid => 1, :last_jam_addr => 1) }
let (:guitarist) { FactoryGirl.create(:user, :last_jam_locidispid => 1, :last_jam_addr => 1) }
let (:bassist) { FactoryGirl.create(:user, :last_jam_locidispid => 1, :last_jam_addr => 1) }
let (:vocalist) { FactoryGirl.create(:user, :last_jam_locidispid => 1, :last_jam_addr => 1) }
let (:loser) { FactoryGirl.create(:user, :last_jam_locidispid => 2, :last_jam_addr => 2) }
let (:session1) do
FactoryGirl.create(:music_session,
:creator => drummer,
:scheduled_start => Time.now() + 2.days,
:musician_access => true,
:approval_required => false)
:approval_required => false,
:created_at => Time.now - 1.hour)
end
let (:session2) do
FactoryGirl.create(:music_session,
:creator => drummer,
:scheduled_start => Time.now() + 2.days,
:musician_access => true,
:approval_required => false)
:approval_required => false,
:created_at => Time.now - 1.hour)
end
before(:each) do
MusicianInstrument.delete_all
RsvpSlot.delete_all
JamRuby::Score.delete_all
scheduled_batch.reset!
drummer.musician_instruments << FactoryGirl.build(:musician_instrument, user: drummer, instrument: drums, proficiency_level: 2)
drummer.musician_instruments << FactoryGirl.build(:musician_instrument, user: drummer, instrument: guitar, proficiency_level: 2)
@ -73,7 +66,6 @@ describe EmailBatchScheduledSessions do
FactoryGirl.create(:rsvp_slot, :instrument => drums, :music_session => session1)
FactoryGirl.create(:rsvp_slot, :instrument => guitar, :music_session => session1)
FactoryGirl.create(:rsvp_slot, :instrument => bass, :music_session => session1)
FactoryGirl.create(:rsvp_slot, :instrument => drums, :music_session => session2)
FactoryGirl.create(:rsvp_slot, :instrument => guitar, :music_session => session2)
FactoryGirl.create(:rsvp_slot, :instrument => bass, :music_session => session2)
@ -82,24 +74,54 @@ describe EmailBatchScheduledSessions do
# oo = FactoryGirl.create(:rsvp_request, :user => vocalist, :rsvp_slot => oo)
# oo.rsvp_request_slot.update_attributes(chosen: true)
JamRuby::Score.createx(1, 'a', 1, 1, 'a', 1, 10)
JamRuby::Score.createx(1, 'a', 1, 2, 'a', 2, Score::MAX_YELLOW_LATENCY + 1)
end
before(:each) do
end
it 'sets up data properly' do
JamRuby::Score.createx(1, 'a', 1, 1, 'a', 1, 10)
JamRuby::Score.createx(1, 'a', 1, 2, 'a', 2, Score::MAX_YELLOW_LATENCY + 1)
expect(drummer.instruments.include?(drums)).to eq(true)
expect(drummer.instruments.include?(guitar)).to eq(true)
obj = scheduled_batch.fetch_recipients
expect(obj.count).to eq(3)
expect(obj.count).to eq(2)
scheduled_batch.deliver_batch
expect(UserMailer.deliveries.length).to eq(2)
end
it 'sends email' do
ebatch = scheduled_batch
ebatch.deliver_batch
expect(UserMailer.deliveries.length).to eq(3)
it 'handles large batches' do
creators = []
8.downto(1) do |nn|
creators << uu = FactoryGirl.create(:user, :last_jam_locidispid => 5, :last_jam_addr => 5)
msess = FactoryGirl.create(:music_session,
:creator => uu,
:scheduled_start => Time.now() + 2.days,
:musician_access => true,
:approval_required => false,
:created_at => Time.now - 1.hour)
FactoryGirl.create(:rsvp_slot, :instrument => drums, :music_session => msess)
FactoryGirl.create(:rsvp_slot, :instrument => guitar, :music_session => msess)
FactoryGirl.create(:rsvp_slot, :instrument => bass, :music_session => msess)
end
instruments = [drums, guitar, bass]
4.downto(1) do |nn|
uu = FactoryGirl.create(:user, :last_jam_locidispid => 6, :last_jam_addr => 6)
uu.musician_instruments << FactoryGirl.build(:musician_instrument,
user: uu,
instrument: instruments.sample,
proficiency_level: 2)
end
JamRuby::Score.createx(5, 'a', 5, 6, 'a', 6, 10)
JamRuby::Score.createx(5, 'a', 5, 7, 'a', 7, Score::MAX_YELLOW_LATENCY + 1)
FactoryGirl.create(:user, :last_jam_locidispid => 8, :last_jam_addr => 8)
FactoryGirl.create(:user, :last_jam_locidispid => 7, :last_jam_addr => 7)
receivers = []
scheduled_batch.fetch_recipients(3) do |receiver, sessions|
receivers << receiver
expect(sessions.count).to eq(8)
end
expect(receivers.count).to eq(4)
end
end

View File

@ -2,7 +2,162 @@ require 'spec_helper'
describe RsvpRequest do
it "success" do
# FactoryGirl.create(:rsvp_request)
before(:each) do
RsvpRequestRsvpSlot.delete_all
RsvpRequest.delete_all
RsvpSlot.delete_all
Invitation.delete_all
MusicSession.delete_all
User.delete_all
@session_invitee = FactoryGirl.create(:user)
@session_invitee.save
@non_session_invitee = FactoryGirl.create(:user)
@non_session_invitee.save
@session_creator = FactoryGirl.create(:user)
@session_creator.save
# session invitations require sender and receiver to be friends
FactoryGirl.create(:friendship, :user => @session_invitee, :friend => @session_creator)
FactoryGirl.create(:friendship, :user => @session_creator, :friend => @session_invitee)
@music_session = FactoryGirl.build(:music_session, :creator => @session_creator)
@music_session.save
@slot1 = FactoryGirl.build(:rsvp_slot, :music_session => @music_session, :instrument => JamRuby::Instrument.find('electric guitar'))
@slot1.save
@slot2 = FactoryGirl.build(:rsvp_slot, :music_session => @music_session, :instrument => JamRuby::Instrument.find('drums'))
@slot2.save
@invitation = FactoryGirl.build(:invitation, :sender => @session_creator, :receiver => @session_invitee, :music_session => @music_session)
@invitation.save
end
describe "create" do
it "should require a valid music session" do
expect {RsvpRequest.create({:session_id => "1234", :rsvp_slots => [@slot1.id, @slot2.id]}, @session_invitee)}.to raise_error(JamRuby::StateError)
end
it "should require at least 1 slot" do
expect {RsvpRequest.create({:session_id => @music_session.id}, @session_invitee)}.to raise_error(JamRuby::StateError)
end
it "should not allow user to RSVP for slot he has already RSVPed to" do
# allow open RSVPs
@music_session.open_rsvps = true
@music_session.save
RsvpRequest.create({:session_id => @music_session.id, :rsvp_slots => [@slot1.id, @slot2.id]}, @non_session_invitee)
expect {RsvpRequest.create({:session_id => @music_session.id, :rsvp_slots => [@slot1.id, @slot2.id]}, @non_session_invitee)}.to raise_error(JamRuby::StateError)
end
it "should allow invitee to RSVP to session with closed RSVPs" do
rsvp = RsvpRequest.create({:session_id => @music_session.id, :rsvp_slots => [@slot1.id, @slot2.id], :message => "Let's Jam!"}, @session_invitee)
# verify comment
# verify 2 notifications were created
end
it "should allow non-invitee to RSVP to session with open RSVPs" do
# allow open RSVPs
@music_session.open_rsvps = true
@music_session.save
expect {RsvpRequest.create({:session_id => @music_session.id, :rsvp_slots => [@slot1.id, @slot2.id]}, @non_session_invitee)}.to_not raise_error
# verify notification was created
n = Notification.find_by_source_user_id(@non_session_invitee.id)
n.description.should == NotificationTypes::SCHEDULED_SESSION_RSVP
end
it "should not allow user to RSVP to slot that has already been accepted" do
# allow open RSVPs
@music_session.open_rsvps = true
@music_session.save
rsvp = RsvpRequest.create({:session_id => @music_session.id, :rsvp_slots => [@slot1.id, @slot2.id]}, @non_session_invitee)
request_slots = RsvpRequestRsvpSlot.all
# accept 1 of the slots
rs1 = RsvpRequestRsvpSlot.find_by_rsvp_slot_id(@slot1.id)
rs2 = RsvpRequestRsvpSlot.find_by_rsvp_slot_id(@slot2.id)
RsvpRequest.update({:id => rsvp.id, :session_id => @music_session.id, :rsvp_responses => [{:request_slot_id => rs1.id, :accept => true}, {:request_slot_id => rs2.id, :accept => false}]}, @session_creator)
# attempt to create a request for the already accepted slot
expect {RsvpRequest.create({:session_id => @music_session.id, :rsvp_slots => [rs1.id]}, @non_session_invitee)}.to raise_error(JamRuby::StateError)
end
it "should not allow non-invitee to RSVP to session with closed RSVPs" do
expect {RsvpRequest.create({:session_id => @music_session.id, :rsvp_slots => [@slot1.id, @slot2.id]}, @non_session_invitee)}.to raise_error(JamRuby::PermissionError)
end
end
describe "index" do
it "should allow retrieval of RSVPs by session" do
# allow open RSVPs
@music_session.open_rsvps = true
@music_session.save
user2 = FactoryGirl.create(:user)
RsvpRequest.create({:session_id => @music_session.id, :rsvp_slots => [@slot1.id, @slot2.id], :message => "Let's Jam!"}, @non_session_invitee)
RsvpRequest.create({:session_id => @music_session.id, :rsvp_slots => [@slot1.id], :message => "Let's Jam!"}, user2)
rsvps = RsvpRequest.index(@music_session)
rsvps.count.should == 2
end
it "should allow retrieval of RSVPs by session and user" do
# allow open RSVPs
@music_session.open_rsvps = true
@music_session.save
user2 = FactoryGirl.create(:user)
RsvpRequest.create({:session_id => @music_session.id, :rsvp_slots => [@slot1.id, @slot2.id], :message => "Let's Jam!"}, @non_session_invitee)
RsvpRequest.create({:session_id => @music_session.id, :rsvp_slots => [@slot1.id], :message => "Let's Jam!"}, user2)
rsvps = RsvpRequest.index(@music_session, @non_session_invitee)
rsvps.count.should == 1
end
end
describe "update" do
it "should only allow session organizer to approve request" do
# attempt to approve with non-organizer
# approve with organizer
# verify notification was created
end
it "should not allow approval of RSVP for a slot that has already been approved" do
end
end
describe "cancel" do
it "should allow session organizer to cancel" do
end
it "should allow RSVP creator to cancel" do
# test comment
# verify notification was created
end
it "should not allow anyone else to cancel" do
end
it "should allow user to cancel a single session" do
end
it "should allow user to cancel all future sessions" do
end
end
end

View File

@ -80,7 +80,7 @@ gem 'iso-639'
gem 'language_list'
group :development, :test do
gem 'rspec-rails'
gem 'rspec-rails', "2.99.0"
gem "activerecord-import", "~> 0.4.1"
gem 'guard-rspec', '0.5.5'
gem 'jasmine', '1.3.1'

View File

@ -5,19 +5,17 @@
context.JK = context.JK || {};
context.JK.FindSessionScreen = function (app) {
var CATEGORY = {
INVITATION: {index: 0, id: "table#sessions-invitations"},
FRIEND: {index: 1, id: "table#sessions-friends"},
OTHER: {index: 2, id: "table#sessions-other"}
ACTIVE: {index: 0, id: "table#sessions-active"},
SCHEDULED: {index: 1, id: "table#sessions-scheduled"}
};
var logger = context.JK.logger;
var rest = context.JK.Rest();
var sessionLatency;
var sessions = {};
var invitationSessionGroup = {};
var friendSessionGroup = {};
var otherSessionGroup = {};
var sessionCounts = [0, 0, 0];
var activeSessionGroup = {};
var scheduledSessionGroup = {};
var sessionCounts = [0, 0];
var sessionList;
var currentQuery = defaultQuery();
var currentPage = 0;
@ -105,47 +103,33 @@
function refreshDisplay() {
var priorVisible;
var INVITATION = 'div#sessions-invitations';
var FRIEND = 'div#sessions-friends';
var OTHER = 'div#sessions-other';
var ACTIVE = 'div#sessions-active';
var SCHEDULED = 'div#sessions-scheduled';
// INVITATION
//logger.debug("sessionCounts[CATEGORY.INVITATION.index]=" + sessionCounts[CATEGORY.INVITATION.index]);
if (sessionCounts[CATEGORY.INVITATION.index] === 0) {
// ACTIVE
//logger.debug("sessionCounts[CATEGORY.ACTIVE.index]=" + sessionCounts[CATEGORY.ACTIVE.index]);
if (sessionCounts[CATEGORY.ACTIVE.index] === 0) {
priorVisible = false;
$(INVITATION).hide();
$(ACTIVE).hide();
}
else {
priorVisible = true;
$(INVITATION).show();
$(ACTIVE).show();
}
// FRIEND
if (!priorVisible) {
$(FRIEND).removeClass('mt35');
$(SCHEDULED).removeClass('mt35');
}
//logger.debug("sessionCounts[CATEGORY.FRIEND.index]=" + sessionCounts[CATEGORY.FRIEND.index]);
if (sessionCounts[CATEGORY.FRIEND.index] === 0) {
//logger.debug("sessionCounts[CATEGORY.SCHEDULED.index]=" + sessionCounts[CATEGORY.SCHEDULED.index]);
if (sessionCounts[CATEGORY.SCHEDULED.index] === 0) {
priorVisible = false;
$(FRIEND).hide();
$(SCHEDULED).hide();
}
else {
priorVisible = true;
$(FRIEND).show();
}
// OTHER
if (!priorVisible) {
$(OTHER).removeClass('mt35');
}
//logger.debug("sessionCounts[CATEGORY.OTHER.index]=" + sessionCounts[CATEGORY.OTHER.index]);
if (sessionCounts[CATEGORY.OTHER.index] === 0) {
$(OTHER).hide();
}
else {
$(OTHER).show();
$(SCHEDULED).show();
}
}
@ -272,9 +256,9 @@
* of the renderSession method without having to do
* as much heavy setup.
*/
function setSession(session) {
invitationSessionGroup[session.id] = session;
}
// function setSession(session) {
// invitationSessionGroup[session.id] = session;
// }
/**
* Render a single session line into the table.
@ -285,16 +269,12 @@
// store session in the appropriate bucket and increment category counts
var session = sessions[sessionId];
if (containsInvitation(session)) {
invitationSessionGroup[sessionId] = session;
sessionCounts[CATEGORY.INVITATION.index]++;
activeSessionGroup[sessionId] = session;
sessionCounts[CATEGORY.ACTIVE.index]++;
}
else if (containsFriend(session)) {
friendSessionGroup[sessionId] = session;
sessionCounts[CATEGORY.FRIEND.index]++;
}
else {
otherSessionGroup[sessionId] = session;
sessionCounts[CATEGORY.OTHER.index]++;
scheduledSessionGroup[sessionId] = session;
sessionCounts[CATEGORY.SCHEDULED.index]++;
}
// hack to prevent duplicate rows from being rendered when filtering
@ -303,25 +283,18 @@
logger.debug('Rendering session ID = ' + sessionId);
if (invitationSessionGroup[sessionId] != null) {
$tbGroup = $(CATEGORY.INVITATION.id);
if (activeSessionGroup[sessionId] != null) {
$tbGroup = $(CATEGORY.ACTIVE.id);
if ($("table#sessions-invitations tr[id='" + sessionId + "']").length > 0) {
if ($("table#sessions-active tr[id='" + sessionId + "']").length > 0) {
sessionAlreadyRendered = true;
}
}
else if (friendSessionGroup[sessionId] != null) {
else if (scheduledSessionGroup[sessionId] != null) {
;
$tbGroup = $(CATEGORY.FRIEND.id);
$tbGroup = $(CATEGORY.SCHEDULED.id);
if ($("table#sessions-friends tr[id='" + sessionId + "']").length > 0) {
sessionAlreadyRendered = true;
}
}
else if (otherSessionGroup[sessionId] != null) {
$tbGroup = $(CATEGORY.OTHER.id);
if ($("table#sessions-other tr[id='" + sessionId + "']").length > 0) {
if ($("table#sessions-scheduled tr[id='" + sessionId + "']").length > 0) {
sessionAlreadyRendered = true;
}
}
@ -359,16 +332,14 @@
currentPage = 0;
$noMoreSessions.hide();
$scroller.infinitescroll('resume');
$('table#sessions-invitations').children(':not(:first-child)').remove();
$('table#sessions-friends').children(':not(:first-child)').remove();
$('table#sessions-other').children(':not(:first-child)').remove();
$('table#sessions-active').children(':not(:first-child)').remove();
$('table#sessions-scheduled').children(':not(:first-child)').remove();
sessionCounts = [0, 0, 0];
sessionCounts = [0, 0];
sessions = {};
invitationSessionGroup = {};
friendSessionGroup = {};
otherSessionGroup = {};
activeSessionGroup = {};
scheduledSessionGroup = {};
}
function deleteSession(evt) {
@ -480,7 +451,7 @@
this.afterShow = afterShow;
// Following exposed for easier testing.
this.setSession = setSession;
// this.setSession = setSession;
this.clearResults = clearResults;
this.getCategoryEnum = getCategoryEnum;

View File

@ -50,14 +50,28 @@
var template = $('#template-hover-session').html();
var sessionPageUrl = "/sessions/" + response.id;
var sessionPageLinkText = "WEB PAGE";
// if session hasn't begun, it must be a scheduled session so link to SESSION INFO page
if (!response.active_music_session && !response.session_removed_at) {
sessionPageUrl += "/details";
sessionPageLinkText = "SESSION DETAILS";
}
var sessionHtml = context.JK.fillTemplate(template, {
musicSessionId: response.id,
name: response.name,
description: response.description,
genre: response.genres.toUpperCase(),
genre: response.genre_id.toUpperCase(),
comment_count: response.comment_count,
like_count: response.like_count,
created_at: $.timeago(response.created_at),
musicians: musicianHtml
musicians: musicianHtml,
url: sessionPageUrl,
externalLinkText: sessionPageLinkText,
start_time: response.scheduled_start,
recurrence: response.recurring_mode === 'weekly' ? 'Recurs weekly on this day at this time' : ''
});
$(hoverSelector).append('<h2>Session Detail</h2>' + sessionHtml);

View File

@ -138,11 +138,17 @@
}
function getInvitedFriends() {
return invitedFriendNames;
return invitedFriends;
}
this.getInvitedFriends = getInvitedFriends;
function getInvitedFriendNames() {
return invitedFriendNames;
}
this.getInvitedFriendNames = getInvitedFriendNames;
function removeInvitation(evt) {
var idx = invitedFriends.indexOf($(evt.currentTarget).parent().attr('user-id'));
if (0 <= idx) {

View File

@ -56,6 +56,19 @@
});
}
function uploadMusicNotations(formData) {
return $.ajax({
type: "POST",
processData: false,
contentType: false,
dataType: "json",
cache: false,
async: false,
url: "/api/music_notations",
data: formData
});
}
function legacyJoinSession(options) {
var sessionId = options["session_id"];
delete options["session_id"];
@ -1114,6 +1127,7 @@
this.initialize = initialize;
this.legacyCreateSession = legacyCreateSession;
this.createScheduledSession = createScheduledSession;
this.uploadMusicNotations = uploadMusicNotations;
this.legacyJoinSession = legacyJoinSession;
this.joinSession = joinSession;
this.getUserDetail = getUserDetail;

View File

@ -214,6 +214,7 @@
var notificationHtml = context.JK.fillTemplate(template, {
notificationId: val.notification_id,
sessionId: val.session_id,
hoveraction: val.session_id ? "session" : "",
avatar_url: context.JK.resolveAvatarUrl(val.photo_url),
text: val.formatted_msg,
date: $.timeago(val.created_at)
@ -358,6 +359,43 @@
moreTextLink.hide();
}
}
else if (type === context.JK.MessageType.SCHEDULED_SESSION_INVITATION) {
linkSessionInfoNotification(payload, $notification, $btnNotificationAction);
}
else if (type === context.JK.MessageType.SCHEDULED_SESSION_RSVP) {
linkSessionInfoNotification(payload, $notification, $btnNotificationAction);
}
else if (type === context.JK.MessageType.SCHEDULED_SESSION_RSVP_APPROVED) {
linkSessionInfoNotification(payload, $notification, $btnNotificationAction);
}
else if (type === context.JK.MessageType.SCHEDULED_SESSION_RSVP_CANCELLED) {
linkSessionInfoNotification(payload, $notification, $btnNotificationAction);
}
else if (type === context.JK.MessageType.SCHEDULED_SESSION_RSVP_CANCELLED_ORG) {
linkSessionInfoNotification(payload, $notification, $btnNotificationAction);
}
else if (type === context.JK.MessageType.SCHEDULED_SESSION_CANCELLED) {
linkSessionInfoNotification(payload, $notification, $btnNotificationAction);
}
else if (type === context.JK.MessageType.SCHEDULED_SESSION_RESCHEDULED) {
linkSessionInfoNotification(payload, $notification, $btnNotificationAction);
}
else if (type === context.JK.MessageType.SCHEDULED_SESSION_REMINDER) {
linkSessionInfoNotification(payload, $notification, $btnNotificationAction);
}
else if (type === context.JK.MessageType.SCHEDULED_SESSION_COMMENT) {
linkSessionInfoNotification(payload, $notification, $btnNotificationAction);
}
context.JK.bindHoverEvents($("#sidebar-div"));
}
function linkSessionInfoNotification(payload, $notification, $btnNotificationAction) {
var $action_btn = $notification.find($btnNotificationAction);
$action_btn.text('SESSION DETAILS');
$action_btn.click(function() {
context.JK.popExternalLink('/sessions/' + payload.session_id + '/details');
});
}
function acceptBandInvitation(args) {
@ -1110,6 +1148,7 @@
var notificationHtml = context.JK.fillTemplate(template, {
notificationId: payload.notification_id,
sessionId: payload.session_id,
hoveraction: payload.session_id ? "session" : "",
avatar_url: context.JK.resolveAvatarUrl(payload.photo_url),
text: payload.msg instanceof jQuery ? payload.msg.html() : payload.msg ,
date: $.timeago(payload.created_at)

View File

@ -41,12 +41,6 @@
// Step4 layout
var $policyTypes = null;
var sessionStep1 = null;
var sessionStep2 = null;
var sessionStep3 = null;
var sessionStep4 = null;
var sessionStep5 = null;
var TOTAL_STEPS = 5;
var STEP_SELECT_TYPE = 0;
var STEP_SELECT_PLAYING = 1;
@ -171,7 +165,7 @@
var sessionNotations = [];
for (var i = 0; i < createSessionSettings.notations.length; i++) {
var name = createSessionSettings.notations.item(i).name;
var name = createSessionSettings.notations.filename;
sessionNotations.push(name);
}
$('#session-notations-disp').html(sessionNotations.join(', '));
@ -179,7 +173,7 @@
$('#session-language-disp').html(createSessionSettings.language.label);
var sessionInvited = [];
var invitedFriends = inviteMusiciansUtil.getInvitedFriends();
var invitedFriends = inviteMusiciansUtil.getInvitedFriendNames();
$.each(invitedFriends, function(index, friend) {
sessionInvited.push(friend);
});
@ -219,9 +213,9 @@
function beforeMoveStep1() {
if (createSessionSettings.createType == 'start-scheduled') {
var session = scheduledSessions[createSessionSettings.selectedSessionId];
createSessionSettings.startDate = new Date(session.scheduled_start).toDateString();
createSessionSettings.startDate = new Date(session.scheduled_start_time).toDateString();
createSessionSettings.startTime = getFormattedTime(new Date(session.scheduled_start), false);
createSessionSettings.genresValues = [session.genre.description];
createSessionSettings.genresValues = session.genres;
createSessionSettings.genres = [session.genre_id];
createSessionSettings.timezone.label = session.timezone_description;
createSessionSettings.timezone.value = session.timezone;
@ -233,6 +227,7 @@
createSessionSettings.session_policy = session.legal_policy;
createSessionSettings.musician_access.label = session.musician_access_description;
createSessionSettings.fans_access.label = session.fan_access_description;
createSessionSettings.recurring_mode.value = session.recurring_mode;
}
else if (createSessionSettings.createType == 'quick-start') {
createSessionSettings.genresValues = ['Pop'];
@ -249,6 +244,8 @@
createSessionSettings.musician_access.value = "only-rsvp";
createSessionSettings.fans_access.label = "Fans may not listen to session";
createSessionSettings.fans_access.value = "no-listen-chat";
createSessionSettings.recurring_mode.label = 'Not Recurring';
createSessionSettings.recurring_mode.value = 'once';
}
else {
createSessionSettings.startDate = $('#session-start-date').val();
@ -303,18 +300,46 @@
$('#divSessionGenre').removeClass("error");
}
createSessionSettings.genres = genres;
createSessionSettings.genresValues = genresValues;
createSessionSettings.name = name;
createSessionSettings.description = description;
createSessionSettings.notations = $('#session-step-2 #session-select-files').get(0).files;
if (isValid) {
createSessionSettings.genres = genres;
createSessionSettings.genresValues = genresValues;
createSessionSettings.name = name;
createSessionSettings.description = description;
createSessionSettings.notations = $('#session-step-2 #session-select-files').get(0).files;
if (createSessionSettings.notations.length > 0) {
var formData = new FormData();
$.each(createSessionSettings.notations, function(i, file) {
formData.append('files[]', file);
});
formData.append('client_id', app.clientId);
rest.uploadMusicNotations(formData)
.done(function(response) {
var error_files = [];
$.each(response, function(i, music_notation) {
if (music_notation.errors) {
error_files.push(createSessionSettings.notations[i].name);
}
})
if (error_files.length > 0) {
app.notifyAlert("Failed to upload files. ", error_files.join(', '));
}
createSessionSettings.notations = response;
})
.fail(function(jqXHR) {
app.notifyServerError(jqXHR, "Unable to upload music notations");
})
}
}
return isValid;
}
function beforeMoveStep3() {
var $languageList = $('#session-language-list');
createSessionSettings.language.label = $languageList.val();
createSessionSettings.language.value = $languageList.val();
createSessionSettings.language.label = $languageList.get(0).options[$languageList.get(0).selectedIndex].text;
return true;
}
@ -377,11 +402,14 @@
data.legal_policy = createSessionSettings.session_policy;
data.legal_terms = true;
data.language = createSessionSettings.language.value;
if (createSessionSettings.createType == 'quick-start') {
if (createSessionSettings.createType == 'quick-start' || createSessionSettings.createType == 'immediately') {
data.start = new Date().toDateString() + ' ' + getFormattedTime(new Date(), false);
}
else {
data.start = createSessionSettings.startDate + ' ' + createSessionSettings.startTime;
}
data.invitations = inviteMusiciansUtil.getInvitedFriends();
data.recurring_mode = createSessionSettings.recurring_mode;
data.recurring_mode = createSessionSettings.recurring_mode.value;
data.music_notations = createSessionSettings.music_notations;
if (createSessionSettings.createType == 'start-scheduled') {
@ -398,12 +426,33 @@
}
var joinSession = function(sessionId) {
var options = {};
options.client_id = app.clientId;
options.session_id = sessionId;
options.as_musician = true;
options.tracks = tracks;
rest.joinSession(options)
.done(function(response) {
var invitationCount = data.invitations.length;
context.location = '/client#/session/' + sessionId;
context.JK.GA.trackSessionCount(data.musician_access, data.fan_access, invitationCount);
context.JK.GA.trackSessionMusicians(context.JK.GA.SessionCreationTypes.create);
})
.fail(function(jqXHR) {
var handled = false;
if(jqXHR.status = 422) {
var response = JSON.parse(jqXHR.responseText);
if(response["errors"] && response["errors"]["tracks"] && response["errors"]["tracks"][0] == "Please select at least one track") {
app.notifyAlert("No Inputs Configured", $('<span>You will need to reconfigure your audio device.</span>'));
handled = true;
}
}
if(!handled) {
app.notifyServerError(jqXHR, "Unable to Create Session");
}
})
};
if (createSessionSettings.createType == 'start-scheduled') {
@ -415,12 +464,16 @@
var newSessionId = response.id;
$(".btn-next").off('click');
if (createSessionSettings.createType == 'quick-start') {
if (createSessionSettings.createType == 'quick-start' || createSessionSettings.createType == "immediately") {
joinSession(newSessionId);
}
else {
app.notifyAlert("Session is successfully published.");
context.location = '/client#/home';
}
})
.fail(function(jqXHR){
app.notifyServerError(jqXHR, "Unable to Create Session");
app.notifyServerError(jqXHR, "Unable to schedule a session");
});
}
}
@ -525,12 +578,12 @@
$btnBack.hide();
}
if (step == STEP_SELECT_TYPE && createSessionSettings.createType == 'start-scheduled' && createSessionSettings.selectedSessionId == null) {
$btnNext.removeClass('button-orange').addClass('button-grey');
}
else {
$btnNext.removeClass('button-grey').addClass('button-orange');
}
// if (step == STEP_SELECT_TYPE && createSessionSettings.createType == 'start-scheduled' && createSessionSettings.selectedSessionId == null) {
// $btnNext.removeClass('button-orange').addClass('button-grey');
// }
// else {
// $btnNext.removeClass('button-grey').addClass('button-orange');
// }
if (step == STEP_SELECT_CONFIRM) {
$btnNext.html(createSessionSettings.startType);
@ -697,6 +750,9 @@
inviteMusiciansUtil.loadFriends();
context.JK.guardAgainstBrowser(app);
context.JK.dropdown($('#session-musician-access'));
context.JK.dropdown($('#session-fans-access'));
}
function changeSelectedFiles() {
@ -786,6 +842,14 @@
if (createSessionSettings.createType == 'start-scheduled') {
$('#start-scheduled-wrapper').show();
$('#schedule-future-wrapper').hide();
createSessionSettings = {
createType: 'start-scheduled',
timezone: {},
recurring_mode: {},
language: {},
musician_access: {},
fans_access: {}
};
}
else if (createSessionSettings.createType == 'schedule-future') {
$('#start-scheduled-wrapper').hide();

View File

@ -53,7 +53,7 @@
//= require web/downloads
//= require web/congratulations
//= require web/sessions
//= require web/scheduled_session
//= require web/session_info
//= require web/recordings
//= require web/welcome
//= require banner

View File

@ -12,18 +12,18 @@ class ApiMusicNotationsController < ApiController
raise JamArgumentError, "client_id must be specified"
end
@music_notation = MusicNotation.new
@music_notation.client_id = client_id
@music_notation.file_url = params[:file]
@music_notation.user = current_user
@music_notation.save
@music_notations = []
if @music_notation.errors.any?
response.status = :unprocessable_entity
respond_with @music_notation
else
respond_with @music_notation, responder: ApiResponder, :statue => 201
end
params[:files].each do |file|
music_notation = MusicNotation.new
music_notation.file_url = file
music_notation.user = current_user
music_notation.save
@music_notations.push music_notation
end if params[:files]
respond_with @music_notations, responder: ApiResponder, :statue => 201
end
def download

View File

@ -1,3 +1,3 @@
object @music_notations
attribute :id
attribute :id, :filename

View File

@ -19,7 +19,7 @@ else
attributes :id, :music_session_id, :name, :description, :musician_access, :approval_required, :fan_access, :fan_chat,
:band_id, :user_id, :genre_id, :created_at, :like_count, :comment_count, :scheduled_start, :scheduled_duration,
:language, :recurring_mode, :language_description, :scheduled_start_time, :access_description, :timezone, :timezone_description,
:musician_access_description, :fan_access_description
:musician_access_description, :fan_access_description, :session_removed_at, :legal_policy
node :share_url do |history|
unless history.share_token.nil?
@ -27,6 +27,10 @@ else
end
end
node :genres do |item|
[item.genre.description] # XXX: need to return single genre; not array
end
child(:creator => :creator) {
attributes :name, :photo_url
}
@ -51,10 +55,6 @@ else
}
}
child(:genre => :genre) {
attributes :description
}
child(:session_info_comments => :session_info_comments) {
attributes :comment, :created_at
@ -66,10 +66,15 @@ else
child(:music_notations => :music_notations) {
node do |music_notation|
attributes :id
node(:filename) { |music_notation| music_notation.filename }
# note(:filename) { |music_notation| music_notation.filename }
end
}
child({:invitations => :invitations}) {
attributes :id, :sender_id, :receiver_id
}
child(:active_music_session => :active_music_session) {
attributes :claimed_recording_initiator_id, :track_changes_counter
@ -103,9 +108,6 @@ else
}
child({:invitations => :invitations}) {
attributes :id, :sender_id, :receiver_id
}
# only show join_requests if the current_user is in the session
node(:join_requests, :if => lambda { |music_session| music_session.users.exists?(current_user) } ) do |music_session|

View File

@ -35,14 +35,11 @@
</div>
<div class="content-scroller">
<div class="content-wrapper" style="padding-left:35px;padding-top:10px;">
<div id="sessions-invitations">
<%= render :partial => "sessionList", :locals => {:title => "sessions you're invited to", :category => "sessions-invitations"} %>
<div id="sessions-active">
<%= render :partial => "sessionList", :locals => {:title => "current, active sessions", :category => "sessions-active"} %>
</div>
<div id="sessions-friends" class="mt35">
<%= render :partial => "sessionList", :locals => {:title => "sessions with friends or bandmates", :category => "sessions-friends"} %>
</div>
<div id="sessions-other" class="mt35">
<%= render :partial => "sessionList", :locals => {:title => "other sessions", :category => "sessions-other"} %>
<%= render :partial => "sessionList", :locals => {:title => "future, scheduled sessions", :category => "sessions-scheduled"} %>
</div>
<span class="btn-next-wrapper"><a href="/api/sessions/nindex/clientid?page=1" class="btn-next">Next</a></span>
</div>

View File

@ -20,6 +20,7 @@
<div class="small left">{genre}</div>
<div class="small right">{created_at}</div>
<br clear="all" />
<div class="f11 mt5 mb5"><b>{name}</b></div>
<div class="f11 mt5 mb5">{description}</div>
<div class="small">
<span id="spnCommentCount">{comment_count}</span> <img src="/assets/content/icon_comment.png" width="13" height="12" align="absmiddle" style="vertical-align:middle;" />&nbsp;&nbsp;&nbsp;
@ -30,12 +31,16 @@
<table class="musicians" cellpadding="0" cellspacing="5">
{musicians}
</table>
<br /><br />
<br />
SCHEDULE:<br />
<div class="f11 mt5 mb5">Starts at {start_time}</div>
<div class="f11 mt5 mb5">{recurrence}</div>
<br />
<div align="center">
<div class="left"><a id="btnLike" onclick="addSessionLike('{musicSessionId}');" class="button-orange">LIKE</a></div>
<div style="display:none;" class="left"><a id="btnComment" class="button-orange">COMMENT</a></div>
<div class="left"><a id="btnShare" layout-link="share-dialog" class="button-orange">SHARE</a></div>
<div class="left"><a href="/sessions/{musicSessionId}" class="button-orange" rel="external" target="_blank">WEB PAGE</a></div>
<div class="left"><a href="{url}" class="button-orange" rel="external" target="_blank">{externalLinkText}</a></div>
</div>
<br /><br />
</div>

View File

@ -27,35 +27,35 @@
<div class="icheckbuttons">
<ul id="create-session-type">
<li>
<li create-type="start-scheduled">
<input type="radio" name="session-when" id="session-when-start-scheduled" checked="checked" info-value="start-scheduled" />
<label for="session-when-start-scheduled" class="radio-text">
I have already scheduled a session, and I want to start it now
</label>
<div class="clearall"></div>
</li>
<li>
<li create-type="schedule-future">
<input type="radio" name="session-when" id="session-when-schedule-future" info-value="schedule-future" />
<label for="session-when-schedule-future" class="radio-text">
I want to schedule a session for a specific future time
</label>
<div class="clearall"></div>
</li>
<li>
<li create-type="rsvp">
<input type="radio" name="session-when" id="session-when-rsvp" info-value="rsvp" />
<label for="session-when-rsvp" class="radio-text">
I want to choose the time after others RSVP to my session
</label>
<div class="clearall"></div>
</li>
<li>
<li create-type="immediately">
<input type="radio" name="session-when" id="session-when-immediately" info-value="immediately" />
<label for="session-when-immediately" class="radio-text">
I want to start a new session right now for others to join
</label>
<div class="clearall"></div>
</li>
<li>
<li create-type="quick-start">
<input type="radio" name="session-when" id="session-when-quick-start" info-value="quick-start" />
<label for="session-when-quick-start" class="radio-text">
I want to quick start a test session just for me

View File

@ -2,12 +2,10 @@
<table id="<%= category %>" class="findsession-table" cellspacing="0" cellpadding="0" border="0">
<!-- header -->
<tr>
<th align="left" width="100">GENRE</th>
<th align="left" width="25%">DESCRIPTION</th>
<th align="left" width="100">SESSION</th>
<th align="left" width="20%">MUSICIANS</th>
<th align="left" width="15%">AUDIENCE</th>
<th width="60" style="text-align:center">LATENCY</th>
<th width="50" style="text-align:center">LISTEN</th>
<th align="left" width="15%">POLICIES</th>
<th class="noborder" width="30" style="text-align:center">JOIN</th>
</tr>
<!-- session row goes here -->

View File

@ -209,7 +209,7 @@
<script type="text/template" id="template-notification-panel">
<li session-id="{sessionId}" notification-id="{notificationId}">
<div class="avatar-small"><img src="{avatar_url}" /></div>
<div class="note-text">
<div session-id="{sessionId}" hoveraction="session" class="note-text">
{text}<br/>
<em>{date}</em>
<div class="note-delete">
@ -226,7 +226,6 @@
</li>
</script>
<!-- Chat panel template -->
<script type="text/template" id="template-chat-message">
<div class="chat-message">

View File

@ -39,3 +39,7 @@ NewMusicianEmailer:
class: "JamRuby::NewMusicianEmailer"
description: "Sends weekly emails of new users with good latency"
MusicSessionScheduler:
cron: "0 */5 0 * *"
class: "JamRuby::MusicSessionScheduler"
description: "Schedules music sessions that are marked as recurring"

View File

@ -12,6 +12,8 @@ describe "Chat Message", :js => true, :type => :feature, :capybara_feature => tr
UserMailer.deliveries.clear
ActiveMusicSession.delete_all
ChatMessage.delete_all
FactoryGirl.create(:friendship, :user => user1, :friend => user2)
end
# what are all the ways to be in a session?
@ -33,6 +35,8 @@ describe "Chat Message", :js => true, :type => :feature, :capybara_feature => tr
description = "Find chat panel expanded when join session"
create_session(creator: user1, description: description)
wait_for_ajax
join_session(user2, description: description)
find(".chatcontents").should be_visible

View File

@ -18,6 +18,7 @@ describe "Find Session", :js => true, :type => :feature, :capybara_feature => tr
ActiveMusicSession.delete_all
sign_in_poltergeist user
visit "/client#/findSession"
FactoryGirl.create(:friendship, :user => user, :friend => finder)
end
# when no sessions have been created:

View File

@ -14,6 +14,7 @@ describe "In a Session", :js => true, :type => :feature, :capybara_feature => tr
before(:each) do
UserMailer.deliveries.clear
ActiveMusicSession.delete_all
FactoryGirl.create(:friendship, :user => user, :friend => finder)
end

View File

@ -15,6 +15,8 @@ describe "Reconnect", :js => true, :type => :feature, :capybara_feature => true
before(:each) do
Diagnostic.delete_all
emulate_client
FactoryGirl.create(:friendship, :user => user1, :friend => user2)
end
it "websocket connection is down on initial connection" do

View File

@ -76,7 +76,16 @@ describe "User Progression", :type => :api do
it "joined any session" do
user.first_music_session_at.should be_nil
client = FactoryGirl.create(:connection, :user => user, :ip_address => "1.1.1.1", :client_id => "1.1")
post '/api/sessions/legacy.json', defopts.merge({:client_id => client.client_id}).to_json, "CONTENT_TYPE" => 'application/json'
client = FactoryGirl.create(:connection, :user => user, :ip_address => "1.1.1.1")
post '/api/sessions.json', defopts.to_json, "CONTENT_TYPE" => 'application/json'
last_response.status.should eql(201)
# now fetch it's data
music_session = JSON.parse(last_response.body)
post "/api/sessions/#{music_session["id"]}/participants.json", defpart.merge({ :client_id => client.client_id}).to_json, "CONTENT_TYPE" => 'application/json'
last_response.status.should eql(201)
last_response.status.should eql(201)
user.reload
user.first_music_session_at.should_not be_nil
@ -100,16 +109,23 @@ describe "User Progression", :type => :api do
client = FactoryGirl.create(:connection, :user => user, :ip_address => "1.1.1.1", :client_id => "1_1")
client2 = FactoryGirl.create(:connection, :user => user2, :ip_address => "1.1.1.2", :client_id => "1_2")
client3 = FactoryGirl.create(:connection, :user => user3, :ip_address => "1.1.1.3", :client_id => "1_3")
post '/api/sessions/legacy.json', defopts.merge({:client_id => client.client_id}).to_json, "CONTENT_TYPE" => 'application/json'
post '/api/sessions.json', defopts.to_json, "CONTENT_TYPE" => 'application/json'
last_response.status.should eql(201)
# now fetch it's data
music_session = JSON.parse(last_response.body)
post "/api/sessions/#{music_session["id"]}/participants.json", defpart.merge({ :client_id => client.client_id}).to_json, "CONTENT_TYPE" => 'application/json'
last_response.status.should eql(201)
music_session = JSON.parse(last_response.body)
login(user2)
post "/api/sessions/#{music_session["id"]}/participants/legacy.json", { :client_id => client2.client_id, :as_musician => true, :tracks => [{"instrument_id" => "bass guitar", "sound" => "mono", "client_track_id" => "client_track_guid"}]}.to_json, "CONTENT_TYPE" => 'application/json'
post "/api/sessions/#{music_session["id"]}/participants.json", { :client_id => client2.client_id, :as_musician => true, :tracks => [{"instrument_id" => "bass guitar", "sound" => "mono", "client_track_id" => "client_track_guid"}]}.to_json, "CONTENT_TYPE" => 'application/json'
last_response.status.should eql(201)
login(user3)
post "/api/sessions/#{music_session["id"]}/participants/legacy.json", { :client_id => client3.client_id, :as_musician => true, :tracks => [{"instrument_id" => "bass guitar", "sound" => "mono", "client_track_id" => "client_track_guid"}]}.to_json, "CONTENT_TYPE" => 'application/json'
post "/api/sessions/#{music_session["id"]}/participants.json", { :client_id => client3.client_id, :as_musician => true, :tracks => [{"instrument_id" => "bass guitar", "sound" => "mono", "client_track_id" => "client_track_guid"}]}.to_json, "CONTENT_TYPE" => 'application/json'
last_response.status.should eql(201)
# instrument the created_at of the music_history field to be at the beginning of time, so that we cross the 15 minute threshold of a 'real session

View File

@ -213,10 +213,13 @@ end
# in finding this session)
def create_session(options={})
creator = options[:creator] || FactoryGirl.create(:user)
unique_session_name = options[:name] || "create_join_session #{SecureRandom.urlsafe_base64}"
unique_session_desc = options[:description] || "create_join_session #{SecureRandom.urlsafe_base64}"
genre = options[:genre] || 'Rock'
musician_access = options[:musician_access].nil? ? true : options[:musician_access]
approval_required = options[:approval_required].nil? ? true : options[:approval_required]
fan_access = options[:fan_access].nil? ? true : options[:fan_access]
fan_chat = options[:fan_chat].nil? ? true : options[:fan_chat]
# create session in one client
in_client(creator) do
@ -225,18 +228,45 @@ def create_session(options={})
sign_in_poltergeist creator
wait_until_curtain_gone
visit "/client#/createSession"
expect(page).to have_selector('h2', text: 'session info')
expect(page).to have_selector('h1', text: 'create session')
within('#create-session-form') do
fill_in('description', :with => unique_session_desc)
#select(genre, :from => 'genres', :visible => false) # this works, but is 'cheating' because easydropdown hides the native select element
jk_select(genre, '#create-session-form select[name="genres"]')
jk_select(musician_access ? 'Public' : 'Private', '#create-session-form select#musician-access')
jk_select(fan_access ? 'Public' : 'Private', '#create-session-form select#fan-access')
find('#create-session-form div.musician-access-false.iradio_minimal').trigger(:click)
find('div.intellectual-property ins').trigger(:click)
find('#btn-create-session').trigger(:click) # fails if page width is low
# step 1
find('li[create-type="immediately"] ins').trigger(:click)
find('.btn-next').trigger(:click)
# step 2
jk_select(genre, '#create-session-form select[name="genres"]')
fill_in('session-name', :with => unique_session_name)
fill_in('session-description', :with => unique_session_desc)
find('.btn-next').trigger(:click)
# step 3
find('.btn-next').trigger(:click)
# step 4
musician_access_value = "Musicians may join by approval"
if !musician_access && !approval_required
musician_access_value = "Only RSVP musicians may join"
elsif musician_access && approval_required
musician_access_value = "Musicians may join at will"
end
jk_select(musician_access_value, '#session-musician-access')
fan_access_value = "Fans may listen, chat with each other"
if !fan_access && !fan_chat
fan_access_value = 'Fans may not listen to session'
elsif fan_access && fan_chat
fan_access_value = 'Fans may listen, chat with the band'
end
jk_select(fan_access_value, '#session-fans-access')
find('#divSessionPolicy ins').trigger(:click)
find('.btn-next').trigger(:click)
# step 5
find('.btn-next').trigger(:click)
end
# verify that the in-session page is showing