diff --git a/admin/Gemfile b/admin/Gemfile index cae7f7e72..c07af8f93 100644 --- a/admin/Gemfile +++ b/admin/Gemfile @@ -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" diff --git a/admin/Gemfile.lock b/admin/Gemfile.lock index 3983afb54..e11ac010b 100644 --- a/admin/Gemfile.lock +++ b/admin/Gemfile.lock @@ -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) diff --git a/admin/app/admin/jam_ruby_users.rb b/admin/app/admin/jam_ruby_users.rb index 41381f456..fff7b460d 100644 --- a/admin/app/admin/jam_ruby_users.rb +++ b/admin/app/admin/jam_ruby_users.rb @@ -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 diff --git a/admin/app/admin/subscription_override.rb b/admin/app/admin/subscription_override.rb index 78bbb5c36..8831c66cf 100644 --- a/admin/app/admin/subscription_override.rb +++ b/admin/app/admin/subscription_override.rb @@ -1,4 +1,4 @@ -ActiveAdmin.register User, :as => 'Subscription' do +ActiveAdmin.register User, :as => 'User_Override' do menu :label => 'Subscription', :parent => 'Users' diff --git a/ruby/lib/jam_ruby/models/user.rb b/ruby/lib/jam_ruby/models/user.rb index 04b8a2cbc..ee73d9bbe 100644 --- a/ruby/lib/jam_ruby/models/user.rb +++ b/ruby/lib/jam_ruby/models/user.rb @@ -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 diff --git a/web/Gemfile b/web/Gemfile index 4238b00b0..9f7c35692 100644 --- a/web/Gemfile +++ b/web/Gemfile @@ -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 diff --git a/web/Gemfile.lock b/web/Gemfile.lock index 3a3873f27..d64fd95f1 100644 --- a/web/Gemfile.lock +++ b/web/Gemfile.lock @@ -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) diff --git a/web/app/assets/javascripts/react-components/CurrentSubscription.js.jsx.coffee b/web/app/assets/javascripts/react-components/CurrentSubscription.js.jsx.coffee index 18c7fa05f..ff8fe5184 100644 --- a/web/app/assets/javascripts/react-components/CurrentSubscription.js.jsx.coffee +++ b/web/app/assets/javascripts/react-components/CurrentSubscription.js.jsx.coffee @@ -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 = "
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.
" + else + message = "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.
" + else + if this.state.selectedPlan == null || this.state.selectedPlan == '' + @performSubmit() + return + else + message = "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)} .
" + + 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(``) for plan in yearlies plan_codes.push(``) - plansJsx = `` + plansJsx = `` changeClass = 'button-orange update-plan' if !@state.selectedPlan? || @state.updating @@ -225,6 +308,20 @@ AppStore = context.AppStore billingAddendum = `However, your cancelled {effective_plan_name} plan is still active until the end of the billing cycle.`# `You have {this.displayTime(remaining_month_play_time)} time remaining this month. Only the time you spend in a session with 2 or more people uses your session play time.
+You have unlimited play time.
+{explanation} {billingAddendum}
{warning}- The JamKazam FAQ can be found on our support site here: JamKazam Frequently Asked Questions. + The JamKazam FAQ can be found on our support site here: JamKazam Frequently Asked Questions.
\ No newline at end of file diff --git a/web/app/views/corps/features.html.erb b/web/app/views/corps/features.html.erb index f06dfc52f..8582cd7fe 100644 --- a/web/app/views/corps/features.html.erb +++ b/web/app/views/corps/features.html.erb @@ -4,7 +4,7 @@- Musicians can enjoy four major features of the new JamKazam service, as described below. Also, several Tutorial Videos 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 Tutorial Videos are available to see how various features work in more detail.
- For a great introduction to the service, please watch the JamKazam Overview video. + For a great introduction to the service, please watch the JamKazam Overview video.
@@ -23,5 +23,5 @@
- Also, several Tutorial Videos are available to see how various features work in more detail. + Also, several Tutorial Videos are available to see how various features work in more detail.
\ No newline at end of file diff --git a/web/app/views/dialogs/_banner.html.slim b/web/app/views/dialogs/_banner.html.slim index 6c6c47c9d..fd1000ca7 100644 --- a/web/app/views/dialogs/_banner.html.slim +++ b/web/app/views/dialogs/_banner.html.slim @@ -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 - 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 \ No newline at end of file