Merge remote-tracking branch 'origin/develop' into develop
This commit is contained in:
commit
f442196f8d
|
|
@ -78,4 +78,5 @@ add_user_bio.sql
|
|||
users_geocoding.sql
|
||||
recordings_public_launch.sql
|
||||
notification_band_invite.sql
|
||||
band_photo_filepicker.sql
|
||||
band_photo_filepicker.sql
|
||||
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';
|
||||
|
|
@ -2,8 +2,8 @@ module JamRuby
|
|||
class Band < ActiveRecord::Base
|
||||
|
||||
attr_accessible :name, :website, :biography, :city, :state,
|
||||
:country, :original_fpfile_photo, :cropped_fpfile_photo,
|
||||
:cropped_s3_path_photo, :crop_selection_photo, :photo_url
|
||||
:country, :original_fpfile_photo, :cropped_fpfile_photo,
|
||||
:cropped_s3_path_photo, :crop_selection_photo, :photo_url
|
||||
|
||||
attr_accessor :updating_photo
|
||||
|
||||
|
|
@ -13,6 +13,8 @@ module JamRuby
|
|||
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"
|
||||
|
|
@ -40,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
|
||||
|
|
@ -96,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
|
||||
|
|
@ -125,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?
|
||||
|
|
@ -139,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)
|
||||
|
|
@ -168,35 +172,28 @@ 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
|
||||
|
|
@ -207,61 +204,83 @@ module JamRuby
|
|||
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)
|
||||
)
|
||||
: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.nil?
|
||||
S3Util.delete(aws_bucket, File.dirname(self.cropped_s3_path) + '/cropped.jpg')
|
||||
S3Util.delete(aws_bucket, self.cropped_s3_path)
|
||||
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
|
||||
|
||||
return self.update_attributes(
|
||||
:original_fpfile_photo => nil,
|
||||
:cropped_fpfile_photo => nil,
|
||||
:cropped_s3_path_photo => nil,
|
||||
:crop_selection_photo => nil,
|
||||
:photo_url => nil
|
||||
)
|
||||
:original_fpfile_photo => nil,
|
||||
:cropped_fpfile_photo => nil,
|
||||
:cropped_s3_path_photo => nil,
|
||||
:crop_selection_photo => nil,
|
||||
:photo_url => nil
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
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
|
||||
def self.validate_genres(genres, is_nil_ok)
|
||||
if is_nil_ok && genres.nil?
|
||||
return
|
||||
end
|
||||
|
||||
if genres.nil?
|
||||
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
|
||||
else
|
||||
if genres.size < Limits::MIN_GENRES_PER_BAND
|
||||
raise JamRuby::JamArgumentError, ValidationMessages::GENRE_MINIMUM_NOT_MET
|
||||
end
|
||||
end
|
||||
|
||||
if genres.size > Limits::MAX_GENRES_PER_BAND
|
||||
raise JamRuby::JamArgumentError, ValidationMessages::GENRE_LIMIT_EXCEEDED
|
||||
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
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -229,8 +229,8 @@
|
|||
userNames = [];
|
||||
userIds = [];
|
||||
userPhotoUrls = [];
|
||||
//bandId = "1158c8b6-4c92-47dc-82bf-1e390c4f9b2c";
|
||||
bandId = $("#hdn-band-id").val();
|
||||
bandId = "1158c8b6-4c92-47dc-82bf-1e390c4f9b2c";
|
||||
//bandId = $("#hdn-band-id").val();
|
||||
resetForm();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,228 @@
|
|||
(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 = '';
|
||||
/*for (var jj=0, ilen=bb['instruments'].length; jj<ilen; jj++) {
|
||||
if (bb['instruments'][jj].instrument_id in instrument_logo_map) {
|
||||
instr = instrument_logo_map[bb['instruments'][jj].instrument_id];
|
||||
}
|
||||
instr_logos += '<img src="' + instr + '" width="24" height="24" /> ';
|
||||
}*/
|
||||
players = '';
|
||||
playerVals = {};
|
||||
for (var jj=0, ilen=bb['players'].length; jj<ilen; jj++) {
|
||||
aPlayer = bb['players'][jj];
|
||||
var player_instrs = '';
|
||||
/*for (var kk=0, klen=aPlayer['instruments'].length; kk<klen; kk++) {
|
||||
var pinstr = aPlayer['instruments'][kk];
|
||||
if (pinstr.instrument_id in instrument_logo_map) {
|
||||
instr = instrument_logo_map[pinstr.instrument_id];
|
||||
}
|
||||
player_instrs += '<img src="' + instr + '" width="24" height="24" /> ';
|
||||
}*/
|
||||
|
||||
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);
|
||||
|
||||
bVals = {
|
||||
avatar_url: context.JK.resolveAvatarUrl(bb.photo_url),
|
||||
profile_url: "/#/profile/" + bb.id,
|
||||
band_name: bb.name,
|
||||
band_location: bb.city + ', ' + bb.state,
|
||||
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_follow_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.user_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.user_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);
|
||||
|
|
@ -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 + '&';
|
||||
}
|
||||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -56,20 +56,9 @@
|
|||
}
|
||||
|
||||
.query-distance-params {
|
||||
float:left;
|
||||
width:50px;
|
||||
float: left;
|
||||
width: 80px;
|
||||
margin-left: 10px;
|
||||
-webkit-border-radius: 6px;
|
||||
border-radius: 6px;
|
||||
background-color:$ColorTextBoxBackground;
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -197,9 +197,9 @@ class ApiBandsController < ApiController
|
|||
@band.update_photo(original_fpfile, cropped_fpfile, crop_selection, Rails.application.config.aws_bucket_public)
|
||||
|
||||
if @band.errors.any?
|
||||
respond_with @band, status: :unprocessable_entity
|
||||
render :json => { :message => "Unexpected error updating photo."}, :status => :unprocessable_entity
|
||||
else
|
||||
respond_with @band, responder: ApiResponder, status: 200
|
||||
render :json => {}, :status => :ok
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -207,9 +207,9 @@ class ApiBandsController < ApiController
|
|||
@band.delete_photo(Rails.application.config.aws_bucket_public)
|
||||
|
||||
if @band.errors.any?
|
||||
respond_with @band, status: :unprocessable_entity
|
||||
render :json => { :message => "Unexpected error deleting photo."}, :status => :unprocessable_entity
|
||||
else
|
||||
respond_with @band, responder: ApiResponder, status: 204
|
||||
render :json => {}, :status => :ok
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 => :genre 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
|
||||
|
|
|
|||
|
|
@ -1,13 +1,61 @@
|
|||
<!-- Band Screen -->
|
||||
<div layout="screen" layout-id="bands" class="screen secondary">
|
||||
<div class="content-head">
|
||||
<%= 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 -%>
|
||||
<%= 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 => 'content-wrapper band-wrapper') %>
|
||||
<% end -%>
|
||||
<% end -%>
|
||||
<% end -%>
|
||||
<% end -%>
|
||||
|
||||
<div class="content-icon">
|
||||
<%= image_tag "content/icon_bands.png", {:height => 19, :width => 19} %>
|
||||
</div>
|
||||
|
||||
<h1>bands</h1>
|
||||
<%= render "screen_navigation" %>
|
||||
<!-- Session Row Template -->
|
||||
<script type="text/template" id="template-find-band-row">
|
||||
<div class="profile-band-list-result band-list-result">
|
||||
<div style="float:left">
|
||||
<!-- avatar -->
|
||||
<div class="avatar-small"><img src="{avatar_url}" /></div>
|
||||
|
||||
<!-- name & location -->
|
||||
<div style="width:220px;" class="result-name">{band_name}<br />
|
||||
<span class="result-location">{band_location}
|
||||
<br /><br />
|
||||
<div id="result_instruments" class="nowrap">{instruments}</div>
|
||||
<br clear="all" /><br />
|
||||
{follow_count} <img src="../assets/content/icon_followers.png" width="22" height="12" align="absmiddle" /> {recording_count} <img src="../assets/content/icon_recordings.png" width="12" height="13" align="absmiddle" /> {session_count} <img src="../assets/content/icon_session_tiny.png" width="12" height="12" align="absmiddle" /></span><br /><br />
|
||||
</div>
|
||||
</div>
|
||||
<p>This feature not yet implemented</p>
|
||||
</div>
|
||||
<div class="left ml35 f11 whitespace w40"><br />
|
||||
{biography}<br />
|
||||
<br />
|
||||
<div data-band-id={band_id}>
|
||||
{band_action_template}
|
||||
</div>
|
||||
</div>
|
||||
<div class="left ml10 w25 band-players">
|
||||
<br />
|
||||
<small><strong>FOLLOWING:</strong></small>
|
||||
<table class="musicians" cellpadding="0" cellspacing="5">{band_follow_template}</table>
|
||||
</div>
|
||||
<br clear="all" />
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/template" id="template-band-action-btns">
|
||||
<a href="{profile_url}" class="button-orange smallbutton m0">PROFILE</a><a href="#" class="{button_follow} smallbutton search-m-follow">FOLLOW</a>
|
||||
</script>
|
||||
|
||||
<script type="text/template" id="template-band-player-info">
|
||||
<tr>
|
||||
<td width="24"><a href="{profile_url}" class="avatar-tiny"><img src="{avatar_url}" /></a></td>
|
||||
<td><a href="{profile_url}"><strong>{player_name}</strong></a></td>
|
||||
<td>{player_instruments}</td>
|
||||
</tr>
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -7,29 +7,19 @@
|
|||
<%= content_tag(:div, :class => 'filter-element') do -%>
|
||||
<!-- instrument filter -->
|
||||
<%= 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'} ) %>
|
||||
<%= content_tag(:div, :class => 'filter-element') do -%>
|
||||
<%= select_tag(:musician_instrument,
|
||||
options_for_select([['Any', '']].concat(JamRuby::Instrument.all.collect { |ii| [ii.description, ii.id] }))) %>
|
||||
<% end -%>
|
||||
<% end -%>
|
||||
<!-- distance filter -->
|
||||
<%= 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) %>
|
||||
<%= 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 => 'right mr10') %>
|
||||
<% end -%>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<%= 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, 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 -%>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
<% filter_label = defined?(search_type) && search_type == Search::PARAM_BAND ? :band : :musician %>
|
||||
<%= 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;") %>
|
||||
<!-- order by filter -->
|
||||
<%= select_tag("#{filter_label}_order_by", options_for_select(Search::ORDERINGS), {:class => "#{filter_label}-order-by"} ) %>
|
||||
<% end -%>
|
||||
<%= content_tag(:div, :class => 'filter-element') do -%>
|
||||
<% if :musician == filter_label %>
|
||||
<!-- instrument filter -->
|
||||
<%= content_tag(:div, 'Instrument:', :class => 'filter-element') %>
|
||||
<%= content_tag(:div, :class => 'filter-element') do -%>
|
||||
<%= select_tag("#{filter_label}_instrument",
|
||||
options_for_select([['Any', '']].concat(JamRuby::Instrument.all.collect { |ii| [ii.description, ii.id] }))) %>
|
||||
<% end -%>
|
||||
<% elsif :band == filter_label %>
|
||||
<!-- genre filter -->
|
||||
<%= content_tag(:div, 'Genre:', :class => 'filter-element') %>
|
||||
<%= content_tag(:div, :class => 'filter-element') do -%>
|
||||
<%= select_tag("#{filter_label}_genre",
|
||||
options_for_select([['Any', '']].concat(JamRuby::Genre.all.collect { |ii| [ii.description, ii.id] }))) %>
|
||||
<% end -%>
|
||||
<% end %>
|
||||
<% end -%>
|
||||
<!-- distance filter -->
|
||||
<%= content_tag(:div, :class => 'filter-element') do -%>
|
||||
<%= content_tag(:div, 'Within', :class => 'filter-element') %>
|
||||
<%= 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') do -%>
|
||||
miles of <%= content_tag(:span, current_user.current_city(request.remote_ip), :id => "#{filter_label}-filter-city") %>
|
||||
<% end -%>
|
||||
<% end -%>
|
||||
<% end -%>
|
||||
|
|
@ -155,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);
|
||||
|
|
|
|||
|
|
@ -14,6 +14,14 @@ namespace :db do
|
|||
make_friends
|
||||
end
|
||||
|
||||
task populate_bands: :environment do
|
||||
make_bands
|
||||
end
|
||||
|
||||
task populate_band_members: :environment do
|
||||
make_band_members
|
||||
end
|
||||
|
||||
desc "Fill database with music session sample data"
|
||||
task populate_music_sessions: :environment do
|
||||
make_users(10) if 14 > User.count
|
||||
|
|
@ -56,16 +64,24 @@ def make_music_sessions_user_history
|
|||
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_bands
|
||||
10.times do |nn|
|
||||
name = Faker::Name.name
|
||||
website = Faker::Internet.url
|
||||
biography = Faker::Lorem.sentence
|
||||
city = Faker::Address.city
|
||||
state = Faker::Address.state_abbr
|
||||
country = Faker::Address.country
|
||||
city = 'Austin' # Faker::Address.city
|
||||
state = 'TX' # Faker::Address.state_abbr
|
||||
country = 'US'
|
||||
|
||||
Band.create!(
|
||||
bb = Band.new(
|
||||
name: name,
|
||||
website: website,
|
||||
biography: biography,
|
||||
|
|
@ -73,6 +89,11 @@ def make_bands
|
|||
state: state,
|
||||
country: country,
|
||||
)
|
||||
begin
|
||||
bb.save!
|
||||
rescue
|
||||
puts $!.to_s + ' ' + bb.errors.inspect
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue