This commit is contained in:
Scott Comer 2014-02-20 20:40:22 -06:00
commit 9d5958175b
56 changed files with 967 additions and 158 deletions

View File

@ -37,7 +37,6 @@ gem 'bootstrap-will_paginate', '0.0.6'
gem 'carrierwave', '0.9.0'
gem 'carrierwave_direct'
gem 'uuidtools', '2.1.2'
#gem 'bcrypt-ruby', '3.0.1'
gem 'jquery-rails' # , '2.3.0' # pinned because jquery-ui-rails was split from jquery-rails, but activeadmin doesn't support this gem yet
gem 'jquery-ui-rails'
gem 'rails3-jquery-autocomplete'

View File

@ -37,7 +37,7 @@ ActiveAdmin.register JamRuby::PromoLatest, :as => 'Latest' do
def create
promo = PromoLatest.create_with_params(params[:jam_ruby_promo_latest])
redirect_to('/admin/latests')
redirect_to admin_latests_path
end
def edit
@ -48,7 +48,7 @@ ActiveAdmin.register JamRuby::PromoLatest, :as => 'Latest' do
def update
resource.update_with_params(params[:jam_ruby_promo_latest]).save!
redirect_to('/admin/latests')
redirect_to admin_latests_path
end
end

View File

@ -1,6 +1,7 @@
<%= semantic_form_for([:admin, @promo], :html => {:multipart => true}, :url => @promo.new_record? ? admin_latests_path : "/admin/latests/#{@promo.id}") do |f| %>
<%= f.inputs :name => "Recording or Session", :for => :latest do |latest_form| %>
<%= latest_form.input :id, :as => :select, :collection => @latests.collect { |ll| [ll[:name], ll[:id]] }, :label => "Latest", :required => true, :selected => @promo.latest.try(:id) %>
<%= f.input(:latest_id, :label => "Unique ID (Recording or Session)", :input_html => {:maxlength => 128}) %>
<% #= latest_form.input :id, :as => :select, :collection => @latests.collect { |ll| [ll[:name], ll[:id]] }, :label => "Latest", :required => true, :selected => @promo.latest.try(:id) %>
<% end %>
<%= f.inputs do %>
<%= f.input(:position, :label => "Position", :input_html => {:maxlength => 4}) %>

View File

@ -113,4 +113,6 @@ feed_use_recording.sql
feed_autoincrement_primary_key.sql
music_sessions_plays.sql
plays_likes_counters.sql
add_upright_bass.sql
add_upright_bass.sql
music_session_history_public.sql
track_claimed_recording.sql

View File

@ -0,0 +1,2 @@
ALTER TABLE music_sessions_history ADD COLUMN fan_access BOOLEAN NOT NULL DEFAULT TRUE;

View File

@ -0,0 +1,3 @@
ALTER TABLE recordings_likers ADD COLUMN claimed_recording_id VARCHAR(64) NOT NULL REFERENCES claimed_recordings(id);
ALTER TABLE recordings_plays ADD COLUMN claimed_recording_id VARCHAR(64) NOT NULL REFERENCES claimed_recordings(id);
ALTER TABLE recordings_likers ADD COLUMN favorite BOOLEAN NOT NULL DEFAULT TRUE;

View File

@ -3,14 +3,18 @@
echo "updating dependencies"
bundle install --path vendor/bundle
echo "running rspec tests"
bundle exec rspec
if [ -z $SKIP_TESTS ]; then
echo "running rspec tests"
bundle exec rspec
if [ "$?" = "0" ]; then
if [ "$?" = "0" ]; then
echo "tests completed"
else
else
echo "tests failed."
exit 1
fi
else
echo "skipping tests"
fi
echo "build complete"

View File

@ -67,8 +67,7 @@ module JamRuby
end
def recent_history
recordings = ClaimedRecording.joins(:recording)
.where(:recordings => {:band_id => "#{self.id}"})
recordings = Recording.where(:band_id => self.id)
.order('created_at DESC')
.limit(10)

View File

@ -3,13 +3,14 @@ module JamRuby
attr_accessible :name, :description, :is_public, :is_downloadable, :genre_id, :recording_id, :user_id, 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
belongs_to :genre, :class_name => "JamRuby::Genre"
has_many :recorded_tracks, :through => :recording, :class_name => "JamRuby::RecordedTrack"
has_many :playing_sessions, :class_name => "JamRuby::MusicSession"
has_one :share_token, :class_name => "JamRuby::ShareToken", :inverse_of => :shareable, :foreign_key => 'shareable_id'
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
belongs_to :genre, :class_name => "JamRuby::Genre"
has_many :recorded_tracks, :through => :recording, :class_name => "JamRuby::RecordedTrack"
has_many :playing_sessions, :class_name => "JamRuby::MusicSession"
has_many :likes, :class_name => "JamRuby::RecordingLiker", :foreign_key => "claimed_recording_id"
has_many :plays, :class_name => "JamRuby::RecordingPlay", :foreign_key => "claimed_recording_id"
has_one :share_token, :class_name => "JamRuby::ShareToken", :inverse_of => :shareable, :foreign_key => 'shareable_id'
validates :name, no_profanity: true, length: {minimum: 3, maximum: 64}, presence: true
validates :description, no_profanity: true, length: {maximum: 8000}
@ -23,6 +24,7 @@ module JamRuby
before_create :generate_share_token
SHARE_TOKEN_LENGTH = 8
FIXNUM_MAX = (2**(0.size * 8 -2) -1)
def user_belongs_to_recording
@ -72,6 +74,50 @@ module JamRuby
token.gsub(/[^0-9A-Za-z]/, '')
end
# right now, the only thing that is brought back is ClaimedRecordings, and you can only query your own favorites
def self.index_favorites(user, params = {})
limit = params[:limit]
limit ||= 20
limit = limit.to_i
# validate sort
sort = params[:sort]
sort ||= 'date'
raise "not valid sort #{sort}" unless sort == "date"
start = params[:start].presence
start ||= 0
start = start.to_i
type_filter = params[:type]
type_filter ||= 'claimed_recording'
raise "not valid type #{type_filter}" unless type_filter == "claimed_recording"
target_user = params[:user]
raise PermissionError, "must specify current user" unless user
raise "user must be specified" unless target_user
if target_user != user.id
raise PermissionError, "unable to view another user's favorites"
end
query = ClaimedRecording.limit(limit).order('created_at DESC').offset(start)
query = query.joins(:likes)
query = query.where('favorite = true')
query = query.where("recordings_likers.liker_id = '#{target_user}'")
query = query.where("claimed_recordings.is_public = TRUE OR claimed_recordings.user_id = '#{target_user}'")
if query.length == 0
[query, nil]
elsif query.length < limit
[query, nil]
else
[query, start + limit]
end
end
private
def generate_share_token

View File

