From 5135fe7faf23871d1ad07e4b936427fb6915326f Mon Sep 17 00:00:00 2001 From: Steven Miers Date: Fri, 3 Oct 2014 13:36:51 -0500 Subject: [PATCH 01/19] VRFS-2024 - Migration, model and spec for video source. --- db/manifest | 3 ++- db/up/video_sources.sql | 9 +++++++++ ruby/lib/jam_ruby.rb | 1 + ruby/lib/jam_ruby/models/connection.rb | 1 + ruby/lib/jam_ruby/models/video_source.rb | 10 ++++++++++ ruby/spec/factories.rb | 4 ++++ .../spec/jam_ruby/models/video_source_spec.rb | 20 +++++++++++++++++++ 7 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 db/up/video_sources.sql create mode 100644 ruby/lib/jam_ruby/models/video_source.rb create mode 100644 ruby/spec/jam_ruby/models/video_source_spec.rb diff --git a/db/manifest b/db/manifest index 8114e06ee..5d7ffd7b8 100755 --- a/db/manifest +++ b/db/manifest @@ -214,4 +214,5 @@ fix_find_session_sorting_2216a.sql fix_find_session_sorting_2216b.sql fix_find_session_sorting_2216c.sql entabulate_current_network_scores.sql -discard_scores_changed.sql \ No newline at end of file +discard_scores_changed.sql +video_sources.sql diff --git a/db/up/video_sources.sql b/db/up/video_sources.sql new file mode 100644 index 000000000..cab646c94 --- /dev/null +++ b/db/up/video_sources.sql @@ -0,0 +1,9 @@ +CREATE TABLE video_sources ( + id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(), + connection_id VARCHAR(64) NOT NULL, + client_video_source_id VARCHAR(64) NOT NULL, + + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP +); + diff --git a/ruby/lib/jam_ruby.rb b/ruby/lib/jam_ruby.rb index eb8fc345e..5c98fa960 100755 --- a/ruby/lib/jam_ruby.rb +++ b/ruby/lib/jam_ruby.rb @@ -173,6 +173,7 @@ require "jam_ruby/models/chat_message" require "jam_ruby/models/generic_state" require "jam_ruby/models/score_history" require "jam_ruby/models/jam_company" +require "jam_ruby/models/video_source" include Jampb diff --git a/ruby/lib/jam_ruby/models/connection.rb b/ruby/lib/jam_ruby/models/connection.rb index 311eaaf13..9083b4543 100644 --- a/ruby/lib/jam_ruby/models/connection.rb +++ b/ruby/lib/jam_ruby/models/connection.rb @@ -17,6 +17,7 @@ module JamRuby belongs_to :music_session, :class_name => "JamRuby::ActiveMusicSession", foreign_key: :music_session_id has_one :latency_tester, class_name: 'JamRuby::LatencyTester', foreign_key: :client_id, primary_key: :client_id has_many :tracks, :class_name => "JamRuby::Track", :inverse_of => :connection, :foreign_key => 'connection_id', :dependent => :delete_all + has_many :video_sources, :class_name => "JamRuby::VideoSource", :inverse_of => :connection, :foreign_key => 'connection_id', :dependent => :delete_all validates :as_musician, :inclusion => {:in => [true, false]} validates :client_type, :inclusion => {:in => [TYPE_CLIENT, TYPE_BROWSER, TYPE_LATENCY_TESTER]} diff --git a/ruby/lib/jam_ruby/models/video_source.rb b/ruby/lib/jam_ruby/models/video_source.rb new file mode 100644 index 000000000..ebf095241 --- /dev/null +++ b/ruby/lib/jam_ruby/models/video_source.rb @@ -0,0 +1,10 @@ +# Video analog to JamRuby::Track +module JamRuby + class VideoSource < ActiveRecord::Base + self.table_name = "video_sources" + self.primary_key = 'id' + default_scope order('created_at ASC') + belongs_to :connection, :class_name => "JamRuby::Connection", :inverse_of => :video_sources, :foreign_key => 'connection_id' + validates :connection, presence: true + end +end \ No newline at end of file diff --git a/ruby/spec/factories.rb b/ruby/spec/factories.rb index 249cd8247..3f552fa0e 100644 --- a/ruby/spec/factories.rb +++ b/ruby/spec/factories.rb @@ -231,6 +231,10 @@ FactoryGirl.define do sequence(:client_track_id) { |n| "client_track_id#{n}"} end + factory :video_source, :class => JamRuby::VideoSource do + client_video_source_id "test_source_id" + end + factory :recorded_track, :class => JamRuby::RecordedTrack do instrument JamRuby::Instrument.first sound 'stereo' diff --git a/ruby/spec/jam_ruby/models/video_source_spec.rb b/ruby/spec/jam_ruby/models/video_source_spec.rb new file mode 100644 index 000000000..02b9c4e1c --- /dev/null +++ b/ruby/spec/jam_ruby/models/video_source_spec.rb @@ -0,0 +1,20 @@ +require 'spec_helper' + +describe VideoSource do + + let (:user) {FactoryGirl.create(:user) } + let (:music_session) { FactoryGirl.create(:active_music_session, :creator => user)} + let (:connection) { FactoryGirl.create(:connection, :user => user, :music_session => music_session) } + let (:msuh) {FactoryGirl.create(:music_session_user_history, :history => music_session.music_session, :user => user, :client_id => connection.client_id) } + + before(:each) do + msuh.touch + end + + describe "simple create" do + it "create a video source" do + track = FactoryGirl.create(:video_source, :connection => connection) + track.should_not be_nil + end + end +end \ No newline at end of file From 66feb39de8ddbecc56ff6e0700eea6dd8da203de Mon Sep 17 00:00:00 2001 From: Steven Miers Date: Fri, 3 Oct 2014 14:12:09 -0500 Subject: [PATCH 02/19] VRFS-2023 - Migration, models and spec for recorded_video, a video analog to recorded_track. --- db/manifest | 1 + db/up/recorded_videos.sql | 17 +++++++++++++++ ruby/lib/jam_ruby.rb | 1 + ruby/lib/jam_ruby/models/recorded_video.rb | 18 ++++++++++++++++ ruby/lib/jam_ruby/models/recording.rb | 1 + ruby/lib/jam_ruby/models/user.rb | 1 + ruby/lib/jam_ruby/models/video_source.rb | 2 +- ruby/spec/factories.rb | 6 ++++++ .../jam_ruby/models/recorded_video_spec.rb | 21 +++++++++++++++++++ .../spec/jam_ruby/models/video_source_spec.rb | 5 +++-- 10 files changed, 70 insertions(+), 3 deletions(-) create mode 100644 db/up/recorded_videos.sql create mode 100644 ruby/lib/jam_ruby/models/recorded_video.rb create mode 100644 ruby/spec/jam_ruby/models/recorded_video_spec.rb diff --git a/db/manifest b/db/manifest index 5d7ffd7b8..9407c2a3f 100755 --- a/db/manifest +++ b/db/manifest @@ -216,3 +216,4 @@ fix_find_session_sorting_2216c.sql entabulate_current_network_scores.sql discard_scores_changed.sql video_sources.sql +recorded_videos.sql diff --git a/db/up/recorded_videos.sql b/db/up/recorded_videos.sql new file mode 100644 index 000000000..fc8e22814 --- /dev/null +++ b/db/up/recorded_videos.sql @@ -0,0 +1,17 @@ +CREATE TABLE recorded_videos ( + id BIGINT PRIMARY KEY, + user_id VARCHAR(64) REFERENCES users(id) ON DELETE CASCADE, + fully_uploaded BOOLEAN NOT NULL DEFAULT FALSE, + recording_id VARCHAR(64) NOT NULL, + length BIGINT, + client_video_source_id VARCHAR(64) NOT NULL, + url VARCHAR(1024), + file_offset BIGINT, + upload_failures INTEGER NOT NULL DEFAULT 0, + discard BOOLEAN, + + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP +); + +ALTER TABLE recorded_videos ALTER COLUMN id SET DEFAULT nextval('tracks_next_tracker_seq'); diff --git a/ruby/lib/jam_ruby.rb b/ruby/lib/jam_ruby.rb index 5c98fa960..9daaa1e8d 100755 --- a/ruby/lib/jam_ruby.rb +++ b/ruby/lib/jam_ruby.rb @@ -174,6 +174,7 @@ require "jam_ruby/models/generic_state" require "jam_ruby/models/score_history" require "jam_ruby/models/jam_company" require "jam_ruby/models/video_source" +require "jam_ruby/models/recorded_video" include Jampb diff --git a/ruby/lib/jam_ruby/models/recorded_video.rb b/ruby/lib/jam_ruby/models/recorded_video.rb new file mode 100644 index 000000000..63837c53a --- /dev/null +++ b/ruby/lib/jam_ruby/models/recorded_video.rb @@ -0,0 +1,18 @@ +module JamRuby + # Video analog to JamRuby::RecordedTrack + class RecordedVideo < ActiveRecord::Base + belongs_to :user, :class_name => "JamRuby::User", :inverse_of => :recorded_videos + belongs_to :recording, :class_name => "JamRuby::Recording", :inverse_of => :recorded_videos + + validates :client_video_source_id, :presence => true + + def self.create_from_video_source(video_source, recording) + recorded_video_source = self.new + recorded_video_source.recording = recording + recorded_video_source.client_video_source_id = video_source.id + recorded_video_source.user = video_source.connection.user + recorded_video_source.save + recorded_video_source + end + end +end diff --git a/ruby/lib/jam_ruby/models/recording.rb b/ruby/lib/jam_ruby/models/recording.rb index edd2a4d1a..f1ff2677c 100644 --- a/ruby/lib/jam_ruby/models/recording.rb +++ b/ruby/lib/jam_ruby/models/recording.rb @@ -9,6 +9,7 @@ module JamRuby has_many :claimed_recordings, :class_name => "JamRuby::ClaimedRecording", :inverse_of => :recording, :foreign_key => 'recording_id', :dependent => :destroy has_many :mixes, :class_name => "JamRuby::Mix", :inverse_of => :recording, :foreign_key => 'recording_id', :dependent => :destroy has_many :recorded_tracks, :class_name => "JamRuby::RecordedTrack", :foreign_key => :recording_id, :dependent => :destroy + has_many :recorded_videos, :class_name => "JamRuby::RecordedVideo", :foreign_key => :recording_id, :dependent => :destroy has_many :comments, :class_name => "JamRuby::RecordingComment", :foreign_key => "recording_id", :dependent => :destroy has_many :likes, :class_name => "JamRuby::RecordingLiker", :foreign_key => "recording_id", :dependent => :destroy has_many :plays, :class_name => "JamRuby::PlayablePlay", :as => :playable, :dependent => :destroy diff --git a/ruby/lib/jam_ruby/models/user.rb b/ruby/lib/jam_ruby/models/user.rb index 9cdc68a1c..672673b8f 100644 --- a/ruby/lib/jam_ruby/models/user.rb +++ b/ruby/lib/jam_ruby/models/user.rb @@ -103,6 +103,7 @@ module JamRuby # saved tracks has_many :recorded_tracks, :foreign_key => "user_id", :class_name => "JamRuby::RecordedTrack", :inverse_of => :user + has_many :recorded_videos, :foreign_key => "user_id", :class_name => "JamRuby::RecordedVideo", :inverse_of => :user # invited users has_many :invited_users, :foreign_key => "sender_id", :class_name => "JamRuby::InvitedUser" diff --git a/ruby/lib/jam_ruby/models/video_source.rb b/ruby/lib/jam_ruby/models/video_source.rb index ebf095241..4517bf4bf 100644 --- a/ruby/lib/jam_ruby/models/video_source.rb +++ b/ruby/lib/jam_ruby/models/video_source.rb @@ -1,5 +1,5 @@ -# Video analog to JamRuby::Track module JamRuby + # Video analog to JamRuby::Track class VideoSource < ActiveRecord::Base self.table_name = "video_sources" self.primary_key = 'id' diff --git a/ruby/spec/factories.rb b/ruby/spec/factories.rb index 3f552fa0e..2d030b752 100644 --- a/ruby/spec/factories.rb +++ b/ruby/spec/factories.rb @@ -248,6 +248,12 @@ FactoryGirl.define do association :recording, factory: :recording end + factory :recorded_video, :class => JamRuby::RecordedVideo do + sequence(:client_id) { |n| "client_id-#{n}"} + sequence(:track_id) { |n| "track_id-#{n}"} + sequence(:client_track_id) { |n| "client_track_id-#{n}"} + end + factory :instrument, :class => JamRuby::Instrument do description { |n| "Instrument #{n}" } end diff --git a/ruby/spec/jam_ruby/models/recorded_video_spec.rb b/ruby/spec/jam_ruby/models/recorded_video_spec.rb new file mode 100644 index 000000000..e8043f24a --- /dev/null +++ b/ruby/spec/jam_ruby/models/recorded_video_spec.rb @@ -0,0 +1,21 @@ +require 'spec_helper' +require 'rest-client' + +describe RecordedVideo do + include UsesTempFiles + let (:user) {FactoryGirl.create(:user)} + let (:connection) {FactoryGirl.create(:connection, :user => user)} + let (:music_session){FactoryGirl.create(:active_music_session, :creator => user, :musician_access => true)} + let (:recording) {FactoryGirl.create(:recording, :music_session => music_session, :owner => user)} + let (:video_source) {FactoryGirl.create(:video_source, :connection => connection)} + + it "should create from a video source" do + recorded_video_source = RecordedVideo.create_from_video_source(video_source, recording) + recorded_video_source.should_not be_nil + recorded_video_source.user.id.should == video_source.connection.user.id + recorded_video_source.fully_uploaded.should == false + recorded_video_source.client_video_source_id.should == video_source.id + end + +end + diff --git a/ruby/spec/jam_ruby/models/video_source_spec.rb b/ruby/spec/jam_ruby/models/video_source_spec.rb index 02b9c4e1c..166443c22 100644 --- a/ruby/spec/jam_ruby/models/video_source_spec.rb +++ b/ruby/spec/jam_ruby/models/video_source_spec.rb @@ -6,6 +6,7 @@ describe VideoSource do let (:music_session) { FactoryGirl.create(:active_music_session, :creator => user)} let (:connection) { FactoryGirl.create(:connection, :user => user, :music_session => music_session) } let (:msuh) {FactoryGirl.create(:music_session_user_history, :history => music_session.music_session, :user => user, :client_id => connection.client_id) } + before(:each) do msuh.touch @@ -13,8 +14,8 @@ describe VideoSource do describe "simple create" do it "create a video source" do - track = FactoryGirl.create(:video_source, :connection => connection) - track.should_not be_nil + video_source = FactoryGirl.create(:video_source, :connection => connection) + video_source.should_not be_nil end end end \ No newline at end of file From 14c9a5b469023a4b680803248defd3aeb6222b39 Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Sun, 5 Oct 2014 22:12:50 -0400 Subject: [PATCH 03/19] VRFS-2278 show tooltip for instrument icons on Find Session and Session Detail screens, show user friendly error when unable to approve RSVP --- ruby/lib/jam_ruby/models/rsvp_request.rb | 2 +- .../javascripts/accounts_session_detail.js | 24 +++++++++++++++---- web/app/assets/javascripts/findSession.js | 3 +++ web/app/assets/javascripts/jamkazam.js | 4 ++-- web/app/assets/javascripts/sessionList.js | 4 ++-- web/app/assets/javascripts/utils.js | 3 +++ 6 files changed, 30 insertions(+), 10 deletions(-) diff --git a/ruby/lib/jam_ruby/models/rsvp_request.rb b/ruby/lib/jam_ruby/models/rsvp_request.rb index 689aad72e..f30851efe 100644 --- a/ruby/lib/jam_ruby/models/rsvp_request.rb +++ b/ruby/lib/jam_ruby/models/rsvp_request.rb @@ -182,7 +182,7 @@ module JamRuby end if rsvp_slot.chosen && r[:accept] - raise StateError, "The #{rsvp_slot.instrument_id} slot has already been approved for another user." + raise StateError, "All RSVP slots for the #{rsvp_slot.instrument_id} have been already approved." end if r[:accept] diff --git a/web/app/assets/javascripts/accounts_session_detail.js b/web/app/assets/javascripts/accounts_session_detail.js index c43a8b537..a93d0b1c7 100644 --- a/web/app/assets/javascripts/accounts_session_detail.js +++ b/web/app/assets/javascripts/accounts_session_detail.js @@ -101,7 +101,18 @@ rest.updateRsvpRequest(rsvpId, params) .done(refreshSessionDetail) - .fail(app.ajaxError); + .fail(function(jqXHR, textStatus, errorMessage) { + if (jqXHR.status === 400) { + app.notify( + { + title: "Unable to Approve RSVP", + text: jqXHR.responseJSON.message + }); + } + else { + app.ajaxError(jqXHR, textStatus, errorMessage); + } + }); } function declineRsvpRequest(e) { @@ -132,6 +143,9 @@ }); context.JK.bindHoverEvents(); + // context.JK.bindInstrumentHover($('#pendingRSVPs')); + // context.JK.bindInstrumentHover($('#session-rsvps')); + // context.JK.bindInstrumentHover($('#still-needed')); } function loadSessionData() { @@ -243,7 +257,7 @@ $.each(pending_rsvp_request.instrument_list, function (index, instrument) { var instrumentId = instrument == null ? null : instrument.id; var inst = context.JK.getInstrumentIcon24(instrumentId); - instrumentLogoHtml += ' '; + instrumentLogoHtml += ' '; }) } @@ -281,7 +295,7 @@ $.each(approved_rsvp.instrument_list, function(index, instrument) { var instrumentId = instrument == null ? null : instrument.id; var inst = context.JK.getInstrumentIcon24(instrumentId); - instrumentLogoHtml += ' '; + instrumentLogoHtml += ' '; }); } @@ -312,7 +326,7 @@ rsvpHtml = context._.template( $("#template-account-session-rsvp").html(), - {id: approved_rsvp.id, user_id: approved_rsvp.user_id, avatar_url: avatar_url, + {id: approved_rsvp.id, avatar_url: avatar_url, user_name: approved_rsvp.name, instruments: instrumentLogoHtml, latency: latencyHtml, is_owner: sessionData.isOwner, request_id: request_id}, {variable: 'data'} @@ -346,7 +360,7 @@ resultHtml += context._.template( $("#template-account-invited").html(), - {avatar_url: avatar_url, user_id: invitation.reciever_id}, + {avatar_url: avatar_url, user_id: invitation.receiver_id}, {variable: 'data'} ); }); diff --git a/web/app/assets/javascripts/findSession.js b/web/app/assets/javascripts/findSession.js index df765fb3a..98db4761f 100644 --- a/web/app/assets/javascripts/findSession.js +++ b/web/app/assets/javascripts/findSession.js @@ -85,6 +85,9 @@ context.JK.bindHoverEvents(); $ssSpinner.hide(); }); + + // context.JK.bindInstrumentHover($(CATEGORY.ACTIVE.id)); + // context.JK.bindInstrumentHover($(CATEGORY.SCHEDULED.id)); } /***************** ACTIVE SESSIONS *****************/ diff --git a/web/app/assets/javascripts/jamkazam.js b/web/app/assets/javascripts/jamkazam.js index 08d79d34a..d8fb6e4aa 100644 --- a/web/app/assets/javascripts/jamkazam.js +++ b/web/app/assets/javascripts/jamkazam.js @@ -123,11 +123,11 @@ */ function ajaxError(jqXHR, textStatus, errorMessage) { - if (jqXHR.status == 404) { + if (jqXHR.status === 404) { logger.error("Unexpected ajax error: " + textStatus + ", msg:" + errorMessage); app.notify({title: "Oops!", text: "What you were looking for is gone now."}); } - else if (jqXHR.status = 422) { + else if (jqXHR.status === 422) { logger.error("Unexpected ajax error: " + textStatus + ", msg: " + errorMessage + ", response: " + jqXHR.responseText); // present a nicer message try { diff --git a/web/app/assets/javascripts/sessionList.js b/web/app/assets/javascripts/sessionList.js index 06d26efa6..d58218dbf 100644 --- a/web/app/assets/javascripts/sessionList.js +++ b/web/app/assets/javascripts/sessionList.js @@ -369,7 +369,7 @@ var track = participant.tracks[j]; logger.debug("Find:Finding instruments. Participant tracks:", participant.tracks); var inst = context.JK.getInstrumentIcon24(track.instrument_id); - instrumentLogoHtml += ' '; + instrumentLogoHtml += ' '; } var id = participant.user.id; @@ -400,7 +400,7 @@ for (j=0; j < user.instrument_list.length; j++) { var instrument = user.instrument_list[j]; var inst = context.JK.getInstrumentIcon24(instrument.id); - instrumentLogoHtml += ' '; + instrumentLogoHtml += ' '; } } diff --git a/web/app/assets/javascripts/utils.js b/web/app/assets/javascripts/utils.js index b83d901c7..2afdd2f53 100644 --- a/web/app/assets/javascripts/utils.js +++ b/web/app/assets/javascripts/utils.js @@ -239,6 +239,9 @@ var instrumentId = $element.attr('data-instrument-id'); if(instrumentId) { + if (instrumentId === "null") { + instrumentId = "not specified"; + } context.JK.hoverBubble($element, instrumentId, options); } else { From 7856e43f1e93afaf4b5c4b775f97921e586cb82b Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Mon, 6 Oct 2014 09:20:31 -0400 Subject: [PATCH 04/19] VRFS-2219 active sessions should sort to top of Feed --- db/manifest | 2 +- db/up/add_active_feed.rb | 1 + ruby/lib/jam_ruby/models/feed.rb | 6 ++--- ruby/lib/jam_ruby/models/music_session.rb | 7 ++++++ ruby/spec/jam_ruby/models/feed_spec.rb | 25 +++++++++++-------- .../controllers/api_feeds_controller_spec.rb | 2 ++ 6 files changed, 28 insertions(+), 15 deletions(-) create mode 100644 db/up/add_active_feed.rb diff --git a/db/manifest b/db/manifest index ae595ece9..5e0250284 100755 --- a/db/manifest +++ b/db/manifest @@ -216,4 +216,4 @@ fix_find_session_sorting_2216c.sql entabulate_current_network_scores.sql discard_scores_changed.sql emails_from_update.sql - +add_active_feed.rb \ No newline at end of file diff --git a/db/up/add_active_feed.rb b/db/up/add_active_feed.rb new file mode 100644 index 000000000..725b36ec6 --- /dev/null +++ b/db/up/add_active_feed.rb @@ -0,0 +1 @@ +alter table feeds add column active BOOLEAN DEFAULT FALSE; \ No newline at end of file diff --git a/ruby/lib/jam_ruby/models/feed.rb b/ruby/lib/jam_ruby/models/feed.rb index cd68b8bd4..c2448e511 100644 --- a/ruby/lib/jam_ruby/models/feed.rb +++ b/ruby/lib/jam_ruby/models/feed.rb @@ -47,13 +47,13 @@ module JamRuby # handle sort if sort == 'date' query = query.where("feeds.id < #{start}") - query = query.order('feeds.id DESC') + query = query.order('feeds.active DESC, feeds.id DESC') elsif sort == 'plays' query = query.offset(start) - query = query.order("COALESCE(recordings.play_count, music_sessions.play_count) DESC ") + query = query.order("feeds.active DESC, COALESCE(recordings.play_count, music_sessions.play_count) DESC") elsif sort == 'likes' query = query.offset(start) - query = query.order("COALESCE(recordings.like_count, music_sessions.like_count) DESC ") + query = query.order("feeds.active DESC, COALESCE(recordings.like_count, music_sessions.like_count) DESC") else raise "sort not implemented: #{sort}" end diff --git a/ruby/lib/jam_ruby/models/music_session.rb b/ruby/lib/jam_ruby/models/music_session.rb index 67e3eebe2..0095eb652 100644 --- a/ruby/lib/jam_ruby/models/music_session.rb +++ b/ruby/lib/jam_ruby/models/music_session.rb @@ -74,6 +74,7 @@ module JamRuby def add_to_feed feed = Feed.new feed.music_session = self + feed.active = true end @@ -604,6 +605,12 @@ module JamRuby hist.end_history if hist + feed = Feed.find_by_music_session_id(session_id) + unless feed.nil? + feed.active = false + feed.save + end + Notification.send_session_ended(session_id) end diff --git a/ruby/spec/jam_ruby/models/feed_spec.rb b/ruby/spec/jam_ruby/models/feed_spec.rb index dc790f13c..a0ec224da 100644 --- a/ruby/spec/jam_ruby/models/feed_spec.rb +++ b/ruby/spec/jam_ruby/models/feed_spec.rb @@ -54,16 +54,16 @@ describe Feed do end describe "sorting" do - it "sorts by index (date) DESC" do + it "sorts by active flag / index (date) DESC" do claimed_recording = FactoryGirl.create(:claimed_recording) feeds, start = Feed.index(user1) feeds.length.should == 2 - feeds[0].recording.should == claimed_recording.recording - feeds[1].music_session.should == claimed_recording.recording.music_session.music_session + feeds[1].recording.should == claimed_recording.recording + feeds[0].music_session.should == claimed_recording.recording.music_session.music_session end - it "sort by plays DESC" do + it "sort by active flag / plays DESC" do claimed_recording1 = FactoryGirl.create(:claimed_recording) claimed_recording2 = FactoryGirl.create(:claimed_recording) @@ -77,8 +77,8 @@ describe Feed do feeds, start = Feed.index(user1, :sort => 'plays') feeds.length.should == 4 - feeds[0].recording.should == claimed_recording2.recording - feeds[1].recording.should == claimed_recording1.recording + feeds[2].recording.should == claimed_recording2.recording + feeds[3].recording.should == claimed_recording1.recording FactoryGirl.create(:playable_play, playable: claimed_recording1.recording.music_session.music_session, user: user1) FactoryGirl.create(:playable_play, playable: claimed_recording1.recording.music_session.music_session, user: user2) @@ -88,11 +88,11 @@ describe Feed do feeds, start = Feed.index(user1, :sort => 'plays') feeds.length.should == 4 feeds[0].music_session.should == claimed_recording1.recording.music_session.music_session - feeds[1].recording.should == claimed_recording2.recording - feeds[2].recording.should == claimed_recording1.recording + feeds[2].recording.should == claimed_recording2.recording + feeds[3].recording.should == claimed_recording1.recording end - it "sort by likes DESC" do + it "sort by active flag / likes DESC" do claimed_recording1 = FactoryGirl.create(:claimed_recording) claimed_recording2 = FactoryGirl.create(:claimed_recording) @@ -106,6 +106,7 @@ describe Feed do feeds, start = Feed.index(user1, :sort => 'likes') feeds.length.should == 4 + feeds = feeds.where("feeds.music_session_id is null") feeds[0].recording.should == claimed_recording2.recording feeds[1].recording.should == claimed_recording1.recording @@ -116,8 +117,8 @@ describe Feed do feeds, start = Feed.index(user1, :sort => 'likes') feeds.length.should == 4 feeds[0].music_session.should == claimed_recording1.recording.music_session.music_session - feeds[1].recording.should == claimed_recording2.recording - feeds[2].recording.should == claimed_recording1.recording + feeds[2].recording.should == claimed_recording2.recording + feeds[3].recording.should == claimed_recording1.recording end end @@ -195,6 +196,8 @@ describe Feed do it "supports date pagination" do claimed_recording = FactoryGirl.create(:claimed_recording) + MusicSession.removed_music_session(claimed_recording.recording.music_session.music_session.id) + options = {limit: 1} feeds, start = Feed.index(user1, options) feeds.length.should == 1 diff --git a/web/spec/controllers/api_feeds_controller_spec.rb b/web/spec/controllers/api_feeds_controller_spec.rb index e6b73e23f..2437e5d14 100644 --- a/web/spec/controllers/api_feeds_controller_spec.rb +++ b/web/spec/controllers/api_feeds_controller_spec.rb @@ -94,6 +94,8 @@ describe ApiFeedsController do claimed_recording.recording.created_at = 3.days.ago claimed_recording.recording.save! + MusicSession.removed_music_session(claimed_recording.recording.music_session.music_session.id) + get :index, { limit: 1 } json = JSON.parse(response.body, :symbolize_names => true) json[:entries].length.should == 1 From 993074b136d5799a36f7fe2acbba4746c0007553 Mon Sep 17 00:00:00 2001 From: Seth Call Date: Mon, 6 Oct 2014 09:36:55 -0500 Subject: [PATCH 05/19] * pinning back devise --- ruby/Gemfile | 2 +- web/Gemfile | 2 +- websocket-gateway/Gemfile | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ruby/Gemfile b/ruby/Gemfile index 8352f613f..8457d4649 100644 --- a/ruby/Gemfile +++ b/ruby/Gemfile @@ -31,7 +31,7 @@ gem 'sendgrid', '1.2.0' gem 'aws-sdk' #, '1.29.1' gem 'carrierwave', '0.9.0' gem 'aasm', '3.0.16' -gem 'devise', '>= 1.1.2' +gem 'devise', '3.3.0' # 3.4.0 causes: uninitialized constant ActionController::Metal (NameError) gem 'postgres-copy' gem 'geokit' gem 'geokit-rails' diff --git a/web/Gemfile b/web/Gemfile index ad080e413..2f263ec0a 100644 --- a/web/Gemfile +++ b/web/Gemfile @@ -55,7 +55,7 @@ gem 'carrierwave_direct' gem 'fog' gem 'haml-rails' gem 'unf' #optional fog dependency -gem 'devise', '>= 1.1.2' +gem 'devise', '3.3.0' #3.4.0 causes uninitialized constant ActionController::Metal (NameError) gem 'postgres-copy' #group :libv8 do # gem 'libv8', "~> 3.11.8" diff --git a/websocket-gateway/Gemfile b/websocket-gateway/Gemfile index b0f63d310..06d45c942 100644 --- a/websocket-gateway/Gemfile +++ b/websocket-gateway/Gemfile @@ -34,7 +34,7 @@ gem 'rb-readline' gem 'aasm', '3.0.16' gem 'carrierwave' gem 'fog' -gem 'devise' +gem 'devise', '3.3.0' # 3.4.0 causes uninitialized constant ActionController::Metal (NameError) gem 'postgres-copy' gem 'aws-sdk' #, '1.29.1' gem 'bugsnag' From 2d71a12a79f3a6c3237920b3cfe7d9c014322d21 Mon Sep 17 00:00:00 2001 From: Seth Call Date: Mon, 6 Oct 2014 14:53:50 -0500 Subject: [PATCH 06/19] * pinning back oj for now --- web/Gemfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/Gemfile b/web/Gemfile index 2f263ec0a..c97941bd1 100644 --- a/web/Gemfile +++ b/web/Gemfile @@ -18,7 +18,7 @@ else gem 'jam_websockets', "0.1.#{ENV["BUILD_NUMBER"]}" ENV['NOKOGIRI_USE_SYSTEM_LIBRARIES'] ||= "true" end -gem 'oj' +gem 'oj', '2.10.2' gem 'builder' gem 'rails', '~>3.2.11' gem 'railties', '~>3.2.11' From dffdb78f71da23b03e1688e2bae0f01d56587d4d Mon Sep 17 00:00:00 2001 From: Steven Miers Date: Mon, 6 Oct 2014 16:17:36 -0500 Subject: [PATCH 07/19] Merge develop into this branch. --- db/manifest | 2 ++ db/up/add_active_feed.sql | 1 + db/up/emails_from_update.sql | 2 ++ ruby/Gemfile | 2 +- ruby/lib/jam_ruby/app/mailers/corp_mailer.rb | 2 +- .../app/mailers/invited_user_mailer.rb | 2 +- ruby/lib/jam_ruby/app/mailers/user_mailer.rb | 2 +- .../progress_mailer/gear_notsess.html.erb | 2 +- .../progress_mailer/reg_notconnect.html.erb | 2 +- .../user_mailer/friend_request.html.erb | 2 +- .../user_mailer/new_musicians.html.erb | 2 +- .../user_mailer/password_reset.text.erb | 2 +- .../scheduled_session_daily.html.erb | 4 +-- .../user_mailer/text_message.html.erb | 4 +-- ruby/lib/jam_ruby/models/email_batch.rb | 2 +- ruby/lib/jam_ruby/models/feed.rb | 6 ++--- ruby/lib/jam_ruby/models/rsvp_request.rb | 2 +- ruby/spec/jam_ruby/models/feed_spec.rb | 25 +++++++++++-------- web/Gemfile | 4 +-- .../javascripts/accounts_session_detail.js | 24 +++++++++++++++--- web/app/assets/javascripts/findSession.js | 3 +++ web/app/assets/javascripts/jamkazam.js | 4 +-- web/app/assets/javascripts/sessionList.js | 4 +-- web/app/assets/javascripts/utils.js | 18 +++++++++++++ .../stylesheets/client/account.css.scss | 1 - .../stylesheets/dialogs/base_dialog.css.scss | 1 - .../clients/_account_session_detail.html.haml | 4 +-- .../controllers/api_feeds_controller_spec.rb | 2 ++ websocket-gateway/Gemfile | 2 +- 29 files changed, 89 insertions(+), 44 deletions(-) create mode 100644 db/up/add_active_feed.sql create mode 100644 db/up/emails_from_update.sql diff --git a/db/manifest b/db/manifest index 9407c2a3f..4ec0efd8d 100755 --- a/db/manifest +++ b/db/manifest @@ -215,5 +215,7 @@ fix_find_session_sorting_2216b.sql fix_find_session_sorting_2216c.sql entabulate_current_network_scores.sql discard_scores_changed.sql +emails_from_update.sql +add_active_feed.sql video_sources.sql recorded_videos.sql diff --git a/db/up/add_active_feed.sql b/db/up/add_active_feed.sql new file mode 100644 index 000000000..725b36ec6 --- /dev/null +++ b/db/up/add_active_feed.sql @@ -0,0 +1 @@ +alter table feeds add column active BOOLEAN DEFAULT FALSE; \ No newline at end of file diff --git a/db/up/emails_from_update.sql b/db/up/emails_from_update.sql new file mode 100644 index 000000000..a06e645ec --- /dev/null +++ b/db/up/emails_from_update.sql @@ -0,0 +1,2 @@ +ALTER TABLE email_batches ALTER from_email SET DEFAULT 'JamKazam '; + diff --git a/ruby/Gemfile b/ruby/Gemfile index 8352f613f..8457d4649 100644 --- a/ruby/Gemfile +++ b/ruby/Gemfile @@ -31,7 +31,7 @@ gem 'sendgrid', '1.2.0' gem 'aws-sdk' #, '1.29.1' gem 'carrierwave', '0.9.0' gem 'aasm', '3.0.16' -gem 'devise', '>= 1.1.2' +gem 'devise', '3.3.0' # 3.4.0 causes: uninitialized constant ActionController::Metal (NameError) gem 'postgres-copy' gem 'geokit' gem 'geokit-rails' diff --git a/ruby/lib/jam_ruby/app/mailers/corp_mailer.rb b/ruby/lib/jam_ruby/app/mailers/corp_mailer.rb index 0c829c149..1c9239c8b 100644 --- a/ruby/lib/jam_ruby/app/mailers/corp_mailer.rb +++ b/ruby/lib/jam_ruby/app/mailers/corp_mailer.rb @@ -11,7 +11,7 @@ module JamRuby layout "user_mailer" - DEFAULT_SENDER = "noreply@jamkazam.com" + DEFAULT_SENDER = "JamKazam " default :from => DEFAULT_SENDER diff --git a/ruby/lib/jam_ruby/app/mailers/invited_user_mailer.rb b/ruby/lib/jam_ruby/app/mailers/invited_user_mailer.rb index e01846424..ed772126b 100644 --- a/ruby/lib/jam_ruby/app/mailers/invited_user_mailer.rb +++ b/ruby/lib/jam_ruby/app/mailers/invited_user_mailer.rb @@ -9,7 +9,7 @@ module JamRuby class InvitedUserMailer < ActionMailer::Base include SendGrid - DEFAULT_SENDER = "noreply@jamkazam.com" + DEFAULT_SENDER = "JamKazam " default :from => DEFAULT_SENDER diff --git a/ruby/lib/jam_ruby/app/mailers/user_mailer.rb b/ruby/lib/jam_ruby/app/mailers/user_mailer.rb index dc1cc3a8d..ccc0cf52c 100644 --- a/ruby/lib/jam_ruby/app/mailers/user_mailer.rb +++ b/ruby/lib/jam_ruby/app/mailers/user_mailer.rb @@ -11,7 +11,7 @@ layout "user_mailer" - DEFAULT_SENDER = "noreply@jamkazam.com" + DEFAULT_SENDER = "JamKazam " default :from => DEFAULT_SENDER diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/gear_notsess.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/gear_notsess.html.erb index 43be52177..75b82aa15 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/gear_notsess.html.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/gear_notsess.html.erb @@ -10,7 +10,7 @@ It’s still very early in our company’s development, so we don’t have zillions of users online on our service yet. If you click Find Session, you will often not find a good session to join, both due to the number of musicians online at any given time, and also because you won’t see private sessions where groups of musicians don’t want to be interrupted in their sessions.

-

If you are having trouble getting into sessions, we’d suggest you click the Musicians tile on the home screen of the app or the website: Go To Musicians Page +

If you are having trouble getting into sessions, we’d suggest you click the Musicians tile on the home screen of the app or the website: Go To Musicians Page

This will display the JamKazam musicians sorted by latency to you - in other words, you can see which musicians have good network connections to you. Any musicians with green and yellow latency scores have good enough connections to support a play session with you. We recommend that read the profiles of these musicians to find others with shared musical interests and good network connections to you, and then use the Message button to say hi and see if they are interested in playing with you. If they are, use the Connect button to “friend” them on JamKazam, and use the Message button to set up a time to meet online for a session. diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/reg_notconnect.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/reg_notconnect.html.erb index 10eeeb0da..59254f3ab 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/reg_notconnect.html.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/reg_notconnect.html.erb @@ -7,7 +7,7 @@

Find Other Musicians on JamKazam
-To find and connect with other musicians who are already on JamKazam, we’d suggest you click the Musicians tile on the home screen of the app or the website: Go To Musicians Page +To find and connect with other musicians who are already on JamKazam, we’d suggest you click the Musicians tile on the home screen of the app or the website: Go To Musicians Page

This will display the JamKazam musicians sorted by latency to you - in other words, you can see which musicians have good network connections to you. Any musicians with green and yellow latency scores have good enough connections to support a play session with you. We recommend that you read the profiles of these musicians to find others with shared musical interests and good network connections to you, and then use the Message button to say hi and see if they are interested in playing with you. If they are, use the Connect button to “friend” them on JamKazam, and use the Message button to set up a time to meet online for a session. diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/friend_request.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/friend_request.html.erb index 81de23226..56b9c3623 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/friend_request.html.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/friend_request.html.erb @@ -2,4 +2,4 @@

