From 939f8cdf82bc31cbf7ae895297102c611ba31730 Mon Sep 17 00:00:00 2001 From: Seth Call Date: Fri, 15 May 2015 12:34:35 -0500 Subject: [PATCH 01/13] * VRFS-3255 (shopping cart only on /client) , VRFS-3253 - frictionless shopping done with tests --- db/manifest | 1 + db/up/optimized_redeemption.sql | 13 + ruby/lib/jam_ruby.rb | 1 + .../jam_ruby/models/active_music_session.rb | 1 + ruby/lib/jam_ruby/models/anonymous_user.rb | 11 +- ruby/lib/jam_ruby/models/jam_track_right.rb | 73 +++++ .../jam_ruby/models/machine_fingerprint.rb | 35 ++ ruby/lib/jam_ruby/models/sale.rb | 141 ++++---- ruby/lib/jam_ruby/models/shopping_cart.rb | 12 + ruby/lib/jam_ruby/models/signup_hint.rb | 2 + ruby/lib/jam_ruby/models/user.rb | 30 +- .../jam_ruby/models/jam_track_right_spec.rb | 120 +++++++ ruby/spec/jam_ruby/models/sale_spec.rb | 46 +-- .../jam_ruby/models/shopping_cart_spec.rb | 42 +-- ruby/spec/jam_ruby/models/signup_hint_spec.rb | 2 +- web/app/assets/javascripts/application.js | 3 + .../assets/javascripts/checkout_payment.js | 14 - web/app/assets/javascripts/checkout_signin.js | 21 +- .../javascripts/checkout_utils.js.coffee | 10 + .../javascripts/dialog/openJamTrackDialog.js | 1 + .../assets/javascripts/dialog/signinDialog.js | 15 +- .../javascripts/download_jamtrack.js.coffee | 23 +- .../javascripts/everywhere/everywhere.js | 1 + web/app/assets/javascripts/jam_rest.js | 22 ++ .../javascripts/jam_track_preview.js.coffee | 2 +- .../javascripts/jam_track_screen.js.coffee | 33 +- web/app/assets/javascripts/redeem_complete.js | 264 +++++++++++++++ web/app/assets/javascripts/redeem_signup.js | 244 ++++++++++++++ web/app/assets/javascripts/session.js | 1 + web/app/assets/javascripts/sessionModel.js | 1 + web/app/assets/javascripts/shopping_cart.js | 38 ++- .../assets/javascripts/web/signin_helper.js | 24 +- web/app/assets/stylesheets/client/client.css | 3 + .../stylesheets/client/content.css.scss | 50 +-- .../stylesheets/client/jamtrack.css.scss | 92 +++++- .../client/redeem_complete.css.scss | 123 +++++++ .../stylesheets/client/redeem_signup.css.scss | 247 ++++++++++++++ .../stylesheets/users/signinCommon.css.scss | 4 + .../controllers/api_jam_tracks_controller.rb | 28 +- web/app/controllers/api_recurly_controller.rb | 13 +- .../api_shopping_carts_controller.rb | 9 + web/app/controllers/api_users_controller.rb | 37 +++ web/app/controllers/application_controller.rb | 1 + web/app/controllers/clients_controller.rb | 1 + web/app/controllers/sessions_controller.rb | 33 +- web/app/controllers/users_controller.rb | 17 - web/app/helpers/sessions_helper.rb | 28 +- web/app/views/api_users/show.rabl | 2 +- web/app/views/clients/_jamtrack.html.slim | 83 ----- .../views/clients/_jamtrack_browse.html.slim | 86 +++++ .../views/clients/_redeem_complete.html.slim | 47 +++ .../views/clients/_redeem_signup.html.slim | 67 ++++ web/app/views/clients/index.html.erb | 16 +- web/app/views/layouts/client.html.erb | 2 +- web/app/views/users/_user_dropdown.html.erb | 2 +- web/app/views/users/new.html.erb | 14 +- web/config/routes.rb | 1 + web/lib/user_manager.rb | 5 +- .../controllers/api_users_controller_spec.rb | 49 +++ web/spec/features/checkout_spec.rb | 303 +++++++++++++----- web/spec/features/redeem_spec.rb | 0 61 files changed, 2198 insertions(+), 412 deletions(-) create mode 100644 db/up/optimized_redeemption.sql create mode 100644 ruby/lib/jam_ruby/models/machine_fingerprint.rb create mode 100644 web/app/assets/javascripts/redeem_complete.js create mode 100644 web/app/assets/javascripts/redeem_signup.js create mode 100644 web/app/assets/stylesheets/client/redeem_complete.css.scss create mode 100644 web/app/assets/stylesheets/client/redeem_signup.css.scss delete mode 100644 web/app/views/clients/_jamtrack.html.slim create mode 100644 web/app/views/clients/_jamtrack_browse.html.slim create mode 100644 web/app/views/clients/_redeem_complete.html.slim create mode 100644 web/app/views/clients/_redeem_signup.html.slim create mode 100644 web/spec/features/redeem_spec.rb diff --git a/db/manifest b/db/manifest index 223d8cc39..48ba477b9 100755 --- a/db/manifest +++ b/db/manifest @@ -283,3 +283,4 @@ payment_history.sql jam_track_right_private_key.sql first_downloaded_jamtrack_at.sql signing.sql +optimized_redeemption.sql \ No newline at end of file diff --git a/db/up/optimized_redeemption.sql b/db/up/optimized_redeemption.sql new file mode 100644 index 000000000..476fef48d --- /dev/null +++ b/db/up/optimized_redeemption.sql @@ -0,0 +1,13 @@ +CREATE TABLE machine_fingerprints ( + id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(), + user_id VARCHAR(64) NOT NULL REFERENCES users(id) ON DELETE CASCADE, + fingerprint VARCHAR(20000) NOT NULL UNIQUE, + when_taken VARCHAR NOT NULL, + print_type VARCHAR NOT NULL, + remote_ip VARCHAR(1000) NOT NULL, + jam_track_right_id BIGINT REFERENCES jam_track_rights(id) ON DELETE SET NULL, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP +); + +ALTER TABLE jam_track_rights ADD COLUMN redeemed_and_fingerprinted BOOLEAN DEFAULT FALSE; \ No newline at end of file diff --git a/ruby/lib/jam_ruby.rb b/ruby/lib/jam_ruby.rb index f6fac2e21..09b125e3d 100755 --- a/ruby/lib/jam_ruby.rb +++ b/ruby/lib/jam_ruby.rb @@ -103,6 +103,7 @@ require "jam_ruby/models/genre" require "jam_ruby/models/user" require "jam_ruby/models/anonymous_user" require "jam_ruby/models/signup_hint" +require "jam_ruby/models/machine_fingerprint" require "jam_ruby/models/rsvp_request" require "jam_ruby/models/rsvp_slot" require "jam_ruby/models/rsvp_request_rsvp_slot" diff --git a/ruby/lib/jam_ruby/models/active_music_session.rb b/ruby/lib/jam_ruby/models/active_music_session.rb index ce9768b9a..182157e23 100644 --- a/ruby/lib/jam_ruby/models/active_music_session.rb +++ b/ruby/lib/jam_ruby/models/active_music_session.rb @@ -774,6 +774,7 @@ module JamRuby self.opening_jam_track = true self.save self.opening_jam_track = false + #self.tick_track_changes end def close_jam_track diff --git a/ruby/lib/jam_ruby/models/anonymous_user.rb b/ruby/lib/jam_ruby/models/anonymous_user.rb index 3d3d6e656..ff7b60730 100644 --- a/ruby/lib/jam_ruby/models/anonymous_user.rb +++ b/ruby/lib/jam_ruby/models/anonymous_user.rb @@ -4,10 +4,11 @@ module JamRuby class AnonymousUser - attr_accessor :id + attr_accessor :id, :cookies - def initialize(id) + def initialize(id, cookies) @id = id + @cookies = cookies end def shopping_carts @@ -23,7 +24,11 @@ module JamRuby end def has_redeemable_jamtrack - APP_CONFIG.one_free_jamtrack_per_user + APP_CONFIG.one_free_jamtrack_per_user && !@cookies[:redeemed_jamtrack] + end + + def signup_hint + SignupHint.find_by_anonymous_user_id(@id) end end end diff --git a/ruby/lib/jam_ruby/models/jam_track_right.rb b/ruby/lib/jam_ruby/models/jam_track_right.rb index 9150786ab..98ea69a51 100644 --- a/ruby/lib/jam_ruby/models/jam_track_right.rb +++ b/ruby/lib/jam_ruby/models/jam_track_right.rb @@ -3,6 +3,9 @@ module JamRuby # describes what users have rights to which tracks class JamTrackRight < ActiveRecord::Base include JamRuby::S3ManagerMixin + + @@log = Logging.logger[JamTrackRight] + attr_accessible :user, :jam_track, :user_id, :jam_track_id, :download_count attr_accessible :user_id, :jam_track_id, as: :admin attr_accessible :url_48, :md5_48, :length_48, :url_44, :md5_44, :length_44 @@ -211,6 +214,76 @@ module JamRuby .where('jam_tracks.id IN (?)', jamtracks) end + def guard_against_fraud(current_user, fingerprint, remote_ip) + if current_user.blank? + return "no user specified" + end + + # admin's get to skip fraud check + if current_user.admin + return nil + end + + if fingerprint.nil? || fingerprint.empty? + return "no fingerprint specified" + end + + all_fingerprint = fingerprint[:all] + running_fingerprint = fingerprint[:running] + + if all_fingerprint.blank? + return "no all fingerprint specified" + end + + if running_fingerprint.blank? + return "no running fingerprint specified" + end + + if redeemed && !redeemed_and_fingerprinted + # if this is a free JamTrack, we need to check for fraud or accidental misuse + + # first of all, does this user have any other JamTracks aside from this one that have already been redeemed it and are marked free? + other_redeemed_freebie = JamTrackRight.where(redeemed:true).where(redeemed_and_fingerprinted: true).where('id != ?', id).where(user_id: current_user.id).first + + if other_redeemed_freebie + return "already redeemed another" + end + + # can we find a jam track that belongs to someone else with the same fingerprint + match = MachineFingerprint.find_by_fingerprint(all_fingerprint) + + if match && match.user != current_user + AdminMailer.alerts(subject: "'All' fingerprint collision by #{current_user.name}", + body: "MachineFingerprint #{match.inspect}\n\nCurrent User: #{current_user.admin_url}") + + # try to record the other fingerprint + MachineFingerprint.create(running_fingerprint, current_user, MachineFingerprint::TAKEN_ON_FRAUD_CONFLICT, MachineFingerprint::PRINT_TYPE_ACTIVE, remote_ip, self) + return "other user has 'all' fingerprint" + end + + match = MachineFingerprint.find_by_fingerprint(running_fingerprint) + + if match && match.user != current_user + AdminMailer.alerts(subject: "'Running' fingerprint collision by #{current_user.name}", + body: "MachineFingerprint #{match.inspect}\n\nCurrent User: #{current_user.admin_url}") + # try to record the other fingerprint + MachineFingerprint.create(all_fingerprint, current_user, MachineFingerprint::TAKEN_ON_FRAUD_CONFLICT, MachineFingerprint::PRINT_TYPE_ALL, remote_ip, self) + return "other user has 'running' fingerprint" + end + + # we made it past all checks; let's slap on the redeemed_fingerprint + self.redeemed_and_fingerprinted = true + + MachineFingerprint.create(all_fingerprint, current_user, MachineFingerprint::TAKEN_ON_SUCCESSFUL_DOWNLOAD, MachineFingerprint::PRINT_TYPE_ALL, remote_ip, self) + MachineFingerprint.create(running_fingerprint, current_user, MachineFingerprint::TAKEN_ON_SUCCESSFUL_DOWNLOAD, MachineFingerprint::PRINT_TYPE_ACTIVE, remote_ip, self) + + save! + end + + + nil + end + def self.stats stats = {} diff --git a/ruby/lib/jam_ruby/models/machine_fingerprint.rb b/ruby/lib/jam_ruby/models/machine_fingerprint.rb new file mode 100644 index 000000000..7d0076e50 --- /dev/null +++ b/ruby/lib/jam_ruby/models/machine_fingerprint.rb @@ -0,0 +1,35 @@ +module JamRuby + class MachineFingerprint < ActiveRecord::Base + + @@log = Logging.logger[MachineFingerprint] + + belongs_to :user, :class_name => "JamRuby::User" + belongs_to :jam_track_right, :class_name => "JamRuby::JamTrackRight" + + TAKEN_ON_SUCCESSFUL_DOWNLOAD = 'dl' + TAKEN_ON_FRAUD_CONFLICT = 'fc' + + PRINT_TYPE_ALL = 'a' + PRINT_TYPE_ACTIVE = 'r' + + + validates :user, presence:true + validates :when_taken, :inclusion => {:in => [TAKEN_ON_SUCCESSFUL_DOWNLOAD, TAKEN_ON_FRAUD_CONFLICT]} + validates :fingerprint, presence: true, uniqueness:true + validates :print_type, presence: true, :inclusion => {:in =>[PRINT_TYPE_ALL, PRINT_TYPE_ACTIVE]} + validates :remote_ip, presence: true + + def self.create(fingerprint, user, when_taken, print_type, remote_ip, jam_track_right = nil) + mf = MachineFingerprint.new + mf.fingerprint = fingerprint + mf.user = user + mf.when_taken = when_taken + mf.print_type = print_type + mf.remote_ip = remote_ip + mf.jam_track_right = jam_track_right + unless mf.save + @@log.error("unable to create machine fingerprint: #{mf.errors.inspect}") + end + end + end +end \ No newline at end of file diff --git a/ruby/lib/jam_ruby/models/sale.rb b/ruby/lib/jam_ruby/models/sale.rb index 732bd45bb..bca02f526 100644 --- a/ruby/lib/jam_ruby/models/sale.rb +++ b/ruby/lib/jam_ruby/models/sale.rb @@ -128,6 +128,10 @@ module JamRuby # just a pain to implement end + def self.is_only_freebie(shopping_carts_jam_tracks) + shopping_carts_jam_tracks.length == 1 && shopping_carts_jam_tracks[0].product_info[:free] + end + # this method will either return a valid sale, or throw a RecurlyClientError or ActiveRecord validation error (save! failed) # it may return an nil sale if the JamTrack(s) specified by the shopping carts are already owned def self.order_jam_tracks(current_user, shopping_carts_jam_tracks) @@ -139,58 +143,76 @@ module JamRuby sale = create_jam_track_sale(current_user) if sale.valid? - account = client.get_account(current_user) - if account.present? + if is_only_freebie(shopping_carts_jam_tracks) + sale.process_jam_tracks(current_user, shopping_carts_jam_tracks, nil) - purge_pending_adjustments(account) + sale.recurly_subtotal_in_cents = 0 + sale.recurly_tax_in_cents = 0 + sale.recurly_total_in_cents = 0 + sale.recurly_currency = 'USD' - created_adjustments = sale.process_jam_tracks(current_user, shopping_carts_jam_tracks, account) + sale_line_item = sale.sale_line_items[0] + sale_line_item.recurly_tax_in_cents = 0 + sale_line_item.recurly_total_in_cents = 0 + sale_line_item.recurly_currency = 'USD' + sale_line_item.recurly_discount_in_cents = 0 + sale.save - # now invoice the sale ... almost done + else - begin - invoice = account.invoice! - sale.recurly_invoice_id = invoice.uuid - sale.recurly_invoice_number = invoice.invoice_number + account = client.get_account(current_user) + if account.present? - # now slap in all the real tax/purchase totals - sale.recurly_subtotal_in_cents = invoice.subtotal_in_cents - sale.recurly_tax_in_cents = invoice.tax_in_cents - sale.recurly_total_in_cents = invoice.total_in_cents - sale.recurly_currency = invoice.currency + purge_pending_adjustments(account) + + created_adjustments = sale.process_jam_tracks(current_user, shopping_carts_jam_tracks, account) + + # now invoice the sale ... almost done + + begin + invoice = account.invoice! + sale.recurly_invoice_id = invoice.uuid + sale.recurly_invoice_number = invoice.invoice_number + + # now slap in all the real tax/purchase totals + sale.recurly_subtotal_in_cents = invoice.subtotal_in_cents + sale.recurly_tax_in_cents = invoice.tax_in_cents + sale.recurly_total_in_cents = invoice.total_in_cents + sale.recurly_currency = invoice.currency + + # and resolve against sale_line_items + sale.sale_line_items.each do |sale_line_item| + found_line_item = false + invoice.line_items.each do |line_item| + if line_item.uuid == sale_line_item.recurly_adjustment_uuid + sale_line_item.recurly_tax_in_cents = line_item.tax_in_cents + sale_line_item.recurly_total_in_cents =line_item.total_in_cents + sale_line_item.recurly_currency = line_item.currency + sale_line_item.recurly_discount_in_cents = line_item.discount_in_cents + found_line_item = true + break + end - # and resolve against sale_line_items - sale.sale_line_items.each do |sale_line_item| - found_line_item = false - invoice.line_items.each do |line_item| - if line_item.uuid == sale_line_item.recurly_adjustment_uuid - sale_line_item.recurly_tax_in_cents = line_item.tax_in_cents - sale_line_item.recurly_total_in_cents =line_item.total_in_cents - sale_line_item.recurly_currency = line_item.currency - sale_line_item.recurly_discount_in_cents = line_item.discount_in_cents - found_line_item = true - break end + if !found_line_item + @@log.error("can't find line item #{sale_line_item.recurly_adjustment_uuid}") + puts "CANT FIND LINE ITEM" + end end - if !found_line_item - @@log.error("can't find line item #{sale_line_item.recurly_adjustment_uuid}") - puts "CANT FIND LINE ITEM" + unless sale.save + raise RecurlyClientError, "Invalid sale (at end)." end + rescue Recurly::Resource::Invalid => e + # this exception is thrown by invoice! if the invoice is invalid + sale.rollback_adjustments(current_user, created_adjustments) + sale = nil + raise ActiveRecord::Rollback # kill all db activity, but don't break outside logic end - - unless sale.save - raise RecurlyClientError, "Invalid sale (at end)." - end - rescue Recurly::Resource::Invalid => e - # this exception is thrown by invoice! if the invoice is invalid - sale.rollback_adjustments(current_user, created_adjustments) - sale = nil - raise ActiveRecord::Rollback # kill all db activity, but don't break outside logic + else + raise RecurlyClientError, "Could not find account to place order." end - else - raise RecurlyClientError, "Could not find account to place order." end else raise RecurlyClientError, "Invalid sale." @@ -238,30 +260,33 @@ module JamRuby return end - # ask the shopping cart to create the correct Recurly adjustment attributes for a JamTrack - adjustments = shopping_cart.create_adjustment_attributes(current_user) + if account + # ask the shopping cart to create the correct Recurly adjustment attributes for a JamTrack + adjustments = shopping_cart.create_adjustment_attributes(current_user) - adjustments.each do |adjustment| + adjustments.each do |adjustment| - # create the adjustment at Recurly (this may not look like it, but it is a REST API) - created_adjustment = account.adjustments.new(adjustment) - created_adjustment.save + # create the adjustment at Recurly (this may not look like it, but it is a REST API) + created_adjustment = account.adjustments.new(adjustment) + created_adjustment.save - # if the adjustment could not be made, bail - raise RecurlyClientError.new(created_adjustment.errors) if created_adjustment.errors.any? + # if the adjustment could not be made, bail + raise RecurlyClientError.new(created_adjustment.errors) if created_adjustment.errors.any? - # keep track of adjustments we created for this order, in case we have to roll them back - created_adjustments << created_adjustment + # keep track of adjustments we created for this order, in case we have to roll them back + created_adjustments << created_adjustment - if ShoppingCart.is_product_purchase?(adjustment) - # this was a normal product adjustment, so track it as such - recurly_adjustment_uuid = created_adjustment.uuid - else - # this was a 'credit' adjustment, so track it as such - recurly_adjustment_credit_uuid = created_adjustment.uuid + if ShoppingCart.is_product_purchase?(adjustment) + # this was a normal product adjustment, so track it as such + recurly_adjustment_uuid = created_adjustment.uuid + else + # this was a 'credit' adjustment, so track it as such + recurly_adjustment_credit_uuid = created_adjustment.uuid + end end end + # create one sale line item for every jam track sale_line_item = SaleLineItem.create_from_shopping_cart(self, shopping_cart, nil, recurly_adjustment_uuid, recurly_adjustment_credit_uuid) @@ -279,7 +304,11 @@ module JamRuby end # also if the purchase was a free one, then update the user record to no longer allow redeemed jamtracks - User.where(id: current_user.id).update_all(has_redeemable_jamtrack: false) if shopping_cart.free? + if shopping_cart.free? + User.where(id: current_user.id).update_all(has_redeemable_jamtrack: false) + current_user.has_redeemable_jamtrack = false # make sure model reflects the truth + end + # this can't go in the block above, as it's here to fix bad subscription UUIDs in an update path if jam_track_right.recurly_adjustment_uuid != recurly_adjustment_uuid diff --git a/ruby/lib/jam_ruby/models/shopping_cart.rb b/ruby/lib/jam_ruby/models/shopping_cart.rb index dc975bd40..568d94048 100644 --- a/ruby/lib/jam_ruby/models/shopping_cart.rb +++ b/ruby/lib/jam_ruby/models/shopping_cart.rb @@ -152,6 +152,12 @@ module JamRuby def self.add_jam_track_to_cart(any_user, jam_track) cart = nil ShoppingCart.transaction do + + if any_user.has_redeemable_jamtrack + # if you still have a freebie available to you, or if you are an anonymous user, we make sure there is nothing else in your shopping cart + any_user.destroy_all_shopping_carts + end + mark_redeem = ShoppingCart.user_has_redeemable_jam_track?(any_user) cart = ShoppingCart.create(any_user, jam_track, 1, mark_redeem) end @@ -173,7 +179,13 @@ module JamRuby carts[0].save end end + end + def port(user, anonymous_user) + + ShoppingCart.transaction do + move_to_user(user, anonymous_user, anonymous_user.shopping_carts) + end end end end \ No newline at end of file diff --git a/ruby/lib/jam_ruby/models/signup_hint.rb b/ruby/lib/jam_ruby/models/signup_hint.rb index b415d45a4..c95353d6c 100644 --- a/ruby/lib/jam_ruby/models/signup_hint.rb +++ b/ruby/lib/jam_ruby/models/signup_hint.rb @@ -6,6 +6,7 @@ module JamRuby # we use it to figure out what to do with the user after they signup class SignupHint < ActiveRecord::Base + belongs_to :jam_track, class_name: 'JamRuby::JamTrack' belongs_to :user, class_name: 'JamRuby::User' @@ -23,6 +24,7 @@ module JamRuby hint.anonymous_user_id = anonymous_user.id hint.redirect_location = options[:redirect_location] if options.has_key?(:redirect_location) hint.want_jamblaster = options[:want_jamblaster] if options.has_key?(:want_jamblaster) + #hint.jam_track = JamTrack.find(options[:jam_track]) if options.has_key?(:jam_track) hint.expires_at = 15.minutes.from_now hint.save hint diff --git a/ruby/lib/jam_ruby/models/user.rb b/ruby/lib/jam_ruby/models/user.rb index 618c5818b..fcdeffc3c 100644 --- a/ruby/lib/jam_ruby/models/user.rb +++ b/ruby/lib/jam_ruby/models/user.rb @@ -953,6 +953,7 @@ module JamRuby recaptcha_failed = options[:recaptcha_failed] any_user = options[:any_user] reuse_card = options[:reuse_card] + signup_hint = options[:signup_hint] user = User.new @@ -1018,8 +1019,6 @@ module JamRuby end end - - unless fb_signup.nil? user.update_fb_authorization(fb_signup) @@ -1072,6 +1071,18 @@ module JamRuby user.save + # 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 && + # signup_hint.jam_track && + # user.shopping_carts.length == 1 && + # user.shopping_carts[0].cart_product == signup_hint.jam_track && + # user.shopping_carts[0].product_info[:free] + # + # if only_freebie_in_cart + # Sale.place_order(user, user.shopping_carts) + # end + user.errors.add("recaptcha", "verification failed") if recaptcha_failed if user.errors.any? @@ -1577,6 +1588,21 @@ module JamRuby APP_CONFIG.admin_root_url + "/admin/jam_track_rights?q[user_id_equals]=#{id}&commit=Filter&order=created_at DESC" end + # these are signup attributes that we default to when not presenting the typical form @ /signup + def self.musician_defaults(remote_ip, confirmation_url, any_user, options) + options = options || {} + options[:remote_ip] = remote_ip + options[:birth_date] = nil + options[:instruments] = [{:instrument_id => 'other', :proficiency_level => 1, :priority => 1}] + options[:musician] = true + options[:skip_recaptcha] = true + options[:invited_user] = nil + options[:fb_signup] = nil + options[:signup_confirm_url] = confirmation_url + options[:any_user] = any_user + options + end + private def create_remember_token self.remember_token = SecureRandom.urlsafe_base64 diff --git a/ruby/spec/jam_ruby/models/jam_track_right_spec.rb b/ruby/spec/jam_ruby/models/jam_track_right_spec.rb index 1c68e2037..1adef7d18 100644 --- a/ruby/spec/jam_ruby/models/jam_track_right_spec.rb +++ b/ruby/spec/jam_ruby/models/jam_track_right_spec.rb @@ -208,5 +208,125 @@ describe JamTrackRight do end end + describe "guard_against_fraud" do + let(:user) {FactoryGirl.create(:user)} + let(:other) {FactoryGirl.create(:user)} + let(:first_fingerprint) { {all: 'all', running: 'running' } } + let(:new_fingerprint) { {all: 'all_2', running: 'running' } } + let(:remote_ip) {'1.1.1.1'} + let(:jam_track_right) { FactoryGirl.create(:jam_track_right, user: user, redeemed: true, redeemed_and_fingerprinted: false) } + let(:jam_track_right_purchased) { FactoryGirl.create(:jam_track_right, user: user, redeemed: false, redeemed_and_fingerprinted: false) } + let(:jam_track_right_other) { FactoryGirl.create(:jam_track_right, user: other, redeemed: true, redeemed_and_fingerprinted: false) } + let(:jam_track_right_other_purchased) { FactoryGirl.create(:jam_track_right, user: other, redeemed: false, redeemed_and_fingerprinted: false) } + + it "denies no current_user" do + jam_track_right.guard_against_fraud(nil, first_fingerprint, remote_ip).should eq('no user specified') + end + + it "denies no fingerprint" do + jam_track_right.guard_against_fraud(user, nil, remote_ip).should eq('no fingerprint specified') + end + + it "allows redemption (success)" do + jam_track_right.guard_against_fraud(user, first_fingerprint, remote_ip).should be_nil + jam_track_right.valid?.should be_true + jam_track_right.redeemed_and_fingerprinted.should be_true + + + mf = MachineFingerprint.find_by_fingerprint(first_fingerprint[:all]) + mf.user.should eq(user) + mf.fingerprint.should eq(first_fingerprint[:all]) + mf.when_taken.should eq(MachineFingerprint::TAKEN_ON_SUCCESSFUL_DOWNLOAD) + mf.print_type.should eq(MachineFingerprint::PRINT_TYPE_ALL) + mf.jam_track_right.should eq(jam_track_right) + + mf = MachineFingerprint.find_by_fingerprint(first_fingerprint[:running]) + mf.user.should eq(user) + mf.fingerprint.should eq(first_fingerprint[:running]) + mf.when_taken.should eq(MachineFingerprint::TAKEN_ON_SUCCESSFUL_DOWNLOAD) + mf.print_type.should eq(MachineFingerprint::PRINT_TYPE_ACTIVE) + mf.jam_track_right.should eq(jam_track_right) + end + + it "ignores already successfully redeemed" do + jam_track_right.redeemed_and_fingerprinted = true + jam_track_right.save! + + jam_track_right.guard_against_fraud(user, new_fingerprint, remote_ip).should be_nil + jam_track_right.valid?.should be_true + + # and no new fingerprints + MachineFingerprint.count.should eq(0) + end + + it "ignores already normally purchased" do + jam_track_right.guard_against_fraud(user, first_fingerprint, remote_ip) + MachineFingerprint.count.should eq(2) + + jam_track_right_purchased.guard_against_fraud(user, new_fingerprint, remote_ip).should be_nil + jam_track_right_purchased.valid?.should be_true + jam_track_right_purchased.redeemed_and_fingerprinted.should be_false # fingerprint should not be set on normal purchase + + jam_track_right.redeemed_and_fingerprinted.should be_true # should still be redeemed_and fingerprinted; just checking for weird side-effects + + # no new fingerprints + MachineFingerprint.count.should eq(2) + end + + it "protects against re-using fingerprint across users (conflicts on all fp)" do + jam_track_right.guard_against_fraud(user, first_fingerprint, remote_ip).should be_nil + MachineFingerprint.count.should eq(2) + first_fingerprint[:running] = 'running_2' + jam_track_right_other.guard_against_fraud(other, first_fingerprint, remote_ip).should eq("other user has 'all' fingerprint") + + mf = MachineFingerprint.find_by_fingerprint(first_fingerprint[:running]) + mf.user.should eq(other) + mf.fingerprint.should eq(first_fingerprint[:running]) + mf.when_taken.should eq(MachineFingerprint::TAKEN_ON_FRAUD_CONFLICT) + mf.print_type.should eq(MachineFingerprint::PRINT_TYPE_ACTIVE) + mf.jam_track_right.should eq(jam_track_right_other) + MachineFingerprint.count.should eq(3) + end + + it "protects against re-using fingerprint across users (conflicts on running fp)" do + jam_track_right.guard_against_fraud(user, first_fingerprint, remote_ip).should be_nil + MachineFingerprint.count.should eq(2) + first_fingerprint[:all] = 'all_2' + jam_track_right_other.guard_against_fraud(other, first_fingerprint, remote_ip).should eq("other user has 'running' fingerprint") + + mf = MachineFingerprint.find_by_fingerprint(first_fingerprint[:all]) + mf.user.should eq(other) + mf.fingerprint.should eq(first_fingerprint[:all]) + mf.when_taken.should eq(MachineFingerprint::TAKEN_ON_FRAUD_CONFLICT) + mf.print_type.should eq(MachineFingerprint::PRINT_TYPE_ALL) + mf.jam_track_right.should eq(jam_track_right_other) + MachineFingerprint.count.should eq(3) + end + + # if you try to buy a regular jamtrack with a fingerprint belonging to another user? so what. you paid for it + it "allows re-use of fingerprint if jamtrack is a normal purchase" do + jam_track_right.guard_against_fraud(user, first_fingerprint, remote_ip).should be_nil + MachineFingerprint.count.should eq(2) + jam_track_right_other_purchased.guard_against_fraud(other, first_fingerprint, remote_ip).should be_nil + MachineFingerprint.count.should eq(2) + end + + it "stops you from redeeming two jamtracks" do + right1 = FactoryGirl.create(:jam_track_right, user: user, redeemed: true, redeemed_and_fingerprinted: true) + jam_track_right.guard_against_fraud(user, first_fingerprint, remote_ip).should eq('already redeemed another') + MachineFingerprint.count.should eq(0) + end + + it "let's you download a free jamtrack if you have a second but undownloaded free one" do + right1 = FactoryGirl.create(:jam_track_right, user: user, redeemed: true, redeemed_and_fingerprinted: false) + jam_track_right.guard_against_fraud(user, first_fingerprint, remote_ip).should be_nil + MachineFingerprint.count.should eq(2) + + right1.guard_against_fraud(user, first_fingerprint, remote_ip).should eq('already redeemed another') + MachineFingerprint.count.should eq(2) + end + + end + end diff --git a/ruby/spec/jam_ruby/models/sale_spec.rb b/ruby/spec/jam_ruby/models/sale_spec.rb index b08aad36d..47dda7213 100644 --- a/ruby/spec/jam_ruby/models/sale_spec.rb +++ b/ruby/spec/jam_ruby/models/sale_spec.rb @@ -87,9 +87,9 @@ describe Sale do sales.should eq(user.sales) sale = sales[0] - sale.recurly_invoice_id.should_not be_nil + sale.recurly_invoice_id.should be_nil - sale.recurly_subtotal_in_cents.should eq(jam_track_price_in_cents) + 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') @@ -97,7 +97,7 @@ describe Sale do sale.sale_line_items.length.should == 1 sale_line_item = sale.sale_line_items[0] sale_line_item.recurly_tax_in_cents.should eq(0) - sale_line_item.recurly_total_in_cents.should eq(jam_track_price_in_cents) + sale_line_item.recurly_total_in_cents.should eq(0) 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) @@ -109,8 +109,8 @@ describe Sale do sale_line_item.recurly_plan_code.should eq(jamtrack.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_not be_nil + sale_line_item.recurly_adjustment_uuid.should be_nil + sale_line_item.recurly_adjustment_credit_uuid.should be_nil sale_line_item.recurly_adjustment_uuid.should eq(user.jam_track_rights.last.recurly_adjustment_uuid) sale_line_item.recurly_adjustment_credit_uuid.should eq(user.jam_track_rights.last.recurly_adjustment_credit_uuid) @@ -118,31 +118,11 @@ describe Sale do recurly_account = client.get_account(user) adjustments = recurly_account.adjustments adjustments.should_not be_nil - adjustments.should have(2).items - free_purchase= adjustments[0] - free_purchase.unit_amount_in_cents.should eq((jamtrack.price * 100).to_i) - free_purchase.accounting_code.should eq(ShoppingCart::PURCHASE_FREE) - free_purchase.description.should eq("JamTrack: " + jamtrack.name) - free_purchase.state.should eq('invoiced') - free_purchase.uuid.should eq(sale_line_item.recurly_adjustment_uuid) - - free_credit = adjustments[1] - free_credit.unit_amount_in_cents.should eq(-(jamtrack.price * 100).to_i) - free_credit.accounting_code.should eq(ShoppingCart::PURCHASE_FREE_CREDIT) - free_credit.description.should eq("JamTrack: " + jamtrack.name + " (Credit)") - free_credit.state.should eq('invoiced') - free_credit.uuid.should eq(sale_line_item.recurly_adjustment_credit_uuid) + adjustments.should have(0).items invoices = recurly_account.invoices - invoices.should have(1).items - invoice = invoices[0] - invoice.uuid.should eq(sale.recurly_invoice_id) - invoice.line_items.should have(2).items # should have both adjustments associated - invoice.line_items[0].should eq(free_credit) - invoice.line_items[1].should eq(free_purchase) - invoice.subtotal_in_cents.should eq((jamtrack.price * 100).to_i) - invoice.total_in_cents.should eq(0) - invoice.state.should eq('collected') + invoices.should have(0).items + # verify jam_track_rights data user.jam_track_rights.should_not be_nil @@ -238,7 +218,7 @@ describe Sale do # also, verify that no earlier adjustments were affected recurly_account = client.get_account(user) adjustments = recurly_account.adjustments - adjustments.should have(2).items + adjustments.should have(0).items # because the only successful purchase was a freebie, there should be no recurly adjustments end # this test counts on the fact that two adjustments are made when buying a free JamTrack @@ -246,13 +226,13 @@ describe Sale do # we can see if the first one is ultimately destroyed it "rolls back created adjustments if error" do - shopping_cart = ShoppingCart.create user, jamtrack, 1, true + shopping_cart = ShoppingCart.create user, jamtrack, 1, false # grab the real response; we will modify it to make a nil accounting code adjustment_attrs = shopping_cart.create_adjustment_attributes(user) client.find_or_create_account(user, billing_info) - adjustment_attrs[1][:unit_amount_in_cents] = nil # invalid amount + adjustment_attrs[0][:unit_amount_in_cents] = nil # invalid amount ShoppingCart.any_instance.stub(:create_adjustment_attributes).and_return(adjustment_attrs) expect { Sale.place_order(user, [shopping_cart]) }.to raise_error(JamRuby::RecurlyClientError) @@ -265,7 +245,7 @@ describe Sale do end it "rolls back adjustments created before the order" do - shopping_cart = ShoppingCart.create user, jamtrack, 1, true + shopping_cart = ShoppingCart.create user, jamtrack, 1, false client.find_or_create_account(user, billing_info) # create a single adjustment on the account @@ -281,7 +261,7 @@ describe Sale do recurly_account = client.get_account(user) adjustments = recurly_account.adjustments - adjustments.should have(2).items # two adjustments are created for a free jamtrack; that should be all there is + adjustments.should have(1).items # two adjustments are created for a free jamtrack; that should be all there is end end diff --git a/ruby/spec/jam_ruby/models/shopping_cart_spec.rb b/ruby/spec/jam_ruby/models/shopping_cart_spec.rb index 13f6777bc..6be02e8d4 100644 --- a/ruby/spec/jam_ruby/models/shopping_cart_spec.rb +++ b/ruby/spec/jam_ruby/models/shopping_cart_spec.rb @@ -21,34 +21,36 @@ describe ShoppingCart do user.shopping_carts[0].quantity.should == 1 end + + it "maintains only one fre JamTrack in ShoppingCart" do + cart1 = ShoppingCart.add_jam_track_to_cart(user, jam_track) + cart1.should_not be_nil + cart1.errors.any?.should be_false + user.reload + cart2 = ShoppingCart.add_jam_track_to_cart(user, jam_track) + cart2.errors.any?.should be_false + user.reload + user.shopping_carts.length.should eq(1) + cart3 = ShoppingCart.add_jam_track_to_cart(user, jam_track2) + cart3.errors.any?.should be_false + user.reload + user.shopping_carts.length.should eq(1) + end + it "should not add duplicate JamTrack to ShoppingCart" do + 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.reload cart2 = ShoppingCart.add_jam_track_to_cart(user, jam_track) cart2.errors.any?.should be_true - end describe "redeemable behavior" do - it "adds redeemable item to shopping cart" do - user.has_redeemable_jamtrack.should be_true - - # first item added to shopping cart should be marked for redemption - cart = ShoppingCart.add_jam_track_to_cart(user, jam_track) - cart.marked_for_redeem.should eq(1) - - # but the second item should not - - user.reload - - cart = ShoppingCart.add_jam_track_to_cart(user, jam_track2) - cart.marked_for_redeem.should eq(0) - end - - it "removes redeemable item to shopping cart" 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) @@ -58,12 +60,12 @@ describe ShoppingCart do cart2.should_not be_nil cart1.marked_for_redeem.should eq(1) - cart2.marked_for_redeem.should eq(0) + cart2.marked_for_redeem.should eq(1) ShoppingCart.remove_jam_track_from_cart(user, jam_track) - user.shopping_carts.length.should eq(1) + user.shopping_carts.length.should eq(0) cart2.reload - cart1.marked_for_redeem.should eq(1) + cart2.marked_for_redeem.should eq(1) end end end diff --git a/ruby/spec/jam_ruby/models/signup_hint_spec.rb b/ruby/spec/jam_ruby/models/signup_hint_spec.rb index 1ec79efef..fc17d2e03 100644 --- a/ruby/spec/jam_ruby/models/signup_hint_spec.rb +++ b/ruby/spec/jam_ruby/models/signup_hint_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' describe SignupHint do - let(:user) {AnonymousUser.new(SecureRandom.uuid)} + let(:user) {AnonymousUser.new(SecureRandom.uuid, nil)} describe "refresh_by_anoymous_user" do it "creates" do diff --git a/web/app/assets/javascripts/application.js b/web/app/assets/javascripts/application.js index 030fd6e88..08a2918e8 100644 --- a/web/app/assets/javascripts/application.js +++ b/web/app/assets/javascripts/application.js @@ -48,6 +48,9 @@ //= require utils //= require subscription_utils //= require custom_controls +//= require web/signup_helper +//= require web/signin_helper +//= require web/signin //= require_directory . //= require_directory ./dialog //= require_directory ./wizard diff --git a/web/app/assets/javascripts/checkout_payment.js b/web/app/assets/javascripts/checkout_payment.js index 900efd3ab..9b72f4fc5 100644 --- a/web/app/assets/javascripts/checkout_payment.js +++ b/web/app/assets/javascripts/checkout_payment.js @@ -560,20 +560,6 @@ $screen.find("#payment-info-next").on('click', next); } - function beforeShowOrder() { - step = 3; - renderNavigation(); - populateOrderPage(); - } - - - function populateOrderPage() { - - rest.getShoppingCarts() - .done(renderOrderPage) - .fail(app.ajaxError); - } - function toggleShippingAsBilling(e) { e.preventDefault(); diff --git a/web/app/assets/javascripts/checkout_signin.js b/web/app/assets/javascripts/checkout_signin.js index 6985c3b71..9dad91bdf 100644 --- a/web/app/assets/javascripts/checkout_signin.js +++ b/web/app/assets/javascripts/checkout_signin.js @@ -19,6 +19,7 @@ var $contentHolder = null; var $btnNext = null; var $btnFacebook = null; + var checkoutUtils = context.JK.CheckoutUtilsInstance; function beforeShow(data) { renderNavigation(); @@ -96,9 +97,23 @@ $signinBtn.text('TRYING...').addClass('disabled') rest.login({email: email, password: password, remember_me: true}) - .done(function() { - window.location = '/client#/checkoutPayment' - window.location.reload(); + .done(function(user) { + // now determine where we should send the user + rest.getShoppingCarts() + .done(function(carts) { + if(checkoutUtils.hasOneFreeItemInShoppingCart(carts)) { + window.location = '/client#/redeemComplete' + window.location.reload(); + } + else { + window.location = '/client#/checkoutPayment' + window.location.reload(); + } + }) + .fail(function() { + window.location = '/client#/jamtrackBrowse' + window.location.reload(); + }) }) .fail(function(jqXHR) { if(jqXHR.status == 422) { diff --git a/web/app/assets/javascripts/checkout_utils.js.coffee b/web/app/assets/javascripts/checkout_utils.js.coffee index d97804ca5..7f61f0fb8 100644 --- a/web/app/assets/javascripts/checkout_utils.js.coffee +++ b/web/app/assets/javascripts/checkout_utils.js.coffee @@ -43,6 +43,16 @@ class CheckoutUtils getLastPurchase: () => return @lastPurchaseResponse + hasOneFreeItemInShoppingCart: (carts) => + + if carts.length == 0 + # nothing is in the user's shopping cart. They shouldn't be here. + return false; + else if carts.length > 1 + # the user has multiple items in their shopping cart. They shouldn't be here. + return false; + + return carts[0].product_info.free # global instance context.JK.CheckoutUtilsInstance = new CheckoutUtils() \ No newline at end of file diff --git a/web/app/assets/javascripts/dialog/openJamTrackDialog.js b/web/app/assets/javascripts/dialog/openJamTrackDialog.js index b3df383e9..3dd131e41 100644 --- a/web/app/assets/javascripts/dialog/openJamTrackDialog.js +++ b/web/app/assets/javascripts/dialog/openJamTrackDialog.js @@ -89,6 +89,7 @@ rest.openJamTrack({id: context.JK.CurrentSessionModel.id(), jam_track_id: jamTrack.id}) .done(function(response) { $dialog.data('result', {success:true, jamTrack: jamTrack}) + context.JK.CurrentSessionModel.updateSession(response);s app.layout.closeDialog('open-jam-track-dialog'); }) .fail(function(jqXHR) { diff --git a/web/app/assets/javascripts/dialog/signinDialog.js b/web/app/assets/javascripts/dialog/signinDialog.js index a76d649d5..a1b56b11d 100644 --- a/web/app/assets/javascripts/dialog/signinDialog.js +++ b/web/app/assets/javascripts/dialog/signinDialog.js @@ -11,11 +11,21 @@ var dialogId = '#signin-dialog'; var $dialog = null; var signinHelper = null; + var redirectTo = null; - function beforeShow() { + function beforeShow(args) { logger.debug("showing login form") - signinHelper.reset(); + if(args.redirect_to) { + redirectTo = "/client#/redeemComplete" + } + else { + redirectTo = null; + } + if(redirectTo) { + logger.debug("setting redirect to in login dialog") + } + signinHelper.reset(redirectTo); } function afterShow() { @@ -24,6 +34,7 @@ function afterHide() { logger.debug("hiding login form") + redirectTo = null; } function initialize(){ diff --git a/web/app/assets/javascripts/download_jamtrack.js.coffee b/web/app/assets/javascripts/download_jamtrack.js.coffee index 800cdc276..58592a73c 100644 --- a/web/app/assets/javascripts/download_jamtrack.js.coffee +++ b/web/app/assets/javascripts/download_jamtrack.js.coffee @@ -206,6 +206,8 @@ context.JK.DownloadJamTrack = class DownloadJamTrack showInitial: () => @logger.debug("showing #{@state.name}") @sampleRate = context.jamClient.GetSampleRate() + @fingerprint = context.jamClient.SessionGetMacHash() + logger.debug("fingerprint: ", @fingerprint) @sampleRateForFilename = if @sampleRate == 48 then '48' else '44' @attempts = @attempts + 1 this.expectTransition() @@ -450,7 +452,7 @@ context.JK.DownloadJamTrack = class DownloadJamTrack @attemptedEnqueue = true @ajaxEnqueueAborted = false - @rest.enqueueJamTrack({id: @jamTrack.id, sample_rate: @sampleRate}) + @rest.enqueueJamTrack({id: @jamTrack.id, sample_rate: @sampleRate, fingerprint: @fingerprint}) .done(this.processEnqueueJamTrack) .fail(this.processEnqueueJamTrackFail) @@ -474,9 +476,24 @@ context.JK.DownloadJamTrack = class DownloadJamTrack else @logger.debug("DownloadJamTrack: ignoring processEnqueueJamTrack response") - processEnqueueJamTrackFail: () => + displayUIForGuard:(response) => + display = switch response.message + when 'no user specified' then 'Please log back in.' + when 'no fingerprint specified' then 'There was a problem communicating between client and server. Please restart JamKazam.' + when 'no all fingerprint specified' then 'There was a problem communicating between client and server. Please restart JamKazam.' + when 'no running fingerprint specified' then 'There was a problem communicating between client and server. Please restart JamKazam.' + when 'already redeemed another' then "It appears you have already redeemed your one free JamTrack for your household. We are sorry, but we cannot let you download this JamTrack free. If you believe this is an error, please contact us at support@jamkazam.com." + when "other user has 'all' fingerprint" then "It appears you have already redeemed your one free JamTrack for your household. We are sorry, but we cannot let you download this JamTrack free. If you believe this is an error, please contact us at support@jamkazam.com." + when "other user has 'running' fingerprint" then "It appears you have already redeemed your one free JamTrack for your household. We are sorry, but we cannot let you download this JamTrack free. If you believe this is an error, please contact us at support@jamkazam.com." + else "Something went wrong #{response.message}. Please restart JamKazam" + + processEnqueueJamTrackFail: (jqXHR) => unless @ajaxEnqueueAborted - this.transitionError("enqueue-error", "Unable to ask the server to build your JamTrack.") + if jqXHR.status == 403 + display = this.displayUIForGuard(JSON.parse(jqXHR.responseText)) + this.transitionError("enqueue-error", display) + else + this.transitionError("enqueue-error", "Unable to ask the server to build your JamTrack.") else @logger.debug("DownloadJamTrack: ignoring processEnqueueJamTrackFail response") diff --git a/web/app/assets/javascripts/everywhere/everywhere.js b/web/app/assets/javascripts/everywhere/everywhere.js index 741f70b3b..8186b3b58 100644 --- a/web/app/assets/javascripts/everywhere/everywhere.js +++ b/web/app/assets/javascripts/everywhere/everywhere.js @@ -210,6 +210,7 @@ if (!userProfile.show_jamtrack_guide && userProfile.show_whats_next && userProfile.show_whats_next_count < 10 && window.location.pathname.indexOf(gon.client_path) == 0 && window.location.hash.indexOf('/checkout') == -1 && + window.location.hash.indexOf('/redeem') == -1 && !app.layout.isDialogShowing('getting-started')) { app.layout.showDialog('getting-started'); diff --git a/web/app/assets/javascripts/jam_rest.js b/web/app/assets/javascripts/jam_rest.js index 9b5115e2a..b8fcf54f6 100644 --- a/web/app/assets/javascripts/jam_rest.js +++ b/web/app/assets/javascripts/jam_rest.js @@ -1662,6 +1662,26 @@ }); } + function signup(data) { + return $.ajax({ + type: "POST", + url: '/api/users', + dataType: "json", + contentType: 'application/json', + data: JSON.stringify(data), + }); + } + + function portOverCarts() { + return $.ajax({ + type: "POST", + url: '/api/shopping_carts/port', + dataType: "json", + contentType: 'application/json', + data: JSON.stringify(data) + }) + } + function createAlert(subject, data) { var message = {subject:subject}; $.extend(message, data); @@ -1825,6 +1845,8 @@ this.playJamTrack = playJamTrack; this.createSignupHint = createSignupHint; this.createAlert = createAlert; + this.signup = signup; + this.portOverCarts = portOverCarts; return this; }; diff --git a/web/app/assets/javascripts/jam_track_preview.js.coffee b/web/app/assets/javascripts/jam_track_preview.js.coffee index 73cd2719e..58388278b 100644 --- a/web/app/assets/javascripts/jam_track_preview.js.coffee +++ b/web/app/assets/javascripts/jam_track_preview.js.coffee @@ -61,7 +61,7 @@ context.JK.JamTrackPreview = class JamTrackPreview if @options.master_shows_duration duration = 'entire song' if @jamTrack.duration - duration = "0:00 - #{context.JK.prettyPrintSeconds(@jamTrack.duration)}" + duration = "#{context.JK.prettyPrintSeconds(@jamTrack.duration)}" part = duration else part = @jamTrack.name + ' by ' + @jamTrack.original_artist diff --git a/web/app/assets/javascripts/jam_track_screen.js.coffee b/web/app/assets/javascripts/jam_track_screen.js.coffee index 1dc48338e..64b970d19 100644 --- a/web/app/assets/javascripts/jam_track_screen.js.coffee +++ b/web/app/assets/javascripts/jam_track_screen.js.coffee @@ -192,9 +192,23 @@ context.JK.JamTrackScreen=class JamTrackScreen addToCartJamtrack:(e) => e.preventDefault() - params = id: $(e.target).attr('data-jamtrack-id') + $target = $(e.target) + params = id: $target.attr('data-jamtrack-id') + isFree = $(e.target).is('.is_free') + rest.addJamtrackToShoppingCart(params).done((response) => - context.location = '/client#/shoppingCart' + if(isFree) + if context.JK.currentUserId? + alert("TODO") + 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) => @@ -211,15 +225,15 @@ context.JK.JamTrackScreen=class JamTrackScreen if expand trackElement.find('.extra').removeClass('hidden') - detailArrow.html('hide tracks ') + detailArrow.html('hide tracks ') for track in jamTrack.tracks trackElement.find("[jamtrack-track-id='#{track.id}']").removeClass('hidden') else trackElement.find('.extra').addClass('hidden') - detailArrow.html('preview all tracks ') + detailArrow.html('show all tracks ') count = 0 for track in jamTrack.tracks - if count < 2 + if count < 6 trackElement.find("[jamtrack-track-id='#{track.id}']").removeClass('hidden') else trackElement.find("[jamtrack-track-id='#{track.id}']").addClass('hidden') @@ -281,14 +295,15 @@ context.JK.JamTrackScreen=class JamTrackScreen if track.part != '' track.instrument_desc += ' (' + track.part + ')' - free_state = if gon.global.one_free_jamtrack_per_user then 'free' else 'non-free' - if @user - free_state = if @user.free_jamtrack then 'free' else 'non-free' + 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 + free_state: free_state, + is_free: is_free @jamtrackItem = $(context._.template($('#template-jamtrack').html(), options, variable: 'data')) that.renderJamtrack(@jamtrackItem, jamtrack) that.registerEvents(@jamtrackItem) diff --git a/web/app/assets/javascripts/redeem_complete.js b/web/app/assets/javascripts/redeem_complete.js new file mode 100644 index 000000000..5f93cd4ce --- /dev/null +++ b/web/app/assets/javascripts/redeem_complete.js @@ -0,0 +1,264 @@ +(function (context, $) { + + "use strict"; + context.JK = context.JK || {}; + context.JK.RedeemCompleteScreen = function (app) { + + var EVENTS = context.JK.EVENTS; + var logger = context.JK.logger; + var rest = context.JK.Rest(); + var jamTrackUtils = context.JK.JamTrackUtils; + var checkoutUtils = context.JK.CheckoutUtilsInstance; + + var $screen = null; + var $navigation = null; + var $templatePurchasedJamTrack = null; + var $thanksPanel = null; + var $jamTrackInBrowser = null; + var $jamTrackInClient = null; + var $purchasedJamTrack = null; + var $purchasedJamTrackHeader = null; + var $purchasedJamTracks = null; + var userDetail = null; + var step = null; + var downloadJamTracks = []; + var purchasedJamTracks = null; + var purchasedJamTrackIterator = 0; + var $backBtn = null; + var $downloadApplicationLink = null; + var $noPurchasesPrompt = null; + var shoppingCartItem = null; + + + function beforeShow() { + + } + + function afterShow(data) { + $noPurchasesPrompt.addClass('hidden') + $purchasedJamTracks.empty() + $thanksPanel.addClass("hidden") + $purchasedJamTrackHeader.attr('status', 'in-progress') + $jamTrackInBrowser.addClass('hidden') + $jamTrackInClient.addClass('hidden') + + + // if there is no current user, but it apperas we have a login cookie, just refresh + if(!context.JK.currentUserId && $.cookie('remember_token')) { + window.location.reload(); + } + else { + redeemJamTrack() + } + + //prepThanks() + } + + function handleShoppingCartResponse(carts) { + + if(!checkoutUtils.hasOneFreeItemInShoppingCart(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#/jamtrackBrowse' + } + 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 + + 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(); + }) + .fail(function() { + + }) + } + } + + function redeemJamTrack() { + rest.getShoppingCarts() + .done(handleShoppingCartResponse) + .fail(app.ajaxError); + + } + + function beforeHide() { + if(downloadJamTracks) { + context._.each(downloadJamTracks, function(downloadJamTrack) { + downloadJamTrack.destroy(); + downloadJamTrack.root.remove(); + }) + + downloadJamTracks = []; + } + purchasedJamTracks = null; + purchasedJamTrackIterator = 0; + } + + function prepThanks() { + showThanks(); + } + + function showThanks(purchaseResponse) { + + + var purchaseResponse = checkoutUtils.getLastPurchase(); + + if(!purchaseResponse || purchaseResponse.length == 0) { + // user got to this page with no context + logger.debug("no purchases found; nothing to show") + $noPurchasesPrompt.removeClass('hidden') + } + else { + if(gon.isNativeClient) { + $jamTrackInClient.removeClass('hidden') + } + else { + $jamTrackInBrowser.removeClass('hidden'); + } + $thanksPanel.removeClass('hidden') + handleJamTracksPurchased(purchaseResponse.jam_tracks) + } + } + + function handleJamTracksPurchased(jamTracks) { + // were any JamTracks purchased? + var jamTracksPurchased = jamTracks && jamTracks.length > 0; + if(jamTracksPurchased) { + if(gon.isNativeClient) { + $jamTrackInClient.removeClass('hidden') + context.JK.GA.virtualPageView('/redeemInClient'); + startDownloadJamTracks(jamTracks) + } + else { + $jamTrackInBrowser.removeClass('hidden'); + + app.user().done(function(user) { + // cut off time + var cutoff = new Date("May 8, 2015 00:00:00"); + if(new Date(user.created_at).getTime() < cutoff.getTime()) { + logger.debug("existing user recorded") + context.JK.GA.virtualPageView('/redeemInBrowserExistingUser'); + } + else { + logger.debug("new user recorded") + context.JK.GA.virtualPageView('/redeemInBrowserNewUser'); + } + }) + + + + app.user().done(function(user) { + if(!user.first_downloaded_client_at) { + $downloadApplicationLink.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.attr('status', 'done') + } + } + + function events() { + $backBtn.on('click', function(e) { + e.preventDefault(); + + context.location = '/client#/jamtrackBrowse' + }) + } + + function initialize() { + var screenBindings = { + 'beforeShow': beforeShow, + 'afterShow': afterShow, + 'beforeHide': beforeHide + }; + app.bindScreen('redeemComplete', screenBindings); + + $screen = $("#redeemCompleteScreen"); + $templatePurchasedJamTrack = $('#template-purchased-jam-track'); + $thanksPanel = $screen.find(".thanks-panel"); + $jamTrackInBrowser = $screen.find(".jam-tracks-in-browser"); + $jamTrackInClient = $screen.find(".jam-tracks-in-client"); + $purchasedJamTrack = $thanksPanel.find(".thanks-detail.purchased-jam-track"); + $purchasedJamTrackHeader = $purchasedJamTrack.find(".purchased-jam-track-header"); + $purchasedJamTracks = $purchasedJamTrack.find(".purchased-list") + $backBtn = $screen.find('.back'); + $downloadApplicationLink = $screen.find('.download-jamkazam-wrapper'); + $noPurchasesPrompt = $screen.find('.no-purchases-prompt') + + if ($screen.length == 0) throw "$screen must be specified"; + + events(); + } + + this.initialize = initialize; + + return this; + } +}) +(window, jQuery); \ No newline at end of file diff --git a/web/app/assets/javascripts/redeem_signup.js b/web/app/assets/javascripts/redeem_signup.js new file mode 100644 index 000000000..bc7a13641 --- /dev/null +++ b/web/app/assets/javascripts/redeem_signup.js @@ -0,0 +1,244 @@ +(function(context,$) { + + "use strict"; + context.JK = context.JK || {}; + context.JK.RedeemSignUpScreen = function(app) { + + var logger = context.JK.logger; + var rest = context.JK.Rest(); + + var $screen = null; + var $signupForm = null; + var $self = $(this); + var $email = null; + var $password = null; + var $firstName = null; + var $lastName = null; + + var $signupBtn = null; + var $inputElements = null; + var $contentHolder = null; + var $btnNext = null; + var $btnFacebook = null; + var $termsOfServiceL = null; + var $termsOfServiceR = null; + var shoppingCartItem = null; + var $jamtrackName = null; + var $signinLink = null; + + function beforeShow(data) { + renderLoggedInState(); + } + + function afterShow(data) { + } + + + function renderLoggedInState(){ + + if(isLoggedIn()) { + $contentHolder.removeClass('not-signed-in').addClass('signed-in') + } + else { + $jamtrackName.text('') + $contentHolder.addClass('hidden') + $contentHolder.removeClass('signed-in').addClass('not-signed-in') + // now check that the user has one, and only one, free jamtrack in their shopping cart. + rest.getShoppingCarts() + .done(handleShoppingCartResponse) + .fail(app.ajaxError); + } + } + + function isLoggedIn() { + return !!context.JK.currentUserId; + } + + function events() { + $btnFacebook.on('click', onClickSignupFacebook) + $signupForm.on('submit', signup) + $signupBtn.on('click', signup) + $signinLink.on('click', onSignin); + } + + function handleShoppingCartResponse(carts) { + + if(carts.length == 0) { + // nothing is in the user's shopping cart. They shouldn't be here. + logger.error("invalid access of redeemJamTrack page") + window.location = '/client#/jamtrackBrowse' + } + 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") + window.location = '/client#/jamtrackBrowse' + } + else { + var item = carts[0]; + + if(item.product_info.free) { + // ok, we have one, free item. save it for + shoppingCartItem = item; + $jamtrackName.text('"' + shoppingCartItem.product_info.name + '"') + $contentHolder.removeClass('hidden') + } + else { + // the user has a non-free, single item in their basket. They shouldn't be here. + logger.error("invalid access of redeemJamTrack page") + window.location = '/client#/jamtrackBrowse' + } + } + + var $latestCartHtml = ""; + + var any_in_us = false + context._.each(carts, function(cart) { + if(cart.product_info.sales_region == 'United States') { + any_in_us = true + } + }) + } + function onClickSignupFacebook() { + // tos must already be clicked + + var $btn = $(e.target) + $btn.addClass('disabled') + + var $field = $termsOfServiceL.closest('.field') + $field.find('.error-text').remove() + + logger.debug("field, ", $field, $termsOfServiceL) + if($termsOfServiceL.is(":checked")) { + + rest.createSignupHint({redirect_location: '/client#/redeemComplete'}) + .done(function() { + // send the user on to facebook signin + window.location = $btn.attr('href'); + }) + .fail(function() { + app.notify({text:"Facebook Signup is not working properly"}); + }) + .always(function() { + $btn.removeClass('disabled') + }) + } + else { + $field.addClass("error").addClass("transparent"); + $field.append(""); + } + return false; + } + + function onSuccessfulSignin() { + // the user has signed in; + + // move all shopping carts from the anonymous user to the signed in user + /*rest.portOverCarts() + .done(function() { + logger.debug("ported over carts") + window.location = '/client#/redeemComplete' + }) + .fail(function() { + window.location.reload(); + }) + +*/ + window.location = '/client#/redeemComplete' + } + + function onSignin() { + app.layout.showDialog('signin-dialog', {redirect_to:onSuccessfulSignin}); + return false; + } + + function signup() { + if($signupBtn.is('.disabled')) { + return false; + } + + // clear out previous errors + $signupForm.find('.field.error').removeClass('error') + $signupForm.find('ul.error-text').remove() + + var email = $email.val(); + var password = $password.val(); + var first_name = $firstName.val(); + var last_name = $lastName.val(); + var terms = $termsOfServiceR.is(':checked') + + $signupBtn.text('TRYING...').addClass('disabled') + + + rest.signup({email: email, password: password, first_name: first_name, last_name: last_name, terms:terms}) + .done(function(response) { + window.location = '/client#/redeemComplete' + window.location.reload() + }) + .fail(function(jqXHR) { + if(jqXHR.status == 422) { + var response = JSON.parse(jqXHR.responseText) + if(response.errors) { + var $errors = context.JK.format_errors('first_name', response); + if ($errors) $firstName.closest('.field').addClass('error').append($errors); + + $errors = context.JK.format_errors('last_name', response); + if ($errors) $lastName.closest('.field').addClass('error').append($errors); + + $errors = context.JK.format_errors('password', response); + if ($errors) $password.closest('.field').addClass('error').append($errors); + + var $errors = context.JK.format_errors('email', response); + if ($errors) $email.closest('.field').addClass('error').append($errors); + + var $errors = context.JK.format_errors('terms_of_service', response); + if ($errors) $termsOfServiceR.closest('.field').addClass('error').append($errors); + } + else { + app.notify({title: 'Unknown Signup Error', text: jqXHR.responseText}) + } + } + else { + app.notifyServerError(jqXHR, "Unable to Sign Up") + } + }) + .always(function() { + $signupBtn.text('SIGNUP').removeClass('disabled') + }) + + + return false; + } + + + function initialize() { + var screenBindings = { + 'beforeShow': beforeShow, + 'afterShow': afterShow + }; + app.bindScreen('redeemSignup', screenBindings); + + $screen = $("#redeemSignupScreen"); + $signupForm = $screen.find(".signup-form"); + $signupBtn = $signupForm.find('.signup-submit'); + $email = $signupForm.find('input[name="email"]'); + $password = $signupForm.find('input[name="password"]'); + $firstName = $signupForm.find('input[name="first_name"]'); + $lastName = $signupForm.find('input[name="last_name"]'); + $inputElements = $signupForm.find('.input-elements'); + $contentHolder = $screen.find('.content-holder'); + $btnFacebook = $screen.find('.signup-facebook') + $termsOfServiceL = $screen.find('.left-side .terms_of_service input[type="checkbox"]') + $termsOfServiceR = $screen.find('.right-side .terms_of_service input[type="checkbox"]') + $jamtrackName = $screen.find('.jamtrack-name'); + $signinLink = $screen.find('.signin') + + if($screen.length == 0) throw "$screen must be specified"; + + events(); + } + + this.initialize = initialize; + + return this; + } +})(window,jQuery); \ No newline at end of file diff --git a/web/app/assets/javascripts/session.js b/web/app/assets/javascripts/session.js index feaed19de..a00991840 100644 --- a/web/app/assets/javascripts/session.js +++ b/web/app/assets/javascripts/session.js @@ -501,6 +501,7 @@ rest.openJamTrack({id: context.JK.CurrentSessionModel.id(), jam_track_id: jamTrack.id}) .done(function(response) { // now actually load the jamtrack + context.JK.CurrentSessionModel.updateSession(response); loadJamTrack(jamTrack); }) .fail(function(jqXHR) { diff --git a/web/app/assets/javascripts/sessionModel.js b/web/app/assets/javascripts/sessionModel.js index b2f501ff2..cd7edb8ae 100644 --- a/web/app/assets/javascripts/sessionModel.js +++ b/web/app/assets/javascripts/sessionModel.js @@ -156,6 +156,7 @@ } // did I open up the current JamTrack? function selfOpenedJamTracks() { + logger.debug("currentSession", currentSession) return currentSession && (currentSession.jam_track_initiator_id == context.JK.currentUserId) } diff --git a/web/app/assets/javascripts/shopping_cart.js b/web/app/assets/javascripts/shopping_cart.js index 9de0c7cf2..9193d9735 100644 --- a/web/app/assets/javascripts/shopping_cart.js +++ b/web/app/assets/javascripts/shopping_cart.js @@ -30,23 +30,35 @@ function proceedCheckout(e) { e.preventDefault(); - logger.debug("proceedCheckout") - if (!context.JK.currentUserId) { - logger.debug("proceeding to signin screen because there is no user") - window.location = '/client#/checkoutSignin'; - } - else { - var user = app.currentUser(); - - if(user.has_recurly_account && user.reuse_card) { - logger.debug("proceeding to checkout order screen because we have card info already") - window.location = '/client#/checkoutOrder'; + if (context.JK.currentUserFreeJamTrack) { + 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' } else { - logger.debug("proceeding to checkout payment screen because we do not have card info") - window.location = '/client#/checkoutPayment'; + logger.debug("proceeding to redeem signup screen because user has a free jamtrack and is not logged in") + window.location = '/client#/redeemSignup' } } + else { + if (!context.JK.currentUserId) { + logger.debug("proceeding to signin screen because there is no user") + window.location = '/client#/checkoutSignin'; + } + else { + var user = app.currentUser(); + + if(user.has_recurly_account && user.reuse_card) { + logger.debug("proceeding to checkout order screen because we have card info already") + window.location = '/client#/checkoutOrder'; + } + else { + logger.debug("proceeding to checkout payment screen because we do not have card info") + window.location = '/client#/checkoutPayment'; + } + } + } + } function removeCart(e) { diff --git a/web/app/assets/javascripts/web/signin_helper.js b/web/app/assets/javascripts/web/signin_helper.js index 76a5dfaab..56bef7160 100644 --- a/web/app/assets/javascripts/web/signin_helper.js +++ b/web/app/assets/javascripts/web/signin_helper.js @@ -20,21 +20,26 @@ var $rememberMe = null; var useAjax = false; var EVENTS = context.JK.EVENTS; - - function reset() { + var argRedirectTo = null; + + function reset(_redirectTo) { + argRedirectTo = _redirectTo; + clear(); + } + + function clear() { $signinForm.removeClass('login-error') $email.val(''); $password.val(''); $rememberMe.attr('checked', 'checked') } - function login() { var email = $email.val(); var password = $password.val(); var rememberMe = $rememberMe.is(':checked') - reset(); + clear(); $signinBtn.text('TRYING...'); @@ -42,6 +47,15 @@ .done(function() { //app.layout.closeDialog('signin-dialog') + if(argRedirectTo) { + if(argRedirectTo instanceof Function) { + argRedirectTo(); + } + else { + window.location.href = argRedirectTo; + } + return; + } var redirectTo = $.QueryString['redirect-to']; if(redirectTo) { logger.debug("redirectTo:" + redirectTo); @@ -68,7 +82,7 @@ function events() { $signinCancelBtn.click(function(e) { - app.layout.closeDialog('signin-dialog'); + app.layout.closeDialog('signin-dialog', true); e.stopPropagation(); return false; }); diff --git a/web/app/assets/stylesheets/client/client.css b/web/app/assets/stylesheets/client/client.css index aa551ede2..dd1e80976 100644 --- a/web/app/assets/stylesheets/client/client.css +++ b/web/app/assets/stylesheets/client/client.css @@ -59,6 +59,8 @@ *= require ./checkout_payment *= require ./checkout_order *= require ./checkout_complete + *= require ./redeem_signup + *= require ./redeem_complete *= require ./genreSelector *= require ./sessionList *= require ./searchResults @@ -75,4 +77,5 @@ *= require users/syncViewer *= require ./downloadJamTrack *= require ./jamTrackPreview + *= require users/signinCommon */ \ No newline at end of file diff --git a/web/app/assets/stylesheets/client/content.css.scss b/web/app/assets/stylesheets/client/content.css.scss index d34980aeb..50d7e4876 100644 --- a/web/app/assets/stylesheets/client/content.css.scss +++ b/web/app/assets/stylesheets/client/content.css.scss @@ -314,30 +314,6 @@ a.gold { color: #cc9900 !important; } -a.arrow-up { - float:right; - margin-right:5px; - display:block; - margin-top:6px; - width: 0; - height: 0; - border-left: 7px solid transparent; - border-right: 7px solid transparent; - border-bottom: 7px solid #333; -} - -a.arrow-down { - float:right; - margin-right:5px; - display:block; - margin-top:6px; - width: 0; - height: 0; - border-left: 7px solid transparent; - border-right: 7px solid transparent; - border-top: 7px solid #333; -} - .settings-session-description { padding:10px; width:200px; @@ -537,6 +513,32 @@ ul.shortcuts { padding:2px 8px !important; } + + +a.arrow-up { + float:right; + margin-right:5px; + display:block; + margin-top:6px; + width: 0; + height: 0; + border-left: 7px solid transparent; + border-right: 7px solid transparent; + border-bottom: 7px solid #333; +} + +a.arrow-down { + float:right; + margin-right:5px; + display:block; + margin-top:6px; + width: 0; + height: 0; + border-left: 7px solid transparent; + border-right: 7px solid transparent; + border-top: 7px solid #333; +} + a.arrow-up-orange { margin-left:5px; margin-bottom:2px; diff --git a/web/app/assets/stylesheets/client/jamtrack.css.scss b/web/app/assets/stylesheets/client/jamtrack.css.scss index b460fb214..0bbce8be2 100644 --- a/web/app/assets/stylesheets/client/jamtrack.css.scss +++ b/web/app/assets/stylesheets/client/jamtrack.css.scss @@ -31,6 +31,9 @@ } } + table.jamtrack-table { + table-layout:fixed; + } .jamtrack-content { text-align: center; border: 1px solid #222222; @@ -47,22 +50,41 @@ text-align: left; } + th.jamtrack-detail { + padding:6px; + } + + th.jamtrack-tracks { + padding:6px; + } + + th.jamtrack-action { + padding:6px; + text-align:center; + } + + td.jamtrack-action { + padding:0; + position:relative; + } + .jamtrack-detail { @include border_box_sizing; - width: 35%; + width: 25%; padding: 10px 0 0 10px; .detail-label { - width: 40%; + width: 80px; float: left; margin-top: 5px; font-weight: 400; font-size: 11px; + clear:both; } .detail-value { - width: 50%; float: left; margin-top: 5px; + margin-bottom:15px; font-size:11px; } @@ -84,12 +106,37 @@ margin-right: 5px; padding-top: 5px; vertical-align: bottom; + color:#fc0; + + .arrow-down { + float:none; + margin-left:5px; + margin-top:0; + margin-right:0; + border-top: 4px solid #fc0; + border-left: 4px solid transparent; + border-right: 4px solid transparent; + display:inline-block; + } + .arrow-up { + float:none; + margin-right:0; + margin-left:5px; + margin-bottom:2px; + border-bottom: 4px solid #fc0; + border-left: 4px solid transparent; + border-right: 4px solid transparent; + display:inline-block; + } } .jamtrack-tracks { + padding-bottom:30px; + position:relative; @include border_box_sizing; - width: 45%; - padding: 10px 0px; + width:55%; + //padding: 10px 0px; + .tracks-caption { margin-top: 5px; margin-bottom: 10px; @@ -117,12 +164,31 @@ .detail-arrow { + position:absolute; float: right; margin-right: 10px; + bottom:14px; + left:12px; } + .jamtrack-name { + font-size:16px; + white-space: normal; + } + + .jamtrack-original-artist { + font-size:16px; + margin-top:10px; + margin-bottom:5px; + white-space: normal; + } + + .jamtrack-track { - margin:0 0 8px 7px; + float:left; + padding:0 0 8px 7px; + width: 250px; + @include border_box_sizing; &.hidden { display:none; @@ -131,14 +197,23 @@ .jam-track-preview { font-size:11px; + white-space:nowrap; } .jamtrack-action { @include border_box_sizing; width: 20%; - // padding: 0px 0px; text-align: center; - // vertical-align: top; + + .jamtrack-action-container { + display: flex; + align-items: center; + justify-content: center; + position:absolute; + height:100%; + width:100%; + + } .play-button { margin-top: 5px; } @@ -149,6 +224,7 @@ &.free { margin-top:0; + display:none; .free-state { font-size: 11px; margin-top: 5px; diff --git a/web/app/assets/stylesheets/client/redeem_complete.css.scss b/web/app/assets/stylesheets/client/redeem_complete.css.scss new file mode 100644 index 000000000..ece08d208 --- /dev/null +++ b/web/app/assets/stylesheets/client/redeem_complete.css.scss @@ -0,0 +1,123 @@ +@import "client/common.css.scss"; +#redeemCompleteScreen { + + p { + font-size:14px; + margin:0; + } + + .order-prompt { + color:white; + line-height:125%; + } + + h2 { + color:white; + background-color:#4d4d4d; + font-weight:normal; + margin: 0 0 10px 0; + font-size:14px; + padding: 3px 0 3px 10px; + height: 14px; + line-height: 14px; + vertical-align: middle; + text-align:left; + } + + .action-bar { + margin-top:20px; + } + + #checkout-info-help { + margin-right:1px; + } + + .checkout-complete-wrapper { + padding:50px; + } + + .why-download { + margin-top:20px; + } + + .no-purchases-prompt { + + } + + .jam-tracks-in-browser { + + } + .thanks-panel { + + + span.notice { + font-style:italic; + font-size:12px; + } + + br.purchase-downloads { + clear:both; + margin-bottom:20px; + } + + .download-jamkazam { + color:$ColorLink; + border-radius: 4px; + border-style:solid; + border-color:#AAA; + border-width:1px; + padding:10px; + margin-top:20px; + display:inline-block; + } + + .download-jamkazam-wrapper { + text-align:center; + display:block; + margin-top:35px; + + &.hidden { + display:none; + } + } + .thanks-detail.purchased-jam-track { + + margin-top:20px; + + .purchased-jam-track-header { + font-size: 15px; + margin-bottom:10px; + + span { + display:none; + } + + &[status="in-progress"] { + span.in-progress-msg { + display:inline; + } + } + + &[status="done"] { + span.done-msg { + display:inline; + } + } + } + + ul.purchased-list { + float:left; + margin:20px 100px 0 20px; + + li { + margin:0; + } + } + + .download-jamtrack { + width:auto; + vertical-align: middle; // to make bullets mid-align when error shows + } + } + } +} \ No newline at end of file diff --git a/web/app/assets/stylesheets/client/redeem_signup.css.scss b/web/app/assets/stylesheets/client/redeem_signup.css.scss new file mode 100644 index 000000000..611d0f06e --- /dev/null +++ b/web/app/assets/stylesheets/client/redeem_signup.css.scss @@ -0,0 +1,247 @@ +@import "client/common.css.scss"; + +#redeemSignupScreen { + + .redeem-signup { + padding:30px; + } + .g-recaptcha { + //transform:scale(0.80); + //transform-origin:0 0; + } + + .jamtrack-name { + font-weight:bold; + } + .content-holder { + + //margin-top:40px; + color:$ColorTextTypical; + + &.signed-in { + .left-side, .right-side { + display:none; + } + .not-signed-in.prompt { + display:none; + } + } + &.not-signed-in { + .already-signed-in { + display:none; + } + } + } + + .not-signed-in.prompt { + text-align:center; + } + .already-signed-in { + text-align:center; + h3 { + text-align:center; + } + } + + a.forgot-password { + position:absolute; + top:0; + left:0; + font-size:10px; + } + + .error-text { + margin:0; + + li { + margin-bottom:5px; + } + } + + .signup-submit { + margin-right:2px; + } + + .signup-facebook { + text-align:center; + } + + .signup-later-prompt { + margin:30px 0 30px 0; + text-align:center; + } + + .signup-prompt { + float:right; + text-align:left; + margin:30px 0 15px 0; + width:60%; + max-width:300px; + @include border_box_sizing; + + span { + text-align:left; + } + } + + p { + font-size:14px; + line-height:125%; + } + + + .login-error { + + div.actions { + margin-top:10px; + } + + .field { + background-color: #330000; + border: 1px solid #990000; + padding:8px; + } + } + + .field { + display:block; + @include border_box_sizing; + padding:6px 8px; + margin:0px -8px; + white-space: nowrap; + + &.error { + background-color:#300; + border: solid 1px #900; + + li { + list-style:none; + } + } + } + + .login-error-msg { + display:none; + margin-top:10px; + text-align:center; + color:#F00; + font-size:11px; + width:60%; + max-width:300px; + @include border_box_sizing; + float:right; + margin-bottom:10px; + } + + + .login-error .login-error-msg { + display:block; + } + + h3 + { + color:$ColorTextHighlight; + text-align:left; + font-size:16px; + font-weight:700; + margin-bottom:15px; + } + + input { + @include border_box_sizing; + } + + + .btnNext { + margin:0 auto; + } + + .left-side, .right-side { + margin-top:50px; + } + .left-side { + float:left; + width:50%; + @include border_box_sizing; + border-width:0 1px 0 0; + border-color:white; + border-style:solid; + text-align:right; + padding: 0 60px; + margin-bottom:20px; + + .actions { + width:60%; + max-width:300px; + @include border_box_sizing; + position:relative; + float:right; + } + + .terms_of_service { + text-align:center; + label { + display:inline; + } + font-size:11px; + } + } + + a.signin { + text-decoration: underline; + font-size:12px; + margin-left:15px; + } + .left-side-content { + @include border_box_sizing; + float:right; + text-align:center; + } + + + .right-side { + float:left; + width:50%; + @include border_box_sizing; + padding: 0 60px; + + .actions { + margin-top:11px; + margin-left:-8px; + white-space: nowrap; + input { + width:auto; + } + } + + + input { + width:80%; + max-width:300px; + } + label { + display:inline-block; + width:80px; + text-align:left; + } + + .terms_of_service { + input { + width: auto; + margin-left: -2px; + } + label { + display:inline; + } + font-size:11px; + } + } + + .facebook-prompt { + margin:40px 0 10px 0; + float:right; + text-align:left; + width:249px; + @include border_box_sizing; + } +} \ No newline at end of file diff --git a/web/app/assets/stylesheets/users/signinCommon.css.scss b/web/app/assets/stylesheets/users/signinCommon.css.scss index 3a5d7ca0a..63f8ad2b2 100644 --- a/web/app/assets/stylesheets/users/signinCommon.css.scss +++ b/web/app/assets/stylesheets/users/signinCommon.css.scss @@ -8,6 +8,10 @@ height:auto; } + strong { + font-weight:bold; + } + label { margin-bottom:2px; } diff --git a/web/app/controllers/api_jam_tracks_controller.rb b/web/app/controllers/api_jam_tracks_controller.rb index 8dd019cd0..a6a3bc44c 100644 --- a/web/app/controllers/api_jam_tracks_controller.rb +++ b/web/app/controllers/api_jam_tracks_controller.rb @@ -73,13 +73,23 @@ class ApiJamTracksController < ApiController def download if @jam_track_right.valid? + + all_fingerprint = params[:all_fp] + running_fingerprint = params[:running_fp] + + error = @jam_track_right.guard_against_fraud(current_user, {all:all_fingerprint, running: running_fingerprint}, request.remote_ip) + if error + log.warn("potential fraud detected: #{error}") + render :json => { :message => error }, :status => 403 + return + end + sample_rate = params[:sample_rate].nil? ? nil : params[:sample_rate].to_i if @jam_track_right && @jam_track_right.ready?(sample_rate) @jam_track_right.update_download_count - @jam_track_right.last_downloaded_at = Time.now - if @jam_track_right.first_downloaded_at.nil? - @jam_track_right.first_downloaded_at = Time.now - end + now = Time.now + @jam_track_right.last_downloaded_at = now + @jam_track_right.first_downloaded_at = now if @jam_track_right.first_downloaded_at.nil? @jam_track_right.save! redirect_to @jam_track_right.sign_url(120, sample_rate) else @@ -92,6 +102,16 @@ class ApiJamTracksController < ApiController end def enqueue + + fingerprint = params[:fingerprint] + + error = @jam_track_right.guard_against_fraud(current_user, fingerprint, request.remote_ip) + if error + log.warn("potential fraud detected: #{error}") + render :json => { :message => error }, :status => 403 + return + end + sample_rate = params[:sample_rate].nil? ? nil : params[:sample_rate].to_i enqueued = @jam_track_right.enqueue_if_needed(sample_rate) log.debug("jamtrack #{enqueued ? "ENQUEUED" : "NOT ENQUEUED"}: jam_track_right=#{@jam_track_right.id} sample_rate=#{sample_rate} ") diff --git a/web/app/controllers/api_recurly_controller.rb b/web/app/controllers/api_recurly_controller.rb index 177c3c4cb..f3090e7a2 100644 --- a/web/app/controllers/api_recurly_controller.rb +++ b/web/app/controllers/api_recurly_controller.rb @@ -25,26 +25,20 @@ class ApiRecurlyController < ApiController # keep reuse card up-to-date User.where(id: current_user.id).update_all(reuse_card: params[:reuse_card_next_time]) else + options = { - remote_ip: request.remote_ip, first_name: billing_info[:first_name], last_name: billing_info[:last_name], email: params[:email], password: params[:password], password_confirmation: params[:password], terms_of_service: terms_of_service, - instruments: [{:instrument_id => 'other', :proficiency_level => 1, :priority => 1}], - birth_date: nil, location: {:country => billing_info[:country], :state => billing_info[:state], :city => billing_info[:city]}, - musician: true, - skip_recaptcha: true, - invited_user: nil, - fb_signup: nil, - signup_confirm_url: ApplicationHelper.base_uri(request) + "/confirm", - any_user: any_user, reuse_card: reuse_card_next_time } + options = User.musician_defaults(request.remote_ip, ApplicationHelper.base_uri(request) + "/confirm", any_user, options) + user = UserManager.new.signup(options) if user.errors.any? @@ -142,6 +136,7 @@ class ApiRecurlyController < ApiController if error render json: {errors: {message: error}}, :status => 404 else + set_purchased_jamtrack_cookie render :json => response, :status => 200 end rescue RecurlyClientError => x diff --git a/web/app/controllers/api_shopping_carts_controller.rb b/web/app/controllers/api_shopping_carts_controller.rb index 761c3dc81..c962ae3fc 100644 --- a/web/app/controllers/api_shopping_carts_controller.rb +++ b/web/app/controllers/api_shopping_carts_controller.rb @@ -51,6 +51,15 @@ class ApiShoppingCartsController < ApiController respond_with responder: ApiResponder, :status => 204 end + # take all shopping carts from anonymous user and copy them to logged in user + def port + if current_user && anonymous_user + ShoppingCart.port(current_user, anonymous_user) + else + render :json => {message: 'one or both users not available'}, :status => 403 + end + end + def clear_all any_user.destroy_all_shopping_carts render :json=>{}, :status=>200 diff --git a/web/app/controllers/api_users_controller.rb b/web/app/controllers/api_users_controller.rb index 58a3a8de1..3114fc26b 100644 --- a/web/app/controllers/api_users_controller.rb +++ b/web/app/controllers/api_users_controller.rb @@ -32,6 +32,43 @@ class ApiUsersController < ApiController respond_with @user, responder: ApiResponder, :status => 200 end + # in other words, a minimal signup + def create + # today, this only accepts a minimal registration; it could be made to take in more if we wanted + signup_hint = nil + if anonymous_user + signup_hint = anonymous_user.signup_hint + if signup_hint && signup_hint.jam_track.nil? + signup_hint = nil # it doesn't make sense to pass in signup hints that are not free jam-track centric (at least, not today) + end + end + + # recaptcha_response: params['g-recaptcha-response'] + + options = { + first_name: params[:first_name], + last_name: params[:last_name], + email: params[:email], + password: params[:password], + password_confirmation: params[:password], + terms_of_service: params[:terms], + location: {:country => nil, :state => nil, :city => nil}, + signup_hint: signup_hint + } + + options = User.musician_defaults(request.remote_ip, ApplicationHelper.base_uri(request) + "/confirm", any_user, options) + + @user = UserManager.new.signup(options) + + if @user.errors.any? + respond_with_model(@user) + else + sign_in @user + new_user(@user, signup_hint) # sets a cookie used for GA analytics (one-time new user stuff in JavaScript) + respond_with_model(@user, new: true, location: lambda { return api_user_detail_url(@user.id) }) + end + end + def update @user = User.find(params[:id]) diff --git a/web/app/controllers/application_controller.rb b/web/app/controllers/application_controller.rb index 844faf7ea..7f242aff0 100644 --- a/web/app/controllers/application_controller.rb +++ b/web/app/controllers/application_controller.rb @@ -35,6 +35,7 @@ class ApplicationController < ActionController::Base cookies.permanent[:user_uuid] = SecureRandom.uuid unless cookies[:user_uuid] end + private def add_user_info_to_bugsnag(notif) # Add some app-specific data which will be displayed on a custom diff --git a/web/app/controllers/clients_controller.rb b/web/app/controllers/clients_controller.rb index d05fd60bd..4842aafd1 100644 --- a/web/app/controllers/clients_controller.rb +++ b/web/app/controllers/clients_controller.rb @@ -16,6 +16,7 @@ class ClientsController < ApplicationController return end + @in_client_page = true @minimal_curtain = Rails.application.config.minimal_curtain gon.recurly_tax_estimate_jam_track_plan = Rails.application.config.recurly_tax_estimate_jam_track_plan render :layout => 'client' diff --git a/web/app/controllers/sessions_controller.rb b/web/app/controllers/sessions_controller.rb index 7118cc953..4962d93a8 100644 --- a/web/app/controllers/sessions_controller.rb +++ b/web/app/controllers/sessions_controller.rb @@ -121,8 +121,37 @@ class SessionsController < ApplicationController end fb_signup.save! - redirect_to "#{signup_path}?facebook_signup=#{fb_signup.lookup_id}" - return + # see if we can find a SignupHint for a JamTrack; if so, bounce them back to the redeemComplete page to let them know we bought it + + if anonymous_user + signup_hint = anonymous_user.signup_hint + if signup_hint && signup_hint.redirect_location + options = { + first_name: first_name, + last_name: last_name, + email: email, + terms_of_service: true, + location: {:country => nil, :state => nil, :city => nil}, + } + + options = User.musician_defaults(request.remote_ip, ApplicationHelper.base_uri(request) + "/confirm", any_user, options) + + user = UserManager.new.signup(options) + + if user.errors.any? + redirect_to signup_hint.redirect_location + return + end + + sign_in(user) + new_user(user, signup_hint) + redirect_to signup_hint.redirect_location + return + end + else + redirect_to "#{signup_path}?facebook_signup=#{fb_signup.lookup_id}" + return + end end if current_user.nil? diff --git a/web/app/controllers/users_controller.rb b/web/app/controllers/users_controller.rb index 72e4a74e4..a1d17d28d 100644 --- a/web/app/controllers/users_controller.rb +++ b/web/app/controllers/users_controller.rb @@ -180,23 +180,6 @@ class UsersController < ApplicationController end end - # given the current user, and any signup hint (can be nil) - # handle the final destination of the user - def handle_signup_hint(user, signup_hint, default_redirect) - redirect_url = default_redirect - if signup_hint - if signup_hint.want_jamblaster - User.where(id: user.id).update_all(want_jamblaster: true) - end - - if signup_hint.redirect_location - redirect_url = signup_hint.redirect_location - end - end - - redirect_url - end - def congratulations_fan @no_user_dropdown = true render :layout => "web" diff --git a/web/app/helpers/sessions_helper.rb b/web/app/helpers/sessions_helper.rb index f9599bdef..6e6cb7c7b 100644 --- a/web/app/helpers/sessions_helper.rb +++ b/web/app/helpers/sessions_helper.rb @@ -2,6 +2,7 @@ module SessionsHelper def sign_in(user) set_remember_token(user) + set_purchased_jamtrack_cookie unless user.has_redeemable_jamtrack self.current_user = user end @@ -21,6 +22,12 @@ module SessionsHelper end end + + # should be set whenever a user logs in who has redeemed a free jamtrack, or whenever the user + def set_purchased_jamtrack_cookie + cookies.permanent[:redeemed_jamtrack] = true + end + def complete_sign_in(user, redirect=true) sign_in user @@ -64,7 +71,7 @@ module SessionsHelper def anonymous_user if anon_cookie - @anonymous_user ||= AnonymousUser.new(anon_cookie) + @anonymous_user ||= AnonymousUser.new(anon_cookie, cookies) else nil end @@ -91,6 +98,25 @@ module SessionsHelper cookies[:new_user] = { musician: user.musician, registrationType: user.user_authorization('facebook') ? 'Facebook' : 'Native', want_jamblaster: want_jamblaster, redirect_location: redirect_location }.to_json end + + # given the current user, and any signup hint (can be nil) + # handle the final destination of the user + def handle_signup_hint(user, signup_hint, default_redirect) + redirect_url = default_redirect + if signup_hint + if signup_hint.want_jamblaster + User.where(id: user.id).update_all(want_jamblaster: true) + end + + if signup_hint.redirect_location + redirect_url = signup_hint.redirect_location + end + end + + redirect_url + end + + def current_user?(user) user == current_user end diff --git a/web/app/views/api_users/show.rabl b/web/app/views/api_users/show.rabl index c86a6e71c..a7585f4e3 100644 --- a/web/app/views/api_users/show.rabl +++ b/web/app/views/api_users/show.rabl @@ -10,7 +10,7 @@ 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 + 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 node :geoiplocation do |user| geoiplocation = current_user.geoiplocation diff --git a/web/app/views/clients/_jamtrack.html.slim b/web/app/views/clients/_jamtrack.html.slim deleted file mode 100644 index 0d3a5478f..000000000 --- a/web/app/views/clients/_jamtrack.html.slim +++ /dev/null @@ -1,83 +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 - thead - tr - th JAMTRACK - th TRACKS INCLUDED / PREVIEW - th.center 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 - .detail-label - | Title: - .detail-value - | {{data.jamtrack.name}} - .clearall.detail-label - | Original Artist: - .detail-value - | {{data.jamtrack.original_artist}} - .clearall.detail-label - | Genre: - .detail-value - | {{data.jamtrack.genres[0]}} - .clearall.detail-label.extra.hidden - | Writer(s): - .detail-value.extra.hidden - | {{data.jamtrack.songwriter}} - .clearall.detail-label.extra.hidden - | Publisher: - .detail-value.extra.hidden - | {{data.jamtrack.publisher}} - td.jamtrack-tracks - .detail-arrow - .jamtrack-detail-btn.orange - ="{% if (data.expanded) { %}" - | hide tracks - a.details-arrow.arrow-up-orange - ="{% } else { %}" - | preview all tracks - a.details-arrow.arrow-down-orange - ="{% } %}" - ="{% _.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 - / 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}} - .free-state.hidden - | (first one is FREE) - ="{% 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? - ="{% }; %}" diff --git a/web/app/views/clients/_jamtrack_browse.html.slim b/web/app/views/clients/_jamtrack_browse.html.slim new file mode 100644 index 000000000..f7d7b515a --- /dev/null +++ b/web/app/views/clients/_jamtrack_browse.html.slim @@ -0,0 +1,86 @@ +#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? + ="{% }; %}" diff --git a/web/app/views/clients/_redeem_complete.html.slim b/web/app/views/clients/_redeem_complete.html.slim new file mode 100644 index 000000000..ec0c06154 --- /dev/null +++ b/web/app/views/clients/_redeem_complete.html.slim @@ -0,0 +1,47 @@ +div layout="screen" layout-id="redeemComplete" id="redeemCompleteScreen" 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 + .content-body-scroller + .content-wrapper + .checkout-navigation-bar + .checkout-complete-wrapper + .no-purchases-prompt.hidden + | You have not made any purchases recently. Why not go go  + a href="/client#/jamtrackBrowse" browse our collection of JamTracks + | ? + .thanks-panel + + .jam-tracks-in-browser.hidden + p Thank you for joining our community, and congratulations on getting your first JamTrack! + p.why-download + | JamTracks are full multi-track recordings with lots of special features, so they are not  + | just standard audio files. To play with your JamTrack, you'll need to download and install  + | our free Mac or Windows app. This is the last step in the process, and you'll be ready to play.  + | This free app also lets you play online in real time with other musicians over the Internet at no cost! + + a.download-jamkazam-wrapper href="/downloads" rel="external" + .download-jamkazam + | Click Here to Get the Free JamKazam Application + + .jam-tracks-in-client.hidden + + h2 Congratulations on getting your JamTrack! + + .thanks-detail.purchased-jam-track + h2.purchased-jam-track-header status="in-progress" + span.in-progress-msg Downloading Your JamTrack + span.done-msg All purchased JamTracks have been downloaded successfully! You can now play them in a session. + 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 + .clearall.hidden + .action-bar + .right + a.button-orange.checkout-done href="/client#/home" DONE + .clearall diff --git a/web/app/views/clients/_redeem_signup.html.slim b/web/app/views/clients/_redeem_signup.html.slim new file mode 100644 index 000000000..1b2ad59e8 --- /dev/null +++ b/web/app/views/clients/_redeem_signup.html.slim @@ -0,0 +1,67 @@ +div layout="screen" layout-id="redeemSignup" id="redeemSignupScreen" class="screen secondary no-login-required" + .content + .content-head + .content-icon= image_tag("content/icon_shopping_cart.png", {:height => 19, :width => 19}) + h1 check out + = render "screen_navigation" + .content-body + .content-body-scroller + .redeem-signup + + .content-holder + .already-signed-in + h3 YOU ARE ALREADY LOGGED IN + p.carry-on-prompt + | You can go back to browsing. + .actions + a.btnNext.button-orange href="/client#/jamtrackBrowse" BROWSE JAMTRACKS + .not-signed-in.prompt + | To get your free  + span.jamtrack-name + |  JamTrack, join thousands of musicians in the JamKazam community by registering for your free account. + .left-side + .left-side-content + = link_to image_tag("content/button_facebook_signup.png", {:width => 249, :height => 46}), '/auth/facebook', class: "signup-facebook" + br clear="all" + .field.terms_of_service + input type="checkbox" + label + | I have read and agree to the JamKazam + br + = link_to "terms of service", corp_terms_path, rel: "external" + |. + br clear="all" + + .right-side + h3 OR SIGN UP USING YOUR EMAIL + + .signup-form + form.signup-form + .input-elements + .field + label.inline First Name: + input name='first_name' autofocus="true" type="text" + .field + label.inline Last Name: + input name='last_name' type="text" + .field + label.inline Email: + input name='email' type="text" + .field + label.inline Password: + input name='password' autofocus="true" type="password" + .field.terms_of_service + input type="checkbox" + label + | I have read and agree to the JamKazam   + = link_to "terms of service", corp_terms_path, rel: "external" + |. + .field.recaptcha style="display:none" + - if Rails.application.config.recaptcha_enable + #recaptcha_select name="recaptcha_response_field" class="g-recaptcha" data-sitekey=Rails.application.config.recaptcha_public_key + .actions + input.button-orange.signup-submit type="submit" value="SIGNUP" + + = link_to "Already have a JamKazam account? Sign in", "#", class: 'signin' + + br clear='all' \ No newline at end of file diff --git a/web/app/views/clients/index.html.erb b/web/app/views/clients/index.html.erb index 4c2b91a0f..4296ced1a 100644 --- a/web/app/views/clients/index.html.erb +++ b/web/app/views/clients/index.html.erb @@ -37,13 +37,15 @@ <%= render "band_setup_photo" %> <%= render "users/feed_music_session_ajax" %> <%= render "users/feed_recording_ajax" %> -<%= render "jamtrack" %> +<%= render "jamtrack_browse" %> <%= render "jamtrack_landing" %> <%= render "shopping_cart" %> <%= render "checkout_signin" %> <%= render "checkout_payment" %> <%= render "checkout_order" %> <%= render "checkout_complete" %> +<%= render "redeem_signup" %> +<%= render "redeem_complete" %> <%= render "order" %> <%= render "feed" %> <%= render "bands" %> @@ -111,12 +113,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 %> <% 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%> <% end %> @@ -276,6 +280,12 @@ var checkoutCompleteScreen = new JK.CheckoutCompleteScreen(JK.app); checkoutCompleteScreen.initialize(); + var redeemSignUpScreen = new JK.RedeemSignUpScreen(JK.app); + redeemSignUpScreen.initialize(); + + var redeemCompleteScreen = new JK.RedeemCompleteScreen(JK.app); + redeemCompleteScreen.initialize(); + var findMusicianScreen = new JK.FindMusicianScreen(JK.app); findMusicianScreen.initialize(JK.TextMessageDialogInstance); @@ -309,6 +319,10 @@ var singlePlayerProfileGuardDialog = new JK.SinglePlayerProfileGuardDialog(JK.app); singlePlayerProfileGuardDialog.initialize(); + var signinDialog = new JK.SigninDialog(JK.app); + signinDialog.initialize(); + JK.SigninPage(); // initialize signin helper + // do a client update early check upon initialization JK.ClientUpdateInstance.check() diff --git a/web/app/views/layouts/client.html.erb b/web/app/views/layouts/client.html.erb index 50c2dd645..dd7d51a9b 100644 --- a/web/app/views/layouts/client.html.erb +++ b/web/app/views/layouts/client.html.erb @@ -39,6 +39,6 @@ <%= yield %> <%= render "shared/ga" %> <%= render "shared/recurly" %> - + <%= render "shared/google_nocaptcha" %> diff --git a/web/app/views/users/_user_dropdown.html.erb b/web/app/views/users/_user_dropdown.html.erb index 44a0ebfb7..40d20c8e7 100644 --- a/web/app/views/users/_user_dropdown.html.erb +++ b/web/app/views/users/_user_dropdown.html.erb @@ -1,7 +1,7 @@
-<% if Rails.application.config.jam_tracks_available %> +<% if Rails.application.config.jam_tracks_available && @in_client_page %> diff --git a/web/app/views/users/new.html.erb b/web/app/views/users/new.html.erb index 83a2c5c0c..f7b718af5 100644 --- a/web/app/views/users/new.html.erb +++ b/web/app/views/users/new.html.erb @@ -117,13 +117,13 @@
-
- - <%= f.check_box :terms_of_service %> - I have read and agree to the JamKazam <%= link_to "terms of service", corp_terms_path, :rel => "external" %> - . - -
+
+ + <%= f.check_box :terms_of_service %> + I have read and agree to the JamKazam <%= link_to "terms of service", corp_terms_path, :rel => "external" %> + . + +
<% if Rails.application.config.recaptcha_enable %> diff --git a/web/config/routes.rb b/web/config/routes.rb index e57693f97..f9a2b8244 100644 --- a/web/config/routes.rb +++ b/web/config/routes.rb @@ -262,6 +262,7 @@ SampleApp::Application.routes.draw do match '/data_validation' => 'api_users#validate_data', :via => :get match '/users' => 'api_users#index', :via => :get + match '/users' => 'api_users#create', :via => :post match '/users/:id' => 'api_users#show', :via => :get, :as => 'api_user_detail' #match '/users' => 'api_users#create', :via => :post match '/users/:id' => 'api_users#update', :via => :post diff --git a/web/lib/user_manager.rb b/web/lib/user_manager.rb index b94c1c1c8..0ce291b60 100644 --- a/web/lib/user_manager.rb +++ b/web/lib/user_manager.rb @@ -27,6 +27,8 @@ class UserManager < BaseManager signup_confirm_url = options[:signup_confirm_url] affiliate_referral_id = options[:affiliate_referral_id] any_user = options[:any_user] + signup_hint = options[:signup_hint] + recaptcha_failed = false unless options[:skip_recaptcha] # allow callers to opt-of recaptcha recaptcha_failed = fb_signup ? false : !@google_client.verify_recaptcha(options[:recaptcha_response]) @@ -67,7 +69,8 @@ class UserManager < BaseManager fb_signup: fb_signup, signup_confirm_url: signup_confirm_url, affiliate_referral_id: affiliate_referral_id, - any_user: any_user) + any_user: any_user, + signup_hint: signup_hint) user end diff --git a/web/spec/controllers/api_users_controller_spec.rb b/web/spec/controllers/api_users_controller_spec.rb index 0c2990cf6..a95ffebf7 100644 --- a/web/spec/controllers/api_users_controller_spec.rb +++ b/web/spec/controllers/api_users_controller_spec.rb @@ -11,10 +11,59 @@ describe ApiUsersController do controller.current_user = user end + describe "create" do + it "successful" do + email = 'user_create1@jamkazam.com' + post :create, first_name: 'Seth', last_name: 'Call', email: email, password: 'jam123', terms: true, format: 'json' + response.should be_success + found = User.find_by_email(email) + found.city.should be_nil + found.state.should be_nil + found.country.should be_nil + found.musician.should be_true + found.musician_instruments.count.should be(1) + found.last_jam_updated_reason.should eq('r') + found.last_jam_locidispid.should_not be_nil + end + + it "no first name" do + email = 'user_create2@jamkazam.com' + post :create, first_name: nil, last_name: 'Call', email: email, password: 'jam123', terms: true, format: 'json' + response.status.should eq(422) + error_data = JSON.parse(response.body) + error_data['errors']['first_name'].should eq(["can't be blank"]) + end + + it "no email" do + email = nil + post :create, first_name: nil, last_name: 'Call', email: email, password: 'jam123', terms: true, format: 'json' + response.status.should eq(422) + error_data = JSON.parse(response.body) + error_data['errors']['email'].should eq(["can't be blank", "is invalid"]) + end + + it "short password" do + email = nil + post :create, first_name: nil, last_name: 'Call', email: email, password: 'jam', terms: true, format: 'json' + response.status.should eq(422) + error_data = JSON.parse(response.body) + error_data['errors']['password'].should eq(["is too short (minimum is 6 characters)"]) + end + + it "no terms" do + email = 'user_create3@jamkazam.com' + post :create, first_name: 'Seth', last_name: 'Call', email: email, password: 'jam123', terms: false, format: 'json' + response.status.should eq(422) + error_data = JSON.parse(response.body) + error_data['errors']['terms_of_service'].should eq(["must be accepted"]) + end + end + describe "update mod" do it "empty mod" do post :update, id:user.id, mods: {}, :format=>'json' response.should be_success + user.reload user.mods_json.should == {} end diff --git a/web/spec/features/checkout_spec.rb b/web/spec/features/checkout_spec.rb index 297504b14..d0a3a9b0c 100644 --- a/web/spec/features/checkout_spec.rb +++ b/web/spec/features/checkout_spec.rb @@ -498,6 +498,7 @@ describe "Checkout", :js => true, :type => :feature, :capybara_feature => true d end it "shows one free, one not free item correctly (not-Texas)" do + pending "not possible to have one free and one not-free in shopping cart currently" ShoppingCart.add_jam_track_to_cart(user, jamtrack_acdc_backinblack) user.reload ShoppingCart.add_jam_track_to_cart(user, jamtrack_pearljam_evenflow) @@ -521,6 +522,7 @@ describe "Checkout", :js => true, :type => :feature, :capybara_feature => true d end it "shows one free, one not free item correctly (Texas)" do + pending "not possible to have one free and one not-free in shopping cart currently" ShoppingCart.add_jam_track_to_cart(user, jamtrack_acdc_backinblack) user.reload ShoppingCart.add_jam_track_to_cart(user, jamtrack_pearljam_evenflow) @@ -673,6 +675,9 @@ describe "Checkout", :js => true, :type => :feature, :capybara_feature => true d it "shows purchase error correctly" do + user.has_redeemable_jamtrack = false + user.save! + ShoppingCart.add_jam_track_to_cart(user, jamtrack_acdc_backinblack) @recurlyClient.create_account(user, billing_info) @@ -700,73 +705,29 @@ describe "Checkout", :js => true, :type => :feature, :capybara_feature => true d find('h1', text: 'jamtracks') #find('a', text: 'What is a JamTrack?') - find("a.jamtrack-add-cart[data-jamtrack-id=\"#{jamtrack_acdc_backinblack.id}\"]").trigger(:click) - find('h1', text: 'shopping cart') - find('.cart-item-caption', text: "JamTrack: #{jamtrack_acdc_backinblack.name}") - find('.cart-item-price', text: "$ #{0.00}") # 1st one is free! - find('.shopping-sub-total', text:"Subtotal:$ 0.00") - - # attempt to checkout - find('a.button-orange', text: 'PROCEED TO CHECKOUT').trigger(:click) - + find("a.jamtrack-add-cart[data-jamtrack-id=\"#{jamtrack_acdc_backinblack.id}\"]", text: 'GET IT FREE!').trigger(:click) + find('h3', text: 'OR SIGN UP USING YOUR EMAIL') shopping_carts = ShoppingCart.all shopping_carts.count.should eq(1) shopping_cart = shopping_carts[0] shopping_cart.anonymous_user_id.should_not be_nil shopping_cart.user_id.should be_nil - # we should now be on checkoutSignin - find('h3', text: 'ALREADY A MEMBER OF THE JAMKAZAM COMMUNITY?') - verify_nav(1) - - # skip to payment without signing in - find('a.btnNext').trigger(:click) - - # this should take us to the payment screen - find('p.payment-prompt') - find('.jamkazam-account-signup') - - # 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' - fill_in 'checkout-signup-email', with: 'guy@jamkazam.com' - fill_in 'checkout-signup-password', with: 'jam123' - find('#divJamKazamTos ins.iCheck-helper').trigger(:click) # accept TOS + fill_in 'first_name', with: 'Seth' + fill_in 'last_name', with: 'Call' + fill_in 'email', with: 'guy@jamkazam.com' + fill_in 'password', with: 'jam123' + find('.right-side .terms_of_service input').trigger(:click) # accept TOS # try to submit, and see order page - find('#payment-info-next').trigger(:click) - - # now see order page, and everything should appear free - find('p.order-prompt') - find('.order-items-value.order-total', text:'$0.00') - find('.order-items-value.shipping-handling', text:'$0.00') - find('.order-items-value.sub-total', text:'$0.00') - find('.order-items-value.taxes', text:'$0.00') - find('.order-items-value.grand-total', text:'$0.00') + find('.signup-submit').trigger(:click) + find('.jam-tracks-in-browser') guy = User.find_by_email('guy@jamkazam.com') # verify that the shopping cart has user_id info updated - shopping_cart.reload - shopping_cart.anonymous_user_id.should be_nil - shopping_cart.user.should eq(guy) - - # also verify that there is still only one shopping cart, implying we deleted the anonymous user's shopping cart - shopping_carts = ShoppingCart.all - shopping_carts.count.should eq(1) - - # 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') + guy.shopping_carts.length.should eq(0) guy.reload jam_track_right = jamtrack_acdc_backinblack.right_for_user(guy) @@ -779,7 +740,7 @@ describe "Checkout", :js => true, :type => :feature, :capybara_feature => true d guy.sales.length.should eq(1) sale = guy.sales.first sale.sale_line_items.length.should eq(1) - acdc_sale = SaleLineItem.find_by_recurly_adjustment_uuid(jam_track_right.recurly_adjustment_uuid) + acdc_sale = sale.sale_line_items[0] acdc_sale.recurly_plan_code.should eq(jamtrack_acdc_backinblack.plan_code) acdc_sale.product_type.should eq('JamTrack') acdc_sale.product_id.should eq(jamtrack_acdc_backinblack.id) @@ -789,11 +750,15 @@ describe "Checkout", :js => true, :type => :feature, :capybara_feature => true d acdc_sale.sale.should eq(sale) + # this is a little cheat to make the billing info dropdown already say US + guy.country = 'US' + guy.save! + # now, go back to checkout flow again, and make sure we are told there are no free jam tracks visit "/client#/jamtrackBrowse" - find("a.jamtrack-add-cart[data-jamtrack-id=\"#{jamtrack_pearljam_evenflow.id}\"]").trigger(:click) + 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}") @@ -802,6 +767,24 @@ describe "Checkout", :js => true, :type => :feature, :capybara_feature => true d # 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 @@ -844,16 +827,38 @@ describe "Checkout", :js => true, :type => :feature, :capybara_feature => true d end - it "for existing user" do + + it "for existing user with a freebie available (already logged in)" do + fast_signin(user, "/client#/jamtrackBrowse") find('h1', text: 'jamtracks') #find('a', text: 'What is a JamTrack?') - find("a.jamtrack-add-cart[data-jamtrack-id=\"#{jamtrack_acdc_backinblack.id}\"]").trigger(:click) + 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 + jam_track_right = jamtrack_acdc_backinblack.right_for_user(user) + # make sure it appears the user actually bought the jamtrack! + jam_track_right.should_not be_nil + jam_track_right.redeemed.should be_true + user.has_redeemable_jamtrack.should be_false + end + + it "for existing user with no freebie available (already logged in)" do + user.has_redeemable_jamtrack = false + user.save! + + fast_signin(user, "/client#/jamtrackBrowse") + find('h1', text: 'jamtracks') + #find('a', text: 'What is a JamTrack?') + + find("a.jamtrack-add-cart[data-jamtrack-id=\"#{jamtrack_acdc_backinblack.id}\"]", text: 'ADD TO CART').trigger(:click) find('h1', text: 'shopping cart') find('.cart-item-caption', text: "JamTrack: #{jamtrack_acdc_backinblack.name}") - find('.cart-item-price', text: "$ #{0.00}") # 1st one is free! - find('.shopping-sub-total', text:"Subtotal:$ 0.00") + find('.cart-item-price', text: "$ #{jamtrack_acdc_backinblack.price}") # 1st one is free! + find('.shopping-sub-total', text:"Subtotal:$ 1.99") # attempt to checkout find('a.button-orange', text: 'PROCEED TO CHECKOUT').trigger(:click) @@ -878,11 +883,11 @@ describe "Checkout", :js => true, :type => :feature, :capybara_feature => true d # now see order page, and everything should appear free find('p.order-prompt') - find('.order-items-value.order-total', text:'$0.00') + 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:'$0.00') - find('.order-items-value.taxes', text:'$0.00') - find('.order-items-value.grand-total', 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) @@ -894,11 +899,11 @@ describe "Checkout", :js => true, :type => :feature, :capybara_feature => true d jam_track_right = jamtrack_acdc_backinblack.right_for_user(user) # make sure it appears the user actually bought the jamtrack! jam_track_right.should_not be_nil - jam_track_right.redeemed.should be_true + jam_track_right.redeemed.should be_false user.has_redeemable_jamtrack.should be_false end - it "for redeemable user that starts shopping anonymously" do + it "for existing user with a freebie (starts shopping anonymously)" do user.has_redeemable_jamtrack = true user.save! @@ -907,11 +912,138 @@ describe "Checkout", :js => true, :type => :feature, :capybara_feature => true d find('h1', text: 'jamtracks') #find('a', text: 'What is a JamTrack?') - find("a.jamtrack-add-cart[data-jamtrack-id=\"#{jamtrack_acdc_backinblack.id}\"]").trigger(:click) + find("a.jamtrack-add-cart[data-jamtrack-id=\"#{jamtrack_acdc_backinblack.id}\"]", text: 'GET IT FREE!').trigger(:click) + + find('h3', text: 'OR SIGN UP USING YOUR EMAIL') + shopping_carts = ShoppingCart.all + shopping_carts.count.should eq(1) + shopping_cart = shopping_carts[0] + shopping_cart.anonymous_user_id.should_not be_nil + shopping_cart.user_id.should be_nil + + find('.right-side a.signin').trigger(:click) + + # log in dialog should be showing + # try a bogus user/pass first + within('.signin-form') do + fill_in "session[email]", with: user.email + fill_in "session[password]", with: user.password + end + + find('.signin-submit').trigger(:click) + + # this should log the user in, cause a full-page reload, and the order should be placed or redeemComplete + find('.jam-tracks-in-browser') + + user.reload + + # verify that the shopping cart has user_id info updated + shopping_carts = ShoppingCart.all + shopping_carts.count.should eq(0) + shopping_cart = shopping_carts[0] + + + user.reload + jam_track_right = jamtrack_acdc_backinblack.right_for_user(user) + # make sure it appears the user actually bought the jamtrack! + jam_track_right.should_not be_nil + jam_track_right.redeemed.should be_true + user.has_redeemable_jamtrack.should be_false + + # verify sales data + user.sales.length.should eq(1) + sale = user.sales.first + sale.sale_line_items.length.should eq(1) + acdc_sale = sale.sale_line_items[0] + acdc_sale.recurly_plan_code.should eq(jamtrack_acdc_backinblack.plan_code) + acdc_sale.product_type.should eq('JamTrack') + acdc_sale.product_id.should eq(jamtrack_acdc_backinblack.id) + acdc_sale.quantity.should eq(1) + acdc_sale.free.should eq(1) + acdc_sale.unit_price.should eq(1.99) + acdc_sale.sale.should eq(sale) + end + + it "for existing user with a freebie (starts shopping anonymously on 'used' browser)" do + user.has_redeemable_jamtrack = true + user.save! + set_cookie('redeemed_jamtrack', 'true') + + # the point of this is to also prove that the free jamtrack does not carry over to the existing user, once they log in + visit "/client#/jamtrackBrowse" + find('h1', text: 'jamtracks') + #find('a', text: 'What is a JamTrack?') + + find("a.jamtrack-add-cart[data-jamtrack-id=\"#{jamtrack_acdc_backinblack.id}\"]", text:'ADD TO CART').trigger(:click) find('h1', text: 'shopping cart') find('.cart-item-caption', text: "JamTrack: #{jamtrack_acdc_backinblack.name}") - find('.cart-item-price', text: "$ #{0.00}") # 1st one is free! - find('.shopping-sub-total', text:"Subtotal:$ 0.00") + find('.cart-item-price', text: "$ 1.99") # 1st one is free! + find('.shopping-sub-total', text:"Subtotal:$ 1.99") + + # attempt to checkout + find('a.button-orange', text: 'PROCEED TO CHECKOUT').trigger(:click) + + shopping_carts = ShoppingCart.all + shopping_carts.count.should eq(1) + shopping_cart = shopping_carts[0] + shopping_cart.anonymous_user_id.should_not be_nil + shopping_cart.user_id.should be_nil + + # we should now be on checkoutSignin + find('h3', text: 'ALREADY A MEMBER OF THE JAMKAZAM COMMUNITY?') + verify_nav(1) + + fill_in "email", with: user.email + fill_in "password", with: user.password + find('.signin-submit').trigger(:click) + + # this should log the user in, cause a full-page reload, and the order should be placed or redeemComplete + find('.jam-tracks-in-browser') + + user.reload + + # verify that the shopping cart has user_id info updated + shopping_carts = ShoppingCart.all + shopping_carts.count.should eq(0) + shopping_cart = shopping_carts[0] + + + user.reload + jam_track_right = jamtrack_acdc_backinblack.right_for_user(user) + # make sure it appears the user actually bought the jamtrack! + jam_track_right.should_not be_nil + jam_track_right.redeemed.should be_true + user.has_redeemable_jamtrack.should be_false + + # verify sales data + user.sales.length.should eq(1) + sale = user.sales.first + sale.sale_line_items.length.should eq(1) + acdc_sale = sale.sale_line_items[0] + acdc_sale.recurly_plan_code.should eq(jamtrack_acdc_backinblack.plan_code) + acdc_sale.product_type.should eq('JamTrack') + acdc_sale.product_id.should eq(jamtrack_acdc_backinblack.id) + acdc_sale.quantity.should eq(1) + acdc_sale.free.should eq(1) + acdc_sale.unit_price.should eq(1.99) + acdc_sale.sale.should eq(sale) + end + + it "for user with no freebies (starts shopping anonymously on 'used' browser)" do + user.has_redeemable_jamtrack = false + user.save! + set_cookie('redeemed_jamtrack', 'true') + + # the point of this is to also prove that the free jamtrack does not carry over to the existing user, once they log in + visit "/client#/jamtrackBrowse" + find('h1', text: 'jamtracks') + #find('a', text: 'What is a JamTrack?') + + find("a.jamtrack-add-cart[data-jamtrack-id=\"#{jamtrack_acdc_backinblack.id}\"]", text:'ADD TO CART').trigger(:click) + find('h1', text: 'shopping cart') + find('.cart-item-caption', text: "JamTrack: #{jamtrack_acdc_backinblack.name}") + find('.cart-item-price', text: "$ 1.99") # 1st one is free! + find('.shopping-sub-total', text:"Subtotal:$ 1.99") # attempt to checkout find('a.button-orange', text: 'PROCEED TO CHECKOUT').trigger(:click) @@ -926,7 +1058,6 @@ describe "Checkout", :js => true, :type => :feature, :capybara_feature => true d find('h3', text: 'ALREADY A MEMBER OF THE JAMKAZAM COMMUNITY?') verify_nav(1) - # try a bogus user/pass first fill_in "email", with: user.email fill_in "password", with: user.password find('.signin-submit').trigger(:click) @@ -947,24 +1078,14 @@ describe "Checkout", :js => true, :type => :feature, :capybara_feature => true d # try to submit, and see order page find('#payment-info-next').trigger(:click) + # now see order page, and everything should appear free find('p.order-prompt') - find('.order-items-value.order-total', text:'$0.00') + 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:'$0.00') - find('.order-items-value.taxes', text:'$0.00') - find('.order-items-value.grand-total', text:'$0.00') - - user.reload - - # verify that the shopping cart has user_id info updated - shopping_carts = ShoppingCart.all - shopping_carts.count.should eq(1) - shopping_cart = shopping_carts[0] - - shopping_cart.anonymous_user_id.should be_nil - shopping_cart.user.should eq(user) - + 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) @@ -972,11 +1093,19 @@ describe "Checkout", :js => true, :type => :feature, :capybara_feature => true d # 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 + + # verify that the shopping cart has user_id info updated + shopping_carts = ShoppingCart.all + shopping_carts.count.should eq(0) + shopping_cart = shopping_carts[0] + + user.reload jam_track_right = jamtrack_acdc_backinblack.right_for_user(user) # make sure it appears the user actually bought the jamtrack! jam_track_right.should_not be_nil - jam_track_right.redeemed.should be_true + jam_track_right.redeemed.should be_false user.has_redeemable_jamtrack.should be_false # verify sales data @@ -988,7 +1117,7 @@ describe "Checkout", :js => true, :type => :feature, :capybara_feature => true d acdc_sale.product_type.should eq('JamTrack') acdc_sale.product_id.should eq(jamtrack_acdc_backinblack.id) acdc_sale.quantity.should eq(1) - acdc_sale.free.should eq(1) + acdc_sale.free.should eq(0) acdc_sale.unit_price.should eq(1.99) acdc_sale.sale.should eq(sale) end diff --git a/web/spec/features/redeem_spec.rb b/web/spec/features/redeem_spec.rb new file mode 100644 index 000000000..e69de29bb From 8e7ebcf3d66c5aa0c9964971e3145932c8f4c3e3 Mon Sep 17 00:00:00 2001 From: Seth Call Date: Fri, 15 May 2015 15:02:00 -0500 Subject: [PATCH 02/13] * VRFS-3236 - update landing pages for jamtracks --- ruby/lib/jam_ruby/models/jam_track_right.rb | 5 +- .../assets/images/web/free-jamtrack-cta.png | Bin 0 -> 8882 bytes .../javascripts/jam_track_preview.js.coffee | 29 +++++--- .../javascripts/web/individual_jamtrack.js | 22 ++++-- .../web/individual_jamtrack_band.js | 19 ++--- .../client/jamTrackPreview.css.scss | 6 ++ .../landings/individual_jamtrack.css.scss | 7 +- .../individual_jamtrack_band.css.scss | 7 +- .../landings/landing_page_new.css.scss | 57 +++++++++++++++ .../controllers/api_jam_tracks_controller.rb | 4 +- web/app/controllers/landings_controller.rb | 4 ++ web/app/views/dialogs/_videoDialog.html.erb | 2 +- .../landings/individual_jamtrack.html.slim | 36 +++------- .../individual_jamtrack_band.html.slim | 36 +++------- .../landings/product_jamblaster.html.slim | 2 +- .../landings/product_jamtracks.html.slim | 2 +- .../views/landings/product_platform.html.slim | 2 +- .../views/landings/watch_bands_1.html.slim | 2 +- .../views/landings/watch_bands_2.html.slim | 2 +- .../views/landings/watch_bands_3.html.slim | 2 +- .../landings/watch_bands_tight.html.slim | 2 +- web/app/views/landings/watch_kick.html.slim | 4 +- web/app/views/landings/watch_kick_2.html.slim | 2 +- web/app/views/landings/watch_kick_3.html.slim | 2 +- web/app/views/landings/watch_kick_4.html.slim | 4 +- .../views/landings/watch_overview_1.html.slim | 4 +- .../views/landings/watch_overview_2.html.slim | 2 +- .../views/landings/watch_overview_3.html.slim | 2 +- .../landings/watch_overview_tight.html.slim | 2 +- web/app/views/layouts/web.html.erb | 9 ++- web/app/views/users/_downloads.html.slim | 2 +- .../api_jam_tracks_controller_spec.rb | 66 +++++++++++++++--- .../api_shopping_carts_controller_spec.rb | 2 +- web/spec/controllers/api_signup_hint_spec.rb | 2 +- .../features/individual_jamtrack_band_spec.rb | 57 +++------------ web/spec/features/individual_jamtrack_spec.rb | 53 +++++--------- web/spec/features/jamtrack_shopping_spec.rb | 4 +- web/spec/features/products_spec.rb | 40 ----------- web/spec/features/signup_spec.rb | 4 +- 39 files changed, 262 insertions(+), 247 deletions(-) create mode 100644 web/app/assets/images/web/free-jamtrack-cta.png diff --git a/ruby/lib/jam_ruby/models/jam_track_right.rb b/ruby/lib/jam_ruby/models/jam_track_right.rb index 98ea69a51..5f919c13b 100644 --- a/ruby/lib/jam_ruby/models/jam_track_right.rb +++ b/ruby/lib/jam_ruby/models/jam_track_right.rb @@ -274,8 +274,11 @@ module JamRuby # we made it past all checks; let's slap on the redeemed_fingerprint self.redeemed_and_fingerprinted = true + MachineFingerprint.create(all_fingerprint, current_user, MachineFingerprint::TAKEN_ON_SUCCESSFUL_DOWNLOAD, MachineFingerprint::PRINT_TYPE_ALL, remote_ip, self) - MachineFingerprint.create(running_fingerprint, current_user, MachineFingerprint::TAKEN_ON_SUCCESSFUL_DOWNLOAD, MachineFingerprint::PRINT_TYPE_ACTIVE, remote_ip, self) + if all_fingerprint != running_fingerprint + MachineFingerprint.create(running_fingerprint, current_user, MachineFingerprint::TAKEN_ON_SUCCESSFUL_DOWNLOAD, MachineFingerprint::PRINT_TYPE_ACTIVE, remote_ip, self) + end save! end diff --git a/web/app/assets/images/web/free-jamtrack-cta.png b/web/app/assets/images/web/free-jamtrack-cta.png new file mode 100644 index 0000000000000000000000000000000000000000..c8f073167918613ea0a9250c4fae8d03da74d8a9 GIT binary patch literal 8882 zcmW-n1ymbd6NW>fK=BWEX(>|N9f}j&r9hy#yL+LyTX8~hcMnc+x8hLTy}13`|0G$t zXHWL--nldHJafa96{XQph*3Zw5IR^!LKOspqXUllkP(4x@IzxFutPMGla>Iz{`=&# z7yWB_=OClw3<6>F{`KOD6F?K0rMk9@xV^2dshtaO z3Id5cnSOOKHKBC3bg`h61}i9=Fqn1o#}QZ#$(d7re;uX$Ja{>HAYtNVysZN8Vt?S#vp_l}zD zq4wLH*%@a=MZ*q5)t*!RmBxl&%Xzr^`p&+V(!;{C$2AQTtQ0ltRPLvmuCv;iCLMAZ z1QRb9$%0RnQQFkpT+Y^w;Hu*hJ{K#PPU2@(*8{n6%Ul_;jls!8vGGu#I>LKi9c1Sv{#Q&p9)p1wdzWM2&05-mIk_W9iP6y<&2 zet86N88t^(plAa1FFKVxtY8S7K82v@^~=M{;a#w31mqC7i|{Dg1CGEwHX-iRj2dn( zmMNm|O@w>!e;TyN+6pvZgt8$iNQBp3fBDHyAoec1dY}b)8lT*-fj!t=c z_d|WAwDNBFkYP^WNeug#oSAZhha~b%p}Bdjg*tf<&L%4f8fRle-N7K+54-iCfxRsP z9ws9XS!{|E;jT*|q@Ll|i}Ai+d^T;hjwBhfvf}t5F?~4w>{Q0c@LNWc@7|ank=&aY zP#s0cIcSeQZH)I3y70f85ABhbl)o|j8z(AQZ%D&0I&k*GUrNVSK|AAiB76An@mCuL zrmeFhR8C7J#*S>!3&*xPU!F2d@;86tkMLO;`Pj zpnTeo4kLF{XmX0w-Cw2OSY@QsR~DNb#0brDyT8&)Ta`y<^g|>yt+3&ZOqaZ${bDpV z>x|Y#Z<3*ihPz=KD}1hE5-SjGgRbf%iQT>E{o0DXd3((xR2wP(mxq&7bVT7*gI|vV zL4Q+I`I62?v*5ZW)^((8ol)7i86s(;s90=4@J9Ok2;ce}-4thMFE%QD58FVg`APPU zu=}Z_v*4-wp^rQtkk5}y8TjI#d$_nLo#nJGVe z_>xeE`}vP}JG`Ko?U}qKD4^S{{nG5`BD^!_YV(QyWB1nqD^6_dI;ms(z}}cei!RHC z;scDxwAbc);t-ntGJ$wHFj|=FMOUWfv9Kcw8J2Ma$dD^7j=E*VeQ&JGvPRjbFroHv zDa^Ki(FR4avHGt^C|TK1*a-129tJL=qQ0ovuhVI5!f&=xlhY-l#v+t(FCLy!qY*bx zxNFrChe%R~{r%r_#LW^Cyu>ZJE^4rm zg;-mJ?m!3OU$0DjRJPSWc3kP4zBhMI#|$E4nJbKy6dVakw|G;B7odLwzc5A<@o8Lj zW>ze)cO0h)QZ+q88{zTnr>BXkg-$Nxw*>O*G~x;_nkc>+wqiG8BkD~J9m*N7WEceddMvDN_bs{D{;n&__L6eDT%JXw${q9Nw4gT@`-SD+nR znAacCEa+S756zd3j)0ySyt}9O_=)l0H1RYj6h~@4;_6!Pau@0AmE}ZuBI9ZeQb3J3 z(pCFC2i)C3#@WmY^R4cSmH^_2+nKrMxC5gU{MBWhPR%W43%uHpj4bHSGnqGBxIkeH zEnv7uw^zsM3df%W!s#Nm3kxpuB%K|Lc1|6*sQKo%~lI9lYwpufFz@nEP}yV@FqIyp5iL zm%Y2(?$si>xFOP}zIk4&ox7!i2%-ZGc~@|BmArC}k{?Uh*yJb35xb^OycadSNTKVY zbm6#J!o3-~Zi8Bfcf6O=ssf9Q0wFS%OU<>1#5YjEiWtjnukG`>ih(uE)=K{0^Fc#7 z=E`EEAQDUpN!(}s?K3N}?@H-E!yWfsFHdVWCgbfK-a#BYxV%f-V5ck68zm9s$#rQ_ zCN#7bfudEh0d-DfY((Mi3$r;h@3L;-shyAti)+IoTCcu(ZXIhjFsIC|h(Aa}Ob);o zhv7#HEv3~?0?B1z5ZbuysJ3b+#C$s1O&qfG6Jm;X#iE~)b0%$rEm&w2rz@ewdUd;d zrX0e?$N}&35+6x;jcxe67;V0t2>P+psYN=v!q_C27`ZaSRr`y1;?gn^x=LEF^qDVT z+WH?G;spD4)M=$n#f@Vhr!<7Y331fnvxF(c?u{KkXV`yUxGQD_^coeG)`Z`>9Us66 zJ3WNK(LdP@jb&}e^&GaCK3UiiiF|o}-kbPcw=>A5knMO71a?^pZ(1HwM>wK5UXfN% zb0%E#Z?mp>cm-_ZG28z-FlP6s>)U zLIlIOYW`rND(+%jG2I7#F=uZ9NGC-eL@8lp@m=CEWCbhW(M+*_>xzSuEgJ}xyKX%8 zwyTS#LMl}Erf(vL2yvqx`^c~J>R#Md=4@!xWL8y+TtoX)GKB_yjsB#DWkxAcOh@Zc zE)*~CZTZNR(a<947~=hj4$ShY_x6|IlpW9RWr-+d z+!fmmn*D}IBU#KO8*hnEymx)yd%2GwTG7jbIKU~u^)_WL*VcW9Um=Se3Y~TqwbeOj zIb?pEo@sgQj`1BOWh2dVD%EfGjs3zLPQVQ8QHX_tD3 zkUgR#o;eIx7)cgCOPHi_M#TM9ztpSaLkEHL z=6e3Awbqj}!$!-K@o1)SGFh3=embyjFlDUqeRfO_xhw6#>n5AG?=Ffev%EsB!SNDY z18%QfVxmc3u6J?y!uZL!tlVBKAuwGEZt@+!t21aa7`ecAxR7Mn@a1T0?oKj36o2&n zxZTz_zM1>$Q0R?^&jZQ+oAu4>0p^yCs@_%PfzL9;s9lVtKq)StvE$<^xE zTYr53<4m#tt|=PxpHM>4j83>Ez`0{v z1tqHruz7+I_x;Nw413#7@3mX}rl(&yb0<^3pcR;QCdQ!{nrVy;NLb4Hgb$GH>~fQaA65P|42`{!E}F*|Gd>ZC{wMU`Wg3t07K zghWEcXva@SJUKq8%eSu3NOkR;cNG7JJo&`0(Z6A0{fciBWgn)7tz;)OMu;<~?nlRm z#Ax^9s0p!1dNC`rNiLqJOO~#Ds?{`M6C)#Lf8)AWtuL5Wm6vef%9fARD7+Mjvj5YG z90;Bvr*~R(mHc=o`5&Bz#|Ej5S>5!Hu3QyQ`H^w;ov-nn<_XjWKc8~L77hPs@#y!) zeMjJ8I@hkr3%D2KOdu$2M86Qvo%RcBEx^d1W!^)OY^08?ZJ|BW{wKsZyRlZ{I3*A_n&FcI!1B}7?@(rx-3J;l1EcOFMVKNpBu=w+V|FkO~j)ei(?u zwUyVxrf-@kLn()MrQlZ^Qi2!^e^bK)l)pS8JabuaNF(>!N^2s=HM+-h?k91F$0wPH z>YFO4|2HLEuoHi(u#tzv3jBQXBzNz0TX%hzqAf?7jKe}uw-EDveIsr2x@+^U(2@j%|bRTOj}b;!hcK@Du%H>g15&4 z$=cc+8OBcRfE$ZrZ?X}gCC$%X+&wZZsA*R2x_S$hTJ&sPm0nn*U~XJR0?8DhKe?{0 z#Y7}nng7vhl0;-y)k_j`K=}IswURAoV>Cyf*`T5M9golfuEhCP&@aF3QHtE zjIi!s?;}th8!wz5;v&G+byIRAVz~DOa36_@$e)&HQX*?dAqon2O3`^w^^A~jnzIpu z!yQ$YSIRqxzL})pL{52tufJOnOM-j$ZVj+7vZ9lvj`HUdiMN1Ws?4lRS40>n zbE~J!^|XZa57OFpSxg2YtYPpTx$;MO`KD}5LZL*+&J>>VPI{tfpHNhq%TY@){SJRm zK#9UsI0^uaa8^?+Jec!vEw1p6&B}}cMP(mv^18cV7CPS~ik(MW3}A`*R8eT#=CwH@ zo}2VZ8MiTj3|>IKlQb=}c$L216(kbxeOZZwR3xcT2#}r?5a*iaTb=qM70c)(HVn=X z<|ryXgjo6h0|3W{tdQunC*nsbGIuE|ly-zx;V?CS$T}i5{U^u6igq=uuo@l9TaUcT zk`8Jh%P*CLt5h}vRO(&dSY&nDXq!s4I9H7OjvhZtfas7xQl!@3{0_$zjZ*ZV$`;oi zcMo+e#*;^$SC6;GTtxRLwaI|y7O$GQ;OV1L1GV{y43t^j9e@7MfRw+qe|eM!NPe=c zrT5Axevy}yZ?csA-oTN}ep+JE-_&y0CiGWb;d1>Roac1Ek?RRKF{g<-7VBxmzJZH9 z?-WBWB4CPLwWqA-HU?=7r19wpwmD!Rw#QsCRXkbl5JxCM(XIEa)o7|cHnq9dd#l>U zqWUklXH-+cM~JIklqm}O$kKgB9iPp-_UgV%-HXi;RvmEk@J@ejerm&RRG;Z-d{ zHiMf0T=G-_eXcKiH}?yWFa6HeJgPeDgY6te)h5FpeVR|~_tYPdpUj5F^th;_S50X> zpW0(TunM61!(J7m9eY56bzVXw5wQ+ecT+0@&JiJSb4~TNR~~%!_N$V{x+IkT!dELz zr|Qze!uUqcfJTb$e%n_$l(a}@v8%yl7F!6}6xoTNuAnA^+Tb6O-OJf%dBKU2) zTfrm%cXuBhnaXCwn@g?YRY{yOC+23wUguOx$Ll0$wEPom$VM)JSuyf0Z1MY44(3Rm zgGuF=Cg30K){uYLEmsV22>T*~nOp2@zts^vZ8sF83o4cc+mEM(fZ57v`~{D@?6}<{ zVKX+}HmnI*>1cx#^pBEE6%aj&5t6q8oIC%(#7#SV#vrYCFVU>4vDD?v(Qckr+uj{6 z2P4o8fMngB#cJW$HyH!Y&4pi`c$M2!P%UJHLaJ)PnRSy?$%R)YGBSFB1qSBE;Skiw z7RaRr0DvJkA>ay$ekA<4B->kNoC7LUJ^wvUjNs zk{s{hvxX&g1~Wl)_WbRBR&Fhc=-R?p{`ccN^SpmsX$VEk^H+F zc!g}ejtKO=kNLlvJua=ASQ$S8*{mWUe@}ib*#gm#G+^ETiKy&`0FKp4h8W1CpJ|mG zXI}j^D~@`hf?<%Ntzg#-?V8)1QIOD@V*h9BiyGtXmitR)UB`~>`eyCjo#;PV6#^e_ zo-IuAbV`Pz$oa!0iu8>+ZS5f3H0{|R%qQY2cp0%i#>cvy8QaF&$bDiG{?X}s#SHSh zA7^*fvUl`W??*g;+=13K?z7UfG5f)`&1zK>Ta1?wAj{=k>+C#Ak&i%DgBIp&sb}<& z_gJva0>djSCb7Zw>7iGN?~9IP=4yWh&VUg&G1f;mizsCx*x!7KQz!>|01v8Lb;Vzg z?IZ25f&ysgGgTj6ccN*cQ6znJtK4|@R(HzUXIkVHE??~RY=NLzZGt+dI_;J!We#o; ze{Ujz*sOgg#g~n(xpMVgSzhsYb%9;-s@H^ddPv8$@4?X*+HloQ?g0m?7wM;58DHxR z;`G&1X5S>2s4^Q16NRa-AOPaf1by4a+Czc(PktZ#mWT&X0A_=CVoOQ0M+I8ZktVhI z*6Z|fT$I58WdtIR;MJlR$O*BKl~tJAhzy{Ybd|*tApEG|xqO4Xg&z-X=hcNw2FUH{ zVvNX~Fd-|SoCz|=avKZvBj?ny)aWmDv{zEQpmRVa&o&Lu=X>7sr3<<%K%+G1Z%5pP zbGMKA0Fm3+5=`*h{)aDyTTUV{z*D!x*P)qO{Q~mQXtO3=4n;q3#Qs_r3%IS_ zHN{I-)`h?4ik?I-AIl_0wa8NftX_fN?7N0xsh<*w`*5{1=W6e!b}UZwnFS*yJGE&} zF%!d)s#6++xcKzR7Q(VK*HDUHC~e=I?rkRDZ^f>kl(s(jEv$J$P0!Pwnch^_GVQRy z9kLe2Y8~;duc1=gj8H3fSYrl>_E(|+YchUQXdu=ED}iip%=4Q?QYMr-t7`;>9SkJ} zGY22i3UZdW(lIp`)r=Dv(5gNmX~z`TbM;`W;98Ezc(}WVQF@ai8nyMM;jOc(uA^In z>9#NvMPC2O&x=3b*1~RMI2{(tsarGueZR9-Pqt>_N2b$G?I4IwZeQKKK^yiTifr>w zyPvCc45Gf-P7^hlhL<7Ge-Bu($eM2%v4PJ6Ba0o~q>ntkq_)dHeVki%DWfE7sI12b z>4X+(R){B2r?1)ps4QE$Qa7y6Vq3u3+~Kw!4B$5gdz;0@U|4CkrBA( zfYs-B&o+#F!+`E(^EXjMif#W=gt2bG8yb}_!LF7-S5dA?rcx=Qp3A-z6IGa}_mPn) zKN^_UCf$R2(>Pm1xD=sExc4)|4e3u;SI+8i4zT%=)=g|XVs|_uaJUIIt&==kgP`_> zr$=jL2g#QqOZpmSjhtt|YSOK3+=-h)3C4fc2<=Ba^NeVIVy>mupt^untp?5*?Ur_1 zf^3+C#`}Avdj+cm-9}u~-A?^(C;&NR$!rF6G2@ISv*P7t%KEGp#<(v&fn(%xuF4hk ze3m8}R>4L6VoGkcBu`UFC-n$7iYUIYjj|+*(Z7QsKc~0l_jd_)EaWH~?d?ARQT&~` z_w#MtAW>?>s?8>F1a{)~l&ZhFAWls$Vgy_^kmsTJLt9I|2Y6TUX-P6t zs&9aRUElXH-1$2C9~#@Ivee`F6x*3yW;CVY3G#8vX_kXJlIeeR9VH3Kgrm{>Z_q% z1MCzWW`6Oj#;5j-Qn+&=_?)*^fHr_PBYCMXM}VcMZ0x5D+@lp z$&2gpNqIh);UWbDcpeW#K~t8!v-yDd)boa-lt?>(Y+!i7u{^3oC++ES*BVgW&9KbAet*4!bE_}~O>HIJ|<@o8<|PbvDQ zJJft+v)oP9u<}gYlrm{~nS_1LlLL(-Izf%@JRW9%9;6wp)Q7>K&qyZ`1%vTHh^6B~ zMW&d>nYlyO*B+*bTDf|*OJ^U$oV@UWqkSHd*Y_q0d1R%G)O?%^pkTvArd(nTK`=}%>*332S z4ZSUOQnnr*c27zZsId{syS-X#{&*H}(CM$=JWL9RYV3HmkqWv>q2sxt>w7&Qe^yXK zMN-r}|MdtR)QY|1wIdbaH`3LOA>BJjwoaaTLk-hQ*;bKIHX(y6q=$YsK}gf$jkVu&6?lfou1|Rj$^a79TE@$ajvyCP%nea#5mJDPZfR|6!TztA zmie?aZf9`PQ|E}gk{cx)#IYQ3Au5_0Baug_3qLLP$umVzMX}ybN~;q23`{!0?=!YF z`*HX`KcNnnS;NMbefLX3@ebs!C!N?tX|L(2?ox2XgtGL)piMFCDG7CZ>U`ZNi33z{ zIP9Ud9@9YD(Ei0P_0n&cB_c^a0+~}7J63tX@_?^*@>fCV1O4}m;>JL&HB1J0B7#fXM3XO62s=uE zGb`zS9;jl{Ff~M#9u|9YZ#;wRGMT)}ShjyZw3FmpaNwdRzz=;iSDLv|`FQ}KLzVTV z5S6OE8h;oD0`o$rK`Kj6oL^^w;0_>{OszD{B#2#(E=x0fn9J}&`=V5;I$dsUgw*?i zXY3l>@%BIY1Z~wjV5g(co#a#1n@qIN=e={77w$Jl`&Yq83_<_+fj-{9(+*Cg*$acV z)Vd~3KA(07^JeYj&yP<}!D@Rh{x7=j#vDW%e4}fZGcq!V*LFZ0EC*aGeckJ}We1xx z3QbUUne>jTN2}PDFVFewTySV=93O4~AU|-mGQ&S3(I4Li7cwok$AWvOi88SUfIPNM z82Z5edL4M8?v7<-&*v1?;`!m<1OtMB>Cu#NIRo=oz_$AfFwOctV5-bdM~oPC=gij> z?mI~69qQ`d&lFkTO)T3{`%i*SGx_7^Q5$a^Rs^($5T;RM$hY*2ap;+8k?8|@jfA$edpk}kw<_7_) zGC0}N&feS^Ob@~dMb}umqJKtdY-&8OKBRZQ&xW^Z8`$e*k)=9~4s?aJL#~r1<752% z&sP;;JThgjeIIA(plhQ5+cGMQdd$WtDz>sf>-FD(yWcQMm=X0ddXqqXv9C)36ucVL zd4{in+>2GNM(ur=d?Wx1V`R2IL#a!yE|3Su#r6V-vPC>W zpf@Q0)&i`vTz1E_gXD>S#Pr$})>K3z?$o6KRVI@ZHS|k0_@@2Zyc@Nl)qyx+ldF*S{lA8{USx<_zkOp>s-&xCg0li$ z_~9a_ic2Q!xD)Xy*BW{Jj4}Dc}2& z;&X&6B5^5fR2JEo;haFKN;Oae=1gX7xCy30v$e0aBbSSMJOribNG_8nLJl{!LqH@Kt+YsfIKZXEyzAvTYb`kzXs*IW zs$pRtdSML0einY3Vu0Z0PBP@21x2-rRN0F!FQR1jI_GlypCy=0HdV<#$B6QcYkiQy zR0h^5bP96pM^c&qYafc9-dOUmgsXn|x3~fNEh2V3kx1RbM*-IRH=Qm*3n)ia-DW literal 0 HcmV?d00001 diff --git a/web/app/assets/javascripts/jam_track_preview.js.coffee b/web/app/assets/javascripts/jam_track_preview.js.coffee index 58388278b..a02a45896 100644 --- a/web/app/assets/javascripts/jam_track_preview.js.coffee +++ b/web/app/assets/javascripts/jam_track_preview.js.coffee @@ -9,7 +9,7 @@ context.JK.JamTrackPreview = class JamTrackPreview @EVENTS = context.JK.EVENTS @rest = context.JK.Rest() @logger = context.JK.logger - @options = options || {master_shows_duration: false, color:'gray'} + @options = options || {master_shows_duration: false, color:'gray', add_line_break: false} @app = app @jamTrack = jamTrack @jamTrackTrack = jamTrackTrack @@ -56,17 +56,26 @@ context.JK.JamTrackPreview = class JamTrackPreview if @jamTrackTrack.track_type == 'Track' part = "#{@jamTrackTrack.part}" if @jamTrackTrack.part? && @jamTrackTrack.part != instrumentDescription - + @part.text("(#{part})") if part != '' else - if @options.master_shows_duration - duration = 'entire song' - if @jamTrack.duration - duration = "#{context.JK.prettyPrintSeconds(@jamTrack.duration)}" - part = duration - else - part = @jamTrack.name + ' by ' + @jamTrack.original_artist + if @options.master_adds_line_break + part = '"' + @jamTrack.name + '"' + ' by ' + @jamTrack.original_artist + + @part.html("#{part}") if part != '' + @part.addClass('adds-line-break') + else + + if @options.master_shows_duration + duration = 'entire song' + if @jamTrack.duration + duration = "#{context.JK.prettyPrintSeconds(@jamTrack.duration)}" + part = duration + else + part = @jamTrack.name + ' by ' + @jamTrack.original_artist + + @part.text("(#{part})") if part != '' + - @part.text("(#{part})") if part != '' if @jamTrackTrack.preview_mp3_url? diff --git a/web/app/assets/javascripts/web/individual_jamtrack.js b/web/app/assets/javascripts/web/individual_jamtrack.js index 2d33e9c5d..172a94bc2 100644 --- a/web/app/assets/javascripts/web/individual_jamtrack.js +++ b/web/app/assets/javascripts/web/individual_jamtrack.js @@ -9,24 +9,32 @@ var logger = context.JK.logger; var $page = null; var $jamtrack_name = null; + var $jamtrack_band = null; var $previews = null; var $jamTracksButton = null; var $genericHeader = null; var $individualizedHeader = null; + var $ctaJamTracksButton = null; function fetchJamTrack() { - rest.getJamTrack({plan_code: gon.jam_track_plan_code}) + rest.getJamTrackWithArtistInfo({plan_code: gon.jam_track_plan_code}) .done(function (jam_track) { logger.debug("jam_track", jam_track) if(!gon.just_previews) { if (gon.generic) { $genericHeader.removeClass('hidden'); + $jamTracksButton.attr('href', '/client#/jamtrackBrowse') + $jamTracksButton.removeClass('hidden').text("Check out all 100+ JamTracks") + } else { $individualizedHeader.removeClass('hidden') - $jamtrack_name.text(jam_track.name); + $jamtrack_name.text('"' + jam_track.name + '"'); + $jamtrack_band.text(jam_track.original_artist) $jamTracksButton.attr('href', '/client?artist=' + jam_track.original_artist + '#/jamtrackBrowse') + $jamTracksButton.removeClass('hidden').text("Preview all " + jam_track.band_jam_track_count + " of our " + jam_track.original_artist + " JamTracks") + $ctaJamTracksButton.attr('href', '/client?artist=' + jam_track.original_artist + '#/jamtrackBrowse') } } @@ -36,24 +44,28 @@ $previews.append($element); - new context.JK.JamTrackPreview(app, $element, jam_track, track, {master_shows_duration: false, color:'black'}) + new context.JK.JamTrackPreview(app, $element, jam_track, track, {master_shows_duration: false, color:'black', master_adds_line_break: true}) }) $previews.append('
') + + }) .fail(function () { app.notify({title: 'Unable to fetch JamTrack', text: "Please refresh the page or try again later."}) }) - } function initialize() { $page = $('body') $jamtrack_name = $page.find('.jamtrack_name') + $jamtrack_band = $page.find('.jamtrack_band') $previews = $page.find('.previews') - $jamTracksButton = $page.find('.browse-jamtracks-wrapper .white-bordered-button') + $jamTracksButton = $page.find('.browse-jamtracks') + $ctaJamTracksButton = $page.find('.cta-free-jamtrack'); $genericHeader = $page.find('h1.generic') $individualizedHeader = $page.find('h1.individualized') + fetchJamTrack(); } diff --git a/web/app/assets/javascripts/web/individual_jamtrack_band.js b/web/app/assets/javascripts/web/individual_jamtrack_band.js index df08517c9..afc4528a5 100644 --- a/web/app/assets/javascripts/web/individual_jamtrack_band.js +++ b/web/app/assets/javascripts/web/individual_jamtrack_band.js @@ -13,27 +13,28 @@ var $jamTrackNoun = null; var $previews = null; var $jamTracksButton = null; + var $jamtrack_band = null; var $checkItOut = null; + var $ctaJamTracksButton = null; function fetchJamTrack() { rest.getJamTrackWithArtistInfo({plan_code: gon.jam_track_plan_code}) .done(function (jam_track) { logger.debug("jam_track", jam_track) - $jamTrackBandInfo.text(jam_track.band_jam_track_count + ' ' + jam_track.original_artist); + $jamtrack_band.text(jam_track.original_artist) $jamTracksButton.attr('href', '/client?artist=' + jam_track.original_artist + '#/jamtrackBrowse') + $jamTracksButton.removeClass('hidden').text("Preview all " + jam_track.band_jam_track_count + " of our " + jam_track.original_artist + " JamTracks") + $ctaJamTracksButton.attr('href', '/client?artist=' + jam_track.original_artist + '#/jamtrackBrowse') + - if(jam_track.band_jam_track_count == 1) { - $jamTrackNoun.text('JamTrack') - $checkItOut.text(', Check It Out!') - } context._.each(jam_track.tracks, function (track) { var $element = $('
') $previews.append($element); - new context.JK.JamTrackPreview(app, $element, jam_track, track, {master_shows_duration: false, color:'black'}) + new context.JK.JamTrackPreview(app, $element, jam_track, track, {master_shows_duration: false, color:'black', master_adds_line_break:true}) }) $previews.append('
') @@ -48,9 +49,9 @@ $page = $('body') $jamTrackBandInfo = $page.find('.jamtrack_band_info') $previews = $page.find('.previews') - $jamTracksButton = $page.find('.browse-jamtracks-wrapper .white-bordered-button') - $jamTrackNoun = $page.find('.jamtrack_noun') - $checkItOut = $page.find('.check-it-out') + $jamtrack_band = $page.find('.jamtrack_band') + $jamTracksButton = $page.find('.browse-jamtracks') + $ctaJamTracksButton = $page.find('.cta-free-jamtrack'); fetchJamTrack(); } diff --git a/web/app/assets/stylesheets/client/jamTrackPreview.css.scss b/web/app/assets/stylesheets/client/jamTrackPreview.css.scss index 71145f1a4..37b871e77 100644 --- a/web/app/assets/stylesheets/client/jamTrackPreview.css.scss +++ b/web/app/assets/stylesheets/client/jamTrackPreview.css.scss @@ -68,4 +68,10 @@ display:none; } } + + .adds-line-break { + display:block; + margin-left:66px; + vertical-align: top; + } } \ No newline at end of file diff --git a/web/app/assets/stylesheets/landings/individual_jamtrack.css.scss b/web/app/assets/stylesheets/landings/individual_jamtrack.css.scss index 6111876ee..773f12be1 100644 --- a/web/app/assets/stylesheets/landings/individual_jamtrack.css.scss +++ b/web/app/assets/stylesheets/landings/individual_jamtrack.css.scss @@ -16,17 +16,20 @@ body.web.landing_jamtrack.individual_jamtrack { width:90%; } + .prompt { + margin-top:10px; + } + .jam-track-preview-holder { margin-bottom: 7px; - float: left; &[data-track-type="Master"] { width: 100%; } &[data-track-type="Track"] { - width: 50%; + width: 100%; } } } \ No newline at end of file diff --git a/web/app/assets/stylesheets/landings/individual_jamtrack_band.css.scss b/web/app/assets/stylesheets/landings/individual_jamtrack_band.css.scss index db25181b1..56c4fc1ae 100644 --- a/web/app/assets/stylesheets/landings/individual_jamtrack_band.css.scss +++ b/web/app/assets/stylesheets/landings/individual_jamtrack_band.css.scss @@ -16,17 +16,20 @@ body.web.landing_jamtrack.individual_jamtrack_band { width:90%; } + .prompt { + margin-top:10px; + } + .jam-track-preview-holder { margin-bottom: 7px; - float: left; &[data-track-type="Master"] { width: 100%; } &[data-track-type="Track"] { - width: 50%; + width: 100%; } } } \ No newline at end of file diff --git a/web/app/assets/stylesheets/landings/landing_page_new.css.scss b/web/app/assets/stylesheets/landings/landing_page_new.css.scss index 897152536..85381683d 100644 --- a/web/app/assets/stylesheets/landings/landing_page_new.css.scss +++ b/web/app/assets/stylesheets/landings/landing_page_new.css.scss @@ -2,6 +2,28 @@ body.web.landing_page { + div.cta-free-jamtrack { + top: 32px; + position: absolute; + left: 383px; + + a { + width: 296px; + height: 57px; + } + + .value-indicator { + position:absolute; + left: 311px; + top: 19px; + width:80px; + } + + img { + height:100%; + width:100%; + } + } .two_by_two { h1 { @@ -29,6 +51,41 @@ body.web.landing_page { } } + .one_by_two { + h1 { + margin:0 0 5px; + padding:7px 0; + display:inline-block; + + &.hidden { + display:none; + } + } + .row { + @include border_box_sizing; + + &:nth-of-type(1) { + padding:20px 0 0 0; + } + + .column { + @include border_box_sizing; + + &:nth-of-type(1) { + width:35%; + } + + &:nth-of-type(2) { + width:65%; + } + } + } + .video-container { + width:100%; + padding-bottom:56.25%; + } + } + &.landing_jamtrack, &.landing_product { .landing-tag { diff --git a/web/app/controllers/api_jam_tracks_controller.rb b/web/app/controllers/api_jam_tracks_controller.rb index a6a3bc44c..d85f93bd9 100644 --- a/web/app/controllers/api_jam_tracks_controller.rb +++ b/web/app/controllers/api_jam_tracks_controller.rb @@ -139,7 +139,7 @@ class ApiJamTracksController < ApiController # jamtracks come in the form id-44 or id-48, so we need to do a little extra parsing - puts "#{jamtracks.inspect}" + jamtrack_ids = Set.new jamtracks_fq_ids = Set.new jamtracks.each do |jamtrack| @@ -151,8 +151,6 @@ class ApiJamTracksController < ApiController end end - - puts "#{jamtrack_ids.inspect} #{jamtracks_fq_ids.inspect}" @jam_tracks = JamTrackRight.list_keys(current_user, jamtrack_ids) @jamtracks_fq_ids = jamtracks_fq_ids end diff --git a/web/app/controllers/landings_controller.rb b/web/app/controllers/landings_controller.rb index e7e7150ca..5700ac543 100644 --- a/web/app/controllers/landings_controller.rb +++ b/web/app/controllers/landings_controller.rb @@ -67,6 +67,8 @@ class LandingsController < ApplicationController end def individual_jamtrack + @no_landing_tag = true + @show_cta_free_jamtrack = true @jam_track = JamTrack.find_by_plan_code("jamtrack-" + params[:plan_code]) gon.jam_track_plan_code = params[:plan_code] ? "jamtrack-" + params[:plan_code] : nil gon.generic = params[:generic] @@ -74,6 +76,8 @@ class LandingsController < ApplicationController end def individual_jamtrack_band + @no_landing_tag = true + @show_cta_free_jamtrack = true @jam_track = JamTrack.find_by_plan_code("jamtrack-" + params[:plan_code]) gon.jam_track_plan_code = params[:plan_code] ? "jamtrack-" + params[:plan_code] : nil diff --git a/web/app/views/dialogs/_videoDialog.html.erb b/web/app/views/dialogs/_videoDialog.html.erb index bc2a72099..ec590743e 100644 --- a/web/app/views/dialogs/_videoDialog.html.erb +++ b/web/app/views/dialogs/_videoDialog.html.erb @@ -10,7 +10,7 @@
- +
diff --git a/web/app/views/landings/individual_jamtrack.html.slim b/web/app/views/landings/individual_jamtrack.html.slim index 53d4bc729..c3b6e9daa 100644 --- a/web/app/views/landings/individual_jamtrack.html.slim +++ b/web/app/views/landings/individual_jamtrack.html.slim @@ -1,42 +1,26 @@ - provide(:page_name, 'landing_page full landing_jamtrack individual_jamtrack') - provide(:description, @jam_track.nil? ? nil : "Preview multi-track JamTrack recording: #{@jam_track.name} by #{@jam_track.original_artist}. Way better than a backing track.") -.two_by_two +.one_by_two .row .column h1.hidden.individualized - | Check Out Our  + | Preview  strong.jamtrack_name - |  JamTrack + br + | JamTrack by  + span.jamtrack_band + h1.hidden.generic - | We Have 100+ Amazing JamTracks, Check One Out! - p Click the play buttons below to hear the master mix and each fully isolated track. All are included in each single JamTrack. + | Preview One of Our JamTracks + p.prompt Click play buttons to preview tracks. Every JamTrack includes fully isolated tracks for each part of the song! .previews + a.browse-jamtracks.hidden .column h1 See What You Can Do With JamTracks .video-wrapper .video-container - iframe src="//www.youtube.com/embed/askHvcCoNfw" frameborder="0" allowfullscreen - br clear="all" - .row - .column - h1 - | Get Your First JamTrack Free Now! - p Click the GET A JAMTRACK FREE button below. Browse to find the one you want. Click Add to cart, and we'll apply a credit during checkout to make this first one free! We're confident you'll be back for more. - .browse-jamtracks-wrapper - a.white-bordered-button href="/client#/jamtrackBrowse" GET A JAMTRACK FREE! - .column - h1 Why Are JamTracks Different & Better? - p - | JamTracks are the best way to play with your favorite music.  - | Unlike traditional backing tracks, JamTracks are complete multitrack recordings,  - | with fully isolated tracks for each part. Used with the free JamKazam app/service, you can: - ul.jamtrack-reasons - li Solo just the individual track you want to play to hear and learn it - li Mute just the track you want to play, and play along with the rest - li Make audio recordings and share them via Facebook or URL - li Make video recordings and share them via YouTube or URL - li And even go online to play JamTracks with others in real time! + iframe src="//www.youtube.com/embed/askHvcCoNfw" frameborder="0" allowfullscreen="allowfullscreen" br clear="all" br clear="all" diff --git a/web/app/views/landings/individual_jamtrack_band.html.slim b/web/app/views/landings/individual_jamtrack_band.html.slim index a16b43745..88237cd56 100644 --- a/web/app/views/landings/individual_jamtrack_band.html.slim +++ b/web/app/views/landings/individual_jamtrack_band.html.slim @@ -1,42 +1,22 @@ - provide(:page_name, 'landing_page full landing_jamtrack individual_jamtrack_band') - provide(:description, @jam_track.nil? ? nil : "Preview multi-track JamTrack recording: #{@jam_track.name} by #{@jam_track.original_artist}. Way better than a backing track.") -.two_by_two +.one_by_two .row .column h1 - | We Have  - span.jamtrack_band_info - |   - span.jamtrack_noun JamTracks - span.check-it-out , Check One Out! - p Click the play buttons below to hear the master mix and each fully isolated track. All are included in each single JamTrack. + | Preview a  + | JamTrack by  + span.jamtrack_band + + p.prompt Click play buttons to preview tracks. Every JamTrack includes fully isolated tracks for each part of the song! .previews + a.browse-jamtracks.hidden .column h1 See What You Can Do With JamTracks .video-wrapper .video-container - iframe src="//www.youtube.com/embed/askHvcCoNfw" frameborder="0" allowfullscreen - br clear="all" - .row - .column - h1 - | Get Your First JamTrack Free Now! - p Click the GET A JAMTRACK FREE button below. Browse to find the one you want. Click Add to cart, and we'll apply a credit during checkout to make this first one free! We're confident you'll be back for more. - .browse-jamtracks-wrapper - a.white-bordered-button href="/client#/jamtrackBrowse" GET A JAMTRACK FREE! - .column - h1 Why Are JamTracks Different & Better? - p - | JamTracks are the best way to play with your favorite music.  - | Unlike traditional backing tracks, JamTracks are complete multitrack recordings,  - | with fully isolated tracks for each part. Used with the free JamKazam app/service, you can: - ul.jamtrack-reasons - li Solo just the individual track you want to play to hear and learn it - li Mute just the track you want to play, and play along with the rest - li Make audio recordings and share them via Facebook or URL - li Make video recordings and share them via YouTube or URL - li And even go online to play JamTracks with others in real time! + iframe src="//www.youtube.com/embed/askHvcCoNfw" frameborder="0" allowfullscreen="allowfullscreen" br clear="all" br clear="all" diff --git a/web/app/views/landings/product_jamblaster.html.slim b/web/app/views/landings/product_jamblaster.html.slim index ad5c22023..1b9e65d06 100644 --- a/web/app/views/landings/product_jamblaster.html.slim +++ b/web/app/views/landings/product_jamblaster.html.slim @@ -18,7 +18,7 @@ h1 See What You Can Do With The JamBlaster .video-wrapper .video-container - iframe src="//www.youtube.com/embed/YHZQHfKDdMc" frameborder="0" allowfullscreen + iframe src="//www.youtube.com/embed/YHZQHfKDdMc" frameborder="0" allowfullscreen="allowfullscreen" br clear="all" .row .column diff --git a/web/app/views/landings/product_jamtracks.html.slim b/web/app/views/landings/product_jamtracks.html.slim index 86aff514e..acfaeffd1 100644 --- a/web/app/views/landings/product_jamtracks.html.slim +++ b/web/app/views/landings/product_jamtracks.html.slim @@ -13,7 +13,7 @@ h1 See What You Can With JamTracks .video-wrapper .video-container - iframe src="//www.youtube.com/embed/askHvcCoNfw" frameborder="0" allowfullscreen + iframe src="//www.youtube.com/embed/askHvcCoNfw" frameborder="0" allowfullscreen="allowfullscreen" br clear="all" .row .column diff --git a/web/app/views/landings/product_platform.html.slim b/web/app/views/landings/product_platform.html.slim index ecb6d8c9c..13d2647ce 100644 --- a/web/app/views/landings/product_platform.html.slim +++ b/web/app/views/landings/product_platform.html.slim @@ -21,7 +21,7 @@ h1 See What You Can Do With JamKazam .video-wrapper .video-container - iframe src="//www.youtube.com/embed/ylYcvTY9CVo" frameborder="0" allowfullscreen + iframe src="//www.youtube.com/embed/ylYcvTY9CVo" frameborder="0" allowfullscreen="allowfullscreen" br clear="all" .row .column diff --git a/web/app/views/landings/watch_bands_1.html.slim b/web/app/views/landings/watch_bands_1.html.slim index a271b1735..6b178d59e 100644 --- a/web/app/views/landings/watch_bands_1.html.slim +++ b/web/app/views/landings/watch_bands_1.html.slim @@ -5,7 +5,7 @@ h1 Watch 6 Bands Play Together from Different Locations .video-wrapper .video-container - iframe src="//www.youtube.com/embed/I2reeNKtRjg" frameborder="0" allowfullscreen + iframe src="//www.youtube.com/embed/I2reeNKtRjg" frameborder="0" allowfullscreen="allowfullscreen" .cta-container h2 It's FREE! Ready to Go? = link_to image_tag("web/cta_button.png", :alt => "Sign up now for your free account!"), signup_path, class: "signup", id: "signup" diff --git a/web/app/views/landings/watch_bands_2.html.slim b/web/app/views/landings/watch_bands_2.html.slim index 504b83120..76fa70ff2 100644 --- a/web/app/views/landings/watch_bands_2.html.slim +++ b/web/app/views/landings/watch_bands_2.html.slim @@ -5,7 +5,7 @@ h1 See How JamKazam Works .video-wrapper .video-container - iframe src="//www.youtube.com/embed/ylYcvTY9CVo" frameborder="0" allowfullscreen + iframe src="//www.youtube.com/embed/ylYcvTY9CVo" frameborder="0" allowfullscreen="allowfullscreen" .cta-container h2 It's FREE! Ready to Go? = link_to image_tag("web/cta_button.png", :alt => "Sign up now for your free account!"), signup_path, class: "signup", id: "signup" diff --git a/web/app/views/landings/watch_bands_3.html.slim b/web/app/views/landings/watch_bands_3.html.slim index 814578d58..7982c99ba 100644 --- a/web/app/views/landings/watch_bands_3.html.slim +++ b/web/app/views/landings/watch_bands_3.html.slim @@ -5,7 +5,7 @@ h1 See How to Get Started .video-wrapper .video-container - iframe src="//www.youtube.com/embed/DBo--aj_P1w" frameborder="0" allowfullscreen + iframe src="//www.youtube.com/embed/DBo--aj_P1w" frameborder="0" allowfullscreen="allowfullscreen" .cta-container h2 It's FREE! Ready to Go? = link_to image_tag("web/cta_button.png", :alt => "Sign up now for your free account!"), signup_path, class: "signup", id: "signup" diff --git a/web/app/views/landings/watch_bands_tight.html.slim b/web/app/views/landings/watch_bands_tight.html.slim index 70ce2f991..84ec2fc51 100644 --- a/web/app/views/landings/watch_bands_tight.html.slim +++ b/web/app/views/landings/watch_bands_tight.html.slim @@ -4,7 +4,7 @@ h1 Watch 6 Bands Play Together from Different Locations .video-wrapper .video-container - iframe src="//www.youtube.com/embed/I2reeNKtRjg" frameborder="0" allowfullscreen + iframe src="//www.youtube.com/embed/I2reeNKtRjg" frameborder="0" allowfullscreen="allowfullscreen" .row .column .cta-container diff --git a/web/app/views/landings/watch_kick.html.slim b/web/app/views/landings/watch_kick.html.slim index 3e39eb859..03dd463f1 100644 --- a/web/app/views/landings/watch_kick.html.slim +++ b/web/app/views/landings/watch_kick.html.slim @@ -7,7 +7,7 @@ b  JamBlaster .video-wrapper .video-container - iframe src="//www.youtube.com/embed/gAJAIHMyois?rel=0&autoplay=1" frameborder="0" allowfullscreen + iframe src="//www.youtube.com/embed/gAJAIHMyois?rel=0&autoplay=1" frameborder="0" allowfullscreen="allowfullscreen" .cta-container h1 span.badge-number 3 @@ -20,7 +20,7 @@ | Learn About the Free JamKazam Service .video-wrapper .video-container - iframe src="//www.youtube.com/embed/ylYcvTY9CVo" frameborder="0" allowfullscreen + iframe src="//www.youtube.com/embed/ylYcvTY9CVo" frameborder="0" allowfullscreen="allowfullscreen" .cta-container h1 span.badge-number 4 diff --git a/web/app/views/landings/watch_kick_2.html.slim b/web/app/views/landings/watch_kick_2.html.slim index 5d038e2f1..05c661e73 100644 --- a/web/app/views/landings/watch_kick_2.html.slim +++ b/web/app/views/landings/watch_kick_2.html.slim @@ -9,7 +9,7 @@ p Band performance starts at 1:00 mark .video-wrapper .video-container - iframe src="//www.youtube.com/embed/gAJAIHMyois" frameborder="0" allowfullscreen + iframe src="//www.youtube.com/embed/gAJAIHMyois" frameborder="0" allowfullscreen="allowfullscreen" .cta-container p | If you don't own an audio interface, we strongly recommend that you grab a JamBlaster on KickStarter now. It is far faster than traditional interfaces and easily  diff --git a/web/app/views/landings/watch_kick_3.html.slim b/web/app/views/landings/watch_kick_3.html.slim index 2fc6a788a..602da4342 100644 --- a/web/app/views/landings/watch_kick_3.html.slim +++ b/web/app/views/landings/watch_kick_3.html.slim @@ -12,7 +12,7 @@ b JamBlaster .video-wrapper .video-container - iframe src="//www.youtube.com/embed/2Zk7-04IAx4?rel=0&autoplay=1" frameborder="0" allowfullscreen + iframe src="//www.youtube.com/embed/2Zk7-04IAx4?rel=0&autoplay=1" frameborder="0" allowfullscreen="allowfullscreen" .cta-container p | If you want to be able to play like this, grab a JamBlaster on KickStarter while it's available - only about 20 more days! diff --git a/web/app/views/landings/watch_kick_4.html.slim b/web/app/views/landings/watch_kick_4.html.slim index d11973adc..8a4682104 100644 --- a/web/app/views/landings/watch_kick_4.html.slim +++ b/web/app/views/landings/watch_kick_4.html.slim @@ -6,7 +6,7 @@ | Learn About the Free JamKazam Service .video-wrapper .video-container - iframe src="//www.youtube.com/embed/ylYcvTY9CVo" frameborder="0" allowfullscreen + iframe src="//www.youtube.com/embed/ylYcvTY9CVo" frameborder="0" allowfullscreen="allowfullscreen" .cta-container p | If you already own an audio interface, you are ready to go! @@ -22,7 +22,7 @@ | from Atlanta, Austin, Chicago & Brooklyn .video-wrapper .video-container - iframe src="//www.youtube.com/embed/2Zk7-04IAx4" frameborder="0" allowfullscreen + iframe src="//www.youtube.com/embed/2Zk7-04IAx4" frameborder="0" allowfullscreen="allowfullscreen" .cta-container p | If you don't already own an audio interface, grab a JamBlaster on KickStarter today! Absolutely the best way to play online. diff --git a/web/app/views/landings/watch_overview_1.html.slim b/web/app/views/landings/watch_overview_1.html.slim index aef2a3119..6eb6f52c9 100644 --- a/web/app/views/landings/watch_overview_1.html.slim +++ b/web/app/views/landings/watch_overview_1.html.slim @@ -5,7 +5,7 @@ h1 Watch Video to See How JamKazam Works .video-wrapper .video-container - iframe src="//www.youtube.com/embed/ylYcvTY9CVo" frameborder="0" allowfullscreen + iframe src="//www.youtube.com/embed/ylYcvTY9CVo" frameborder="0" allowfullscreen="allowfullscreen" .cta-container h2 It's FREE! Ready to Go? = link_to image_tag("web/cta_button.png", :alt => "Sign up now for your free account!"), signup_path, class: "signup", id: "signup", rel: "external" @@ -15,7 +15,7 @@ b  JamBlaster .video-wrapper .video-container - iframe src="//www.youtube.com/embed/gAJAIHMyois" frameborder="0" allowfullscreen + iframe src="//www.youtube.com/embed/gAJAIHMyois" frameborder="0" allowfullscreen="allowfullscreen" .cta-container h2 More Resources: a href="https://www.youtube.com/watch?v=_7qj5RXyHCo" rel="external" diff --git a/web/app/views/landings/watch_overview_2.html.slim b/web/app/views/landings/watch_overview_2.html.slim index 07b5f073d..a6cd76427 100644 --- a/web/app/views/landings/watch_overview_2.html.slim +++ b/web/app/views/landings/watch_overview_2.html.slim @@ -5,7 +5,7 @@ h1 Watch 6 Bands Play Together from Different Locations .video-wrapper .video-container - iframe src="//www.youtube.com/embed/I2reeNKtRjg" frameborder="0" allowfullscreen + iframe src="//www.youtube.com/embed/I2reeNKtRjg" frameborder="0" allowfullscreen="allowfullscreen" .cta-container h2 It's FREE! Ready to Go? = link_to image_tag("web/cta_button.png", :alt => "Sign up now for your free account!"), signup_path, class: "signup", id: "signup" diff --git a/web/app/views/landings/watch_overview_3.html.slim b/web/app/views/landings/watch_overview_3.html.slim index 3a18002c3..eaf7d6880 100644 --- a/web/app/views/landings/watch_overview_3.html.slim +++ b/web/app/views/landings/watch_overview_3.html.slim @@ -5,7 +5,7 @@ h1 See How to Get Started Using JamKazam .video-wrapper .video-container - iframe src="//www.youtube.com/embed/DBo--aj_P1w" frameborder="0" allowfullscreen + iframe src="//www.youtube.com/embed/DBo--aj_P1w" frameborder="0" allowfullscreen="allowfullscreen" .cta-container h2 It's FREE! Ready to Go? = link_to image_tag("web/cta_button.png", :alt => "Sign up now for your free account!"), signup_path, class: "signup", id: "signup" diff --git a/web/app/views/landings/watch_overview_tight.html.slim b/web/app/views/landings/watch_overview_tight.html.slim index c64f0dc78..ca9c5f930 100644 --- a/web/app/views/landings/watch_overview_tight.html.slim +++ b/web/app/views/landings/watch_overview_tight.html.slim @@ -4,7 +4,7 @@ h1 Watch Overview Video to See How JamKazam Works .video-wrapper .video-container - iframe src="//www.youtube.com/embed/ylYcvTY9CVo" frameborder="0" allowfullscreen + iframe src="//www.youtube.com/embed/ylYcvTY9CVo" frameborder="0" allowfullscreen="allowfullscreen" .row .column .cta-container diff --git a/web/app/views/layouts/web.html.erb b/web/app/views/layouts/web.html.erb index 417f70dc9..929e8d7ed 100644 --- a/web/app/views/layouts/web.html.erb +++ b/web/app/views/layouts/web.html.erb @@ -54,13 +54,20 @@ <% end %>
- <% unless @welcome_page %> + <% unless @welcome_page || @no_landing_tag %>

Live music platform &
social network for musicians

<% end %> + <% if @show_cta_free_jamtrack %> +
+ <%= link_to image_tag("web/free-jamtrack-cta.png", :alt => "ClICK HERE TO PICK YOUR FIRST JAMTRACK FREE!"), "/client#/jamtrackBrowse", class: "cta-free-jamtrack" %> + $1.99 value +
+ + <% end %>
diff --git a/web/app/views/users/_downloads.html.slim b/web/app/views/users/_downloads.html.slim index f43413be0..8ccd21b4c 100644 --- a/web/app/views/users/_downloads.html.slim +++ b/web/app/views/users/_downloads.html.slim @@ -47,7 +47,7 @@ |  for your first JamTrack - free! Add it to your shopping cart, and we'll |  make it free during the checkout process. Free offer good for 1 week only! .video-container - iframe src="//www.youtube.com/embed/askHvcCoNfw" frameborder="0" allowfullscreen + iframe src="//www.youtube.com/embed/askHvcCoNfw" frameborder="0" allowfullscreen="allowfullscreen" a.go-jamtrack-shopping href="/client#/jamtrackBrowse" rel="external" | Shop for free diff --git a/web/spec/controllers/api_jam_tracks_controller_spec.rb b/web/spec/controllers/api_jam_tracks_controller_spec.rb index d96e78d23..fc4685eb9 100644 --- a/web/spec/controllers/api_jam_tracks_controller_spec.rb +++ b/web/spec/controllers/api_jam_tracks_controller_spec.rb @@ -15,6 +15,7 @@ describe ApiJamTracksController do end before(:each) do + MachineFingerprint.destroy_all JamTrackRight.destroy_all JamTrack.destroy_all @user = FactoryGirl.create(:user) @@ -65,7 +66,7 @@ describe ApiJamTracksController do it "finds a download" do #get "/download/#{right.id}/" right = JamTrackRight.create(:user=>@user, :jam_track=>@jam_track) - get :download, { :format=>'json', :id=>@jam_track.id } + get :download, { :format=>'json', :id=>@jam_track.id, all_fp: 'all', running_fp: 'running' } response.should be_success response.status.should == 202 @@ -142,12 +143,13 @@ describe ApiJamTracksController do ResqueSpec.reset! end - it "download depends on rights" do - get :download, :id=>@jam_track.id, sample_rate: 48 + it "download depends on rights" do + fingerprint={all:'all', running:'running'} + get :download, :id=>@jam_track.id, sample_rate: 48, all_fp: 'all', running_fp: 'running' response.status.should == 403 right = JamTrackRight.create(:user=>@user, :jam_track=>@jam_track) - get :download, :id=>@jam_track.id, sample_rate: 48 + get :download, :id=>@jam_track.id, sample_rate: 48, all_fp: 'all', running_fp: 'running' response.status.should == 202 right.download_count.should eq(0) right.private_key_44.should be_nil @@ -166,20 +168,19 @@ describe ApiJamTracksController do right.private_key_48.should_not be_nil right.download_count.should eq(0) - get :download, :id=>@jam_track.id, sample_rate: 48 + get :download, :id=>@jam_track.id, sample_rate: 48, all_fp: 'all', running_fp: 'running' response.status.should == 302 - puts response.location response.location.should =~ /.*#{Regexp.escape(right.filename(:url_48))}.*/ right.reload right.download_count.should eq(1) end it "supports multiple bitrates" do - get :download, :id=>@jam_track.id, :sample_rate=>44 + get :download, :id=>@jam_track.id, :sample_rate=>44, all_fp: 'all', running_fp: 'running' response.status.should == 403 right = JamTrackRight.create(:user=>@user, :jam_track=>@jam_track) - get :download, :id=>@jam_track.id, :sample_rate=>44 + get :download, :id=>@jam_track.id, :sample_rate=>44, all_fp: 'all', running_fp: 'running' response.status.should == 202 right.download_count.should eq(0) right.private_key_44.should be_nil @@ -198,7 +199,7 @@ describe ApiJamTracksController do right.private_key_48.should be_nil right.download_count.should eq(0) - get :download, :id=>@jam_track.id, :sample_rate=>44 + get :download, :id=>@jam_track.id, :sample_rate=>44, all_fp: 'all', running_fp: 'running' response.status.should == 302 response.location.should =~ /.*#{Regexp.escape(right.filename(:url_44))}.*/ right.reload @@ -276,7 +277,7 @@ describe ApiJamTracksController do it "success" do right = FactoryGirl.create(:jam_track_right, user: @user, signed_44: false, signed_48:false) right.signing_queued_at.should be_nil - post :enqueue, {:format=>'json', :id=>right.jam_track.id} + post :enqueue, {:format=>'json', :id=>right.jam_track.id, fingerprint: {all: 'all', running: 'running'} } response.should be_success right.reload @@ -295,4 +296,49 @@ describe ApiJamTracksController do json['error_count'].should eq(0) end end + + + describe "guard fraud" do + it "stops second user from downloading using same machine" do + + right = JamTrackRight.create(:user=>@user, :jam_track=>@jam_track) + right.redeemed = true + right.save! + get :download, :id=>@jam_track.id, sample_rate: 48, all_fp: 'all', running_fp: 'running' + response.status.should == 202 + + user2 = FactoryGirl.create(:user) + + controller.current_user = user2 + + right = JamTrackRight.create(:user=>user2, :jam_track=>@jam_track) + right.redeemed = true + right.save! + get :download, :id=>@jam_track.id, sample_rate: 48, all_fp: 'all', running_fp: 'running' + response.status.should == 403 + JSON.parse(response.body)['message'].should eq("other user has 'all' fingerprint") + end + + it "stops second user from enqueuing using same machine" do + right = JamTrackRight.create(:user=>@user, :jam_track=>@jam_track) + right.redeemed = true + right.save! + right.signing_queued_at.should be_nil + post :enqueue, {:format=>'json', :id=>right.jam_track.id, fingerprint: {all: 'all', running: 'running'} } + response.should be_success + + user2 = FactoryGirl.create(:user) + + controller.current_user = user2 + + right = JamTrackRight.create(:user=>user2, :jam_track=>@jam_track) + right.redeemed = true + right.save! + right.signing_queued_at.should be_nil + post :enqueue, {:format=>'json', :id=>right.jam_track.id, fingerprint: {all: 'all', running: 'running'} } + get :download, :id=>@jam_track.id, sample_rate: 48, all_fp: 'all', running_fp: 'running' + response.status.should == 403 + JSON.parse(response.body)['message'].should eq("other user has 'all' fingerprint") + end + end end diff --git a/web/spec/controllers/api_shopping_carts_controller_spec.rb b/web/spec/controllers/api_shopping_carts_controller_spec.rb index 4c9f69079..c6f196d0d 100644 --- a/web/spec/controllers/api_shopping_carts_controller_spec.rb +++ b/web/spec/controllers/api_shopping_carts_controller_spec.rb @@ -55,7 +55,7 @@ describe ApiShoppingCartsController do describe "anonymous" do - let(:user) { AnonymousUser.new('abc') } + let(:user) { AnonymousUser.new('abc', {}) } before(:each) do controller.current_user = nil diff --git a/web/spec/controllers/api_signup_hint_spec.rb b/web/spec/controllers/api_signup_hint_spec.rb index ac9a4e323..1bafa164a 100644 --- a/web/spec/controllers/api_signup_hint_spec.rb +++ b/web/spec/controllers/api_signup_hint_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe ApiSignupHintsController, :type=>:controller do render_views - let(:user) {AnonymousUser.new(SecureRandom.uuid)} + let(:user) {AnonymousUser.new(SecureRandom.uuid, {})} before(:each) do SignupHint.delete_all diff --git a/web/spec/features/individual_jamtrack_band_spec.rb b/web/spec/features/individual_jamtrack_band_spec.rb index 9fa47b3b2..badfb8583 100644 --- a/web/spec/features/individual_jamtrack_band_spec.rb +++ b/web/spec/features/individual_jamtrack_band_spec.rb @@ -15,60 +15,19 @@ describe "Individual JamTrack Band", :js => true, :type => :feature, :capybara_f let(:user) { FactoryGirl.create(:user) } let(:jamtrack_acdc_backinblack) { @jamtrack_acdc_backinblack } - let(:billing_info) { - { - first_name: 'Seth', - last_name: 'Call', - address1: '10704 Buckthorn Drive', - city: 'Austin', - state: 'Texas', - country: 'US', - zip: '78759', - number: '4111111111111111', - month: '08', - year: '2017', - verification_value: '012' - } - } - - def create_account(user, billing_info) - @recurlyClient.create_account(user, billing_info) - @created_accounts << user - end before(:all) do - - @recurlyClient = RecurlyClient.new - @created_accounts = [] - @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 - # make sure tax estimate plans are there - @recurlyClient.create_jam_track_plan(@jamtrack_acdc_backinblack) unless @recurlyClient.find_jam_track_plan(@jamtrack_acdc_backinblack) - end - - - after(:each) do - @created_accounts.each do |user| - if user.recurly_code - begin - @account = Recurly::Account.find(user.recurly_code) - if @account.present? - @account.destroy - end - rescue - end - end - end - end describe "AC/DC Back in Black" do it "logged out" do visit "/landing/jamtracks/band/acdc-backinblack" - find('h1', text: "We Have 1 #{@jamtrack_acdc_backinblack.original_artist} JamTrack, Check It Out!") + find('.jamtrack_band', text: @jamtrack_acdc_backinblack.original_artist) jamtrack_acdc_backinblack.jam_track_tracks.each do |track| if track.master? find('.jam-track-preview-holder[data-id="' + track.id + '"] img.instrument-icon[data-instrument-id="other"]') @@ -78,16 +37,17 @@ describe "Individual JamTrack Band", :js => true, :type => :feature, :capybara_f find('.jam-track-preview-holder[data-id="' + track.id + '"] .instrument-name', text:track.instrument.description) end end - find('a.white-bordered-button')['href'].should eq("/client?artist=#{jamtrack_acdc_backinblack.original_artist}#/jamtrackBrowse") + find('a.cta-free-jamtrack')['href'].should eq("/client?artist=#{jamtrack_acdc_backinblack.original_artist}#/jamtrackBrowse") + find('a.browse-jamtracks')['href'].should eq("/client?artist=#{jamtrack_acdc_backinblack.original_artist}#/jamtrackBrowse") - find('a.white-bordered-button').trigger(:click) + find('a.browse-jamtracks').trigger(:click) find('h1', text: 'jamtracks') end it "logged in" do fast_signin(user, "/landing/jamtracks/band/acdc-backinblack") - find('h1', text: "We Have 1 #{@jamtrack_acdc_backinblack.original_artist} JamTrack, Check It Out!") + find('.jamtrack_band', text: @jamtrack_acdc_backinblack.original_artist) jamtrack_acdc_backinblack.jam_track_tracks.each do |track| if track.master? find('.jam-track-preview-holder[data-id="' + track.id + '"] img.instrument-icon[data-instrument-id="other"]') @@ -97,9 +57,10 @@ describe "Individual JamTrack Band", :js => true, :type => :feature, :capybara_f find('.jam-track-preview-holder[data-id="' + track.id + '"] .instrument-name', text:track.instrument.description) end end - find('a.white-bordered-button')['href'].should eq("/client?artist=#{jamtrack_acdc_backinblack.original_artist}#/jamtrackBrowse") + find('a.cta-free-jamtrack')['href'].should eq("/client?artist=#{jamtrack_acdc_backinblack.original_artist}#/jamtrackBrowse") + find('a.browse-jamtracks')['href'].should eq("/client?artist=#{jamtrack_acdc_backinblack.original_artist}#/jamtrackBrowse") - find('a.white-bordered-button').trigger(:click) + find('a.browse-jamtracks').trigger(:click) find('h1', text: 'jamtracks') end end diff --git a/web/spec/features/individual_jamtrack_spec.rb b/web/spec/features/individual_jamtrack_spec.rb index 3483a8b86..1711554b6 100644 --- a/web/spec/features/individual_jamtrack_spec.rb +++ b/web/spec/features/individual_jamtrack_spec.rb @@ -31,44 +31,19 @@ describe "Individual JamTrack", :js => true, :type => :feature, :capybara_featur } } - def create_account(user, billing_info) - @recurlyClient.create_account(user, billing_info) - @created_accounts << user - end - before(:all) do - - @recurlyClient = RecurlyClient.new - @created_accounts = [] - @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 - # make sure plans are there - @recurlyClient.create_jam_track_plan(@jamtrack_acdc_backinblack) unless @recurlyClient.find_jam_track_plan(@jamtrack_acdc_backinblack) - end - - - after(:each) do - @created_accounts.each do |user| - if user.recurly_code - begin - @account = Recurly::Account.find(user.recurly_code) - if @account.present? - @account.destroy - end - rescue - end - end - end - end describe "AC/DC Back in Black" do it "logged out" do visit "/landing/jamtracks/acdc-backinblack" - find('h1', text: 'Check Out Our Back in Black JamTrack') + find('.jamtrack_name', '"Back in Black"') + find('.jamtrack_band', '"AC/DC"') jamtrack_acdc_backinblack.jam_track_tracks.each do |track| if track.master? find('.jam-track-preview-holder[data-id="' + track.id + '"] img.instrument-icon[data-instrument-id="other"]') @@ -78,16 +53,18 @@ describe "Individual JamTrack", :js => true, :type => :feature, :capybara_featur find('.jam-track-preview-holder[data-id="' + track.id + '"] .instrument-name', text:track.instrument.description) end end - find('a.white-bordered-button')['href'].should eq("/client?artist=#{jamtrack_acdc_backinblack.original_artist}#/jamtrackBrowse") + find('a.cta-free-jamtrack')['href'].should eq("/client?artist=#{jamtrack_acdc_backinblack.original_artist}#/jamtrackBrowse") + find('a.browse-jamtracks')['href'].should eq("/client?artist=#{jamtrack_acdc_backinblack.original_artist}#/jamtrackBrowse") - find('a.white-bordered-button').trigger(:click) + find('a.browse-jamtracks').trigger(:click) find('h1', text: 'jamtracks') end it "logged in" do fast_signin(user, "/landing/jamtracks/acdc-backinblack") - find('h1', text: 'Check Out Our Back in Black JamTrack') + find('.jamtrack_name', '"Back in Black"') + find('.jamtrack_band', '"AC/DC"') jamtrack_acdc_backinblack.jam_track_tracks.each do |track| if track.master? find('.jam-track-preview-holder[data-id="' + track.id + '"] img.instrument-icon[data-instrument-id="other"]') @@ -97,16 +74,17 @@ describe "Individual JamTrack", :js => true, :type => :feature, :capybara_featur find('.jam-track-preview-holder[data-id="' + track.id + '"] .instrument-name', text:track.instrument.description) end end - find('a.white-bordered-button')['href'].should eq("/client?artist=#{jamtrack_acdc_backinblack.original_artist}#/jamtrackBrowse") + find('a.cta-free-jamtrack')['href'].should eq("/client?artist=#{jamtrack_acdc_backinblack.original_artist}#/jamtrackBrowse") + find('a.browse-jamtracks')['href'].should eq("/client?artist=#{jamtrack_acdc_backinblack.original_artist}#/jamtrackBrowse") - find('a.white-bordered-button').trigger(:click) + find('a.browse-jamtracks').trigger(:click) find('h1', text: 'jamtracks') end it "generic version" do visit "/landing/jamtracks/acdc-backinblack?generic=true" - find('h1', text: 'We Have 100+ Amazing JamTracks, Check One Out!') + find('h1', text: 'Preview One of Our JamTracks') jamtrack_acdc_backinblack.jam_track_tracks.each do |track| if track.master? find('.jam-track-preview-holder[data-id="' + track.id + '"] img.instrument-icon[data-instrument-id="other"]') @@ -116,10 +94,13 @@ describe "Individual JamTrack", :js => true, :type => :feature, :capybara_featur find('.jam-track-preview-holder[data-id="' + track.id + '"] .instrument-name', text:track.instrument.description) end end - find('a.white-bordered-button')['href'].should eq("/client#/jamtrackBrowse") + find('a.cta-free-jamtrack')['href'].should eq("/client#/jamtrackBrowse") + find('a.browse-jamtracks')['href'].should eq("/client#/jamtrackBrowse") - find('a.white-bordered-button').trigger(:click) + find('a.browse-jamtracks').trigger(:click) find('h1', text: 'jamtracks') + + end end end diff --git a/web/spec/features/jamtrack_shopping_spec.rb b/web/spec/features/jamtrack_shopping_spec.rb index 3cf01fc6d..23da6a3f4 100644 --- a/web/spec/features/jamtrack_shopping_spec.rb +++ b/web/spec/features/jamtrack_shopping_spec.rb @@ -35,9 +35,9 @@ describe "JamTrack Shopping", :js => true, :type => :feature, :capybara_feature def find_jamtrack jamtrack, options = {} jamtrack_record = find(".jamtrack-record[jamtrack-id=\"#{jamtrack.id}\"]") - jamtrack_record.find('.detail-value', text: jamtrack.name) + #jamtrack_record.find('.detail-value', text: jamtrack.name) #jamtrack_record.find('.detail-value', text: jamtrack.recording_type) - jamtrack_record.find('.detail-value', text: jamtrack.original_artist) + #jamtrack_record.find('.detail-value', text: jamtrack.original_artist) # jamtrack_record.find('.detail-value', text: jamtrack.genre.description) # jamtrack_record.find('.detail-value', text: [jamtrack.songwriter, jamtrack.publisher].join(', ')) # jamtrack_record.find('.copyright-value', text: jamtrack.licensor.name) diff --git a/web/spec/features/products_spec.rb b/web/spec/features/products_spec.rb index 4fecc2703..37afb0df8 100644 --- a/web/spec/features/products_spec.rb +++ b/web/spec/features/products_spec.rb @@ -15,54 +15,14 @@ describe "Product Pages", :js => true, :type => :feature, :capybara_feature => t let(:user) { FactoryGirl.create(:user) } let(:jamtrack_acdc_backinblack) { @jamtrack_acdc_backinblack } - let(:billing_info) { - { - first_name: 'Seth', - last_name: 'Call', - address1: '10704 Buckthorn Drive', - city: 'Austin', - state: 'Texas', - country: 'US', - zip: '78759', - number: '4111111111111111', - month: '08', - year: '2017', - verification_value: '012' - } - } - - def create_account(user, billing_info) - @recurlyClient.create_account(user, billing_info) - @created_accounts << user - end - before(:all) do - @recurlyClient = RecurlyClient.new - @created_accounts = [] - @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') - # make sure plans are there - @recurlyClient.create_jam_track_plan(@jamtrack_acdc_backinblack) unless @recurlyClient.find_jam_track_plan(@jamtrack_acdc_backinblack) end - after(:each) do - @created_accounts.each do |user| - if user.recurly_code - begin - @account = Recurly::Account.find(user.recurly_code) - if @account.present? - @account.destroy - end - rescue - end - end - end - end - describe "JamBlaster" do before(:all) do diff --git a/web/spec/features/signup_spec.rb b/web/spec/features/signup_spec.rb index 3b1ff4400..ff62b51bf 100644 --- a/web/spec/features/signup_spec.rb +++ b/web/spec/features/signup_spec.rb @@ -293,7 +293,7 @@ describe "Signup", :js => true, :type => :feature, :capybara_feature => true do # get a anonymous cookie set up anon_user_id = page.driver.cookies["user_uuid"] - anon_user = AnonymousUser.new(anon_user_id.value) + anon_user = AnonymousUser.new(anon_user_id.value, {}) SignupHint.refresh_by_anoymous_user(anon_user, {redirect_location: '/products/jamblaster', want_jamblaster: true}) visit signup_path @@ -321,7 +321,7 @@ describe "Signup", :js => true, :type => :feature, :capybara_feature => true do # get a anonymous cookie set up anon_user_id = page.driver.cookies["user_uuid"] - anon_user = AnonymousUser.new(anon_user_id.value) + anon_user = AnonymousUser.new(anon_user_id.value, {}) hint = SignupHint.refresh_by_anoymous_user(anon_user, {redirect_location: '/products/jamblaster', want_jamblaster: true}) hint.expires_at = 1.day.ago hint.save! From eba9afab045ab4cd71df42c59d4e631b9fa7ef56 Mon Sep 17 00:00:00 2001 From: Seth Call Date: Fri, 15 May 2015 15:30:15 -0500 Subject: [PATCH 03/13] * fix bug in ability to open JamTrack --- web/app/assets/javascripts/dialog/openJamTrackDialog.js | 2 +- web/app/assets/javascripts/redeem_complete.js | 5 ++--- web/app/helpers/sessions_helper.rb | 1 + web/spec/features/products_spec.rb | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/web/app/assets/javascripts/dialog/openJamTrackDialog.js b/web/app/assets/javascripts/dialog/openJamTrackDialog.js index 3dd131e41..867314632 100644 --- a/web/app/assets/javascripts/dialog/openJamTrackDialog.js +++ b/web/app/assets/javascripts/dialog/openJamTrackDialog.js @@ -89,7 +89,7 @@ rest.openJamTrack({id: context.JK.CurrentSessionModel.id(), jam_track_id: jamTrack.id}) .done(function(response) { $dialog.data('result', {success:true, jamTrack: jamTrack}) - context.JK.CurrentSessionModel.updateSession(response);s + context.JK.CurrentSessionModel.updateSession(response); app.layout.closeDialog('open-jam-track-dialog'); }) .fail(function(jqXHR) { diff --git a/web/app/assets/javascripts/redeem_complete.js b/web/app/assets/javascripts/redeem_complete.js index 5f93cd4ce..6d5ec9a3d 100644 --- a/web/app/assets/javascripts/redeem_complete.js +++ b/web/app/assets/javascripts/redeem_complete.js @@ -140,9 +140,8 @@ $jamTrackInBrowser.removeClass('hidden'); app.user().done(function(user) { - // cut off time - var cutoff = new Date("May 8, 2015 00:00:00"); - if(new Date(user.created_at).getTime() < cutoff.getTime()) { + // relative to 1 day ago (24 * 60 * 60 * 1000) + if(new Date(user.created_at).getTime() < new Date().getTime() - 86400000) { logger.debug("existing user recorded") context.JK.GA.virtualPageView('/redeemInBrowserExistingUser'); } diff --git a/web/app/helpers/sessions_helper.rb b/web/app/helpers/sessions_helper.rb index 6e6cb7c7b..a5e914512 100644 --- a/web/app/helpers/sessions_helper.rb +++ b/web/app/helpers/sessions_helper.rb @@ -95,6 +95,7 @@ module SessionsHelper redirect_location = signup_hint.redirect_location end + cookies[:new_user] = { musician: user.musician, registrationType: user.user_authorization('facebook') ? 'Facebook' : 'Native', want_jamblaster: want_jamblaster, redirect_location: redirect_location }.to_json end diff --git a/web/spec/features/products_spec.rb b/web/spec/features/products_spec.rb index 37afb0df8..98f1ce38a 100644 --- a/web/spec/features/products_spec.rb +++ b/web/spec/features/products_spec.rb @@ -52,7 +52,7 @@ describe "Product Pages", :js => true, :type => :feature, :capybara_feature => t click_button "SIGN IN" end - # should be back at the jamblaster product page, and told we placed our order + # should be back loat the jamblaster product page, and told we placed our order find('h1', text: 'The JamBlaster by JamKazam') find('#banner h1', text: 'virtual order placed') From 2c6a5fe81a72efefbcbfcd5369d0075058b62ed9 Mon Sep 17 00:00:00 2001 From: Seth Call Date: Fri, 15 May 2015 16:01:39 -0500 Subject: [PATCH 04/13] * fix facebook signup issues VRFS-3253 --- web/app/assets/javascripts/everywhere/everywhere.js | 4 ++-- web/app/assets/javascripts/redeem_signup.js | 9 ++++----- .../assets/stylesheets/client/redeem_complete.css.scss | 5 ++++- web/app/controllers/sessions_controller.rb | 3 +++ web/app/views/clients/_redeem_complete.html.slim | 2 -- web/app/views/landings/product_jamblaster.html.slim | 2 +- 6 files changed, 14 insertions(+), 11 deletions(-) diff --git a/web/app/assets/javascripts/everywhere/everywhere.js b/web/app/assets/javascripts/everywhere/everywhere.js index 8186b3b58..1b27ba754 100644 --- a/web/app/assets/javascripts/everywhere/everywhere.js +++ b/web/app/assets/javascripts/everywhere/everywhere.js @@ -230,8 +230,8 @@ try { cookie = JSON.parse(cookie) - context.JK.signup = {} - context.JK.signup = cookie + context.JK.signupData = {} + context.JK.signupData = cookie $(function() { // ga() object isn't ready until the page is loaded diff --git a/web/app/assets/javascripts/redeem_signup.js b/web/app/assets/javascripts/redeem_signup.js index bc7a13641..3c50dd965 100644 --- a/web/app/assets/javascripts/redeem_signup.js +++ b/web/app/assets/javascripts/redeem_signup.js @@ -98,11 +98,10 @@ } }) } - function onClickSignupFacebook() { + function onClickSignupFacebook(e) { // tos must already be clicked - var $btn = $(e.target) - $btn.addClass('disabled') + $btnFacebook.addClass('disabled') var $field = $termsOfServiceL.closest('.field') $field.find('.error-text').remove() @@ -113,13 +112,13 @@ rest.createSignupHint({redirect_location: '/client#/redeemComplete'}) .done(function() { // send the user on to facebook signin - window.location = $btn.attr('href'); + window.location = $btnFacebook.attr('href'); }) .fail(function() { app.notify({text:"Facebook Signup is not working properly"}); }) .always(function() { - $btn.removeClass('disabled') + $btnFacebook.removeClass('disabled') }) } else { diff --git a/web/app/assets/stylesheets/client/redeem_complete.css.scss b/web/app/assets/stylesheets/client/redeem_complete.css.scss index ece08d208..617e1a01f 100644 --- a/web/app/assets/stylesheets/client/redeem_complete.css.scss +++ b/web/app/assets/stylesheets/client/redeem_complete.css.scss @@ -13,7 +13,6 @@ h2 { color:white; - background-color:#4d4d4d; font-weight:normal; margin: 0 0 10px 0; font-size:14px; @@ -22,6 +21,10 @@ line-height: 14px; vertical-align: middle; text-align:left; + + &.purchased-jam-track-header { + background-color:#4d4d4d; + } } .action-bar { diff --git a/web/app/controllers/sessions_controller.rb b/web/app/controllers/sessions_controller.rb index 4962d93a8..36c54e58c 100644 --- a/web/app/controllers/sessions_controller.rb +++ b/web/app/controllers/sessions_controller.rb @@ -147,6 +147,9 @@ class SessionsController < ApplicationController new_user(user, signup_hint) redirect_to signup_hint.redirect_location return + else + redirect_to "#{signup_path}?facebook_signup=#{fb_signup.lookup_id}" + return end else redirect_to "#{signup_path}?facebook_signup=#{fb_signup.lookup_id}" diff --git a/web/app/views/clients/_redeem_complete.html.slim b/web/app/views/clients/_redeem_complete.html.slim index ec0c06154..223ba2c82 100644 --- a/web/app/views/clients/_redeem_complete.html.slim +++ b/web/app/views/clients/_redeem_complete.html.slim @@ -35,8 +35,6 @@ div layout="screen" layout-id="redeemComplete" id="redeemCompleteScreen" class=" h2.purchased-jam-track-header status="in-progress" span.in-progress-msg Downloading Your JamTrack span.done-msg All purchased JamTracks have been downloaded successfully! You can now play them in a session. - 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 diff --git a/web/app/views/landings/product_jamblaster.html.slim b/web/app/views/landings/product_jamblaster.html.slim index 1b9e65d06..8fd33fd5d 100644 --- a/web/app/views/landings/product_jamblaster.html.slim +++ b/web/app/views/landings/product_jamblaster.html.slim @@ -69,7 +69,7 @@ javascript: confirmOrder(data.app); }) } - else if(window.JK.signup && window.JK.signup.want_jamblaster) { + else if(window.JK.signupData && window.JK.signupData.want_jamblaster) { // if the user has come here as a result of a signup attempt, and if they indicated that they want the jamblaster, tell em it's done promptConfirmed(data.app) } From b0cfad89f18db9ef106b5c726c859b1bc0cce5ef Mon Sep 17 00:00:00 2001 From: Seth Call Date: Fri, 15 May 2015 16:14:18 -0500 Subject: [PATCH 05/13] * fix any youtube URI in http --- web/app/controllers/users_controller.rb | 4 ++-- web/app/views/clients/_ftue.html.erb | 12 ++++++------ .../wizard/loopback/_loopback_wizard.html.haml | 6 +++--- .../views/dialogs/_gettingStartedDialog.html.slim | 2 +- web/app/views/dialogs/_whatsNextDialog.html | 4 ++-- web/app/views/events/event.html.haml | 2 +- web/app/views/music_sessions/show.html.erb | 2 +- web/app/views/shared/_cta_sidebar.html.erb | 6 +++--- web/app/views/users/home.html.slim | 6 +++--- 9 files changed, 22 insertions(+), 22 deletions(-) diff --git a/web/app/controllers/users_controller.rb b/web/app/controllers/users_controller.rb index a1d17d28d..47675f9ce 100644 --- a/web/app/controllers/users_controller.rb +++ b/web/app/controllers/users_controller.rb @@ -366,12 +366,12 @@ class UsersController < ApplicationController end if params[:id].present? && (service=params[:service]).present? service ||= 'facebook' - url = CGI::escape('http://www.jamkazam.com') + url = CGI::escape('https://www.jamkazam.com') txt = CGI::escape('Check out JamKazam -- Play music together over the Internet as if in the same room') if 'twitter'==service url = "https://twitter.com/intent/tweet?text=#{txt}&url=#{url}" elsif 'facebook'==service - url = "http://www.facebook.com/sharer/sharer.php?u=#{url}&t=#{txt}" + url = "https://www.facebook.com/sharer/sharer.php?u=#{url}&t=#{txt}" elsif 'google'==service url = "https://plus.google.com/share?url=#{url}" end diff --git a/web/app/views/clients/_ftue.html.erb b/web/app/views/clients/_ftue.html.erb index 9ef6872bd..3c1548b23 100644 --- a/web/app/views/clients/_ftue.html.erb +++ b/web/app/views/clients/_ftue.html.erb @@ -140,20 +140,20 @@
    diff --git a/web/app/views/clients/wizard/loopback/_loopback_wizard.html.haml b/web/app/views/clients/wizard/loopback/_loopback_wizard.html.haml index a16768ed9..31c7bc34c 100644 --- a/web/app/views/clients/wizard/loopback/_loopback_wizard.html.haml +++ b/web/app/views/clients/wizard/loopback/_loopback_wizard.html.haml @@ -14,18 +14,18 @@ %ul.device_type - %li.ftue-video-link.first{'external-link-win'=>"http://www.youtube.com/watch?v=b1JrwGeUcOo", 'external-link-mac'=>"http://www.youtube.com/watch?v=TRzb7OTlO-Q"} + %li.ftue-video-link.first{'external-link-win'=>"https://www.youtube.com/watch?v=b1JrwGeUcOo", 'external-link-mac'=>"https://www.youtube.com/watch?v=TRzb7OTlO-Q"} AUDIO DEVICE WITH PORTS FOR INSTRUMENT OR MIC INPUT JACKS %br %p = image_tag "content/audio_capture_ftue.png", {:width => 243, :height => 70} - %li.ftue-video-link{'external-link-win'=>"http://www.youtube.com/watch?v=IDrLa8TOXwQ",'external-link-mac'=>"http://www.youtube.com/watch?v=vIs7ArrjMpE"} + %li.ftue-video-link{'external-link-win'=>"https://www.youtube.com/watch?v=IDrLa8TOXwQ",'external-link-mac'=>"https://www.youtube.com/watch?v=vIs7ArrjMpE"} USB MICROPHONE %br %p = image_tag "content/microphone_ftue.png", {:width => 70, :height => 113} - %li.ftue-video-link{'external-link-win'=>"http://www.youtube.com/watch?v=PCri4Xed4CA",'external-link-mac'=>"http://www.youtube.com/watch?v=Gatmd_ja47U"} + %li.ftue-video-link{'external-link-win'=>"https://www.youtube.com/watch?v=PCri4Xed4CA",'external-link-mac'=>"https://www.youtube.com/watch?v=Gatmd_ja47U"} COMPUTER'S BUILT-IN MIC & SPEAKERS/HEADPHONES %br %p diff --git a/web/app/views/dialogs/_gettingStartedDialog.html.slim b/web/app/views/dialogs/_gettingStartedDialog.html.slim index e6b6b5db1..649885d7b 100644 --- a/web/app/views/dialogs/_gettingStartedDialog.html.slim +++ b/web/app/views/dialogs/_gettingStartedDialog.html.slim @@ -69,7 +69,7 @@ | There is a lot you can do with JamKazam, and more great features available every week. Check the following link for a list of videos and other resources you can use to take advantage of everything that’s available: - a rel="external" purpose="youtube-tutorials" href="http://www.youtube.com/channel/UC38nc9MMZgExJAd7ca3rkUA" JamKazam Tutorials & Resources + a rel="external" purpose="youtube-tutorials" href="https://www.youtube.com/channel/UC38nc9MMZgExJAd7ca3rkUA" JamKazam Tutorials & Resources br clear="both" .row.dialog-buttons .buttons diff --git a/web/app/views/dialogs/_whatsNextDialog.html b/web/app/views/dialogs/_whatsNextDialog.html index e1402ffe2..32050d555 100644 --- a/web/app/views/dialogs/_whatsNextDialog.html +++ b/web/app/views/dialogs/_whatsNextDialog.html @@ -46,10 +46,10 @@

    diff --git a/web/app/views/events/event.html.haml b/web/app/views/events/event.html.haml index b0b9b109a..186ed42eb 100644 --- a/web/app/views/events/event.html.haml +++ b/web/app/views/events/event.html.haml @@ -39,7 +39,7 @@ %div{align: 'center'} LEARN ABOUT JAMKAZAM