@ -20,7 +20,7 @@ module JamRuby
sort ||= 'date'
raise "not valid sort #{sort}" unless SORT_TYPES.include?(sort)
start = params[:start]
start = params[:start].presence
if sort == 'date'
start ||= FIXNUM_MAX
else
@ -36,17 +36,18 @@ module JamRuby
type_filter ||= 'all'
raise "not valid type #{type_filter}" unless TYPE_FILTERS.include?(type_filter)
include_private = params[:include_private]
include_private ||= false # default to false
include_private = false if user.nil? # and force to false if the current user is nil
target_user = params[:user]
target_band = params[:band]
query = Feed.includes([:recording]).includes([:music_session_history]).limit(limit)
#query = Feed.includes([:recording]).includes([:music_session_history]).limit(limit)
query = Feed.joins("LEFT OUTER JOIN recordings ON recordings.id = feeds.recording_id")
.joins("LEFT OUTER JOIN music_sessions_history ON music_sessions_history.id = feeds.music_session_id")
.limit(limit)
# handle sort
if sort == 'date'
query = query.where("id < #{start}")
query = query.order('id DESC')
query = query.where("feeds.id < #{start}")
query = query.order('feeds.id DESC')
elsif sort == 'plays'
query = query.offset(start)
query = query.order("COALESCE(recordings.play_count, music_sessions_history.play_count) DESC ")
@ -65,18 +66,64 @@ module JamRuby
# handle type filters
if type_filter == 'music_session_history'
query = query.where('music_session_id is not NULL')
query = query.where('feeds.music_session_id is not NULL')
elsif type_filter == 'recording'
query = query.where('recording_id is not NULL')
query = query.where('feeds.recording_id is not NULL')
end
# handle private times
if include_private
if target_user
if target_user != user.id
require_public_recordings = "claimed_recordings.is_public = TRUE AND"
require_public_sessions = "music_sessions_history.fan_access = TRUE AND"
end
query = query.joins("LEFT OUTER JOIN claimed_recordings ON recordings.id = claimed_recordings.recording_id AND #{require_public_recordings} (claimed_recordings.user_id = '#{target_user}' OR (recordings.band_id IN (SELECT band_id FROM bands_musicians where user_id='#{target_user}')))")
query = query.joins("LEFT OUTER JOIN music_sessions_user_history ON music_sessions_history.id = music_sessions_user_history.music_session_id AND #{require_public_sessions} music_sessions_user_history.user_id = '#{target_user}'")
query = query.group("feeds.id, feeds.recording_id, feeds.music_session_id, feeds.created_at, feeds.updated_at, recordings.id, music_sessions_history.id")
if sort == 'plays'
query = query.group("COALESCE(recordings.play_count, music_sessions_history.play_count)")
elsif sort == 'likes'
query = query.group("COALESCE(recordings.like_count, music_sessions_history.like_count)")
end
query = query.where('recordings.id is NULL OR claimed_recordings.id IS NOT NULL')
query = query.where('music_sessions_history.id is NULL OR music_sessions_user_history.id IS NOT NULL')
elsif target_band
unless Band.find(target_band).users.include?(user)
require_public_recordings = "claimed_recordings.is_public = TRUE AND"
require_public_sessions = "music_sessions_history.fan_access = TRUE AND"
end
query = query.joins("LEFT OUTER JOIN claimed_recordings ON recordings.id = claimed_recordings.recording_id AND #{require_public_recordings} recordings.band_id = '#{target_band}'")
query = query.where("music_sessions_history IS NULL OR #{require_public_sessions} music_sessions_history.band_id = '#{target_band}'")
query = query.group("feeds.id, feeds.recording_id, feeds.music_session_id, feeds.created_at, feeds.updated_at, recordings.id, music_sessions_history.id")
if sort == 'plays'
query = query.group("COALESCE(recordings.play_count, music_sessions_history.play_count)")
elsif sort == 'likes'
query = query.group("COALESCE(recordings.like_count, music_sessions_history.like_count)")
end
query = query.where('recordings.id is NULL OR claimed_recordings.id IS NOT NULL')
#query = query.where('music_sessions_history.id is NULL OR music_sessions_user_history.id IS NOT NULL')
else
query = query.joins('LEFT OUTER JOIN claimed_recordings ON recordings.id = claimed_recordings.recording_id AND claimed_recordings.is_public = TRUE')
query = query.joins("LEFT OUTER JOIN music_sessions_user_history ON music_sessions_history.id = music_sessions_user_history.music_session_id AND music_sessions_history.fan_access = TRUE")
query = query.group("feeds.id, feeds.recording_id, feeds.music_session_id, feeds.created_at, feeds.updated_at, recordings.id, music_sessions_history.id")
if sort == 'plays'
query = query.group("COALESCE(recordings.play_count, music_sessions_history.play_count)")
elsif sort == 'likes'
query = query.group("COALESCE(recordings.like_count, music_sessions_history.like_count)")
end
query = query.where('recordings.id is NULL OR claimed_recordings.is_public = TRUE')
query = query.where('music_sessions_history.id is NULL OR music_sessions_user_history.id IS NOT NULL')
end
if query.length == 0
[query, nil]
elsif query.length < limit

View File

@ -24,7 +24,7 @@ module JamRuby
has_many :recordings, :class_name => "JamRuby::Recording", :inverse_of => :music_session
belongs_to :band, :inverse_of => :music_sessions, :class_name => "JamRuby::Band", :foreign_key => "band_id"
after_save :require_at_least_one_genre, :limit_max_genres
after_save :require_at_least_one_genre, :limit_max_genres, :sync_music_session_history
after_destroy do |obj|
JamRuby::MusicSessionHistory.removed_music_session(obj.id)
@ -277,5 +277,9 @@ module JamRuby
end
end
end
def sync_music_session_history
MusicSessionHistory.save(self)
end
end
end

View File