<%= @body %>

-

To accept this friend request, click here.

\ No newline at end of file +

To accept this friend request, click here.

diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/new_musicians.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/new_musicians.html.erb index 8551c23df..bf5f12c0e 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/new_musicians.html.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/new_musicians.html.erb @@ -24,7 +24,7 @@ Hi <%= @user.first_name %>, <% end %>

-

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. +

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,

diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/password_reset.text.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/password_reset.text.erb index 4cbcc6646..7f4ae462d 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/password_reset.text.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/password_reset.text.erb @@ -1 +1 @@ -Visit this link so that you can change your JamKazam password: Reset Password. \ No newline at end of file +Visit this link so that you can change your JamKazam password: <%= @password_reset_url %>.. \ No newline at end of file diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_daily.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_daily.html.erb index 221c06839..5fb602b24 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_daily.html.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_daily.html.erb @@ -68,7 +68,7 @@ <%= sess.genre.description %> <%= sess.name %>
- ">Details + ">Details <%= sess.description %> @@ -86,7 +86,7 @@ -

To see ALL the scheduled sessions that you might be interested in joining, view our Find Session page.

+

To see ALL the scheduled sessions that you might be interested in joining, view our Find Session page.

Best Regards,

diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/text_message.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/text_message.html.erb index e18666bf3..cb083ca1b 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/text_message.html.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/text_message.html.erb @@ -4,5 +4,5 @@ <% content_for :note do %> <%= @note %> -

To reply to this message, click here.

-<% end %> \ No newline at end of file +

To reply to this message, click here.

+<% end %> diff --git a/ruby/lib/jam_ruby/models/email_batch.rb b/ruby/lib/jam_ruby/models/email_batch.rb index 06a248300..5fcc93543 100644 --- a/ruby/lib/jam_ruby/models/email_batch.rb +++ b/ruby/lib/jam_ruby/models/email_batch.rb @@ -12,7 +12,7 @@ module JamRuby VAR_FIRST_NAME = '@FIRSTNAME' VAR_LAST_NAME = '@LASTNAME' - DEFAULT_SENDER = "noreply@jamkazam.com" + DEFAULT_SENDER = "JamKazam " BATCH_SIZE = 500 BODY_TEMPLATE =< 'plays') feeds.length.should == 4 - feeds[0].recording.should == claimed_recording2.recording - feeds[1].recording.should == claimed_recording1.recording + feeds[2].recording.should == claimed_recording2.recording + feeds[3].recording.should == claimed_recording1.recording FactoryGirl.create(:playable_play, playable: claimed_recording1.recording.music_session.music_session, user: user1) FactoryGirl.create(:playable_play, playable: claimed_recording1.recording.music_session.music_session, user: user2) @@ -88,11 +88,11 @@ describe Feed do feeds, start = Feed.index(user1, :sort => 'plays') feeds.length.should == 4 feeds[0].music_session.should == claimed_recording1.recording.music_session.music_session - feeds[1].recording.should == claimed_recording2.recording - feeds[2].recording.should == claimed_recording1.recording + feeds[2].recording.should == claimed_recording2.recording + feeds[3].recording.should == claimed_recording1.recording end - it "sort by likes DESC" do + it "sort by active flag / likes DESC" do claimed_recording1 = FactoryGirl.create(:claimed_recording) claimed_recording2 = FactoryGirl.create(:claimed_recording) @@ -106,6 +106,7 @@ describe Feed do feeds, start = Feed.index(user1, :sort => 'likes') feeds.length.should == 4 + feeds = feeds.where("feeds.music_session_id is null") feeds[0].recording.should == claimed_recording2.recording feeds[1].recording.should == claimed_recording1.recording @@ -116,8 +117,8 @@ describe Feed do feeds, start = Feed.index(user1, :sort => 'likes') feeds.length.should == 4 feeds[0].music_session.should == claimed_recording1.recording.music_session.music_session - feeds[1].recording.should == claimed_recording2.recording - feeds[2].recording.should == claimed_recording1.recording + feeds[2].recording.should == claimed_recording2.recording + feeds[3].recording.should == claimed_recording1.recording end end @@ -195,6 +196,8 @@ describe Feed do it "supports date pagination" do claimed_recording = FactoryGirl.create(:claimed_recording) + MusicSession.removed_music_session(claimed_recording.recording.music_session.music_session.id) + options = {limit: 1} feeds, start = Feed.index(user1, options) feeds.length.should == 1 diff --git a/web/Gemfile b/web/Gemfile index ad080e413..c97941bd1 100644 --- a/web/Gemfile +++ b/web/Gemfile @@ -18,7 +18,7 @@ else gem 'jam_websockets', "0.1.#{ENV["BUILD_NUMBER"]}" ENV['NOKOGIRI_USE_SYSTEM_LIBRARIES'] ||= "true" end -gem 'oj' +gem 'oj', '2.10.2' gem 'builder' gem 'rails', '~>3.2.11' gem 'railties', '~>3.2.11' @@ -55,7 +55,7 @@ gem 'carrierwave_direct' gem 'fog' gem 'haml-rails' gem 'unf' #optional fog dependency -gem 'devise', '>= 1.1.2' +gem 'devise', '3.3.0' #3.4.0 causes uninitialized constant ActionController::Metal (NameError) gem 'postgres-copy' #group :libv8 do # gem 'libv8', "~> 3.11.8" diff --git a/web/app/assets/javascripts/accounts_session_detail.js b/web/app/assets/javascripts/accounts_session_detail.js index 65ec07db8..a93d0b1c7 100644 --- a/web/app/assets/javascripts/accounts_session_detail.js +++ b/web/app/assets/javascripts/accounts_session_detail.js @@ -101,7 +101,18 @@ rest.updateRsvpRequest(rsvpId, params) .done(refreshSessionDetail) - .fail(app.ajaxError); + .fail(function(jqXHR, textStatus, errorMessage) { + if (jqXHR.status === 400) { + app.notify( + { + title: "Unable to Approve RSVP", + text: jqXHR.responseJSON.message + }); + } + else { + app.ajaxError(jqXHR, textStatus, errorMessage); + } + }); } function declineRsvpRequest(e) { @@ -130,6 +141,11 @@ rsvpCancelDlg.initialize(); context.JK.app.layout.showDialog('rsvp-cancel-dialog'); }); + + context.JK.bindHoverEvents(); + // context.JK.bindInstrumentHover($('#pendingRSVPs')); + // context.JK.bindInstrumentHover($('#session-rsvps')); + // context.JK.bindInstrumentHover($('#still-needed')); } function loadSessionData() { @@ -241,7 +257,7 @@ $.each(pending_rsvp_request.instrument_list, function (index, instrument) { var instrumentId = instrument == null ? null : instrument.id; var inst = context.JK.getInstrumentIcon24(instrumentId); - instrumentLogoHtml += ' '; + instrumentLogoHtml += ' '; }) } @@ -279,7 +295,7 @@ $.each(approved_rsvp.instrument_list, function(index, instrument) { var instrumentId = instrument == null ? null : instrument.id; var inst = context.JK.getInstrumentIcon24(instrumentId); - instrumentLogoHtml += ' '; + instrumentLogoHtml += ' '; }); } @@ -344,7 +360,7 @@ resultHtml += context._.template( $("#template-account-invited").html(), - {avatar_url: avatar_url, user_id: invitation.reciever_id}, + {avatar_url: avatar_url, user_id: invitation.receiver_id}, {variable: 'data'} ); }); diff --git a/web/app/assets/javascripts/findSession.js b/web/app/assets/javascripts/findSession.js index df765fb3a..98db4761f 100644 --- a/web/app/assets/javascripts/findSession.js +++ b/web/app/assets/javascripts/findSession.js @@ -85,6 +85,9 @@ context.JK.bindHoverEvents(); $ssSpinner.hide(); }); + + // context.JK.bindInstrumentHover($(CATEGORY.ACTIVE.id)); + // context.JK.bindInstrumentHover($(CATEGORY.SCHEDULED.id)); } /***************** ACTIVE SESSIONS *****************/ diff --git a/web/app/assets/javascripts/jamkazam.js b/web/app/assets/javascripts/jamkazam.js index 08d79d34a..d8fb6e4aa 100644 --- a/web/app/assets/javascripts/jamkazam.js +++ b/web/app/assets/javascripts/jamkazam.js @@ -123,11 +123,11 @@ */ function ajaxError(jqXHR, textStatus, errorMessage) { - if (jqXHR.status == 404) { + if (jqXHR.status === 404) { logger.error("Unexpected ajax error: " + textStatus + ", msg:" + errorMessage); app.notify({title: "Oops!", text: "What you were looking for is gone now."}); } - else if (jqXHR.status = 422) { + else if (jqXHR.status === 422) { logger.error("Unexpected ajax error: " + textStatus + ", msg: " + errorMessage + ", response: " + jqXHR.responseText); // present a nicer message try { diff --git a/web/app/assets/javascripts/sessionList.js b/web/app/assets/javascripts/sessionList.js index 06d26efa6..d58218dbf 100644 --- a/web/app/assets/javascripts/sessionList.js +++ b/web/app/assets/javascripts/sessionList.js @@ -369,7 +369,7 @@ var track = participant.tracks[j]; logger.debug("Find:Finding instruments. Participant tracks:", participant.tracks); var inst = context.JK.getInstrumentIcon24(track.instrument_id); - instrumentLogoHtml += ' '; + instrumentLogoHtml += ' '; } var id = participant.user.id; @@ -400,7 +400,7 @@ for (j=0; j < user.instrument_list.length; j++) { var instrument = user.instrument_list[j]; var inst = context.JK.getInstrumentIcon24(instrument.id); - instrumentLogoHtml += ' '; + instrumentLogoHtml += ' '; } } diff --git a/web/app/assets/javascripts/utils.js b/web/app/assets/javascripts/utils.js index 904b12084..2afdd2f53 100644 --- a/web/app/assets/javascripts/utils.js +++ b/web/app/assets/javascripts/utils.js @@ -232,6 +232,24 @@ }); } + context.JK.bindInstrumentHover = function($parent, options) { + context._.each($parent.find("[hoveraction='instrument']"), function(element) { + var $element = $(element); + + var instrumentId = $element.attr('data-instrument-id'); + + if(instrumentId) { + if (instrumentId === "null") { + instrumentId = "not specified"; + } + context.JK.hoverBubble($element, instrumentId, options); + } + else { + logger.warn("no instrument-id on hoveraction=instrument element") + } + }); + } + context.JK.bindHoverEvents = function ($parent) { var timeout = 300; var fadeoutValue = 100; diff --git a/web/app/assets/stylesheets/client/account.css.scss b/web/app/assets/stylesheets/client/account.css.scss index 4717dc86d..81d700c12 100644 --- a/web/app/assets/stylesheets/client/account.css.scss +++ b/web/app/assets/stylesheets/client/account.css.scss @@ -325,7 +325,6 @@ } td.rsvp-buttons { float:right; - width:242px; text-align:right; } diff --git a/web/app/assets/stylesheets/dialogs/base_dialog.css.scss b/web/app/assets/stylesheets/dialogs/base_dialog.css.scss index a4d5e964c..4a183d9d3 100644 --- a/web/app/assets/stylesheets/dialogs/base_dialog.css.scss +++ b/web/app/assets/stylesheets/dialogs/base_dialog.css.scss @@ -6,7 +6,6 @@ border: 1px solid $ColorScreenPrimary; color: #fff; min-width: 400px; - min-height: 375px; z-index: 100; h2 { diff --git a/web/app/views/clients/_account_session_detail.html.haml b/web/app/views/clients/_account_session_detail.html.haml index 396dd2c24..28fc61218 100644 --- a/web/app/views/clients/_account_session_detail.html.haml +++ b/web/app/views/clients/_account_session_detail.html.haml @@ -85,7 +85,7 @@ %script{type: 'text/template', id: 'template-account-pending-rsvp'} %tr %td.avatar-cell - %a{href: "#", 'user-id' => "{{data.user_id}}", 'hoveraction' => "musician", class: 'avatar-tiny'} + %a{href: "/client#/profile/{{data.user_id}}", 'user-id' => "{{data.user_id}}", 'hoveraction' => "musician", class: 'avatar-tiny'} %img{src: "{{data.avatar_url}}"} %td {{data.user_name}} @@ -103,7 +103,7 @@ %script{type: 'text/template', id: 'template-account-session-rsvp'} %tr %td.avatar-cell - %a{href: "#", 'user-id' => "{{data.user_id}}", 'hoveraction' => "musician", class: 'avatar-tiny'} + %a{href: "/client#/profile/{{data.id}}", 'user-id' => "{{data.id}}", 'hoveraction' => "musician", class: 'avatar-tiny'} %img{src: "{{data.avatar_url}}"} %td {{data.user_name}} diff --git a/web/spec/controllers/api_feeds_controller_spec.rb b/web/spec/controllers/api_feeds_controller_spec.rb index e6b73e23f..2437e5d14 100644 --- a/web/spec/controllers/api_feeds_controller_spec.rb +++ b/web/spec/controllers/api_feeds_controller_spec.rb @@ -94,6 +94,8 @@ describe ApiFeedsController do claimed_recording.recording.created_at = 3.days.ago claimed_recording.recording.save! + MusicSession.removed_music_session(claimed_recording.recording.music_session.music_session.id) + get :index, { limit: 1 } json = JSON.parse(response.body, :symbolize_names => true) json[:entries].length.should == 1 diff --git a/websocket-gateway/Gemfile b/websocket-gateway/Gemfile index b0f63d310..06d45c942 100644 --- a/websocket-gateway/Gemfile +++ b/websocket-gateway/Gemfile @@ -34,7 +34,7 @@ gem 'rb-readline' gem 'aasm', '3.0.16' gem 'carrierwave' gem 'fog' -gem 'devise' +gem 'devise', '3.3.0' # 3.4.0 causes uninitialized constant ActionController::Metal (NameError) gem 'postgres-copy' gem 'aws-sdk' #, '1.29.1' gem 'bugsnag' From 47490ea3d90d55cb9b8e4b260dbb6ee6a37a64d9 Mon Sep 17 00:00:00 2001 From: Steven Miers Date: Mon, 6 Oct 2014 16:17:46 -0500 Subject: [PATCH 08/19] VRFS-2025 Incremental --- ruby/lib/jam_ruby/connection_manager.rb | 4 ++-- .../jam_ruby/models/active_music_session.rb | 6 ++--- ruby/lib/jam_ruby/models/connection.rb | 22 ++++++++++++++++++- ruby/lib/jam_ruby/models/music_session.rb | 7 ++++++ ruby/spec/jam_ruby/models/connection_spec.rb | 4 ++++ 5 files changed, 37 insertions(+), 6 deletions(-) diff --git a/ruby/lib/jam_ruby/connection_manager.rb b/ruby/lib/jam_ruby/connection_manager.rb index e8349c97d..95c4ba91d 100644 --- a/ruby/lib/jam_ruby/connection_manager.rb +++ b/ruby/lib/jam_ruby/connection_manager.rb @@ -321,7 +321,7 @@ SQL end end - def join_music_session(user, client_id, music_session, as_musician, tracks, audio_latency) + def join_music_session(user, client_id, music_session, as_musician, tracks, audio_latency, video_sources=nil) connection = nil ConnectionManager.active_record_transaction do |connection_manager| @@ -329,7 +329,7 @@ SQL connection = Connection.find_by_client_id_and_user_id!(client_id, user.id) - connection.join_the_session(music_session, as_musician, tracks, user, audio_latency) + connection.join_the_session(music_session, as_musician, tracks, user, audio_latency, video_sources) # connection.music_session_id = music_session.id # connection.as_musician = as_musician # connection.joining_session = true diff --git a/ruby/lib/jam_ruby/models/active_music_session.rb b/ruby/lib/jam_ruby/models/active_music_session.rb index c594655d2..f3e08bcf9 100644 --- a/ruby/lib/jam_ruby/models/active_music_session.rb +++ b/ruby/lib/jam_ruby/models/active_music_session.rb @@ -447,7 +447,7 @@ module JamRuby [music_sessions, user_scores] end - def self.participant_create user, music_session_id, client_id, as_musician, tracks, audio_latency + def self.participant_create(user, music_session_id, client_id, as_musician, tracks, audio_latency, video_sources=nil) music_session = MusicSession.find(music_session_id) if music_session.active_music_session @@ -458,7 +458,7 @@ module JamRuby active_music_session.with_lock do # VRFS-1297 active_music_session.tick_track_changes - connection = ConnectionManager.new.join_music_session(user, client_id, active_music_session, as_musician, tracks, audio_latency) + connection = ConnectionManager.new.join_music_session(user, client_id, active_music_session, as_musician, tracks, audio_latency, video_sources) if connection.errors.any? # rollback the transaction to make sure nothing is disturbed in the database @@ -515,7 +515,7 @@ module JamRuby # auto-join this user into the newly created session as_musician = true - connection = ConnectionManager.new.join_music_session(user, client_id, active_music_session, as_musician, tracks, audio_latency) + connection = ConnectionManager.new.join_music_session(user, client_id, active_music_session, as_musician, tracks, audio_latency, video_sources) unless connection.errors.any? user.update_progression_field(:first_music_session_at) diff --git a/ruby/lib/jam_ruby/models/connection.rb b/ruby/lib/jam_ruby/models/connection.rb index 9083b4543..a1092300e 100644 --- a/ruby/lib/jam_ruby/models/connection.rb +++ b/ruby/lib/jam_ruby/models/connection.rb @@ -163,12 +163,18 @@ module JamRuby true end - def join_the_session(music_session, as_musician, tracks, user, audio_latency) + # + def join_the_session(music_session, as_musician, tracks, user, audio_latency) + join_the_session(music_session, as_musician, tracks, nil, user, audio_latency) + end + + def join_the_session(music_session, as_musician, tracks, videos, user, audio_latency) self.music_session_id = music_session.id self.as_musician = as_musician self.joining_session = true self.joined_session_at = Time.now associate_tracks(tracks) unless tracks.nil? + associate_videos(videos) unless videos.nil? self.save # if user joins the session as a musician, update their addr and location @@ -193,6 +199,20 @@ module JamRuby end end + def associate_videos(videos) + unless videos.nil? + self.videos.clear() + videos.each do |video| + v = VideoSource.new + v.connection = self + v.sound = video["sound"] + v.client_video_source_id = video["client_video_source_id"] + v.save # todo what if it fails? + self.videos << v + end + end + end + def self.update_locidispids(use_copied = true) # using addr, we can rebuild locidispid diff --git a/ruby/lib/jam_ruby/models/music_session.rb b/ruby/lib/jam_ruby/models/music_session.rb index 67e3eebe2..0095eb652 100644 --- a/ruby/lib/jam_ruby/models/music_session.rb +++ b/ruby/lib/jam_ruby/models/music_session.rb @@ -74,6 +74,7 @@ module JamRuby def add_to_feed feed = Feed.new feed.music_session = self + feed.active = true end @@ -604,6 +605,12 @@ module JamRuby hist.end_history if hist + feed = Feed.find_by_music_session_id(session_id) + unless feed.nil? + feed.active = false + feed.save + end + Notification.send_session_ended(session_id) end diff --git a/ruby/spec/jam_ruby/models/connection_spec.rb b/ruby/spec/jam_ruby/models/connection_spec.rb index c391c7f29..fe1c69ed0 100644 --- a/ruby/spec/jam_ruby/models/connection_spec.rb +++ b/ruby/spec/jam_ruby/models/connection_spec.rb @@ -100,4 +100,8 @@ describe JamRuby::Connection do conn.locidispid.should == 0 end end + + describe "join_the_session" do + + end end From 71f6b7edc6ac2640e92065a650cf592b7ec153f8 Mon Sep 17 00:00:00 2001 From: Seth Call Date: Mon, 6 Oct 2014 16:44:30 -0500 Subject: [PATCH 09/19] * VRFS-2304 - create scoring timeout when doing a network test --- admin/Gemfile | 2 +- admin/app/admin/connections.rb | 1 + admin/app/admin/scoring_load.rb | 2 +- db/manifest | 3 +- db/up/connection_network_testing.sql | 44 +++++ ruby/lib/jam_ruby/connection_manager.rb | 2 +- ruby/lib/jam_ruby/models/connection.rb | 2 +- ruby/lib/jam_ruby/models/get_work.rb | 3 +- ruby/lib/jam_ruby/models/user.rb | 3 +- ruby/spec/jam_ruby/models/get_work_spec.rb | 10 + .../javascripts/dialog/networkTestDialog.js | 3 +- .../javascripts/everywhere/everywhere.js | 3 + web/app/assets/javascripts/fakeJamClient.js | 15 ++ web/app/assets/javascripts/jam_rest.js | 14 ++ .../assets/javascripts/networkTestHelper.js | 187 +++++++++++++----- .../wizard/gear/step_network_test.js | 2 + web/app/controllers/api_users_controller.rb | 13 +- web/config/application.rb | 2 + web/config/initializers/gon.rb | 1 + web/config/routes.rb | 1 + 20 files changed, 255 insertions(+), 58 deletions(-) create mode 100644 db/up/connection_network_testing.sql diff --git a/admin/Gemfile b/admin/Gemfile index 716543c5e..21e2c819a 100644 --- a/admin/Gemfile +++ b/admin/Gemfile @@ -117,4 +117,4 @@ end gem 'pry' gem 'pry-remote' gem 'pry-stack_explorer' -gem 'pry-debugger' +#gem 'pry-debugger' diff --git a/admin/app/admin/connections.rb b/admin/app/admin/connections.rb index b97e71164..92cfb668e 100644 --- a/admin/app/admin/connections.rb +++ b/admin/app/admin/connections.rb @@ -91,6 +91,7 @@ ActiveAdmin.register JamRuby::Connection, :as => 'Connection' do row :locidispid row :aasm_state row :udp_reachable + row :is_network_testing row :scoring_failures row :scoring_timeout_occurrences row :scoring_failures_offset diff --git a/admin/app/admin/scoring_load.rb b/admin/app/admin/scoring_load.rb index e020a4316..f6f3e3b2c 100644 --- a/admin/app/admin/scoring_load.rb +++ b/admin/app/admin/scoring_load.rb @@ -5,7 +5,7 @@ ActiveAdmin.register_page "Current Scoring Load" do table_for GetWork.summary do column "Work", :work_count column "Who", Proc.new { |connection| "#{connection.first_name} #{connection.last_name} - #{connection.email}" } - column "Errors", Proc.new { |connection| "#{connection.udp_reachable != false ? "" : "No STUN,"} #{connection.in_timeout != 'f' ? "Timeout," : ""} #{connection.in_session != 'f' ? "In-Session," : ""}" } + column "Errors", Proc.new { |connection| "#{connection.udp_reachable != false ? "" : "No STUN,"} #{connection.is_network_testing != false ? "NETWORK TESTING" : ""} #{connection.in_timeout != 'f' ? "Timeout," : ""} #{connection.in_session != 'f' ? "In-Session," : ""}" } column "Total Timeouts", :scoring_timeout_occurrences column "Current Scoring Failures", :scoring_failures column "Offset", :scoring_failures_offset diff --git a/db/manifest b/db/manifest index 5e0250284..076b72aa0 100755 --- a/db/manifest +++ b/db/manifest @@ -216,4 +216,5 @@ fix_find_session_sorting_2216c.sql entabulate_current_network_scores.sql discard_scores_changed.sql emails_from_update.sql -add_active_feed.rb \ No newline at end of file +add_active_feed.rb +connection_network_testing.sql \ No newline at end of file diff --git a/db/up/connection_network_testing.sql b/db/up/connection_network_testing.sql new file mode 100644 index 000000000..3cd9e78df --- /dev/null +++ b/db/up/connection_network_testing.sql @@ -0,0 +1,44 @@ +-- let the server know if the client is network testing. If so, then also remove them from work +ALTER TABLE connections ADD COLUMN is_network_testing BOOLEAN DEFAULT FALSE NOT NULL; + +DROP FUNCTION IF EXISTS get_work (my_client_id VARCHAR(64), mylocidispid BIGINT, myaddr BIGINT, return_rows INT, stale_score INTERVAL); +CREATE FUNCTION get_work (my_client_id VARCHAR(64), mylocidispid BIGINT, myaddr BIGINT, return_rows INT, stale_score INTERVAL) RETURNS TABLE (client_id VARCHAR(64)) VOLATILE AS $$ +BEGIN + RETURN QUERY WITH + scorable_locations AS ( + SELECT DISTINCT locidispid FROM connections WHERE client_type = 'client' AND connections.client_id != my_client_id AND addr != myaddr AND udp_reachable AND is_network_testing = FALSE AND NOW() > scoring_timeout AND connections.music_session_id IS NULL AND + locidispid NOT IN (SELECT DISTINCT blocidispid FROM most_recent_scores WHERE alocidispid = mylocidispid AND (current_timestamp - score_dt) < stale_score) AND + locidispid/1000000 IN (SELECT locid FROM geoiplocations WHERE geog && st_buffer((SELECT geog FROM geoiplocations WHERE locid = mylocidispid/1000000), 4023360)) + ) + + SELECT tmp.client_id FROM (SELECT connections.client_id, random() AS r, row_number() OVER (PARTITION BY connections.locidispid) AS rownum FROM connections, scorable_locations + WHERE connections.locidispid = scorable_locations.locidispid AND client_type = 'client' AND connections.client_id != my_client_id AND addr != myaddr AND udp_reachable AND NOW() > scoring_timeout AND connections.music_session_id IS NULL ) tmp WHERE rownum <= 1 ORDER BY r LIMIT return_rows; + + RETURN; + +END; +$$ LANGUAGE plpgsql; + + +DROP FUNCTION IF EXISTS get_work_summary (stale_score INTERVAL); +CREATE FUNCTION get_work_summary (stale_score INTERVAL) RETURNS TABLE (work_count BIGINT, client_id VARCHAR(64), email VARCHAR, first_name VARCHAR, last_name VARCHAR, user_id VARCHAR(64), udp_reachable BOOLEAN, in_timeout BOOLEAN, in_session BOOLEAN, scoring_failures INT, scoring_failures_offset INT, scoring_timeout_occurrences INT, is_network_testing BOOLEAN) VOLATILE AS $$ +BEGIN + RETURN QUERY + SELECT SUM(CASE WHEN tmp.test_client_id IS NULL OR tmp.in_session OR tmp.in_timeout OR tmp.udp_reachable = FALSE OR tmp.is_network_testing = TRUE THEN 0 ELSE 1 END) AS work_count, tmp.client_id AS client_id, users.email, users.first_name, users.last_name, users.id AS user_id, tmp.udp_reachable, tmp.in_timeout, tmp.in_session, tmp.scoring_failures, tmp.scoring_failures_offset, tmp.scoring_timeout_occurrences, tmp.is_network_testing FROM + (SELECT connections.client_type, scorable_locations.client_id AS test_client_id, connections.client_id AS client_id, connections.user_id AS user_id, connections.udp_reachable, connections.scoring_timeout > NOW() as in_timeout, connections.music_session_id IS NOT NULL AS in_session, connections.scoring_failures, connections.scoring_failures_offset, connections.scoring_timeout_occurrences, connections.is_network_testing, scorable_locations.client_id IS NULL AS same_client, row_number() OVER (PARTITION BY connections.locidispid) AS rownum FROM connections LEFT OUTER JOIN scorable_locations(connections.client_id, connections.locidispid, connections.addr, stale_score) + ON connections.locidispid != scorable_locations.locidispid) tmp INNER JOIN users ON tmp.user_id = users.id WHERE tmp.client_type = 'client' GROUP BY tmp.client_id, users.email, users.first_name, users.last_name, users.id, tmp.same_client, tmp.udp_reachable, tmp.in_timeout, tmp.in_session, tmp.scoring_failures, tmp.scoring_failures_offset, tmp.scoring_timeout_occurrences, tmp.is_network_testing ORDER BY work_count DESC; + RETURN; +END; +$$ LANGUAGE plpgsql; + +DROP FUNCTION IF EXISTS get_work_summary_no_agg(stale_score INTERVAL); +-- useful for debugging get_work_summary +CREATE FUNCTION get_work_summary_no_agg (stale_score INTERVAL) RETURNS TABLE (client_id VARCHAR(64), test_client_id VARCHAR(64), email VARCHAR, first_name VARCHAR, last_name VARCHAR, user_id VARCHAR(64), udp_reachable BOOLEAN, in_timeout BOOLEAN, scoring_failures INT, scoring_failures_offset INT, scoring_timeout_occurrences INT, is_network_testing BOOLEAN) VOLATILE AS $$ +BEGIN + RETURN QUERY + SELECT tmp.client_id AS client_id, tmp.test_client_id, users.email, users.first_name, users.last_name, users.id AS user_id, tmp.udp_reachable, tmp.in_timeout, tmp.scoring_failures, tmp.scoring_failures_offset, tmp.scoring_timeout_occurrences, tmp.is_network_testing FROM + (SELECT scorable_locations.client_id AS test_client_id, connections.client_id AS client_id, connections.user_id AS user_id, connections.udp_reachable, connections.scoring_timeout > NOW() as in_timeout, connections.scoring_failures, connections.scoring_failures_offset, connections.scoring_timeout_occurrences, connections.is_network_testing, scorable_locations.client_id IS NULL AS same_client, row_number() OVER (PARTITION BY connections.locidispid) AS rownum FROM connections LEFT OUTER JOIN scorable_locations(connections.client_id, connections.locidispid, connections.addr, stale_score) + ON connections.locidispid != scorable_locations.locidispid AND connections.client_type = 'client') tmp INNER JOIN users ON tmp.user_id = users.id ORDER BY tmp.client_id; + RETURN; +END; +$$ LANGUAGE plpgsql; \ No newline at end of file diff --git a/ruby/lib/jam_ruby/connection_manager.rb b/ruby/lib/jam_ruby/connection_manager.rb index e8349c97d..9033bbe66 100644 --- a/ruby/lib/jam_ruby/connection_manager.rb +++ b/ruby/lib/jam_ruby/connection_manager.rb @@ -89,7 +89,7 @@ module JamRuby udp_reachable_value = udp_reachable.nil? ? 'udp_reachable' : udp_reachable sql =< "JamRuby::Track", :inverse_of => :connection, :foreign_key => 'connection_id', :dependent => :delete_all - validates :as_musician, :inclusion => {:in => [true, false]} + validates :as_musician, :inclusion => {:in => [true, false, nil]} validates :client_type, :inclusion => {:in => [TYPE_CLIENT, TYPE_BROWSER, TYPE_LATENCY_TESTER]} validates_numericality_of :last_jam_audio_latency, greater_than:0, :allow_nil => true validate :can_join_music_session, :if => :joining_session? diff --git a/ruby/lib/jam_ruby/models/get_work.rb b/ruby/lib/jam_ruby/models/get_work.rb index 8946770fd..df5003925 100644 --- a/ruby/lib/jam_ruby/models/get_work.rb +++ b/ruby/lib/jam_ruby/models/get_work.rb @@ -12,6 +12,7 @@ module JamRuby def self.get_work_list(connection, rows = 25, staleness_hours = 120) + return [] if connection.is_network_testing # short-circuit 0 results if is_network_testing return [] unless connection.udp_reachable # short-circuit 0 results if udp_reachable return [] if connection.scoring_timeout > Time.now # short-circuit 0 results if in scoring timeout return [] if connection.in_session? @@ -25,7 +26,7 @@ module JamRuby end def self.summary(staleness_hours = 120) - r = GetWork.select([:work_count, :client_id, :email, :first_name, :last_name, :user_id, :udp_reachable, :in_timeout, :in_session, :scoring_failures, :scoring_failures_offset, :scoring_timeout_occurrences]).find_by_sql("select work_count, client_id, email, first_name, last_name, user_id, udp_reachable, in_timeout, in_session, scoring_failures, scoring_failures_offset, scoring_timeout_occurrences FROM get_work_summary(INTERVAL '#{staleness_hours} hours')" ) + r = GetWork.select([:work_count, :client_id, :email, :first_name, :last_name, :user_id, :udp_reachable, :in_timeout, :in_session, :scoring_failures, :scoring_failures_offset, :scoring_timeout_occurrences, :is_network_testing]).find_by_sql("select work_count, client_id, email, first_name, last_name, user_id, udp_reachable, in_timeout, in_session, scoring_failures, scoring_failures_offset, scoring_timeout_occurrences, is_network_testing FROM get_work_summary(INTERVAL '#{staleness_hours} hours')" ) end end end diff --git a/ruby/lib/jam_ruby/models/user.rb b/ruby/lib/jam_ruby/models/user.rb index 9cdc68a1c..06d19d5a5 100644 --- a/ruby/lib/jam_ruby/models/user.rb +++ b/ruby/lib/jam_ruby/models/user.rb @@ -1271,8 +1271,7 @@ module JamRuby if audio_latency > 2 # updating the connection is best effort if connection - connection.last_jam_audio_latency = audio_latency - connection.save + Connection.where(:id => connection.id).update_all(:last_jam_audio_latency => audio_latency) end self.last_jam_audio_latency = audio_latency diff --git a/ruby/spec/jam_ruby/models/get_work_spec.rb b/ruby/spec/jam_ruby/models/get_work_spec.rb index b47b7041d..e05c6cb95 100644 --- a/ruby/spec/jam_ruby/models/get_work_spec.rb +++ b/ruby/spec/jam_ruby/models/get_work_spec.rb @@ -176,6 +176,16 @@ describe GetWork do GetWork.get_work_list(other_connection2).should == [my_connection.client_id] end + it "excludes network testing clients" do + my_connection = FactoryGirl.create(:connection, locidispid: austin_geo[:locidispid], addr: 1) + other_connection = FactoryGirl.create(:connection, locidispid: dallas_geo[:locidispid], addr: 2, is_network_testing: true) + other_connection2 = FactoryGirl.create(:connection, locidispid: houston_geoip[:locidispid], addr: 3) + + GetWork.get_work_list(my_connection).should == [other_connection2.client_id] + GetWork.get_work_list(other_connection).should == [] + GetWork.get_work_list(other_connection2).should == [my_connection.client_id] + end + it "excludes scoring_timeout clients (1)" do my_connection = FactoryGirl.create(:connection, locidispid: austin_geo[:locidispid], addr: 1) other_connection = FactoryGirl.create(:connection, locidispid: dallas_geo[:locidispid], addr: 2, scoring_timeout: 1.days.from_now) diff --git a/web/app/assets/javascripts/dialog/networkTestDialog.js b/web/app/assets/javascripts/dialog/networkTestDialog.js index 5d64ceb64..da0d7130e 100644 --- a/web/app/assets/javascripts/dialog/networkTestDialog.js +++ b/web/app/assets/javascripts/dialog/networkTestDialog.js @@ -54,13 +54,14 @@ } function beforeShow() { + networkTest.haltScoring(); if(!networkTest.isScoring()) { networkTest.reset(); } } function afterHide() { - + networkTest.resumeScoring(); } function initialize() { diff --git a/web/app/assets/javascripts/everywhere/everywhere.js b/web/app/assets/javascripts/everywhere/everywhere.js index e90049966..71fd1169a 100644 --- a/web/app/assets/javascripts/everywhere/everywhere.js +++ b/web/app/assets/javascripts/everywhere/everywhere.js @@ -140,6 +140,9 @@ } function updateScoringIntervals() { + // make sure latency testing is still going on, in case a refresh occurred during network test + context.jamClient.SetLatencyTestBlocked(false) + // set scoring intervals if(context.jamClient.SetScoreWorkTimingInterval){ var success = context.jamClient.SetScoreWorkTimingInterval( diff --git a/web/app/assets/javascripts/fakeJamClient.js b/web/app/assets/javascripts/fakeJamClient.js index f6af7789f..393501e1b 100644 --- a/web/app/assets/javascripts/fakeJamClient.js +++ b/web/app/assets/javascripts/fakeJamClient.js @@ -362,6 +362,18 @@ return 8; } + function SetLatencyTestBlocked(blocked) { + + } + + function isLatencyTestBlocked() { + return false; + } + + function GetLastLatencyTestTimes() { + return { initiated: 10000, requested: 10000} + } + function GetASIODevices() { var response =[{"device_id":0,"device_name":"Realtek High Definition Audio","device_type": 0,"interfaces":[{"interface_id":0,"interface_name":"Realtek HDA SPDIF Out","pins":[{"is_input":false,"pin_id":0,"pin_name":"PC Speaker"}]},{"interface_id":1,"interface_name":"Realtek HD Audio rear output","pins":[{"is_input":false,"pin_id":0,"pin_name":"PC Speaker"}]},{"interface_id":2,"interface_name":"Realtek HD Audio Mic input","pins":[{"is_input":true,"pin_id":0,"pin_name":"Recording Control"}]},{"interface_id":3,"interface_name":"Realtek HD Audio Line input","pins":[{"is_input":true,"pin_id":0,"pin_name":"Recording Control"}]},{"interface_id":4,"interface_name":"Realtek HD Digital input","pins":[{"is_input":true,"pin_id":0,"pin_name":"Capture"}]},{"interface_id":5,"interface_name":"Realtek HD Audio Stereo input","pins":[{"is_input":true,"pin_id":0,"pin_name":"Recording Control"}]}],"wavert_supported":false},{"device_id":1,"device_name":"M-Audio FW Audiophile","device_type": 1,"interfaces":[{"interface_id":0,"interface_name":"FW AP Multi","pins":[{"is_input":false,"pin_id":0,"pin_name":"Output"},{"is_input":true,"pin_id":1,"pin_name":"Input"}]},{"interface_id":1,"interface_name":"FW AP 1/2","pins":[{"is_input":false,"pin_id":0,"pin_name":"Output"},{"is_input":true,"pin_id":1,"pin_name":"Input"}]},{"interface_id":2,"interface_name":"FW AP SPDIF","pins":[{"is_input":false,"pin_id":0,"pin_name":"Output"},{"is_input":true,"pin_id":1,"pin_name":"Input"}]},{"interface_id":3,"interface_name":"FW AP 3/4","pins":[{"is_input":false,"pin_id":0,"pin_name":"Output"}]}],"wavert_supported":false},{"device_id":2,"device_name":"Virtual Audio Cable","device_type": 2,"interfaces":[{"interface_id":0,"interface_name":"Virtual Cable 2","pins":[{"is_input":true,"pin_id":0,"pin_name":"Capture"},{"is_input":false,"pin_id":1,"pin_name":"Output"}]},{"interface_id":1,"interface_name":"Virtual Cable 1","pins":[{"is_input":true,"pin_id":0,"pin_name":"Capture"},{"is_input":false,"pin_id":1,"pin_name":"Output"}]}],"wavert_supported":false},{"device_id":3,"device_name":"WebCamDV WDM Audio Capture","device_type": 3,"interfaces":[{"interface_id":0,"interface_name":"WebCamDV Audio","pins":[{"is_input":true,"pin_id":0,"pin_name":"Recording Control"},{"is_input":false,"pin_id":1,"pin_name":"Volume Control"}]}],"wavert_supported":false}]; return response; @@ -823,6 +835,9 @@ this.IsMyNetworkWireless = IsMyNetworkWireless; this.SetNetworkTestScore = SetNetworkTestScore; this.GetNetworkTestScore = GetNetworkTestScore; + this.SetLatencyTestBlocked = SetLatencyTestBlocked; + this.isLatencyTestBlocked = isLatencyTestBlocked; + this.GetLastLatencyTestTimes = GetLastLatencyTestTimes; this.RegisterQuitCallback = RegisterQuitCallback; this.LeaveSessionAndMinimize = LeaveSessionAndMinimize; this.GetAutoStart = GetAutoStart; diff --git a/web/app/assets/javascripts/jam_rest.js b/web/app/assets/javascripts/jam_rest.js index 3c1e95027..ff031af99 100644 --- a/web/app/assets/javascripts/jam_rest.js +++ b/web/app/assets/javascripts/jam_rest.js @@ -503,6 +503,19 @@ }); } + function updateNetworkTesting(options) { + var id = getId(options); + + return $.ajax({ + type: "POST", + dataType: "json", + contentType: 'application/json', + url: "/api/users/" + id + "/is_network_testing", + data: JSON.stringify(options), + processData: false + }); + } + function updateAvatar(options) { var id = getId(options); @@ -1222,6 +1235,7 @@ this.getInstruments = getInstruments; this.getGenres = getGenres; this.updateUdpReachable = updateUdpReachable; + this.updateNetworkTesting = updateNetworkTesting; this.updateAvatar = updateAvatar; this.deleteAvatar = deleteAvatar; this.getFilepickerPolicy = getFilepickerPolicy; diff --git a/web/app/assets/javascripts/networkTestHelper.js b/web/app/assets/javascripts/networkTestHelper.js index 0e6d3add8..601ecd860 100644 --- a/web/app/assets/javascripts/networkTestHelper.js +++ b/web/app/assets/javascripts/networkTestHelper.js @@ -167,6 +167,35 @@ return lastNetworkFailure; } + function haltScoring() { + context.jamClient.SetLatencyTestBlocked(true) + rest.updateNetworkTesting({client_id: app.clientId, is_network_testing: true}) + .fail(function(jqXHR) { + + if(jqXHR.status == 404) { + // assume connection is missing + app.notifyAlert("Not Connected", "You must be connected to the server to run the network test.") + } + else { + app.notifyServerError(jqXHR, "Unable to tell server that we are beginning the network test") + } + }) + } + + function resumeScoring() { + context.jamClient.SetLatencyTestBlocked(false) + rest.updateNetworkTesting({client_id: app.clientId, is_network_testing: false}) + .fail(function(jqXHR) { + if(jqXHR.status == 404) { + // assume connection is missing + // do nothing in this case + } + else { + app.notifyServerError(jqXHR, "Unable to tell server that we are ending the network test") + } + }) + } + function storeLastNetworkFailure(reason, data) { if (!trackedPass) { lastNetworkFailure = {reason: reason, data: data}; @@ -471,63 +500,125 @@ } } + function pauseForRecentScoresTime() { + var lastScoreTimes = context.jamClient.GetLastLatencyTestTimes() + + console.log(lastScoreTimes) + + return 0; + + var noPause = 0; + var longAgo = 1000000; + var initiated = lastScoreTimes.initiatied; + var requested = lastScoreTimes.requested; + + if(initiated === null || initiated === undefined) { + logger.warn("lastScoreTimes.initiated is not set"); + initiated = longAgo; + } + if(requested === null || requested === undefined) { + logger.warn("lastScoreTimes.requested is not set"); + requested = longAgo; + } + + if(initiated == 0) { + logger.debug("lastScoreTimes.initiated is zero"); + initiated = longAgo; + } + if(requested == 0) { + logger.debug("lastScoreTimes.requested is zero"); + requested = longAgo; + } + + if(initiated < 0) { + logger.debug("lastScoreTimes.initiated is less than zero"); + initiated = longAgo; + } + if(requested < 0) { + logger.debug("lastScoreTimes.requested is less than zero"); + requested = longAgo; + } + + var mostRecentValue = initiated < requested ? initiated : requested; + + if(mostRecentValue > gon.globalftue_network_test_min_wait_since_last_score * 1000) { + return noPause; // our last score was past our min wait; so no delay necessary + } + else { + // pause for the remainder of the min wait threshold + var remainder = gon.globalftue_network_test_min_wait_since_last_score * 1000 - mostRecentValue; + + if(remainder > 1500) { + // we need to update the UI because this is a long time for a mystery pause + $startNetworkTestBtn.text('SHORT QUIET PERIOD...') + } + + return remainder; + } + } function prepareNetworkTest() { if (scoring) return false; - logger.info("starting network test"); - resetTestState(); - scoring = true; - $self.triggerHandler(NETWORK_TEST_START); - renderStartTest(); - rest.getLatencyTester() - .done(function (response) { - // ensure there are no tests ongoing - serverClientId = response.client_id; - testSummary.serverClientId = serverClientId; + setTimeout(function() { - logger.info("beginning network test against client_id: " + serverClientId); + logger.info("starting network test"); + resetTestState(); + scoring = true; + $self.triggerHandler(NETWORK_TEST_START); + renderStartTest(); + rest.getLatencyTester() + .done(function (response) { + // ensure there are no tests ongoing - primePump() - .done(function () { - postPumpRun(); - }) - .fail(function () { - logger.debug("unable to determine user's network type. primePump failed.") - context.JK.Banner.showAlert({ - title: 'Unable to Determine Network Type', - buttons: [ - {name: 'CANCEL', click: function () { - cancelTest(); - }}, - {name: 'RUN NETWORK TEST ANYWAY', click: function () { - attemptTestPass(); - ; - }} - ], - html: "

