diff --git a/db/manifest b/db/manifest index 853a1cef6..dbc4afe31 100755 --- a/db/manifest +++ b/db/manifest @@ -221,3 +221,4 @@ connection_network_testing.sql video_sources.sql recorded_videos.sql emails_from_update2.sql +add_youtube_flag_to_claimed_recordings.sql \ No newline at end of file diff --git a/db/up/add_youtube_flag_to_claimed_recordings.sql b/db/up/add_youtube_flag_to_claimed_recordings.sql new file mode 100644 index 000000000..5ad549f7f --- /dev/null +++ b/db/up/add_youtube_flag_to_claimed_recordings.sql @@ -0,0 +1 @@ +ALTER TABLE claimed_recordings ADD COLUMN upload_to_youtube BOOLEAN NOT NULL DEFAULT false; \ No newline at end of file diff --git a/ruby/lib/jam_ruby.rb b/ruby/lib/jam_ruby.rb index 9daaa1e8d..394975a34 100755 --- a/ruby/lib/jam_ruby.rb +++ b/ruby/lib/jam_ruby.rb @@ -51,6 +51,7 @@ require "jam_ruby/resque/scheduled/new_musician_emailer" require "jam_ruby/resque/scheduled/music_session_scheduler" require "jam_ruby/resque/scheduled/active_music_session_cleaner" require "jam_ruby/resque/scheduled/score_history_sweeper" +require "jam_ruby/resque/scheduled/scheduled_music_session_cleaner" require "jam_ruby/resque/google_analytics_event" require "jam_ruby/resque/batch_email_job" require "jam_ruby/mq_router" diff --git a/ruby/lib/jam_ruby/models/claimed_recording.rb b/ruby/lib/jam_ruby/models/claimed_recording.rb index 9fa1e569a..88898cb89 100644 --- a/ruby/lib/jam_ruby/models/claimed_recording.rb +++ b/ruby/lib/jam_ruby/models/claimed_recording.rb @@ -3,7 +3,7 @@ module JamRuby include HtmlSanitize html_sanitize strict: [:name, :description] - attr_accessible :name, :description, :is_public, :genre_id, :recording_id, :user_id, as: :admin + attr_accessible :name, :description, :is_public, :genre_id, :recording_id, :user_id, :upload_to_youtube, as: :admin belongs_to :recording, :class_name => "JamRuby::Recording", :inverse_of => :claimed_recordings, :foreign_key => 'recording_id' belongs_to :user, :class_name => "JamRuby::User", :inverse_of => :claimed_recordings @@ -17,6 +17,8 @@ module JamRuby validates :name, no_profanity: true, length: {minimum: 3, maximum: 64}, presence: true validates :description, no_profanity: true, length: {maximum: 8000} validates :is_public, :inclusion => {:in => [true, false]} + validates :upload_to_youtube, :inclusion => {:in => [true, false]} + validates :genre, presence: true validates :user, presence: true validates_uniqueness_of :user_id, :scope => :recording_id diff --git a/ruby/lib/jam_ruby/models/recorded_video.rb b/ruby/lib/jam_ruby/models/recorded_video.rb index fc787d20a..42f40ea9c 100644 --- a/ruby/lib/jam_ruby/models/recorded_video.rb +++ b/ruby/lib/jam_ruby/models/recorded_video.rb @@ -6,6 +6,10 @@ module JamRuby validates :client_video_source_id, :presence => true + def upload_sign(content_md5) + + end + def self.create_from_video_source(video_source, recording) recorded_video_source = self.new recorded_video_source.recording = recording diff --git a/ruby/lib/jam_ruby/models/recording.rb b/ruby/lib/jam_ruby/models/recording.rb index f467fe563..1d9c6fd9c 100644 --- a/ruby/lib/jam_ruby/models/recording.rb +++ b/ruby/lib/jam_ruby/models/recording.rb @@ -180,8 +180,8 @@ module JamRuby # Called when a user wants to "claim" a recording. To do this, the user must have been one of the tracks in the recording. - def claim(user, name, description, genre, is_public) - + def claim(user, name, description, genre, is_public, upload_to_youtube=false) + upload_to_youtube = !!upload_to_youtube # Correct where nil is borking save unless self.users.exists?(user) raise PermissionError, "user was not in this session" end @@ -193,6 +193,7 @@ module JamRuby claimed_recording.description = description claimed_recording.genre = genre claimed_recording.is_public = is_public + claimed_recording.upload_to_youtube = upload_to_youtube self.claimed_recordings << claimed_recording if claimed_recording.save @@ -305,7 +306,7 @@ module JamRuby uploads = [] # Uploads now include videos in addition to the tracks. - # This is accomplished using a SQL union via arel, as follows: + # This is accomplished using a SQL UNION query 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 @@ -356,7 +357,7 @@ module JamRuby # 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.user_id' => user.id) \ - .where('recorded_items.fully_uploaded =?', false) \ + .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") \ diff --git a/ruby/lib/jam_ruby/models/user.rb b/ruby/lib/jam_ruby/models/user.rb index b33a1d2c0..de0592801 100644 --- a/ruby/lib/jam_ruby/models/user.rb +++ b/ruby/lib/jam_ruby/models/user.rb @@ -324,7 +324,7 @@ module JamRuby read_attribute(:music_session_id) end - # ===== ARTIFICIAL ATTRIBUTES CREATED BY ActiveMusicSession.ams_users, MusicSession.sms_uses + # ===== ARTIFICIAL ATTRIBUTES CREATED BY ActiveMusicSession.ams_users, MusicSession.sms_users def full_score return nil unless has_attribute?(:full_score) a = read_attribute(:full_score) @@ -344,6 +344,14 @@ module JamRuby end # ====== END ARTIFICAL ATTRIBUTES + def score_info(destination_user) + if self.last_jam_locidispid && destination_user.last_jam_locidispid + self.connection.execute("select score from current_network_scores where alocidispid = #{self.last_jam_locidispid} and blocidispid = #{destination_user.last_jam_locidispid}").check + else + nil + end + end + # mods comes back as text; so give ourselves a parsed version def mods_json @mods_json ||= mods ? JSON.parse(mods, symbolize_names: true) : {} diff --git a/ruby/spec/jam_ruby/models/recording_spec.rb b/ruby/spec/jam_ruby/models/recording_spec.rb index 6a6ab6ee6..0989e777c 100644 --- a/ruby/spec/jam_ruby/models/recording_spec.rb +++ b/ruby/spec/jam_ruby/models/recording_spec.rb @@ -126,6 +126,7 @@ describe Recording do @claimed_recording.description.should == "description" @claimed_recording.genre.should == @genre @claimed_recording.is_public.should == true + @claimed_recording.upload_to_youtube.should == false end it "should fail if a user who was not in the session claims a recording" do @@ -149,6 +150,7 @@ describe Recording do @claimed_recording.description.should == "description2" @claimed_recording.genre.should == @genre2 @claimed_recording.is_public.should == false + @claimed_recording.upload_to_youtube.should == false end it "should only allow the owner to edit a claimed recording" do @@ -195,6 +197,29 @@ describe Recording do @recording.all_discarded.should == false end + it "should set youtube flag" do + + @connection.join_the_session(@music_session, true, nil, @user, 10) + @recording = Recording.start(@music_session, @user) + @recording.stop + @recording.reload + @genre = FactoryGirl.create(:genre) + @recording.claim(@user, "name", "description", @genre, true, true) + + @recording.reload + @recording.users.length.should == 1 + @recording.users.first.should == @user + @user.recordings.length.should == 1 + @user.recordings.first.should == @recording + @recording.claimed_recordings.length.should == 1 + @claimed_recording = @recording.claimed_recordings.first + @claimed_recording.name.should == "name" + @claimed_recording.description.should == "description" + @claimed_recording.genre.should == @genre + @claimed_recording.is_public.should == true + @claimed_recording.upload_to_youtube.should == true + end + it "should destroy the entire recording if there was only one claimed_recording which is discarded" do @recording = Recording.start(@music_session, @user) @recording.stop diff --git a/web/Gemfile b/web/Gemfile index c97941bd1..4c31c7956 100644 --- a/web/Gemfile +++ b/web/Gemfile @@ -43,6 +43,7 @@ gem 'omniauth', '1.1.1' gem 'omniauth-facebook', '1.4.1' gem 'omniauth-twitter' gem 'omniauth-google-oauth2', '0.2.1' +gem 'google-api-client' gem 'twitter' gem 'fb_graph', '2.5.9' gem 'sendgrid', '1.2.0' diff --git a/web/app/assets/javascripts/hoverMusician.js b/web/app/assets/javascripts/hoverMusician.js index 70f688d35..97af8da8a 100644 --- a/web/app/assets/javascripts/hoverMusician.js +++ b/web/app/assets/javascripts/hoverMusician.js @@ -7,8 +7,12 @@ var logger = context.JK.logger; var rest = context.JK.Rest(); var hoverSelector = "#musician-hover"; + var helpBubble = context.JK.HelpBubbleHelper; + var $templateLatency = null; + var sessionUtils = context.JK.SessionUtils; this.showBubble = function() { + $templateLatency = $("#template-account-session-latency"); var mouseLeft = x < (document.body.clientWidth / 2); var mouseTop = y < (document.body.clientHeight / 2); var css = {}; @@ -82,10 +86,29 @@ } } + var fullScore = null; + + if (response.last_jam_audio_latency && response.my_audio_latency && response.internet_score) { + fullScore = response.last_jam_audio_latency + response.my_audio_latency + response.internet_score; + } + + // latency badge template needs these 2 properties + $.extend(response, { + audio_latency: response.last_jam_audio_latency, + full_score: fullScore + }); + + var latencyBadge = context._.template( + $templateLatency.html(), + $.extend(sessionUtils.createLatency(response), response), + {variable: 'data'} + ); + var musicianHtml = context.JK.fillTemplate(template, { userId: response.id, avatar_url: context.JK.resolveAvatarUrl(response.photo_url), name: response.name, + first_name: response.first_name, location: response.location, instruments: instrumentHtml, friend_count: response.friend_count, @@ -95,6 +118,7 @@ session_display: sessionDisplayStyle, join_display: joinDisplayStyle, sessionId: sessionId, + latency_badge: latencyBadge, //friendAction: response.is_friend ? "removeMusicianFriend" : (response.pending_friend_request ? "" : "sendMusicianFriendRequest"), friendAction: response.is_friend ? "" : (response.pending_friend_request ? "" : "sendMusicianFriendRequest"), followAction: response.is_following ? "removeMusicianFollowing" : "addMusicianFollowing", diff --git a/web/app/assets/javascripts/session_utils.js b/web/app/assets/javascripts/session_utils.js index 725da855d..482aaeab1 100644 --- a/web/app/assets/javascripts/session_utils.js +++ b/web/app/assets/javascripts/session_utils.js @@ -77,34 +77,34 @@ description = 'me'; } else if (!full_score) { - latencyDescription = LATENCY.UNKNOWN.description; + latencyDescription = LATENCY.UNKNOWN.description; latencyStyle = LATENCY.UNKNOWN.style; - iconName = 'purple' - description = 'missing' + iconName = 'purple'; + description = 'missing'; } else if (full_score <= LATENCY.GOOD.max) { latencyDescription = LATENCY.GOOD.description; latencyStyle = LATENCY.GOOD.style; - iconName = 'green' - description = 'good' + iconName = 'green'; + description = 'good'; } else if (full_score <= LATENCY.MEDIUM.max) { latencyDescription = LATENCY.MEDIUM.description; latencyStyle = LATENCY.MEDIUM.style; iconName = 'yellow'; - description = 'fair' + description = 'fair'; } else if (full_score <= LATENCY.POOR.max) { latencyDescription = LATENCY.POOR.description; latencyStyle = LATENCY.POOR.style; - iconName = 'red' - description = 'poor' + iconName = 'red'; + description = 'poor'; } else { latencyStyle = LATENCY.UNACCEPTABLE.style; latencyDescription = LATENCY.UNACCEPTABLE.description; - iconName = 'blue' - description = 'unacceptable' + iconName = 'blue'; + description = 'unacceptable'; } return { diff --git a/web/app/assets/stylesheets/client/account.css.scss b/web/app/assets/stylesheets/client/account.css.scss index 81d700c12..74183442c 100644 --- a/web/app/assets/stylesheets/client/account.css.scss +++ b/web/app/assets/stylesheets/client/account.css.scss @@ -115,7 +115,7 @@ background-color: #C5C5C5; border: medium none; box-shadow: 2px 2px 3px 0 #888888 inset; - color: #666666; + color: #000; font-size: 14px; height: 178px; overflow: auto; diff --git a/web/app/assets/stylesheets/client/band.css.scss b/web/app/assets/stylesheets/client/band.css.scss index 4da4130d3..d2e8504d5 100644 --- a/web/app/assets/stylesheets/client/band.css.scss +++ b/web/app/assets/stylesheets/client/band.css.scss @@ -13,7 +13,7 @@ border:none; -webkit-box-shadow: inset 2px 2px 3px 0px #888; box-shadow: inset 2px 2px 3px 0px #888; - color:#666; + color:#000; overflow:auto; font-size:14px; } diff --git a/web/app/assets/stylesheets/client/content.css.scss b/web/app/assets/stylesheets/client/content.css.scss index 68434368c..9bee28a72 100644 --- a/web/app/assets/stylesheets/client/content.css.scss +++ b/web/app/assets/stylesheets/client/content.css.scss @@ -222,7 +222,6 @@ border:none; -webkit-box-shadow: inset 2px 2px 3px 0px #888; box-shadow: inset 2px 2px 3px 0px #888; - color:#666; } } diff --git a/web/app/assets/stylesheets/client/createSession.css.scss b/web/app/assets/stylesheets/client/createSession.css.scss index a4cbec1dd..83eeba993 100644 --- a/web/app/assets/stylesheets/client/createSession.css.scss +++ b/web/app/assets/stylesheets/client/createSession.css.scss @@ -209,7 +209,7 @@ border: none; -webkit-box-shadow: inset 2px 2px 3px 0px #888; box-shadow: inset 2px 2px 3px 0px #888; - color: #666; + color: #000; overflow: auto; font-size: 14px; diff --git a/web/app/assets/stylesheets/client/ftue.css.scss b/web/app/assets/stylesheets/client/ftue.css.scss index ef81f1a39..1082b843e 100644 --- a/web/app/assets/stylesheets/client/ftue.css.scss +++ b/web/app/assets/stylesheets/client/ftue.css.scss @@ -528,14 +528,14 @@ div[layout-id="ftue3"] { border:none; -webkit-box-shadow: inset 2px 2px 3px 0px #888; box-shadow: inset 2px 2px 3px 0px #888; - color:#666; + color:#000; overflow:auto; font-size:14px; } .ftue-instrumentlist select, .ftue-instrumentlist .easydropdown { width:100%; - color:#666; + color:#000; } table.audiogeartable { diff --git a/web/app/assets/stylesheets/client/hoverBubble.css.scss b/web/app/assets/stylesheets/client/hoverBubble.css.scss index a53fff3b8..b8d6ec315 100644 --- a/web/app/assets/stylesheets/client/hoverBubble.css.scss +++ b/web/app/assets/stylesheets/client/hoverBubble.css.scss @@ -1,3 +1,5 @@ +@import 'common'; + .bubble { width:350px; min-height:200px; @@ -74,4 +76,48 @@ -moz-border-radius:12px; border-radius:12px; } + + .musician-latency { + margin-right:35px; + position:relative; + width:350px; + } + + .latency-holder { + position:absolute; + width:100%; + text-align:center; + } + + .latency { + min-width: 50px; + display:inline-block; + padding:4px; + font-family:Arial, Helvetica, sans-serif; + font-weight:200; + font-size:11px; + text-align:center; + @include border-radius(2px); + color:white; + } + + .latency-unknown { + background-color:$latencyBadgeUnknown; + } + + .latency-unacceptable { + background-color:$latencyBadgeUnacceptable; + } + + .latency-good { + background-color:$latencyBadgeGood; + } + + .latency-fair{ + background-color:$latencyBadgeFair; + } + + .latency-poor { + background-color:$latencyBadgePoor; + } } \ No newline at end of file diff --git a/web/app/assets/stylesheets/client/jamkazam.css.scss b/web/app/assets/stylesheets/client/jamkazam.css.scss index 46df063a6..8ccd7a022 100644 --- a/web/app/assets/stylesheets/client/jamkazam.css.scss +++ b/web/app/assets/stylesheets/client/jamkazam.css.scss @@ -302,7 +302,6 @@ input[type="button"] { .search-box { float:left; - width:140px; margin-left: 10px; -webkit-border-radius: 6px; border-radius: 6px; @@ -321,7 +320,6 @@ input[type="button"] { input[type="text"], input[type="password"]{ background-color:$ColorTextBoxBackground; border:none; - color:#666; padding:3px; font-size:15px; } diff --git a/web/app/assets/stylesheets/client/screen_common.css.scss b/web/app/assets/stylesheets/client/screen_common.css.scss index 30cc32a06..f36438ea4 100644 --- a/web/app/assets/stylesheets/client/screen_common.css.scss +++ b/web/app/assets/stylesheets/client/screen_common.css.scss @@ -143,7 +143,6 @@ textarea { border:none; -webkit-box-shadow: inset 2px 2px 3px 0px #888; box-shadow: inset 2px 2px 3px 0px #888; - color:#333; } diff --git a/web/app/assets/stylesheets/easydropdown_jk.css.scss b/web/app/assets/stylesheets/easydropdown_jk.css.scss index 4b2ff52b6..47e43c108 100644 --- a/web/app/assets/stylesheets/easydropdown_jk.css.scss +++ b/web/app/assets/stylesheets/easydropdown_jk.css.scss @@ -106,15 +106,12 @@ body.jam { .dropdown-wrapper li { padding: 5px 5px; font-size:15px; - - color: #666666; } .dropdown-wrapper li { margin:0; padding:3px; font-size:15px; - color: #666666; &.focus { background-color: #ed3618; @@ -151,8 +148,6 @@ body.jam div.dropdown { .selected, .dropdown li { padding: 5px 5px; font-size:15px; - - color: #666666; } .selected:after { box-shadow: none; @@ -166,7 +161,6 @@ body.jam div.dropdown { margin:0; padding:3px; font-size:15px; - color: #666666; &.focus { background-color: #ed3618; diff --git a/web/app/controllers/api_recordings_controller.rb b/web/app/controllers/api_recordings_controller.rb index 66c5625f9..e7c67b29d 100644 --- a/web/app/controllers/api_recordings_controller.rb +++ b/web/app/controllers/api_recordings_controller.rb @@ -79,7 +79,7 @@ class ApiRecordingsController < ApiController # claim will create a claimed recording for the creator def claim - claim = @recording.claim(current_user, params[:name], params[:description], Genre.find_by_id(params[:genre]), params[:is_public]) + claim = @recording.claim(current_user, params[:name], params[:description], Genre.find_by_id(params[:genre]), params[:is_public], params[:upload_to_youtube]) if claim.errors.any? response.status = :unprocessable_entity diff --git a/web/app/controllers/sessions_controller.rb b/web/app/controllers/sessions_controller.rb index f2f705141..7a2bb8ca7 100644 --- a/web/app/controllers/sessions_controller.rb +++ b/web/app/controllers/sessions_controller.rb @@ -134,11 +134,16 @@ class SessionsController < ApplicationController # Always make and save a new authorization. This is because they expire, and honestly there's no cost # to just making and saving it. + user_auth_hash = { + :provider => auth_hash[:provider], + :uid => auth_hash[:uid], + :token => auth_hash[:credentials][:token], + :token_expiration => Time.at(auth_hash[:credentials][:expires_at]), + :secret => auth_hash[:credentials][:secret] + } + #if authorization.nil? - authorization = current_user.user_authorizations.build :provider => auth_hash[:provider], - :uid => auth_hash[:uid], - :token => auth_hash[:credentials][:token], - :token_expiration => Time.at(auth_hash[:credentials][:expires_at]) + authorization = current_user.user_authorizations.build(user_auth_hash) authorization.save #end diff --git a/web/app/views/api_users/show.rabl b/web/app/views/api_users/show.rabl index b2827fdba..fd8b9b87e 100644 --- a/web/app/views/api_users/show.rabl +++ b/web/app/views/api_users/show.rabl @@ -30,6 +30,12 @@ elsif current_user node :pending_friend_request do |uu| current_user.pending_friend_request?(@user) end + node :my_audio_latency do |user| + current_user.last_jam_audio_latency.round if current_user.last_jam_audio_latency + end + node :internet_score do |user| + current_user.score_info(user) + end end child :friends => :friends do diff --git a/web/app/views/clients/_hoverMusician.html.erb b/web/app/views/clients/_hoverMusician.html.erb index 0a185a3ed..dd1994d6d 100644 --- a/web/app/views/clients/_hoverMusician.html.erb +++ b/web/app/views/clients/_hoverMusician.html.erb @@ -115,6 +115,11 @@
{biography}

