Merge branch 'develop' of bitbucket.org:jamkazam/jam-cloud into develop

This commit is contained in:
Jonathan Kolyer 2014-10-20 03:29:36 +00:00
commit 85fa427f02
28 changed files with 199 additions and 37 deletions

View File

@ -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

View File

@ -0,0 +1 @@
ALTER TABLE claimed_recordings ADD COLUMN upload_to_youtube BOOLEAN NOT NULL DEFAULT false;

View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -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") \

View File

@ -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) : {}

View File

@ -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

View File

@ -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'

View File

@ -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",

View File

@ -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 {

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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 {

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -115,6 +115,11 @@
</div>
<br />
<div class="f11">{biography}</div><br />
<div class="left f11 musician-latency">
Your latency to {first_name} is:&nbsp;&nbsp;{latency_badge}
</div>
<br clear="both"/>
<br clear="both"/>
<small><strong>FOLLOWING:</strong></small><br /><br />
<table class="musicians" cellpadding="0" cellspacing="5">
{followings}

View File

@ -50,7 +50,7 @@
</div>
<br clear="both"/>
</div>
<div class="left musician-latency" >
<div class="left musician-latency">
<div class="latency-help">Your latency<br/>to {musician_first_name} is: </div>
<div class="latency-holder">
{latency_badge}

View File

@ -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

View File

@ -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

View File

@ -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