%br = image_tag 'web/carousel_musicians.jpg', width:350, alt:'JamKazam Overview', class: 'video-slide', - :'data-video-header' => 'JamKazam Overview', :'data-video-url' => 'http://www.youtube.com/embed/ylYcvTY9CVo?autoplay=1' + :'data-video-header' => 'JamKazam Overview', :'data-video-url' => 'https://www.youtube.com/embed/ylYcvTY9CVo?autoplay=1' %br{clear:'all'} diff --git a/web/app/views/music_sessions/show.html.erb b/web/app/views/music_sessions/show.html.erb index 3e2d35829..d2b8d8ae4 100644 --- a/web/app/views/music_sessions/show.html.erb +++ b/web/app/views/music_sessions/show.html.erb @@ -104,7 +104,7 @@
<%= image_tag('web/carousel_musicians.jpg', width:350, alt:'JamKazam Overview', class: 'video-slide', :'data-video-header' => 'JamKazam Overview', - :'data-video-url' => 'http://www.youtube.com/embed/ylYcvTY9CVo?autoplay=1') %> + :'data-video-url' => 'https://www.youtube.com/embed/ylYcvTY9CVo?autoplay=1') %> <% else %> diff --git a/web/app/views/shared/_cta_sidebar.html.erb b/web/app/views/shared/_cta_sidebar.html.erb index 9ab1506ac..fe84f61a9 100644 --- a/web/app/views/shared/_cta_sidebar.html.erb +++ b/web/app/views/shared/_cta_sidebar.html.erb @@ -4,7 +4,7 @@ Already have an account?

