This commit is contained in:
Seth Call 2021-01-10 23:44:49 -06:00
parent 3e953b1b4c
commit ee1dc427ce
16 changed files with 169 additions and 37 deletions

View File

@ -85,7 +85,7 @@ gem 'zip-codes'
gem 'email_validator'
gem 'best_in_place' #, github: 'bernat/best_in_place'
gem 'auto_strip_attributes', '2.6.0'
gem 'elasticsearch'
#group :libv8 do
# gem 'libv8', "~> 4.5.95"

View File

@ -153,6 +153,14 @@ GEM
domain_name (0.5.20170404)
unf (>= 0.0.5, < 1.0.0)
dotenv (2.2.1)
elasticsearch (7.5.0)
elasticsearch-api (= 7.5.0)
elasticsearch-transport (= 7.5.0)
elasticsearch-api (7.5.0)
multi_json
elasticsearch-transport (7.5.0)
faraday (>= 0.14, < 1)
multi_json
email_validator (1.6.0)
activemodel
erubis (2.7.0)
@ -631,6 +639,7 @@ DEPENDENCIES
country-select
database_cleaner
devise
elasticsearch
email_validator
eventmachine (= 1.2.3)
execjs (= 1.4.0)

View File

@ -225,7 +225,7 @@ ActiveAdmin.register JamRuby::User, :as => 'Users' do
'sets secret override to give user a free plan (link goes to another page)'
end
div do
link_to("Give No-Payment Plan", edit_admin_subscription_path(user.id))
link_to("Give No-Payment Plan", edit_admin_user_override_path(user.id))
end
end
@ -234,16 +234,25 @@ ActiveAdmin.register JamRuby::User, :as => 'Users' do
'Change Plan Actions'
end
h4 do
'Change desired plan xactly as if the user did it on /client#/accounts/subscription'
'Change desired plan exactly as if the user did it on /client#/accounts/subscription'
end
div do
link_to("change plan to silver", change_to_plan_admin_user_path(user.id, plan_code: 'jamsubsilver'), :data => {:confirm => 'Are you sure?'})
link_to("change plan to silver monthly", change_to_plan_admin_user_path(user.id, plan_code: 'jamsubsilver'), :data => {:confirm => 'Are you sure?'})
end
div do
link_to("change plan to gold", change_to_plan_admin_user_path(user.id, plan_code: 'jamsubgold'), :data => {:confirm => 'Are you sure?'})
link_to("change plan to gold monthly", change_to_plan_admin_user_path(user.id, plan_code: 'jamsubgold'), :data => {:confirm => 'Are you sure?'})
end
div do
link_to("change plan to platinum", change_to_plan_admin_user_path(user.id, plan_code: 'jamsubplatinum'), :data => {:confirm => 'Are you sure?'})
link_to("change plan to platinum monthly", change_to_plan_admin_user_path(user.id, plan_code: 'jamsubplatinum'), :data => {:confirm => 'Are you sure?'})
end
div do
link_to("change plan to silver yearly", change_to_plan_admin_user_path(user.id, plan_code: 'jamsubsilveryearly'), :data => {:confirm => 'Are you sure?'})
end
div do
link_to("change plan to gold yearly", change_to_plan_admin_user_path(user.id, plan_code: 'jamsubgoldyearly'), :data => {:confirm => 'Are you sure?'})
end
div do
link_to("change plan to platinum yearly", change_to_plan_admin_user_path(user.id, plan_code: 'jamsubplatinumyearly'), :data => {:confirm => 'Are you sure?'})
end
div do
link_to("change plan to free", change_to_plan_admin_user_path(user.id, plan_code: ''), :data => {:confirm => 'Are you sure?'})
@ -416,23 +425,17 @@ ActiveAdmin.register JamRuby::User, :as => 'Users' do
links << link_to("Edit", edit_resource_path(user), :class => "member_link edit_link")
links
end
column "ID" do |user|
link_to(truncate(user.id, {:length => 12}),
resource_path(user),
{:title => user.id})
end
column "Email" do |user|
link_to user.email, resource_path(user)
end
column :admin
column :subscription_plan_code
column :desired_plan_code
column :created_at
column :musician do |user|
user.musician? ? true : false
end
column :city
column :state
column :first_name
column :last_name
column :city
column :state
end
controller do

