* VRFS-3708 - allow redemption of gift cards
This commit is contained in:
parent
bb9beb9cab
commit
7fbb215fca
|
|
@ -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_giftcards_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
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
class JamRuby::GiftCard
|
||||
|
||||
attr_accessor :csv
|
||||
|
||||
|
||||
def process_csv
|
||||
|
||||
end
|
||||
end
|
||||
|
|
@ -310,3 +310,4 @@ web_playable_jamtracks.sql
|
|||
affiliate_partner_rate.sql
|
||||
track_downloads.sql
|
||||
jam_track_lang_idx.sql
|
||||
giftcard.sql
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -253,6 +253,7 @@ 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"
|
||||
|
||||
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."
|
||||
|
|
|
|||
|
|
@ -24,11 +24,33 @@ module JamRuby
|
|||
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
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
module JamRuby
|
||||
class GiftCard < ActiveRecord::Base
|
||||
|
||||
@@log = Logging.logger[GiftCard]
|
||||
|
||||
JAM_TRACKS_10 = 'jam_tracks_10'
|
||||
JAM_TRACKS_20 = 'jam_tracks_20'
|
||||
CARD_TYPES =
|
||||
[
|
||||
JAM_TRACKS_10,
|
||||
JAM_TRACKS_20
|
||||
]
|
||||
|
||||
|
||||
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_10
|
||||
user.gifted_jamtracks += 10
|
||||
elsif card_type == JAM_TRACKS_20
|
||||
user.gifted_jamtracks += 20
|
||||
else
|
||||
raise "unknown card type #{card_type}"
|
||||
end
|
||||
user.save!
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -129,7 +129,29 @@ module JamRuby
|
|||
end
|
||||
|
||||
def self.is_only_freebie(shopping_carts_jam_tracks)
|
||||
shopping_carts_jam_tracks.length == 1 && shopping_carts_jam_tracks[0].product_info[:free]
|
||||
free = true
|
||||
shopping_carts_jam_tracks.each do |cart|
|
||||
free = cart.product_info[:free]
|
||||
|
||||
if !free
|
||||
break
|
||||
end
|
||||
end
|
||||
free
|
||||
end
|
||||
|
||||
# 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)
|
||||
|
|
@ -311,10 +333,17 @@ module JamRuby
|
|||
jam_track_right.redeemed = shopping_cart.free?
|
||||
end
|
||||
|
||||
# also if the purchase was a free one, then update the user record to no longer allow redeemed jamtracks
|
||||
# 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?
|
||||
User.where(id: current_user.id).update_all(has_redeemable_jamtrack: false)
|
||||
current_user.has_redeemable_jamtrack = false # make sure model reflects the truth
|
||||
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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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,6 +22,7 @@ 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')
|
||||
|
||||
|
|
@ -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,6 +79,16 @@ 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)
|
||||
|
|
@ -81,6 +119,7 @@ module JamRuby
|
|||
|
||||
if free?
|
||||
|
||||
puts "GOT A FREEBIE!"
|
||||
# create the credit, then the pseudo charge
|
||||
[
|
||||
{
|
||||
|
|
@ -134,28 +173,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
|
||||
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_all_shopping_carts
|
||||
any_user.reload
|
||||
end
|
||||
|
||||
mark_redeem = ShoppingCart.user_has_redeemable_jam_track?(any_user)
|
||||
|
|
@ -168,19 +211,48 @@ module JamRuby
|
|||
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
|
||||
|
||||
# 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,9 @@ module JamRuby
|
|||
# events
|
||||
has_many :event_sessions, :class_name => "JamRuby::EventSession"
|
||||
|
||||
# gift cards
|
||||
has_many :gift_cards, :class_name=> "JamRuby::GiftCard"
|
||||
|
||||
# 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 +197,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 +218,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 +238,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 +272,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 +1048,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 +1060,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 +1167,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 +1222,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
|
||||
|
||||
|
|
|
|||
|
|
@ -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,9 @@ 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::GiftCard::JAM_TRACKS_10
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -5,6 +5,23 @@ 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)}
|
||||
|
||||
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,6 +64,9 @@ 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(:client) { RecurlyClient.new }
|
||||
let(:billing_info) {
|
||||
|
|
@ -87,6 +107,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 +153,92 @@ 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
|
||||
shopping_cart4 = ShoppingCart.create user, jamtrack4, 1, false
|
||||
|
||||
client.find_or_create_account(user, billing_info)
|
||||
|
||||
sales = Sale.place_order(user, [shopping_cart3, shopping_cart4])
|
||||
|
||||
user.reload
|
||||
user.sales.length.should eq(2)
|
||||
sale = sales[0]
|
||||
sale.reload
|
||||
|
||||
sale.recurly_invoice_id.should_not 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], jamtrack3)
|
||||
|
||||
paid_right = JamTrackRight.where(user_id:user.id).where(jam_track_id: jamtrack4.id).first
|
||||
|
||||
sale_line_item.recurly_total_in_cents.should eq(jam_track_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(JamTrack::PRODUCT_TYPE)
|
||||
sale_line_item.unit_price.should eq(jamtrack4.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(jamtrack4.plan_code)
|
||||
sale_line_item.product_id.should eq(jamtrack.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 eq(paid_right.recurly_adjustment_uuid)
|
||||
|
||||
user.has_redeemable_jamtrack.should be_false
|
||||
user.gifted_jamtracks.should eq(0)
|
||||
|
||||
end
|
||||
|
||||
it "for a free jam track with an affiliate association" do
|
||||
partner = FactoryGirl.create(:affiliate_partner)
|
||||
user.affiliate_referral = partner
|
||||
|
|
|
|||
|
|
@ -3,8 +3,13 @@ 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) }
|
||||
|
||||
before(:each) do
|
||||
ShoppingCart.delete_all
|
||||
|
|
@ -13,6 +18,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
|
||||
|
|
@ -22,16 +30,16 @@ describe ShoppingCart do
|
|||
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 = ShoppingCart.add_jam_track_to_cart(user, jam_track2, clear: true)
|
||||
cart3.errors.any?.should be_false
|
||||
user.reload
|
||||
user.shopping_carts.length.should eq(1)
|
||||
|
|
@ -53,19 +61,131 @@ describe ShoppingCart 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 "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,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)
|
||||
|
|
|
|||
|
|
@ -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')
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1187,6 +1187,7 @@
|
|||
});
|
||||
|
||||
deferred.done(function(user) {
|
||||
context.JK.currentUserFreeJamTrack = user.show_free_jamtrack
|
||||
window.UserActions.loaded(user)
|
||||
})
|
||||
|
||||
|
|
@ -1791,12 +1792,17 @@
|
|||
}
|
||||
|
||||
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 getShoppingCarts() {
|
||||
|
|
@ -1810,12 +1816,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 +1997,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",
|
||||
|
|
@ -2190,6 +2212,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'
|
||||
|
|
@ -76,10 +70,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 +152,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 +297,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 +395,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 @state.user?.purchased_jamtracks_count == 0 && @state.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()
|
||||
|
|
@ -91,10 +91,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 +219,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 +434,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()
|
||||
|
|
@ -517,12 +537,9 @@ MIX_MODES = context.JK.MIX_MODES
|
|||
|
||||
|
||||
beforeShow: () ->
|
||||
@setState({is_free: context.JK.currentUserFreeJamTrack})
|
||||
if !@state.first_search
|
||||
@search(@state.type, window.JamTrackSearchInput)
|
||||
|
||||
|
||||
|
||||
onAppInit: (@app) ->
|
||||
|
||||
window.JamTrackSearchInput = '' # need to be not null; otherwise react-select chokes
|
||||
|
|
@ -530,10 +547,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})
|
||||
|
||||
})
|
||||
|
|
@ -2,5 +2,6 @@ context = window
|
|||
|
||||
@UserActions = Reflux.createActions({
|
||||
loaded: {}
|
||||
modify: {}
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
)
|
||||
})
|
||||
|
|
@ -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})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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%;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -126,8 +126,15 @@ class ApiRecurlyController < ApiController
|
|||
error=nil
|
||||
response = {jam_tracks: []}
|
||||
|
||||
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|
|
||||
|
|
|
|||
|
|
@ -20,13 +20,13 @@ 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
|
||||
|
||||
|
|
@ -42,7 +42,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 +52,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],
|
||||
location: {:country => nil, :state => nil, :city => nil},
|
||||
signup_hint: signup_hint,
|
||||
gift_card: params[:gift_card],
|
||||
affiliate_referral_id: cookies[:affiliate_visitor]
|
||||
}
|
||||
|
||||
|
|
@ -919,6 +920,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,10 @@ 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
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -1 +1,5 @@
|
|||
extends "api_shopping_carts/show"
|
||||
extends "api_shopping_carts/show"
|
||||
|
||||
node :show_free_jamtrack do
|
||||
any_user.show_free_jamtrack?
|
||||
end
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
node :show_free_jamtrack do
|
||||
any_user.show_free_jamtrack?
|
||||
end
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
node :show_free_jamtrack do
|
||||
any_user.show_free_jamtrack?
|
||||
end
|
||||
|
|
@ -11,15 +11,15 @@ end
|
|||
|
||||
# give back more info if the user being fetched is yourself
|
||||
if @user == current_user
|
||||
attributes :email, :original_fpfile, :cropped_fpfile, :crop_selection, :session_settings, :show_whats_next, :show_whats_next_count, :subscribe_email, :auth_twitter, :new_notifications, :sales_count, :reuse_card, :purchased_jamtracks_count, :first_downloaded_client_at, :created_at, :first_opened_jamtrack_web_player
|
||||
attributes :email, :original_fpfile, :cropped_fpfile, :crop_selection, :session_settings, :show_whats_next, :show_whats_next_count, :subscribe_email, :auth_twitter, :new_notifications, :sales_count, :reuse_card, :purchased_jamtracks_count, :first_downloaded_client_at, :created_at, :first_opened_jamtrack_web_player, :gifted_jamtracks, :has_redeemable_jamtrack
|
||||
|
||||
node :geoiplocation do |user|
|
||||
geoiplocation = current_user.geoiplocation
|
||||
geoiplocation.info if geoiplocation
|
||||
end
|
||||
|
||||
node :free_jamtrack do |user|
|
||||
Rails.application.config.one_free_jamtrack_per_user && user.has_redeemable_jamtrack
|
||||
node :show_free_jamtrack do |user|
|
||||
user.show_free_jamtrack?
|
||||
end
|
||||
|
||||
node :show_jamtrack_guide do |user|
|
||||
|
|
|
|||
|
|
@ -1,86 +0,0 @@
|
|||
#jamtrackScreen.screen.secondary.no-login-required layout='screen' layout-id='jamtrackBrowse'
|
||||
.content
|
||||
.content-head
|
||||
.content-icon=image_tag("content/icon_jamtracks.png", height:19, width:19 )
|
||||
h1 jamtracks
|
||||
=render "screen_navigation"
|
||||
.content-body
|
||||
=form_tag('', {:id => 'jamtrack-find-form', :class => 'inner-content'}) do
|
||||
=render(:partial => "web_filter", :locals => {:search_type => Search::PARAM_JAMTRACK})
|
||||
.filter-body
|
||||
.content-body-scroller
|
||||
.profile-wrapper
|
||||
h2 shop for jamtracks
|
||||
table.generaltable.jamtrack-table
|
||||
thead
|
||||
tr
|
||||
th.jamtrack-detail JAMTRACK
|
||||
th.jamtrack-tracks TRACKS INCLUDED / PREVIEW
|
||||
th.jamtrack-action SHOP
|
||||
tbody.jamtrack-content
|
||||
a.btn-next-pager href="/api/jamtracks?page=1" Next
|
||||
.end-of-jamtrack-list.end-of-list="No more Jamtracks"
|
||||
|
||||
script#template-jamtrack type='text/template'
|
||||
tr.jamtrack-record jamtrack-id="{{data.jamtrack.id}}"
|
||||
td.jamtrack-detail
|
||||
.jamtrack-name
|
||||
| "{{data.jamtrack.name}}"
|
||||
.jamtrack-original-artist
|
||||
| by {{data.jamtrack.original_artist}}
|
||||
br clear="all"
|
||||
.clearall.detail-label.extra.hidden.song-writer
|
||||
| Songwriters:
|
||||
.detail-value.extra.hidden
|
||||
| {{data.jamtrack.songwriter}}
|
||||
.clearall.detail-label.extra.hidden
|
||||
| Publishers:
|
||||
.detail-value.extra.hidden
|
||||
| {{data.jamtrack.publisher}}
|
||||
.clearall.detail-label.extra.hidden
|
||||
| Genre:
|
||||
.detail-value.extra.hidden
|
||||
| {{data.jamtrack.genres[0]}}
|
||||
.clearall.detail-label.extra.hidden
|
||||
| Version:
|
||||
.detail-value.extra.hidden
|
||||
| {{data.jamtrack.recording_type}}
|
||||
td.jamtrack-tracks
|
||||
.detail-arrow
|
||||
.jamtrack-detail-btn
|
||||
="{% if (data.expanded) { %}"
|
||||
| hide tracks
|
||||
a.details-arrow.arrow-up
|
||||
="{% } else { %}"
|
||||
| show all tracks
|
||||
a.details-arrow.arrow-down
|
||||
="{% } %}"
|
||||
="{% _.each(data.jamtrack.tracks, function(track) { %}"
|
||||
.jamtrack-track.hidden jamtrack-track-id="{{track.id}}"
|
||||
/ .instrument-desc
|
||||
/ | {{track.instrument_desc}}
|
||||
/.track-instrument
|
||||
.jamtrack-preview
|
||||
.clearall
|
||||
="{% }); %}"
|
||||
td.jamtrack-action
|
||||
.jamtrack-action-container
|
||||
.jamtrack-actions
|
||||
/ a.play-button href="#" data-jamtrack-id="{{data.jamtrack.id}}"
|
||||
/ =image_tag "shared/play_button.png"
|
||||
.jamtrack-price class="{{data.free_state}}"
|
||||
| {{"$ " + data.jamtrack.price}}
|
||||
="{% if (data.is_free) { %}"
|
||||
a.jamtrack-add-cart.button-orange.is_free href="#" data-jamtrack-id="{{data.jamtrack.id}}" GET IT FREE!
|
||||
="{% } else if (data.jamtrack.purchased) { %}"
|
||||
a.jamtrack-add-cart-disabled.button-grey.button-disabled href="javascript:void(0)" PURCHASED
|
||||
="{% } else if (data.jamtrack.added_cart) { %}"
|
||||
a.jamtrack-add-cart-disabled.button-grey.button-disabled href="client#/shoppingCart" ALREADY IN CART
|
||||
="{% } else { %}"
|
||||
a.jamtrack-add-cart.button-orange href="#" data-jamtrack-id="{{data.jamtrack.id}}" ADD TO CART
|
||||
="{% }; %}"
|
||||
="{% if (data.jamtrack.sales_region==JK.AVAILABILITY_US) { %}"
|
||||
.jamtrack-license
|
||||
| This JamTrack available only to US customers.
|
||||
a.license-us-why.orange href="#" why?
|
||||
="{% }; %}"
|
||||
|
|
@ -1,290 +0,0 @@
|
|||
div layout="screen" layout-id="order" id="orderScreen" class="screen secondary"
|
||||
.content
|
||||
.content-head
|
||||
.content-icon= image_tag("content/icon_shopping_cart.png", {:height => 19, :width => 19})
|
||||
h1 check out
|
||||
= render "screen_navigation"
|
||||
.content-body
|
||||
#order_error.error.hidden
|
||||
.content-body-scroller
|
||||
.content-wrapper
|
||||
.checkout-navigation-bar
|
||||
.checkout-payment-info
|
||||
form class="payment-info" id="checkout-payment-info"
|
||||
.billing-address
|
||||
h2.billing-caption Billing Address
|
||||
#divBillingFirstName
|
||||
.billing-label
|
||||
label for="billing-first-name" First Name:
|
||||
.billing-value
|
||||
input type="text" id="billing-first-name"
|
||||
.clearall
|
||||
#divBillingLastName
|
||||
.billing-label
|
||||
label for="billing-last-name" Last Name:
|
||||
.billing-value
|
||||
input type="text" id="billing-last-name"
|
||||
.clearall
|
||||
#divBillingAddress1
|
||||
.billing-label
|
||||
label for="billing-address1" Address 1:
|
||||
.billing-value
|
||||
input type="text" id="billing-address1"
|
||||
.clearall
|
||||
.billing-label
|
||||
label for="billing-address2" Address 2:
|
||||
.billing-value
|
||||
input type="text" id="billing-address2"
|
||||
.clearall
|
||||
#divBillingCity
|
||||
.billing-label
|
||||
label for="billing-city" City:
|
||||
.billing-value
|
||||
input type="text" id="billing-city"
|
||||
.clearall
|
||||
#divBillingState
|
||||
.billing-label
|
||||
label for="billing-state" State/Region:
|
||||
.billing-value
|
||||
input type="text" id="billing-state"
|
||||
.clearall
|
||||
#divBillingZip
|
||||
.billing-label
|
||||
label for="billing-zip" Zip:
|
||||
.billing-value
|
||||
input type="text" id="billing-zip"
|
||||
.clearall
|
||||
#divBillingCountry
|
||||
.billing-label
|
||||
label for="billing-country" Country:
|
||||
.billing-value
|
||||
input type="text" id="billing-country"
|
||||
.clearall
|
||||
.payment-method
|
||||
h2.payment-method-caption Payment Method
|
||||
b Enter Card Information
|
||||
br
|
||||
#divCardName
|
||||
.card-label.mt10
|
||||
label for="card-name" Name of Card:
|
||||
.card-value.mt10
|
||||
input type="text" id="card-name"
|
||||
.clearall
|
||||
#divCardNumber
|
||||
.card-label.mt10
|
||||
label for="card-number" Card Number:
|
||||
.card-value.mt10
|
||||
input type="text" id="card-number"
|
||||
.clearall
|
||||
#divCardExpiry
|
||||
.card-label.mt10 Expiration Date:
|
||||
.card-value.mt10
|
||||
=date_select("card", "expire-date", use_two_digit_numbers: true, discard_day: true, :start_year => Time.now.year, :end_year => Time.now.year + 18, :order => [:month, :day, :year], :default => -25.years.from_now, :html=>{:class => "account-profile-birthdate", :id=>"card-expiry"} )
|
||||
.clearall
|
||||
#divCardVerify
|
||||
.card-label.mt10
|
||||
label for="card-verify" Verification Value:
|
||||
.card-value.mt10
|
||||
input type="text" id="card-verify"
|
||||
.clearall
|
||||
.card-label.mt15
|
||||
.card-value.mt15
|
||||
.save-card-checkbox.ichecbuttons
|
||||
input type="checkbox" id="save-card" name="save-card" checked="checked"
|
||||
.divSaveCardHelper
|
||||
label for="save-card" Save card for future use
|
||||
.clearall
|
||||
.clearall
|
||||
.clearall
|
||||
|
||||
.action-bar.mt15
|
||||
.shipping-address
|
||||
h2.shipping-address-label Shipping Address
|
||||
.shipping-as-billing.ichecbuttons
|
||||
input type="checkbox" id="shipping-as-billing" name="shipping-as-billing" checked="checked"
|
||||
.divBillingHelper
|
||||
label for="shipping-as-billing" Same as billing address
|
||||
.clearall
|
||||
.shipping-address-detail.hidden
|
||||
#divShippingFirstName
|
||||
.shipping-label
|
||||
label for="shipping-first-name" First Name:
|
||||
.shipping-value
|
||||
input type="text" id="shipping-first-name"
|
||||
.clearall
|
||||
#divShippingLastName
|
||||
.shipping-label
|
||||
label for="shipping-last-name" Last Name:
|
||||
.shipping-value
|
||||
input type="text" id="shipping-last-name"
|
||||
.clearall
|
||||
#divShippingAddress1
|
||||
.shipping-label
|
||||
label for="shipping-address1" Address 1:
|
||||
.shipping-value
|
||||
input type="text" id="shipping-address1"
|
||||
.clearall
|
||||
.shipping-label
|
||||
label for="shipping-address2" Address 2:
|
||||
.shipping-value
|
||||
input type="text" id="shipping-address2"
|
||||
.clearall
|
||||
#divShippingCity
|
||||
.shipping-label
|
||||
label for="shipping-city" City:
|
||||
.shipping-value
|
||||
input type="text" id="shipping-city"
|
||||
.clearall
|
||||
#divShippingState
|
||||
.shipping-label
|
||||
label for="shipping-state" State/Region:
|
||||
.shipping-value
|
||||
input type="text" id="shipping-state"
|
||||
.clearall
|
||||
#divShippingZip
|
||||
.shipping-label
|
||||
label for="shipping-zip" Zip:
|
||||
.shipping-value
|
||||
input type="text" id="shipping-zip"
|
||||
.clearall
|
||||
#divShippingCountry
|
||||
.shipping-label
|
||||
label for="shipping-country" Country:
|
||||
.shipping-value
|
||||
input type="text" id="shipping-country"
|
||||
.clearall
|
||||
.right.mt30
|
||||
a href="#" id="payment-info-help" class="button-grey" HELP
|
||||
a href="#" id="payment-info-next" class="button-orange" NEXT
|
||||
.clearall
|
||||
.order-panel.hidden
|
||||
.order-header.left
|
||||
h2 Review Your Order
|
||||
.mt5
|
||||
span By placing your order, you agree to JamKazam's
|
||||
'
|
||||
a href="/corp/terms" terms of service
|
||||
'
|
||||
span and
|
||||
'
|
||||
a href="/corp/returns" returns policy
|
||||
span .
|
||||
.right.mt10
|
||||
a href="#" class="button-grey" HELP
|
||||
.clearall
|
||||
|
||||
.order-content
|
||||
.thanks-panel.hidden
|
||||
h2 Thank you for your order!
|
||||
br
|
||||
.thanks-detail We'll send you an email confirming your order shortly.
|
||||
br
|
||||
.thanks-detail.jam-tracks-in-browser.hidden
|
||||
| To play your purchased JamTrack, launch the JamKazam application and open the JamTrack while in a session.
|
||||
.thanks-detail.purchased-jam-track.hidden
|
||||
h2.purchased-jam-track-header Downloading Your Purchased JamTracks
|
||||
span Each JamTrack will be downloaded sequentially.
|
||||
br
|
||||
span.notice Note that you do not have to wait for this to complete in order to use your JamTrack later.
|
||||
br.clear
|
||||
ul.purchased-list
|
||||
|
||||
|
||||
|
||||
script type='text/template' id='template-order-content'
|
||||
.order-left-page
|
||||
.payment-info-page
|
||||
.address-info
|
||||
b.left Billing Address
|
||||
a.left.ml5.change-payment-info href="#" change
|
||||
.clearall
|
||||
span.mt5= "{{data.billing_info.first_name}} {{data.billing_info.last_name}}"
|
||||
br
|
||||
span.mt5= "{{data.billing_info.address1}}"
|
||||
br
|
||||
span.mt5= "{{data.billing_info.address2}}"
|
||||
br
|
||||
br
|
||||
b.left Shipping Address
|
||||
a.left.ml5.change-payment-info href="#" change
|
||||
.clearall
|
||||
= "{% if (data.shipping_as_billing) { %}"
|
||||
span.mt5 same as billing address
|
||||
= "{% } else { %}"
|
||||
span.mt5= "{{data.shipping_info.first_name}} {{data.shipping_info.last_name}}"
|
||||
br
|
||||
span.mt5= "{{data.shipping_info.address1}}"
|
||||
br
|
||||
span.mt5= "{{data.shipping_info.address2}}"
|
||||
= "{% } %}"
|
||||
br
|
||||
.payment-method-info
|
||||
b.left Payment Method
|
||||
a.left.ml5.change-payment-info href="#" change
|
||||
.clearall
|
||||
|
||||
/= image_tag ''
|
||||
="Ending in: {{data.billing_info.number.slice(-4)}}"
|
||||
|
||||
.clearall
|
||||
.order-items-page
|
||||
.cart-items
|
||||
.cart-item-caption#header
|
||||
span Your order includes:
|
||||
.cart-item-price
|
||||
span style="text-decoration: underline;" Price
|
||||
.cart-item-quantity
|
||||
span style="text-decoration: underline;" Quantity
|
||||
.clearall
|
||||
= "{% if (data.carts.length == 0) { %}"
|
||||
.no-cart-items You have no orders now.
|
||||
= "{% } %}"
|
||||
= "{% _.each(data.carts, function(cart) { %}"
|
||||
.cart-item cart-id="{{cart.id}}"
|
||||
.cart-item-caption
|
||||
= "{{cart.cart_type}}: {{cart.product_info.name}}"
|
||||
.cart-item-price
|
||||
= "$ {{cart.product_info.price}}"
|
||||
.cart-item-quantity
|
||||
= "{{cart.quantity}}"
|
||||
.clearall
|
||||
= "{% }); %}"
|
||||
.clearall
|
||||
.order-right-page
|
||||
a href="#" class="button-orange place-order" PLACE YOUR ORDER
|
||||
br
|
||||
br
|
||||
b.mt10 Order Summary:
|
||||
br
|
||||
.left Items:
|
||||
.right= "${{data.sub_total}}"
|
||||
.clearall
|
||||
.left Shipping & handling
|
||||
.right $0.00
|
||||
br
|
||||
hr
|
||||
.left Total before Tax:
|
||||
.right= "${{data.sub_total}}"
|
||||
.clearall
|
||||
.left Taxes:
|
||||
.right= "${{data.taxes}}"
|
||||
.clearall
|
||||
br
|
||||
hr
|
||||
b.order-total
|
||||
.left Order Total:
|
||||
.right= "${{data.grand_total}}"
|
||||
.clearall
|
||||
br
|
||||
div style="text-align: left;"
|
||||
span By placing your order, you agree to JamKazam's
|
||||
'
|
||||
a href="/corp/terms" terms of service
|
||||
'
|
||||
span and
|
||||
'
|
||||
a href="/corp/returns" returns policy
|
||||
span .
|
||||
|
||||
script type='text/template' id='template-purchased-jam-track'
|
||||
li data-jam-track-id="{{data.jam_track_id}}"
|
||||
|
|
@ -27,6 +27,9 @@ div layout="screen" layout-id="redeemComplete" id="redeemCompleteScreen" class="
|
|||
.download-jamkazam
|
||||
| Click Here to Get the Free JamKazam Application
|
||||
|
||||
a.back-to-browsing href="/client#/jamtrack"
|
||||
| or click here to browse more jamtracks
|
||||
|
||||
.jam-tracks-in-client.hidden
|
||||
|
||||
h2 Congratulations on getting your JamTrack!
|
||||
|
|
|
|||
|
|
@ -48,7 +48,6 @@
|
|||
<%= render "checkout_complete" %>
|
||||
<%= render "redeem_signup" %>
|
||||
<%= render "redeem_complete" %>
|
||||
<%= render "order" %>
|
||||
<%= render "feed" %>
|
||||
<%= render "bands" %>
|
||||
<%= render "musicians" %>
|
||||
|
|
@ -122,14 +121,14 @@
|
|||
JK.currentUserName = '<%= current_user.name %>';
|
||||
JK.currentUserMusician = '<%= current_user.musician %>';
|
||||
JK.currentUserAdmin = <%= current_user.admin %>;
|
||||
JK.currentUserFreeJamTrack = <%= APP_CONFIG.one_free_jamtrack_per_user && current_user.has_redeemable_jamtrack %>
|
||||
JK.currentUserFreeJamTrack = <%= current_user.show_free_jamtrack? %>
|
||||
<% else %>
|
||||
JK.currentUserId = null;
|
||||
JK.currentUserAvatarUrl = null;
|
||||
JK.currentUserName = null;
|
||||
JK.currentUserMusician = null;
|
||||
JK.currentUserAdmin = false;
|
||||
JK.currentUserFreeJamTrack = <%= APP_CONFIG.one_free_jamtrack_per_user && anonymous_user.nil? ? false : anonymous_user.has_redeemable_jamtrack%>
|
||||
JK.currentUserFreeJamTrack = <%= anonymous_user.nil? ? false : anonymous_user.show_free_jamtrack? %>
|
||||
<% end %>
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
- provide(:page_name, 'landing_page full redeem_giftcard')
|
||||
- provide(:description, 'Here you can redeem a gift card and associate it with your JamKazam account.')
|
||||
- provide(:title, 'Redeem a Gift Card')
|
||||
|
||||
= react_component 'RedeemGiftCardPage'
|
||||
|
|
@ -113,13 +113,13 @@
|
|||
JK.currentUserAvatarUrl = JK.resolveAvatarUrl('<%= current_user.photo_url %>');
|
||||
JK.currentUserName = '<%= current_user.name %>';
|
||||
JK.currentUserMusician = '<%= current_user.musician %>';
|
||||
JK.currentUserFreeJamTrack = <%= APP_CONFIG.one_free_jamtrack_per_user && current_user.has_redeemable_jamtrack %>
|
||||
<% else %>
|
||||
JK.currentUserId = null;
|
||||
JK.currentUserFreeJamTrack = <%= current_user.show_free_jamtrack? %>
|
||||
<% else %>
|
||||
JK.currentUserId = null;
|
||||
JK.currentUserAvatarUrl = null;
|
||||
JK.currentUserName = null;
|
||||
JK.currentUserMusician = null;
|
||||
JK.currentUserFreeJamTrack = <%= APP_CONFIG.one_free_jamtrack_per_user && anonymous_user.nil? ? false : anonymous_user.has_redeemable_jamtrack%>
|
||||
JK.currentUserFreeJamTrack = <%= anonymous_user.nil? ? false : anonymous_user.show_free_jamtrack? %>
|
||||
<% end %>
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ if Rails.env == "development" && Rails.application.config.bootstrap_dev_users
|
|||
User.create_dev_user("David", "Wilson", "david@jamkazam.com", "jam123", "Austin", "TX", "US", nil, 'http://www.jamkazam.com/assets/avatars/avatar_david.jpg')
|
||||
User.create_dev_user("Jonathan", "Kolyer", "jonathan@jamkazam.com", "jam123", "Austin", "TX", "US", nil, nil)
|
||||
User.create_dev_user("Oswald", "Becca", "os@jamkazam.com", "jam123", "Austin", "TX", "US", nil, nil)
|
||||
User.create_dev_user("Anthony", "Davis", "anthony@jamkazam.com", "jam123", "Austin", "TX", "US", nil, nil)
|
||||
User.create_dev_user("Steven", "Miers", "steven@jamkazam.com", "jam123", "Austin", "TX", "US", nil, nil)
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@ SampleApp::Application.routes.draw do
|
|||
match '/signin', to: 'sessions#create', via: :post
|
||||
match '/signout', to: 'sessions#destroy', via: :delete
|
||||
|
||||
match '/redeem_giftcard', to: 'landings#redeem_giftcard', via: :get
|
||||
|
||||
# landing pages
|
||||
match '/landing/wb', to: 'landings#watch_bands', via: :get, as: 'landing_wb'
|
||||
match '/landing/wo', to: 'landings#watch_overview', via: :get, as: 'landing_wo'
|
||||
|
|
@ -452,6 +454,9 @@ SampleApp::Application.routes.draw do
|
|||
match '/users/:id/syncs/:user_sync_id' => 'api_user_syncs#show', :via => :get
|
||||
match '/users/:id/syncs/deletables' => 'api_user_syncs#deletables', :via => :post
|
||||
|
||||
# giftcards
|
||||
match '/users/:id/gift_cards' => 'api_users#redeem_giftcard', :via => :post
|
||||
|
||||
|
||||
|
||||
# bands
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ class UserManager < BaseManager
|
|||
any_user = options[:any_user]
|
||||
signup_hint = options[:signup_hint]
|
||||
affiliate_partner = options[:affiliate_partner]
|
||||
gift_card = options[:gift_card]
|
||||
|
||||
recaptcha_failed = false
|
||||
unless options[:skip_recaptcha] # allow callers to opt-of recaptcha
|
||||
|
|
@ -72,7 +73,8 @@ class UserManager < BaseManager
|
|||
affiliate_referral_id: affiliate_referral_id,
|
||||
any_user: any_user,
|
||||
signup_hint: signup_hint,
|
||||
affiliate_partner: affiliate_partner)
|
||||
affiliate_partner: affiliate_partner,
|
||||
gift_card: gift_card)
|
||||
user
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -25,11 +25,14 @@ describe ApiShoppingCartsController do
|
|||
|
||||
it "add_jamtrack" do
|
||||
post :add_jamtrack, {:format => 'json', id: jam_track.id}
|
||||
response.status.should == 201
|
||||
response.status.should == 200
|
||||
end
|
||||
|
||||
it "index" do
|
||||
cart = ShoppingCart.create(user, jam_track)
|
||||
cart.errors.any?.should be_false
|
||||
user.reload
|
||||
user.shopping_carts.count.should eq(1)
|
||||
|
||||
get :index, {:format => 'json'}
|
||||
response.status.should == 200
|
||||
|
|
@ -41,7 +44,7 @@ describe ApiShoppingCartsController do
|
|||
it "remove_cart" do
|
||||
cart = ShoppingCart.create(user, jam_track)
|
||||
delete :remove_cart, {:format => 'json', id: cart.id}
|
||||
response.status.should == 204
|
||||
response.status.should == 200
|
||||
ShoppingCart.find_by_id(cart.id).should be_nil
|
||||
end
|
||||
|
||||
|
|
@ -64,7 +67,9 @@ describe ApiShoppingCartsController do
|
|||
|
||||
it "add_jamtrack" do
|
||||
post :add_jamtrack, {:format => 'json', id: jam_track.id}
|
||||
response.status.should == 201
|
||||
response.status.should == 200
|
||||
user.reload
|
||||
user.shopping_carts.count.should eql(1)
|
||||
end
|
||||
|
||||
it "index" do
|
||||
|
|
@ -80,7 +85,7 @@ describe ApiShoppingCartsController do
|
|||
it "remove_cart" do
|
||||
cart = ShoppingCart.create(user, jam_track)
|
||||
delete :remove_cart, {:format => 'json', id: cart.id}
|
||||
response.status.should == 204
|
||||
response.status.should == 200
|
||||
ShoppingCart.find_by_id(cart.id).should be_nil
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -5,12 +5,134 @@ describe ApiUsersController do
|
|||
|
||||
let (:user) { FactoryGirl.create(:user) }
|
||||
let (:conn) { FactoryGirl.create(:connection, user: user, last_jam_audio_latency: 5) }
|
||||
let (:jam_track) { FactoryGirl.create(:jam_track)}
|
||||
|
||||
|
||||
before(:each) do
|
||||
controller.current_user = user
|
||||
end
|
||||
|
||||
describe "redeem_giftcard" do
|
||||
let!(:gift_card) {FactoryGirl.create(:gift_card)}
|
||||
|
||||
it "can succeed" do
|
||||
post :redeem_giftcard, id:user.id, gift_card: gift_card.code, format:'json'
|
||||
|
||||
response.should be_success
|
||||
|
||||
user.reload
|
||||
gift_card.reload
|
||||
|
||||
user.gift_cards.should eq([gift_card])
|
||||
user.gifted_jamtracks.should eq(10)
|
||||
gift_card.user.should eq(user)
|
||||
end
|
||||
|
||||
it "indicates if you've redeemed it" do
|
||||
gift_card.user = user
|
||||
gift_card.save!
|
||||
|
||||
post :redeem_giftcard, id:user.id, gift_card: gift_card.code, format:'json'
|
||||
|
||||
response.status.should eq(422)
|
||||
error_data = JSON.parse(response.body)
|
||||
error_data['errors']['gift_card'].should eq(["already redeemed by you"])
|
||||
|
||||
user.reload
|
||||
gift_card.reload
|
||||
|
||||
user.gift_cards.should eq([gift_card])
|
||||
user.gifted_jamtracks.should eq(10)
|
||||
gift_card.user.should eq(user)
|
||||
end
|
||||
|
||||
it "indicates if someone else has redeemed it" do
|
||||
user2 = FactoryGirl.create(:user)
|
||||
gift_card.user = user2
|
||||
gift_card.save!
|
||||
|
||||
post :redeem_giftcard, id:user.id, gift_card: gift_card.code, format:'json'
|
||||
|
||||
response.status.should eq(422)
|
||||
error_data = JSON.parse(response.body)
|
||||
error_data['errors']['gift_card'].should eq(["already redeemed by another"])
|
||||
|
||||
user.reload
|
||||
gift_card.reload
|
||||
|
||||
user.gift_cards.should eq([])
|
||||
user.gifted_jamtracks.should eq(0)
|
||||
gift_card.user.should eq(user2)
|
||||
end
|
||||
|
||||
it "marks free shopping cart item as free" do
|
||||
# sort of a 'do nothing' really
|
||||
cart1 = ShoppingCart.add_jam_track_to_cart(user, jam_track)
|
||||
cart1.marked_for_redeem.should eq(1)
|
||||
|
||||
post :redeem_giftcard, id:user.id, gift_card: gift_card.code, format:'json'
|
||||
|
||||
response.should be_success
|
||||
|
||||
user.reload
|
||||
gift_card.reload
|
||||
|
||||
user.gift_cards.should eq([gift_card])
|
||||
user.gifted_jamtracks.should eq(10)
|
||||
gift_card.user.should eq(user)
|
||||
cart1.reload
|
||||
cart1.marked_for_redeem.should eq(1)
|
||||
end
|
||||
|
||||
it "marks non-free shopping cart item as free" do
|
||||
# sort of a 'do nothing' really
|
||||
user.has_redeemable_jamtrack = false
|
||||
user.save!
|
||||
|
||||
cart1 = ShoppingCart.add_jam_track_to_cart(user, jam_track)
|
||||
cart1.marked_for_redeem.should eq(0)
|
||||
|
||||
post :redeem_giftcard, id:user.id, gift_card: gift_card.code, format:'json'
|
||||
|
||||
response.should be_success
|
||||
|
||||
user.reload
|
||||
gift_card.reload
|
||||
|
||||
user.gift_cards.should eq([gift_card])
|
||||
user.gifted_jamtracks.should eq(10)
|
||||
gift_card.user.should eq(user)
|
||||
cart1.reload
|
||||
cart1.marked_for_redeem.should eq(1)
|
||||
end
|
||||
|
||||
it "leaves shopping cart alone if too many items in it for size of new gift card" do
|
||||
# sort of a 'do nothing' really
|
||||
user.has_redeemable_jamtrack = false
|
||||
user.save!
|
||||
|
||||
11.times do |i|
|
||||
jamtrack = FactoryGirl.create(:jam_track)
|
||||
cart1 = ShoppingCart.add_jam_track_to_cart(user, jamtrack)
|
||||
cart1.marked_for_redeem.should eq(0)
|
||||
end
|
||||
|
||||
post :redeem_giftcard, id:user.id, gift_card: gift_card.code, format:'json'
|
||||
|
||||
response.should be_success
|
||||
|
||||
user.reload
|
||||
gift_card.reload
|
||||
|
||||
user.gift_cards.should eq([gift_card])
|
||||
user.gifted_jamtracks.should eq(10)
|
||||
gift_card.user.should eq(user)
|
||||
user.shopping_carts.each do |cart|
|
||||
cart.marked_for_redeem.should eq(0)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "create" do
|
||||
it "successful" do
|
||||
email = 'user_create1@jamkazam.com'
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@ FactoryGirl.define do
|
|||
subscribe_email true
|
||||
last_jam_audio_latency 5
|
||||
reuse_card true
|
||||
has_redeemable_jamtrack true
|
||||
gifted_jamtracks 0
|
||||
|
||||
factory :fan do
|
||||
musician false
|
||||
|
|
@ -837,4 +839,9 @@ FactoryGirl.define do
|
|||
factory :affiliate_legalese, class: 'JamRuby::AffiliateLegalese' do
|
||||
legalese Faker::Lorem.paragraphs(6).join("\n\n")
|
||||
end
|
||||
|
||||
factory :gift_card, class: 'JamRuby::GiftCard' do
|
||||
sequence(:code) {|n| n.to_s}
|
||||
card_type GiftCard::JAM_TRACKS_10
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ describe "Checkout", :js => true, :type => :feature, :capybara_feature => true d
|
|||
let(:user) { FactoryGirl.create(:user) }
|
||||
let(:jamtrack_acdc_backinblack) { @jamtrack_acdc_backinblack }
|
||||
let(:jamtrack_pearljam_evenflow) { @jamtrack_pearljam_evenflow }
|
||||
let(:jamtrack_led_zeppelin_kashmir) {@jamtrack_led_zeppelin_kashmir}
|
||||
|
||||
let(:billing_info) {
|
||||
{
|
||||
|
|
@ -35,8 +36,11 @@ describe "Checkout", :js => true, :type => :feature, :capybara_feature => true d
|
|||
@recurlyClient = RecurlyClient.new
|
||||
@created_accounts = []
|
||||
|
||||
JamTrack.delete_all
|
||||
|
||||
@jamtrack_acdc_backinblack = FactoryGirl.create(:jam_track, name: 'Back in Black', original_artist: 'AC/DC', sales_region: 'United States', make_track: true, plan_code: 'jamtrack-acdc-backinblack')
|
||||
@jamtrack_pearljam_evenflow = FactoryGirl.create(:jam_track, name: 'Even Flow', original_artist: 'Pearl Jam', sales_region: 'United States', make_track: true, plan_code: 'jamtrack-pearljam-evenflow')
|
||||
@jamtrack_led_zeppelin_kashmir = FactoryGirl.create(:jam_track, name: 'Kashmir', original_artist: 'Led Zeppelin', sales_region: 'United States', make_track: true, plan_code: 'jamtrack-led-zeppelin-kashmir')
|
||||
|
||||
# make sure plans are there
|
||||
@recurlyClient.create_jam_track_plan(@jamtrack_acdc_backinblack) unless @recurlyClient.find_jam_track_plan(@jamtrack_acdc_backinblack)
|
||||
|
|
@ -1225,4 +1229,98 @@ describe "Checkout", :js => true, :type => :feature, :capybara_feature => true d
|
|||
acdc_sale.sale.should eq(sale)
|
||||
end
|
||||
end
|
||||
|
||||
describe "gift cards" do
|
||||
|
||||
it "user has both redeemable jamtrack and gift card jamtracks" do
|
||||
|
||||
jamtrack_led_zeppelin_kashmir.touch
|
||||
jamtrack_pearljam_evenflow.touch
|
||||
|
||||
user.gifted_jamtracks = 1
|
||||
user.save!
|
||||
|
||||
fast_signin(user, "/client?song=#{jamtrack_acdc_backinblack.name}#/jamtrack/search")
|
||||
find('h1', text: 'jamtracks')
|
||||
find("a.jamtrack-add-cart[data-jamtrack-id=\"#{jamtrack_acdc_backinblack.id}\"]", text: 'GET IT FREE!').trigger(:click)
|
||||
find('.jam-tracks-in-browser')
|
||||
user.reload
|
||||
user.has_redeemable_jamtrack.should be_false
|
||||
|
||||
find('a.back-to-browsing').trigger(:click)
|
||||
find('h1', text: 'search jamtracks')
|
||||
find('.search-controls .Select-control').trigger(:mousedown)
|
||||
# wait for the 'Type to search' prompt to show
|
||||
find('.search-controls .Select-search-prompt')
|
||||
find('.search-by-string-btn').trigger(:click)
|
||||
find('.jamtrack-record[data-jamtrack-id="' + jamtrack_led_zeppelin_kashmir.id + '"]')
|
||||
find("a.jamtrack-add-cart[data-jamtrack-id=\"#{jamtrack_led_zeppelin_kashmir.id}\"]", text: 'GET IT FREE!').trigger(:click)
|
||||
find('.jam-tracks-in-browser')
|
||||
sleep 2
|
||||
user.reload
|
||||
user.has_redeemable_jamtrack.should be_false
|
||||
user.gifted_jamtracks.should eq(0)
|
||||
|
||||
find('a.back-to-browsing').trigger(:click)
|
||||
find('h1', text: 'search jamtracks')
|
||||
find('.search-controls .Select-control').trigger(:mousedown)
|
||||
# wait for the 'Type to search' prompt to show
|
||||
find('.search-controls .Select-search-prompt')
|
||||
find('.search-by-string-btn').trigger(:click)
|
||||
find('.jamtrack-record[data-jamtrack-id="' + jamtrack_pearljam_evenflow.id + '"]')
|
||||
find("a.jamtrack-add-cart[data-jamtrack-id=\"#{jamtrack_pearljam_evenflow.id}\"]", text: 'ADD TO CART').trigger(:click)
|
||||
|
||||
find('h1', text: 'shopping cart')
|
||||
find('.cart-item-caption', text: "JamTrack: #{jamtrack_pearljam_evenflow.name}")
|
||||
find('.cart-item-price', text: "$ #{jamtrack_pearljam_evenflow.price}")
|
||||
find('.shopping-sub-total', text:"Subtotal:$ #{jamtrack_pearljam_evenflow.price}")
|
||||
|
||||
# attempt to checkout
|
||||
find('a.button-orange', text: 'PROCEED TO CHECKOUT').trigger(:click)
|
||||
|
||||
# should be at payment page
|
||||
|
||||
# this should take us to the payment screen
|
||||
find('p.payment-prompt')
|
||||
|
||||
# fill out all billing info and account info
|
||||
fill_in 'billing-first-name', with: 'Seth'
|
||||
fill_in 'billing-last-name', with: 'Call'
|
||||
fill_in 'billing-address1', with: '10704 Buckthorn Drive'
|
||||
fill_in 'billing-city', with: 'Austin'
|
||||
fill_in 'billing-state', with: 'Texas'
|
||||
fill_in 'billing-zip', with: '78759'
|
||||
fill_in 'card-number', with: '4111111111111111'
|
||||
fill_in 'card-verify', with: '012'
|
||||
#jk_select('US', '#checkoutPaymentScreen #divBillingCountry #billing-country')
|
||||
|
||||
find('#payment-info-next').trigger(:click)
|
||||
|
||||
# should be taken straight to order page
|
||||
|
||||
# now see order page, and everything should no longer appear free
|
||||
find('p.order-prompt')
|
||||
find('.order-items-value.order-total', text:'$1.99')
|
||||
find('.order-items-value.shipping-handling', text:'$0.00')
|
||||
find('.order-items-value.sub-total', text:'$1.99')
|
||||
find('.order-items-value.taxes', text:'$0.16')
|
||||
find('.order-items-value.grand-total', text:'$2.15')
|
||||
|
||||
# click the ORDER button
|
||||
find('.place-order-center a.button-orange.place-order').trigger(:click)
|
||||
|
||||
# and now we should see confirmation, and a notice that we are in a normal browser
|
||||
find('.thanks-detail.jam-tracks-in-browser')
|
||||
|
||||
user.reload
|
||||
|
||||
sleep 3 # challenge to all comers! WHY DO I HAVE TO SLEEP FOR THIS ASSERTION TO BE TRUE! GAH . and 1 second won't do it
|
||||
|
||||
user.reload
|
||||
user.has_redeemable_jamtrack.should be_false
|
||||
user.gifted_jamtracks.should eq(0)
|
||||
user.purchased_jamtracks_count.should eq(3)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ require 'spec_helper'
|
|||
|
||||
describe "JamTrack Landing", :js => true, :type => :feature, :capybara_feature => true do
|
||||
|
||||
let(:user) { FactoryGirl.create(:user, has_redeemable_jamtrack: true) }
|
||||
let(:user) { FactoryGirl.create(:user, free_jamtracks: 1) }
|
||||
let(:jt_us) { FactoryGirl.create(:jam_track, :name=>'jt_us', sales_region: 'United States', make_track: true, original_artist: "foobar") }
|
||||
let(:jt_ww) { FactoryGirl.create(:jam_track, :name=>'jt_ww', sales_region: 'Worldwide', make_track: true, original_artist: "barfoo") }
|
||||
let(:jt_rock) { FactoryGirl.create(:jam_track, :name=>'jt_rock', genres: [JamRuby::Genre.find('avante-garde')], make_track: true, original_artist: "badfood") }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ require 'spec_helper'
|
|||
|
||||
describe "JamTrack Shopping", :js => true, :type => :feature, :capybara_feature => true do
|
||||
|
||||
let(:user) { FactoryGirl.create(:user, has_redeemable_jamtrack: false) }
|
||||
let(:user) { FactoryGirl.create(:user, gifted_jamtracks: 0, has_redeemable_jamtrack: false) }
|
||||
let(:jt_us) { FactoryGirl.create(:jam_track, :name=>'jt_us', sales_region: 'Worldwide', make_track: true, original_artist: "foobar") }
|
||||
let(:jt_ww) { FactoryGirl.create(:jam_track, :name=>'jt_ww', sales_region: 'Worldwide', make_track: true, original_artist: "barfoo") }
|
||||
let(:jt_rock) { FactoryGirl.create(:jam_track, :name=>'jt_rock', genres: [JamRuby::Genre.find('rock')], make_track: true, original_artist: "badfood") }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,169 @@
|
|||
require 'spec_helper'
|
||||
|
||||
# tests what happens when the websocket connection goes away
|
||||
describe "Redeem Gift Card", :js => true, :type => :feature, :capybara_feature => true do
|
||||
|
||||
subject { page }
|
||||
|
||||
let(:user1) { FactoryGirl.create(:user) }
|
||||
let(:jamtrack_acdc_backinblack) { @jamtrack_acdc_backinblack }
|
||||
let(:gift_card) {FactoryGirl.create(:gift_card)}
|
||||
|
||||
before(:all) do
|
||||
User.delete_all
|
||||
JamTrack.delete_all
|
||||
|
||||
@jamtrack_acdc_backinblack = FactoryGirl.create(:jam_track, name: 'Back in Black', original_artist: 'AC/DC', sales_region: 'United States', make_track: true, plan_code: 'jamtrack-acdc-backinblack')
|
||||
end
|
||||
|
||||
describe "not logged in" do
|
||||
it "suceeeds" do
|
||||
visit '/redeem_giftcard'
|
||||
|
||||
find('h2', text:'Redeem Your Gift Card')
|
||||
fill_in "code", with: gift_card.code
|
||||
fill_in "email", with: "gifter1@jamkazam.com"
|
||||
fill_in "password", with: "jam123"
|
||||
find('.redeem-container ins').trigger(:click)
|
||||
|
||||
find('button.redeem-giftcard').trigger(:click)
|
||||
|
||||
find('.done-action a.go-browse').trigger(:click)
|
||||
|
||||
find('.no-free-jamtrack')
|
||||
|
||||
user = User.find_by_email("gifter1@jamkazam.com")
|
||||
gift_card.reload
|
||||
gift_card.user.should eq(user)
|
||||
user.reload
|
||||
user.gifted_jamtracks.should eq(10)
|
||||
end
|
||||
|
||||
it "validates correctly" do
|
||||
visit '/redeem_giftcard'
|
||||
|
||||
find('h2', text:'Redeem Your Gift Card')
|
||||
|
||||
find('button.redeem-giftcard').trigger(:click)
|
||||
|
||||
find('.errors.active', text: "Email can't be blank")
|
||||
|
||||
find('h2', text:'Redeem Your Gift Card')
|
||||
fill_in "code", with: gift_card.code
|
||||
fill_in "email", with: "gifter2@jamkazam.com"
|
||||
fill_in "password", with: "jam123"
|
||||
find('.redeem-container ins').trigger(:click)
|
||||
|
||||
find('button.redeem-giftcard').trigger(:click)
|
||||
|
||||
find('.done-action a.go-browse').trigger(:click)
|
||||
|
||||
find('.no-free-jamtrack')
|
||||
|
||||
user = User.find_by_email("gifter2@jamkazam.com")
|
||||
gift_card.reload
|
||||
gift_card.user.should eq(user)
|
||||
user.reload
|
||||
user.gifted_jamtracks.should eq(10)
|
||||
end
|
||||
|
||||
it "converts shopping cart items to free" do
|
||||
|
||||
visit '/redeem_giftcard'
|
||||
|
||||
anon_user_id = page.driver.cookies["user_uuid"]
|
||||
anon_user = AnonymousUser.new(anon_user_id.value, {})
|
||||
|
||||
cart = ShoppingCart.add_jam_track_to_cart(anon_user, jamtrack_acdc_backinblack)
|
||||
cart.skip_mix_check = true
|
||||
cart.marked_for_redeem = 0
|
||||
cart.save!
|
||||
|
||||
find('h2', text:'Redeem Your Gift Card')
|
||||
fill_in "code", with: gift_card.code
|
||||
fill_in "email", with: "gifter_carted1@jamkazam.com"
|
||||
fill_in "password", with: "jam123"
|
||||
find('.redeem-container ins').trigger(:click)
|
||||
|
||||
find('button.redeem-giftcard').trigger(:click)
|
||||
|
||||
find('.done-action a.go-browse').trigger(:click)
|
||||
|
||||
find('.no-free-jamtrack')
|
||||
|
||||
cart.reload
|
||||
cart.marked_for_redeem.should eq(1)
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
describe "logged in" do
|
||||
it "succeeds" do
|
||||
fast_signin(user1, '/redeem_giftcard')
|
||||
|
||||
find('h2', text:'Redeem Your Gift Card')
|
||||
fill_in "code", with: gift_card.code
|
||||
|
||||
find('button.redeem-giftcard').trigger(:click)
|
||||
|
||||
find('.done-action a.go-browse').trigger(:click)
|
||||
|
||||
find('.no-free-jamtrack')
|
||||
|
||||
gift_card.reload
|
||||
gift_card.user.should eq(user1)
|
||||
user1.reload
|
||||
user1.gifted_jamtracks.should eq(10)
|
||||
end
|
||||
end
|
||||
|
||||
describe "logged in" do
|
||||
it "validates" do
|
||||
fast_signin(user1, '/redeem_giftcard')
|
||||
|
||||
find('h2', text:'Redeem Your Gift Card')
|
||||
|
||||
find('button.redeem-giftcard').trigger(:click)
|
||||
|
||||
find('.errors.active', text: "Gift Card Code does not exist")
|
||||
|
||||
fill_in "code", with: gift_card.code
|
||||
|
||||
find('button.redeem-giftcard').trigger(:click)
|
||||
|
||||
find('.done-action a.go-browse').trigger(:click)
|
||||
|
||||
find('.no-free-jamtrack')
|
||||
|
||||
gift_card.reload
|
||||
gift_card.user.should eq(user1)
|
||||
user1.reload
|
||||
user1.gifted_jamtracks.should eq(10)
|
||||
end
|
||||
|
||||
it "converts shopping cart items to free" do
|
||||
|
||||
fast_signin(user1, '/redeem_giftcard')
|
||||
cart = ShoppingCart.add_jam_track_to_cart(user1, jamtrack_acdc_backinblack)
|
||||
cart.skip_mix_check = true
|
||||
cart.marked_for_redeem = 0
|
||||
cart.save!
|
||||
|
||||
visit '/redeem_giftcard'
|
||||
|
||||
find('h2', text:'Redeem Your Gift Card')
|
||||
|
||||
fill_in "code", with: gift_card.code
|
||||
find('button.redeem-giftcard').trigger(:click)
|
||||
find('.done-action a.go-browse').trigger(:click)
|
||||
find('.no-free-jamtrack')
|
||||
|
||||
gift_card.reload
|
||||
gift_card.user.should eq(user1)
|
||||
user1.reload
|
||||
user1.gifted_jamtracks.should eq(10)
|
||||
cart.reload
|
||||
cart.marked_for_redeem.should eq(1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -707,4 +707,77 @@ describe UserManager do
|
|||
user.errors.any?.should be_false
|
||||
end # it "passes when facebook signup"
|
||||
end # describe "with nocaptcha"
|
||||
|
||||
describe "gift_card" do
|
||||
|
||||
let(:gift_card) {FactoryGirl.create(:gift_card)}
|
||||
|
||||
it "can succeed when specified" do
|
||||
user = @user_manager.signup(remote_ip: "1.2.3.4",
|
||||
first_name: "bob",
|
||||
last_name: "smith",
|
||||
email: "giftcard1@jamkazam.com",
|
||||
password: "foobar",
|
||||
password_confirmation: "foobar",
|
||||
terms_of_service: true,
|
||||
instruments: @instruments,
|
||||
musician: true,
|
||||
location: @loca,
|
||||
signup_confirm_url: "http://localhost:3000/confirm",
|
||||
gift_card: gift_card.code)
|
||||
user.errors.any?.should be_false
|
||||
gift_card.reload
|
||||
gift_card.user.should eq(user)
|
||||
user = User.find(user.id)
|
||||
user.has_redeemable_jamtrack.should be_true
|
||||
user.gifted_jamtracks.should eq(10)
|
||||
user.gift_cards[0].should eq(gift_card)
|
||||
end
|
||||
|
||||
it "will fail if invalid gift card code" do
|
||||
user = @user_manager.signup(remote_ip: "1.2.3.4",
|
||||
first_name: "bob",
|
||||
last_name: "smith",
|
||||
email: "giftcard2@jamkazam.com",
|
||||
password: "foobar",
|
||||
password_confirmation: "foobar",
|
||||
terms_of_service: true,
|
||||
instruments: @instruments,
|
||||
musician: true,
|
||||
location: @loca,
|
||||
signup_confirm_url: "http://localhost:3000/confirm",
|
||||
gift_card: '')
|
||||
user.errors.any?.should be_true
|
||||
user.errors["gift_card"].should eq(["not found"])
|
||||
user.gifted_jamtracks.should eq(0)
|
||||
gift_card.reload
|
||||
gift_card.user.should be_nil
|
||||
|
||||
user.gift_cards.length.should eq(0)
|
||||
end
|
||||
|
||||
it "will fail if used gift card" do
|
||||
gift_card.user = FactoryGirl.create(:user)
|
||||
|
||||
user = @user_manager.signup(remote_ip: "1.2.3.4",
|
||||
first_name: "bob",
|
||||
last_name: "smith",
|
||||
email: "giftcard2@jamkazam.com",
|
||||
password: "foobar",
|
||||
password_confirmation: "foobar",
|
||||
terms_of_service: true,
|
||||
instruments: @instruments,
|
||||
musician: true,
|
||||
location: @loca,
|
||||
signup_confirm_url: "http://localhost:3000/confirm",
|
||||
gift_card: '')
|
||||
user.errors.any?.should be_true
|
||||
user.errors["gift_card"].should eq(["not found"])
|
||||
user.gifted_jamtracks.should eq(0)
|
||||
gift_card.reload
|
||||
gift_card.user.should be_nil
|
||||
|
||||
user.gift_cards.length.should eq(0)
|
||||
end
|
||||
end
|
||||
end # test
|
||||
|
|
|
|||
|
|
@ -627,7 +627,7 @@ describe "Active Music Session API ", :type => :api do
|
|||
music_session = JSON.parse(last_response.body)[0]
|
||||
|
||||
# start a recording
|
||||
post "/api/recordings/start", {:format => :json, :music_session_id => music_session['id'] }.to_json, "CONTENT_TYPE" => 'application/json'
|
||||
post "/api/recordings/start", {:format => :json, :music_session_id => music_session['id'], record_video:false }.to_json, "CONTENT_TYPE" => 'application/json'
|
||||
last_response.status.should eql(201)
|
||||
|
||||
# user 2 should not be able to join
|
||||
|
|
|
|||
Loading…
Reference in New Issue