We are unable to determine if your computer is connected to your network using WiFi.

" + - "

We strongly advise against running the JamKazam application on a WiFi connection. " + - "We recommend using a wired Ethernet connection from your computer to your router. " + - "A WiFi connection is likely to cause significant issues in both latency and audio quality.

"}) - }); - }) - .fail(function (jqXHR) { - if (jqXHR.status == 404) { - // means there are no network testers available. - // we have to skip this part of the UI - testSummary.final = {reason: 'no_servers'} - } - else { - if (context.JK.isNetworkError(arguments)) { - testSummary.final = {reason: 'no_network'} + serverClientId = response.client_id; + + testSummary.serverClientId = serverClientId; + + logger.info("beginning network test against client_id: " + serverClientId); + + primePump() + .done(function () { + postPumpRun(); + }) + .fail(function () { + logger.debug("unable to determine user's network type. primePump failed.") + context.JK.Banner.showAlert({ + title: 'Unable to Determine Network Type', + buttons: [ + {name: 'CANCEL', click: function () { + cancelTest(); + }}, + {name: 'RUN NETWORK TEST ANYWAY', click: function () { + attemptTestPass(); + ; + }} + ], + html: "

We are unable to determine if your computer is connected to your network using WiFi.

" + + "

We strongly advise against running the JamKazam application on a WiFi connection. " + + "We recommend using a wired Ethernet connection from your computer to your router. " + + "A WiFi connection is likely to cause significant issues in both latency and audio quality.

