\ No newline at end of file
diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/signup_survey.text.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/signup_survey.text.erb
new file mode 100644
index 000000000..4834ebde6
--- /dev/null
+++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/signup_survey.text.erb
@@ -0,0 +1,11 @@
+<%= I18n.t 'user_mailer.signup_survey.greeting' -%> <%= @user.first_name -%> -
+
+<%= I18n.t 'user_mailer.signup_survey.paragraph1' -%>
+
+<%= @survey_url %>
+
+<%= I18n.t 'user_mailer.signup_survey.ps' -%>
+<%= I18n.t 'user_mailer.signup_survey.ps_text' -%>
+
+<%= I18n.t 'user_mailer.signup_survey.regards' -%>,
+<%= I18n.t 'user_mailer.signup_survey.signature' -%>
diff --git a/ruby/lib/jam_ruby/lib/email_profile_reminder.rb b/ruby/lib/jam_ruby/lib/email_profile_reminder.rb
new file mode 100644
index 000000000..c5de827fc
--- /dev/null
+++ b/ruby/lib/jam_ruby/lib/email_profile_reminder.rb
@@ -0,0 +1,48 @@
+module JamRuby
+ class EmailProfileReminder
+ @@log = Logging.logger[EmailProfileReminder]
+
+ def self.send_reminders
+ begin
+ #If the user has not updated their profile 1 day after signup, then send reminder email1
+ reminder1_users.find_each do |user|
+ UserMailer.profile_complete_reminder1(user).deliver_now
+ User.where(id: user.id).update_all(profile_complete_reminder1_sent_at: Time.now)
+ end
+
+ #If the user has not updated their profile 3 days after signup, then send reminder email2
+ reminder2_users.find_each do |user|
+ UserMailer.profile_complete_reminder2(user).deliver_now
+ User.where(id: user.id).update_all(profile_complete_reminder2_sent_at: Time.now)
+ end
+
+ #If the user has not updated their profile 5 days after signup, then send reminder email3
+ reminder3_users.find_each do |user|
+ UserMailer.profile_complete_reminder3(user).deliver_now
+ User.where(id: user.id).update_all(profile_complete_reminder3_sent_at: Time.now)
+ end
+ rescue Exception => e
+ @@log.error("unable to send profile reminder email=#{e}")
+ puts "unable to send profile reminder email=#{e}"
+ end
+ end
+
+ def self.prospect_users
+ User.where("users.profile_completed_at IS NULL AND users.subscribe_email = ?", true)
+ end
+
+ def self.reminder1_users
+ EmailProfileReminder.prospect_users.where("users.created_at < ? AND users.profile_complete_reminder1_sent_at IS NULL", 1.day.ago)
+ end
+
+ def self.reminder2_users
+ EmailProfileReminder.prospect_users.where("users.created_at < ? AND users.profile_complete_reminder1_sent_at IS NOT NULL AND users.profile_complete_reminder2_sent_at IS NULL", 3.days.ago)
+ end
+
+ def self.reminder3_users
+ EmailProfileReminder.prospect_users.where("users.created_at < ? AND users.profile_complete_reminder2_sent_at IS NOT NULL AND users.profile_complete_reminder3_sent_at IS NULL", 5.days.ago)
+ end
+
+
+ end
+end
\ No newline at end of file
diff --git a/ruby/lib/jam_ruby/lib/email_signup_survey.rb b/ruby/lib/jam_ruby/lib/email_signup_survey.rb
new file mode 100644
index 000000000..1fe847013
--- /dev/null
+++ b/ruby/lib/jam_ruby/lib/email_signup_survey.rb
@@ -0,0 +1,23 @@
+module JamRuby
+ class EmailSignupSurvey
+ @@log = Logging.logger[EmailSignupSurvey]
+
+ def self.send_survey
+ begin
+ # if signup survey email has not been sent to this user, then send it
+ survey_users.find_each do |user|
+ UserMailer.signup_survey(user).deliver_now
+ User.where(id: user.id).update_all(signup_survey_sent_at: Time.now)
+ end
+ rescue Exception => e
+ @@log.error("unable to send surevy email e=#{e}")
+ puts "unable to send surevy email e=#{e}"
+ end
+ end
+
+ def self.survey_users
+ cutoff_date = Date.parse(Rails.application.config.signup_survey_cutoff_date) # Define a cutoff date for the survey/gear setup emails
+ User.where("users.signup_survey_sent_at IS NULL AND users.created_at < ? AND users.created_at > ?", 1.days.ago, cutoff_date)
+ end
+ end
+end
\ No newline at end of file
diff --git a/ruby/lib/jam_ruby/lib/gear_setup_reminder.rb b/ruby/lib/jam_ruby/lib/gear_setup_reminder.rb
new file mode 100644
index 000000000..cc5eb608a
--- /dev/null
+++ b/ruby/lib/jam_ruby/lib/gear_setup_reminder.rb
@@ -0,0 +1,47 @@
+module JamRuby
+ class GearSetupReminder
+
+ @@log = Logging.logger[GearSetupReminder]
+
+ def self.send_reminders
+ begin
+ cutoff_date = Date.parse(Rails.application.config.signup_survey_cutoff_date) # Define a cutoff date for the survey/gear setup emails
+
+ reminder1_users(cutoff_date).find_each do |user|
+ UserMailer.gear_setup_reminder1(user).deliver_now
+ User.where(id: user.id).update_all(gear_setup_reminder1_sent_at: Time.now)
+ end
+
+ reminder2_users(cutoff_date).find_each do |user|
+ UserMailer.gear_setup_reminder2(user).deliver_now
+ User.where(id: user.id).update_all(gear_setup_reminder2_sent_at: Time.now)
+ end
+
+ reminder3_users(cutoff_date).find_each do |user|
+ UserMailer.gear_setup_reminder3(user).deliver_now
+ User.where(id: user.id).update_all(gear_setup_reminder3_sent_at: Time.now)
+ end
+ rescue Exception => e
+ @@log.error("unable to send gear setup reminder email #{e}")
+ puts "unable to send gear setup reminder email #{e}"
+ end
+ end
+
+ def self.prospect_users
+ User.where("users.first_certified_gear_at IS NULL")
+ end
+
+ def self.reminder1_users(cutoff_date)
+ GearSetupReminder.prospect_users.where("users.created_at < ? AND users.created_at > ? AND users.gear_setup_reminder1_sent_at IS NULL", 1.day.ago, cutoff_date)
+ end
+
+ def self.reminder2_users(cutoff_date)
+ GearSetupReminder.prospect_users.where("users.created_at < ? AND users.created_at > ? AND users.gear_setup_reminder1_sent_at IS NOT NULL AND users.gear_setup_reminder2_sent_at IS NULL", 3.days.ago, cutoff_date)
+ end
+
+ def self.reminder3_users(cutoff_date)
+ GearSetupReminder.prospect_users.where("users.created_at < ? AND users.created_at > ? AND users.gear_setup_reminder2_sent_at IS NOT NULL AND users.gear_setup_reminder3_sent_at IS NULL", 5.days.ago, cutoff_date)
+ end
+
+ end
+end
\ No newline at end of file
diff --git a/ruby/lib/jam_ruby/models/active_music_session.rb b/ruby/lib/jam_ruby/models/active_music_session.rb
index c909156fe..16260f839 100644
--- a/ruby/lib/jam_ruby/models/active_music_session.rb
+++ b/ruby/lib/jam_ruby/models/active_music_session.rb
@@ -863,6 +863,10 @@ module JamRuby
self.save!(:validate => false)
end
+ def in_session?(user)
+ self.users.exists?(user.id)
+ end
+
def connected_participant_count
Connection.where(:music_session_id => self.id,
:aasm_state => Connection::CONNECT_STATE.to_s,
diff --git a/ruby/lib/jam_ruby/models/recording.rb b/ruby/lib/jam_ruby/models/recording.rb
index 926144983..7a29f29a0 100644
--- a/ruby/lib/jam_ruby/models/recording.rb
+++ b/ruby/lib/jam_ruby/models/recording.rb
@@ -75,6 +75,11 @@ module JamRuby
has_stream_mix
end
+ def can_stop?(user)
+ # only allow the starting-user to create (ideally, perhaps, only the client that did it)
+ user == owner
+ end
+
# this should be a has-one relationship. until this, this is easiest way to get from recording > mix
def mix
self.mixes[0] if self.mixes.length > 0
@@ -214,7 +219,7 @@ module JamRuby
def has_access?(user)
return false if user.nil?
- users.exists?(user.id) || attached_with_lesson(user) #|| plays.where("player_id=?", user).count != 0
+ users.exists?(user.id) || attached_with_lesson(user) || (music_session && music_session.in_session?(user))
end
def attached_with_lesson(user)
diff --git a/ruby/lib/jam_ruby/models/user.rb b/ruby/lib/jam_ruby/models/user.rb
index eab4d54a3..3bd1da941 100644
--- a/ruby/lib/jam_ruby/models/user.rb
+++ b/ruby/lib/jam_ruby/models/user.rb
@@ -420,6 +420,12 @@ module JamRuby
User.where(id: self.id).update_all(updates)
end
+
+ # check if the profile looks complete
+ if musician_instruments.length > 0 || genre_players.length > 0
+ User.where(id: self.id).update_all(profile_completed_at: Time.now)
+ end
+
end
def self.hourly_check
diff --git a/ruby/lib/jam_ruby/resque/scheduled/hourly_job.rb b/ruby/lib/jam_ruby/resque/scheduled/hourly_job.rb
index e534e98cf..45606b896 100644
--- a/ruby/lib/jam_ruby/resque/scheduled/hourly_job.rb
+++ b/ruby/lib/jam_ruby/resque/scheduled/hourly_job.rb
@@ -13,6 +13,9 @@ module JamRuby
#TeacherPayment.hourly_check
User.hourly_check
AffiliatePartner.tally_up(Date.today)
+ EmailProfileReminder.send_reminders
+ EmailSignupSurvey.send_survey
+ GearSetupReminder.send_reminders
ConnectionManager.new.cleanup_dangling
@@log.info("done")
diff --git a/ruby/lib/jam_ruby/resque/scheduled/profile_reminder_emailer.rb b/ruby/lib/jam_ruby/resque/scheduled/profile_reminder_emailer.rb
new file mode 100644
index 000000000..9eaba001a
--- /dev/null
+++ b/ruby/lib/jam_ruby/resque/scheduled/profile_reminder_emailer.rb
@@ -0,0 +1,15 @@
+module JamRuby
+ class ProfileReminderEmailer
+ extend Resque::Plugins::JamLonelyJob
+
+ @queue = :scheduled_profile_reminder_emailer
+ @@log = Logging.logger[ProfileReminderEmailer]
+
+ def self.perform
+ @@log.debug("waking up")
+ EmailProfileReminder.send_reminders
+ @@log.debug("done")
+ end
+
+ end
+end
\ No newline at end of file
diff --git a/web/app/assets/javascripts/modern/scripts.js b/web/app/assets/javascripts/modern/scripts.js
index 392a0d30d..78120ec25 100644
--- a/web/app/assets/javascripts/modern/scripts.js
+++ b/web/app/assets/javascripts/modern/scripts.js
@@ -14,6 +14,7 @@
//= require react-components/actions/VideoActions
//= require client_init
//= require utils
+//= require subscription_utils
//= require jamkazam
//= require modern/JamServer_copy
diff --git a/web/app/controllers/api_recordings_controller.rb b/web/app/controllers/api_recordings_controller.rb
index 3564e514e..74b8dc424 100644
--- a/web/app/controllers/api_recordings_controller.rb
+++ b/web/app/controllers/api_recordings_controller.rb
@@ -187,6 +187,11 @@ class ApiRecordingsController < ApiController
def stop
+ # only allow the creator to stop the recording
+ if @recording.can_stop?(current_user) == false
+ raise JamPermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
+ end
+
@recording.stop
if @recording.errors.any?
diff --git a/web/config/application.rb b/web/config/application.rb
index 033060c28..3ca4f1cf5 100644
--- a/web/config/application.rb
+++ b/web/config/application.rb
@@ -386,6 +386,7 @@ if defined?(Bundler)
config.video_available = "full"
config.alerts_api_enabled = true
+ config.show_recording_debug_status = false
config.gear_check_ignore_high_latency = false
config.remove_whitespace_credit_card = false
config.estimate_taxes = true
@@ -519,6 +520,8 @@ if defined?(Bundler)
config.spa_origin_url = "http://beta.jamkazam.local:4000"
config.user_match_monitoring_email = "user_match_monitoring_email@jamkazam.com"
config.send_user_match_mail_only_to_jamkazam_team = true
+ config.signup_survey_url = "https://www.surveymonkey.com/r/WVBKLYL"
+ config.signup_survey_cutoff_date = "2025-06-10"
config.action_mailer.asset_host = config.action_controller.asset_host
end
end
diff --git a/web/config/environments/development.rb b/web/config/environments/development.rb
index efd1faf54..858e677b1 100644
--- a/web/config/environments/development.rb
+++ b/web/config/environments/development.rb
@@ -126,4 +126,6 @@ SampleApp::Application.configure do
config.action_controller.asset_host = 'http://www.jamkazam.local:3000'
config.send_user_match_mail_only_to_jamkazam_team = false
+ config.signup_survey_url = "https://www.surveymonkey.com/r/WVBKLYL"
+ config.signup_survey_cutoff_date = "2025-06-10"
end
diff --git a/web/config/initializers/gon.rb b/web/config/initializers/gon.rb
index cbf6ec62e..6f675776f 100644
--- a/web/config/initializers/gon.rb
+++ b/web/config/initializers/gon.rb
@@ -31,5 +31,6 @@ Gon.global.braintree_token = Rails.application.config.braintree_token
Gon.global.paypal_admin_only = Rails.application.config.paypal_admin_only
Gon.global.use_video_conferencing_server = Rails.application.config.use_video_conferencing_server
Gon.global.manual_override_installer_ends_with = Rails.application.config.manual_override_installer_ends_with
+Gon.global.show_recording_debug_status = Rails.application.config.show_recording_debug_status
Gon.global.env = Rails.env
Gon.global.version = ::JamWeb::VERSION
diff --git a/web/config/locales/en.yml b/web/config/locales/en.yml
index 6b0ecd22f..82453cdb5 100644
--- a/web/config/locales/en.yml
+++ b/web/config/locales/en.yml
@@ -71,3 +71,83 @@ en:
paragraph2: "Your account was imported for you, so you'll need to set a password. Click the button below to set a password for your JamKazam account."
paragraph3: "Thanks for joining JamKazam!"
signature: "The JamKazam Team"
+ profile_complete_reminder1:
+ subject: "Update your JamKazam profile now & get connected to other musicians"
+ greeting: "Hello"
+ paragraph1: "If you may be interested in playing music live online with other musicians, the first thing you should do is fill out your JamKazam profile. The information in your profile lets other musicians with similar interests find, message, and connect with you, and also lets JamKazam’s matchmaking features give you recommendations for great musical connections. Click the button below to update your profile now. It only takes 2 minutes to complete your profile."
+ update_profile: "Update Profile"
+ paragraph2: "After you have updated your profile, the next thing you should do is download, install, and run the JamKazam app. You’ll need this app to play online with others, and the app also gives you access to more advanced JamTracks features if you signed up to use our huge catalog of backing tracks. After you download and install the app, we recommend you open the app and then leave the app running for about 10-15 minutes on your computer. The app will use this time to quietly collect Internet data that we use to figure out which other musicians on JamKazam you’ll have the best connections with – i.e. the lowest latency (or lag) when playing together"
+ paragraph3: "Click a button below to go to the JamKazam app download page. (Most users should click the Download App button, but if you’re on a Mac that can’t run MacOS 10.15 or later, click the Download Legacy App button, as that version of the app supports older MacOS versions back to 10.7.) After you download it, double click the downloaded installer, and follow the on-screen instructions to install the app, then start the app and leave it running for about 15 minutes."
+ download_app: "Download App"
+ download_legacy_app: "Download Legacy App"
+ paragraph4: "For next steps, don’t forget you can always refer back to the Welcome email we sent you when you signed up. And if you run into any problems or get stuck, please send us email at support@jamkazam.com. We’re always happy to help"
+ regards: "Best Regards,"
+ signature: "JamKazam Team"
+
+ profile_complete_reminder2:
+ subject: "Complete your JamKazam profile"
+ greeting: "Hello"
+ paragraph1: "We share your profile with JamKazam members who may be a good fit to play music with you during your first week on the platform via an automated email feature. Don’t miss this opportunity to connect. Click the button below to update your profile now, before it’s shared with others!"
+ update_profile: "Update Profile"
+ paragraph2: "For next steps after your profile, don’t forget you can always refer back to the Welcome email we sent you when you signed up. And if you run into any problems or get stuck, please send us email at support@jamkazam.com. We’re always happy to help!"
+ regards: "Best Regards,"
+ signature: "JamKazam Team"
+
+ profile_complete_reminder3:
+ subject: "Complete your JamKazam profile"
+ greeting: "Hello"
+ paragraph1: "Your profile is your key to connecting with other musicians on JamKazam. It lets others know what instruments you play at what level of proficiency and what kinds of music you like to play. This lets our existing community find and reach out to you to connect and play, and this information also powers our automated matchmaking features that make recommendations to you. If you think you might want to play music live online on JamKazam, please click the button below now to fill out your profile!"
+ update_profile: "Update Profile"
+ regards: "Best Regards,"
+ signature: "JamKazam Team"
+
+ gear_setup_reminder1:
+ subject: "Set up audio gear in JamKazam now so you can get in your first session"
+ greeting: "Hello"
+ paragraph1: "The next thing you should do with JamKazam is set up your audio gear and test it in a solo session by yourself."
+ paragraph2: |
+ If you already have an audio interface and the ability to connect your computer to your home router using an Ethernet cable, you are ready to set up your gear. You can find all of our gear setup articles here. We recommend you use our articles on setting up your audio interface for Mac or for Windows to make sure you get this critical step done properly, and that you use our article on connecting your computer via Ethernet, which is the other critical setup step.
+ paragraph3: |
+ If you’re not sure what gear you need, we recommend you start by reading this article that explains this topic in general terms. Next, check this list of articles to find the one that best describes you. You need to use an audio interface rather than relying on the built-in mic on your computer, and you need to connect your computer to your Internet router using an Ethernet cable rather than using WiFi. See this list of articles for recommendations on gear. If you’re worried about spending money on gear without knowing how well JamKazam will work for you, you can buy gear on Amazon, try it for a week, and return it for a refund if you’re not happy for a risk-free trial experience.
+ paragraph4: |
+ If you have any trouble or feel confused about gear setup, you can email us for help at support@jamkazam.com. You can also visit with a JamKazam support team member in our weekly Zoom office hours, which is offered every Wednesday from 11am to 12pm US Central Time.
+ regards: "Best Regards,"
+ signature: "JamKazam Team"
+
+ gear_setup_reminder2:
+ subject: "Set up your gear in JamKazam now to connect with other musicians"
+ greeting: "Hello"
+ paragraph1: "We share your profile with JamKazam members who may be a good fit to play music with you during your first week on the platform via an automated email feature. Don’t miss this opportunity to get connected!"
+ paragraph2: "One of the critical pieces of information in getting you connected is your latency to other musicians on JamKazam (this is the amount of time it takes to get your audio to them). To get this information, you need to set up your gear in the JamKazam app."
+ paragraph3: |
+ If you already have an audio interface and the ability to connect your computer to your home router using an Ethernet cable, you are ready to set up your gear. You can find all of our gear setup articles here. We recommend you use our articles on setting up your audio interface for Mac or for Windows to make sure you get this critical step done properly, and that you use our article on connecting your computer via Ethernet, which is the other critical setup step.
+ paragraph4: |
+ If you’re not sure what gear you need, we recommend you start by reading this article that explains this topic in general terms. Next, check this list of articles to find the one that best describes you. You need to use an audio interface rather than relying on the built-in mic on your computer, and you need to connect your computer to your Internet router using an Ethernet cable rather than using WiFi. See this list of articles for recommendations on gear. If you’re worried about spending money on gear without knowing how well JamKazam will work for you, you can buy gear on Amazon, try it for a week, and return it for a refund if you’re not happy for a risk-free trial experience.
+ paragraph5: |
+ If you have any trouble or feel confused about gear setup, you can email us for help at support@jamkazam.com. You can also visit with a JamKazam support team member in our weekly Zoom office hours, which is offered every Wednesday from 11am to 12pm US Central Time.
+ regards: "Best Regards,"
+ signature: "JamKazam Team"
+
+ gear_setup_reminder3:
+ subject: Don’t waste your free 30-day premium gold plan - set up your gear now!
+ greeting: "Hello"
+ paragraph1: |
+ When you sign up for JamKazam, we give you a free 30-day premium gold plan so you can fully experience how amazing our online sessions are and how JamKazam can help you play more music with more people to bring more musical joy to your life.
+ paragraph2: |
+ Don’t waste your 30-day window! Set up your gear in the JamKazam app now, and get started.
+ paragraph3: |
+ If you already have an audio interface and the ability to connect your computer to your home router using an Ethernet cable, you are ready to set up your gear. You can find all of our gear setup articles here. We recommend you use our articles on setting up your audio interface for Mac or for Windows to make sure you get this critical step done properly, and that you use our article on connecting your computer via Ethernet, which is the other critical setup step.
+ paragraph4: |
+ If you’re not sure what gear you need, we recommend you start by reading this article that explains this topic in general terms. Next, check this list of articles to find the one that best describes you. You need to use an audio interface rather than relying on the built-in mic on your computer, and you need to connect your computer to your Internet router using an Ethernet cable rather than using WiFi. See this list of articles for recommendations on gear. If you’re worried about spending money on gear without knowing how well JamKazam will work for you, you can buy gear on Amazon, try it for a week, and return it for a refund if you’re not happy for a risk-free trial experience.
+ paragraph5: |
+ If you have any trouble or feel confused about gear setup, you can email us for help at support@jamkazam.com. You can also visit with a JamKazam support team member in our weekly Zoom office hours, which is offered every Wednesday from 11am to 12pm US Central Time.
+ regards: "Best Regards,"
+ signature: "JamKazam Team"
+ signup_survey:
+ subject: "Let us help you to be successful on JamKazam"
+ greeting: "Hi"
+ paragraph1: "Thanks for signing up to join our community of musicians! Please click the link below and take 2 minutes to let us know a little more about your goals. Our support team will use this information to provide tailored, individual help to you to make it faster and easier for you to be successful."
+ ps: "p.s."
+ ps_text: "If we can help in any way, please always feel free to contact us at"
+ regards: "Best Regards,"
+ signature: "JamKazam Team"
\ No newline at end of file