* wip
This commit is contained in:
parent
43b9fd0559
commit
3496aa999f
|
|
@ -24,6 +24,7 @@
|
|||
}
|
||||
|
||||
function beforeShow() {
|
||||
$dialog.data('result', null)
|
||||
emptyList();
|
||||
resetPagination();
|
||||
showing = true;
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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}}"
|
||||
|
|
@ -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"} %> Close</a>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue