Merge with develop
This commit is contained in:
commit
6edb4b6012
|
|
@ -5,9 +5,14 @@ ActiveAdmin.register JamRuby::JamTrack, :as => 'JamTracks' do
|
|||
config.sort_order = 'name_asc'
|
||||
config.batch_actions = false
|
||||
|
||||
filter :genre
|
||||
filter :genres
|
||||
filter :status, :as => :select, collection: JamRuby::JamTrack::STATUS
|
||||
|
||||
scope("Default", default: true) { |scope| scope }
|
||||
scope("Onboarding TODO") { |scope| scope.where('onboarding_exceptions is not null') }
|
||||
scope("Tency Only") { |scope| scope.joins('INNER JOIN jam_track_licensors as licensors ON jam_tracks.licensor_id = licensors.id').where("licensors.name = 'Tency Music'") }
|
||||
scope("Onboarding TODO w/ Tency Only") { |scope| scope.joins('INNER JOIN jam_track_licensors as licensors ON jam_tracks.licensor_id = licensors.id').where("licensors.name = 'Tency Music'").where('onboarding_exceptions is not null') }
|
||||
|
||||
form :partial => 'form'
|
||||
|
||||
index do
|
||||
|
|
@ -24,11 +29,21 @@ ActiveAdmin.register JamRuby::JamTrack, :as => 'JamTracks' do
|
|||
|
||||
column :original_artist
|
||||
column :name
|
||||
column :onboarding_flags do |jam_track| jam_track.onboard_warnings end
|
||||
column :onboarding_exceptions do |jam_track|
|
||||
if jam_track.onboarding_exceptions
|
||||
exceptions = JSON.parse(jam_track.onboarding_exceptions)
|
||||
exceptions.keys.join(',')
|
||||
else
|
||||
''
|
||||
end
|
||||
|
||||
end
|
||||
column :status
|
||||
column :master_track do |jam_track| jam_track.master_track.nil? ? 'None' : (link_to "Download", jam_track.master_track.url_by_sample_rate(44)) end
|
||||
column :licensor
|
||||
column :genre
|
||||
column :genres do |jam_track|
|
||||
jam_track.genres.map(&:description).join(',')
|
||||
end
|
||||
column :price
|
||||
column :reproduction_royalty
|
||||
column :public_performance_royalty
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
= f.input :songwriter, :input_html => { :rows=>1, :maxlength=>1000 }
|
||||
= f.input :publisher, :input_html => { :rows=>1, :maxlength=>1000 }
|
||||
= f.input :licensor, collection: JamRuby::JamTrackLicensor.all, include_blank: true
|
||||
= f.input :genre, collection: JamRuby::Genre.all, include_blank: false
|
||||
= f.input :genres
|
||||
= f.input :duration, hint: 'this should rarely need editing because it comes from the import process'
|
||||
= f.input :sales_region, collection: JamRuby::JamTrack::SALES_REGION, include_blank: false
|
||||
= f.input :price, :required => true, :input_html => {type: 'numeric'}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ class JamRuby::JamTrack
|
|||
end
|
||||
|
||||
def jmep_json_generate
|
||||
self.genre_id = nil if self.genre_id == ''
|
||||
self.licensor_id = nil if self.licensor_id == ''
|
||||
self.jmep_json = nil if self.jmep_json == ''
|
||||
self.time_signature = nil if self.time_signature == ''
|
||||
|
|
|
|||
|
|
@ -299,3 +299,5 @@ enhance_band_profile.sql
|
|||
alter_band_profile_rate_defaults.sql
|
||||
repair_band_profile.sql
|
||||
profile_teacher.sql
|
||||
jam_track_onboarding_enhancements.sql
|
||||
jam_track_name_drop_unique.sql
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
ALTER TABLE jam_tracks DROP CONSTRAINT jam_tracks_name_key;
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
-- "rsvp_slots_instrument_id_fkey" FOREIGN KEY (instrument_id) REFERENCES instruments(id)
|
||||
-- "musicians_instruments_instrument_id_fkey" FOREIGN KEY (instrument_id) REFERENCES instruments(id) ON DELETE CASCADE
|
||||
-- "saved_tracks_instrument_id_fkey" FOREIGN KEY (instrument_id) REFERENCES instruments(id) ON DELETE CASCADE
|
||||
ALTER TABLE rsvp_slots DROP CONSTRAINT rsvp_slots_instrument_id_fkey;
|
||||
ALTER TABLE musicians_instruments DROP CONSTRAINT musicians_instruments_instrument_id_fkey;
|
||||
ALTER TABLE recorded_tracks DROP CONSTRAINT saved_tracks_instrument_id_fkey;
|
||||
UPDATE instruments SET id = 'double bass', description = 'Double Bass' WHERE id = 'upright bass';
|
||||
UPDATE rsvp_slots SET instrument_id = 'double bass' where instrument_id = 'upright bass';
|
||||
UPDATE musicians_instruments SET instrument_id = 'double bass' where instrument_id = 'upright bass';
|
||||
UPDATE recorded_tracks SET instrument_id = 'double bass' where instrument_id = 'upright bass';
|
||||
ALTER TABLE rsvp_slots ADD CONSTRAINT rsvp_slots_instrument_id_fkey FOREIGN KEY (instrument_id) REFERENCES instruments(id) ON DELETE SET NULL;
|
||||
ALTER TABLE musicians_instruments ADD CONSTRAINT musicians_instruments_instrument_id_fkey FOREIGN KEY (instrument_id) REFERENCES instruments(id) ON DELETE CASCADE;
|
||||
ALTER TABLE recorded_tracks ADD CONSTRAINT saved_tracks_instrument_id_fkey FOREIGN KEY (instrument_id) REFERENCES instruments(id) ON DELETE CASCADE;
|
||||
|
||||
INSERT INTO instruments (id, description, popularity) VALUES ('steel guitar', 'Steel Guitar', 1);
|
||||
INSERT INTO instruments (id, description, popularity) VALUES ('orchestra', 'Orchestra', 1);
|
||||
INSERT INTO instruments (id, description, popularity) VALUES ('glockenspiel', 'Glockenspiel', 1);
|
||||
INSERT INTO instruments (id, description, popularity) VALUES ('dobro', 'Dobro', 1);
|
||||
INSERT INTO instruments (id, description, popularity) VALUES ('harp', 'Harp', 1);
|
||||
INSERT INTO instruments (id, description, popularity) VALUES ('vocoder', 'Vocoder', 1);
|
||||
INSERT INTO instruments (id, description, popularity) VALUES ('flugelhorn', 'Flugelhorn', 1);
|
||||
INSERT INTO instruments (id, description, popularity) VALUES ('timpani', 'Timpani', 1);
|
||||
INSERT INTO instruments (id, description, popularity) VALUES ('bassoon', 'Bassoon', 1);
|
||||
INSERT INTO instruments (id, description, popularity) VALUES ('charango', 'Charango', 1);
|
||||
INSERT INTO instruments (id, description, popularity) VALUES ('theremin', 'Theremin', 1);
|
||||
INSERT INTO instruments (id, description, popularity) VALUES ('sitar', 'Sitar', 1);
|
||||
INSERT INTO instruments (id, description, popularity) VALUES ('piccolo', 'Piccolo', 1);
|
||||
INSERT INTO instruments (id, description, popularity) VALUES ('bagpipes', 'Bagpipes', 1);
|
||||
ALTER TABLE jam_tracks ADD COLUMN onboarding_exceptions JSON;
|
||||
ALTER TABLE jam_track_tracks ADD COLUMN original_filename VARCHAR;
|
||||
ALTER TABLE jam_tracks ADD COLUMN additional_info VARCHAR;
|
||||
ALTER TABLE jam_tracks ADD COLUMN language VARCHAR NOT NULL DEFAULT 'eng';
|
||||
ALTER TABLE jam_tracks ADD COLUMN year INTEGER;
|
||||
ALTER TABLE jam_tracks ADD COLUMN vendor_id VARCHAR;
|
||||
|
||||
INSERT INTO jam_track_licensors (name, description) VALUES ('Tency Music', 'Tency Music is a music production company specialized in re-recordings.');
|
||||
|
||||
CREATE TABLE genres_jam_tracks (
|
||||
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
jam_track_id VARCHAR(64) NOT NULL REFERENCES jam_tracks(id) ON DELETE CASCADE,
|
||||
genre_id VARCHAR(64) NOT NULL REFERENCES genres(id) ON DELETE CASCADE,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
INSERT INTO genres_jam_tracks (jam_track_id, genre_id) ((SELECT jam_tracks.id, jam_tracks.genre_id FROM jam_tracks));
|
||||
ALTER TABLE jam_tracks DROP COLUMN genre_id;
|
||||
|
||||
-- holds precount, click.wav, click.txt
|
||||
CREATE TABLE jam_track_files (
|
||||
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
jam_track_id VARCHAR(64) REFERENCES jam_tracks(id) ON DELETE CASCADE,
|
||||
file_type VARCHAR NOT NULL,
|
||||
original_filename VARCHAR NOT NULL,
|
||||
precount_num INTEGER,
|
||||
url VARCHAR,
|
||||
md5 VARCHAR,
|
||||
length bigint,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
INSERT INTO genres (id, description) VALUES ('soft rock', 'Soft Rock');
|
||||
INSERT INTO genres (id, description) VALUES ('rap', 'Rap');
|
||||
INSERT INTO genres (id, description) VALUES ('tv & movie soundtrack', 'TV & Movie Soundtrack');
|
||||
INSERT INTO genres (id, description) VALUES ('holiday', 'Holiday');
|
||||
INSERT INTO genres (id, description) VALUES ('kids', 'Kids');
|
||||
INSERT INTO genres (id, description) VALUES ('disco', 'Disco');
|
||||
INSERT INTO genres (id, description) VALUES ('soul', 'Soul');
|
||||
INSERT INTO genres (id, description) VALUES ('hard rock', 'Hard Rock');
|
||||
INSERT INTO genres (id, description) VALUES ('funk', 'Funk');
|
||||
INSERT INTO genres (id, description) VALUES ('dance', 'Dance');
|
||||
INSERT INTO genres (id, description) VALUES ('creole', 'Creole');
|
||||
INSERT INTO genres (id, description) VALUES ('traditional', 'Traditional');
|
||||
INSERT INTO genres (id, description) VALUES ('oldies', 'Oldies');
|
||||
INSERT INTO genres (id, description) VALUES ('world', 'World');
|
||||
INSERT INTO genres (id, description) VALUES ('musical', 'Musical');
|
||||
INSERT INTO genres (id, description) VALUES ('celtic', 'Celtic');
|
||||
|
|
@ -206,6 +206,8 @@ require "jam_ruby/models/jam_track"
|
|||
require "jam_ruby/models/jam_track_track"
|
||||
require "jam_ruby/models/jam_track_right"
|
||||
require "jam_ruby/models/jam_track_tap_in"
|
||||
require "jam_ruby/models/jam_track_file"
|
||||
require "jam_ruby/models/genre_jam_track"
|
||||
require "jam_ruby/app/mailers/async_mailer"
|
||||
require "jam_ruby/app/mailers/batch_mailer"
|
||||
require "jam_ruby/app/mailers/progress_mailer"
|
||||
|
|
@ -237,11 +239,14 @@ require "jam_ruby/jmep_manager"
|
|||
require "jam_ruby/models/performance_sample"
|
||||
require "jam_ruby/models/online_presence"
|
||||
require "jam_ruby/models/json_store"
|
||||
require "jam_ruby/models/base_search"
|
||||
require "jam_ruby/models/musician_search"
|
||||
require "jam_ruby/models/teacher"
|
||||
require "jam_ruby/models/teacher_experience"
|
||||
require "jam_ruby/models/language"
|
||||
require "jam_ruby/models/subject"
|
||||
require "jam_ruby/models/band_search"
|
||||
require "jam_ruby/import/tency_stem_mapping"
|
||||
|
||||
include Jampb
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,360 @@
|
|||
module JamRuby
|
||||
|
||||
# this is probably a one-off class used to map Tency-named stems into JamKazam-named stems
|
||||
class TencyStemMapping
|
||||
|
||||
@@log = Logging.logger[TencyStemMapping]
|
||||
|
||||
def s3_manager
|
||||
@s3_manager ||= S3Manager.new('jamkazam-tency', APP_CONFIG.aws_access_key_id, APP_CONFIG.aws_secret_access_key)
|
||||
end
|
||||
|
||||
def initialize
|
||||
@originals_folder = "/Volumes/sethcall/Dropbox/seth@jamkazam.com/JamTracks - Tency Music - Original Folder for Normalization Map"
|
||||
@mapping_folder = "/Volumes/sethcall/Dropbox/seth@jamkazam.com/JamTracks - Tency Music"
|
||||
@original_songs = {}
|
||||
@mapping_songs = {}
|
||||
@mappings = {}
|
||||
end
|
||||
|
||||
def create_map
|
||||
tency_originals
|
||||
tency_maps
|
||||
|
||||
dump
|
||||
end
|
||||
|
||||
def create_mapping_map
|
||||
tency_maps
|
||||
|
||||
dump_map
|
||||
end
|
||||
|
||||
def hydrate
|
||||
@original_songs = YAML.load_file('original_songs.yml')
|
||||
@mapping_songs = YAML.load_file('mapping_songs.yml')
|
||||
end
|
||||
|
||||
def parse_sanitized_filename(filename)
|
||||
instrument = nil
|
||||
part = nil
|
||||
|
||||
basename = File.basename(filename)
|
||||
stem = basename.index('Stem')
|
||||
|
||||
if stem
|
||||
stripped = basename[(stem + 'Stem'.length)..-5] # takes of 'stem' and '.wav'
|
||||
stripped.strip!
|
||||
dash = stripped.index('-')
|
||||
|
||||
if dash == 0
|
||||
stripped = stripped[1..-1].strip!
|
||||
# now we should have something like "Vocal - Lead" (instrument - part)
|
||||
instrument, part = stripped.split('-')
|
||||
instrument.strip! if instrument
|
||||
part.strip! if part
|
||||
else
|
||||
"no or misplaced dash for #{filename}"
|
||||
end
|
||||
|
||||
else
|
||||
raise "no stem for #{filename}"
|
||||
end
|
||||
|
||||
[instrument, part]
|
||||
end
|
||||
|
||||
# For all the tracks that I have labeled manually as
|
||||
# Instrument = Upright Bass and Part = Upright Bass,
|
||||
# can you please change both the Instrument and Part to Double Bass instead?
|
||||
#
|
||||
def check_mappings
|
||||
missing_instrument = 0
|
||||
missing_part = 0
|
||||
part_names = []
|
||||
|
||||
hydrate
|
||||
@mapping_songs.each do |cache_id, data|
|
||||
mapped_filename = data[:filename]
|
||||
@@log.debug("parsing #{mapped_filename}")
|
||||
instrument, part = parse_sanitized_filename(mapped_filename)
|
||||
@@log.debug("parsed #{instrument} (#{part})")
|
||||
missing_instrument = missing_instrument + 1 unless instrument
|
||||
missing_part = missing_part + 1 unless part
|
||||
part_names << mapped_filename unless part
|
||||
end
|
||||
|
||||
@@log.info("SUMMARY")
|
||||
@@log.info("-------")
|
||||
@@log.info("missing instruments:#{missing_instrument} missing parts: #{missing_part}")
|
||||
@@log.info("files with no parts: #{part_names}")
|
||||
|
||||
# files with no parts:
|
||||
# ["Huey Lewis And The News - Heart And Soul - 31957/Heart And Soul Stem - Synth 2.wav",
|
||||
# "ZZ Top - Tush - 20852/Tush Stem - Clicktrack.wav",
|
||||
# "Crosby Stills And Nash - Teach Your Children - 15440/Teach Your Children Stem - Bass Guitar.wav",
|
||||
# /Brad Paisley - She's Everything - 19886/She's Everything Stem - Clicktrack.wav",
|
||||
# "Toby Keith - Beer For My Horses - 7221/Beer For My Horses Stem - Lap Steel.wav",
|
||||
# Toby Keith - Beer For My Horses - 7221/Beer For My Horses Stem - Acoustic Guitar.wav"
|
||||
|
||||
end
|
||||
|
||||
def track_mapping(basename, instr_part)
|
||||
instrument = instr_part[:instrument]
|
||||
part = instr_part[:part]
|
||||
|
||||
basename.downcase!
|
||||
|
||||
info = @mappings[basename]
|
||||
|
||||
unless info
|
||||
info = {matches:[]}
|
||||
@mappings[basename] = info
|
||||
end
|
||||
|
||||
info[:matches] << instr_part
|
||||
end
|
||||
|
||||
def correlate
|
||||
mapped = 0
|
||||
unmapped = 0
|
||||
unmapped_details = []
|
||||
no_instrument = []
|
||||
common_unknown_instruments = {}
|
||||
|
||||
hydrate
|
||||
@mapping_songs.each do |cache_id, data|
|
||||
# go through each track hand-mapped, and find it's matching song if any.
|
||||
|
||||
mapped_filename = data[:filename]
|
||||
found_original = @original_songs[cache_id]
|
||||
if found_original
|
||||
# mapping made
|
||||
|
||||
original_filename = found_original[:filename]
|
||||
original_basename = File.basename(original_filename).downcase
|
||||
|
||||
mapped = mapped + 1
|
||||
|
||||
instrument, part = parse_sanitized_filename(mapped_filename)
|
||||
instr_part = JamTrackImporter.determine_instrument(instrument, part)
|
||||
|
||||
instr_part[:instrument]
|
||||
|
||||
if instr_part[:instrument]
|
||||
|
||||
# track the mapping of this one
|
||||
track_mapping(original_basename, instr_part)
|
||||
|
||||
else
|
||||
@@log.error("unable to determine instrument for #{File.basename(mapped_filename)}")
|
||||
no_instrument << ({filename: File.basename(mapped_filename), instrument: instrument, part: part})
|
||||
common_unknown_instruments["#{instrument}-(#{part})"] = 1
|
||||
end
|
||||
|
||||
else
|
||||
unmapped = unmapped + 1
|
||||
unmapped_details << {filename: mapped_filename}
|
||||
end
|
||||
end
|
||||
|
||||
puts("SUMMARY")
|
||||
puts("-------")
|
||||
puts("MAPPED:#{mapped} UNMAPPED:#{unmapped}")
|
||||
unmapped_details.each do |unmapped_detail|
|
||||
puts "UNMAPPED FILE: #{File.basename(unmapped_detail[:filename])}"
|
||||
end
|
||||
puts("UNKNOWN INSTRUMENT: #{no_instrument.length}")
|
||||
no_instrument.each do |item|
|
||||
puts("UNKNOWN INSTRUMENT: #{item[:filename]}")
|
||||
end
|
||||
common_unknown_instruments.each do |key, value|
|
||||
puts("#{key}")
|
||||
end
|
||||
@mappings.each do |basename, mapping|
|
||||
matches = mapping[:matches]
|
||||
counts = matches.each_with_object(Hash.new(0)) { |word,counts| counts[word] += 1 }
|
||||
ordered_matches = counts.sort_by {|k, v| -v}
|
||||
output = ""
|
||||
ordered_matches.each do |match|
|
||||
detail = match[0]
|
||||
count = match[1]
|
||||
output << "#{detail[:instrument]}(#{detail[:part]})/#{count}, "
|
||||
end
|
||||
|
||||
puts "map detail: #{basename}: #{output}"
|
||||
|
||||
mapping[:ordered] = ordered_matches
|
||||
mapping[:detail] = output
|
||||
end
|
||||
CSV.open("mapping.csv", "wb") do |csv|
|
||||
@mappings.each do |basename, mapping|
|
||||
item = mapping[:ordered]
|
||||
|
||||
trust_worthy = item.length == 1
|
||||
unless trust_worthy
|
||||
# if the 1st item is at least 4 'counts' more than the next item, we can consider it trust_worthy
|
||||
if item[0][1] - 4 > item[1][1]
|
||||
trust_worthy = true
|
||||
end
|
||||
end
|
||||
csv << [ basename, item[0][0][:instrument], item[0][0][:part], item[0][1], trust_worthy ]
|
||||
end
|
||||
end
|
||||
CSV.open("determinate-single-matches.csv", "wb") do |csv|
|
||||
@mappings.each do |basename, mapping|
|
||||
if mapping[:ordered].length == 1 && mapping[:ordered][0][1] == 1
|
||||
item = mapping[:ordered]
|
||||
csv << [ basename, item[0][0][:instrument], item[0][0][:part], item[0][1] ]
|
||||
end
|
||||
end
|
||||
end
|
||||
CSV.open("determinate-multi-matches.csv", "wb") do |csv|
|
||||
@mappings.each do |basename, mapping|
|
||||
if mapping[:ordered].length == 1 && mapping[:ordered][0][1] > 1
|
||||
item = mapping[:ordered]
|
||||
csv << [ basename, item[0][0][:instrument], item[0][0][:part], item[0][1] ]
|
||||
end
|
||||
end
|
||||
end
|
||||
CSV.open("ambiguous-matches.csv", "wb") do |csv|
|
||||
@mappings.each do |basename, mapping|
|
||||
if mapping[:ordered].length > 1
|
||||
csv << [ basename, mapping[:detail] ]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def dump
|
||||
File.open('original_songs.yml', 'w') {|f| f.write(YAML.dump(@original_songs)) }
|
||||
File.open('mapping_songs.yml', 'w') {|f| f.write(YAML.dump(@mapping_songs)) }
|
||||
end
|
||||
def dump_map
|
||||
File.open('mapping_songs.yml', 'w') {|f| f.write(YAML.dump(@mapping_songs)) }
|
||||
end
|
||||
|
||||
def md5(filepath)
|
||||
Digest::MD5.file(filepath).hexdigest
|
||||
end
|
||||
|
||||
def tency_original_check
|
||||
songs = Pathname.new(@originals_folder).children.select { |c| c.directory? }
|
||||
songs.each do |song|
|
||||
dirs = Pathname.new(song).children.select {|c| c.directory? }
|
||||
|
||||
@@log.debug "SONG #{song}"
|
||||
dirs.each do |dir|
|
||||
@@log.debug "#{dir.basename.to_s}"
|
||||
end
|
||||
@@log.debug ""
|
||||
end
|
||||
end
|
||||
|
||||
def tency_originals
|
||||
songs = Pathname.new(@originals_folder).children.select { |c| c.directory? }
|
||||
songs.each do |filename|
|
||||
id = parse_id(filename.basename.to_s )
|
||||
files = Pathname.new(filename).children.select {|c| c.file? }
|
||||
|
||||
# also look into any 1st level folders we might find
|
||||
|
||||
dirs = Pathname.new(filename).children.select {|c| c.directory? }
|
||||
dirs.each do |dir|
|
||||
more_tracks = Pathname.new(dir).children.select {|c| c.file? }
|
||||
files = files + more_tracks
|
||||
end
|
||||
|
||||
files.each do |file|
|
||||
@@log.debug("processing original track #{file.to_s}")
|
||||
md5 = md5(file.to_s)
|
||||
song = {md5:md5, filename:file.to_s, id:id}
|
||||
@original_songs[cache_id(id, md5)] = song
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def tency_maps
|
||||
songs = Pathname.new(@mapping_folder).children.select { |c| c.directory? }
|
||||
songs.each do |song_filename|
|
||||
id = parse_id_mapped(song_filename.basename.to_s )
|
||||
@@log.debug "processing song #{song_filename.to_s}"
|
||||
|
||||
tracks = Pathname.new(song_filename).children.select {|c| c.file? }
|
||||
tracks.each do |track|
|
||||
if track.to_s.include? "Stem"
|
||||
@@log.debug("processing mapped track #{track.to_s}")
|
||||
md5 = md5(track.to_s)
|
||||
|
||||
song = {md5:md5, filename:track.to_s}
|
||||
@mapping_songs[cache_id(id, md5)] = song
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def cache_id(id, md5)
|
||||
"#{id}-#{md5}"
|
||||
end
|
||||
|
||||
def parse_id(filename)
|
||||
#amy-winehouse_you-know-i-m-no-good-feat-ghostface-killah_11767
|
||||
|
||||
index = filename.rindex('_')
|
||||
if index
|
||||
id = filename[(index + 1)..-1]
|
||||
|
||||
if id.end_with?('/')
|
||||
id = id[0...-1]
|
||||
end
|
||||
|
||||
id = id.to_i
|
||||
|
||||
if id == 0
|
||||
raise "no valid ID in filename: #{filename}"
|
||||
end
|
||||
else
|
||||
raise "no _ in filename: #{filename}"
|
||||
end
|
||||
id
|
||||
end
|
||||
|
||||
def parse_id_mapped(filename)
|
||||
#Flyleaf - I'm So Sick - 15771
|
||||
|
||||
index = filename.rindex('-')
|
||||
if index
|
||||
id = filename[(index + 1)..-1]
|
||||
|
||||
if id.end_with?('/')
|
||||
id = id[0...-1]
|
||||
end
|
||||
|
||||
id.strip!
|
||||
|
||||
id = id.to_i
|
||||
|
||||
if id == 0
|
||||
raise "no valid ID in filename: #{filename}"
|
||||
end
|
||||
else
|
||||
raise "no - in filename: #{filename}"
|
||||
end
|
||||
id
|
||||
end
|
||||
|
||||
|
||||
|
||||
def tency_originals2
|
||||
s3_manager.list_directories('mapper').each do |song_folder|
|
||||
@@log.debug("searching through tency directory. song folder:'#{song_folder}'")
|
||||
|
||||
id = parse_id(song_folder)
|
||||
@@log.debug("ID #{id}")
|
||||
|
||||
top_folder = s3_manager.list_directories(song_folder)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -71,6 +71,7 @@ module JamRuby
|
|||
end
|
||||
|
||||
def follower_count
|
||||
# FIXME: this could be a lot of followers; calling size loads all the data into memory
|
||||
self.followers.size
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,428 @@
|
|||
module JamRuby
|
||||
class BandSearch < BaseSearch
|
||||
|
||||
cattr_accessor :jschema, :search_meta
|
||||
attr_accessor :user_counters
|
||||
|
||||
serialize :data_blob, JSON
|
||||
|
||||
KEY_BAND_SEARCH_TYPE = 'band_search_type'
|
||||
KEY_BAND_TYPE = 'band_type'
|
||||
KEY_BAND_STATUS = 'band_status'
|
||||
KEY_PLAY_COMMIT = 'play_commitment'
|
||||
KEY_TOUR_OPTION = 'touring_option'
|
||||
KEY_PERF_SAMPLES = 'performance_samples'
|
||||
KEY_HIRE_MAX_COST = 'max_cost'
|
||||
KEY_HIRE_FREE = 'free_gigs'
|
||||
|
||||
TO_JOIN = 'to_join'
|
||||
TO_HIRE = 'to_hire'
|
||||
|
||||
BAND_SEARCH_TYPE_VALS = [TO_JOIN, TO_HIRE]
|
||||
BAND_SEARCH_TYPES = {
|
||||
TO_JOIN => 'search bands',
|
||||
TO_HIRE => 'search bands to hire',
|
||||
}
|
||||
|
||||
BAND_TYPE_VAL_STRS = [ANY_VAL_STR, 'amateur', 'professional']
|
||||
BAND_TYPES = {
|
||||
BAND_TYPE_VAL_STRS[0] => BAND_TYPE_VAL_STRS[0].camelcase,
|
||||
BAND_TYPE_VAL_STRS[1] => BAND_TYPE_VAL_STRS[1].camelcase,
|
||||
BAND_TYPE_VAL_STRS[2] => BAND_TYPE_VAL_STRS[2].camelcase,
|
||||
}
|
||||
|
||||
SORT_VALS = %W{ distance }
|
||||
SORT_ORDERS = {
|
||||
SORT_VALS[0] => 'Distance to Me'
|
||||
}
|
||||
# SORT_VALS = %W{ distance latency }
|
||||
# SORT_ORDERS = {
|
||||
# SORT_VALS[0] => 'Distance to Me'
|
||||
# SORT_VALS[1] => 'Latency to Me',
|
||||
# }
|
||||
|
||||
HIRE_SORT_VALS = %W{ distance price_asc price_desc }
|
||||
HIRE_SORT_ORDERS = {
|
||||
HIRE_SORT_VALS[0] => 'Distance to Me',
|
||||
HIRE_SORT_VALS[1] => 'Gig Minimum Price (Low to High)',
|
||||
HIRE_SORT_VALS[2] => 'Gig Minimum Price (High to Low)',
|
||||
}
|
||||
|
||||
BAND_STATUS_VALS = [ANY_VAL_STR,
|
||||
GenrePlayer::VIRTUAL_BAND,
|
||||
GenrePlayer::TRADITIONAL_BAND,
|
||||
]
|
||||
BAND_STATUS = {
|
||||
BAND_STATUS_VALS[0] => 'Any',
|
||||
BAND_STATUS_VALS[1] => 'Virtual Band',
|
||||
BAND_STATUS_VALS[2] => 'Traditional Band',
|
||||
}
|
||||
|
||||
PLAY_COMMIT_VALS = [ANY_VAL_STR,
|
||||
'1',
|
||||
'2',
|
||||
'3',
|
||||
'4',
|
||||
]
|
||||
PLAY_COMMITS = {
|
||||
PLAY_COMMIT_VALS[0] => 'Any',
|
||||
PLAY_COMMIT_VALS[1] => 'Infrequent',
|
||||
PLAY_COMMIT_VALS[2] => 'Once a Week',
|
||||
PLAY_COMMIT_VALS[3] => '2-3 Times Per Week',
|
||||
PLAY_COMMIT_VALS[4] => '4+ Times Per Week',
|
||||
}
|
||||
|
||||
TOUR_OPTION_VALS = [ANY_VAL_STR,
|
||||
VAL_YES,
|
||||
VAL_NO,
|
||||
]
|
||||
TOUR_OPTIONS = {
|
||||
TOUR_OPTION_VALS[0] => 'Any',
|
||||
TOUR_OPTION_VALS[1] => VAL_YES,
|
||||
TOUR_OPTION_VALS[2] => VAL_NO,
|
||||
}
|
||||
|
||||
PERF_SAMPLES_VALS = TOUR_OPTION_VALS.clone
|
||||
PERF_SAMPLES = TOUR_OPTIONS.clone
|
||||
|
||||
COUNT_FOLLOW = :count_follow
|
||||
COUNT_RECORD = :count_record
|
||||
COUNT_SESSION = :count_session
|
||||
|
||||
def self.json_schema
|
||||
return @@jschema if @@jschema
|
||||
@@jschema = {
|
||||
TO_JOIN => BaseSearch.json_schema.merge({
|
||||
KEY_SORT_ORDER => self::SORT_VALS[0],
|
||||
KEY_BAND_TYPE => self::BAND_TYPE_VAL_STRS[0].to_s,
|
||||
KEY_BAND_STATUS => BAND_STATUS_VALS[0],
|
||||
KEY_PLAY_COMMIT => PLAY_COMMIT_VALS[0],
|
||||
KEY_TOUR_OPTION => TOUR_OPTION_VALS[0],
|
||||
}),
|
||||
TO_HIRE => {
|
||||
KEY_SORT_ORDER => self::HIRE_SORT_VALS[0],
|
||||
KEY_GENRES => [],
|
||||
KEY_GIGS => self::GIG_COUNTS[0].to_s,
|
||||
KEY_BAND_STATUS => BAND_STATUS_VALS[0],
|
||||
KEY_PERF_SAMPLES => self::PERF_SAMPLES_VALS[0],
|
||||
KEY_HIRE_MAX_COST => 0,
|
||||
KEY_HIRE_FREE => 0,
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
def self.search_filter_meta
|
||||
return @@search_meta if @@search_meta
|
||||
toJoinMeta = super(self.json_schema[TO_JOIN])
|
||||
toJoinMeta.merge!({
|
||||
KEY_BAND_TYPE => { keys: BAND_TYPE_VAL_STRS, map: BAND_TYPES },
|
||||
KEY_BAND_STATUS => { keys: BAND_STATUS_VALS, map: BAND_STATUS },
|
||||
KEY_PLAY_COMMIT => { keys: PLAY_COMMIT_VALS, map: PLAY_COMMITS },
|
||||
KEY_TOUR_OPTION => { keys: TOUR_OPTION_VALS, map: TOUR_OPTIONS }
|
||||
})
|
||||
toHireMeta = super(self.json_schema[TO_HIRE],
|
||||
{ keys: HIRE_SORT_VALS, map: HIRE_SORT_ORDERS })
|
||||
toHireMeta.merge!({
|
||||
KEY_BAND_STATUS => { keys: BAND_STATUS_VALS, map: BAND_STATUS },
|
||||
KEY_PERF_SAMPLES => { keys: PERF_SAMPLES_VALS, map: PERF_SAMPLES },
|
||||
})
|
||||
@@search_meta = {
|
||||
TO_JOIN => toJoinMeta,
|
||||
TO_HIRE => toHireMeta,
|
||||
}
|
||||
end
|
||||
|
||||
def self.search_target_class
|
||||
Band
|
||||
end
|
||||
|
||||
def _genres(rel, filter)
|
||||
super(rel, filter)
|
||||
end
|
||||
|
||||
def _concert_gigs(rel, filter)
|
||||
gg = filter[KEY_GIGS].to_i
|
||||
rel = rel.where(concert_count: gg) if 0 <= gg
|
||||
rel
|
||||
end
|
||||
|
||||
def _band_status(rel, filter)
|
||||
case filter[KEY_BAND_STATUS]
|
||||
when GenrePlayer::VIRTUAL_BAND
|
||||
rel.where(band_status: GenrePlayer::VIRTUAL_BAND.sub('_band',''))
|
||||
when GenrePlayer::TRADITIONAL_BAND
|
||||
rel.where(band_status: GenrePlayer::TRADITIONAL_BAND.sub('_band',''))
|
||||
else
|
||||
rel
|
||||
end
|
||||
end
|
||||
|
||||
def _play_commitment(rel, filter)
|
||||
unless ANY_VAL_STR == filter[KEY_PLAY_COMMIT]
|
||||
rel = rel.where(play_commitment: filter[KEY_PLAY_COMMIT].to_i)
|
||||
end
|
||||
rel
|
||||
end
|
||||
|
||||
def _touring_option(rel, filter)
|
||||
case filter[KEY_TOUR_OPTION]
|
||||
when VAL_YES
|
||||
rel.where(touring_option: true)
|
||||
when VAL_NO
|
||||
rel.where(touring_option: false)
|
||||
else
|
||||
rel
|
||||
end
|
||||
end
|
||||
|
||||
def _performance_samples(rel, filter)
|
||||
case filter[KEY_PERF_SAMPLES]
|
||||
when VAL_YES
|
||||
rel.joins("LEFT OUTER JOIN performance_samples AS ps ON ps.player_id = bands.id AND player_type = '#{Band.name}'").where(["ps.id IS NOT NULL"])
|
||||
when VAL_NO
|
||||
rel.joins("LEFT OUTER JOIN performance_samples AS ps ON ps.player_id = bands.id AND player_type = '#{Band.name}'").where(["ps.id IS NULL"])
|
||||
else
|
||||
rel
|
||||
end
|
||||
end
|
||||
|
||||
def _max_cost(rel, filter)
|
||||
if 0 < (max_cost = filter[KEY_HIRE_MAX_COST].to_i)
|
||||
col = Band.arel_table[:gig_minimum]
|
||||
rel = rel.where(col.lteq(max_cost)).where(col.gt(0))
|
||||
end
|
||||
rel
|
||||
end
|
||||
|
||||
def _free_gigs(rel, filter)
|
||||
case filter[KEY_HIRE_FREE]
|
||||
when VAL_YES
|
||||
rel.where(free_gigs: true)
|
||||
when VAL_NO
|
||||
rel.where(free_gigs: false)
|
||||
else
|
||||
rel
|
||||
end
|
||||
end
|
||||
|
||||
def _band_type(rel, filter)
|
||||
case filter[KEY_BAND_TYPE]
|
||||
when BAND_TYPE_VAL_STRS[1]
|
||||
rel.where(band_type: BAND_TYPE_VAL_STRS[1])
|
||||
when BAND_TYPE_VAL_STRS[2]
|
||||
rel.where(band_type: BAND_TYPE_VAL_STRS[2])
|
||||
else
|
||||
rel
|
||||
end
|
||||
end
|
||||
|
||||
def _sort_order(rel, filter)
|
||||
val = filter[KEY_SORT_ORDER]
|
||||
if 'distance' == val || val.blank?
|
||||
locidispid = self.user.last_jam_locidispid || 0
|
||||
my_locid = locidispid / 1000000
|
||||
rel = rel.joins("LEFT JOIN geoiplocations AS my_geo ON my_geo.locid = #{my_locid}")
|
||||
rel = rel.joins("LEFT JOIN geoiplocations AS other_geo ON other_geo.latitude = bands.lat AND other_geo.longitude = bands.lng")
|
||||
rel = rel.group("bands.id, my_geo.geog, other_geo.geog")
|
||||
rel = rel.order('st_distance(my_geo.geog, other_geo.geog)')
|
||||
|
||||
elsif 'price_asc' == val
|
||||
rel = rel.order('gig_minimum ASC')
|
||||
|
||||
elsif 'price_desc' == val
|
||||
rel = rel.order('gig_minimum DESC')
|
||||
end
|
||||
rel
|
||||
end
|
||||
|
||||
def do_search(filter)
|
||||
rel = Band.unscoped
|
||||
filter.keys.each do |fkey|
|
||||
mname = "_#{fkey}"
|
||||
if self.respond_to?(mname)
|
||||
rel = self.send(mname.to_sym, rel, filter)
|
||||
end
|
||||
end
|
||||
rel
|
||||
end
|
||||
|
||||
def search_includes(rel, subtype=TO_JOIN)
|
||||
TO_JOIN == subtype ? rel.includes([:instruments]) : rel
|
||||
end
|
||||
|
||||
def _process_results_page(_results)
|
||||
@results = _results
|
||||
if user
|
||||
@user_counters = @results.inject({}) { |hh,val| hh[val.id] = {}; hh }
|
||||
|
||||
# this gets counts for each search result
|
||||
@results.each do |bb|
|
||||
counters = {
|
||||
COUNT_FOLLOW => Follow.where(:followable_id => bb.id).count,
|
||||
COUNT_RECORD => Recording.where(:band_id => bb.id).count,
|
||||
COUNT_SESSION => MusicSession.where(:band_id => bb.id).count
|
||||
}
|
||||
@user_counters[bb.id] = counters
|
||||
end
|
||||
else
|
||||
@user_counters = {}
|
||||
end
|
||||
self
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def _count(band, key)
|
||||
if mm = @user_counters[band.id]
|
||||
return mm[key]
|
||||
end if @user_counters
|
||||
0
|
||||
end
|
||||
|
||||
public
|
||||
|
||||
def follow_count(band)
|
||||
_count(band, COUNT_FOLLOW)
|
||||
end
|
||||
|
||||
def record_count(band)
|
||||
_count(band, COUNT_RECORD)
|
||||
end
|
||||
|
||||
def session_count(band)
|
||||
_count(band, COUNT_SESSION)
|
||||
end
|
||||
|
||||
def is_follower?(band)
|
||||
if mm = @user_counters[band.id]
|
||||
return mm.include?(RESULT_FOLLOW)
|
||||
end if @user_counters
|
||||
false
|
||||
end
|
||||
|
||||
def search_type
|
||||
self.class.to_s
|
||||
end
|
||||
|
||||
def is_blank?(subtype=TO_JOIN)
|
||||
self.search_filter_for_subtype(subtype) == self.class.json_schema[subtype]
|
||||
end
|
||||
|
||||
def reset_filter(subtype, data=nil)
|
||||
data ||= self.class.json_schema[subtype]
|
||||
dblob = self.data_blob
|
||||
dblob[subtype] = data
|
||||
self.data_blob = dblob
|
||||
self.save
|
||||
end
|
||||
|
||||
def reset_search_results(subtype=TO_JOIN)
|
||||
reset_filter(subtype)
|
||||
search_results_page(subtype)
|
||||
end
|
||||
|
||||
def self.search_filter_json(user, subtype=TO_JOIN)
|
||||
self.user_search_filter(user).json[subtype]
|
||||
end
|
||||
|
||||
def search_filter_for_subtype(subtype)
|
||||
self.data_blob[subtype]
|
||||
end
|
||||
|
||||
def search_results_page(subtype=TO_JOIN, filter=nil, page=1)
|
||||
if filter
|
||||
reset_filter(subtype, filter)
|
||||
else
|
||||
filter = self.search_filter_for_subtype(subtype)
|
||||
end
|
||||
rel = do_search(filter)
|
||||
|
||||
@page_number = [page.to_i, 1].max
|
||||
rel = rel.paginate(:page => @page_number, :per_page => self.class::PER_PAGE)
|
||||
|
||||
rel = self.search_includes(rel, subtype)
|
||||
@page_count = rel.total_pages
|
||||
|
||||
_process_results_page(rel.all)
|
||||
end
|
||||
|
||||
def _add_description(descrip, add)
|
||||
descrip += "; " if 0 < descrip.length
|
||||
descrip + add
|
||||
end
|
||||
|
||||
def description(subtype=TO_JOIN)
|
||||
return '' if self.is_blank?(subtype)
|
||||
|
||||
filter = search_filter_for_subtype(subtype)
|
||||
str = ''
|
||||
|
||||
if filter.has_key?(KEY_SORT_ORDER)
|
||||
str += 'Sort = '
|
||||
case sort = filter[KEY_SORT_ORDER]
|
||||
when 'distance'
|
||||
str += SORT_ORDERS[sort]
|
||||
when 'latency'
|
||||
str += SORT_ORDERS[sort]
|
||||
when 'price_asc'
|
||||
str += HIRE_SORT_ORDERS[sort]
|
||||
when 'price_desc'
|
||||
str += HIRE_SORT_ORDERS[sort]
|
||||
end
|
||||
end
|
||||
if (val = filter[KEY_BAND_TYPE]) != ANY_VAL_STR
|
||||
str = _add_description(str, "Band type = #{BAND_TYPES[val]}")
|
||||
end if filter.has_key?(KEY_BAND_TYPE)
|
||||
|
||||
if (val = filter[KEY_BAND_STATUS]) != ANY_VAL_STR
|
||||
str = _add_description(str, "Band status = #{BAND_STATUS[val]}")
|
||||
end if filter.has_key?(KEY_BAND_STATUS)
|
||||
|
||||
if (val = filter[KEY_PLAY_COMMIT]) != ANY_VAL_STR
|
||||
str = _add_description(str, "Play commitment = #{PLAY_COMMITS[val]}")
|
||||
end if filter.has_key?(KEY_PLAY_COMMIT)
|
||||
|
||||
if (val = filter[KEY_TOUR_OPTION]) != ANY_VAL_STR
|
||||
str = _add_description(str, "Touring options = #{TOUR_OPTIONS[val]}")
|
||||
end if filter.has_key?(KEY_TOUR_OPTION)
|
||||
|
||||
if (val = filter[KEY_PERF_SAMPLES]) != ANY_VAL_STR
|
||||
str = _add_description(str, "Performance samples = #{PERF_SAMPLES[val]}")
|
||||
end if filter.has_key?(KEY_PERF_SAMPLES)
|
||||
|
||||
if (val = filter[KEY_HIRE_MAX_COST].to_i) > 0
|
||||
str = _add_description(str, "Maximum gig cost = $#{val}")
|
||||
end if filter.has_key?(KEY_HIRE_MAX_COST)
|
||||
|
||||
if 0 < filter[KEY_HIRE_FREE]
|
||||
str = _add_description(str, "Bands playing free gigs")
|
||||
end if filter.has_key?(KEY_HIRE_FREE)
|
||||
|
||||
if (val = filter[KEY_GIGS].to_i) != GIG_COUNTS[0]
|
||||
str = _add_description(str, "Concert gigs = #{GIG_LABELS[val]}")
|
||||
end if filter.has_key?(KEY_GIGS)
|
||||
|
||||
if 0 < (val = filter[KEY_GENRES]).length
|
||||
gstr = "Genres = "
|
||||
genres = Genre.where(["id IN (?)", val]).order('description').pluck(:description)
|
||||
gstr += genres.join(', ')
|
||||
str = _add_description(str, gstr)
|
||||
end if filter.has_key?(KEY_GENRES)
|
||||
|
||||
if 0 < ((val = filter[KEY_INSTRUMENTS]) || '').length
|
||||
istr = "Instruments = "
|
||||
instr_ids = val.collect { |vv| vv['instrument_id'] }
|
||||
instrs = Instrument.where(["id IN (?)", instr_ids]).order(:description)
|
||||
instrs.each_with_index do |ii, idx|
|
||||
proficiency = val.detect { |vv| vv['instrument_id'] == ii.id }['proficiency_level']
|
||||
istr += "#{ii.description} (#{INSTRUMENT_PROFICIENCY[proficiency.to_i]})"
|
||||
istr += ', ' unless idx==(instrs.length-1)
|
||||
end
|
||||
str = _add_description(str, istr)
|
||||
end if filter.has_key?(KEY_INSTRUMENTS)
|
||||
str = "Current Search: #{str}"
|
||||
str
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,196 @@
|
|||
module JamRuby
|
||||
class BaseSearch < JsonStore
|
||||
|
||||
attr_accessor :page_count, :results, :page_number
|
||||
|
||||
ANY_VAL_STR = 'any'
|
||||
ANY_VAL_INT = -1
|
||||
|
||||
VAL_YES = 'yes'
|
||||
VAL_NO = 'no'
|
||||
|
||||
PER_PAGE = 10
|
||||
PG_SMALLINT_MAX = 32767
|
||||
|
||||
KEY_SKILL = 'skill_level'
|
||||
KEY_GENRES = 'genres'
|
||||
KEY_INSTRUMENTS = 'instruments'
|
||||
KEY_GIGS = 'concert_gigs'
|
||||
KEY_SORT_ORDER = 'sort_order'
|
||||
|
||||
SORT_VALS = %W{ latency distance }
|
||||
SORT_ORDERS = {
|
||||
SORT_VALS[0] => 'Latency to Me',
|
||||
SORT_VALS[1] => 'Distance to Me'
|
||||
}
|
||||
|
||||
SKILL_VALS = [ANY_VAL_INT, 1, 2]
|
||||
SKILL_LEVELS = {
|
||||
SKILL_VALS[0] => 'Any',
|
||||
SKILL_VALS[1] => 'Amateur',
|
||||
SKILL_VALS[2] => 'Pro',
|
||||
}
|
||||
|
||||
GIG_COUNTS = [ANY_VAL_INT, 0, 1, 2, 3, 4]
|
||||
GIG_LABELS = {
|
||||
GIG_COUNTS[0] => 'Any',
|
||||
GIG_COUNTS[1] => 'under 10',
|
||||
GIG_COUNTS[2] => '10 to 50',
|
||||
GIG_COUNTS[3] => '50 to 100',
|
||||
GIG_COUNTS[4] => 'over 100'
|
||||
}
|
||||
|
||||
INSTRUMENT_PROFICIENCY = {
|
||||
1 => 'Beginner',
|
||||
2 => 'Intermediate',
|
||||
3 => 'Expert',
|
||||
}
|
||||
|
||||
def self.json_schema
|
||||
{
|
||||
KEY_SORT_ORDER => self::SORT_VALS[0],
|
||||
KEY_INSTRUMENTS => [],
|
||||
KEY_GENRES => [],
|
||||
KEY_GIGS => self::GIG_COUNTS[0].to_s,
|
||||
}
|
||||
end
|
||||
|
||||
def self.search_filter_meta(jschema=nil, sort_order=nil)
|
||||
jschema ||= self.json_schema
|
||||
schema_keys = jschema.keys
|
||||
sort_order ||= { keys: self::SORT_VALS, map: self::SORT_ORDERS }
|
||||
multi_keys = jschema.collect { |kk,vv| vv.is_a?(Array) ? kk : nil }.compact
|
||||
{
|
||||
per_page: self::PER_PAGE,
|
||||
filter_keys: {
|
||||
keys: schema_keys,
|
||||
multi: multi_keys,
|
||||
single: schema_keys - multi_keys,
|
||||
},
|
||||
sort_order: sort_order
|
||||
}
|
||||
end
|
||||
|
||||
RESULT_FOLLOW = :follows
|
||||
RESULT_FRIEND = :friends
|
||||
|
||||
COUNT_FRIEND = :count_friend
|
||||
COUNT_FOLLOW = :count_follow
|
||||
COUNT_RECORD = :count_record
|
||||
COUNT_SESSION = :count_session
|
||||
COUNTERS = [COUNT_FRIEND, COUNT_FOLLOW, COUNT_RECORD, COUNT_SESSION]
|
||||
|
||||
def self.user_search_filter(user)
|
||||
unless ss = user.send(self.name.demodulize.tableize.singularize)
|
||||
ss = self.create_search(user)
|
||||
end
|
||||
ss
|
||||
end
|
||||
|
||||
def self.search_filter_json(user)
|
||||
self.user_search_filter(user).json
|
||||
end
|
||||
|
||||
def self.create_search(user)
|
||||
ms = self.new
|
||||
ms.user = user
|
||||
ms.data_blob = self.json_schema
|
||||
ms.save!
|
||||
ms
|
||||
end
|
||||
|
||||
def self.search_target_class
|
||||
end
|
||||
|
||||
# FIXME: SQL INJECTION
|
||||
def _genres(rel, query_data=json)
|
||||
gids = query_data[KEY_GENRES]
|
||||
unless gids.blank?
|
||||
gidsql = gids.join("','")
|
||||
gpsql = "SELECT player_id FROM genre_players WHERE (player_type = '#{self.class.search_target_class.name}' AND genre_id IN ('#{gidsql}'))"
|
||||
rel = rel.where("#{self.class.search_target_class.table_name}.id IN (#{gpsql})")
|
||||
end
|
||||
rel
|
||||
end
|
||||
|
||||
# FIXME: SQL INJECTION
|
||||
def _instruments(rel, query_data=json)
|
||||
unless (instruments = query_data[KEY_INSTRUMENTS]).blank?
|
||||
instsql = "SELECT player_id FROM musicians_instruments WHERE (("
|
||||
instsql += instruments.collect do |inst|
|
||||
"instrument_id = '#{inst['instrument_id']}' AND proficiency_level = #{inst['proficiency_level']}"
|
||||
end.join(") OR (")
|
||||
instsql += "))"
|
||||
rel = rel.where("#{self.class.search_target_class.table_name}.id IN (#{instsql})")
|
||||
end
|
||||
rel
|
||||
end
|
||||
|
||||
def _gigs(rel)
|
||||
gg = json[KEY_GIGS].to_i
|
||||
rel = rel.where('concert_count = ?',gg) if 0 <= gg
|
||||
rel
|
||||
end
|
||||
|
||||
def _skills(rel)
|
||||
if 0 < (val = json[KEY_SKILL].to_i)
|
||||
rel = rel.where(['skill_level = ?', val])
|
||||
end
|
||||
rel
|
||||
end
|
||||
|
||||
def _sort_order(rel)
|
||||
end
|
||||
|
||||
def do_search(params={})
|
||||
end
|
||||
|
||||
def process_results_page(objs)
|
||||
end
|
||||
|
||||
def search_includes(rel)
|
||||
rel
|
||||
end
|
||||
|
||||
def search_results_page(filter=nil, page=1)
|
||||
if filter
|
||||
self.data_blob = filter
|
||||
self.save
|
||||
else
|
||||
filter = self.data_blob
|
||||
end
|
||||
|
||||
rel = do_search(filter)
|
||||
|
||||
@page_number = [page.to_i, 1].max
|
||||
rel = rel.paginate(:page => @page_number, :per_page => self.class::PER_PAGE)
|
||||
|
||||
rel = self.search_includes(rel)
|
||||
@page_count = rel.total_pages
|
||||
|
||||
process_results_page(rel.all)
|
||||
end
|
||||
|
||||
def reset_filter
|
||||
self.data_blob = self.class.json_schema
|
||||
self.save
|
||||
end
|
||||
|
||||
def reset_search_results
|
||||
reset_filter
|
||||
search_results_page
|
||||
end
|
||||
|
||||
def search_type
|
||||
self.class.to_s
|
||||
end
|
||||
|
||||
def is_blank?
|
||||
self.data_blob == self.class.json_schema
|
||||
end
|
||||
|
||||
def description
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
@ -31,6 +31,5 @@ module JamRuby
|
|||
GenericState.find('default')
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -19,7 +19,8 @@ module JamRuby
|
|||
has_and_belongs_to_many :teachers, :class_name => "JamRuby::Teacher", :join_table => "teachers_genres"
|
||||
|
||||
# jam tracks
|
||||
has_many :jam_tracks, :class_name => "JamRuby::JamTrack"
|
||||
has_many :genres_jam_tracks, :class_name => "JamRuby::GenreJamTrack", :foreign_key => "genre_id"
|
||||
has_many :jam_tracks, :through => :genres_jam_tracks, :class_name => "JamRuby::JamTrack", :source => :genre
|
||||
|
||||
def to_s
|
||||
description
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
module JamRuby
|
||||
class GenreJamTrack < ActiveRecord::Base
|
||||
|
||||
self.table_name = 'genres_jam_tracks'
|
||||
belongs_to :jam_track, class_name: 'JamRuby::JamTrack'
|
||||
belongs_to :genre, class_name: 'JamRuby::Genre'
|
||||
end
|
||||
end
|
||||
|
|
@ -14,12 +14,12 @@ module JamRuby
|
|||
|
||||
attr_accessor :uploading_preview
|
||||
attr_accessible :name, :description, :bpm, :time_signature, :status, :recording_type,
|
||||
:original_artist, :songwriter, :publisher, :licensor, :licensor_id, :pro, :genre, :genre_id, :sales_region, :price,
|
||||
:original_artist, :songwriter, :publisher, :licensor, :licensor_id, :pro, :genres_jam_tracks_attributes, :sales_region, :price,
|
||||
:reproduction_royalty, :public_performance_royalty, :reproduction_royalty_amount,
|
||||
:licensor_royalty_amount, :pro_royalty_amount, :plan_code, :initial_play_silence, :jam_track_tracks_attributes,
|
||||
:jam_track_tap_ins_attributes, :version, :jmep_json, :jmep_text, :pro_ascap, :pro_bmi, :pro_sesac, :duration, as: :admin
|
||||
:jam_track_tap_ins_attributes, :genre_ids, :version, :jmep_json, :jmep_text, :pro_ascap, :pro_bmi, :pro_sesac, :duration, as: :admin
|
||||
|
||||
validates :name, presence: true, uniqueness: true, length: {maximum: 200}
|
||||
validates :name, presence: true, length: {maximum: 200}
|
||||
validates :plan_code, presence: true, uniqueness: true, length: {maximum: 50 }
|
||||
validates :description, length: {maximum: 1000}
|
||||
validates :time_signature, inclusion: {in: [nil] + [''] + TIME_SIGNATURES} # the empty string is needed because of activeadmin
|
||||
|
|
@ -39,14 +39,17 @@ module JamRuby
|
|||
validates :public_performance_royalty, inclusion: {in: [nil, true, false]}
|
||||
validates :duration, numericality: {only_integer: true}, :allow_nil => true
|
||||
|
||||
validates_format_of :reproduction_royalty_amount, with: /^\d+\.*\d{0,3}$/
|
||||
validates_format_of :licensor_royalty_amount, with: /^\d+\.*\d{0,3}$/
|
||||
validates_format_of :reproduction_royalty_amount, with: /^\d+\.*\d{0,4}$/, :allow_blank => true
|
||||
validates_format_of :licensor_royalty_amount, with: /^\d+\.*\d{0,4}$/, :allow_blank => true
|
||||
|
||||
belongs_to :genre, class_name: "JamRuby::Genre"
|
||||
belongs_to :licensor , class_name: 'JamRuby::JamTrackLicensor', foreign_key: 'licensor_id'
|
||||
belongs_to :licensor , class_name: 'JamRuby::JamTrackLicensor', foreign_key: 'licensor_id', :inverse_of => :jam_tracks
|
||||
|
||||
has_many :genres_jam_tracks, :class_name => "JamRuby::GenreJamTrack", :foreign_key => "jam_track_id"
|
||||
has_many :genres, :through => :genres_jam_tracks, :class_name => "JamRuby::Genre", :source => :genre
|
||||
|
||||
has_many :jam_track_tracks, :class_name => "JamRuby::JamTrackTrack", order: 'track_type ASC, position ASC, part ASC, instrument_id ASC'
|
||||
has_many :jam_track_tap_ins, :class_name => "JamRuby::JamTrackTapIn", order: 'offset_time ASC'
|
||||
has_many :jam_track_files, :class_name => "JamRuby::JamTrackFile"
|
||||
|
||||
has_many :jam_track_rights, :class_name => "JamRuby::JamTrackRight" #, inverse_of: 'jam_track', :foreign_key => "jam_track_id" # '
|
||||
|
||||
|
|
@ -67,6 +70,82 @@ module JamRuby
|
|||
accepts_nested_attributes_for :jam_track_tracks, allow_destroy: true
|
||||
accepts_nested_attributes_for :jam_track_tap_ins, allow_destroy: true
|
||||
|
||||
|
||||
# we can make sure a few things stay in sync here.
|
||||
# 1) the reproduction_royalty_amount has to stay in sync based on duration
|
||||
# 2) the onboarding_exceptions JSON column
|
||||
after_save :sync_reproduction_royalty
|
||||
after_save :sync_onboarding_exceptions
|
||||
|
||||
|
||||
def sync_reproduction_royalty
|
||||
|
||||
# reproduction royalty table based on duration
|
||||
|
||||
# The statutory mechanical royalty rate for permanent digital downloads is:
|
||||
# 9.10¢ per copy for songs 5 minutes or less, or
|
||||
# 1.75¢ per minute or fraction thereof, per copy for songs over 5 minutes.
|
||||
# So the base rate is 9.1 cents for anything up to 5 minutes.
|
||||
# 5.01 to 6 minutes should be 10.5 cents.
|
||||
# 6.01 to 7 minutes should be 12.25 cents.
|
||||
# Etc.
|
||||
|
||||
royalty = nil
|
||||
if self.duration
|
||||
minutes = (self.duration - 1) / 60
|
||||
extra_minutes = minutes - 4
|
||||
extra_minutes = 0 if extra_minutes < 0
|
||||
royalty = (0.091 + (0.0175 * extra_minutes)).round(5)
|
||||
end
|
||||
self.update_column(:reproduction_royalty_amount, royalty)
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
def sync_onboarding_exceptions
|
||||
|
||||
exceptions = {}
|
||||
if self.duration.nil?
|
||||
exceptions[:no_duration] = true
|
||||
end
|
||||
|
||||
if self.genres.count == 0
|
||||
exceptions[:no_genres] = true
|
||||
end
|
||||
|
||||
if self.year.nil?
|
||||
exceptions[:no_year] = true
|
||||
end
|
||||
|
||||
if self.licensor.nil?
|
||||
exceptions[:no_licensor] = true
|
||||
end
|
||||
|
||||
if self.missing_instrument_info?
|
||||
exceptions[:unknown_instrument] = true
|
||||
end
|
||||
|
||||
if self.master_track.nil?
|
||||
exceptions[:no_master] = true
|
||||
end
|
||||
|
||||
if missing_previews?
|
||||
exceptions[:missing_previews] = true
|
||||
end
|
||||
|
||||
if duplicate_positions?
|
||||
exceptions[:duplicate_positions] = true
|
||||
end
|
||||
|
||||
if exceptions.keys.length == 0
|
||||
self.update_column(:onboarding_exceptions, nil)
|
||||
else
|
||||
self.update_column(:onboarding_exceptions, exceptions.to_json)
|
||||
end
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
def duplicate_positions?
|
||||
counter = {}
|
||||
jam_track_tracks.each do |track|
|
||||
|
|
@ -87,6 +166,17 @@ module JamRuby
|
|||
duplicate
|
||||
end
|
||||
|
||||
def missing_instrument_info?
|
||||
missing_instrument_info = false
|
||||
self.jam_track_tracks.each do |track|
|
||||
if track.instrument_id == 'other' && (track.part == nil || track.part.start_with?('Other'))
|
||||
missing_instrument_info = true
|
||||
break
|
||||
end
|
||||
end
|
||||
missing_instrument_info
|
||||
end
|
||||
|
||||
def missing_previews?
|
||||
missing_preview = false
|
||||
self.jam_track_tracks.each do |track|
|
||||
|
|
@ -171,7 +261,7 @@ module JamRuby
|
|||
end
|
||||
|
||||
if options[:group_artist]
|
||||
query = query.select("original_artist, array_agg(jam_tracks.id) AS id, MIN(name) AS name, MIN(description) AS description, MIN(recording_type) AS recording_type, MIN(original_artist) AS original_artist, MIN(songwriter) AS songwriter, MIN(publisher) AS publisher, MIN(sales_region) AS sales_region, MIN(price) AS price, MIN(version) AS version, MIN(genre_id) AS genre_id")
|
||||
query = query.select("original_artist, array_agg(jam_tracks.id) AS id, MIN(name) AS name, MIN(description) AS description, MIN(recording_type) AS recording_type, MIN(original_artist) AS original_artist, MIN(songwriter) AS songwriter, MIN(publisher) AS publisher, MIN(sales_region) AS sales_region, MIN(price) AS price, MIN(version) AS version")
|
||||
query = query.group("original_artist")
|
||||
query = query.order('jam_tracks.original_artist')
|
||||
else
|
||||
|
|
@ -180,7 +270,12 @@ module JamRuby
|
|||
end
|
||||
|
||||
query = query.where("jam_tracks.status = ?", 'Production') unless user.admin
|
||||
query = query.where("jam_tracks.genre_id = '#{options[:genre]}'") unless options[:genre].blank?
|
||||
|
||||
unless options[:genre].blank?
|
||||
query = query.joins(:genres)
|
||||
query = query.where('genre_id = ? ', options[:genre])
|
||||
end
|
||||
|
||||
query = query.where("jam_track_tracks.instrument_id = '#{options[:instrument]}' and jam_track_tracks.track_type != 'Master'") unless options[:instrument].blank?
|
||||
query = query.where("jam_tracks.sales_region = '#{options[:availability]}'") unless options[:availability].blank?
|
||||
|
||||
|
|
@ -231,7 +326,12 @@ module JamRuby
|
|||
query = query.order('jam_tracks.original_artist')
|
||||
|
||||
query = query.where("jam_tracks.status = ?", 'Production') unless user.admin
|
||||
query = query.where("jam_tracks.genre_id = '#{options[:genre]}'") unless options[:genre].blank?
|
||||
|
||||
unless options[:genre].blank?
|
||||
query = query.joins(:genres)
|
||||
query = query.where('genre_id = ? ', options[:genre])
|
||||
end
|
||||
|
||||
query = query.where("jam_track_tracks.instrument_id = '#{options[:instrument]}'") unless options[:instrument].blank?
|
||||
query = query.where("jam_tracks.sales_region = '#{options[:availability]}'") unless options[:availability].blank?
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,78 @@
|
|||
module JamRuby
|
||||
|
||||
# holds a click track or precount file
|
||||
class JamTrackFile < ActiveRecord::Base
|
||||
include JamRuby::S3ManagerMixin
|
||||
|
||||
# there should only be one Master per JamTrack, but there can be N Track per JamTrack
|
||||
FILE_TYPE = %w{ClickWav ClickTxt Precount}
|
||||
|
||||
@@log = Logging.logger[JamTrackFile]
|
||||
|
||||
before_destroy :delete_s3_files
|
||||
|
||||
attr_accessible :jam_track_id, :file_type, :filename, as: :admin
|
||||
attr_accessible :url, :md5, :length, as: :admin
|
||||
|
||||
attr_accessor :original_audio_s3_path, :skip_uploader, :preview_generate_error
|
||||
|
||||
before_destroy :delete_s3_files
|
||||
|
||||
validates :file_type, inclusion: {in: FILE_TYPE }
|
||||
|
||||
belongs_to :jam_track, class_name: "JamRuby::JamTrack"
|
||||
|
||||
# create storage directory that will house this jam_track, as well as
|
||||
def store_dir
|
||||
"jam_track_files"
|
||||
end
|
||||
|
||||
# create name of the file
|
||||
def filename(original_name)
|
||||
"#{store_dir}/#{jam_track.original_artist}/#{jam_track.name}/#{original_name}"
|
||||
end
|
||||
|
||||
def manually_uploaded_filename
|
||||
if click_wav?
|
||||
filename('click.wav')
|
||||
elsif click_txt?
|
||||
filename('click.txt')
|
||||
elsif precount?
|
||||
filename('precount.wav')
|
||||
else
|
||||
raise 'unknown file type: ' + file_type
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def click_wav?
|
||||
track_type == 'ClickWav'
|
||||
end
|
||||
|
||||
def click_txt?
|
||||
track_type == 'ClickTxt'
|
||||
end
|
||||
|
||||
def precount?
|
||||
track_type == 'Precount'
|
||||
end
|
||||
|
||||
# creates a short-lived URL that has access to the object.
|
||||
# the idea is that this is used when a user who has the rights to this tries to download this JamTrack
|
||||
# we would verify their rights (can_download?), and generates a URL in response to the click so that they can download
|
||||
# but the url is short lived enough so that it wouldn't be easily shared
|
||||
def sign_url(expiration_time = 120)
|
||||
s3_manager.sign_url(self[url], {:expires => expiration_time, :response_content_type => 'audio/wav', :secure => true})
|
||||
end
|
||||
|
||||
def can_download?(user)
|
||||
# I think we have to make a special case for 'previews', but maybe that's just up to the controller to not check can_download?
|
||||
jam_track.owners.include?(user)
|
||||
end
|
||||
|
||||
|
||||
def delete_s3_files
|
||||
s3_manager.delete(self[:url]) if self[:url] && s3_manager.exists?(self[:url])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
module JamRuby
|
||||
class JamTrackLicensor < ActiveRecord::Base
|
||||
|
||||
table_name = 'jam_track_licensors'
|
||||
|
||||
attr_accessible :name, :description, :attention, :address_line_1, :address_line_2,
|
||||
:city, :state, :zip_code, :contact, :email, :phone, as: :admin
|
||||
|
||||
|
|
@ -16,6 +18,6 @@ module JamRuby
|
|||
validates :email, length: {maximum: 200}
|
||||
validates :phone, length: {maximum: 200}
|
||||
|
||||
has_many :jam_tracks, :class_name => "JamRuby::JamTrack", foreign_key: 'licensor_id'
|
||||
has_many :jam_tracks, :class_name => "JamRuby::JamTrack", foreign_key: 'licensor_id', :inverse_of => :licensor
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ module JamRuby
|
|||
before_destroy :delete_s3_files
|
||||
|
||||
validates :position, presence: true, numericality: {only_integer: true}, length: {in: 1..1000}
|
||||
validates :part, length: {maximum: 25}
|
||||
validates :part, length: {maximum: 35}
|
||||
validates :track_type, inclusion: {in: TRACK_TYPE }
|
||||
validates :preview_start_time, numericality: {only_integer: true}, length: {in: 1..1000}, :allow_nil => true
|
||||
validates_uniqueness_of :part, scope: [:jam_track_id, :instrument_id]
|
||||
|
|
@ -131,81 +131,19 @@ module JamRuby
|
|||
end
|
||||
|
||||
|
||||
|
||||
def generate_preview
|
||||
|
||||
begin
|
||||
Dir.mktmpdir do |tmp_dir|
|
||||
|
||||
input = File.join(tmp_dir, 'in.ogg')
|
||||
output = File.join(tmp_dir, 'out.ogg')
|
||||
output_mp3 = File.join(tmp_dir, 'out.mp3')
|
||||
|
||||
start = self.preview_start_time.to_f / 1000
|
||||
stop = start + 20
|
||||
|
||||
raise 'no track' unless self["url_44"]
|
||||
|
||||
s3_manager.download(self.url_by_sample_rate(44), input)
|
||||
|
||||
command = "sox \"#{input}\" \"#{output}\" trim #{sprintf("%.3f", start)} =#{sprintf("%.3f", stop)}"
|
||||
|
||||
@@log.debug("trimming using: " + command)
|
||||
|
||||
sox_output = `#{command}`
|
||||
|
||||
result_code = $?.to_i
|
||||
|
||||
if result_code != 0
|
||||
@@log.debug("fail #{result_code}")
|
||||
@preview_generate_error = "unable to execute cut command #{sox_output}"
|
||||
else
|
||||
# now create mp3 off of ogg preview
|
||||
|
||||
convert_mp3_cmd = "#{APP_CONFIG.ffmpeg_path} -i \"#{output}\" -ab 192k \"#{output_mp3}\""
|
||||
|
||||
@@log.debug("converting to mp3 using: " + convert_mp3_cmd)
|
||||
|
||||
convert_output = `#{convert_mp3_cmd}`
|
||||
|
||||
result_code = $?.to_i
|
||||
|
||||
if result_code != 0
|
||||
@@log.debug("fail #{result_code}")
|
||||
@preview_generate_error = "unable to execute mp3 convert command #{convert_output}"
|
||||
else
|
||||
ogg_digest = ::Digest::MD5.file(output)
|
||||
mp3_digest = ::Digest::MD5.file(output_mp3)
|
||||
self["preview_md5"] = ogg_md5 = ogg_digest.hexdigest
|
||||
self["preview_mp3_md5"] = mp3_md5 = mp3_digest.hexdigest
|
||||
|
||||
@@log.debug("uploading ogg preview to #{self.preview_filename('ogg')}")
|
||||
s3_public_manager.upload(self.preview_filename(ogg_md5, 'ogg'), output, content_type: 'audio/ogg', content_md5: ogg_digest.base64digest)
|
||||
@@log.debug("uploading mp3 preview to #{self.preview_filename('mp3')}")
|
||||
s3_public_manager.upload(self.preview_filename(mp3_md5, 'mp3'), output_mp3, content_type: 'audio/mpeg', content_md5: mp3_digest.base64digest)
|
||||
|
||||
self.skip_uploader = true
|
||||
|
||||
original_ogg_preview_url = self["preview_url"]
|
||||
original_mp3_preview_url = self["preview_mp3_url"]
|
||||
|
||||
# and finally update the JamTrackTrack with the new info
|
||||
self["preview_url"] = self.preview_filename(ogg_md5, 'ogg')
|
||||
self["preview_length"] = File.new(output).size
|
||||
# and finally update the JamTrackTrack with the new info
|
||||
self["preview_mp3_url"] = self.preview_filename(mp3_md5, 'mp3')
|
||||
self["preview_mp3_length"] = File.new(output_mp3).size
|
||||
self.save!
|
||||
|
||||
# if all that worked, now delete old previews, if present
|
||||
begin
|
||||
s3_public_manager.delete(original_ogg_preview_url) if original_ogg_preview_url && original_ogg_preview_url != self["preview_url"]
|
||||
s3_public_manager.delete(original_mp3_preview_url) if original_mp3_preview_url && original_mp3_preview_url != track["preview_mp3_url"]
|
||||
rescue
|
||||
puts "UNABLE TO CLEANUP OLD PREVIEW URL"
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
process_preview(input, tmp_dir)
|
||||
end
|
||||
rescue Exception => e
|
||||
@@log.error("error in sox command #{e.to_s}")
|
||||
|
|
@ -214,6 +152,76 @@ module JamRuby
|
|||
|
||||
end
|
||||
|
||||
# input is the original ogg file for the track. tmp_dir is where this code can safely generate output stuff and have it cleaned up later
|
||||
def process_preview(input, tmp_dir)
|
||||
uuid = SecureRandom.uuid
|
||||
output = File.join(tmp_dir, "#{uuid}.ogg")
|
||||
output_mp3 = File.join(tmp_dir, "#{uuid}.mp3")
|
||||
|
||||
start = self.preview_start_time.to_f / 1000
|
||||
stop = start + 20
|
||||
|
||||
command = "sox \"#{input}\" \"#{output}\" trim #{sprintf("%.3f", start)} =#{sprintf("%.3f", stop)}"
|
||||
|
||||
@@log.debug("trimming using: " + command)
|
||||
|
||||
sox_output = `#{command}`
|
||||
|
||||
result_code = $?.to_i
|
||||
|
||||
if result_code != 0
|
||||
@@log.debug("fail #{result_code}")
|
||||
@preview_generate_error = "unable to execute cut command #{sox_output}"
|
||||
else
|
||||
# now create mp3 off of ogg preview
|
||||
|
||||
convert_mp3_cmd = "#{APP_CONFIG.ffmpeg_path} -i \"#{output}\" -ab 192k \"#{output_mp3}\""
|
||||
|
||||
@@log.debug("converting to mp3 using: " + convert_mp3_cmd)
|
||||
|
||||
convert_output = `#{convert_mp3_cmd}`
|
||||
|
||||
result_code = $?.to_i
|
||||
|
||||
if result_code != 0
|
||||
@@log.debug("fail #{result_code}")
|
||||
@preview_generate_error = "unable to execute mp3 convert command #{convert_output}"
|
||||
else
|
||||
ogg_digest = ::Digest::MD5.file(output)
|
||||
mp3_digest = ::Digest::MD5.file(output_mp3)
|
||||
self["preview_md5"] = ogg_md5 = ogg_digest.hexdigest
|
||||
self["preview_mp3_md5"] = mp3_md5 = mp3_digest.hexdigest
|
||||
|
||||
@@log.debug("uploading ogg preview to #{self.preview_filename('ogg')}")
|
||||
s3_public_manager.upload(self.preview_filename(ogg_md5, 'ogg'), output, content_type: 'audio/ogg', content_md5: ogg_digest.base64digest)
|
||||
@@log.debug("uploading mp3 preview to #{self.preview_filename('mp3')}")
|
||||
s3_public_manager.upload(self.preview_filename(mp3_md5, 'mp3'), output_mp3, content_type: 'audio/mpeg', content_md5: mp3_digest.base64digest)
|
||||
|
||||
self.skip_uploader = true
|
||||
|
||||
original_ogg_preview_url = self["preview_url"]
|
||||
original_mp3_preview_url = self["preview_mp3_url"]
|
||||
|
||||
# and finally update the JamTrackTrack with the new info
|
||||
self["preview_url"] = self.preview_filename(ogg_md5, 'ogg')
|
||||
self["preview_length"] = File.new(output).size
|
||||
# and finally update the JamTrackTrack with the new info
|
||||
self["preview_mp3_url"] = self.preview_filename(mp3_md5, 'mp3')
|
||||
self["preview_mp3_length"] = File.new(output_mp3).size
|
||||
self.save!
|
||||
|
||||
# if all that worked, now delete old previews, if present
|
||||
begin
|
||||
s3_public_manager.delete(original_ogg_preview_url) if original_ogg_preview_url && original_ogg_preview_url != self["preview_url"]
|
||||
s3_public_manager.delete(original_mp3_preview_url) if original_mp3_preview_url && original_mp3_preview_url != track["preview_mp3_url"]
|
||||
rescue
|
||||
puts "UNABLE TO CLEANUP OLD PREVIEW URL"
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
def normalize_position
|
||||
|
|
|
|||
|
|
@ -1,22 +1,12 @@
|
|||
module JamRuby
|
||||
class MusicianSearch < JsonStore
|
||||
class MusicianSearch < BaseSearch
|
||||
|
||||
attr_accessor :page_count, :results, :user_counters, :page_number
|
||||
cattr_accessor :jschema, :search_meta
|
||||
attr_accessor :user_counters
|
||||
|
||||
ANY_VAL_STR = 'any'
|
||||
ANY_VAL_INT = -1
|
||||
|
||||
PER_PAGE = 10
|
||||
PG_SMALLINT_MAX = 32767
|
||||
|
||||
KEY_GIGS = 'concert_gigs'
|
||||
KEY_STUDIOS = 'studio_sessions'
|
||||
KEY_AGES = 'ages'
|
||||
KEY_SKILL = 'skill_level'
|
||||
KEY_GENRES = 'genres'
|
||||
KEY_INSTRUMENTS = 'instruments'
|
||||
KEY_INTERESTS = 'interests'
|
||||
KEY_SORT_ORDER = 'sort_order'
|
||||
|
||||
SORT_VALS = %W{ latency distance }
|
||||
SORT_ORDERS = {
|
||||
|
|
@ -24,22 +14,6 @@ module JamRuby
|
|||
SORT_VALS[1] => 'Distance to Me'
|
||||
}
|
||||
|
||||
SKILL_VALS = [ANY_VAL_INT, 1, 2]
|
||||
SKILL_LEVELS = {
|
||||
SKILL_VALS[0] => 'Any',
|
||||
SKILL_VALS[1] => 'Amateur',
|
||||
SKILL_VALS[2] => 'Pro',
|
||||
}
|
||||
|
||||
GIG_COUNTS = [ANY_VAL_INT, 0, 1, 2, 3, 4]
|
||||
GIG_LABELS = {
|
||||
GIG_COUNTS[0] => 'Any',
|
||||
GIG_COUNTS[1] => 'under 10',
|
||||
GIG_COUNTS[2] => '10 to 50',
|
||||
GIG_COUNTS[3] => '50 to 100',
|
||||
GIG_COUNTS[4] => 'over 100'
|
||||
}
|
||||
|
||||
STUDIO_COUNTS = [ANY_VAL_INT, 0, 1, 2, 3, 4]
|
||||
STUDIOS_LABELS = {
|
||||
STUDIO_COUNTS[0] => 'Any',
|
||||
|
|
@ -74,81 +48,28 @@ module JamRuby
|
|||
INTEREST_VALS[5] => 'Co-Writing'
|
||||
}
|
||||
|
||||
INSTRUMENT_PROFICIENCY = {
|
||||
1 => 'Beginner',
|
||||
2 => 'Intermediate',
|
||||
3 => 'Expert',
|
||||
}
|
||||
|
||||
JSON_SCHEMA = {
|
||||
KEY_SORT_ORDER => SORT_VALS[0],
|
||||
KEY_INSTRUMENTS => [],
|
||||
KEY_INTERESTS => INTEREST_VALS[0],
|
||||
KEY_GENRES => [],
|
||||
KEY_GIGS => GIG_COUNTS[0].to_s,
|
||||
KEY_STUDIOS => STUDIO_COUNTS[0].to_s,
|
||||
KEY_SKILL => SKILL_VALS[0].to_s,
|
||||
KEY_AGES => []
|
||||
}
|
||||
JSON_SCHEMA_KEYS = JSON_SCHEMA.keys
|
||||
MULTI_VALUE_KEYS = JSON_SCHEMA.collect { |kk,vv| vv.is_a?(Array) ? kk : nil }.compact
|
||||
SINGLE_VALUE_KEYS = JSON_SCHEMA.keys - MULTI_VALUE_KEYS
|
||||
|
||||
SEARCH_FILTER_META = {
|
||||
per_page: PER_PAGE,
|
||||
filter_keys: {
|
||||
keys: JSON_SCHEMA_KEYS,
|
||||
multi: MULTI_VALUE_KEYS,
|
||||
single: SINGLE_VALUE_KEYS,
|
||||
},
|
||||
sort_order: { keys: SORT_VALS, map: SORT_ORDERS },
|
||||
interests: { keys: INTEREST_VALS, map: INTERESTS },
|
||||
ages: { keys: AGE_COUNTS, map: AGES }
|
||||
}
|
||||
|
||||
def self.user_search_filter(user)
|
||||
unless ms = user.musician_search
|
||||
ms = self.create_search(user)
|
||||
end
|
||||
ms
|
||||
def self.json_schema
|
||||
return @@jschema if @@jschema
|
||||
@@jschema = BaseSearch.json_schema.merge({
|
||||
KEY_INTERESTS => INTEREST_VALS[0],
|
||||
KEY_STUDIOS => STUDIO_COUNTS[0].to_s,
|
||||
KEY_AGES => [],
|
||||
KEY_SKILL => self::SKILL_VALS[0].to_s,
|
||||
})
|
||||
end
|
||||
|
||||
def self.search_filter_json(user)
|
||||
self.user_search_filter(user).json
|
||||
def self.search_filter_meta
|
||||
return @@search_meta if @@search_meta
|
||||
@@search_meta = super.merge({
|
||||
interests: { keys: INTEREST_VALS, map: INTERESTS },
|
||||
ages: { keys: AGE_COUNTS, map: AGES }
|
||||
})
|
||||
end
|
||||
|
||||
def self.create_search(user)
|
||||
ms = self.new
|
||||
ms.user = user
|
||||
ms.data_blob = JSON_SCHEMA
|
||||
ms.save!
|
||||
ms
|
||||
def self.search_target_class
|
||||
User
|
||||
end
|
||||
|
||||
# XXX SQL INJECTION
|
||||
def _genres(rel)
|
||||
gids = json[KEY_GENRES]
|
||||
unless gids.blank?
|
||||
gidsql = gids.join("','")
|
||||
gpsql = "SELECT player_id FROM genre_players WHERE (player_type = 'JamRuby::User' AND genre_id IN ('#{gidsql}'))"
|
||||
rel = rel.where("users.id IN (#{gpsql})")
|
||||
end
|
||||
rel
|
||||
end
|
||||
|
||||
# XXX SQL INJECTION
|
||||
def _instruments(rel)
|
||||
unless (instruments = json['instruments']).blank?
|
||||
instsql = "SELECT player_id FROM musicians_instruments WHERE (("
|
||||
instsql += instruments.collect do |inst|
|
||||
"instrument_id = '#{inst['id']}' AND proficiency_level = #{inst['level']}"
|
||||
end.join(") OR (")
|
||||
instsql += "))"
|
||||
rel = rel.where("users.id IN (#{instsql})")
|
||||
end
|
||||
rel
|
||||
end
|
||||
|
||||
def _ages(rel)
|
||||
unless (vals = json[KEY_AGES]).blank?
|
||||
return rel if vals.detect { |vv| ANY_VAL_INT == vv }
|
||||
|
|
@ -193,7 +114,7 @@ module JamRuby
|
|||
|
||||
def _skills(rel)
|
||||
if 0 < (val = json[KEY_SKILL].to_i)
|
||||
rel = rel.where(['skill_level = ?', val])
|
||||
rel = rel.where(skill_level: val)
|
||||
end
|
||||
rel
|
||||
end
|
||||
|
|
@ -207,8 +128,8 @@ module JamRuby
|
|||
end
|
||||
|
||||
def _sort_order(rel)
|
||||
val = json[KEY_SORT_ORDER]
|
||||
if SORT_VALS[1] == val
|
||||
val = json[self.class::KEY_SORT_ORDER]
|
||||
if self.class::SORT_VALS[1] == val
|
||||
locidispid = self.user.last_jam_locidispid || 0
|
||||
my_locid = locidispid / 1000000
|
||||
rel = rel.joins("LEFT JOIN geoiplocations AS my_geo ON my_geo.locid = #{my_locid}")
|
||||
|
|
@ -235,45 +156,11 @@ module JamRuby
|
|||
rel
|
||||
end
|
||||
|
||||
def search_results_page(filter=nil, page=1)
|
||||
if filter
|
||||
self.data_blob = filter
|
||||
self.save
|
||||
else
|
||||
filter = self.data_blob
|
||||
end
|
||||
|
||||
rel = do_search(filter)
|
||||
|
||||
@page_number = [page.to_i, 1].max
|
||||
rel = rel.paginate(:page => @page_number, :per_page => PER_PAGE)
|
||||
|
||||
rel = rel.includes([:instruments, :followings, :friends])
|
||||
@page_count = rel.total_pages
|
||||
|
||||
musician_results(rel.all)
|
||||
end
|
||||
|
||||
def reset_filter
|
||||
self.data_blob = JSON_SCHEMA
|
||||
self.save
|
||||
def search_includes(rel)
|
||||
rel.includes([:instruments, :followings, :friends])
|
||||
end
|
||||
|
||||
def reset_search_results
|
||||
reset_filter
|
||||
search_results_page
|
||||
end
|
||||
|
||||
RESULT_FOLLOW = :follows
|
||||
RESULT_FRIEND = :friends
|
||||
|
||||
COUNT_FRIEND = :count_friend
|
||||
COUNT_FOLLOW = :count_follow
|
||||
COUNT_RECORD = :count_record
|
||||
COUNT_SESSION = :count_session
|
||||
COUNTERS = [COUNT_FRIEND, COUNT_FOLLOW, COUNT_RECORD, COUNT_SESSION]
|
||||
|
||||
def musician_results(_results)
|
||||
def process_results_page(_results)
|
||||
@results = _results
|
||||
@user_counters = {} and return self unless user
|
||||
|
||||
|
|
@ -351,7 +238,7 @@ module JamRuby
|
|||
end
|
||||
|
||||
def is_blank?
|
||||
self.data_blob == JSON_SCHEMA
|
||||
self.data_blob == self.class.json_schema
|
||||
end
|
||||
|
||||
def description
|
||||
|
|
|
|||
|
|
@ -173,6 +173,7 @@ module JamRuby
|
|||
has_many :performance_samples, :class_name => "JamRuby::PerformanceSample", :foreign_key=> 'player_id'
|
||||
|
||||
has_one :musician_search, :class_name => 'JamRuby::MusicianSearch'
|
||||
has_one :band_search, :class_name => 'JamRuby::BandSearch'
|
||||
|
||||
before_save :create_remember_token, :if => :should_validate_password?
|
||||
before_save :stringify_avatar_info , :if => :updating_avatar
|
||||
|
|
|
|||
|
|
@ -750,7 +750,7 @@ FactoryGirl.define do
|
|||
licensor_royalty_amount 0.999
|
||||
sequence(:plan_code) { |n| "jamtrack-#{n}" }
|
||||
|
||||
genre JamRuby::Genre.first
|
||||
genres [JamRuby::Genre.first]
|
||||
association :licensor, factory: :jam_track_licensor
|
||||
|
||||
factory :jam_track_with_tracks do
|
||||
|
|
|
|||
|
|
@ -22,11 +22,13 @@ describe JamTrackImporter do
|
|||
in_directory_with_file(metafile)
|
||||
|
||||
before(:each) do
|
||||
JamTrackImporter.storage_format = 'default'
|
||||
content_for_file(YAML.dump(sample_yml))
|
||||
end
|
||||
|
||||
it "no meta" do
|
||||
s3_metalocation = 'audio/Artist 1/Bogus Place/meta.yml'
|
||||
JamTrackImporter.storage_format = 'default'
|
||||
JamTrackImporter.load_metalocation(s3_metalocation).should be_nil
|
||||
end
|
||||
|
||||
|
|
@ -38,9 +40,105 @@ describe JamTrackImporter do
|
|||
end
|
||||
end
|
||||
|
||||
describe "sort_tracks" do
|
||||
let(:jam_track) { FactoryGirl.create(:jam_track) }
|
||||
let(:importer) { JamTrackImporter.new() }
|
||||
let(:vocal) {Instrument.find('voice')}
|
||||
let(:drums) {Instrument.find('drums')}
|
||||
let(:bass_guitar) {Instrument.find('bass guitar')}
|
||||
let(:piano) {Instrument.find('piano')}
|
||||
let(:keyboard) {Instrument.find('keyboard')}
|
||||
let(:acoustic_guitar) {Instrument.find('acoustic guitar')}
|
||||
let(:electric_guitar) {Instrument.find('electric guitar')}
|
||||
let(:other) {Instrument.find('other')}
|
||||
|
||||
it "the big sort" do
|
||||
# specified in https://jamkazam.atlassian.net/browse/VRFS-3296
|
||||
vocal_lead = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: vocal, part: 'Lead')
|
||||
vocal_lead_female = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: vocal, part: 'Lead Female')
|
||||
vocal_lead_male = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: vocal, part: 'Lead Male')
|
||||
vocal_backing = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: vocal, part: 'Backing')
|
||||
vocal_random = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: vocal, part: 'Random')
|
||||
drums_drums = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: drums, part: 'Drums')
|
||||
drums_percussion = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: drums, part: 'Percussion')
|
||||
drums_random_1 = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: drums, part: 'A')
|
||||
drums_random_2 = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: drums, part: 'C')
|
||||
bass_guitar_bass = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: bass_guitar, part: 'Bass')
|
||||
bass_guitar_random_1 = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: bass_guitar, part: 'some bass')
|
||||
bass_guitar_random_2 = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: bass_guitar, part: 'zome bass')
|
||||
piano_piano = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: piano, part: 'Piano')
|
||||
keyboard_synth_1 = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: keyboard, part: 'Synth 1')
|
||||
keyboard_synth_2 = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: keyboard, part: 'Synth 2')
|
||||
keyboard_pads = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: keyboard, part: 'Pads')
|
||||
keyboard_random_1 = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: keyboard, part: 'A')
|
||||
keyboard_random_2 = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: keyboard, part: 'Z')
|
||||
acoust_guitar_lead = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: acoustic_guitar, part: 'Lead')
|
||||
acoust_guitar_lead_x = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: acoustic_guitar, part: 'Lead X')
|
||||
acoust_guitar_solo_1 = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: acoustic_guitar, part: 'Solo 1')
|
||||
acoust_guitar_solo_2 = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: acoustic_guitar, part: 'Solo 2')
|
||||
acoust_guitar_rhythm = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: acoustic_guitar, part: 'Rhythm')
|
||||
acoust_guitar_random_1 = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: acoustic_guitar, part: 'A')
|
||||
acoust_guitar_random_2 = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: acoustic_guitar, part: 'Z')
|
||||
elect_guitar_lead = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: electric_guitar, part: 'Lead')
|
||||
elect_guitar_lead_x = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: electric_guitar, part: 'Lead X')
|
||||
elect_guitar_solo_1 = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: electric_guitar, part: 'Solo 1')
|
||||
elect_guitar_solo_2 = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: electric_guitar, part: 'Solo 2')
|
||||
elect_guitar_rhythm = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: electric_guitar, part: 'Rhythm')
|
||||
elect_guitar_random_1 = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: electric_guitar, part: 'A')
|
||||
elect_guitar_random_2 = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: electric_guitar, part: 'Z')
|
||||
other_1 = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: other, part: 'Other 1')
|
||||
other_2 = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: other, part: 'Other 2')
|
||||
|
||||
expected = [
|
||||
vocal_lead,
|
||||
vocal_lead_female,
|
||||
vocal_lead_male,
|
||||
vocal_backing,
|
||||
vocal_random,
|
||||
drums_drums,
|
||||
drums_percussion,
|
||||
drums_random_1,
|
||||
drums_random_2,
|
||||
bass_guitar_bass,
|
||||
piano_piano,
|
||||
keyboard_synth_1,
|
||||
keyboard_synth_2,
|
||||
keyboard_pads,
|
||||
keyboard_random_1,
|
||||
keyboard_random_2,
|
||||
acoust_guitar_lead,
|
||||
acoust_guitar_lead_x,
|
||||
acoust_guitar_rhythm,
|
||||
acoust_guitar_random_1,
|
||||
acoust_guitar_solo_1,
|
||||
acoust_guitar_solo_2,
|
||||
acoust_guitar_random_2,
|
||||
elect_guitar_lead,
|
||||
elect_guitar_lead_x,
|
||||
elect_guitar_solo_1,
|
||||
elect_guitar_solo_2,
|
||||
elect_guitar_rhythm,
|
||||
elect_guitar_random_1,
|
||||
elect_guitar_random_2,
|
||||
bass_guitar_random_1,
|
||||
bass_guitar_random_2,
|
||||
other_1,
|
||||
other_2
|
||||
]
|
||||
shuffled = expected.shuffle
|
||||
sorted_tracks = importer.sort_tracks(shuffled)
|
||||
|
||||
importer.set_custom_weight(vocal_lead).should eq(100)
|
||||
|
||||
expected.each_with_index do |expected_track, i|
|
||||
sorted_tracks[i].should eq(expected_track)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "synchronize" do
|
||||
let(:jam_track) { JamTrack.new }
|
||||
let(:importer) { JamTrackImporter.new }
|
||||
let(:importer) { JamTrackImporter.new() }
|
||||
let(:minimum_meta) { nil }
|
||||
let(:metalocation) { 'audio/Artist 1/Song 1/meta.yml' }
|
||||
let(:options) {{ skip_audio_upload:true }}
|
||||
|
|
@ -64,7 +162,7 @@ describe JamTrackImporter do
|
|||
|
||||
describe "parse_wav" do
|
||||
it "Guitar" do
|
||||
result = JamTrackImporter.new.parse_wav('blah/Ready for Love Stem - Guitar - Main.wav')
|
||||
result = JamTrackImporter.new.parse_file('blah/Ready for Love Stem - Guitar - Main.wav')
|
||||
result[:instrument].should eq('electric guitar')
|
||||
result[:part].should eq('Main')
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,6 +1,19 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe 'Band search' do
|
||||
describe 'Band Search Model' do
|
||||
|
||||
let!(:searcher) { FactoryGirl.create(:austin_user) }
|
||||
let!(:search) { BandSearch.user_search_filter(searcher) }
|
||||
|
||||
let!(:austin_user) { FactoryGirl.create(:austin_user) }
|
||||
let!(:dallas_user) { FactoryGirl.create(:dallas_user) }
|
||||
let!(:miami_user) { FactoryGirl.create(:miami_user) }
|
||||
let!(:seattle_user) { FactoryGirl.create(:seattle_user) }
|
||||
|
||||
let!(:user_types) { [:austin_user, :dallas_user, :miami_user, :seattle_user] }
|
||||
|
||||
let!(:to_join) { search.search_filter_for_subtype(BandSearch::TO_JOIN) }
|
||||
let!(:to_hire) { search.search_filter_for_subtype(BandSearch::TO_HIRE) }
|
||||
|
||||
before(:all) do
|
||||
Recording.delete_all
|
||||
|
|
@ -20,213 +33,310 @@ describe 'Band search' do
|
|||
FactoryGirl.create(:band_musician, :band => bb, :user => FactoryGirl.create(:user))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "creates search obj" do
|
||||
|
||||
before(:all) do
|
||||
User.delete_all
|
||||
end
|
||||
|
||||
it "associates to user" do
|
||||
expect(search.user).to eq(searcher)
|
||||
searcher.reload
|
||||
expect(searcher.band_search).to eq(search)
|
||||
end
|
||||
|
||||
it "sets json" do
|
||||
expect(search.search_filter_for_subtype(BandSearch::TO_JOIN)).to eq(BandSearch.json_schema[BandSearch::TO_JOIN])
|
||||
expect(search.search_filter_for_subtype(BandSearch::TO_HIRE)).to eq(BandSearch.json_schema[BandSearch::TO_HIRE])
|
||||
end
|
||||
|
||||
it "loads all bands by default" do
|
||||
search.search_results_page
|
||||
expect(search.results.count).to eq(Band.count)
|
||||
end
|
||||
|
||||
it "has follower counts" do
|
||||
Follow.create(user_id: searcher.id, followable: Band.first)
|
||||
search.search_results_page
|
||||
expect(search.follow_count(Band.first)).to eq(1)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
context 'default filter settings' do
|
||||
describe "generates description" do
|
||||
|
||||
it "finds all bands" do
|
||||
# expects all the bands
|
||||
num = Band.count
|
||||
results = Search.band_filter({ :per_page => num })
|
||||
expect(results.results.count).to eq(num)
|
||||
def check_description(_filter, subtype, key, value, lookup, label)
|
||||
_filter[key] = value
|
||||
search.search_results_page(subtype, _filter)
|
||||
expect(search.description(subtype)).to match(/Current Search: Sort = .*; #{label} = #{lookup[value]}$/)
|
||||
end
|
||||
|
||||
it "finds bands with proper ordering" do
|
||||
# the ordering should be create_at since no followers exist
|
||||
expect(Follow.count).to eq(0)
|
||||
results = Search.band_filter({ :per_page => Band.count })
|
||||
it "renders no description for blank" do
|
||||
search.search_results_page
|
||||
expect(search.description).to eq('')
|
||||
end
|
||||
|
||||
it "renders description for sort order" do
|
||||
to_join[BandSearch::KEY_TOUR_OPTION] = BandSearch::VAL_YES
|
||||
search.search_results_page(BandSearch::TO_JOIN, to_join)
|
||||
search.search_results_page
|
||||
expect(search.description).to match(/Sort =/)
|
||||
end
|
||||
|
||||
context "to_join" do
|
||||
|
||||
it "renders description for band type" do
|
||||
check_description(to_join,
|
||||
BandSearch::TO_JOIN,
|
||||
BandSearch::KEY_BAND_TYPE,
|
||||
BandSearch::BAND_TYPE_VAL_STRS[1],
|
||||
BandSearch::BAND_TYPES,
|
||||
'Band type')
|
||||
end
|
||||
|
||||
it "renders description for band status" do
|
||||
check_description(to_join,
|
||||
BandSearch::TO_JOIN,
|
||||
BandSearch::KEY_BAND_STATUS,
|
||||
BandSearch::SKILL_VALS[1],
|
||||
BandSearch::BAND_STATUS,
|
||||
'Band status')
|
||||
end
|
||||
|
||||
it "renders description for concert gigs" do
|
||||
check_description(to_join,
|
||||
BandSearch::TO_JOIN,
|
||||
BandSearch::KEY_GIGS,
|
||||
BandSearch::GIG_COUNTS[1],
|
||||
BandSearch::GIG_LABELS,
|
||||
'Concert gigs')
|
||||
end
|
||||
|
||||
it "renders description for play commitment" do
|
||||
check_description(to_join,
|
||||
BandSearch::TO_JOIN,
|
||||
BandSearch::KEY_PLAY_COMMIT,
|
||||
BandSearch::PLAY_COMMIT_VALS[1],
|
||||
BandSearch::PLAY_COMMITS,
|
||||
'Play commitment')
|
||||
end
|
||||
|
||||
it "renders description for tour option" do
|
||||
check_description(to_join,
|
||||
BandSearch::TO_JOIN,
|
||||
BandSearch::KEY_TOUR_OPTION,
|
||||
BandSearch::VAL_YES,
|
||||
BandSearch::TOUR_OPTIONS,
|
||||
'Touring options')
|
||||
end
|
||||
|
||||
it "renders description for genres" do
|
||||
to_join[BandSearch::KEY_GENRES] = [Genre.first.id]
|
||||
search.search_results_page(BandSearch::TO_JOIN, to_join)
|
||||
expect(search.description).to match(/Current Search: Sort = .*; Genres = #{Genre.first.description}$/)
|
||||
end
|
||||
|
||||
it "renders description for instruments" do
|
||||
to_join[BandSearch::KEY_INSTRUMENTS] = [{ 'instrument_id' => Instrument.first.id, 'proficiency_level' => 1 }]
|
||||
search.search_results_page(BandSearch::TO_JOIN, to_join)
|
||||
expect(search.description).to match(/Current Search: Sort = .*; Instruments = #{Instrument.first.description} \(#{BandSearch::INSTRUMENT_PROFICIENCY[1]}\)$/)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
context "to_hire" do
|
||||
it "renders description for genres" do
|
||||
to_hire[BandSearch::KEY_GENRES] = [Genre.first.id]
|
||||
search.search_results_page(BandSearch::TO_HIRE, to_hire)
|
||||
expect(search.description(BandSearch::TO_HIRE)).to match(/Current Search: Sort = .*; Genres = #{Genre.first.description}$/)
|
||||
end
|
||||
|
||||
it "renders description for band status" do
|
||||
check_description(to_hire,
|
||||
BandSearch::TO_HIRE,
|
||||
BandSearch::KEY_BAND_STATUS,
|
||||
BandSearch::BAND_STATUS_VALS[1],
|
||||
BandSearch::BAND_STATUS,
|
||||
'Band status')
|
||||
end
|
||||
|
||||
it "renders description for concert gigs" do
|
||||
check_description(to_hire,
|
||||
BandSearch::TO_HIRE,
|
||||
BandSearch::KEY_GIGS,
|
||||
BandSearch::GIG_COUNTS[1],
|
||||
BandSearch::GIG_LABELS,
|
||||
'Concert gigs')
|
||||
end
|
||||
|
||||
it "renders description for performance samples" do
|
||||
check_description(to_hire,
|
||||
BandSearch::TO_HIRE,
|
||||
BandSearch::KEY_PERF_SAMPLES,
|
||||
BandSearch::PERF_SAMPLES_VALS[1],
|
||||
BandSearch::PERF_SAMPLES,
|
||||
'Performance samples')
|
||||
end
|
||||
|
||||
it "renders description max cost" do
|
||||
to_hire[BandSearch::KEY_HIRE_MAX_COST] = 100
|
||||
search.search_results_page(BandSearch::TO_HIRE, to_hire)
|
||||
expect(search.description(BandSearch::TO_HIRE)).to match(/Current Search: Sort = .*; Maximum gig cost = \$100$/)
|
||||
end
|
||||
|
||||
it "renders description free gigs" do
|
||||
to_hire[BandSearch::KEY_HIRE_FREE] = 1
|
||||
search.search_results_page(BandSearch::TO_HIRE, to_hire)
|
||||
expect(search.description(BandSearch::TO_HIRE)).to match(/Current Search: Sort = .*; Bands playing free gigs$/)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
describe "filtering by keys" do
|
||||
|
||||
let!(:band) { Band.first }
|
||||
|
||||
context 'all search keys' do
|
||||
|
||||
let!(:filter) { to_join }
|
||||
|
||||
it "filters by gigs" do
|
||||
band.update_attribute(:concert_count, BandSearch::GIG_COUNTS[2])
|
||||
filter[BandSearch::KEY_GIGS] = BandSearch::GIG_COUNTS[2]
|
||||
search.search_results_page(BandSearch::TO_JOIN, filter)
|
||||
expect(search.results.count).to eq(1)
|
||||
expect(search.results[0].id).to eq(band.id)
|
||||
end
|
||||
it "filters by genre" do
|
||||
band_id = band.id
|
||||
filter[BandSearch::KEY_GENRES] = [band_id]
|
||||
search.search_results_page(BandSearch::TO_JOIN, filter)
|
||||
expect(search.results.count).to eq(Band.all.map(&:genres).flatten.select { |bb| bb.id == band_id }.count)
|
||||
end
|
||||
|
||||
it "filters by band_type" do
|
||||
band.update_attribute(:band_type, BandSearch::BAND_TYPE_VAL_STRS[1])
|
||||
filter[BandSearch::KEY_BAND_TYPE] = BandSearch::BAND_TYPE_VAL_STRS[1]
|
||||
search.search_results_page(BandSearch::TO_JOIN, filter)
|
||||
expect(search.results.count).to eq(1)
|
||||
expect(search.results[0].id).to eq(band.id)
|
||||
end
|
||||
|
||||
it "filters by instruments" do
|
||||
minst = FactoryGirl.create(:musician_instrument)
|
||||
band.musician_instruments << minst
|
||||
band.save
|
||||
filter[BandSearch::KEY_INSTRUMENTS] = [{'instrument_id' => minst.instrument_id,
|
||||
'proficiency_level' => minst.proficiency_level
|
||||
}]
|
||||
search.search_results_page(BandSearch::TO_JOIN, filter)
|
||||
expect(search.results.count).to eq(1)
|
||||
expect(search.results[0].id).to eq(band.id)
|
||||
|
||||
filter[BandSearch::KEY_INSTRUMENTS] = [{'instrument_id' => minst.instrument_id,
|
||||
'proficiency_level' => minst.proficiency_level + 1
|
||||
}]
|
||||
search.search_results_page(BandSearch::TO_JOIN, filter)
|
||||
expect(search.results.count).to eq(0)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
context 'to_join' do
|
||||
|
||||
let!(:filter) { to_join }
|
||||
|
||||
it "sorts by distance" do
|
||||
bands = Band.all.reverse
|
||||
bb = bands.first
|
||||
bb.lat, bb.lng = austin_geoip[:geoiplocation].latitude, austin_geoip[:geoiplocation].longitude
|
||||
bb.save!
|
||||
bb = bands.second
|
||||
bb.lat, bb.lng = dallas_geoip[:geoiplocation].latitude, dallas_geoip[:geoiplocation].longitude
|
||||
bb.save!
|
||||
bb = bands.third
|
||||
bb.lat, bb.lng = miami_geoip[:geoiplocation].latitude, miami_geoip[:geoiplocation].longitude
|
||||
bb.save!
|
||||
bb = bands.fourth
|
||||
bb.lat, bb.lng = seattle_geoip[:geoiplocation].latitude, seattle_geoip[:geoiplocation].longitude
|
||||
bb.save!
|
||||
|
||||
filter[BandSearch::KEY_SORT_ORDER] = BandSearch::SORT_VALS[0]
|
||||
search.search_results_page(BandSearch::TO_JOIN, filter)
|
||||
expect(search.results.count).to eq(Band.count)
|
||||
expect(search.results.first.id).to eq(bands.first.id)
|
||||
expect(search.results.second.id).to eq(bands.second.id)
|
||||
expect(search.results.third.id).to eq(bands.third.id)
|
||||
expect(search.results.fourth.id).to eq(bands.fourth.id)
|
||||
end
|
||||
|
||||
it "filters by play commitment" do
|
||||
band.update_attribute(BandSearch::KEY_PLAY_COMMIT, BandSearch::PLAY_COMMIT_VALS[1].to_i)
|
||||
filter[BandSearch::KEY_PLAY_COMMIT] = BandSearch::PLAY_COMMIT_VALS[1]
|
||||
search.search_results_page(BandSearch::TO_JOIN, filter)
|
||||
expect(search.results.count).to eq(1)
|
||||
expect(search.results[0].id).to eq(band.id)
|
||||
end
|
||||
|
||||
it "filters by tour option" do
|
||||
band.update_attribute(BandSearch::KEY_TOUR_OPTION, true)
|
||||
filter[BandSearch::KEY_TOUR_OPTION] = BandSearch::VAL_YES
|
||||
search.search_results_page(BandSearch::TO_JOIN, filter)
|
||||
expect(search.results.count).to eq(1)
|
||||
expect(search.results[0].id).to eq(band.id)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
context 'to_hire' do
|
||||
|
||||
rbands = @bands.reverse
|
||||
results.results.each_with_index do |uu, idx|
|
||||
expect(uu.id).to eq(@bands.reverse[idx].id)
|
||||
end
|
||||
end
|
||||
let!(:filter) { to_hire }
|
||||
|
||||
it "sorts bands by followers" do
|
||||
users = []
|
||||
4.downto(1) { |nn| users << FactoryGirl.create(:user) }
|
||||
|
||||
users.each_with_index do |u, index|
|
||||
if index != 0
|
||||
f1 = Follow.new
|
||||
f1.user = u
|
||||
f1.followable = @band4
|
||||
f1.save
|
||||
end
|
||||
it "filters by free gigs" do
|
||||
band.update_attribute(BandSearch::KEY_HIRE_FREE, true)
|
||||
filter[BandSearch::KEY_HIRE_FREE] = BandSearch::VAL_YES
|
||||
search.search_results_page(BandSearch::TO_HIRE, filter)
|
||||
expect(search.results.count).to eq(1)
|
||||
expect(search.results[0].id).to eq(band.id)
|
||||
end
|
||||
|
||||
users.each_with_index do |u, index|
|
||||
if index != 0
|
||||
f1 = Follow.new
|
||||
f1.user = u
|
||||
f1.followable = @band3
|
||||
f1.save
|
||||
end
|
||||
it "filters by max cost" do
|
||||
band.update_attribute(:gig_minimum, 10)
|
||||
filter[BandSearch::KEY_HIRE_MAX_COST] = 5
|
||||
search.search_results_page(BandSearch::TO_HIRE, filter)
|
||||
expect(search.results.count).to eq(0)
|
||||
|
||||
filter[BandSearch::KEY_HIRE_MAX_COST] = 15
|
||||
search.search_results_page(BandSearch::TO_HIRE, filter)
|
||||
expect(search.results.count).to eq(1)
|
||||
end
|
||||
|
||||
f1 = Follow.new
|
||||
f1.user = users.first
|
||||
f1.followable = @band2
|
||||
f1.save
|
||||
it "filters by perform samples" do
|
||||
filter[BandSearch::KEY_PERF_SAMPLES] = BandSearch::VAL_YES
|
||||
search.search_results_page(BandSearch::TO_HIRE, filter)
|
||||
expect(search.results.count).to eq(0)
|
||||
|
||||
# establish sorting order
|
||||
# @band4.followers.concat(users[1..-1])
|
||||
# @band3.followers.concat(users[1..3])
|
||||
# @band2.followers.concat(users[0])
|
||||
@bands.map(&:reload)
|
||||
filter[BandSearch::KEY_PERF_SAMPLES] = BandSearch::VAL_NO
|
||||
search.search_results_page(BandSearch::TO_HIRE, filter)
|
||||
expect(search.results.count).to eq(Band.count)
|
||||
|
||||
expect(@band4.followers.count).to be 3
|
||||
expect(Follow.count).to be 7
|
||||
|
||||
# refresh the order to ensure it works right
|
||||
users.each_with_index do |u, index|
|
||||
if index != 0
|
||||
f1 = Follow.new
|
||||
f1.user = u
|
||||
f1.followable = @band2
|
||||
f1.save
|
||||
end
|
||||
ps = PerformanceSample.new
|
||||
ps.player = band
|
||||
ps.service_type = 'youtube'
|
||||
ps.service_id = 'abc123'
|
||||
ps.save
|
||||
# PerformanceSample.create(player: band, service_type: 'youtube', service_id: 'abc123')
|
||||
filter[BandSearch::KEY_PERF_SAMPLES] = BandSearch::VAL_YES
|
||||
search.search_results_page(BandSearch::TO_HIRE, filter)
|
||||
expect(search.results.count).to eq(1)
|
||||
expect(search.results[0].id).to eq(band.id)
|
||||
end
|
||||
|
||||
# @band2.followers.concat(users[1..-1])
|
||||
results = Search.band_filter({ :per_page => @bands.size }, users[0])
|
||||
expect(results.results[0].id).to eq(@band2.id)
|
||||
|
||||
# check the follower count for given entry
|
||||
expect(results.results[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_filter(params)
|
||||
expect(results.results.count).to be 2
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def make_session(band)
|
||||
usr = band.users[0]
|
||||
session = FactoryGirl.create(:active_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) }
|
||||
|
||||
users.each do |u|
|
||||
f1 = Follow.new
|
||||
f1.user = u
|
||||
f1.followable = @band1
|
||||
f1.save
|
||||
end
|
||||
|
||||
# establish sorting order
|
||||
# @band1.followers.concat(users)
|
||||
results = Search.band_filter({},@band1)
|
||||
uu = results.results.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_filter({},@band1)
|
||||
uu = results.results.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_filter({ :orderby => 'plays' })
|
||||
expect(results.results[0].id).to eq(@band2.id)
|
||||
expect(results.results[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(:active_music_session, :music_session => session)
|
||||
|
||||
results = Search.band_filter({ :orderby => 'playing' })
|
||||
expect(results.results.count).to be 1
|
||||
expect(results.results.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(:active_music_session, :music_session => session)
|
||||
results = Search.band_filter({ :orderby => 'playing' })
|
||||
expect(results.results.count).to be 2
|
||||
expect(results.results[0].id).to eq(@band4.id)
|
||||
expect(results.results[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_filter({ :genre => ggg.id })
|
||||
results.results.each do |rr|
|
||||
expect(rr.genres.detect { |gg| gg.id==ggg.id }.id).to eq(genre.id)
|
||||
end
|
||||
expect(results.results.count).to be 1
|
||||
end
|
||||
|
||||
it "finds bands within a given distance of given location" do
|
||||
pending 'distance search changes'
|
||||
num = Band.count
|
||||
expect(@band1.lat).to_not be_nil
|
||||
# short distance
|
||||
results = Search.band_filter({ :per_page => num,
|
||||
:distance => 10,
|
||||
:city => 'Apex' }, @band1)
|
||||
expect(results.results.count).to be num
|
||||
# long distance
|
||||
results = Search.band_filter({ :per_page => num,
|
||||
:distance => 1000,
|
||||
:city => 'Miami',
|
||||
:state => 'FL' }, @band1)
|
||||
expect(results.results.count).to be num
|
||||
end
|
||||
|
||||
it "finds bands within a given distance of bands location" do
|
||||
pending 'distance search changes'
|
||||
expect(@band1.lat).to_not be_nil
|
||||
# uses the location of @band1
|
||||
results = Search.band_filter({ :distance => 10, :per_page => Band.count }, @band1)
|
||||
expect(results.results.count).to be Band.count
|
||||
end
|
||||
|
||||
it "finds no bands within a given distance of location" do
|
||||
pending 'distance search changes'
|
||||
expect(@band1.lat).to_not be_nil
|
||||
results = Search.band_filter({ :distance => 10, :city => 'San Francisco' }, @band1)
|
||||
expect(results.results.count).to be 0
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -12,6 +12,90 @@ describe JamTrack do
|
|||
jam_track = FactoryGirl.create(:jam_track)
|
||||
jam_track.licensor.should_not be_nil
|
||||
jam_track.licensor.jam_tracks.should == [jam_track]
|
||||
jam_track.genres.length.should eq(1)
|
||||
end
|
||||
|
||||
describe 'sync_reproduction_royalty' do
|
||||
it "all possible conditions" do
|
||||
jam_track = FactoryGirl.create(:jam_track)
|
||||
jam_track.reproduction_royalty_amount.should be_nil
|
||||
|
||||
jam_track.duration = 0
|
||||
jam_track.save!
|
||||
jam_track.reproduction_royalty_amount.to_f.should eq(0.091)
|
||||
|
||||
jam_track.duration = 1
|
||||
jam_track.save!
|
||||
jam_track.reproduction_royalty_amount.to_f.should eq(0.091)
|
||||
|
||||
jam_track.duration = 5 * 60 - 1 # just under 5 minutes
|
||||
jam_track.save!
|
||||
jam_track.reproduction_royalty_amount.to_f.should eq(0.091)
|
||||
|
||||
jam_track.duration = 5 * 60
|
||||
jam_track.save!
|
||||
jam_track.reproduction_royalty_amount.to_f.should eq(0.091)
|
||||
|
||||
jam_track.duration = 6 * 60 - 1 # just under 6 minutes
|
||||
jam_track.save!
|
||||
jam_track.reproduction_royalty_amount.should eq(0.091 + 0.0175)
|
||||
|
||||
jam_track.duration = 6 * 60
|
||||
jam_track.save!
|
||||
jam_track.reproduction_royalty_amount.should eq(0.091 + 0.0175)
|
||||
|
||||
jam_track.duration = 7 * 60 - 1
|
||||
jam_track.save!
|
||||
jam_track.reproduction_royalty_amount.should eq(0.091 + 0.0175 * 2)
|
||||
|
||||
jam_track.duration = 7 * 60
|
||||
jam_track.save!
|
||||
jam_track.reproduction_royalty_amount.should eq(0.091 + 0.0175 * 2)
|
||||
|
||||
jam_track.duration = 8 * 60 - 1
|
||||
jam_track.save!
|
||||
jam_track.reproduction_royalty_amount.should eq(0.091 + 0.0175 * 3)
|
||||
|
||||
jam_track.duration = 8 * 60
|
||||
jam_track.save!
|
||||
jam_track.reproduction_royalty_amount.should eq(0.091 + 0.0175 * 3)
|
||||
|
||||
jam_track.duration = 9 * 60 - 1
|
||||
jam_track.save!
|
||||
jam_track.reproduction_royalty_amount.should eq(0.091 + 0.0175 * 4)
|
||||
|
||||
jam_track.duration = 9 * 60
|
||||
jam_track.save!
|
||||
jam_track.reproduction_royalty_amount.should eq(0.091 + 0.0175 * 4)
|
||||
|
||||
jam_track.duration = 10 * 60 - 1
|
||||
jam_track.save!
|
||||
jam_track.reproduction_royalty_amount.should eq(0.091 + 0.0175 * 5)
|
||||
|
||||
jam_track.duration = 10 * 60
|
||||
jam_track.save!
|
||||
jam_track.reproduction_royalty_amount.should eq(0.091 + 0.0175 * 5)
|
||||
|
||||
jam_track.duration = 11 * 60 - 1
|
||||
jam_track.save!
|
||||
jam_track.reproduction_royalty_amount.should eq(0.091 + 0.0175 * 6)
|
||||
|
||||
jam_track.duration = 11 * 60
|
||||
jam_track.save!
|
||||
jam_track.reproduction_royalty_amount.should eq(0.091 + 0.0175 * 6)
|
||||
|
||||
jam_track.duration = 12 * 60 - 1
|
||||
jam_track.save!
|
||||
jam_track.reproduction_royalty_amount.should eq(0.091 + 0.0175 * 7)
|
||||
|
||||
jam_track.duration = 12 * 60
|
||||
jam_track.save!
|
||||
jam_track.reproduction_royalty_amount.should eq(0.091 + 0.0175 * 7)
|
||||
|
||||
jam_track.duration = 13 * 60
|
||||
jam_track.save!
|
||||
jam_track.reproduction_royalty_amount.should eq(0.091 + 0.0175 * 8)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'plays' do
|
||||
|
|
@ -98,6 +182,26 @@ describe JamTrack do
|
|||
query[1].should eq(jam_track1)
|
||||
end
|
||||
|
||||
it "queries on genre" do
|
||||
jam_track1 = FactoryGirl.create(:jam_track_with_tracks, original_artist: 'artist', name: 'a')
|
||||
jam_track2 = FactoryGirl.create(:jam_track_with_tracks, original_artist: 'artist', name: 'b')
|
||||
jam_track1.genres = [Genre.find('rock')]
|
||||
jam_track2.genres = [Genre.find('asian')]
|
||||
jam_track1.save!
|
||||
jam_track2.save!
|
||||
|
||||
query, pager = JamTrack.index({genre: 'rock'}, user)
|
||||
query.size.should == 1
|
||||
query[0].should eq(jam_track1)
|
||||
|
||||
query, pager = JamTrack.index({genre: 'asian'}, user)
|
||||
query.size.should == 1
|
||||
query[0].should eq(jam_track2)
|
||||
|
||||
query, pager = JamTrack.index({genre: 'african'}, user)
|
||||
query.size.should == 0
|
||||
end
|
||||
|
||||
it "supports showing purchased only" do
|
||||
jam_track1 = FactoryGirl.create(:jam_track_with_tracks, name: 'a')
|
||||
|
||||
|
|
@ -170,7 +274,7 @@ describe JamTrack do
|
|||
end
|
||||
|
||||
it "100.1234" do
|
||||
jam_track = FactoryGirl.build(:jam_track, reproduction_royalty_amount: 100.1234)
|
||||
jam_track = FactoryGirl.build(:jam_track, reproduction_royalty_amount: 100.12345)
|
||||
jam_track.valid?.should be_false
|
||||
jam_track.errors[:reproduction_royalty_amount].should == ['is invalid']
|
||||
end
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ describe JamTrackTrack do
|
|||
it "created" do
|
||||
jam_track_track = FactoryGirl.create(:jam_track_track)
|
||||
jam_track_track.jam_track.should_not be_nil
|
||||
jam_track_track.jam_track.reload
|
||||
jam_track_track.jam_track.jam_track_tracks.should == [jam_track_track]
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -115,7 +115,8 @@ group :development, :test do
|
|||
gem 'test-unit'
|
||||
# gem 'teaspoon'
|
||||
# gem 'teaspoon-jasmine'
|
||||
# gem 'puma'
|
||||
gem 'puma'
|
||||
gem 'byebug'
|
||||
end
|
||||
group :unix do
|
||||
gem 'therubyracer' #, '0.11.0beta8'
|
||||
|
|
|
|||
|
|
@ -1,257 +0,0 @@
|
|||
(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;
|
||||
var helpBubble = context.JK.HelpBubbleHelper;
|
||||
var $screen = $('#bands-screen');
|
||||
var $results = $screen.find('#band-filter-results');
|
||||
|
||||
function loadBands(queryString) {
|
||||
// squelch nulls and undefines
|
||||
queryString = !!queryString ? queryString : "";
|
||||
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
url: "/api/search.json?" + queryString,
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 eTemplate = $('#template-band-edit-btns').html();
|
||||
var bVals, bb, renderings='';
|
||||
var instr_logos, instr;
|
||||
var players, playerVals, aPlayer, isMember;
|
||||
|
||||
for (ii=0, len=bands.length; ii < len; ii++) {
|
||||
bb = bands[ii];
|
||||
instr_logos = '';
|
||||
players = '';
|
||||
playerVals = {};
|
||||
isMember = false;
|
||||
for (var jj=0, ilen=bb['players'].length; jj<ilen; jj++) {
|
||||
var toolTip = '';
|
||||
aPlayer = bb['players'][jj];
|
||||
var player_instrs = '';
|
||||
var iter_pinstruments = aPlayer['instruments'].split(',');
|
||||
for (var kk=0, klen=iter_pinstruments.length; kk<klen; kk++) {
|
||||
var pinstr = iter_pinstruments[kk];
|
||||
var toolTip = '';
|
||||
if (pinstr in instrument_logo_map) {
|
||||
instr = instrument_logo_map[pinstr].asset;
|
||||
toolTip = pinstr;
|
||||
}
|
||||
player_instrs += '<img src="' + instr + '" title="' + toolTip + '"/>';
|
||||
}
|
||||
if (!isMember) {
|
||||
isMember = aPlayer.user_id == context.JK.currentUserId;
|
||||
}
|
||||
playerVals = {
|
||||
user_id: aPlayer.user_id,
|
||||
player_name: aPlayer.name,
|
||||
profile_url: '/client#/profile/' + aPlayer.user_id,
|
||||
avatar_url: context.JK.resolveAvatarUrl(aPlayer.photo_url),
|
||||
player_instruments: player_instrs
|
||||
};
|
||||
|
||||
players += context.JK.fillTemplate(pTemplate, playerVals);
|
||||
}
|
||||
|
||||
var actionVals, band_actions;
|
||||
if (isMember) {
|
||||
actionVals = {
|
||||
profile_url: "/client#/bandProfile/" + bb.id,
|
||||
band_edit_url: "/client#/band/setup/" + bb.id + '/step1',
|
||||
band_member_url: "/client#/band/setup/" + bb.id + '/step2'
|
||||
};
|
||||
band_actions = context.JK.fillTemplate(eTemplate, actionVals);
|
||||
} else {
|
||||
actionVals = {
|
||||
profile_url: "/client#/bandProfile/" + bb.id,
|
||||
button_follow: bb['is_following'] ? '' : 'button-orange',
|
||||
button_message: 'button-orange'
|
||||
};
|
||||
band_actions = context.JK.fillTemplate(aTemplate, actionVals);
|
||||
}
|
||||
|
||||
var bgenres = '';
|
||||
for (jj=0, ilen=bb['genres'].length; jj<ilen; jj++) {
|
||||
bgenres += bb['genres'][jj]['description'] + '<br />';
|
||||
}
|
||||
|
||||
bgenres += '<br />';
|
||||
|
||||
bVals = {
|
||||
avatar_url: context.JK.resolveBandAvatarUrl(bb.photo_url),
|
||||
profile_url: "/client#/bandProfile/" + 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 $rendering = $(context.JK.fillTemplate(mTemplate, bVals))
|
||||
|
||||
var $offsetParent = $results.closest('.content');
|
||||
var data = {entity_type: 'band'};
|
||||
|
||||
var options = {positions: ['top', 'bottom', 'right', 'left'], offsetParent: $offsetParent};
|
||||
context.JK.helpBubble($('.follower-count', $rendering), 'follower-count', data, options);
|
||||
context.JK.helpBubble($('.recording-count', $rendering), 'recording-count', data, options);
|
||||
context.JK.helpBubble($('.session-count', $rendering), 'session-count', data, options);
|
||||
|
||||
$results.append($rendering);
|
||||
}
|
||||
|
||||
$('.search-m-follow').on('click', followBand);
|
||||
context.JK.bindHoverEvents();
|
||||
}
|
||||
|
||||
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
|
||||
// @FIXME -- this will need to be tweaked when we allow unfollowing
|
||||
$('div[data-band-id='+newFollowing.band_id+'] .search-m-follow').removeClass('button-orange').addClass('button-grey');
|
||||
},
|
||||
error: app.ajaxError(arguments)
|
||||
});
|
||||
}
|
||||
|
||||
function events() {
|
||||
$('#band_query_distance').change(refreshDisplay);
|
||||
$('#band_genre').change(refreshDisplay);
|
||||
$('#band_order_by').change(refreshDisplay);
|
||||
|
||||
$('#band-filter-results').closest('.content-body-scroller').bind('scroll', function() {
|
||||
if ($(this).scrollTop() + $(this).innerHeight() >= $(this)[0].scrollHeight) {
|
||||
if (page_num < page_count) {
|
||||
page_num += 1;
|
||||
search();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
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);
|
||||
|
|
@ -1798,6 +1798,19 @@
|
|||
});
|
||||
}
|
||||
|
||||
function getBandSearchFilter(query) {
|
||||
var qarg = query === undefined ? '' : query;
|
||||
return $.get("/api/search/bands.json?"+qarg);
|
||||
}
|
||||
|
||||
function postBandSearchFilter(query) {
|
||||
return $.ajax({
|
||||
type: "POST",
|
||||
url: "/api/search/bands.json",
|
||||
data: query
|
||||
});
|
||||
}
|
||||
|
||||
function getMount(options) {
|
||||
var id = getId(options);
|
||||
return $.ajax({
|
||||
|
|
@ -2046,6 +2059,8 @@
|
|||
this.addRecordingTimeline = addRecordingTimeline;
|
||||
this.getMusicianSearchFilter = getMusicianSearchFilter;
|
||||
this.postMusicianSearchFilter = postMusicianSearchFilter;
|
||||
this.getBandSearchFilter = getBandSearchFilter;
|
||||
this.postBandSearchFilter = postBandSearchFilter;
|
||||
this.playJamTrack = playJamTrack;
|
||||
this.createSignupHint = createSignupHint;
|
||||
this.createAlert = createAlert;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,858 @@
|
|||
$ = jQuery
|
||||
context = window
|
||||
context.JK ||= {};
|
||||
|
||||
context.JK.BaseSearchFilter = class BaseSearchFilter
|
||||
|
||||
constructor: () ->
|
||||
@rest = context.JK.Rest()
|
||||
@logger = context.JK.logger
|
||||
@searchFilter = null
|
||||
@profileUtils = context.JK.ProfileUtils
|
||||
@helpBubble = context.JK.HelpBubbleHelper
|
||||
@searchResults = null
|
||||
@isSearching = false
|
||||
@pageNumber = 1
|
||||
@instrument_logo_map = context.JK.getInstrumentIconMap24()
|
||||
@searchType = ''
|
||||
@searchTypeS = ''
|
||||
@restGet = null
|
||||
@restPost = null
|
||||
@searchMeta = null
|
||||
|
||||
init: (app) =>
|
||||
@app = app
|
||||
@screenBindings = { 'afterShow': this.afterShow, 'afterHide': this.afterHide }
|
||||
@app.bindScreen(@searchTypeS, @screenBindings)
|
||||
|
||||
@screen = $('#'+@searchTypeS+'-screen')
|
||||
@resultsListContainer = @screen.find('#'+@searchType+'-search-filter-results-list')
|
||||
@spinner = @screen.find('.paginate-wait')
|
||||
|
||||
this.registerResultsPagination()
|
||||
|
||||
afterShow: () =>
|
||||
@screen.find('#'+@searchType+'-search-filter-results').show()
|
||||
@screen.find('#'+@searchType+'-search-filter-builder').hide()
|
||||
this.getUserFilterResults()
|
||||
|
||||
showBuilder: () =>
|
||||
@screen.find('#'+@searchType+'-search-filter-results').hide()
|
||||
@screen.find('#'+@searchType+'-search-filter-builder').show()
|
||||
@resultsListContainer.empty()
|
||||
|
||||
afterHide: () =>
|
||||
@resultsListContainer.empty()
|
||||
|
||||
searchMetaData: () =>
|
||||
@searchMeta
|
||||
|
||||
filterData: () =>
|
||||
@searchFilter.data_blob
|
||||
|
||||
renderSearchFilter: () =>
|
||||
$.when(@restGet()).done (sFilter) =>
|
||||
this.loadSearchFilter(sFilter)
|
||||
|
||||
loadSearchFilter: (sFilter) =>
|
||||
|
||||
_populateSelectWithKeys: (struct, selection, keys, element) =>
|
||||
element.children().remove()
|
||||
$.each keys, (idx, value) =>
|
||||
label = struct[value]
|
||||
blankOption = $ '<option value=""></option>'
|
||||
blankOption.text label
|
||||
blankOption.attr 'value', value
|
||||
blankOption.attr 'selected', '' if value == selection
|
||||
element.append(blankOption)
|
||||
context.JK.dropdown(element)
|
||||
|
||||
_populateSelectIdentifier: (identifier) =>
|
||||
elem = $ '#'+@searchType+'-search-filter-builder select[name='+identifier+']'
|
||||
struct = this.searchMetaData()[identifier]['map']
|
||||
keys = this.searchMetaData()[identifier]['keys']
|
||||
this._populateSelectWithKeys(struct, this.filterData()[identifier], keys, elem)
|
||||
|
||||
_populateSelectWithInt: (sourceStruct, selection, element) =>
|
||||
struct =
|
||||
'-1': 'Any'
|
||||
$.extend(struct, sourceStruct)
|
||||
this._populateSelectWithKeys(struct, selection, Object.keys(struct).sort(), element)
|
||||
|
||||
_populateSortOrder: () =>
|
||||
this._populateSelectIdentifier('sort_order')
|
||||
|
||||
_populateGigs: () =>
|
||||
elem = $ '#'+@searchType+'-search-filter-builder select[name=concert_gigs]'
|
||||
this._populateSelectWithInt(@profileUtils.gigMap, this.filterData().concert_gigs.toString(), elem)
|
||||
|
||||
_populateGenres: () =>
|
||||
@screen.find('#search-filter-genres').empty()
|
||||
@rest.getGenres().done (genres) =>
|
||||
genreTemplate = @screen.find('#template-search-filter-setup-genres').html()
|
||||
filterGenres = this.filterData().genres
|
||||
$.each genres, (index, genre) =>
|
||||
if 0 < filterGenres.length
|
||||
genreMatch = $.grep(filterGenres, (n, i) ->
|
||||
n == genre.id)
|
||||
else
|
||||
genreMatch = []
|
||||
if genreMatch.length > 0 then selected = 'checked' else selected = ''
|
||||
genreHtml = context.JK.fillTemplate(genreTemplate,
|
||||
id: genre.id
|
||||
description: genre.description
|
||||
checked: selected)
|
||||
@screen.find('#search-filter-genres').append genreHtml
|
||||
|
||||
_populateInstruments: () =>
|
||||
@screen.find('#search-filter-instruments').empty()
|
||||
@rest.getInstruments().done (instruments) =>
|
||||
$.each instruments, (index, instrument) =>
|
||||
instrumentTemplate = @screen.find('#template-search-filter-setup-instrument').html()
|
||||
selected = ''
|
||||
proficiency = '1'
|
||||
if 0 < this.filterData().instruments.length
|
||||
instMatch = $.grep(this.filterData().instruments, (inst, i) ->
|
||||
yn = inst.instrument_id == instrument.id
|
||||
proficiency = inst.proficiency_level if yn
|
||||
yn)
|
||||
selected = 'checked' if instMatch.length > 0
|
||||
instrumentHtml = context.JK.fillTemplate(instrumentTemplate,
|
||||
id: instrument.id
|
||||
description: instrument.description
|
||||
checked: selected)
|
||||
@screen.find('#search-filter-instruments').append instrumentHtml
|
||||
profsel = '#search-filter-instruments tr[data-instrument-id="'+instrument.id+'"] select'
|
||||
jprofsel = @screen.find(profsel)
|
||||
jprofsel.val(proficiency)
|
||||
context.JK.dropdown(jprofsel)
|
||||
return true
|
||||
|
||||
_builderSelectValue: (identifier) =>
|
||||
elem = $ '#'+@searchType+'-search-filter-builder select[name='+identifier+']'
|
||||
elem.val()
|
||||
|
||||
_builderSelectMultiValue: (identifier) =>
|
||||
vals = []
|
||||
elem = $ '#search-filter-'+identifier+' input[type=checkbox]:checked'
|
||||
if 'instruments' == identifier
|
||||
elem.each (idx) ->
|
||||
row = $(this).parent().parent()
|
||||
instrument =
|
||||
instrument_id: row.data('instrument-id')
|
||||
proficiency_level: row.find('select').val()
|
||||
vals.push instrument
|
||||
else
|
||||
elem.each (idx) ->
|
||||
if $(this).prop('checked')
|
||||
vals.push $(this).val()
|
||||
vals
|
||||
|
||||
willSearch: (reload) =>
|
||||
return false if @isSearching
|
||||
@isSearching = true
|
||||
if reload
|
||||
@pageNumber = 1
|
||||
@screen.find('#'+@searchType+'-search-filter-spinner').show()
|
||||
@resultsListContainer.empty()
|
||||
@screen.find('#'+@searchType+'-search-filter-builder').hide()
|
||||
@screen.find('#'+@searchType+'-search-filter-results').show()
|
||||
true
|
||||
|
||||
didSearch: (response) =>
|
||||
this.loadSearchFilter(response.filter_json)
|
||||
@searchResults = response
|
||||
@screen.find('#'+@searchType+'-search-filter-spinner').hide()
|
||||
this.renderResultsPage()
|
||||
@screen.find('.paginate-wait').hide()
|
||||
@isSearching = false
|
||||
|
||||
resetFilter: () =>
|
||||
if this.willSearch(true)
|
||||
@restPost({ filter: 'reset' }).done(this.didSearch)
|
||||
|
||||
cancelFilter: () =>
|
||||
this.resetFilter()
|
||||
|
||||
getUserFilterResults: () =>
|
||||
if this.willSearch(true)
|
||||
this.doRestGet()
|
||||
|
||||
doRestGet: (query) =>
|
||||
query2 = 'results=true&'
|
||||
unless (typeof query == "undefined")
|
||||
query2 += query
|
||||
@restGet(query2).done(this.didSearch)
|
||||
|
||||
performSearch: () =>
|
||||
if this.willSearch(true)
|
||||
$.each this.searchMetaData().filter_keys.single, (index, key) =>
|
||||
this.filterData()[key] = this._builderSelectValue(key)
|
||||
$.each this.searchMetaData().filter_keys.multi, (index, key) =>
|
||||
this.filterData()[key] = this._builderSelectMultiValue(key)
|
||||
@restPost({ filter: JSON.stringify(this.filterData()), page: @pageNumber }).done(this.didSearch)
|
||||
|
||||
renderResultsHeader: () =>
|
||||
|
||||
renderResultsPage: () =>
|
||||
|
||||
_formatLocation: (band) ->
|
||||
if band.city and band.state
|
||||
band.city + ', ' + band.state
|
||||
else if band.city
|
||||
band.city
|
||||
else if band.regionname
|
||||
band.regionname
|
||||
else
|
||||
'Location Unavailable'
|
||||
|
||||
friendRequestCallback: (user_id)=>
|
||||
# TODO:
|
||||
|
||||
paginate: () =>
|
||||
if @pageNumber < @searchResults.page_count && this.willSearch(false)
|
||||
@screen.find('.paginate-wait').show()
|
||||
@pageNumber += 1
|
||||
@restPost({ filter: JSON.stringify(this.filterData()), page: @pageNumber }).done(this.didSearch)
|
||||
return true
|
||||
false
|
||||
|
||||
registerResultsPagination: () =>
|
||||
_resultsListContainer = @resultsListContainer
|
||||
_headerHeight = @screen.find('#'+@searchType+'-search-filter-results-header').height()
|
||||
_paginator = this.paginate
|
||||
|
||||
@screen.find('.content-body-scroller').scroll ->
|
||||
if _resultsListContainer.is(':visible')
|
||||
jthis = $(this)
|
||||
wintop = jthis.scrollTop()
|
||||
winheight = jthis.innerHeight()
|
||||
docheight = jthis[0].scrollHeight - _headerHeight
|
||||
scrollTrigger = 0.98;
|
||||
if ((wintop / (docheight - winheight)) >= scrollTrigger)
|
||||
_paginator()
|
||||
|
||||
|
||||
context.JK.MusicianSearchFilter = class MusicianSearchFilter extends BaseSearchFilter
|
||||
|
||||
constructor: () ->
|
||||
super()
|
||||
@searchType = 'musician'
|
||||
@searchTypeS = @searchType+'s'
|
||||
@restGet = @rest.getMusicianSearchFilter
|
||||
@restPost = @rest.postMusicianSearchFilter
|
||||
@searchMeta = gon.musician_search_meta
|
||||
|
||||
init: (app) =>
|
||||
super(app)
|
||||
@screen.find('#btn-'+@searchType+'-search-builder').on 'click', =>
|
||||
this.showBuilder()
|
||||
@screen.find('#btn-'+@searchType+'-search-reset').on 'click', =>
|
||||
this.resetFilter()
|
||||
|
||||
renderSearchFilter: () =>
|
||||
super()
|
||||
|
||||
loadSearchFilter: (sFilter) =>
|
||||
super(sFilter)
|
||||
|
||||
@searchFilter = JSON.parse(sFilter)
|
||||
args =
|
||||
interests: this.filterData().interests
|
||||
skill_level: this.filterData().skill_level
|
||||
studio_sessions: this.filterData().studio_sessions
|
||||
concert_gigs: this.filterData().concert_gigs
|
||||
|
||||
template = context.JK.fillTemplate(@screen.find('#template-musician-search-filter').html(), args)
|
||||
|
||||
content_root = @screen.find('#musician-search-filter-builder')
|
||||
content_root.html template
|
||||
|
||||
@screen.find('#btn-perform-musician-search').on 'click', =>
|
||||
this.performSearch()
|
||||
|
||||
@screen.find('#btn-musician-search-cancel').on 'click', =>
|
||||
this.cancelFilter()
|
||||
|
||||
this._populateSkill()
|
||||
this._populateStudio()
|
||||
this._populateGigs()
|
||||
this._populateInterests()
|
||||
this._populateAges()
|
||||
this._populateGenres()
|
||||
this._populateInstruments()
|
||||
this._populateSortOrder()
|
||||
|
||||
_populateSortOrder: () =>
|
||||
this._populateSelectIdentifier('sort_order')
|
||||
|
||||
_populateInterests: () =>
|
||||
this._populateSelectIdentifier('interests')
|
||||
|
||||
_populateStudio: () =>
|
||||
elem = $ '#musician-search-filter-builder select[name=studio_sessions]'
|
||||
this._populateSelectWithInt(@profileUtils.studioMap, this.filterData().studio_sessions.toString(), elem)
|
||||
|
||||
_populateAges: () =>
|
||||
@screen.find('#search-filter-ages').empty()
|
||||
ages_map = this.searchMetaData()['ages']['map']
|
||||
$.each this.searchMetaData()['ages']['keys'], (index, key) =>
|
||||
ageTemplate = @screen.find('#template-search-filter-setup-ages').html()
|
||||
selected = ''
|
||||
ageLabel = ages_map[key]
|
||||
if 0 < this.filterData().ages.length
|
||||
key_val = key.toString()
|
||||
ageMatch = $.grep(this.filterData().ages, (n, i) ->
|
||||
n == key_val)
|
||||
selected = 'checked' if ageMatch.length > 0
|
||||
ageHtml = context.JK.fillTemplate(ageTemplate,
|
||||
id: key
|
||||
description: ageLabel
|
||||
checked: selected)
|
||||
@screen.find('#search-filter-ages').append ageHtml
|
||||
|
||||
_populateGenres: () =>
|
||||
super()
|
||||
|
||||
_populateSkill: () =>
|
||||
elem = $ '#'+@searchType+'-search-filter-builder select[name=skill_level]'
|
||||
this._populateSelectWithInt(@profileUtils.skillLevelMap, this.filterData().skill_level.toString(), elem)
|
||||
|
||||
_populateInstruments: () =>
|
||||
super()
|
||||
|
||||
willSearch: (reload) =>
|
||||
super(reload)
|
||||
|
||||
didSearch: (response) =>
|
||||
super(response)
|
||||
|
||||
resetFilter: () =>
|
||||
super()
|
||||
|
||||
cancelFilter: () =>
|
||||
super()
|
||||
|
||||
getUserFilterResults: () =>
|
||||
super()
|
||||
|
||||
performSearch: () =>
|
||||
super()
|
||||
|
||||
renderResultsHeader: () =>
|
||||
@screen.find('#'+@searchType+'-search-filter-description').html(@searchResults.description)
|
||||
if @searchResults.is_blank_filter
|
||||
@screen.find('#btn-'+@searchType+'-search-reset').hide()
|
||||
else
|
||||
@screen.find('#btn-'+@searchType+'-search-reset').show()
|
||||
|
||||
renderResultsPage: () =>
|
||||
super()
|
||||
this.renderResultsHeader() if @pageNumber == 1
|
||||
musicians = @searchResults.musicians
|
||||
len = musicians.length
|
||||
if 0 == len
|
||||
@screen.find('#musician-search-filter-results-list-blank').show()
|
||||
@screen.find('#musician-search-filter-results-list-blank').html('No results found')
|
||||
return
|
||||
else
|
||||
@screen.find('#musician-search-filter-results-list-blank').hide()
|
||||
|
||||
ii = 0
|
||||
mTemplate = @screen.find('#template-search-musician-row').html()
|
||||
aTemplate = @screen.find('#template-search-musician-action-btns').html()
|
||||
mVals = undefined
|
||||
musician = undefined
|
||||
renderings = ''
|
||||
instr_logos = undefined
|
||||
follows = undefined
|
||||
followVals = undefined
|
||||
aFollow = undefined
|
||||
myAudioLatency = @searchResults.my_audio_latency
|
||||
while ii < len
|
||||
musician = musicians[ii]
|
||||
if context.JK.currentUserId == musician.id
|
||||
ii++
|
||||
continue
|
||||
instr_logos = ''
|
||||
jj = 0
|
||||
ilen = musician['instruments'].length
|
||||
while jj < ilen
|
||||
instr_id = musician['instruments'][jj].instrument_id
|
||||
if instr_img = @instrument_logo_map[instr_id]
|
||||
instr_logos += '<img height="24" width="24" src="' + instr_img.asset + '" title="' + instr_id + '"/>'
|
||||
jj++
|
||||
actionVals =
|
||||
profile_url: '/client#/profile/' + musician.id
|
||||
friend_class: 'button-' + (if musician['is_friend'] then 'grey' else 'orange')
|
||||
friend_caption: (if musician.is_friend then 'DIS' else '') + 'CONNECT'
|
||||
follow_class: 'button-' + (if musician['is_following'] then 'grey' else 'orange')
|
||||
follow_caption: (if musician.is_following then 'UN' else '') + 'FOLLOW'
|
||||
message_class: 'button-orange'
|
||||
message_caption: 'MESSAGE'
|
||||
button_message: 'button-orange'
|
||||
musician_actions = context.JK.fillTemplate(aTemplate, actionVals)
|
||||
latencyBadge = context._.template($("#template-account-session-latency").html(), $.extend(sessionUtils.createLatency(musician), musician), variable: 'data')
|
||||
mVals =
|
||||
avatar_url: context.JK.resolveAvatarUrl(musician.photo_url)
|
||||
profile_url: '/client#/profile/' + musician.id
|
||||
musician_name: musician.name
|
||||
musician_location: this._formatLocation(musician)
|
||||
instruments: instr_logos
|
||||
biography: musician['biography']
|
||||
follow_count: musician['follow_count']
|
||||
friend_count: musician['friend_count']
|
||||
recording_count: musician['recording_count']
|
||||
session_count: musician['session_count']
|
||||
musician_id: musician['id']
|
||||
musician_action_template: musician_actions
|
||||
latency_badge: latencyBadge
|
||||
musician_first_name: musician['first_name']
|
||||
$rendering = $(context.JK.fillTemplate(mTemplate, mVals))
|
||||
$offsetParent = @resultsListContainer.closest('.content')
|
||||
data = entity_type: 'musician'
|
||||
options =
|
||||
positions: [
|
||||
'top'
|
||||
'bottom'
|
||||
'right'
|
||||
'left'
|
||||
]
|
||||
offsetParent: $offsetParent
|
||||
scoreOptions = offsetParent: $offsetParent
|
||||
context.JK.helpBubble($('.follower-count', $rendering), 'follower-count', data, options);
|
||||
context.JK.helpBubble($('.friend-count', $rendering), 'friend-count', data, options);
|
||||
context.JK.helpBubble($('.recording-count', $rendering), 'recording-count', data, options);
|
||||
context.JK.helpBubble($('.session-count', $rendering), 'session-count', data, options);
|
||||
@helpBubble.scoreBreakdown $('.latency', $rendering), false, musician['full_score'], myAudioLatency, musician['audio_latency'], musician['score'], scoreOptions
|
||||
@resultsListContainer.append $rendering
|
||||
$rendering.find('.biography').dotdotdot()
|
||||
ii++
|
||||
|
||||
this._bindMessageMusician()
|
||||
this._bindFriendMusician()
|
||||
this._bindFollowMusician()
|
||||
|
||||
context.JK.bindHoverEvents()
|
||||
return
|
||||
|
||||
_bindMessageMusician: () =>
|
||||
objThis = this
|
||||
@screen.find('.search-m-message').on 'click', (evt) ->
|
||||
userId = $(this).parent().data('musician-id')
|
||||
objThis.app.layout.showDialog 'text-message', d1: userId
|
||||
|
||||
|
||||
_bindFriendMusician: () =>
|
||||
objThis = this
|
||||
@screen.find('.search-m-friend').on 'click', (evt) ->
|
||||
# if the musician is already a friend, remove the button-orange class, and prevent the link from working
|
||||
if 0 == $(this).closest('.button-orange').size()
|
||||
return false
|
||||
$(this).click (ee) ->
|
||||
ee.preventDefault()
|
||||
return
|
||||
evt.stopPropagation()
|
||||
uid = $(this).parent().data('musician-id')
|
||||
objThis.rest.sendFriendRequest objThis.app, uid, this.friendRequestCallback
|
||||
|
||||
_bindFollowMusician: () =>
|
||||
objThis = this
|
||||
@screen.find('.search-m-follow').on 'click', (evt) ->
|
||||
# if the musician 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 (ee) ->
|
||||
ee.preventDefault()
|
||||
return
|
||||
evt.stopPropagation()
|
||||
newFollowing = {}
|
||||
newFollowing.user_id = $(this).parent().data('musician-id')
|
||||
url = '/api/users/' + context.JK.currentUserId + '/followings'
|
||||
$.ajax
|
||||
type: 'POST'
|
||||
dataType: 'json'
|
||||
contentType: 'application/json'
|
||||
url: url
|
||||
data: JSON.stringify(newFollowing)
|
||||
processData: false
|
||||
success: (response) ->
|
||||
# remove the orange look to indicate it's not selectable
|
||||
# @FIXME -- this will need to be tweaked when we allow unfollowing
|
||||
objThis.screen.find('div[data-musician-id=' + newFollowing.user_id + '] .search-m-follow').removeClass('button-orange').addClass 'button-grey'
|
||||
return
|
||||
error: objThis.app.ajaxError
|
||||
|
||||
_formatLocation: (musician) ->
|
||||
if musician.city and musician.state
|
||||
musician.city + ', ' + musician.state
|
||||
else if musician.city
|
||||
musician.city
|
||||
else if musician.regionname
|
||||
musician.regionname
|
||||
else
|
||||
'Location Unavailable'
|
||||
|
||||
friendRequestCallback: (user_id)=>
|
||||
# TODO:
|
||||
|
||||
paginate: () =>
|
||||
super()
|
||||
|
||||
registerResultsPagination: () =>
|
||||
super()
|
||||
|
||||
|
||||
context.JK.BandSearchFilter = class BandSearchFilter extends BaseSearchFilter
|
||||
|
||||
constructor: () ->
|
||||
super()
|
||||
@searchType = 'band'
|
||||
@searchTypeS = @searchType+'s'
|
||||
@restGet = @rest.getBandSearchFilter
|
||||
@restPost = @rest.postBandSearchFilter
|
||||
@searchMeta = gon.band_search_meta
|
||||
@searchSubType = 'to_join'
|
||||
|
||||
init: (app) =>
|
||||
super(app)
|
||||
|
||||
@screen.find('#btn-'+@searchType+'-search-builder-to_join').on 'click', =>
|
||||
this.showBuilderToJoin()
|
||||
@screen.find('#btn-'+@searchType+'-search-builder-to_hire').on 'click', =>
|
||||
this.showBuilderToHire()
|
||||
@screen.find('#btn-'+@searchType+'-search-builder').on 'click', =>
|
||||
this.showBuilderActive()
|
||||
@screen.find('#btn-'+@searchType+'-search-reset').on 'click', =>
|
||||
this.resetFilter()
|
||||
|
||||
@resultsList = @screen.find('#band-search-filter-results-list')
|
||||
@screen.find('#band-search-filter-results-filtered').hide()
|
||||
|
||||
isToHire: () =>
|
||||
'to_hire' == @searchSubType
|
||||
|
||||
showBuilderActive: () =>
|
||||
if this.isToHire()
|
||||
this.showBuilderToHire()
|
||||
else
|
||||
this.showBuilderToJoin()
|
||||
|
||||
showBuilderToJoin: () =>
|
||||
@screen.find('.band-search-filter-builder-top-to_join').show()
|
||||
@screen.find('.band-search-filter-builder-top-to_hire').hide()
|
||||
@searchSubType = 'to_join'
|
||||
this.showBuilder()
|
||||
this._loadSearchFilter() if @searchFilter
|
||||
# @screen.find('.band-search-filter-builder-top-to_join h2').html('search bands')
|
||||
|
||||
showBuilderToHire: () =>
|
||||
@screen.find('.band-search-filter-builder-top-to_join').hide()
|
||||
@screen.find('.band-search-filter-builder-top-to_hire').show()
|
||||
@searchSubType = 'to_hire'
|
||||
this.showBuilder()
|
||||
this._loadSearchFilter() if @searchFilter
|
||||
# @screen.find('.band-search-filter-builder-top-to_hire h2').html('search bands to hire')
|
||||
|
||||
searchMetaData: () =>
|
||||
@searchMeta[@searchSubType]
|
||||
|
||||
renderSearchFilter: () =>
|
||||
super()
|
||||
|
||||
_searchFilterArgsToJoin: () =>
|
||||
args =
|
||||
touring_option: this.filterData().touring_option
|
||||
band_status: this.filterData().band_status
|
||||
play_commitment: this.filterData().play_commitment
|
||||
band_type: this.filterData().band_type
|
||||
concert_gigs: this.filterData().concert_gigs
|
||||
|
||||
_searchFilterArgsToHire: () =>
|
||||
if 0 < this.filterData().max_cost
|
||||
has_max_cost = 'checked'
|
||||
else
|
||||
has_max_cost = ''
|
||||
if 1==this.filterData().free_gigs
|
||||
has_free_gigs = 'checked'
|
||||
else
|
||||
has_free_gigs = ''
|
||||
|
||||
args =
|
||||
band_status: this.filterData().band_status
|
||||
concert_gigs: this.filterData().concert_gigs
|
||||
performance_samples: this.filterData().performance_samples
|
||||
has_max_cost: has_max_cost
|
||||
max_cost: this.filterData().max_cost
|
||||
has_free_gigs: has_free_gigs
|
||||
|
||||
_populateSearchFilterToJoin: () =>
|
||||
this._populateInstruments()
|
||||
this._populateSkill()
|
||||
this._populateGigs()
|
||||
this._populatePlayCommit()
|
||||
this._populateTourOption()
|
||||
this._populateBandStatus()
|
||||
|
||||
_populateSearchFilterToHire: () =>
|
||||
this._populateBandStatus()
|
||||
this._populateGigs()
|
||||
this._populatePerformSamples()
|
||||
|
||||
loadSearchFilter: (sFilter) =>
|
||||
super(sFilter)
|
||||
@searchFilter = JSON.parse(sFilter)
|
||||
this._loadSearchFilter()
|
||||
|
||||
_loadSearchFilter: () =>
|
||||
switch @searchSubType
|
||||
when 'to_join' then args = this._searchFilterArgsToJoin()
|
||||
when 'to_hire' then args = this._searchFilterArgsToHire()
|
||||
|
||||
template = context.JK.fillTemplate(@screen.find('#template-band-search-filter-'+@searchSubType).html(), args)
|
||||
|
||||
content_root = @screen.find('#band-search-filter-builder')
|
||||
content_root.html template
|
||||
|
||||
@screen.find('#btn-perform-band-search').on 'click', =>
|
||||
this.performSearch()
|
||||
|
||||
@screen.find('#btn-band-search-cancel').on 'click', =>
|
||||
this.cancelFilter()
|
||||
|
||||
this._populateGenres()
|
||||
this._populateSortOrder() if this.isToHire()
|
||||
|
||||
switch @searchSubType
|
||||
when 'to_join' then this._populateSearchFilterToJoin()
|
||||
when 'to_hire' then this._populateSearchFilterToHire()
|
||||
|
||||
_populateSkill: () =>
|
||||
this._populateSelectIdentifier('band_type')
|
||||
|
||||
_populateBandStatus: () =>
|
||||
this._populateSelectIdentifier('band_status')
|
||||
|
||||
_populatePlayCommit: () =>
|
||||
this._populateSelectIdentifier('play_commitment')
|
||||
|
||||
_populateTourOption: () =>
|
||||
this._populateSelectIdentifier('touring_option')
|
||||
|
||||
_populateSortOrder: () =>
|
||||
this._populateSelectIdentifier('sort_order')
|
||||
|
||||
_populatePerformSamples: () =>
|
||||
this._populateSelectIdentifier('performance_samples')
|
||||
|
||||
_populateGenres: () =>
|
||||
super()
|
||||
|
||||
_populateInstruments: () =>
|
||||
super()
|
||||
|
||||
willSearch: (reload) =>
|
||||
super(reload)
|
||||
|
||||
didSearch: (response) =>
|
||||
super(response)
|
||||
|
||||
resetFilter: () =>
|
||||
if this.willSearch(true)
|
||||
@screen.find('#band-search-filter-results-blank').show()
|
||||
@screen.find('#band-search-filter-results-filtered').hide()
|
||||
@screen.find('#band-search-filter-description').html('')
|
||||
@restPost({ filter: 'reset', subtype: @searchSubType }).done(this.didSearch)
|
||||
|
||||
cancelFilter: () =>
|
||||
super()
|
||||
|
||||
doRestGet: (query) =>
|
||||
super('subtype='+@searchSubType)
|
||||
|
||||
performSearch: () =>
|
||||
if this.willSearch(true)
|
||||
filterPost = this.filterData()
|
||||
$.each this.searchMetaData().filter_keys.single, (index, key) =>
|
||||
filterPost[key] = this._builderSelectValue(key)
|
||||
$.each this.searchMetaData().filter_keys.multi, (index, key) =>
|
||||
filterPost[key] = this._builderSelectMultiValue(key)
|
||||
|
||||
if this.isToHire()
|
||||
filterPost['max_cost'] = parseInt($('#max_cost_amount').val())
|
||||
filterPost['free_gigs'] = if $('#free_gigs').prop('checked') then 1 else 0
|
||||
|
||||
postData = { subtype: @searchSubType, filter: JSON.stringify(filterPost), page: @pageNumber }
|
||||
@restPost(postData).done(this.didSearch)
|
||||
|
||||
renderResultsHeader: () =>
|
||||
if @searchResults.is_blank_filter
|
||||
@screen.find('#band-search-filter-results-blank').show()
|
||||
@screen.find('#band-search-filter-results-filtered').hide()
|
||||
else
|
||||
@screen.find('#band-search-filter-results-blank').hide()
|
||||
@screen.find('#band-search-filter-results-filtered').show()
|
||||
@screen.find('#band-search-filter-description').html(@searchResults.description)
|
||||
|
||||
renderResultsPage: () =>
|
||||
super()
|
||||
this.renderResultsHeader() if @pageNumber == 1
|
||||
bands = @searchResults.bands
|
||||
len = bands.length
|
||||
if 0 == len
|
||||
@screen.find('#band-search-filter-results-list').hide()
|
||||
@screen.find('#band-search-filter-results-list-blank').show()
|
||||
@screen.find('#band-search-filter-results-list-blank').html('No results found')
|
||||
return
|
||||
else
|
||||
@screen.find('#band-search-filter-results-list-blank').hide()
|
||||
@screen.find('#band-search-filter-results-list').show()
|
||||
this.renderBands(bands)
|
||||
|
||||
renderBands: (bands) =>
|
||||
toolTip = undefined
|
||||
ii = undefined
|
||||
len = undefined
|
||||
mTemplate = $('#template-find-band-row').html()
|
||||
pTemplate = $('#template-band-player-info').html()
|
||||
aTemplate = $('#template-band-action-btns').html()
|
||||
eTemplate = $('#template-band-edit-btns').html()
|
||||
bVals = undefined
|
||||
bb = undefined
|
||||
renderings = ''
|
||||
instr_logos = undefined
|
||||
instr = undefined
|
||||
players = undefined
|
||||
playerVals = undefined
|
||||
aPlayer = undefined
|
||||
isMember = undefined
|
||||
ii = 0
|
||||
len = bands.length
|
||||
while ii < len
|
||||
bb = bands[ii]
|
||||
instr_logos = ''
|
||||
players = ''
|
||||
playerVals = {}
|
||||
isMember = false
|
||||
jj = 0
|
||||
ilen = bb['players'].length
|
||||
while jj < ilen
|
||||
toolTip = ''
|
||||
aPlayer = bb['players'][jj]
|
||||
player_instrs = ''
|
||||
iter_pinstruments = aPlayer['instruments'].split(',')
|
||||
kk = 0
|
||||
klen = iter_pinstruments.length
|
||||
while kk < klen
|
||||
pinstr = iter_pinstruments[kk]
|
||||
toolTip = ''
|
||||
if pinstr of @instrument_logo_map
|
||||
instr = @instrument_logo_map[pinstr].asset
|
||||
toolTip = pinstr
|
||||
player_instrs += '<img src="' + instr + '" title="' + toolTip + '"/>'
|
||||
kk++
|
||||
if !isMember
|
||||
isMember = aPlayer.user_id == context.JK.currentUserId
|
||||
playerVals =
|
||||
user_id: aPlayer.user_id
|
||||
player_name: aPlayer.name
|
||||
profile_url: '/client#/profile/' + aPlayer.user_id
|
||||
avatar_url: context.JK.resolveAvatarUrl(aPlayer.photo_url)
|
||||
player_instruments: player_instrs
|
||||
players += context.JK.fillTemplate(pTemplate, playerVals)
|
||||
jj++
|
||||
actionVals = undefined
|
||||
band_actions = undefined
|
||||
if isMember
|
||||
actionVals =
|
||||
profile_url: '/client#/bandProfile/' + bb.id
|
||||
band_edit_url: '/client#/band/setup/' + bb.id + '/step1'
|
||||
band_member_url: '/client#/band/setup/' + bb.id + '/step2'
|
||||
band_actions = context.JK.fillTemplate(eTemplate, actionVals)
|
||||
else
|
||||
actionVals =
|
||||
profile_url: '/client#/bandProfile/' + bb.id
|
||||
button_follow: if bb['is_following'] then '' else 'button-orange'
|
||||
button_message: 'button-orange'
|
||||
band_actions = context.JK.fillTemplate(aTemplate, actionVals)
|
||||
bgenres = ''
|
||||
jj = 0
|
||||
ilen = bb['genres'].length
|
||||
while jj < ilen
|
||||
bgenres += bb['genres'][jj]['description'] + '<br />'
|
||||
jj++
|
||||
bgenres += '<br />'
|
||||
bVals =
|
||||
avatar_url: context.JK.resolveBandAvatarUrl(bb.photo_url)
|
||||
profile_url: '/client#/bandProfile/' + 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
|
||||
$rendering = $(context.JK.fillTemplate(mTemplate, bVals))
|
||||
$offsetParent = @resultsList.closest('.content')
|
||||
data = entity_type: 'band'
|
||||
options =
|
||||
positions: [
|
||||
'top'
|
||||
'bottom'
|
||||
'right'
|
||||
'left'
|
||||
]
|
||||
offsetParent: $offsetParent
|
||||
context.JK.helpBubble $('.follower-count', $rendering), 'follower-count', data, options
|
||||
context.JK.helpBubble $('.recording-count', $rendering), 'recording-count', data, options
|
||||
context.JK.helpBubble $('.session-count', $rendering), 'session-count', data, options
|
||||
@resultsList.append $rendering
|
||||
ii++
|
||||
|
||||
this._bindFollowBand()
|
||||
|
||||
context.JK.bindHoverEvents()
|
||||
return
|
||||
|
||||
_bindFollowBand: () =>
|
||||
objThis = this
|
||||
@screen.find('.search-m-follow').on 'click', (evt) ->
|
||||
if 0 == $(this).closest('.button-orange').size()
|
||||
return false
|
||||
$(this).click (ee) ->
|
||||
ee.preventDefault()
|
||||
return
|
||||
evt.stopPropagation()
|
||||
newFollowing = {}
|
||||
newFollowing.band_id = $(this).parent().data('band-id')
|
||||
url = '/api/users/' + context.JK.currentUserId + '/followings'
|
||||
$.ajax
|
||||
type: 'POST'
|
||||
dataType: 'json'
|
||||
contentType: 'application/json'
|
||||
url: url
|
||||
data: JSON.stringify(newFollowing)
|
||||
processData: false
|
||||
success: (response) ->
|
||||
$('div[data-band-id=' + newFollowing.band_id + '] .search-m-follow').removeClass('button-orange').addClass 'button-grey'
|
||||
return
|
||||
error: objThis.app.ajaxError(arguments)
|
||||
|
||||
_formatLocation: (band) ->
|
||||
|
||||
friendRequestCallback: (user_id)=>
|
||||
# TODO:
|
||||
|
||||
paginate: () =>
|
||||
super()
|
||||
|
||||
registerResultsPagination: () =>
|
||||
super()
|
||||
|
||||
filterData: () =>
|
||||
super()[@searchSubType]
|
||||
|
||||
|
|
@ -1,412 +0,0 @@
|
|||
$ = jQuery
|
||||
context = window
|
||||
context.JK ||= {};
|
||||
|
||||
context.JK.MusicianSearchFilter = class MusicianSearchFilter
|
||||
|
||||
constructor: () ->
|
||||
@rest = context.JK.Rest()
|
||||
@logger = context.JK.logger
|
||||
@searchFilter = null
|
||||
@profileUtils = context.JK.ProfileUtils
|
||||
@helpBubble = context.JK.HelpBubbleHelper
|
||||
@searchResults = null
|
||||
@isSearching = false
|
||||
@pageNumber = 1
|
||||
@instrument_logo_map = context.JK.getInstrumentIconMap24()
|
||||
@instrumentSelector = null
|
||||
|
||||
init: (app) =>
|
||||
@app = app
|
||||
@screenBindings = { 'afterShow': this.afterShow, 'afterHide': this.afterHide }
|
||||
@app.bindScreen('musicians', @screenBindings)
|
||||
|
||||
@screen = $('#musicians-screen')
|
||||
@resultsListContainer = @screen.find('#musician-search-filter-results-list')
|
||||
@spinner = @screen.find('.paginate-wait')
|
||||
@instrumentSelector = new context.JK.InstrumentSelector(JK.app)
|
||||
@instrumentSelector.initialize(false, true)
|
||||
|
||||
this.registerResultsPagination()
|
||||
|
||||
@screen.find('#btn-musician-search-builder').on 'click', =>
|
||||
this.showBuilder()
|
||||
false
|
||||
|
||||
@screen.find('#btn-musician-search-reset').on 'click', =>
|
||||
this.resetFilter()
|
||||
false
|
||||
|
||||
afterShow: () =>
|
||||
@screen.find('#musician-search-filter-results').show()
|
||||
@screen.find('#musician-search-filter-builder').hide()
|
||||
this.getUserFilterResults()
|
||||
|
||||
showBuilder: () =>
|
||||
@screen.find('#musician-search-filter-results').hide()
|
||||
@screen.find('#musician-search-filter-builder').show()
|
||||
@resultsListContainer.empty()
|
||||
|
||||
afterHide: () =>
|
||||
@resultsListContainer.empty()
|
||||
|
||||
renderSearchFilter: () =>
|
||||
$.when(this.rest.getMusicianSearchFilter()).done (sFilter) =>
|
||||
this.loadSearchFilter(sFilter)
|
||||
|
||||
loadSearchFilter: (sFilter) =>
|
||||
@searchFilter = JSON.parse(sFilter)
|
||||
args =
|
||||
interests: @searchFilter.data_blob.interests
|
||||
skill_level: @searchFilter.data_blob.skill_level
|
||||
studio_sessions: @searchFilter.data_blob.studio_sessions
|
||||
concert_gigs: @searchFilter.data_blob.concert_gigs
|
||||
|
||||
template = context.JK.fillTemplate(@screen.find('#template-musician-search-filter').html(), args)
|
||||
|
||||
content_root = @screen.find('#musician-search-filter-builder')
|
||||
content_root.html template
|
||||
|
||||
@screen.find('#btn-perform-musician-search').on 'click', =>
|
||||
this.performSearch()
|
||||
false
|
||||
|
||||
@screen.find('#btn-musician-search-cancel').on 'click', =>
|
||||
this.cancelFilter()
|
||||
false
|
||||
|
||||
this._populateSkill()
|
||||
this._populateStudio()
|
||||
this._populateGigs()
|
||||
this._populateInterests()
|
||||
this._populateAges()
|
||||
this._populateGenres()
|
||||
this._populateInstruments()
|
||||
this._populateSortOrder()
|
||||
|
||||
|
||||
|
||||
_populateSelectWithKeys: (struct, selection, keys, element) =>
|
||||
element.children().remove()
|
||||
$.each keys, (idx, value) =>
|
||||
label = struct[value]
|
||||
blankOption = $ '<option value=""></option>'
|
||||
blankOption.text label
|
||||
blankOption.attr 'value', value
|
||||
element.append(blankOption)
|
||||
element.val(selection)
|
||||
context.JK.dropdown(element)
|
||||
|
||||
_populateSelectIdentifier: (identifier) =>
|
||||
elem = $ '#musician-search-filter-builder select[name='+identifier+']'
|
||||
struct = gon.musician_search_meta[identifier]['map']
|
||||
keys = gon.musician_search_meta[identifier]['keys']
|
||||
console.log("@searchFilter", @searchFilter, identifier)
|
||||
this._populateSelectWithKeys(struct, @searchFilter.data_blob[identifier], keys, elem)
|
||||
|
||||
_populateSelectWithInt: (sourceStruct, selection, element) =>
|
||||
struct =
|
||||
'-1': 'Any'
|
||||
$.extend(struct, sourceStruct)
|
||||
this._populateSelectWithKeys(struct, selection, Object.keys(struct).sort(), element)
|
||||
|
||||
_populateSortOrder: () =>
|
||||
this._populateSelectIdentifier('sort_order')
|
||||
|
||||
_populateInterests: () =>
|
||||
this._populateSelectIdentifier('interests')
|
||||
|
||||
_populateStudio: () =>
|
||||
elem = $ '#musician-search-filter-builder select[name=studio_sessions]'
|
||||
this._populateSelectWithInt(@profileUtils.studioMap, @searchFilter.data_blob.studio_sessions.toString(), elem)
|
||||
|
||||
_populateGigs: () =>
|
||||
elem = $ '#musician-search-filter-builder select[name=concert_gigs]'
|
||||
this._populateSelectWithInt(@profileUtils.gigMap, @searchFilter.data_blob.concert_gigs.toString(), elem)
|
||||
|
||||
_populateSkill: () =>
|
||||
elem = $ '#musician-search-filter-builder select[name=skill_level]'
|
||||
this._populateSelectWithInt(@profileUtils.skillLevelMap, @searchFilter.data_blob.skill_level.toString(), elem)
|
||||
|
||||
_populateAges: () =>
|
||||
@screen.find('#search-filter-ages').empty()
|
||||
ages_map = gon.musician_search_meta['ages']['map']
|
||||
$.each gon.musician_search_meta['ages']['keys'], (index, key) =>
|
||||
ageTemplate = @screen.find('#template-search-filter-setup-ages').html()
|
||||
ageLabel = ages_map[key]
|
||||
if 0 < @searchFilter.data_blob.ages.length
|
||||
key_val = key.toString()
|
||||
ageMatch = $.grep(@searchFilter.data_blob.ages, (n, i) ->
|
||||
n == key_val)
|
||||
selected = 'checked' if ageMatch.length > 0
|
||||
ageHtml = context._.template(ageTemplate,
|
||||
{ id: key
|
||||
description: ageLabel
|
||||
checked: selected},
|
||||
{variable: 'data'})
|
||||
@screen.find('#search-filter-ages').append ageHtml
|
||||
|
||||
_populateGenres: () =>
|
||||
@screen.find('#search-filter-genres').empty()
|
||||
@rest.getGenres().done (genres) =>
|
||||
genreTemplate = @screen.find('#template-search-filter-setup-genres').html()
|
||||
$.each genres, (index, genre) =>
|
||||
if 0 < @searchFilter.data_blob.genres.length
|
||||
genreMatch = $.grep(@searchFilter.data_blob.genres, (n, i) ->
|
||||
n == genre.id)
|
||||
else
|
||||
genreMatch = []
|
||||
selected = 'checked' if genreMatch.length > 0
|
||||
genreHtml = context._.template(genreTemplate,
|
||||
{ id: genre.id
|
||||
description: genre.description
|
||||
checked: selected },
|
||||
{ variable: 'data' })
|
||||
@screen.find('#search-filter-genres').append genreHtml
|
||||
|
||||
_populateInstruments: () =>
|
||||
|
||||
# TODO hydrate user's selection from json_store
|
||||
@instrumentSelector.render(@screen.find('.session-instrumentlist'), [])
|
||||
@instrumentSelector.setSelectedInstruments(@searchFilter.data_blob.instruments)
|
||||
|
||||
|
||||
_builderSelectValue: (identifier) =>
|
||||
elem = $ '#musician-search-filter-builder select[name='+identifier+']'
|
||||
elem.val()
|
||||
|
||||
_builderSelectMultiValue: (identifier) =>
|
||||
vals = []
|
||||
elem = $ '#search-filter-'+identifier+' input[type=checkbox]:checked'
|
||||
if 'instruments' == identifier
|
||||
vals = @instrumentSelector.getSelectedInstruments()
|
||||
else
|
||||
elem.each (idx) ->
|
||||
vals.push $(this).val()
|
||||
vals
|
||||
|
||||
willSearch: (reload) =>
|
||||
return false if @isSearching
|
||||
@isSearching = true
|
||||
if reload
|
||||
@pageNumber = 1
|
||||
@screen.find('#musician-search-filter-spinner').show()
|
||||
@resultsListContainer.empty()
|
||||
@screen.find('#musician-search-filter-builder').hide()
|
||||
@screen.find('#musician-search-filter-results').show()
|
||||
true
|
||||
|
||||
didSearch: (response) =>
|
||||
this.loadSearchFilter(response.filter_json)
|
||||
@searchResults = response
|
||||
@screen.find('#musician-search-filter-spinner').hide()
|
||||
this.renderMusicians()
|
||||
@screen.find('.paginate-wait').hide()
|
||||
@isSearching = false
|
||||
|
||||
resetFilter: () =>
|
||||
if this.willSearch(true)
|
||||
@rest.postMusicianSearchFilter({ filter: 'reset' }).done(this.didSearch)
|
||||
|
||||
cancelFilter: () =>
|
||||
this.resetFilter()
|
||||
|
||||
getUserFilterResults: () =>
|
||||
if this.willSearch(true)
|
||||
@rest.getMusicianSearchFilter('results=true').done(this.didSearch)
|
||||
|
||||
performSearch: () =>
|
||||
if this.willSearch(true)
|
||||
filter = {}
|
||||
$.each gon.musician_search_meta.filter_keys.single, (index, key) =>
|
||||
filter[key] = this._builderSelectValue(key)
|
||||
$.each gon.musician_search_meta.filter_keys.multi, (index, key) =>
|
||||
filter[key] = this._builderSelectMultiValue(key)
|
||||
@rest.postMusicianSearchFilter({ filter: JSON.stringify(filter), page: @pageNumber }).done(this.didSearch)
|
||||
|
||||
renderResultsHeader: () =>
|
||||
if @searchResults.is_blank_filter
|
||||
@screen.find('#btn-musician-search-reset').hide()
|
||||
@screen.find('.musician-search-text').text('Click search button to look for musicians with similar interests, skill levels, etc.')
|
||||
else
|
||||
@screen.find('#btn-musician-search-reset').show()
|
||||
@screen.find('.musician-search-text').text(@searchResults.summary)
|
||||
|
||||
renderMusicians: () =>
|
||||
this.renderResultsHeader() if @pageNumber == 1
|
||||
musicians = @searchResults.musicians
|
||||
len = musicians.length
|
||||
if 0 == len
|
||||
@screen.find('#musician-search-filter-results-list-blank').show()
|
||||
@screen.find('#musician-search-filter-results-list-blank').html('No results found')
|
||||
return
|
||||
else
|
||||
@screen.find('#musician-search-filter-results-list-blank').hide()
|
||||
|
||||
ii = 0
|
||||
mTemplate = @screen.find('#template-search-musician-row').html()
|
||||
aTemplate = @screen.find('#template-search-musician-action-btns').html()
|
||||
mVals = undefined
|
||||
musician = undefined
|
||||
renderings = ''
|
||||
instr_logos = undefined
|
||||
follows = undefined
|
||||
followVals = undefined
|
||||
aFollow = undefined
|
||||
myAudioLatency = @searchResults.my_audio_latency
|
||||
while ii < len
|
||||
musician = musicians[ii]
|
||||
if context.JK.currentUserId == musician.id
|
||||
ii++
|
||||
continue
|
||||
instr_logos = ''
|
||||
jj = 0
|
||||
ilen = musician['instruments'].length
|
||||
while jj < ilen
|
||||
instr_id = musician['instruments'][jj].instrument_id
|
||||
if instr_img = @instrument_logo_map[instr_id]
|
||||
instr_logos += '<img height="24" width="24" src="' + instr_img.asset + '" title="' + instr_id + '"/>'
|
||||
jj++
|
||||
actionVals =
|
||||
profile_url: '/client#/profile/' + musician.id
|
||||
friend_class: 'button-' + (if musician['is_friend'] then 'grey' else 'orange')
|
||||
friend_caption: (if musician.is_friend then 'DIS' else '') + 'CONNECT'
|
||||
follow_class: 'button-' + (if musician['is_following'] then 'grey' else 'orange')
|
||||
follow_caption: (if musician.is_following then 'UN' else '') + 'FOLLOW'
|
||||
message_class: 'button-orange'
|
||||
message_caption: 'MESSAGE'
|
||||
button_message: 'button-orange'
|
||||
musician_actions = context.JK.fillTemplate(aTemplate, actionVals)
|
||||
latencyBadge = context._.template($("#template-account-session-latency").html(), $.extend(sessionUtils.createLatency(musician), musician), variable: 'data')
|
||||
mVals =
|
||||
avatar_url: context.JK.resolveAvatarUrl(musician.photo_url)
|
||||
profile_url: '/client#/profile/' + musician.id
|
||||
musician_name: musician.name
|
||||
musician_location: this._formatLocation(musician)
|
||||
instruments: instr_logos
|
||||
biography: musician['biography']
|
||||
follow_count: musician['follow_count']
|
||||
friend_count: musician['friend_count']
|
||||
recording_count: musician['recording_count']
|
||||
session_count: musician['session_count']
|
||||
musician_id: musician['id']
|
||||
musician_action_template: musician_actions
|
||||
latency_badge: latencyBadge
|
||||
musician_first_name: musician['first_name']
|
||||
$rendering = $(context.JK.fillTemplate(mTemplate, mVals))
|
||||
$offsetParent = @resultsListContainer.closest('.content')
|
||||
data = entity_type: 'musician'
|
||||
options =
|
||||
positions: [
|
||||
'top'
|
||||
'bottom'
|
||||
'right'
|
||||
'left'
|
||||
]
|
||||
offsetParent: $offsetParent
|
||||
scoreOptions = offsetParent: $offsetParent
|
||||
context.JK.helpBubble($('.follower-count', $rendering), 'follower-count', data, options);
|
||||
context.JK.helpBubble($('.friend-count', $rendering), 'friend-count', data, options);
|
||||
context.JK.helpBubble($('.recording-count', $rendering), 'recording-count', data, options);
|
||||
context.JK.helpBubble($('.session-count', $rendering), 'session-count', data, options);
|
||||
@helpBubble.scoreBreakdown $('.latency', $rendering), false, musician['full_score'], myAudioLatency, musician['audio_latency'], musician['score'], scoreOptions
|
||||
@resultsListContainer.append $rendering
|
||||
$rendering.find('.biography').dotdotdot()
|
||||
ii++
|
||||
|
||||
this._bindMessageMusician()
|
||||
this._bindFriendMusician()
|
||||
this._bindFollowMusician()
|
||||
|
||||
context.JK.bindHoverEvents()
|
||||
return
|
||||
|
||||
_bindMessageMusician: () =>
|
||||
objThis = this
|
||||
@screen.find('.search-m-message').on 'click', (evt) ->
|
||||
userId = $(this).parent().data('musician-id')
|
||||
objThis.app.layout.showDialog 'text-message', d1: userId
|
||||
return false
|
||||
|
||||
|
||||
_bindFriendMusician: () =>
|
||||
objThis = this
|
||||
@screen.find('.search-m-friend').on 'click', (evt) =>
|
||||
# if the musician is already a friend, remove the button-orange class, and prevent the link from working
|
||||
$self = $(evt.target)
|
||||
if 0 == $self.closest('.button-orange').size()
|
||||
return false
|
||||
logger.debug("evt.target", evt.target)
|
||||
$self.click (ee) ->
|
||||
ee.preventDefault()
|
||||
return false
|
||||
evt.stopPropagation()
|
||||
uid = $self.parent().data('musician-id')
|
||||
objThis.rest.sendFriendRequest objThis.app, uid, this.friendRequestCallback
|
||||
@app.notify({text: 'A friend request has been sent.'})
|
||||
return false
|
||||
|
||||
_bindFollowMusician: () =>
|
||||
objThis = this
|
||||
@screen.find('.search-m-follow').on 'click', (evt) ->
|
||||
# if the musician 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 (ee) ->
|
||||
ee.preventDefault()
|
||||
return false
|
||||
evt.stopPropagation()
|
||||
newFollowing = {}
|
||||
newFollowing.user_id = $(this).parent().data('musician-id')
|
||||
url = '/api/users/' + context.JK.currentUserId + '/followings'
|
||||
$.ajax
|
||||
type: 'POST'
|
||||
dataType: 'json'
|
||||
contentType: 'application/json'
|
||||
url: url
|
||||
data: JSON.stringify(newFollowing)
|
||||
processData: false
|
||||
success: (response) ->
|
||||
# remove the orange look to indicate it's not selectable
|
||||
# @FIXME -- this will need to be tweaked when we allow unfollowing
|
||||
objThis.screen.find('div[data-musician-id=' + newFollowing.user_id + '] .search-m-follow').removeClass('button-orange').addClass 'button-grey'
|
||||
return false
|
||||
error: objThis.app.ajaxError
|
||||
return false
|
||||
|
||||
_formatLocation: (musician) ->
|
||||
if musician.city and musician.state
|
||||
musician.city + ', ' + musician.state
|
||||
else if musician.city
|
||||
musician.city
|
||||
else if musician.regionname
|
||||
musician.regionname
|
||||
else
|
||||
'Location Unavailable'
|
||||
|
||||
friendRequestCallback: (user_id)=>
|
||||
# TODO:
|
||||
|
||||
paginate: () =>
|
||||
|
||||
if @pageNumber < @searchResults.page_count && this.willSearch(false)
|
||||
@screen.find('.paginate-wait').show()
|
||||
@pageNumber += 1
|
||||
@rest.postMusicianSearchFilter({ filter: JSON.stringify(@searchFilter.data_blob), page: @pageNumber }).done(this.didSearch)
|
||||
return true
|
||||
false
|
||||
|
||||
registerResultsPagination: () =>
|
||||
_resultsListContainer = @resultsListContainer
|
||||
_headerHeight = @screen.find('#musician-search-filter-results-header').height()
|
||||
_paginator = this.paginate
|
||||
|
||||
@screen.find('.content-body-scroller').scroll ->
|
||||
if _resultsListContainer.is(':visible')
|
||||
jthis = $(this)
|
||||
wintop = jthis.scrollTop()
|
||||
winheight = jthis.innerHeight()
|
||||
docheight = jthis[0].scrollHeight - _headerHeight
|
||||
scrollTrigger = 0.98;
|
||||
if ((wintop / (docheight - winheight)) >= scrollTrigger)
|
||||
_paginator()
|
||||
|
|
@ -32,6 +32,7 @@ MIX_MODES = context.JK.MIX_MODES
|
|||
componentClasses = classNames({
|
||||
"session-track" : true
|
||||
"metronome" : true
|
||||
"in-jam-track" : @props.location == 'jam-track'
|
||||
"no-mixer" : @props.mode == MIX_MODES.MASTER # show it as disabled if in master mode
|
||||
"in-jam-track" : @props.location == 'jam-track'
|
||||
})
|
||||
|
|
|
|||
|
|
@ -32,7 +32,9 @@ context.JK.WebcamViewer = class WebcamViewer
|
|||
this.loadResolutions()
|
||||
this.selectResolution()
|
||||
@initialScan = true
|
||||
@client.SessStopVideoSharing()
|
||||
# protect against non-video clients pointed at video-enabled server from getting into a session
|
||||
if @client.SessStopVideoSharing
|
||||
@client.SessStopVideoSharing()
|
||||
#client.SessSetInsetPosition(5)
|
||||
#client.SessSetInsetSize(1)
|
||||
#client.FTUESetAutoSelectVideoLayout(false)
|
||||
|
|
@ -82,14 +84,16 @@ context.JK.WebcamViewer = class WebcamViewer
|
|||
|
||||
selectedDeviceName:() =>
|
||||
webcamName="None Configured"
|
||||
webcam = @client.FTUECurrentSelectedVideoDevice()
|
||||
# protect against non-video clients pointed at video-enabled server from getting into a session
|
||||
webcam = if @client.FTUECurrentSelectedVideoDevice? then @client.FTUECurrentSelectedVideoDevice() else null
|
||||
if (webcam? && Object.keys(webcam).length>0)
|
||||
webcamName = _.values(webcam)[0]
|
||||
|
||||
webcamName
|
||||
|
||||
loadWebCams:() =>
|
||||
devices = @client.FTUEGetVideoCaptureDeviceNames()
|
||||
# protect against non-video clients pointed at video-enabled server from getting into a session
|
||||
devices = if @client.FTUEGetVideoCaptureDeviceNames? then @client.FTUEGetVideoCaptureDeviceNames() else []
|
||||
selectedDevice = this.selectedDeviceName()
|
||||
selectControl = @webcamSelect
|
||||
context._.each devices, (device) ->
|
||||
|
|
@ -107,7 +111,8 @@ context.JK.WebcamViewer = class WebcamViewer
|
|||
@root.find('.no-webcam-msg').addClass 'hidden'
|
||||
|
||||
loadResolutions:() =>
|
||||
resolutions = @client.FTUEGetAvailableEncodeVideoResolutions()
|
||||
# protect against non-video clients pointed at video-enabled server from getting into a session
|
||||
resolutions = if @client.FTUEGetAvailableEncodeVideoResolutions? then @client.FTUEGetAvailableEncodeVideoResolutions() else {}
|
||||
selectControl = @resolutionSelect
|
||||
@logger.debug 'FOUND THESE RESOLUTIONS', resolutions, selectControl
|
||||
context._.each resolutions, (value, key, obj) ->
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
@import "client/common.css.scss";
|
||||
|
||||
#band-setup, #band-profile {
|
||||
#band-setup, #band-profile, #bands-filter-to_hire, #bands-filter-to_join {
|
||||
font-family: Raleway, Arial, Helvetica, verdana, arial, sans-serif;
|
||||
.band-field {
|
||||
input[type="text"], select, textarea {
|
||||
|
|
@ -495,10 +495,178 @@
|
|||
label {
|
||||
font-size: 1.05em;
|
||||
}
|
||||
}
|
||||
|
||||
label.strong-label {
|
||||
font-weight: bold;
|
||||
font-size: 1.1em;
|
||||
#bands-screen {
|
||||
|
||||
.col-left {
|
||||
float: left;
|
||||
width: 50%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.col-right {
|
||||
float: right;
|
||||
width: 50%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
#band-search-filter-spinner {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
#band-search-filter-results-list {
|
||||
.profile-band-list-result {
|
||||
padding-top: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.builder-section {
|
||||
padding: 10px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.builder-sort-order {
|
||||
.text-label {
|
||||
float: right;
|
||||
margin-right: 10px;
|
||||
padding-top: 5px;
|
||||
}
|
||||
.sort-order-selector {
|
||||
float: right;
|
||||
.easydropdown-wrapper {
|
||||
width: 140px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#band-search-filter-builder {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.band-search-filter-builder-bottom {
|
||||
text-align: right;
|
||||
#btn-perform-band-search {
|
||||
width: 120px;
|
||||
margin-left: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
tr:nth-child(even) td {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
#band-search-filter-results-header {
|
||||
padding: 10px 10px 10px 10px;
|
||||
}
|
||||
|
||||
#band-search-filter-description {
|
||||
padding: 5px 5px 5px 5px;
|
||||
display: inline;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
#btn-band-search-builder {
|
||||
float: left;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
#btn-band-search-reset {
|
||||
float: right;
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
#bands-filter-to_hire {
|
||||
width: 100%;
|
||||
|
||||
.builder-selector {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
#max_cost_amount {
|
||||
width: 60px;
|
||||
}
|
||||
|
||||
.col-left {
|
||||
float: left;
|
||||
width: 45%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
padding-right: 20px;
|
||||
|
||||
}
|
||||
|
||||
.col-right {
|
||||
float: right;
|
||||
width: 45%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
|
||||
.easydropdown-wrapper {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#bands-filter-to_join {
|
||||
width: 100%;
|
||||
|
||||
.builder-selector {
|
||||
margin-top: 10px;
|
||||
}
|
||||
.lhs {
|
||||
float: left;
|
||||
width: 40%;
|
||||
.easydropdown-wrapper {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
.rhs {
|
||||
float: right;
|
||||
width: 40%;
|
||||
.easydropdown-wrapper {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
.col-left {
|
||||
float: left;
|
||||
width: 30%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
padding-right: 20px;
|
||||
|
||||
.easydropdown-wrapper {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.col-right {
|
||||
float: right;
|
||||
width: 66%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
|
||||
}
|
||||
|
||||
.search-filter-setup-genres {
|
||||
}
|
||||
|
||||
.band-setup-genres {
|
||||
.easydropdown-wrapper {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
.builder-section {
|
||||
padding: 10px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -254,15 +254,15 @@
|
|||
.col-left {
|
||||
@include border_box_sizing;
|
||||
float: left;
|
||||
width: 33%;
|
||||
width: 45%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
.col-right {
|
||||
float: right;
|
||||
width: 67%;
|
||||
@include border_box_sizing;
|
||||
width: 45%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
|
||||
|
|
@ -306,6 +306,14 @@
|
|||
}
|
||||
.builder-ages {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color:#c5c5c5;
|
||||
border:none;
|
||||
-webkit-box-shadow: inset 2px 2px 3px 0px #888;
|
||||
box-shadow: inset 2px 2px 3px 0px #888;
|
||||
color:#000;
|
||||
overflow:auto;
|
||||
font-size:12px;
|
||||
}
|
||||
.builder-instruments {
|
||||
width: 100%;
|
||||
|
|
@ -321,6 +329,21 @@
|
|||
}
|
||||
}
|
||||
|
||||
.musician-setup-genres {
|
||||
width:100%;
|
||||
height:200px;
|
||||
background-color:#c5c5c5;
|
||||
border:none;
|
||||
-webkit-box-shadow: inset 2px 2px 3px 0px #888;
|
||||
box-shadow: inset 2px 2px 3px 0px #888;
|
||||
color:#000;
|
||||
overflow:auto;
|
||||
font-size:12px;
|
||||
.easydropdown-wrapper {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.filter-element {
|
||||
|
|
|
|||
|
|
@ -175,6 +175,17 @@
|
|||
.track-controls {
|
||||
margin-left:0;
|
||||
}
|
||||
|
||||
&.in-jam-track {
|
||||
min-height:56px;
|
||||
|
||||
.track-buttons {
|
||||
margin-top:2px;
|
||||
}
|
||||
table.vu {
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.recorded-track, &.jam-track, &.recorded-category, &.jam-track-category {
|
||||
|
|
|
|||
|
|
@ -482,7 +482,7 @@ class ApiMusicSessionsController < ApiController
|
|||
comment.save
|
||||
|
||||
if comment.errors.any?
|
||||
render :json => { :message => "Unexpected error occurred" }, :status => 500
|
||||
render :json => { :errors => comment.errors }, :status => 422
|
||||
return
|
||||
else
|
||||
render :json => {}, :status => 201
|
||||
|
|
@ -508,7 +508,7 @@ class ApiMusicSessionsController < ApiController
|
|||
comment.save
|
||||
|
||||
if comment.errors.any?
|
||||
render :json => { :message => "Unexpected error occurred" }, :status => 500
|
||||
render :json => { :errors => comment.errors }, :status => 422
|
||||
return
|
||||
else
|
||||
music_session = MusicSession.find(params[:id])
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@ class ApiRecordingsController < ApiController
|
|||
comment.save
|
||||
|
||||
if comment.errors.any?
|
||||
render :json => { :message => "Unexpected error occurred" }, :status => 500
|
||||
render :json => { :errors => comment.errors }, :status => 422
|
||||
return
|
||||
else
|
||||
render :json => {}, :status => 201
|
||||
|
|
@ -178,7 +178,7 @@ class ApiRecordingsController < ApiController
|
|||
liker.save
|
||||
|
||||
if liker.errors.any?
|
||||
render :json => { :message => "Unexpected error occurred" }, :status => 500
|
||||
render :json => { :errors => liker.errors }, :status => 422
|
||||
return
|
||||
else
|
||||
render :json => {}, :status => 201
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ class ApiSearchController < ApiController
|
|||
|
||||
def index
|
||||
if 1 == params[Search::PARAM_MUSICIAN].to_i || 1 == params[Search::PARAM_BAND].to_i
|
||||
query = params.clone
|
||||
query = parasobj.clone
|
||||
query[:remote_ip] = request.remote_ip
|
||||
if 1 == query[Search::PARAM_MUSICIAN].to_i
|
||||
@search = Search.musician_filter(query, current_user)
|
||||
|
|
@ -32,13 +32,35 @@ class ApiSearchController < ApiController
|
|||
end
|
||||
|
||||
elsif request.post?
|
||||
ms = MusicianSearch.user_search_filter(current_user)
|
||||
sobj = MusicianSearch.user_search_filter(current_user)
|
||||
filter = params[:filter]
|
||||
if filter == 'reset'
|
||||
@search = ms.reset_search_results
|
||||
@search = sobj.reset_search_results
|
||||
else
|
||||
json = JSON.parse(filter, :create_additions => false)
|
||||
@search = ms.search_results_page(json, [params[:page].to_i, 1].max)
|
||||
@search = sobj.search_results_page(json, [params[:page].to_i, 1].max)
|
||||
end
|
||||
respond_with @search, responder: ApiResponder, status: 201, template: 'api_search/index'
|
||||
end
|
||||
end
|
||||
|
||||
def bands
|
||||
if request.get?
|
||||
if params[:results]
|
||||
@search = BandSearch.user_search_filter(current_user).search_results_page(params[:subtype])
|
||||
respond_with @search, responder: ApiResponder, status: 201, template: 'api_search/index'
|
||||
else
|
||||
render :json => BandSearch.search_filter_json(current_user, params[:subtype]), :status => 200
|
||||
end
|
||||
|
||||
elsif request.post?
|
||||
sobj = BandSearch.user_search_filter(current_user)
|
||||
filter = params[:filter]
|
||||
if filter == 'reset'
|
||||
@search = sobj.reset_search_results(params[:subtype])
|
||||
else
|
||||
json = JSON.parse(filter, :create_additions => false)
|
||||
@search = sobj.search_results_page(params[:subtype], json, [params[:page].to_i, 1].max)
|
||||
end
|
||||
respond_with @search, responder: ApiResponder, status: 201, template: 'api_search/index'
|
||||
end
|
||||
|
|
|
|||
|
|
@ -796,7 +796,7 @@ class ApiUsersController < ApiController
|
|||
play.save
|
||||
|
||||
if play.errors.any?
|
||||
render :json => { :message => "Unexpected error occurred" }, :status => 500
|
||||
render :json => { :errors => play.errors }, :status => 422
|
||||
else
|
||||
render :json => {}, :status => 201
|
||||
end
|
||||
|
|
|
|||
|
|
@ -69,7 +69,12 @@ class SpikesController < ApplicationController
|
|||
end
|
||||
|
||||
def musician_search_filter
|
||||
# gon.musician_search_meta = MusicianSearch::SEARCH_FILTER_META
|
||||
# gon.musician_search_meta = MusicianSearch.search_filter_meta
|
||||
render :layout => 'web'
|
||||
end
|
||||
|
||||
def band_search_filter
|
||||
gon.band_search_meta = BandSearch.search_filter_meta
|
||||
render :layout => 'web'
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -67,7 +67,8 @@ module ClientHelper
|
|||
gon.ftue_network_test_duration = Rails.application.config.ftue_network_test_duration
|
||||
gon.ftue_network_test_max_clients = Rails.application.config.ftue_network_test_max_clients
|
||||
gon.ftue_maximum_gear_latency = Rails.application.config.ftue_maximum_gear_latency
|
||||
gon.musician_search_meta = MusicianSearch::SEARCH_FILTER_META
|
||||
gon.musician_search_meta = MusicianSearch.search_filter_meta
|
||||
gon.band_search_meta = BandSearch.search_filter_meta
|
||||
|
||||
# is this the native client or browser?
|
||||
@nativeClient = is_native_client?
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ object @jam_track
|
|||
attributes :id, :name, :description, :recording_type, :original_artist, :songwriter, :publisher, :sales_region, :price, :version, :duration
|
||||
|
||||
node :genres do |item|
|
||||
[item.genre.description] # XXX: need to return single genre; not array
|
||||
item.genres.select(:description).map(&:description)
|
||||
end
|
||||
|
||||
node :added_cart do |item|
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
object @jam_track
|
||||
|
||||
attributes :id, :name, :description, :initial_play_silence, :original_artist, :version, :genre
|
||||
attributes :id, :name, :description, :initial_play_silence, :original_artist, :version
|
||||
|
||||
node :genre do |jam_track|
|
||||
jam_track.genre.present? ? jam_track.genre.id : nil
|
||||
node :genres do |item|
|
||||
item.genres.select(:description).map(&:description)
|
||||
end
|
||||
|
||||
node :jmep do |jam_track|
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
object @search
|
||||
|
||||
node :search_type do |ss| ss.search_type end
|
||||
|
||||
if @search.is_a?(MusicianSearch)
|
||||
if @search.is_a?(BaseSearch)
|
||||
|
||||
node :page_count do |foo|
|
||||
@search.page_count
|
||||
|
|
@ -12,18 +10,19 @@ if @search.is_a?(MusicianSearch)
|
|||
current_user.last_jam_audio_latency.round if current_user.last_jam_audio_latency
|
||||
end
|
||||
|
||||
node :is_blank_filter do |foo|
|
||||
@search.is_blank?
|
||||
end
|
||||
|
||||
node :filter_json do |foo|
|
||||
@search.to_json
|
||||
end
|
||||
|
||||
node :summary do |foo|
|
||||
@search.description
|
||||
end
|
||||
if @search.is_a? MusicianSearch
|
||||
node :description do |foo|
|
||||
@search.description
|
||||
end
|
||||
|
||||
node :is_blank_filter do |foo|
|
||||
@search.is_blank?
|
||||
end
|
||||
|
||||
child(:results => :musicians) {
|
||||
attributes :id, :first_name, :last_name, :name, :city, :state, :country, :online, :musician, :photo_url, :biography, :regionname, :score, :full_score
|
||||
|
||||
|
|
@ -53,8 +52,8 @@ if @search.is_a?(MusicianSearch)
|
|||
node :name do |uu| uu.name end
|
||||
end
|
||||
|
||||
node :follow_count do |musician| @search.follow_count(musician) end
|
||||
node :friend_count do |musician| @search.friend_count(musician) end
|
||||
node :follow_count do |musician| @search.follow_count(musician) end
|
||||
node :recording_count do |musician| @search.record_count(musician) end
|
||||
node :session_count do |musician| @search.session_count(musician) end
|
||||
|
||||
|
|
@ -62,8 +61,49 @@ if @search.is_a?(MusicianSearch)
|
|||
last_jam_audio_latency(musician)
|
||||
end
|
||||
}
|
||||
|
||||
elsif @search.is_a?(BandSearch)
|
||||
|
||||
node :is_blank_filter do |foo|
|
||||
@search.is_blank?(params[:subtype])
|
||||
end
|
||||
|
||||
node :description do |foo|
|
||||
@search.description(params[:subtype])
|
||||
end
|
||||
|
||||
child(:results => :bands) {
|
||||
attributes :id, :name, :city, :state, :country, :photo_url, :biography, :logo_url, :website
|
||||
|
||||
node :is_following do |band|
|
||||
@search.is_follower?(band)
|
||||
end
|
||||
|
||||
node :biography do |band|
|
||||
band.biography.nil? ? "" : band.biography
|
||||
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
|
||||
|
||||
else
|
||||
|
||||
node :search_type do |ss| ss.search_type end
|
||||
|
||||
if @search.session_invite_search?
|
||||
child(:results => :suggestions) {
|
||||
node :value do |uu| uu.name end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,216 @@
|
|||
.content-body-scroller
|
||||
div#band-search-filter-builder.content-wrapper
|
||||
|
||||
div#band-search-filter-results.content-wrapper
|
||||
div#band-search-filter-results-header
|
||||
#band-search-filter-results-blank
|
||||
a.button-orange#btn-band-search-builder-to_join href="#" SEARCH FOR BAND TO JOIN
|
||||
| - or -
|
||||
a.button-orange#btn-band-search-builder-to_hire href="#" SEARCH FOR BAND TO HIRE
|
||||
#band-search-filter-results-filtered
|
||||
a.button-orange#btn-band-search-builder href="#" SEARCH
|
||||
a.button-grey#btn-band-search-reset href="#" RESET
|
||||
div#band-search-filter-description
|
||||
div.clearall
|
||||
div#band-search-filter-spinner.spinner-large
|
||||
|
||||
div#band-search-filter-results-wrapper
|
||||
div#band-search-filter-results-list-blank
|
||||
div.content-wrapper#band-search-filter-results-list
|
||||
div.paginate-wait
|
||||
Fetching more results...
|
||||
div.spinner-small
|
||||
|
||||
script#template-band-search-filter-to_join type="text/template"
|
||||
#bands-filter-to_join
|
||||
.band-search-filter-builder-top.builder-section
|
||||
.col-left
|
||||
h2 search bands
|
||||
/ .col-right.builder-sort-order
|
||||
/ .sort-order-selector
|
||||
/ select.easydropdown name="sort_order"
|
||||
/ option selected="selected" value="{sort_order}" {sort_order}
|
||||
/ .text-label Sort Results By:
|
||||
.clearall
|
||||
|
||||
.band-search-filter-builder-middle1.builder-section
|
||||
.col-left
|
||||
.field
|
||||
label for="search-filter-genres" Genres:
|
||||
.search-filter-setup-genres.band-setup-genres
|
||||
table#search-filter-genres cellpadding="10" cellspacing="6" width="100%"
|
||||
|
||||
.col-right
|
||||
.field
|
||||
label for="search-filter-instruments"
|
||||
| Looking for New Members with These Skills:
|
||||
.search-filter-setup-instruments.band-setup-genres.builder-instruments
|
||||
table#search-filter-instruments cellpadding="10" cellspacing="6" width="100%"
|
||||
|
||||
.clearall
|
||||
|
||||
.band-search-filter-builder-middle2.builder-section
|
||||
.col-left
|
||||
.field.builder-selector
|
||||
label Type:
|
||||
select.easydropdown name="band_type"
|
||||
option selected="selected" value="{band_type}" {band_type}
|
||||
|
||||
.field.builder-selector
|
||||
label Play Commitment:
|
||||
select.easydropdown name="play_commitment"
|
||||
option selected="selected" value="{play_commitment}" {play_commitment}
|
||||
|
||||
.col-right
|
||||
.field.builder-selector
|
||||
.lhs
|
||||
label Status:
|
||||
select.easydropdown name="band_status"
|
||||
option selected="selected" value="{band_status}" {band_status}
|
||||
|
||||
.field.builder-selector
|
||||
.rhs
|
||||
label Concert Gigs Played:
|
||||
select.easydropdown name="concert_gigs"
|
||||
option selected="selected" value="{concert_gigs}" {concert_gigs}
|
||||
|
||||
.clearall
|
||||
|
||||
.field.builder-selector
|
||||
.lhs
|
||||
label Touring Option:
|
||||
select.easydropdown name="touring_option"
|
||||
option selected="selected" value="{touring_option}" {touring_option}
|
||||
.clearall
|
||||
|
||||
.clearall
|
||||
.band-search-filter-builder-bottom.builder-section.builder-action-buttons
|
||||
.col-right
|
||||
a#btn-band-search-cancel.builder-button.button-grey href="#" CANCEL
|
||||
a#btn-perform-band-search.builder-button.button-orange href="#" SEARCH
|
||||
|
||||
script#template-band-search-filter-to_hire type="text/template"
|
||||
#bands-filter-to_hire
|
||||
.band-search-filter-builder-top-to_hire.builder-section
|
||||
.col-left
|
||||
h2 search bands to hire
|
||||
.col-right.builder-sort-order
|
||||
.sort-order-selector
|
||||
select.easydropdown name="sort_order"
|
||||
option selected="selected" value="{sort_order}" {sort_order}
|
||||
.text-label Sort Results By:
|
||||
.clearall
|
||||
|
||||
.band-search-filter-builder-middle1.builder-section
|
||||
.col-left
|
||||
.field
|
||||
label for="search-filter-genres" Genres:
|
||||
.search-filter-setup-genres.band-setup-genres
|
||||
table#search-filter-genres cellpadding="10" cellspacing="6" width="100%"
|
||||
|
||||
.col-right
|
||||
.field.builder-selector
|
||||
label Status:
|
||||
select.easydropdown name="band_status"
|
||||
option selected="selected" value="{band_status}" {band_status}
|
||||
|
||||
.field.builder-selector
|
||||
label Concert Gigs Played:
|
||||
select.easydropdown name="concert_gigs"
|
||||
option selected="selected" value="{concert_gigs}" {concert_gigs}
|
||||
|
||||
.field.builder-selector
|
||||
label Performance Sample Available:
|
||||
select.easydropdown name="performance_samples"
|
||||
option selected="selected" value="{performance_samples}" {performance_samples}
|
||||
|
||||
.clearall
|
||||
|
||||
.band-search-filter-builder-middle2.builder-section
|
||||
.field.builder-selector
|
||||
<input type="checkbox" id="has_max_cost" {has_max_cost} > Find bands to play a paid gig at a cost not to exceed $
|
||||
input type="text" id="max_cost_amount" name="max_cost" value="{max_cost}"
|
||||
|
||||
.field.builder-selector
|
||||
<input type="checkbox" id="free_gigs" name="free_gigs" {has_free_gigs} > Find bands that will play free gigs
|
||||
|
||||
.clearall
|
||||
|
||||
.clearall
|
||||
.band-search-filter-builder-bottom.builder-section.builder-action-buttons
|
||||
.col-right
|
||||
a#btn-band-search-cancel.builder-button.button-grey href="#" CANCEL
|
||||
a#btn-perform-band-search.builder-button.button-orange href="#" SEARCH
|
||||
|
||||
script#template-search-filter-setup-instrument type="text/template"
|
||||
tr data-instrument-id="{id}"
|
||||
td <input type="checkbox" {checked} />{description}
|
||||
td align="right" width="50%"
|
||||
select.proficiency_selector name="proficiency"
|
||||
option value="1" Beginner
|
||||
option value="2" Intermediate
|
||||
option value="3" Expert
|
||||
|
||||
script#template-search-filter-setup-genres type="text/template"
|
||||
tr
|
||||
td <input value="{id}" {checked} type="checkbox" />{description}
|
||||
|
||||
script#template-find-band-row type="text/template"
|
||||
.profile-band-list-result.band-list-result
|
||||
.f11
|
||||
.left style="width:63px;margin-top:-12px;"
|
||||
.avatar-small
|
||||
img src="{avatar_url}" /
|
||||
.right.mband-players style="width:265px; margin-top:-4px;"
|
||||
table.musicians cellpadding="0" cellspacing="5"
|
||||
| {band_player_template}
|
||||
div style="margin-left: 63px; margin-right: 275px;margin-top: 12px;"
|
||||
.first-row data-hint="top-row"
|
||||
.lcol.left
|
||||
.result-name
|
||||
| {band_name}
|
||||
.result-location
|
||||
| {band_location}
|
||||
br
|
||||
#result_genres.nowrap.mt10
|
||||
| {genres}
|
||||
.whitespace
|
||||
.biography
|
||||
| {biography}
|
||||
.clearleft
|
||||
.button-row
|
||||
.lcol.stats.left
|
||||
span.follower-count
|
||||
| {follow_count}
|
||||
img src="../assets/content/icon_followers.png" width="22" height="12" align="absmiddle" style="margin-right:4px;"
|
||||
span.recording-count
|
||||
| {recording_count}
|
||||
img src="../assets/content/icon_recordings.png" width="12" height="13" align="absmiddle" style="margin-right:4px;"
|
||||
span.session-count
|
||||
| {session_count}
|
||||
img src="../assets/content/icon_session_tiny.png" width="12" height="12" align="absmiddle"
|
||||
.clearall
|
||||
.result-list-button-wrapper data-band-id="{band_id}"
|
||||
| {band_action_template}
|
||||
.clearall
|
||||
|
||||
script#template-band-action-btns type="text/template"
|
||||
a.button-orange.smallbutton href="{profile_url}" PROFILE
|
||||
a.smallbutton.search-m-follow href="#" class="{button_follow}" FOLLOW
|
||||
|
||||
script#template-band-edit-btns type="text/template"
|
||||
a.button-orange.smallbutton href="{profile_url}" PROFILE
|
||||
a.button-orange.smallbutton href="{band_edit_url}" EDIT BAND
|
||||
a.button-orange.smallbutton href="{band_member_url}" INVITE
|
||||
|
||||
script#template-band-player-info type="text/template"
|
||||
tr
|
||||
td
|
||||
a.avatar-tiny href="{profile_url}" user-id="{user_id}" hoveraction="musician"
|
||||
img src="{avatar_url}"
|
||||
td style="padding: 0 4px;width:88px;"
|
||||
a user-id="{user_id}" hoveraction="musician" href="{profile_url}"
|
||||
strong
|
||||
| {player_name}
|
||||
td.instruments
|
||||
| {player_instruments}
|
||||
|
|
@ -1,86 +0,0 @@
|
|||
<!-- Band Screen -->
|
||||
<%= content_tag(:div, :layout => 'screen', 'layout-id' => 'bands', :class => "screen secondary", :id => "bands-screen") 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 -%>
|
||||
<%= form_tag('', {:id => 'find-band-form', :class => 'inner-content'}) do -%>
|
||||
<%= render(:partial => "web_filter", :locals => {:search_type => Search::PARAM_BAND}) %>
|
||||
<%= content_tag(:div, :class => 'filter-body') do %>
|
||||
<%= content_tag(:div, :class => 'content-body-scroller') do -%>
|
||||
<%= content_tag(:div, content_tag(:div, '', :id => 'band-filter-results', :class => 'filter-results'), :class => 'content-wrapper') %>
|
||||
<% end -%>
|
||||
<% end -%>
|
||||
<% end -%>
|
||||
<% end -%>
|
||||
<% end -%>
|
||||
<% end -%>
|
||||
|
||||
<!-- Session Row Template -->
|
||||
<script type="text/template" id="template-find-band-row"><!-- -->
|
||||
<div class="profile-band-list-result band-list-result">
|
||||
<div class="f11">
|
||||
<div class="left" style="width:63px;margin-top:-12px;">
|
||||
<!-- avatar -->
|
||||
<div class="avatar-small"><img src="{avatar_url}" /></div>
|
||||
</div>
|
||||
<div class="right mband-players" style="width:265px; margin-top:-4px;">
|
||||
<table class="musicians" cellpadding="0" cellspacing="5">{band_player_template}</table>
|
||||
</div>
|
||||
<div class="" style="margin-left: 63px; margin-right: 275px;margin-top: 12px;">
|
||||
<div class="first-row" data-hint="top-row">
|
||||
<div class="lcol left">
|
||||
<!-- name & location -->
|
||||
<div class="result-name">{band_name}</div>
|
||||
<div class="result-location">{band_location}</div>
|
||||
<br />
|
||||
<div id="result_genres" class="nowrap mt10">{genres}</div>
|
||||
</div>
|
||||
<div class="whitespace">
|
||||
<div class="biography">{biography}</div>
|
||||
</div>
|
||||
<div class="clearleft"></div>
|
||||
</div>
|
||||
<div class="button-row">
|
||||
<div class="lcol stats left">
|
||||
<span class="follower-count">{follow_count} <img src="../assets/content/icon_followers.png" width="22" height="12" align="absmiddle" style="margin-right:4px;"/></span>
|
||||
<span class="recording-count">{recording_count} <img src="../assets/content/icon_recordings.png" width="12" height="13" align="absmiddle" style="margin-right:4px;"/></span>
|
||||
<span class="session-count">{session_count} <img src="../assets/content/icon_session_tiny.png" width="12" height="12" align="absmiddle" /></span>
|
||||
</div>
|
||||
<div class="clearall"></div>
|
||||
<div class="result-list-button-wrapper" data-band-id={band_id}>
|
||||
{band_action_template}
|
||||
</div>
|
||||
<div class="clearall"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/template" id="template-band-action-btns">
|
||||
<a href="{profile_url}" class="button-orange smallbutton">PROFILE</a>
|
||||
<a href="#" class="{button_follow} smallbutton search-m-follow">FOLLOW</a>
|
||||
</script>
|
||||
|
||||
<script type="text/template" id="template-band-edit-btns">
|
||||
<a href="{profile_url}" class="button-orange smallbutton">PROFILE</a>
|
||||
<a href="{band_edit_url}" class="button-orange smallbutton">EDIT BAND</a>
|
||||
<a href="{band_member_url}" class="button-orange smallbutton">INVITE</a>
|
||||
</script>
|
||||
|
||||
<script type="text/template" id="template-band-player-info">
|
||||
<tr>
|
||||
<td>
|
||||
<a href="{profile_url}" user-id="{user_id}" hoveraction="musician" class="avatar-tiny"><img src="{avatar_url}" /></a>
|
||||
</td>
|
||||
<td style="padding: 0 4px;width:88px;">
|
||||
<a user-id="{user_id}" hoveraction="musician" href="{profile_url}"><strong>{player_name}</strong></a>
|
||||
</td>
|
||||
<td class="instruments">{player_instruments}</td>
|
||||
</tr>
|
||||
</script>
|
||||
|
||||
|
|
@ -0,0 +1,140 @@
|
|||
#bands-screen.screen.secondary layout="screen" layout-id="bands"
|
||||
.content
|
||||
.content-head
|
||||
.content-icon
|
||||
img alt="Icon_bands" height="19" src="/assets/content/icon_bands.png" width="19" /
|
||||
h1 bands
|
||||
= render "screen_navigation"
|
||||
.content-body
|
||||
= render "clients/band_search_filter"
|
||||
|
||||
script#template-band-search-filter-to_join type="text/template"
|
||||
#bands-filter-to_join
|
||||
#band-search-filter-builder-top.builder-section
|
||||
.col-left
|
||||
h2 search bands
|
||||
.col-right.builder-sort-order
|
||||
.text-label Sort Results By:
|
||||
select.easydropdown name="sort_order"
|
||||
option selected="selected" value="{sort_order}" {sort_order}
|
||||
.clearall
|
||||
|
||||
#band-search-filter-builder-middle1.builder-section
|
||||
.col-left
|
||||
.field
|
||||
label for="search-filter-genres" Genres:
|
||||
.search-filter-setup-genres.band-setup-genres
|
||||
table#search-filter-genres cellpadding="10" cellspacing="6" width="100%"
|
||||
|
||||
.col-right
|
||||
.field
|
||||
label for="search-filter-instruments"
|
||||
| Instruments & Skill Level:
|
||||
.search-filter-setup-instruments.band-setup-genres.builder-instruments
|
||||
table#search-filter-instruments cellpadding="10" cellspacing="6" width="100%"
|
||||
.clearall
|
||||
|
||||
#band-search-filter-builder-middle2.builder-section
|
||||
.col-left
|
||||
.field.builder-selector
|
||||
label Type:
|
||||
select.easydropdown name="band_type"
|
||||
option selected="selected" value="{band_type}" {band_type}
|
||||
|
||||
.field.builder-selector
|
||||
label Play Commitment:
|
||||
select.easydropdown name="play_commit"
|
||||
option selected="selected" value="{play_commit}" {play_commit}
|
||||
|
||||
.col-right
|
||||
.field.builder-selector
|
||||
label Status:
|
||||
select.easydropdown name="skill_level"
|
||||
option selected="selected" value="{skill_level}" {skill_level}
|
||||
|
||||
.field.builder-selector
|
||||
label Concert Gigs Played:
|
||||
select.easydropdown name="concert_gigs"
|
||||
option selected="selected" value="{concert_gigs}" {concert_gigs}
|
||||
|
||||
.field.builder-selector
|
||||
label Touring Option:
|
||||
select.easydropdown name="tour_option"
|
||||
option selected="selected" value="{tour_option}" {tour_option}
|
||||
|
||||
.clearall
|
||||
|
||||
.clearall
|
||||
#band-search-filter-builder-bottom.builder-section.builder-action-buttons
|
||||
.col-right
|
||||
a#btn-perform-band-search.builder-button.button-orange href="#" SEARCH
|
||||
a#btn-band-search-cancel.builder-button.button-grey href="#" CANCEL
|
||||
|
||||
/! Session Row Template
|
||||
script#template-search-band-row type="text/template"
|
||||
.profile-band-list-result.band-list-result
|
||||
.f11
|
||||
.left style="width:63px;margin-top:-12px;"
|
||||
/! avatar
|
||||
.avatar-small
|
||||
img src="{avatar_url}" /
|
||||
.right.mband-players style="width:265px; margin-top:-4px;"
|
||||
table.musicians cellpadding="0" cellspacing="5"
|
||||
| {band_player_template}
|
||||
div style="margin-left: 63px; margin-right: 275px;margin-top: 12px;"
|
||||
.first-row data-hint="top-row"
|
||||
.lcol.left
|
||||
/! name and location
|
||||
.result-name
|
||||
| {band_name}
|
||||
.result-location
|
||||
| {band_location}
|
||||
br /
|
||||
#result_genres.nowrap.mt10
|
||||
| {genres}
|
||||
.whitespace
|
||||
.biography
|
||||
| {biography}
|
||||
.clearleft
|
||||
.button-row
|
||||
.lcol.stats.left
|
||||
span.follower-count
|
||||
| {follow_count}
|
||||
img src="../assets/content/icon_followers.png" width="22" height="12" align="absmiddle" style="margin-right:4px;" /
|
||||
span.recording-count
|
||||
| {recording_count}
|
||||
img src="../assets/content/icon_recordings.png" width="12" height="13" align="absmiddle" style="margin-right:4px;" /
|
||||
span.session-count
|
||||
| {session_count}
|
||||
img src="../assets/content/icon_session_tiny.png" width="12" height="12" align="absmiddle" /
|
||||
.clearall
|
||||
.result-list-button-wrapper data-band-id="{band_id}"
|
||||
| {band_action_template}
|
||||
.clearall
|
||||
|
||||
script#template-search-band-action-btns type="text/template"
|
||||
a.button-orange smallbutton href="{profile_url}"
|
||||
PROFILE
|
||||
a class="{button_follow} smallbutton search-m-follow" href="#"
|
||||
FOLLOW
|
||||
|
||||
script#template-search-band-edit-btns type="text/template"
|
||||
a href="{profile_url}" class="button-orange smallbutton"
|
||||
PROFILE
|
||||
a href="{band_edit_url}" class="button-orange smallbutton"
|
||||
EDIT BAND
|
||||
a href="{band_member_url}" class="button-orange smallbutton"
|
||||
INVITE
|
||||
|
||||
script#template-search-band-player-info type="text/template"
|
||||
tr
|
||||
td
|
||||
a.avatar-tiny href="{profile_url}" user-id="{user_id}" hoveraction="musician"
|
||||
img src="{avatar_url}" /
|
||||
td style="padding: 0 4px;width:88px"
|
||||
a user-id="{user_id}" hoveraction="musician" href="{profile_url}"
|
||||
strong
|
||||
| {player_name}
|
||||
td.instruments
|
||||
| {player_instruments}
|
||||
|
||||
|
|
@ -4,7 +4,6 @@
|
|||
div#musician-search-filter-results.content-wrapper
|
||||
div#musician-search-filter-results-header
|
||||
a#btn-musician-search-builder.button-orange href="#" SEARCH
|
||||
span.musician-search-text Click search button to look for musicians with similar interests, skill levels, etc.
|
||||
a#btn-musician-search-reset.button-grey href="#" RESET
|
||||
div#musician-search-filter-description
|
||||
div.clearall
|
||||
|
|
@ -22,51 +21,51 @@ script#template-musician-search-filter type="text/template"
|
|||
.col-left
|
||||
h2 search musicians
|
||||
.col-right.builder-sort-order
|
||||
.text-label Sort Results By:
|
||||
select.easydropdown name="sort_order"
|
||||
option selected="selected" value="{sort_order}" {sort_order}
|
||||
.text-label Sort Results By:
|
||||
select.easydropdown name="sort_order"
|
||||
option selected="selected" value="{sort_order}" {sort_order}
|
||||
.clearall
|
||||
|
||||
#musician-search-filter-builder-middle.builder-section
|
||||
.col-left
|
||||
.field
|
||||
label for="search-filter-genres" Genres
|
||||
.search-filter-setup-genres.band-setup-genres
|
||||
#search-filter-genres
|
||||
label for="search-filter-genres" Genres:
|
||||
.search-filter-setup-genres.musician-setup-genres
|
||||
table#search-filter-genres cellpadding="10" cellspacing="6" width="100%"
|
||||
|
||||
.field.builder-selector
|
||||
label Interests
|
||||
label Interests:
|
||||
select.easydropdown name="interests"
|
||||
option selected="selected" value="{interests}" {interests}
|
||||
|
||||
.field.builder-selector
|
||||
label Studio Sessions Played
|
||||
label Studio Sessions Played:
|
||||
select.easydropdown name="studio_sessions"
|
||||
option selected="selected" value="{studio_sessions}" {studio_sessions}
|
||||
|
||||
.col-right
|
||||
.field
|
||||
label for="search-filter-instruments"
|
||||
| Instruments & Skill Level
|
||||
.search-filter-setup-instruments.band-setup-genres.builder-instruments.session-instrumentlist
|
||||
| Instruments & Skill Level:
|
||||
.search-filter-setup-instruments.musician-setup-genres.builder-instruments
|
||||
table#search-filter-instruments cellpadding="10" cellspacing="6" width="100%"
|
||||
|
||||
.col-left
|
||||
.field.builder-selector
|
||||
label Status
|
||||
label Status:
|
||||
select.easydropdown name="skill_level"
|
||||
option selected="selected" value="{skill_level}" {skill_label}
|
||||
|
||||
.field.builder-selector
|
||||
label Concert Gigs Played
|
||||
label Concert Gigs Played:
|
||||
select.easydropdown name="concert_gigs"
|
||||
option selected="selected" value="{concert_gigs}" {concert_gigs}
|
||||
|
||||
.col-right
|
||||
.field.builder-selector
|
||||
label for="search-filter-ages" Ages
|
||||
.search-filter-setup-ages.band-setup-genres.builder-ages
|
||||
#search-filter-ages
|
||||
label for="search-filter-ages" Ages:
|
||||
.search-filter-setup-ages.builder-ages
|
||||
table#search-filter-ages cellpadding="10" cellspacing="6" width="100%"
|
||||
.clearall
|
||||
|
||||
.clearall
|
||||
|
|
@ -85,25 +84,13 @@ script#template-search-filter-setup-instrument type="text/template"
|
|||
option value="2" Intermediate
|
||||
option value="3" Expert
|
||||
|
||||
script#template-search-filter-setup-genres type="text/template"
|
||||
.genre-option
|
||||
| {% if(data.checked) { %}
|
||||
input value="{{data.id}}" checked="checked" type="checkbox"
|
||||
| {% } else { %}
|
||||
input value="{{data.id}}" type="checkbox"
|
||||
| {% } %}
|
||||
label
|
||||
| {{data.description}}
|
||||
script#template-search-filter-setup-genres type="text/template"
|
||||
tr
|
||||
td <input value="{id}" {checked} type="checkbox" />{description}
|
||||
|
||||
script#template-search-filter-setup-ages type="text/template"
|
||||
.age-option
|
||||
| {% if(data.checked) { %}
|
||||
input value="{{data.id}}" checked="checked" type="checkbox"
|
||||
| {% } else { %}
|
||||
input value="{{data.id}}" type="checkbox"
|
||||
| {% } %}
|
||||
label
|
||||
| {{data.description}}
|
||||
script#template-search-filter-setup-ages type="text/template"
|
||||
tr
|
||||
td <input value="{id}" {checked} type="checkbox" />{description}
|
||||
|
||||
/! Session Row Template
|
||||
script#template-search-musician-row type="text/template"
|
||||
|
|
|
|||
|
|
@ -314,21 +314,17 @@
|
|||
// var findMusicianScreen = new JK.FindMusicianScreen(JK.app);
|
||||
//findMusicianScreen.initialize(JK.TextMessageDialogInstance);
|
||||
|
||||
var findBandScreen = new JK.BandSearchFilter();
|
||||
findBandScreen.init(JK.app);
|
||||
|
||||
var redeemSignUpScreen = new JK.RedeemSignUpScreen(JK.app);
|
||||
redeemSignUpScreen.initialize();
|
||||
|
||||
var redeemCompleteScreen = new JK.RedeemCompleteScreen(JK.app);
|
||||
redeemCompleteScreen.initialize();
|
||||
|
||||
var findBandScreen = new JK.FindBandScreen(JK.app);
|
||||
findBandScreen.initialize();
|
||||
|
||||
//var sessionScreen = new JK.SessionScreen(JK.app);
|
||||
//sessionScreen.initialize(localRecordingsDialog, recordingFinishedDialog, JK.FriendSelectorDialogInstance);
|
||||
|
||||
AppActions.appInit.trigger(JK.app)
|
||||
|
||||
|
||||
var addNewGearDialog = new JK.AddNewGearDialog(JK.app);
|
||||
addNewGearDialog.initialize();
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
= javascript_include_tag "profile_utils"
|
||||
= javascript_include_tag "member_search_filter"
|
||||
= stylesheet_link_tag "client/band"
|
||||
#bands-screen
|
||||
= render "clients/band_search_filter"
|
||||
|
||||
javascript:
|
||||
var initialized = false;
|
||||
$(document).on('JAMKAZAM_READY', function(e, data) {
|
||||
setTimeout(function() {
|
||||
window.band_search_filter = new JK.BandSearchFilter();
|
||||
band_search_filter.init(data.app);
|
||||
band_search_filter.afterShow();
|
||||
}, 1)
|
||||
});
|
||||
|
|
@ -1,15 +1,15 @@
|
|||
= javascript_include_tag "profile_utils"
|
||||
= javascript_include_tag "musician_search_filter"
|
||||
= javascript_include_tag "member_search_filter"
|
||||
= stylesheet_link_tag "client/musician"
|
||||
#musician_search_spike
|
||||
= render "clients/musician_search_filter"
|
||||
#musicians-screen
|
||||
= render "clients/musician_search_filter"
|
||||
|
||||
javascript:
|
||||
var initialized = false;
|
||||
$(document).on('JAMKAZAM_READY', function(e, data) {
|
||||
setTimeout(function() {
|
||||
window.musician_search_filter = new JK.MusicianSearchFilter();
|
||||
musician_search_filter.init();
|
||||
musician_search_filter.init(data.app);
|
||||
musician_search_filter.afterShow();
|
||||
}, 1)
|
||||
});
|
||||
|
|
|
|||
|
|
@ -118,6 +118,7 @@ SampleApp::Application.routes.draw do
|
|||
match '/site_validate', to: 'spikes#site_validate'
|
||||
match '/recording_source', to: 'spikes#recording_source'
|
||||
match '/musician_search_filter', to: 'spikes#musician_search_filter'
|
||||
match '/band_search_filter', to: 'spikes#band_search_filter'
|
||||
|
||||
# junk pages
|
||||
match '/help', to: 'static_pages#help'
|
||||
|
|
@ -485,6 +486,7 @@ SampleApp::Application.routes.draw do
|
|||
# search
|
||||
match '/search' => 'api_search#index', :via => :get
|
||||
match '/search/musicians' => 'api_search#musicians', :via => [:get, :post]
|
||||
match '/search/bands' => 'api_search#bands', :via => [:get, :post]
|
||||
|
||||
# join requests
|
||||
match '/join_requests/:id' => 'api_join_requests#show', :via => :get, :as => 'api_join_request_detail'
|
||||
|
|
|
|||
|
|
@ -5,24 +5,11 @@ class MaxMindManager < BaseManager
|
|||
end
|
||||
|
||||
def self.countries
|
||||
Country.get_all.map do |c|
|
||||
country = Carmen::Country.coded(c.countrycode)
|
||||
{
|
||||
countrycode: c.countrycode,
|
||||
countryname: country.name
|
||||
}
|
||||
end
|
||||
Country.get_all.map { |c| {countrycode: c.countrycode, countryname: c.countryname} }
|
||||
end
|
||||
|
||||
def self.regions(country)
|
||||
Region.get_all(country).map do |r|
|
||||
country = Carmen::Country.coded(r.countrycode)
|
||||
region = country.subregions.coded(r.region)
|
||||
{
|
||||
region: r.region,
|
||||
name: region.name
|
||||
}
|
||||
end
|
||||
Region.get_all(country).map { |r| { region: r.region, name: r.regionname } }
|
||||
end
|
||||
|
||||
def self.cities(country, region)
|
||||
|
|
|
|||
|
|
@ -4,15 +4,49 @@ namespace :jam_tracks do
|
|||
JamTrackImporter.dry_run
|
||||
end
|
||||
|
||||
task tency_dry_run: :environment do |task, args|
|
||||
JamTrackImporter.storage_format = 'Tency'
|
||||
JamTrackImporter.dry_run
|
||||
end
|
||||
|
||||
task tency_create_masters: :environment do |task, args|
|
||||
JamTrackImporter.storage_format = 'Tency'
|
||||
JamTrackImporter.create_masters
|
||||
end
|
||||
|
||||
|
||||
task tency_create_master: :environment do |task, args|
|
||||
JamTrackImporter.storage_format = 'Tency'
|
||||
|
||||
path = ENV['TRACK_PATH']
|
||||
|
||||
if !path
|
||||
puts "TRACK_PATH must be set to something like audio/AC DC/Back in Black or mapped/50 Cent - In Da Club - 12401"
|
||||
exit(1)
|
||||
end
|
||||
|
||||
JamTrackImporter.create_master(path)
|
||||
end
|
||||
|
||||
|
||||
task tency_delta: :environment do |task, args|
|
||||
JamTrackImporter.storage_format = 'Tency'
|
||||
JamTrackImporter.tency_delta
|
||||
end
|
||||
|
||||
task sync: :environment do |task, args|
|
||||
path = ENV['TRACK_PATH']
|
||||
|
||||
if !path
|
||||
puts "TRACK_PATH must be set to something like AD DC/Back in Black"
|
||||
puts "TRACK_PATH must be set to something like audio/AC DC/Back in Black or mapped/50 Cent - In Da Club - 12401"
|
||||
exit(1)
|
||||
end
|
||||
|
||||
JamTrackImporter.synchronize_from_meta("audio/#{path}/meta.yml", skip_audio_upload:false)
|
||||
if path.start_with?('mapped')
|
||||
JamTrackImporter.storage_format = 'Tency'
|
||||
end
|
||||
|
||||
JamTrackImporter.synchronize_from_meta("#{path}/meta.yml", skip_audio_upload:false)
|
||||
end
|
||||
|
||||
task resync_audio: :environment do |task, args|
|
||||
|
|
@ -26,11 +60,26 @@ namespace :jam_tracks do
|
|||
JamTrackImporter.synchronize_from_meta("audio/#{path}/meta.yml", resync_audio:true, skip_audio_upload:false)
|
||||
end
|
||||
|
||||
task tency_genre_dump: :environment do |task, args|
|
||||
JamTrackImporter.storage_format = 'Tency'
|
||||
JamTrackImporter.genre_dump
|
||||
end
|
||||
|
||||
task sync_tency: :environment do |task, args|
|
||||
JamTrackImporter.storage_format = 'Tency'
|
||||
JamTrackImporter.synchronize_all(skip_audio_upload:false)
|
||||
end
|
||||
|
||||
task onboarding_exceptions: :environment do |task, args|
|
||||
JamTrackImporter.onboarding_exceptions
|
||||
end
|
||||
|
||||
task sync_all: :environment do |task, args|
|
||||
JamTrackImporter.synchronize_all(skip_audio_upload:false)
|
||||
end
|
||||
|
||||
task sync_all_dev: :environment do |task, args|
|
||||
JamTrackImporter.storage_format = 'default'
|
||||
JamTrackImporter.synchronize_all(skip_audio_upload:true)
|
||||
end
|
||||
|
||||
|
|
@ -91,4 +140,10 @@ namespace :jam_tracks do
|
|||
task download_masters: :environment do |task, arg|
|
||||
JamTrackImporter.download_masters
|
||||
end
|
||||
|
||||
|
||||
task tency: :environment do |task, arg|
|
||||
mapper = TencyStemMapping.new
|
||||
mapper.correlate
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ 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})
|
||||
BandMusician.create({:user_id => uu.id, :band_id => bb.id})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -128,6 +128,7 @@ describe ApiJamTracksController do
|
|||
# of this process is checked in other tests:
|
||||
@ogg_path = File.join('spec', 'files', 'on.ogg')
|
||||
@jam_track = FactoryGirl.create(:jam_track) #jam_track_track.jam_track
|
||||
@jam_track.reload
|
||||
jam_track_track = @jam_track.jam_track_tracks.first
|
||||
|
||||
# 48 kHz:
|
||||
|
|
|
|||
|
|
@ -743,7 +743,7 @@ FactoryGirl.define do
|
|||
make_track true
|
||||
end
|
||||
|
||||
genre JamRuby::Genre.first
|
||||
genres [JamRuby::Genre.first]
|
||||
association :licensor, factory: :jam_track_licensor
|
||||
|
||||
after(:create) do |jam_track, evaluator|
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ describe "JamTrack Shopping", :js => true, :type => :feature, :capybara_feature
|
|||
let(:user) { FactoryGirl.create(:user, has_redeemable_jamtrack: false) }
|
||||
let(:jt_us) { FactoryGirl.create(:jam_track, :name=>'jt_us', sales_region: 'Worldwide', make_track: true, original_artist: "foobar") }
|
||||
let(:jt_ww) { FactoryGirl.create(:jam_track, :name=>'jt_ww', sales_region: 'Worldwide', make_track: true, original_artist: "barfoo") }
|
||||
let(:jt_rock) { FactoryGirl.create(:jam_track, :name=>'jt_rock', genre: JamRuby::Genre.find('rock'), make_track: true, original_artist: "badfood") }
|
||||
let(:jt_blues) { FactoryGirl.create(:jam_track, :name=>'jt_blues', genre: JamRuby::Genre.find('blues'), make_track: true, original_artist: "foodbart") }
|
||||
let(:jt_rock) { FactoryGirl.create(:jam_track, :name=>'jt_rock', genres: [JamRuby::Genre.find('rock')], make_track: true, original_artist: "badfood") }
|
||||
let(:jt_blues) { FactoryGirl.create(:jam_track, :name=>'jt_blues', genres: [JamRuby::Genre.find('blues')], make_track: true, original_artist: "foodbart") }
|
||||
|
||||
before(:all) do
|
||||
Capybara.javascript_driver = :poltergeist
|
||||
|
|
|
|||
Loading…
Reference in New Issue