View File

@ -1,4 +1,4 @@
ActiveAdmin.register User, :as => 'Subscription' do
ActiveAdmin.register User, :as => 'User_Override' do
menu :label => 'Subscription', :parent => 'Users'

View File

@ -1045,7 +1045,7 @@ module JamRuby
user.reset_password_token = SecureRandom.urlsafe_base64
user.reset_password_token_created = Time.now
user.save
user.save(validate:false)
reset_url = "#{base_uri}/reset_password_token?token=#{user.reset_password_token}&email=#{CGI.escape(email)}"
UserMailer.password_reset(user, reset_url).deliver_now

View File

@ -119,6 +119,7 @@ gem 'zip-codes'
gem 'email_validator'
#gem "browserify-rails", "~> 0.7"
gem 'elasticsearch'
if ENV['FASTER_PATH'] == '1'
# https://github.com/danielpclark/faster_path

View File

@ -152,6 +152,14 @@ GEM
domain_name (0.5.20170404)
unf (>= 0.0.5, < 1.0.0)
dotenv (2.2.1)
elasticsearch (7.4.0)
elasticsearch-api (= 7.4.0)
elasticsearch-transport (= 7.4.0)
elasticsearch-api (7.4.0)
multi_json
elasticsearch-transport (7.4.0)
faraday
multi_json
em-websocket (0.5.1)
eventmachine (>= 0.12.9)
http_parser.rb (~> 0.6.0)
@ -767,6 +775,7 @@ DEPENDENCIES
coffee-script-source (= 1.12.2)
database_cleaner (= 1.3.0)
devise (= 3.3.0)
elasticsearch
em-websocket (>= 0.4.0)
email_validator
eventmachine (= 1.2.3)

View File