"}) + }); + }) + .fail(function (jqXHR) { + if (jqXHR.status == 404) { + // means there are no network testers available. + // we have to skip this part of the UI + testSummary.final = {reason: 'no_servers'} } else { - testSummary.final = {reason: 'rest_api_error'} + if (context.JK.isNetworkError(arguments)) { + testSummary.final = {reason: 'no_network'} + } + else { + testSummary.final = {reason: 'rest_api_error'} + } } - } - testFinished(); - }) + testFinished(); + }) + }, pauseForRecentScoresTime()) + return false; } @@ -844,6 +935,8 @@ this.reset = reset; this.cancel = cancel; this.getLastNetworkFailure = getLastNetworkFailure; + this.haltScoring = haltScoring; + this.resumeScoring = resumeScoring; this.NETWORK_TEST_START = NETWORK_TEST_START; this.NETWORK_TEST_DONE = NETWORK_TEST_DONE; diff --git a/web/app/assets/javascripts/wizard/gear/step_network_test.js b/web/app/assets/javascripts/wizard/gear/step_network_test.js index b82a622ae..17f28d06a 100644 --- a/web/app/assets/javascripts/wizard/gear/step_network_test.js +++ b/web/app/assets/javascripts/wizard/gear/step_network_test.js @@ -53,11 +53,13 @@ } function beforeShow() { + networkTest.haltScoring(); networkTest.cancel(); updateButtons(); } function beforeHide() { + networkTest.resumeScoring(); networkTest.cancel(); } diff --git a/web/app/controllers/api_users_controller.rb b/web/app/controllers/api_users_controller.rb index ddfcf4630..d296e334b 100644 --- a/web/app/controllers/api_users_controller.rb +++ b/web/app/controllers/api_users_controller.rb @@ -669,8 +669,17 @@ class ApiUsersController < ApiController def udp_reachable Connection.transaction do @connection = Connection.find_by_client_id!(params[:client_id]) - @connection.udp_reachable = params[:udp_reachable] - @connection.save + # deliberately don't updated_at on connection! only heartbeats do that + Connection.where(:id => @connection.id).update_all(:udp_reachable => params[:udp_reachable]) + respond_with_model(@connection) + end + end + + def is_network_testing + Connection.transaction do + @connection = Connection.find_by_client_id!(params[:client_id]) + # deliberately don't updated_at on connection! only heartbeats do that + Connection.where(:id => @connection.id).update_all(:is_network_testing => params[:is_network_testing]) respond_with_model(@connection) end end diff --git a/web/config/application.rb b/web/config/application.rb index 575654d27..6947079af 100644 --- a/web/config/application.rb +++ b/web/config/application.rb @@ -248,6 +248,8 @@ if defined?(Bundler) config.ftue_network_test_packet_size = 60 # number of times that the backend retries before giving up config.ftue_network_test_backend_retries = 10 + # amount of time that we want passed until we run the next network test + config.ftue_network_test_min_wait_since_last_score = 5 # the maximum amount of allowable latency config.ftue_maximum_gear_latency = 20 diff --git a/web/config/initializers/gon.rb b/web/config/initializers/gon.rb index e2b1feb79..567b1e8e0 100644 --- a/web/config/initializers/gon.rb +++ b/web/config/initializers/gon.rb @@ -4,4 +4,5 @@ Gon.global.ftue_network_test_backend_retries = Rails.application.config.ftue_net Gon.global.twitter_public_account = Rails.application.config.twitter_public_account Gon.global.scoring_get_work_interval = Rails.application.config.scoring_get_work_interval Gon.global.scoring_get_work_backoff_interval = Rails.application.config.scoring_get_work_backoff_interval +Gon.global.ftue_network_test_min_wait_since_last_score = Rails.application.config.ftue_network_test_min_wait_since_last_score Gon.global.env = Rails.env diff --git a/web/config/routes.rb b/web/config/routes.rb index 723298515..5bdab1017 100644 --- a/web/config/routes.rb +++ b/web/config/routes.rb @@ -297,6 +297,7 @@ SampleApp::Application.routes.draw do # udp reachable (can stun?) match '/users/:id/udp_reachable' => 'api_users#udp_reachable', :via => :post + match '/users/:id/is_network_testing' => 'api_users#is_network_testing', :via => :post # social match '/users/:id/share/session/:provider' => 'api_users#share_session', :via => :get From 57ddb863798db1cb5fcc8168b4aec47cdf07f340 Mon Sep 17 00:00:00 2001 From: Seth Call Date: Mon, 6 Oct 2014 16:45:14 -0500 Subject: [PATCH 10/19] * fixing .sql/.rb in manifest --- db/manifest | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/manifest b/db/manifest index 076b72aa0..474221f66 100755 --- a/db/manifest +++ b/db/manifest @@ -216,5 +216,5 @@ fix_find_session_sorting_2216c.sql entabulate_current_network_scores.sql discard_scores_changed.sql emails_from_update.sql -add_active_feed.rb +add_active_feed.sql connection_network_testing.sql \ No newline at end of file From 1ce0ac34efb5959acac5c7e99d0054e24e981b86 Mon Sep 17 00:00:00 2001 From: Steven Miers Date: Mon, 6 Oct 2014 17:02:10 -0500 Subject: [PATCH 11/19] VRFS-2025 : Add video_sources to join_the_session and its callers. Creates and attaches video_sources just as it does tracks. --- ruby/lib/jam_ruby/models/connection.rb | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/ruby/lib/jam_ruby/models/connection.rb b/ruby/lib/jam_ruby/models/connection.rb index a1092300e..3ba2c28d5 100644 --- a/ruby/lib/jam_ruby/models/connection.rb +++ b/ruby/lib/jam_ruby/models/connection.rb @@ -163,12 +163,7 @@ module JamRuby true end - # - def join_the_session(music_session, as_musician, tracks, user, audio_latency) - join_the_session(music_session, as_musician, tracks, nil, user, audio_latency) - end - - def join_the_session(music_session, as_musician, tracks, videos, user, audio_latency) + def join_the_session(music_session, as_musician, tracks, user, audio_latency, videos=nil) self.music_session_id = music_session.id self.as_musician = as_musician self.joining_session = true @@ -201,14 +196,13 @@ module JamRuby def associate_videos(videos) unless videos.nil? - self.videos.clear() + self.video_sources.clear() videos.each do |video| v = VideoSource.new v.connection = self - v.sound = video["sound"] v.client_video_source_id = video["client_video_source_id"] v.save # todo what if it fails? - self.videos << v + self.video_sources << v end end end From 8ec75bb4e78520310724569c94fc9fb3ae2d6413 Mon Sep 17 00:00:00 2001 From: Steven Miers Date: Mon, 6 Oct 2014 17:02:33 -0500 Subject: [PATCH 12/19] VRFS-2025 : Specs for video_sources park. --- .../models/active_music_session_spec.rb | 33 +++++++++++++++++++ ruby/spec/jam_ruby/models/connection_spec.rb | 5 ++- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/ruby/spec/jam_ruby/models/active_music_session_spec.rb b/ruby/spec/jam_ruby/models/active_music_session_spec.rb index 28ac362cc..ac0288f23 100644 --- a/ruby/spec/jam_ruby/models/active_music_session_spec.rb +++ b/ruby/spec/jam_ruby/models/active_music_session_spec.rb @@ -711,5 +711,38 @@ describe ActiveMusicSession do @music_session.get_connection_ids(exclude_client_id: @connection2.client_id, as_musician: true).should == [@connection1.client_id] end end + + describe "join_the_session" do + let(:creator_1) { FactoryGirl.create(:user, last_jam_locidispid: 4, last_jam_audio_latency: 8) } + let(:creator_conn_1) { FactoryGirl.create(:connection, user: creator_1, ip_address: '4.4.4.4', locidispid: 4, addr:4) } + let!(:music_session_1) { FactoryGirl.create(:active_music_session, :creator => creator_1, genre: Genre.find('african'), language: 'eng', description: "Bunny Jumps" ) } + let(:tracks) { [{'sound' => 'mono', 'client_track_id' => 'abc', 'instrument_id' => 'piano'}] } + let(:videos) { [{'client_video_source_id' => 'abc'}] } + + it "joins the session with no video" do + creator_conn_1.join_the_session(music_session_1.music_session, true, tracks, creator_1, 10) + creator_conn_1.errors.any?.should be_false + + music_sessions = ActiveMusicSession.index(creator_1) + music_sessions.should_not be_nil + music_sessions.length.should == 1 + music_sessions[0].connections.should have(1).items + music_sessions[0].connections.should have(1).items + music_sessions[0].connections[0].tracks.should have(1).items + music_sessions[0].connections[0].video_sources.should have(0).items + end + + it "joins the session with video" do + creator_conn_1.join_the_session(music_session_1.music_session, true, tracks, creator_1, 10, videos) + creator_conn_1.errors.any?.should be_false + music_sessions = ActiveMusicSession.index(creator_1) + music_sessions.should_not be_nil + music_sessions.length.should == 1 + creator_conn_1.video_sources.should have(1).items + music_sessions[0].connections.should have(1).items + music_sessions[0].connections[0].video_sources.should have(1).items + music_sessions[0].connections[0].tracks.should have(1).items + end + end end diff --git a/ruby/spec/jam_ruby/models/connection_spec.rb b/ruby/spec/jam_ruby/models/connection_spec.rb index fe1c69ed0..dc7d8cdba 100644 --- a/ruby/spec/jam_ruby/models/connection_spec.rb +++ b/ruby/spec/jam_ruby/models/connection_spec.rb @@ -9,6 +9,8 @@ describe JamRuby::Connection do :ip_address => "1.1.1.1", :client_id => "1") } + let(:tracks) { [{'sound' => 'mono', 'client_track_id' => 'abc', 'instrument_id' => 'piano'}] } + it 'starts in the correct state' do connection = FactoryGirl.create(:connection, :user => user, @@ -101,7 +103,4 @@ describe JamRuby::Connection do end end - describe "join_the_session" do - - end end From e25e3b16a970fc6234888f127dc180c9ee0b56ab Mon Sep 17 00:00:00 2001 From: Steven Miers Date: Mon, 6 Oct 2014 18:17:08 -0500 Subject: [PATCH 13/19] VRFS-2027: Create video recordings from source in ApiRecordingsController#start Also includes spec. --- ruby/lib/jam_ruby/models/recording.rb | 4 ++++ ruby/spec/jam_ruby/models/recording_spec.rb | 19 ++++++++++++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/ruby/lib/jam_ruby/models/recording.rb b/ruby/lib/jam_ruby/models/recording.rb index f1ff2677c..a6d84bced 100644 --- a/ruby/lib/jam_ruby/models/recording.rb +++ b/ruby/lib/jam_ruby/models/recording.rb @@ -153,6 +153,10 @@ module JamRuby connection.tracks.each do |track| recording.recorded_tracks << RecordedTrack.create_from_track(track, recording) end + + connection.video_sources.each do |video| + recording.recorded_videos << RecordedVideo.create_from_video_source(video, recording) + end end end end diff --git a/ruby/spec/jam_ruby/models/recording_spec.rb b/ruby/spec/jam_ruby/models/recording_spec.rb index 0bc9702e0..0110cead2 100644 --- a/ruby/spec/jam_ruby/models/recording_spec.rb +++ b/ruby/spec/jam_ruby/models/recording_spec.rb @@ -8,9 +8,9 @@ describe Recording do @music_session = FactoryGirl.create(:active_music_session, :creator => @user, :musician_access => true) @connection = FactoryGirl.create(:connection, :user => @user, :music_session => @music_session) @track = FactoryGirl.create(:track, :connection => @connection, :instrument => @instrument) + @video_source = FactoryGirl.create(:video_source, :connection => @connection) end - - + it "should allow finding of recorded tracks" do user2 = FactoryGirl.create(:user) connection2 = FactoryGirl.create(:connection, :user => user2, :music_session => @music_session) @@ -39,7 +39,7 @@ describe Recording do @recorded_tracks.length.should == 1 @recorded_tracks.first.instrument_id == @track.instrument_id @recorded_tracks.first.user_id == @track.connection.user_id - end + end it "should not start a recording if the session is already being recorded" do Recording.start(@music_session, @user).errors.any?.should be_false @@ -286,6 +286,19 @@ describe Recording do @recording2.errors.any?.should be_false end end + + + it "set video from source" do + @music_session.is_recording?.should be_false + @recording = Recording.start(@music_session, @user) + @music_session.reload + @music_session.recordings[0].should == @recording + @recording.owner_id.should == @user.id + + @recorded_videos = RecordedVideo.where(:recording_id => @recording.id) + @recorded_videos.should have(1).items + @recorded_videos[0].client_video_source_id.should eq(@video_source.id) + end end From d4655cd65aa112de54dc61e37e7746c6aaff5a2a Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Mon, 6 Oct 2014 19:26:06 -0400 Subject: [PATCH 14/19] renamed file with .sql extension --- db/up/{add_active_feed.rb => add_active_feed.sql} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename db/up/{add_active_feed.rb => add_active_feed.sql} (100%) diff --git a/db/up/add_active_feed.rb b/db/up/add_active_feed.sql similarity index 100% rename from db/up/add_active_feed.rb rename to db/up/add_active_feed.sql From bffba5fcbc49e6e8b15e116c9b93baf44eeae468 Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Mon, 6 Oct 2014 21:03:19 -0400 Subject: [PATCH 15/19] VRFS-2219 changes based on Seth code review --- ruby/lib/jam_ruby/models/active_music_session.rb | 5 +++++ ruby/lib/jam_ruby/models/music_session.rb | 6 ------ .../resque/scheduled/active_music_session_cleaner.rb | 1 + ruby/spec/jam_ruby/models/feed_spec.rb | 3 ++- web/spec/controllers/api_feeds_controller_spec.rb | 3 ++- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/ruby/lib/jam_ruby/models/active_music_session.rb b/ruby/lib/jam_ruby/models/active_music_session.rb index c594655d2..2baf10718 100644 --- a/ruby/lib/jam_ruby/models/active_music_session.rb +++ b/ruby/lib/jam_ruby/models/active_music_session.rb @@ -47,6 +47,11 @@ module JamRuby end def before_destroy + feed = Feed.find_by_music_session_id(self.id) + unless feed.nil? + feed.active = false + feed.save + end self.mount.destroy if self.mount end diff --git a/ruby/lib/jam_ruby/models/music_session.rb b/ruby/lib/jam_ruby/models/music_session.rb index 0095eb652..81947a5a3 100644 --- a/ruby/lib/jam_ruby/models/music_session.rb +++ b/ruby/lib/jam_ruby/models/music_session.rb @@ -605,12 +605,6 @@ module JamRuby hist.end_history if hist - feed = Feed.find_by_music_session_id(session_id) - unless feed.nil? - feed.active = false - feed.save - end - Notification.send_session_ended(session_id) end diff --git a/ruby/lib/jam_ruby/resque/scheduled/active_music_session_cleaner.rb b/ruby/lib/jam_ruby/resque/scheduled/active_music_session_cleaner.rb index 18722217d..e700a0427 100644 --- a/ruby/lib/jam_ruby/resque/scheduled/active_music_session_cleaner.rb +++ b/ruby/lib/jam_ruby/resque/scheduled/active_music_session_cleaner.rb @@ -38,6 +38,7 @@ module JamRuby stale_sessions.each do |s| if s.connections.count == 0 + s.before_destroy s.delete end end diff --git a/ruby/spec/jam_ruby/models/feed_spec.rb b/ruby/spec/jam_ruby/models/feed_spec.rb index a0ec224da..f63d03116 100644 --- a/ruby/spec/jam_ruby/models/feed_spec.rb +++ b/ruby/spec/jam_ruby/models/feed_spec.rb @@ -196,7 +196,8 @@ describe Feed do it "supports date pagination" do claimed_recording = FactoryGirl.create(:claimed_recording) - MusicSession.removed_music_session(claimed_recording.recording.music_session.music_session.id) + ams = ActiveMusicSession.find(claimed_recording.recording.music_session.music_session.id) + ams.before_destroy options = {limit: 1} feeds, start = Feed.index(user1, options) diff --git a/web/spec/controllers/api_feeds_controller_spec.rb b/web/spec/controllers/api_feeds_controller_spec.rb index 2437e5d14..78a60b021 100644 --- a/web/spec/controllers/api_feeds_controller_spec.rb +++ b/web/spec/controllers/api_feeds_controller_spec.rb @@ -94,7 +94,8 @@ describe ApiFeedsController do claimed_recording.recording.created_at = 3.days.ago claimed_recording.recording.save! - MusicSession.removed_music_session(claimed_recording.recording.music_session.music_session.id) + ams = ActiveMusicSession.find(claimed_recording.recording.music_session.music_session.id) + ams.before_destroy get :index, { limit: 1 } json = JSON.parse(response.body, :symbolize_names => true) From 94963f2ad160a4bc54183a5720cd00374e8b1428 Mon Sep 17 00:00:00 2001 From: Steven Miers Date: Tue, 7 Oct 2014 15:34:05 -0500 Subject: [PATCH 16/19] VRFS-2028 : Add videos to list_uploads, in addition to tracks. This is accomplished using a SQL union via arel. --- ruby/lib/jam_ruby/models/recording.rb | 93 ++++++++++++++++++++++----- 1 file changed, 76 insertions(+), 17 deletions(-) diff --git a/ruby/lib/jam_ruby/models/recording.rb b/ruby/lib/jam_ruby/models/recording.rb index a6d84bced..4368c3234 100644 --- a/ruby/lib/jam_ruby/models/recording.rb +++ b/ruby/lib/jam_ruby/models/recording.rb @@ -303,22 +303,82 @@ module JamRuby since = 0 unless since || since == '' # guard against nil uploads = [] - RecordedTrack - .joins(:recording) - .where(:user_id => user.id) - .where(:fully_uploaded => false) - .where('recorded_tracks.id > ?', since) - .where("upload_failures <= #{APP_CONFIG.max_track_upload_failures}") - .where("duration IS NOT NULL") - .where('all_discarded = false') - .order('recorded_tracks.id') - .limit(limit).each do |recorded_track| - uploads.push({ - :type => "recorded_track", - :client_track_id => recorded_track.client_track_id, - :recording_id => recorded_track.recording_id, - :next => recorded_track.id - }) + + # Uploads now include videos in addition to the tracks. + # This is accomplished using a SQL union via arel, as follows: + + # Select fields from track. Note the reorder, which removes + # the default scope sort as it b0rks the union. Also note the + # alias so that we can differentiate tracks and videos when + # processing the results: + track_arel = RecordedTrack.select([ + :id, + :recording_id, + :url, + :fully_uploaded, + :upload_failures, + :client_track_id, + Arel::Nodes::As.new('track', Arel.sql('item_type')) + ]).reorder("") + + # Select fields for video. Note that it must include + # the same number of fields as the track in order for + # the union to work: + vid_arel = RecordedVideo.select([ + :id, + :recording_id, + :url, + :fully_uploaded, + :upload_failures, + :client_video_source_id, + Arel::Nodes::As.new('video', Arel.sql('item_type')) + ]).reorder("") + + # Glue them together: + union = track_arel.union(vid_arel) + + # Create a table alias from the union so we can get back to arel: + utable = RecordedTrack.arel_table.create_table_alias(union, :recorded_items) + arel = track_arel.from(utable) + arel = arel.select([ + :id, + :recording_id, + :url, + :fully_uploaded, + :upload_failures, + :client_track_id, + :item_type + ]) + + # Further joining and criteria for the unioned object: + arel = arel.joins("INNER JOIN (SELECT id as rec_id, all_discarded, duration FROM recordings) recs ON rec_id=recorded_items.recording_id") \ + .where('recorded_items.fully_uploaded =?', false) \ + .where('recorded_items.id > ?', since) \ + .where("upload_failures <= #{APP_CONFIG.max_track_upload_failures}") \ + .where("duration IS NOT NULL") \ + .where('all_discarded = false') \ + .order('recorded_items.id') \ + .limit(limit) + + # Load into array: + arel.each do |recorded_item| + if(recorded_item.item_type=='video') + # A video: + uploads << ({ + :type => "recorded_video", + :client_video_source_id => recorded_item.client_track_id, + :recording_id => recorded_item.recording_id, + :next => recorded_item.id + }) + else + # A track: + uploads << ({ + :type => "recorded_track", + :client_track_id => recorded_item.client_track_id, + :recording_id => recorded_item.recording_id, + :next => recorded_item.id + }) + end end next_value = uploads.length > 0 ? uploads[-1][:next].to_s : nil @@ -326,7 +386,6 @@ module JamRuby next_value = since # echo back to the client the same value they passed in, if there are no results end - { "uploads" => uploads, "next" => next_value.to_s From e26c254d36fe95b836f251c5fa56d2b527b86e99 Mon Sep 17 00:00:00 2001 From: Steven Miers Date: Tue, 7 Oct 2014 15:36:16 -0500 Subject: [PATCH 17/19] VRFS-2028 : Tests for verifying both types are there and have expected attributes in the hash. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I.E., type is “recorded_track” or “recorded_video” as appropriate, and videos have client_video_source_id attribute. Also test pagination. --- ruby/spec/jam_ruby/models/recording_spec.rb | 48 ++++++++++++++++++++- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/ruby/spec/jam_ruby/models/recording_spec.rb b/ruby/spec/jam_ruby/models/recording_spec.rb index 0110cead2..d7a5cf709 100644 --- a/ruby/spec/jam_ruby/models/recording_spec.rb +++ b/ruby/spec/jam_ruby/models/recording_spec.rb @@ -7,8 +7,7 @@ describe Recording do @instrument = FactoryGirl.create(:instrument, :description => 'a great instrument') @music_session = FactoryGirl.create(:active_music_session, :creator => @user, :musician_access => true) @connection = FactoryGirl.create(:connection, :user => @user, :music_session => @music_session) - @track = FactoryGirl.create(:track, :connection => @connection, :instrument => @instrument) - @video_source = FactoryGirl.create(:video_source, :connection => @connection) + @track = FactoryGirl.create(:track, :connection => @connection, :instrument => @instrument) end it "should allow finding of recorded tracks" do @@ -289,6 +288,8 @@ describe Recording do it "set video from source" do + @video_source = FactoryGirl.create(:video_source, :connection => @connection) + @music_session.is_recording?.should be_false @recording = Recording.start(@music_session, @user) @music_session.reload @@ -299,6 +300,49 @@ describe Recording do @recorded_videos.should have(1).items @recorded_videos[0].client_video_source_id.should eq(@video_source.id) end + + it "should include video when listing uploads" do + @video_source = FactoryGirl.create(:video_source, :connection => @connection) + @recording = Recording.start(@music_session, @user) + @recording.stop + @recording.reload + @genre = FactoryGirl.create(:genre) + @recording.claim(@user, "Recording", "Recording Description", @genre, true) + + # We should have 2 items; a track and a video: + uploads = Recording.list_uploads(@user) + uploads["uploads"].should have(2).items + uploads["uploads"][0][:type].should eq("recorded_track") + uploads["uploads"][1][:type].should eq("recorded_video") + uploads["uploads"][0].should include(:client_track_id) + uploads["uploads"][1].should include(:client_video_source_id) + + # Next page should have nothing: + uploads = Recording.list_uploads(@user, 10, uploads["next"]) + uploads["uploads"].should have(0).items + end + + it "should paginate with video" do + @video_source = FactoryGirl.create(:video_source, :connection => @connection) + @recording = Recording.start(@music_session, @user) + @recording.stop + @recording.reload + @genre = FactoryGirl.create(:genre) + @recording.claim(@user, "Recording", "Recording Description", @genre, true) + + # Limit to 1, so we can test pagination: + uploads = Recording.list_uploads(@user, 1) + uploads["uploads"].should have(1).items # First page + + # Second page: + uploads = Recording.list_uploads(@user, 1, uploads["next"]) + uploads["uploads"].should have(1).items + + # Last page (should be empty): + uploads = Recording.list_uploads(@user, 10, uploads["next"]) + uploads["uploads"].should have(0).items + end + end From eddd8a526c65ae82f40b199b1e4703bf58154f38 Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Tue, 7 Oct 2014 20:39:13 -0400 Subject: [PATCH 18/19] VRFS-2320 include from user info in session comment emails --- ruby/lib/jam_ruby/app/mailers/user_mailer.rb | 9 +++++---- .../user_mailer/scheduled_session_comment.html.erb | 4 ++-- .../user_mailer/scheduled_session_comment.text.erb | 2 ++ ruby/lib/jam_ruby/models/notification.rb | 5 ++--- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/ruby/lib/jam_ruby/app/mailers/user_mailer.rb b/ruby/lib/jam_ruby/app/mailers/user_mailer.rb index ccc0cf52c..c0c1b5a5d 100644 --- a/ruby/lib/jam_ruby/app/mailers/user_mailer.rb +++ b/ruby/lib/jam_ruby/app/mailers/user_mailer.rb @@ -412,22 +412,23 @@ end end - def scheduled_session_comment(user, msg, comment, session) - return if !user.subscribe_email + def scheduled_session_comment(target_user, source_user, msg, comment, session) + return if !target_user.subscribe_email - email = user.email + email = target_user.email subject = "New Session Comment" unique_args = {:type => "scheduled_session_comment"} @body = msg @session_name = session.name @session_date = session.pretty_scheduled_start(true) @comment = comment + @source_user = source_user @session_url = "#{APP_CONFIG.external_root_url}/sessions/#{session.id}/details" sendgrid_category "Notification" sendgrid_unique_args :type => unique_args[:type] sendgrid_recipients([email]) - sendgrid_substitute('@USERID', [user.id]) + sendgrid_substitute('@USERID', [target_user.id]) mail(:to => email, :subject => subject) do |format| format.text diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_comment.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_comment.html.erb index 7ebe56c8f..3f0837c2c 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_comment.html.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_comment.html.erb @@ -1,7 +1,7 @@ <% provide(:title, 'Scheduled Session Comment') %> -

