VRFS-3728 merge
|
|
@ -44,7 +44,7 @@ gem 'rails3-jquery-autocomplete'
|
|||
gem 'activeadmin' #, github: 'activeadmin', branch: '0-6-stable'
|
||||
gem 'mime-types', '1.25'
|
||||
gem 'meta_search'
|
||||
gem 'fog', "~> 1.32.0"
|
||||
gem 'fog'
|
||||
gem 'unf', '0.1.3' #optional fog dependency
|
||||
gem 'country-select'
|
||||
gem 'aasm', '3.0.16'
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
ActiveAdmin.register JamRuby::DownloadTracker, :as => 'DownloadTrackers' do
|
||||
|
||||
menu :label => 'Download Trackers', :parent => 'JamTracks'
|
||||
|
||||
config.batch_actions = false
|
||||
config.filters = true
|
||||
config.per_page = 50
|
||||
|
||||
filter :remote_ip
|
||||
|
||||
index do
|
||||
column 'User' do |oo| oo.user ? link_to(oo.user.email, oo.user.admin_url, {:title => oo.user.email}) : '' end
|
||||
column 'Remote IP' do |oo| oo.remote_ip end
|
||||
column 'JamTrack' do |oo| oo.jam_track end
|
||||
column 'Paid' do |oo| oo.paid end
|
||||
column 'Blacklisted?' do |oo| IpBlacklist.listed(oo.remote_ip) ? 'Yes' : 'No' end
|
||||
column "" do |oo|
|
||||
link_to 'Blacklist This IP', "download_trackers/#{oo.id}/blacklist_by_ip"
|
||||
end
|
||||
end
|
||||
|
||||
member_action :blacklist_by_ip, :method => :get do
|
||||
tracker = DownloadTracker.find(params[:id])
|
||||
|
||||
if !IpBlacklist.listed(tracker.remote_ip)
|
||||
ip = IpBlacklist.new
|
||||
ip.remote_ip = tracker.remote_ip
|
||||
ip.save!
|
||||
end
|
||||
|
||||
redirect_to admin_download_trackers_path, :notice => "IP address #{tracker.remote_ip} blacklisted."
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -32,6 +32,7 @@ ActiveAdmin.register_page "Fake Purchaser" do
|
|||
jam_track_right.user = user
|
||||
jam_track_right.jam_track = jam_track
|
||||
jam_track_right.is_test_purchase = true
|
||||
jam_track_right.version = jam_track.version
|
||||
jam_track_right.save!
|
||||
count = count + 1
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
ActiveAdmin.register_page "Giftcarduploads" do
|
||||
|
||||
menu :label => 'Gift Cards Upload', :parent => 'JamTracks'
|
||||
|
||||
page_action :upload_giftcards, :method => :post do
|
||||
GiftCard.transaction do
|
||||
|
||||
puts params
|
||||
|
||||
file = params[:jam_ruby_gift_card][:csv]
|
||||
array_of_arrays = CSV.read(file.tempfile.path)
|
||||
array_of_arrays.each do |row|
|
||||
if row.length != 1
|
||||
raise "UKNONWN CSV FORMAT! Must be 1 column"
|
||||
end
|
||||
|
||||
code = row[0]
|
||||
|
||||
gift_card = GiftCard.new
|
||||
gift_card.code = code
|
||||
gift_card.card_type = params[:jam_ruby_gift_card][:card_type]
|
||||
gift_card.origin = file .original_filename
|
||||
gift_card.save!
|
||||
end
|
||||
|
||||
redirect_to admin_giftcarduploads_path, :notice => "Created #{array_of_arrays.length} gift cards!"
|
||||
end
|
||||
end
|
||||
|
||||
content do
|
||||
semantic_form_for GiftCard.new, :url => admin_giftcarduploads_upload_giftcards_path, :builder => ActiveAdmin::FormBuilder do |f|
|
||||
f.inputs "Upload Gift Cards" do
|
||||
f.input :csv, as: :file, required: true, :label => "A single column CSV that contains ONE type of gift card (5 JamTrack, 10 JamTrack, etc)"
|
||||
f.input :card_type, required:true, as: :select, :collection => JamRuby::GiftCard::CARD_TYPES
|
||||
end
|
||||
f.actions
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
ActiveAdmin.register JamRuby::GiftCard, :as => 'GiftCards' do
|
||||
|
||||
menu :label => 'Gift Cards', :parent => 'JamTracks'
|
||||
|
||||
config.batch_actions = false
|
||||
config.filters = true
|
||||
config.per_page = 50
|
||||
|
||||
scope("Redeemed Most Recently", default: true) { |scope| scope.where('user_id IS NOT NULL').order('updated_at DESC') }
|
||||
scope("Available") { |scope| scope.where('user_id is NULL') }
|
||||
|
||||
filter :card_type
|
||||
filter :origin
|
||||
filter :code
|
||||
|
||||
index do
|
||||
column 'User' do |oo| oo.user ? link_to(oo.user.email, oo.user.admin_url, {:title => oo.user.email}) : '' end
|
||||
column 'Code' do |oo| oo.code end
|
||||
column 'Card Type' do |oo| oo.card_type end
|
||||
column 'Origin' do |oo| oo.origin end
|
||||
column 'Created' do |oo| oo.created_at end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -11,7 +11,8 @@ ActiveAdmin.register JamRuby::JamTrack, :as => 'JamTracks' do
|
|||
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') }
|
||||
scope("TimTracks Only") { |scope| scope.joins('INNER JOIN jam_track_licensors as licensors ON jam_tracks.licensor_id = licensors.id').where("licensors.name = 'Tim Waurick'") }
|
||||
# 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'
|
||||
|
||||
|
|
|
|||
|
|
@ -15,5 +15,11 @@ class EmailController < ApplicationController
|
|||
headers['Content-Type'] ||= 'text/csv'
|
||||
|
||||
@users = User.where(subscribe_email: true)
|
||||
|
||||
# if specified, return only users that have redeemed or bought a JamTrack
|
||||
if params[:any_jam_track]
|
||||
@users = @users.select('DISTINCT users.id, email, first_name, last_name').joins(:sales => :sale_line_items).where("sale_line_items.product_type = 'JamTrack'")
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
@ -13,6 +13,7 @@
|
|||
= f.input :publisher, :input_html => { :rows=>1, :maxlength=>1000 }
|
||||
= f.input :licensor, collection: JamRuby::JamTrackLicensor.all, include_blank: true
|
||||
= f.input :genres
|
||||
= f.input :year
|
||||
= 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'}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
class JamRuby::GiftCard
|
||||
|
||||
attr_accessor :csv
|
||||
|
||||
|
||||
def process_csv
|
||||
|
||||
end
|
||||
end
|
||||
|
|
@ -2,28 +2,5 @@ class JamRuby::JamTrack
|
|||
|
||||
# add a custom validation
|
||||
|
||||
attr_accessor :preview_generate_error
|
||||
|
||||
before_save :jmep_json_generate
|
||||
validate :jmep_text_validate
|
||||
|
||||
def jmep_text_validate
|
||||
begin
|
||||
JmepManager.execute(self.jmep_text)
|
||||
rescue ArgumentError => err
|
||||
errors.add(:jmep_text, err.to_s)
|
||||
end
|
||||
end
|
||||
|
||||
def jmep_json_generate
|
||||
self.licensor_id = nil if self.licensor_id == ''
|
||||
self.jmep_json = nil if self.jmep_json == ''
|
||||
self.time_signature = nil if self.time_signature == ''
|
||||
|
||||
begin
|
||||
self[:jmep_json] = JmepManager.execute(self.jmep_text)
|
||||
rescue ArgumentError => err
|
||||
#errors.add(:jmep_text, err.to_s)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -310,3 +310,8 @@ web_playable_jamtracks.sql
|
|||
affiliate_partner_rate.sql
|
||||
track_downloads.sql
|
||||
jam_track_lang_idx.sql
|
||||
giftcard.sql
|
||||
add_description_to_crash_dumps.sql
|
||||
acappella.sql
|
||||
purchasable_gift_cards.sql
|
||||
versionable_jamtracks.sql
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
INSERT INTO genres (id, description) values ('acapella', 'A Capella');
|
||||
ALTER TABLE jam_track_licensors ADD COLUMN slug VARCHAR UNIQUE;
|
||||
|
|
@ -0,0 +1 @@
|
|||
ALTER TABLE crash_dumps ADD COLUMN description VARCHAR(20000);
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
CREATE TABLE gift_cards (
|
||||
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
code VARCHAR(64) UNIQUE NOT NULL,
|
||||
user_id VARCHAR (64) REFERENCES users(id) ON DELETE CASCADE,
|
||||
card_type VARCHAR(64) NOT NULL,
|
||||
origin VARCHAR(200),
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE INDEX gift_card_user_id_idx ON gift_cards(user_id);
|
||||
|
||||
ALTER TABLE users ADD COLUMN gifted_jamtracks INTEGER DEFAULT 0;
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
|
||||
|
||||
CREATE TABLE gift_card_types (
|
||||
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
card_type VARCHAR(64) NOT NULL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
INSERT INTO gift_card_types (id, card_type) VALUES ('jam_tracks_5', 'jam_tracks_5');
|
||||
INSERT INTO gift_card_types (id, card_type) VALUES ('jam_tracks_10', 'jam_tracks_10');
|
||||
|
||||
CREATE TABLE gift_card_purchases (
|
||||
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
user_id VARCHAR(64) NOT NULL REFERENCES users(id) ON DELETE SET NULL,
|
||||
gift_card_type_id VARCHAR(64) REFERENCES gift_card_types(id) ON DELETE SET NULL,
|
||||
recurly_adjustment_uuid VARCHAR(500),
|
||||
recurly_adjustment_credit_uuid VARCHAR(500),
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
|
||||
ALTER TABLE sale_line_items ADD COLUMN gift_card_purchase_id VARCHAR(64) REFERENCES gift_card_purchases(id);
|
||||
|
|
@ -0,0 +1 @@
|
|||
ALTER TABLE jam_track_rights ADD COLUMN version VARCHAR NOT NULL DEFAULT '0';
|
||||
|
|
@ -253,6 +253,9 @@ require "jam_ruby/models/musician_search"
|
|||
require "jam_ruby/models/band_search"
|
||||
require "jam_ruby/import/tency_stem_mapping"
|
||||
require "jam_ruby/models/jam_track_search"
|
||||
require "jam_ruby/models/gift_card"
|
||||
require "jam_ruby/models/gift_card_purchase"
|
||||
require "jam_ruby/models/gift_card_type"
|
||||
|
||||
include Jampb
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ module ValidationMessages
|
|||
# sessions
|
||||
SESSION_NOT_FOUND = "Session not found."
|
||||
|
||||
NOT_FOUND = 'not found'
|
||||
|
||||
# genres
|
||||
RECORDING_GENRE_LIMIT_EXCEEDED = "No more than 1 genre is allowed."
|
||||
BAND_GENRE_LIMIT_EXCEEDED = "No more than 3 genres are allowed."
|
||||
|
|
|
|||
|
|
@ -29,10 +29,187 @@ module JamRuby
|
|||
end
|
||||
|
||||
def finish(reason, detail)
|
||||
@@log.info("JamTrackImporter:#{self.name} #{reason}")
|
||||
self.reason = reason
|
||||
self.detail = detail
|
||||
end
|
||||
|
||||
def import_click_track(jam_track)
|
||||
# we need to download the click track, if it exists.
|
||||
Dir.mktmpdir do |tmp_dir|
|
||||
|
||||
@@log.info("importing clicking track for #{jam_track.original_artist}:#{jam_track.name}")
|
||||
|
||||
if jam_track.click_track
|
||||
@@log.info("already has click track: #{jam_track.original_artist}:#{jam_track.name}")
|
||||
finish('success', 'already_has_click_track')
|
||||
return
|
||||
end
|
||||
|
||||
click_track_file = jam_track.click_track_file
|
||||
if click_track_file.nil?
|
||||
@@log.info("no click track for #{jam_track.original_artist}:#{jam_track.name}")
|
||||
finish('success', 'no_click_track')
|
||||
return
|
||||
end
|
||||
|
||||
original_filename = click_track_file[:original_filename]
|
||||
|
||||
if original_filename.nil?
|
||||
@@log.info("no click track s3 path for #{jam_track.original_artist}:#{jam_track.name}")
|
||||
finish('no_original_source', 'click track is missing s3 path:' + click_track_file.id)
|
||||
return
|
||||
end
|
||||
|
||||
#wav_file = File.join(tmp_dir, File.basename(click_track_file[:original_filename]))
|
||||
#JamTrackImporter.song_storage_manager.download(click_track_file[:original_filename], wav_file)
|
||||
|
||||
JamTrack.transaction do
|
||||
click_track = jam_track.click_track
|
||||
|
||||
if click_track.nil?
|
||||
click_track = JamTrackTrack.new
|
||||
click_track.original_filename = click_track_file[:original_filename]
|
||||
click_track.original_audio_s3_path = click_track_file[:original_filename]
|
||||
click_track.track_type = 'Click'
|
||||
click_track.part = 'Clicktrack'
|
||||
click_track.instrument_id = 'computer'
|
||||
click_track.jam_track = jam_track
|
||||
click_track.position = 10000
|
||||
if !click_track.save
|
||||
@@log.error("unable to create jamtrack click track #{click_track.errors.inspect}")
|
||||
finish("jam_track_click", "unable to create: #{click_track.errors.inspect}")
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
jam_track.increment_version!
|
||||
|
||||
# with the click track in hand, flesh out the details
|
||||
synchronize_audio_track(jam_track, tmp_dir, false, click_track)
|
||||
|
||||
finish('success', nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def generate_jmep(jam_track)
|
||||
if !jam_track.blank?
|
||||
finish('success', 'jmep already exists')
|
||||
return
|
||||
else
|
||||
# we need to download the click track, if it exists.
|
||||
Dir.mktmpdir do |tmp_dir|
|
||||
|
||||
master_track = jam_track.master_track
|
||||
|
||||
click_track = jam_track.click_track_file
|
||||
|
||||
if master_track.nil?
|
||||
finish('no_master_track', nil)
|
||||
return
|
||||
end
|
||||
|
||||
master_track_file = File.join(tmp_dir, File.basename(master_track[:url_48]))
|
||||
begin
|
||||
JamTrackImporter.private_s3_manager.download(master_track.url_by_sample_rate(44), master_track_file)
|
||||
rescue Exception => e
|
||||
@@log.error("unable to download master track")
|
||||
finish("no-download-master", master_track.url_by_sample_rate(44))
|
||||
return
|
||||
end
|
||||
|
||||
if click_track
|
||||
click_track_file = File.join(tmp_dir, File.basename(click_track[:original_filename]))
|
||||
JamTrackImporter.song_storage_manager.download(click_track[:original_filename], click_track_file)
|
||||
else
|
||||
# we'll use the master for click analysis. not ideal, but would work
|
||||
click_track_file = master_track_file
|
||||
end
|
||||
|
||||
start_time = determine_start_time(master_track_file, tmp_dir, master_track[:url])
|
||||
|
||||
# bpm comes from git clone http://www.pogo.org.uk/~mark/bpm-tools.git
|
||||
|
||||
sox="sox #{Shellwords.escape(click_track_file)} -t raw -r 44100 -e float -c 1 - | bpm"
|
||||
cmd = "bash -c #{Shellwords.escape(sox)}"
|
||||
@@log.debug("executing cmd #{cmd}")
|
||||
output=`#{cmd}`
|
||||
|
||||
result_code = $?.to_i
|
||||
|
||||
if result_code == 0
|
||||
bpm = output.to_f
|
||||
|
||||
@@log.debug("bpm: #{bpm} start_time: #{start_time}")
|
||||
|
||||
metro_fin = "#{Time.at(start_time).utc.strftime("%H:%M:%S")}:#{((start_time - start_time.to_i) * 1000).round}"
|
||||
|
||||
jmep = ""
|
||||
jmep << "# created via code using bpm/silence detection (bpm:#{bpm})\r\n"
|
||||
jmep << "prelude@10.0 #number of seconds before music starts\r\n"
|
||||
jmep << "metro_fin@#{metro_fin} bpm=#{bpm}, ticks=8, pmode=stream, name=Beep, play=mono"
|
||||
|
||||
@@log.info("jmep generated: #{jmep}")
|
||||
|
||||
jam_track.jmep_text = jmep
|
||||
if jam_track.save
|
||||
finish('success', nil)
|
||||
else
|
||||
@@log.error("jamtrack did not save. #{jam_track.errors.inspect}")
|
||||
finish("no-save", "jamtrack did not save. #{jam_track.errors.inspect}")
|
||||
return
|
||||
end
|
||||
else
|
||||
finish("bpm-fail", "failed to run bpm: #{output}")
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
def determine_start_time(audio_file, tmp_dir, original_filename)
|
||||
burp_gaps = ['0.3', '0.2', '0.1', '0.05']
|
||||
|
||||
out_wav = File.join(tmp_dir, 'stripped.wav')
|
||||
total_time_command = "soxi -D \"#{audio_file}\""
|
||||
total_time = `#{total_time_command}`.to_f
|
||||
|
||||
result_code = -20
|
||||
stripped_time = total_time # default to the case where we just start the preview at the beginning
|
||||
|
||||
burp_gaps.each do |gap|
|
||||
command_strip_lead_silence = "sox \"#{audio_file}\" \"#{out_wav}\" silence 1 #{gap} 1%"
|
||||
|
||||
@@log.debug("stripping silence: " + command_strip_lead_silence)
|
||||
|
||||
output = `#{command_strip_lead_silence}`
|
||||
|
||||
result_code = $?.to_i
|
||||
|
||||
if result_code == 0
|
||||
stripped_time_command = "soxi -D \"#{out_wav}\""
|
||||
stripped_time_test = `#{stripped_time_command}`.to_f
|
||||
|
||||
if stripped_time_test < 1 # meaning a very short duration
|
||||
@@log.warn("could not determine the start of non-silence. assuming beginning")
|
||||
stripped_time = total_time # default to the case where we just start the preview at the beginning
|
||||
else
|
||||
stripped_time = stripped_time_test # accept the measured time of the stripped file and move on by using break
|
||||
break
|
||||
end
|
||||
else
|
||||
@@log.warn("unable to determine silence for jam_track #{original_filename}, #{output}")
|
||||
stripped_time = total_time # default to the case where we just start the preview at the beginning
|
||||
end
|
||||
end
|
||||
|
||||
preview_start_time = total_time - stripped_time
|
||||
|
||||
preview_start_time
|
||||
end
|
||||
|
||||
def synchronize_preview_dev(jam_track)
|
||||
jam_track.jam_track_tracks.each do |track|
|
||||
|
|
@ -231,6 +408,7 @@ module JamRuby
|
|||
original_artist = parsed_metalocation[1]
|
||||
name = parsed_metalocation[2]
|
||||
|
||||
|
||||
JamTrackImporter.summaries[:unique_artists] << original_artist
|
||||
|
||||
success = dry_run_metadata(metadata, original_artist, name)
|
||||
|
|
@ -269,6 +447,11 @@ module JamRuby
|
|||
@storage_format == 'Tency'
|
||||
end
|
||||
|
||||
def is_tim_tracks_storage?
|
||||
assert_storage_set
|
||||
@storage_format == 'TimTracks'
|
||||
end
|
||||
|
||||
def assert_storage_set
|
||||
raise "no storage_format set" if @storage_format.nil?
|
||||
end
|
||||
|
|
@ -276,7 +459,7 @@ module JamRuby
|
|||
|
||||
def parse_metalocation(metalocation)
|
||||
# metalocation = mapped/4 Non Blondes - What's Up - 6475/meta.yml
|
||||
if is_tency_storage?
|
||||
if is_tency_storage? || is_tim_tracks_storage?
|
||||
|
||||
suffix = '/meta.yml'
|
||||
|
||||
|
|
@ -305,15 +488,21 @@ module JamRuby
|
|||
return nil
|
||||
end
|
||||
|
||||
last_dash = metalocation.rindex('-')
|
||||
if last_dash
|
||||
song = metalocation[(first_dash+3)...last_dash].strip
|
||||
if is_tim_tracks_storage?
|
||||
song = metalocation[(first_dash+3)..-1].strip
|
||||
bits << song
|
||||
else
|
||||
finish("invalid_metalocation", "metalocation not valid #{metalocation}")
|
||||
return nil
|
||||
elsif is_tency_storage?
|
||||
last_dash = metalocation.rindex('-')
|
||||
if last_dash
|
||||
song = metalocation[(first_dash+3)...last_dash].strip
|
||||
bits << song
|
||||
else
|
||||
finish("invalid_metalocation", "metalocation not valid #{metalocation}")
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
bits << 'meta.yml'
|
||||
bits
|
||||
else
|
||||
|
|
@ -338,24 +527,14 @@ module JamRuby
|
|||
end
|
||||
end
|
||||
|
||||
# if you change this, it will (at least without some work )break development usage of jamtracks
|
||||
def gen_plan_code(original_artist, name)
|
||||
# remove all non-alphanumeric chars from artist as well as name
|
||||
artist_code = original_artist.gsub(/[^0-9a-z]/i, '').downcase
|
||||
name_code = name.gsub(/[^0-9a-z]/i, '').downcase
|
||||
"jamtrack-#{artist_code[0...20]}-#{name_code}"[0...50] # make sure it's a max of 50 long
|
||||
end
|
||||
|
||||
def dry_run_metadata(metadata, original_artist, name)
|
||||
|
||||
self.name = metadata["name"] || name
|
||||
|
||||
original_artist = metadata["original_artist"] || original_artist
|
||||
plan_code = metadata["plan_code"] || gen_plan_code(original_artist, self.name)
|
||||
description = metadata["description"]
|
||||
|
||||
@@log.debug("#{self.name} original_artist=#{original_artist}")
|
||||
@@log.debug("#{self.name} plan_code=#{plan_code}")
|
||||
|
||||
true
|
||||
end
|
||||
|
|
@ -494,7 +673,6 @@ module JamRuby
|
|||
jam_track.year = metadata[:year]
|
||||
jam_track.genres = determine_genres(metadata)
|
||||
jam_track.language = determine_language(metadata)
|
||||
jam_track.plan_code = metadata["plan_code"] || gen_plan_code(jam_track.original_artist, jam_track.name)
|
||||
jam_track.price = 1.99
|
||||
jam_track.reproduction_royalty_amount = nil
|
||||
jam_track.reproduction_royalty = true
|
||||
|
|
@ -507,16 +685,25 @@ module JamRuby
|
|||
jam_track.alternative_license_status = false
|
||||
jam_track.hfa_license_desired = true
|
||||
jam_track.server_fixation_date = Time.now
|
||||
jam_track.slug = metadata['slug']
|
||||
unless jam_track.slug
|
||||
jam_track.generate_slug
|
||||
end
|
||||
|
||||
if is_tency_storage?
|
||||
jam_track.vendor_id = metadata[:id]
|
||||
jam_track.licensor = JamTrackLicensor.find_by_name('Tency Music')
|
||||
jam_track.licensor = JamTrackLicensor.find_by_name!('Tency Music')
|
||||
#add_licensor_metadata('Tency Music', metalocation)
|
||||
elsif is_tim_tracks_storage?
|
||||
jam_track.vendor_id = metadata[:id]
|
||||
jam_track.licensor = JamTrackLicensor.find_by_name!('Tim Waurick')
|
||||
end
|
||||
jam_track.slug = metadata['slug']
|
||||
if jam_track.slug.nil?
|
||||
jam_track.generate_slug
|
||||
end
|
||||
jam_track.plan_code = metadata["plan_code"]
|
||||
if jam_track.plan_code.nil?
|
||||
jam_track.gen_plan_code
|
||||
end
|
||||
|
||||
|
||||
|
||||
else
|
||||
if !options[:resync_audio]
|
||||
#@@log.debug("#{self.name} skipped because it already exists in database")
|
||||
|
|
@ -664,8 +851,11 @@ module JamRuby
|
|||
instrument = 'other'
|
||||
part = 'Bouzouki'
|
||||
elsif potential_instrument == 'claps' || potential_instrument == 'hand claps'
|
||||
instrument = 'computer'
|
||||
instrument = 'other'
|
||||
part = 'Claps'
|
||||
elsif potential_instrument == 'snaps' || potential_instrument == 'snap'
|
||||
instrument = 'other'
|
||||
part = 'Snaps'
|
||||
else
|
||||
found_instrument = Instrument.find_by_id(potential_instrument)
|
||||
if found_instrument
|
||||
|
|
@ -774,7 +964,6 @@ module JamRuby
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
|
@ -900,6 +1089,10 @@ module JamRuby
|
|||
if track.track_type == 'Master'
|
||||
instrument_weight = 1000
|
||||
end
|
||||
|
||||
if track.track_type == 'Click'
|
||||
instrument_weight = 10000
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
|
@ -976,7 +1169,22 @@ module JamRuby
|
|||
|
||||
end
|
||||
|
||||
sorted_tracks[sorted_tracks.length - 1].position = 1000
|
||||
# get click/master tracks position re-set correctly
|
||||
|
||||
last_track = sorted_tracks[sorted_tracks.length - 1]
|
||||
second_to_last = sorted_tracks[sorted_tracks.length - 2]
|
||||
|
||||
if last_track.track_type == 'Master'
|
||||
last_track.position = 1000
|
||||
elsif last_track.track_type == 'Click'
|
||||
last_track.position = 10000
|
||||
end
|
||||
|
||||
if second_to_last.track_type == 'Master'
|
||||
second_to_last.position = 1000
|
||||
elsif second_to_last.track_type == 'Click'
|
||||
second_to_last.position = 10000
|
||||
end
|
||||
|
||||
sorted_tracks
|
||||
end
|
||||
|
|
@ -1082,7 +1290,6 @@ module JamRuby
|
|||
@@log.debug("#{self.name} track! instrument: #{parsed_wav[:instrument] ? parsed_wav[:instrument] : 'N/A'}, part: #{parsed_wav[:part] ? parsed_wav[:part] : 'N/A'}, filename: #{parsed_wav[:filename]} ")
|
||||
end
|
||||
|
||||
|
||||
track.instrument_id = parsed_wav[:instrument] || 'other'
|
||||
track.track_type = 'Track'
|
||||
track.part = parsed_wav[:part] || "Other #{unknowns}"
|
||||
|
|
@ -1093,6 +1300,13 @@ module JamRuby
|
|||
elsif parsed_wav[:type] == :clickwav
|
||||
file.file_type = 'ClickWav'
|
||||
addt_files << file
|
||||
|
||||
# and also add a JamTrackTrack for this click track
|
||||
track.track_type = 'Click'
|
||||
track.part = 'Clicktrack'
|
||||
track.instrument_id = 'computer'
|
||||
track.position = 10000
|
||||
tracks << track
|
||||
elsif parsed_wav[:type] == :precount
|
||||
file.file_type = 'Precount'
|
||||
file.precount_num = parsed_wav[:precount_num]
|
||||
|
|
@ -1142,97 +1356,8 @@ module JamRuby
|
|||
begin
|
||||
Dir.mktmpdir do |tmp_dir|
|
||||
|
||||
generate_mp3_aac_stem(jam_track, tmp_dir, skip_audio_upload)
|
||||
jam_track.jam_track_tracks.each do |track|
|
||||
|
||||
basename = File.basename(track.original_audio_s3_path)
|
||||
s3_dirname = File.dirname(track.original_audio_s3_path)
|
||||
|
||||
# make a 44100 version, and a 48000 version
|
||||
ogg_44100_filename = File.basename(basename, ".wav") + "-44100.ogg"
|
||||
ogg_48000_filename = File.basename(basename, ".wav") + "-48000.ogg"
|
||||
|
||||
ogg_44100_s3_path = track.filename(ogg_44100_filename)
|
||||
ogg_48000_s3_path = track.filename(ogg_48000_filename)
|
||||
|
||||
track.skip_uploader = true
|
||||
|
||||
if skip_audio_upload
|
||||
track["url_44"] = ogg_44100_s3_path
|
||||
track["md5_44"] = 'md5'
|
||||
track["length_44"] = 1
|
||||
|
||||
track["url_48"] = ogg_48000_s3_path
|
||||
track["md5_48"] = 'md5'
|
||||
track["length_48"] = 1
|
||||
|
||||
# we can't fake the preview as easily because we don't know the MD5 of the current item
|
||||
#track["preview_md5"] = 'md5'
|
||||
#track["preview_mp3_md5"] = 'md5'
|
||||
#track["preview_url"] = track.preview_filename('md5', 'ogg')
|
||||
#track["preview_length"] = 1
|
||||
#track["preview_mp3_url"] = track.preview_filename('md5', 'mp3')
|
||||
#track["preview_mp3_length"] = 1
|
||||
#track["preview_start_time"] = 0
|
||||
else
|
||||
wav_file = File.join(tmp_dir, basename)
|
||||
|
||||
# bring the original wav file down from S3 to local file system
|
||||
JamTrackImporter::song_storage_manager.download(track.original_audio_s3_path, wav_file)
|
||||
|
||||
sample_rate = `soxi -r "#{wav_file}"`.strip
|
||||
|
||||
ogg_44100 = File.join(tmp_dir, ogg_44100_filename)
|
||||
ogg_48000 = File.join(tmp_dir, File.basename(basename, ".wav") + "-48000.ogg")
|
||||
|
||||
if sample_rate == "44100"
|
||||
`oggenc "#{wav_file}" -q 6 -o "#{ogg_44100}"`
|
||||
else
|
||||
`oggenc "#{wav_file}" --resample 44100 -q 6 -o "#{ogg_44100}"`
|
||||
end
|
||||
|
||||
if sample_rate == "48000"
|
||||
`oggenc "#{wav_file}" -q 6 -o "#{ogg_48000}"`
|
||||
else
|
||||
`oggenc "#{wav_file}" --resample 48000 -q 6 -o "#{ogg_48000}"`
|
||||
end
|
||||
|
||||
# upload the new ogg files to s3
|
||||
@@log.debug("uploading 44100 to #{ogg_44100_s3_path}")
|
||||
|
||||
jamkazam_s3_manager.upload(ogg_44100_s3_path, ogg_44100)
|
||||
|
||||
@@log.debug("uploading 48000 to #{ogg_48000_s3_path}")
|
||||
|
||||
jamkazam_s3_manager.upload(ogg_48000_s3_path, ogg_48000)
|
||||
|
||||
ogg_44100_digest = ::Digest::MD5.file(ogg_44100)
|
||||
# and finally update the JamTrackTrack with the new info
|
||||
track["url_44"] = ogg_44100_s3_path
|
||||
track["md5_44"] = ogg_44100_digest.hexdigest
|
||||
track["length_44"] = File.new(ogg_44100).size
|
||||
|
||||
track["url_48"] = ogg_48000_s3_path
|
||||
track["md5_48"] = ::Digest::MD5.file(ogg_48000).hexdigest
|
||||
track["length_48"] = File.new(ogg_48000).size
|
||||
|
||||
synchronize_duration(jam_track, ogg_44100)
|
||||
jam_track.save!
|
||||
|
||||
# convert entire master ogg file to mp3, and push both to public destination
|
||||
if track.track_type == 'Master'
|
||||
preview_succeeded = synchronize_master_preview(track, tmp_dir, ogg_44100, ogg_44100_digest)
|
||||
|
||||
if !preview_succeeded
|
||||
return false
|
||||
end
|
||||
elsif track.track_type == 'Track'
|
||||
synchronize_track_preview(track, tmp_dir, ogg_44100)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
track.save!
|
||||
synchronize_audio_track(jam_track, tmp_dir, skip_audio_upload, track)
|
||||
end
|
||||
end
|
||||
rescue Exception => e
|
||||
|
|
@ -1243,6 +1368,139 @@ module JamRuby
|
|||
return true
|
||||
end
|
||||
|
||||
def synchronize_audio_track(jam_track, tmp_dir, skip_audio_upload, track)
|
||||
basename = File.basename(track.original_audio_s3_path)
|
||||
|
||||
# make a 44100 version, and a 48000 version
|
||||
ogg_44100_filename = File.basename(basename, ".wav") + "-44100.ogg"
|
||||
ogg_48000_filename = File.basename(basename, ".wav") + "-48000.ogg"
|
||||
|
||||
|
||||
# make a 44100 version, and a 48000 version
|
||||
mp3_48000_filename = File.basename(basename, ".wav") + "-48000.mp3"
|
||||
aac_48000_filename = File.basename(basename, ".wav") + "-48000.aac"
|
||||
|
||||
ogg_44100_s3_path = track.filename(ogg_44100_filename)
|
||||
ogg_48000_s3_path = track.filename(ogg_48000_filename)
|
||||
|
||||
mp3_48000_s3_path = track.filename(mp3_48000_filename)
|
||||
aac_48000_s3_path = track.filename(aac_48000_filename)
|
||||
|
||||
track.skip_uploader = true
|
||||
|
||||
if skip_audio_upload
|
||||
track["url_44"] = ogg_44100_s3_path
|
||||
track["md5_44"] = 'md5'
|
||||
track["length_44"] = 1
|
||||
|
||||
track["url_48"] = ogg_48000_s3_path
|
||||
track["md5_48"] = 'md5'
|
||||
track["length_48"] = 1
|
||||
|
||||
track["url_mp3_48"] = mp3_48000_filename
|
||||
track["md5_mp3_48"] = 'md5'
|
||||
track["length_mp3_48"] = 1
|
||||
|
||||
track["url_aac_48"] = aac_48000_filename
|
||||
track["md5_aac_48"] = 'md5'
|
||||
track["length_aac_48"] = 1
|
||||
|
||||
# we can't fake the preview as easily because we don't know the MD5 of the current item
|
||||
#track["preview_md5"] = 'md5'
|
||||
#track["preview_mp3_md5"] = 'md5'
|
||||
#track["preview_url"] = track.preview_filename('md5', 'ogg')
|
||||
#track["preview_length"] = 1
|
||||
#track["preview_mp3_url"] = track.preview_filename('md5', 'mp3')
|
||||
#track["preview_mp3_length"] = 1
|
||||
#track["preview_start_time"] = 0
|
||||
else
|
||||
wav_file = File.join(tmp_dir, basename)
|
||||
|
||||
# bring the original wav file down from S3 to local file system
|
||||
JamTrackImporter::song_storage_manager.download(track.original_audio_s3_path, wav_file)
|
||||
|
||||
sample_rate = `soxi -r "#{wav_file}"`.strip
|
||||
|
||||
ogg_44100 = File.join(tmp_dir, ogg_44100_filename)
|
||||
ogg_48000 = File.join(tmp_dir, File.basename(basename, ".wav") + "-48000.ogg")
|
||||
|
||||
if sample_rate == "44100"
|
||||
`oggenc "#{wav_file}" -q 6 -o "#{ogg_44100}"`
|
||||
else
|
||||
`oggenc "#{wav_file}" --resample 44100 -q 6 -o "#{ogg_44100}"`
|
||||
end
|
||||
|
||||
if sample_rate == "48000"
|
||||
`oggenc "#{wav_file}" -q 6 -o "#{ogg_48000}"`
|
||||
else
|
||||
`oggenc "#{wav_file}" --resample 48000 -q 6 -o "#{ogg_48000}"`
|
||||
end
|
||||
|
||||
# upload the new ogg files to s3
|
||||
@@log.debug("uploading 44100 to #{ogg_44100_s3_path}")
|
||||
|
||||
jamkazam_s3_manager.upload(ogg_44100_s3_path, ogg_44100)
|
||||
|
||||
@@log.debug("uploading 48000 to #{ogg_48000_s3_path}")
|
||||
|
||||
jamkazam_s3_manager.upload(ogg_48000_s3_path, ogg_48000)
|
||||
|
||||
ogg_44100_digest = ::Digest::MD5.file(ogg_44100)
|
||||
# and finally update the JamTrackTrack with the new info
|
||||
track["url_44"] = ogg_44100_s3_path
|
||||
track["md5_44"] = ogg_44100_digest.hexdigest
|
||||
track["length_44"] = File.new(ogg_44100).size
|
||||
|
||||
track["url_48"] = ogg_48000_s3_path
|
||||
track["md5_48"] = ::Digest::MD5.file(ogg_48000).hexdigest
|
||||
track["length_48"] = File.new(ogg_48000).size
|
||||
|
||||
# now create mp3 and aac files
|
||||
mp3_48000 = File.join(tmp_dir, File.basename(basename, ".wav") + "-48000.mp3")
|
||||
aac_48000 = File.join(tmp_dir, File.basename(basename, ".wav") + "-48000.aac")
|
||||
|
||||
`ffmpeg -i "#{wav_file}" -ar 48000 -ab 192k "#{mp3_48000}"`
|
||||
|
||||
`ffmpeg -i "#{wav_file}" -c:a libfdk_aac -b:a 192k "#{aac_48000}"`
|
||||
|
||||
# upload the new ogg files to s3
|
||||
@@log.debug("uploading mp3 48000 to #{mp3_48000_s3_path}")
|
||||
|
||||
jamkazam_s3_manager.upload(mp3_48000_s3_path, mp3_48000)
|
||||
|
||||
@@log.debug("uploading aac 48000 to #{aac_48000_s3_path}")
|
||||
|
||||
jamkazam_s3_manager.upload(aac_48000_s3_path, aac_48000)
|
||||
|
||||
mp3_48000_digest = ::Digest::MD5.file(mp3_48000)
|
||||
# and finally update the JamTrackTrack with the new info
|
||||
track["url_mp3_48"] = mp3_48000_s3_path
|
||||
track["md5_mp3_48"] = mp3_48000_digest.hexdigest
|
||||
track["length_mp3_48"] = File.new(mp3_48000).size
|
||||
|
||||
track["url_aac_48"] = aac_48000_s3_path
|
||||
track["md5_aac_48"] = ::Digest::MD5.file(aac_48000).hexdigest
|
||||
track["length_aac_48"] = File.new(aac_48000).size
|
||||
|
||||
synchronize_duration(jam_track, ogg_44100)
|
||||
jam_track.save!
|
||||
|
||||
# convert entire master ogg file to mp3, and push both to public destination
|
||||
if track.track_type == 'Master'
|
||||
preview_succeeded = synchronize_master_preview(track, tmp_dir, ogg_44100, ogg_44100_digest)
|
||||
|
||||
if !preview_succeeded
|
||||
return false
|
||||
end
|
||||
elsif track.track_type == 'Track' || track.track_type == 'Click'
|
||||
synchronize_track_preview(track, tmp_dir, ogg_44100)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
track.save!
|
||||
end
|
||||
|
||||
def generate_mp3_aac_stem(jam_track, tmp_dir, skip_audio_upload)
|
||||
jam_track.jam_track_tracks.each do |track|
|
||||
|
||||
|
|
@ -1252,6 +1510,7 @@ module JamRuby
|
|||
next
|
||||
end
|
||||
|
||||
puts "track.original_audio_s3_path #{track.original_audio_s3_path}"
|
||||
basename = File.basename(track.original_audio_s3_path)
|
||||
s3_dirname = File.dirname(track.original_audio_s3_path)
|
||||
|
||||
|
|
@ -1262,6 +1521,7 @@ module JamRuby
|
|||
mp3_48000_s3_path = track.filename(mp3_48000_filename)
|
||||
aac_48000_s3_path = track.filename(aac_48000_filename)
|
||||
|
||||
puts "mp3_48000_s3_path #{mp3_48000_s3_path}"
|
||||
track.skip_uploader = true
|
||||
|
||||
if skip_audio_upload
|
||||
|
|
@ -1341,58 +1601,15 @@ module JamRuby
|
|||
|
||||
def synchronize_track_preview(track, tmp_dir, ogg_44100)
|
||||
|
||||
out_wav = File.join(tmp_dir, 'stripped.wav')
|
||||
|
||||
burp_gaps = ['0.3', '0.2', '0.1', '0.05']
|
||||
|
||||
total_time_command = "soxi -D \"#{ogg_44100}\""
|
||||
total_time = `#{total_time_command}`.to_f
|
||||
|
||||
result_code = -20
|
||||
stripped_time = total_time # default to the case where we just start the preview at the beginning
|
||||
|
||||
burp_gaps.each do |gap|
|
||||
command_strip_lead_silence = "sox \"#{ogg_44100}\" \"#{out_wav}\" silence 1 #{gap} 1%"
|
||||
|
||||
@@log.debug("stripping silence: " + command_strip_lead_silence)
|
||||
|
||||
output = `#{command_strip_lead_silence}`
|
||||
|
||||
result_code = $?.to_i
|
||||
|
||||
if result_code == 0
|
||||
stripped_time_command = "soxi -D \"#{out_wav}\""
|
||||
stripped_time_test = `#{stripped_time_command}`.to_f
|
||||
|
||||
if stripped_time_test < 1 # meaning a very short duration
|
||||
@@log.warn("could not determine the start of non-silencea. assuming beginning")
|
||||
stripped_time = total_time # default to the case where we just start the preview at the beginning
|
||||
else
|
||||
stripped_time = stripped_time_test # accept the measured time of the stripped file and move on by using break
|
||||
break
|
||||
end
|
||||
else
|
||||
@@log.warn("unable to determine silence for jam_track #{track.original_filename}, #{output}")
|
||||
stripped_time = total_time # default to the case where we just start the preview at the beginning
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
preview_start_time = total_time - stripped_time
|
||||
preview_start_time = determine_start_time(ogg_44100, tmp_dir, track.original_filename)
|
||||
|
||||
# this is in seconds; convert to integer milliseconds
|
||||
preview_start_time = (preview_start_time * 1000).to_i
|
||||
|
||||
preview_start_time = nil if preview_start_time < 0
|
||||
preview_start_time = 0 if preview_start_time < 0
|
||||
|
||||
track.preview_start_time = preview_start_time
|
||||
|
||||
if track.preview_start_time
|
||||
@@log.debug("determined track start time to be #{track.preview_start_time}")
|
||||
else
|
||||
@@log.debug("determined track start time to be #{track.preview_start_time}")
|
||||
end
|
||||
|
||||
track.process_preview(ogg_44100, tmp_dir) if track.preview_start_time
|
||||
|
||||
if track.preview_generate_error
|
||||
|
|
@ -1606,6 +1823,8 @@ module JamRuby
|
|||
def song_storage_manager
|
||||
if is_tency_storage?
|
||||
tency_s3_manager
|
||||
elsif is_tim_tracks_storage?
|
||||
tim_tracks_s3_manager
|
||||
else
|
||||
s3_manager
|
||||
end
|
||||
|
|
@ -1619,6 +1838,10 @@ module JamRuby
|
|||
@tency_s3_manager ||= S3Manager.new('jamkazam-tency', APP_CONFIG.aws_access_key_id, APP_CONFIG.aws_secret_access_key)
|
||||
end
|
||||
|
||||
def tim_tracks_s3_manager
|
||||
@tim_tracks_s3_manager ||= S3Manager.new('jamkazam-timtracks', APP_CONFIG.aws_access_key_id, APP_CONFIG.aws_secret_access_key)
|
||||
end
|
||||
|
||||
def s3_manager
|
||||
@s3_manager ||= S3Manager.new(APP_CONFIG.aws_bucket_jamtracks, APP_CONFIG.aws_access_key_id, APP_CONFIG.aws_secret_access_key)
|
||||
end
|
||||
|
|
@ -1657,10 +1880,32 @@ module JamRuby
|
|||
@storage_format == 'Tency'
|
||||
end
|
||||
|
||||
def is_tim_tracks_storage?
|
||||
assert_storage_set
|
||||
@storage_format == 'TimTracks'
|
||||
end
|
||||
|
||||
def assert_storage_set
|
||||
raise "no storage_format set" if @storage_format.nil?
|
||||
end
|
||||
|
||||
def iterate_tim_tracks_song_storage(&blk)
|
||||
count = 0
|
||||
song_storage_manager.list_directories('mapped').each do |song|
|
||||
@@log.debug("searching through song directory '#{song}'")
|
||||
|
||||
metalocation = "#{song}meta.yml"
|
||||
|
||||
metadata = load_metalocation(metalocation)
|
||||
|
||||
blk.call(metadata, metalocation)
|
||||
|
||||
count += 1
|
||||
#break if count > 100
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
def iterate_tency_song_storage(&blk)
|
||||
count = 0
|
||||
song_storage_manager.list_directories('mapped').each do |song|
|
||||
|
|
@ -1700,6 +1945,10 @@ module JamRuby
|
|||
iterate_tency_song_storage do |metadata, metalocation|
|
||||
blk.call(metadata, metalocation)
|
||||
end
|
||||
elsif is_tim_tracks_storage?
|
||||
iterate_tim_tracks_song_storage do |metadata, metalocation|
|
||||
blk.call(metadata, metalocation)
|
||||
end
|
||||
else
|
||||
iterate_default_song_storage do |metadata, metalocation|
|
||||
blk.call(metadata, metalocation)
|
||||
|
|
@ -1915,6 +2164,73 @@ module JamRuby
|
|||
end
|
||||
end
|
||||
|
||||
def import_click_track(jam_track)
|
||||
importer = JamTrackImporter.new
|
||||
importer.name = jam_track.name
|
||||
importer.import_click_track(jam_track)
|
||||
|
||||
importer
|
||||
end
|
||||
def generate_jmep(jam_track)
|
||||
importer = JamTrackImporter.new
|
||||
importer.name = jam_track.name
|
||||
importer.generate_jmep(jam_track)
|
||||
|
||||
importer
|
||||
end
|
||||
|
||||
def import_click_tracks
|
||||
importers = []
|
||||
|
||||
JamTrack.all.each do |jam_track|
|
||||
#jam_track = JamTrack.find('126')
|
||||
importers << import_click_track(jam_track)
|
||||
end
|
||||
|
||||
@@log.info("SUMMARY")
|
||||
@@log.info("-------")
|
||||
importers.each do |importer|
|
||||
if importer
|
||||
if importer.reason == "success"
|
||||
@@log.info("#{importer.name} #{importer.reason}")
|
||||
else
|
||||
@@log.error("#{importer.name} failed to generate jmep.")
|
||||
@@log.error("#{importer.name} reason=#{importer.reason}")
|
||||
@@log.error("#{importer.name} detail=#{importer.detail}")
|
||||
end
|
||||
else
|
||||
@@log.error("NULL IMPORTER")
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
def generate_jmeps
|
||||
importers = []
|
||||
|
||||
JamTrack.all.each do |jam_track|
|
||||
importers << generate_jmep(jam_track)
|
||||
end
|
||||
|
||||
@@log.info("SUMMARY")
|
||||
@@log.info("-------")
|
||||
importers.each do |importer|
|
||||
if importer
|
||||
if importer.reason == "success"
|
||||
@@log.info("#{importer.name} #{importer.reason}")
|
||||
else
|
||||
@@log.error("#{importer.name} failed to generate jmep.")
|
||||
@@log.error("#{importer.name} reason=#{importer.reason}")
|
||||
@@log.error("#{importer.name} detail=#{importer.detail}")
|
||||
end
|
||||
else
|
||||
@@log.error("NULL IMPORTER")
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def synchronize_previews
|
||||
importers = []
|
||||
|
||||
|
|
@ -2328,7 +2644,12 @@ module JamRuby
|
|||
else
|
||||
begin
|
||||
data = s3_manager.read_all(metalocation)
|
||||
return YAML.load(data)
|
||||
meta = YAML.load(data)
|
||||
|
||||
if is_tim_tracks_storage?
|
||||
meta[:genres] = ['acapella']
|
||||
end
|
||||
meta
|
||||
rescue AWS::S3::Errors::NoSuchKey
|
||||
return nil
|
||||
end
|
||||
|
|
@ -2395,3 +2716,4 @@ module JamRuby
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ module JamRuby
|
|||
jam_file_opts=""
|
||||
jam_track.jam_track_tracks.each do |jam_track_track|
|
||||
|
||||
next if jam_track_track.track_type != "Track" # master mixes do not go into the JKZ
|
||||
next if jam_track_track.track_type == "Master" # master mixes do not go into the JKZ
|
||||
|
||||
# use the jam_track_track ID as the filename.ogg/.wav, because it's important metadata
|
||||
nm = jam_track_track.id + File.extname(jam_track_track.url_by_sample_rate(sample_rate))
|
||||
|
|
@ -52,7 +52,8 @@ module JamRuby
|
|||
step = bump_step(jam_track_right, step)
|
||||
|
||||
copy_url_to_file(track_url, track_filename)
|
||||
jam_file_opts << " -i #{Shellwords.escape("#{track_filename}+#{jam_track_track.part}")}"
|
||||
part = jam_track_track.track_type == 'Click' ? 'ClickTrack' : jam_track_track.part
|
||||
jam_file_opts << " -i #{Shellwords.escape("#{track_filename}+#{part}")}"
|
||||
end
|
||||
#puts "LS + " + `ls -la '#{tmp_dir}'`
|
||||
|
||||
|
|
|
|||
|
|
@ -119,18 +119,16 @@ class JamRuby::AffiliatePartner < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def should_attribute_sale?(shopping_cart)
|
||||
if shopping_cart.is_jam_track?
|
||||
if created_within_affiliate_window(shopping_cart.user, Time.now)
|
||||
product_info = shopping_cart.product_info
|
||||
# subtract the total quantity from the freebie quantity, to see how much we should attribute to them
|
||||
real_quantity = product_info[:quantity].to_i - product_info[:marked_for_redeem].to_i
|
||||
{fee_in_cents: (1.99 * 100 * real_quantity * rate.to_f).round}
|
||||
else
|
||||
false
|
||||
end
|
||||
|
||||
if created_within_affiliate_window(shopping_cart.user, Time.now)
|
||||
product_info = shopping_cart.product_info
|
||||
# subtract the total quantity from the freebie quantity, to see how much we should attribute to them
|
||||
real_quantity = product_info[:quantity].to_i - product_info[:marked_for_redeem].to_i
|
||||
{fee_in_cents: (product_info[:price] * 100 * real_quantity * rate.to_f).round}
|
||||
else
|
||||
raise 'shopping cart type not implemented yet'
|
||||
false
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def cumulative_earnings_in_dollars
|
||||
|
|
|
|||
|
|
@ -15,20 +15,47 @@ module JamRuby
|
|||
ShoppingCart.where(anonymous_user_id: @id).order('created_at DESC')
|
||||
end
|
||||
|
||||
|
||||
def destroy_all_shopping_carts
|
||||
ShoppingCart.destroy_all(anonymous_user_id: @id)
|
||||
end
|
||||
|
||||
def destroy_jam_track_shopping_carts
|
||||
ShoppingCart.destroy_all(anonymous_user_id: @id, cart_type: JamTrack::PRODUCT_TYPE)
|
||||
end
|
||||
|
||||
def admin
|
||||
false
|
||||
end
|
||||
|
||||
def has_redeemable_jamtrack
|
||||
raise "not a cookied anonymous user" if @cookies.nil?
|
||||
|
||||
APP_CONFIG.one_free_jamtrack_per_user && !@cookies[:redeemed_jamtrack]
|
||||
end
|
||||
|
||||
def gifted_jamtracks
|
||||
0
|
||||
end
|
||||
|
||||
def free_jamtracks
|
||||
if has_redeemable_jamtrack
|
||||
1
|
||||
else
|
||||
0
|
||||
end
|
||||
end
|
||||
|
||||
def show_free_jamtrack?
|
||||
ShoppingCart.user_has_redeemable_jam_track?(self)
|
||||
end
|
||||
|
||||
def signup_hint
|
||||
SignupHint.where(anonymous_user_id: @id).where('expires_at > ?', Time.now).first
|
||||
end
|
||||
|
||||
def reload
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -97,6 +97,7 @@ module JamRuby
|
|||
body = "IP Address: #{remote_ip}\n"
|
||||
body << "Download Count: #{violation['count']}\n"
|
||||
body << "Add to blacklist: #{IpBlacklist.admin_url}"
|
||||
body << "Check Activity: #{IpBlacklist.admin_activity_url(remote_ip)}"
|
||||
|
||||
AdminMailer.alerts({
|
||||
subject:"Single IP Access Violation. IP:#{remote_ip}",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
# represents the gift card you hold in your hand
|
||||
module JamRuby
|
||||
class GiftCard < ActiveRecord::Base
|
||||
|
||||
@@log = Logging.logger[GiftCard]
|
||||
|
||||
JAM_TRACKS_5 = 'jam_tracks_5'
|
||||
JAM_TRACKS_10 = 'jam_tracks_10'
|
||||
CARD_TYPES =
|
||||
[
|
||||
JAM_TRACKS_5,
|
||||
JAM_TRACKS_10
|
||||
]
|
||||
|
||||
|
||||
belongs_to :user, class_name: "JamRuby::User"
|
||||
|
||||
validates :card_type, presence: true, inclusion: {in: CARD_TYPES}
|
||||
validates :code, presence: true, uniqueness: true
|
||||
|
||||
after_save :check_gifted
|
||||
|
||||
def check_gifted
|
||||
if user && user_id_changed?
|
||||
if card_type == JAM_TRACKS_5
|
||||
user.gifted_jamtracks += 5
|
||||
elsif card_type == JAM_TRACKS_10
|
||||
user.gifted_jamtracks += 10
|
||||
else
|
||||
raise "unknown card type #{card_type}"
|
||||
end
|
||||
user.save!
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
# reperesents the gift card you buy from the site (but physical gift card is modeled by GiftCard)
|
||||
module JamRuby
|
||||
class GiftCardPurchase < ActiveRecord::Base
|
||||
|
||||
@@log = Logging.logger[GiftCardPurchase]
|
||||
|
||||
attr_accessible :user, :gift_card_type
|
||||
|
||||
def name
|
||||
gift_card_type.sale_display
|
||||
end
|
||||
|
||||
# who purchased the card?
|
||||
belongs_to :user, class_name: "JamRuby::User"
|
||||
belongs_to :gift_card_type, class_name: "JamRuby::GiftCardType"
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
# reperesents the gift card you buy from the site (but physical gift card is modeled by GiftCard)
|
||||
module JamRuby
|
||||
class GiftCardType < ActiveRecord::Base
|
||||
|
||||
@@log = Logging.logger[GiftCardType]
|
||||
|
||||
PRODUCT_TYPE = 'GiftCardType'
|
||||
|
||||
JAM_TRACKS_5 = 'jam_tracks_5'
|
||||
JAM_TRACKS_10 = 'jam_tracks_10'
|
||||
CARD_TYPES =
|
||||
[
|
||||
JAM_TRACKS_5,
|
||||
JAM_TRACKS_10
|
||||
]
|
||||
|
||||
validates :card_type, presence: true, inclusion: {in: CARD_TYPES}
|
||||
|
||||
def self.jam_track_5
|
||||
GiftCardType.find(JAM_TRACKS_5)
|
||||
end
|
||||
|
||||
def self.jam_track_10
|
||||
GiftCardType.find(JAM_TRACKS_10)
|
||||
end
|
||||
|
||||
def name
|
||||
sale_display
|
||||
end
|
||||
|
||||
def price
|
||||
if card_type == JAM_TRACKS_5
|
||||
10.00
|
||||
elsif card_type == JAM_TRACKS_10
|
||||
20.00
|
||||
else
|
||||
raise "unknown card type #{card_type}"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def sale_display
|
||||
if card_type == JAM_TRACKS_5
|
||||
'JamTracks Gift Card (5)'
|
||||
elsif card_type == JAM_TRACKS_10
|
||||
'JamTracks Gift Card (10)'
|
||||
else
|
||||
raise "unknown card type #{card_type}"
|
||||
end
|
||||
end
|
||||
|
||||
def plan_code
|
||||
if card_type == JAM_TRACKS_5
|
||||
"jamtrack-giftcard-5"
|
||||
elsif card_type == JAM_TRACKS_10
|
||||
"jamtrack-giftcard-10"
|
||||
else
|
||||
raise "unknown card type #{card_type}"
|
||||
end
|
||||
end
|
||||
|
||||
def sales_region
|
||||
'Worldwide'
|
||||
end
|
||||
|
||||
def to_s
|
||||
sale_display
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -15,6 +15,10 @@ module JamRuby
|
|||
APP_CONFIG.admin_root_url + "/admin/ip_blacklists/"
|
||||
end
|
||||
|
||||
def self.admin_activity_url(remote_ip)
|
||||
APP_CONFIG.admin_root_url + "/admin/download_trackers?q[remote_ip_equals]=#{URI.escape(remote_ip)}&commit=Filter&order=id_desc"
|
||||
end
|
||||
|
||||
def admin_url
|
||||
APP_CONFIG.admin_root_url + "/admin/ip_blacklists/" + id
|
||||
end
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ module JamRuby
|
|||
: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, :genre_ids, :version, :jmep_json, :jmep_text, :pro_ascap, :pro_bmi, :pro_sesac, :duration,
|
||||
:server_fixation_date, :hfa_license_status, :hfa_license_desired, :alternative_license_status, :hfa_license_number, :hfa_song_code, :album_title, as: :admin
|
||||
:server_fixation_date, :hfa_license_status, :hfa_license_desired, :alternative_license_status, :hfa_license_number, :hfa_song_code, :album_title, :year, as: :admin
|
||||
|
||||
validates :name, presence: true, length: {maximum: 200}
|
||||
validates :plan_code, presence: true, uniqueness: true, length: {maximum: 50 }
|
||||
|
|
@ -86,6 +86,10 @@ module JamRuby
|
|||
after_save :sync_reproduction_royalty
|
||||
after_save :sync_onboarding_exceptions
|
||||
|
||||
def increment_version!
|
||||
self.version = version.to_i + 1
|
||||
save!
|
||||
end
|
||||
|
||||
def sync_reproduction_royalty
|
||||
|
||||
|
|
@ -155,6 +159,9 @@ module JamRuby
|
|||
true
|
||||
end
|
||||
|
||||
def sale_display
|
||||
"JamTrack: " + name
|
||||
end
|
||||
def duplicate_positions?
|
||||
counter = {}
|
||||
jam_track_tracks.each do |track|
|
||||
|
|
@ -338,7 +345,7 @@ module JamRuby
|
|||
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_track_tracks.instrument_id = '#{options[:instrument]}' and jam_track_tracks.track_type = 'Track'") unless options[:instrument].blank?
|
||||
query = query.where("jam_tracks.sales_region = '#{options[:availability]}'") unless options[:availability].blank?
|
||||
|
||||
# FIXME: n+1 queries for rights and genres
|
||||
|
|
@ -347,9 +354,8 @@ module JamRuby
|
|||
# :jam_track_rights,
|
||||
# :genres])
|
||||
# { genres_jam_tracks: :genre },
|
||||
query = query.includes([{ jam_track_tracks: :instrument },
|
||||
{ genres_jam_tracks: :genre },
|
||||
:jam_track_tap_ins])
|
||||
# query = query.includes([{ jam_track_tracks: :instrument },
|
||||
# { genres_jam_tracks: :genre }])
|
||||
|
||||
count = query.total_entries
|
||||
|
||||
|
|
@ -432,13 +438,20 @@ module JamRuby
|
|||
end
|
||||
end
|
||||
|
||||
def click_track_file
|
||||
JamTrackFile.where(jam_track_id: self.id).where(file_type: 'ClickWav').first
|
||||
end
|
||||
|
||||
def click_track
|
||||
JamTrackTrack.where(jam_track_id: self.id).where(track_type: 'Click').first
|
||||
end
|
||||
|
||||
def master_track
|
||||
JamTrackTrack.where(jam_track_id: self.id).where(track_type: 'Master').first
|
||||
end
|
||||
|
||||
def stem_tracks
|
||||
JamTrackTrack.where(jam_track_id: self.id).where(track_type: 'Track')
|
||||
JamTrackTrack.where(jam_track_id: self.id).where("track_type = 'Track' or track_type = 'Click'")
|
||||
end
|
||||
|
||||
def can_download?(user)
|
||||
|
|
@ -465,6 +478,27 @@ module JamRuby
|
|||
|
||||
def generate_slug
|
||||
self.slug = sluggarize(original_artist) + '-' + sluggarize(name)
|
||||
|
||||
if licensor
|
||||
raise "no slug on licensor #{licensor.id}" if licensor.slug.nil?
|
||||
self.slug << "-" + licensor.slug
|
||||
end
|
||||
end
|
||||
|
||||
def gen_plan_code
|
||||
# remove all non-alphanumeric chars from artist as well as name
|
||||
artist_code = original_artist.gsub(/[^0-9a-z]/i, '').downcase
|
||||
name_code = name.gsub(/[^0-9a-z]/i, '').downcase
|
||||
self.plan_code = "jamtrack-#{artist_code[0...20]}-#{name_code}"
|
||||
|
||||
if licensor
|
||||
raise "no slug on licensor #{licensor.id}" if licensor.slug.nil?
|
||||
self.plan_code << "-" + licensor.slug
|
||||
end
|
||||
|
||||
self.plan_code = self.plan_code[0...50] # make sure it's a max of 50 long
|
||||
|
||||
|
||||
end
|
||||
|
||||
def to_s
|
||||
|
|
@ -492,5 +526,30 @@ module JamRuby
|
|||
|
||||
Digest::MD5.hexdigest(dates)
|
||||
end
|
||||
|
||||
attr_accessor :preview_generate_error
|
||||
|
||||
before_save :jmep_json_generate
|
||||
validate :jmep_text_validate
|
||||
|
||||
def jmep_text_validate
|
||||
begin
|
||||
JmepManager.execute(self.jmep_text)
|
||||
rescue ArgumentError => err
|
||||
errors.add(:jmep_text, err.to_s)
|
||||
end
|
||||
end
|
||||
|
||||
def jmep_json_generate
|
||||
self.licensor_id = nil if self.licensor_id == ''
|
||||
self.jmep_json = nil if self.jmep_json == ''
|
||||
self.time_signature = nil if self.time_signature == ''
|
||||
|
||||
begin
|
||||
self[:jmep_json] = JmepManager.execute(self.jmep_text)
|
||||
rescue ArgumentError => err
|
||||
#errors.add(:jmep_text, err.to_s)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -27,9 +27,18 @@ module JamRuby
|
|||
"jam_track_files"
|
||||
end
|
||||
|
||||
def licensor_suffix
|
||||
suffix = ''
|
||||
if jam_track.licensor
|
||||
raise "no licensor name" if jam_track.licensor.name.nil?
|
||||
suffix = " - #{jam_track.licensor.name}"
|
||||
end
|
||||
suffix
|
||||
end
|
||||
|
||||
# create name of the file
|
||||
def filename(original_name)
|
||||
"#{store_dir}/#{jam_track.original_artist}/#{jam_track.name}/#{original_name}"
|
||||
"#{store_dir}/#{jam_track.original_artist}/#{jam_track.name}#{licensor_suffix}/#{original_name}"
|
||||
end
|
||||
|
||||
def manually_uploaded_filename
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ module JamRuby
|
|||
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
|
||||
:city, :state, :zip_code, :contact, :email, :phone, :slug, as: :admin
|
||||
|
||||
validates :name, presence: true, uniqueness: true, length: {maximum: 200}
|
||||
validates :description, length: {maximum: 1000}
|
||||
|
|
|
|||
|
|
@ -83,6 +83,11 @@ module JamRuby
|
|||
end
|
||||
end
|
||||
|
||||
if parsed["count-in"]
|
||||
all_quiet = false
|
||||
tweaked = true
|
||||
end
|
||||
|
||||
if all_quiet
|
||||
errors.add(:settings, 'are all muted')
|
||||
end
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ module JamRuby
|
|||
belongs_to :last_mixdown, class_name: 'JamRuby::JamTrackMixdown', foreign_key: 'last_mixdown_id', inverse_of: :jam_track_right
|
||||
belongs_to :last_stem, class_name: 'JamRuby::JamTrackTrack', foreign_key: 'last_stem_id', inverse_of: :jam_track_right
|
||||
|
||||
validates :version, presence: true
|
||||
validates :user, presence: true
|
||||
validates :jam_track, presence: true
|
||||
validates :is_test_purchase, inclusion: {in: [true, false]}
|
||||
|
|
@ -133,8 +134,33 @@ module JamRuby
|
|||
end
|
||||
end
|
||||
|
||||
def cleanup_old_package!
|
||||
if self.jam_track.version != self.version
|
||||
delete_s3_files
|
||||
self[:url_48] = nil
|
||||
self[:url_44] = nil
|
||||
self.signing_queued_at = nil
|
||||
self.signing_started_at_48 = nil
|
||||
self.signing_started_at_44 = nil
|
||||
self.last_signed_at = nil
|
||||
self.current_packaging_step = nil
|
||||
self.packaging_steps = nil
|
||||
self.should_retry = false
|
||||
self.signing_44 = false
|
||||
self.signing_48 = false
|
||||
self.signed_44 = false
|
||||
self.signed_48 = false
|
||||
self.queued = false
|
||||
self.version = self.jam_track.version
|
||||
self.save!
|
||||
end
|
||||
end
|
||||
# if the job is already signed, just queued up for signing, or currently signing, then don't enqueue... otherwise fire it off
|
||||
def enqueue_if_needed(sample_rate=48)
|
||||
|
||||
# delete any package that's out dated
|
||||
cleanup_old_package!
|
||||
|
||||
state = signing_state(sample_rate)
|
||||
if state == 'SIGNED' || state == 'SIGNING' || state == 'QUEUED'
|
||||
false
|
||||
|
|
@ -148,9 +174,9 @@ module JamRuby
|
|||
# @return true if signed && file exists for the sample_rate specifed:
|
||||
def ready?(sample_rate=48)
|
||||
if sample_rate==48
|
||||
self.signed_48 && self.url_48.present? && self.url_48.file.exists?
|
||||
self.signed_48 && self.url_48.present? && self.url_48.file.exists? && self.version == self.jam_track.version
|
||||
else
|
||||
self.signed_44 && self.url_44.present? && self.url_44.file.exists?
|
||||
self.signed_44 && self.url_44.present? && self.url_44.file.exists? && self.version == self.jam_track.version
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ module JamRuby
|
|||
sqlstr = "'#{instruments.join("','")}'"
|
||||
rel = rel.joins(:jam_track_tracks)
|
||||
rel = rel.where("jam_track_tracks.instrument_id IN (#{sqlstr})")
|
||||
rel = rel.where("jam_track_tracks.track_type != 'Master'")
|
||||
rel = rel.where("jam_track_tracks.track_type = 'Track'")
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ module JamRuby
|
|||
include JamRuby::S3PublicManagerMixin
|
||||
|
||||
# there should only be one Master per JamTrack, but there can be N Track per JamTrack
|
||||
TRACK_TYPE = %w{Track Master}
|
||||
TRACK_TYPE = %w{Track Master Click}
|
||||
|
||||
@@log = Logging.logger[JamTrackTrack]
|
||||
|
||||
|
|
@ -41,9 +41,19 @@ module JamRuby
|
|||
"jam_track_tracks"
|
||||
end
|
||||
|
||||
|
||||
def licensor_suffix
|
||||
suffix = ''
|
||||
if jam_track.licensor
|
||||
raise "no licensor name" if jam_track.licensor.name.nil?
|
||||
suffix = " - #{jam_track.licensor.name}"
|
||||
end
|
||||
suffix
|
||||
end
|
||||
|
||||
# create name of the file
|
||||
def filename(original_name)
|
||||
"#{store_dir}/#{jam_track.original_artist}/#{jam_track.name}/#{original_name}"
|
||||
"#{store_dir}/#{jam_track.original_artist}/#{jam_track.name}#{licensor_suffix}/#{original_name}"
|
||||
end
|
||||
|
||||
# create name of the preview file.
|
||||
|
|
@ -54,7 +64,7 @@ module JamRuby
|
|||
end
|
||||
|
||||
def preview_directory
|
||||
"jam_track_previews/#{jam_track.original_artist}/#{jam_track.name}"
|
||||
"jam_track_previews/#{jam_track.original_artist}/#{jam_track.name}#{licensor_suffix}"
|
||||
end
|
||||
|
||||
def has_preview?
|
||||
|
|
@ -192,10 +202,10 @@ module JamRuby
|
|||
|
||||
# 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)
|
||||
raise "Does not include AAC generation. Must be updated before used."
|
||||
uuid = SecureRandom.uuid
|
||||
output = File.join(tmp_dir, "#{uuid}.ogg")
|
||||
output_mp3 = File.join(tmp_dir, "#{uuid}.mp3")
|
||||
output_aac = File.join(tmp_dir, "#{uuid}.aac")
|
||||
|
||||
start = self.preview_start_time.to_f / 1000
|
||||
stop = start + 20
|
||||
|
|
@ -225,35 +235,55 @@ module JamRuby
|
|||
@@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)
|
||||
convert_aac_cmd = "#{APP_CONFIG.ffmpeg_path} -i \"#{output}\" -c:a libfdk_aac -b:a 192k \"#{output_aac}\""
|
||||
@@log.debug("converting to aac using: " + convert_aac_cmd)
|
||||
|
||||
self.skip_uploader = true
|
||||
convert_output = `#{convert_aac_cmd}`
|
||||
|
||||
original_ogg_preview_url = self["preview_url"]
|
||||
original_mp3_preview_url = self["preview_mp3_url"]
|
||||
result_code = $?.to_i
|
||||
|
||||
# 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 result_code != 0
|
||||
@@log.debug("fail #{result_code}")
|
||||
@preview_generate_error = "unable to execute aac convert command #{convert_output}"
|
||||
else
|
||||
|
||||
# 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"
|
||||
ogg_digest = ::Digest::MD5.file(output)
|
||||
mp3_digest = ::Digest::MD5.file(output_mp3)
|
||||
aac_digest = ::Digest::MD5.file(output_aac)
|
||||
self["preview_md5"] = ogg_md5 = ogg_digest.hexdigest
|
||||
self["preview_mp3_md5"] = mp3_md5 = mp3_digest.hexdigest
|
||||
self["preview_aac_md5"] = aac_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)
|
||||
@@log.debug("uploading aac preview to #{self.preview_filename('aac')}")
|
||||
s3_public_manager.upload(self.preview_filename(aac_md5, 'aac'), output_aac, content_type: 'audio/aac', content_md5: aac_digest.base64digest)
|
||||
|
||||
self.skip_uploader = true
|
||||
|
||||
original_ogg_preview_url = self["preview_url"]
|
||||
original_mp3_preview_url = self["preview_mp3_url"]
|
||||
original_aac_preview_url = self["preview_aac_url"]
|
||||
|
||||
self["preview_url"] = self.preview_filename(ogg_md5, 'ogg')
|
||||
self["preview_length"] = File.new(output).size
|
||||
self["preview_mp3_url"] = self.preview_filename(mp3_md5, 'mp3')
|
||||
self["preview_mp3_length"] = File.new(output_mp3).size
|
||||
self["preview_aac_url"] = self.preview_filename(aac_md5, 'aac')
|
||||
self["preview_aac_length"] = File.new(output_aac).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"]
|
||||
s3_public_manager.delete(original_aac_preview_url) if original_aac_preview_url && original_aac_preview_url != track["preview_aac_url"]
|
||||
rescue
|
||||
puts "UNABLE TO CLEANUP OLD PREVIEW URL"
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -92,53 +92,15 @@ module JamRuby
|
|||
transaction.save!
|
||||
|
||||
# now that we have the transaction saved, we also need to delete the jam_track_right if this is a refund, or voided
|
||||
|
||||
|
||||
if transaction.transaction_type == 'refund' || transaction.transaction_type == 'void'
|
||||
sale = Sale.find_by_recurly_invoice_id(transaction.invoice_id)
|
||||
|
||||
if sale && sale.is_jam_track_sale?
|
||||
if sale.sale_line_items.length == 1
|
||||
if sale.recurly_total_in_cents == transaction.amount_in_cents
|
||||
line_item = sale.sale_line_items[0]
|
||||
jam_track = line_item.product
|
||||
jam_track_right = jam_track.right_for_user(transaction.user) if jam_track
|
||||
if jam_track_right
|
||||
line_item.affiliate_refunded = true
|
||||
line_item.affiliate_refunded_at = Time.now
|
||||
line_item.save!
|
||||
if sale
|
||||
AdminMailer.recurly_alerts(transaction.user, {
|
||||
subject: "ACTION REQUIRED: #{transaction.user.email} has refund on invoice",
|
||||
body: "You will have to manually revoke any JamTrackRights in our database for the appropriate JamTracks"
|
||||
}).deliver
|
||||
|
||||
jam_track_right.destroy
|
||||
|
||||
# associate which JamTrack we assume this is related to in this one success case
|
||||
transaction.jam_track = jam_track
|
||||
transaction.save!
|
||||
|
||||
AdminMailer.recurly_alerts(transaction.user, {
|
||||
subject: "NOTICE: #{transaction.user.email} has had JamTrack: #{jam_track.name} revoked",
|
||||
body: "A #{transaction.transaction_type} event came from Recurly for sale with Recurly invoice ID #{sale.recurly_invoice_id}. We deleted their right to the track in our own database as a result."
|
||||
}).deliver
|
||||
else
|
||||
AdminMailer.recurly_alerts(transaction.user, {
|
||||
subject: "NOTICE: #{transaction.user.email} got a refund, but unable to find JamTrackRight to delete",
|
||||
body: "This should just mean the user already has no rights to the JamTrackRight when the refund came in. Not a big deal, but sort of weird..."
|
||||
}).deliver
|
||||
end
|
||||
|
||||
else
|
||||
AdminMailer.recurly_alerts(transaction.user, {
|
||||
subject: "ACTION REQUIRED: #{transaction.user.email} got a refund it was not for total value of a JamTrack sale",
|
||||
body: "We received a #{transaction.transaction_type} notice for an amount that was not the same as the original sale. So, no action was taken in the database. sale total: #{sale.recurly_total_in_cents}, refund amount: #{transaction.amount_in_cents}"
|
||||
}).deliver
|
||||
end
|
||||
|
||||
|
||||
else
|
||||
AdminMailer.recurly_alerts(transaction.user, {
|
||||
subject: "ACTION REQUIRED: #{transaction.user.email} has refund on invoice with multiple JamTracks",
|
||||
body: "You will have to manually revoke any JamTrackRights in our database for the appropriate JamTracks"
|
||||
}).deliver
|
||||
end
|
||||
else
|
||||
AdminMailer.recurly_alerts(transaction.user, {
|
||||
subject: "ACTION REQUIRED: #{transaction.user.email} has refund with no correlator to sales",
|
||||
|
|
|
|||
|
|
@ -69,27 +69,12 @@ module JamRuby
|
|||
}
|
||||
end
|
||||
|
||||
def self.preview_invoice(current_user, shopping_carts)
|
||||
|
||||
line_items = {jam_tracks: []}
|
||||
shopping_carts_jam_tracks = []
|
||||
shopping_carts_subscriptions = []
|
||||
shopping_carts.each do |shopping_cart|
|
||||
|
||||
if shopping_cart.is_jam_track?
|
||||
shopping_carts_jam_tracks << shopping_cart
|
||||
else
|
||||
# XXX: this may have to be revisited when we actually have something other than JamTracks for puchase
|
||||
shopping_carts_subscriptions << shopping_cart
|
||||
end
|
||||
def self.ios_purchase(current_user, jam_track, receipt)
|
||||
jam_track_right = JamRuby::JamTrackRight.find_or_create_by_user_id_and_jam_track_id(current_user.id, jam_track.id) do |jam_track_right|
|
||||
jam_track_right.redeemed = false
|
||||
jam_track_right.version = jam_track.version
|
||||
end
|
||||
|
||||
jam_track_items = preview_invoice_jam_tracks(current_user, shopping_carts_jam_tracks)
|
||||
line_items[:jam_tracks] = jam_track_items if jam_track_items
|
||||
|
||||
# TODO: process shopping_carts_subscriptions
|
||||
|
||||
line_items
|
||||
end
|
||||
|
||||
# place_order will create one or more sales based on the contents of shopping_carts for the current user
|
||||
|
|
@ -99,19 +84,14 @@ module JamRuby
|
|||
def self.place_order(current_user, shopping_carts)
|
||||
|
||||
sales = []
|
||||
shopping_carts_jam_tracks = []
|
||||
shopping_carts_subscriptions = []
|
||||
shopping_carts.each do |shopping_cart|
|
||||
|
||||
if shopping_cart.is_jam_track?
|
||||
shopping_carts_jam_tracks << shopping_cart
|
||||
else
|
||||
# XXX: this may have to be revisited when we actually have something other than JamTracks for puchase
|
||||
shopping_carts_subscriptions << shopping_cart
|
||||
end
|
||||
|
||||
if Sale.is_mixed(shopping_carts)
|
||||
# the controller checks this too; this is just an extra-level of sanity checking
|
||||
return sales
|
||||
end
|
||||
|
||||
jam_track_sale = order_jam_tracks(current_user, shopping_carts_jam_tracks)
|
||||
jam_track_sale = order_jam_tracks(current_user, shopping_carts)
|
||||
sales << jam_track_sale if jam_track_sale
|
||||
|
||||
# TODO: process shopping_carts_subscriptions
|
||||
|
|
@ -119,22 +99,52 @@ module JamRuby
|
|||
sales
|
||||
end
|
||||
|
||||
def self.preview_invoice_jam_tracks(current_user, shopping_carts_jam_tracks)
|
||||
### XXX TODO;
|
||||
|
||||
# we currently use a fake plan in Recurly to estimate taxes using the Pricing.Attach metod in Recurly.js
|
||||
def self.is_only_freebie(shopping_carts)
|
||||
free = true
|
||||
shopping_carts.each do |cart|
|
||||
free = cart.product_info[:free]
|
||||
|
||||
# if we were to implement this the right way (ensure adjustments are on the account as necessary), then it would be better (more correct)
|
||||
# just a pain to implement
|
||||
if !free
|
||||
break
|
||||
end
|
||||
end
|
||||
free
|
||||
end
|
||||
|
||||
def self.is_only_freebie(shopping_carts_jam_tracks)
|
||||
shopping_carts_jam_tracks.length == 1 && shopping_carts_jam_tracks[0].product_info[:free]
|
||||
# we don't allow mixed shopping carts :/
|
||||
def self.is_mixed(shopping_carts)
|
||||
free = false
|
||||
non_free = false
|
||||
shopping_carts.each do |cart|
|
||||
if cart.product_info[:free]
|
||||
free = true
|
||||
else
|
||||
non_free = true
|
||||
end
|
||||
end
|
||||
free && non_free
|
||||
end
|
||||
|
||||
# this method will either return a valid sale, or throw a RecurlyClientError or ActiveRecord validation error (save! failed)
|
||||
# it may return an nil sale if the JamTrack(s) specified by the shopping carts are already owned
|
||||
def self.order_jam_tracks(current_user, shopping_carts_jam_tracks)
|
||||
def self.order_jam_tracks(current_user, shopping_carts)
|
||||
|
||||
shopping_carts_jam_tracks = []
|
||||
shopping_carts_subscriptions = []
|
||||
shopping_carts_gift_cards = []
|
||||
|
||||
shopping_carts.each do |shopping_cart|
|
||||
if shopping_cart.is_jam_track?
|
||||
shopping_carts_jam_tracks << shopping_cart
|
||||
elsif shopping_cart.is_gift_card?
|
||||
shopping_carts_gift_cards << shopping_cart
|
||||
else
|
||||
# XXX: this may have to be revisited when we actually have something other than JamTracks for puchase
|
||||
raise "unknown shopping cart type #{shopping_cart.cart_type}"
|
||||
shopping_carts_subscriptions << shopping_cart
|
||||
end
|
||||
end
|
||||
|
||||
client = RecurlyClient.new
|
||||
|
||||
|
|
@ -143,8 +153,8 @@ module JamRuby
|
|||
sale = create_jam_track_sale(current_user)
|
||||
|
||||
if sale.valid?
|
||||
if is_only_freebie(shopping_carts_jam_tracks)
|
||||
sale.process_jam_tracks(current_user, shopping_carts_jam_tracks, nil)
|
||||
if is_only_freebie(shopping_carts)
|
||||
sale.process_shopping_carts(current_user, shopping_carts, nil)
|
||||
|
||||
sale.recurly_subtotal_in_cents = 0
|
||||
sale.recurly_tax_in_cents = 0
|
||||
|
|
@ -159,11 +169,13 @@ module JamRuby
|
|||
return sale
|
||||
end
|
||||
|
||||
sale_line_item = sale.sale_line_items[0]
|
||||
sale_line_item.recurly_tax_in_cents = 0
|
||||
sale_line_item.recurly_total_in_cents = 0
|
||||
sale_line_item.recurly_currency = 'USD'
|
||||
sale_line_item.recurly_discount_in_cents = 0
|
||||
sale.sale_line_items.each do |sale_line_item|
|
||||
sale_line_item = sale.sale_line_items[0]
|
||||
sale_line_item.recurly_tax_in_cents = 0
|
||||
sale_line_item.recurly_total_in_cents = 0
|
||||
sale_line_item.recurly_currency = 'USD'
|
||||
sale_line_item.recurly_discount_in_cents = 0
|
||||
end
|
||||
sale.save
|
||||
|
||||
else
|
||||
|
|
@ -173,7 +185,7 @@ module JamRuby
|
|||
|
||||
purge_pending_adjustments(account)
|
||||
|
||||
created_adjustments = sale.process_jam_tracks(current_user, shopping_carts_jam_tracks, account)
|
||||
created_adjustments = sale.process_shopping_carts(current_user, shopping_carts, account)
|
||||
|
||||
# now invoice the sale ... almost done
|
||||
|
||||
|
|
@ -229,13 +241,13 @@ module JamRuby
|
|||
sale
|
||||
end
|
||||
|
||||
def process_jam_tracks(current_user, shopping_carts_jam_tracks, account)
|
||||
def process_shopping_carts(current_user, shopping_carts, account)
|
||||
|
||||
created_adjustments = []
|
||||
|
||||
begin
|
||||
shopping_carts_jam_tracks.each do |shopping_cart|
|
||||
process_jam_track(current_user, shopping_cart, account, created_adjustments)
|
||||
shopping_carts.each do |shopping_cart|
|
||||
process_shopping_cart(current_user, shopping_cart, account, created_adjustments)
|
||||
end
|
||||
rescue Recurly::Error, NoMethodError => x
|
||||
# rollback any adjustments created if error
|
||||
|
|
@ -251,7 +263,7 @@ module JamRuby
|
|||
end
|
||||
|
||||
|
||||
def process_jam_track(current_user, shopping_cart, account, created_adjustments)
|
||||
def process_shopping_cart(current_user, shopping_cart, account, created_adjustments)
|
||||
recurly_adjustment_uuid = nil
|
||||
recurly_adjustment_credit_uuid = nil
|
||||
|
||||
|
|
@ -259,15 +271,20 @@ module JamRuby
|
|||
shopping_cart.reload
|
||||
|
||||
# get the JamTrack in this shopping cart
|
||||
jam_track = shopping_cart.cart_product
|
||||
cart_product = shopping_cart.cart_product
|
||||
|
||||
if jam_track.right_for_user(current_user)
|
||||
# if the user already owns the JamTrack, we should just skip this cart item, and destroy it
|
||||
# if this occurs, we have to reload every shopping_cart as we iterate. so, we do at the top of the loop
|
||||
ShoppingCart.remove_jam_track_from_cart(current_user, shopping_cart)
|
||||
return
|
||||
if shopping_cart.is_jam_track?
|
||||
jam_track = cart_product
|
||||
if jam_track.right_for_user(current_user)
|
||||
# if the user already owns the JamTrack, we should just skip this cart item, and destroy it
|
||||
# if this occurs, we have to reload every shopping_cart as we iterate. so, we do at the top of the loop
|
||||
ShoppingCart.remove_jam_track_from_cart(current_user, shopping_cart)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
if account
|
||||
# ask the shopping cart to create the correct Recurly adjustment attributes for a JamTrack
|
||||
adjustments = shopping_cart.create_adjustment_attributes(current_user)
|
||||
|
|
@ -300,38 +317,70 @@ module JamRuby
|
|||
|
||||
# if the sale line item is invalid, blow up the transaction
|
||||
unless sale_line_item.valid?
|
||||
@log.error("sale item invalid! #{sale_line_item.errors.inspect}")
|
||||
@@log.error("sale item invalid! #{sale_line_item.errors.inspect}")
|
||||
puts("sale item invalid! #{sale_line_item.errors.inspect}")
|
||||
Stats.write('web.recurly.purchase.sale_invalid', {message: sale_line_item.errors.to_s, value: 1})
|
||||
raise RecurlyClientError.new(sale_line_item.errors)
|
||||
end
|
||||
|
||||
# create a JamTrackRight (this needs to be in a transaction too to make sure we don't make these by accident)
|
||||
jam_track_right = JamRuby::JamTrackRight.find_or_create_by_user_id_and_jam_track_id(current_user.id, jam_track.id) do |jam_track_right|
|
||||
jam_track_right.redeemed = shopping_cart.free?
|
||||
end
|
||||
if shopping_cart.is_jam_track?
|
||||
jam_track = cart_product
|
||||
|
||||
# also if the purchase was a free one, then update the user record to no longer allow redeemed jamtracks
|
||||
if shopping_cart.free?
|
||||
User.where(id: current_user.id).update_all(has_redeemable_jamtrack: false)
|
||||
current_user.has_redeemable_jamtrack = false # make sure model reflects the truth
|
||||
end
|
||||
|
||||
|
||||
# this can't go in the block above, as it's here to fix bad subscription UUIDs in an update path
|
||||
if jam_track_right.recurly_adjustment_uuid != recurly_adjustment_uuid
|
||||
jam_track_right.recurly_adjustment_uuid = recurly_adjustment_uuid
|
||||
jam_track_right.recurly_adjustment_credit_uuid = recurly_adjustment_credit_uuid
|
||||
unless jam_track_right.save
|
||||
raise RecurlyClientError.new(jam_track_right.errors)
|
||||
# create a JamTrackRight (this needs to be in a transaction too to make sure we don't make these by accident)
|
||||
jam_track_right = JamRuby::JamTrackRight.find_or_create_by_user_id_and_jam_track_id(current_user.id, jam_track.id) do |jam_track_right|
|
||||
jam_track_right.redeemed = shopping_cart.free?
|
||||
jam_track_right.version = jam_track.version
|
||||
end
|
||||
|
||||
# also if the purchase was a free one, then:
|
||||
# first, mark the free has_redeemable_jamtrack field if that's still true
|
||||
# and if still they have more free things, then redeem the giftable_jamtracks
|
||||
if shopping_cart.free?
|
||||
if user.has_redeemable_jamtrack
|
||||
User.where(id: current_user.id).update_all(has_redeemable_jamtrack: false)
|
||||
current_user.has_redeemable_jamtrack = false
|
||||
else
|
||||
User.where(id: current_user.id).update_all(gifted_jamtracks: current_user.gifted_jamtracks - 1)
|
||||
current_user.gifted_jamtracks = current_user.gifted_jamtracks - 1
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# this can't go in the block above, as it's here to fix bad subscription UUIDs in an update path
|
||||
if jam_track_right.recurly_adjustment_uuid != recurly_adjustment_uuid
|
||||
jam_track_right.recurly_adjustment_uuid = recurly_adjustment_uuid
|
||||
jam_track_right.recurly_adjustment_credit_uuid = recurly_adjustment_credit_uuid
|
||||
unless jam_track_right.save
|
||||
raise RecurlyClientError.new(jam_track_right.errors)
|
||||
end
|
||||
end
|
||||
|
||||
# blow up the transaction if the JamTrackRight did not get created
|
||||
raise RecurlyClientError.new(jam_track_right.errors) if jam_track_right.errors.any?
|
||||
|
||||
elsif shopping_cart.is_gift_card?
|
||||
gift_card_type = cart_product
|
||||
raise "gift card is null" if gift_card_type.nil?
|
||||
raise if current_user.nil?
|
||||
|
||||
shopping_cart.quantity.times do |item|
|
||||
gift_card_purchase = GiftCardPurchase.new(
|
||||
{
|
||||
user: current_user,
|
||||
gift_card_type: gift_card_type
|
||||
})
|
||||
|
||||
unless gift_card_purchase.save
|
||||
raise RecurlyClientError.new(gift_card_purchase.errors)
|
||||
end
|
||||
end
|
||||
|
||||
else
|
||||
raise 'unknown shopping cart type: ' + shopping_cart.cart_type
|
||||
end
|
||||
|
||||
# delete the shopping cart; it's been dealt with
|
||||
shopping_cart.destroy if shopping_cart
|
||||
|
||||
# blow up the transaction if the JamTrackRight did not get created
|
||||
raise RecurlyClientError.new(jam_track_right.errors) if jam_track_right.errors.any?
|
||||
end
|
||||
|
||||
|
||||
|
|
@ -361,7 +410,7 @@ module JamRuby
|
|||
def self.create_jam_track_sale(user)
|
||||
sale = Sale.new
|
||||
sale.user = user
|
||||
sale.sale_type = JAMTRACK_SALE
|
||||
sale.sale_type = JAMTRACK_SALE # gift cards and jam tracks are sold with this type of sale
|
||||
sale.order_total = 0
|
||||
sale.save
|
||||
sale
|
||||
|
|
|
|||
|
|
@ -4,14 +4,16 @@ module JamRuby
|
|||
JAMBLASTER = 'JamBlaster'
|
||||
JAMCLOUD = 'JamCloud'
|
||||
JAMTRACK = 'JamTrack'
|
||||
GIFTCARD = 'GiftCardType'
|
||||
|
||||
belongs_to :sale, class_name: 'JamRuby::Sale'
|
||||
belongs_to :jam_track, class_name: 'JamRuby::JamTrack'
|
||||
belongs_to :jam_track_right, class_name: 'JamRuby::JamTrackRight'
|
||||
belongs_to :gift_card, class_name: 'JamRuby::GiftCard'
|
||||
belongs_to :affiliate_referral, class_name: 'JamRuby::AffiliatePartner', foreign_key: :affiliate_referral_id
|
||||
has_many :recurly_transactions, class_name: 'JamRuby::RecurlyTransactionWebHook', inverse_of: :sale_line_item, foreign_key: 'subscription_id', primary_key: 'recurly_subscription_uuid'
|
||||
|
||||
validates :product_type, inclusion: {in: [JAMBLASTER, JAMCLOUD, JAMTRACK]}
|
||||
validates :product_type, inclusion: {in: [JAMBLASTER, JAMCLOUD, JAMTRACK, GIFTCARD]}
|
||||
validates :unit_price, numericality: {only_integer: false}
|
||||
validates :quantity, numericality: {only_integer: true}
|
||||
validates :free, numericality: {only_integer: true}
|
||||
|
|
@ -21,9 +23,19 @@ module JamRuby
|
|||
validates :recurly_plan_code, presence:true
|
||||
validates :sale, presence:true
|
||||
|
||||
def is_jam_track?
|
||||
product_type == JAMTRACK
|
||||
end
|
||||
|
||||
def is_gift_card?
|
||||
product_type == GIFTCARD
|
||||
end
|
||||
|
||||
def product
|
||||
if product_type == JAMTRACK
|
||||
JamTrack.find_by_id(product_id)
|
||||
elsif product_type == GIFTCARD
|
||||
GiftCardType.find_by_id(product_id)
|
||||
else
|
||||
raise 'unsupported product type'
|
||||
end
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ module JamRuby
|
|||
|
||||
attr_accessible :quantity, :cart_type, :product_info
|
||||
|
||||
attr_accessor :skip_mix_check
|
||||
|
||||
validates_uniqueness_of :cart_id, scope: [:cart_type, :user_id, :anonymous_user_id]
|
||||
|
||||
belongs_to :user, :inverse_of => :shopping_carts, :class_name => "JamRuby::User", :foreign_key => "user_id"
|
||||
|
|
@ -20,12 +22,13 @@ module JamRuby
|
|||
validates :cart_type, presence: true
|
||||
validates :cart_class_name, presence: true
|
||||
validates :marked_for_redeem, numericality: {only_integer: true}
|
||||
validate :not_mixed
|
||||
|
||||
default_scope order('created_at DESC')
|
||||
|
||||
def product_info
|
||||
product = self.cart_product
|
||||
{name: product.name, price: product.price, product_id: cart_id, plan_code: product.plan_code, real_price: real_price(product), total_price: total_price(product), quantity: quantity, marked_for_redeem: marked_for_redeem, free: free?, sales_region: product.sales_region} unless product.nil?
|
||||
{type: cart_type, name: product.name, price: product.price, product_id: cart_id, plan_code: product.plan_code, real_price: real_price(product), total_price: total_price(product), quantity: quantity, marked_for_redeem: marked_for_redeem, free: free?, sales_region: product.sales_region, sale_display:product.sale_display} unless product.nil?
|
||||
end
|
||||
|
||||
# multiply quantity by price
|
||||
|
|
@ -38,6 +41,31 @@ module JamRuby
|
|||
(quantity - marked_for_redeem) * product.price
|
||||
end
|
||||
|
||||
def not_mixed
|
||||
|
||||
return if @skip_mix_check
|
||||
existing_carts = []
|
||||
this_user = any_user()
|
||||
|
||||
if this_user
|
||||
existing_carts = this_user.shopping_carts
|
||||
end
|
||||
|
||||
existing_carts = existing_carts.to_a
|
||||
existing_carts << self
|
||||
|
||||
if Sale.is_mixed(existing_carts)
|
||||
if free?
|
||||
errors.add(:base, "You can not add a free JamTrack to a cart with non-free items. Please clear out your cart.")
|
||||
return false
|
||||
else
|
||||
errors.add(:base, "You can not add a non-free JamTrack to a cart containing free items. Please clear out your cart.")
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
false
|
||||
end
|
||||
|
||||
def cart_product
|
||||
self.cart_class_name.classify.constantize.find_by_id(self.cart_id) unless self.cart_class_name.blank?
|
||||
|
|
@ -51,7 +79,18 @@ module JamRuby
|
|||
marked_for_redeem == quantity
|
||||
end
|
||||
|
||||
def any_user
|
||||
if user
|
||||
user
|
||||
elsif anonymous_user_id
|
||||
AnonymousUser.new(anonymous_user_id, nil)
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def self.create user, product, quantity = 1, mark_redeem = false
|
||||
|
||||
cart = ShoppingCart.new
|
||||
if user.is_a?(User)
|
||||
cart.user = user
|
||||
|
|
@ -72,39 +111,42 @@ module JamRuby
|
|||
cart_type == JamTrack::PRODUCT_TYPE
|
||||
end
|
||||
|
||||
def is_gift_card?
|
||||
cart_type == GiftCardType::PRODUCT_TYPE
|
||||
end
|
||||
|
||||
# returns an array of adjustments for the shopping cart
|
||||
def create_adjustment_attributes(current_user)
|
||||
raise "not a jam track" unless is_jam_track?
|
||||
raise "not a jam track or gift card" unless is_jam_track? || is_gift_card?
|
||||
|
||||
info = self.product_info
|
||||
|
||||
if free?
|
||||
|
||||
# create the credit, then the pseudo charge
|
||||
[
|
||||
{
|
||||
accounting_code: PURCHASE_FREE_CREDIT,
|
||||
currency: 'USD',
|
||||
unit_amount_in_cents: -(info[:total_price] * 100).to_i,
|
||||
description: "JamTrack: " + info[:name] + " (Credit)",
|
||||
description: info[:sale_display] + " (Credit)",
|
||||
tax_exempt: true
|
||||
},
|
||||
{
|
||||
accounting_code: PURCHASE_FREE,
|
||||
currency: 'USD',
|
||||
unit_amount_in_cents: (info[:total_price] * 100).to_i,
|
||||
description: "JamTrack: " + info[:name],
|
||||
description: info[:sale_display],
|
||||
tax_exempt: true
|
||||
}
|
||||
]
|
||||
else
|
||||
|
||||
[
|
||||
{
|
||||
accounting_code: PURCHASE_NORMAL,
|
||||
currency: 'USD',
|
||||
unit_amount_in_cents: (info[:total_price] * 100).to_i,
|
||||
description: "JamTrack: " + info[:name],
|
||||
description: info[:sale_display],
|
||||
tax_exempt: false
|
||||
}
|
||||
]
|
||||
|
|
@ -113,8 +155,13 @@ module JamRuby
|
|||
|
||||
def self.move_to_user(user, anonymous_user, shopping_carts)
|
||||
shopping_carts.each do |shopping_cart|
|
||||
mark_redeem = ShoppingCart.user_has_redeemable_jam_track?(user)
|
||||
cart = ShoppingCart.create(user, shopping_cart.cart_product, shopping_cart.quantity, mark_redeem)
|
||||
if shopping_cart.is_jam_track?
|
||||
mark_redeem = ShoppingCart.user_has_redeemable_jam_track?(user)
|
||||
cart = ShoppingCart.create(user, shopping_cart.cart_product, shopping_cart.quantity, mark_redeem)
|
||||
else
|
||||
cart = ShoppingCart.create(user, shopping_cart.cart_product, shopping_cart.quantity, false)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
anonymous_user.destroy_all_shopping_carts
|
||||
|
|
@ -134,28 +181,32 @@ module JamRuby
|
|||
# if no shpping carts have been marked, then mark it redeemable
|
||||
# should be wrapped in a TRANSACTION
|
||||
def self.user_has_redeemable_jam_track?(any_user)
|
||||
mark_redeem = false
|
||||
if APP_CONFIG.one_free_jamtrack_per_user && any_user.has_redeemable_jamtrack
|
||||
mark_redeem = true # start out assuming we can redeem...
|
||||
|
||||
if any_user.has_redeemable_jamtrack || any_user.gifted_jamtracks > 0
|
||||
|
||||
free_in_cart = 0
|
||||
any_user.shopping_carts.each do |shopping_cart|
|
||||
# but if we find any shopping cart item already marked for redeem, then back out of mark_redeem=true
|
||||
if shopping_cart.cart_type == JamTrack::PRODUCT_TYPE && shopping_cart.marked_for_redeem > 0
|
||||
mark_redeem = false
|
||||
break
|
||||
if shopping_cart.cart_type == JamTrack::PRODUCT_TYPE
|
||||
free_in_cart += shopping_cart.marked_for_redeem
|
||||
end
|
||||
end
|
||||
|
||||
any_user.free_jamtracks > free_in_cart
|
||||
else
|
||||
false
|
||||
end
|
||||
mark_redeem
|
||||
end
|
||||
|
||||
# adds a jam_track to cart, checking for promotions
|
||||
def self.add_jam_track_to_cart(any_user, jam_track)
|
||||
def self.add_jam_track_to_cart(any_user, jam_track, clear:false)
|
||||
cart = nil
|
||||
ShoppingCart.transaction do
|
||||
|
||||
if any_user.has_redeemable_jamtrack
|
||||
# if you still have a freebie available to you, or if you are an anonymous user, we make sure there is nothing else in your shopping cart
|
||||
any_user.destroy_all_shopping_carts
|
||||
if clear
|
||||
# if you are an anonymous user, we make sure there is nothing else in your shopping cart ... keep it clean for the 'new user rummaging around for a freebie scenario'
|
||||
any_user.destroy_jam_track_shopping_carts
|
||||
any_user.reload
|
||||
end
|
||||
|
||||
mark_redeem = ShoppingCart.user_has_redeemable_jam_track?(any_user)
|
||||
|
|
@ -164,23 +215,66 @@ module JamRuby
|
|||
cart
|
||||
end
|
||||
|
||||
def self.add_item_to_cart(any_user, item)
|
||||
cart = nil
|
||||
ShoppingCart.transaction do
|
||||
cart = ShoppingCart.create(any_user, item, 1, false)
|
||||
end
|
||||
cart
|
||||
end
|
||||
|
||||
# deletes a jam track from the shopping cart, updating redeem flag as necessary
|
||||
def self.remove_jam_track_from_cart(any_user, cart)
|
||||
ShoppingCart.transaction do
|
||||
cart.destroy
|
||||
# check if we should move the redemption
|
||||
|
||||
# so that user.shopping_carts reflects truth
|
||||
any_user.reload
|
||||
|
||||
# check if we should move the redemption around automatically
|
||||
mark_redeem = ShoppingCart.user_has_redeemable_jam_track?(any_user)
|
||||
|
||||
carts = any_user.shopping_carts
|
||||
|
||||
# if we find any carts on the account, mark one redeemable
|
||||
# if we find any carts on the account that are not redeemed, mark first one redeemable
|
||||
if mark_redeem && carts.length > 0
|
||||
carts[0].redeem(mark_redeem)
|
||||
carts[0].save
|
||||
carts.each do |cart|
|
||||
if cart.marked_for_redeem == 0
|
||||
if cart.quantity > 1
|
||||
raise 'unknown situation for redeemption juggling'
|
||||
end
|
||||
cart.redeem(mark_redeem)
|
||||
cart.save
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.remove_item_from_cart(any_user, cart)
|
||||
ShoppingCart.transaction do
|
||||
cart.destroy
|
||||
end
|
||||
end
|
||||
|
||||
# if the number of items in the shopping cart is less than gifted_jamtracks on the user, then fix them all up
|
||||
def self.apply_gifted_jamtracks(user)
|
||||
jam_track_carts = user.shopping_carts.where(cart_type:JamTrack::PRODUCT_TYPE)
|
||||
|
||||
if jam_track_carts.count > user.gifted_jamtracks
|
||||
# just whack everything in their shopping cart
|
||||
user.destroy_all_shopping_carts
|
||||
return
|
||||
end
|
||||
|
||||
jam_track_carts.each do |cart|
|
||||
cart.skip_mix_check = true
|
||||
cart.marked_for_redeem = 1
|
||||
cart.save!
|
||||
end
|
||||
end
|
||||
|
||||
def port(user, anonymous_user)
|
||||
|
||||
ShoppingCart.transaction do
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ module JamRuby
|
|||
attr_accessible :first_name, :last_name, :email, :city, :password, :password_confirmation, :state, :country, :birth_date, :subscribe_email, :terms_of_service, :original_fpfile, :cropped_fpfile, :cropped_large_fpfile, :cropped_s3_path, :cropped_large_s3_path, :photo_url, :large_photo_url, :crop_selection
|
||||
|
||||
# updating_password corresponds to a lost_password
|
||||
attr_accessor :updating_password, :updating_email, :updated_email, :update_email_confirmation_url, :administratively_created, :current_password, :setting_password, :confirm_current_password, :updating_avatar, :updating_progression_field, :mods_json
|
||||
attr_accessor :updating_password, :updating_email, :updated_email, :update_email_confirmation_url, :administratively_created, :current_password, :setting_password, :confirm_current_password, :updating_avatar, :updating_progression_field, :mods_json, :expecting_gift_card
|
||||
|
||||
belongs_to :icecast_server_group, class_name: "JamRuby::IcecastServerGroup", inverse_of: :users, foreign_key: 'icecast_server_group_id'
|
||||
|
||||
|
|
@ -148,6 +148,11 @@ module JamRuby
|
|||
# events
|
||||
has_many :event_sessions, :class_name => "JamRuby::EventSession"
|
||||
|
||||
# gift cards
|
||||
has_many :gift_cards, :class_name=> "JamRuby::GiftCard"
|
||||
has_many :gift_card_purchases, :class_name=> "JamRuby::GiftCardPurchase"
|
||||
|
||||
|
||||
# affiliate_partner
|
||||
has_one :affiliate_partner, :class_name => "JamRuby::AffiliatePartner", :foreign_key => :partner_user_id, inverse_of: :partner_user
|
||||
belongs_to :affiliate_referral, :class_name => "JamRuby::AffiliatePartner", :foreign_key => :affiliate_referral_id, :counter_cache => :referral_user_count
|
||||
|
|
@ -194,6 +199,7 @@ module JamRuby
|
|||
validates :terms_of_service, :acceptance => {:accept => true, :on => :create, :allow_nil => false }
|
||||
validates :reuse_card, :inclusion => {:in => [true, false]}
|
||||
validates :has_redeemable_jamtrack, :inclusion => {:in => [true, false]}
|
||||
validates :gifted_jamtracks, presence: true, :numericality => { :less_than_or_equal_to => 100 }
|
||||
validates :subscribe_email, :inclusion => {:in => [nil, true, false]}
|
||||
validates :musician, :inclusion => {:in => [true, false]}
|
||||
validates :show_whats_next, :inclusion => {:in => [nil, true, false]}
|
||||
|
|
@ -214,6 +220,7 @@ module JamRuby
|
|||
validate :email_case_insensitive_uniqueness
|
||||
validate :update_email_case_insensitive_uniqueness, :if => :updating_email
|
||||
validate :validate_mods
|
||||
validate :presence_gift_card, :if => :expecting_gift_card
|
||||
|
||||
scope :musicians, where(:musician => true)
|
||||
scope :fans, where(:musician => false)
|
||||
|
|
@ -233,6 +240,18 @@ module JamRuby
|
|||
end
|
||||
end
|
||||
|
||||
def has_any_free_jamtracks
|
||||
has_redeemable_jamtrack || gifted_jamtracks > 0
|
||||
end
|
||||
|
||||
def free_jamtracks
|
||||
(has_redeemable_jamtrack ? 1 : 0) + gifted_jamtracks
|
||||
end
|
||||
|
||||
def show_free_jamtrack?
|
||||
ShoppingCart.user_has_redeemable_jam_track?(self)
|
||||
end
|
||||
|
||||
def failed_qualification(reason)
|
||||
self.last_failed_certified_gear_at = DateTime.now
|
||||
self.last_failed_certified_gear_reason = reason
|
||||
|
|
@ -255,6 +274,12 @@ module JamRuby
|
|||
end
|
||||
end
|
||||
|
||||
def presence_gift_card
|
||||
if self.gift_cards.length == 0
|
||||
errors.add(:gift_card, ValidationMessages::NOT_FOUND)
|
||||
end
|
||||
end
|
||||
|
||||
def validate_current_password
|
||||
# checks if the user put in their current password (used when changing your email, for instance)
|
||||
errors.add(:current_password, ValidationMessages::NOT_YOUR_PASSWORD) if should_confirm_existing_password? && !valid_password?(self.current_password)
|
||||
|
|
@ -1025,6 +1050,7 @@ module JamRuby
|
|||
reuse_card = options[:reuse_card]
|
||||
signup_hint = options[:signup_hint]
|
||||
affiliate_partner = options[:affiliate_partner]
|
||||
gift_card = options[:gift_card]
|
||||
|
||||
user = User.new
|
||||
|
||||
|
|
@ -1036,6 +1062,9 @@ module JamRuby
|
|||
user.terms_of_service = terms_of_service
|
||||
user.musician = musician
|
||||
user.reuse_card unless reuse_card.nil?
|
||||
user.gifted_jamtracks = 0
|
||||
user.has_redeemable_jamtrack = true
|
||||
|
||||
|
||||
# FIXME: Setting random password for social network logins. This
|
||||
# is because we have validations all over the place on this.
|
||||
|
|
@ -1140,8 +1169,22 @@ module JamRuby
|
|||
end
|
||||
end
|
||||
|
||||
found_gift_card = nil
|
||||
|
||||
# if a gift card value was passed in, then try to find that gift card and apply it to user
|
||||
if gift_card
|
||||
user.expecting_gift_card = true
|
||||
found_gift_card = GiftCard.where(code:gift_card).where(user_id:nil).first
|
||||
user.gift_cards << found_gift_card if found_gift_card
|
||||
end
|
||||
|
||||
user.save
|
||||
|
||||
if found_gift_card
|
||||
user.reload
|
||||
ShoppingCart.apply_gifted_jamtracks(user)
|
||||
end
|
||||
|
||||
# if the user has just one, free jamtrack in their shopping cart, and it matches the signup hint, then auto-buy it
|
||||
# only_freebie_in_cart =
|
||||
# signup_hint &&
|
||||
|
|
@ -1181,6 +1224,7 @@ module JamRuby
|
|||
end
|
||||
end
|
||||
end
|
||||
user.reload if user.id# gift card adding gifted_jamtracks doesn't reflect here until reload
|
||||
user
|
||||
end # def signup
|
||||
|
||||
|
|
@ -1636,6 +1680,11 @@ module JamRuby
|
|||
ShoppingCart.where("user_id=?", self).destroy_all
|
||||
end
|
||||
|
||||
def destroy_jam_track_shopping_carts
|
||||
ShoppingCart.destroy_all(anonymous_user_id: @id, cart_type: JamTrack::PRODUCT_TYPE)
|
||||
end
|
||||
|
||||
|
||||
def unsubscribe_token
|
||||
self.class.create_access_token(self)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -10,9 +10,11 @@ module JamRuby
|
|||
|
||||
include JamRuby::S3ManagerMixin
|
||||
|
||||
TAP_IN_PADDING = 2
|
||||
|
||||
MAX_PAN = 90
|
||||
MIN_PAN = -90
|
||||
KNOCK_SECONDS = 0.035
|
||||
|
||||
attr_accessor :mixdown_package_id, :settings, :mixdown_package, :mixdown, :step
|
||||
@queue = :jam_track_mixdown_packager
|
||||
|
|
@ -55,6 +57,8 @@ module JamRuby
|
|||
@mixdown = @mixdown_package.jam_track_mixdown
|
||||
@settings = JSON.parse(@mixdown.settings)
|
||||
|
||||
process_jmep
|
||||
|
||||
track_settings
|
||||
|
||||
# compute the step count
|
||||
|
|
@ -102,6 +106,236 @@ module JamRuby
|
|||
vol != 1.0 || pan != 0
|
||||
end
|
||||
|
||||
def process_jmep
|
||||
@start_points = []
|
||||
@initial_padding = 0.0
|
||||
|
||||
speed = @settings['speed'] || 0
|
||||
|
||||
@speed_factor = 1.0 + (-speed.to_f / 100.0)
|
||||
@inverse_speed_factor = 1 - (-speed.to_f / 100)
|
||||
|
||||
log.info("speed factor #{@speed_factor}")
|
||||
|
||||
jmep = @mixdown.jam_track.jmep_json
|
||||
if jmep
|
||||
jmep = JSON.parse(jmep)
|
||||
end
|
||||
|
||||
if jmep.nil?
|
||||
log.debug("no jmep")
|
||||
return
|
||||
end
|
||||
|
||||
events = jmep["Events"]
|
||||
|
||||
return if events.nil? || events.length == 0
|
||||
|
||||
metronome = nil
|
||||
events.each do |event|
|
||||
if event.has_key?("metronome")
|
||||
metronome = event["metronome"]
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if metronome.nil? || metronome.length == 0
|
||||
log.debug("no metronome events for jmep", jmep)
|
||||
return
|
||||
end
|
||||
|
||||
@start_points = metronome.select { |x| puts x.inspect; x["action"] == "start" }
|
||||
|
||||
log.debug("found #{@start_points.length} metronome start points")
|
||||
|
||||
start_point = @start_points[0]
|
||||
|
||||
if start_point
|
||||
start_time = parse_time(start_point["ts"])
|
||||
|
||||
if start_time < 2.0
|
||||
padding = start_time - 2.0
|
||||
@initial_padding = padding.abs
|
||||
@initial_tap_in = start_time
|
||||
end
|
||||
end
|
||||
|
||||
if @speed_factor != 1.0
|
||||
metronome.length.times do |count|
|
||||
|
||||
# we expect to find metronome start/stop grouped
|
||||
if count % 2 == 0
|
||||
|
||||
start = metronome[count]
|
||||
stop = metronome[count + 1]
|
||||
|
||||
if start["action"] != "start" || stop["action"] != "stop"
|
||||
# bail out
|
||||
log.error("found de-coupled metronome events #{start.to_json} | #{stop.to_json}")
|
||||
next
|
||||
end
|
||||
|
||||
bpm = start["bpm"].to_f
|
||||
stop_time = parse_time(stop['ts'])
|
||||
ticks = stop['ticks'].to_i
|
||||
|
||||
|
||||
new_bpm = bpm * @inverse_speed_factor
|
||||
new_stop_time = stop_time * @speed_factor
|
||||
new_start_time = new_stop_time - (60.0/new_bpm * ticks)
|
||||
|
||||
log.info("original bpm:#{bpm} start: #{parse_time(start["ts"])} stop: #{stop_time}")
|
||||
log.info("updated bpm:#{new_bpm} start: #{new_start_time} stop: #{new_stop_time}")
|
||||
|
||||
stop["ts"] = new_stop_time
|
||||
start["ts"] = new_start_time
|
||||
start["bpm"] = new_bpm
|
||||
stop["bpm"] = new_bpm
|
||||
|
||||
@tap_in_initial_silence = (@initial_tap_in + @initial_padding) * @speed_factor
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@start_points = metronome.select { |x| puts x.inspect; x["action"] == "start" }
|
||||
|
||||
end
|
||||
|
||||
# format like: "-0:00:02:820"
|
||||
def parse_time(ts)
|
||||
|
||||
if ts.is_a?(Float)
|
||||
return ts
|
||||
end
|
||||
|
||||
time = 0.0
|
||||
negative = false
|
||||
|
||||
if ts.start_with?('-')
|
||||
negative = true
|
||||
end
|
||||
|
||||
# parse time_format
|
||||
bits = ts.split(':').reverse
|
||||
|
||||
bit_position = 0
|
||||
bits.each do |bit|
|
||||
if bit_position == 0
|
||||
# milliseconds
|
||||
milliseconds = bit.to_f
|
||||
time += milliseconds/1000
|
||||
elsif bit_position == 1
|
||||
# seconds
|
||||
time += bit.to_f
|
||||
elsif bit_position == 2
|
||||
# minutes
|
||||
time += 60 * bit.to_f
|
||||
elsif bit_position == 3
|
||||
# hours
|
||||
# not bothering
|
||||
end
|
||||
|
||||
bit_position += 1
|
||||
end
|
||||
|
||||
if negative
|
||||
time = 0.0 - time
|
||||
end
|
||||
|
||||
time
|
||||
end
|
||||
|
||||
def path_to_resources
|
||||
File.join(File.dirname(File.expand_path(__FILE__)), '../../../lib/jam_ruby/app/assets/sounds')
|
||||
end
|
||||
|
||||
def knock_file
|
||||
if long_sample_rate == 44100
|
||||
knock = File.join(path_to_resources, 'knock44.wav')
|
||||
else
|
||||
knock = File.join(path_to_resources, 'knock48.wav')
|
||||
end
|
||||
|
||||
log.debug("knock file path: " + knock)
|
||||
knock
|
||||
end
|
||||
|
||||
def create_silence(tmp_dir, segment_count, duration)
|
||||
file = File.join(tmp_dir, "#{segment_count}.wav")
|
||||
|
||||
# -c 2 means stereo
|
||||
cmd("sox -n -r #{long_sample_rate} -c 2 #{file} trim 0.0 #{duration}", "silence")
|
||||
|
||||
file
|
||||
end
|
||||
|
||||
def create_tapin_track(tmp_dir)
|
||||
|
||||
return nil if @start_points.length == 0
|
||||
|
||||
segment_count = 0
|
||||
|
||||
|
||||
#initial_silence = @initial_tap_in + @initial_padding
|
||||
|
||||
initial_silence = @tap_in_initial_silence
|
||||
|
||||
#log.info("tapin data: initial_tap_in: #{@initial_tap_in}, initial_padding: #{@initial_padding}, initial_silence: #{initial_silence}")
|
||||
|
||||
time_points = []
|
||||
files = []
|
||||
if initial_silence > 0
|
||||
|
||||
files << create_silence(tmp_dir, segment_count, initial_silence)
|
||||
|
||||
time_points << {type: :silence, ts: initial_silence}
|
||||
segment_count += 1
|
||||
end
|
||||
|
||||
|
||||
time_cursor = nil
|
||||
@start_points.each do |start_point|
|
||||
tap_time = parse_time(start_point["ts"])
|
||||
if !time_cursor.nil?
|
||||
between_silence = tap_time - time_cursor
|
||||
files << create_silence(tmp_dir, segment_count, between_silence)
|
||||
time_points << {type: :silence, ts: between_silence}
|
||||
end
|
||||
time_cursor = tap_time
|
||||
bpm = start_point["bpm"].to_f
|
||||
|
||||
tick_silence = 60.0/bpm - KNOCK_SECONDS
|
||||
|
||||
ticks = start_point["ticks"].to_i
|
||||
|
||||
ticks.times do |tick|
|
||||
files << knock_file
|
||||
files << create_silence(tmp_dir, segment_count, tick_silence)
|
||||
time_points << {type: :knock, ts: KNOCK_SECONDS}
|
||||
time_points << {type: :silence, ts: tick_silence}
|
||||
time_cursor + 60.0/bpm
|
||||
segment_count += 1
|
||||
end
|
||||
end
|
||||
|
||||
log.info("time points for tap-in: #{time_points.inspect}")
|
||||
# do we need to pad with time? not sure
|
||||
|
||||
sequence_cmd = "sox "
|
||||
files.each do |file|
|
||||
sequence_cmd << "\"#{file}\" "
|
||||
end
|
||||
|
||||
count_in = File.join(tmp_dir, "count-in.wav")
|
||||
sequence_cmd << "\"#{count_in}\""
|
||||
|
||||
cmd(sequence_cmd, "count_in")
|
||||
@count_in_file = count_in
|
||||
count_in
|
||||
end
|
||||
|
||||
# creates a list of tracks to actually mix
|
||||
def track_settings
|
||||
altered_tracks = @settings["tracks"] || []
|
||||
|
|
@ -113,6 +347,15 @@ module JamRuby
|
|||
stems = @mixdown.jam_track.stem_tracks
|
||||
@track_count = stems.length
|
||||
|
||||
@include_count_in = @settings["count-in"] && @start_points.length > 0 && @mixdown_package.encrypt_type.nil?
|
||||
|
||||
# temp
|
||||
# @include_count_in = true
|
||||
|
||||
if @include_count_in
|
||||
@track_count += 1
|
||||
end
|
||||
|
||||
stems.each do |stem|
|
||||
|
||||
vol = 1.0
|
||||
|
|
@ -139,10 +382,14 @@ module JamRuby
|
|||
|
||||
# if we didn't deliberately skip this one, and if there was no 'match' (meaning user did not specify), then we leave this in unchanged
|
||||
if !skipped && !match
|
||||
@track_settings << {stem:stem, vol:vol, pan:pan}
|
||||
@track_settings << {stem: stem, vol: vol, pan: pan}
|
||||
end
|
||||
end
|
||||
|
||||
if @include_count_in
|
||||
@track_settings << {count_in: true, vol: 1.0, pan: 0}
|
||||
end
|
||||
|
||||
@track_settings
|
||||
end
|
||||
|
||||
|
|
@ -153,14 +400,14 @@ module JamRuby
|
|||
# k = f(i) = (i)/(2*MAX_PAN) + 0.5
|
||||
# so f(MIN_PAN) = -0.5 + 0.5 = 0
|
||||
|
||||
k = ((pan * (1.0))/ (2.0 * MAX_PAN )) + 0.5
|
||||
k = ((pan * (1.0))/ (2.0 * MAX_PAN)) + 0.5
|
||||
l, r = 0
|
||||
|
||||
if k == 0
|
||||
l = 0.0
|
||||
r = 1.0
|
||||
else
|
||||
l = Math.sqrt(k)
|
||||
l = Math.sqrt(k)
|
||||
r = Math.sqrt(1-k)
|
||||
end
|
||||
|
||||
|
|
@ -169,24 +416,26 @@ module JamRuby
|
|||
|
||||
def package
|
||||
|
||||
puts @settings.inspect
|
||||
puts @track_count
|
||||
puts @track_settings
|
||||
puts @track_settings.count
|
||||
log.info("Settings: #{@settings.to_json}")
|
||||
|
||||
Dir.mktmpdir do |tmp_dir|
|
||||
|
||||
# download all files
|
||||
@track_settings.each do |track|
|
||||
jam_track_track = track[:stem]
|
||||
|
||||
file = File.join(tmp_dir, jam_track_track.id + '.ogg')
|
||||
if track[:count_in]
|
||||
file = create_tapin_track(tmp_dir)
|
||||
bump_step(@mixdown_package)
|
||||
else
|
||||
jam_track_track = track[:stem]
|
||||
|
||||
bump_step(@mixdown_package)
|
||||
file = File.join(tmp_dir, jam_track_track.id + '.ogg')
|
||||
|
||||
# download each track needed
|
||||
s3_manager.download(jam_track_track.url_by_sample_rate(@mixdown_package.sample_rate), file)
|
||||
bump_step(@mixdown_package)
|
||||
|
||||
# download each track needed
|
||||
s3_manager.download(jam_track_track.url_by_sample_rate(@mixdown_package.sample_rate), file)
|
||||
end
|
||||
|
||||
track[:file] = file
|
||||
end
|
||||
|
|
@ -206,6 +455,8 @@ module JamRuby
|
|||
|
||||
apply_vol_and_pan tmp_dir
|
||||
|
||||
create_silence_padding tmp_dir
|
||||
|
||||
mix tmp_dir
|
||||
|
||||
pitch_speed tmp_dir
|
||||
|
|
@ -218,6 +469,7 @@ module JamRuby
|
|||
@track_settings.each do |track|
|
||||
|
||||
jam_track_track = track[:stem]
|
||||
count_in = track[:count_in]
|
||||
file = track[:file]
|
||||
|
||||
unless should_alter_volume? track
|
||||
|
|
@ -235,7 +487,11 @@ module JamRuby
|
|||
|
||||
# sox claps.wav claps-remixed.wav remix 1v1.0 2v1.0
|
||||
|
||||
volumed_file = File.join(tmp_dir, jam_track_track.id + '-volumed.ogg')
|
||||
if count_in
|
||||
volumed_file = File.join(tmp_dir, 'count-in' + '-volumed.ogg')
|
||||
else
|
||||
volumed_file = File.join(tmp_dir, jam_track_track.id + '-volumed.ogg')
|
||||
end
|
||||
|
||||
cmd("sox \"#{file}\" \"#{volumed_file}\" remix 1v#{channel_r} 2v#{channel_l}", 'vol_pan')
|
||||
|
||||
|
|
@ -244,6 +500,29 @@ module JamRuby
|
|||
end
|
||||
end
|
||||
|
||||
def create_silence_padding(tmp_dir)
|
||||
if @initial_padding > 0 && @include_count_in
|
||||
|
||||
@padding_file = File.join(tmp_dir, "initial_padding.ogg")
|
||||
|
||||
# -c 2 means stereo
|
||||
cmd("sox -n -r #{long_sample_rate} -c 2 #{@padding_file} trim 0.0 #{@initial_padding}", "initial_padding")
|
||||
|
||||
@track_settings.each do |track|
|
||||
|
||||
next if track[:count_in]
|
||||
|
||||
input = track[:volumed_file]
|
||||
output = input[0..-5] + '-padded.ogg'
|
||||
|
||||
padd_cmd = "sox '#{@padding_file}' '#{input}' '#{output}'"
|
||||
|
||||
cmd(padd_cmd, "pad_track_with_silence")
|
||||
track[:volumed_file] = output
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# output is @mix_file
|
||||
def mix(tmp_dir)
|
||||
|
||||
|
|
@ -251,6 +530,11 @@ module JamRuby
|
|||
|
||||
@mix_file = File.join(tmp_dir, "mix.ogg")
|
||||
|
||||
|
||||
pitch = @settings['pitch'] || 0
|
||||
speed = @settings['speed'] || 0
|
||||
|
||||
|
||||
# if there is only one track to mix, we need to skip mixing (sox will barf if you try to mix one file), but still divide by number of tracks
|
||||
if @track_settings.count == 1
|
||||
mix_divide = 1.0/@track_count
|
||||
|
|
@ -263,6 +547,11 @@ module JamRuby
|
|||
cmd = "sox -m"
|
||||
mix_divide = 1.0/@track_count
|
||||
@track_settings.each do |track|
|
||||
|
||||
# if pitch/shifted, we lay the tap-in after pitch/speed shift
|
||||
# next if (pitch != 0 || speed != 0) && track[:count_in]
|
||||
next if track[:count_in]
|
||||
|
||||
volumed_file = track[:volumed_file]
|
||||
cmd << " -v #{mix_divide} \"#{volumed_file}\""
|
||||
end
|
||||
|
|
@ -275,6 +564,13 @@ module JamRuby
|
|||
|
||||
end
|
||||
|
||||
def long_sample_rate
|
||||
sample_rate = 48000
|
||||
if @mixdown_package.sample_rate != 48
|
||||
sample_rate = 44100
|
||||
end
|
||||
sample_rate
|
||||
end
|
||||
|
||||
# output is @speed_mix_file
|
||||
def pitch_speed tmp_dir
|
||||
|
|
@ -300,17 +596,21 @@ module JamRuby
|
|||
|
||||
# usage: sbsms infile<.wav|.aif|.mp3|.ogg> outfile<.ogg> rate[0.01:100] halfsteps[-48:48] outSampleRateInHz
|
||||
|
||||
sample_rate = 48000
|
||||
if @mixdown_package.sample_rate != 48
|
||||
sample_rate = 44100
|
||||
end
|
||||
sample_rate = long_sample_rate
|
||||
|
||||
# rate comes in as a percent (like 5, -5 for 5%, -5%). We need to change that to 1.05/
|
||||
sbsms_speed = speed/100.0
|
||||
sbsms_speed = 1.0 + sbsms_speed
|
||||
|
||||
sbsms_pitch = pitch
|
||||
cmd( "sbsms \"#{@mix_file}\" \"#{@speed_mix_file}\" #{sbsms_speed} #{sbsms_pitch} #{sample_rate}", 'speed_pitch_shift')
|
||||
cmd("sbsms \"#{@mix_file}\" \"#{@speed_mix_file}\" #{sbsms_speed} #{sbsms_pitch} #{sample_rate}", 'speed_pitch_shift')
|
||||
end
|
||||
|
||||
if @include_count_in
|
||||
# lay the tap-ins over the recording
|
||||
layered = File.join(tmp_dir, "layered_speed_mix.ogg")
|
||||
cmd("sox -m '#{@count_in_file}' '#{@speed_mix_file}' '#{layered}'", "layer_tap_in")
|
||||
@speed_mix_file = layered
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -337,7 +637,7 @@ module JamRuby
|
|||
|
||||
length = File.size(output)
|
||||
computed_md5 = Digest::MD5.new
|
||||
File.open(output, 'rb').each {|line| computed_md5.update(line)}
|
||||
File.open(output, 'rb').each { |line| computed_md5.update(line) }
|
||||
md5 = computed_md5.to_s
|
||||
|
||||
@mixdown_package.finish_sign(s3_url, private_key, length, md5.to_s)
|
||||
|
|
@ -399,7 +699,7 @@ module JamRuby
|
|||
end
|
||||
|
||||
private_key_file = File.join(tmp_dir, 'skey.pem')
|
||||
File.open(private_key_file, 'w') {|f| f.write(private_key) }
|
||||
File.open(private_key_file, 'w') { |f| f.write(private_key) }
|
||||
|
||||
log.debug("PRIVATE KEY")
|
||||
log.debug(private_key)
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ FactoryGirl.define do
|
|||
terms_of_service true
|
||||
last_jam_audio_latency 5
|
||||
reuse_card true
|
||||
has_redeemable_jamtrack true
|
||||
gifted_jamtracks 0
|
||||
|
||||
#u.association :musician_instrument, factory: :musician_instrument, user: u
|
||||
|
||||
|
|
@ -858,4 +860,18 @@ FactoryGirl.define do
|
|||
legalese Faker::Lorem.paragraphs(6).join("\n\n")
|
||||
end
|
||||
|
||||
factory :gift_card, class: 'JamRuby::GiftCard' do
|
||||
sequence(:code) {n.to_s}
|
||||
card_type JamRuby::GiftCardType::JAM_TRACKS_5
|
||||
end
|
||||
|
||||
factory :gift_card_type, class: 'JamRuby::GiftCardType' do
|
||||
card_type JamRuby::GiftCardType::JAM_TRACKS_5
|
||||
end
|
||||
|
||||
factory :gift_card_purchase, class: 'JamRuby::GiftCardPurchase' do
|
||||
|
||||
association :user, factory: :user
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -234,6 +234,17 @@ describe JamTrack do
|
|||
query.size.should == 2
|
||||
|
||||
end
|
||||
|
||||
it "deals with aggregration (regression)" do
|
||||
|
||||
query, pager, count = JamTrack.index({sort_by: 'jamtrack', artist: 'K.C. And The Sunshine Band'}, user)
|
||||
count.should == 0
|
||||
|
||||
jam_track1 = FactoryGirl.create(:jam_track_with_tracks, name: 'Take a Chance On Me', original_artist: 'K.C. And The Sunshine Band')
|
||||
|
||||
query, pager, count = JamTrack.index({sort_by: 'jamtrack', artist: 'K.C. And The Sunshine Band'}, user)
|
||||
count.should == 1
|
||||
end
|
||||
end
|
||||
|
||||
describe "validations" do
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ describe RecurlyTransactionWebHook do
|
|||
|
||||
RecurlyTransactionWebHook.create_from_xml(document)
|
||||
|
||||
JamTrackRight.find_by_id(jam_track_right.id).should be_nil
|
||||
JamTrackRight.find_by_id(jam_track_right.id).should_not be_nil
|
||||
end
|
||||
|
||||
it "deletes jam_track_right when voided" do
|
||||
|
|
@ -154,7 +154,7 @@ describe RecurlyTransactionWebHook do
|
|||
|
||||
RecurlyTransactionWebHook.create_from_xml(document)
|
||||
|
||||
JamTrackRight.find_by_id(jam_track_right.id).should be_nil
|
||||
JamTrackRight.find_by_id(jam_track_right.id).should_not be_nil
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ describe SaleLineItem do
|
|||
let(:user) {FactoryGirl.create(:user)}
|
||||
let(:user2) {FactoryGirl.create(:user)}
|
||||
let(:jam_track) {FactoryGirl.create(:jam_track)}
|
||||
let(:gift_card) {FactoryGirl.create(:gift_card_type, card_type: GiftCardType::JAM_TRACKS_10)}
|
||||
|
||||
describe "associations" do
|
||||
|
||||
|
|
@ -23,7 +24,7 @@ describe SaleLineItem do
|
|||
|
||||
describe "state" do
|
||||
|
||||
it "success" do
|
||||
it "jam track success" do
|
||||
sale = Sale.create_jam_track_sale(user)
|
||||
shopping_cart = ShoppingCart.create(user, jam_track)
|
||||
sale_line_item = SaleLineItem.create_from_shopping_cart(sale, shopping_cart, 'some_recurly_uuid', nil, nil)
|
||||
|
|
@ -37,5 +38,20 @@ describe SaleLineItem do
|
|||
success: true
|
||||
})
|
||||
end
|
||||
|
||||
it "gift card success" do
|
||||
sale = Sale.create_jam_track_sale(user)
|
||||
shopping_cart = ShoppingCart.create(user, gift_card)
|
||||
sale_line_item = SaleLineItem.create_from_shopping_cart(sale, shopping_cart, 'some_recurly_uuid', nil, nil)
|
||||
transaction = FactoryGirl.create(:recurly_transaction_web_hook, subscription_id: 'some_recurly_uuid')
|
||||
|
||||
sale_line_item.reload
|
||||
sale_line_item.state.should eq({
|
||||
void: false,
|
||||
refund: false,
|
||||
fail: false,
|
||||
success: true
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -5,6 +5,24 @@ describe Sale do
|
|||
let(:user) {FactoryGirl.create(:user)}
|
||||
let(:user2) {FactoryGirl.create(:user)}
|
||||
let(:jam_track) {FactoryGirl.create(:jam_track)}
|
||||
let(:jam_track2) {FactoryGirl.create(:jam_track)}
|
||||
let(:jam_track3) {FactoryGirl.create(:jam_track)}
|
||||
let(:gift_card) {GiftCardType.jam_track_5}
|
||||
|
||||
def assert_free_line_item(sale_line_item, jamtrack)
|
||||
sale_line_item.recurly_tax_in_cents.should be_nil
|
||||
sale_line_item.recurly_total_in_cents.should be_nil
|
||||
sale_line_item.recurly_currency.should be_nil
|
||||
sale_line_item.recurly_discount_in_cents.should be_nil
|
||||
sale_line_item.product_type.should eq(JamTrack::PRODUCT_TYPE)
|
||||
sale_line_item.unit_price.should eq(jamtrack.price)
|
||||
sale_line_item.quantity.should eq(1)
|
||||
sale_line_item.free.should eq(1)
|
||||
sale_line_item.sales_tax.should be_nil
|
||||
sale_line_item.shipping_handling.should eq(0)
|
||||
sale_line_item.recurly_plan_code.should eq(jamtrack.plan_code)
|
||||
sale_line_item.product_id.should eq(jamtrack.id)
|
||||
end
|
||||
|
||||
describe "index" do
|
||||
it "empty" do
|
||||
|
|
@ -47,7 +65,11 @@ describe Sale do
|
|||
|
||||
let(:user) {FactoryGirl.create(:user)}
|
||||
let(:jamtrack) { FactoryGirl.create(:jam_track) }
|
||||
let(:jamtrack2) { FactoryGirl.create(:jam_track) }
|
||||
let(:jamtrack3) { FactoryGirl.create(:jam_track) }
|
||||
let(:jamtrack4) { FactoryGirl.create(:jam_track) }
|
||||
let(:jam_track_price_in_cents) { (jamtrack.price * 100).to_i }
|
||||
let(:gift_card_price_in_cents) { (gift_card.price * 100).to_i }
|
||||
let(:client) { RecurlyClient.new }
|
||||
let(:billing_info) {
|
||||
info = {}
|
||||
|
|
@ -75,6 +97,77 @@ describe Sale do
|
|||
end
|
||||
end
|
||||
|
||||
it "for a gift card" do
|
||||
shopping_cart = ShoppingCart.create user, gift_card, 1, false
|
||||
client.find_or_create_account(user, billing_info)
|
||||
|
||||
sales = Sale.place_order(user, [shopping_cart])
|
||||
|
||||
user.reload
|
||||
user.sales.length.should eq(1)
|
||||
|
||||
sales.should eq(user.sales)
|
||||
sale = sales[0]
|
||||
sale.recurly_invoice_id.should_not be_nil
|
||||
|
||||
sale.recurly_subtotal_in_cents.should eq(gift_card_price_in_cents)
|
||||
sale.recurly_tax_in_cents.should eq(0)
|
||||
sale.recurly_total_in_cents.should eq(gift_card_price_in_cents)
|
||||
sale.recurly_currency.should eq('USD')
|
||||
|
||||
sale.order_total.should eq(gift_card.price)
|
||||
sale.sale_line_items.length.should == 1
|
||||
sale_line_item = sale.sale_line_items[0]
|
||||
# validate we are storing pricing info from recurly
|
||||
sale_line_item.recurly_tax_in_cents.should eq(0)
|
||||
sale_line_item.recurly_total_in_cents.should eq(gift_card_price_in_cents)
|
||||
sale_line_item.recurly_currency.should eq('USD')
|
||||
sale_line_item.recurly_discount_in_cents.should eq(0)
|
||||
sale_line_item.product_type.should eq(GiftCardType::PRODUCT_TYPE)
|
||||
sale_line_item.unit_price.should eq(gift_card.price)
|
||||
sale_line_item.quantity.should eq(1)
|
||||
sale_line_item.free.should eq(0)
|
||||
sale_line_item.sales_tax.should be_nil
|
||||
sale_line_item.shipping_handling.should eq(0)
|
||||
sale_line_item.recurly_plan_code.should eq(gift_card.plan_code)
|
||||
sale_line_item.product_id.should eq(gift_card.id)
|
||||
sale_line_item.recurly_subscription_uuid.should be_nil
|
||||
sale_line_item.recurly_adjustment_uuid.should_not be_nil
|
||||
sale_line_item.recurly_adjustment_credit_uuid.should be_nil
|
||||
sale_line_item.recurly_adjustment_uuid.should_not be_nil
|
||||
|
||||
# verify subscription is in Recurly
|
||||
recurly_account = client.get_account(user)
|
||||
adjustments = recurly_account.adjustments
|
||||
adjustments.should_not be_nil
|
||||
adjustments.should have(1).items
|
||||
purchase= adjustments[0]
|
||||
purchase.unit_amount_in_cents.should eq((gift_card.price * 100).to_i)
|
||||
purchase.accounting_code.should eq(ShoppingCart::PURCHASE_NORMAL)
|
||||
purchase.description.should eq("JamTracks Gift Card (5)")
|
||||
purchase.state.should eq('invoiced')
|
||||
purchase.uuid.should eq(sale_line_item.recurly_adjustment_uuid)
|
||||
|
||||
invoices = recurly_account.invoices
|
||||
invoices.should have(1).items
|
||||
invoice = invoices[0]
|
||||
invoice.uuid.should eq(sale.recurly_invoice_id)
|
||||
invoice.line_items.should have(1).items # should have single adjustment associated
|
||||
invoice.line_items[0].should eq(purchase)
|
||||
invoice.subtotal_in_cents.should eq((gift_card.price * 100).to_i)
|
||||
invoice.total_in_cents.should eq((gift_card.price * 100).to_i)
|
||||
invoice.state.should eq('collected')
|
||||
|
||||
# verify jam_track_rights data
|
||||
user.gift_card_purchases.should_not be_nil
|
||||
user.gift_card_purchases.should have(1).items
|
||||
user.gift_card_purchases.last.gift_card_type.should eq(GiftCardType.jam_track_5)
|
||||
user.has_redeemable_jamtrack.should be_true
|
||||
|
||||
sale_line_item.affiliate_referral.should be_nil
|
||||
sale_line_item.affiliate_referral_fee_in_cents.should be_nil
|
||||
end
|
||||
|
||||
|
||||
it "for a free jam track" do
|
||||
shopping_cart = ShoppingCart.create user, jamtrack, 1, true
|
||||
|
|
@ -87,6 +180,7 @@ describe Sale do
|
|||
|
||||
sales.should eq(user.sales)
|
||||
sale = sales[0]
|
||||
|
||||
sale.recurly_invoice_id.should be_nil
|
||||
|
||||
sale.recurly_subtotal_in_cents.should eq(0)
|
||||
|
|
@ -132,6 +226,69 @@ describe Sale do
|
|||
user.has_redeemable_jamtrack.should be_false
|
||||
end
|
||||
|
||||
it "for two jam tracks (1 freebie, 1 gifted), then 1 gifted/1 pay" do
|
||||
user.gifted_jamtracks = 2
|
||||
user.save!
|
||||
|
||||
shopping_cart1 = ShoppingCart.create user, jamtrack, 1, true
|
||||
shopping_cart2 = ShoppingCart.create user, jamtrack2, 1, true
|
||||
|
||||
client.find_or_create_account(user, billing_info)
|
||||
|
||||
sales = Sale.place_order(user, [shopping_cart1, shopping_cart2])
|
||||
|
||||
user.reload
|
||||
user.sales.length.should eq(1)
|
||||
sale = sales[0]
|
||||
sale.reload
|
||||
|
||||
sale.recurly_invoice_id.should be_nil
|
||||
|
||||
sale.recurly_subtotal_in_cents.should eq(0)
|
||||
sale.recurly_tax_in_cents.should eq(0)
|
||||
sale.recurly_total_in_cents.should eq(0)
|
||||
sale.recurly_currency.should eq('USD')
|
||||
sale.order_total.should eq(0)
|
||||
sale.sale_line_items.length.should == 2
|
||||
|
||||
assert_free_line_item(sale.sale_line_items[0], jamtrack)
|
||||
assert_free_line_item(sale.sale_line_items[1], jamtrack2)
|
||||
|
||||
# verify jam_track_rights data
|
||||
right1 = JamTrackRight.where(user_id: user.id).where(jam_track_id: jamtrack.id).first
|
||||
right2 = JamTrackRight.where(user_id: user.id).where(jam_track_id: jamtrack2.id).first
|
||||
user.jam_track_rights.should have(2).items
|
||||
|
||||
right1.redeemed.should be_true
|
||||
right2.redeemed.should be_true
|
||||
user.has_redeemable_jamtrack.should be_false
|
||||
user.gifted_jamtracks.should eq(1)
|
||||
|
||||
|
||||
|
||||
# OK! Now make a second purchase; this time, buy one free, one not free
|
||||
shopping_cart3 = ShoppingCart.create user, jamtrack3, 1, true
|
||||
|
||||
client.find_or_create_account(user, billing_info)
|
||||
|
||||
sales = Sale.place_order(user, [shopping_cart3])
|
||||
|
||||
user.reload
|
||||
user.sales.length.should eq(2)
|
||||
sale = sales[0]
|
||||
sale.reload
|
||||
|
||||
sale.recurly_invoice_id.should be_nil
|
||||
sale.recurly_subtotal_in_cents.should eq(0)
|
||||
sale.recurly_tax_in_cents.should eq(0)
|
||||
sale.recurly_total_in_cents.should eq(0)
|
||||
sale.recurly_currency.should eq('USD')
|
||||
sale.order_total.should eq(0)
|
||||
sale.sale_line_items.length.should == 1
|
||||
|
||||
assert_free_line_item(sale.sale_line_items[0], jamtrack3)
|
||||
end
|
||||
|
||||
it "for a free jam track with an affiliate association" do
|
||||
partner = FactoryGirl.create(:affiliate_partner)
|
||||
user.affiliate_referral = partner
|
||||
|
|
|
|||
|
|
@ -3,8 +3,15 @@ require 'spec_helper'
|
|||
describe ShoppingCart do
|
||||
|
||||
let(:user) { FactoryGirl.create(:user) }
|
||||
let(:jam_track) {FactoryGirl.create(:jam_track) }
|
||||
let(:jam_track2) {FactoryGirl.create(:jam_track) }
|
||||
let(:jam_track) { FactoryGirl.create(:jam_track) }
|
||||
let(:jam_track2) { FactoryGirl.create(:jam_track) }
|
||||
let(:jam_track3) { FactoryGirl.create(:jam_track) }
|
||||
let(:jam_track4) { FactoryGirl.create(:jam_track) }
|
||||
let(:jam_track5) { FactoryGirl.create(:jam_track) }
|
||||
let(:jam_track6) { FactoryGirl.create(:jam_track) }
|
||||
let(:jam_track7) { FactoryGirl.create(:jam_track) }
|
||||
let(:gift_card) {FactoryGirl.create(:gift_card_type)}
|
||||
let(:gift_card2) {FactoryGirl.create(:gift_card_type)}
|
||||
|
||||
before(:each) do
|
||||
ShoppingCart.delete_all
|
||||
|
|
@ -13,6 +20,9 @@ describe ShoppingCart do
|
|||
it "can reference a shopping cart" do
|
||||
shopping_cart = ShoppingCart.create user, jam_track, 1
|
||||
|
||||
shopping_cart.errors.any?.should be_false
|
||||
shopping_cart.valid?.should be_true
|
||||
user.reload
|
||||
ShoppingCart.count.should == 1
|
||||
user.shopping_carts.count.should == 1
|
||||
user.shopping_carts[0].product_info[:name].should == jam_track.name
|
||||
|
|
@ -21,18 +31,21 @@ describe ShoppingCart do
|
|||
user.shopping_carts[0].quantity.should == 1
|
||||
end
|
||||
|
||||
|
||||
it "maintains only one fre JamTrack in ShoppingCart" do
|
||||
cart1 = ShoppingCart.add_jam_track_to_cart(user, jam_track)
|
||||
it "maintains only one free JamTrack in ShoppingCart" do
|
||||
cart1 = ShoppingCart.add_jam_track_to_cart(user, jam_track, clear: true)
|
||||
cart1.should_not be_nil
|
||||
cart1.errors.any?.should be_false
|
||||
user.reload
|
||||
cart2 = ShoppingCart.add_jam_track_to_cart(user, jam_track)
|
||||
cart2 = ShoppingCart.add_jam_track_to_cart(user, jam_track, clear: true)
|
||||
cart2.errors.any?.should be_false
|
||||
user.reload
|
||||
user.shopping_carts.length.should eq(1)
|
||||
cart3 = ShoppingCart.add_jam_track_to_cart(user, jam_track2)
|
||||
cart3.errors.any?.should be_false
|
||||
cart3 = ShoppingCart.add_item_to_cart(user, gift_card)
|
||||
cart3.errors.any?.should be_true
|
||||
user.reload
|
||||
user.shopping_carts.length.should eq(1)
|
||||
cart4 = ShoppingCart.add_jam_track_to_cart(user, jam_track2, clear: true)
|
||||
cart4.errors.any?.should be_false
|
||||
user.reload
|
||||
user.shopping_carts.length.should eq(1)
|
||||
end
|
||||
|
|
@ -48,24 +61,159 @@ describe ShoppingCart do
|
|||
cart2.errors.any?.should be_true
|
||||
end
|
||||
|
||||
it "a second giftcard just adds quantity" do
|
||||
|
||||
end
|
||||
|
||||
describe "redeemable behavior" do
|
||||
|
||||
it "removes redeemable item to shopping cart (maintains only one in cart)" do
|
||||
|
||||
user.has_redeemable_jamtrack.should be_true
|
||||
cart1 = ShoppingCart.add_jam_track_to_cart(user, jam_track, clear: true)
|
||||
cart1.should_not be_nil
|
||||
cart1.errors.any?.should be_false
|
||||
cart1.marked_for_redeem.should eq(1)
|
||||
user.reload
|
||||
cart2 = ShoppingCart.add_jam_track_to_cart(user, jam_track2, clear: true)
|
||||
cart2.should_not be_nil
|
||||
cart2.errors.any?.should be_false
|
||||
cart2.marked_for_redeem.should eq(1)
|
||||
|
||||
ShoppingCart.find_by_id(cart1.id).should be nil
|
||||
|
||||
|
||||
ShoppingCart.remove_jam_track_from_cart(user, cart2)
|
||||
|
||||
user.reload
|
||||
user.shopping_carts.length.should eq(0)
|
||||
ShoppingCart.find_by_id(cart2.id).should be nil
|
||||
end
|
||||
end
|
||||
|
||||
describe "multiple free jamtracks" do
|
||||
|
||||
before(:each) do
|
||||
user.gifted_jamtracks = 5
|
||||
user.save!
|
||||
end
|
||||
|
||||
it "user can add and remove jamtracks without issue, until 'mixed' free/non-free is hit" do
|
||||
cart1 = ShoppingCart.add_jam_track_to_cart(user, jam_track)
|
||||
cart1.should_not be_nil
|
||||
cart1.errors.any?.should be_false
|
||||
|
||||
user.reload
|
||||
cart2 = ShoppingCart.add_jam_track_to_cart(user, jam_track2)
|
||||
cart2.should_not be_nil
|
||||
|
||||
cart2.errors.any?.should be_false
|
||||
user.reload
|
||||
user.shopping_carts.length.should eq(2)
|
||||
cart1.marked_for_redeem.should eq(1)
|
||||
cart2.marked_for_redeem.should eq(1)
|
||||
ShoppingCart.remove_jam_track_from_cart(user, jam_track)
|
||||
|
||||
user.shopping_carts.length.should eq(0)
|
||||
cart2.reload
|
||||
cart3 = ShoppingCart.add_jam_track_to_cart(user, jam_track3)
|
||||
cart3.errors.any?.should be_false
|
||||
user.reload
|
||||
user.shopping_carts.length.should eq(3)
|
||||
cart1.marked_for_redeem.should eq(1)
|
||||
cart2.marked_for_redeem.should eq(1)
|
||||
cart3.marked_for_redeem.should eq(1)
|
||||
|
||||
cart4 = ShoppingCart.add_jam_track_to_cart(user, jam_track4)
|
||||
cart4.errors.any?.should be_false
|
||||
user.reload
|
||||
user.shopping_carts.length.should eq(4)
|
||||
cart1.marked_for_redeem.should eq(1)
|
||||
cart2.marked_for_redeem.should eq(1)
|
||||
cart3.marked_for_redeem.should eq(1)
|
||||
cart4.marked_for_redeem.should eq(1)
|
||||
|
||||
cart5 = ShoppingCart.add_jam_track_to_cart(user, jam_track5)
|
||||
cart5.errors.any?.should be_false
|
||||
user.reload
|
||||
user.shopping_carts.length.should eq(5)
|
||||
cart1.marked_for_redeem.should eq(1)
|
||||
cart2.marked_for_redeem.should eq(1)
|
||||
cart3.marked_for_redeem.should eq(1)
|
||||
cart4.marked_for_redeem.should eq(1)
|
||||
cart5.marked_for_redeem.should eq(1)
|
||||
|
||||
cart6 = ShoppingCart.add_jam_track_to_cart(user, jam_track6)
|
||||
cart6.errors.any?.should be_false
|
||||
user.reload
|
||||
user.shopping_carts.length.should eq(6)
|
||||
cart1.marked_for_redeem.should eq(1)
|
||||
cart2.marked_for_redeem.should eq(1)
|
||||
cart3.marked_for_redeem.should eq(1)
|
||||
cart4.marked_for_redeem.should eq(1)
|
||||
cart5.marked_for_redeem.should eq(1)
|
||||
cart6.marked_for_redeem.should eq(1)
|
||||
|
||||
cart7 = ShoppingCart.add_jam_track_to_cart(user, jam_track7)
|
||||
cart7.errors.any?.should be_true
|
||||
user.reload
|
||||
user.shopping_carts.length.should eq(6)
|
||||
cart1.marked_for_redeem.should eq(1)
|
||||
cart2.marked_for_redeem.should eq(1)
|
||||
cart3.marked_for_redeem.should eq(1)
|
||||
cart4.marked_for_redeem.should eq(1)
|
||||
cart5.marked_for_redeem.should eq(1)
|
||||
cart6.marked_for_redeem.should eq(1)
|
||||
end
|
||||
end
|
||||
|
||||
describe "gift cards" do
|
||||
it "can not add multiple of same type" do
|
||||
cart1 = ShoppingCart.add_item_to_cart(user, gift_card)
|
||||
cart1.should_not be_nil
|
||||
cart1.errors.any?.should be_false
|
||||
|
||||
user.reload
|
||||
user.has_redeemable_jamtrack = true
|
||||
user.shopping_carts.length.should eq(1)
|
||||
user.shopping_carts[0].quantity.should eql(1)
|
||||
|
||||
cart2 = ShoppingCart.add_item_to_cart(user, gift_card)
|
||||
cart2.should_not be_nil
|
||||
# it's the same type, so it's blocked
|
||||
cart2.errors.any?.should be_true
|
||||
cart2.errors[:cart_id].should eq(["has already been taken"])
|
||||
end
|
||||
end
|
||||
|
||||
describe "mixed" do
|
||||
it "non-free then free" do
|
||||
# you shouldn't be able to add a free after a non-free
|
||||
user.has_redeemable_jamtrack = false
|
||||
user.save!
|
||||
|
||||
cart1 = ShoppingCart.add_jam_track_to_cart(user, jam_track)
|
||||
cart1.should_not be_nil
|
||||
cart1.errors.any?.should be_false
|
||||
|
||||
user.has_redeemable_jamtrack = true
|
||||
user.save!
|
||||
user.reload
|
||||
cart2 = ShoppingCart.add_jam_track_to_cart(user, jam_track2)
|
||||
cart2.errors.any?.should be_true
|
||||
cart2.errors[:base].should eq(["You can not add a free JamTrack to a cart with non-free items. Please clear out your cart."])
|
||||
|
||||
user.shopping_carts.length.should eq(1)
|
||||
end
|
||||
|
||||
it "free then non-free" do
|
||||
|
||||
cart1 = ShoppingCart.add_jam_track_to_cart(user, jam_track)
|
||||
cart1.should_not be_nil
|
||||
cart1.errors.any?.should be_false
|
||||
|
||||
user.reload
|
||||
|
||||
cart2 = ShoppingCart.add_jam_track_to_cart(user, jam_track2)
|
||||
cart2.errors.any?.should be_true
|
||||
cart2.errors[:base].should eq(["You can not add a non-free JamTrack to a cart containing free items. Please clear out your cart."])
|
||||
|
||||
user.shopping_carts.length.should eq(1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -95,13 +95,13 @@ end
|
|||
|
||||
config.before(:suite) do
|
||||
DatabaseCleaner.strategy = :transaction
|
||||
DatabaseCleaner.clean_with(:deletion, {pre_count: true, reset_ids:false, :except => %w[instruments genres icecast_server_groups jamcompany jamisp geoipblocks geoipisp geoiplocations cities regions countries generic_state spatial_ref_sys] })
|
||||
DatabaseCleaner.clean_with(:deletion, {pre_count: true, reset_ids:false, :except => %w[gift_card_types instruments genres icecast_server_groups jamcompany jamisp geoipblocks geoipisp geoiplocations cities regions countries generic_state spatial_ref_sys] })
|
||||
end
|
||||
|
||||
config.around(:each) do |example|
|
||||
# set no_transaction: true as metadata on your test to use deletion strategy instead
|
||||
if example.metadata[:no_transaction]
|
||||
DatabaseCleaner.strategy = :deletion, {pre_count: true, reset_ids:false, :except => %w[instruments genres icecast_server_groups jamcompany jamisp geoipblocks geoipisp geoiplocations cities regions countries generic_state spatial_ref_sys] }
|
||||
DatabaseCleaner.strategy = :deletion, {pre_count: true, reset_ids:false, :except => %w[gift_card_types instruments genres icecast_server_groups jamcompany jamisp geoipblocks geoipisp geoiplocations cities regions countries generic_state spatial_ref_sys] }
|
||||
else
|
||||
DatabaseCleaner.strategy = :transaction
|
||||
end
|
||||
|
|
|
|||
|
After Width: | Height: | Size: 821 KiB |
|
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 6.0 KiB After Width: | Height: | Size: 18 KiB |
|
|
@ -40,8 +40,8 @@
|
|||
var template= context.JK.fillTemplate($('#template-account-profile-avatar').html(), {
|
||||
"fp_apikey" : gon.fp_apikey,
|
||||
"data-fp-store-path" : createStorePath(userDetail) + createOriginalFilename(userDetail),
|
||||
"fp_policy" : filepicker_policy.policy,
|
||||
"fp_signature" : filepicker_policy.signature
|
||||
"fp_policy" : encodeURIComponent(filepicker_policy.policy),
|
||||
"fp_signature" : encodeURIComponent(filepicker_policy.signature)
|
||||
});
|
||||
$('#account-profile-avatar-content-scroller').html(template);
|
||||
|
||||
|
|
@ -202,7 +202,6 @@
|
|||
renderNoAvatar(avatarSpace);
|
||||
}
|
||||
else {
|
||||
|
||||
rest.getFilepickerPolicy({handle: fpfile.url})
|
||||
.done(function(filepickerPolicy) {
|
||||
avatarSpace.children().remove();
|
||||
|
|
|
|||
|
|
@ -137,6 +137,9 @@
|
|||
else if(type === ALERT_NAMES.VIDEO_WINDOW_CLOSED) {
|
||||
context.VideoActions.videoWindowClosed()
|
||||
}
|
||||
else if (type === ALERT_NAMES.VST_CHANGED) {
|
||||
context.ConfigureTracksActions.onVstChanged()
|
||||
}
|
||||
else if((!context.JK.CurrentSessionModel || !context.JK.CurrentSessionModel.inSession()) &&
|
||||
(ALERT_NAMES.INPUT_IO_RATE == type || ALERT_NAMES.INPUT_IO_JTR == type || ALERT_NAMES.OUTPUT_IO_RATE == type || ALERT_NAMES.OUTPUT_IO_JTR== type)) {
|
||||
// squelch these events if not in session
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
var $templatePurchasedJamTrack = null;
|
||||
var $thanksPanel = null;
|
||||
var $jamTrackInBrowser = null;
|
||||
var $giftCardPurchased = null;
|
||||
var $purchasedJamTrack = null;
|
||||
var $purchasedJamTrackHeader = null;
|
||||
var $purchasedJamTracks = null;
|
||||
|
|
@ -75,9 +76,17 @@
|
|||
else {
|
||||
$thanksPanel.removeClass('hidden')
|
||||
handleJamTracksPurchased(purchaseResponse.jam_tracks)
|
||||
handleGiftCardsPurchased(purchaseResponse.gift_cards)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function handleGiftCardsPurchased(gift_cards) {
|
||||
// were any GiftCards purchased?
|
||||
if(gift_cards && gift_cards.length > 0) {
|
||||
$giftCardPurchased.removeClass('hidden')
|
||||
}
|
||||
}
|
||||
function handleJamTracksPurchased(jamTracks) {
|
||||
// were any JamTracks purchased?
|
||||
var jamTracksPurchased = jamTracks && jamTracks.length > 0;
|
||||
|
|
@ -194,6 +203,7 @@
|
|||
$templatePurchasedJamTrack = $('#template-purchased-jam-track');
|
||||
$thanksPanel = $screen.find(".thanks-panel");
|
||||
$jamTrackInBrowser = $screen.find(".thanks-detail.jam-tracks-in-browser");
|
||||
$giftCardPurchased = $screen.find('.thanks-detail.gift-card')
|
||||
$purchasedJamTrack = $thanksPanel.find(".thanks-detail.purchased-jam-track");
|
||||
$purchasedJamTrackHeader = $purchasedJamTrack.find(".purchased-jam-track-header");
|
||||
$purchasedJamTracks = $purchasedJamTrack.find(".purchased-list")
|
||||
|
|
|
|||
|
|
@ -135,15 +135,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
function displayTax(effectiveQuantity, item_tax, total_with_tax) {
|
||||
var totalTax = 0;
|
||||
var totalPrice = 0;
|
||||
|
||||
var unitTax = item_tax * effectiveQuantity;
|
||||
totalTax += unitTax;
|
||||
|
||||
var totalUnitPrice = total_with_tax * effectiveQuantity;
|
||||
totalPrice += totalUnitPrice;
|
||||
function displayTax(totalTax, totalPrice) {
|
||||
|
||||
$screen.find('.order-right-page .order-items-value.taxes').text('$' + totalTax.toFixed(2))
|
||||
$screen.find('.order-right-page .order-items-value.grand-total').text('$' + totalPrice.toFixed(2))
|
||||
|
|
@ -181,8 +173,16 @@
|
|||
taxRate = 0.0825;
|
||||
}
|
||||
|
||||
var unitTax = 1.99 * taxRate;
|
||||
displayTax(effectiveQuantity, unitTax, 1.99 + unitTax)
|
||||
var estimatedTax = 0;
|
||||
var estimatedTotal = 0;
|
||||
|
||||
context._.each(carts, function(cart) {
|
||||
var cart_quantity = cart.product_info.quantity - cart.product_info.marked_for_redeem
|
||||
estimatedTax += cart.product_info.price * cart_quantity * taxRate;
|
||||
estimatedTotal += cart.product_info.price * cart_quantity;
|
||||
})
|
||||
|
||||
displayTax(Math.round(estimatedTax*100)/100, Math.round((estimatedTotal + estimatedTax)*100)/100)
|
||||
}
|
||||
else {
|
||||
checkoutUtils.configureRecurly()
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@
|
|||
$reuseExistingCardChk.iCheck(userDetail.reuse_card && userDetail.has_recurly_account ? 'check' : 'uncheck').attr('checked', userDetail.reuse_card)
|
||||
|
||||
// show appropriate prompt text based on whether user has a free jamtrack
|
||||
if(user.free_jamtrack) {
|
||||
if(user.has_redeemable_jamtrack) {
|
||||
$freeJamTrackPrompt.removeClass('hidden')
|
||||
}
|
||||
else {
|
||||
|
|
|
|||
|
|
@ -55,6 +55,16 @@ class CheckoutUtils
|
|||
|
||||
return carts[0].product_info.free
|
||||
|
||||
hasOnlyFreeItemsInShoppingCart: (carts) =>
|
||||
if carts.length == 0
|
||||
return false
|
||||
|
||||
for cart in carts
|
||||
if !cart.product_info.free
|
||||
return false
|
||||
|
||||
return true
|
||||
|
||||
configureRecurly: () =>
|
||||
unless @configuredRecurly
|
||||
context.recurly.configure(gon.global.recurly_public_api_key)
|
||||
|
|
|
|||
|
|
@ -61,7 +61,10 @@
|
|||
})
|
||||
}
|
||||
|
||||
app.layout.showDialog('client-update')
|
||||
if(!app.layout.isDialogShowing('client-update')) {
|
||||
app.layout.showDialog('client-update')
|
||||
}
|
||||
|
||||
//$('#client_update').show()
|
||||
//$('#client_update_overlay').show()
|
||||
}
|
||||
|
|
@ -192,6 +195,11 @@
|
|||
|
||||
function runCheck(product, version, uri, size, currentVersion) {
|
||||
|
||||
if (app.clientUpdating) {
|
||||
logger.debug("client is already updating; skipping")
|
||||
return
|
||||
}
|
||||
|
||||
if(currentVersion === undefined) {
|
||||
currentVersion = context.jamClient.ClientUpdateVersion();
|
||||
|
||||
|
|
@ -302,7 +310,7 @@
|
|||
|
||||
$(document).on(EVENTS.SESSION_ENDED, function(e, data){
|
||||
if(app.clientUpdating) {
|
||||
updateClientUpdateDialog("update-start", { uri: updateUri })
|
||||
updateClientUpdateDialog("update-start", { uri: updateUri})
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@
|
|||
|
||||
$browserJamTrackBtn.click(function() {
|
||||
app.layout.closeDialog('getting-started')
|
||||
window.location = '/client#/jamtrack/search'
|
||||
window.location = '/client#/jamtrack'
|
||||
return false;
|
||||
})
|
||||
|
||||
|
|
@ -69,9 +69,9 @@
|
|||
|
||||
function beforeShow() {
|
||||
app.user().done(function(user) {
|
||||
var jamtrackRule = user.free_jamtrack ? 'has-free-jamtrack' : 'no-free-jamtrack'
|
||||
var jamtrackRule = user.has_redeemable_jamtrack ? 'has-free-jamtrack' : 'no-free-jamtrack'
|
||||
$jamTrackSection.removeClass('has-free-jamtrack').removeClass('no-free-jamtrack').addClass(jamtrackRule)
|
||||
if(user.free_jamtrack) {
|
||||
if(user.has_redeemable_jamtrack) {
|
||||
$jamTracksLimitedTime.removeClass('hidden')
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -369,8 +369,8 @@ context.JK.DownloadJamTrack = class DownloadJamTrack
|
|||
@trackDetail = context.jamClient.JamTrackGetTrackDetail ("#{@jamTrack.id}-#{@sampleRateForFilename}")
|
||||
|
||||
if @trackDetail.version?
|
||||
@logger.error("after invalidating package, the version is still wrong!")
|
||||
throw "after invalidating package, the version is still wrong!"
|
||||
@logger.error("after invalidating package, the version is still wrong!", @trackDetail)
|
||||
throw "after invalidating package, the version is still wrong! #{@trackDetail.version}"
|
||||
|
||||
switch @trackDetail.key_state
|
||||
when 'pending'
|
||||
|
|
|
|||
|
|
@ -126,7 +126,8 @@
|
|||
RECORDING_DONE :48, //the recording writer thread is done
|
||||
VIDEO_WINDOW_OPENED :49, //video window opened
|
||||
VIDEO_WINDOW_CLOSED :50,
|
||||
LAST_ALERT : 51
|
||||
VST_CHANGED: 51, // VST state changed
|
||||
LAST_ALERT : 52
|
||||
}
|
||||
// recreate eThresholdType enum from MixerDialog.h
|
||||
context.JK.ALERT_TYPES = {
|
||||
|
|
@ -190,7 +191,8 @@
|
|||
48: {"title": "", "message": ""}, // RECORDING_DONE
|
||||
49: {"title": "", "message": ""}, // VIDEO_WINDOW_OPENED
|
||||
50: {"title": "", "message": ""}, // VIDEO_WINDOW_CLOSED
|
||||
51: {"title": "", "message": ""} // LAST_ALERT
|
||||
51: {"title": "", "message": ""}, // VST_CHANGED
|
||||
52: {"title": "", "message": ""} // LAST_ALERT
|
||||
};
|
||||
|
||||
// add the alert's name to the ALERT_TYPES structure
|
||||
|
|
|
|||
|
|
@ -1187,6 +1187,7 @@
|
|||
});
|
||||
|
||||
deferred.done(function(user) {
|
||||
context.JK.currentUserFreeJamTrack = user.show_free_jamtrack
|
||||
window.UserActions.loaded(user)
|
||||
})
|
||||
|
||||
|
|
@ -1791,12 +1792,28 @@
|
|||
}
|
||||
|
||||
function addJamtrackToShoppingCart(options) {
|
||||
return $.ajax({
|
||||
var deferred = $.ajax({
|
||||
type: "POST",
|
||||
url: '/api/shopping_carts/add_jamtrack?' + $.param(options),
|
||||
dataType: "json",
|
||||
contentType: 'application/json'
|
||||
});
|
||||
|
||||
deferred.done(function(response) {
|
||||
window.UserActions.modify(response)
|
||||
})
|
||||
return deferred
|
||||
}
|
||||
|
||||
function addGiftCardToShoppingCart(options) {
|
||||
var deferred = $.ajax({
|
||||
type: "POST",
|
||||
url: '/api/shopping_carts/add_gift_card?' + $.param(options),
|
||||
dataType: "json",
|
||||
contentType: 'application/json'
|
||||
});
|
||||
|
||||
return deferred
|
||||
}
|
||||
|
||||
function getShoppingCarts() {
|
||||
|
|
@ -1810,12 +1827,17 @@
|
|||
}
|
||||
|
||||
function removeShoppingCart(options) {
|
||||
return $.ajax({
|
||||
var deferred = $.ajax({
|
||||
type: "DELETE",
|
||||
url: '/api/shopping_carts?' + $.param(options),
|
||||
dataType: "json",
|
||||
contentType: 'application/json'
|
||||
})
|
||||
|
||||
deferred.done(function(response) {
|
||||
window.UserActions.modify(response)
|
||||
})
|
||||
return deferred
|
||||
}
|
||||
|
||||
function clearShoppingCart(options) {
|
||||
|
|
@ -1986,6 +2008,17 @@
|
|||
});
|
||||
}
|
||||
|
||||
function redeemGiftCard(data) {
|
||||
var id = getId(data);
|
||||
return $.ajax({
|
||||
type: "POST",
|
||||
url: '/api/users/' + id + '/gift_cards',
|
||||
dataType: "json",
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify(data),
|
||||
});
|
||||
}
|
||||
|
||||
function portOverCarts() {
|
||||
return $.ajax({
|
||||
type: "POST",
|
||||
|
|
@ -2166,6 +2199,7 @@
|
|||
this.enqueueJamTrack = enqueueJamTrack;
|
||||
this.getBackingTracks = getBackingTracks;
|
||||
this.addJamtrackToShoppingCart = addJamtrackToShoppingCart;
|
||||
this.addGiftCardToShoppingCart = addGiftCardToShoppingCart;
|
||||
this.getShoppingCarts = getShoppingCarts;
|
||||
this.removeShoppingCart = removeShoppingCart;
|
||||
this.clearShoppingCart = clearShoppingCart;
|
||||
|
|
@ -2190,6 +2224,7 @@
|
|||
this.playJamTrack = playJamTrack;
|
||||
this.createSignupHint = createSignupHint;
|
||||
this.createAlert = createAlert;
|
||||
this.redeemGiftCard = redeemGiftCard;
|
||||
this.signup = signup;
|
||||
this.portOverCarts = portOverCarts;
|
||||
return this;
|
||||
|
|
|
|||
|
|
@ -1,484 +0,0 @@
|
|||
$ = jQuery
|
||||
context = window
|
||||
context.JK ||= {}
|
||||
|
||||
context.JK.JamTrackScreen=class JamTrackScreen
|
||||
LIMIT = 10
|
||||
instrument_logo_map = context.JK.getInstrumentIconMap24()
|
||||
|
||||
constructor: (@app) ->
|
||||
@EVENTS = context.JK.EVENTS
|
||||
@logger = context.JK.logger
|
||||
@screen = null
|
||||
@content = null
|
||||
@scroller = null
|
||||
@genre = null
|
||||
@artist = null
|
||||
@instrument = null
|
||||
@availability = null
|
||||
@nextPager = null
|
||||
@noMoreJamtracks = null
|
||||
@currentPage = 0
|
||||
@next = null
|
||||
@currentQuery = this.defaultQuery()
|
||||
@expanded = null
|
||||
@shownHelperBubbles = false
|
||||
|
||||
beforeShow:(data) =>
|
||||
this.setFilterFromURL()
|
||||
|
||||
if context.JK.currentUserId?
|
||||
@app.user().done((user) =>
|
||||
@user = user
|
||||
this.refresh()
|
||||
).fail((arg) =>
|
||||
@logger.error("app.user.done failed: " + JSON.stringify(arg))
|
||||
|
||||
@logger.debug(arg.statusCode);
|
||||
|
||||
throw 'fail should not occur if user is available'
|
||||
)
|
||||
else
|
||||
this.refresh()
|
||||
unless @shownHelperBubbles
|
||||
@shownHelperBubbles = true
|
||||
@startHelperBubbles()
|
||||
|
||||
afterShow:(data) =>
|
||||
context.JK.Tracking.jamtrackBrowseTrack(@app)
|
||||
|
||||
beforeHide: () =>
|
||||
this.clearCtaHelpTimeout()
|
||||
this.clearBandFilterHelpTimeout()
|
||||
this.clearMasterHelpTimeout()
|
||||
this.clearResults();
|
||||
|
||||
events:() =>
|
||||
@genre.on 'change', this.search
|
||||
@artist.on 'change', this.search
|
||||
@instrument.on 'change', this.search
|
||||
@availability.on 'change', this.search
|
||||
|
||||
clearResults:() =>
|
||||
@currentPage = 0
|
||||
@content.empty()
|
||||
@noMoreJamtracks.hide()
|
||||
@next = null
|
||||
|
||||
startHelperBubbles: () =>
|
||||
@showBandFilterHelpTimeout = setTimeout(@showBandFilterHelp, 3500)
|
||||
|
||||
showBandFilterHelp: () =>
|
||||
context.JK.HelpBubbleHelper.jamtrackBrowseBand(@artist.closest('.easydropdown-wrapper'), $('body'))
|
||||
|
||||
@showMasterHelpDueTime = new Date().getTime() + 11000 # 6000 ms for band tooltip to display, and 5 seconds of quiet time
|
||||
@scroller.on('scroll', @masterHelpScrollWatch)
|
||||
@scroller.on('scroll', @clearBubbles)
|
||||
@showMasterHelpTimeout = setTimeout(@showMasterHelp, @masterHelpDueTime())
|
||||
|
||||
clearBubbles: () =>
|
||||
if @helpBubble?
|
||||
@helpBubble.btOff()
|
||||
@helpBubble = null
|
||||
|
||||
# computes when we should show the master help bubble
|
||||
masterHelpDueTime: () =>
|
||||
dueTime = @showMasterHelpDueTime - new Date().getTime()
|
||||
if dueTime <= 0
|
||||
dueTime = 2000
|
||||
dueTime
|
||||
|
||||
|
||||
# computes when we should show the master help bubble
|
||||
ctaHelpDueTime: () =>
|
||||
dueTime = @showCtaHelpDueTime - new Date().getTime()
|
||||
if dueTime <= 0
|
||||
dueTime = 2000
|
||||
dueTime
|
||||
|
||||
# if the user scrolls, reset the master help due time
|
||||
masterHelpScrollWatch: () =>
|
||||
@clearMasterHelpTimeout()
|
||||
@showMasterHelpTimeout = setTimeout(@showMasterHelp, @masterHelpDueTime() + 2000)
|
||||
|
||||
# if the user scrolls, reset the master help due time
|
||||
ctaHelpScrollWatch: () =>
|
||||
@clearCtaHelpTimeout()
|
||||
@showCtaHelpTimeout = setTimeout(@showCtaHelp, @ctaHelpDueTime() + 2000)
|
||||
|
||||
|
||||
showCtaHelp: () =>
|
||||
@scroller.off('scroll', @ctaHelpScrollWatch)
|
||||
@clearCtaHelpTimeout()
|
||||
|
||||
cutoff = @scroller.offset().top;
|
||||
|
||||
@screen.find('.jamtrack-actions').each((i, element) =>
|
||||
$element = $(element)
|
||||
|
||||
if ($element.offset().top >= cutoff)
|
||||
@helpBubble = context.JK.HelpBubbleHelper.jamtrackBrowseCta($element, $('body'))
|
||||
return false
|
||||
else
|
||||
return true
|
||||
)
|
||||
|
||||
showMasterHelp: () =>
|
||||
@scroller.off('scroll', @masterHelpScrollWatch)
|
||||
@clearMasterHelpTimeout()
|
||||
|
||||
# don't show the help if the user has already clicked a preview
|
||||
unless @userPreviewed
|
||||
cutoff = @scroller.offset().top;
|
||||
|
||||
@screen.find('.jamtrack-preview[data-track-type="Master"]').each((i, element) =>
|
||||
$element = $(element)
|
||||
|
||||
if ($element.offset().top >= cutoff)
|
||||
@helpBubble = context.JK.HelpBubbleHelper.jamtrackBrowseMasterMix($element.find('.play-button'), $('body'))
|
||||
return false
|
||||
else
|
||||
return true
|
||||
)
|
||||
|
||||
@showCtaHelpDueTime = new Date().getTime() + 11000
|
||||
@scroller.on('scroll', @ctaHelpScrollWatch)
|
||||
@showCtaHelpTimeout = setTimeout(@showCtaHelp, @ctaHelpDueTime()) # 6000 ms for bubble show time, and 5000ms for delay
|
||||
|
||||
previewPlayed: () =>
|
||||
@userPreviewed = true
|
||||
|
||||
clearCtaHelpTimeout:() =>
|
||||
if @showCtaHelpTimeout?
|
||||
clearTimeout(@showCtaHelpTimeout)
|
||||
@showCtaHelpTimeout = null
|
||||
|
||||
clearBandFilterHelpTimeout: () =>
|
||||
if @showBandFilterHelpTimeout?
|
||||
clearTimeout(@showBandFilterHelpTimeout)
|
||||
@showBandFilterHelpTimeout = null
|
||||
|
||||
clearMasterHelpTimeout: () =>
|
||||
if @showMasterHelpTimeout?
|
||||
clearTimeout(@showMasterHelpTimeout)
|
||||
@showMasterHelpTimeout = null
|
||||
|
||||
setFilterFromURL:() =>
|
||||
# Grab parms from URL for artist, instrument, and availability
|
||||
parms=this.getParams()
|
||||
|
||||
if(parms.artist?)
|
||||
@artist.val(parms.artist)
|
||||
else
|
||||
@artist.val('')
|
||||
if(parms.instrument?)
|
||||
@instrument.val(parms.instrument)
|
||||
else
|
||||
@instrument.val('')
|
||||
if(parms.availability?)
|
||||
@availability.val(parms.availability)
|
||||
else
|
||||
@availability.val('')
|
||||
|
||||
if window.history.replaceState #ie9 proofing
|
||||
window.history.replaceState({}, "", "/client#/jamtrackBrowse")
|
||||
|
||||
getParams:() =>
|
||||
params = {}
|
||||
q = window.location.href.split("?")[1]
|
||||
if q?
|
||||
q = q.split('#')[0]
|
||||
raw_vars = q.split("&")
|
||||
for v in raw_vars
|
||||
[key, val] = v.split("=")
|
||||
params[key] = decodeURIComponent(val)
|
||||
params
|
||||
|
||||
setFilterState: (state) =>
|
||||
if state
|
||||
@genre.easyDropDown('enable').removeAttr('disabled')
|
||||
@artist.easyDropDown('enable').removeAttr('disabled')
|
||||
@instrument.easyDropDown('enable').removeAttr('disabled')
|
||||
@availability.easyDropDown('enable').removeAttr('disabled')
|
||||
else
|
||||
@genre.easyDropDown('disable').attr('disabled', 'disabled')
|
||||
@artist.easyDropDown('disable').attr('disabled', 'disabled')
|
||||
@instrument.easyDropDown('disable').attr('disabled', 'disabled')
|
||||
@availability.easyDropDown('disable').attr('disabled', 'disabled')
|
||||
|
||||
refresh:() =>
|
||||
this.clearResults()
|
||||
@currentQuery = this.buildQuery()
|
||||
that = this
|
||||
this.setFilterState(false)
|
||||
rest.getJamTracks(@currentQuery).done((response) =>
|
||||
that.handleJamtrackResponse(response)
|
||||
).fail( (jqXHR) =>
|
||||
that.clearResults()
|
||||
that.noMoreJamtracks.show()
|
||||
that.app.notifyServerError jqXHR, 'Jamtrack Unavailable'
|
||||
).always () =>
|
||||
that.setFilterState(true)
|
||||
|
||||
search:() =>
|
||||
this.refresh()
|
||||
false
|
||||
|
||||
defaultQuery:() =>
|
||||
query =
|
||||
per_page: LIMIT
|
||||
page: @currentPage+1
|
||||
if @next
|
||||
query.since = @next
|
||||
query
|
||||
|
||||
buildQuery:() =>
|
||||
@currentQuery = this.defaultQuery()
|
||||
# genre filter
|
||||
# var genres = @screen.find('#jamtrack_genre').val()
|
||||
# if (genres !== undefined) {
|
||||
# @currentQuery.genre = genres
|
||||
# }
|
||||
# instrument filter
|
||||
|
||||
instrument = @instrument.val()
|
||||
if instrument?
|
||||
@currentQuery.instrument = instrument
|
||||
|
||||
# artist filter
|
||||
art = @artist.val()
|
||||
if art?
|
||||
@currentQuery.artist = art
|
||||
|
||||
# availability filter
|
||||
availability = @availability.val()
|
||||
if availability?
|
||||
@currentQuery.availability = availability
|
||||
@currentQuery
|
||||
|
||||
handleJamtrackResponse:(response) =>
|
||||
@next = response.next
|
||||
this.renderJamtracks(response)
|
||||
if response.next == null
|
||||
# if we less results than asked for, end searching
|
||||
@scroller.infinitescroll 'pause'
|
||||
if @currentPage == 0 and response.jamtracks.length == 0
|
||||
@content.append '<td colspan="3" class="no-jamtracks-msg\'>No JamTracks found.</div>'
|
||||
if @currentPage > 0
|
||||
@noMoreJamtracks.show()
|
||||
# there are bugs with infinitescroll not removing the 'loading'.
|
||||
# it's most noticeable at the end of the list, so whack all such entries
|
||||
$('.infinite-scroll-loader').remove()
|
||||
else
|
||||
@currentPage++
|
||||
this.buildQuery()
|
||||
this.registerInfiniteScroll()
|
||||
|
||||
|
||||
registerInfiniteScroll:() =>
|
||||
that = this
|
||||
@scroller.infinitescroll {
|
||||
behavior: 'local'
|
||||
navSelector: '#jamtrackScreen .btn-next-pager'
|
||||
nextSelector: '#jamtrackScreen .btn-next-pager'
|
||||
binder: @scroller
|
||||
dataType: 'json'
|
||||
appendCallback: false
|
||||
prefill: false
|
||||
bufferPx: 100
|
||||
loading:
|
||||
msg: $('<div class="infinite-scroll-loader">Loading ...</div>')
|
||||
img: '/assets/shared/spinner.gif'
|
||||
path: (page) =>
|
||||
'/api/jamtracks?' + $.param(that.buildQuery())
|
||||
|
||||
}, (json, opts) =>
|
||||
this.handleJamtrackResponse(json)
|
||||
@scroller.infinitescroll 'resume'
|
||||
|
||||
playJamtrack:(e) =>
|
||||
e.preventDefault()
|
||||
|
||||
addToCartJamtrack:(e) =>
|
||||
e.preventDefault()
|
||||
$target = $(e.target)
|
||||
params = id: $target.attr('data-jamtrack-id')
|
||||
isFree = $(e.target).is('.is_free')
|
||||
|
||||
rest.addJamtrackToShoppingCart(params).done((response) =>
|
||||
if(isFree)
|
||||
if context.JK.currentUserId?
|
||||
context.JK.currentUserFreeJamTrack = true # make sure the user sees no more free notices
|
||||
context.location = '/client#/redeemComplete'
|
||||
else
|
||||
# now make a rest call to buy it
|
||||
context.location = '/client#/redeemSignup'
|
||||
|
||||
else
|
||||
context.location = '/client#/shoppingCart'
|
||||
|
||||
).fail @app.ajaxError
|
||||
|
||||
licenseUSWhy:(e) =>
|
||||
e.preventDefault()
|
||||
@app.layout.showDialog 'jamtrack-availability-dialog'
|
||||
|
||||
handleExpanded:(trackElement) =>
|
||||
jamTrack = trackElement.data('jamTrack')
|
||||
expanded = trackElement.data('expanded')
|
||||
expand = !expanded
|
||||
trackElement.data('expanded', expand)
|
||||
|
||||
detailArrow = trackElement.find('.jamtrack-detail-btn')
|
||||
|
||||
if expand
|
||||
trackElement.find('.extra').removeClass('hidden')
|
||||
detailArrow.html('hide tracks <a class="details-arrow arrow-up"></a>')
|
||||
for track in jamTrack.tracks
|
||||
trackElement.find("[jamtrack-track-id='#{track.id}']").removeClass('hidden')
|
||||
else
|
||||
trackElement.find('.extra').addClass('hidden')
|
||||
detailArrow.html('show all tracks <a class="details-arrow arrow-down"></a>')
|
||||
count = 0
|
||||
for track in jamTrack.tracks
|
||||
if count < 6
|
||||
trackElement.find("[jamtrack-track-id='#{track.id}']").removeClass('hidden')
|
||||
else
|
||||
trackElement.find("[jamtrack-track-id='#{track.id}']").addClass('hidden')
|
||||
count++
|
||||
|
||||
|
||||
registerEvents:(parent) =>
|
||||
#@screen.find('.jamtrack-detail-btn').on 'click', this.showJamtrackDescription
|
||||
parent.find('.play-button').on 'click', this.playJamtrack
|
||||
parent.find('.jamtrack-add-cart').on 'click', this.addToCartJamtrack
|
||||
parent.find('.license-us-why').on 'click', this.licenseUSWhy
|
||||
parent.find('.jamtrack-detail-btn').on 'click', this.toggleExpanded
|
||||
# @screen.find('.jamtrack-preview').each (index, element) =>
|
||||
# new JK.JamTrackPreview(data.app, $element, jamTrack, track, {master_shows_duration: true})
|
||||
|
||||
rerenderJamtracks:() =>
|
||||
if @currentData?
|
||||
@clearResults()
|
||||
@renderJamtracks(@currentData)
|
||||
false
|
||||
|
||||
computeWeight: (jam_track_track, instrument) =>
|
||||
weight = switch
|
||||
when jam_track_track.track_type == 'Master' then 0
|
||||
when jam_track_track.instrument?.id == instrument then 1 + jam_track_track.position
|
||||
else 10000 + jam_track_track.position
|
||||
|
||||
renderJamtracks:(data) =>
|
||||
@currentData = data
|
||||
that = this
|
||||
|
||||
for jamtrack in data.jamtracks
|
||||
jamtrackExpanded = this.expanded==jamtrack.id
|
||||
trackRow = _.clone(jamtrack)
|
||||
trackRow.track_cnt = jamtrack.tracks.length
|
||||
trackRow.tracks = []
|
||||
|
||||
# if an instrument is selected by the user, then re-order any jam tracks with a matching instrument to the top
|
||||
instrument = @instrument.val()
|
||||
if instrument?
|
||||
jamtrack.tracks.sort((a, b) =>
|
||||
aWeight = @computeWeight(a, instrument)
|
||||
bWeight = @computeWeight(b, instrument)
|
||||
return aWeight - bWeight
|
||||
)
|
||||
|
||||
for track in jamtrack.tracks
|
||||
trackRow.tracks.push(track)
|
||||
if track.track_type=='Master'
|
||||
track.instrument_desc = "Master"
|
||||
else
|
||||
inst = '../assets/content/icon_instrument_default24.png'
|
||||
if track.instrument?
|
||||
if track.instrument.id in instrument_logo_map
|
||||
inst = instrument_logo_map[track.instrument.id].asset
|
||||
track.instrument_desc = track.instrument.description
|
||||
track.instrument_url = inst
|
||||
|
||||
if track.part != ''
|
||||
track.instrument_desc += ' (' + track.part + ')'
|
||||
|
||||
free_state = if context.JK.currentUserFreeJamTrack then 'free' else 'non-free'
|
||||
|
||||
is_free = free_state == 'free'
|
||||
|
||||
options =
|
||||
jamtrack: trackRow
|
||||
expanded: false
|
||||
free_state: free_state,
|
||||
is_free: is_free
|
||||
@jamtrackItem = $(context._.template($('#template-jamtrack').html(), options, variable: 'data'))
|
||||
that.renderJamtrack(@jamtrackItem, jamtrack)
|
||||
that.registerEvents(@jamtrackItem)
|
||||
|
||||
|
||||
renderJamtrack:(jamtrackElement, jamTrack) =>
|
||||
jamtrackElement.data('jamTrack', jamTrack)
|
||||
jamtrackElement.data('expanded', true)
|
||||
|
||||
@content.append jamtrackElement
|
||||
|
||||
#if this.expanded==jamTrack.id
|
||||
for track in jamTrack.tracks
|
||||
trackRow = jamtrackElement.find("[jamtrack-track-id='#{track.id}']")
|
||||
previewElement = trackRow.find(".jamtrack-preview")
|
||||
preview = new JK.JamTrackPreview(@app, previewElement, jamTrack, track, {master_shows_duration: true, color:'gray'})
|
||||
$(preview).on(@EVENTS.PREVIEW_PLAYED, @previewPlayed)
|
||||
|
||||
this.handleExpanded(jamtrackElement, false)
|
||||
|
||||
showJamtrackDescription:(e) =>
|
||||
e.preventDefault()
|
||||
@description = $(e.target).parent('.detail-arrow').next()
|
||||
if @description.css('display') == 'none'
|
||||
@description.show()
|
||||
else
|
||||
@description.hide()
|
||||
|
||||
toggleExpanded:(e) =>
|
||||
e.preventDefault()
|
||||
jamtrackRecord = $(e.target).parents('.jamtrack-record')
|
||||
jamTrackId = jamtrackRecord.attr("jamtrack-id")
|
||||
|
||||
this.handleExpanded(jamtrackRecord)
|
||||
|
||||
initialize:() =>
|
||||
|
||||
screenBindings =
|
||||
'beforeShow': this.beforeShow
|
||||
'afterShow': this.afterShow
|
||||
'beforeHide' : this.beforeHide
|
||||
@app.bindScreen 'jamtrackBrowse', screenBindings
|
||||
@screen = $('#jamtrack-find-form')
|
||||
@scroller = @screen.find('.content-body-scroller')
|
||||
@content = @screen.find('.jamtrack-content')
|
||||
@genre = @screen.find('#jamtrack_genre')
|
||||
@artist = @screen.find('#jamtrack_artist')
|
||||
@instrument = @screen.find('#jamtrack_instrument')
|
||||
@availability = @screen.find('#jamtrack_availability')
|
||||
@nextPager = @screen.find('a.btn-next-pager')
|
||||
@noMoreJamtracks = @screen.find('.end-of-jamtrack-list')
|
||||
if @screen.length == 0
|
||||
throw new Error('@screen must be specified')
|
||||
if @scroller.length == 0
|
||||
throw new Error('@scroller must be specified')
|
||||
if @content.length == 0
|
||||
throw new Error('@content must be specified')
|
||||
if @noMoreJamtracks.length == 0
|
||||
throw new Error('@noMoreJamtracks must be specified')
|
||||
#if(@genre.length == 0) throw new Error("@genre must be specified")
|
||||
|
||||
if @artist.length == 0
|
||||
throw new Error('@artist must be specified')
|
||||
if @instrument.length == 0
|
||||
throw new Error('@instrument must be specified')
|
||||
#if @availability.length == 0
|
||||
# throw new Error('@availability must be specified')
|
||||
this.events()
|
||||
|
||||
|
||||
|
|
@ -1,80 +0,0 @@
|
|||
$ = jQuery
|
||||
context = window
|
||||
context.JK ||= {}
|
||||
|
||||
context.JK.JamTrackLanding = class JamTrackLanding
|
||||
constructor: (@app) ->
|
||||
@rest = context.JK.Rest()
|
||||
@client = context.jamClient
|
||||
@logger = context.JK.logger
|
||||
@screen = null
|
||||
@noFreeJamTrack = null
|
||||
@freeJamTrack = null
|
||||
@bandList = null
|
||||
@noBandsFound = null
|
||||
|
||||
initialize:() =>
|
||||
screenBindings =
|
||||
'beforeShow': @beforeShow
|
||||
'afterShow': @afterShow
|
||||
|
||||
#@app.bindScreen('jamtrackLanding', screenBindings)
|
||||
@screen = $('#jamtrackLanding')
|
||||
@noFreeJamTrack = @screen.find('.no-free-jamtrack')
|
||||
@freeJamTrack = @screen.find('.free-jamtrack')
|
||||
@bandList = @screen.find('#band_list')
|
||||
@noBandsFound = @screen.find('#no_bands_found')
|
||||
|
||||
beforeShow:() =>
|
||||
|
||||
@noFreeJamTrack.addClass('hidden')
|
||||
@freeJamTrack.addClass('hidden')
|
||||
|
||||
afterShow:() =>
|
||||
|
||||
if context.JK.currentUserId
|
||||
@app.user().done(@onUser)
|
||||
else
|
||||
@onUser({free_jamtrack: gon.global.one_free_jamtrack_per_user})
|
||||
|
||||
onUser:(user) =>
|
||||
if user.free_jamtrack
|
||||
@freeJamTrack.removeClass('hidden')
|
||||
else
|
||||
@noFreeJamTrack.removeClass('hidden')
|
||||
|
||||
# Get artist names and build links
|
||||
@rest.getJamTrackArtists({group_artist: true, per_page:100})
|
||||
.done(this.buildArtistLinks)
|
||||
.fail(this.handleFailure)
|
||||
|
||||
# Bind links to action that will open the jam_tracks list view filtered to given artist_name:
|
||||
# artist_name
|
||||
this.bindArtistLinks()
|
||||
|
||||
buildArtistLinks:(response) =>
|
||||
# Get artist names and build links
|
||||
@logger.debug("buildArtest links response", response)
|
||||
|
||||
artists = response.artists
|
||||
$("#band_list>li:not('#no_bands_found')").remove()
|
||||
if artists.length==0
|
||||
@noBandsFound.removeClass("hidden")
|
||||
else
|
||||
@noBandsFound.addClass("hidden")
|
||||
|
||||
# client#/jamtrack
|
||||
for artist in artists
|
||||
artistLink = "<a href='client?artist=#{encodeURIComponent(artist.original_artist)}#/jamtrack/search' class='artist-link' artist='#{artist.original_artist}'>#{artist.original_artist} (#{artist.song_count})</a>"
|
||||
@bandList.append("<li>#{artistLink}</li>")
|
||||
|
||||
# We don't want to do a full page load if this is clicked on here:
|
||||
bindArtistLinks:() =>
|
||||
that=this
|
||||
@bandList.on "click", "a.artist-link", (event)->
|
||||
context.location="client#/jamtrack/search"
|
||||
if window.history.replaceState # ie9 proofing
|
||||
window.history.replaceState({}, "", this.href)
|
||||
event.preventDefault()
|
||||
|
||||
handleFailure:(error) =>
|
||||
|
|
@ -1,670 +0,0 @@
|
|||
(function(context,$) {
|
||||
|
||||
"use strict";
|
||||
context.JK = context.JK || {};
|
||||
context.JK.OrderScreen = function(app) {
|
||||
|
||||
var EVENTS = context.JK.EVENTS;
|
||||
var logger = context.JK.logger;
|
||||
|
||||
var $screen = null;
|
||||
var $templateOrderContent = null;
|
||||
var $templatePurchasedJamTrack = null;
|
||||
var $navigation = null;
|
||||
var $billingInfo = null;
|
||||
var $shippingInfo = null;
|
||||
var $paymentMethod = null;
|
||||
var $shippingAddress = null;
|
||||
var $shippingAsBilling = null;
|
||||
var $paymentInfoPanel = null;
|
||||
var $orderPanel = null;
|
||||
var $thanksPanel = null;
|
||||
var $jamTrackInBrowser = null;
|
||||
var $purchasedJamTrack = null;
|
||||
var $purchasedJamTrackHeader = null;
|
||||
var $purchasedJamTracks = null;
|
||||
var $orderContent = null;
|
||||
var userDetail = null;
|
||||
var step = null;
|
||||
var billing_info = null;
|
||||
var shipping_info = null;
|
||||
var shipping_as_billing = null;
|
||||
var downloadJamTracks = [];
|
||||
var purchasedJamTracks = null;
|
||||
var purchasedJamTrackIterator = 0;
|
||||
|
||||
function beforeShow() {
|
||||
beforeShowPaymentInfo();
|
||||
resetJamTrackDownloadInfo();
|
||||
}
|
||||
|
||||
function beforeShowPaymentInfo() {
|
||||
step = 2;
|
||||
renderNavigation();
|
||||
renderAccountInfo();
|
||||
$("#order_error").addClass("hidden")
|
||||
}
|
||||
|
||||
function resetJamTrackDownloadInfo() {
|
||||
$purchasedJamTrack.addClass('hidden');
|
||||
$purchasedJamTracks.children().remove()
|
||||
$jamTrackInBrowser.hide('hidden');
|
||||
}
|
||||
|
||||
function renderAccountInfo() {
|
||||
rest.getUserDetail()
|
||||
.done(populateAccountInfo)
|
||||
.error(app.ajaxError);
|
||||
}
|
||||
|
||||
function populateAccountInfo(user) {
|
||||
userDetail = user;
|
||||
|
||||
if (userDetail.has_recurly_account) {
|
||||
rest.getBillingInfo()
|
||||
.done(function(response) {
|
||||
$billingInfo.find("#billing-first-name").val(response.first_name);
|
||||
$billingInfo.find("#billing-last-name").val(response.last_name);
|
||||
$billingInfo.find("#billing-address1").val(response.address1);
|
||||
$billingInfo.find("#billing-address2").val(response.address2);
|
||||
$billingInfo.find("#billing-city").val(response.city);
|
||||
$billingInfo.find("#billing-state").val(response.state);
|
||||
$billingInfo.find("#billing-zip").val(response.zip);
|
||||
$billingInfo.find("#billing-country").val(response.country);
|
||||
|
||||
$shippingAddress.find("#shipping-first-name").val(response.first_name);
|
||||
$shippingAddress.find("#shipping-last-name").val(response.last_name);
|
||||
$shippingAddress.find("#shipping-address1").val(response.address1);
|
||||
$shippingAddress.find("#shipping-address2").val(response.address2);
|
||||
$shippingAddress.find("#shipping-city").val(response.city);
|
||||
$shippingAddress.find("#shipping-state").val(response.state);
|
||||
$shippingAddress.find("#shipping-zip").val(response.zip);
|
||||
$shippingAddress.find("#shipping-country").val(response.country);
|
||||
})
|
||||
.error(app.ajaxError);
|
||||
}
|
||||
else {
|
||||
$billingInfo.find("#billing-first-name").val(userDetail.first_name);
|
||||
$billingInfo.find("#billing-last-name").val(userDetail.last_name);
|
||||
$billingInfo.find("#billing-city").val(userDetail.city);
|
||||
$billingInfo.find("#billing-state").val(userDetail.state);
|
||||
$billingInfo.find("#billing-country").val(userDetail.country);
|
||||
|
||||
$shippingAddress.find("#shipping-first-name").val(userDetail.first_name);
|
||||
$shippingAddress.find("#shipping-last-name").val(userDetail.last_name);
|
||||
$shippingAddress.find("#shipping-city").val(userDetail.city);
|
||||
$shippingAddress.find("#shipping-state").val(userDetail.state);
|
||||
$shippingAddress.find("#shipping-country").val(userDetail.country);
|
||||
}
|
||||
}
|
||||
|
||||
function afterShow(data) {
|
||||
// XXX : style-test code
|
||||
// moveToThanks({jam_tracks: [{id: 14, jam_track_right_id: 11, name: 'Back in Black'}, {id: 15, jam_track_right_id: 11, name: 'In Bloom'}, {id: 16, jam_track_right_id: 11, name: 'Love Bird Supreme'}]});
|
||||
}
|
||||
|
||||
function beforeHide() {
|
||||
if(downloadJamTracks) {
|
||||
context._.each(downloadJamTracks, function(downloadJamTrack) {
|
||||
downloadJamTrack.destroy();
|
||||
downloadJamTrack.root.remove();
|
||||
})
|
||||
|
||||
downloadJamTracks = [];
|
||||
}
|
||||
purchasedJamTracks = null;
|
||||
purchasedJamTrackIterator = 0;
|
||||
}
|
||||
|
||||
// TODO: Refactor: this function is long and fraught with many return points.
|
||||
function next(e) {
|
||||
e.preventDefault();
|
||||
$("#order_error").addClass("hidden")
|
||||
|
||||
// validation
|
||||
var billing_first_name = $billingInfo.find("#billing-first-name").val();
|
||||
var billing_last_name = $billingInfo.find("#billing-last-name").val();
|
||||
var billing_address1 = $billingInfo.find("#billing-address1").val();
|
||||
var billing_address2 = $billingInfo.find("#billing-address2").val();
|
||||
var billing_city = $billingInfo.find("#billing-city").val();
|
||||
var billing_state = $billingInfo.find("#billing-state").val();
|
||||
var billing_zip = $billingInfo.find("#billing-zip").val();
|
||||
var billing_country = $billingInfo.find("#billing-country").val();
|
||||
|
||||
if (!billing_first_name) {
|
||||
$billingInfo.find('#divBillingFirstName .error-text').remove();
|
||||
$billingInfo.find('#divBillingFirstName').addClass("error");
|
||||
$billingInfo.find('#billing-first-name').after("<ul class='error-text'><li>First Name is required</li></ul>");
|
||||
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
$billingInfo.find('#divBillingFirstName').removeClass("error");
|
||||
}
|
||||
|
||||
if (!billing_last_name) {
|
||||
$billingInfo.find('#divBillingLastName .error-text').remove();
|
||||
$billingInfo.find('#divBillingLastName').addClass("error");
|
||||
$billingInfo.find('#billing-last-name').after("<ul class='error-text'><li>Last Name is required</li></ul>");
|
||||
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
$billingInfo.find('#divBillingLastName').removeClass("error");
|
||||
}
|
||||
|
||||
if (!billing_address1) {
|
||||
$billingInfo.find('#divBillingAddress1 .error-text').remove();
|
||||
$billingInfo.find('#divBillingAddress1').addClass("error");
|
||||
$billingInfo.find('#billing-address1').after("<ul class='error-text'><li>Address is required</li></ul>");
|
||||
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
$billingInfo.find('#divBillingAddress1').removeClass("error");
|
||||
}
|
||||
|
||||
if (!billing_zip) {
|
||||
$billingInfo.find('#divBillingZip .error-text').remove();
|
||||
$billingInfo.find('#divBillingZip').addClass("error");
|
||||
$billingInfo.find('#billing-zip').after("<ul class='error-text'><li>Zip code is required</li></ul>");
|
||||
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
$billingInfo.find('#divBillingZip').removeClass("error");
|
||||
}
|
||||
|
||||
if (!billing_state) {
|
||||
$billingInfo.find('#divBillingState .error-text').remove();
|
||||
$billingInfo.find('#divBillingState').addClass("error");
|
||||
$billingInfo.find('#billing-zip').after("<ul class='error-text'><li>State is required</li></ul>");
|
||||
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
$billingInfo.find('#divBillingState').removeClass("error");
|
||||
}
|
||||
|
||||
if (!billing_city) {
|
||||
$billingInfo.find('#divBillingCity .error-text').remove();
|
||||
$billingInfo.find('#divBillingCity').addClass("error");
|
||||
$billingInfo.find('#billing-city').after("<ul class='error-text'><li>City is required</li></ul>");
|
||||
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
$billingInfo.find('#divBillingCity').removeClass("error");
|
||||
}
|
||||
|
||||
if (!billing_country) {
|
||||
$billingInfo.find('#divBillingCountry .error-text').remove();
|
||||
$billingInfo.find('#divBillingCountry').addClass("error");
|
||||
$billingInfo.find('#billing-country').after("<ul class='error-text'><li>Country is required</li></ul>");
|
||||
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
$billingInfo.find('#divBillingCountry').removeClass("error");
|
||||
}
|
||||
|
||||
shipping_as_billing = $shippingAsBilling.is(":checked");
|
||||
var shipping_first_name, shipping_last_name, shipping_address1, shipping_address2;
|
||||
var shipping_city, shipping_state, shipping_zip, shipping_country;
|
||||
|
||||
if (!shipping_as_billing) {
|
||||
shipping_first_name = $shippingAddress.find("#shipping-first-name").val();
|
||||
shipping_last_name = $shippingAddress.find("#shipping-last-name").val();
|
||||
shipping_address1 = $shippingAddress.find("#shipping-address1").val();
|
||||
shipping_address2 = $shippingAddress.find("#shipping-address2").val();
|
||||
shipping_city = $shippingAddress.find("#shipping-city").val();
|
||||
shipping_state = $shippingAddress.find("#shipping-state").val();
|
||||
shipping_zip = $shippingAddress.find("#shipping-zip").val();
|
||||
shipping_country = $shippingAddress.find("#shipping-country").val();
|
||||
|
||||
if (!shipping_first_name) {
|
||||
$shippingAddress.find('#divShippingFirstName .error-text').remove();
|
||||
$shippingAddress.find('#divShippingFirstName').addClass("error");
|
||||
$shippingAddress.find('#shipping-first-name').after("<ul class='error-text'><li>First Name is required</li></ul>");
|
||||
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
$shippingInfo.find('#divShippingFirstName').removeClass("error");
|
||||
}
|
||||
|
||||
if (!shipping_last_name) {
|
||||
$shippingAddress.find('#divShippingLastName .error-text').remove();
|
||||
$shippingAddress.find('#divShippingLastName').addClass("error");
|
||||
$shippingAddress.find('#shipping-last-name').after("<ul class='error-text'><li>Last Name is required</li></ul>");
|
||||
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
$shippingInfo.find('#divShippingLastName').removeClass("error");
|
||||
}
|
||||
|
||||
if (!shipping_address1) {
|
||||
$shippingAddress.find('#divShippingAddress1 .error-text').remove();
|
||||
$shippingAddress.find('#divShippingAddress1').addClass("error");
|
||||
$shippingAddress.find('#shipping-address1').after("<ul class='error-text'><li>Address is required</li></ul>");
|
||||
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
$shippingInfo.find('#divShippingAddress1').removeClass("error");
|
||||
}
|
||||
|
||||
if (!shipping_zip) {
|
||||
$shippingAddress.find('#divShippingZip .error-text').remove();
|
||||
$shippingAddress.find('#divShippingZip').addClass("error");
|
||||
$shippingAddress.find('#shipping-zip').after("<ul class='error-text'><li>Zip code is required</li></ul>");
|
||||
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
$shippingInfo.find('#divShippingZip').removeClass("error");
|
||||
}
|
||||
|
||||
if (!shipping_state) {
|
||||
$shippingAddress.find('#divShippingState .error-text').remove();
|
||||
$shippingAddress.find('#divShippingState').addClass("error");
|
||||
$shippingAddress.find('#shipping-zip').after("<ul class='error-text'><li>State is required</li></ul>");
|
||||
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
$shippingInfo.find('#divShippingState').removeClass("error");
|
||||
}
|
||||
|
||||
if (!shipping_city) {
|
||||
$shippingAddress.find('#divShippingCity .error-text').remove();
|
||||
$shippingAddress.find('#divShippingCity').addClass("error");
|
||||
$shippingAddress.find('#shipping-city').after("<ul class='error-text'><li>City is required</li></ul>");
|
||||
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
$shippingInfo.find('#divShippingCity').removeClass("error");
|
||||
}
|
||||
|
||||
if (!shipping_country) {
|
||||
$shippingAddress.find('#divShippingCountry .error-text').remove();
|
||||
$shippingAddress.find('#divShippingCountry').addClass("error");
|
||||
$shippingAddress.find('#shipping-country').after("<ul class='error-text'><li>Country is required</li></ul>");
|
||||
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
$shippingAddress.find('#divShippingCountry').removeClass("error");
|
||||
}
|
||||
}
|
||||
|
||||
var card_name = $paymentMethod.find("#card-name").val();
|
||||
var card_number = $paymentMethod.find("#card-number").val();
|
||||
var card_year = $paymentMethod.find("#card_expire-date_1i").val();
|
||||
var card_month = $paymentMethod.find("#card_expire-date_2i").val();
|
||||
var card_verify = $paymentMethod.find("#card-verify").val();
|
||||
|
||||
if (!card_name) {
|
||||
$paymentMethod.find('#divCardName .error-text').remove();
|
||||
$paymentMethod.find('#divCardName').addClass("error");
|
||||
$paymentMethod.find('#card-name').after("<ul class='error-text'><li>Card Name is required</li></ul>");
|
||||
return false;
|
||||
} else {
|
||||
$paymentMethod.find('#divCardName').removeClass("error");
|
||||
}
|
||||
|
||||
if (!card_number) {
|
||||
$paymentMethod.find('#divCardNumber .error-text').remove();
|
||||
$paymentMethod.find('#divCardNumber').addClass("error");
|
||||
$paymentMethod.find('#card-number').after("<ul class='error-text'><li>Card Number is required</li></ul>");
|
||||
return false;
|
||||
} else if (!$.payment.validateCardNumber(card_number)) {
|
||||
$paymentMethod.find('#divCardNumber .error-text').remove();
|
||||
$paymentMethod.find('#divCardNumber').addClass("error");
|
||||
$paymentMethod.find('#card-number').after("<ul class='error-text'><li>Card Number is not valid</li></ul>");
|
||||
return false;
|
||||
} else {
|
||||
$paymentMethod.find('#divCardNumber').removeClass("error");
|
||||
}
|
||||
|
||||
if (!$.payment.validateCardExpiry(card_month, card_year)) {
|
||||
$paymentMethod.find('#divCardExpiry .error-text').remove();
|
||||
$paymentMethod.find('#divCardExpiry').addClass("error");
|
||||
$paymentMethod.find('#card-expiry').after("<ul class='error-text'><li>Card Number is not valid</li></ul>");
|
||||
} else {
|
||||
$paymentMethod.find('#divCardExpiry').removeClass("error");
|
||||
}
|
||||
|
||||
if (!card_verify) {
|
||||
$paymentMethod.find('#divCardVerify .error-text').remove();
|
||||
$paymentMethod.find('#divCardVerify').addClass("error");
|
||||
$paymentMethod.find('#card-verify').after("<ul class='error-text'><li>Card Verification Value is required</li></ul>");
|
||||
|
||||
return false;
|
||||
} else if(!$.payment.validateCardCVC(card_verify)) {
|
||||
$paymentMethod.find('#divCardVerify .error-text').remove();
|
||||
$paymentMethod.find('#divCardVerify').addClass("error");
|
||||
$paymentMethod.find('#card-verify').after("<ul class='error-text'><li>Card Verification Value is not valid.</li></ul>");
|
||||
|
||||
return false;
|
||||
} else {
|
||||
$paymentMethod.find('#divCardVerify').removeClass("error");
|
||||
}
|
||||
|
||||
billing_info = {};
|
||||
shipping_info = {};
|
||||
billing_info.first_name = billing_first_name;
|
||||
billing_info.last_name = billing_last_name;
|
||||
billing_info.address1 = billing_address1;
|
||||
billing_info.address2 = billing_address2;
|
||||
billing_info.city = billing_city;
|
||||
billing_info.state = billing_state;
|
||||
billing_info.country = billing_country;
|
||||
billing_info.zip = billing_zip;
|
||||
billing_info.number = card_number;
|
||||
billing_info.month = card_month;
|
||||
billing_info.year = card_year;
|
||||
billing_info.verification_value = card_verify;
|
||||
|
||||
if (shipping_as_billing) {
|
||||
shipping_info = $.extend({},billing_info);
|
||||
delete shipping_info.number;
|
||||
delete shipping_info.month;
|
||||
delete shipping_info.year;
|
||||
delete shipping_info.verification_value;
|
||||
} else {
|
||||
shipping_info.first_name = shipping_first_name;
|
||||
shipping_info.last_name = shipping_last_name;
|
||||
shipping_info.address1 = shipping_address1;
|
||||
shipping_info.address2 = shipping_address2;
|
||||
shipping_info.city = shipping_city;
|
||||
shipping_info.state = shipping_state;
|
||||
shipping_info.country = shipping_country;
|
||||
shipping_info.zip = shipping_zip;
|
||||
}
|
||||
|
||||
$paymentInfoPanel.find("#payment-info-next").addClass("disabled");
|
||||
$paymentInfoPanel.find("#payment-info-next").off("click");
|
||||
|
||||
rest.createRecurlyAccount({billing_info: billing_info})
|
||||
.done(function() {
|
||||
moveToOrder();
|
||||
$paymentInfoPanel.find("#payment-info-next").removeClass("disabled");
|
||||
$paymentInfoPanel.find("#payment-info-next").on("click", next);
|
||||
})
|
||||
.fail(errorHandling);
|
||||
}
|
||||
|
||||
function errorHandling(xhr, ajaxOptions, thrownError) {
|
||||
$.each(xhr.responseJSON.errors, function(key, error) {
|
||||
if (key == 'number') {
|
||||
$paymentMethod.find('#divCardNumber .error-text').remove();
|
||||
$paymentMethod.find('#divCardNumber').addClass("error");
|
||||
$paymentMethod.find('#card-number').after("<ul class='error-text'><li>" + error + "</li></ul>");
|
||||
}
|
||||
else if (key == 'verification_value') {
|
||||
$paymentMethod.find('#divCardVerify .error-text').remove();
|
||||
$paymentMethod.find('#divCardVerify').addClass("error");
|
||||
$paymentMethod.find('#card-verify').after("<ul class='error-text'><li>" + error + "</li></ul>");
|
||||
}
|
||||
});
|
||||
|
||||
$paymentInfoPanel.find("#payment-info-next").addClass("disabled");
|
||||
$paymentInfoPanel.find("#payment-info-next").on('click', next);
|
||||
}
|
||||
|
||||
function orderErrorHandling(xhr, ajaxOptions, thrownError) {
|
||||
var message = "Error submitting payment: "
|
||||
$.each(xhr.responseJSON.errors, function(key, error) {
|
||||
message += key + ": " + error
|
||||
})
|
||||
$("#order_error").text(message)
|
||||
$("#order_error").removeClass("hidden")
|
||||
$orderContent.find(".place-order").on('click', placeOrder)
|
||||
}
|
||||
|
||||
function beforeShowOrder() {
|
||||
step = 3;
|
||||
renderNavigation();
|
||||
populateOrderPage();
|
||||
}
|
||||
|
||||
function clearOrderPage() {
|
||||
$orderContent.empty();
|
||||
}
|
||||
|
||||
function populateOrderPage() {
|
||||
clearOrderPage();
|
||||
|
||||
rest.getShoppingCarts()
|
||||
.done(renderOrderPage)
|
||||
.fail(app.ajaxError);
|
||||
}
|
||||
|
||||
function renderOrderPage(carts) {
|
||||
var data = {}
|
||||
|
||||
var sub_total = 0.0
|
||||
var taxes = 0.0
|
||||
$.each(carts, function(index, cart) {
|
||||
sub_total += parseFloat(cart.product_info.price) * parseFloat(cart.quantity)
|
||||
});
|
||||
data.grand_total = (sub_total + taxes).toFixed(2)
|
||||
data.sub_total = sub_total.toFixed(2)
|
||||
data.taxes = taxes.toFixed(2)
|
||||
data.carts = carts
|
||||
data.billing_info = billing_info
|
||||
data.shipping_info = shipping_info
|
||||
data.shipping_as_billing = shipping_as_billing
|
||||
var orderContentHtml = $(
|
||||
context._.template(
|
||||
$templateOrderContent.html(),
|
||||
data,
|
||||
{variable: 'data'}
|
||||
)
|
||||
)
|
||||
|
||||
$orderContent.append(orderContentHtml)
|
||||
|
||||
$orderPanel.find(".change-payment-info").on('click', moveToPaymentInfo)
|
||||
$orderContent.find(".place-order").on('click', placeOrder)
|
||||
}
|
||||
|
||||
function moveToOrder() {
|
||||
$paymentInfoPanel.addClass("hidden");
|
||||
$orderPanel.removeClass("hidden");
|
||||
beforeShowOrder();
|
||||
}
|
||||
|
||||
function moveToThanks(purchaseResponse) {
|
||||
$("#order_error").addClass("hidden")
|
||||
$paymentInfoPanel.addClass("hidden")
|
||||
$orderPanel.addClass("hidden")
|
||||
$thanksPanel.removeClass("hidden")
|
||||
rest.clearShoppingCart()
|
||||
beforeShowOrder()
|
||||
handleJamTracksPurchased(purchaseResponse.jam_tracks)
|
||||
}
|
||||
|
||||
function handleJamTracksPurchased(jamTracks) {
|
||||
// were any JamTracks purchased?
|
||||
var jamTracksPurchased = jamTracks && jamTracks.length > 0;
|
||||
if(jamTracksPurchased) {
|
||||
if(gon.isNativeClient) {
|
||||
startDownloadJamTracks(jamTracks)
|
||||
}
|
||||
else {
|
||||
$jamTrackInBrowser.removeClass('hidden');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function startDownloadJamTracks(jamTracks) {
|
||||
// there can be multiple purchased JamTracks, so we cycle through them
|
||||
|
||||
purchasedJamTracks = jamTracks;
|
||||
|
||||
// populate list of jamtracks purchased, that we will iterate through graphically
|
||||
context._.each(jamTracks, function(jamTrack) {
|
||||
var downloadJamTrack = new context.JK.DownloadJamTrack(app, jamTrack, 'small');
|
||||
var $purchasedJamTrack = $(context._.template(
|
||||
$templatePurchasedJamTrack.html(),
|
||||
jamTrack,
|
||||
{variable: 'data'}
|
||||
));
|
||||
|
||||
$purchasedJamTracks.append($purchasedJamTrack)
|
||||
|
||||
// show it on the page
|
||||
$purchasedJamTrack.append(downloadJamTrack.root)
|
||||
|
||||
downloadJamTracks.push(downloadJamTrack)
|
||||
})
|
||||
|
||||
iteratePurchasedJamTracks();
|
||||
}
|
||||
|
||||
function iteratePurchasedJamTracks() {
|
||||
if(purchasedJamTrackIterator < purchasedJamTracks.length ) {
|
||||
var downloadJamTrack = downloadJamTracks[purchasedJamTrackIterator++];
|
||||
|
||||
// make sure the 'purchasing JamTrack' section can be seen
|
||||
$purchasedJamTrack.removeClass('hidden');
|
||||
|
||||
// the widget indicates when it gets to any transition; we can hide it once it reaches completion
|
||||
$(downloadJamTrack).on(EVENTS.JAMTRACK_DOWNLOADER_STATE_CHANGED, function(e, data) {
|
||||
|
||||
if(data.state == downloadJamTrack.states.synchronized) {
|
||||
logger.debug("jamtrack " + downloadJamTrack.jamTrack.name + " synchronized;")
|
||||
//downloadJamTrack.root.remove();
|
||||
downloadJamTrack.destroy();
|
||||
|
||||
// go to the next JamTrack
|
||||
iteratePurchasedJamTracks()
|
||||
}
|
||||
})
|
||||
|
||||
logger.debug("jamtrack " + downloadJamTrack.jamTrack.name + " downloader initializing")
|
||||
|
||||
// kick off the download JamTrack process
|
||||
downloadJamTrack.init()
|
||||
|
||||
// XXX style-test code
|
||||
// downloadJamTrack.transitionError("package-error", "The server failed to create your package.")
|
||||
|
||||
}
|
||||
else {
|
||||
logger.debug("done iterating over purchased JamTracks")
|
||||
$purchasedJamTrackHeader.text('All purchased JamTracks have been downloaded successfully! You can now play them in a session.')
|
||||
}
|
||||
}
|
||||
|
||||
function moveToPaymentInfo(e) {
|
||||
e.preventDefault();
|
||||
$paymentInfoPanel.removeClass("hidden");
|
||||
$orderPanel.addClass("hidden");
|
||||
beforeShowPaymentInfo();
|
||||
}
|
||||
|
||||
function toggleShippingAsBilling(e) {
|
||||
e.preventDefault();
|
||||
|
||||
var shipping_as_billing = $(e.target).is(':checked');
|
||||
|
||||
if (!shipping_as_billing) {
|
||||
$shippingAddress.removeClass("hidden");
|
||||
}
|
||||
else {
|
||||
$shippingAddress.addClass("hidden");
|
||||
}
|
||||
}
|
||||
|
||||
function placeOrder(e) {
|
||||
e.preventDefault();
|
||||
$orderContent.find(".place-order").off('click')
|
||||
rest.getShoppingCarts()
|
||||
.done(function(carts) {
|
||||
var jam_track_ids = _.map(carts, function(cart){
|
||||
return cart.product_info.product_id
|
||||
})
|
||||
rest.placeOrder({jam_tracks: jam_track_ids})
|
||||
.done(moveToThanks)
|
||||
.fail(orderErrorHandling);
|
||||
}
|
||||
).fail(app.ajaxError);
|
||||
}
|
||||
|
||||
function events() {
|
||||
$paymentInfoPanel.find("#payment-info-next").on('click', next);
|
||||
$shippingAsBilling.on('ifChanged', toggleShippingAsBilling);
|
||||
}
|
||||
|
||||
function reset() {
|
||||
}
|
||||
|
||||
function renderNavigation() {
|
||||
$navigation.html("");
|
||||
var navigationHtml = $(
|
||||
context._.template(
|
||||
$('#template-checkout-navigation').html(),
|
||||
{current: step},
|
||||
{variable: 'data'}
|
||||
)
|
||||
);
|
||||
|
||||
$navigation.append(navigationHtml);
|
||||
}
|
||||
|
||||
function initializeControls() {
|
||||
$("form.payment-info").iCheck({
|
||||
checkboxClass: 'icheckbox_minimal',
|
||||
radioClass: 'iradio_minimal',
|
||||
inheritClass: true
|
||||
});
|
||||
|
||||
// Use jquery.payment to limit characters and length:
|
||||
$paymentMethod.find("#card-number").payment('formatCardNumber');
|
||||
$paymentMethod.find("#card-verify").payment('formatCardCVC');
|
||||
}
|
||||
|
||||
function initialize() {
|
||||
var screenBindings = {
|
||||
'beforeShow': beforeShow,
|
||||
'afterShow': afterShow,
|
||||
'beforeHide' : beforeHide
|
||||
};
|
||||
app.bindScreen('order', screenBindings);
|
||||
|
||||
$screen = $("#orderScreen");
|
||||
$templateOrderContent = $("#template-order-content");
|
||||
$templatePurchasedJamTrack = $('#template-purchased-jam-track');
|
||||
$paymentInfoPanel = $screen.find(".checkout-payment-info");
|
||||
$orderPanel = $screen.find(".order-panel");
|
||||
$thanksPanel = $screen.find(".thanks-panel");
|
||||
$jamTrackInBrowser = $screen.find(".thanks-detail.jam-tracks-in-browser");
|
||||
$purchasedJamTrack = $thanksPanel.find(".thanks-detail.purchased-jam-track");
|
||||
$purchasedJamTrackHeader = $purchasedJamTrack.find(".purchased-jam-track-header");
|
||||
$purchasedJamTracks = $purchasedJamTrack.find(".purchased-list")
|
||||
$navigation = $screen.find(".checkout-navigation-bar");
|
||||
$billingInfo = $paymentInfoPanel.find(".billing-address");
|
||||
$shippingInfo = $paymentInfoPanel.find(".shipping-address");
|
||||
$paymentMethod = $paymentInfoPanel.find(".payment-method");
|
||||
$shippingAddress = $paymentInfoPanel.find(".shipping-address-detail");
|
||||
$shippingAsBilling = $paymentInfoPanel.find("#shipping-as-billing");
|
||||
$orderContent = $orderPanel.find(".order-content");
|
||||
|
||||
if($screen.length == 0) throw "$screen must be specified";
|
||||
if($navigation.length == 0) throw "$navigation must be specified";
|
||||
|
||||
initializeControls();
|
||||
|
||||
events();
|
||||
}
|
||||
|
||||
this.initialize = initialize;
|
||||
|
||||
return this;
|
||||
}
|
||||
})(window,jQuery);
|
||||
|
|
@ -4,17 +4,11 @@ MIX_MODES = context.JK.MIX_MODES
|
|||
|
||||
@JamTrackFilterScreen = React.createClass({
|
||||
|
||||
mixins: [Reflux.listenTo(@AppStore,"onAppInit")]
|
||||
mixins: [Reflux.listenTo(@AppStore,"onAppInit"), Reflux.listenTo(@UserStore,"onUserChanged")]
|
||||
|
||||
LIMIT: 20
|
||||
instrument_logo_map: context.JK.getInstrumentIconMap24()
|
||||
|
||||
computeWeight: (jam_track_track, instrument) ->
|
||||
weight = switch
|
||||
when jam_track_track.track_type == 'Master' then 0
|
||||
when jam_track_track.instrument?.id == instrument then 1 + jam_track_track.position
|
||||
else 10000 + jam_track_track.position
|
||||
|
||||
render: () ->
|
||||
|
||||
searchText = if @state.first_search then 'SEARCH' else 'SEARCH AGAIN'
|
||||
|
|
@ -36,19 +30,21 @@ MIX_MODES = context.JK.MIX_MODES
|
|||
)
|
||||
|
||||
for track in jamtrack.tracks
|
||||
trackRow.tracks.push(track)
|
||||
if track.track_type=='Master'
|
||||
track.instrument_desc = "Master"
|
||||
else
|
||||
inst = '../assets/content/icon_instrument_default24.png'
|
||||
if track.instrument?
|
||||
if track.instrument.id in @instrument_logo_map
|
||||
inst = @instrument_logo_map[track.instrument.id].asset
|
||||
track.instrument_desc = track.instrument.description
|
||||
track.instrument_url = inst
|
||||
|
||||
if track.part != ''
|
||||
track.instrument_desc += ' (' + track.part + ')'
|
||||
if track.track_type == 'Master' || track.track_type == 'Track'
|
||||
trackRow.tracks.push(track)
|
||||
if track.track_type == 'Master'
|
||||
track.instrument_desc = "Master"
|
||||
else if track.track_type == 'Track'
|
||||
inst = '../assets/content/icon_instrument_default24.png'
|
||||
if track.instrument?
|
||||
if track.instrument.id in @instrument_logo_map
|
||||
inst = @instrument_logo_map[track.instrument.id].asset
|
||||
track.instrument_desc = track.instrument.description
|
||||
track.instrument_url = inst
|
||||
|
||||
if track.part != ''
|
||||
track.instrument_desc += ' (' + track.part + ')'
|
||||
|
||||
trackRow.free_state = if @state.is_free then 'free' else 'non-free'
|
||||
|
||||
|
|
@ -76,10 +72,10 @@ MIX_MODES = context.JK.MIX_MODES
|
|||
</div>`
|
||||
|
||||
actionBtn = null
|
||||
if jamtrack.is_free
|
||||
actionBtn = `<a className="jamtrack-add-cart button-orange is_free" href="#" data-jamtrack-id={jamtrack.id}> GET IT FREE!</a>`
|
||||
else if jamtrack.purchased
|
||||
if jamtrack.purchased
|
||||
actionBtn = `<a className="jamtrack-add-cart-disabled button-grey button-disabled" href="javascript:void(0)">PURCHASED</a>`
|
||||
else if jamtrack.is_free
|
||||
actionBtn = `<a className="jamtrack-add-cart button-orange is_free" href="#" data-jamtrack-id={jamtrack.id}> GET IT FREE!</a>`
|
||||
else if jamtrack.added_cart
|
||||
actionBtn = `<a className="jamtrack-add-cart-disabled button-grey button-disabled" href="client#/shoppingCart">ALREADY IN CART</a>`
|
||||
else
|
||||
|
|
@ -158,15 +154,13 @@ MIX_MODES = context.JK.MIX_MODES
|
|||
</div>
|
||||
</div>`
|
||||
|
||||
|
||||
getInitialState: () ->
|
||||
{search: '', type: 'user-input', jamtracks:[], show_all_artists: false, currentPage: 0, next: null, searching: false, count: 0, is_free: context.JK.currentUserFreeJamTrack}
|
||||
|
||||
|
||||
clearResults:() ->
|
||||
#@content.empty()
|
||||
#@noMoreJamtracks.hide()
|
||||
@setState({currentPage: 0, next: null, jamtracks:[], type: 'user-input', searching:false, is_free: context.JK.currentUserFreeJamTrack})
|
||||
@setState({currentPage: 0, next: null, jamtracks:[], type: 'user-input', searching:false, is_free: @user.show_free_jamtrack})
|
||||
|
||||
getInitialState: () ->
|
||||
{search: '', type: 'user-input', jamtracks:[], show_all_artists: false, currentPage: 0, next: null, searching: false, count: 0, is_free: context.JK.currentUserFreeJamTrack}
|
||||
|
||||
|
||||
defaultQuery:(extra) ->
|
||||
|
|
@ -305,16 +299,21 @@ MIX_MODES = context.JK.MIX_MODES
|
|||
isFree = $(e.target).is('.is_free')
|
||||
|
||||
@rest.addJamtrackToShoppingCart(params).done((response) =>
|
||||
if(isFree)
|
||||
if context.JK.currentUserId?
|
||||
context.JK.currentUserFreeJamTrack = true # make sure the user sees no more free notices
|
||||
context.location = '/client#/redeemComplete'
|
||||
if context.JK.currentUserId?
|
||||
if isFree
|
||||
if @user.has_redeemable_jamtrack
|
||||
# this is the 1st jamtrack; let's user the user to completion
|
||||
context.location = '/client#/redeemComplete'
|
||||
else
|
||||
# this is must be a user's gifted jamtrack, to treat them normally in that they'll go to the shopping cart
|
||||
#context.location = '/client#/shoppingCart'
|
||||
context.location = '/client#/redeemComplete'
|
||||
else
|
||||
# now make a rest call to buy it
|
||||
context.location = '/client#/redeemSignup'
|
||||
|
||||
# this user has nothing free; so send them to shopping cart
|
||||
context.location = '/client#/shoppingCart'
|
||||
else
|
||||
context.location = '/client#/shoppingCart'
|
||||
# user not logged in; make them signup
|
||||
context.location = '/client#/redeemSignup'
|
||||
|
||||
).fail(() => @app.ajaxError)
|
||||
|
||||
|
|
@ -398,4 +397,15 @@ MIX_MODES = context.JK.MIX_MODES
|
|||
'afterShow': @afterShow
|
||||
|
||||
@app.bindScreen('jamtrack/filter', screenBindings)
|
||||
|
||||
onUserChanged: (userState) ->
|
||||
@user = userState?.user
|
||||
@setState({is_free: @user?.show_free_jamtrack})
|
||||
|
||||
computeWeight: (jam_track_track, instrument) ->
|
||||
weight = switch
|
||||
when jam_track_track.track_type == 'Master' then 0
|
||||
when jam_track_track.instrument?.id == instrument then 1 + jam_track_track.position
|
||||
else 10000 + jam_track_track.position
|
||||
|
||||
})
|
||||
|
|
@ -13,12 +13,13 @@ rest = context.JK.Rest()
|
|||
{user: null, purchasedJamTracks: []}
|
||||
|
||||
onUserChanged: (userState) ->
|
||||
@user = userState?.user
|
||||
@onUser(userState.user) if userState.user
|
||||
|
||||
render: () ->
|
||||
|
||||
howTo = null
|
||||
if @state.user?.free_jamtrack
|
||||
if @user?.purchased_jamtracks_count == 0 && @user?.has_redeemable_jamtrack
|
||||
howTo =
|
||||
`<div className="free-jamtrack">
|
||||
<span>
|
||||
|
|
@ -206,11 +207,6 @@ rest = context.JK.Rest()
|
|||
|
||||
@processUrl()
|
||||
|
||||
if !context.JK.currentUserId
|
||||
@onUser({free_jamtrack: context.JK.currentUserFreeJamTrack})
|
||||
|
||||
|
||||
|
||||
beforeShow: () ->
|
||||
@setState({user: null})
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ MIX_MODES = context.JK.MIX_MODES
|
|||
|
||||
@JamTrackSearchScreen = React.createClass({
|
||||
|
||||
mixins: [Reflux.listenTo(@AppStore,"onAppInit")]
|
||||
mixins: [Reflux.listenTo(@AppStore,"onAppInit"), Reflux.listenTo(@UserStore,"onUserChanged")]
|
||||
|
||||
LIMIT: 10
|
||||
instrument_logo_map: context.JK.getInstrumentIconMap24()
|
||||
|
|
@ -35,19 +35,22 @@ MIX_MODES = context.JK.MIX_MODES
|
|||
)
|
||||
###
|
||||
for track in jamtrack.tracks
|
||||
trackRow.tracks.push(track)
|
||||
if track.track_type=='Master'
|
||||
track.instrument_desc = "Master"
|
||||
else
|
||||
inst = '../assets/content/icon_instrument_default24.png'
|
||||
if track.instrument?
|
||||
if track.instrument.id in @instrument_logo_map
|
||||
inst = @instrument_logo_map[track.instrument.id].asset
|
||||
track.instrument_desc = track.instrument.description
|
||||
track.instrument_url = inst
|
||||
|
||||
if track.part != ''
|
||||
track.instrument_desc += ' (' + track.part + ')'
|
||||
if track.track_type == 'Master' || track.track_type == 'Track'
|
||||
trackRow.tracks.push(track)
|
||||
|
||||
if track.track_type == 'Master'
|
||||
track.instrument_desc = "Master"
|
||||
else if track.track_type == 'Track'
|
||||
inst = '../assets/content/icon_instrument_default24.png'
|
||||
if track.instrument?
|
||||
if track.instrument.id in @instrument_logo_map
|
||||
inst = @instrument_logo_map[track.instrument.id].asset
|
||||
track.instrument_desc = track.instrument.description
|
||||
track.instrument_url = inst
|
||||
|
||||
if track.part != ''
|
||||
track.instrument_desc += ' (' + track.part + ')'
|
||||
|
||||
trackRow.free_state = if @state.is_free then 'free' else 'non-free'
|
||||
|
||||
|
|
@ -91,10 +94,10 @@ MIX_MODES = context.JK.MIX_MODES
|
|||
</div>`
|
||||
|
||||
actionBtn = null
|
||||
if jamtrack.is_free
|
||||
actionBtn = `<a className="jamtrack-add-cart button-orange is_free" href="#" data-jamtrack-id={jamtrack.id}> GET IT FREE!</a>`
|
||||
else if jamtrack.purchased
|
||||
if jamtrack.purchased
|
||||
actionBtn = `<a className="jamtrack-add-cart-disabled button-grey button-disabled" href="javascript:void(0)">PURCHASED</a>`
|
||||
else if jamtrack.is_free
|
||||
actionBtn = `<a className="jamtrack-add-cart button-orange is_free" href="#" data-jamtrack-id={jamtrack.id}> GET IT FREE!</a>`
|
||||
else if jamtrack.added_cart
|
||||
actionBtn = `<a className="jamtrack-add-cart-disabled button-grey button-disabled" href="client#/shoppingCart">ALREADY IN CART</a>`
|
||||
else
|
||||
|
|
@ -219,14 +222,13 @@ MIX_MODES = context.JK.MIX_MODES
|
|||
|
||||
|
||||
clearResults:() ->
|
||||
@setState({currentPage: 0, next: null, show_all_artists: false, artists:[], jamtracks:[], type: 'user-input', searching:false, artist: null, song:null, is_free: context.JK.currentUserFreeJamTrack, first_search: true})
|
||||
@setState({currentPage: 0, next: null, show_all_artists: false, artists:[], jamtracks:[], type: 'user-input', searching:false, artist: null, song:null, is_free: @user.show_free_jamtrack, first_search: true})
|
||||
|
||||
|
||||
getInitialState: () ->
|
||||
{search: '', type: 'user-input', artists:[], jamtracks:[], show_all_artists: false, currentPage: 0, next: null, searching: false, first_search: true, count: 0, is_free: context.JK.currentUserFreeJamTrack}
|
||||
|
||||
onSelectChange: (val) ->
|
||||
#@logger.debug("CHANGE #{val}")
|
||||
|
||||
return false unless val?
|
||||
|
||||
|
|
@ -435,18 +437,39 @@ MIX_MODES = context.JK.MIX_MODES
|
|||
isFree = $(e.target).is('.is_free')
|
||||
|
||||
@rest.addJamtrackToShoppingCart(params).done((response) =>
|
||||
if(isFree)
|
||||
if context.JK.currentUserId?
|
||||
context.JK.currentUserFreeJamTrack = true # make sure the user sees no more free notices
|
||||
context.location = '/client#/redeemComplete'
|
||||
if context.JK.currentUserId?
|
||||
if isFree
|
||||
if @user.has_redeemable_jamtrack
|
||||
# this is the 1st jamtrack; let's user the user to completion
|
||||
context.location = '/client#/redeemComplete'
|
||||
else
|
||||
# this is must be a user's gifted jamtrack, to treat them normally in that they'll go to the shopping cart
|
||||
#context.location = '/client#/shoppingCart'
|
||||
context.location = '/client#/redeemComplete'
|
||||
else
|
||||
# now make a rest call to buy it
|
||||
context.location = '/client#/redeemSignup'
|
||||
|
||||
# this user has nothing free; so send them to shopping cart
|
||||
context.location = '/client#/shoppingCart'
|
||||
else
|
||||
context.location = '/client#/shoppingCart'
|
||||
if isFree
|
||||
# user not logged in; make them signup
|
||||
context.location = '/client#/redeemSignup'
|
||||
else
|
||||
# this user has nothing free; so send them to shopping cart
|
||||
context.location = '/client#/shoppingCart'
|
||||
|
||||
).fail(() => @app.ajaxError)
|
||||
|
||||
).fail(((jqxhr) =>
|
||||
|
||||
handled = false
|
||||
if jqxhr.status == 422
|
||||
body = JSON.parse(jqxhr.responseText)
|
||||
if body.errors && body.errors.base
|
||||
handled = true
|
||||
context.JK.Banner.showAlert("You can not have a mix of free and non-free items in your shopping cart.<br/><br/>If you want to add this new item to your shopping cart, then clear out all current items by clicking on the shopping cart icon and clicking 'delete' next to each item.")
|
||||
if !handled
|
||||
@app.ajaxError(arguments[0], arguments[1], arguments[2])
|
||||
|
||||
))
|
||||
|
||||
licenseUSWhy:(e) ->
|
||||
e.preventDefault()
|
||||
|
|
@ -510,6 +533,9 @@ MIX_MODES = context.JK.MIX_MODES
|
|||
if search?
|
||||
performSearch = true
|
||||
@search(search.searchType, search.searchData)
|
||||
else
|
||||
if !@state.first_search
|
||||
@search(@state.type, window.JamTrackSearchInput)
|
||||
|
||||
if performSearch
|
||||
if window.history.replaceState #ie9 proofing
|
||||
|
|
@ -517,11 +543,6 @@ MIX_MODES = context.JK.MIX_MODES
|
|||
|
||||
|
||||
beforeShow: () ->
|
||||
@setState({is_free: context.JK.currentUserFreeJamTrack})
|
||||
if !@state.first_search
|
||||
@search(@state.type, window.JamTrackSearchInput)
|
||||
|
||||
|
||||
|
||||
onAppInit: (@app) ->
|
||||
|
||||
|
|
@ -530,10 +551,14 @@ MIX_MODES = context.JK.MIX_MODES
|
|||
@rest = context.JK.Rest()
|
||||
@logger = context.JK.logger
|
||||
|
||||
|
||||
screenBindings =
|
||||
'beforeShow': @beforeShow
|
||||
'afterShow': @afterShow
|
||||
|
||||
@app.bindScreen('jamtrack/search', screenBindings)
|
||||
|
||||
onUserChanged: (userState) ->
|
||||
@user = userState?.user
|
||||
@setState({is_free: @user?.show_free_jamtrack})
|
||||
|
||||
})
|
||||
|
|
@ -32,6 +32,11 @@ mixins.push(Reflux.listenTo(JamTrackPlayerStore, 'onJamTrackPlayerStoreChanged')
|
|||
|
||||
mixins: mixins
|
||||
|
||||
computeWeight: (jam_track_track) ->
|
||||
weight = switch
|
||||
when jam_track_track.track_type == 'Master' then 0
|
||||
when jam_track_track.track_type == 'Click' then 10000
|
||||
else jam_track_track.position
|
||||
|
||||
onJamTrackPlayerStoreChanged: (changes) ->
|
||||
#logger.debug("PopupMediaControls: jamtrack changed", changes)
|
||||
|
|
@ -222,9 +227,16 @@ mixins.push(Reflux.listenTo(JamTrackPlayerStore, 'onJamTrackPlayerStoreChanged')
|
|||
|
||||
active = jamTrack.last_stem_id?
|
||||
trackOptions = []
|
||||
for track in jamTrack.tracks
|
||||
if track.track_type == 'Track'
|
||||
|
||||
jamTrack.tracks.sort((a, b) =>
|
||||
aWeight = @computeWeight(a)
|
||||
bWeight = @computeWeight(b)
|
||||
return aWeight - bWeight
|
||||
)
|
||||
|
||||
|
||||
for track in jamTrack.tracks
|
||||
if track.track_type == 'Track' || track.track_type == 'Click'
|
||||
|
||||
if track.instrument
|
||||
instrumentId = track.instrument.id
|
||||
|
|
@ -239,7 +251,6 @@ mixins.push(Reflux.listenTo(JamTrackPlayerStore, 'onJamTrackPlayerStoreChanged')
|
|||
boundStemPlayClick = this.downloadStem.bind(this)
|
||||
boundStemChange = this.stemChanged.bind(this)
|
||||
|
||||
console.log("jamTrack.lastStemId", jamTrack.last_stem_id)
|
||||
myMixdowns.push `
|
||||
<div key={track.id} className={classNames({'stem-track' : true, 'mixdown-display': true, 'active' : active})}>
|
||||
<div className="mixdown-name">
|
||||
|
|
@ -267,8 +278,12 @@ mixins.push(Reflux.listenTo(JamTrackPlayerStore, 'onJamTrackPlayerStoreChanged')
|
|||
tracks = []
|
||||
if jamTrack?
|
||||
for track in jamTrack.tracks
|
||||
if track.track_type == 'Track'
|
||||
if track.instrument
|
||||
if track.track_type == 'Track' || track.track_type == 'Click'
|
||||
if track.track_type == 'Click'
|
||||
instrumentId = track.instrument.id
|
||||
instrumentDescription = 'Clicktrack'
|
||||
part = ''
|
||||
else if track.instrument
|
||||
instrumentId = track.instrument.id
|
||||
instrumentDescription = track.instrument.description
|
||||
if track.part? && track.part != instrumentDescription
|
||||
|
|
@ -280,9 +295,17 @@ mixins.push(Reflux.listenTo(JamTrackPlayerStore, 'onJamTrackPlayerStoreChanged')
|
|||
tracks.push(`
|
||||
<tr className="stem">
|
||||
<td><img src={context.JK.getInstrumentIcon24(instrumentId)} className="instrument-icon" /> {instrumentDescription} {part}</td>
|
||||
<td className="mute"><input type="checkbox" className="stem-mute" data-stem-id={track.id} /></td>
|
||||
<td className="mute"><input type="checkbox" className="stem-mute" data-stem-id={track.id} defaultChecked={track.track_type == 'Click'}/></td>
|
||||
</tr>`)
|
||||
|
||||
if jamTrack?.jmep?.Events? && jamTrack.jmep.Events[0].metronome?
|
||||
# tap-in detected; show user tap-in option
|
||||
tracks.push(`
|
||||
<tr className="stem">
|
||||
<td><img src={context.JK.getInstrumentIcon24('computer')} className="instrument-icon" /> Count-in</td>
|
||||
<td className="mute"><input type="checkbox" className="stem-mute" data-stem-id="count-in" /></td>
|
||||
</tr>`)
|
||||
|
||||
stems = `<div key="stems" className="stems">
|
||||
<table>
|
||||
<thead>
|
||||
|
|
@ -632,6 +655,7 @@ mixins.push(Reflux.listenTo(JamTrackPlayerStore, 'onJamTrackPlayerStoreChanged')
|
|||
else
|
||||
pitch = parseInt(pitch)
|
||||
|
||||
count_in = false
|
||||
|
||||
# get mute state of all tracks
|
||||
$mutes = $(@getDOMNode()).find('.stems .stem .stem-mute')
|
||||
|
|
@ -642,10 +666,13 @@ mixins.push(Reflux.listenTo(JamTrackPlayerStore, 'onJamTrackPlayerStoreChanged')
|
|||
stemId = $mute.attr('data-stem-id')
|
||||
muted = $mute.is(':checked')
|
||||
|
||||
tracks.push({id: stemId, mute: muted})
|
||||
if stemId == 'count-in'
|
||||
count_in = !muted
|
||||
else
|
||||
tracks.push({id: stemId, mute: muted})
|
||||
)
|
||||
|
||||
mixdown = {jamTrackID: @state.jamTrackState.jamTrack.id, name: name, settings: {speed:speed, pitch: pitch, tracks:tracks}}
|
||||
mixdown = {jamTrackID: @state.jamTrackState.jamTrack.id, name: name, settings: {speed:speed, pitch: pitch, "count-in": count_in, tracks:tracks}}
|
||||
|
||||
JamTrackPlayerActions.createMixdown(mixdown, @createMixdownDone, @createMixdownFail)
|
||||
|
||||
|
|
|
|||
|
|
@ -248,7 +248,7 @@ mixins.push(Reflux.listenTo(JamTrackStore, 'onJamTrackChanged'))
|
|||
|
||||
trackOptions = []
|
||||
for track in jamTrack.tracks
|
||||
if track.track_type == 'Track'
|
||||
if track.track_type == 'Track' || track.track_type == 'Click'
|
||||
|
||||
if track.instrument
|
||||
instrumentId = track.instrument.id
|
||||
|
|
|
|||
|
|
@ -276,8 +276,7 @@ ChannelGroupIds = context.JK.ChannelGroupIds
|
|||
# All the JamTracks
|
||||
mediaTracks.push(`<SessionJamTrackCategory key="JamTrackCategory" jamTrackName={this.state.jamTrackName} mixers={this.state.mediaCategoryMixer} mode={MIX_MODES.PERSONAL} />`)
|
||||
|
||||
# show metronome only if it's a full jamtrack
|
||||
if @state.metronome? && @state.jamTrackMixdown.id == null
|
||||
if @state.metronome? # && @state.jamTrackMixdown.id == null
|
||||
@state.metronome.mode = MIX_MODES.PERSONAL
|
||||
mediaTracks.push(`<SessionMetronome key="JamTrackMetronome" {...this.state.metronome} location="jam-track" />`)
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
context = window
|
||||
|
||||
@ConfigureTracksActions = Reflux.createActions({
|
||||
reset: {}
|
||||
trySave: {}
|
||||
midiScan: {}
|
||||
vstScan: {}
|
||||
vstScanComplete: {}
|
||||
clearVsts: {}
|
||||
cancelEdit: {}
|
||||
deleteTrack: {}
|
||||
updateOutputs: {}
|
||||
showAddNewTrack: {}
|
||||
showEditTrack: {}
|
||||
showEditOutputs: {}
|
||||
showVstSettings: {}
|
||||
associateInputsWithTrack: {}
|
||||
associateInstrumentWithTrack: {}
|
||||
associateVSTWithTrack: {}
|
||||
associateMIDIWithTrack: {}
|
||||
desiredTrackType: {}
|
||||
})
|
||||
|
|
@ -2,5 +2,6 @@ context = window
|
|||
|
||||
@UserActions = Reflux.createActions({
|
||||
loaded: {}
|
||||
modify: {}
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -402,6 +402,9 @@ MIX_MODES = context.JK.MIX_MODES;
|
|||
else
|
||||
trackName = instrumentName
|
||||
|
||||
if jamTrack.track_type == 'Click'
|
||||
trackName = 'Clicktrack'
|
||||
|
||||
data =
|
||||
name: jamTrackName
|
||||
trackName: trackName
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ context = window
|
|||
jamTracks: () ->
|
||||
if @session && @session.jam_track
|
||||
@session.jam_track.tracks.filter((track)->
|
||||
track.track_type == 'Track'
|
||||
track.track_type == 'Track' || track.track_type == 'Click'
|
||||
)
|
||||
else
|
||||
null
|
||||
|
|
|
|||
|
|
@ -0,0 +1,94 @@
|
|||
context = window
|
||||
rest = context.JK.Rest()
|
||||
|
||||
@GiftCardLandingPage = React.createClass({
|
||||
|
||||
render: () ->
|
||||
|
||||
if this.state.done
|
||||
ctaButtonText10 = 'sending you in...'
|
||||
ctaButtonText20 = 'sending you in...'
|
||||
else if this.state.processing
|
||||
ctaButtonText10 = 'hold on...'
|
||||
ctaButtonText20 = 'hold on...'
|
||||
else
|
||||
ctaButtonText10 = `<span>ADD $10 CARD<br/>TO CART</span>`
|
||||
ctaButtonText20 = `<span>ADD $20 CARD<br/>TO CART</span>`
|
||||
|
||||
|
||||
ctaButtons =
|
||||
`<div className="cta-buttons">
|
||||
<button className={classNames({'five-jt': true, 'gift-card': true, 'cta-button' : true, 'processing': this.state.processing})} onClick={this.ctaClick.bind(this, 5)}>{ctaButtonText10}</button>
|
||||
<button className={classNames({'ten-jt': true, 'gift-card': true, 'cta-button' : true, 'processing': this.state.processing})} onClick={this.ctaClick.bind(this, 10)}>{ctaButtonText20}</button>
|
||||
</div>`
|
||||
|
||||
|
||||
`<div className="top-container">
|
||||
<div className="full-row name-and-artist">
|
||||
<div>
|
||||
<img className="gift-card-preview" width="300" height="191" src="/assets/landing/gift_card.png" alt="gift card "/>
|
||||
<h1 className="jam-track-name">$10 or $20 JAMTRACKS GIFT CARDS</h1>
|
||||
<h2 className="original-artist">A PERFECT GIFT FOR THE HOLIDAYS</h2>
|
||||
<div className="clearall"/>
|
||||
</div>
|
||||
<div className="preview-and-action-box">
|
||||
<img src="/assets/landing/jamtrack_landing_arrow_1.png" className="arrow1" />
|
||||
<img src="/assets/landing/jamtrack_landing_arrow_2.png" className="arrow2" />
|
||||
<div className="preview-jamtrack-header gift-card">
|
||||
Preview A JamTrack
|
||||
<div className="jamtrack-title">"{this.props.jam_track.name}"</div>
|
||||
</div>
|
||||
<div className={classNames({'preview-area': true, 'gift-card': true})}>
|
||||
<p>Click the play buttons below to preview the master mix and 20-second samples of all the isolated tracks.</p>
|
||||
<div className="tracks previews">
|
||||
|
||||
</div>
|
||||
<p className="gift-getter">
|
||||
Get a $10 gift card (good for 5 songs) or a $20 gift card (good for 10 songs), and your happy
|
||||
gift card getter can choose their favorites from our catalog of 3,700+ popular songs.
|
||||
</p>
|
||||
{ctaButtons}
|
||||
<a className="browse-all" href="/client?search=#/jamtrack/search">or browse our catalog of 3,700+ songs</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row summary-text">
|
||||
<p className="top-summary">
|
||||
JamTracks by JamKazam are the best way to play along with your favorite songs. Far better and different than traditional
|
||||
backing tracks, our JamTracks are complete multi-track professional recordings, with fully isolated tracks for each part of the music.
|
||||
And our free app and Internet service are packed with features that give you unmatched creative freedom to learn, practice, record, play with others, and share your performances.
|
||||
</p>
|
||||
</div>
|
||||
</div>`
|
||||
|
||||
getInitialState: () ->
|
||||
{processing:false}
|
||||
|
||||
componentDidMount:() ->
|
||||
$root = $(this.getDOMNode())
|
||||
|
||||
# add item to cart, create the user if necessary, and then place the order to get the free JamTrack.
|
||||
ctaClick: (card_type, e) ->
|
||||
e.preventDefault()
|
||||
|
||||
return if @state.processing
|
||||
|
||||
loggedIn = context.JK.currentUserId?
|
||||
|
||||
rest.addGiftCardToShoppingCart({id: card_type}).done((response) =>
|
||||
|
||||
if loggedIn
|
||||
@setState({done: true})
|
||||
context.location = '/client#/shoppingCart'
|
||||
else
|
||||
@setState({done: true})
|
||||
context.location = '/client#/shoppingCart'
|
||||
|
||||
).fail((jqXHR, textStatus, errorMessage) =>
|
||||
if jqXHR.status == 422
|
||||
errors = JSON.parse(jqXHR.responseText)
|
||||
cart_errors = errors?.errors?.cart_id
|
||||
context.JK.app.ajaxError(jqXHR, textStatus, errorMessage)
|
||||
@setState({processing:false})
|
||||
)
|
||||
})
|
||||
|
|
@ -119,10 +119,9 @@ rest = context.JK.Rest()
|
|||
isFree = context.JK.currentUserFreeJamTrack
|
||||
|
||||
|
||||
rest.addJamtrackToShoppingCart({id: @props.jam_track.id}).done((response) =>
|
||||
rest.addJamtrackToShoppingCart({id: @props.jam_track.id, clear:true}).done((response) =>
|
||||
if isFree
|
||||
if loggedIn
|
||||
context.JK.currentUserFreeJamTrack = true # make sure the user sees no more free notices
|
||||
@setState({done: true})
|
||||
context.location = '/client?redeemed_flow=1#/jamtrack'
|
||||
else
|
||||
|
|
|
|||
|
|
@ -0,0 +1,159 @@
|
|||
context = window
|
||||
rest = context.JK.Rest()
|
||||
ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;
|
||||
|
||||
@RedeemGiftCardPage = React.createClass({
|
||||
|
||||
render: () ->
|
||||
|
||||
|
||||
if this.state.formErrors?
|
||||
for key, value of this.state.formErrors
|
||||
break
|
||||
|
||||
errorText = context.JK.getFullFirstError(key, @state.formErrors, {email: 'Email', password: 'Password', gift_card: 'Gift Card Code', 'terms_of_service' : 'The terms of service'})
|
||||
|
||||
buttonClassnames = classNames({'redeem-giftcard': true, 'button-orange': true, disabled: @state.processing || @state.done })
|
||||
|
||||
if @state.done
|
||||
button =
|
||||
`<div key="done" className="done-action">
|
||||
<div>You have {this.state.gifted_jamtracks} free JamTracks on your account!</div>
|
||||
<div>You can now <a className="go-browse" href="/client#/jamtrack">browse our collection</a> and redeem them.</div>
|
||||
</div>`
|
||||
else
|
||||
button = `<button key="button" className={buttonClassnames} onClick={this.action}>REDEEM GIFT CARD</button>`
|
||||
|
||||
action = `<ReactCSSTransitionGroup transitionName="session-track-list">
|
||||
{button}
|
||||
</ReactCSSTransitionGroup>`
|
||||
|
||||
|
||||
if context.JK.currentUserId?
|
||||
form =
|
||||
`<form onSubmit={this.submit}>
|
||||
<label>Gift Card Code:</label><input type="text" name="code"/>
|
||||
{action}
|
||||
</form>`
|
||||
instruments = `<p className="instructions">Enter the code from the back of your gift card to associate it with your account.</p>`
|
||||
else
|
||||
form =
|
||||
`<form onSubmit={this.submit}>
|
||||
<label>Gift Card Code:</label><input type="text" name="code"/>
|
||||
<label>Email:</label><input type="text" name="email"/>
|
||||
<label>Password:</label><input type="password" name="password"/>
|
||||
<div className="clearall"/>
|
||||
<input className="terms-checkbox" type="checkbox" name="terms" /><label className="terms-help">I have read and agree to the JamKazam <a href="/corp/terms" onClick={this.termsClicked}>terms of service</a></label>
|
||||
<div className="clearall"/>
|
||||
{action}
|
||||
</form>`
|
||||
instruments = `<p className="instructions">Enter the code from the back of your gift card to associate it with your new JamKazam account.</p>`
|
||||
|
||||
|
||||
classes = classNames({'redeem-container': true, 'not-logged-in': !context.JK.currentUserId?, 'logged-in': context.JK.currentUserId? })
|
||||
`<div className={classes}>
|
||||
<div className="redeem-content">
|
||||
<h2>Redeem Your Gift Card</h2>
|
||||
{instruments}
|
||||
{form}
|
||||
<div className={classNames({'errors': true, 'active': this.state.formErrors})}>
|
||||
{errorText}
|
||||
</div>
|
||||
</div>
|
||||
</div>`
|
||||
|
||||
getInitialState: () ->
|
||||
{formErrors: null, processing:false, gifted_jamtracks: null}
|
||||
|
||||
privacyPolicy: (e) ->
|
||||
e.preventDefault()
|
||||
|
||||
context.JK.popExternalLink('/corp/privacy')
|
||||
|
||||
termsClicked: (e) ->
|
||||
e.preventDefault()
|
||||
|
||||
context.JK.popExternalLink('/corp/terms')
|
||||
|
||||
componentDidMount:() ->
|
||||
$root = $(this.getDOMNode())
|
||||
$checkbox = $root.find('.terms-checkbox')
|
||||
console.log("$checkbox", $checkbox)
|
||||
context.JK.checkbox($checkbox)
|
||||
|
||||
submit: (e) ->
|
||||
@action(e)
|
||||
action: (e) ->
|
||||
|
||||
if @state.done || @state.processing
|
||||
e.preventDefault()
|
||||
return
|
||||
|
||||
if context.JK.currentUserId?
|
||||
@redeem(e)
|
||||
else
|
||||
@signup(e)
|
||||
|
||||
redeem: (e) ->
|
||||
e.preventDefault()
|
||||
return if @state.done || @state.processing
|
||||
|
||||
$root = $(@getDOMNode())
|
||||
$code = $root.find('input[name="code"]')
|
||||
code = $code.val()
|
||||
|
||||
rest.redeemGiftCard({gift_card: code})
|
||||
.done((response) =>
|
||||
|
||||
@setState({formErrors: null, processing:false, done: true, gifted_jamtracks: response.gifted_jamtracks})
|
||||
|
||||
).fail((jqXHR) =>
|
||||
@setState({processing:false})
|
||||
|
||||
if jqXHR.status == 422
|
||||
response = JSON.parse(jqXHR.responseText)
|
||||
if response.errors
|
||||
@setState({formErrors: response.errors})
|
||||
else
|
||||
context.JK.app.notify({title: 'Unknown Error', text: jqXHR.responseText})
|
||||
else
|
||||
context.JK.app.notifyServerError(jqXHR, "Unable to Redeem Giftcard")
|
||||
)
|
||||
|
||||
signup: (e) ->
|
||||
e.preventDefault()
|
||||
|
||||
return if @state.done || @state.processing
|
||||
|
||||
$root = $(@getDOMNode())
|
||||
$email = $root.find('input[name="email"]')
|
||||
$code = $root.find('input[name="code"]')
|
||||
$password = $root.find('input[name="password"]')
|
||||
terms = $root.find('input[name="terms"]').is(':checked')
|
||||
|
||||
@setState({processing:true})
|
||||
email = $email.val()
|
||||
password = $password.val()
|
||||
code = $code.val()
|
||||
if !code
|
||||
# must pass up non-null value to indicate user is trying to redeem giftcard while creating account
|
||||
code = ''
|
||||
|
||||
rest.signup({email: email, password: password, gift_card: code, terms: terms})
|
||||
.done((response) =>
|
||||
|
||||
@setState({formErrors: null, processing:false, done: true, gifted_jamtracks: response.gifted_jamtracks})
|
||||
|
||||
).fail((jqXHR) =>
|
||||
@setState({processing:false})
|
||||
|
||||
if jqXHR.status == 422
|
||||
response = JSON.parse(jqXHR.responseText)
|
||||
if response.errors
|
||||
@setState({formErrors: response.errors})
|
||||
else
|
||||
context.JK.app.notify({title: 'Unknown Signup Error', text: jqXHR.responseText})
|
||||
else
|
||||
context.JK.app.notifyServerError(jqXHR, "Unable to Sign Up")
|
||||
)
|
||||
})
|
||||
|
|
@ -135,7 +135,7 @@ JamTrackActions = @JamTrackActions
|
|||
@trackDetail = context.jamClient.JamTrackGetTrackDetail (fqId)
|
||||
|
||||
if @trackDetail.version?
|
||||
logger.error("after invalidating package, the version is still wrong!")
|
||||
logger.error("after invalidating package, the version is still wrong!", @trackDetail.version)
|
||||
throw "after invalidating package, the version is still wrong!"
|
||||
|
||||
if @jamTrack.activeMixdown.client_state == 'cant_open'
|
||||
|
|
@ -165,6 +165,20 @@ JamTrackActions = @JamTrackActions
|
|||
# JamTrackPlay means 'load'
|
||||
logger.debug("JamTrackStore: loading mixdown")
|
||||
context.jamClient.JamTrackStopPlay();
|
||||
|
||||
if @jamTrack.jmep
|
||||
|
||||
if @jamTrack.activeMixdown.settings.speed?
|
||||
@jamTrack.jmep.speed = @jamTrack.activeMixdown.settings.speed
|
||||
else
|
||||
@jamTrack.jmep.speed = 0
|
||||
|
||||
logger.debug("setting jmep data. speed:" + @jamTrack.jmep.speed)
|
||||
|
||||
context.jamClient.JamTrackLoadJmep(fqId, @jamTrack.jmep)
|
||||
else
|
||||
logger.debug("no jmep data for jamtrack")
|
||||
|
||||
result = context.jamClient.JamTrackPlay(fqId);
|
||||
if !result
|
||||
@jamTrack.activeMixdown.client_state = 'cant_open'
|
||||
|
|
|
|||
|
|
@ -8,10 +8,24 @@ logger = context.JK.logger
|
|||
|
||||
listenables: @UserActions
|
||||
|
||||
init: ->
|
||||
this.listenTo(context.AppStore, this.onAppInit)
|
||||
|
||||
onAppInit: (@app) ->
|
||||
@loadAnonymousUser()
|
||||
|
||||
loadAnonymousUser: () ->
|
||||
@user = {id: null, has_redeemable_jamtrack: context.JK.currentUserFreeJamTrack, purchased_jamtracks_count:0, show_free_jamtrack: context.JK.currentUserFreeJamTrack }
|
||||
@changed()
|
||||
|
||||
onLoaded:(user) ->
|
||||
@user = user
|
||||
@changed()
|
||||
|
||||
onModify: (changes) ->
|
||||
@user = $.extend({}, @user, changes)
|
||||
@changed()
|
||||
|
||||
changed:() ->
|
||||
@trigger({user: @user})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ BackendToFrontend = {
|
|||
}
|
||||
|
||||
BackendToFrontendFPS = {
|
||||
|
||||
0: 30,
|
||||
1: 24,
|
||||
2: 20,
|
||||
|
|
@ -140,6 +139,11 @@ BackendToFrontendFPS = {
|
|||
@state.videoShared = @videoShared
|
||||
this.trigger(@state)
|
||||
|
||||
onBringVideoToFront: ->
|
||||
if @videoShared
|
||||
@logger.debug("BringVideoToFront")
|
||||
context.jamClient.BringVideoWindowToFront();
|
||||
|
||||
onTestVideo: () ->
|
||||
|
||||
return unless context.jamClient.testVideoRender?
|
||||
|
|
@ -150,7 +154,7 @@ BackendToFrontendFPS = {
|
|||
|
||||
onToggleVideo: () ->
|
||||
if @videoShared
|
||||
@onStopVideo()
|
||||
@onBringVideoToFront()
|
||||
else
|
||||
@onStartVideo()
|
||||
|
||||
|
|
|
|||
|
|
@ -273,6 +273,7 @@
|
|||
function handleRecordingStopped(recordingId, result) {
|
||||
|
||||
if(recordingId == "video") {
|
||||
// comes from VideoRecordingStopped
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -324,6 +325,16 @@
|
|||
function handleRecordingAborted(recordingId, result) {
|
||||
|
||||
if(recordingId == "video") {
|
||||
|
||||
// comes from AbortedVideoRecording
|
||||
recordingId = result;
|
||||
if (arguments.length == 2) {
|
||||
result = arguments[2]
|
||||
}
|
||||
logger.debug("video recording aborted", result)
|
||||
context.JK.Banner.showAlert("Video has stopped recording. Audio is still recording.")
|
||||
//context.RecordingActions.stopRecording()
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,11 +31,6 @@
|
|||
|
||||
|
||||
function beforeShow() {
|
||||
|
||||
}
|
||||
|
||||
function afterShow(data) {
|
||||
|
||||
context.JK.Tracking.redeemCompleteTrack()
|
||||
|
||||
$noPurchasesPrompt.addClass('hidden')
|
||||
|
|
@ -44,6 +39,10 @@
|
|||
$purchasedJamTrackHeader.attr('status', 'in-progress')
|
||||
$jamTrackInBrowser.addClass('hidden')
|
||||
$jamTrackInClient.addClass('hidden')
|
||||
}
|
||||
|
||||
function afterShow(data) {
|
||||
|
||||
|
||||
|
||||
// if there is no current user, but it apperas we have a login cookie, just refresh
|
||||
|
|
@ -59,23 +58,19 @@
|
|||
|
||||
function handleShoppingCartResponse(carts) {
|
||||
|
||||
if(!checkoutUtils.hasOneFreeItemInShoppingCart(carts)) {
|
||||
if(!checkoutUtils.hasOnlyFreeItemsInShoppingCart(carts)) {
|
||||
// the user has multiple items in their shopping cart. They shouldn't be here.
|
||||
logger.error("invalid access of redeemComplete page")
|
||||
window.location = '/client#/jamtrack/search'
|
||||
}
|
||||
else {
|
||||
// ok, we have one, free item. save it for
|
||||
shoppingCartItem = carts[0];
|
||||
|
||||
rest.placeOrder()
|
||||
.done(function(purchaseResponse) {
|
||||
context.JK.currentUserFreeJamTrack = false // make sure the user sees no more free notices without having to do a full page refresh
|
||||
rest.updateUser()
|
||||
|
||||
checkoutUtils.setLastPurchase(purchaseResponse)
|
||||
jamTrackUtils.checkShoppingCart()
|
||||
//app.refreshUser() // this only causes grief in tests for some reason, and with currentUserFreeJamTrack = false above, this is probably now unnecessary
|
||||
|
||||
prepThanks();
|
||||
})
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@
|
|||
else if(carts.length > 1) {
|
||||
// the user has multiple items in their shopping cart. They shouldn't be here.
|
||||
logger.error("invalid access of redeemJamTrack page; multiple")
|
||||
window.location = '/client#/jamtrack/search'
|
||||
window.location = '/client#/shoppingCart'
|
||||
}
|
||||
else {
|
||||
var item = carts[0];
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
var $screen = null;
|
||||
var $content = null;
|
||||
var totalCost = 0;
|
||||
|
||||
function beforeShow(data) {
|
||||
clearContent();
|
||||
|
|
@ -30,7 +31,7 @@
|
|||
function proceedCheckout(e) {
|
||||
e.preventDefault();
|
||||
|
||||
if (context.JK.currentUserFreeJamTrack) {
|
||||
if (totalCost == 0) {
|
||||
if(context.JK.currentUserId) {
|
||||
logger.debug("proceeding to redeem complete screen because user has a free jamtrack and is logged in")
|
||||
window.location = '/client#/redeemComplete'
|
||||
|
|
@ -120,6 +121,8 @@
|
|||
});
|
||||
data.sub_total = sub_total;
|
||||
|
||||
totalCost = data.sub_total;
|
||||
|
||||
data.carts = carts;
|
||||
var $cartsHtml = $(
|
||||
context._.template(
|
||||
|
|
|
|||
|
|
@ -41,6 +41,10 @@
|
|||
|
||||
context._.each(jam_track.tracks, function (track) {
|
||||
|
||||
if (track.track_type == 'Click') {
|
||||
return;
|
||||
}
|
||||
|
||||
var $element = $('<div class="jam-track-preview-holder"></div>')
|
||||
|
||||
$previews.append($element);
|
||||
|
|
|
|||
|
|
@ -30,6 +30,10 @@
|
|||
|
||||
context._.each(jam_track.tracks, function (track) {
|
||||
|
||||
if (track.track_type == 'Click') {
|
||||
return;
|
||||
}
|
||||
|
||||
var $element = $('<div class="jam-track-preview-holder"></div>')
|
||||
|
||||
$previews.append($element);
|
||||
|
|
|
|||
|
|
@ -40,6 +40,10 @@
|
|||
|
||||
context._.each(jam_track.tracks, function (track) {
|
||||
|
||||
if (track.track_type == 'Click') {
|
||||
return;
|
||||
}
|
||||
|
||||
var $element = $('<div class="jam-track-preview-holder"></div>')
|
||||
|
||||
$previews.append($element);
|
||||
|
|
|
|||
|
|
@ -73,6 +73,10 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
.thanks-detail.gift-card, .thanks-detail.jam-tracks-in-browser{
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.thanks-detail.purchased-jam-track {
|
||||
|
||||
margin-top:20px;
|
||||
|
|
|
|||
|
|
@ -702,4 +702,23 @@ $ReactSelectVerticalPadding: 3px;
|
|||
|
||||
.Select-search-prompt {
|
||||
padding:3px 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.session-track-list-enter {
|
||||
opacity: 0.01;
|
||||
transition: opacity .5s ease-in;
|
||||
|
||||
&.session-track-list-enter-active {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.session-track-list-leave {
|
||||
opacity:1;
|
||||
transition: opacity .5s ease-in;
|
||||
|
||||
&.session-track-list-leave-active {
|
||||
opacity: 0.01;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -386,22 +386,3 @@ $session-screen-divider: 1190px;
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.session-track-list-enter {
|
||||
opacity: 0.01;
|
||||
transition: opacity .5s ease-in;
|
||||
|
||||
&.session-track-list-enter-active {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.session-track-list-leave {
|
||||
opacity:1;
|
||||
transition: opacity .5s ease-in;
|
||||
|
||||
&.session-track-list-leave-active {
|
||||
opacity: 0.01;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@
|
|||
display:inline-block;
|
||||
}
|
||||
|
||||
.download-jamkazam-wrapper {
|
||||
.download-jamkazam-wrapper, .back-to-browsing {
|
||||
text-align:center;
|
||||
display:block;
|
||||
margin-top:35px;
|
||||
|
|
@ -83,6 +83,7 @@
|
|||
display:none;
|
||||
}
|
||||
}
|
||||
|
||||
.thanks-detail.purchased-jam-track {
|
||||
|
||||
margin-top:20px;
|
||||
|
|
|
|||
|
|
@ -162,6 +162,18 @@ body.web.individual_jamtrack {
|
|||
text-align: center;
|
||||
}
|
||||
|
||||
img.gift-card-preview {
|
||||
width:300px;
|
||||
float: left;
|
||||
margin-left: -15px; // because image has black on the left, which you can't see on back background
|
||||
margin-right: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
p.gift-getter {
|
||||
margin-top:20px;
|
||||
line-height:125%;
|
||||
}
|
||||
|
||||
img.app-preview {
|
||||
width: 340px;
|
||||
float: left;
|
||||
|
|
@ -188,6 +200,7 @@ body.web.individual_jamtrack {
|
|||
}
|
||||
|
||||
.cta-button {
|
||||
cursor:pointer;
|
||||
background-color: $cta-color;
|
||||
|
||||
&.processing {
|
||||
|
|
@ -205,6 +218,9 @@ body.web.individual_jamtrack {
|
|||
|
||||
.browse-all {
|
||||
color: #ffb800;
|
||||
text-decoration: underline;
|
||||
text-align: center;
|
||||
display: block;
|
||||
}
|
||||
|
||||
p {
|
||||
|
|
@ -313,6 +329,16 @@ body.web.individual_jamtrack {
|
|||
border-width: 0 0 $chunkyBorderWidth;
|
||||
border-style: solid;
|
||||
border-color: $copy-color-on-dark;
|
||||
|
||||
&.gift-card {
|
||||
padding:20px 0 10px;
|
||||
.jamtrack-title {
|
||||
margin-top:10px;
|
||||
font-size:18px;
|
||||
font-style:italic;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.preview-area {
|
||||
|
|
@ -320,6 +346,11 @@ body.web.individual_jamtrack {
|
|||
padding: 10px;
|
||||
|
||||
border-width: 0 0 $chunkyBorderWidth;
|
||||
|
||||
&.gift-card {
|
||||
border-width: 0 0 2px;
|
||||
}
|
||||
|
||||
border-style: solid;
|
||||
border-color: $copy-color-on-dark;
|
||||
|
||||
|
|
@ -338,6 +369,9 @@ body.web.individual_jamtrack {
|
|||
margin-bottom:10px;
|
||||
}
|
||||
|
||||
.cta-buttons {
|
||||
text-align:center;
|
||||
}
|
||||
.cta-button {
|
||||
font-size: 24px;
|
||||
color: white;
|
||||
|
|
@ -348,6 +382,13 @@ body.web.individual_jamtrack {
|
|||
width: 100%;
|
||||
border: 1px outset buttonface;
|
||||
font-family: Raleway, Arial, Helvetica, sans-serif;
|
||||
|
||||
&.gift-card {
|
||||
font-size:16px;
|
||||
width:138px;
|
||||
margin:15px 5px;
|
||||
display:inline-block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -385,12 +426,7 @@ body.web.individual_jamtrack {
|
|||
border: 1px outset buttonface;
|
||||
font-family: Raleway, Arial, Helvetica, sans-serif;
|
||||
}
|
||||
.browse-all {
|
||||
text-decoration: underline;
|
||||
text-align: center;
|
||||
display: block;
|
||||
|
||||
}
|
||||
.privacy-policy {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,90 @@
|
|||
@import "client/common";
|
||||
|
||||
body.web.redeem_giftcard {
|
||||
|
||||
h2 {
|
||||
margin-bottom:20px;
|
||||
}
|
||||
|
||||
label{
|
||||
margin-bottom:4px;
|
||||
color:$ColorTextTypical;
|
||||
}
|
||||
|
||||
input{
|
||||
margin-bottom:20px;
|
||||
width:200px;
|
||||
}
|
||||
|
||||
.redeem-container {
|
||||
margin-left:350px;
|
||||
width:400px;
|
||||
padding-top:20px;
|
||||
|
||||
&.logged-in {
|
||||
button {
|
||||
margin-top:10px !important;
|
||||
}
|
||||
}
|
||||
|
||||
&.not-logged-in {
|
||||
|
||||
}
|
||||
}
|
||||
.redeem-content {
|
||||
|
||||
}
|
||||
p.instructions {
|
||||
line-height:125%;
|
||||
color:$ColorTextTypical;
|
||||
margin-bottom:20px;
|
||||
}
|
||||
|
||||
button {
|
||||
display:block !important;
|
||||
height: 29px !important;
|
||||
margin-bottom: 10px;
|
||||
margin-right: 0px;
|
||||
font-size: 16px !important;
|
||||
padding: 7px 3px !important;
|
||||
line-height:inherit !important;
|
||||
margin-left:2px !important;
|
||||
margin-top:15px;
|
||||
}
|
||||
|
||||
.icheckbox_minimal {
|
||||
float: left;
|
||||
top: -2px;
|
||||
margin-left: 0;
|
||||
margin-right:10px;
|
||||
}
|
||||
|
||||
.errors {
|
||||
font-size:14px;
|
||||
height:20px;
|
||||
margin:0;
|
||||
visibility: hidden;
|
||||
color: red;
|
||||
font-weight: bold;
|
||||
|
||||
&.active {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
|
||||
form {
|
||||
margin-bottom:20px;
|
||||
}
|
||||
.terms-help {
|
||||
float:left;
|
||||
margin-top:-5px;
|
||||
font-size:12px;
|
||||
width:178px;
|
||||
}
|
||||
|
||||
.done-action {
|
||||
margin-top: 20px;
|
||||
line-height: 125%;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -3,7 +3,7 @@ class ApiJamTracksController < ApiController
|
|||
# have to be signed in currently to see this screen
|
||||
before_filter :api_signed_in_user, :except => [:index, :autocomplete, :show_with_artist_info, :artist_index]
|
||||
before_filter :api_any_user, :only => [:index, :autocomplete, :show_with_artist_info, :artist_index]
|
||||
before_filter :lookup_jam_track_right, :only => [:download,:enqueue, :show_jam_track_right, :mark_active, :download_stem]
|
||||
before_filter :lookup_jam_track_right, :only => [:download, :enqueue, :show_jam_track_right, :mark_active, :download_stem]
|
||||
before_filter :ip_blacklist, :only => [:download_stem, :download]
|
||||
before_filter :user_blacklist, :only => [:download_stem, :download]
|
||||
|
||||
|
|
@ -285,6 +285,25 @@ class ApiJamTracksController < ApiController
|
|||
puts "jamtrack_mixdowns #{jamtrack_mixdowns}"
|
||||
end
|
||||
|
||||
def ios_order_placed
|
||||
jam_track = JamTrack.find(params[:jam_track_id])
|
||||
|
||||
sales = Sale.ios_purchase(current_user, jam_track, nil)
|
||||
|
||||
#
|
||||
# sales.each do |sale|
|
||||
# if sale.is_jam_track_sale?
|
||||
# sale.sale_line_items.each do |line_item|
|
||||
# jam_track = line_item.product
|
||||
# jam_track_right = jam_track.right_for_user(current_user)
|
||||
# response[:jam_tracks] << {name: jam_track.name, id: jam_track.id, jam_track_right_id: jam_track_right.id, version: jam_track.version}
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
response = {name: jam_track.name, id: jam_track.id, jam_track_right_id: jam_track.right_for_user(current_user).id, version: jam_track.version}
|
||||
render :json => response, :status => 200
|
||||
end
|
||||
|
||||
private
|
||||
def lookup_jam_track_right
|
||||
@jam_track_right = JamTrackRight.where("jam_track_id=? AND user_id=?", params[:id], current_user.id).first
|
||||
|
|
|
|||
|
|
@ -124,16 +124,28 @@ class ApiRecurlyController < ApiController
|
|||
|
||||
def place_order
|
||||
error=nil
|
||||
response = {jam_tracks: []}
|
||||
response = {jam_tracks: [], gift_cards: []}
|
||||
|
||||
if Sale.is_mixed(current_user.shopping_carts)
|
||||
msg = "has free and non-free items. Try removing non-free items."
|
||||
render json: {message: "Cart " + msg, errors: {cart: [msg]}}, :status => 404
|
||||
return
|
||||
end
|
||||
|
||||
sales = Sale.place_order(current_user, current_user.shopping_carts)
|
||||
|
||||
|
||||
sales.each do |sale|
|
||||
if sale.is_jam_track_sale?
|
||||
sale.sale_line_items.each do |line_item|
|
||||
sale.sale_line_items.each do |line_item|
|
||||
if line_item.is_jam_track?
|
||||
jam_track = line_item.product
|
||||
jam_track_right = jam_track.right_for_user(current_user)
|
||||
response[:jam_tracks] << {name: jam_track.name, id: jam_track.id, jam_track_right_id: jam_track_right.id, version: jam_track.version}
|
||||
elsif line_item.is_gift_card?
|
||||
gift_card = line_item.product
|
||||
response[:gift_cards] << {name: gift_card.name, id: gift_card.id}
|
||||
else
|
||||
raise 'unknown sale line item type: ' + line_item.product_type
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -20,13 +20,41 @@ class ApiShoppingCartsController < ApiController
|
|||
raise StateError, "Invalid JamTrack."
|
||||
end
|
||||
|
||||
@cart = ShoppingCart.add_jam_track_to_cart(any_user, jam_track)
|
||||
@cart = ShoppingCart.add_jam_track_to_cart(any_user, jam_track, clear:params[:clear])
|
||||
|
||||
if @cart.errors.any?
|
||||
response.status = :unprocessable_entity
|
||||
respond_with @cart
|
||||
else
|
||||
respond_with @cart, responder: ApiResponder, :status => 201
|
||||
# let add_jamtrack.rabl take over
|
||||
end
|
||||
end
|
||||
|
||||
def add_gift_card
|
||||
gift_card_type = nil
|
||||
|
||||
id = params[:id]
|
||||
|
||||
if id && id.to_i == 5
|
||||
gift_card_type = 'jam_tracks_5'
|
||||
elsif id && id.to_i == 10
|
||||
gift_card_type = 'jam_tracks_10'
|
||||
end
|
||||
|
||||
gift_card = GiftCardType.find_by_id(gift_card_type)
|
||||
|
||||
# verify GiftCard exists
|
||||
if gift_card.nil?
|
||||
raise StateError, "Invalid JamTrack."
|
||||
end
|
||||
|
||||
@cart = ShoppingCart.add_item_to_cart(any_user, gift_card)
|
||||
|
||||
if @cart.errors.any?
|
||||
response.status = :unprocessable_entity
|
||||
respond_with @cart
|
||||
else
|
||||
# let add_gift_card.rabl take over
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -42,7 +70,7 @@ class ApiShoppingCartsController < ApiController
|
|||
response.statue = :unprocessable_entity
|
||||
respond_with @cart
|
||||
else
|
||||
respond_with @cart, responder: ApiResponder, :status => 200
|
||||
# let update_cart.rabl take over
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -52,7 +80,7 @@ class ApiShoppingCartsController < ApiController
|
|||
|
||||
ShoppingCart.remove_jam_track_from_cart(any_user, @cart)
|
||||
|
||||
respond_with responder: ApiResponder, :status => 204
|
||||
# let remove_cart.rabl take over
|
||||
end
|
||||
|
||||
# take all shopping carts from anonymous user and copy them to logged in user
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@ ApiUsersController < ApiController
|
|||
:band_invitation_index, :band_invitation_show, :band_invitation_update, # band invitations
|
||||
:set_password, :begin_update_email, :update_avatar, :delete_avatar, :generate_filepicker_policy,
|
||||
:share_session, :share_recording,
|
||||
:affiliate_report, :audio_latency, :broadcast_notification]
|
||||
before_filter :ip_blacklist, :only => [:create]
|
||||
:affiliate_report, :audio_latency, :broadcast_notification, :redeem_giftcard]
|
||||
before_filter :ip_blacklist, :only => [:create, :redeem_giftcard]
|
||||
|
||||
respond_to :json, :except => :calendar
|
||||
respond_to :ics, :only => :calendar
|
||||
|
|
@ -81,6 +81,7 @@ ApiUsersController < ApiController
|
|||
terms_of_service: params[:terms_of_service].to_i,
|
||||
location: {:country => nil, :state => nil, :city => nil},
|
||||
signup_hint: signup_hint,
|
||||
gift_card: params[:gift_card],
|
||||
affiliate_referral_id: cookies[:affiliate_visitor]
|
||||
}
|
||||
|
||||
|
|
@ -598,6 +599,7 @@ ApiUsersController < ApiController
|
|||
@dump.user_id = params[:user_id]
|
||||
@dump.session_id = params[:session_id]
|
||||
@dump.timestamp = params[:timestamp]
|
||||
@dump.description = params[:description]
|
||||
|
||||
unless @dump.save
|
||||
# There are at least some conditions on valid dumps (need client_type)
|
||||
|
|
@ -919,6 +921,45 @@ ApiUsersController < ApiController
|
|||
.find(params[:id])
|
||||
end
|
||||
|
||||
def redeem_giftcard
|
||||
@gift_card = GiftCard.find_by_code(params[:gift_card])
|
||||
|
||||
if @gift_card.nil?
|
||||
render json: {errors:{gift_card: ['does not exist']}}, status: 422
|
||||
return
|
||||
end
|
||||
|
||||
if current_user.gift_cards.count >= 5
|
||||
render json: {errors:{gift_card: ['has too many on account']}}, status: 422
|
||||
return
|
||||
end
|
||||
|
||||
if @gift_card.user
|
||||
if @gift_card.user == current_user
|
||||
render json: {errors:{gift_card: ['already redeemed by you']}}, status: 422
|
||||
return
|
||||
else
|
||||
render json: {errors:{gift_card: ['already redeemed by another']}}, status: 422
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
@gift_card.user = current_user
|
||||
@gift_card.save
|
||||
|
||||
if @gift_card.errors.any?
|
||||
respond_with_model(@gift_card)
|
||||
return
|
||||
else
|
||||
|
||||
# apply gift card items to everything in shopping cart
|
||||
current_user.reload
|
||||
ShoppingCart.apply_gifted_jamtracks(current_user)
|
||||
render json: {gifted_jamtracks:current_user.gifted_jamtracks}, status: 200
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
###################### RECORDINGS #######################
|
||||
# def recording_index
|
||||
# @recordings = User.recording_index(current_user, params[:id])
|
||||
|
|
|
|||
|
|
@ -208,5 +208,33 @@ class LandingsController < ApplicationController
|
|||
render 'affiliate_program', layout: 'web'
|
||||
end
|
||||
|
||||
def redeem_giftcard
|
||||
@no_landing_tag = true
|
||||
@landing_tag_play_learn_earn = true
|
||||
render 'redeem_giftcard', layout: 'web'
|
||||
end
|
||||
|
||||
def buy_gift_card
|
||||
@no_landing_tag = true
|
||||
@landing_tag_play_learn_earn = true
|
||||
@show_after_black_bar_border = true
|
||||
@jam_track = JamTrack.find_by_slug('elton-john-rocket-man')
|
||||
@jam_track = JamTrack.first unless @jam_track
|
||||
|
||||
instrument_id = nil
|
||||
instrument_name = nil
|
||||
instrument_count = 0
|
||||
|
||||
band_jam_track_count = @jam_track.band_jam_track_count
|
||||
jam_track_count = JamTrack.count
|
||||
@title = individual_jamtrack_title(false, params[:generic], @jam_track)
|
||||
@description = individual_jamtrack_desc(false, params[:generic], @jam_track)
|
||||
@page_data = {jam_track: @jam_track, all_track_count: jam_track_count, band_track_count: band_jam_track_count, band: false, generic: params[:generic], instrument: instrument_name, instrument_id: instrument_id, instrument_count: instrument_count}
|
||||
gon.jam_track_plan_code = @jam_track.plan_code if @jam_track
|
||||
gon.generic = params[:generic]
|
||||
gon.instrument_id = instrument_id
|
||||
|
||||
render 'buy_gift_card', layout: 'web'
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
extends "api_shopping_carts/show"
|
||||
|
||||
node :show_free_jamtrack do
|
||||
any_user.show_free_jamtrack?
|
||||
end
|
||||