+
+ Your latency to {first_name} is:  {latency_badge} +
+
+
FOLLOWING:

{followings} diff --git a/web/app/views/clients/_musicians.html.erb b/web/app/views/clients/_musicians.html.erb index 60279346f..cd626c8f0 100644 --- a/web/app/views/clients/_musicians.html.erb +++ b/web/app/views/clients/_musicians.html.erb @@ -50,7 +50,7 @@
-
+
Your latency
to {musician_first_name} is:
{latency_badge} diff --git a/web/config/environments/development.rb b/web/config/environments/development.rb index 797e9aeba..96431df93 100644 --- a/web/config/environments/development.rb +++ b/web/config/environments/development.rb @@ -83,4 +83,7 @@ SampleApp::Application.configure do config.send_join_session_email_notifications = true + # For product = JamKazamDev + config.youtube_developer_key = "AI39si5bPqiNc5GQHscWJh9Wl1WTAr9aZqr_YncUvaR7Kz0rgPdBVWVubHZ94xZ3KLIBqtE9mu3VZe-UpMU80QxXoC66kBNp7A" + config.youtube_app_name = "JamKazamDev" end diff --git a/web/config/environments/test.rb b/web/config/environments/test.rb index 55df32b20..0c9d096b0 100644 --- a/web/config/environments/test.rb +++ b/web/config/environments/test.rb @@ -76,6 +76,9 @@ SampleApp::Application.configure do config.twitter_app_id = 'e7hGc71gmcBgo6Wvdta6Sg' config.twitter_app_secret = 'PfG1jAUMnyrimPcDooUVQaJrG1IuDjUyGg5KciOo' + config.youtube_developer_key = "AI39si4VB6mzeQxS0CGWsZhnOvV3nptz7vtuyeMc6pw1Kwtv6J_O1b0ZMj0QLULFtv7hnfAkimAPFy9RfJJFWsds4vUAZjnDVg" + config.youtube_app_name = "JamKazamTest" + config.use_promos_on_homepage = false config.use_cached_session_scores = true diff --git a/web/spec/controllers/sessions_controller_spec.rb b/web/spec/controllers/sessions_controller_spec.rb index 5ec9699d2..65aad4fff 100644 --- a/web/spec/controllers/sessions_controller_spec.rb +++ b/web/spec/controllers/sessions_controller_spec.rb @@ -111,6 +111,42 @@ describe SessionsController do end end + describe "google_login" do + before(:each) do + OmniAuth.config.mock_auth[:google_login] = OmniAuth::AuthHash.new({ + 'uid' => '100', + 'provider' => 'google_login', + 'credentials' => { + 'token' => 'google_logintoken', + 'secret' => 'google_loginsecret', + 'expires_at' => 1000000000 + } + }) + end + + it "should update user_authorization for existing user" do + cookie_jar[:remember_token] = user.remember_token # controller.current_user is not working. i think because of omniauth + request.env["omniauth.auth"] = OmniAuth.config.mock_auth[:google_login] + visit '/auth/google_login' + user.reload + auth = user.user_authorization('google_login') + auth.uid.should == '100' + auth.token.should == 'google_logintoken' + auth.secret.should == 'google_loginsecret' + + # also verify that a second visit does *not* create another new user + visit '/auth/google_login' + + user.reload + auth = user.user_authorization('google_login') + auth.uid.should == '100' + auth.token.should == 'google_logintoken' + auth.secret.should == 'google_loginsecret' + end + end + + + end