- <%= image_tag "web/thumbnail_jamtracks.jpg", {:width => 350, :alt => "", :class => 'video-slide', :'data-video-header' => 'JamTracks', :'data-video-url' => 'http://www.youtube.com/embed/askHvcCoNfw?autoplay=1'} %>

- <%= image_tag "web/thumbnail_platform.jpg", {:width => 350, :alt => "", :class => 'video-slide', :'data-video-header' => 'JamKazam Platform', :'data-video-url' => 'http://www.youtube.com/embed/ylYcvTY9CVo?autoplay=1'} %>

- <%= image_tag "web/thumbnail_jamblaster.jpg", {:width => 350, :alt => "", :class => 'video-slide', :'data-video-header' => 'JamKazam Platform', :'data-video-url' => 'http://www.youtube.com/embed/YHZQHfKDdMc?autoplay=1'} %> + <%= image_tag "web/thumbnail_jamtracks.jpg", {:width => 350, :alt => "", :class => 'video-slide', :'data-video-header' => 'JamTracks', :'data-video-url' => 'https://www.youtube.com/embed/askHvcCoNfw?autoplay=1'} %>

+ <%= image_tag "web/thumbnail_platform.jpg", {:width => 350, :alt => "", :class => 'video-slide', :'data-video-header' => 'JamKazam Platform', :'data-video-url' => 'https://www.youtube.com/embed/ylYcvTY9CVo?autoplay=1'} %>

+ <%= image_tag "web/thumbnail_jamblaster.jpg", {:width => 350, :alt => "", :class => 'video-slide', :'data-video-header' => 'JamKazam Platform', :'data-video-url' => 'https://www.youtube.com/embed/YHZQHfKDdMc?autoplay=1'} %> \ No newline at end of file diff --git a/web/app/views/users/home.html.slim b/web/app/views/users/home.html.slim index e8ae96180..69c67c883 100644 --- a/web/app/views/users/home.html.slim +++ b/web/app/views/users/home.html.slim @@ -16,7 +16,7 @@ a.learn-more-jamtracks href='/products/jamtracks' learn more .home-column - = link_to image_tag("web/thumbnail_platform.jpg", :alt => "JamKazam explanatory video!"), '#', class: "platform-video video-item", 'data-video-header' => 'JamKazam Platform', 'data-video-url' => 'http://www.youtube.com/embed/ylYcvTY9CVo?autoplay=1' + = link_to image_tag("web/thumbnail_platform.jpg", :alt => "JamKazam explanatory video!"), '#', class: "platform-video video-item", 'data-video-header' => 'JamKazam Platform', 'data-video-url' => 'https://www.youtube.com/embed/ylYcvTY9CVo?autoplay=1' h3 Online Music Collaboration Platform p @@ -33,7 +33,7 @@ br clear="all" .home-column.last - = link_to image_tag("web/thumbnail_jamblaster.jpg", :alt => "JamBlaster explanatory video!"), '#', class: "jamblaster-video video-item", 'data-video-header' => 'JamBlaster', 'data-video-url' => 'http://www.youtube.com/embed/YHZQHfKDdMc?autoplay=1' + = link_to image_tag("web/thumbnail_jamblaster.jpg", :alt => "JamBlaster explanatory video!"), '#', class: "jamblaster-video video-item", 'data-video-header' => 'JamBlaster', 'data-video-url' => 'https://www.youtube.com/embed/YHZQHfKDdMc?autoplay=1' h3 Ultra Low-Latency Audio Interface p @@ -55,7 +55,7 @@ br clear="all" .endorsement-promo .home-buzz h2 What Musicians in the JamKazam Community Are Saying - = link_to image_tag("web/thumbnail_buzz.jpg", :alt => "JamKazam Endorsements!", width:300), '#', class: "endorsements-video video-item", 'data-video-header' => 'JamKazam Community', 'data-video-url' => 'http://www.youtube.com/embed/_7qj5RXyHCo?autoplay=1' + = link_to image_tag("web/thumbnail_buzz.jpg", :alt => "JamKazam Endorsements!", width:300), '#', class: "endorsements-video video-item", 'data-video-header' => 'JamKazam Community', 'data-video-url' => 'https://www.youtube.com/embed/_7qj5RXyHCo?autoplay=1' br clear="all" From 515b2013cc097abb691cde27a5a8fe7a2ee80b75 Mon Sep 17 00:00:00 2001 From: Seth Call Date: Fri, 15 May 2015 16:24:58 -0500 Subject: [PATCH 06/13] * fix details showing for metadata VRFS-3254 --- .../music_sessions/session_info.html.haml | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/web/app/views/music_sessions/session_info.html.haml b/web/app/views/music_sessions/session_info.html.haml index e49bc10f7..4a71e6aaa 100644 --- a/web/app/views/music_sessions/session_info.html.haml +++ b/web/app/views/music_sessions/session_info.html.haml @@ -2,18 +2,18 @@ - provide(:description, description_for_music_session(@music_session)) - content_for :social_meta do - %meta {property: "fb:app_id", content: Rails.application.config.facebook_app_id} - %meta {property: "og:title", content: title_for_music_session(@music_session)} - %meta {property: "og:url", content: request.original_url} - %meta {property: "og:description", content: description_for_music_session(@music_session)} - %meta {property: "og:image", content: facebook_image_for_music_session(@music_session)} - %meta {property: "og:image:width", content: facebook_image_size_for_music_session(@music_session)} - %meta {property: "og:image:height", content: facebook_image_size_for_music_session(@music_session)} - %meta {property: "og:type", content: 'website'} - %meta {property: "twitter:card", content: 'summary'} - %meta {property: "twitter:site", content: '@jamkazam'} - %meta {property: "twitter:title", content: title_for_music_session(@music_session)} - %meta {property: "twitter:description", content: description_for_music_session(@music_session)} + %meta{property: "fb:app_id", content: Rails.application.config.facebook_app_id} + %meta{property: "og:title", content: title_for_music_session(@music_session)} + %meta{property: "og:url", content: request.original_url} + %meta{property: "og:description", content: description_for_music_session(@music_session)} + %meta{property: "og:image", content: facebook_image_for_music_session(@music_session)} + %meta{property: "og:image:width", content: facebook_image_size_for_music_session(@music_session)} + %meta{property: "og:image:height", content: facebook_image_size_for_music_session(@music_session)} + %meta{property: "og:type", content: 'website'} + %meta{property: "twitter:card", content: 'summary'} + %meta{property: "twitter:site", content: '@jamkazam'} + %meta{property: "twitter:title", content: title_for_music_session(@music_session)} + %meta{property: "twitter:description", content: description_for_music_session(@music_session)} - unless @music_session.nil? - provide(:title, @music_session.name) From 0264c539b1dbef8dbb51e1913a98f30459e3b9e7 Mon Sep 17 00:00:00 2001 From: Seth Call Date: Fri, 15 May 2015 18:25:47 -0500 Subject: [PATCH 07/13] *hardcoding https where http is found --- ruby/lib/jam_ruby/app/mailers/invited_user_mailer.rb | 2 +- .../app/views/jam_ruby/corp_mailer/feedback.html.erb | 2 +- .../app/views/jam_ruby/corp_mailer/feedback.text.erb | 2 +- .../jam_ruby/progress_mailer/client_notdl.html.erb | 2 +- .../jam_ruby/progress_mailer/client_notdl.text.erb | 2 +- .../jam_ruby/progress_mailer/gear_notsess.html.erb | 2 +- .../jam_ruby/progress_mailer/gear_notsess.text.erb | 2 +- .../jam_ruby/progress_mailer/reg_notconnect.html.erb | 2 +- .../jam_ruby/progress_mailer/reg_notconnect.text.erb | 2 +- .../jam_ruby/progress_mailer/reg_notlike.html.erb | 2 +- .../jam_ruby/progress_mailer/reg_notlike.text.erb | 2 +- .../jam_ruby/user_mailer/new_musicians.html.erb | 2 +- .../jam_ruby/user_mailer/new_musicians.text.erb | 2 +- .../user_mailer/scheduled_session_daily.html.erb | 8 ++++---- .../user_mailer/scheduled_session_daily.text.erb | 2 +- .../app/views/layouts/from_user_mailer.html.erb | 4 ++-- .../app/views/layouts/from_user_mailer.text.erb | 2 +- .../jam_ruby/app/views/layouts/user_mailer.text.erb | 2 +- ruby/lib/jam_ruby/models/icecast_mount_template.rb | 2 +- .../javascripts/dialog/invitationDialog.js.erb | 2 +- web/app/views/clients/_createSession.html.erb | 2 +- web/app/views/clients/_order.html.slim | 8 ++++---- web/app/views/corps/audio.html.erb | 12 ++++++------ web/app/views/layouts/_footer.html.erb | 2 +- web/app/views/static_pages/about.html.erb | 2 +- web/lib/tasks/urls.rake | 2 +- web/public/robots.txt | 2 +- 27 files changed, 39 insertions(+), 39 deletions(-) diff --git a/ruby/lib/jam_ruby/app/mailers/invited_user_mailer.rb b/ruby/lib/jam_ruby/app/mailers/invited_user_mailer.rb index ed772126b..dab372c1f 100644 --- a/ruby/lib/jam_ruby/app/mailers/invited_user_mailer.rb +++ b/ruby/lib/jam_ruby/app/mailers/invited_user_mailer.rb @@ -52,7 +52,7 @@ module JamRuby def generate_signup_url(invited_user) invited_user.generate_signup_url - # "http://www.jamkazam.com/signup?invitation_code=#{invited_user.invitation_code}" + # "https://www.jamkazam.com/signup?invitation_code=#{invited_user.invitation_code}" end end end diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/corp_mailer/feedback.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/corp_mailer/feedback.html.erb index 2f21454bf..febb229c0 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/corp_mailer/feedback.html.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/corp_mailer/feedback.html.erb @@ -8,7 +8,7 @@