<%= @body %>

-

<%= @comment %>

+

- <%= @source_user.name %>

+

View Session Details

\ No newline at end of file diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_comment.text.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_comment.text.erb index 6a7dc5f59..5ae68c0db 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_comment.text.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_comment.text.erb @@ -5,4 +5,6 @@ <%= @comment %> +- <%= @source_user.name %> + See session details at <%= @session_url %>. \ No newline at end of file diff --git a/ruby/lib/jam_ruby/models/notification.rb b/ruby/lib/jam_ruby/models/notification.rb index 217205337..777f4853c 100644 --- a/ruby/lib/jam_ruby/models/notification.rb +++ b/ruby/lib/jam_ruby/models/notification.rb @@ -930,14 +930,13 @@ module JamRuby rsvp_requests = RsvpRequest.index(music_session) target_users = send_to_cancelled ? rsvp_requests.map { |r| r.user } : rsvp_requests.where(:canceled => false).map { |r| r.user } target_users = target_users.concat([music_session.creator]) + source_user = creator pending_invites = music_session.pending_invitations # remove the creator from the array target_users = target_users.concat(pending_invites).uniq - [creator] target_users.each do |target_user| - source_user = creator - notification = Notification.new notification.description = NotificationTypes::SCHEDULED_SESSION_COMMENT notification.source_user_id = source_user.id @@ -964,7 +963,7 @@ module JamRuby end begin - UserMailer.scheduled_session_comment(target_user, notification_msg, comment, music_session).deliver + UserMailer.scheduled_session_comment(target_user, source_user, notification_msg, comment, music_session).deliver rescue => e @@log.error("Unable to send SCHEDULED_SESSION_COMMENT email to user #{target_user.email} #{e}") end From b30d71de6abca418db2d9155d509a09df12e5a4b Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Tue, 7 Oct 2014 21:16:56 -0400 Subject: [PATCH 19/19] VRFS-2320 use from_user_mailer template for session comment --- ruby/lib/jam_ruby/app/mailers/user_mailer.rb | 7 ++++--- .../user_mailer/scheduled_session_comment.html.erb | 12 ++++++++---- .../user_mailer/scheduled_session_comment.text.erb | 2 +- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/ruby/lib/jam_ruby/app/mailers/user_mailer.rb b/ruby/lib/jam_ruby/app/mailers/user_mailer.rb index c0c1b5a5d..46275db4a 100644 --- a/ruby/lib/jam_ruby/app/mailers/user_mailer.rb +++ b/ruby/lib/jam_ruby/app/mailers/user_mailer.rb @@ -412,7 +412,7 @@ end end - def scheduled_session_comment(target_user, source_user, msg, comment, session) + def scheduled_session_comment(target_user, sender, msg, comment, session) return if !target_user.subscribe_email email = target_user.email @@ -422,7 +422,8 @@ @session_name = session.name @session_date = session.pretty_scheduled_start(true) @comment = comment - @source_user = source_user + @sender = sender + @suppress_user_has_account_footer = true @session_url = "#{APP_CONFIG.external_root_url}/sessions/#{session.id}/details" sendgrid_category "Notification" sendgrid_unique_args :type => unique_args[:type] @@ -432,7 +433,7 @@ mail(:to => email, :subject => subject) do |format| format.text - format.html + format.html { render :layout => "from_user_mailer" } end end diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_comment.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_comment.html.erb index 3f0837c2c..a367a7444 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_comment.html.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_comment.html.erb @@ -1,7 +1,11 @@ -<% provide(:title, 'Scheduled Session Comment') %> +<% provide(:title, "Scheduled Session Comment from #{@sender.name}") %> +<% provide(:photo_url, @sender.resolved_photo_url) %> -

<%= @comment %>

+<% content_for :note do %> +

<%= @comment %>

-

- <%= @source_user.name %>

+

<%= @session_name %>

+

<%= @session_date %>

-

View Session Details

\ No newline at end of file +

View Session Details

+<% end %> \ No newline at end of file diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_comment.text.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_comment.text.erb index 5ae68c0db..5bb7377a2 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_comment.text.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_comment.text.erb @@ -5,6 +5,6 @@ <%= @comment %> -- <%= @source_user.name %> +- <%= @sender.name %> See session details at <%= @session_url %>. \ No newline at end of file