@ -19,7 +19,7 @@ module JamRuby
:class_name => 'JamRuby::MusicSession',
:foreign_key => 'music_session_id')
has_many :music_session_user_histories, :class_name => "JamRuby::MusicSessionUserHistory", :foreign_key => "music_session_id"
has_many :music_session_user_histories, :class_name => "JamRuby::MusicSessionUserHistory", :foreign_key => "music_session_id", :dependent => :delete_all
has_many :comments, :class_name => "JamRuby::MusicSessionComment", :foreign_key => "music_session_id"
has_many :likes, :class_name => "JamRuby::MusicSessionLiker", :foreign_key => "session_id"
has_many :plays, :class_name => "JamRuby::MusicSessionPlay", :foreign_key => "music_session_id"
@ -39,10 +39,6 @@ module JamRuby
feed.music_session_history = self
end
def like_count
self.likes.size
end
def comment_count
self.comments.size
end
@ -51,12 +47,14 @@ module JamRuby
tracks = []
self.music_session_user_histories.each do |msuh|
user = User.find(msuh.user_id)
instruments = msuh.instruments.split(SEPARATOR)
instruments.each do |instrument|
t = Track.new
t.musician = user
t.instrument_id = instrument
tracks << t
unless msuh.instruments.blank?
instruments = msuh.instruments.split(SEPARATOR)
instruments.each do |instrument|
t = Track.new
t.musician = user
t.instrument_id = instrument
tracks << t
end
end
end
tracks
@ -97,6 +95,18 @@ module JamRuby
.where(%Q{ music_sessions_user_history.music_session_id = '#{music_session_id}'})
end
# returns one user history per user, with instruments all crammed together, and with total duration
def unique_user_histories
MusicSessionUserHistory
.joins(:user)
.select("STRING_AGG(instruments, '|') AS total_instruments,
SUM(date_part('epoch', COALESCE(music_sessions_user_history.session_removed_at, music_sessions_user_history.created_at) - music_sessions_user_history.created_at)) AS total_duration,
music_sessions_user_history.user_id, music_sessions_user_history.music_session_id, users.first_name, users.last_name, users.photo_url")
.group("music_sessions_user_history.user_id, music_sessions_user_history.music_session_id, users.first_name, users.last_name, users.photo_url")
.order("music_sessions_user_history.user_id")
.where(%Q{ music_sessions_user_history.music_session_id = '#{music_session_id}'})
end
def duration_minutes
end_time = self.session_removed_at || Time.now
(end_time - self.created_at) / 60.0
@ -131,6 +141,7 @@ module JamRuby
session_history.user_id = music_session.creator.id
session_history.band_id = music_session.band.id unless music_session.band.nil?
session_history.genres = music_session.genres.map { |g| g.id }.join SEPARATOR
session_history.fan_access = music_session.fan_access
session_history.save!
end

View File

@ -107,7 +107,7 @@ class JamRuby::PromoLatest < JamRuby::Promotional
end
def update_with_params(params)
if (latest_id = params[:latest][:id]).present?
if (latest_id = params[:latest_id]).present?
self.latest = Recording.where(:id => latest_id).limit(1).all[0] ||
MusicSession.where(:id => latest_id).limit(1).all[0]
end

View File

@ -29,7 +29,6 @@ module JamRuby
before_save :sanitize_active_admin
before_create :add_to_feed
def add_to_feed
feed = Feed.new
feed.recording = self
@ -40,14 +39,6 @@ module JamRuby
self.band_id = nil if self.band_id == ''
end
def like_count
self.likes.size
end
def play_count
self.plays.size
end
def comment_count
self.comments.size
end
@ -319,26 +310,6 @@ module JamRuby
save
end
=begin
# This is no longer remotely right.
def self.search(query, options = { :limit => 10 })
# only issue search if at least 2 characters are specified
if query.nil? || query.length < 2
return []
end
# create 'anded' statement
query = Search.create_tsquery(query)
if query.nil? || query.length == 0
return []
end
return Recording.where("description_tsv @@ to_tsquery('jamenglish', ?)", query).limit(options[:limit])
end
=end
private
def self.validate_user_is_band_member(user, band)
unless band.users.exists? user

View File

@ -6,7 +6,9 @@ module JamRuby
self.primary_key = 'id'
belongs_to :recording, :class_name => "JamRuby::Recording", :foreign_key => "recording_id", :counter_cache => :like_count
belongs_to :claimed_recording, :class_name => "JamRuby::ClaimedRecording", :foreign_key => "claimed_recording_id"
belongs_to :user, :class_name => "JamRuby::User", :foreign_key => "liker_id"
validates :favorite, :inclusion => {:in => [true, false]}
end
end

View File

@ -6,6 +6,7 @@ module JamRuby
self.primary_key = 'id'
belongs_to :recording, :class_name => "JamRuby::Recording", :foreign_key => "recording_id", :counter_cache => :play_count
belongs_to :claimed_recording, :class_name => "JamRuby::ClaimedRecording", :foreign_key => "claimed_recording_id"
belongs_to :user, :class_name => "JamRuby::User", :foreign_key => "player_id"
end

View File

@ -275,8 +275,7 @@ module JamRuby
end
def recent_history
recordings = ClaimedRecording.joins(:recording)
.where(:recordings => {:owner_id => "#{self.id}"})
recordings = Recording.where(:owner_id => self.id)
.order('created_at DESC')
.limit(10)

View File

@ -50,7 +50,7 @@ FactoryGirl.define do
factory :music_session do
after(:create) { |session|
MusicSessionHistory.save(session)
FactoryGirl.create(:music_session_user_history, :history => session.music_session_history, :user => session.creator)
}
factory :music_session_with_mount do
@ -66,6 +66,7 @@ FactoryGirl.define do
music_session nil
end
fan_access true
music_session_id { music_session.id }
description { music_session.description }
user_id { music_session.user_id }
@ -78,6 +79,7 @@ FactoryGirl.define do
user nil
end
instruments 'guitar'
music_session_id { history.music_session_id }
user_id { user.id }
sequence(:client_id) { |n| "Connection #{n}" }

View File

@ -23,7 +23,7 @@ describe ConnectionManager do
description = "some session"
@conn.exec("INSERT INTO music_sessions (user_id, description, musician_access, approval_required, fan_chat, fan_access) VALUES ($1, $2, $3, $4, $5, $6) RETURNING id", [user_id, description, options[:musician_access], options[:approval_required], options[:fan_chat], options[:fan_access]]) do |result|
session_id = result.getvalue(0, 0)
@conn.exec("INSERT INTO music_sessions_history (music_session_id, description, user_id) VALUES ($1, $2, $3)", [session_id, description, user_id])
@conn.exec("INSERT INTO music_sessions_history (music_session_id, description, user_id, fan_access) VALUES ($1, $2, $3, $4)", [session_id, description, user_id, true])
return session_id
end
end

View File

@ -125,4 +125,91 @@ describe ClaimedRecording do
instance.remove_non_alpha_num("JDnfHsimMQ").should == 'JDnfHsimMQ'
end
end
describe "favorite_index" do
let(:other_user) { FactoryGirl.create(:user) }
it "returns nothing" do
favorites, start = ClaimedRecording.index_favorites(@user, user: @user.id)
favorites.length.should == 0
start.should be_nil
end
it "angry when no user specified" do
expect { ClaimedRecording.index_favorites(@user, user:other_user ) }.to raise_error "unable to view another user's favorites"
end
it "user must be specified" do
expect { ClaimedRecording.index_favorites(@user) }.to raise_error "user must be specified"
end
it "finds favorite claimed_recording if true, not if false" do
claimed_recording1 = FactoryGirl.create(:claimed_recording, user: @user)
like = FactoryGirl.create(:recording_like, user: @user, claimed_recording: claimed_recording1, recording: claimed_recording1.recording, favorite: true)
favorites, start = ClaimedRecording.index_favorites(@user, user: @user.id)
favorites.length.should == 1
start.should be_nil
like.favorite = false
like.save!
# remove from favorites
favorites, start = ClaimedRecording.index_favorites(@user, user: @user.id)
favorites.length.should == 0
start.should be_nil
end
it "finds others public claimed recordings" do
claimed_recording1 = FactoryGirl.create(:claimed_recording, user: other_user)
like = FactoryGirl.create(:recording_like, user: @user, claimed_recording: claimed_recording1, recording: claimed_recording1.recording, favorite: true)
favorites, start = ClaimedRecording.index_favorites(@user, user: @user.id)
favorites.length.should == 1
start.should be_nil
end
it "can find others private claimed recordings" do
claimed_recording1 = FactoryGirl.create(:claimed_recording, user: other_user)
like = FactoryGirl.create(:recording_like, user: @user, claimed_recording: claimed_recording1, recording: claimed_recording1.recording, favorite: false)
favorites, start = ClaimedRecording.index_favorites(@user, user: @user.id)
favorites.length.should == 0
start.should be_nil
end
it "can find own private claimed recordings" do
claimed_recording1 = FactoryGirl.create(:claimed_recording, user: @user)
like = FactoryGirl.create(:recording_like, user: @user, claimed_recording: claimed_recording1, recording: claimed_recording1.recording, favorite: true)
favorites, start = ClaimedRecording.index_favorites(@user, user: @user.id)
favorites.length.should == 1
start.should be_nil
end
it "pagination" do
claimed_recording1 = FactoryGirl.create(:claimed_recording, user: @user)
claimed_recording2 = FactoryGirl.create(:claimed_recording, user: @user)
like1 = FactoryGirl.create(:recording_like, user: @user, claimed_recording: claimed_recording1, recording: claimed_recording1.recording, favorite: true)
like2 = FactoryGirl.create(:recording_like, user: @user, claimed_recording: claimed_recording2, recording: claimed_recording2.recording, favorite: true)
favorites, start = ClaimedRecording.index_favorites(@user, user: @user.id, limit:1)
favorites.length.should == 1
start.should_not be_nil
favorites, start = ClaimedRecording.index_favorites(@user, user: @user.id, limit:1, start: start)
favorites.length.should == 1
start.should_not be_nil
favorites, start = ClaimedRecording.index_favorites(@user, user: @user.id, limit:1, start: start)
favorites.length.should == 0
start.should be_nil
end
end
end

View File

@ -6,6 +6,7 @@ describe Feed do
let (:user2) { FactoryGirl.create(:user) }
let (:user3) { FactoryGirl.create(:user) }
let (:user4) { FactoryGirl.create(:user) }
let (:band) { FactoryGirl.create(:band) }
it "no result" do
feeds, start = Feed.index(user1)
@ -14,6 +15,7 @@ describe Feed do
it "one claimed recording" do
claimed_recording = FactoryGirl.create(:claimed_recording)
MusicSessionUserHistory.delete_all # the factory makes a music_session while making the recording/claimed_recording
MusicSessionHistory.delete_all # the factory makes a music_session while making the recording/claimed_recording
feeds, start = Feed.index(user1)
feeds.length.should == 1
@ -25,6 +27,7 @@ describe Feed do
second_track = FactoryGirl.create(:recorded_track, recording: recording)
recording.recorded_tracks << second_track
FactoryGirl.create(:claimed_recording, recording: recording, user: second_track.user)
MusicSessionUserHistory.delete_all # the factory makes a music_session while making the recording/claimed_recording
MusicSessionHistory.delete_all
# verify the mess above only made one recording
@ -41,6 +44,15 @@ describe Feed do
feeds[0].music_session_history == music_session.music_session_history
end
it "does not return a recording with no claimed recordings" do
recording = FactoryGirl.create(:recording)
MusicSessionUserHistory.delete_all # the factory makes a music_session while making the recording/claimed_recording
MusicSessionHistory.delete_all
feeds, start = Feed.index(user1)
feeds.length.should == 0
end
describe "sorting" do
it "sorts by index (date) DESC" do
claimed_recording = FactoryGirl.create(:claimed_recording)
@ -55,13 +67,13 @@ describe Feed do
claimed_recording1 = FactoryGirl.create(:claimed_recording)
claimed_recording2 = FactoryGirl.create(:claimed_recording)
FactoryGirl.create(:recording_play, recording: claimed_recording1.recording, user:claimed_recording1.user)
FactoryGirl.create(:recording_play, recording: claimed_recording1.recording, claimed_recording: claimed_recording1, user:claimed_recording1.user)
feeds, start = Feed.index(user1, :sort => 'plays')
feeds.length.should == 4
FactoryGirl.create(:recording_play, recording: claimed_recording2.recording, user:claimed_recording1.user)
FactoryGirl.create(:recording_play, recording: claimed_recording2.recording, user:claimed_recording2.user)
FactoryGirl.create(:recording_play, recording: claimed_recording2.recording, claimed_recording: claimed_recording2, user:claimed_recording1.user)
FactoryGirl.create(:recording_play, recording: claimed_recording2.recording, claimed_recording: claimed_recording2, user:claimed_recording2.user)
feeds, start = Feed.index(user1, :sort => 'plays')
feeds.length.should == 4
@ -84,13 +96,13 @@ describe Feed do
claimed_recording1 = FactoryGirl.create(:claimed_recording)
claimed_recording2 = FactoryGirl.create(:claimed_recording)
FactoryGirl.create(:recording_like, recording: claimed_recording1.recording, user:claimed_recording1.user)
FactoryGirl.create(:recording_like, recording: claimed_recording1.recording, claimed_recording: claimed_recording1, user:claimed_recording1.user)
feeds, start = Feed.index(user1, :sort => 'likes')
feeds.length.should == 4
FactoryGirl.create(:recording_like, recording: claimed_recording2.recording, user:claimed_recording1.user)
FactoryGirl.create(:recording_like, recording: claimed_recording2.recording, user:claimed_recording2.user)
FactoryGirl.create(:recording_like, recording: claimed_recording2.recording, claimed_recording: claimed_recording2, user:claimed_recording1.user)
FactoryGirl.create(:recording_like, recording: claimed_recording2.recording, claimed_recording: claimed_recording2, user:claimed_recording2.user)
feeds, start = Feed.index(user1, :sort => 'likes')
feeds.length.should == 4
@ -242,6 +254,205 @@ describe Feed do
end
end
describe "public feed" do
it "only public" do
claimed_recording1 = FactoryGirl.create(:claimed_recording)
claimed_recording1.is_public = false
claimed_recording1.save!
feeds, start = Feed.index(claimed_recording1.user)
feeds.length.should == 1
claimed_recording1.recording.music_session.fan_access = false
claimed_recording1.recording.music_session.save!
feeds, start = Feed.index(claimed_recording1.user)
feeds.length.should == 0
end
end
describe "band feeds" do
it "does show other band's stuff in this feed" do
other_band = FactoryGirl.create(:band)
music_session = FactoryGirl.create(:music_session, band: other_band)
FactoryGirl.create(:music_session_user_history, :history => music_session.music_session_history, :user => user1)
claimed_recording1 = FactoryGirl.create(:claimed_recording)
claimed_recording1.is_public = true
claimed_recording1.recording.band = other_band
claimed_recording1.recording.save!
claimed_recording1.save!
feeds, start = Feed.index(user1, band: band.id)
feeds.length.should == 0
end
it "shows public recordings to you and to others" do
user1.bands << band
user1.save!
music_session = FactoryGirl.create(:music_session, band: band)
music_session.music_session_history.fan_access.should be_true
feeds, start = Feed.index(user1, band: band.id)
feeds.length.should == 1
feeds[0].music_session_history.should == music_session.music_session_history
feeds, start = Feed.index(user2, band: band.id)
feeds.length.should == 1
feeds[0].music_session_history.should == music_session.music_session_history
end
it "shows private sessions to you, not to others" do
user1.bands << band
user1.save!
music_session = FactoryGirl.create(:music_session, band: band, fan_access: false)
music_session.music_session_history.fan_access.should be_false
feeds, start = Feed.index(user1, band: band.id)
feeds.length.should == 1
feeds[0].music_session_history.should == music_session.music_session_history
feeds[0].music_session_history.fan_access.should be_false
feeds, start = Feed.index(user2, band: band.id)
feeds.length.should == 0
end
it "shows public recordings to you and to others" do
claimed_recording1 = FactoryGirl.create(:claimed_recording)
claimed_recording1.is_public = true
claimed_recording1.recording.band = band
claimed_recording1.recording.save!
claimed_recording1.save!
feeds, start = Feed.index(claimed_recording1.user, band: band.id)
feeds.length.should == 1
feeds[0].recording.should == claimed_recording1.recording
feeds, start = Feed.index(user1, band: band.id)
feeds.length.should == 1
feeds[0].recording.should == claimed_recording1.recording
end
it "shows private recordings to you, not to others" do
claimed_recording1 = FactoryGirl.create(:claimed_recording)
claimed_recording1.is_public = false
claimed_recording1.recording.band = band
claimed_recording1.recording.save!
claimed_recording1.save!
claimed_recording1.user.bands << band
claimed_recording1.user.save!
feeds, start = Feed.index(claimed_recording1.user, band: band.id)
feeds.length.should == 1
feeds[0].recording.should == claimed_recording1.recording
feeds, start = Feed.index(user1, band: band.id)
feeds.length.should == 0
end
end
describe "user feeds" do
it "does not show stuff from other people" do
music_session = FactoryGirl.create(:music_session)
FactoryGirl.create(:music_session_user_history, :history => music_session.music_session_history, :user => user2)
claimed_recording1 = FactoryGirl.create(:claimed_recording)
claimed_recording1.is_public = true
claimed_recording1.save!
feeds, start = Feed.index(user1, user: user1.id)
feeds.length.should == 0
end
it "shows public sessions to you and to others" do
music_session = FactoryGirl.create(:music_session)
FactoryGirl.create(:music_session_user_history, :history => music_session.music_session_history, :user => user1)
feeds, start = Feed.index(user1, user: user1.id)
feeds.length.should == 1
feeds[0].music_session_history.should == music_session.music_session_history
feeds, start = Feed.index(user2, user: user1.id)
feeds.length.should == 1
feeds[0].music_session_history.should == music_session.music_session_history
end
it "shows private sessions to you, not to others" do
music_session = FactoryGirl.create(:music_session, fan_access: false)
music_session.music_session_history.fan_access.should be_false
FactoryGirl.create(:music_session_user_history, :history => music_session.music_session_history, :user => user1)
feeds, start = Feed.index(user1, user: user1.id)
feeds.length.should == 1
feeds[0].music_session_history.should == music_session.music_session_history
feeds[0].music_session_history.fan_access.should be_false
feeds, start = Feed.index(user2, user: user1.id)
feeds.length.should == 0
end
it "shows public recordings to you and to others" do
claimed_recording1 = FactoryGirl.create(:claimed_recording)
claimed_recording1.is_public = true
claimed_recording1.save!
feeds, start = Feed.index(claimed_recording1.user, user: claimed_recording1.user.id)
feeds.length.should == 1
feeds[0].recording.should == claimed_recording1.recording
feeds, start = Feed.index(user1, user: claimed_recording1.user.id)
feeds.length.should == 1
feeds[0].recording.should == claimed_recording1.recording
end
it "shows private recordings to you, not to others" do
claimed_recording1 = FactoryGirl.create(:claimed_recording)
claimed_recording1.is_public = false
claimed_recording1.save!
feeds, start = Feed.index(claimed_recording1.user, user: claimed_recording1.user.id)
feeds.length.should == 1
feeds[0].recording.should == claimed_recording1.recording
feeds, start = Feed.index(user1, user: claimed_recording1.user.id)
feeds.length.should == 0
end
it "shows band recordings to you even though you did not claim a recording" do
user1.bands << band
user1.save!
user2.bands << band
user2.save!
claimed_recording1 = FactoryGirl.create(:claimed_recording, user: user2)
claimed_recording1.is_public = true
claimed_recording1.recording.band = band
claimed_recording1.recording.save!
claimed_recording1.save!
feeds, start = Feed.index(user1, user: user1.id)
feeds.length.should == 1
feeds[0].recording.should == claimed_recording1 .recording
# make it private; should still be available
claimed_recording1.is_public = false
claimed_recording1.save!
feeds, start = Feed.index(user1, user: user1.id)
feeds.length.should == 1
feeds[0].recording.should == claimed_recording1 .recording
# take user1 out of the band; shouldn't be able to see it
user1.bands.delete_all
feeds, start = Feed.index(user1, user: user1.id)
feeds.length.should == 0
end
end
end

View File

@ -2,25 +2,77 @@ require 'spec_helper'
describe MusicSessionHistory do
let(:some_user) { FactoryGirl.create(:user) }
let(:music_session) { FactoryGirl.create(:music_session_no_history) }
let(:history) { FactoryGirl.create(:music_session_history, :music_session => music_session) }
let(:user_history1) { FactoryGirl.create(:music_session_user_history, :history => history, :user => music_session.creator) }
let(:user_history2) { FactoryGirl.create(:music_session_user_history, :history => history, :user => some_user) }
let(:user_history1) { FactoryGirl.create(:music_session_user_history, :history => music_session.music_session_history, :user => music_session.creator, :created_at => 2.days.ago, :session_removed_at => 1.days.ago) }
let(:user_history2) { FactoryGirl.create(:music_session_user_history, :history => music_session.music_session_history, :user => some_user, :created_at => 2.days.ago, :session_removed_at => 1.days.ago) }
let(:user_history3) { FactoryGirl.create(:music_session_user_history, :history => music_session.music_session_history, :user => music_session.creator, :created_at => 3.days.ago, :session_removed_at => 2.days.ago) }
let(:user_history4) { FactoryGirl.create(:music_session_user_history, :history => music_session.music_session_history, :user => some_user, :created_at => 3.days.ago, :session_removed_at => 2.days.ago) }
it "create" do
history.description.should eql(music_session.description)
music_session.music_session_history.description.should eql(music_session.description)
end
it "unique users" do
user_history1.should_not be_nil
user_history2.should_not be_nil
users = history.unique_users
users = music_session.music_session_history.unique_users
users.length.should eql(2)
users.include?(some_user).should be_true
users.include?(music_session.creator).should be_true
user_history3.should_not be_nil
user_history4.should_not be_nil
users = music_session.music_session_history.unique_users
users.length.should eql(2)
users.include?(some_user).should be_true
users.include?(music_session.creator).should be_true
end
it "unique_user_histories" do
created_at = 4.days.ago
session_removed_at = created_at + 1.days
user_history1.created_at = created_at
user_history1.session_removed_at = session_removed_at
user_history1.save!
user_history2.created_at = created_at
user_history2.session_removed_at = session_removed_at
user_history2.save!
histories = music_session.music_session_history.unique_user_histories
histories.length.should eql(2)
histories[0].first_name.should_not be_nil
histories[0].last_name.should_not be_nil
histories[0].photo_url.should be_nil
histories[0].total_duration.to_i.should == 1.day.to_i
histories[0].total_instruments.should == 'guitar'
histories[1].total_duration.to_i.should == 1.day.to_i
histories[1].total_instruments.should == 'guitar'
user_history3.created_at = created_at
user_history3.session_removed_at = session_removed_at
user_history3.save!
user_history4.created_at = created_at
user_history4.session_removed_at = session_removed_at
user_history4.save!
histories = music_session.music_session_history.unique_user_histories
histories.length.should eql(2)
histories[0].total_duration.to_i.should == 2.day.to_i
histories[0].total_instruments.should == 'guitar|guitar'
histories[1].total_duration.to_i.should == 2.day.to_i
histories[1].total_instruments.should == 'guitar|guitar'
users = histories.map {|i| i.user}
users.include?(some_user).should be_true
users.include?(music_session.creator).should be_true
end
end

View File

@ -4,9 +4,8 @@ describe MusicSessionUserHistory do
let(:some_user) { FactoryGirl.create(:user) }
let(:music_session) { FactoryGirl.create(:music_session_no_history) }
let(:history) { FactoryGirl.create(:music_session_history, :music_session => music_session) }
let(:user_history1) { FactoryGirl.create(:music_session_user_history, :history => history, :user => music_session.creator) }
let(:user_history2) { FactoryGirl.create(:music_session_user_history, :history => history, :user => some_user) }
let(:user_history1) { FactoryGirl.create(:music_session_user_history, :history => music_session.music_session_history, :user => music_session.creator) }
let(:user_history2) { FactoryGirl.create(:music_session_user_history, :history => music_session.music_session_history, :user => some_user) }
describe "create" do
it {user_history1.music_session_id.should == music_session.id }
@ -78,7 +77,7 @@ describe MusicSessionUserHistory do
end
it "two histories with same user within bounds of history1" do
user_history3 = FactoryGirl.create(:music_session_user_history, :history => history, :user => some_user)
user_history3 = FactoryGirl.create(:music_session_user_history, :history => music_session.music_session_history, :user => some_user)
# if user2 comes and goes 2 times while user one is there, it shouldn't be a false 3
user_history1.session_removed_at = user_history1.created_at + 5
@ -99,7 +98,7 @@ describe MusicSessionUserHistory do
it "two histories with different user within bounds of history1" do
third_user = FactoryGirl.create(:user);
user_history3 = FactoryGirl.create(:music_session_user_history, :history => history, :user => third_user)
user_history3 = FactoryGirl.create(:music_session_user_history, :history => music_session.music_session_history, :user => third_user)
# if user2 comes and goes 2 times while user one is there, it shouldn't be a false 3
user_history1.session_removed_at = user_history1.created_at + 5
@ -120,7 +119,7 @@ describe MusicSessionUserHistory do
it "two overlapping histories with different user within bounds of history1" do
third_user = FactoryGirl.create(:user);
user_history3 = FactoryGirl.create(:music_session_user_history, :history => history, :user => third_user)
user_history3 = FactoryGirl.create(:music_session_user_history, :history => music_session.music_session_history, :user => third_user)
# if user2 comes and goes 2 times while user one is there, it shouldn't be a false 3
user_history1.session_removed_at = user_history1.created_at + 5

View File

@ -61,6 +61,7 @@ Spork.prefork do
#
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
RSpec.configure do |config|
config.color_enabled = true
config.treat_symbols_as_metadata_keys_with_true_values = true
config.run_all_when_everything_filtered = true
config.filter_run :focus

View File

@ -50,11 +50,11 @@ gem 'filepicker-rails', '0.1.0'
gem 'aws-sdk', '1.29.1'
gem 'aasm', '3.0.16'
gem 'carrierwave'
gem 'carrierwave_direct'
gem 'fog'
gem 'haml-rails'
gem 'unf' #optional fog dependency
gem 'devise', '>= 1.1.2'
gem 'puma' # the presence of this gem on mac seems to prevent normal startup of rails.
gem 'postgres-copy'
#group :libv8 do
# gem 'libv8', "~> 3.11.8"

View File

@ -40,6 +40,7 @@
var recordingHtml = context.JK.fillTemplate(template, {
recordingId: recording.id,
claimedRecordingId: claimedRecording.id,
name: claimedRecording.name,
genre: claimedRecording.genre_id.toUpperCase(),
created_at: context.JK.formatDateTime(recording.created_at),

View File

@ -70,6 +70,7 @@
onSelect: addInvitation,
serviceUrl: '/api/search.json?srch_sessinv=1',
minChars: 3,
autoSelectFirst: true
};
$('#friend-input').attr("placeholder", "Type a friend\'s name").prop('disabled', false);

View File

@ -83,26 +83,36 @@
});
}
function addRecordingLike(recordingId, userId) {
function addRecordingLike(recordingId, claimedRecordingId, userId) {
return $.ajax({
url: '/api/recordings/' + recordingId + "/likes",
type: "POST",
data : JSON.stringify({"user_id": userId}),
data : JSON.stringify({"user_id": userId, claimed_recording_id: claimedRecordingId}),
dataType : 'json',
contentType: 'application/json'
});
}
function addRecordingPlay(recordingId, userId) {
function addRecordingPlay(recordingId, claimedRecordingId, userId) {
return $.ajax({
url: '/api/recordings/' + recordingId + "/plays",
type: "POST",
data : JSON.stringify({"user_id": userId}),
data : JSON.stringify({user_id: userId, claimed_recording_id: claimedRecordingId}),
dataType : 'json',
contentType: 'application/json'
});
}
function updateFavorite(claimedRecordingId, favorite) {
return $.ajax({
url: '/api/favorites/' + claimedRecordingId,
type: "POST",
data : JSON.stringify({favorite: favorite}),
dataType : 'json',
contentType: 'application/json'
});
}
function validateBand(band) {
return $.ajax({
type: "POST",
@ -906,6 +916,7 @@
this.getBandPhotoFilepickerPolicy = getBandPhotoFilepickerPolicy;
this.getBand = getBand;
this.validateBand = validateBand;
this.updateFavorite = updateFavorite;
this.createBandInvitation = createBandInvitation;
this.updateBandInvitation = updateBandInvitation;
this.removeBandMember = removeBandMember;

View File

@ -8,7 +8,7 @@
var $scope = $(".landing-details");
function like() {
rest.addRecordingLike(recordingId, JK.currentUserId)
rest.addRecordingLike(recordingId, claimedRecordingId, JK.currentUserId)
.done(function(response) {
$("#spnLikeCount").html(parseInt($("#spnLikeCount").text()) + 1);
$("#btnLike", $scope).unbind("click");
@ -16,7 +16,7 @@
}
function play() {
rest.addRecordingPlay(recordingId, JK.currentUserId)
rest.addRecordingPlay(recordingId, claimedRecordingId, JK.currentUserId)
.done(function(response) {
$("#spnPlayCount", $scope).html(parseInt($("#spnPlayCount").text()) + 1);
});

View File

@ -45,7 +45,6 @@
.recording-slider {
position:absolute;
left:25%;
top:0px;
}

View File

@ -34,16 +34,16 @@ class ApiController < ApplicationController
def respond_with_model(model, options = {})
if model.errors.any?
response.status = :unprocessable_entity
respond_with model
respond_with model, layout: nil
else
status = options[:new] && options[:new] == true ? 201 : 200
redirect_on_success = options[:location]
if redirect_on_success
location = redirect_on_success.call
raise "location must return something" unless location # development time error
respond_with model, responder: ApiResponder, status: status, location: location
respond_with model, responder: ApiResponder, status: status, location: location, layout: nil
else
respond_with model, responder: ApiResponder, status: status
respond_with model, responder: ApiResponder, status: status, location:nil
end
end
end

View File

@ -0,0 +1,26 @@
class ApiFavoritesController < ApiController
respond_to :json
before_filter :api_signed_in_user
def index
@claimed_recordings, @next = ClaimedRecording.index_favorites(current_user,
start: params[:since],
limit: params[:limit],
sort: params[:sort],
type: params[:type],
user: params[:user])
render "api_favorites/index", :layout => nil
end
def update
id = params[:id]
like = RecordingLiker.find_by_liker_id_and_claimed_recording_id!(current_user.id, id)
like.favorite = params[:favorite] if params.has_key? :favorite
like.save
respond_with_model(like)
end
end

View File

@ -8,7 +8,9 @@ class ApiFeedsController < ApiController
limit: params[:limit],
sort: params[:sort],
time_range: params[:time_range],
type: params[:type])
type: params[:type],
user: params[:user],
band: params[:band])
render "api_feeds/index", :layout => nil
end

View File

@ -121,6 +121,8 @@ class ApiRecordingsController < ApiController
liker = RecordingLiker.new
liker.recording_id = params[:id]
liker.liker_id = params[:user_id]
liker.claimed_recording_id = params[:claimed_recording_id]
liker.favorite = true
liker.ip_address = request.remote_ip
liker.save
@ -142,6 +144,7 @@ class ApiRecordingsController < ApiController
play = RecordingPlay.new
play.recording_id = params[:id]
play.player_id = params[:user_id]
play.claimed_recording_id = params[:claimed_recording_id]
play.ip_address = request.remote_ip
play.save

View File

@ -0,0 +1,20 @@
# encoding: utf-8
class ImageUploader < CarrierWave::Uploader::Base
include CarrierWaveDirect::Uploader
include CarrierWave::MimeTypes
process :set_content_type
def initialize(*)
super
JamRuby::UploaderConfiguration.set_aws_public_configuration(self)
end
# Add a white list of extensions which are allowed to be uploaded.
def extension_white_list
%w(jpg jpeg gif png)
end
end

View File

@ -0,0 +1,7 @@
node :next do |page|
@next
end
node :entries do |page|
partial "api_claimed_recordings/show", object: @claimed_recordings
end

View File

@ -7,15 +7,28 @@ glue :music_session_history do
'music_session_history'
end
attributes :id, :description, :genres, :created_at, :session_removed_at, :comment_count, :like_count, :play_count
attributes :id, :description, :genres, :created_at, :session_removed_at, :comment_count, :like_count, :play_count, :fan_access
child(:user => :creator) {
attributes :id, :first_name, :last_name, :photo_url
}
child(:unique_users => :participants) {
attributes :id, :first_name, :last_name, :photo_url
child(:unique_user_histories => :participants) {
attributes :first_name, :last_name, :photo_url
node :id do |history|
history.user_id
end
# total_duration comes back from the database as a string
node :duration do |history|
history.total_duration.nil? ? 0 : history.total_duration.to_i
end
node :instruments do |history|
history.total_instruments.nil? ? [] : history.total_instruments.split('|').uniq
end
}
child(:band => :band) {
@ -67,7 +80,7 @@ glue :recording do
child(:claimed_recordings => :claimed_recordings) {
attributes :id, :name, :description, :is_public, :is_downloadable, :genre_id
attributes :id, :name, :description, :is_public, :genre_id
child(:user => :creator) {
attributes :id, :first_name, :last_name, :photo_url

View File

@ -48,10 +48,13 @@
<div class="account-mid profile">
<div class="left small mr20" align="center">
<a href="#" class="avatar_large"><img src="{photoUrl}" id="profile-avatar" /></a></div>
<strong>Name:</strong> {name}<br />
<strong>Location:</strong> {location}<br />
<strong>Instruments:</strong> {instruments}
<a href="#" class="avatar_large"><img src="{photoUrl}" id="profile-avatar" /></a>
</div>
<div class="whitespace" style="margin-left:78px;">
<strong>Name:</strong> {name}<br />
<strong>Location:</strong> {location}<br />
<strong>Instruments:</strong> {instruments}
</div>
</div>
<div class="right">

View File

@ -38,7 +38,7 @@
{musicians}
</table><br />
<div align="center">
<div class="left"><a id="btnLike" onclick="addRecordingLike('{recordingId}');" class="button-orange">LIKE</a></div>
<div class="left"><a id="btnLike" onclick="addRecordingLike('{recordingId}', '{claimedRecordingId}');" class="button-orange">LIKE</a></div>
<div style="display:none;" class="left"><a id="btnComment" class="button-orange">COMMENT</a></div>
<div class="left"><a id="btnShare" layout-link="share-dialog" class="button-orange">SHARE</a></div>
</div>

View File

@ -52,10 +52,22 @@
<br clear="all" />
<div class="w100">
<div class="recording-controls">
<a class="left mr20" href="#"><%= image_tag "content/icon_playbutton.png", {:width => 20, :height => 20, :alt => ""} %></a>
<% if !@music_session.music_session.mount.blank? %>
<a class="left mr20" href="#">
<%= image_tag "content/icon_playbutton.png", {:id => "imgPlayPause", :width => 20, :height => 20, :alt => ""} %>
</a>
<% end %>
<% if @music_session.session_removed_at.blank? %>
<div class="session-status">SESSION IN PROGRESS</div>
<div class="recording-current">1:23</div>
<div class="recording-current"></div>
<audio controls preload="none" style="display:none;">
<% unless @music_session.music_session.mount.blank? %>
<source src="<%= @music_session.music_session.mount.url %>" type="<%= @music_session.music_session.mount.resolve_string(:mime_type) %>">
<% end %>
</audio>
<% if @music_session.music_session.mount.blank? %>
<div>No audio available</div>
<% end %>
<% else %>
<div class="session-status-ended">LIVE SESSION ENDED</div>
<% end %>
@ -99,8 +111,38 @@
<% content_for :extra_js do %>
<script type="text/javascript">
$(function () {
var showMusicSession = new JK.ShowMusicSession(JK.app);
showMusicSession.initialize("<%= @music_session.id %>");
var showMusicSession = new JK.ShowMusicSession(JK.app);
showMusicSession.initialize("<%= @music_session.id %>");
// remainder of this code is related to playing/pausing the session
var htmlAudio = $(".recording-controls").find('audio').get(0);
function formatTime(time) {
var minutes = Math.floor(time / 60);
var seconds = Math.floor(time % 60);
return minutes.toString() + ":" + (seconds > 9 ? seconds.toString() : '0' + seconds.toString());
}
$(htmlAudio).on('timeupdate', function() {
$(".recording-current").html(formatTime(htmlAudio.currentTime));
// reset icon to play and slider to far left when done
if (percentComplete === 100) {
$("#imgPlayPause").attr('src', '/assets/content/icon_playbutton.png');
}
});
$("#btnPlayPause").click(function() {
if (htmlAudio.paused) {
htmlAudio.play();
$("#imgPlayPause").attr('src', '/assets/content/icon_pausebutton.png');
}
else {
htmlAudio.pause();
$("#imgPlayPause").attr('src', '/assets/content/icon_playbutton.png');
}
});
});
})
</script>
<% end %>

View File

@ -18,7 +18,7 @@
<% end %>
<div class="landing-band">
<% unless @claimed_recording.recording.band.nil? %>
<% unless @claimed_recording.recording.band.blank? %>
<div class="landing-avatar">
<% unless @claimed_recording.recording.band.photo_url.blank? %>
<%= image_tag "#{@claimed_recording.recording.band.photo_url}", {:alt => ""} %>
@ -51,17 +51,29 @@
<br clear="all" /><%= @claimed_recording.description %><br /><br />
<div class="w100">
<div class="recording-controls">
<a id="btnPlay" class="left"><%= image_tag "content/icon_playbutton.png", {:width => 20, :height => 20, :alt => ""} %></a>
<% if @claimed_recording.has_mix? %>
<a id="btnPlayPause" class="left" href="#">
<%= image_tag "content/icon_playbutton.png", {:id => "imgPlayPause", :width => 20, :height => 20, :alt => ""} %>
</a>
<% end %>
<div class="recording-position">
<div class="recording-time">0:00</div>
<div class="recording-playback">
<div class="recording-slider"><%= image_tag "content/slider_playcontrols.png", {:width => 5, :height => 16, :alt => ""} %></div>
</div>
<div class="recording-time">4:59</div>
<div id="recordingDuration" class="recording-time"></div>
</div>
<div class="recording-current">1:23</div>
<div class="recording-current">0:00</div>
<audio controls preload="none" style="display:none;">
<% if @claimed_recording.has_mix? %>
<source src="<%= claimed_recording_download_url(@claimed_recording.id, 'mp3') %>" type="mp3">
<source src="<%= claimed_recording_download_url(@claimed_recording.id, 'ogg') %>" type="ogg">
<% end %>
</audio>
<% if !@claimed_recording.has_mix? %>
<div>No audio available</div>
<% end %>
</div>
<div class="left white"><%= @claimed_recording.genre_id.capitalize %></div>
<div class="right white">
<span id="spnPlayCount"><%= @claimed_recording.recording.play_count %></span>
@ -101,7 +113,45 @@
$(function () {
var showRecording = new JK.ShowRecording(JK.app);
showRecording.initialize("<%= @claimed_recording.id %>", "<%= @claimed_recording.recording_id %>");
})
// remainder of this code is related to playing/pausing the recording
var htmlAudio = $(".recording-controls").find('audio').get(0);
var durationInitialized = false;
function formatTime(time) {
var minutes = Math.floor(time / 60);
var seconds = Math.floor(time % 60);
return minutes.toString() + ":" + (seconds > 9 ? seconds.toString() : '0' + seconds.toString());
}
// this calculates the original
$(htmlAudio).on('timeupdate', function() {
if (!durationInitialized) {
$("#recordingDuration").html(formatTime(htmlAudio.duration));
durationInitialized = true;
}
var percentComplete = (htmlAudio.currentTime / htmlAudio.duration) * 100;
$(".recording-slider").css({'left': percentComplete + '%'});
$(".recording-current").html(formatTime(htmlAudio.currentTime));
// reset icon to play and slider to far left when done
if (percentComplete === 100) {
$("#imgPlayPause").attr('src', '/assets/content/icon_playbutton.png');
$(".recording-slider").css({'left': 0 + '%'});
}
});
$("#btnPlayPause").click(function() {
if (htmlAudio.paused) {
htmlAudio.play();
$("#imgPlayPause").attr('src', '/assets/content/icon_pausebutton.png');
}
else {
htmlAudio.pause();
$("#imgPlayPause").attr('src', '/assets/content/icon_playbutton.png');
}
});
});
</script>
<% end %>

View File

@ -4,14 +4,15 @@
<% recent_history.each do |history_record| %>
<% if history_record.instance_of? ClaimedRecording %>
<% if history_record.instance_of? Recording %>
<div class="grey f16">
<em><%= history_record.created_at.strftime("%b #{history_record.created_at.day.ordinalize}") %>:</em>
</div>
<div class="f16">
<span class="orange"><strong>RECORDING:</strong></span>
<a recording-id="<%= history_record.id %>" hoveraction="recording" href="/recordings/<%= history_record.id %>" class="white">Test</a>
<a recording-id="<%= history_record.claimed_recordings.first.id %>" hoveraction="recording" href="/recordings/<%= history_record.claimed_recordings.first.id %>" class="white"><%= history_record.claimed_recordings.first.name %></a>
</div>
<div class="f13 lightgrey"><%= history_record.claimed_recordings.first.description %></div>
<% elsif history_record.instance_of? MusicSessionHistory %>
<div class="grey f16">
@ -31,9 +32,9 @@
<span class="grey">Session Ended. Unavailable.</span>
<% end %>
</div>
<div class="f13 lightgrey"><%= history_record.description %></div>
<% end %>
<div class="f13 lightgrey"><%= history_record.description %></div>
<% if history_record != recent_history.last %>
<br /><br />
<% end %>

View File

@ -1,7 +1,7 @@
<!-- buzz item -->
<%= content_tag(:div, :class => "buzz-item small", :data => { :buzz_item => buzz_item.id}) do %>
<%= content_tag(:div, image_tag(buzz_item.image), :class => "avatar_large mr20") %>
<%= content_tag(:div, image_tag(buzz_item.image_url, :size => '54x54'), :class => "avatar_large mr20") %>
<%= content_tag(:div, buzz_item.text_long, :class => "buzz-item-text") %>
<%= content_tag(:div, "--#{buzz_item.text_short}", :class => "right", :style => "margin-top:6px;") %>
<%= content_tag(:div, nil, :class => "clearall") %>

View File

@ -2,7 +2,7 @@
<%= content_tag(:div, :class => "feed-entry") do %>
<!-- avatar -->
<%= content_tag(:div, image_tag(src="images/content/avatar_band1.jpg")) %>
<%= content_tag(:div, image_tag(src="content/avatar_band1.jpg")) %>
<!--<div class="avatar-small ib"><img src="images/content/avatar_band1.jpg"></div>-->
<!-- type and artist -->

View File

@ -26,7 +26,7 @@
<%= content_tag(:div, :class => "home-questions") do -%>
Have questions about how JamKazam works?
<a href="#" id="faq-open">Here are some answers</a>.
<a id="faq-open" href="https://jamkazam.desk.com/customer/portal/articles/1305119-frequently-asked-questions-faq" target="_blank">Here are some answers</a>.
<% end %>
<% end %>
<% end %>

View File

@ -57,7 +57,17 @@ if [ -z $SKIP_TESTS ]; then
bundle exec rspec
if [ "$?" = "0" ]; then
echo "success: ran rspec tests"
else
elif [ "$?" = "20" ]; then
echo "retrying once more"
bundle exec rspec
if [ "$?" = "0" ]; then
echo "success: ran rspec tests"
else
echo "running rspec tests for the second time failed."
exit 1
fi
else
echo "running rspec tests failed."
exit 1
fi

View File

@ -0,0 +1,3 @@
class JamRuby::PromoBuzz < JamRuby::Promotional
mount_uploader :image, ImageUploader
end

View File

@ -347,9 +347,14 @@ SampleApp::Application.routes.draw do
match '/feeds' => 'api_feeds#index', :via => :get
# scoring
# todo scoring should pick the clientid up from the current logged in user
match '/scoring/work/:clientid' => 'api_scoring#work', :via => :get
match '/scoring/worklist/:clientid' => 'api_scoring#worklist', :via => :get
match '/scoring/record' => 'api_scoring#record', :via => :post
# favorites
match '/favorites' => 'api_favorites#index', :via => :get
match '/favorites/:id' => 'api_favorites#update', :via => :post
end
end

View File

@ -43,9 +43,6 @@ MusicSessionManager < BaseManager
# save session parameters for next session
User.save_session_settings(user, music_session)
# save session history
MusicSessionHistory.save(music_session)
# auto-join this user into the newly created session
as_musician = true
connection = ConnectionManager.new.join_music_session(user, client_id, music_session, as_musician, tracks)
@ -96,12 +93,9 @@ MusicSessionManager < BaseManager
update[:genres] = genre_array
end
if music_session.update_attributes(update)
# save session history (only thing that could change is description)
MusicSessionHistory.save(music_session)
end
music_session.update_attributes(update)
return music_session
music_session
end
def participant_create(user, music_session_id, client_id, as_musician, tracks)

View File

@ -32,6 +32,7 @@ namespace :db do
end
task populate: :environment do
make_users(10) if 14 > User.count
make_friends
make_bands
make_band_members

View File

@ -0,0 +1,87 @@
require 'spec_helper'
describe ApiFavoritesController do
render_views
let(:user) { FactoryGirl.create(:user) }
let(:user2) { FactoryGirl.create(:user) }
let(:band) { FactoryGirl.create(:band) }
let(:music_session) { FactoryGirl.create(:music_session, creator: user) }
let(:claimed_recording) { FactoryGirl.create(:claimed_recording) }
before(:each) do
RecordingLiker.delete_all
ClaimedRecording.delete_all
controller.current_user = nil
end
describe "index" do
it "insists on login" do
get :index
response.status.should == 403
end
it "requires user param" do
controller.current_user = user
expect { get :index }.to raise_error "user must be specified"
end
it "can return nothing" do
controller.current_user = user
get :index, { user: user}
json = JSON.parse(response.body, :symbolize_names => true)
json[:entries].length.should == 0
json[:since].should be_nil
end
it "returns one thing" do
claimed_recording.touch
like = FactoryGirl.create(:recording_like, user: user, claimed_recording: claimed_recording, recording: claimed_recording.recording, favorite: true)
controller.current_user = user
get :index, { user: user}
json = JSON.parse(response.body, :symbolize_names => true)
json[:entries].length.should == 1
json[:since].should be_nil
end
end
describe "update" do
it "insists on login" do
post :update, {id: '1'}
response.status.should == 403
end
it "404 if no like for record" do
controller.current_user = user
post :update, {id: claimed_recording.id}
response.status.should == 404
end
it "no favorite specified leaves record alone" do
controller.current_user = user
like = FactoryGirl.create(:recording_like, user: user, claimed_recording: claimed_recording, recording: claimed_recording.recording, favorite: true)
post :update, {:format => 'json', id: claimed_recording.id}
response.status.should == 200
like.reload
like.favorite.should be_true
end
it "can set favorite to false" do
controller.current_user = user
like = FactoryGirl.create(:recording_like, user: user, claimed_recording: claimed_recording, recording: claimed_recording.recording, favorite: true)
post :update, {:format => 'json', id: claimed_recording.id, favorite:false}
response.status.should == 200
like.reload
like.favorite.should be_false
end
end
end

View File

@ -4,11 +4,14 @@ describe ApiFeedsController do
render_views
let(:user) { FactoryGirl.create(:user) }
let(:user2) { FactoryGirl.create(:user) }
let(:band) { FactoryGirl.create(:band) }
let(:music_session) {FactoryGirl.create(:music_session, creator: user) }
let(:claimed_recording) {FactoryGirl.create(:claimed_recording) }
before(:each) do
MusicSession.delete_all
MusicSessionUserHistory.delete_all
MusicSessionHistory.delete_all
Recording.delete_all
end
@ -23,6 +26,7 @@ describe ApiFeedsController do
it "returns a recording" do
claimed_recording.touch
# artifact of factory of :claimed_recording that this gets created
MusicSessionUserHistory.delete_all
MusicSessionHistory.delete_all
get :index
@ -109,4 +113,65 @@ describe ApiFeedsController do
_next.should be_nil
end
end
describe "user targetting" do
it "user viewing own profile" do
music_session.fan_access = false
music_session.save!
controller.current_user = music_session.creator
get :index, { user: music_session.creator.id }
json = JSON.parse(response.body, :symbolize_names => true)
json[:entries].length.should == 1
end
it "user viewing someone else's profile" do
music_session.fan_access = false
music_session.save!
controller.current_user = user2
music_session.music_session_history.reload
music_session.music_session_history.fan_access.should be_false
get :index, { user: music_session.creator.id }
json = JSON.parse(response.body, :symbolize_names => true)
json[:entries].length.should == 0
end
end
describe "band targetting" do
it "user viewing own band" do
user.bands << band
user.save!
claimed_recording1 = FactoryGirl.create(:claimed_recording, user: user)
claimed_recording1.is_public = false
claimed_recording1.recording.band = band
claimed_recording1.recording.save!
claimed_recording1.save!
controller.current_user = user
get :index, { band: band.id }
json = JSON.parse(response.body, :symbolize_names => true)
json[:entries].length.should == 1
end
it "user viewing someone else's band" do
user.bands << band
user.save!
claimed_recording1 = FactoryGirl.create(:claimed_recording, user: user)
claimed_recording1.is_public = false
claimed_recording1.recording.band = band
claimed_recording1.recording.save!
claimed_recording1.save!
controller.current_user = user2
get :index, { band: band.id }
json = JSON.parse(response.body, :symbolize_names => true)
json[:entries].length.should == 0
end
end
end

View File

@ -52,12 +52,20 @@ FactoryGirl.define do
association :creator, :factory => :user
after(:create) { |session|
MusicSessionHistory.save(session)
FactoryGirl.create(:music_session_user_history, :history => session.music_session_history, :user => session.creator)
}
end
factory :music_session_user_history, :class => JamRuby::MusicSessionUserHistory do
ignore do
history nil
user nil
end
music_session_id { history.music_session_id }
user_id { user.id }
sequence(:client_id) { |n| "Connection #{n}" }
end
@ -344,4 +352,20 @@ FactoryGirl.define do
sequence(:token) { |n| "token-#{n}"}
token_expires_at Time.now
end
factory :recording_play, :class => JamRuby::RecordingPlay do
end
factory :music_session_play, :class => JamRuby::MusicSessionPlay do
end
factory :recording_like, :class => JamRuby::RecordingLiker do
end
factory :music_session_like, :class => JamRuby::MusicSessionLiker do
end
end

View File

@ -8,8 +8,6 @@ describe "social metadata" do
subject { page }
share_examples_for :has_default_metadata do
it "should have default metadata" do
page.find('meta[property="fb:app_id"]', :visible => false)['content'].should == Rails.application.config.facebook_app_id
@ -22,7 +20,6 @@ describe "social metadata" do
end
end
describe "default layout metadata" do
let(:user) {FactoryGirl.create(:user) }

View File

@ -24,14 +24,21 @@ require 'jam_ruby'
# uncomment this to see active record logs
# ActiveRecord::Base.logger = Logger.new(STDOUT) if defined?(ActiveRecord::Base)
include JamRuby
# put ActionMailer into test mode
ActionMailer::Base.delivery_method = :test
RecordedTrack.observers.disable :all # only a few tests want this observer active
# a way to kill tests if they aren't running. capybara is hanging intermittently, I think
tests_started = false
Thread.new {
sleep 30
unless tests_started
puts "tests are hung. exiting..."
exit! 20
end
}
Spork.prefork do
# Loading more in this block will cause your tests to run faster. However,
@ -67,11 +74,6 @@ Spork.prefork do
config.visible_text_only = true
end
Capybara.server do |app, port|
require 'rack/handler/puma'
Rack::Handler::Puma.run(app, :Port => port)
end
# Requires supporting ruby files with custom matchers and macros, etc,
# in spec/support/ and its subdirectories.
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
@ -110,11 +112,10 @@ Spork.prefork do
config.include Requests::FeatureHelpers, type: :feature
config.before(:suite) do
tests_started = true
end
config.before(:all) do
end
config.before(:each) do
@ -141,8 +142,8 @@ Spork.prefork do
# dump response.body if an example fails
if example.metadata[:type] == :controller && example.exception
puts "'#{determine_test_name(example.metadata)}' controller test failed."
puts "response.status = #{response.status}, response.body = " + response.body
puts "'#{determine_test_name(example.metadata)}' controller test failed."
puts "response.status = #{response.status}, response.body = " + response.body
end
end

View File

@ -56,8 +56,8 @@ end
def sign_in_poltergeist(user)
visit signin_path
fill_in "Email Address:", with: user.email
fill_in "Password:", with: user.password
fill_in "session_email", with: user.email
fill_in "session_password", with: user.password
click_button "SIGN IN"
if Capybara.javascript_driver == :poltergeist