-This email was received because someone left feedback at http://www.jamkazam.com/corp/contact +This email was received because someone left feedback at http://www.jamkazam.com/corp/contact

diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/corp_mailer/feedback.text.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/corp_mailer/feedback.text.erb index 4612cf5ee..ee99b3544 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/corp_mailer/feedback.text.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/corp_mailer/feedback.text.erb @@ -5,4 +5,4 @@ From <%= @email %>: <%= @body %> -This email was received because someone left feedback at http://www.jamkazam.com/corp/contact \ No newline at end of file +This email was received because someone left feedback at https://www.jamkazam.com/corp/contact \ No newline at end of file diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/client_notdl.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/client_notdl.html.erb index 5ce39a3c6..cb0654e8d 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/client_notdl.html.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/client_notdl.html.erb @@ -7,7 +7,7 @@

-Go to Download Page +Go to Download Page

diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/client_notdl.text.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/client_notdl.text.erb index 4ec636c7b..cfda033fb 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/client_notdl.text.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/client_notdl.text.erb @@ -4,7 +4,7 @@ Hello <%= EmailBatchProgression::VAR_FIRST_NAME %> -- We noticed that you have registered as a JamKazam musician, but you have not yet downloaded and started using the free JamKazam application. You can find other musicians and listen to sessions and recordings on our website, but you need the free JamKazam application to play with other musicians online. Please click the link below to go to the download page for the free JamKazam application, or visit our JamKazam support center so that we can help you get up and running. -Go to Download Page: http://www.jamkazam.com/downloads +Go to Download Page: https://www.jamkazam.com/downloads Go to Support Center: https://jamkazam.desk.com diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/gear_notsess.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/gear_notsess.html.erb index 0a72b2017..5ecea0b58 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/gear_notsess.html.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/gear_notsess.html.erb @@ -10,7 +10,7 @@ It’s still very early in our company’s development, so we don’t have zillions of users online on our service yet. If you click Find Session, you will often not find a good session to join, both due to the number of musicians online at any given time, and also because you won’t see private sessions where groups of musicians don’t want to be interrupted in their sessions.

