diff --git a/admin/Gemfile b/admin/Gemfile index e79c7489d..c19542b30 100644 --- a/admin/Gemfile +++ b/admin/Gemfile @@ -38,7 +38,7 @@ gem 'carrierwave', '0.9.0' gem 'carrierwave_direct' gem 'uuidtools', '2.1.2' gem 'jquery-rails' # , '2.3.0' # pinned because jquery-ui-rails was split from jquery-rails, but activeadmin doesn't support this gem yet -gem 'jquery-ui-rails' +gem 'jquery-ui-rails', '4.2.1' gem 'rails3-jquery-autocomplete' gem 'activeadmin', '0.6.2' gem 'mime-types', '1.25' @@ -108,7 +108,7 @@ group :development, :test do gem 'factory_girl_rails', '4.1.0' gem 'database_cleaner', '0.7.0' gem 'launchy' - gem 'faker' + gem 'faker', '1.3.0' end group :test do diff --git a/db/manifest b/db/manifest index 5bad3d1e0..5e3de51ff 100755 --- a/db/manifest +++ b/db/manifest @@ -183,3 +183,5 @@ add_file_name_music_notation.sql change_scheduled_start_music_session.sql music_sessions_iso_639_3.sql discardable_claimed_recordings.sql +fix_null_scheduled_start.sql +fix_use_open_rsvp.sql \ No newline at end of file diff --git a/db/up/fix_null_scheduled_start.sql b/db/up/fix_null_scheduled_start.sql new file mode 100644 index 000000000..2ac2807bf --- /dev/null +++ b/db/up/fix_null_scheduled_start.sql @@ -0,0 +1,70 @@ +-- my_audio_latency can have a special value of -1, which means 'unknown'. +CREATE OR REPLACE FUNCTION sms_index (my_user_id VARCHAR, my_locidispid BIGINT, my_audio_latency INTEGER) RETURNS VOID STRICT VOLATILE AS $$ + BEGIN + -- output table to hold tagged music sessions with latency + CREATE TEMPORARY TABLE sms_music_session_tmp (music_session_id VARCHAR(64) NOT NULL, tag INTEGER, latency INTEGER) ON COMMIT DROP; + + -- populate sms_music_session_tmp as all music sessions + -- XXX: we should pass in enough info to match pagination/query to reduce the impact of this step + INSERT INTO sms_music_session_tmp SELECT DISTINCT id, NULL::INTEGER AS tag, NULL::INTEGER AS latency + FROM music_sessions where scheduled_start IS NULL OR scheduled_start > (NOW() - (interval '15 minute')); + + -- tag accepted rsvp as 1 + UPDATE sms_music_session_tmp q SET tag = 1 FROM rsvp_slots s, rsvp_requests_rsvp_slots rrs, rsvp_requests r WHERE + q.music_session_id = s.music_session_id AND + s.id = rrs.rsvp_slot_id AND + rrs.rsvp_request_id = r.id AND + r.user_id = my_user_id AND + rrs.chosen = TRUE AND + q.tag is NULL; + + -- tag invitation as 2 + UPDATE sms_music_session_tmp q SET tag = 2 FROM invitations i WHERE + q.music_session_id = i.music_session_id AND + i.receiver_id = my_user_id AND + q.tag IS NULL; + + -- musician access as 3 + UPDATE sms_music_session_tmp q SET tag = 3 FROM music_sessions m WHERE + q.music_session_id = m.id AND + m.musician_access = TRUE AND + q.tag IS NULL; + + -- delete anything not tagged + DELETE FROM sms_music_session_tmp WHERE tag IS NULL; + + -- output table to hold users involved in the sms_music_session_tmp sessions and their latency + CREATE TEMPORARY TABLE sms_users_tmp (music_session_id VARCHAR(64), user_id VARCHAR(64) NOT NULL, latency INTEGER) ON COMMIT DROP; + + IF my_audio_latency > -1 THEN + -- populate sms_users_tmp with users that have an approved RSVP for sessions in the sms_music_session_tmp table, accompanied with full latency and music session + INSERT INTO sms_users_tmp SELECT q.music_session_id, users.id, (s.score+my_audio_latency+users.last_jam_audio_latency)/2 AS latency + FROM sms_music_session_tmp q + INNER JOIN rsvp_slots ON rsvp_slots.music_session_id = q.music_session_id + INNER JOIN rsvp_requests_rsvp_slots ON rsvp_requests_rsvp_slots.rsvp_slot_id = rsvp_slots.id + INNER JOIN rsvp_requests ON rsvp_requests.id = rsvp_requests_rsvp_slots.rsvp_request_id + INNER JOIN users ON rsvp_requests.user_id = users.id + LEFT OUTER JOIN current_scores s ON s.alocidispid = users.last_jam_locidispid + WHERE + s.blocidispid = my_locidispid AND + rsvp_requests_rsvp_slots.chosen = TRUE; + + -- populate sms_users_tmp with invited users for session in the sms_music_session_tmp table, accompanied with full latency and music session + -- specify NULL for music_session_id, because we don't want RSVP users to affect the AVG computed for each session later + INSERT INTO sms_users_tmp SELECT NULL, users.id, (s.score+my_audio_latency+users.last_jam_audio_latency)/2 AS latency + FROM sms_music_session_tmp q + INNER JOIN invitations ON invitations.music_session_id = q.music_session_id + INNER JOIN users ON invitations.receiver_id = users.id + LEFT OUTER JOIN current_scores s ON s.alocidispid = users.last_jam_locidispid + WHERE + s.blocidispid = my_locidispid AND + users.id NOT IN (SELECT user_id FROM sms_users_tmp); + END IF; + + -- calculate the average latency + UPDATE sms_music_session_tmp q SET latency = (select AVG(u.latency) FROM sms_users_tmp u WHERE + q.music_session_id = u.music_session_id); + + RETURN; + END; +$$ LANGUAGE plpgsql; \ No newline at end of file diff --git a/db/up/fix_use_open_rsvp.sql b/db/up/fix_use_open_rsvp.sql new file mode 100644 index 000000000..f271d265d --- /dev/null +++ b/db/up/fix_use_open_rsvp.sql @@ -0,0 +1,70 @@ +-- my_audio_latency can have a special value of -1, which means 'unknown'. +CREATE OR REPLACE FUNCTION sms_index (my_user_id VARCHAR, my_locidispid BIGINT, my_audio_latency INTEGER) RETURNS VOID STRICT VOLATILE AS $$ + BEGIN + -- output table to hold tagged music sessions with latency + CREATE TEMPORARY TABLE sms_music_session_tmp (music_session_id VARCHAR(64) NOT NULL, tag INTEGER, latency INTEGER) ON COMMIT DROP; + + -- populate sms_music_session_tmp as all music sessions + -- XXX: we should pass in enough info to match pagination/query to reduce the impact of this step + INSERT INTO sms_music_session_tmp SELECT DISTINCT id, NULL::INTEGER AS tag, NULL::INTEGER AS latency + FROM music_sessions where scheduled_start IS NULL OR scheduled_start > (NOW() - (interval '15 minute')); + + -- tag accepted rsvp as 1 + UPDATE sms_music_session_tmp q SET tag = 1 FROM rsvp_slots s, rsvp_requests_rsvp_slots rrs, rsvp_requests r WHERE + q.music_session_id = s.music_session_id AND + s.id = rrs.rsvp_slot_id AND + rrs.rsvp_request_id = r.id AND + r.user_id = my_user_id AND + rrs.chosen = TRUE AND + q.tag is NULL; + + -- tag invitation as 2 + UPDATE sms_music_session_tmp q SET tag = 2 FROM invitations i WHERE + q.music_session_id = i.music_session_id AND + i.receiver_id = my_user_id AND + q.tag IS NULL; + + -- musician access as 3 + UPDATE sms_music_session_tmp q SET tag = 3 FROM music_sessions m WHERE + q.music_session_id = m.id AND + m.open_rsvps = TRUE AND + q.tag IS NULL; + + -- delete anything not tagged + DELETE FROM sms_music_session_tmp WHERE tag IS NULL; + + -- output table to hold users involved in the sms_music_session_tmp sessions and their latency + CREATE TEMPORARY TABLE sms_users_tmp (music_session_id VARCHAR(64), user_id VARCHAR(64) NOT NULL, latency INTEGER) ON COMMIT DROP; + + IF my_audio_latency > -1 THEN + -- populate sms_users_tmp with users that have an approved RSVP for sessions in the sms_music_session_tmp table, accompanied with full latency and music session + INSERT INTO sms_users_tmp SELECT q.music_session_id, users.id, (s.score+my_audio_latency+users.last_jam_audio_latency)/2 AS latency + FROM sms_music_session_tmp q + INNER JOIN rsvp_slots ON rsvp_slots.music_session_id = q.music_session_id + INNER JOIN rsvp_requests_rsvp_slots ON rsvp_requests_rsvp_slots.rsvp_slot_id = rsvp_slots.id + INNER JOIN rsvp_requests ON rsvp_requests.id = rsvp_requests_rsvp_slots.rsvp_request_id + INNER JOIN users ON rsvp_requests.user_id = users.id + LEFT OUTER JOIN current_scores s ON s.alocidispid = users.last_jam_locidispid + WHERE + s.blocidispid = my_locidispid AND + rsvp_requests_rsvp_slots.chosen = TRUE; + + -- populate sms_users_tmp with invited users for session in the sms_music_session_tmp table, accompanied with full latency and music session + -- specify NULL for music_session_id, because we don't want RSVP users to affect the AVG computed for each session later + INSERT INTO sms_users_tmp SELECT NULL, users.id, (s.score+my_audio_latency+users.last_jam_audio_latency)/2 AS latency + FROM sms_music_session_tmp q + INNER JOIN invitations ON invitations.music_session_id = q.music_session_id + INNER JOIN users ON invitations.receiver_id = users.id + LEFT OUTER JOIN current_scores s ON s.alocidispid = users.last_jam_locidispid + WHERE + s.blocidispid = my_locidispid AND + users.id NOT IN (SELECT user_id FROM sms_users_tmp); + END IF; + + -- calculate the average latency + UPDATE sms_music_session_tmp q SET latency = (select AVG(u.latency) FROM sms_users_tmp u WHERE + q.music_session_id = u.music_session_id); + + RETURN; + END; +$$ LANGUAGE plpgsql; \ No newline at end of file diff --git a/ruby/Gemfile b/ruby/Gemfile index 6c4e9277e..c4acf6d44 100644 --- a/ruby/Gemfile +++ b/ruby/Gemfile @@ -54,7 +54,7 @@ group :test do gem "rspec", "2.11" gem 'spork', '0.9.0' gem 'database_cleaner', '0.7.0' - gem 'faker' + gem 'faker', '1.3.0' gem 'resque_spec' #, :path => "/home/jam/src/resque_spec/" gem 'timecop' gem 'rspec-prof' diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/batch_mailer/send_batch_email_test.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/batch_mailer/send_batch_email_test.html.erb deleted file mode 120000 index f14e9223c..000000000 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/batch_mailer/send_batch_email_test.html.erb +++ /dev/null @@ -1 +0,0 @@ -send_batch_email.html.erb \ No newline at end of file diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/batch_mailer/send_batch_email_test.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/batch_mailer/send_batch_email_test.html.erb new file mode 100644 index 000000000..31bd20e21 --- /dev/null +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/batch_mailer/send_batch_email_test.html.erb @@ -0,0 +1 @@ +<%= @body %> diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/batch_mailer/send_batch_email_test.text.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/batch_mailer/send_batch_email_test.text.erb deleted file mode 120000 index 2a1e564e8..000000000 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/batch_mailer/send_batch_email_test.text.erb +++ /dev/null @@ -1 +0,0 @@ -send_batch_email.text.erb \ No newline at end of file diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/batch_mailer/send_batch_email_test.text.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/batch_mailer/send_batch_email_test.text.erb new file mode 100644 index 000000000..31bd20e21 --- /dev/null +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/batch_mailer/send_batch_email_test.text.erb @@ -0,0 +1 @@ +<%= @body %> diff --git a/ruby/spec/factories.rb b/ruby/spec/factories.rb index 7ee7c6137..41c9f5f2c 100644 --- a/ruby/spec/factories.rb +++ b/ruby/spec/factories.rb @@ -94,7 +94,7 @@ FactoryGirl.define do recurring_mode 'once' genre JamRuby::Genre.first association :creator, :factory => :user - open_rsvps false + open_rsvps true scheduled_start Time.now factory :recurring_music_session_weekly do diff --git a/ruby/spec/jam_ruby/models/music_session_spec.rb b/ruby/spec/jam_ruby/models/music_session_spec.rb index e1a494ca6..97ec4a941 100644 --- a/ruby/spec/jam_ruby/models/music_session_spec.rb +++ b/ruby/spec/jam_ruby/models/music_session_spec.rb @@ -264,6 +264,29 @@ describe MusicSession do user_scores.length.should == 0 end + it "one session shows/hides based on open_rsvps" do + creator.last_jam_locidispid = conn.locidispid + creator.save! + + music_session = FactoryGirl.create(:music_session, creator: creator, scheduled_start: nil) + music_sessions, user_scores = sms(searcher, default_opts) + music_sessions.length.should == 1 + + music_session.open_rsvps = false + music_session.save! + music_sessions, user_scores = sms(searcher, default_opts) + music_sessions.length.should == 0 + end + + it "one session with no scheduled_start time" do + creator.last_jam_locidispid = conn.locidispid + creator.save! + + music_session = FactoryGirl.create(:music_session, creator: creator, scheduled_start: nil) + music_sessions, user_scores = sms(searcher, default_opts) + music_sessions.length.should == 1 + end + it "one session, one RSVP (creator)" do creator.last_jam_locidispid = conn.locidispid creator.save! @@ -398,19 +421,19 @@ describe MusicSession do user_scores[creator_1.id][:latency].should == (bad_network_score + searcher_1.last_jam_audio_latency + creator_1.last_jam_audio_latency ) / 2 # let's make music_session_3 invisible, and verify the count goes to 2 - music_session_3.musician_access = false + music_session_3.open_rsvps = false music_session_3.save! music_sessions, user_scores = sms(searcher_1, {client_id: searcher_conn_1.client_id}) music_sessions.length.should == 2 # let's make music_session_2 invisible, but still the count should be the same (because searcher_1 have an invite) - music_session_2.musician_access = false + music_session_2.open_rsvps = false music_session_2.save! music_sessions, user_scores = sms(searcher_1, {client_id: searcher_conn_1.client_id}) music_sessions.length.should == 2 # and lastly with music_session_1, make it invisible, and still it should be visible to the searcher (because searcher_1 has an invite) - music_session_1.musician_access = false + music_session_1.open_rsvps = false music_session_1.save! music_sessions, user_scores = sms(searcher_1, {client_id: searcher_conn_1.client_id}) music_sessions.length.should == 2 diff --git a/ruby/spec/jam_ruby/models/rsvp_request_spec.rb b/ruby/spec/jam_ruby/models/rsvp_request_spec.rb index bd9cfaff0..4052ba922 100644 --- a/ruby/spec/jam_ruby/models/rsvp_request_spec.rb +++ b/ruby/spec/jam_ruby/models/rsvp_request_spec.rb @@ -102,6 +102,8 @@ describe RsvpRequest do end it "should not allow non-invitee to RSVP to session with closed RSVPs" do + @music_session.open_rsvps = false + @music_session.save! expect {RsvpRequest.create({:session_id => @music_session.id, :rsvp_slots => [@slot1.id, @slot2.id]}, @non_session_invitee)}.to raise_error(JamRuby::PermissionError) end diff --git a/web/Gemfile b/web/Gemfile index 2c3a862e1..5877760cb 100644 --- a/web/Gemfile +++ b/web/Gemfile @@ -24,10 +24,10 @@ gem 'builder' gem 'rails', '~>3.2.11' gem 'railties', '~>3.2.11' gem 'jquery-rails' -gem 'jquery-ui-rails' +gem 'jquery-ui-rails', '4.2.1' gem 'bootstrap-sass', '2.0.4' gem 'bcrypt-ruby', '3.0.1' -gem 'faker', '1.0.1' +gem 'faker', '1.3.0' gem 'will_paginate', '3.0.3' gem 'bootstrap-will_paginate', '0.0.6' gem 'em-websocket', '>=0.4.0' #, :path => '/Users/seth/workspace/em-websocket' diff --git a/web/app/assets/javascripts/banner.js b/web/app/assets/javascripts/banner.js index 863e5dd98..b64fda123 100644 --- a/web/app/assets/javascripts/banner.js +++ b/web/app/assets/javascripts/banner.js @@ -57,6 +57,8 @@ } } + hide(); + logger.debug("opening banner:" + options.title); var $h1 = $banner.find('h1'); @@ -74,6 +76,7 @@ } + if((options.type == "alert" && !options.buttons) || options.close) { var closeButtonText = 'CLOSE'; diff --git a/web/app/assets/javascripts/fakeJamClient.js b/web/app/assets/javascripts/fakeJamClient.js index af144dfd6..13da1b672 100644 --- a/web/app/assets/javascripts/fakeJamClient.js +++ b/web/app/assets/javascripts/fakeJamClient.js @@ -774,9 +774,8 @@ logger.debug("SessionLiveBroadcastStop requested"); } - function RegisterQuitCallback() { - - } + function RegisterQuitCallback() { } + function LeaveSessionAndMinimize() {} // Javascript Bridge seems to camel-case // Set the instance functions: @@ -809,6 +808,7 @@ this.SetNetworkTestScore = SetNetworkTestScore; this.GetNetworkTestScore = GetNetworkTestScore; this.RegisterQuitCallback = RegisterQuitCallback; + this.LeaveSessionAndMinimize = LeaveSessionAndMinimize; this.connected = true; // FTUE (round 3) diff --git a/web/app/assets/javascripts/landing/landing.js b/web/app/assets/javascripts/landing/landing.js index 3da8e39a0..0a42a8499 100644 --- a/web/app/assets/javascripts/landing/landing.js +++ b/web/app/assets/javascripts/landing/landing.js @@ -32,4 +32,4 @@ //= require web/signin //= require landing/init //= require landing/signup -//= require shareDialog \ No newline at end of file +//= require shareDialog diff --git a/web/app/assets/javascripts/shutdownDialog.js b/web/app/assets/javascripts/shutdownDialog.js index 60c837861..9cd1ec082 100644 --- a/web/app/assets/javascripts/shutdownDialog.js +++ b/web/app/assets/javascripts/shutdownDialog.js @@ -14,6 +14,7 @@ {name: 'Completely Shut Down the App', click: function() {context.jamClient.ShutdownApplication()}}, {name: 'Let App Run in Background', click: function() { context.jamClient.RegisterQuitCallback("window.JK.ShutdownDialogCallback"); + context.jamClient.LeaveSessionAndMinimize(); context.JK.Banner.hide(); } } diff --git a/web/spec/factories.rb b/web/spec/factories.rb index 5987ed5af..4f59a0493 100644 --- a/web/spec/factories.rb +++ b/web/spec/factories.rb @@ -111,7 +111,7 @@ FactoryGirl.define do legal_policy 'Standard' genre JamRuby::Genre.first association :creator, :factory => :user - open_rsvps false + open_rsvps true scheduled_start Time.now recurring_mode 'once' scheduled_duration "30 minutes" diff --git a/web/spec/features/session_info_spec.rb b/web/spec/features/session_info_spec.rb index eb26e81cf..4dfab932a 100644 --- a/web/spec/features/session_info_spec.rb +++ b/web/spec/features/session_info_spec.rb @@ -37,7 +37,7 @@ describe "Session Info", :js => true, :type => :feature, :capybara_feature => tr FactoryGirl.create(:friendship, :user => @rsvp_declined_user, :friend => @session_creator) FactoryGirl.create(:friendship, :user => @session_creator, :friend => @rsvp_declined_user) - @music_session = FactoryGirl.build(:music_session, :creator => @session_creator, :scheduled_start => Time.now.utc + 2.days, :musician_access => true, :approval_required => true) + @music_session = FactoryGirl.build(:music_session, :creator => @session_creator, :scheduled_start => Time.now.utc + 2.days, :musician_access => true, :approval_required => true, :open_rsvps => false) @music_session.save @url = "/sessions/#{@music_session.id}/details"