diff --git a/db/manifest b/db/manifest
index b60019172..6ddf7a6aa 100755
--- a/db/manifest
+++ b/db/manifest
@@ -78,4 +78,6 @@ add_user_bio.sql
users_geocoding.sql
recordings_public_launch.sql
notification_band_invite.sql
+band_photo_filepicker.sql
+bands_geocoding.sql
store_s3_filenames.sql
diff --git a/db/up/band_photo_filepicker.sql b/db/up/band_photo_filepicker.sql
new file mode 100644
index 000000000..181fc1469
--- /dev/null
+++ b/db/up/band_photo_filepicker.sql
@@ -0,0 +1,4 @@
+ALTER TABLE bands ADD COLUMN original_fpfile_photo VARCHAR(8000) DEFAULT NULL;
+ALTER TABLE bands ADD COLUMN cropped_fpfile_photo VARCHAR(8000) DEFAULT NULL;
+ALTER TABLE bands ADD COLUMN cropped_s3_path_photo VARCHAR(512) DEFAULT NULL;
+ALTER TABLE bands ADD COLUMN crop_selection_photo VARCHAR(256) DEFAULT NULL;
\ No newline at end of file
diff --git a/db/up/bands_geocoding.sql b/db/up/bands_geocoding.sql
new file mode 100644
index 000000000..cf612ac0e
--- /dev/null
+++ b/db/up/bands_geocoding.sql
@@ -0,0 +1,4 @@
+ALTER TABLE bands ADD COLUMN lat NUMERIC(15,10);
+ALTER TABLE bands ADD COLUMN lng NUMERIC(15,10);
+
+UPDATE bands SET country = 'US' WHERE country = 'USA';
diff --git a/ruby/lib/jam_ruby/models/band.rb b/ruby/lib/jam_ruby/models/band.rb
index 5f47cdb9d..3ce6fee36 100644
--- a/ruby/lib/jam_ruby/models/band.rb
+++ b/ruby/lib/jam_ruby/models/band.rb
@@ -1,12 +1,20 @@
module JamRuby
class Band < ActiveRecord::Base
- attr_accessible :name, :website, :biography, :city, :state, :country
+ attr_accessible :name, :website, :biography, :city, :state,
+ :country, :original_fpfile_photo, :cropped_fpfile_photo,
+ :cropped_s3_path_photo, :crop_selection_photo, :photo_url
+
+ attr_accessor :updating_photo
self.primary_key = 'id'
+ before_save :stringify_photo_info , :if => :updating_photo
+ validate :validate_photo_info
validates :biography, no_profanity: true
+ before_save :check_lat_lng
+
# musicians
has_many :band_musicians, :class_name => "JamRuby::BandMusician"
has_many :users, :through => :band_musicians, :class_name => "JamRuby::User"
@@ -34,6 +42,9 @@ module JamRuby
has_many :music_sessions, :class_name => "JamRuby::MusicSession", :foreign_key => "band_id"
has_many :music_session_history, :class_name => "JamRuby::MusicSessionHistory", :foreign_key => "band_id", :inverse_of => :band
+ include Geokit::ActsAsMappable::Glue unless defined?(acts_as_mappable)
+ acts_as_mappable
+
def liker_count
return self.likers.size
end
@@ -57,6 +68,14 @@ module JamRuby
loc
end
+ def validate_photo_info
+ if updating_photo
+ # we want to mak sure that original_fpfile and cropped_fpfile seems like real fpfile info objects (i.e, json objects from filepicker.io)
+ errors.add(:original_fpfile_photo, ValidationMessages::INVALID_FPFILE) if self.original_fpfile_photo.nil? || self.original_fpfile_photo["key"].nil? || self.original_fpfile_photo["url"].nil?
+ errors.add(:cropped_fpfile_photo, ValidationMessages::INVALID_FPFILE) if self.cropped_fpfile_photo.nil? || self.cropped_fpfile_photo["key"].nil? || self.cropped_fpfile_photo["url"].nil?
+ end
+ end
+
def add_member(user_id, admin)
BandMusician.create(:band_id => self.id, :user_id => user_id, :admin => admin)
end
@@ -82,11 +101,11 @@ module JamRuby
if hide_private
recordings = Recording.joins(:band_recordings)
- .where(:bands_recordings => {:band_id => "#{band_id}"}, :public => true)
+ .where(:bands_recordings => {:band_id => "#{band_id}"}, :public => true)
else
recordings = Recording.joins(:band_recordings)
- .where(:bands_recordings => {:band_id => "#{band_id}"})
+ .where(:bands_recordings => {:band_id => "#{band_id}"})
end
return recordings
@@ -111,11 +130,10 @@ module JamRuby
# helper method for creating / updating a Band
def self.save(id, name, website, biography, city, state, country, genres, user_id, photo_url, logo_url)
-
user = User.find(user_id)
# new band
- if id.nil?
+ if id.blank?
# ensure person creating this Band is a Musician
unless user.musician?
@@ -125,7 +143,7 @@ module JamRuby
validate_genres(genres, false)
band = Band.new()
- # band update
+ # band update
else
validate_genres(genres, true)
band = Band.find(id)
@@ -154,56 +172,115 @@ module JamRuby
# country
band.country = country unless country.nil?
- # genres
- unless genres.nil?
- ActiveRecord::Base.transaction do
- # delete all genres for this band first
- unless band.id.nil? || band.id.length == 0
- band.genres.delete_all
- end
-
- # loop through each genre in the array and save to the db
- genres.each do |genre_id|
- g = Genre.find(genre_id)
- band.genres << g
- end
- end
- end
-
# photo url
band.photo_url = photo_url unless photo_url.nil?
# logo url
band.logo_url = logo_url unless logo_url.nil?
- band.updated_at = Time.now.getutc
- band.save
+ # band.updated_at = Time.now.getutc
+ band.save!
+ band.reload
+
+ # genres
+ unless genres.nil?
+ ActiveRecord::Base.transaction do
+ # delete all genres for this band first
+ band.genres.delete_all if id.present?
+ # loop through each genre in the array and save to the db
+ genres.each { |genre_id| band.genres << Genre.find(genre_id) }
+ end
+ end
# add the creator as the admin
- if id.nil?
- BandMusician.create(:band_id => band.id, :user_id => user_id, :admin => true)
- end
+ BandMusician.create(:band_id => band.id, :user_id => user_id, :admin => true) if id.blank?
return band
end
- private
- def self.validate_genres(genres, is_nil_ok)
- if is_nil_ok && genres.nil?
- return
+ def update_photo(original_fpfile, cropped_fpfile, crop_selection, aws_bucket)
+ self.updating_photo = true
+
+ cropped_s3_path = cropped_fpfile["key"]
+
+ return self.update_attributes(
+ :original_fpfile_photo => original_fpfile,
+ :cropped_fpfile_photo => cropped_fpfile,
+ :cropped_s3_path_photo => cropped_s3_path,
+ :crop_selection_photo => crop_selection,
+ :photo_url => S3Util.url(aws_bucket, cropped_s3_path, :secure => false)
+ )
+ end
+
+ def delete_photo(aws_bucket)
+
+ Band.transaction do
+
+ unless self.cropped_s3_path_photo.nil?
+ S3Util.delete(aws_bucket, File.dirname(self.cropped_s3_path_photo) + '/cropped.jpg')
+ S3Util.delete(aws_bucket, self.cropped_s3_path_photo)
end
- if genres.nil?
- raise JamRuby::JamArgumentError, ValidationMessages::GENRE_MINIMUM_NOT_MET
- else
- if genres.size < Limits::MIN_GENRES_PER_BAND
- raise JamRuby::JamArgumentError, ValidationMessages::GENRE_MINIMUM_NOT_MET
- end
+ return self.update_attributes(
+ :original_fpfile_photo => nil,
+ :cropped_fpfile_photo => nil,
+ :cropped_s3_path_photo => nil,
+ :crop_selection_photo => nil,
+ :photo_url => nil
+ )
+ end
+ end
- if genres.size > Limits::MAX_GENRES_PER_BAND
- raise JamRuby::JamArgumentError, ValidationMessages::GENRE_LIMIT_EXCEEDED
+ def check_lat_lng
+ if (city_changed? || state_changed? || country_changed?)
+ update_lat_lng
+ end
+ true
+ end
+
+ def update_lat_lng
+ if self.city
+ query = { :city => self.city }
+ query[:region] = self.state unless self.state.blank?
+ query[:country] = self.country unless self.country.blank?
+ if geo = MaxMindGeo.where(query).limit(1).first
+ if geo.lat && geo.lng && (self.lat != geo.lat || self.lng != geo.lng)
+ self.lat, self.lng = geo.lat, geo.lng
+ return true
end
end
end
+ self.lat, self.lng = nil, nil
+ false
+ end
+
+ private
+ def self.validate_genres(genres, is_nil_ok)
+ if is_nil_ok && genres.nil?
+ return
+ end
+
+ if genres.nil?
+ raise JamRuby::JamArgumentError, ValidationMessages::GENRE_MINIMUM_NOT_MET
+ else
+ if genres.size < Limits::MIN_GENRES_PER_BAND
+ raise JamRuby::JamArgumentError, ValidationMessages::GENRE_MINIMUM_NOT_MET
+ end
+
+ if genres.size > Limits::MAX_GENRES_PER_BAND
+ raise JamRuby::JamArgumentError, ValidationMessages::GENRE_LIMIT_EXCEEDED
+ end
+ end
+ end
+
+ def stringify_photo_info
+ # fpfile comes in as a hash, which is a easy-to-use and validate form. However, we store it as a VARCHAR,
+ # so we need t oconvert it to JSON before storing it (otherwise it gets serialized as a ruby object)
+ # later, when serving this data out to the REST API, we currently just leave it as a string and make a JSON capable
+ # client parse it, because it's very rare when it's needed at all
+ self.original_fpfile_photo = original_fpfile_photo.to_json if !original_fpfile_photo.nil?
+ self.cropped_fpfile_photo = cropped_fpfile_photo.to_json if !cropped_fpfile_photo.nil?
+ self.crop_selection_photo = crop_selection_photo.to_json if !crop_selection_photo.nil?
+ end
end
end
diff --git a/ruby/lib/jam_ruby/models/max_mind_geo.rb b/ruby/lib/jam_ruby/models/max_mind_geo.rb
index 81868c4cd..713938552 100644
--- a/ruby/lib/jam_ruby/models/max_mind_geo.rb
+++ b/ruby/lib/jam_ruby/models/max_mind_geo.rb
@@ -40,7 +40,35 @@ module JamRuby
end
end
User.find_each { |usr| usr.update_lat_lng }
+ Band.find_each { |bnd| bnd.update_lat_lng }
end
+
+ def self.where_latlng(relation, params, current_user=nil)
+ if 0 < (distance = params[:distance].to_i)
+ latlng = []
+ if location_city = params[:city]
+ if geo = self.where(:city => params[:city]).limit(1).first
+ latlng = [geo.lat, geo.lng]
+ end
+ elsif current_user
+ if current_user.lat.nil? || current_user.lng.nil?
+ if params[:remote_ip] && (geo = self.ip_lookup(params[:remote_ip]))
+ latlng = [geo.lat, geo.lng] if geo.lat && geo.lng
+ end
+ else
+ latlng = [current_user.lat, current_user.lng]
+ end
+ elsif params[:remote_ip] && (geo = self.ip_lookup(params[:remote_ip]))
+ latlng = [geo.lat, geo.lng] if geo.lat && geo.lng
+ end
+ if latlng.present?
+ relation = relation.where(['lat IS NOT NULL AND lng IS NOT NULL'])
+ .within(distance, :origin => latlng)
+ end
+ end
+ relation
+ end
+
end
end
diff --git a/ruby/lib/jam_ruby/models/search.rb b/ruby/lib/jam_ruby/models/search.rb
index 63221d8aa..930bb109c 100644
--- a/ruby/lib/jam_ruby/models/search.rb
+++ b/ruby/lib/jam_ruby/models/search.rb
@@ -2,6 +2,7 @@ module JamRuby
# not a active_record model; just a search result
class Search
attr_accessor :bands, :musicians, :fans, :recordings, :friends, :search_type
+ attr_accessor :bands_filter, :musicians_filter
LIMIT = 10
# performs a site-white search
@@ -30,6 +31,8 @@ module JamRuby
@fans = []
@recordings = []
@friends = []
+ @musicians_filter = []
+ @bands_filter = []
if search_results.nil?
return
@@ -39,7 +42,6 @@ module JamRuby
if result.class == User
if result.musician
@musicians.push(result)
- @search_type = PARAM_MUSICIAN
else
@fans.push(result)
end
@@ -84,19 +86,23 @@ module JamRuby
attr_accessor :user_counters, :page_num, :page_count
PARAM_MUSICIAN = :srch_m
+ PARAM_BAND = :srch_b
- M_PER_PAGE = 10
+ B_PER_PAGE = M_PER_PAGE = 10
M_MILES_DEFAULT = 500
+ B_MILES_DEFAULT = 0
M_ORDER_FOLLOWS = ['Most Followed', :followed]
M_ORDER_PLAYS = ['Most Plays', :plays]
M_ORDER_PLAYING = ['Playing Now', :playing]
- M_ORDERINGS = [M_ORDER_FOLLOWS, M_ORDER_PLAYS, M_ORDER_PLAYING]
- M_ORDERING_KEYS = M_ORDERINGS.collect { |oo| oo[1] }
+ ORDERINGS = B_ORDERINGS = M_ORDERINGS = [M_ORDER_FOLLOWS, M_ORDER_PLAYS, M_ORDER_PLAYING]
+ B_ORDERING_KEYS = M_ORDERING_KEYS = M_ORDERINGS.collect { |oo| oo[1] }
- def self.musician_order_param(params)
+ DISTANCE_OPTS = B_DISTANCE_OPTS = M_DISTANCE_OPTS = [['Any', 0], [1000.to_s, 1000], [500.to_s, 500], [250.to_s, 250], [100.to_s, 100], [50.to_s, 50], [25.to_s, 25]]
+
+ def self.order_param(params, keys=M_ORDERING_KEYS)
ordering = params[:orderby]
- ordering.blank? ? M_ORDERING_KEYS[0] : M_ORDERING_KEYS.detect { |oo| oo.to_s == ordering }
+ ordering.blank? ? keys[0] : keys.detect { |oo| oo.to_s == ordering }
end
def self.musician_search(params={}, current_user=nil)
@@ -106,31 +112,10 @@ module JamRuby
.where(['minst.instrument_id = ? AND users.id IS NOT NULL', instrument])
end
- location_distance, location_city = params[:distance], params[:city]
- distance, latlng = nil, []
- if location_distance && location_city
- if geo = MaxMindGeo.where(:city => params[:city]).limit(1).first
- distance, latlng = location_distance, [geo.lat, geo.lng]
- end
- elsif current_user
- if current_user.lat.nil? || current_user.lng.nil?
- if params[:remote_ip] && (geo = MaxMindGeo.ip_lookup(params[:remote_ip]))
- latlng = [geo.lat, geo.lng] if geo.lat && geo.lng
- end
- else
- latlng = [current_user.lat, current_user.lng]
- end
- elsif params[:remote_ip] && (geo = MaxMindGeo.ip_lookup(params[:remote_ip]))
- latlng = [geo.lat, geo.lng] if geo.lat && geo.lng
- end
- if latlng.present?
- distance ||= location_distance || M_MILES_DEFAULT
- rel = rel.where(['lat IS NOT NULL AND lng IS NOT NULL'])
- .within(distance, :origin => latlng)
- end
+ rel = MaxMindGeo.where_latlng(rel, params, current_user)
sel_str = 'users.*'
- case ordering = self.musician_order_param(params)
+ case ordering = self.order_param(params)
when :plays # FIXME: double counting?
sel_str = "COUNT(records)+COUNT(sessions) AS play_count, #{sel_str}"
rel = rel.joins("LEFT JOIN music_sessions AS sessions ON sessions.user_id = users.id")
@@ -150,9 +135,7 @@ module JamRuby
end
rel = rel.select(sel_str)
- perpage = [(params[:per_page] || M_PER_PAGE).to_i, 100].min
- page = [params[:page].to_i, 1].max
- rel = rel.paginate(:page => page, :per_page => perpage)
+ rel, page = self.relation_pagination(rel, params)
rel = rel.includes([:instruments, :followings, :friends])
objs = rel.all
@@ -161,6 +144,12 @@ module JamRuby
srch.musician_results_for_user(objs, current_user)
end
+ def self.relation_pagination(rel, params)
+ perpage = [(params[:per_page] || M_PER_PAGE).to_i, 100].min
+ page = [params[:page].to_i, 1].max
+ [rel.paginate(:page => page, :per_page => perpage), page]
+ end
+
RESULT_FOLLOW = :follows
RESULT_FRIEND = :friends
@@ -171,10 +160,10 @@ module JamRuby
COUNTERS = [COUNT_FRIEND, COUNT_FOLLOW, COUNT_RECORD, COUNT_SESSION]
def musician_results_for_user(results, user)
- @search_type, @musicians = PARAM_MUSICIAN, results
+ @search_type, @musicians_filter = PARAM_MUSICIAN, results
if user
@user_counters = results.inject({}) { |hh,val| hh[val.id] = []; hh }
- mids = "'#{@musicians.map(&:id).join("','")}'"
+ mids = "'#{@musicians_filter.map(&:id).join("','")}'"
# this gets counts for each search result on friends/follows/records/sessions
results.each do |uu|
@@ -258,5 +247,73 @@ module JamRuby
end
end
+ def self.band_search(params={}, current_user=nil)
+ rel = Band.scoped
+
+ unless (genre = params[:genre]).blank?
+ rel = Band.joins("RIGHT JOIN bands_genres AS bgenres ON bgenres.band_id = bands.id")
+ .where(['bgenres.genre_id = ? AND bands.id IS NOT NULL', genre])
+ end
+
+ rel = MaxMindGeo.where_latlng(rel, params, current_user)
+
+ sel_str = 'bands.*'
+ case ordering = self.order_param(params)
+ when :plays # FIXME: double counting?
+ sel_str = "COUNT(records)+COUNT(sessions) AS play_count, #{sel_str}"
+ rel = rel.joins("LEFT JOIN music_sessions AS sessions ON sessions.band_id = bands.id")
+ .joins("LEFT JOIN recordings AS records ON records.band_id = bands.id")
+ .group("bands.id")
+ .order("play_count DESC, bands.created_at DESC")
+ when :followed
+ sel_str = "COUNT(follows) AS search_follow_count, #{sel_str}"
+ rel = rel.joins("LEFT JOIN bands_followers AS follows ON follows.band_id = bands.id")
+ .group("bands.id")
+ .order("COUNT(follows) DESC, bands.created_at DESC")
+ when :playing
+ rel = rel.joins("LEFT JOIN music_sessions_history AS msh ON msh.band_id = bands.id")
+ .where('msh.music_session_id IS NOT NULL AND msh.session_removed_at IS NULL')
+ .order("bands.created_at DESC")
+ end
+
+ rel = rel.select(sel_str)
+ rel, page = self.relation_pagination(rel, params)
+ rel = rel.includes([{ :users => :instruments }, :genres ])
+
+ objs = rel.all
+ srch = Search.new
+ srch.page_num, srch.page_count = page, objs.total_pages
+ srch.band_results_for_user(objs, current_user)
+ end
+
+ def band_results_for_user(results, user)
+ @search_type, @bands_filter = PARAM_BAND, results
+ if user
+ @user_counters = results.inject({}) { |hh,val| hh[val.id] = []; hh }
+ mids = "'#{@bands_filter.map(&:id).join("','")}'"
+
+ # this gets counts for each search result
+ results.each do |bb|
+ counters = { }
+ counters[COUNT_FOLLOW] = BandFollowing.where(:band_id => bb.id).count
+ counters[COUNT_RECORD] = Recording.where(:band_id => bb.id).count
+ counters[COUNT_SESSION] = MusicSession.where(:band_id => bb.id).count
+ @user_counters[bb.id] << counters
+ end
+
+ # this section determines follow/like/friend status for each search result
+ # so that action links can be activated or not
+
+ rel = Band.select("bands.id AS bid")
+ rel = rel.joins("LEFT JOIN bands_followers AS follows ON follows.follower_id = '#{user.id}'")
+ rel = rel.where(["bands.id IN (#{mids}) AND follows.band_id = bands.id"])
+ rel.all.each { |val| @user_counters[val.bid] << RESULT_FOLLOW }
+
+ else
+ @user_counters = {}
+ end
+ self
+ end
+
end
end
diff --git a/ruby/lib/jam_ruby/models/user.rb b/ruby/lib/jam_ruby/models/user.rb
index b9d81bdb2..cc933e38f 100644
--- a/ruby/lib/jam_ruby/models/user.rb
+++ b/ruby/lib/jam_ruby/models/user.rb
@@ -261,6 +261,10 @@ module JamRuby
return self.band_likes.size
end
+ def following?(user)
+ self.followings.exists?(user)
+ end
+
def follower_count
return self.followers.size
end
@@ -618,6 +622,10 @@ module JamRuby
favorite.save
end
+ def favorite_count
+ 0 # FIXME: update this with recording likes count when implemented
+ end
+
def self.delete_favorite(user_id, recording_id)
JamRuby::UserFavorite.delete_all "(user_id = '#{user_id}' AND recording_id = '#{recording_id}')"
end
diff --git a/ruby/spec/jam_ruby/models/band_filter_search_spec.rb b/ruby/spec/jam_ruby/models/band_filter_search_spec.rb
new file mode 100644
index 000000000..51e43f403
--- /dev/null
+++ b/ruby/spec/jam_ruby/models/band_filter_search_spec.rb
@@ -0,0 +1,187 @@
+require 'spec_helper'
+
+describe 'Band search' do
+
+ before(:each) do
+ @geocode1 = FactoryGirl.create(:geocoder)
+ @geocode2 = FactoryGirl.create(:geocoder)
+ @bands = []
+ @bands << @band1 = FactoryGirl.create(:band)
+ @bands << @band2 = FactoryGirl.create(:band)
+ @bands << @band3 = FactoryGirl.create(:band)
+ @bands << @band4 = FactoryGirl.create(:band)
+
+ @bands.each do |bb|
+ FactoryGirl.create(:band_musician, :band => bb, :user => FactoryGirl.create(:user))
+ (rand(4)+1).downto(1) do |nn|
+ FactoryGirl.create(:band_musician, :band => bb, :user => FactoryGirl.create(:user))
+ end
+ end
+
+ end
+
+ context 'default filter settings' do
+
+ it "finds all bands" do
+ # expects all the bands
+ num = Band.count
+ results = Search.band_search({ :per_page => num })
+ expect(results.bands_filter.count).to eq(num)
+ end
+
+ it "finds bands with proper ordering" do
+ # the ordering should be create_at since no followers exist
+ expect(BandFollower.count).to eq(0)
+ results = Search.band_search({ :per_page => Band.count })
+ results.bands_filter.each_with_index do |uu, idx|
+ expect(uu.id).to eq(@bands.reverse[idx].id)
+ end
+ end
+
+ it "sorts bands by followers" do
+ users = []
+ 4.downto(1) { |nn| users << FactoryGirl.create(:user) }
+
+ # establish sorting order
+ @band4.followers.concat(users[1..-1])
+ @band3.followers.concat(users[1..3])
+ @band2.followers.concat(users[0])
+ @bands.map(&:reload)
+
+ expect(@band4.followers.count).to be 3
+ expect(BandFollower.count).to be 7
+
+ # refresh the order to ensure it works right
+ @band2.followers.concat(users[1..-1])
+ results = Search.band_search({ :per_page => @bands.size }, users[0])
+ expect(results.bands_filter[0].id).to eq(@band2.id)
+
+ # check the follower count for given entry
+ expect(results.bands_filter[0].search_follow_count.to_i).not_to eq(0)
+ # check the follow relationship between current_user and result
+ expect(results.is_follower?(@band2)).to be true
+ end
+
+ it 'paginates properly' do
+ # make sure pagination works right
+ params = { :per_page => 2, :page => 1 }
+ results = Search.band_search(params)
+ expect(results.bands_filter.count).to be 2
+ end
+
+ end
+
+ def make_session(band)
+ usr = band.users[0]
+ session = FactoryGirl.create(:music_session, :creator => usr, :description => "Session", :band => band)
+ FactoryGirl.create(:connection, :user => usr, :music_session => session)
+ user = FactoryGirl.create(:user)
+ session
+ end
+
+ context 'band stat counters' do
+
+ it "follow stat shows follower count" do
+ users = []
+ 2.downto(1) { |nn| users << FactoryGirl.create(:user) }
+
+ # establish sorting order
+ @band1.followers.concat(users)
+ results = Search.band_search({},@band1)
+ uu = results.bands_filter.detect { |mm| mm.id == @band1.id }
+ expect(uu).to_not be_nil
+ expect(results.follow_count(uu)).to eq(users.count)
+ end
+
+ it "session stat shows session count" do
+ make_session(@band1)
+ @band1.reload
+ results = Search.band_search({},@band1)
+ uu = results.bands_filter.detect { |mm| mm.id == @band1.id }
+ expect(uu).to_not be_nil
+ expect(results.session_count(uu)).to be 1
+ end
+
+ end
+
+ context 'band sorting' do
+
+ it "by plays" do
+ make_session(@band2)
+ make_session(@band2)
+ make_session(@band2)
+ make_session(@band1)
+ # order results by num recordings
+ results = Search.band_search({ :orderby => 'plays' })
+ expect(results.bands_filter[0].id).to eq(@band2.id)
+ expect(results.bands_filter[1].id).to eq(@band1.id)
+ end
+
+ it "by now playing" do
+ # should get 1 result with 1 active session
+ session = make_session(@band3)
+ FactoryGirl.create(:music_session_history, :music_session => session)
+
+ results = Search.band_search({ :orderby => 'playing' })
+ expect(results.bands_filter.count).to be 1
+ expect(results.bands_filter.first.id).to eq(@band3.id)
+
+ # should get 2 results with 2 active sessions
+ # sort order should be created_at DESC
+ session = make_session(@band4)
+ FactoryGirl.create(:music_session_history, :music_session => session)
+ results = Search.band_search({ :orderby => 'playing' })
+ expect(results.bands_filter.count).to be 2
+ expect(results.bands_filter[0].id).to eq(@band4.id)
+ expect(results.bands_filter[1].id).to eq(@band3.id)
+ end
+
+ end
+
+
+ context 'filter settings' do
+ it "searches bands for a genre" do
+ genre = FactoryGirl.create(:genre)
+ @band1.genres << genre
+ @band1.reload
+ ggg = @band1.genres.detect { |gg| gg.id == genre.id }
+ expect(ggg).to_not be_nil
+ results = Search.band_search({ :genre => ggg.id })
+ results.bands_filter.each do |rr|
+ expect(rr.genres.detect { |gg| gg.id==ggg.id }.id).to eq(genre.id)
+ end
+ expect(results.bands_filter.count).to be 1
+ end
+
+ it "finds bands within a given distance of given location" do
+ num = Band.count
+ expect(@band1.lat).to_not be_nil
+ # short distance
+ results = Search.band_search({ :per_page => num,
+ :distance => 10,
+ :city => 'Apex' }, @band1)
+ expect(results.bands_filter.count).to be num
+ # long distance
+ results = Search.band_search({ :per_page => num,
+ :distance => 1000,
+ :city => 'Miami',
+ :state => 'FL' }, @band1)
+ expect(results.bands_filter.count).to be num
+ end
+
+ it "finds bands within a given distance of bands location" do
+ expect(@band1.lat).to_not be_nil
+ # uses the location of @band1
+ results = Search.band_search({ :distance => 10, :per_page => Band.count }, @band1)
+ expect(results.bands_filter.count).to be Band.count
+ end
+
+ it "finds no bands within a given distance of location" do
+ expect(@band1.lat).to_not be_nil
+ results = Search.band_search({ :distance => 10, :city => 'San Francisco' }, @band1)
+ expect(results.bands_filter.count).to be 0
+ end
+
+ end
+
+end
diff --git a/ruby/spec/jam_ruby/models/band_location_spec.rb b/ruby/spec/jam_ruby/models/band_location_spec.rb
new file mode 100644
index 000000000..fae562a53
--- /dev/null
+++ b/ruby/spec/jam_ruby/models/band_location_spec.rb
@@ -0,0 +1,39 @@
+require 'spec_helper'
+
+describe Band do
+
+ before do
+ @geocode1 = FactoryGirl.create(:geocoder)
+ @geocode2 = FactoryGirl.create(:geocoder)
+ @band = FactoryGirl.create(:band)
+ end
+
+ describe "with profile location data" do
+ it "should have lat/lng values" do
+ geo = MaxMindGeo.find_by_city(@band.city)
+ @band.lat.should == geo.lat
+ @band.lng.should == geo.lng
+ end
+ it "should have updated lat/lng values" do
+ @band.update_attributes({ :city => @geocode2.city,
+ :state => @geocode2.region,
+ :country => @geocode2.country,
+ })
+ geo = MaxMindGeo.find_by_city(@band.city)
+ @band.lat.should == geo.lat
+ @band.lng.should == geo.lng
+ end
+ end
+
+ describe "without location data" do
+ it "should have nil lat/lng values without address" do
+ @band.update_attributes({ :city => nil,
+ :state => nil,
+ :country => nil,
+ })
+ @band.lat.should == nil
+ @band.lng.should == nil
+ end
+ end
+
+end
diff --git a/ruby/spec/jam_ruby/models/band_search_spec.rb b/ruby/spec/jam_ruby/models/band_search_spec.rb
index 2af217b3f..40e26d50f 100644
--- a/ruby/spec/jam_ruby/models/band_search_spec.rb
+++ b/ruby/spec/jam_ruby/models/band_search_spec.rb
@@ -5,7 +5,9 @@ describe User do
let(:user) { FactoryGirl.create(:user) }
before(:each) do
-
+ @geocode1 = FactoryGirl.create(:geocoder)
+ @geocode2 = FactoryGirl.create(:geocoder)
+ @user = FactoryGirl.create(:user)
@band = Band.save(nil, "Example Band", "www.bands.com", "zomg we rock", "Apex", "NC", "US", ["hip hop"], user.id, nil, nil)
end
diff --git a/ruby/spec/jam_ruby/models/musician_search_spec.rb b/ruby/spec/jam_ruby/models/musician_search_spec.rb
index 6eda4ae28..955b2f04f 100644
--- a/ruby/spec/jam_ruby/models/musician_search_spec.rb
+++ b/ruby/spec/jam_ruby/models/musician_search_spec.rb
@@ -18,14 +18,14 @@ describe 'Musician search' do
# expects all the users
num = User.musicians.count
results = Search.musician_search({ :per_page => num })
- expect(results.musicians.count).to eq(num)
+ expect(results.musicians_filter.count).to eq(num)
end
it "finds musicians with proper ordering" do
# the ordering should be create_at since no followers exist
expect(UserFollower.count).to eq(0)
results = Search.musician_search({ :per_page => User.musicians.count })
- results.musicians.each_with_index do |uu, idx|
+ results.musicians_filter.each_with_index do |uu, idx|
expect(uu.id).to eq(@users.reverse[idx].id)
end
end
@@ -41,10 +41,10 @@ describe 'Musician search' do
# refresh the order to ensure it works right
@user2.followers.concat([@user3, @user4, @user2])
results = Search.musician_search({ :per_page => @users.size }, @user3)
- expect(results.musicians[0].id).to eq(@user2.id)
+ expect(results.musicians_filter[0].id).to eq(@user2.id)
# check the follower count for given entry
- expect(results.musicians[0].search_follow_count.to_i).not_to eq(0)
+ expect(results.musicians_filter[0].search_follow_count.to_i).not_to eq(0)
# check the follow relationship between current_user and result
expect(results.is_follower?(@user2)).to be true
end
@@ -53,7 +53,7 @@ describe 'Musician search' do
# make sure pagination works right
params = { :per_page => 2, :page => 1 }
results = Search.musician_search(params)
- expect(results.musicians.count).to be 2
+ expect(results.musicians_filter.count).to be 2
end
end
@@ -96,7 +96,7 @@ describe 'Musician search' do
Friendship.save(@user1.id, @user2.id)
# search on user2
results = Search.musician_search({}, @user2)
- friend = results.musicians.detect { |mm| mm.id == @user1.id }
+ friend = results.musicians_filter.detect { |mm| mm.id == @user1.id }
expect(friend).to_not be_nil
expect(results.friend_count(friend)).to be 1
@user1.reload
@@ -115,7 +115,7 @@ describe 'Musician search' do
expect(@user1.recordings.detect { |rr| rr == recording }).to_not be_nil
results = Search.musician_search({},@user1)
- uu = results.musicians.detect { |mm| mm.id == @user1.id }
+ uu = results.musicians_filter.detect { |mm| mm.id == @user1.id }
expect(uu).to_not be_nil
expect(results.record_count(uu)).to be 1
@@ -130,28 +130,28 @@ describe 'Musician search' do
make_recording(@user1)
# order results by num recordings
results = Search.musician_search({ :orderby => 'plays' }, @user2)
- expect(results.musicians[0].id).to eq(@user1.id)
+ expect(results.musicians_filter[0].id).to eq(@user1.id)
# add more data and make sure order still correct
make_recording(@user2); make_recording(@user2)
results = Search.musician_search({ :orderby => 'plays' }, @user2)
- expect(results.musicians[0].id).to eq(@user2.id)
+ expect(results.musicians_filter[0].id).to eq(@user2.id)
end
it "by now playing" do
# should get 1 result with 1 active session
make_session(@user3)
results = Search.musician_search({ :orderby => 'playing' }, @user2)
- expect(results.musicians.count).to be 1
- expect(results.musicians.first.id).to eq(@user3.id)
+ expect(results.musicians_filter.count).to be 1
+ expect(results.musicians_filter.first.id).to eq(@user3.id)
# should get 2 results with 2 active sessions
# sort order should be created_at DESC
make_session(@user4)
results = Search.musician_search({ :orderby => 'playing' }, @user2)
- expect(results.musicians.count).to be 2
- expect(results.musicians[0].id).to eq(@user4.id)
- expect(results.musicians[1].id).to eq(@user3.id)
+ expect(results.musicians_filter.count).to be 2
+ expect(results.musicians_filter[0].id).to eq(@user4.id)
+ expect(results.musicians_filter[1].id).to eq(@user3.id)
end
end
@@ -166,10 +166,10 @@ describe 'Musician search' do
ii = @user1.instruments.detect { |inst| inst.id == 'tuba' }
expect(ii).to_not be_nil
results = Search.musician_search({ :instrument => ii.id })
- results.musicians.each do |rr|
+ results.musicians_filter.each do |rr|
expect(rr.instruments.detect { |inst| inst.id=='tuba' }.id).to eq(ii.id)
end
- expect(results.musicians.count).to be 1
+ expect(results.musicians_filter.count).to be 1
end
it "finds musicians within a given distance of given location" do
@@ -179,26 +179,26 @@ describe 'Musician search' do
results = Search.musician_search({ :per_page => num,
:distance => 10,
:city => 'Apex' }, @user1)
- expect(results.musicians.count).to be num
+ expect(results.musicians_filter.count).to be num
# long distance
results = Search.musician_search({ :per_page => num,
:distance => 1000,
:city => 'Miami',
:state => 'FL' }, @user1)
- expect(results.musicians.count).to be num
+ expect(results.musicians_filter.count).to be num
end
it "finds musicians within a given distance of users location" do
expect(@user1.lat).to_not be_nil
# uses the location of @user1
results = Search.musician_search({ :distance => 10, :per_page => User.musicians.count }, @user1)
- expect(results.musicians.count).to be User.musicians.count
+ expect(results.musicians_filter.count).to be User.musicians.count
end
it "finds no musicians within a given distance of location" do
expect(@user1.lat).to_not be_nil
results = Search.musician_search({ :distance => 10, :city => 'San Francisco' }, @user1)
- expect(results.musicians.count).to be 0
+ expect(results.musicians_filter.count).to be 0
end
end
diff --git a/web/app/assets/javascripts/accounts_profile_avatar.js b/web/app/assets/javascripts/accounts_profile_avatar.js
index 48bbfc20d..81336953e 100644
--- a/web/app/assets/javascripts/accounts_profile_avatar.js
+++ b/web/app/assets/javascripts/accounts_profile_avatar.js
@@ -7,7 +7,6 @@
var self = this;
var logger = context.JK.logger;
var rest = context.JK.Rest();
- var userId;
var user = {};
var tmpUploadPath = null;
var userDetail = null;
@@ -18,7 +17,6 @@
var userDropdown;
function beforeShow(data) {
- userId = data.id;
}
@@ -150,7 +148,7 @@
var avatar = $('img.preview_profile_avatar', avatarSpace);
var spinner = $('
')
- if(avatar.length == 0) {
+ if(avatar.length === 0) {
avatarSpace.prepend(spinner);
}
else {
diff --git a/web/app/assets/javascripts/bandProfile.js b/web/app/assets/javascripts/bandProfile.js
index 60c63f967..7551163e3 100644
--- a/web/app/assets/javascripts/bandProfile.js
+++ b/web/app/assets/javascripts/bandProfile.js
@@ -5,6 +5,7 @@
context.JK = context.JK || {};
context.JK.BandProfileScreen = function(app) {
var logger = context.JK.logger;
+ var rest = context.JK.Rest();
var bandId;
var isMember = false;
var band = {};
@@ -59,7 +60,7 @@
configureBandFollowingButton(true);
}
else {
- configureMemberFollowingButton(true);
+ configureMemberFollowingButton(true, id);
}
},
error: app.ajaxError
@@ -350,7 +351,6 @@
}
function bindPendingMembers() {
- $("#band-profile-members").append("Pending Band Invitations ");
var url = "/api/bands/" + bandId + "/musicians?pending=true";
$.ajax({
type: "GET",
@@ -359,7 +359,10 @@
async: false,
processData:false,
success: function(response) {
- bindMusicians(response);
+ if (response && response.length > 0) {
+ $("#band-profile-members").append("Pending Band Invitations ");
+ bindMusicians(response);
+ }
},
error: app.ajaxError
});
@@ -400,12 +403,34 @@
var following = isFollowingMember(musician.id);
configureMemberFollowingButton(following, musician.id);
+ configureRemoveMemberButton(musician.id);
+
// TODO: wire up Friend button click handler
// var friend = isFriend(musician.id);
// configureMemberFriendButton(friend, musician.id);
});
}
+ function configureRemoveMemberButton(userId) {
+
+ var $divMember = $('div[user-id=' + userId + ']', '#band-profile-members');
+ var $btnRemoveMember = $divMember.find('#btn-remove-member');
+ if (isMember) {
+ $btnRemoveMember.show();
+ $btnRemoveMember.unbind("click");
+ $btnRemoveMember.click(function() {
+ rest.removeBandMember(bandId, userId)
+ .done(function() {
+ $divMember.remove();
+ })
+ .fail(app.ajaxError);
+ });
+ }
+ else {
+ $btnRemoveMember.hide();
+ }
+ }
+
// TODO: refactor
// checks if person viewing the profile is also a band member
function setIsMember() {
@@ -441,12 +466,10 @@
if (isMember) {
$("#btn-follow-band").hide();
- $("#btn-edit-band-members").show();
$("#btn-edit-band-profile").show();
}
else {
$("#btn-follow-band").show();
- $("#btn-edit-band-members").hide();
$("#btn-edit-band-profile").hide();
}
diff --git a/web/app/assets/javascripts/band_setup.js b/web/app/assets/javascripts/band_setup.js
index ae27f3e27..5752a35e4 100644
--- a/web/app/assets/javascripts/band_setup.js
+++ b/web/app/assets/javascripts/band_setup.js
@@ -229,6 +229,7 @@
userNames = [];
userIds = [];
userPhotoUrls = [];
+ //bandId = "1158c8b6-4c92-47dc-82bf-1e390c4f9b2c";
bandId = $("#hdn-band-id").val();
resetForm();
}
@@ -246,9 +247,22 @@
}
else {
loadGenres();
- loadCountries();
+
+ rest.getResolvedLocation()
+ .done(function(location) {
+ loadCountries(location.country, function() {
+ loadRegions(location.region, function() {
+ loadCities(location.city);
+ });
+ });
+ });
+
+
$("#band-setup-title").html("set up band");
$("#btn-band-setup-save").html("CREATE BAND");
+
+ $("#band-change-photo").unbind('click');
+ $("#band-change-photo").html('Set up band and then add photo.');
}
}
@@ -258,10 +272,14 @@
$("#band-website").val(band.website);
$("#band-biography").val(band.biography);
+ if (band.photo_url) {
+ $("#band-avatar").attr('src', band.photo_url);
+ }
+
loadGenres(band.genres);
loadCountries(band.country, function() {
- loadRegions(band.state, function () {
+ loadRegions(band.state, function() {
loadCities(band.city);
});
});
@@ -357,24 +375,26 @@
nilOption.text(nilOptionText);
$region.append(nilOption);
- rest.getRegions({'country': selectedCountry}).done(function(response) {
- $.each(response["regions"], function(index, region) {
- if(!region) return;
- var option = $(' ');
- option.text(region);
- option.attr("value", region);
+ if (selectedCountry) {
+ rest.getRegions({'country': selectedCountry}).done(function(response) {
+ $.each(response["regions"], function(index, region) {
+ if(!region) return;
+ var option = $(' ');
+ option.text(region);
+ option.attr("value", region);
- if (initialRegion === region) {
- option.attr("selected", "selected");
+ if (initialRegion === region) {
+ option.attr("selected", "selected");
+ }
+
+ $region.append(option);
+ });
+
+ if (onRegionsLoaded) {
+ onRegionsLoaded();
}
-
- $region.append(option);
});
-
- if (onRegionsLoaded) {
- onRegionsLoaded();
- }
- });
+ }
}
function loadCities(initialCity) {
@@ -387,20 +407,22 @@
nilOption.text(nilOptionText);
$city.append(nilOption);
- rest.getCities({'country': selectedCountry, 'region': selectedRegion}) .done(function(response) {
- $.each(response["cities"], function(index, city) {
- if(!city) return;
- var option = $(' ');
- option.text(city);
- option.attr("value", city);
+ if (selectedCountry && selectedRegion) {
+ rest.getCities({'country': selectedCountry, 'region': selectedRegion}) .done(function(response) {
+ $.each(response["cities"], function(index, city) {
+ if(!city) return;
+ var option = $(' ');
+ option.text(city);
+ option.attr("value", city);
- if (initialCity === city) {
- option.attr("selected", "selected");
- }
+ if (initialCity === city) {
+ option.attr("selected", "selected");
+ }
- $city.append(option);
+ $city.append(option);
+ });
});
- });
+ }
}
function friendSelectorCallback(newSelections) {
@@ -467,13 +489,21 @@
$('#band-country').on('change', function(evt) {
evt.stopPropagation();
- loadRegions('');
+ loadRegions();
+ loadCities();
return false;
});
$('#band-region').on('change', function(evt) {
evt.stopPropagation();
- loadCities('');
+ loadCities();
+ return false;
+ });
+
+ $('#band-change-photo').click(function(evt) {
+ evt.stopPropagation();
+ $("#hdn-band-id").val(bandId);
+ context.location = '#/band/setup/photo';
return false;
});
diff --git a/web/app/assets/javascripts/band_setup_photo.js b/web/app/assets/javascripts/band_setup_photo.js
new file mode 100644
index 000000000..f5775cee5
--- /dev/null
+++ b/web/app/assets/javascripts/band_setup_photo.js
@@ -0,0 +1,431 @@
+(function(context,$) {
+
+ "use strict";
+
+ context.JK = context.JK || {};
+ context.JK.BandSetupPhotoScreen = function(app) {
+ var self = this;
+ var logger = context.JK.logger;
+ var rest = context.JK.Rest();
+ var bandId;
+ var band = {};
+ var tmpUploadPath = null;
+ var bandDetail = null;
+ var bandPhoto;
+ var selection = null;
+ var targetCropSize = 88;
+ var updatingBandPhoto = false;
+
+ function beforeShow(data) {
+ bandId = $("#hdn-band-id").val();
+ logger.debug("bandId=" + bandId);
+ if (!bandId) {
+ context.location = '#/home';
+ }
+ }
+
+ function afterShow(data) {
+ resetForm();
+ renderBandPhotoScreen()
+ }
+
+ function resetForm() {
+ // remove all display errors
+ $('#band-setup-photo-content-scroller form .error-text').remove()
+ $('#band-setup-photo-content-scroller form .error').removeClass("error")
+ }
+
+ function populateBandPhoto(bandDetail) {
+ self.bandDetail = bandDetail;
+ rest.getBandPhotoFilepickerPolicy({ id:bandId })
+ .done(function(filepicker_policy) {
+ var template= context.JK.fillTemplate($('#template-band-setup-photo').html(), {
+ "fp_apikey" : gon.fp_apikey,
+ "data-fp-store-path" : createStorePath(bandDetail) + createOriginalFilename(bandDetail),
+ "fp_policy" : filepicker_policy.policy,
+ "fp_signature" : filepicker_policy.signature
+ });
+ $('#band-setup-photo-content-scroller').html(template);
+
+
+ var currentFpfile = determineCurrentFpfile();
+ var currentCropSelection = determineCurrentSelection(bandDetail);
+ renderBandPhoto(currentFpfile, currentCropSelection ? JSON.parse(currentCropSelection) : null);
+ })
+ .error(app.ajaxError);
+
+ }
+
+ // events for main screen
+ function events() {
+ // wire up main panel clicks
+ $('#band-setup-photo-content-scroller').on('click', '#band-setup-photo-upload', function(evt) { evt.stopPropagation(); handleFilePick(); return false; } );
+ $('#band-setup-photo-content-scroller').on('click', '#band-setup-photo-delete', function(evt) { evt.stopPropagation(); handleDeleteBandPhoto(); return false; } );
+ $('#band-setup-photo-content-scroller').on('click', '#band-setup-photo-cancel', function(evt) { evt.stopPropagation(); navToEditProfile(); return false; } );
+ $('#band-setup-photo-content-scroller').on('click', '#band-setup-photo-submit', function(evt) { evt.stopPropagation(); handleUpdateBandPhoto(); return false; } );
+ //$('#band-setup-photo-content-scroller').on('change', 'input[type=filepicker-dragdrop]', function(evt) { evt.stopPropagation(); afterImageUpload(evt.originalEvent.fpfile); return false; } );
+ }
+
+ function handleDeleteBandPhoto() {
+
+ if(self.updatingBandPhoto) {
+ // protect against concurrent update attempts
+ return;
+ }
+
+ self.updatingBandPhoto = true;
+ renderBandPhotoSpinner();
+
+ rest.deleteBandPhoto({ id: bandId })
+ .done(function() {
+ removeBandPhotoSpinner({ delete:true });
+ deleteBandPhotoSuccess(arguments);
+ selection = null;
+ })
+ .fail(function() {
+ app.ajaxError(arguments);
+ $.cookie('original_fpfile_band_photo', null);
+ self.updatingBandPhoto = false;
+ })
+ .always(function() {
+
+ })
+ }
+
+ function deleteBandPhotoSuccess(response) {
+
+ renderBandPhoto(null, null);
+
+ rest.getBand(bandId)
+ .done(function(bandDetail) {
+ self.bandDetail = bandDetail;
+ })
+ .error(app.ajaxError)
+ .always(function() {
+ self.updatingBandPhoto = false;
+ })
+ }
+
+ function handleFilePick() {
+ rest.getBandPhotoFilepickerPolicy({ id: bandId })
+ .done(function(filepickerPolicy) {
+ renderBandPhotoSpinner();
+ logger.debug("rendered spinner");
+ filepicker.setKey(gon.fp_apikey);
+ filepicker.pickAndStore({
+ mimetype: 'image/*',
+ maxSize: 10000*1024,
+ policy: filepickerPolicy.policy,
+ signature: filepickerPolicy.signature
+ },
+ { path: createStorePath(self.bandDetail), access: 'public' },
+ function(fpfiles) {
+ removeBandPhotoSpinner();
+ afterImageUpload(fpfiles[0]);
+ }, function(fperror) {
+ removeBandPhotoSpinner();
+
+ if(fperror.code != 101) { // 101 just means the user closed the dialog
+ alert("unable to upload file: " + JSON.stringify(fperror))
+ }
+ })
+ })
+ .fail(app.ajaxError);
+
+ }
+ function renderBandPhotoScreen() {
+
+ rest.getBand(bandId)
+ .done(populateBandPhoto)
+ .error(app.ajaxError)
+ }
+
+ function navToEditProfile() {
+ resetForm();
+ $("#hdn-band-id").val(bandId);
+ context.location = '#/band/setup';
+ }
+
+ function renderBandPhotoSpinner() {
+ var bandPhotoSpace = $('#band-setup-photo-content-scroller .band-setup-photo .avatar-space');
+ // if there is already an image tag, we only obscure it.
+
+ var bandPhoto = $('img.preview_profile_avatar', bandPhotoSpace);
+
+ var spinner = $('
')
+ if(bandPhoto.length === 0) {
+ bandPhotoSpace.prepend(spinner);
+ }
+ else {
+ // in this case, just style the spinner to obscure using opacity, and center it
+ var jcropHolder = $('.jcrop-holder', bandPhotoSpace);
+ spinner.width(jcropHolder.width());
+ spinner.height(jcropHolder.height());
+ spinner.addClass('op50');
+ var jcrop = bandPhoto.data('Jcrop');
+ if(jcrop) {
+ jcrop.disable();
+ }
+ bandPhotoSpace.append(spinner);
+ }
+ }
+
+ function removeBandPhotoSpinner(options) {
+ var bandPhotoSpace = $('#band-setup-photo-content-scroller .band-setup-photo .avatar-space');
+
+ if(options && options.delete) {
+ bandPhotoSpace.children().remove();
+ }
+
+ var spinner = $('.spinner-large', bandPhotoSpace);
+ spinner.remove();
+ var bandPhoto = $('img.preview_profile_avatar', bandPhotoSpace);
+ var jcrop = bandPhoto.data('Jcrop')
+ if(jcrop) {
+ jcrop.enable();
+ }
+ }
+
+ function renderBandPhoto(fpfile, storedSelection) {
+
+ // clear out
+ var bandPhotoSpace = $('#band-setup-photo-content-scroller .band-setup-photo .avatar-space');
+
+ if(!fpfile) {
+ renderNoBandPhoto(bandPhotoSpace);
+ }
+ else {
+ rest.getBandPhotoFilepickerPolicy({handle: fpfile.url, id: bandId})
+ .done(function(filepickerPolicy) {
+ bandPhotoSpace.children().remove();
+ renderBandPhotoSpinner();
+
+ var photo_url = fpfile.url + '?signature=' + filepickerPolicy.signature + '&policy=' + filepickerPolicy.policy;
+ bandPhoto = new Image();
+ $(bandPhoto)
+ .load(function(e) {
+ removeBandPhotoSpinner();
+
+ bandPhoto = $(this);
+ bandPhotoSpace.append(bandPhoto);
+ var width = bandPhoto.naturalWidth();
+ var height = bandPhoto.naturalHeight();
+
+ if(storedSelection) {
+ var left = storedSelection.x;
+ var right = storedSelection.x2;
+ var top = storedSelection.y;
+ var bottom = storedSelection.y2;
+ }
+ else {
+ if(width < height) {
+ var left = width * .25;
+ var right = width * .75;
+ var top = (height / 2) - (width / 4);
+ var bottom = (height / 2) + (width / 4);
+ }
+ else {
+ var top = height * .25;
+ var bottom = height * .75;
+ var left = (width / 2) - (height / 4);
+ var right = (width / 2) + (height / 4);
+ }
+ }
+
+ // jcrop only works well with px values (not percentages)
+ // so we get container, and work out a decent % ourselves
+ var container = $('#band-setup-photo-content-scroller');
+
+ bandPhoto.Jcrop({
+ aspectRatio: 1,
+ boxWidth: container.width() * .75,
+ boxHeight: container.height() * .75,
+ // minSelect: [targetCropSize, targetCropSize], unnecessary with scaling involved
+ setSelect: [ left, top, right, bottom ],
+ trueSize: [width, height],
+ onRelease: onSelectRelease,
+ onSelect: onSelect,
+ onChange: onChange
+ });
+ })
+ .error(function() {
+ // default to no avatar look of UI
+ renderNoBandPhoto(bandPhotoSpace);
+ })
+ .attr('src', photo_url)
+ .attr('alt', 'profile avatar')
+ .addClass('preview_profile_avatar');
+ })
+ .fail(app.ajaxError);
+ }
+ }
+
+ function afterImageUpload(fpfile) {
+ $.cookie('original_fpfile_band_photo', JSON.stringify(fpfile));
+ renderBandPhoto(fpfile, null);
+ }
+
+ function renderNoBandPhoto(bandPhotoSpace) {
+ // no photo found for band
+
+ removeBandPhotoSpinner();
+
+ var noAvatarSpace = $('
');
+ noAvatarSpace.addClass('no-avatar-space');
+ noAvatarSpace.text('Please upload a photo');
+ bandPhotoSpace.append(noAvatarSpace);
+ }
+
+ function handleUpdateBandPhoto(event) {
+
+ if(self.updatingBandPhoto) {
+ // protect against concurrent update attempts
+ return;
+ }
+
+ if(selection) {
+ var currentSelection = selection;
+ self.updatingBandPhoto = true;
+ renderBandPhotoSpinner();
+
+ console.log("Converting...");
+
+ // we convert two times; first we crop to the selected region,
+ // then we scale to 88x88 (targetCropSize X targetCropSize), which is the largest size we use throughout the site.
+ var fpfile = determineCurrentFpfile();
+ rest.getBandPhotoFilepickerPolicy({ handle: fpfile.url, convert: true, id: bandId })
+ .done(function(filepickerPolicy) {
+ filepicker.setKey(gon.fp_apikey);
+ filepicker.convert(fpfile, {
+ crop: [
+ Math.round(currentSelection.x),
+ Math.round(currentSelection.y),
+ Math.round(currentSelection.w),
+ Math.round(currentSelection.w)],
+ fit: 'crop',
+ format: 'jpg',
+ quality: 90,
+ policy: filepickerPolicy.policy,
+ signature: filepickerPolicy.signature
+ }, { path: createStorePath(self.bandDetail) + 'cropped-' + new Date().getTime() + '.jpg', access: 'public' },
+ function(cropped) {
+ logger.debug("converting cropped");
+ rest.getBandPhotoFilepickerPolicy({handle: cropped.url, convert: true, id: bandId})
+ .done(function(filepickerPolicy) {
+ filepicker.convert(cropped, {
+ height: targetCropSize,
+ width: targetCropSize,
+ fit: 'scale',
+ format: 'jpg',
+ quality: 75,
+ policy: filepickerPolicy.policy,
+ signature: filepickerPolicy.signature
+ }, { path: createStorePath(self.bandDetail), access: 'public' },
+ function(scaled) {
+ logger.debug("converted and scaled final image %o", scaled);
+ rest.updateBandPhoto({
+ original_fpfile: determineCurrentFpfile(),
+ cropped_fpfile: scaled,
+ crop_selection: currentSelection,
+ id: bandId
+ })
+ .done(updateBandPhotoSuccess)
+ .fail(app.ajaxError)
+ .always(function() { removeBandPhotoSpinner(); self.updatingBandPhoto = false;})
+ },
+ function(fperror) {
+ alert("unable to scale selection. error code: " + fperror.code);
+ removeBandPhotoSpinner();
+ self.updatingBandPhoto = false;
+ })
+ })
+ .fail(app.ajaxError);
+ },
+ function(fperror) {
+ alert("unable to crop selection. error code: " + fperror.code);
+ removeBandPhotoSpinner();
+ self.updatingBandPhoto = false;
+ }
+ );
+ })
+ .fail(app.ajaxError);
+ }
+ else {
+ app.notify(
+ { title: "Upload a Band Photo First",
+ text: "To update your band photo, first you must upload an image using the UPLOAD button"
+ },
+ { no_cancel: true });
+ }
+ }
+
+ function updateBandPhotoSuccess(response) {
+ $.cookie('original_fpfile_band_photo', null);
+
+ self.bandDetail = response;
+
+ app.notify(
+ { title: "Band Photo Changed",
+ text: "You have updated your band photo successfully."
+ },
+ { no_cancel: true });
+ }
+
+ function onSelectRelease(event) {
+ }
+
+ function onSelect(event) {
+ selection = event;
+ }
+
+ function onChange(event) {
+ }
+
+ function createStorePath(bandDetail) {
+ return gon.fp_upload_dir + '/' + bandDetail.id + '/'
+ }
+
+ function createOriginalFilename(bandDetail) {
+ // get the s3
+ var fpfile = bandDetail.original_fpfile_photo ? JSON.parse(bandDetail.original_fpfile_photo) : null;
+ return 'original_band_photo.jpg'
+ }
+
+ // retrieves a file that has not yet been used as an band photo (uploaded, but not cropped)
+ function getWorkingFpfile() {
+ return JSON.parse($.cookie('original_fpfile_band_photo'))
+ }
+
+ function determineCurrentFpfile() {
+ // precedence is as follows:
+ // * tempOriginal: if set, then the user is working on a new upload
+ // * storedOriginal: if set, then the user has previously uploaded and cropped a band photo
+ // * null: neither are set above
+
+ var tempOriginal = getWorkingFpfile();
+ var storedOriginal = self.bandDetail.original_fpfile_photo ? JSON.parse(self.bandDetail.original_fpfile_photo) : null;
+
+ return tempOriginal ? tempOriginal : storedOriginal;
+ }
+
+ function determineCurrentSelection(bandDetail) {
+ // if the cookie is set, don't use the storage selection, just default to null
+ return $.cookie('original_fpfile_band_photo') == null ? bandDetail.crop_selection_photo : null;
+ }
+
+ function initialize() {
+ var screenBindings = {
+ 'beforeShow': beforeShow,
+ 'afterShow': afterShow
+ };
+ app.bindScreen('band/setup/photo', screenBindings);
+ events();
+ }
+
+ this.initialize = initialize;
+ this.beforeShow = beforeShow;
+ this.afterShow = afterShow;
+ return this;
+ };
+
+})(window,jQuery);
\ No newline at end of file
diff --git a/web/app/assets/javascripts/configureTrack.js b/web/app/assets/javascripts/configureTrack.js
index 94feb2fc8..966804fcc 100644
--- a/web/app/assets/javascripts/configureTrack.js
+++ b/web/app/assets/javascripts/configureTrack.js
@@ -613,7 +613,7 @@
// track 2 was removed
if (myTrackCount === 2) {
logger.debug("Deleting track " + myTracks[1].trackId);
- client.TrackSetCount(1);
+ context.jamClient.TrackSetCount(1);
//sessionModel.deleteTrack(sessionId, myTracks[1].trackId);
}
}
@@ -830,4 +830,4 @@
return this;
};
- })(window,jQuery);
\ No newline at end of file
+ })(window,jQuery);
diff --git a/web/app/assets/javascripts/findBand.js b/web/app/assets/javascripts/findBand.js
new file mode 100644
index 000000000..2475521d6
--- /dev/null
+++ b/web/app/assets/javascripts/findBand.js
@@ -0,0 +1,229 @@
+(function(context,$) {
+ "use strict";
+
+ context.JK = context.JK || {};
+ context.JK.FindBandScreen = function(app) {
+
+ var logger = context.JK.logger;
+ var bands = {};
+ var bandList;
+ var instrument_logo_map = context.JK.getInstrumentIconMap24();
+ var did_show_band_page = false;
+ var page_num=1, page_count=0;
+
+ function loadBands(queryString) {
+ // squelch nulls and undefines
+ queryString = !!queryString ? queryString : "";
+
+ $.ajax({
+ type: "GET",
+ url: "/api/search.json?" + queryString,
+ async: true,
+ success: afterLoadBands,
+ error: app.ajaxError
+ });
+ }
+
+ function search() {
+ did_show_band_page = true;
+ var queryString = 'srch_b=1&page='+page_num+'&';
+
+ // order by
+ var orderby = $('#band_order_by').val();
+ if (typeof orderby != 'undefined' && orderby.length > 0) {
+ queryString += "orderby=" + orderby + '&';
+ }
+ // genre filter
+ var genre = $('#band_genre').val();
+ if (typeof genre != 'undefined' && !(genre === '')) {
+ queryString += "genre=" + genre + '&';
+ }
+ // distance filter
+ var query_param = $('#band_query_distance').val();
+ if (query_param !== null && query_param.length > 0) {
+ var matches = query_param.match(/(\d+)/);
+ if (0 < matches.length) {
+ var distance = matches[0];
+ queryString += "distance=" + distance + '&';
+ }
+ }
+ loadBands(queryString);
+ }
+
+ function refreshDisplay() {
+ clearResults();
+ search();
+ }
+
+ function afterLoadBands(mList) {
+ // display the 'no bands' banner if appropriate
+ var $noBandsFound = $('#bands-none-found');
+ bandList = mList;
+
+ if(bandList.length == 0) {
+ $noBandsFound.show();
+ bands = [];
+ } else {
+ $noBandsFound.hide();
+ bands = bandList['bands'];
+ if (!(typeof bands === 'undefined')) {
+ $('#band-filter-city').text(bandList['city']);
+ if (0 == page_count) {
+ page_count = bandList['page_count'];
+ }
+ renderBands();
+ }
+ }
+ }
+
+ /**
+ * Render a list of bands
+ */
+ function renderBands() {
+ var ii, len;
+ var mTemplate = $('#template-find-band-row').html();
+ var pTemplate = $('#template-band-player-info').html();
+ var aTemplate = $('#template-band-action-btns').html();
+ var bVals, bb, renderings='';
+ var instr_logos, instr;
+ var players, playerVals, aPlayer;
+
+ for (ii=0, len=bands.length; ii < len; ii++) {
+ bb = bands[ii];
+ instr_logos = '';
+ players = '';
+ playerVals = {};
+ for (var jj=0, ilen=bb['players'].length; jj ';
+ }
+
+ playerVals = {
+ player_name: aPlayer.name,
+ profile_url: '/#/profile/' + aPlayer.user_id,
+ avatar_url: context.JK.resolveAvatarUrl(aPlayer.photo_url),
+ player_instruments: player_instrs
+ };
+ players += context.JK.fillTemplate(pTemplate, playerVals);
+ }
+ var actionVals = {
+ profile_url: "/#/profile/" + bb.id,
+ button_follow: bb['is_following'] ? '' : 'button-orange',
+ button_message: 'button-orange'
+ };
+ var band_actions = context.JK.fillTemplate(aTemplate, actionVals);
+ var bgenres = '';
+ for (jj=0, ilen=bb['genres'].length; jj ';
+ }
+ bgenres += ' ';
+
+ bVals = {
+ avatar_url: context.JK.resolveAvatarUrl(bb.photo_url),
+ profile_url: "/#/profile/" + bb.id,
+ band_name: bb.name,
+ band_location: bb.city + ', ' + bb.state,
+ genres: bgenres,
+ instruments: instr_logos,
+ biography: bb['biography'],
+ follow_count: bb['follow_count'],
+ recording_count: bb['recording_count'],
+ session_count: bb['session_count'],
+ band_id: bb['id'],
+ band_player_template: players,
+ band_action_template: band_actions
+ };
+ var band_row = context.JK.fillTemplate(mTemplate, bVals);
+ renderings += band_row;
+ }
+ $('#band-filter-results').append(renderings);
+
+ $('.search-m-follow').on('click', followBand);
+ }
+
+ function beforeShow(data) {
+ }
+
+ function afterShow(data) {
+ if (!did_show_band_page) {
+ refreshDisplay();
+ }
+ }
+
+ function clearResults() {
+ bands = {};
+ $('#band-filter-results').empty();
+ page_num = 1;
+ page_count = 0;
+ }
+
+ function followBand(evt) {
+ // if the band is already followed, remove the button-orange class, and prevent
+ // the link from working
+ if (0 == $(this).closest('.button-orange').size()) return false;
+ $(this).click(function(ee) {ee.preventDefault();});
+
+ evt.stopPropagation();
+ var newFollowing = {};
+ newFollowing.band_id = $(this).parent().data('band-id');
+ var url = "/api/users/" + context.JK.currentUserId + "/followings";
+ $.ajax({
+ type: "POST",
+ dataType: "json",
+ contentType: 'application/json',
+ url: url,
+ data: JSON.stringify(newFollowing),
+ processData: false,
+ success: function(response) {
+ // remove the orange look to indicate it's not selectable
+ $('div[data-band-id='+newFollowing.band_id+'] .search-m-follow').removeClass('button-orange');
+ },
+ error: app.ajaxError
+ });
+ }
+
+ function events() {
+ $('#band_query_distance').change(refreshDisplay);
+ $('#band_genre').change(refreshDisplay);
+ $('#band_order_by').change(refreshDisplay);
+
+ $('#band-filter-results').bind('scroll', function() {
+ if ($(this).scrollTop() + $(this).innerHeight() >= $(this)[0].scrollHeight) {
+ if (page_num < page_count) {
+ page_num += 1;
+ search();
+ }
+ }
+ });
+ }
+
+ /**
+ * Initialize,
+ */
+ function initialize() {
+ var screenBindings = {
+ 'beforeShow': beforeShow,
+ 'afterShow': afterShow
+ };
+ app.bindScreen('bands', screenBindings);
+
+ events();
+ }
+
+ this.initialize = initialize;
+ this.renderBands = renderBands;
+ this.afterShow = afterShow;
+
+ this.clearResults = clearResults;
+
+ return this;
+ };
+
+})(window,jQuery);
\ No newline at end of file
diff --git a/web/app/assets/javascripts/findMusician.js b/web/app/assets/javascripts/findMusician.js
index 7da599797..7363ed50f 100644
--- a/web/app/assets/javascripts/findMusician.js
+++ b/web/app/assets/javascripts/findMusician.js
@@ -29,12 +29,12 @@
var queryString = 'srch_m=1&page='+page_num+'&';
// order by
- var orderby = $('.musician-order-by').val();
+ var orderby = $('#musician_order_by').val();
if (typeof orderby != 'undefined' && orderby.length > 0) {
queryString += "orderby=" + orderby + '&';
}
// instrument filter
- var instrument = $('.instrument-list').val();
+ var instrument = $('#musician_instrument').val();
if (typeof instrument != 'undefined' && !(instrument === '')) {
queryString += "instrument=" + instrument + '&';
}
@@ -111,7 +111,7 @@
}
var actionVals = {
profile_url: "/#/profile/" + mm.id,
- button_friend: mm['is_friend'] ? '' : 'button-orance',
+ button_friend: mm['is_friend'] ? '' : 'button-orange',
button_follow: mm['is_following'] ? '' : 'button-orange',
button_message: 'button-orange'
};
@@ -197,13 +197,9 @@
}
function events() {
- $("#musician_query_distance").keypress(function(evt) {
- if (evt.which === 13) {
- evt.preventDefault();
- refreshDisplay();
- }
- });
- $('#btn-refresh-musicians').on("click", refreshDisplay);
+ $('#musician_query_distance').change(refreshDisplay);
+ $('#musician_instrument').change(refreshDisplay);
+ $('#musician_order_by').change(refreshDisplay);
$('#musician-filter-results').bind('scroll', function() {
if ($(this).scrollTop() + $(this).innerHeight() >= $(this)[0].scrollHeight) {
@@ -237,4 +233,4 @@
return this;
};
-})(window,jQuery);
\ No newline at end of file
+})(window,jQuery);
diff --git a/web/app/assets/javascripts/jam_rest.js b/web/app/assets/javascripts/jam_rest.js
index 648ced0ff..f0ad75ebc 100644
--- a/web/app/assets/javascripts/jam_rest.js
+++ b/web/app/assets/javascripts/jam_rest.js
@@ -115,6 +115,17 @@
});
}
+ function removeBandMember(bandId, userId) {
+ var url = "/api/bands/" + bandId + "/musicians/" + userId;
+ return $.ajax({
+ type: "DELETE",
+ dataType: "json",
+ url: url,
+ async: false,
+ processData:false
+ });
+ }
+
function getSession(id) {
var url = "/api/sessions/" + id;
return $.ajax({
@@ -173,6 +184,12 @@
});
}
+ function getResolvedLocation() {
+ return $.ajax('/api/resolved_location', {
+ dataType: 'json'
+ });
+ }
+
function getInstruments(options) {
return $.ajax('/api/instruments', {
data : { },
@@ -194,6 +211,12 @@
var cropped_fpfile = options['cropped_fpfile'];
var crop_selection = options['crop_selection'];
+ logger.debug(JSON.stringify({
+ original_fpfile : original_fpfile,
+ cropped_fpfile : cropped_fpfile,
+ crop_selection : crop_selection
+ }));
+
var url = "/api/users/" + id + "/avatar";
return $.ajax({
type: "POST",
@@ -235,6 +258,60 @@
});
}
+ function updateBandPhoto(options) {
+ var id = getId(options);
+
+ var original_fpfile = options['original_fpfile'];
+ var cropped_fpfile = options['cropped_fpfile'];
+ var crop_selection = options['crop_selection'];
+
+ logger.debug(JSON.stringify({
+ original_fpfile : original_fpfile,
+ cropped_fpfile : cropped_fpfile,
+ crop_selection : crop_selection
+ }));
+
+ var url = "/api/bands/" + id + "/photo";
+ return $.ajax({
+ type: "POST",
+ dataType: "json",
+ url: url,
+ contentType: 'application/json',
+ processData:false,
+ data: JSON.stringify({
+ original_fpfile : original_fpfile,
+ cropped_fpfile : cropped_fpfile,
+ crop_selection : crop_selection
+ })
+ });
+ }
+
+ function deleteBandPhoto(options) {
+ var id = getId(options);
+
+ var url = "/api/bands/" + id + "/photo";
+ return $.ajax({
+ type: "DELETE",
+ dataType: "json",
+ url: url,
+ contentType: 'application/json',
+ processData:false
+ });
+ }
+
+ function getBandPhotoFilepickerPolicy(options) {
+ var id = getId(options);
+ var handle = options && options["handle"];
+ var convert = options && options["convert"]
+
+ var url = "/api/bands/" + id + "/filepicker_policy";
+
+ return $.ajax(url, {
+ data : { handle : handle, convert: convert },
+ dataType : 'json'
+ });
+ }
+
function getFriends(options) {
var friends = [];
var id = getId(options);
@@ -455,6 +532,7 @@
this.getRegions = getRegions;
this.getCountries = getCountries;
this.getIsps = getIsps;
+ this.getResolvedLocation = getResolvedLocation;
this.getInstruments = getInstruments;
this.getGenres = getGenres;
this.updateAvatar = updateAvatar;
@@ -481,9 +559,13 @@
this.putTrackSyncChange = putTrackSyncChange;
this.createBand = createBand;
this.updateBand = updateBand;
+ this.updateBandPhoto = updateBandPhoto;
+ this.deleteBandPhoto = deleteBandPhoto;
+ this.getBandPhotoFilepickerPolicy = getBandPhotoFilepickerPolicy;
this.getBand = getBand;
this.createBandInvitation = createBandInvitation;
this.updateBandInvitation = updateBandInvitation;
+ this.removeBandMember = removeBandMember;
return this;
};
diff --git a/web/app/assets/javascripts/profile.js b/web/app/assets/javascripts/profile.js
index 273d88fa9..fb9bab119 100644
--- a/web/app/assets/javascripts/profile.js
+++ b/web/app/assets/javascripts/profile.js
@@ -6,7 +6,7 @@
context.JK.ProfileScreen = function(app) {
var logger = context.JK.logger;
var userId;
- var user = {};
+ var user = null;
var instrument_logo_map = context.JK.getInstrumentIconMap24();
@@ -24,6 +24,7 @@
function beforeShow(data) {
userId = data.id;
+ user = null;
}
function afterShow(data) {
@@ -45,9 +46,84 @@
$('.profile-nav a.#profile-about-link').addClass('active');
}
+ function getUser() {
+ if (user === null) {
+ var url = "/api/users/" + userId;
+ $.ajax({
+ type: "GET",
+ dataType: "json",
+ url: url,
+ async: false,
+ processData:false,
+ success: function(response) {
+ user = response;
+ },
+ error: function(jqXHR, textStatus, errorMessage) {
+ user = null;
+ app.ajaxError(jqXHR, textStatus, errorMessage);
+ }
+ });
+ }
+ return user;
+ }
+
+ function isMusician() {
+ if (getUser()) {
+ return user.musician === true;
+ }
+ return false;
+ }
+
+ function isCurrentUser() {
+ return userId === context.JK.currentUserId;
+ }
+
+ function configureUserType() {
+ if (isMusician()) {
+ $('#profile-history-link').show();
+ $('#profile-bands-link').show();
+ $('#profile-instruments').show();
+ $('#profile-session-stats').show();
+ $('#profile-recording-stats').show();
+
+ // $('#profile-following-stats').hide();
+ // $('#profile-favorites-stats').hide();
+
+ $('#btn-add-friend').show();
+ $('.profile-social-left').show();
+
+ $('#profile-type-label').text('musician');
+ $('#profile-location-label').text('Location');
+
+ } else {
+ $('#profile-history-link').hide();
+ $('#profile-bands-link').hide();
+ $('#profile-instruments').hide();
+ $('#profile-session-stats').hide();
+ $('#profile-recording-stats').hide();
+
+ // $('#profile-following-stats').show();
+ // $('#profile-favorites-stats').show();
+
+ $('#btn-add-friend').hide();
+ $('.profile-social-left').hide();
+
+ $('#profile-type-label').text('fan');
+ $('#profile-location-label').text('Presence');
+ }
+
+ if (isCurrentUser()) {
+ $('#btn-profile-edit').show();
+ } else {
+ $('#btn-profile-edit').hide();
+ }
+ }
+
/****************** MAIN PORTION OF SCREEN *****************/
// events for main screen
function events() {
+ configureUserType();
+
// wire up panel clicks
$('#profile-about-link').click(renderAbout);
$('#profile-history-link').click(renderHistory);
@@ -56,14 +132,12 @@
$('#profile-favorites-link').click(renderFavorites);
// wire up buttons if you're not viewing your own profile
- if (userId != context.JK.currentUserId) {
+ if (!isCurrentUser()) {
// wire up Add Friend click
- var friend = isFriend();
- configureFriendButton(friend);
+ configureFriendButton(isFriend());
// wire up Follow click
- var following = isFollowing();
- configureFollowingButton(following);
+ configureFollowingButton(isFollowing());
}
else {
$('#btn-add-friend').hide();
@@ -94,27 +168,7 @@
}
function isFriend() {
- var alreadyFriend = false;
-
- var url = "/api/users/" + context.JK.currentUserId + "/friends/" + userId;
- $.ajax({
- type: "GET",
- dataType: "json",
- url: url,
- async: false,
- processData: false,
- success: function(response) {
- if (response.id !== undefined) {
- alreadyFriend = true;
- }
- else {
- alreadyFriend = false;
- }
- },
- error: app.ajaxError
- });
-
- return alreadyFriend;
+ return getUser() ? user.is_friend : false;
}
function friendRequestCallback() {
@@ -186,27 +240,7 @@
}
function isFollowing() {
- var alreadyFollowing = false;
-
- var url = "/api/users/" + context.JK.currentUserId + "/followings/" + userId;
- $.ajax({
- type: "GET",
- dataType: "json",
- url: url,
- async: false,
- processData: false,
- success: function(response) {
- if (response.id !== undefined) {
- alreadyFollowing = true;
- }
- else {
- alreadyFollowing = false;
- }
- },
- error: app.ajaxError
- });
-
- return alreadyFollowing;
+ return getUser() ? user.is_following : false;
}
function configureFollowingButton(following) {
@@ -224,6 +258,10 @@
}
}
+ function configureEditProfileButton() {
+ $('#btn-follow-user').click(addFollowing);
+ }
+
// refreshes the currently active tab
function renderActive() {
if ($('#profile-about-link').hasClass('active')) {
@@ -261,21 +299,8 @@
function bindAbout() {
$('#profile-instruments').empty();
- var url = "/api/users/" + userId;
- $.ajax({
- type: "GET",
- dataType: "json",
- url: url,
- async: false,
- processData:false,
- success: function(response) {
- user = response;
- },
- error: app.ajaxError
- });
-
- if (user) {
+ if (getUser()) {
// name
$('#profile-username').html(user.name);
@@ -313,11 +338,18 @@
text = user.follower_count > 1 || user.follower_count === 0 ? " Followers" : " Follower";
$('#profile-follower-stats').html(user.follower_count + text);
- text = user.session_count > 1 || user.session_count === 0 ? " Sessions" : " Session";
- $('#profile-session-stats').html(user.session_count + text);
+ if (isMusician()) {
+ text = user.session_count > 1 || user.session_count === 0 ? " Sessions" : " Session";
+ $('#profile-session-stats').html(user.session_count + text);
- text = user.recording_count > 1 || user.recording_count === 0 ? " Recordings" : " Recording";
- $('#profile-recording-stats').html(user.recording_count + text);
+ text = user.recording_count > 1 || user.recording_count === 0 ? " Recordings" : " Recording";
+ $('#profile-recording-stats').html(user.recording_count + text);
+ } else {
+ text = " Following";
+ $('#profile-following-stats').html(user.following_count + text);
+ text = user.favorite_count > 1 || user.favorite_count === 0 ? " Favorites" : " Favorite";
+ $('#profile-favorite-stats').html(user.favorite_count + text);
+ }
$('#profile-biography').html(user.biography);
}
@@ -341,33 +373,41 @@
$('.profile-nav a.active').removeClass('active');
$('.profile-nav a.#profile-social-link').addClass('active');
+ /*if (isMusician()) {
+ $('.profile-social-left').show();
+ } else {
+ $('.profile-social-left').hide();
+ }*/
+
bindSocial();
}
function bindSocial() {
- // FRIENDS
- var url = "/api/users/" + userId + "/friends";
- $.ajax({
- type: "GET",
- dataType: "json",
- url: url,
- async: false,
- processData:false,
- success: function(response) {
- $.each(response, function(index, val) {
- var template = $('#template-profile-social').html();
- var friendHtml = context.JK.fillTemplate(template, {
- avatar_url: context.JK.resolveAvatarUrl(val.photo_url),
- userName: val.name,
- location: val.location,
- type: "Friends"
- });
+ if (isMusician()) {
+ // FRIENDS
+ var url = "/api/users/" + userId + "/friends";
+ $.ajax({
+ type: "GET",
+ dataType: "json",
+ url: url,
+ async: false,
+ processData:false,
+ success: function(response) {
+ $.each(response, function(index, val) {
+ var template = $('#template-profile-social').html();
+ var friendHtml = context.JK.fillTemplate(template, {
+ avatar_url: context.JK.resolveAvatarUrl(val.photo_url),
+ userName: val.name,
+ location: val.location,
+ type: "Friends"
+ });
- $('#profile-social-friends').append(friendHtml);
- });
- },
- error: app.ajaxError
- });
+ $('#profile-social-friends').append(friendHtml);
+ });
+ },
+ error: app.ajaxError
+ });
+ }
// FOLLOWINGS (USERS)
url = "/api/users/" + userId + "/followings";
@@ -482,7 +522,7 @@
async: false,
processData:false,
success: function(response) {
- if ( (!response || response.length === 0) && context.JK.currentUserId === userId) {
+ if ( (!response || response.length === 0) && isCurrentUser()) {
var noBandHtml = $('#template-no-bands').html();
$("#profile-bands").append(noBandHtml);
}
@@ -548,7 +588,7 @@
}
function addMoreBandsLink() {
- if (context.JK.currentUserId === userId) {
+ if (isCurrentUser()) {
var moreBandsHtml = $('#template-more-bands').html();
$("#profile-bands").append(moreBandsHtml);
}
diff --git a/web/app/assets/stylesheets/client/band.css.scss b/web/app/assets/stylesheets/client/band.css.scss
index c907ef7d5..63152401a 100644
--- a/web/app/assets/stylesheets/client/band.css.scss
+++ b/web/app/assets/stylesheets/client/band.css.scss
@@ -17,6 +17,43 @@
font-size:14px;
}
+.band-setup-photo {
+
+ .avatar-space {
+ color: $color2;
+ margin-bottom: 20px;
+ position:relative;
+ min-height:300px;
+
+ img.preview_profile_avatar {
+ }
+ }
+
+
+ .spinner-large {
+ width:300px;
+ height:300px;
+ line-height: 300px;
+ position:absolute;
+ top:0;
+ left:0;
+ z-index: 2000; // to win over jcrop
+ }
+
+ .no-avatar-space {
+ border:1px dotted $color2;
+
+ color: $color2;
+ width:300px;
+ height:300px;
+ line-height: 300px;
+ text-align: center;
+ vertical-align: middle;
+ background-color:$ColorTextBoxBackground;
+
+ }
+ }
+
.band-profile-header {
padding:20px;
height:120px;
@@ -233,3 +270,22 @@
.band-profile-block-city {
font-size:12px;
}
+
+#band-filter-results {
+ margin: 0 10px 5px 10px;
+ overflow: auto;
+ height: 100%;
+ width: 100%;
+}
+
+.band-list-result {
+ padding-top: 5px;
+ padding-right: 5px;
+ padding-left: 5px;
+}
+
+.band-wrapper {
+ overflow: auto;
+ height: 480px;
+ width: 100%;
+}
diff --git a/web/app/assets/stylesheets/client/common.css.scss b/web/app/assets/stylesheets/client/common.css.scss
index c75f35e17..67a0950f3 100644
--- a/web/app/assets/stylesheets/client/common.css.scss
+++ b/web/app/assets/stylesheets/client/common.css.scss
@@ -34,5 +34,8 @@ $text: #f3f1ee;
$gradient-diff: 30%; $link: $color8;
$border: hsl(210, 50%, 45%);
+$narrow-screen: 1000px; // 990 ? 1000 ?
+$short-screen: 600px; // toolbars / chrome for x768
+
diff --git a/web/app/assets/stylesheets/client/content-orig.css.scss b/web/app/assets/stylesheets/client/content-orig.css.scss
new file mode 100644
index 000000000..039a9e928
--- /dev/null
+++ b/web/app/assets/stylesheets/client/content-orig.css.scss
@@ -0,0 +1,382 @@
+/* This is simply Jeff's content.css file */
+@charset "UTF-8";
+#content {
+ background-color: #353535;
+ border: 1px solid #ed3618;
+ clear: both;
+ float: left;
+ margin-top: 39px;
+ height: auto;
+ width: auto;
+ position:relative;
+ padding-bottom:3px;
+}
+
+.content-head {
+ height:21px;
+ padding:4px;
+ background-color:#ED3618;
+}
+
+.content-icon {
+ margin-right:10px;
+ float:left;
+}
+
+.content-head h1 {
+ margin: -6px 0px 0px 0px;
+ padding:0;
+ float:left;
+ font-weight:100;
+ font-size:24px;
+}
+
+.content-nav {
+ float:right;
+ margin-right:10px;
+}
+
+.home-icon {
+ float:left;
+ margin-right:20px;
+}
+
+.content-nav a.arrow-right {
+ float:left;
+ display:block;
+ margin-top:2px;
+ margin-right:10px;
+ width: 0;
+ height: 0;
+ border-top: 7px solid transparent;
+ border-bottom: 7px solid transparent;
+ border-left: 7px solid #FFF;
+}
+
+.content-nav a.arrow-left {
+ float:left;
+ display:block;
+ margin-top:2px;
+ margin-right:20px;
+ width: 0;
+ height: 0;
+ border-top: 7px solid transparent;
+ border-bottom: 7px solid transparent;
+ border-right:7px solid #FFF;
+}
+
+#content-scroller, .content-scroller {
+ height:inherit;
+ position:relative;
+ display:block;
+ overflow:auto;
+}
+
+.content-wrapper {
+ padding:10px 30px 10px 36px;
+ font-size:15px;
+ color:#ccc;
+ border-bottom: dotted 1px #444;
+ overflow-x:hidden;
+ white-space:nowrap;
+}
+
+.create-session-left {
+ width:50%;
+ float:left;
+}
+
+.create-session-right {
+ width:45%;
+ float:right;
+ font-size:13px;
+}
+
+.content-wrapper h2 {
+ color:#fff;
+ font-weight:600;
+ font-size:24px;
+}
+
+.content-wrapper select, .content-wrapper textarea, .content-wrapper input[type=text], .content-wrapper input[type=password], div.friendbox, .ftue-inner input[type=text], .ftue-inner input[type=password], .dialog-inner textarea, .dialog-inner input[type=text] {
+ font-family:"Raleway", arial, sans-serif;
+ background-color:#c5c5c5;
+ border:none;
+ -webkit-box-shadow: inset 2px 2px 3px 0px #888;
+ box-shadow: inset 2px 2px 3px 0px #888;
+ color:#666;
+}
+
+.create-session-description {
+ padding:5px;
+ width:100%;
+ height:80px;
+}
+
+.friendbox {
+ padding:5px;
+ width:100%;
+ height:60px;
+}
+
+.invite-friend {
+ margin:0px 4px 4px 4px;
+ float:left;
+ display:block;
+ background-color:#666;
+ color:#fff;
+ font-size:12px;
+ -webkit-border-radius: 7px;
+ border-radius: 7px;
+ padding:2px 2px 2px 4px;
+}
+
+.content-wrapper div.friendbox input[type=text] {
+ -webkit-box-shadow: inset 0px 0px 0px 0px #888;
+ box-shadow: inset 0px 0px 0px 0px #888;
+ color:#666;
+ font-style:italic;
+}
+
+#genrelist, #musicianlist {
+ position:relative;
+ z-index:99;
+ width: 175px;
+ -webkit-border-radius: 6px;
+ border-radius: 6px;
+ background-color:#C5C5C5;
+ border: none;
+ color:#333;
+ font-weight:400;
+ padding:0px 0px 0px 8px;
+ height:20px;
+ line-height:20px;
+ overflow:hidden;
+ -webkit-box-shadow: inset 2px 2px 3px 0px #888;
+ box-shadow: inset 2px 2px 3px 0px #888;
+}
+
+#musicianlist, .session-controls #genrelist {
+ width: 150px;
+}
+
+#genrelist a, #musicianlist a {
+ color:#333;
+ text-decoration:none;
+}
+
+.genre-wrapper, .musician-wrapper {
+ float:left;
+ width:175px;
+ height:127px;
+ overflow:auto;
+}
+
+.musician-wrapper, .session-controls .genre-wrapper {
+ width:150px;
+}
+
+.genrecategory {
+ font-size:11px;
+ float:left;
+ width:135px;
+}
+
+.filtercategory, .session-controls .genrecategory {
+ font-size:11px;
+ float:left;
+ width:110px;
+}
+
+a.arrow-up {
+ float:right;
+ margin-right:5px;
+ display:block;
+ margin-top:6px;
+ width: 0;
+ height: 0;
+ border-left: 7px solid transparent;
+ border-right: 7px solid transparent;
+ border-bottom: 7px solid #333;
+}
+
+a.arrow-down {
+ float:right;
+ margin-right:5px;
+ display:block;
+ margin-top:6px;
+ width: 0;
+ height: 0;
+ border-left: 7px solid transparent;
+ border-right: 7px solid transparent;
+ border-top: 7px solid #333;
+}
+
+.settings-session-description {
+ padding:10px;
+ width:300px;
+}
+
+#session-controls {
+ width:100%;
+ padding:11px 0px 11px 0px;
+ background-color:#4c4c4c;
+ min-height:20px;
+ overflow-x:hidden;
+ }
+
+#session-controls .searchbox {
+ float:left;
+ width:140px;
+ margin-left: 10px;
+ -webkit-border-radius: 6px;
+ border-radius: 6px;
+ background-color:#C5C5C5;
+ border: none;
+ color:#333;
+ font-weight:400;
+ padding:0px 0px 0px 8px;
+ height:20px;
+ line-height:20px;
+ overflow:hidden;
+ -webkit-box-shadow: inset 2px 2px 3px 0px #888;
+ box-shadow: inset 2px 2px 3px 0px #888;
+}
+
+#session-controls input[type=text] {
+ background-color:#c5c5c5;
+ border:none;
+ color:#666;
+}
+
+.avatar-tiny {
+ float:left;
+ padding:1px;
+ width:24px;
+ height:24px;
+ background-color:#ed3618;
+ -webkit-border-radius:12px;
+ -moz-border-radius:12px;
+ border-radius:12px;
+}
+
+.ftue-background {
+ background-image:url(../images/content/bkg_ftue.jpg);
+ background-repeat:no-repeat;
+ background-size:cover;
+ min-height:475px;
+ min-width:672px;
+}
+
+table.generaltable {
+ background-color: #262626;
+ border: 1px solid #4D4D4D;
+ color: #FFFFFF;
+ font-size: 11px;
+ margin-top: 6px;
+ width: 100%;
+
+ th {
+ background-color: #4D4D4D;
+ border-right: 1px solid #333333;
+ font-weight: 300;
+ padding: 6px;
+ }
+
+ td {
+ border-right: 1px solid #333333;
+ border-top: 1px solid #333333;
+ padding: 9px 5px 5px;
+ vertical-align: top;
+ white-space: normal;
+ }
+
+ .noborder {
+ border-right: medium none;
+ }
+}
+
+ul.shortcuts {
+ border:1px solid #ED3618;
+
+ li {
+ margin:0;
+ height:20px;
+ line-height:20px;
+ padding:2px;
+ }
+
+ .account-home, .band-setup, .audio, .get-help, .download-app, .invite-friends {
+ border-bottom:1px;
+ border-style:solid;
+ border-color:#ED3618;
+ }
+
+ span.arrow-right {
+ display:inline-block;
+ width: 0;
+ height: 0;
+ border-top: 4px solid transparent;
+ border-bottom: 4px solid transparent;
+ border-left: 4px solid #FFCC00;
+ padding-left:5px;
+ }
+
+ ul.shortcuts-submenu {
+ display:none;
+
+ li {
+ margin:0;
+ height:20px;
+ line-height:20px;
+ padding:2px;
+ color:#FFCC00;
+ }
+
+ li.google-invite, li.email-invite {
+ padding-left:9px;
+ }
+
+ }
+}
+
+.tagline {
+ font-size:30px;
+ margin-top:35px;
+ color:#ed3718;
+ font-weight:300;
+ width:345px;
+ clear:left;
+ white-space:normal;
+}
+
+.smallbutton {
+ font-size:10px !important;
+ padding:2px 8px !important;
+}
+
+.whitespace {
+ white-space:normal;
+}
+
+.w0 {width:0% !important}
+.w5 {width:5% !important}
+.w10 {width:10% !important}
+.w15 {width:15% !important}
+.w20 {width:20% !important}
+.w25 {width:25% !important}
+.w30 {width:30% !important}
+.w35 {width:35% !important}
+.w40 {width:40% !important}
+.w45 {width:45% !important}
+.w50 {width:50% !important}
+.w55 {width:55% !important}
+.w60 {width:60% !important}
+.w65 {width:65% !important}
+.w70 {width:70% !important}
+.w75 {width:75% !important}
+.w80 {width:80% !important}
+.w85 {width:85% !important}
+.w90 {width:90% !important}
+.w95 {width:95% !important}
+.w100 {width:100% !important}
diff --git a/web/app/assets/stylesheets/client/content.css.scss b/web/app/assets/stylesheets/client/content.css.scss
index 2c7d100e8..168845843 100644
--- a/web/app/assets/stylesheets/client/content.css.scss
+++ b/web/app/assets/stylesheets/client/content.css.scss
@@ -1,5 +1,7 @@
-/* This is simply Jeff's content.css file */
-@charset "UTF-8";
+/* This is Daniel's content.css file */
+/* Common styles used in screens */
+@import "client/common.css.scss";@charset "UTF-8";
+
#content {
background-color: #353535;
border: 1px solid #ed3618;
@@ -12,58 +14,96 @@
padding-bottom:3px;
}
-.content-head {
- height:21px;
- padding:4px;
- background-color:#ED3618;
+/* Daniel's tweaks */
+.screen, .screen .content {
+ .content-head {
+ position: absolute;
+ height:21px;
+ padding:4px 0;
+ width:100%;
+ background-color:$ColorScreenPrimary;
+
+ .content-icon {
+ margin: -1px 10px 0 4px;
+ float:left;
+ }
+
+ .content-nav {
+ float:right;
+ margin-right:10px;
+
+ a {
+ &.arrow-right,
+ &.arrow-left {
+ float:left;
+ display:block;
+ margin-top:2px;
+ width: 0;
+ height: 0;
+ border-top: 7px solid transparent;
+ border-bottom: 7px solid transparent;
+ }
+ &.arrow-right {
+ margin-right:10px;
+ border-left: 7px solid #FFF;
+ }
+ &.arrow-left {
+ margin-right:20px;
+ border-right:7px solid #FFF;
+ }
+
+ }
+ }
+
+ h1 {
+ margin: -3px 0px 0px 0px;
+ padding:0;
+ float:left;
+ font-weight:100;
+ font-size:24px;
+ }
+ }
+ .content-body {
+ height:100%;
+ width:100%;
+ box-sizing: border-box;
+ padding-top: 29px;
+
+ .content-body-scroller {
+ height:inherit;
+ position:relative;
+ display:block;
+ overflow:auto;
+// padding: 10px 35px;
+
+ @media screen and (max-width: $narrow-screen) {
+// padding: 10px 20px;
+ }
+
+ &.outer {
+ overflow: hidden;
+ > * {
+ height:inherit;
+ }
+ }
+ }
+ }
}
-.content-icon {
- margin-right:10px;
- float:left;
+.result-list-button-wrapper {
+ margin-top: 10px;
+ margin-bottom: 10px;
+ > a.smallbutton {
+ margin: 2px;
+ }
}
-.content-head h1 {
- margin: -6px 0px 0px 0px;
- padding:0;
- float:left;
- font-weight:100;
- font-size:24px;
-}
-
-.content-nav {
- float:right;
- margin-right:10px;
-}
.home-icon {
float:left;
margin-right:20px;
}
-.content-nav a.arrow-right {
- float:left;
- display:block;
- margin-top:2px;
- margin-right:10px;
- width: 0;
- height: 0;
- border-top: 7px solid transparent;
- border-bottom: 7px solid transparent;
- border-left: 7px solid #FFF;
-}
-
-.content-nav a.arrow-left {
- float:left;
- display:block;
- margin-top:2px;
- margin-right:20px;
- width: 0;
- height: 0;
- border-top: 7px solid transparent;
- border-bottom: 7px solid transparent;
- border-right:7px solid #FFF;
-}
#content-scroller, .content-scroller {
height:inherit;
@@ -72,25 +112,14 @@
overflow:auto;
}
-.content-wrapper {
- padding:10px 30px 10px 36px;
- font-size:15px;
- color:#ccc;
- border-bottom: dotted 1px #444;
- overflow-x:hidden;
- white-space:nowrap;
-}
-
-.create-session-left {
- width:50%;
- float:left;
-}
-
-.create-session-right {
- width:45%;
- float:right;
- font-size:13px;
-}
+//.content-wrapper {
+// padding:10px 30px 10px 36px;
+// font-size:15px;
+// color:#ccc;
+// border-bottom: dotted 1px #444;
+// overflow-x:hidden;
+// white-space:nowrap;
+//}
.content-wrapper h2 {
color:#fff;
@@ -98,7 +127,7 @@
font-size:24px;
}
-.content-wrapper select, .content-wrapper textarea, .content-wrapper input[type=text], .content-wrapper input[type=password], div.friendbox, .ftue-inner input[type=text], .ftue-inner input[type=password], .dialog-inner textarea, .dialog-inner input[type=text] {
+.content-wrapper select, .content-wrapper textarea, .content-wrapper input[type=text], .content-wrapper input[type=password], div.friendbox, .ftue-inner input[type=text], .ftue-inner input[type=password], .dialog-inner textarea, .dialog-inner input[type=text], .dialog-inner select {
font-family:"Raleway", arial, sans-serif;
background-color:#c5c5c5;
border:none;
@@ -222,7 +251,7 @@ a.arrow-down {
padding:11px 0px 11px 0px;
background-color:#4c4c4c;
min-height:20px;
- overflow-x:hidden;
+ overflow-x:scroll;
}
#session-controls .searchbox {
@@ -379,4 +408,4 @@ ul.shortcuts {
.w85 {width:85% !important}
.w90 {width:90% !important}
.w95 {width:95% !important}
-.w100 {width:100% !important}
\ No newline at end of file
+.w100 {width:100% !important}
diff --git a/web/app/assets/stylesheets/client/createSession.css.scss b/web/app/assets/stylesheets/client/createSession.css.scss
index 0979239cd..f345b2ac4 100644
--- a/web/app/assets/stylesheets/client/createSession.css.scss
+++ b/web/app/assets/stylesheets/client/createSession.css.scss
@@ -1,25 +1,27 @@
-.session-left {
- width:40%;
- float:left;
- padding-top:10px;
- margin-left:35px;
+.session-wrapper {
+ padding: 10px 35px;
+ white-space: initial;
+
+ > div.session {
+ width: 50%;
+
+ &.right {
+ font-size: 13px;
+ }
+ }
}
+#btn-choose-friends {
+ margin:0;
+}
#create-session-genre select, #create-session-band select {
- width:145px;
+ min-width:140px;
}
#find-session-genre select, #find-session-musician select {
width:145px;
}
-.session-right {
- width:50%;
- float:right;
- font-size:13px;
- padding-top:10px;
- margin-right:35px;
-}
.session-description {
padding:5px;
@@ -32,12 +34,6 @@
line-height:17px;
}
-.friendbox {
- padding:5px;
- height:60px;
- width:75%;
-}
-
.terms-checkbox {
float:left;
display:block;
@@ -51,19 +47,22 @@
white-space:normal;
}
-div.friendbox {
+.friendbox {
background-color:#c5c5c5;
border:none;
-webkit-box-shadow: inset 2px 2px 3px 0px #888;
box-shadow: inset 2px 2px 3px 0px #888;
color:#333;
-}
+ padding:5px;
+ height:60px;
-div.friendbox input[type=text] {
- -webkit-box-shadow: inset 0px 0px 0px 0px #888;
- box-shadow: inset 0px 0px 0px 0px #888;
- color:#666;
- font-style:italic;
+ input[type=text] {
+ -webkit-box-shadow: inset 0px 0px 0px 0px #888;
+ box-shadow: inset 0px 0px 0px 0px #888;
+ color:#666;
+ font-style:italic;
+
+ }
}
.invitation {
diff --git a/web/app/assets/stylesheets/client/musician.css.scss b/web/app/assets/stylesheets/client/musician.css.scss
index 709fc7f0b..fc78eefa3 100644
--- a/web/app/assets/stylesheets/client/musician.css.scss
+++ b/web/app/assets/stylesheets/client/musician.css.scss
@@ -1,18 +1,35 @@
.filter-element {
float:left;
margin-left: 5px;
+
+ &.wrapper {
+ margin-top: 5px;
+ &.right {
+ float: right;
+ > a {
+ margin-top: 3px;
+ }
+ }
+ }
+
+ // @FIXME labeel is overriding from #session-controls.
+ &.desc {
+ margin-top: 3px;
+ padding-top: 3px;
+ }
}
+
#musician-filter-results {
- margin: 0 10px 5px 10px;
+ margin: 0 10px 0px 10px;
overflow: auto;
height: 100%;
- width: 100%;
+// width: 100%;
}
.musician-wrapper {
- overflow: auto;
- height: 480px;
+// overflow: auto;
+// height: 480px;
width: 100%;
}
@@ -20,8 +37,12 @@
padding-top: 5px;
padding-right: 5px;
padding-left: 5px;
+ box-sizing:border-box;
}
+#session-controls.musician-filter {
+ padding-top: 6px;
+}
.musician-following {
overflow: auto;
-}
\ No newline at end of file
+}
diff --git a/web/app/assets/stylesheets/client/profile.css.scss b/web/app/assets/stylesheets/client/profile.css.scss
index c7f543555..ef0a772dd 100644
--- a/web/app/assets/stylesheets/client/profile.css.scss
+++ b/web/app/assets/stylesheets/client/profile.css.scss
@@ -1,8 +1,8 @@
@import "client/common.css.scss";
.profile-header {
- padding:20px;
- height:120px;
+ padding:10px 20px;
+// height:120px;
}
.profile-header h2 {
@@ -252,4 +252,4 @@
border-top:none;
padding:3px;
vertical-align:middle;
-}
\ No newline at end of file
+}
diff --git a/web/app/assets/stylesheets/client/search.css.scss b/web/app/assets/stylesheets/client/search.css.scss
index 0cb2f25ff..c1a43fe51 100644
--- a/web/app/assets/stylesheets/client/search.css.scss
+++ b/web/app/assets/stylesheets/client/search.css.scss
@@ -56,20 +56,9 @@
}
.query-distance-params {
- float:left;
- width:50px;
- margin-left: 10px;
- -webkit-border-radius: 6px;
- border-radius: 6px;
- background-color:$ColorTextBoxBackground;
+ float: left;
+// width: 80px;
+ margin-left: 2px;
border: none;
- color:#333;
- font-weight:400;
- padding:0px 0px 0px 8px;
- height:18px;
- line-height:18px;
- overflow:hidden;
- -webkit-box-shadow: inset 2px 2px 3px 0px #888;
- box-shadow: inset 2px 2px 3px 0px #888;
}
diff --git a/web/app/assets/stylesheets/client/web_filter.css.scss b/web/app/assets/stylesheets/client/web_filter.css.scss
new file mode 100644
index 000000000..b84bc97ce
--- /dev/null
+++ b/web/app/assets/stylesheets/client/web_filter.css.scss
@@ -0,0 +1,70 @@
+@import "client/common.css.scss";
+@charset "UTF-8";
+
+.filter-results {
+
+ li {
+ position: relative;
+ border-bottom:solid 1px shade($ColorElementPrimary, 20);
+ clear:both;
+ }
+
+ li strong {
+ font-weight:bold;
+ }
+
+ li.offline {
+ background-color: shade($ColorElementPrimary, 20);
+ color: shade($text, 10);
+ opacity:0.5;
+ ms-filter: "alpha(opacity=50)";
+ }
+
+ .avatar-small {
+ float:left;
+ padding:1px;
+ width:36px;
+ height:36px;
+ background-color:#ed3618;
+ margin:10px;
+ -webkit-border-radius:18px;
+ -moz-border-radius:18px;
+ border-radius:18px;
+ }
+
+ .avatar-small img {
+ width: 36px;
+ height: 36px;
+ -webkit-border-radius:18px;
+ -moz-border-radius:18px;
+ border-radius:18px;
+ }
+
+ li a {
+ color:#B3DD15;
+ }
+
+ li a:hover {
+ color:#FFF;
+ }
+
+ .result-name {
+ float:left;
+ font-size:12px;
+ margin-top:12px;
+ font-weight:bold;
+ }
+
+ .result-location {
+ font-size:11px;
+ color:#D5E2E4;
+ font-weight:200;
+ }
+
+ .results-wrapper {
+ width: 300px;
+ overflow-y:auto;
+ overflow-x:hidden;
+ }
+}
+
diff --git a/web/app/controllers/api_bands_controller.rb b/web/app/controllers/api_bands_controller.rb
index b3ca1e623..1d441e21c 100644
--- a/web/app/controllers/api_bands_controller.rb
+++ b/web/app/controllers/api_bands_controller.rb
@@ -3,7 +3,8 @@ class ApiBandsController < ApiController
before_filter :api_signed_in_user, :except => [:index, :show, :follower_index]
before_filter :auth_band_member, :only => [:update,
:recording_create, :recording_update, :recording_destroy,
- :invitation_index, :invitation_show, :invitation_create, :invitation_destroy]
+ :invitation_index, :invitation_show, :invitation_create, :invitation_destroy,
+ :update_photo, :delete_photo, :generate_filepicker_policy]
respond_to :json
@@ -65,7 +66,9 @@ class ApiBandsController < ApiController
def musician_destroy
unless params[:id].blank? || params[:user_id].blank?
+ BandMusician.delete_all "(band_id = '#{params[:id]}' AND user_id = '#{params[:user_id]}')"
end
+ render :json => {}, :status => 202
end
###################### FOLLOWERS ########################
@@ -185,6 +188,56 @@ class ApiBandsController < ApiController
end
end
+ def update_photo
+ original_fpfile = params[:original_fpfile]
+ cropped_fpfile = params[:cropped_fpfile]
+ crop_selection = params[:crop_selection]
+
+ # public bucket to allow images to be available to public
+ @band.update_photo(original_fpfile, cropped_fpfile, crop_selection, Rails.application.config.aws_bucket_public)
+
+ if @band.errors.any?
+ render :json => { :message => "Unexpected error updating photo."}, :status => :unprocessable_entity
+ else
+ render :json => {}, :status => :ok
+ end
+ end
+
+ def delete_photo
+ @band.delete_photo(Rails.application.config.aws_bucket_public)
+
+ if @band.errors.any?
+ render :json => { :message => "Unexpected error deleting photo."}, :status => :unprocessable_entity
+ else
+ render :json => {}, :status => :ok
+ end
+ end
+
+ def generate_filepicker_policy
+ # generates a soon-expiring filepicker policy so that a band can only upload to their own folder in their bucket
+
+ handle = params[:handle]
+
+ call = 'pick,convert,store'
+
+ policy = { :expiry => (DateTime.now + 5.minutes).to_i(),
+ :call => call
+ #:path => 'avatars/' + @band.id + '/.*jpg'
+ }
+
+ # if the caller specifies a handle, add it to the hash
+ unless handle.nil?
+ start = handle.rindex('/') + 1
+ policy[:handle] = handle[start..-1]
+ end
+
+ policy = Base64.urlsafe_encode64( policy.to_json )
+ digest = OpenSSL::Digest::Digest.new('sha256')
+ signature = OpenSSL::HMAC.hexdigest(digest, Rails.application.config.fp_secret, policy)
+
+ render :json => { :signature => signature, :policy => policy }, :status => :ok
+ end
+
#############################################################################
protected
# ensures user is a member of the band
diff --git a/web/app/controllers/api_maxmind_requests_controller.rb b/web/app/controllers/api_maxmind_requests_controller.rb
index 5173c6754..98c0cf8b3 100644
--- a/web/app/controllers/api_maxmind_requests_controller.rb
+++ b/web/app/controllers/api_maxmind_requests_controller.rb
@@ -34,4 +34,10 @@ class ApiMaxmindRequestsController < ApiController
end
end
+ # returns location hash (country, region, state) based on requesting IP
+ def resolved_location
+ location = MaxMindManager.lookup(request.remote_ip)
+ render :json => { :country => location[:country], :region => location[:state], :city => location[:city] }, :status => 200
+ end
+
end
\ No newline at end of file
diff --git a/web/app/controllers/api_music_sessions_controller.rb b/web/app/controllers/api_music_sessions_controller.rb
index 1d1028a8b..9809d49d0 100644
--- a/web/app/controllers/api_music_sessions_controller.rb
+++ b/web/app/controllers/api_music_sessions_controller.rb
@@ -101,11 +101,11 @@ class ApiMusicSessionsController < ApiController
def participant_delete
client_id = params[:id]
- @connection = Connection.find_by_client_id!(client_id)
- music_session = MusicSession.find(@connection.music_session_id)
-
- MusicSessionManager.new.participant_delete(current_user, @connection, music_session)
-
+ if client_id.present? && client_id != 'undefined'
+ @connection = Connection.find_by_client_id!(client_id)
+ music_session = MusicSession.find(@connection.music_session_id)
+ MusicSessionManager.new.participant_delete(current_user, @connection, music_session)
+ end
respond_with @connection, responder: ApiResponder
end
diff --git a/web/app/controllers/api_search_controller.rb b/web/app/controllers/api_search_controller.rb
index 006b64783..63c0ff8d9 100644
--- a/web/app/controllers/api_search_controller.rb
+++ b/web/app/controllers/api_search_controller.rb
@@ -7,11 +7,15 @@ class ApiSearchController < ApiController
def index
if 1 == params[Search::PARAM_MUSICIAN].to_i
- logger.debug("*** params = #{params.inspect}")
query = params.clone
query[:remote_ip] = request.remote_ip
@search = Search.musician_search(query, current_user)
respond_with @search, responder: ApiResponder, :status => 200
+ elsif 1 == params[Search::PARAM_BAND].to_i
+ query = params.clone
+ query[:remote_ip] = request.remote_ip
+ @search = Search.band_search(query, current_user)
+ respond_with @search, responder: ApiResponder, :status => 200
else
@search = Search.search(params[:query], current_user.id)
end
diff --git a/web/app/controllers/api_users_controller.rb b/web/app/controllers/api_users_controller.rb
index 40a96b869..1fa1c4271 100644
--- a/web/app/controllers/api_users_controller.rb
+++ b/web/app/controllers/api_users_controller.rb
@@ -19,7 +19,10 @@ class ApiUsersController < ApiController
end
def show
- @user = User.find(params[:id])
+ @user = User.includes([{:musician_instruments => :instrument},
+ {:band_musicians => :user},
+ :bands, :instruments])
+ .find(params[:id])
respond_with @user, responder: ApiResponder, :status => 200
end
diff --git a/web/app/controllers/artifacts_controller.rb b/web/app/controllers/artifacts_controller.rb
index 45c74c832..180f12286 100644
--- a/web/app/controllers/artifacts_controller.rb
+++ b/web/app/controllers/artifacts_controller.rb
@@ -51,11 +51,12 @@ class ArtifactsController < ApiController
end
def determine_url(artifact)
+
if SampleApp::Application.config.storage_type == :file
# this is basically a dev-time only path of code; we store real artifacts in s3
url = SampleApp::Application.config.jam_admin_root_url + artifact.uri.url
else
- url = artifact.uri.url
+ url = artifact.uri.url.gsub(SampleApp::Application.config.aws_fullhost,SampleApp::Application.config.cloudfront_host)
end
return url
diff --git a/web/app/views/api_bands/show.rabl b/web/app/views/api_bands/show.rabl
index bcd2ed486..c893e696d 100644
--- a/web/app/views/api_bands/show.rabl
+++ b/web/app/views/api_bands/show.rabl
@@ -1,6 +1,7 @@
object @band
-attributes :id, :name, :city, :state, :country, :location, :website, :biography, :photo_url, :logo_url, :liker_count, :follower_count, :recording_count, :session_count
+attributes :id, :name, :city, :state, :country, :location, :website, :biography, :photo_url, :logo_url, :liker_count, :follower_count, :recording_count, :session_count,
+:original_fpfile_photo, :cropped_fpfile_photo, :crop_selection_photo
unless @band.users.nil? || @band.users.size == 0
child :users => :musicians do
diff --git a/web/app/views/api_search/index.rabl b/web/app/views/api_search/index.rabl
index f4ec6a6e8..e7102cee9 100644
--- a/web/app/views/api_search/index.rabl
+++ b/web/app/views/api_search/index.rabl
@@ -1,12 +1,26 @@
object @search
-unless @search.bands.nil? || @search.bands.size == 0
+if @search.bands.present?
child(:bands => :bands) {
attributes :id, :name, :location, :photo_url, :logo_url
}
end
-unless @search.musicians.nil? || @search.musicians.size == 0
+if @search.musicians.present?
+ child(:musicians => :musicians) {
+ attributes :id, :first_name, :last_name, :name, :location, :photo_url
+
+ node :is_friend do |musician|
+ musician.friends?(current_user)
+ end
+
+ child :musician_instruments => :instruments do
+ attributes :instrument_id, :description, :proficiency_level, :priority
+ end
+ }
+end
+
+if @search.musicians_filter.present?
node :city do |user|
current_user.try(:location)
@@ -16,7 +30,7 @@ unless @search.musicians.nil? || @search.musicians.size == 0
@search.page_count
end
- child(:musicians => :musicians) {
+ child(:musicians_filter => :musicians) {
attributes :id, :first_name, :last_name, :name, :city, :state, :country, :email, :online, :musician, :photo_url, :biography
node :is_friend do |musician|
@@ -44,6 +58,36 @@ unless @search.musicians.nil? || @search.musicians.size == 0
}
end
+if @search.bands_filter.present?
+
+ node :page_count do |foo|
+ @search.page_count
+ end
+
+ child(:bands_filter => :bands) {
+ attributes :id, :name, :city, :state, :country, :email, :photo_url, :biography, :logo_url
+
+ node :is_following do |band|
+ @search.is_follower?(band)
+ end
+
+ child :genres => :genres do
+ attributes :genre_id, :description
+ end
+
+ child :users => :players do |pl|
+ node :user_id do |uu| uu.id end
+ node :photo_url do |uu| uu.photo_url end
+ node :name do |uu| uu.name end
+ node :instruments do |uu| uu.instruments.map(&:id).join(',') end
+ end
+
+ node :follow_count do |band| @search.follow_count(band) end
+ node :recording_count do |band| @search.record_count(band) end
+ node :session_count do |band| @search.session_count(band) end
+ }
+end
+
unless @search.fans.nil? || @search.fans.size == 0
child(:fans => :fans) {
attributes :id, :first_name, :last_name, :name, :location, :photo_url
diff --git a/web/app/views/api_users/show.rabl b/web/app/views/api_users/show.rabl
index 9a35978ef..13360ac19 100644
--- a/web/app/views/api_users/show.rabl
+++ b/web/app/views/api_users/show.rabl
@@ -1,11 +1,23 @@
object @user
-attributes :id, :first_name, :last_name, :name, :city, :state, :country, :location, :online, :photo_url, :musician, :gender, :birth_date, :internet_service_provider, :friend_count, :liker_count, :like_count, :band_like_count, :follower_count, :following_count, :band_following_count, :recording_count, :session_count,
-:biography
+attributes :id, :first_name, :last_name, :name, :city, :state, :country, :location, :online, :photo_url, :musician, :gender, :birth_date, :internet_service_provider, :friend_count, :liker_count, :like_count, :band_like_count, :follower_count, :following_count, :band_following_count, :recording_count, :session_count, :biography, :favorite_count
+
+if @user.musician?
+ node :location do @user.location end
+else
+ node :location do @user.online ? 'Online' : 'Offline' end
+end
# give back more info if the user being fetched is yourself
if @user == current_user
attributes :email, :original_fpfile, :cropped_fpfile, :crop_selection, :session_settings, :show_whats_next, :subscribe_email
+elsif current_user
+ node :is_friend do |uu|
+ @user.friends?(current_user)
+ end
+ node :is_following do |uu|
+ @user.following?(current_user)
+ end
end
unless @user.friends.nil? || @user.friends.size == 0
diff --git a/web/app/views/clients/_account.html.erb b/web/app/views/clients/_account.html.erb
index 0bd1a893c..86c8f43d8 100644
--- a/web/app/views/clients/_account.html.erb
+++ b/web/app/views/clients/_account.html.erb
@@ -1,111 +1,117 @@
+
-
-
-
-
- <%= image_tag "content/icon_account.png", {:height => 18, :width => 18} %>
+
+
+
+
+ <%= image_tag "content/icon_account.png", {:height => 18, :width => 18} %>
+
+
my account
+ <%= render "screen_navigation" %>
+
+
+
+
-
my account
- <%= render "screen_navigation" %>
-
-
-
+
-
-
diff --git a/web/app/views/clients/_account_audio_profile.html.erb b/web/app/views/clients/_account_audio_profile.html.erb
index 236bd2c8b..d1e5fc947 100644
--- a/web/app/views/clients/_account_audio_profile.html.erb
+++ b/web/app/views/clients/_account_audio_profile.html.erb
@@ -13,8 +13,10 @@
-
diff --git a/web/app/views/clients/_account_identity.html.erb b/web/app/views/clients/_account_identity.html.erb
index f99233cce..345825c42 100644
--- a/web/app/views/clients/_account_identity.html.erb
+++ b/web/app/views/clients/_account_identity.html.erb
@@ -13,8 +13,10 @@
-
diff --git a/web/app/views/clients/_account_profile.html.erb b/web/app/views/clients/_account_profile.html.erb
index 9a851ca1b..e301ae4e5 100644
--- a/web/app/views/clients/_account_profile.html.erb
+++ b/web/app/views/clients/_account_profile.html.erb
@@ -1,4 +1,4 @@
-
+
@@ -13,8 +13,10 @@
-
diff --git a/web/app/views/clients/_account_profile_avatar.html.erb b/web/app/views/clients/_account_profile_avatar.html.erb
index 57ff42942..49bf17f20 100644
--- a/web/app/views/clients/_account_profile_avatar.html.erb
+++ b/web/app/views/clients/_account_profile_avatar.html.erb
@@ -1,4 +1,4 @@
-
+
@@ -35,7 +35,7 @@
-
+
diff --git a/web/app/views/clients/_bandProfile.html.erb b/web/app/views/clients/_bandProfile.html.erb
index 04e40c750..12c321312 100644
--- a/web/app/views/clients/_bandProfile.html.erb
+++ b/web/app/views/clients/_bandProfile.html.erb
@@ -19,7 +19,6 @@
@@ -92,6 +91,7 @@
{biography}
PROFILE
FOLLOW
+
REMOVE MEMBER
CONNECT
diff --git a/web/app/views/clients/_band_setup.html.erb b/web/app/views/clients/_band_setup.html.erb
index fcacd7aac..6cc1b644e 100644
--- a/web/app/views/clients/_band_setup.html.erb
+++ b/web/app/views/clients/_band_setup.html.erb
@@ -9,126 +9,127 @@
<%= render "screen_navigation" %>
-
+
-
-
-
+
\ No newline at end of file
+
diff --git a/web/app/views/clients/_band_setup_photo.html.erb b/web/app/views/clients/_band_setup_photo.html.erb
new file mode 100644
index 000000000..986821592
--- /dev/null
+++ b/web/app/views/clients/_band_setup_photo.html.erb
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+ <%= image_tag "content/icon_bands.png", {:width => 19, :height => 19} %>
+
+
+
band setup
+ <%= render "screen_navigation" %>
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/web/app/views/clients/_bands.html.erb b/web/app/views/clients/_bands.html.erb
index 8505890b1..6e82eb331 100644
--- a/web/app/views/clients/_bands.html.erb
+++ b/web/app/views/clients/_bands.html.erb
@@ -1,13 +1,61 @@
-
-
+<%= content_tag(:div, :layout => 'screen', 'layout-id' => 'bands', :class => "screen secondary") do -%>
+ <%= content_tag(:div, :class => :content) do -%>
+ <%= content_tag(:div, :class => 'content-head') do -%>
+ <%= content_tag(:div, image_tag("content/icon_bands.png", {:height => 19, :width => 19}), :class => 'content-icon') %>
+ <%= content_tag(:h1, 'bands') %>
+ <%= render "screen_navigation" %>
+ <% end -%>
+ <%= content_tag(:div, :class => 'content-body') do -%>
+ <%= content_tag(:div, :class => 'content-body-scroller') do -%>
+ <%= form_tag('', :id => 'find-band-form') do -%>
+ <%= content_tag(:div, render(:partial => "web_filter", :locals => {:search_type => Search::PARAM_BAND}), :class => 'band-filter', :id => 'session-controls') %>
+ <%= content_tag(:div, :class => 'content-scroller') do -%>
+ <%= content_tag(:div, content_tag(:div, '', :id => 'band-filter-results', :class => 'filter-results'), :class => 'content-wrapper band-wrapper') %>
+ <% end -%>
+ <% end -%>
+ <% end -%>
+ <% end -%>
+ <% end -%>
+<% end -%>
-
- <%= image_tag "content/icon_bands.png", {:height => 19, :width => 19} %>
-
-
-
bands
- <%= render "screen_navigation" %>
+
+
+
+
+
+
+
diff --git a/web/app/views/clients/_createSession.html.erb b/web/app/views/clients/_createSession.html.erb
index f4bf56b7b..114bcaf86 100644
--- a/web/app/views/clients/_createSession.html.erb
+++ b/web/app/views/clients/_createSession.html.erb
@@ -1,5 +1,5 @@
-
+
@@ -9,163 +9,165 @@
create session
<%= render "screen_navigation" %>
+
-
-
-
-
-
+
+
+
+
+
+
+
-
session info
+
session info
+
-
-
-
-
Genre:
-
- <%= render "genreSelector" %>
-
-
-
-
-
Band:
-
-
- Not a Band Session
-
-
-
-
-
-
-
-
-
-
-
Musician Access:
-
-
-
-
-
Fan Access:
-
-
-
-
-
invite musicians
-
-
-
-
-
- Start typing friends' names or:
-
-
-
-
-
-
-
-
-
-
-
- Invite friends and contacts to join you on JamKazam from:
-
-
-
-
-
+
+
invite musicians
+
+
+
+
+
+ Start typing friends' names or:
+
+
-
Facebook
-
- -->
-
+
-
Twitter
-
-->
-
-
+
-
+
+
diff --git a/web/app/views/clients/_feed.html.erb b/web/app/views/clients/_feed.html.erb
index 5f09c1720..80b2a24b1 100644
--- a/web/app/views/clients/_feed.html.erb
+++ b/web/app/views/clients/_feed.html.erb
@@ -1,12 +1,18 @@
-
+
+
-
- <%= image_tag "content/icon_feed.png", {:height => 19, :width => 19} %>
+
+ <%= image_tag "content/icon_feed.png", {:height => 19, :width => 19} %>
+
+
feed
+ <%= render "screen_navigation" %>
+
+
+
+
This feature not yet implemented
+
-
feed
- <%= render "screen_navigation" %>
-
This feature not yet implemented
diff --git a/web/app/views/clients/_findSession.html.erb b/web/app/views/clients/_findSession.html.erb
index af1d851c6..dc8a54bfb 100644
--- a/web/app/views/clients/_findSession.html.erb
+++ b/web/app/views/clients/_findSession.html.erb
@@ -10,43 +10,47 @@
<%= render "screen_navigation" %>
-
-
-
-
Filter Session List:
+
+
+
+
+
+
Filter Session List:
-
-
- <%= render "genreSelector" %>
-
+
+
+ <%= render "genreSelector" %>
+
-
-
-
-
REFRESH
+
+
+
+ <%= render :partial => "sessionList", :locals => {:title => "sessions you're invited to", :category => "sessions-invitations"} %>
+
+
+ <%= render :partial => "sessionList", :locals => {:title => "sessions with friends or bandmates", :category => "sessions-friends"} %>
+
+
+ <%= render :partial => "sessionList", :locals => {:title => "other sessions", :category => "sessions-other"} %>
+
+
+
+
+
+
+ There are currently no public sessions.
-
-
-
- <%= render :partial => "sessionList", :locals => {:title => "sessions you're invited to", :category => "sessions-invitations"} %>
-
-
- <%= render :partial => "sessionList", :locals => {:title => "sessions with friends or bandmates", :category => "sessions-friends"} %>
-
-
- <%= render :partial => "sessionList", :locals => {:title => "other sessions", :category => "sessions-other"} %>
-
-
-
-
-
-
-
- There are currently no public sessions.
@@ -105,4 +109,4 @@
\ No newline at end of file
+
diff --git a/web/app/views/clients/_musician_filter.html.erb b/web/app/views/clients/_musician_filter.html.erb
index 4a351876e..f5650b65d 100644
--- a/web/app/views/clients/_musician_filter.html.erb
+++ b/web/app/views/clients/_musician_filter.html.erb
@@ -1,35 +1,29 @@
-<%= content_tag(:div, :style => "min-width:770px;") do -%>
- <%= content_tag(:div, :class => 'filter-element') do -%>
- <%= content_tag(:div, 'Filter By:', :class => 'filter-element', :style => "padding-top:3px;") %>
-
- <%= select_tag(:musician_order_by, options_for_select(Search::M_ORDERINGS), {:class => 'musician-order-by'} ) %>
- <% end -%>
- <%= content_tag(:div, :class => 'filter-element') do -%>
-
- <%= content_tag(:div, 'Instrument:', :class => 'filter-element') %>
- <%= content_tag(:div, :class => 'filter-element', :id => "find-musician-instrument") do -%>
- <%= select_tag(:instrument,
- options_for_select([['Any', '']].concat(JamRuby::Instrument.all.collect { |ii| [ii.description, ii.id] })),
- {:class => 'instrument-list'} ) %>
- <% end -%>
- <% end -%>
-
- <%= content_tag(:div, :class => 'filter-element') do -%>
- <%= content_tag(:div, 'Within', :class => 'filter-element') %>
- <%= content_tag(:div, :class => 'query-distance-params', :style => "height:25px;") do -%>
- <%= text_field_tag(:query_distance,
- Search::M_MILES_DEFAULT.to_s,
- :id => :musician_query_distance,
- :placeholder => Search::M_MILES_DEFAULT.to_s) %>
- <% end -%>
- <%= content_tag(:div, :class => 'filter-element') do -%>
- miles of <%= content_tag(:span, current_user.current_city(request.remote_ip), :id => 'musician-filter-city') %>
- <% end -%>
- <% end -%>
- <%= content_tag(:div,
- link_to('REFRESH', '#',
- :id => 'btn-refresh-musicians',
- :style => 'text-decoration:none',
- :class => 'button-grey'),
- :class => 'right mr10') %>
+<%= content_tag(:div, :class => 'filter-element wrapper foobar') do -%>
+ <%= content_tag(:div, 'Filter By:', :class => 'filter-element desc') %>
+
+ <%= select_tag(:musician_order_by, options_for_select(Search::M_ORDERINGS), {:class => 'musician-order-by'} ) %>
<% end -%>
+<%= content_tag(:div, :class => "filter-element wrapper") do -%>
+ <%= content_tag(:div, :class => 'filter-element wrapper') do -%>
+
+ <%= content_tag(:div, 'Instrumente:', :class => 'filter-element') %>
+ <%= select_tag(:musician_instrument,
+ options_for_select([['Any', '']].concat(JamRuby::Instrument.all.collect { |ii| [ii.description, ii.id] }))) %>
+ <% end -%>
+<% end -%>
+
+<%= content_tag(:div, :class => 'filter-element wrapper') do -%>
+ <%= content_tag(:div, 'Within', :class => 'filter-element desc') %>
+ <%= content_tag(:div, :class => 'query-distance-params') do -%>
+ <%= select_tag('musician_query_distance', options_for_select(Search::M_DISTANCE_OPTS, Search::M_MILES_DEFAULT)) %>
+ <% end -%>
+ <%= content_tag(:div, :class => 'filter-element') do -%>
+ miles of <%= content_tag(:span, current_user.current_city(request.remote_ip), :id => 'musician-filter-city') %>
+ <% end -%>
+<% end -%>
+<%= content_tag(:div,
+link_to('REFRESH', '#',
+ :id => 'btn-refresh-musicians',
+ :style => 'text-decoration:none',
+ :class => 'button-grey'),
+:class => 'filter-element wrapper right mr10') %>
diff --git a/web/app/views/clients/_musicians.html.erb b/web/app/views/clients/_musicians.html.erb
index 3d3e25793..115aba151 100644
--- a/web/app/views/clients/_musicians.html.erb
+++ b/web/app/views/clients/_musicians.html.erb
@@ -6,10 +6,14 @@
<%= content_tag(:h1, 'musicians') %>
<%= render "screen_navigation" %>
<% end -%>
- <%= form_tag('', :id => 'find-musician-form') do -%>
- <%= content_tag(:div, render(:partial => "musician_filter"), :class => 'musician-filter', :id => 'session-controls') %>
- <%= content_tag(:div, :class => 'content-scroller') do -%>
- <%= content_tag(:div, content_tag(:div, '', :id => 'musician-filter-results'), :class => 'content-wrapper musician-wrapper') %>
+ <%= content_tag(:div, :class => 'content-body') do -%>
+ <%= content_tag(:div, :class => 'content-body-scroller') do -%>
+ <%= form_tag('', :id => 'find-musician-form') do -%>
+ <%= content_tag(:div, render(:partial => "web_filter", :locals => {:search_type => Search::PARAM_MUSICIAN}), :class => 'musician-filter', :id => 'session-controls') %>
+ <%= content_tag(:div, :class => 'content-scroller') do -%>
+ <%= content_tag(:div, content_tag(:div, '', :id => 'musician-filter-results'), :class => 'content-wrapper musician-wrapper') %>
+ <% end -%>
+ <% end -%>
<% end -%>
<% end -%>
<% end -%>
@@ -32,10 +36,10 @@
- {biography}
+ {biography}
-
- {musician_action_template}
+
+ {musician_action_template}
@@ -48,7 +52,13 @@
@@ -149,4 +155,4 @@
{userName}
{location}
-
\ No newline at end of file
+
diff --git a/web/app/views/clients/_session.html.erb b/web/app/views/clients/_session.html.erb
index eda192a6b..4c71c8349 100644
--- a/web/app/views/clients/_session.html.erb
+++ b/web/app/views/clients/_session.html.erb
@@ -5,7 +5,6 @@
<%= image_tag "shared/icon_session.png", {:height => 19, :width => 19} %>
session
- <%= render "screen_navigation" %>
diff --git a/web/app/views/clients/_web_filter.html.erb b/web/app/views/clients/_web_filter.html.erb
new file mode 100644
index 000000000..ae0be5889
--- /dev/null
+++ b/web/app/views/clients/_web_filter.html.erb
@@ -0,0 +1,30 @@
+<% filter_label = defined?(search_type) && search_type == Search::PARAM_BAND ? :band : :musician %>
+<%= content_tag(:div, :class => "filter-element wrapper") do -%>
+ <%= content_tag(:div, 'Filter By:', :class => 'filter-element desc') %>
+
+ <%= select_tag("#{filter_label}_order_by", options_for_select(Search::ORDERINGS), {:class => "#{filter_label}-order-by"} ) %>
+<% end -%>
+<%= content_tag(:div, :class => 'filter-element wrapper') do -%>
+ <% if :musician == filter_label %>
+
+ <%= content_tag(:div, 'Instrument:', :class => 'filter-element desc') %>
+ <%= select_tag("#{filter_label}_instrument",
+ options_for_select([['Any', '']].concat(JamRuby::Instrument.all.collect { |ii| [ii.description, ii.id] }))) %>
+ <% elsif :band == filter_label %>
+
+ <%= content_tag(:div, 'Genre:', :class => 'filter-element desc') %>
+ <%= select_tag("#{filter_label}_genre",
+ options_for_select([['Any', '']].concat(JamRuby::Genre.all.collect { |ii| [ii.description, ii.id] }))) %>
+ <% end %>
+<% end -%>
+
+<%= content_tag(:div, :class => 'filter-element wrapper') do -%>
+ <%= content_tag(:div, 'Within', :class => 'filter-element desc') %>
+ <%= content_tag(:div, :class => 'query-distance-params') do -%>
+ <% default_distance = :musician == filter_label ? Search::M_MILES_DEFAULT : Search::B_MILES_DEFAULT %>
+ <%= select_tag("#{filter_label}_query_distance", options_for_select(Search::DISTANCE_OPTS, default_distance)) %>
+ <% end -%>
+ <%= content_tag(:div, :class => 'filter-element desc') do -%>
+ miles of <%= content_tag(:span, current_user.current_city(request.remote_ip), :id => "#{filter_label}-filter-city") %>
+ <% end -%>
+<% end -%>
diff --git a/web/app/views/clients/index.html.erb b/web/app/views/clients/index.html.erb
index 6985978e4..1e8a95051 100644
--- a/web/app/views/clients/index.html.erb
+++ b/web/app/views/clients/index.html.erb
@@ -22,6 +22,7 @@
<%= render "profile" %>
<%= render "bandProfile" %>
<%= render "band_setup" %>
+<%= render "band_setup_photo" %>
<%= render "feed" %>
<%= render "bands" %>
<%= render "musicians" %>
@@ -141,6 +142,9 @@
var bandSetupScreen = new JK.BandSetupScreen(JK.app);
bandSetupScreen.initialize(invitationDialog, friendSelectorDialog);
+ var bandSetupPhotoScreen = new JK.BandSetupPhotoScreen(JK.app);
+ bandSetupPhotoScreen.initialize();
+
var findSessionScreen = new JK.FindSessionScreen(JK.app);
var sessionLatency = null;
if ("jamClient" in window) {
@@ -151,6 +155,9 @@
var findMusicianScreen = new JK.FindMusicianScreen(JK.app);
findMusicianScreen.initialize();
+ var findBandScreen = new JK.FindBandScreen(JK.app);
+ findBandScreen.initialize();
+
var sessionScreen = new JK.SessionScreen(JK.app);
sessionScreen.initialize();
var sessionSettingsDialog = new JK.SessionSettingsDialog(JK.app, sessionScreen);
diff --git a/web/app/views/corps/news.html.erb b/web/app/views/corps/news.html.erb
index 5160df07c..4c7d4cdf4 100644
--- a/web/app/views/corps/news.html.erb
+++ b/web/app/views/corps/news.html.erb
@@ -2,15 +2,15 @@
<% provide(:purpose, 'news') %>
News
-August 27, 2013 -- Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. READ MORE �
+August 27, 2013 -- Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. READ MORE »
-August 15, 2013 -- Aliquam et nisl vel ligula consectetuer suscipit. Morbi euismod enim eget neque. Donec sagittis massa. Vestibulum quis augue sit amet ipsum laoreet pretium. Nulla facilisi. READ MORE �
+August 15, 2013 -- Aliquam et nisl vel ligula consectetuer suscipit. Morbi euismod enim eget neque. Donec sagittis massa. Vestibulum quis augue sit amet ipsum laoreet pretium. Nulla facilisi. READ MORE »
-August 2, 2013 -- Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. READ MORE �
+August 2, 2013 -- Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. READ MORE »
-July 12, 2013 -- Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. READ MORE �
+July 12, 2013 -- Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. READ MORE »
-July 7, 2013 -- Aliquam et nisl vel ligula consectetuer suscipit. Morbi euismod enim eget neque. Donec sagittis massa. Vestibulum quis augue sit amet ipsum laoreet pretium. Nulla facilisi. READ MORE �
+July 7, 2013 -- Aliquam et nisl vel ligula consectetuer suscipit. Morbi euismod enim eget neque. Donec sagittis massa. Vestibulum quis augue sit amet ipsum laoreet pretium. Nulla facilisi. READ MORE »
diff --git a/web/app/views/corps/terms.html.erb b/web/app/views/corps/terms.html.erb
index 17c00b04e..2a345a72c 100644
--- a/web/app/views/corps/terms.html.erb
+++ b/web/app/views/corps/terms.html.erb
@@ -459,7 +459,7 @@
discover Content that infringes any or violates any of your other rights, which you believe is defamatory,
pornographic, obscene, racist or otherwise liable to cause widespread offence, or which constitutes impersonation,
harassment, spam or otherwise violates these Terms of Service or applicable law, please
- report this to us at legal@jamkazam.com .
+ report this to us at legal@jamkazam.com .
diff --git a/web/app/views/users/_user_dropdown.html.erb b/web/app/views/users/_user_dropdown.html.erb
index ef6b4eed9..558e8d25c 100644
--- a/web/app/views/users/_user_dropdown.html.erb
+++ b/web/app/views/users/_user_dropdown.html.erb
@@ -18,8 +18,10 @@
<%= link_to "Profile", '/client#/account/profile' %>
- <%= link_to "Audio Gear", '/client#/account/audio' %>
- <%= link_to "Band Setup", '/client#/band/setup' %>
+ <% if current_user && current_user.musician? %>
+ <%= link_to "Audio Gear", '/client#/account/audio' %>
+ <%= link_to "Band Setup", '/client#/band/setup' %>
+ <% end %>
\ No newline at end of file
+
diff --git a/web/config/application.rb b/web/config/application.rb
index ba172f22c..713ee2a1f 100644
--- a/web/config/application.rb
+++ b/web/config/application.rb
@@ -122,6 +122,10 @@ if defined?(Bundler)
config.aws_bucket = 'jamkazam-dev'
config.aws_bucket_public = 'jamkazam-dev-public'
config.aws_cache = '315576000'
+ config.aws_fullhost = "#{config.aws_bucket_public}.s3.amazonaws.com"
+
+ # cloudfront host
+ config.cloudfront_host = "d34f55ppvvtgi3.cloudfront.net"
# facebook keys
config.facebook_key = '468555793186398'
diff --git a/web/config/environments/development.rb b/web/config/environments/development.rb
index 35f492750..cbc4b11b9 100644
--- a/web/config/environments/development.rb
+++ b/web/config/environments/development.rb
@@ -45,6 +45,9 @@ SampleApp::Application.configure do
TEST_CONNECT_STATES = false
+ # Overloaded value to match production for using cloudfront in dev mode
+ config.cloudfront_host = "d48bcgsnmsm6a.cloudfront.net"
+
# this is totally awful and silly; the reason this exists is so that if you upload an artifact
# through jam-admin, then jam-web can point users at it. I think 99% of devs won't even see or care about this config, and 0% of users
config.jam_admin_root_url = 'http://192.168.1.152:3333'
diff --git a/web/config/environments/production.rb b/web/config/environments/production.rb
index f4328abb5..61a091e10 100644
--- a/web/config/environments/production.rb
+++ b/web/config/environments/production.rb
@@ -76,6 +76,10 @@ SampleApp::Application.configure do
config.aws_bucket = 'jamkazam'
config.aws_bucket_public = 'jamkazam-public'
+ config.aws_fullhost = "#{config.aws_bucket_public}.s3.amazonaws.com"
+
+ # Dev cloudfront hostname
+ config.cloudfront_host = "d34f55ppvvtgi3.cloudfront.net"
# filepicker app configured to use S3 bucket jamkazam
config.filepicker_rails.api_key = "AhUoVoBZSLirP3esyCl7Zz"
diff --git a/web/config/routes.rb b/web/config/routes.rb
index 502796fcd..1bfb079dd 100644
--- a/web/config/routes.rb
+++ b/web/config/routes.rb
@@ -204,6 +204,11 @@ SampleApp::Application.routes.draw do
match '/bands' => 'api_bands#create', :via => :post
match '/bands/:id' => 'api_bands#update', :via => :post
+ # photo
+ match '/bands/:id/photo' => 'api_bands#update_photo', :via => :post
+ match '/bands/:id/photo' => 'api_bands#delete_photo', :via => :delete
+ match '/bands/:id/filepicker_policy' => 'api_bands#generate_filepicker_policy', :via => :get
+
# band members
match '/bands/:id/musicians' => 'api_bands#musician_index', :via => :get
match '/bands/:id/musicians' => 'api_bands#musician_create', :via => :post
@@ -259,6 +264,7 @@ SampleApp::Application.routes.draw do
match '/regions' => 'api_maxmind_requests#regions', :via => :get
match '/cities' => 'api_maxmind_requests#cities', :via => :get
match '/isps' => 'api_maxmind_requests#isps', :via => :get
+ match '/resolved_location' => 'api_maxmind_requests#resolved_location', :via => :get
# Recordings
diff --git a/web/lib/tasks/sample_data.rake b/web/lib/tasks/sample_data.rake
index 60fe3d33a..4aaebfc62 100644
--- a/web/lib/tasks/sample_data.rake
+++ b/web/lib/tasks/sample_data.rake
@@ -27,5 +27,160 @@ namespace :db do
DatabaseCleaner.start
DatabaseCleaner.clean
end
+
+ task populate_friends: :environment do
+ make_friends
+ end
+
+ task populate_bands: :environment do
+ make_bands
+ end
+
+ task populate_band_members: :environment do
+ make_band_members
+ end
+
+ task populate_band_genres: :environment do
+ make_band_genres
+ end
+
+ desc "Fill database with music session sample data"
+ task populate_music_sessions: :environment do
+ make_users(10) if 14 > User.count
+ make_bands if 0==Band.count
+ make_music_sessions_history
+ make_music_sessions_user_history
+ end
end
+def make_music_sessions_history
+ users = User.all.map(&:id)
+ bands = Band.all.map(&:id)
+ genres = Genre.all.map(&:description)
+ 50.times do |nn|
+ obj = MusicSessionHistory.new
+ obj.music_session_id = rand(100000000).to_s
+ obj.description = Faker::Lorem.paragraph
+ obj.user_id = users[rand(users.count)]
+ obj.band_id = bands[rand(bands.count)]
+ obj.created_at = Time.now - rand(1.month.seconds)
+ obj.session_removed_at = obj.created_at + (rand(3)+1).hour
+ obj.genres = genres.shuffle[0..rand(4)].join(' | ')
+ obj.save!
+ end
+end
+
+def make_music_sessions_user_history
+ users = User.all.map(&:id)
+ hists = MusicSessionHistory.all
+ hists.each do |msh|
+ (rand(9)+1).times do |nn|
+ obj = MusicSessionUserHistory.new
+ obj.music_session_id = msh.music_session_id
+ obj.user_id = users[rand(users.count)]
+ obj.created_at = msh.created_at
+ obj.session_removed_at = obj.created_at + (rand(3)+1).hour
+ obj.client_id = rand(100000000).to_s
+ obj.save!
+ end
+ end
+end
+
+def make_band_members
+ Band.find_each do |bb|
+ User.order('RANDOM()').limit(4).each do |uu|
+ BandMusician.create!({:user_id => uu.id, :band_id => bb.id})
+ end
+ end
+end
+
+def make_band_genres
+ Band.find_each do |bb|
+ next if bb.genres.present?
+ Genre.order('RANDOM()').limit(rand(3)+1).each do |gg|
+ bb.genres << gg
+ end
+ end
+end
+
+def make_bands
+ 10.times do |nn|
+ name = Faker::Name.name
+ website = Faker::Internet.url
+ biography = Faker::Lorem.sentence
+ city = 'Austin' # Faker::Address.city
+ state = 'TX' # Faker::Address.state_abbr
+ country = 'US'
+
+ bb = Band.new(
+ name: name,
+ website: website,
+ biography: biography,
+ city: city,
+ state: state,
+ country: country,
+ )
+ begin
+ bb.save!
+ rescue
+ puts $!.to_s + ' ' + bb.errors.inspect
+ end
+
+ end
+end
+
+def make_users(num=99)
+ admin = User.create!( first_name: Faker::Name.name,
+ last_name: Faker::Name.name,
+ email: "example@railstutorial.org",
+ password: "foobar",
+ password_confirmation: "foobar",
+ terms_of_service: true)
+ admin.toggle!(:admin)
+ num.times do |n|
+ email = "example-#{n+1}@railstutorial.org"
+ password = "password"
+ User.create!(first_name: Faker::Name.name,
+ last_name: Faker::Name.name,
+ terms_of_service: true,
+ email: email,
+ password: password,
+ password_confirmation: password)
+ end
+end
+
+def make_microposts
+ users = User.all(limit: 6)
+ 50.times do
+ content = Faker::Lorem.sentence(5)
+ users.each { |user| user.microposts.create!(content: content) }
+ end
+end
+
+def make_relationships
+ users = User.all
+ user = users.first
+ followed_users = users[2..50]
+ followers = users[3..40]
+ followed_users.each { |followed| user.followings << followed }
+ followers.each { |follower| follower.follow!(user) }
+end
+
+def make_followings
+ users = User.all
+ users.each do |uu|
+ users[0..rand(users.count)].shuffle.each do |uuu|
+ uuu.followings << uu unless 0 < UserFollowing.where(:user_id => uu.id, :follower_id => uuu.id).count
+ uu.followings << uuu unless 0 < UserFollowing.where(:user_id => uuu.id, :follower_id => uu.id).count if rand(3)==0
+ end
+ end
+end
+
+def make_friends
+ users = User.all
+ users[6..-1].each do |uu|
+ users[0..5].shuffle.each do |uuu|
+ Friendship.save(uu.id, uuu.id)
+ end
+ end
+end
diff --git a/web/spec/features/bands_spec.rb b/web/spec/features/bands_spec.rb
new file mode 100644
index 000000000..898df6a02
--- /dev/null
+++ b/web/spec/features/bands_spec.rb
@@ -0,0 +1,33 @@
+require 'spec_helper'
+
+describe "Bands", :js => true, :type => :feature, :capybara_feature => true do
+
+ subject { page }
+
+ before(:all) do
+ Capybara.javascript_driver = :poltergeist
+ Capybara.current_driver = Capybara.javascript_driver
+ Capybara.default_wait_time = 15
+ end
+
+ let(:user) { FactoryGirl.create(:user) }
+ let(:finder) { FactoryGirl.create(:user) }
+
+ before(:each) do
+ UserMailer.deliveries.clear
+ end
+
+ it "band setup is accessible through profile page" do
+ sign_in_poltergeist(user)
+ wait_until_curtain_gone
+ find('div.homecard.profile').trigger(:click)
+ wait_for_ajax
+ find('#profile-bands-link').trigger(:click)
+ wait_for_ajax
+ find('#band-setup-link').trigger(:click)
+ expect(page).to have_selector('#band-setup-title')
+ end
+
+end
+
+
diff --git a/web/spec/features/in_session_spec.rb b/web/spec/features/in_session_spec.rb
index 5d8a1ee38..709777af8 100644
--- a/web/spec/features/in_session_spec.rb
+++ b/web/spec/features/in_session_spec.rb
@@ -21,14 +21,17 @@ describe "In a Session", :js => true, :type => :feature, :capybara_feature => tr
it "can't see a private session until it is made public", :slow => true do
create_session(user, description = "Public or private, I cant decide!")
- set_session_as_private(user)
+ in_client(user) do
+ set_session_as_private
+ end
in_client(finder) do
sign_in_poltergeist finder
visit "/client#/findSession"
expect(page).to have_selector('#sessions-none-found') # verify private session is not found
end
-
- set_session_as_public(user)
+ in_client(user) do
+ set_session_as_public
+ end
join_session(finder, description) # verify the public session is able to be joined
end
@@ -57,11 +60,38 @@ describe "In a Session", :js => true, :type => :feature, :capybara_feature => tr
in_client(finder) { expect(page).to_not have_selector('div.track-label', text: user.name) }
end
- #it "can see all tracks with four users", :slow => true do
- # others = Array.new
- # 3.times { others.push FactoryGirl.create(:user) }
- # create_join_session(user, others)
- # assert_all_tracks_seen(others.push user)
- #end
+ many = 4
+
+ it "can see all tracks with #{many} users in a session", :slow => true do
+ others = Array.new
+ (many-1).times { others.push FactoryGirl.create(:user) }
+ create_join_session(user, others)
+ assert_all_tracks_seen(others.push user)
+ #in_client(others[0]) {page.save_screenshot('tmp/partys_all_here_now.png')}
+ end
+
+ it "a user can change the genre and the change will be seen by another participant" do
+ pending "...it doesn't work this way, but i will reuse this pattern"
+ create_join_session(user, [finder])
+ in_client(user) do
+ @new_genre = change_session_genre
+ end
+ in_client(finder) do
+ expect(get_session_genre).to include(@new_genre)
+ end
+ end
+
+ it "a user can change the genre and the Find Session screen will be updated" do
+ create_session(user)
+ in_client(finder) { sign_in_poltergeist finder }
+ 2.times do
+ in_client(user) do
+ @new_genre = change_session_genre #randomizes it
+ end
+ in_client(finder) do
+ find_session_contains?(@new_genre)
+ end
+ end
+ end
end
diff --git a/web/spec/features/musician_search_spec.rb b/web/spec/features/musician_search_spec.rb
index b2ce07802..e7c29d7aa 100644
--- a/web/spec/features/musician_search_spec.rb
+++ b/web/spec/features/musician_search_spec.rb
@@ -24,14 +24,12 @@ describe "Musician Search", :js => true, :type => :feature, :capybara_feature =>
end
it "shows submits query" do
- find("a#btn-refresh-musicians").trigger(:click)
expect(page).to have_selector('#musician-filter-results .musician-list-result')
end
it "shows blank result set" do
- expect(page).to have_selector('#instrument')
- find('#instrument').find(:xpath, 'option[2]').select_option
- find("a#btn-refresh-musicians").trigger(:click)
+ expect(page).to have_selector('#musician_instrument')
+ find('#musician_instrument').find(:xpath, 'option[2]').select_option
expect(page).to_not have_selector('#musician-filter-results .musician-list-result')
end
diff --git a/web/spec/features/recordings_spec.rb b/web/spec/features/recordings_spec.rb
index dda0de29d..b37891118 100644
--- a/web/spec/features/recordings_spec.rb
+++ b/web/spec/features/recordings_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe "Find Session", :js => true, :type => :feature, :capybara_feature => true, :slow => true do
+describe "Session Recordings", :js => true, :type => :feature, :capybara_feature => true, :slow => true do
subject { page }
diff --git a/web/spec/requests/musician_search_api_spec.rb b/web/spec/requests/musician_search_api_spec.rb
index 11680a2a5..a48a1c6b1 100644
--- a/web/spec/requests/musician_search_api_spec.rb
+++ b/web/spec/requests/musician_search_api_spec.rb
@@ -29,7 +29,7 @@ describe "Musician Search API", :type => :api do
it "default search" do
get_query
good_response
- expect(json['musicians'].count).to be [Search::M_PER_PAGE, User.musicians_geocoded.count].min
+ expect(json['musicians'].count).to be [Search::M_PER_PAGE, User.musicians.count].min
end
context 'location filtering' do
diff --git a/web/spec/support/utilities.rb b/web/spec/support/utilities.rb
index 7c8134e78..38e2467e3 100644
--- a/web/spec/support/utilities.rb
+++ b/web/spec/support/utilities.rb
@@ -125,7 +125,7 @@ end
# this code assumes that there are no music sessions in the database. it should fail on the
-# find('.join-link') call if > 1 session exists because capybara will complain of multile matches
+# find('.join-link') call if > 1 session exists because capybara will complain of multiple matches
def join_session(joiner, unique_session_desc)
in_client(joiner) do
@@ -141,6 +141,7 @@ def join_session(joiner, unique_session_desc)
end
end
+
def create_join_session(creator, joiners=[])
creator, unique_session_desc = create_session(creator)
@@ -151,26 +152,61 @@ def create_join_session(creator, joiners=[])
end
-def set_session_as_private(session_owner)
- in_client(session_owner) do
- find('#session-settings-button').trigger(:click)
- within('#session-settings-dialog') do
+def set_session_as_private()
+ find('#session-settings-button').trigger(:click)
+ within('#session-settings-dialog') do
select('Private', :from => 'session-settings-musician-access')
find('#session-settings-dialog-submit').trigger(:click)
- end
end
end
-def set_session_as_public(session_owner)
- in_client(session_owner) do
- find('#session-settings-button').trigger(:click)
- within('#session-settings-dialog') do
- select('Public', :from => 'session-settings-musician-access')
- find('#session-settings-dialog-submit').trigger(:click)
- end
+def set_session_as_public()
+ find('#session-settings-button').trigger(:click)
+ within('#session-settings-dialog') do
+ select('Public', :from => 'session-settings-musician-access')
+ find('#session-settings-dialog-submit').trigger(:click)
end
end
+def get_options(selector)
+ return find(selector).all('option').collect(&:text).uniq
+end
+
+def selected_genres
+ return page.evaluate_script("JK.GenreSelectorHelper.getSelectedGenres('#session-settings-genre')")
+end
+
+def change_session_genre #randomly just change it
+ here = 'select.genre-list'
+ #wait_for_ajax
+ find('#session-settings-button').trigger(:click)
+ within('#session-settings-dialog') do
+ wait_for_ajax
+ @new_genre = get_options(here).-(["Select Genre"]).-(selected_genres).sample.to_s
+ select(@new_genre, :from => 'genres')
+ wait_for_ajax
+ find('#session-settings-dialog-submit').trigger(:click)
+ end
+ return @new_genre
+end
+
+def get_session_genre
+ here = 'select.genre-list'
+ find('#session-settings-button').trigger(:click)
+ wait_for_ajax
+ @current_genres = selected_genres
+ find('#session-settings-dialog-submit').trigger(:click)
+ return @current_genres.join(" ")
+end
+
+def find_session_contains?(text)
+ visit "/client#/findSession"
+ wait_for_ajax
+ within('#find-session-form') do
+ expect(page).to have_text(text)
+ end
+end
+
def assert_all_tracks_seen(users=[])
users.each do |user|
in_client(user) do