-

If you are having trouble getting into sessions, we’d suggest you click the Musicians tile on the home screen of the app or the website: Go To Musicians Page +

If you are having trouble getting into sessions, we’d suggest you click the Musicians tile on the home screen of the app or the website: Go To Musicians Page

This will display the JamKazam musicians sorted by latency to you - in other words, you can see which musicians have good network connections to you. Any musicians with green and yellow latency scores have good enough connections to support a play session with you. We recommend that read the profiles of these musicians to find others with shared musical interests and good network connections to you, and then use the Message button to say hi and see if they are interested in playing with you. If they are, use the Connect button to “friend” them on JamKazam, and use the Message button to set up a time to meet online for a session. diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/gear_notsess.text.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/gear_notsess.text.erb index d027cf178..e5f74495a 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/gear_notsess.text.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/gear_notsess.text.erb @@ -7,7 +7,7 @@ We noticed that you haven’t yet played in a JamKazam session with multiple mus Find Other Musicians on JamKazam It’s still very early in our company’s development, so we don’t have zillions of users online on our service yet. If you click Find Session, you will often not find a good session to join, both due to the number of musicians online at any given time, and also because you won’t see private sessions where groups of musicians don’t want to be interrupted in their sessions. -If you are having trouble getting into sessions, we’d suggest you click the Musicians tile on the home screen of the app or the website: http://www.jamkazam.com/client#/musicians +If you are having trouble getting into sessions, we’d suggest you click the Musicians tile on the home screen of the app or the website: https://www.jamkazam.com/client#/musicians This will display the JamKazam musicians sorted by latency to you - in other words, you can see which musicians have good network connections to you. Any musicians with green and yellow latency scores have good enough connections to support a play session with you. We recommend that read the profiles of these musicians to find others with shared musical interests and good network connections to you, and then use the Message button to say hi and see if they are interested in playing with you. If they are, use the Connect button to “friend” them on JamKazam, and use the Message button to set up a time to meet online for a session. diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/reg_notconnect.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/reg_notconnect.html.erb index 0a0eada21..cf444d605 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/reg_notconnect.html.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/reg_notconnect.html.erb @@ -7,7 +7,7 @@

Find Other Musicians on JamKazam
-To find and connect with other musicians who are already on JamKazam, we’d suggest you click the Musicians tile on the home screen of the app or the website: Go To Musicians Page +To find and connect with other musicians who are already on JamKazam, we’d suggest you click the Musicians tile on the home screen of the app or the website: Go To Musicians Page

This will display the JamKazam musicians sorted by latency to you - in other words, you can see which musicians have good network connections to you. Any musicians with green and yellow latency scores have good enough connections to support a play session with you. We recommend that you read the profiles of these musicians to find others with shared musical interests and good network connections to you, and then use the Message button to say hi and see if they are interested in playing with you. If they are, use the Connect button to “friend” them on JamKazam, and use the Message button to set up a time to meet online for a session. diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/reg_notconnect.text.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/reg_notconnect.text.erb index 370823a10..cd90de475 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/reg_notconnect.text.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/reg_notconnect.text.erb @@ -5,7 +5,7 @@ Hello <%= EmailBatchProgression::VAR_FIRST_NAME %> -- We noticed that you haven’t yet connected with any friends on JamKazam. Connecting with friends is the best way to help you get into sessions with other musicians on JamKazam. Here are a couple of good ways to connect with others. Find Other Musicians on JamKazam -To find and connect with other musicians who are already on JamKazam, we’d suggest you click the Musicians tile on the home screen of the app or the website: http://www.jamkazam.com/client#/musicians +To find and connect with other musicians who are already on JamKazam, we’d suggest you click the Musicians tile on the home screen of the app or the website: https://www.jamkazam.com/client#/musicians This will display the JamKazam musicians sorted by latency to you - in other words, you can see which musicians have good network connections to you. Any musicians with green and yellow latency scores have good enough connections to support a play session with you. We recommend that you read the profiles of these musicians to find others with shared musical interests and good network connections to you, and then use the Message button to say hi and see if they are interested in playing with you. If they are, use the Connect button to “friend” them on JamKazam, and use the Message button to set up a time to meet online for a session. diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/reg_notlike.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/reg_notlike.html.erb index 3b654a83a..e9c3c4d03 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/reg_notlike.html.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/reg_notlike.html.erb @@ -7,7 +7,7 @@

<% [:twitter, :facebook, :google].each do |site| %> - <%= link_to(image_tag("http://www.jamkazam.com/assets/content/icon_#{site}.png", :style => "vertical-align:top"), "http://www.jamkazam.com/endorse/@USERID/#{site}?src=email") %>  + <%= link_to(image_tag("https://www.jamkazam.com/assets/content/icon_#{site}.png", :style => "vertical-align:top"), "https://www.jamkazam.com/endorse/@USERID/#{site}?src=email") %>  <% end %>

-- Team JamKazam diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/reg_notlike.text.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/reg_notlike.text.erb index 9dddb6ca6..37c4a7623 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/reg_notlike.text.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/reg_notlike.text.erb @@ -5,7 +5,7 @@ Hello <%= EmailBatchProgression::VAR_FIRST_NAME %> -- JamKazam is a young company/service built through the sweat and commitment of a small group of music-loving techies. Please help us continue to grow the service and attract more musicians to play online by liking and/or following us on Facebook, Twitter, and Google+. Just click the icons below to give us little push, thanks! <% [:twitter, :facebook, :google].each do |site| %> - http://www.jamkazam.com/endorse/@USERID/#{site}?src=email + https://www.jamkazam.com/endorse/@USERID/#{site}?src=email <% end %> diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/new_musicians.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/new_musicians.html.erb index 7a25bfe43..be9aa27fb 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/new_musicians.html.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/new_musicians.html.erb @@ -24,7 +24,7 @@ Hi <%= @user.first_name %>, <% end %>

-

There are currently <%= @new_musicians.size%> musicians on JamKazam with low enough latency Internet connections to you to support a good online session. To see ALL the JamKazam musicians with whom you may want to connect and play, view our Musicians page at: http://www.jamkazam.com/client#/musicians. +

There are currently <%= @new_musicians.size%> musicians on JamKazam with low enough latency Internet connections to you to support a good online session. To see ALL the JamKazam musicians with whom you may want to connect and play, view our Musicians page at: http://www.jamkazam.com/client#/musicians.

Best Regards,

diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/new_musicians.text.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/new_musicians.text.erb index df39c005a..05fbbd268 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/new_musicians.text.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/new_musicians.text.erb @@ -11,7 +11,7 @@ The following new musicians have joined JamKazam within the last week, and have <%= user.biography %> <% end %> -There are currently <%= @new_musicians.size%> musicians on JamKazam with low enough latency Internet connections to you to support a good online session. To see ALL the JamKazam musicians with whom you may want to connect and play, view our Musicians page at: http://www.jamkazam.com/client#/musicians. +There are currently <%= @new_musicians.size%> musicians on JamKazam with low enough latency Internet connections to you to support a good online session. To see ALL the JamKazam musicians with whom you may want to connect and play, view our Musicians page at: https://www.jamkazam.com/client#/musicians. Best Regards, Team JamKazam diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_daily.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_daily.html.erb index c4b476d45..2fdc11256 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_daily.html.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_daily.html.erb @@ -68,16 +68,16 @@ <%= sess.genre.description %> <%= sess.name %>
- ">Details + ">Details <%= sess.description %> <%= (sess.latency / 2).round %> ms <% if sess.latency <= (APP_CONFIG.max_good_full_score / 2) %> - <%= image_tag("http://www.jamkazam.com/assets/content/icon_green_score.png", alt: 'good score icon') %> + <%= image_tag("https://www.jamkazam.com/assets/content/icon_green_score.png", alt: 'good score icon') %> <% else %> - <%= image_tag("http://www.jamkazam.com/assets/content/icon_yellow_score.png", alt: 'fair score icon') %> + <%= image_tag("https://www.jamkazam.com/assets/content/icon_yellow_score.png", alt: 'fair score icon') %> <% end %> @@ -86,7 +86,7 @@ -

To see ALL the scheduled sessions that you might be interested in joining, view our Find Session page.

+

To see ALL the scheduled sessions that you might be interested in joining, view our Find Session page.

Best Regards,

diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_daily.text.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_daily.text.erb index 9720550d5..282c6dd90 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_daily.text.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_daily.text.erb @@ -9,7 +9,7 @@ GENRE | NAME | DESCRIPTION | LATENCY <%= sess.genre.description %> | <%= sess.name %> | <%= sess.description %> | <%= sess.latency %> ms <% end %> -To see ALL the scheduled sessions that you might be interested in joining, view our Find Session page at: http://www.jamkazam.com/client#/findSession. +To see ALL the scheduled sessions that you might be interested in joining, view our Find Session page at: https://www.jamkazam.com/client#/findSession. Best Regards, diff --git a/ruby/lib/jam_ruby/app/views/layouts/from_user_mailer.html.erb b/ruby/lib/jam_ruby/app/views/layouts/from_user_mailer.html.erb index 6b10f7f66..5b7ce4aec 100644 --- a/ruby/lib/jam_ruby/app/views/layouts/from_user_mailer.html.erb +++ b/ruby/lib/jam_ruby/app/views/layouts/from_user_mailer.html.erb @@ -19,7 +19,7 @@ - +
JamKazamJamKazam
@@ -51,7 +51,7 @@