@ -32,8 +32,20 @@ AppStore = context.AppStore
return subscriptionCode.price
return "Unknown plan code=#{plan_code}"
getDisplayCycle:(plan_code) ->
if plan_code == ''
plan_code = null
for subscriptionCode in gon.global.subscription_codes
if plan_code == subscriptionCode.id
if subscriptionCode.cycle == "year"
return "annual"
else
return subscriptionCode.cycle + "ly"
return "Unknown plan code=#{plan_code}"
onPlanChanged: (e) ->
val = e.target.value
@originalPlan = this.currentPlan()
@setState({selectedPlan: val})
currentPlan: () ->
@ -48,13 +60,16 @@ AppStore = context.AppStore
onSubmit: (event) ->
if event
event.preventDefault()
@performSubmit()
@prePerformSubmit()
onChangeSubmit: (form) ->
if @state.updating
return
@performSubmit()
@prePerformSubmit()
cancelChangePlan:() ->
console.log("cancel change plan", @originalPlan)
@setState({selectedPlan: @originalPlan })
# user selects button on main page
onUpdatePaymentMethod: () ->
if gon.isNativeClient
@ -68,10 +83,40 @@ AppStore = context.AppStore
else
window.location.href = "/client#/account/paymentHistory"
performSubmit: () ->
prePerformSubmit:() ->
if !@state.selectedPlan?
return
message = null
if this.props.subscription.subscription
if this.state.selectedPlan == null || this.state.selectedPlan == ''
message = "<p>You have chosen to go back down to the FREE PLAN. Your subscription will be canceled, and you will keep your plan until the end of the current billing cycle.</p>"
else
message = "<p>You have selected the #{this.getDisplayNameTier(this.state.selectedPlan).toUpperCase()} #{this.getDisplayCycle(this.state.selectedPlan).toUpperCase()} PLAN and will be charged US$#{this.getDisplayNamePrice(this.state.selectedPlan)} on the start of next billing cycle.</p>"
else
if this.state.selectedPlan == null || this.state.selectedPlan == ''
@performSubmit()
return
else
message = "<p>You have selected the #{this.getDisplayNameTier(this.state.selectedPlan).toUpperCase()} #{this.getDisplayCycle(this.state.selectedPlan).toUpperCase()} PLAN and will be charged US$#{this.getDisplayNamePrice(this.state.selectedPlan)} .</p>"
buttons = []
buttons.push({
name: 'CANCEL',
buttonStyle: 'button-grey',
click: (() => (@cancelChangePlan()))
})
buttons.push({
name: 'CONFIRM',
buttonStyle: 'button-orange',
click: (() => (@performSubmit()))
})
context.JK.Banner.show({
title: "Confirm Plan Change",
html: message,
buttons: buttons})
performSubmit: () ->
@setState({updating: true})
#SubscriptionActions.changeSubscription(this.state.selectedPlan)
rest.changeSubscription(this.state.selectedPlan).done((subscription) =>
@ -138,6 +183,44 @@ AppStore = context.AppStore
document.querySelector('#change-subscription-form').addEventListener('submit', @onChangeSubmit.bind(this))
getTimeRemaining: (t) ->
if t < 0
t = -t
seconds = Math.floor( (t/1000) % 60 );
minutes = Math.floor( (t/1000/60) % 60 );
hours = Math.floor( (t/(1000*60*60)) % 24 );
days = Math.floor( t/(1000*60*60*24) );
return {
'total': t,
'days': days,
'hours': hours,
'minutes': minutes,
'seconds': seconds
};
displayTime: (until_time) ->
untilTime = @getTimeRemaining(until_time * 1000)
timeString = ''
if untilTime.days != 0
timeString += "#{untilTime.days} days, "
if untilTime.hours != 0 || timeString.length > 0
timeString += "#{untilTime.hours} hours, "
if untilTime.minutes != 0 || timeString.length > 0
timeString += "#{untilTime.minutes} minutes, "
if untilTime.seconds != 0 || timeString.length > 0
timeString += "#{untilTime.seconds} seconds"
if timeString == ''
'now!'
timeString
comparePlans: (e) ->
if context.JK.clientType() == 'client'
context.JK.popExternalLink("https://jamkazam.freshdesk.com/support/solutions/articles/66000122535-what-are-jamkazam-s-free-vs-premium-features-")
@ -158,7 +241,7 @@ AppStore = context.AppStore
plan_codes.push(`<option key="yearly" value="yearly" disabled="disabled">-------- YEARLY PLANS --------</option>`)
for plan in yearlies
plan_codes.push(`<option key={plan.id || ''} value={plan.id || ''}>{plan.name} (${plan.price.toFixed(2)}/{plan.cycle})</option>`)
plansJsx = `<select name="plan_code" onChange={this.onPlanChanged} defaultValue={this.currentPlan()} >{plan_codes}</select>`
plansJsx = `<select name="plan_code" onChange={this.onPlanChanged} defaultValue={this.currentPlan()} value={this.currentPlan()}>{plan_codes}</select>`
changeClass = 'button-orange update-plan'
if !@state.selectedPlan? || @state.updating
@ -225,6 +308,20 @@ AppStore = context.AppStore
billingAddendum = `<span>However, your cancelled {effective_plan_name} plan is still active until the end of the billing cycle.</span>`# `<span><br/><br/><span>You will be billed a final time at the <span className="plan-name">{this.getDisplayNameTier(this.props.subscription.subscription.plan.plan_code)}</span> at end of this billing cycle.</span></span>`
else
billingAddendum = null
if @props.subscription.subscription_rules.remaining_month_play_time
remaining_month_play_time = @props.subscription.subscription_rules.remaining_month_play_time
until_time = new Date()
until_time = new Date(until_time.getTime() + remaining_month_play_time * 1000)
#until_time.setSeconds(until_time.getSeconds() + @subscriptionRules.remaining_month_play_time)
playtime = `<div className="play-time">
<label>monthly play time remaining:</label>
<p>You have <span className="playtime">{this.displayTime(remaining_month_play_time)}</span> time remaining this month. Only the time you spend in a session with 2 or more people uses your session play time.</p>
</div>`
else
playtime = `<div className="play-time">
<label>monthly play time remaining:</label>
<p>You have unlimited play time.</p>
</div>`
`<div className="current-subscription">
<div>
<h2>Subscription:</h2>
@ -246,6 +343,7 @@ AppStore = context.AppStore
<p>{explanation} {billingAddendum}</p>
{warning}
</div>
{playtime}
<a className="button-grey" onClick={this.onCancel}>BACK</a>{update_payment_btn}
</div>
</div>

View File

@ -30,7 +30,7 @@ rest = context.JK.Rest()
else
howTo = `<div className="no-free-jamtrack">
<span>
The fastest way to start playing with your JamTracks is to open them below and use our <a href="https://jamkazam.desk.com/customer/portal/articles/2166273-playing-your-jamtracks-in-a-browser" onClick={this.customMixHelpClicked}>custom mix feature</a> to play them back in your browser. To access the full set of JamTrack features, <a href="/downloads" rel="external" onClick={this.downloadsClicked}>install our free app</a>. To learn more about all you can do with JamTracks, check out our <a href="https://jamkazam.desk.com/customer/en/portal/articles/2124663-playing-with-jamtracks" onClick={this.jamTrackHelpClicked}>JamTracks help docs</a>.
The fastest way to start playing with your JamTracks is to open them below and use our <a href="https://jamkazam.freshdesk.com/support/solutions/articles/66000125795-using-jamtracks-in-a-browser" onClick={this.customMixHelpClicked}>custom mix feature</a> to play them back in your browser. To access the full set of JamTrack features, <a href="/downloads" rel="external" onClick={this.downloadsClicked}>install our free app</a>. To learn more about all you can do with JamTracks, check out our <a href="https://jamkazam.freshdesk.com/support/solutions/66000075766" onClick={this.jamTrackHelpClicked}>JamTracks help docs</a>.
</span>
</div>`

View File

@ -487,7 +487,7 @@ mixins.push(Reflux.listenTo(UserStore, 'onUserChanged'))
helpful resources
</div>
<div className="helpful-section">
<a href="https://jamkazam.desk.com/customer/portal/articles/2166273-playing-your-jamtracks-in-a-browser" target="_blank">read a web player help article</a><br/>
<a href="https://jamkazam.freshdesk.com/support/solutions/articles/66000125795-using-jamtracks-in-a-browser" target="_blank">read a web player help article</a><br/>
that explains how to use all the features of this web player
</div>
<div className="helpful-section">

View File

@ -7,6 +7,9 @@
height: 100%;
}
p {
line-height:1.25;
}
* {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
@ -223,5 +226,16 @@
.update-payment-method {
float:right;
}
.play-time {
label {
margin-bottom:8px;
}
margin-top:30px;
margin-bottom:30px;
width:35rem;
}
.playtime {
font-weight:bold;
}
}
}

View File

@ -155,7 +155,8 @@ class ApiRecurlyController < ApiController
admin_override_plan_code: current_user.admin_override_plan_code,
admin_override_ends_at: current_user.admin_override_ends_at,
in_trial: !current_user.subscription_trial_ended?,
trial_ends_at: current_user.subscription_trial_ends_at
trial_ends_at: current_user.subscription_trial_ends_at,
subscription_rules: current_user.subscription_rules
}, :status => 200
rescue RecurlyClientError => x
render json: {:message => x.inspect, errors: x.errors}, :status => 404
@ -175,7 +176,6 @@ class ApiRecurlyController < ApiController
subscription, account = @client.find_subscription(current_user)
past_due = account && account.has_past_due_invoice
has_billing_info = !account.nil? && !account[:billing_info].nil?
render :json => {
past_due: past_due,
subscription: subscription, has_billing_info: has_billing_info,
@ -184,7 +184,8 @@ class ApiRecurlyController < ApiController
admin_override_plan_code: current_user.admin_override_plan_code,
admin_override_ends_at: current_user.admin_override_ends_at,
in_trial: !current_user.subscription_trial_ended?,
trial_ends_at: current_user.subscription_trial_ends_at
trial_ends_at: current_user.subscription_trial_ends_at,
subscription_rules: current_user.subscription_rules,
}, :status => 200
end
@ -226,7 +227,8 @@ class ApiRecurlyController < ApiController
admin_override_plan_code: current_user.admin_override_plan_code,
admin_override_ends_at: current_user.admin_override_ends_at,
in_trial: !current_user.subscription_trial_ended?,
trial_ends_at: current_user.subscription_trial_ends_at
trial_ends_at: current_user.subscription_trial_ends_at,
subscription_rules: current_user.subscription_rules
}
end
rescue RecurlyClientError => x

View File

@ -4,5 +4,5 @@
<h1>Frequently Asked Questions</h1>
<p>
The JamKazam FAQ can be found on our support site here: <a href="https://jamkazam.desk.com/customer/portal/articles/1305119-frequently-asked-questions-faq-" target="_blank">JamKazam Frequently Asked Questions</a>.
The JamKazam FAQ can be found on our support site here: <a href="https://jamkazam.freshdesk.com/support/solutions/folders/66000108417" target="_blank">JamKazam Frequently Asked Questions</a>.
</p>

View File

@ -4,7 +4,7 @@
<h1>Features &amp; Benefits</h1>
<p>
Musicians can enjoy four major features of the new JamKazam service, as described below. Also, several <a href="https://jamkazam.desk.com/customer/portal/topics/673198-tutorials-on-major-features/articles" target="_blank">Tutorial Videos</a> are available to see how various features work in more detail.
Musicians can enjoy four major features of the new JamKazam service, as described below. Also, several <a href="https://www.youtube.com/channel/UC38nc9MMZgExJAd7ca3rkUA" target="_blank">Tutorial Videos</a> are available to see how various features work in more detail.
</p>
<br/>

View File

@ -4,7 +4,7 @@
<h1>Videos</h1>
<p>
For a great introduction to the service, please watch the <a href="http://www.youtube.com/watch?v=ylYcvTY9CVo" target="_blank">JamKazam Overview video</a>.
For a great introduction to the service, please watch the <a href="https://www.youtube.com/watch?v=ylYcvTY9CVo" target="_blank">JamKazam Overview video</a>.
</p>
<p>
@ -23,5 +23,5 @@
</p>
<p>
Also, several <a href="https://jamkazam.desk.com/customer/portal/topics/673198-tutorials-on-major-features/articles" target="_blank">Tutorial Videos</a> are available to see how various features work in more detail.
Also, several <a href="https://www.youtube.com/channel/UC38nc9MMZgExJAd7ca3rkUA" target="_blank">Tutorial Videos</a> are available to see how various features work in more detail.
</p>

View File

@ -59,8 +59,4 @@ script type='text/template' id='template-mixer-mode-change'
span.definition Note on Audio Files
div The volume control on any audio file is always both the master and personal volume control, regardless of the current mode.
br
div
| For more detailed information on this topic, read our knowledge base article on&nbsp;
a rel="external" href="https://jamkazam.desk.com/customer/portal/articles/1757233-using-personal-vs-master-mix-controls" Configuring Master and Personal Mixes in a Session
| .
br