diff --git a/db/up/recurly_adjustments.sql b/db/up/recurly_adjustments.sql index d86e6ba89..dc31d21e9 100644 --- a/db/up/recurly_adjustments.sql +++ b/db/up/recurly_adjustments.sql @@ -15,7 +15,7 @@ ALTER TABLE sale_line_items ADD COLUMN recurly_total_in_cents INTEGER; ALTER TABLE sale_line_items ADD COLUMN recurly_currency VARCHAR; ALTER TABLE sale_line_items ADD COLUMN recurly_discount_in_cents INTEGER; -ALTER TABLE sales ADD COLUMN sale_type VARCHAR NOT NULL; +ALTER TABLE sales ADD COLUMN sale_type VARCHAR NOT NULL DEFAULT 'jamtrack'; ALTER TABLE recurly_transaction_web_hooks ALTER COLUMN subscription_id DROP NOT NULL; diff --git a/ruby/lib/jam_ruby/models/after_signup_hint.rb b/ruby/lib/jam_ruby/models/after_signup_hint.rb new file mode 100644 index 000000000..e5c364e7e --- /dev/null +++ b/ruby/lib/jam_ruby/models/after_signup_hint.rb @@ -0,0 +1,15 @@ +module JamRuby + class AfterSignupHint < ActiveRecord::Base + + before_create :generate_lookup_id + + def self.delete_old + FacebookSignup.where("created_at < :week", {:week => 1.week.ago}).delete_all + end + + private + def generate_lookup_id + self.lookup_id = SecureRandom.urlsafe_base64 + end + end +end diff --git a/ruby/lib/jam_ruby/models/sale.rb b/ruby/lib/jam_ruby/models/sale.rb index cb2aba3b0..732bd45bb 100644 --- a/ruby/lib/jam_ruby/models/sale.rb +++ b/ruby/lib/jam_ruby/models/sale.rb @@ -172,11 +172,11 @@ module JamRuby 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" end end diff --git a/web/app/assets/javascripts/checkout_order.js b/web/app/assets/javascripts/checkout_order.js index bbf95b98b..fbe41c665 100644 --- a/web/app/assets/javascripts/checkout_order.js +++ b/web/app/assets/javascripts/checkout_order.js @@ -8,6 +8,7 @@ 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; @@ -219,6 +220,7 @@ } function moveToThanks(purchaseResponse) { + checkoutUtils.deletePreserveBillingInfo() $("#order_error").addClass("hidden") $orderPanel.addClass("hidden") $thanksPanel.removeClass("hidden") diff --git a/web/app/assets/javascripts/checkout_payment.js b/web/app/assets/javascripts/checkout_payment.js index 7c40ced26..10afdb70d 100644 --- a/web/app/assets/javascripts/checkout_payment.js +++ b/web/app/assets/javascripts/checkout_payment.js @@ -7,6 +7,7 @@ var EVENTS = context.JK.EVENTS; var logger = context.JK.logger; var jamTrackUtils = context.JK.JamTrackUtils; + var checkoutUtils = context.JK.CheckoutUtilsInstance; var $screen = null; var $navigation = null; @@ -30,6 +31,7 @@ var selectCountryLoaded = false; var $freeJamTrackPrompt = null; var $noFreeJamTrackPrompt = null; + var $alreadyEnteredJamTrackPrompt = null; function afterShow() { @@ -44,12 +46,26 @@ function renderAccountInfo() { + + $paymentInfoPanel.addClass('hidden') $reuseExistingCard.addClass('hidden'); $newCardInfo.removeClass('hidden'); $freeJamTrackPrompt.addClass('hidden'); $noFreeJamTrackPrompt.addClass('hidden'); + $alreadyEnteredJamTrackPrompt.addClass('hidden') $("#payment_error").addClass('hidden').text('') + + if(checkoutUtils.shouldPreserveBillingInfo()) { + logger.debug("showing 'user has already set up billing info' because 'preserve billing' session is active") + checkoutUtils.refreshPreserveBillingInfo() + $alreadyEnteredJamTrackPrompt.removeClass('hidden') + return + } + + $paymentInfoPanel.removeClass('hidden') + + var selectCountryReady = selectCountry.ready(); if(!selectCountryReady) { // one time init of country dropdown @@ -138,8 +154,6 @@ } function beforeShow(data) { - // XXX : style-test code - // moveToThanks({jam_tracks: [{id: 14, jam_track_right_id: 11, name: 'Back in Black'}, {id: 15, jam_track_right_id: 11, name: 'In Bloom'}, {id: 16, jam_track_right_id: 11, name: 'Love Bird Supreme'}]}); } function beforeHide() { @@ -152,6 +166,13 @@ // TODO: Refactor: this function is long and fraught with many return points. function next(e) { + + // check if we are showing the 'change payment info' pass; if so, just move on to checkoutOrder + if($alreadyEnteredJamTrackPrompt.is(':visible')) { + logger.debug("skipping payment logic ") + context.location = '/client#/checkoutOrder' + return false; + } $paymentInfoPanel.find('.error-text').remove(); $paymentInfoPanel.find('.error').removeClass('error'); e.preventDefault(); @@ -471,6 +492,8 @@ $screen.find("#payment-info-next").off("click"); rest.createRecurlyAccount({billing_info: billing_info, terms_of_service: terms, email: email, password: password, reuse_card_this_time: reuse_card_this_time, reuse_card_next_time: reuse_card_next_time}) .done(function() { + // so the user can hit back in checkoutOrder and not have to re-enter billing info right away + checkoutUtils.setPreserveBillingInfo(); $screen.find("#payment-info-next").on("click", next); if(isLoggedIn) { @@ -564,6 +587,20 @@ } } + function changeBillingInfo(e) { + if(e) { + e.preventDefault(); + } + + logger.debug("change billing info requested") + + // clear out the skip billing info behavior + checkoutUtils.deletePreserveBillingInfo() + + renderAccountInfo(); + + return false; + } function toggleReuseExistingCard(e) { if(e) { e.preventDefault(); @@ -594,6 +631,7 @@ $screen.find("#payment-info-next").on('click', next); $shippingAsBilling.on('ifChanged', toggleShippingAsBilling); $reuseExistingCardChk.on('ifChanged', toggleReuseExistingCard); + $alreadyEnteredJamTrackPrompt.find('.change-payment-info').on('click', changeBillingInfo) } function reset() { @@ -650,6 +688,7 @@ $newCardInfo = $paymentInfoPanel.find('.new-card-info') $freeJamTrackPrompt = $screen.find('.payment-prompt.free-jamtrack') $noFreeJamTrackPrompt = $screen.find('.payment-prompt.no-free-jamtrack') + $alreadyEnteredJamTrackPrompt = $screen.find('.payment-prompt.already-entered') if($screen.length == 0) throw "$screen must be specified"; diff --git a/web/app/assets/javascripts/checkout_utils.js.coffee b/web/app/assets/javascripts/checkout_utils.js.coffee new file mode 100644 index 000000000..ec6f8bb98 --- /dev/null +++ b/web/app/assets/javascripts/checkout_utils.js.coffee @@ -0,0 +1,41 @@ +$ = jQuery +context = window +context.JK ||= {}; + +class CheckoutUtils + constructor: () -> + @logger = context.JK.logger + @rest = new context.JK.Rest(); + @cookie_name = "preserve_billing" + init: () => + + refreshPreserveBillingInfo:() => + if @shouldPreserveBillingInfo + @logger.debug("refreshing preserve billing info timer") + @setPreserveBillingInfo() + + setPreserveBillingInfo:() => + date = new Date(); + minutes = 1; + date.setTime(date.getTime() + (minutes * 60 * 1000)) + $.removeCookie(@cookie_name, { path: '/' }) + $.cookie(@cookie_name, "jam", { expires: date, path: '/' }) + + deletePreserveBillingInfo:() => + $.removeCookie(@cookie_name, { path: '/' }) + + @logger.debug("deleted preserve billing"); + + unless $.cookie(@cookie_name)? + @logger.error("after deleting the preserve billing cookie, it still exists!") + + + # existance of cookie means we should preserve billing + shouldPreserveBillingInfo:() => + value = $.cookie(@cookie_name) + value? + + + +# global instance +context.JK.CheckoutUtilsInstance = new CheckoutUtils() \ No newline at end of file diff --git a/web/app/assets/javascripts/playbackControls.js b/web/app/assets/javascripts/playbackControls.js index d56a1e214..1a90712a6 100644 --- a/web/app/assets/javascripts/playbackControls.js +++ b/web/app/assets/javascripts/playbackControls.js @@ -34,6 +34,7 @@ var $sliderBar = $('.recording-playback', $parentElement); var $slider = $('.recording-slider', $parentElement); var $playmodeButton = $('.playback-mode-buttons.icheckbuttons input', $parentElement); + var $jamTrackGetReady = $('.jam-track-get-ready', $parentElement); var $self = $(this); @@ -158,7 +159,9 @@ setPlaybackMode(playmode); }); - function styleControls( ) { + function styleControls() { + $jamTrackGetReady.attr('data-mode', playbackMonitorMode); + $parentElement.removeClass('mediafile-mode jamtrack-mode metronome-mode'); if(playbackMonitorMode == PLAYBACK_MONITOR_MODE.MEDIA_FILE) { $parentElement.addClass('mediafile-mode'); @@ -194,6 +197,18 @@ positionMs = 0; } + if(playbackMonitorMode = PLAYBACK_MONITOR_MODE.JAMTRACK) { + + if(isPlaying) { + $jamTrackGetReady.attr('data-current-time', positionMs) + } + else { + // this is so the jamtrack 'Get Ready!' stays hidden when it's not playing + $jamTrackGetReady.attr('data-current-time', -1) + } + + } + if(playbackMonitorMode == PLAYBACK_MONITOR_MODE.METRONOME) { updateIsPlaying(isPlaying); } diff --git a/web/app/assets/stylesheets/client/checkout_order.css.scss b/web/app/assets/stylesheets/client/checkout_order.css.scss index 92db40291..22a208ce0 100644 --- a/web/app/assets/stylesheets/client/checkout_order.css.scss +++ b/web/app/assets/stylesheets/client/checkout_order.css.scss @@ -1,7 +1,6 @@ @import "client/common.css.scss"; #checkoutOrderScreen { - p { font-size:12px; margin:0; @@ -25,8 +24,6 @@ text-align:left; } - - .action-bar { margin-top:20px; } diff --git a/web/app/assets/stylesheets/client/checkout_payment.css.scss b/web/app/assets/stylesheets/client/checkout_payment.css.scss index 39ddaccbf..c9b29bfd6 100644 --- a/web/app/assets/stylesheets/client/checkout_payment.css.scss +++ b/web/app/assets/stylesheets/client/checkout_payment.css.scss @@ -16,6 +16,13 @@ line-height:125%; } + + .change-payment-info-holder { + display:block; + text-align:center; + margin:40px 0; + } + .field.error { background-color: transparent !important; padding: 0 !important; @@ -57,6 +64,9 @@ padding-bottom: 10px; margin-bottom: 20px; + &.hidden { + display:none; + } input[type="text"], input[type="password"] { width: 90%; @include border_box_sizing; diff --git a/web/app/assets/stylesheets/client/session.css.scss b/web/app/assets/stylesheets/client/session.css.scss index 21720a20b..94228e6f0 100644 --- a/web/app/assets/stylesheets/client/session.css.scss +++ b/web/app/assets/stylesheets/client/session.css.scss @@ -84,6 +84,32 @@ .recording-current { top:3px ! important; } + + .jam-track-get-ready { + display:none; + position:absolute; + top:-29px; + margin-left:-50px; + width:100px; + vertical-align:middle; + height:32px; + line-height:32px; + left:50%; + + &[data-mode="JAMTRACK"] { + &[data-current-time="0"] { + display:block; + } + } + .spinner-small { + vertical-align:middle; + display:inline-block; + } + + span { + vertical-align:middle; + } + } } .playback-mode-buttons { diff --git a/web/app/assets/stylesheets/web/recordings.css.scss b/web/app/assets/stylesheets/web/recordings.css.scss index 753a3e160..20b9aca35 100644 --- a/web/app/assets/stylesheets/web/recordings.css.scss +++ b/web/app/assets/stylesheets/web/recordings.css.scss @@ -19,6 +19,10 @@ float:left; margin-left:20px; } + + .jam-track-get-ready { + display:none; + } } .recording-position { diff --git a/web/app/views/clients/_checkout_payment.html.slim b/web/app/views/clients/_checkout_payment.html.slim index e937ef434..1bf5794a4 100644 --- a/web/app/views/clients/_checkout_payment.html.slim +++ b/web/app/views/clients/_checkout_payment.html.slim @@ -16,8 +16,11 @@ div layout="screen" layout-id="checkoutPayment" id="checkoutPaymentScreen" class | There are no "hidden" charges or fees, thank you! p.payment-prompt.no-free-jamtrack.hidden | Please enter your billing address and payment information below.  - - form class="payment-info" id="checkout-payment-info" + p.payment-prompt.already-entered.hidden + | You recently entered payment info successfully. If you want to change your payment info, click the CHANGE PAYMENT INFO button. Otherwise, click the NEXT button to checkout. + span.change-payment-info-holder + a.button-orange.change-payment-info href='#' CHANGE PAYMENT INFO + form.hidden class="payment-info" id="checkout-payment-info" .row.first .left-side .billing-address diff --git a/web/app/views/clients/_play_controls.html.erb b/web/app/views/clients/_play_controls.html.erb index 535e25f07..671b1701f 100644 --- a/web/app/views/clients/_play_controls.html.erb +++ b/web/app/views/clients/_play_controls.html.erb @@ -1,6 +1,10 @@
+
+
+ Get Ready! +
<%= image_tag "content/icon_playbutton.png", {:height => 20, :width => 20, :class=> "playbutton"} %> diff --git a/web/spec/features/checkout_spec.rb b/web/spec/features/checkout_spec.rb index 9484ceed7..18017ae46 100644 --- a/web/spec/features/checkout_spec.rb +++ b/web/spec/features/checkout_spec.rb @@ -265,6 +265,7 @@ describe "Checkout", :js => true, :type => :feature, :capybara_feature => true d find('p.payment-prompt.free-jamtrack') expect(page).to_not have_selector('.jamkazam-account-signup') + expect(page).to_not have_selector('.payment-prompt.already-entered') # fill out all billing info, but not account info fill_in 'billing-first-name', with: 'Seth' @@ -283,6 +284,14 @@ describe "Checkout", :js => true, :type => :feature, :capybara_feature => true d # find empty shopping cart prompt notice find('p.empty-cart-prompt') + # sneak in an extra test... let's hit BACK and confirm that the temporary 'just entered billing info' screen is showing + visit '/client#/checkoutPayment' + find('.payment-prompt.already-entered') + expect(page).to_not have_selector('.payment-prompt.no-free-jamtrack') + expect(page).to_not have_selector('.payment-prompt.free-jamtrack') + expect(page).to_not have_selector('#checkout-payment-info') + + user.reload user.reuse_card.should be_false end diff --git a/web/spec/spec_helper.rb b/web/spec/spec_helper.rb index 20ca30779..c031e9f43 100644 --- a/web/spec/spec_helper.rb +++ b/web/spec/spec_helper.rb @@ -188,7 +188,7 @@ bputs "before register capybara" config.include Requests::FeatureHelpers, type: :feature # Use the specified formatter - #config.formatter = :documentation + config.formatter = :documentation config.before(:suite) do tests_started = true diff --git a/web/spec/support/app_config.rb b/web/spec/support/app_config.rb index 3287dd0be..645562f90 100644 --- a/web/spec/support/app_config.rb +++ b/web/spec/support/app_config.rb @@ -82,6 +82,10 @@ def web_config def one_free_jamtrack_per_user true end + + def secret_token + 'ced345e01611593c1b783bae98e4e56dbaee787747e92a141565f7c61d0ab2c6f98f7396fb4b178258301e2713816e158461af58c14b695901692f91e72b6200' + end end klass.new end