-

This email was sent to you because you have an account at JamKazam. +

This email was sent to you because you have an account at JamKazam.

diff --git a/ruby/lib/jam_ruby/app/views/layouts/from_user_mailer.text.erb b/ruby/lib/jam_ruby/app/views/layouts/from_user_mailer.text.erb index 8bd3c7483..88d4f9234 100644 --- a/ruby/lib/jam_ruby/app/views/layouts/from_user_mailer.text.erb +++ b/ruby/lib/jam_ruby/app/views/layouts/from_user_mailer.text.erb @@ -2,7 +2,7 @@ <% unless @suppress_user_has_account_footer == true %> -This email was sent to you because you have an account at JamKazam / http://www.jamkazam.com. +This email was sent to you because you have an account at JamKazam / https://www.jamkazam.com. <% end %> Copyright <%= Time.now.year %> JamKazam, Inc. All rights reserved. diff --git a/ruby/lib/jam_ruby/app/views/layouts/user_mailer.text.erb b/ruby/lib/jam_ruby/app/views/layouts/user_mailer.text.erb index 49655e237..03accee00 100644 --- a/ruby/lib/jam_ruby/app/views/layouts/user_mailer.text.erb +++ b/ruby/lib/jam_ruby/app/views/layouts/user_mailer.text.erb @@ -5,7 +5,7 @@ <% end %> <% unless @user.nil? || @suppress_user_has_account_footer == true %> -This email was sent to you because you have an account at JamKazam / http://www.jamkazam.com. To unsubscribe: http://www.jamkazam.com/unsubscribe/<%=@user.unsubscribe_token%>. +This email was sent to you because you have an account at JamKazam / https://www.jamkazam.com. To unsubscribe: https://www.jamkazam.com/unsubscribe/<%=@user.unsubscribe_token%>. <% end %> Copyright <%= Time.now.year %> JamKazam, Inc. All rights reserved. diff --git a/ruby/lib/jam_ruby/models/icecast_mount_template.rb b/ruby/lib/jam_ruby/models/icecast_mount_template.rb index c93dc1c8a..c6094669a 100644 --- a/ruby/lib/jam_ruby/models/icecast_mount_template.rb +++ b/ruby/lib/jam_ruby/models/icecast_mount_template.rb @@ -54,7 +54,7 @@ module JamRuby mount.source_pass = APP_CONFIG.icecast_hardcoded_source_password || SecureRandom.urlsafe_base64 mount.stream_name = "JamKazam music session created by #{music_session.creator.name}" mount.stream_description = music_session.description - mount.stream_url = "http://www.jamkazam.com" ## TODO/XXX, the jamkazam url should be the page hosting the widget + mount.stream_url = "https://www.jamkazam.com" ## TODO/XXX, the jamkazam url should be the page hosting the widget mount.genre = music_session.genre.description mount end diff --git a/web/app/assets/javascripts/dialog/invitationDialog.js.erb b/web/app/assets/javascripts/dialog/invitationDialog.js.erb index b7887d9b4..7e3424736 100644 --- a/web/app/assets/javascripts/dialog/invitationDialog.js.erb +++ b/web/app/assets/javascripts/dialog/invitationDialog.js.erb @@ -195,7 +195,7 @@ var obj = { method: 'feed', link: signupUrl, - picture: 'http://www.jamkazam.com/assets/web/logo-256.png', + picture: 'https://www.jamkazam.com/assets/web/logo-256.png', name: 'Join me on JamKazam', caption: 'Play live music in real-time sessions with others over the Internet, as if in the same room.', description: '', diff --git a/web/app/views/clients/_createSession.html.erb b/web/app/views/clients/_createSession.html.erb index 7b6b42b19..97f29f7ca 100644 --- a/web/app/views/clients/_createSession.html.erb +++ b/web/app/views/clients/_createSession.html.erb @@ -131,7 +131,7 @@
- I agree that intellectual property ownership of any musical works created during this session shall be governed by the terms of the Creative Commons CC BY-NC-SA license in accordance with the JamKazam Terms of Service. + I agree that intellectual property ownership of any musical works created during this session shall be governed by the terms of the Creative Commons CC BY-NC-SA license in accordance with the JamKazam Terms of Service.

diff --git a/web/app/views/clients/_order.html.slim b/web/app/views/clients/_order.html.slim index f5ea0cc91..cc8982dfe 100644 --- a/web/app/views/clients/_order.html.slim +++ b/web/app/views/clients/_order.html.slim @@ -163,11 +163,11 @@ div layout="screen" layout-id="order" id="orderScreen" class="screen secondary" .mt5 span By placing your order, you agree to JamKazam's ' - a href="http://www.jamkazam.com/corp/terms" terms of service + a href="/corp/terms" terms of service ' span and ' - a href="http://www.jamkazam.com/corp/returns" returns policy + a href="/corp/returns" returns policy span . .right.mt10 a href="#" class="button-grey" HELP @@ -279,11 +279,11 @@ script type='text/template' id='template-order-content' div style="text-align: left;" span By placing your order, you agree to JamKazam's ' - a href="http://www.jamkazam.com/corp/terms" terms of service + a href="/corp/terms" terms of service ' span and ' - a href="http://www.jamkazam.com/corp/returns" returns policy + a href="/corp/returns" returns policy span . script type='text/template' id='template-purchased-jam-track' diff --git a/web/app/views/corps/audio.html.erb b/web/app/views/corps/audio.html.erb index 7b9876eb4..4d96965ea 100644 --- a/web/app/views/corps/audio.html.erb +++ b/web/app/views/corps/audio.html.erb @@ -18,20 +18,20 @@

Classical: Pachelbel’s “Canon in D”

Rock: Poison’s “Nothin’ But a Good Time”

Jazz: Jimmy Van Heusen’s and Johnny Burke’s “But Beautiful”

\ No newline at end of file diff --git a/web/app/views/layouts/_footer.html.erb b/web/app/views/layouts/_footer.html.erb index 8297f4e70..17db1de4e 100644 --- a/web/app/views/layouts/_footer.html.erb +++ b/web/app/views/layouts/_footer.html.erb @@ -3,7 +3,7 @@
  • <%= link_to "About", about_path %>
  • <%= link_to "Contact", contact_path %>
  • -
  • JamKazam
  • +
  • JamKazam
diff --git a/web/app/views/static_pages/about.html.erb b/web/app/views/static_pages/about.html.erb index 0a8ce82c7..c7b8df7a8 100644 --- a/web/app/views/static_pages/about.html.erb +++ b/web/app/views/static_pages/about.html.erb @@ -1,5 +1,5 @@ <% provide(:title, 'About Us') %>

About Us

- JamKazam is bringing musicians and fans together everywhere. + JamKazam is bringing musicians and fans together everywhere.

diff --git a/web/lib/tasks/urls.rake b/web/lib/tasks/urls.rake index 53871e88f..19e110005 100644 --- a/web/lib/tasks/urls.rake +++ b/web/lib/tasks/urls.rake @@ -5,7 +5,7 @@ namespace :urls do JamTrack.all.each do |jam_track| prefix = "jamtrack-" plan_code = jam_track.plan_code["jamtrack-".length..-1] - f.puts('http://www.jamkazam.com/landing/jamtracks/' + plan_code) + f.puts('https://www.jamkazam.com/landing/jamtracks/' + plan_code) #f.puts('http://www.jamkazam.com/landing/jamtracks/bands/' + plan_code) end } diff --git a/web/public/robots.txt b/web/public/robots.txt index 64907a2ac..0d5783c71 100644 --- a/web/public/robots.txt +++ b/web/public/robots.txt @@ -3,4 +3,4 @@ # To ban all spiders from the entire site uncomment the next two lines: # User-Agent: * # Disallow: / -Sitemap: http://www.jamkazam.com/sitemap.xml.gz \ No newline at end of file +Sitemap: https://www.jamkazam.com/sitemap.xml.gz \ No newline at end of file From 792212e9527cdf5217b8c2e45c4b340b661552e9 Mon Sep 17 00:00:00 2001 From: Seth Call Date: Fri, 15 May 2015 23:28:46 -0500 Subject: [PATCH 08/13] * VRFS-3260 - disable fraud --- ruby/lib/jam_ruby/models/jam_track_right.rb | 1 + .../controllers/api_jam_tracks_controller.rb | 24 +++++++++++-------- web/config/application.rb | 1 + 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/ruby/lib/jam_ruby/models/jam_track_right.rb b/ruby/lib/jam_ruby/models/jam_track_right.rb index 5f919c13b..b59fdcee6 100644 --- a/ruby/lib/jam_ruby/models/jam_track_right.rb +++ b/ruby/lib/jam_ruby/models/jam_track_right.rb @@ -215,6 +215,7 @@ module JamRuby end def guard_against_fraud(current_user, fingerprint, remote_ip) + if current_user.blank? return "no user specified" end diff --git a/web/app/controllers/api_jam_tracks_controller.rb b/web/app/controllers/api_jam_tracks_controller.rb index d85f93bd9..b219570a8 100644 --- a/web/app/controllers/api_jam_tracks_controller.rb +++ b/web/app/controllers/api_jam_tracks_controller.rb @@ -77,11 +77,13 @@ class ApiJamTracksController < ApiController all_fingerprint = params[:all_fp] running_fingerprint = params[:running_fp] - error = @jam_track_right.guard_against_fraud(current_user, {all:all_fingerprint, running: running_fingerprint}, request.remote_ip) - if error - log.warn("potential fraud detected: #{error}") - render :json => { :message => error }, :status => 403 - return + if Rails.application.config.guard_against_fraud + error = @jam_track_right.guard_against_fraud(current_user, {all:all_fingerprint, running: running_fingerprint}, request.remote_ip) + if error + log.warn("potential fraud detected: #{error}") + render :json => { :message => error }, :status => 403 + return + end end sample_rate = params[:sample_rate].nil? ? nil : params[:sample_rate].to_i @@ -105,11 +107,13 @@ class ApiJamTracksController < ApiController fingerprint = params[:fingerprint] - error = @jam_track_right.guard_against_fraud(current_user, fingerprint, request.remote_ip) - if error - log.warn("potential fraud detected: #{error}") - render :json => { :message => error }, :status => 403 - return + if Rails.application.config.guard_against_fraud + error = @jam_track_right.guard_against_fraud(current_user, fingerprint, request.remote_ip) + if error + log.warn("potential fraud detected: #{error}") + render :json => { :message => error }, :status => 403 + return + end end sample_rate = params[:sample_rate].nil? ? nil : params[:sample_rate].to_i diff --git a/web/config/application.rb b/web/config/application.rb index 650596aae..98433834d 100644 --- a/web/config/application.rb +++ b/web/config/application.rb @@ -341,5 +341,6 @@ if defined?(Bundler) config.remove_whitespace_credit_card = false config.estimate_taxes = true config.ad_sense_enabled = false + config.guard_against_fraud = false end end From a62aaeef119c2d2eee2dc39fcbccb96f7c8a98a1 Mon Sep 17 00:00:00 2001 From: Seth Call Date: Fri, 15 May 2015 23:50:27 -0500 Subject: [PATCH 09/13] * VRFS-3260 - fraud check allowed in tests --- web/config/environments/test.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/web/config/environments/test.rb b/web/config/environments/test.rb index 565634690..920391264 100644 --- a/web/config/environments/test.rb +++ b/web/config/environments/test.rb @@ -107,5 +107,6 @@ SampleApp::Application.configure do config.log_level = :debug config.jam_tracks_available = true config.video_available = "full" + config.guard_against_fraud = true end From f5595a03d54dd92b5a973791938882dbbfc20a53 Mon Sep 17 00:00:00 2001 From: Seth Call Date: Sat, 16 May 2015 10:18:35 -0500 Subject: [PATCH 10/13] * actually send email when fraud detected --- admin/app/admin/jam_ruby_users.rb | 1 + ruby/lib/jam_ruby/models/jam_track_right.rb | 4 ++-- web/config/environments/development.rb | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/admin/app/admin/jam_ruby_users.rb b/admin/app/admin/jam_ruby_users.rb index 0fe3c29d9..61a1d3db7 100644 --- a/admin/app/admin/jam_ruby_users.rb +++ b/admin/app/admin/jam_ruby_users.rb @@ -32,6 +32,7 @@ ActiveAdmin.register JamRuby::User, :as => 'Users' do row :birth_date row :gender row :email_confirmed + row :remember_token row :image do user.photo_url ? image_tag(user.photo_url) : '' end end active_admin_comments diff --git a/ruby/lib/jam_ruby/models/jam_track_right.rb b/ruby/lib/jam_ruby/models/jam_track_right.rb index b59fdcee6..7e5a491d8 100644 --- a/ruby/lib/jam_ruby/models/jam_track_right.rb +++ b/ruby/lib/jam_ruby/models/jam_track_right.rb @@ -255,7 +255,7 @@ module JamRuby if match && match.user != current_user AdminMailer.alerts(subject: "'All' fingerprint collision by #{current_user.name}", - body: "MachineFingerprint #{match.inspect}\n\nCurrent User: #{current_user.admin_url}") + body: "MachineFingerprint #{match.inspect}\n\nCurrent User: #{current_user.admin_url}").deliver # try to record the other fingerprint MachineFingerprint.create(running_fingerprint, current_user, MachineFingerprint::TAKEN_ON_FRAUD_CONFLICT, MachineFingerprint::PRINT_TYPE_ACTIVE, remote_ip, self) @@ -266,7 +266,7 @@ module JamRuby if match && match.user != current_user AdminMailer.alerts(subject: "'Running' fingerprint collision by #{current_user.name}", - body: "MachineFingerprint #{match.inspect}\n\nCurrent User: #{current_user.admin_url}") + body: "MachineFingerprint #{match.inspect}\n\nCurrent User: #{current_user.admin_url}").deliver # try to record the other fingerprint MachineFingerprint.create(all_fingerprint, current_user, MachineFingerprint::TAKEN_ON_FRAUD_CONFLICT, MachineFingerprint::PRINT_TYPE_ALL, remote_ip, self) return "other user has 'running' fingerprint" diff --git a/web/config/environments/development.rb b/web/config/environments/development.rb index 52ebbcd08..6567e404e 100644 --- a/web/config/environments/development.rb +++ b/web/config/environments/development.rb @@ -95,4 +95,5 @@ SampleApp::Application.configure do config.video_available= ENV['VIDEO_AVAILABILITY'] || "none" config.email_generic_from = 'nobody-dev@jamkazam.com' config.email_alerts_alias = ENV['ALERT_EMAIL'] || 'alerts-dev@jamkazam.com' + config.guard_against_fraud = true end From 781a9838b70676a492cf3066645dc17cba9a9f20 Mon Sep 17 00:00:00 2001 From: Seth Call Date: Mon, 18 May 2015 10:33:58 -0500 Subject: [PATCH 11/13] * VRFS-3216 - add virtual page views for JamTrack funnels, add test mode for fraud check VRFS-3260 --- ruby/lib/jam_ruby/models/jam_track_right.rb | 44 ++++++++------- ruby/spec/support/utilities.rb | 4 ++ web/app/assets/javascripts/application.js | 1 + .../javascripts/jam_track_screen.js.coffee | 1 + web/app/assets/javascripts/redeem_signup.js | 2 + .../javascripts/web/individual_jamtrack.js | 1 + .../web/individual_jamtrack_band.js | 1 + .../assets/javascripts/web/tracking.js.coffee | 56 +++++++++++++++++++ web/app/assets/javascripts/web/web.js | 1 + web/config/application.rb | 1 + 10 files changed, 93 insertions(+), 19 deletions(-) create mode 100644 web/app/assets/javascripts/web/tracking.js.coffee diff --git a/ruby/lib/jam_ruby/models/jam_track_right.rb b/ruby/lib/jam_ruby/models/jam_track_right.rb index 7e5a491d8..fda1ecb97 100644 --- a/ruby/lib/jam_ruby/models/jam_track_right.rb +++ b/ruby/lib/jam_ruby/models/jam_track_right.rb @@ -6,21 +6,21 @@ module JamRuby @@log = Logging.logger[JamTrackRight] - attr_accessible :user, :jam_track, :user_id, :jam_track_id, :download_count + attr_accessible :user, :jam_track, :user_id, :jam_track_id, :download_count attr_accessible :user_id, :jam_track_id, as: :admin attr_accessible :url_48, :md5_48, :length_48, :url_44, :md5_44, :length_44 - belongs_to :user, class_name: "JamRuby::User" # the owner, or purchaser of the jam_track + belongs_to :user, class_name: "JamRuby::User" # the owner, or purchaser of the jam_track belongs_to :jam_track, class_name: "JamRuby::JamTrack" - validates :user, presence:true - validates :jam_track, presence:true - validates :is_test_purchase, inclusion: {in: [true, false]} + validates :user, presence: true + validates :jam_track, presence: true + validates :is_test_purchase, inclusion: {in: [true, false]} validate :verify_download_count after_save :after_save - validates_uniqueness_of :user_id, scope: :jam_track_id - + validates_uniqueness_of :user_id, scope: :jam_track_id + # Uploads the JKZ: mount_uploader :url_48, JamTrackRightUploader mount_uploader :url_44, JamTrackRightUploader @@ -45,7 +45,7 @@ module JamRuby def filename(bitrate) "#{jam_track.name}-#{bitrate == :url_48 ? '48' : '44'}.jkz" end - + def verify_download_count if (self.download_count < 0 || self.download_count > MAX_JAM_TRACK_DOWNLOADS) && !@current_user.admin errors.add(:download_count, "must be less than or equal to #{MAX_JAM_TRACK_DOWNLOADS}") @@ -105,8 +105,8 @@ module JamRuby end def delete_s3_files - remove_url_48! - remove_url_44! + remove_url_48! + remove_url_44! end @@ -244,7 +244,7 @@ module JamRuby # if this is a free JamTrack, we need to check for fraud or accidental misuse # first of all, does this user have any other JamTracks aside from this one that have already been redeemed it and are marked free? - other_redeemed_freebie = JamTrackRight.where(redeemed:true).where(redeemed_and_fingerprinted: true).where('id != ?', id).where(user_id: current_user.id).first + other_redeemed_freebie = JamTrackRight.where(redeemed: true).where(redeemed_and_fingerprinted: true).where('id != ?', id).where(user_id: current_user.id).first if other_redeemed_freebie return "already redeemed another" @@ -259,17 +259,23 @@ module JamRuby # try to record the other fingerprint MachineFingerprint.create(running_fingerprint, current_user, MachineFingerprint::TAKEN_ON_FRAUD_CONFLICT, MachineFingerprint::PRINT_TYPE_ACTIVE, remote_ip, self) - return "other user has 'all' fingerprint" + if APP_CONFIG.error_on_fraud + return "other user has 'all' fingerprint" + end end - match = MachineFingerprint.find_by_fingerprint(running_fingerprint) + if all_fingerprint != running_fingerprint + match = MachineFingerprint.find_by_fingerprint(running_fingerprint) - if match && match.user != current_user - AdminMailer.alerts(subject: "'Running' fingerprint collision by #{current_user.name}", - body: "MachineFingerprint #{match.inspect}\n\nCurrent User: #{current_user.admin_url}").deliver - # try to record the other fingerprint - MachineFingerprint.create(all_fingerprint, current_user, MachineFingerprint::TAKEN_ON_FRAUD_CONFLICT, MachineFingerprint::PRINT_TYPE_ALL, remote_ip, self) - return "other user has 'running' fingerprint" + if match && match.user != current_user + AdminMailer.alerts(subject: "'Running' fingerprint collision by #{current_user.name}", + body: "MachineFingerprint #{match.inspect}\n\nCurrent User: #{current_user.admin_url}").deliver + # try to record the other fingerprint + MachineFingerprint.create(all_fingerprint, current_user, MachineFingerprint::TAKEN_ON_FRAUD_CONFLICT, MachineFingerprint::PRINT_TYPE_ALL, remote_ip, self) + if APP_CONFIG.error_on_fraud + return "other user has 'running' fingerprint" + end + end end # we made it past all checks; let's slap on the redeemed_fingerprint diff --git a/ruby/spec/support/utilities.rb b/ruby/spec/support/utilities.rb index c033de858..5e9380eac 100644 --- a/ruby/spec/support/utilities.rb +++ b/ruby/spec/support/utilities.rb @@ -194,6 +194,10 @@ def app_config 'blah' end + def error_on_fraud + true + end + private def audiomixer_workspace_path diff --git a/web/app/assets/javascripts/application.js b/web/app/assets/javascripts/application.js index 08a2918e8..474503da2 100644 --- a/web/app/assets/javascripts/application.js +++ b/web/app/assets/javascripts/application.js @@ -51,6 +51,7 @@ //= require web/signup_helper //= require web/signin_helper //= require web/signin +//= require web/tracking //= require_directory . //= require_directory ./dialog //= require_directory ./wizard diff --git a/web/app/assets/javascripts/jam_track_screen.js.coffee b/web/app/assets/javascripts/jam_track_screen.js.coffee index 64b970d19..43411b93b 100644 --- a/web/app/assets/javascripts/jam_track_screen.js.coffee +++ b/web/app/assets/javascripts/jam_track_screen.js.coffee @@ -40,6 +40,7 @@ context.JK.JamTrackScreen=class JamTrackScreen this.refresh() afterShow:(data) => + context.JK.Tracking.jamtrackBrowseTrack(@app) beforeHide: () => this.clearResults(); diff --git a/web/app/assets/javascripts/redeem_signup.js b/web/app/assets/javascripts/redeem_signup.js index 3c50dd965..e0785321f 100644 --- a/web/app/assets/javascripts/redeem_signup.js +++ b/web/app/assets/javascripts/redeem_signup.js @@ -31,6 +31,7 @@ } function afterShow(data) { + } @@ -40,6 +41,7 @@ $contentHolder.removeClass('not-signed-in').addClass('signed-in') } else { + context.JK.Tracking.redeemSignupTrack(app) $jamtrackName.text('') $contentHolder.addClass('hidden') $contentHolder.removeClass('signed-in').addClass('not-signed-in') diff --git a/web/app/assets/javascripts/web/individual_jamtrack.js b/web/app/assets/javascripts/web/individual_jamtrack.js index 172a94bc2..9eff40023 100644 --- a/web/app/assets/javascripts/web/individual_jamtrack.js +++ b/web/app/assets/javascripts/web/individual_jamtrack.js @@ -66,6 +66,7 @@ $genericHeader = $page.find('h1.generic') $individualizedHeader = $page.find('h1.individualized') + context.JK.Tracking.adTrack(app) fetchJamTrack(); } diff --git a/web/app/assets/javascripts/web/individual_jamtrack_band.js b/web/app/assets/javascripts/web/individual_jamtrack_band.js index afc4528a5..c05f58772 100644 --- a/web/app/assets/javascripts/web/individual_jamtrack_band.js +++ b/web/app/assets/javascripts/web/individual_jamtrack_band.js @@ -53,6 +53,7 @@ $jamTracksButton = $page.find('.browse-jamtracks') $ctaJamTracksButton = $page.find('.cta-free-jamtrack'); + context.JK.Tracking.adTrack(app) fetchJamTrack(); } diff --git a/web/app/assets/javascripts/web/tracking.js.coffee b/web/app/assets/javascripts/web/tracking.js.coffee new file mode 100644 index 000000000..e57a1b9e8 --- /dev/null +++ b/web/app/assets/javascripts/web/tracking.js.coffee @@ -0,0 +1,56 @@ + + +$ = jQuery +context = window +context.JK ||= {}; + +class Tracking + constructor: () -> + @logger = context.JK.logger + @rest = new context.JK.Rest(); + + adTrack: (app) => + utmSource = $.QueryString['utm_source'] + if utmSource == 'facebook-ads' || utmSource == 'google-ads' || utmSource == 'twitter-ads' || utmSource == 'affiliate' || utmSource == 'pr' + if !context.jamClient.IsNativeClient() + @logger.debug("new user recorded") + context.JK.GA.virtualPageView('/landing/jamtracks/new-user/') + + app.user().done( (user) => + # relative to 1 day ago (24 * 60 * 60 * 1000) + if new Date(user.created_at).getTime() < new Date().getTime() - 86400000 + @logger.debug("existing user recorded") + context.JK.GA.virtualPageView('/landing/jamtracks/existing-user/'); + + ) + + jamtrackBrowseTrack: (app) => + app.user().done( (user) => + if context.jamClient.IsNativeClient() + @logger.debug("client user recorded") + context.JK.GA.virtualPageView('/client#/jamtrackBrowse/user-in-app') + else + if new Date(user.created_at).getTime() < new Date().getTime() - 86400000 + @logger.debug("existing user recorded") + context.JK.GA.virtualPageView('/client#/jamtrackBrowse/existing-user') + else + @logger.debug("existing new recorded") + context.JK.GA.virtualPageView('/client#/jamtrackBrowse/new-user') + ) + + redeemSignupTrack: (app) => + app.user().done( (user) => + if context.jamClient.IsNativeClient() + @logger.debug("client user recorded") + context.JK.GA.virtualPageView('/client#/redeemSignup/user-in-app') + else + if new Date(user.created_at).getTime() < new Date().getTime() - 86400000 + @logger.debug("existing existing recorded") + context.JK.GA.virtualPageView('/client#/redeemSignup/existing-user') + else + @logger.debug("existing new recorded") + context.JK.GA.virtualPageView('/client#/redeemSignup/new-user') + ) + +context.JK.Tracking = new Tracking() + diff --git a/web/app/assets/javascripts/web/web.js b/web/app/assets/javascripts/web/web.js index b4e835dbe..408eaf41e 100644 --- a/web/app/assets/javascripts/web/web.js +++ b/web/app/assets/javascripts/web/web.js @@ -62,6 +62,7 @@ //= require web/session_info //= require web/recordings //= require web/home +//= require web/tracking //= require web/individual_jamtrack //= require web/individual_jamtrack_band //= require fakeJamClient diff --git a/web/config/application.rb b/web/config/application.rb index 98433834d..4de4e6d8c 100644 --- a/web/config/application.rb +++ b/web/config/application.rb @@ -342,5 +342,6 @@ if defined?(Bundler) config.estimate_taxes = true config.ad_sense_enabled = false config.guard_against_fraud = false + config.error_on_fraud = false end end From 1be53f25630161a1c1d446e711e9a3ac174c61dd Mon Sep 17 00:00:00 2001 From: Seth Call Date: Mon, 18 May 2015 14:08:39 -0500 Subject: [PATCH 12/13] * VRFS-3216 - refine landing events --- .../assets/javascripts/web/tracking.js.coffee | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/web/app/assets/javascripts/web/tracking.js.coffee b/web/app/assets/javascripts/web/tracking.js.coffee index e57a1b9e8..58699e93b 100644 --- a/web/app/assets/javascripts/web/tracking.js.coffee +++ b/web/app/assets/javascripts/web/tracking.js.coffee @@ -13,17 +13,25 @@ class Tracking utmSource = $.QueryString['utm_source'] if utmSource == 'facebook-ads' || utmSource == 'google-ads' || utmSource == 'twitter-ads' || utmSource == 'affiliate' || utmSource == 'pr' if !context.jamClient.IsNativeClient() - @logger.debug("new user recorded") - context.JK.GA.virtualPageView('/landing/jamtracks/new-user/') - app.user().done( (user) => # relative to 1 day ago (24 * 60 * 60 * 1000) if new Date(user.created_at).getTime() < new Date().getTime() - 86400000 @logger.debug("existing user recorded") context.JK.GA.virtualPageView('/landing/jamtracks/existing-user/'); - + else + @logger.debug("new user recorded") + context.JK.GA.virtualPageView('/landing/jamtracks/new-user/') ) + else + app.user().done( (user) => + # relative to 1 day ago (24 * 60 * 60 * 1000) + if new Date(user.created_at).getTime() < new Date().getTime() - 86400000 + @logger.debug("existing user recorded") + context.JK.GA.virtualPageView('/landing/jamtracks/existing-user/'); + + ) + jamtrackBrowseTrack: (app) => app.user().done( (user) => if context.jamClient.IsNativeClient() From 48f61552ce277cd99e605f2b1a15d697127762e6 Mon Sep 17 00:00:00 2001 From: Seth Call Date: Mon, 18 May 2015 14:18:48 -0500 Subject: [PATCH 13/13] * VRFS-3216 - send up stats more fully formed --- .../assets/javascripts/web/tracking.js.coffee | 83 +++++++++++-------- 1 file changed, 50 insertions(+), 33 deletions(-) diff --git a/web/app/assets/javascripts/web/tracking.js.coffee b/web/app/assets/javascripts/web/tracking.js.coffee index 58699e93b..b3fb626f4 100644 --- a/web/app/assets/javascripts/web/tracking.js.coffee +++ b/web/app/assets/javascripts/web/tracking.js.coffee @@ -13,52 +13,69 @@ class Tracking utmSource = $.QueryString['utm_source'] if utmSource == 'facebook-ads' || utmSource == 'google-ads' || utmSource == 'twitter-ads' || utmSource == 'affiliate' || utmSource == 'pr' if !context.jamClient.IsNativeClient() - app.user().done( (user) => - # relative to 1 day ago (24 * 60 * 60 * 1000) - if new Date(user.created_at).getTime() < new Date().getTime() - 86400000 - @logger.debug("existing user recorded") - context.JK.GA.virtualPageView('/landing/jamtracks/existing-user/'); - else - @logger.debug("new user recorded") - context.JK.GA.virtualPageView('/landing/jamtracks/new-user/') - ) - + if context.JK.currentUserId? + app.user().done( (user) => + # relative to 1 day ago (24 * 60 * 60 * 1000) + if new Date(user.created_at).getTime() < new Date().getTime() - 86400000 + @logger.debug("existing user recorded") + context.JK.GA.virtualPageView('/landing/jamtracks/existing-user/'); + else + @logger.debug("new user recorded") + context.JK.GA.virtualPageView('/landing/jamtracks/new-user/') + ) + else + @logger.debug("new user recorded") + context.JK.GA.virtualPageView('/landing/jamtracks/new-user/') else - app.user().done( (user) => - # relative to 1 day ago (24 * 60 * 60 * 1000) - if new Date(user.created_at).getTime() < new Date().getTime() - 86400000 - @logger.debug("existing user recorded") - context.JK.GA.virtualPageView('/landing/jamtracks/existing-user/'); - - ) + @logger.debug("existing user recorded") + context.JK.GA.virtualPageView('/landing/jamtracks/existing-user/'); jamtrackBrowseTrack: (app) => - app.user().done( (user) => + if context.JK.currentUserId? + app.user().done( (user) => + if context.jamClient.IsNativeClient() + @logger.debug("client user recorded") + context.JK.GA.virtualPageView('/client#/jamtrackBrowse/user-in-app') + else + if new Date(user.created_at).getTime() < new Date().getTime() - 86400000 + @logger.debug("existing user recorded") + context.JK.GA.virtualPageView('/client#/jamtrackBrowse/existing-user') + else + @logger.debug("existing new recorded") + context.JK.GA.virtualPageView('/client#/jamtrackBrowse/new-user') + ) + else if context.jamClient.IsNativeClient() @logger.debug("client user recorded") context.JK.GA.virtualPageView('/client#/jamtrackBrowse/user-in-app') else - if new Date(user.created_at).getTime() < new Date().getTime() - 86400000 - @logger.debug("existing user recorded") - context.JK.GA.virtualPageView('/client#/jamtrackBrowse/existing-user') - else - @logger.debug("existing new recorded") - context.JK.GA.virtualPageView('/client#/jamtrackBrowse/new-user') - ) + @logger.debug("existing new recorded") + context.JK.GA.virtualPageView('/client#/jamtrackBrowse/new-user') + + redeemSignupTrack: (app) => - app.user().done( (user) => + if context.JK.currentUserId? + app.user().done( (user) => + if context.jamClient.IsNativeClient() + @logger.debug("client user recorded") + context.JK.GA.virtualPageView('/client#/redeemSignup/user-in-app') + else + if new Date(user.created_at).getTime() < new Date().getTime() - 86400000 + @logger.debug("existing existing recorded") + context.JK.GA.virtualPageView('/client#/redeemSignup/existing-user') + else + @logger.debug("existing new recorded") + context.JK.GA.virtualPageView('/client#/redeemSignup/new-user') + ) + else if context.jamClient.IsNativeClient() @logger.debug("client user recorded") context.JK.GA.virtualPageView('/client#/redeemSignup/user-in-app') else - if new Date(user.created_at).getTime() < new Date().getTime() - 86400000 - @logger.debug("existing existing recorded") - context.JK.GA.virtualPageView('/client#/redeemSignup/existing-user') - else - @logger.debug("existing new recorded") - context.JK.GA.virtualPageView('/client#/redeemSignup/new-user') - ) + @logger.debug("existing new recorded") + context.JK.GA.virtualPageView('/client#/redeemSignup/new-user') + context.JK.Tracking = new Tracking()