diff --git a/web/app/assets/javascripts/react-components/actions/SubscriptionActions.js.coffee b/web/app/assets/javascripts/react-components/actions/SubscriptionActions.js.coffee
new file mode 100644
index 000000000..b06291f16
--- /dev/null
+++ b/web/app/assets/javascripts/react-components/actions/SubscriptionActions.js.coffee
@@ -0,0 +1,8 @@
+context = window
+
+@SubscriptionActions = Reflux.createActions({
+ updateSubscription: {}
+ changeSubscription: {}
+ cancelSubscription: {}
+ updatePayment: {}
+})
diff --git a/web/app/assets/javascripts/react-components/helpers/SessionHelper.js.coffee b/web/app/assets/javascripts/react-components/helpers/SessionHelper.js.coffee
index 8db01b34d..247abb3c3 100644
--- a/web/app/assets/javascripts/react-components/helpers/SessionHelper.js.coffee
+++ b/web/app/assets/javascripts/react-components/helpers/SessionHelper.js.coffee
@@ -2,7 +2,7 @@ context = window
@SessionHelper = class SessionHelper
- constructor: (app, session, participantsEverSeen, isRecording, downloadingJamTrack, preppingVstEnable) ->
+ constructor: (app, session, participantsEverSeen, isRecording, downloadingJamTrack, preppingVstEnable, sessionRules, subscriptionRules) ->
@app = app
@session = session
@participantsEverSeen = participantsEverSeen
@@ -10,6 +10,8 @@ context = window
@downloadingJamTrack = downloadingJamTrack
@preppingVstEnable = preppingVstEnable
@isLesson = @session?.lesson_session?
+ @sessionRules = sessionRules
+ @subscriptionRules = subscriptionRules
if @isLesson
@lessonId = @session.lesson_session.id
diff --git a/web/app/assets/javascripts/react-components/stores/BroadcastStore.js.coffee b/web/app/assets/javascripts/react-components/stores/BroadcastStore.js.coffee
index 1d5968687..6c98178c2 100644
--- a/web/app/assets/javascripts/react-components/stores/BroadcastStore.js.coffee
+++ b/web/app/assets/javascripts/react-components/stores/BroadcastStore.js.coffee
@@ -2,6 +2,7 @@ $ = jQuery
context = window
logger = context.JK.logger
broadcastActions = @BroadcastActions
+SessionActions = @SessionActions
rest = context.JK.Rest()
@@ -17,6 +18,10 @@ BroadcastStore = Reflux.createStore(
currentLessonTimer: null
teacherFault: false
isJamClass: false
+ sessionRules: null
+ subscriptionRules: null
+ subscriptionConcern: null
+ currentSubscriptionTimer: null
init: ->
this.listenTo(context.AppStore, this.onAppInit)
this.listenTo(context.SessionStore, this.onSessionChange)
@@ -29,6 +34,45 @@ BroadcastStore = Reflux.createStore(
@timeManagement()
@changed()
+ subscriptionTick: () ->
+ @subscriptionManagement()
+ @changed()
+
+ openBrowserToPayment: () ->
+ context.JK.popExternalLink("/client#/account/subscription", true)
+
+ openBrowserToPlanComparison: () ->
+ context.JK.popExternalLink("https://jamkazam.freshdesk.com/support/solutions/articles/66000122535-what-are-jamkazam-s-free-vs-premium-features-")
+ return 'noclose'
+
+ subscriptionManagement: () ->
+ @subscriptionConcern.until = @lessonUtils.getTimeRemaining(@subscriptionConcern.main_concern_time)
+ if @subscriptionConcern.until.total < -15000
+ leaveBehavior =
+ location: "/client#/findSession"
+ buttons = []
+ buttons.push({name: 'CLOSE', buttonStyle: 'button-grey'})
+ buttons.push({name: 'COMPARE PLANS', buttonStyle: 'button-grey', click: (() => (@openBrowserToPlanComparison()))})
+ buttons.push({
+ name: 'UPGRADE PLAN',
+ buttonStyle: 'button-orange',
+ click: (() => (@openBrowserToPayment()))
+ })
+
+ if @subscriptionConcern.main_concern_type == "remaining_month_play_time"
+ context.JK.Banner.show({
+ title: "Out of Time For This Month",
+ html: context._.template($('#template-no-remaining-month-play-time').html(), {}, { variable: 'data' }),
+ buttons: buttons});
+ else
+ context.JK.Banner.show({
+ title: "Out of Time For This Session",
+ html: context._.template($('#template-no-remaining-session-play-time').html(), {}, { variable: 'data' }),
+ buttons: buttons});
+
+ SessionActions.leaveSession.trigger(leaveBehavior)
+
+
timeManagement: () ->
lastCheck = $.extend({}, @currentLesson)
lessonSession = @currentLesson
@@ -61,7 +105,7 @@ BroadcastStore = Reflux.createStore(
logger.debug("BroadcastStore: lesson is over")
@currentLesson.completed = true
@currentLesson.success = @analysis.success
- @clearTimer()
+ @clearLessonTimer()
@changed()
else if @analysis.analysis.reason != 'teacher_fault'
logger.debug("BroadcastStore: not teacher fault; clearing lesson info")
@@ -69,21 +113,31 @@ BroadcastStore = Reflux.createStore(
else
logger.debug("BroadcastStore: teacher is at fault")
@teacherFault = true
- @clearTimer()
+ @clearLessonTimer()
@changed()
clearLesson: () ->
if @currentLesson?
@currentLesson = null
- @clearTimer()
+ @clearLessonTimer()
@teacherFault = false
@changed()
- clearTimer: () ->
+ clearSubscription: () ->
+ @subscriptionConcern = null
+ @clearSubscriptionTimer()
+ @changed()
+
+ clearLessonTimer: () ->
if @currentLessonTimer?
clearInterval(@currentLessonTimer)
@currentLessonTimer = null
+ clearSubscriptionTimer: () ->
+ if @currentSubscriptionTimer?
+ clearInterval(@currentSubscriptionTimer)
+ @currentSubscriptionTimer = null
+
onNavChange: (nav) ->
path = nav.screenPath.toLowerCase()
@isJamClass = path.indexOf('jamclass') > -1 || path.indexOf('teacher') > -1
@@ -93,29 +147,59 @@ BroadcastStore = Reflux.createStore(
@session = session
currentSession = session.session
- if currentSession? && currentSession.lesson_session? && session.inSession()
+ if currentSession? && session.inSession()
+ @subscriptionRules = session.subscriptionRules
+ @sessionRules = session.sessionRules
- @currentSession = currentSession
+ if @subscriptionRules
- lessonSession = currentSession.lesson_session
- # so that receivers can check type of info coming at them via one-way events
- lessonSession.isLesson = true
+ if !@subscriptionRules.remaining_month_until? && !@sessionRules.remaining_session_until?
+ console.log("no license issues")
+ @subscriptionConcern = null
+ else
+ @subscriptionConcern = {}
+ if !@subscriptionRules.remaining_month_until?
+ @subscriptionConcern.main_concern_time = @sessionRules.remaining_session_until
+ @subscriptionConcern.main_concern_type = "remaining_session_play_time"
+ else if !@sessionRules.remaining_session_play_time?
+ @subscriptionConcern.main_concern_time = @subscriptionRules.remaining_month_until
+ @subscriptionConcern.main_concern_type = "remaining_month_play_time"
+ else
+ if @sessionRules.remaining_session_play_time < @subscriptionRules.remaining_month_play_time
+ @subscriptionConcern.main_concern_time = @sessionRules.remaining_session_until
+ @subscriptionConcern.main_concern_type = "remaining_session_play_time"
+ else
+ @subscriptionConcern.main_concern_time = @subscriptionRules.remaining_month_until
+ @subscriptionConcern.main_concern_type = "remaining_month_play_time"
- if lessonSession.status == 'completed'
- lessonSession.completed = true
- lessonSession.success = lessonSession.success
- #else
- # rest.getLessonAnalysis({id: lessonSession.id}).done((response) => @lessonAnalysisDone(response)).fail(@app.ajaxError)
+ @subscriptionManagement()
+ #logger.debug("BroadcastStore: session can play until: ", @subscriptionConcern.until, @subscriptionConcern.main_concert_time)
+ if !@currentSubscriptionTimer?
+ @currentSubscriptionTimer= setInterval((() => @subscriptionTick()), 1000)
+ @changed()
- @currentLesson = lessonSession
- @timeManagement()
- logger.debug("BroadcastStore: currentLesson until: ", @currentLesson.until, lessonSession.scheduled_start)
- if !@currentLessonTimer?
- @currentLessonTimer = setInterval((() => @lessonTick()), 1000)
- @changed()
+ if currentSession.lesson_session?
+ @currentSession = currentSession
+ lessonSession = currentSession.lesson_session
+ # so that receivers can check type of info coming at them via one-way events
+ lessonSession.isLesson = true
+
+ if lessonSession.status == 'completed'
+ lessonSession.completed = true
+ lessonSession.success = lessonSession.success
+ #else
+ # rest.getLessonAnalysis({id: lessonSession.id}).done((response) => @lessonAnalysisDone(response)).fail(@app.ajaxError)
+
+ @currentLesson = lessonSession
+ @timeManagement()
+ logger.debug("BroadcastStore: currentLesson until: ", @currentLesson.until, lessonSession.scheduled_start)
+ if !@currentLessonTimer?
+ @currentLessonTimer = setInterval((() => @lessonTick()), 1000)
+ @changed()
else
@clearLesson()
+ @clearSubscription()
onLoad: () ->
logger.debug("loading broadcast notification...")
@@ -136,21 +220,10 @@ BroadcastStore = Reflux.createStore(
@changed()
changed: () ->
- if @currentLesson?
- @currentLesson.isStudent == @currentLesson.student_id == context.JK.currentUserId
- @currentLesson.isTeacher = !@currentLesson.isStudent
- @currentLesson.teacherFault = @teacherFault
- @currentLesson.teacherPresent = @session.findParticipantByUserId(@currentLesson.teacher_id)
- @currentLesson.studentPresent = @session.findParticipantByUserId(@currentLesson.student_id)
- if (@currentLesson.teacherPresent? && @currentLesson.isStudent) || (@currentLesson.studentPresent? && @currentLesson.isTeacher)
- # don't show anything if the other person is there
- this.trigger(null)
- else
- this.trigger(@currentLesson)
- else if @isJamClass
- this.trigger({isJamClass: true})
+ if @subscriptionConcern?
+ this.trigger({subscriptionConcern: @subscriptionConcern})
else
- this.trigger(@broadcast)
+ this.trigger(null)
}
)
diff --git a/web/app/assets/javascripts/react-components/stores/SessionStore.js.coffee b/web/app/assets/javascripts/react-components/stores/SessionStore.js.coffee
index 5c8065d73..11db9980c 100644
--- a/web/app/assets/javascripts/react-components/stores/SessionStore.js.coffee
+++ b/web/app/assets/javascripts/react-components/stores/SessionStore.js.coffee
@@ -21,6 +21,8 @@ ConfigureTracksActions = @ConfigureTracksActions
currentSessionId: null
currentSession: null
currentOrLastSession: null
+ sessionRules: null
+ subscriptionRules: null
startTime: null
currentParticipants: {}
participantsEverSeen: {}
@@ -53,7 +55,7 @@ ConfigureTracksActions = @ConfigureTracksActions
@sessionUtils = context.JK.SessionUtils
@recordingModel = new context.JK.RecordingModel(@app, rest, context.jamClient);
RecordingActions.initModel(@recordingModel)
- @helper = new context.SessionHelper(@app, @currentSession, @participantsEverSeen, @isRecording, @downloadingJamTrack, @enableVstTimeout?)
+ @helper = new context.SessionHelper(@app, @currentSession, @participantsEverSeen, @isRecording, @downloadingJamTrack, @enableVstTimeout?, @sessionRules, @subscriptionRules)
onSessionJoinedByOther: (payload) ->
clientId = payload.client_id
@@ -78,7 +80,7 @@ ConfigureTracksActions = @ConfigureTracksActions
onVideoChanged: (@videoState) ->
issueChange: () ->
- @helper = new context.SessionHelper(@app, @currentSession, @participantsEverSeen, @isRecording, @downloadingJamTrack, @enableVstTimeout?)
+ @helper = new context.SessionHelper(@app, @currentSession, @participantsEverSeen, @isRecording, @downloadingJamTrack, @enableVstTimeout?, @sessionRules, @subscriptionRules)
this.trigger(@helper)
onWindowBackgrounded: () ->
@@ -726,6 +728,13 @@ ConfigureTracksActions = @ConfigureTracksActions
deferred.resolve();
deferred
+ openBrowserToPayment: () ->
+ context.JK.popExternalLink("/client#/account/subscription", true)
+
+ openBrowserToPlanComparison: () ->
+ context.JK.popExternalLink("https://jamkazam.freshdesk.com/support/solutions/articles/66000122535-what-are-jamkazam-s-free-vs-premium-features-")
+ return 'noclose'
+
joinSession: () ->
context.jamClient.SessionRegisterCallback("JK.HandleBridgeCallback2");
context.jamClient.RegisterRecordingCallbacks("JK.HandleRecordingStartResult", "JK.HandleRecordingStopResult", "JK.HandleRecordingStarted", "JK.HandleRecordingStopped", "JK.HandleRecordingAborted");
@@ -816,13 +825,44 @@ ConfigureTracksActions = @ConfigureTracksActions
@app.notifyAlert("No Inputs Configured", $('You will need to reconfigure your audio device.'))
else if response["errors"] && response["errors"]["music_session"] && response["errors"]["music_session"][0] == ["is currently recording"]
-
leaveBehavior =
location: "/client#/findSession"
notify:
title: "Unable to Join Session"
text: "The session is currently recording."
SessionActions.leaveSession.trigger(leaveBehavior)
+ else if response["errors"] && response["errors"]["remaining_session_play_time"]
+ leaveBehavior =
+ location: "/client#/findSession"
+ buttons = []
+ buttons.push({name: 'CLOSE', buttonStyle: 'button-grey'})
+ buttons.push({name: 'COMPARE PLANS', buttonStyle: 'button-grey', click: (() => (@openBrowserToPlanComparison()))})
+ buttons.push({
+ name: 'UPGRADE PLAN',
+ buttonStyle: 'button-orange',
+ click: (() => (@openBrowserToPayment()))
+ })
+ context.JK.Banner.show({
+ title: "Out of Time For This Session",
+ html: context._.template($('#template-no-remaining-session-play-time').html(), {}, { variable: 'data' }),
+ buttons: buttons});
+ SessionActions.leaveSession.trigger(leaveBehavior)
+ else if response["errors"] && response["errors"]["remaining_month_play_time"]
+ leaveBehavior =
+ location: "/client#/findSession"
+ buttons = []
+ buttons.push({name: 'CLOSE', buttonStyle: 'button-grey'})
+ buttons.push({name: 'COMPARE PLANS', buttonStyle: 'button-grey', click: (() => (@openBrowserToPlanComparison()))})
+ buttons.push({
+ name: 'UPGRADE PLAN',
+ buttonStyle: 'button-orange',
+ click: (() => (@openBrowserToPayment()))
+ })
+ context.JK.Banner.show({
+ title: "Out of Time for the Month",
+ html: context._.template($('#template-no-remaining-month-play-time').html(), {}, { variable: 'data' }),
+ buttons: buttons});
+ SessionActions.leaveSession.trigger(leaveBehavior)
else
@app.notifyServerError(xhr, 'Unable to Join Session');
else
@@ -1051,6 +1091,30 @@ ConfigureTracksActions = @ConfigureTracksActions
if sessionData != null
@currentOrLastSession = sessionData
+ if sessionData.session_rules
+ @sessionRules = sessionData.session_rules
+ # TESTING:
+ @sessionRules.remaining_session_play_time = 60 * 30 + 15 # 30 minutes and 15 seconds
+
+ # compute timestamp due time
+ if @sessionRules.remaining_session_play_time?
+ until_time = new Date()
+ until_time = new Date(until_time.getTime() + @sessionRules.remaining_session_play_time * 1000)
+ @sessionRules.remaining_session_until = until_time
+
+
+ if sessionData.subscription_rules
+ @subscriptionRules = sessionData.subscription_rules
+ # TESTING:
+ #@subscriptionRules.remaining_month_play_time = 60 * 30 + 15 # 30 minutes and 15 seconds
+
+ if @subscriptionRules.remaining_month_play_time?
+ until_time = new Date()
+ until_time = new Date(until_time.getTime() + @subscriptionRules.remaining_month_play_time * 1000)
+ #until_time.setSeconds(until_time.getSeconds() + @subscriptionRules.remaining_month_play_time)
+ @subscriptionRules.remaining_month_until = until_time
+
+
@currentSession = sessionData
if context.jamClient.UpdateSessionInfo?
@@ -1078,6 +1142,7 @@ ConfigureTracksActions = @ConfigureTracksActions
# called by anyone wanting to leave the session with a certain behavior
onLeaveSession: (behavior) ->
logger.debug("attempting to leave session", behavior)
+
if behavior.notify
@app.layout.notify(behavior.notify)
@@ -1206,6 +1271,8 @@ ConfigureTracksActions = @ConfigureTracksActions
@joinDeferred = null
@isRecording = false
@currentSessionId = null
+ @sessionRules = null
+ @subscriptionRules = null
@currentParticipants = {}
@previousAllTracks = {userTracks: [], backingTracks: [], metronomeTracks: []}
@openBackingTrack = null
diff --git a/web/app/assets/javascripts/react-components/stores/SubscriptionStore.js.coffee b/web/app/assets/javascripts/react-components/stores/SubscriptionStore.js.coffee
new file mode 100644
index 000000000..a36a92a84
--- /dev/null
+++ b/web/app/assets/javascripts/react-components/stores/SubscriptionStore.js.coffee
@@ -0,0 +1,66 @@
+$ = jQuery
+context = window
+logger = context.JK.logger
+
+@SubscriptionStore = Reflux.createStore(
+ {
+ listenables: @SubscriptionActions
+
+ subscription: null
+
+
+ init: ->
+ this.listenTo(context.AppStore, this.onAppInit)
+
+ onAppInit: (@app) ->
+
+ onUpdateSubscription: (subscription) ->
+
+ rest.getSubscription().done (subscription) =>
+ @subscription = subscription
+ console.log("subscription store update", subscription)
+ @trigger(@subscription)
+ .fail(() =>
+ @app.layout.notify({
+ title: "unable to fetch subscription status",
+ text: "Please contact support@jamkazam.com"
+ })
+ )
+
+ onChangeSubscription: (plan_code) ->
+ rest.changeSubscription({plan_code: plan_code}).done((subscription) =>
+ @subscription = subscription
+ console.log("subscription change update", subscription)
+ @app.layout.notify({
+ title: "Subscription updated!",
+ text: "Thank you for supporting JamKazam!"
+ })
+ @trigger(@subscription)
+ )
+ .fail((jqXHR) =>
+ if jqXHR.status == 422
+ @app.layout.notify({
+ title: "you already have this subscription",
+ text: "No changes were made to your account."
+ })
+ else
+ @app.layout.notify({
+ title: "unable to update subscription status",
+ text: "Please contact support@jamkazam.com. Error:\n #{jqXHR.responseText}"
+ })
+ )
+
+ onCancelSubscription: () ->
+ rest.cancelSubscription().done((result) =>
+ @subscription = {}
+ console.log("cancelled successfully")
+ @trigger(@subscription)
+ )
+ .fail((jqXHR) =>
+ @app.layout.notify({
+ title: "Subscription Cancelled",
+ text: "Thanks for being a supporter!"
+ })
+ )
+ }
+)
\ No newline at end of file
diff --git a/web/app/assets/javascripts/utils.js b/web/app/assets/javascripts/utils.js
index 755a7ce1b..cecd6d0e8 100644
--- a/web/app/assets/javascripts/utils.js
+++ b/web/app/assets/javascripts/utils.js
@@ -1209,7 +1209,7 @@
$links.on('click', popOpenBrowser);
}
- context.JK.popExternalLink = function (href) {
+ context.JK.popExternalLink = function (href, login) {
if (!context.jamClient) {
return;
}
@@ -1220,11 +1220,28 @@
href = window.location.protocol + '//' + window.location.host + href;
}
+ if(login) {
+ var rememberToken = $.cookie("remember_token");
+ if(rememberToken) {
+ href = window.location.protocol + '//' + window.location.host + "/passthrough?redirect-to=" + encodeURIComponent(href) + '&stoken=' + encodeURIComponent(rememberToken)
+ }
+
+ }
context.jamClient.OpenSystemBrowser(href);
}
return false;
}
+ context.JK.popExternalLinkAndLogin = function(href) {
+
+ var rememberToken = $.cookie("remember_token");
+
+ context.JK.popExternalLink("https://jamkazam.freshdesk.com/support/solutions/articles/66000122535-what-are-jamkazam-s-free-vs-premium-features-")
+ if(rememberToken) {
+ "https://"
+ }
+ }
+
context.JK.checkbox = function ($checkbox, dark) {
if (dark){
return $checkbox.iCheck({
diff --git a/web/app/assets/stylesheets/client/react-components/AccountSubscriptionScreen.scss b/web/app/assets/stylesheets/client/react-components/AccountSubscriptionScreen.scss
index 0f949ee02..02b05d07a 100644
--- a/web/app/assets/stylesheets/client/react-components/AccountSubscriptionScreen.scss
+++ b/web/app/assets/stylesheets/client/react-components/AccountSubscriptionScreen.scss
@@ -18,13 +18,29 @@
padding-top: 20px;
}
- #subscription-account-data {
+ #subscription-account-data, #subscription-elements {
display:grid;
- display: grid;
align-items: center;
- justify-content: center;
+ #justify-content: center;
grid-template-columns: 50% 50%;
}
+
+ #subscription-form {
+
+ }
+
+ #change-subscription-form {
+ max-width:35rem;
+ display:grid;
+ align-items: center;
+ #justify-content: center;
+ grid-template-columns: 8rem 8rem 8rem;
+ }
+
+ .payment-block {
+ margin-top:20px;
+ }
+
form {
max-width:25rem;
}
@@ -63,7 +79,7 @@
font-size: 1rem;
font-weight: bold;
box-shadow: none;
- border-radius: 0;
+ #border-radius: 0;
color: black;
-webkit-appearance: none;
-webkit-transition: border-color 0.3s;
@@ -140,4 +156,9 @@
margin-bottom: 15px;
}
+ h3 {
+ font-weight:bold;
+ margin:30px 0 20px;
+ }
+
}
diff --git a/web/app/assets/stylesheets/client/react-components/broadcast.scss b/web/app/assets/stylesheets/client/react-components/broadcast.scss
index ce2cd17b1..c327a17bf 100644
--- a/web/app/assets/stylesheets/client/react-components/broadcast.scss
+++ b/web/app/assets/stylesheets/client/react-components/broadcast.scss
@@ -45,6 +45,19 @@
width:100%;
}
}
+
+ &.subscription {
+ border-width:0;
+ p {
+ text-align:center;
+ color:$ColorTextTypical;
+ margin-bottom:10px;
+ }
+ .message {
+ width:100%;
+ font-size:18px;
+ }
+ }
}
.message {
float:left;
diff --git a/web/app/controllers/api_music_sessions_controller.rb b/web/app/controllers/api_music_sessions_controller.rb
index 37bb21c52..c0e8f0e1a 100644
--- a/web/app/controllers/api_music_sessions_controller.rb
+++ b/web/app/controllers/api_music_sessions_controller.rb
@@ -339,12 +339,29 @@ class ApiMusicSessionsController < ApiController
params[:parent_client_id]
)
+
if @connection.errors.any?
response.status = :unprocessable_entity
respond_with @connection
else
-
@music_session = @connection.music_session
+
+ # used in rabl to render extra data
+ @on_join = true
+ @subscription_rules = current_user.subscription_rules
+ @session_rules = { remaining_session_play_time: @music_session.play_time_remaining(current_user) }
+
+ # check if the user has gone past acceptable play time
+ if !@session_rules[:remaining_session_play_time].nil? && @session_rules[:remaining_session_play_time] <= 0
+ # user has no session time for this session left.
+ render :json => { :errors => {:remaining_session_play_time => ['none remaining']}}, :status => 422
+ return
+ elsif !@subscription_rules[:remaining_month_play_time].nil? && @subscription_rules[:remaining_month_play_time] <= 0
+ # user has no session time this month.
+ render :json => { :errors => {:remaining_month_play_time=> ['none remaining']}}, :status => 422
+ return
+ end
+
respond_with @music_session, responder: ApiResponder, :status => 201, :location => api_session_detail_url(@connection.music_session)
end
diff --git a/web/app/controllers/api_recurly_controller.rb b/web/app/controllers/api_recurly_controller.rb
index e3d31491a..1062e4fba 100644
--- a/web/app/controllers/api_recurly_controller.rb
+++ b/web/app/controllers/api_recurly_controller.rb
@@ -124,7 +124,7 @@ class ApiRecurlyController < ApiController
render json: {message: x.inspect, errors: x.errors}, :status => 404
end
- def create_subscriptions
+ def create_subscription
begin
sale = Sale.purchase_subscription(current_user, params[:recurly_token], params[:plan_code])
subscription = Recurly::Subscription.find(current_user.recurly_subscription_id)
@@ -135,11 +135,10 @@ class ApiRecurlyController < ApiController
end
def get_subscription
- subscription_id = current_user.recurly_subscription_id
- subscription = Recurly::Subscription.find(subscription_id) if subscription_id
+ subscription = @client.find_subscription(current_user)
if subscription
- render :json => subscription
+ render :json => subscription.to_json
else
render :json => {}
end
@@ -148,8 +147,13 @@ class ApiRecurlyController < ApiController
def cancel_subscription
begin
@client.cancel_subscription(current_user.recurly_subscription_id)
- subscription = Recurly::Subscription.find(current_user.recurly_subscription_id)
- render :json => subscription.to_json
+ subscription = @client.find_subscription(current_user)
+
+ if subscription
+ render :json => subscription.to_json
+ else
+ render :json => {}
+ end
rescue RecurlyClientError => x
render json: {:message => x.inspect, errors: x.errors}, :status => 404
end
@@ -157,9 +161,14 @@ class ApiRecurlyController < ApiController
def change_subscription_plan
begin
- @client.change_subscription_plan(current_user.recurly_subscription_id, params[:plan_code])
- subscription = Recurly::Subscription.find(current_user.recurly_subscription_id)
- render :json => subscription.to_json
+ result = @client.change_subscription_plan(current_user, params[:plan_code])
+ if !result
+ render json: {:message => "No change made to plan"}, :status => 422
+ else
+ subscription = Recurly::Subscription.find(current_user.recurly_subscription_id)
+ render :json => subscription.to_json
+ end
+
rescue RecurlyClientError => x
render json: {:message => x.inspect, errors: x.errors}, :status => 404
end
@@ -167,7 +176,7 @@ class ApiRecurlyController < ApiController
def change_subscription_payment
begin
- @client.change_subscription_payment(current_user.recurly_subscription_id, params[:recurly_token], params[:billing_ifo])
+ @client.change_subscription_payment(current_user.recurly_subscription_id, params[:recurly_token], params[:billing_info])
subscription = Recurly::Subscription.find(current_user.recurly_subscription_id)
render :json => subscription.to_json
rescue RecurlyClientError => x
diff --git a/web/app/controllers/api_users_controller.rb b/web/app/controllers/api_users_controller.rb
index d3b2fcc6b..ed9560414 100644
--- a/web/app/controllers/api_users_controller.rb
+++ b/web/app/controllers/api_users_controller.rb
@@ -494,13 +494,13 @@ class ApiUsersController < ApiController
limit = 20 if limit <= 0
offset = params[:offset].to_i
offset = 0 if offset < 0
- @notifications = Notification.where(description: 'TEXT_MESSAGE').where('(source_user_id = (?) AND target_user_id = (?)) OR (source_user_id = (?) AND target_user_id = (?))', @user.id, receiver_id, receiver_id, @user.id).offset(offset).limit(limit).order('created_at DESC')
+ @notifications = Notification.joins(:source_user).where(description: 'TEXT_MESSAGE').where('(source_user_id = (?) AND target_user_id = (?)) OR (source_user_id = (?) AND target_user_id = (?))', @user.id, receiver_id, receiver_id, @user.id).offset(offset).limit(limit).order('created_at DESC')
else
limit = params[:limit].to_i
limit = 20 if limit <= 0
offset = params[:offset].to_i
offset = 0 if offset < 0
- @notifications = @user.notifications.offset(offset).limit(limit)
+ @notifications = @user.notifications.joins(:source_user).offset(offset).limit(limit)
end
respond_with @notifications, responder: ApiResponder, :status => 200
diff --git a/web/app/controllers/sessions_controller.rb b/web/app/controllers/sessions_controller.rb
index 0dbc227e3..252e9f1b4 100644
--- a/web/app/controllers/sessions_controller.rb
+++ b/web/app/controllers/sessions_controller.rb
@@ -326,6 +326,17 @@ class SessionsController < ApplicationController
render :json => {has_google_auth: (!!current_user && !!UserAuthorization.google_auth(current_user).first)}
end
+ def passthrough
+ if params['stoken']
+ # should be a remember_me cookie. log them in and redirect
+ user = User.find_by_remember_token(params['stoken'])
+ if !user.nil?
+ sign_in user
+ end
+ end
+ redirect_after_signin('/')
+ end
+
def redirect_after_signin(default)
redirect_to(params['redirect-to'].blank? ? default : params['redirect-to'])
end
diff --git a/web/app/helpers/music_session_helper.rb b/web/app/helpers/music_session_helper.rb
index 91d9f2b74..c91dd7a15 100644
--- a/web/app/helpers/music_session_helper.rb
+++ b/web/app/helpers/music_session_helper.rb
@@ -93,4 +93,6 @@ module MusicSessionHelper
def timezone_list(options)
select_tag('timezone-list', timezone_options, options)
end
+
+
end
diff --git a/web/app/views/api_music_sessions/show.rabl b/web/app/views/api_music_sessions/show.rabl
index ee1fc8410..b0c5a2544 100644
--- a/web/app/views/api_music_sessions/show.rabl
+++ b/web/app/views/api_music_sessions/show.rabl
@@ -15,6 +15,16 @@ else
attributes :id, :name, :description, :musician_access, :approval_required, :friends_can_join, :fan_access, :fan_chat, :band_id, :user_id, :claimed_recording_initiator_id, :track_changes_counter, :max_score, :backing_track_path, :metronome_active, :jam_track_initiator_id, :jam_track_id, :music_session_id_int
+ if @on_join
+ node :subscription_rules do |session|
+ @subscription_rules
+ end
+
+ node :session_rules do |session|
+ @session_rules
+ end
+ end
+
node :can_join do |session|
session.can_join?(current_user, true)
end
@@ -53,7 +63,7 @@ else
attributes :ip_address, :client_id, :joined_session_at, :audio_latency, :id, :metronome_open, :is_jamblaster, :client_role, :parent_client_id, :client_id_int
node :user do |connection|
- { :id => connection.user.id, :photo_url => connection.user.photo_url, :name => connection.user.name, :is_friend => connection.user.friends?(current_user), :connection_state => connection.aasm_state }
+ { :id => connection.user.id, :photo_url => connection.user.photo_url, :name => connection.user.name, :is_friend => connection.user.friends?(current_user), :connection_state => connection.aasm_state, :subscription => connection.user.subscription_plan_code }
end
child(:tracks => :tracks) {
diff --git a/web/app/views/clients/_account_subscription.html.slim b/web/app/views/clients/_account_subscription.html.slim
index 37a224c81..fe96c3903 100644
--- a/web/app/views/clients/_account_subscription.html.slim
+++ b/web/app/views/clients/_account_subscription.html.slim
@@ -1,5 +1,5 @@
#account-subscription.screen.secondary layout="screen" layout-id="account/subscription"
- .content-head
+ .content-head{style="height:26px"}
.content-icon
= image_tag "content/icon_account.png", :size => "27x20"
h1
diff --git a/web/app/views/clients/_help.html.slim b/web/app/views/clients/_help.html.slim
index 637535498..ce9686384 100644
--- a/web/app/views/clients/_help.html.slim
+++ b/web/app/views/clients/_help.html.slim
@@ -276,6 +276,18 @@ script type="text/template" id="template-help-jamtrack-controls-disabled"
script type="text/template" id="template-help-volume-media-mixers"
| Audio files only expose both master and personal mix controls, so any change here will also affect everyone in the session.
+script type="text/template" id="template-no-remaining-session-play-time"
+ .no-remaining-session-play-time
+ p There is no more time left in this session. You can upgrade your plan.
+
+script type="text/template" id="template-no-remaining-month-play-time"
+ .no-remaining-monthly-play-time
+ p There is no more session time left for this month. You can upgrade your plan.
+
+script type="text/template" id="template-session-too-big-kicked"
+ .session-too-big-kicked
+ p Due to your current plan, you were forced to leave the session because someone else joined the session just now. You can upgrade your plan.
+
script type="text/template" id="template-help-downloaded-jamtrack"
.downloaded-jamtrack
p When a JamTrack is first purchased, a user-specific version of it is created on the server. Once it's ready, it's then downloaded to the client.
diff --git a/web/config/application.rb b/web/config/application.rb
index b8b87255d..d17c1ef02 100644
--- a/web/config/application.rb
+++ b/web/config/application.rb
@@ -482,6 +482,6 @@ if defined?(Bundler)
config.root_redirect_on = true
config.root_redirect_subdomain = ''
config.root_redirect_path = '/'
-
+ config.subscription_codes = [{id: 'jamsubsilver', name: 'Silver', price: 4.99}, {id: 'jamsubgold', name: 'Gold', price:9.99}, {id: 'jamsubplatinum', name: 'Platinum', price:19.99}]
end
end
diff --git a/web/config/initializers/gon.rb b/web/config/initializers/gon.rb
index 4eb36c68d..b60748b9a 100644
--- a/web/config/initializers/gon.rb
+++ b/web/config/initializers/gon.rb
@@ -26,4 +26,5 @@ Gon.global.vst_enabled = Rails.application.config.vst_enabled
Gon.global.chat_opened_by_default = Rails.application.config.chat_opened_by_default
Gon.global.network_test_required = Rails.application.config.network_test_required
Gon.global.musician_count = Rails.application.config.musician_count
+Gon.global.subscription_codes = Rails.application.config.subscription_codes
Gon.global.env = Rails.env
diff --git a/web/config/routes.rb b/web/config/routes.rb
index 610fc1fee..da504ac93 100644
--- a/web/config/routes.rb
+++ b/web/config/routes.rb
@@ -27,6 +27,7 @@ Rails.application.routes.draw do
get '/signin', to: 'sessions#signin'
post '/signin', to: 'sessions#create'
delete '/signout', to: 'sessions#destroy'
+ get '/passthrough', to: 'sessions#passthrough'
match '/redeem_giftcard', to: 'landings#redeem_giftcard', via: :get
match '/account/activate/code_old', to: 'landings#account_activate', via: :get
@@ -399,6 +400,11 @@ Rails.application.routes.draw do
match '/recurly/update_billing_info' => 'api_recurly#update_billing_info', :via => :put
match '/recurly/place_order' => 'api_recurly#place_order', :via => :post
match '/ios/order_placed' => 'api_jam_tracks#ios_order_placed', :via => :post
+ match '/recurly/create_subscription' => 'api_recurly#create_subscription', :via => :post
+ match '/recurly/get_subscription' => 'api_recurly#get_subscription', :via => :get
+ match '/recurly/change_subscription' => 'api_recurly#change_subscription_plan', :via => :post
+ match '/recurly/cancel_subscription' => 'api_recurly#cancel_subscription', :via => :post
+ match '/recurly/change_subscription_payment' => 'api_recurly#change_subscription_payment', :via => :post
# paypal
match '/paypal/checkout/detail' => 'api_pay_pal#checkout_detail', :via => :post
diff --git a/websocket-gateway/lib/jam_websockets/router.rb b/websocket-gateway/lib/jam_websockets/router.rb
index 062050a6d..31cbe51ac 100644
--- a/websocket-gateway/lib/jam_websockets/router.rb
+++ b/websocket-gateway/lib/jam_websockets/router.rb
@@ -445,7 +445,7 @@ module JamWebsockets
# a unique ID for this TCP connection, to aid in debugging
client.channel_id = handshake.query["channel_id"]
- @log.debug "client connected #{client} with channel_id: #{client.channel_id}"
+ @log.debug "client connected #{client} with channel_id: #{client.channel_id} Original-IP: #{handshake.headers["X-Forwarded-For"]}"
# check for '?pb' or '?pb=true' in url query parameters