This commit is contained in:
Seth Call 2015-01-29 14:17:55 -06:00
parent 43b9fd0559
commit 3496aa999f
16 changed files with 481 additions and 118 deletions

View File

@ -24,6 +24,7 @@
}
function beforeShow() {
$dialog.data('result', null)
emptyList();
resetPagination();
showing = true;

View File

@ -13,7 +13,7 @@ context.JK ||= {};
# * packaging
# * downloading
#
# errored state can be entered from @jamTrackRightId
# errored state can be entered from @jamTrack.jam_track_right_id
#
# other state; you augment the error to the user by suppling @errorMessage before transitioning
#
@ -29,12 +29,12 @@ context.JK ||= {};
context.JK.DownloadJamTracks = {}
context.JK.DownloadJamTrack = class DownloadJamTrack
constructor: (@app, jamTrackId, jamTrackRightId) ->
constructor: (@app, jamTrack, size = 'large') ->
@EVENTS = context.JK.EVENTS
@rest = context.JK.Rest()
@logger = context.JK.logger
@jamTrackId = jamTrackId
@jamTrackRightId = jamTrackRightId
@jamTrack = jamTrack
@size = size
@attemptedEnqueue = false
@errorReason = null
@errorMessage = null
@ -46,6 +46,12 @@ context.JK.DownloadJamTrack = class DownloadJamTrack
@startTime = null
@attempts = 0
@tracked = false
@ajaxEnqueueAborted = false
@ajaxGetJamTrackRightAborted = false
throw "no JamTrack specified" unless @jamTrack?
throw "invalid size" if @size != 'large' && @size != 'small'
@path = []
@states = {
no_client: { name: 'no-client', show: @showNoClient, leaf: true },
@ -54,38 +60,46 @@ context.JK.DownloadJamTrack = class DownloadJamTrack
downloading: { name: 'downloading', show: @showDownloading },
keying: { name: 'keying', show: @showKeying, max_time: 10000 },
initial: { name: 'initial', show: @showInitial },
quiet: { name: 'quiet', show: @showQuiet },
errored: { name: 'errored', show: @showError, leaf: true}
}
context.JK.DownloadJamTracks[@jamTrackId] = this
context.JK.DownloadJamTracks[@jamTrack.id] = this
downloadJamTrackTemplate = $('#template-download-jamtrack')
throw "no download jamtrack template" if not downloadJamTrackTemplate.exists()
@root = $(downloadJamTrackTemplate.html())
# after you've created the DownloadJamTrack widget, call synchronize which will begin ensuring that the jamtrack
# is downloaded and ready to open
init: () =>
@active = true
this.reset()
@root.on('remove', this.destroy) # automatically destroy self when removed from DOM
@stateHolder = @root.find('.state')
@root.on('remove', this.destroy) # automatically destroy self when removed from DOM
# populate in template and visual transition functions
for state, data of @states
data.template = $("#template-download-jamtrack-state-#{data.name}")
# start off in quiet state, but don't do it through transition system. The transition system expects a change, not initial state
@state = @states.quiet
this.showState()
# after you've created the DownloadJamTrack widget, call synchronize which will begin ensuring that the jamtrack
# is downloaded and ready to open
init: () =>
@active = true
@root.addClass('active')
this.reset()
# check if we are in a browser or client
if !gon.isNativeClient
this.transition(@states.no_client)
else
@states.initial.show()
this.transition(@states.initial)
# when done with the widget, call destroy; this ensures it's not still active, and tracks final metrics
destroy: () =>
$(this).off()
@active = false
@root.removeClass('active')
this.trackProgress()
# since we are not in a leave node, we need to report a state since this is effectively our end state
this.reset()
@ -95,16 +109,40 @@ context.JK.DownloadJamTrack = class DownloadJamTrack
@attempts = 0
@tracked = false
@startTime = new Date()
@state = @states.initial
# reset attemptedEnqueue to false, to allow one attempt to enqueue
@attemptedEnqueue = false
this.clearDownloadTimer()
this.clearTransitionTimer()
this.abortEnqueue()
this.abortGetJamTrackRight()
for state, data of @states
if data.timer?
clearInterval(data.timer)
data.timer = null
abortEnqueue: () =>
if @ajaxEnqueueAborted
@logger.debug("DownloadJamTrack: aborting ajax enqueue")
# we need to clear out @ajaxEnqueue *before* calling abort(), because the .fail callback fires inline
ajax = @ajaxEnqueueAborted
@ajaxEnqueueAborted = true
ajax.abort()
abortGetJamTrackRight: () =>
if @ajaxGetJamTrackRightAborted
@logger.debug("DownloadJamTrack: aborting ajax GetJamTrackRight")
# we need to clear out @ajaxEnqueue *before* calling abort(), because the .fail callback fires inline
ajax = @ajaxGetJamTrackRightAborted
@ajaxGetJamTrackRightAborted = true
ajax.abort()
showState: () =>
@state.stateStartTime = new Date();
@stateHolder.children().remove()
@stateHolder.append(context._.template(@state.template.html(), @jamTrack, { variable: 'data' }))
@stateHolder.find('.' + @size).removeClass('hidden')
@state.show()
# report a stat now that we've reached the end of this widget's journey
trackProgress: () =>
@ -112,6 +150,9 @@ context.JK.DownloadJamTrack = class DownloadJamTrack
if @tracked
return
if @path.length == 0
return
unless @state.leaf
# we've been asked to report at a non-leaf node, meaning the user must have cancelled
@path.push('user-cancelled')
@ -141,25 +182,35 @@ context.JK.DownloadJamTrack = class DownloadJamTrack
showDownloading: () =>
@logger.debug("showing #{@state.name}")
# while downloading, we don't run the transition timer, because the download API is guaranteed to call success, or failure, eventually
context.jamClient.JamTrackDownload(@jamTrackId, this.makeDownloadSuccessCallback(), this.makeDownloadFailureCallback())
context.jamClient.JamTrackDownload(@jamTrack.id, this.makeDownloadSuccessCallback(), this.makeDownloadFailureCallback())
showKeying: () =>
@logger.debug("showing #{@state.name}")
context.jamClient.JamTrackKeysRequest()
this.waitForState()
showQuiet: () =>
@logger.debug("showing #{@state.name}")
showInitial: () =>
@logger.debug("showing #{@state.name}")
@attempts = @attempts + 1
this.expectTransition()
context.JK.SubscriptionUtils.subscribe('jam_track_right', @jamTrackRightId).on(context.JK.EVENTS.SUBSCRIBE_NOTIFICATION, this.onJamTrackRightEvent)
context.JK.SubscriptionUtils.subscribe('jam_track_right', @jamTrack.jam_track_right_id).on(context.JK.EVENTS.SUBSCRIBE_NOTIFICATION, this.onJamTrackRightEvent)
this.checkState()
showError: () =>
@logger.debug("showing #{@state.name}")
context.JK.SubscriptionUtils.unsubscribe('jam_track_right', @jamTrackRightId)
@stateHolder.find('.msg').text(@errorMessage)
@stateHolder.find('.retry-button').click(this.retry)
context.JK.SubscriptionUtils.unsubscribe('jam_track_right', @jamTrack.jam_track_right_id)
if @size == 'large'
@stateHolder.find('.msg').text(@errorMessage)
@stateHolder.find('.retry-button').click(this.retry)
else
@stateHolder.find('.msg').text(@jamTrack.name + ' (error)')
@stateHolder.find('.errormsg').text(@errorMessage)
@stateHolder.find('.retry-button').on('click', this.retry)
retryMsg = ''
if @attempts > 1
retryMsg = 'Continue retrying or contact support@jamkazam.com'
@ -168,7 +219,7 @@ context.JK.DownloadJamTrack = class DownloadJamTrack
showSynchronized: () =>
@logger.debug("showing #{@state.name}")
context.JK.SubscriptionUtils.unsubscribe('jam_track_right', @jamTrackRightId)
context.JK.SubscriptionUtils.unsubscribe('jam_track_right', @jamTrack.jam_track_right_id)
showNoClient: () =>
@logger.debug("showing #{@state.name}")
@ -256,16 +307,22 @@ context.JK.DownloadJamTrack = class DownloadJamTrack
transition: (newState) =>
unless @active
@logger.error("DownloadJamTrack: ignoring state change because we are not active")
if newState == @state
@logger.debug("DownloadJamTrack: ignoring state change #{@state.name}")
return
@logger.debug("DownloadJamTrack: state change: #{@state.name} => #{newState.name}")
if newState == @state
@logger.debug("DownloadJamTrack: ignoring state change #{@state.name} #{newState}")
return
# make sure there is no timer running on the old state
this.clearTransitionTimer()
this.clearStateTimer()
if @state?
@logger.debug("DownloadJamTrack: state change: #{@state.name} => #{newState.name}")
# make sure there is no timer running on the old state
this.clearTransitionTimer()
this.clearStateTimer()
this.abortEnqueue()
@logger.debug("aborting getJamTrack right on state change")
this.abortGetJamTrackRight()
else
@logger.debug("DownloadJamTrack: initial state: #{newState.name}")
@state = newState
@ -275,18 +332,13 @@ context.JK.DownloadJamTrack = class DownloadJamTrack
if @state.leaf
this.trackProgress()
@state.stateStartTime = new Date();
@stateHolder.children().remove()
@stateHolder.append(@state.template.html())
@state.show()
this.showState()
$(this).triggerHandler(@EVENTS.JAMTRACK_DOWNLOADER_STATE_CHANGED, {state: @state})
checkState: () =>
# check for the success state against the local state of the client... if it's playable, then we should be OK
@trackDetail = context.jamClient.JamTrackGetTrackDetail (@jamTrackId)
@trackDetail = context.jamClient.JamTrackGetTrackDetail (@jamTrack.id)
@logger.debug("DownloadJamTrack: JamTrackGetTrackDetail.key_state: " + @trackDetail.key_state)
@ -299,7 +351,8 @@ context.JK.DownloadJamTrack = class DownloadJamTrack
when 'ready'
this.transition(@states.synchronized)
when 'unknown'
@rest.getJamTrackRight({id: @jamTrackId})
@ajaxGetJamTrackRightAborted = false
@rest.getJamTrackRight({id: @jamTrack.id})
.done(this.processJamTrackRight)
.fail(this.processJamTrackRightFail)
@ -315,10 +368,7 @@ context.JK.DownloadJamTrack = class DownloadJamTrack
else
this.expectTransition()
@attemptedEnqueue = true
@rest.enqueueJamTrack({id: @jamTrackId})
.done(this.processEnqueueJamTrack)
.fail(this.processEnqueueJamTrackFail)
this.attemptToEnqueue()
when 'QUEUED'
# when it's queued, there is nothing to do except wait.
this.transition(@states.packaging)
@ -337,29 +387,45 @@ context.JK.DownloadJamTrack = class DownloadJamTrack
else
this.expectTransition()
@attemptedEnqueue = true
@rest.enqueueJamTrack({id: @jamTrackId})
.done(this.processEnqueueJamTrack)
.fail(this.processEnqueueJamTrackFail)
this.attemptToEnqueue()
else
@logger.error("unknown state: " + signingState)
this.transitionError("unknown-state-#{signingState}", "The server sent an unknown state message: " + signingState)
processJamTrackRightFail: () =>
this.transitionError("status-check-error", "Unable to check with the server on the status of your JamTrack.")
attemptToEnqueue: () =>
@attemptedEnqueue = true
@ajaxEnqueueAborted = false
@rest.enqueueJamTrack({id: @jamTrack.id})
.done(this.processEnqueueJamTrack)
.fail(this.processEnqueueJamTrackFail)
processEnqueueJamTrack: (enqueueResponse) =>
this.expectTransition() # the act of enqueuing should send down events to the client. we wait...
processEnqueueJamTrackFail: () =>
this.transitionError("enqueue-error", "Unable to ask the server to build your JamTrack.")
processJamTrackRight: (myJamTrack) =>
this.processSigningState(myJamTrack.signing_state)
unless @ajaxGetJamTrackRightAborted
this.processSigningState(myJamTrack.signing_state)
else
@logger.debug("DownloadJamTrack: ignoring processJamTrackRight response")
processJamTrackRightFail: () =>
unless @ajaxGetJamTrackRightAborted?
this.transitionError("status-check-error", "Unable to check with the server on the status of your JamTrack.")
else
@logger.debug("DownloadJamTrack: ignoring processJamTrackRightFail response")
processEnqueueJamTrack: (enqueueResponse) =>
unless @ajaxEnqueueAborted
this.expectTransition() # the act of enqueuing should send down events to the client. we wait...
else
@logger.debug("DownloadJamTrack: ignoring processEnqueueJamTrack response")
processEnqueueJamTrackFail: () =>
unless @ajaxEnqueueAborted
this.transitionError("enqueue-error", "Unable to ask the server to build your JamTrack.")
else
@logger.debug("DownloadJamTrack: ignoring processEnqueueJamTrackFail response")
onJamTrackRightEvent: (e, data) =>
@logger.debug("DownloadJamTrack: subscription notification received: type:" + data.type)
this.expectTransition()
this.processSigningState(data.body.signing_state)
@ -372,6 +438,7 @@ context.JK.DownloadJamTrack = class DownloadJamTrack
downloadSuccessCallback: (updateLocation) =>
# is the package loadable yet?
@logger.debug("DownloadJamTrack: download complete - on to keying")
this.transition(@states.keying)
downloadFailureCallback: (errorMsg) =>
@ -380,13 +447,13 @@ context.JK.DownloadJamTrack = class DownloadJamTrack
# makes a function name for the backend
makeDownloadProgressCallback: () =>
"JK.DownloadJamTracks['#{@jamTrackId}'].downloadProgressCallback"
"JK.DownloadJamTracks['#{@jamTrack.id}'].downloadProgressCallback"
# makes a function name for the backend
makeDownloadSuccessCallback: () =>
"JK.DownloadJamTracks['#{@jamTrackId}'].downloadSuccessCallback"
"JK.DownloadJamTracks['#{@jamTrack.id}'].downloadSuccessCallback"
# makes a function name for the backend
makeDownloadFailureCallback: () =>
"JK.DownloadJamTracks['#{@jamTrackId}'].downloadFailureCallback"
"JK.DownloadJamTracks['#{@jamTrack.id}'].downloadFailureCallback"

View File

@ -685,10 +685,10 @@
return true;
}
function JamTrackGetTrackDetail() {
return {key_state: 'ready'}
return {key_state: 'unknown'}
}
function JamTrackKeysRequest() {}
function JamTrackDownload() {}
// Method which sets volume
function UpdateMixer(mixerId) {}
@ -988,6 +988,7 @@
this.JamTrackIsPlayable = JamTrackIsPlayable;
this.JamTrackGetTrackDetail = JamTrackGetTrackDetail;
this.JamTrackKeysRequest = JamTrackKeysRequest;
this.JamTrackDownload = JamTrackDownload;
// Scoring Knobs
this.GetScoreWorkTimingInterval = GetScoreWorkTimingInterval;

View File

@ -4,9 +4,12 @@
context.JK = context.JK || {};
context.JK.OrderScreen = function(app) {
var EVENTS = context.JK.EVENTS;
var logger = context.JK.logger;
var $screen = null;
var $templateOrderContent = null;
var $templatePurchasedJamTrack = null;
var $navigation = null;
var $billingInfo = null;
var $shippingInfo = null;
@ -16,15 +19,23 @@
var $paymentInfoPanel = null;
var $orderPanel = null;
var $thanksPanel = null;
var $jamTrackInBrowser = null;
var $purchasedJamTrack = null;
var $purchasedJamTrackHeader = null;
var $purchasedJamTracks = null;
var $orderContent = null;
var userDetail = null;
var step = null;
var billing_info = null;
var shipping_info = null;
var shipping_as_billing = null;
var downloadJamTracks = [];
var purchasedJamTracks = null;
var purchasedJamTrackIterator = 0;
function beforeShow() {
beforeShowPaymentInfo();
beforeShowPaymentInfo();
resetJamTrackDownloadInfo();
}
function beforeShowPaymentInfo() {
@ -33,6 +44,12 @@
renderAccountInfo();
}
function resetJamTrackDownloadInfo() {
$purchasedJamTrack.addClass('hidden');
$purchasedJamTracks.children().remove()
$jamTrackInBrowser.hide('hidden');
}
function renderAccountInfo() {
rest.getUserDetail()
.done(populateAccountInfo)
@ -81,6 +98,21 @@
}
function afterShow(data) {
// XXX : style-test code
// moveToThanks({jam_tracks: [{id: 14, jam_track_right_id: 11, name: 'Back in Black'}, {id: 15, jam_track_right_id: 11, name: 'In Bloom'}, {id: 16, jam_track_right_id: 11, name: 'Love Bird Supreme'}]});
}
function beforeHide() {
if(downloadJamTracks) {
context._.each(downloadJamTracks, function(downloadJamTrack) {
downloadJamTrack.destroy();
downloadJamTrack.root.remove();
})
downloadJamTracks = [];
}
purchasedJamTracks = null;
purchasedJamTrackIterator = 0;
}
function next(e) {
@ -412,7 +444,7 @@
data.shipping_as_billing = shipping_as_billing
var orderContentHtml = $(
context._.template(
$('#template-order-content').html(),
$templateOrderContent.html(),
data,
{variable: 'data'}
)
@ -430,13 +462,86 @@
beforeShowOrder();
}
function moveToThanks() {
function moveToThanks(purchaseResponse) {
$("#order_error").addClass("hidden")
$paymentInfoPanel.addClass("hidden")
$orderPanel.addClass("hidden")
$thanksPanel.removeClass("hidden")
rest.clearShoppingCart()
beforeShowOrder()
handleJamTracksPurchased(purchaseResponse.jam_tracks)
}
function handleJamTracksPurchased(jamTracks) {
// were any JamTracks purchased?
var jamTracksPurchased = jamTracks && jamTracks.length > 0;
if(jamTracksPurchased) {
if(gon.isNativeClient) {
startDownloadJamTracks(jamTracks)
}
else {
$jamTrackInBrowser.removeClass('hidden');
}
}
}
function startDownloadJamTracks(jamTracks) {
// there can be multiple purchased JamTracks, so we cycle through them
purchasedJamTracks = jamTracks;
// populate list of jamtracks purchased, that we will iterate through graphically
context._.each(jamTracks, function(jamTrack) {
var downloadJamTrack = new context.JK.DownloadJamTrack(app, jamTrack, 'small');
var $purchasedJamTrack = $(context._.template(
$templatePurchasedJamTrack.html(),
jamTrack,
{variable: 'data'}
));
$purchasedJamTracks.append($purchasedJamTrack)
// show it on the page
$purchasedJamTrack.append(downloadJamTrack.root)
downloadJamTracks.push(downloadJamTrack)
})
iteratePurchasedJamTracks();
}
function iteratePurchasedJamTracks() {
if(purchasedJamTrackIterator < purchasedJamTracks.length ) {
var downloadJamTrack = downloadJamTracks[purchasedJamTrackIterator++];
// make sure the 'purchasing JamTrack' section can be seen
$purchasedJamTrack.removeClass('hidden');
// the widget indicates when it gets to any transition; we can hide it once it reaches completion
$(downloadJamTrack).on(EVENTS.JAMTRACK_DOWNLOADER_STATE_CHANGED, function(e, data) {
if(data.state == downloadJamTrack.states.synchronized) {
logger.debug("jamtrack " + downloadJamTrack.jamTrack.name + " synchronized;")
//downloadJamTrack.root.remove();
downloadJamTrack.destroy();
// go to the next JamTrack
iteratePurchasedJamTracks()
}
})
logger.debug("jamtrack " + downloadJamTrack.jamTrack.name + " downloader initializing")
// kick off the download JamTrack process
downloadJamTrack.init()
// XXX style-test code
// downloadJamTrack.transitionError("package-error", "The server failed to create your package.")
}
else {
logger.debug("done iterating over purchased JamTracks")
$purchasedJamTrackHeader.text('All purchased JamTracks have been downloaded successfully! You can now play them in a session.')
}
}
function moveToPaymentInfo(e) {
@ -506,21 +611,28 @@
function initialize() {
var screenBindings = {
'beforeShow': beforeShow,
'afterShow': afterShow
'afterShow': afterShow,
'beforeHide' : beforeHide
};
app.bindScreen('order', screenBindings);
$screen = $("#orderScreen");
$paymentInfoPanel = $screen.find(".checkout-payment-info");
$orderPanel = $screen.find(".order-panel");
$thanksPanel = $screen.find(".thanks-panel");
$navigation = $screen.find(".checkout-navigation-bar");
$billingInfo = $paymentInfoPanel.find(".billing-address");
$shippingInfo = $paymentInfoPanel.find(".shipping-address");
$paymentMethod = $paymentInfoPanel.find(".payment-method");
$shippingAddress = $paymentInfoPanel.find(".shipping-address-detail");
$shippingAsBilling = $paymentInfoPanel.find("#shipping-as-billing");
$orderContent = $orderPanel.find(".order-content");
$screen = $("#orderScreen");
$templateOrderContent = $("#template-order-content");
$templatePurchasedJamTrack = $('#template-purchased-jam-track');
$paymentInfoPanel = $screen.find(".checkout-payment-info");
$orderPanel = $screen.find(".order-panel");
$thanksPanel = $screen.find(".thanks-panel");
$jamTrackInBrowser = $screen.find(".thanks-detail.jam-tracks-in-browser");
$purchasedJamTrack = $thanksPanel.find(".thanks-detail.purchased-jam-track");
$purchasedJamTrackHeader = $purchasedJamTrack.find(".purchased-jam-track-header");
$purchasedJamTracks = $purchasedJamTrack.find(".purchased-list")
$navigation = $screen.find(".checkout-navigation-bar");
$billingInfo = $paymentInfoPanel.find(".billing-address");
$shippingInfo = $paymentInfoPanel.find(".shipping-address");
$paymentMethod = $paymentInfoPanel.find(".payment-method");
$shippingAddress = $paymentInfoPanel.find(".shipping-address-detail");
$shippingAsBilling = $paymentInfoPanel.find("#shipping-as-billing");
$orderContent = $orderPanel.find(".order-content");
if($screen.length == 0) throw "$screen must be specified";
if($navigation.length == 0) throw "$navigation must be specified";

View File

@ -503,6 +503,15 @@
}
}
function resetOtherAudioContent() {
if ($('.session-recordings .track').length === 0 && $('.session-recordings .download-jamtrack').length === 0) {
$('.session-recordings .when-empty').show();
$('.session-recording-name-wrapper').hide();
$('.session-recordings .recording-controls').hide();
$('.session-recordings .session-recording-name').text('(No audio loaded)')
}
}
function renderSession() {
$myTracksContainer.empty();
$('.session-track').remove(); // Remove previous tracks
@ -518,11 +527,7 @@
if ($('.session-livetracks .track').length === 0) {
$('.session-livetracks .when-empty').show();
}
if ($('.session-recordings .track').length === 0 && $('.session-recordings .download-jamtrack').length === 0) {
$('.session-recordings .when-empty').show();
$('.session-recording-name-wrapper').hide();
$('.session-recordings .recording-controls').hide();
}
resetOtherAudioContent();
}
function _initDialogs() {
@ -1933,8 +1938,6 @@
var jamTrack = data.result.jamTrack;
logger.debug("JamTrack INFO", jamTrack.id, jamTrack.jam_track_right_id)
// hide 'other audio' placeholder
otherAudioFilled();
@ -1946,7 +1949,7 @@
downloadJamTrack = null
}
downloadJamTrack = new context.JK.DownloadJamTrack(app, jamTrack.id, jamTrack.jam_track_right_id);
downloadJamTrack = new context.JK.DownloadJamTrack(app, jamTrack.id, 'large');
// 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) {
@ -1957,7 +1960,10 @@
downloadJamTrack.destroy();
downloadJamTrack = null;
// XXX: test with this removed; it should be unnecessary
context.jamClient.JamTrackStopPlay();
// JamTrackPlay means 'load'
var result = context.jamClient.JamTrackPlay(jamTrack.id);
if(!result) {
@ -1972,7 +1978,7 @@
// show it on the page
$otherAudioContainer.append(downloadJamTrack.root)
// kick off the download jamtrack process
// kick off the download JamTrack process
downloadJamTrack.init()
}
else {
@ -2005,15 +2011,30 @@
if(sessionModel.recordedTracks()) {
closeRecording();
}
else if(sessionModel.jamTracks()) {
else if(sessionModel.jamTracks() || downloadJamTrack) {
closeJamTrack();
}
else {
logger.error("don't know how to close open media (backing track?)");
logger.error("don't know how to close open media (backing track maybe?)");
}
return false;
}
function closeJamTrack() {
logger.debug("closing recording");
if(downloadJamTrack) {
logger.debug("closing DownloadJamTrack widget")
downloadJamTrack.root.remove();
downloadJamTrack.destroy();
downloadJamTrack = null;
// this is necessary because a syncing widget means no jamtracks are loaded;
// so removing the widget will not cause a backend media change event (and so renderSession will not be called, ultimately)
resetOtherAudioContent();
}
rest.closeJamTrack({id: sessionModel.id()})
.done(function() {
sessionModel.refreshCurrentSession();
@ -2032,6 +2053,8 @@
}
function closeRecording() {
logger.debug("closing recording");
rest.stopPlayClaimedRecording({id: sessionModel.id(), claimed_recording_id: sessionModel.getCurrentSession().claimed_recording.id})
.done(function() {
sessionModel.refreshCurrentSession();

View File

@ -168,6 +168,40 @@
.thanks-panel {
padding: 30px;
span.notice {
font-style:italic;
font-size:12px;
}
br.purchase-downloads {
clear:both;
margin-bottom:20px;
}
.thanks-detail.purchased-jam-track {
margin-top:20px;
.purchased-jam-track-header {
font-size: 15px;
margin-bottom:10px;
}
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
}
}
}
.order-panel {

View File

@ -2,10 +2,8 @@
.download-jamtrack {
display:inline-block;
width:100%;
.state {
text-align:center;
}
.retry-button {
margin-top:20px;
}
@ -23,4 +21,57 @@
text-align:center;
}
.small {
.state {
text-align:left;
}
font-size:inherit;
.msg {
line-height: 32px;
height: 32px;
display: inline-block;
vertical-align: middle;
}
.spinner-small {
display:inline-block;
vertical-align:middle;
}
}
.large {
.state {
text-align:center;
}
}
&.active {
.small {
margin-bottom:5px;
.msg {
font-weight:bold;
color:white;
display:inline;
}
.errormsg {
display:block;
font-size:14px;
}
.retry {
display:block;
margin:3px 0 0 0;
font-size:14px;
}
.retry-button {
float:right;
margin:5px 0 5px 20px;
}
.msg-holder {
display:block;
}
}
}
}

View File

@ -57,20 +57,36 @@ class ApiRecurlyController < ApiController
def place_order
error=nil
puts "PLACING ORDER #{params.inspect}"
response = {jam_tracks:[]}
# 1st confirm that all specified JamTracks exist
jam_tracks = []
params[:jam_tracks].each do |jam_track_id|
jam_track = JamTrack.where("id=?", jam_track_id).first
if jam_track
@client.place_order(current_user, jam_track)
jam_tracks << jam_track
else
error="JamTrack not found for '#{jam_track_id}'"
break
end
end
# then buy each
unless error
jam_tracks.each do |jam_track|
jam_track_right = @client.place_order(current_user, jam_track)
# build up the response object with JamTracks that were purchased.
# if this gets more complicated, we should switch to RABL
response[:jam_tracks] << {name: jam_track.name, id: jam_track.id, jam_track_right_id: jam_track_right.id}
end
end
if error
render json: { errors: {message:error}}, :status => 404
else
render :json=>{}, :status=>200
render :json=>response, :status=>200
end
rescue RecurlyClientError => x
render json: { message: x.inspect, errors: x.errors}, :status => 404

View File

@ -47,6 +47,7 @@ class SpikesController < ApplicationController
gon.jamTrackId = jamTrack.id
gon.jamTrackRightId = jamTrackRight.id
gon.size = params[:size] ? params[:size] : 'large'
gon.switchState = params[:state]
render :layout => 'web'

View File

@ -4,38 +4,83 @@ script type="text/template" id='template-download-jamtrack'
script type="text/template" id="template-download-jamtrack-state-no-client"
.state-no-client
| To play your JamTrack, launch the JamKazam application and open it while in a session.
.large.hidden
.msg
| To play your JamTrack, launch the JamKazam application and open the JamTrack while in a session.
.small.hidden
.msg
| {{data.name}} (launch client)
script type="text/template" id="template-download-jamtrack-state-synchronized"
.state-synchronized
| Your JamTrack is on your system and ready to play.
.large.hidden
.msg
| Your JamTrack is on your system and ready to play.
.small.hidden
.msg
| {{data.name}} (done)
script type="text/template" id="template-download-jamtrack-state-packaging"
.state-packaging
.msg
| Your JamTrack is currently being created on the JamKazam server.
.spinner-large
.large.hidden
.msg
| Your JamTrack is currently being created on the JamKazam server.
.spinner-large
.small.hidden
.msg
| {{data.name}} (packaging)
.spinner-small
script type="text/template" id="template-download-jamtrack-state-downloading"
.state-downloading
.msg
| Your JamTrack is currently being downloaded.
.spinner-large
.large.hidden
.msg
| Your JamTrack is currently being downloaded.
.spinner-large
.small.hidden
.msg
| {{data.name}} (downloading)
.spinner-small
script type="text/template" id="template-download-jamtrack-state-keying"
.state-keying
.msg
| Your JamTrack is being authenticated.
.spinner-large
.large.hidden
.msg
| Your JamTrack is being authenticated.
.spinner-large
.small.hidden
.msg
| {{data.name}} (keying)
.spinner-small
script type="text/template" id="template-download-jamtrack-state-initial"
.state-initial
.msg
| Initializing JamTrack...
.spinner-large
.large.hidden
.msg
| Initializing JamTrack...
.spinner-large
.small.hidden
.msg
| {{data.name}} (initializing)
.spinner-small
script type="text/template" id="template-download-jamtrack-state-quiet"
.state-quiet
.large.hidden
.msg
.small.hidden
.msg
| {{data.name}} (pending)
script type="text/template" id="template-download-jamtrack-state-errored"
.state-errored
.msg
.retry
a.button-orange.retry-button RETRY
.large.hidden
.msg
.retry
a.button-orange.retry-button RETRY
.small.hidden
.msg-holder
.msg
a.button-orange.retry-button RETRY
.errormsg
.retry

View File

@ -178,8 +178,15 @@ div layout="screen" layout-id="order" id="orderScreen" class="screen secondary"
br
.thanks-detail We'll send you an email confirming your order shortly.
br
.thanks-detail If you purchased any JamTracks, the next time you run the JamKazam application, your JamTracks will automatically be downloaded to the app, and you will receive a notification when the download is complete.
.thanks-detail.jam-tracks-in-browser.hidden
| To play your purchased JamTrack, launch the JamKazam application and open the JamTrack while in a session.
.thanks-detail.purchased-jam-track.hidden
h2.purchased-jam-track-header Downloading Your Purchased JamTracks
span Each JamTrack will be downloaded sequentially.
br
span.notice Note that you do not have to wait for this to complete in order to use your JamTrack later.
br.clear
ul.purchased-list
@ -276,4 +283,7 @@ script type='text/template' id='template-order-content'
span and
'
a href="http://www.jamkazam.com/corp/returns" returns policy
span .
span .
script type='text/template' id='template-purchased-jam-track'
li data-jam-track-id="{{data.jam_track_id}}"

View File

@ -105,7 +105,7 @@
<div class="session-recordings">
<h2>other audio</h2>
<div class="session-recording-name-wrapper">
<div class="session-recording-name left">(No recording loaded)</div>
<div class="session-recording-name left">(No audio loaded)</div>
<div class="session-add right">
<a id='close-playback-recording' href="#"><%= image_tag "content/icon_close.png", {:width => 18, :height => 20, :align => "texttop"} %>&nbsp;&nbsp;Close</a>
</div>

View File

@ -31,7 +31,7 @@
a href='/client#/jamtrack' rel="external"
| Shop for JamTracks
.right
a href="#" class="button-grey" layout-action="close"
a href="#" class="button-grey" layout-action="cancel"
| CANCEL

View File

@ -28,7 +28,7 @@ javascript:
initialized = true
setTimeout(function() {
window.downloadJamTrack = new JK.DownloadJamTrack(data.app, gon.jamTrackId, gon.jamTrackRightId)
window.downloadJamTrack = new JK.DownloadJamTrack(data.app, {id: gon.jamTrackId, jam_track_right_id: gon.jamTrackRightId, name: 'Back in Black'}, gon.size)
downloadJamTrack.init()
$('#widget').append(window.downloadJamTrack.root)

View File

@ -69,6 +69,7 @@ module JamRuby
end
def place_order(current_user, jam_track)
jam_track_right = nil
account = get_account(current_user)
if (account.present?)
begin
@ -94,7 +95,7 @@ module JamRuby
else
raise RecurlyClientError, "Could not find account to place order."
end
account
jam_track_right
end
def find_or_create_account(current_user, billing_info=nil)

View File

@ -5,6 +5,7 @@ describe "DownloadJamTrack", ->
window.jamClient = sinon.stub()
this.app = sinon.stub()
this.jamTrackId = '1'
this.jamTrack = {id: this.jamTrackId, jam_track_right_id: '1', name: 'Back in Black'}
window.gon = {}
window.JK.JamServer = {}
window.stats = {}
@ -19,7 +20,7 @@ describe "DownloadJamTrack", ->
beforeEach ->
window.gon.isNativeClient = false
@showNoClientSpy = sinon.spy(JK.DownloadJamTrack.prototype, 'showNoClient')
this.downloadJamTrack = new JK.DownloadJamTrack(@app, @jamTrackId, '1')
this.downloadJamTrack = new JK.DownloadJamTrack(@app, @jamTrack)
$('body').append(this.downloadJamTrack.root)
afterEach ->
@ -44,7 +45,7 @@ describe "DownloadJamTrack", ->
describe "already synchronized", ->
beforeEach ->
@showSynchronizedSpy = sinon.spy(JK.DownloadJamTrack.prototype, 'showSynchronized')
@downloadJamTrack = new JK.DownloadJamTrack(@app, @jamTrackId, '1')
@downloadJamTrack = new JK.DownloadJamTrack(@app, @jamTrack)
$('body').append(@downloadJamTrack.root)
afterEach ->
@ -71,7 +72,7 @@ describe "DownloadJamTrack", ->
@showSynchronizedSpy = sinon.spy(JK.DownloadJamTrack.prototype, 'showSynchronized')
@showErrorSpy = sinon.spy(JK.DownloadJamTrack.prototype, 'showError')
@showKeyingSpy = sinon.spy(JK.DownloadJamTrack.prototype, 'showKeying')
@downloadJamTrack = new JK.DownloadJamTrack(@app, @jamTrackId, '1')
@downloadJamTrack = new JK.DownloadJamTrack(@app, @jamTrack)
@downloadJamTrack.states.keying.max_time = -1 # hurry up the test, instead of waiting 10 seconds
$('body').append(@downloadJamTrack.root)
@ -145,7 +146,7 @@ describe "DownloadJamTrack", ->
@showKeyingSpy = sinon.spy(JK.DownloadJamTrack.prototype, 'showKeying')
@showDownloadingSpy = sinon.spy(JK.DownloadJamTrack.prototype, 'showDownloading')
@showPackagingSpy = sinon.spy(JK.DownloadJamTrack.prototype, 'showPackaging')
@downloadJamTrack = new JK.DownloadJamTrack(@app, @jamTrackId, '1')
@downloadJamTrack = new JK.DownloadJamTrack(@app, @jamTrack)
@downloadJamTrack.states.keying.max_time = -1 # hurry up the test, instead of waiting 10 seconds
$('body').append(@downloadJamTrack.root)