VRFS-3936 merging develop
This commit is contained in:
commit
fa3ba71b22
|
|
@ -83,6 +83,9 @@ gem 'sendgrid_toolkit', '>= 1.1.1'
|
|||
gem 'stripe'
|
||||
gem 'zip-codes'
|
||||
gem 'email_validator'
|
||||
gem 'best_in_place' #, github: 'bernat/best_in_place'
|
||||
|
||||
|
||||
|
||||
#group :libv8 do
|
||||
# gem 'libv8', "~> 4.5.95"
|
||||
|
|
|
|||
|
|
@ -95,6 +95,9 @@ GEM
|
|||
backports (3.11.1)
|
||||
bcrypt (3.1.11)
|
||||
bcrypt-ruby (3.0.1)
|
||||
best_in_place (3.1.1)
|
||||
actionpack (>= 3.2)
|
||||
railties (>= 3.2)
|
||||
binding_of_caller (0.8.0)
|
||||
debug_inspector (>= 0.0.1)
|
||||
bootstrap-sass (2.0.4.0)
|
||||
|
|
@ -628,6 +631,7 @@ DEPENDENCIES
|
|||
amqp (= 0.9.8)
|
||||
aws-sdk (~> 1)
|
||||
bcrypt-ruby (= 3.0.1)
|
||||
best_in_place
|
||||
bootstrap-sass (= 2.0.4)
|
||||
bootstrap-will_paginate (= 0.0.6)
|
||||
bugsnag
|
||||
|
|
|
|||
|
|
@ -11,8 +11,9 @@ Overtime we can add more administrative functions and views, but initially this
|
|||
|
||||
Examples of:
|
||||
|
||||
Button on Show Page of Item: 'Send Client Update Notice' in jam_ruby_artifact_updates.rb
|
||||
* Button on Show Page of Item: 'Send Client Update Notice' in jam_ruby_artifact_updates.rb
|
||||
* Batch Updates in View page: onboarding.rb (CurrentlyOnboarding)
|
||||
|
||||
|
||||
Stuff that is probably breaky:
|
||||
activeadmin_addons https://github.com/platanus/activeadmin_addons
|
||||
activeadmin_addons https://github.com/platanus/activeadmin_addons
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@ ActiveAdmin.register_page "Dashboard" do
|
|||
small ul do
|
||||
li link_to "Users", admin_users_path
|
||||
li link_to "Teachers", admin_teachers_path
|
||||
li link_to "Onboarding Management", admin_currently_onboardings_path
|
||||
li link_to "Onboarding Management", admin_onboarder_managements_path
|
||||
li link_to "Onboarding Settings", admin_onboarders_path
|
||||
li link_to "Lesson Sessions", admin_lesson_sessions_path
|
||||
li link_to "Slow Lesson Responses", admin_slow_responses_path
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,13 @@ ActiveAdmin.register JamRuby::User, :as => 'Users' do
|
|||
|
||||
form :partial => "form"
|
||||
|
||||
member_action :delete_forever, :method => :get do
|
||||
resource.permanently_delete
|
||||
redirect_to :back, {notice: 'User email and login credentials have been permanently changed'}
|
||||
end
|
||||
|
||||
|
||||
|
||||
show do |user|
|
||||
panel "Common" do
|
||||
attributes_table do
|
||||
|
|
@ -60,6 +67,11 @@ ActiveAdmin.register JamRuby::User, :as => 'Users' do
|
|||
end
|
||||
end
|
||||
end
|
||||
row "Delete Forever" do |user|
|
||||
span do
|
||||
link_to("delete forever", delete_forever_admin_user_path(user.id), :data => {:confirm => 'Are you sure?'})
|
||||
end
|
||||
end
|
||||
|
||||
row :jamclass_credits
|
||||
row :via_amazon
|
||||
|
|
@ -243,11 +255,13 @@ ActiveAdmin.register JamRuby::User, :as => 'Users' do
|
|||
@user.email = params[:jam_ruby_user][:email]
|
||||
@user.admin = params[:jam_ruby_user][:admin]
|
||||
@user.is_onboarder = params[:jam_ruby_user][:is_onboarder]
|
||||
@user.subscribe_email = params[:jam_ruby_user][:subscribe_email]
|
||||
@user.musician = params[:jam_ruby_user][:musician]
|
||||
@user.first_name = params[:jam_ruby_user][:first_name]
|
||||
@user.last_name = params[:jam_ruby_user][:last_name]
|
||||
@user.state = params[:jam_ruby_user][:state]
|
||||
@user.city = params[:jam_ruby_user][:city]
|
||||
@user.gifted_jamtracks = params[:jam_ruby_user][:gifted_jamtracks]
|
||||
|
||||
|
||||
if params[:jam_ruby_user][:show_frame_options].to_i == 1
|
||||
|
|
|
|||
|
|
@ -0,0 +1,91 @@
|
|||
ActiveAdmin.register JamRuby::User, :as => 'Onboarder' do
|
||||
|
||||
menu :label => 'Onboarder Settings', :parent => 'JamClass'
|
||||
|
||||
config.sort_order = 'created_at'
|
||||
config.batch_actions = true
|
||||
config.per_page = 100
|
||||
config.paginate = true
|
||||
config.filters = false
|
||||
config.clear_action_items!
|
||||
batch_action :destroy, false
|
||||
|
||||
scope("All Onboarders", default: true) { |scope| scope.where(is_onboarder: true).order(:created_at) }
|
||||
|
||||
controller do
|
||||
active_admin_config.includes.push :onboarding_users
|
||||
|
||||
def update
|
||||
resource.max_onboardings = params[:jam_ruby_user][:max_onboardings]
|
||||
resource.save!
|
||||
success.json {}
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
index do
|
||||
def last_week
|
||||
@last_week_result ||= calculate_last_week
|
||||
end
|
||||
|
||||
def calculate_last_week
|
||||
start_day = Date.today.beginning_of_week(:sunday).yesterday.beginning_of_week(:sunday)
|
||||
end_day = start_day.end_of_week(:sunday)
|
||||
result = [start_day, end_day]
|
||||
result
|
||||
end
|
||||
|
||||
def this_week
|
||||
@this_week_result ||= calculate_this_week
|
||||
end
|
||||
|
||||
def calculate_this_week
|
||||
start_day = Date.today.beginning_of_week(:sunday)
|
||||
end_day = start_day.end_of_week(:sunday)
|
||||
result = [start_day, end_day]
|
||||
result
|
||||
end
|
||||
|
||||
def week_display(week)
|
||||
start_day = week[0]
|
||||
end_day = week[1]
|
||||
mmyy = start_day.strftime('%b')
|
||||
"#{mmyy} #{start_day.day}-#{end_day.day}"
|
||||
end
|
||||
|
||||
def onboarding_select
|
||||
array = []
|
||||
100.times do |i|
|
||||
array.push [i.to_s, i.to_s]
|
||||
end
|
||||
array
|
||||
end
|
||||
column "Name" do |user|
|
||||
div do
|
||||
div do
|
||||
link_to user.name, user.admin_url
|
||||
end
|
||||
div do
|
||||
user.email
|
||||
end
|
||||
end
|
||||
end
|
||||
column "Max Onboardings" do |user|
|
||||
best_in_place user, :max_onboardings, as: :select, url: admin_onboarder_path(user),:collection => onboarding_select
|
||||
end
|
||||
column "Current Week #{week_display(this_week)}" do |user|
|
||||
start_date, last_date = this_week
|
||||
user.onboarding_users.where(onboarder_assigned_at: start_date..last_date).count
|
||||
end
|
||||
column "Previous Week #{week_display(last_week)}" do |user|
|
||||
start_date, last_date = last_week
|
||||
user.onboarding_users.where(onboarder_assigned_at: start_date..last_date).count
|
||||
end
|
||||
column "Current Student WIP" do |user|
|
||||
user.onboarding_users.where('onboarding_status = ? OR onboarding_status = ?', User::ONBOARDING_STATUS_ASSIGNED, User::ONBOARDING_STATUS_EMAILED).count
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
ActiveAdmin.register JamRuby::User, :as => 'CurrentlyOnboarding' do
|
||||
ActiveAdmin.register JamRuby::User, :as => 'OnboarderManagement' do
|
||||
|
||||
menu :label => 'Currently Onboarding', :parent => 'JamClass'
|
||||
menu :label => 'Onboarder Management', :parent => 'JamClass'
|
||||
|
||||
config.sort_order = 'created_at desc'
|
||||
config.batch_actions = true
|
||||
|
|
@ -11,7 +11,7 @@ ActiveAdmin.register JamRuby::User, :as => 'CurrentlyOnboarding' do
|
|||
batch_action :destroy, false
|
||||
|
||||
batch_action :onboarder, form: -> { {
|
||||
support_consultant: (User.where(is_onboarder: true).includes(:onboarding_users).map {|user| ["#{user.name} (#{user.onboarding_users.length})", user.id]}).to_a.unshift(['Unassign', ''])
|
||||
support_consultant: (User.where(is_onboarder: true).includes(:onboarding_users).map {|user| ["#{user.name} (#{user.onboarding_users.where('onboarding_status = ? OR onboarding_status = ?', User::ONBOARDING_STATUS_ASSIGNED, User::ONBOARDING_STATUS_EMAILED).count})", user.id]}).to_a.unshift(['Unassign', ''])
|
||||
} } do |ids, inputs|
|
||||
onboarder = inputs[:support_consultant]
|
||||
if onboarder.blank?
|
||||
|
|
@ -41,7 +41,11 @@ ActiveAdmin.register JamRuby::User, :as => 'CurrentlyOnboarding' do
|
|||
filter :onboarder, as: :select, :collection => User.where(is_onboarder: true), label: 'Support Consultant'
|
||||
filter :onboarder_id_blank, :as => :boolean, label: 'Unassigned'
|
||||
filter :onboarding_escalation_reason_present, :as => :boolean, label: 'Escalated'
|
||||
scope("TestDrive/Amazon Users", default: true) { |scope| scope.joins(:posa_cards).where('posa_cards.lesson_package_type_id in (?)', LessonPackageType::AMAZON_PACKAGES + LessonPackageType::LESSON_PACKAGE_TYPES) }
|
||||
scope("Unassigned", default: true) { |scope| scope.joins(:posa_cards).where(onboarding_status: User::ONBOARDING_STATUS_UNASSIGNED).where('posa_cards.lesson_package_type_id in (?)', LessonPackageType::AMAZON_PACKAGES + LessonPackageType::LESSON_PACKAGE_TYPES) }
|
||||
scope("Escalated") { |scope| scope.joins(:posa_cards).where('onboarding_status = ?', User::ONBOARDING_STATUS_ESCALATED).where('posa_cards.lesson_package_type_id in (?)', LessonPackageType::AMAZON_PACKAGES + LessonPackageType::LESSON_PACKAGE_TYPES) }
|
||||
scope("Needs Manual Email") { |scope| scope.joins(:posa_cards).where(onboarding_status: User::ONBOARDING_STATUS_ONBOARDED).where('(stuck_take_flesson = TRUE AND sent_admin_take_flesson_email_at is NULL) OR (stuck_take_2nd_flesson = TRUE AND sent_admin_take_2nd_flesson_email_at IS NULL) OR (stuck_take_plesson = TRUE AND sent_admin_take_plesson_email_at IS NULL)').where('posa_cards.lesson_package_type_id in (?)', LessonPackageType::AMAZON_PACKAGES + LessonPackageType::LESSON_PACKAGE_TYPES) }
|
||||
scope("Assigned") { |scope| scope.joins(:posa_cards).where('onboarding_status = ? OR onboarding_status = ?', User::ONBOARDING_STATUS_ASSIGNED, User::ONBOARDING_STATUS_EMAILED).where('posa_cards.lesson_package_type_id in (?)', LessonPackageType::AMAZON_PACKAGES + LessonPackageType::LESSON_PACKAGE_TYPES) }
|
||||
scope("All TestDrive/Amazon Users") { |scope| scope.joins(:posa_cards).where('posa_cards.lesson_package_type_id in (?)', LessonPackageType::AMAZON_PACKAGES + LessonPackageType::LESSON_PACKAGE_TYPES) }
|
||||
|
||||
|
||||
controller do
|
||||
|
|
@ -59,10 +63,23 @@ ActiveAdmin.register JamRuby::User, :as => 'CurrentlyOnboarding' do
|
|||
column "Escalated Reason", :onboarding_escalation_reason
|
||||
column "Support Consultant" do |user|
|
||||
if user.onboarder
|
||||
link_to "#{user.onboarder.name} (#{user.onboarder.onboarding_users.count})", user.onboarder.admin_url
|
||||
link_to "#{user.onboarder.name} (#{user.onboarder.onboarding_users.where('onboarding_status = ? OR onboarding_status = ?', User::ONBOARDING_STATUS_ASSIGNED, User::ONBOARDING_STATUS_EMAILED).count})", user.onboarder.admin_url
|
||||
else
|
||||
end
|
||||
end
|
||||
column "Manual Email Needed" do |user|
|
||||
|
||||
div do
|
||||
if user.stuck_take_plesson
|
||||
link_to("sent take paid lesson email", mark_sent_paid_lesson_admin_onboarder_management_path(user.id), {'data-confirm': "You sent an email manually to the user to remind them to take a paid lesson?"})
|
||||
elsif user.stuck_take_2nd_flesson
|
||||
link_to("sent take 2nd lesson email", mark_sent_2nd_free_lesson_admin_onboarder_management_path(user.id), {'data-confirm': "You sent an email manually to the user to remind them to take 2nd free lesson?"})
|
||||
elsif user.stuck_take_flesson
|
||||
link_to("sent take 1st lesson email", mark_sent_1st_free_lesson_admin_onboarder_management_path(user.id), {'data-confirm': "You sent an email manually to the user to remind them to take a 1st free lesson?"})
|
||||
else
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
column "Signup" do |user|
|
||||
user.created_at.to_date
|
||||
|
|
@ -74,6 +91,17 @@ ActiveAdmin.register JamRuby::User, :as => 'CurrentlyOnboarding' do
|
|||
column "Email 4", :onboarding_email_4_sent_at
|
||||
column "Email 5", :onboarding_email_5_sent_at
|
||||
column "Test Session", :onboarding_test_session_scheduled_at
|
||||
column "Admin Actions" do |user|
|
||||
div do
|
||||
if user.is_waiting_onboarding || user.is_onboarding
|
||||
link_to("mark onboarded", mark_onboarded_admin_onboarder_management_path(user.id), { 'data-confirm': "Mark onboarded?"})
|
||||
end
|
||||
if user.is_waiting_onboarding || user.is_onboarding
|
||||
link_to("mark lost", mark_lost_admin_onboarder_management_path(user.id), { 'data-confirm': "Mark lost (reason = Other)?"})
|
||||
end
|
||||
end
|
||||
end
|
||||
column "Onboarder Notes", :onboarding_onboarder_notes
|
||||
end
|
||||
|
||||
member_action :update_onboarder, :method => :post do
|
||||
|
|
@ -82,4 +110,29 @@ ActiveAdmin.register JamRuby::User, :as => 'CurrentlyOnboarding' do
|
|||
redirect_to :back
|
||||
end
|
||||
|
||||
member_action :mark_sent_paid_lesson, :method => :get do
|
||||
resource.mark_sent_paid_lesson
|
||||
redirect_to :back
|
||||
end
|
||||
|
||||
member_action :mark_sent_2nd_free_lesson, :method => :get do
|
||||
resource.mark_sent_2nd_free_lesson
|
||||
redirect_to :back
|
||||
end
|
||||
|
||||
member_action :mark_sent_1st_free_lesson, :method => :get do
|
||||
resource.mark_sent_1st_free_lesson
|
||||
redirect_to :back
|
||||
end
|
||||
|
||||
member_action :mark_onboarded, :method => :get do
|
||||
resource.mark_onboarded
|
||||
redirect_to :back
|
||||
end
|
||||
|
||||
member_action :mark_lost, :method => :get do
|
||||
resource.mark_lost
|
||||
redirect_to :back
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -12,3 +12,8 @@
|
|||
// //= require autocomplete-rails
|
||||
//= require base
|
||||
//= require_tree .
|
||||
|
||||
|
||||
$(document).ready(function() {
|
||||
jQuery(".best_in_place").best_in_place()
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,2 +1,10 @@
|
|||
#= require active_admin/base
|
||||
#= require jquery3
|
||||
#= require best_in_place
|
||||
#= require jquery.purr
|
||||
#= require best_in_place.purr
|
||||
|
||||
$(document).ready ->
|
||||
# IS NOT HAPPENING: USE ACTIVE_ADMIN.JS
|
||||
console.log("DAT COFFEE INIT")
|
||||
jQuery(".best_in_place").best_in_place()
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
module ApplicationHelper
|
||||
|
||||
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,2 +1,3 @@
|
|||
module JamSessionsHelper
|
||||
|
||||
end
|
||||
|
|
@ -3,6 +3,8 @@
|
|||
= f.input :email, label: 'Email'
|
||||
= f.input :admin
|
||||
= f.input :is_onboarder, label: 'Is Support Consultant'
|
||||
= f.input :subscribe_email, label: 'Subscribed to Emails?'
|
||||
= f.input :gifted_jamtracks, label: 'JamTrack Credits'
|
||||
= f.input :first_name
|
||||
= f.input :last_name
|
||||
= f.input :city
|
||||
|
|
|
|||
|
|
@ -383,4 +383,8 @@ age_out_sessions.sql
|
|||
alter_crash_dumps.sql
|
||||
onboarding.sql
|
||||
better_lesson_notices.sql
|
||||
teacher_search_control.sql
|
||||
teacher_search_control.sql
|
||||
user_timezone.sql
|
||||
onboarder_limit.sql
|
||||
onboarding_emails.sql
|
||||
limit_counter_reminders.sql
|
||||
|
|
@ -0,0 +1 @@
|
|||
ALTER TABLE lesson_sessions ADD COLUMN counter_reminders INTEGER NOT NULL DEFAULT 0;
|
||||
|
|
@ -0,0 +1 @@
|
|||
ALTER TABLE users ADD COLUMN max_onboardings INTEGER NOT NULL DEFAULT 0;
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
ALTER TABLE users ADD COLUMN sent_take_flesson_email_at TIMESTAMP WITHOUT TIME ZONE;
|
||||
ALTER TABLE users ADD COLUMN sent_take_flesson_email_times INTEGER NOT NULL DEFAULT 0;
|
||||
ALTER TABLE users ADD COLUMN sent_take_2nd_flesson_email_at TIMESTAMP WITHOUT TIME ZONE;
|
||||
ALTER TABLE users ADD COLUMN sent_take_2nd_flesson_email_times INTEGER NOT NULL DEFAULT 0;
|
||||
ALTER TABLE users ADD COLUMN sent_take_plesson_email_at TIMESTAMP WITHOUT TIME ZONE;
|
||||
ALTER TABLE users ADD COLUMN sent_take_plesson_email_times INTEGER NOT NULL DEFAULT 0;
|
||||
ALTER TABLE users ADD COLUMN second_onboarding_free_lesson_at timestamp without time zone;
|
||||
ALTER TABLE users ADD COLUMN sent_admin_take_flesson_email_at TIMESTAMP WITHOUT TIME ZONE;
|
||||
ALTER TABLE users ADD COLUMN sent_admin_take_2nd_flesson_email_at TIMESTAMP WITHOUT TIME ZONE;
|
||||
ALTER TABLE users ADD COLUMN sent_admin_take_plesson_email_at TIMESTAMP WITHOUT TIME ZONE;
|
||||
ALTER TABLE users ADD COLUMN stuck_take_flesson BOOLEAN NOT NULL DEFAULT FALSE;
|
||||
ALTER TABLE users ADD COLUMN stuck_take_2nd_flesson BOOLEAN NOT NULL DEFAULT FALSE;
|
||||
ALTER TABLE users ADD COLUMN stuck_take_plesson BOOLEAN NOT NULL DEFAULT FALSE;
|
||||
ALTER TABLE teachers ADD COLUMN random_order INTEGER NOT NULL DEFAULT 0;
|
||||
ALTER TABLE users ADD COLUMN send_onboarding_survey BOOLEAN NOT NULL DEFAULT FALSE;
|
||||
ALTER TABLE users ADD COLUMN sent_onboarding_survey_at TIMESTAMP WITHOUT TIME ZONE;
|
||||
CREATE INDEX index_first_onboarding_paid_lesson_at ON users USING btree(first_onboarding_paid_lesson_at);
|
||||
CREATE INDEX index_onboarding_onboarded_at ON users USING btree(onboarding_onboarded_at);
|
||||
CREATE INDEX index_onboarding_status ON users USING btree(onboarding_status);
|
||||
CREATE INDEX index_stuck_take_plesson ON users USING btree(stuck_take_plesson);
|
||||
CREATE INDEX index_stuck_take_2nd_flesson ON users USING btree(stuck_take_2nd_flesson);
|
||||
CREATE INDEX index_stuck_take_flesson ON users USING btree(stuck_take_flesson);
|
||||
CREATE INDEX index_sent_admin_take_flesson_email_at ON users USING btree(sent_admin_take_flesson_email_at);
|
||||
CREATE INDEX index_sent_admin_take_2nd_flesson_email_at ON users USING btree(sent_admin_take_2nd_flesson_email_at);
|
||||
CREATE INDEX index_sent_admin_take_plesson_email_at ON users USING btree(sent_admin_take_plesson_email_at);
|
||||
CREATE INDEX index_posa_cards_lesson_package_type_id ON posa_cards USING btree(lesson_package_type_id);
|
||||
|
||||
UPDATE teachers set random_order = sub.row_number * random() * 1000 from (select id, row_number() over () from teachers) as sub ;
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
ALTER TABLE users ADD COLUMN timezone VARCHAR;
|
||||
ALTER TABLE users ADD COLUMN deleted BOOLEAN NOT NULL DEFAULT FALSE;
|
||||
|
|
@ -52,6 +52,15 @@ module JamRuby
|
|||
subject: options[:subject])
|
||||
end
|
||||
|
||||
def ugly(options)
|
||||
mail(to: options[:to],
|
||||
cc: options[:cc],
|
||||
from: APP_CONFIG.email_generic_from,
|
||||
body: options[:body],
|
||||
content_type: "text/plain",
|
||||
subject: options[:subject])
|
||||
end
|
||||
|
||||
def recurly_alerts(user, options)
|
||||
|
||||
body = options[:body]
|
||||
|
|
|
|||
|
|
@ -49,6 +49,92 @@ module JamRuby
|
|||
end
|
||||
end
|
||||
|
||||
def take_paid_lesson(user)
|
||||
@user = user
|
||||
@lesson = user.taken_lessons.order(:created_at).last
|
||||
@teacher = @lesson.teacher
|
||||
|
||||
if user.sent_take_plesson_email_times == 0
|
||||
@subject = "Book your next lesson with your instructor now!"
|
||||
elsif user.sent_take_plesson_email_times == 1
|
||||
@subject = "Book your next lesson to continue your musical journey"
|
||||
else
|
||||
@subject = "The best way to improve on your instrument is with a great instructor - book today!"
|
||||
end
|
||||
sendgrid_category "promo_lesson_reminder"
|
||||
sendgrid_unique_args :type => "promo_lesson_reminder"
|
||||
|
||||
sendgrid_recipients([user.email])
|
||||
sendgrid_substitute('@USERID', [user.id])
|
||||
|
||||
mail(:to => user.email, :subject => @subject) do |format|
|
||||
format.text
|
||||
format.html
|
||||
end
|
||||
end
|
||||
|
||||
def take_second_free_lesson(user)
|
||||
@user = user
|
||||
@lesson = user.taken_lessons.order(:created_at).last
|
||||
@teacher = @lesson.teacher
|
||||
|
||||
if user.sent_take_2nd_flesson_email_times == 0
|
||||
@subject = "Book your second free lesson now!"
|
||||
elsif user.sent_take_2nd_flesson_email_times == 1
|
||||
@subject = "Book your second free lesson to continue your musical journey"
|
||||
else
|
||||
@subject = "Last reminder to book your next free lesson"
|
||||
end
|
||||
|
||||
sendgrid_category "promo_lesson_reminder"
|
||||
sendgrid_unique_args :type => "promo_lesson_reminder"
|
||||
|
||||
sendgrid_recipients([user.email])
|
||||
sendgrid_substitute('@USERID', [user.id])
|
||||
|
||||
mail(:to => user.email, :subject => @subject) do |format|
|
||||
format.text
|
||||
format.html
|
||||
end
|
||||
end
|
||||
|
||||
def take_first_free_lesson(user)
|
||||
@user = user
|
||||
if user.sent_take_flesson_email_times == 0
|
||||
@subject = "Book your first free lesson now!"
|
||||
elsif user.sent_take_flesson_email_times == 1
|
||||
@subject = "Book your first free lesson to start your musical journey"
|
||||
else
|
||||
@subject = "Last reminder to book your free lessons - $60 value!"
|
||||
end
|
||||
|
||||
sendgrid_category "promo_lesson_reminder"
|
||||
sendgrid_unique_args :type => "promo_lesson_reminder"
|
||||
|
||||
sendgrid_recipients([user.email])
|
||||
sendgrid_substitute('@USERID', [user.id])
|
||||
|
||||
mail(:to => user.email, :subject => @subject) do |format|
|
||||
format.text
|
||||
format.html
|
||||
end
|
||||
end
|
||||
|
||||
def onboarding_survey(user)
|
||||
@user = user
|
||||
@subject = "1-minute JamKazam survey - please help us give good support!"
|
||||
sendgrid_category "onboarding_survey"
|
||||
sendgrid_unique_args :type => "onboarding_survey"
|
||||
|
||||
sendgrid_recipients([user.email])
|
||||
sendgrid_substitute('@USERID', [user.id])
|
||||
|
||||
mail(:to => user.email, :subject => @subject) do |format|
|
||||
format.text
|
||||
format.html
|
||||
end
|
||||
end
|
||||
|
||||
def student_education_welcome_message(user)
|
||||
@user = user
|
||||
@subject = "Welcome to JamKazam and JamClass online lessons!"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
|
||||
<% if !@user.anonymous? %>
|
||||
<p>Hi <%= @user.first_name %>,
|
||||
</p>
|
||||
<% end %>
|
||||
|
||||
<p>
|
||||
Please click this link to take a literally 1-minute survey on your onboarding experience: <a href="https://www.surveymonkey.com/r/93JC2KJ" style="color:#fc0">https://www.surveymonkey.com/r/93JC2KJ</a>. This will help us deliver better support to other students like you. Thank you!
|
||||
</p>
|
||||
|
||||
<p>Best Regards,<br/>
|
||||
Team JamKazam</p>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<% if !@user.anonymous? %>
|
||||
Hi <%= @user.first_name %>,
|
||||
<% end %>
|
||||
|
||||
Please click this link to take a literally 1-minute survey on your onboarding experience: https://www.surveymonkey.com/r/93JC2KJ. This will help us deliver better support to other students like you. Thank you!
|
||||
|
||||
|
||||
Best Regards,
|
||||
Team JamKazam
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
<% provide(:title, @subject) %>
|
||||
|
||||
|
||||
<% if !@user.anonymous? %>
|
||||
<p>Hi <%= @user.first_name %>,
|
||||
</p>
|
||||
<% end %>
|
||||
|
||||
<% if @user.sent_take_flesson_email_times == 0 %>
|
||||
|
||||
<p>We hope you had a great support experience with the JamKazam consultant who prepared you to get into your first free online lesson. Life gets busy. So before you forget about it, please find an instructor who looks great for you, and book your first free lesson now!
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Here is an article that explains how to search for your ideal teacher: <a href="http://bit.ly/2kBPXBz" style="color:#fc0">http://bit.ly/2kBPXBz</a>. And here is an article that explains how to book your first lesson: <a href="http://bit.ly/2k3qNMT" style="color:#fc0">http://bit.ly/2k3qNMT</a>.
|
||||
</p>
|
||||
<p>
|
||||
If you have any trouble, please email us at <a href="mailto:support@jamkazam.com" style="color:#fc0">support@jamkazam.com</a>. Or you can call us at <a href="tel:+18773768742">877-376-8742</a>.
|
||||
</p>
|
||||
|
||||
<% elsif @user.sent_take_flesson_email_times == 1 %>
|
||||
|
||||
<p>We noticed you haven't booked your first free lesson yet. Don't forget to take advantage of this amazing limited promotion. Your two free lessons are valued at approximately $60! Book your first lesson today.</p>
|
||||
<p>
|
||||
Here is an article that explains how to search for your ideal teacher: <a href="http://bit.ly/2kBPXBz" style="color:#fc0">http://bit.ly/2kBPXBz</a>. And here is an article that explains how to book your first lesson: <a href="http://bit.ly/2k3qNMT" style="color:#fc0">http://bit.ly/2k3qNMT</a>.
|
||||
</p>
|
||||
<p>
|
||||
If you have any trouble, please email us at <a href="mailto:support@jamkazam.com" style="color:#fc0">support@jamkazam.com</a>. Or you can call us at <a href="tel:+18773768742">877-376-8742</a>.
|
||||
</p>
|
||||
|
||||
<% else %>
|
||||
|
||||
|
||||
<p>It looks like you're busy, but we wanted to remind you once more to book your first free lesson before you forget and let this terrific promotion get away. Start your musical journey with a world-class instructor who can help you achieve your goals. There is no better way to learn and master your new instrument!</p>
|
||||
<p>
|
||||
Here is an article that explains how to search for your ideal teacher: <a href="http://bit.ly/2kBPXBz" style="color:#fc0">http://bit.ly/2kBPXBz</a>. And here is an article that explains how to book your first lesson: <a href="http://bit.ly/2k3qNMT" style="color:#fc0">http://bit.ly/2k3qNMT</a>.
|
||||
</p>
|
||||
<p>
|
||||
If you have any trouble, please email us at <a href="mailto:support@jamkazam.com" style="color:#fc0">support@jamkazam.com</a>. Or you can call us at <a href="tel:+18773768742">877-376-8742</a>.
|
||||
</p>
|
||||
|
||||
<% end %>
|
||||
|
||||
<p>Best Regards,<br/>
|
||||
Team JamKazam</p>
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
<% if !@user.anonymous? %>
|
||||
Hi <%= @user.first_name %>,
|
||||
<% end %>
|
||||
|
||||
<% if @user.sent_take_flesson_email_times == 0 %>
|
||||
We hope you had a great support experience with the JamKazam consultant who prepared you to get into your first free online lesson. Life gets busy. So before you forget about it, please find an instructor who looks great for you, and book your first free lesson now!
|
||||
|
||||
Here is an article that explains how to search for your ideal teacher: http://bit.ly/2kBPXBz. And here is an article that explains how to book your first lesson:http://bit.ly/2k3qNMT.
|
||||
|
||||
If you have any trouble, please email us at support@jamkazam.com. Or you can call us at 877-376-8742.
|
||||
<% elsif @user.sent_take_flesson_email_times == 1 %>
|
||||
We noticed you haven't booked your first free lesson yet. Don't forget to take advantage of this amazing limited promotion. Your two free lessons are valued at approximately $60! Book your first lesson today.
|
||||
|
||||
Here is an article that explains how to search for your ideal teacher: http://bit.ly/2kBPXBz. And here is an article that explains how to book your first lesson:http://bit.ly/2k3qNMT.
|
||||
|
||||
If you have any trouble, please email us at support@jamkazam.com. Or you can call us at 877-376-8742.
|
||||
<% else %>
|
||||
It looks like you're busy, but we wanted to remind you once more to book your first free lesson before you forget and let this terrific promotion get away. Start your musical journey with a world-class instructor who can help you achieve your goals. There is no better way to learn and master your new instrument!
|
||||
|
||||
Here is an article that explains how to search for your ideal teacher: http://bit.ly/2kBPXBz. And here is an article that explains how to book your first lesson:http://bit.ly/2k3qNMT.
|
||||
|
||||
If you have any trouble, please email us at support@jamkazam.com. Or you can call us at 877-376-8742.
|
||||
<% end %>
|
||||
|
||||
Best Regards,
|
||||
Team JamKazam
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
<% provide(:title, @subject) %>
|
||||
|
||||
|
||||
<% if !@user.anonymous? %>
|
||||
<p>Hi <%= @user.first_name %>,
|
||||
</p>
|
||||
<% end %>
|
||||
|
||||
<% if @user.sent_take_plesson_email_times == 0 %>
|
||||
<p>
|
||||
Now that you've enjoyed your first two lessons free, continue down the musical path you've started with your instructor. Schedule recurring weekly lessons for the best results and fastest progress, or schedule lessons one at a time. It's up to you.
|
||||
</p>
|
||||
<p>
|
||||
You can book your regular weekly or one-at-a-time lessons with your instructor at his/her profile page here: <a href="<%= @teacher.teacher_profile_url %>" style="color:#fc0"><%= @teacher.teacher_profile_url %></a>.
|
||||
</p>
|
||||
<p>
|
||||
If you have any trouble, please email us at <a href="mailto:support@jamkazam.com" style="color:#fc0">support@jamkazam.com</a>. Or you can call us at <a href="tel:+18773768742">877-376-8742</a>.
|
||||
</p>
|
||||
<% elsif @user.sent_take_plesson_email_times == 1 %>
|
||||
<p>
|
||||
You're off to a great start with your music teacher. Don't lose momentum!
|
||||
</p>
|
||||
<p>
|
||||
You can book your regular weekly or one-at-a-time lessons with your instructor at his/her profile page here: <a href="<%= @teacher.teacher_profile_url %>" style="color:#fc0"><%= @teacher.teacher_profile_url %></a>.
|
||||
</p>
|
||||
<p>
|
||||
If you have any trouble, please email us at <a href="mailto:support@jamkazam.com" style="color:#fc0">support@jamkazam.com</a>. Or you can call us at <a href="tel:+18773768742">877-376-8742</a>.
|
||||
</p>
|
||||
<% else %>
|
||||
<p>
|
||||
The best way - by far - to master your instrument and reach your musical goals is to have a great instructor - someone who can guide you, build the right foundation and technique from the beginning, inspire you, and make your practice pay off with the greatest return on your investment of time. If you want to play well, stay on the path with your instructor.
|
||||
</p>
|
||||
<p>
|
||||
You can book your regular weekly or one-at-a-time lessons with your instructor at his/her profile page here: <a href="<%= @teacher.teacher_profile_url %>" style="color:#fc0"><%= @teacher.teacher_profile_url %></a>.
|
||||
</p>
|
||||
<p>
|
||||
Or if you need to find a different instructor for any reason, here's an article on how to search for your ideal teacher: <a href="http://bit.ly/2kBPXBz" style="color:#fc0">http://bit.ly/2kBPXBz</a>. And here is an article that explains how to book your lesson: <a href="http://bit.ly/2k3qNMT" style="color:#fc0">http://bit.ly/2k3qNMT</a>.
|
||||
</p>
|
||||
<p>
|
||||
If you have any trouble, please email us at <a href="mailto:support@jamkazam.com" style="color:#fc0">support@jamkazam.com</a>. Or you can call us at <a href="tel:+18773768742">877-376-8742</a>.
|
||||
</p>
|
||||
<% end %>
|
||||
|
||||
<p>Best Regards,<br/>
|
||||
Team JamKazam</p>
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
<% if !@user.anonymous? %>
|
||||
Hi <%= @user.first_name %>,
|
||||
<% end %>
|
||||
|
||||
<% if @user.sent_take_plesson_email_times == 0 %>
|
||||
Now that you've enjoyed your first two lessons free, continue down the musical path you've started with your instructor. Schedule recurring weekly lessons for the best results and fastest progress, or schedule lessons one at a time. It's up to you.
|
||||
|
||||
You can book your regular weekly or one-at-a-time lessons with your instructor at his/her profile page here: <%= @teacher.teacher_profile_url %>.
|
||||
|
||||
If you have any trouble, please email us at support@jamkazam.com. Or you can call us at 877-376-8742.
|
||||
<% elsif @user.sent_take_plesson_email_times == 1 %>
|
||||
You're off to a great start with your music teacher. Don't lose momentum!
|
||||
|
||||
You can book your regular weekly or one-at-a-time lessons with your instructor at his/her profile page here: <%= @teacher.teacher_profile_url %>.
|
||||
|
||||
If you have any trouble, please email us at support@jamkazam.com. Or you can call us at 877-376-8742.
|
||||
<% else %>
|
||||
The best way - by far - to master your instrument and reach your musical goals is to have a great instructor - someone who can guide you, build the right foundation and technique from the beginning, inspire you, and make your practice pay off with the greatest return on your investment of time. If you want to play well, stay on the path with your instructor.
|
||||
|
||||
You can book your regular weekly or one-at-a-time lessons with your instructor at his/her profile page here: <%= @teacher.teacher_profile_url %>.
|
||||
|
||||
Or if you need to find a different instructor for any reason, here's an article on how to search for your ideal teacher: <a href="http://bit.ly/2kBPXBz" style="color:#fc0">http://bit.ly/2kBPXBz</a>. And here is an article that explains how to book your lesson: http://bit.ly/2k3qNMT.
|
||||
|
||||
If you have any trouble, please email us at support@jamkazam.com. Or you can call us at 877-376-8742.
|
||||
<% end %>
|
||||
|
||||
Best Regards,
|
||||
Team JamKazam
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
<% provide(:title, @subject) %>
|
||||
|
||||
|
||||
<% if !@user.anonymous? %>
|
||||
<p>Hi <%= @user.first_name %>,
|
||||
</p>
|
||||
<% end %>
|
||||
|
||||
<% if @user.sent_take_2nd_flesson_email_times == 0 %>
|
||||
<p>We hope you had a great first music lesson with <%= @teacher.name %>. Schedule your second free lesson with this instructor now at this page: <a href="<%= @teacher.teacher_profile_url %>" style="color:#fc0"><%= @teacher.teacher_profile_url %></a>, and continue your musical journey!</p>
|
||||
<p>
|
||||
If you have any trouble, please email us at <a href="mailto:support@jamkazam.com" style="color:#fc0">support@jamkazam.com</a>. Or you can call us at <a href="tel:+18773768742">877-376-8742</a>.
|
||||
</p>
|
||||
<% elsif @user.sent_take_2nd_flesson_email_times == 1 %>
|
||||
<p>Just a quick reminder to take advantage of your second free lesson, and book it today! Schedule your second lesson with the same instructor from your first lesson at this page: <a href="<%= @teacher.teacher_profile_url %>" style="color:#fc0"><%= @teacher.teacher_profile_url %></a>.</p>
|
||||
<p>Or if you didn't love your instructor for any reason, you can search for a different instructor for your second free lesson. Here's the article on how to search for your ideal teacher: <a href="http://bit.ly/2kBPXBz" style="color:#fc0">http://bit.ly/2kBPXBz</a>. And here is an article that explains how to book your lesson: <a href="http://bit.ly/2k3qNMT" style="color:#fc0">http://bit.ly/2k3qNMT</a>.</p>
|
||||
<p>
|
||||
If you have any trouble, please email us at <a href="mailto:support@jamkazam.com" style="color:#fc0">support@jamkazam.com</a>. Or you can call us at <a href="tel:+18773768742">877-376-8742</a>.
|
||||
</p>
|
||||
<% else %>
|
||||
<p>We're sending you one last reminder to book your second free lesson. Don't put it off to later and forget! A great instructor will make a huge difference in the progress you make in mastering your new instrument. You can book another lesson with your first instructor at his/her profile page here: <a href="<%= @teacher.teacher_profile_url %>" style="color:#fc0"><%= @teacher.teacher_profile_url %></a>.</p>
|
||||
<p>Or if you didn't love your instructor for any reason, you can search for a different instructor for your second free lesson. Here's the article on how to search for your ideal teacher: <a href="http://bit.ly/2kBPXBz" style="color:#fc0">http://bit.ly/2kBPXBz</a>. And here is an article that explains how to book your lesson: <a href="http://bit.ly/2k3qNMT" style="color:#fc0">http://bit.ly/2k3qNMT</a>.</p>
|
||||
<p>
|
||||
If you have any trouble, please email us at <a href="mailto:support@jamkazam.com" style="color:#fc0">support@jamkazam.com</a>. Or you can call us at <a href="tel:+18773768742">877-376-8742</a>.
|
||||
</p>
|
||||
<% end %>
|
||||
|
||||
<p>Best Regards,<br/>
|
||||
Team JamKazam</p>
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
<% if !@user.anonymous? %>
|
||||
Hi <%= @user.first_name %>,
|
||||
<% end %>
|
||||
|
||||
<% if @user.sent_take_2nd_flesson_email_times == 0 %>
|
||||
We hope you had a great first music lesson with <%= @teacher.name %>. Schedule your second free lesson with this instructor now at this page: <%= @teacher.teacher_profile_url %>, and continue your musical journey!
|
||||
|
||||
If you have any trouble, please email us at support@jamkazam.com. Or you can call us at 877-376-8742.
|
||||
<% elsif @user.sent_take_2nd_flesson_email_times == 1 %>
|
||||
Just a quick reminder to take advantage of your second free lesson, and book it today! Schedule your second lesson with the same instructor from your first lesson at this page: <%= @teacher.teacher_profile_url %>.
|
||||
|
||||
Or if you didn't love your instructor for any reason, you can search for a different instructor for your second free lesson. Here's the article on how to search for your ideal teacher: http://bit.ly/2kBPXBz. And here is an article that explains how to book your lesson: http://bit.ly/2k3qNMT.
|
||||
|
||||
If you have any trouble, please email us at support@jamkazam.com. Or you can call us at 877-376-8742.
|
||||
<% else %>
|
||||
We're sending you one last reminder to book your second free lesson. Don't put it off to later and forget! A great instructor will make a huge difference in the progress you make in mastering your new instrument. You can book another lesson with your first instructor at his/her profile page here: <%= @teacher.teacher_profile_url %>.
|
||||
|
||||
Or if you didn't love your instructor for any reason, you can search for a different instructor for your second free lesson. Here's the article on how to search for your ideal teacher: http://bit.ly/2kBPXBz. And here is an article that explains how to book your lesson: http://bit.ly/2k3qNMT.
|
||||
|
||||
If you have any trouble, please email us at support@jamkazam.com. Or you can call us at 877-376-8742.
|
||||
<% end %>
|
||||
|
||||
Best Regards,
|
||||
Team JamKazam
|
||||
|
|
@ -41,6 +41,10 @@ module JamRuby
|
|||
0
|
||||
end
|
||||
|
||||
def timezone
|
||||
@cookies[:'browser.timezone']
|
||||
end
|
||||
|
||||
def free_jamtracks
|
||||
if has_redeemable_jamtrack
|
||||
1
|
||||
|
|
|
|||
|
|
@ -737,7 +737,12 @@ module JamRuby
|
|||
self.autocanceling = true
|
||||
self.active = false
|
||||
self.status = STATUS_UNCONFIRMED
|
||||
save
|
||||
if save
|
||||
if is_test_drive?
|
||||
user.jamclass_credits = user.jamclass_credits + 1
|
||||
user.save(validate:false)
|
||||
end
|
||||
end
|
||||
self
|
||||
end
|
||||
|
||||
|
|
@ -840,7 +845,8 @@ module JamRuby
|
|||
if !user.has_test_drives? && !user.can_buy_test_drive?
|
||||
errors.add(:user, "have no remaining test drives")
|
||||
elsif teacher.has_booked_test_drive_with_student?(user) && !user.admin
|
||||
errors.add(:user, "have an in-progress or successful TestDrive with this teacher already")
|
||||
# we don't want to restrict this anymore. just let'em go to same teacher
|
||||
# errors.add(:user, "have an in-progress or successful TestDrive with this teacher already")
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -962,6 +968,7 @@ module JamRuby
|
|||
if lesson_booking.same_school
|
||||
lesson_booking.same_school_free = false # !user.school.education # non-education schools (music schools) are 'free' when school-on-school
|
||||
end
|
||||
user.update_timezone(lesson_booking_slots[0].timezone) if lesson_booking_slots.length > 0
|
||||
else
|
||||
lesson_booking.same_school = false
|
||||
lesson_booking.same_school_free = false
|
||||
|
|
@ -975,7 +982,7 @@ module JamRuby
|
|||
end if lesson_booking_slots
|
||||
|
||||
if lesson_booking.save
|
||||
description = '' if description.nil?
|
||||
description = '' if description.nil?
|
||||
msg = ChatMessage.create(user, lesson_booking.lesson_sessions[0], description, ChatMessage::CHANNEL_LESSON, nil, teacher, lesson_booking.lesson_sessions[0], 'Lesson Requested')
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -166,12 +166,14 @@ module JamRuby
|
|||
found ||= lesson_session.lesson_booking
|
||||
end
|
||||
|
||||
def pretty_scheduled_start(with_timezone = true)
|
||||
def pretty_scheduled_start(with_timezone = true, user_tz = nil)
|
||||
|
||||
start_time = scheduled_time(0)
|
||||
|
||||
tz_identifier = user_tz || self.timezone
|
||||
|
||||
begin
|
||||
tz = TZInfo::Timezone.get(timezone)
|
||||
tz = TZInfo::Timezone.get(tz_identifier)
|
||||
rescue Exception => e
|
||||
@@log.error("unable to find timezone=#{tz_identifier}, e=#{e}")
|
||||
end
|
||||
|
|
@ -205,12 +207,14 @@ module JamRuby
|
|||
end
|
||||
end
|
||||
|
||||
def pretty_start_time(with_timezone = true)
|
||||
def pretty_start_time(with_timezone = true, user_tz = nil)
|
||||
|
||||
start_time = scheduled_time(0)
|
||||
|
||||
tz_identifier = user_tz || self.timezone
|
||||
|
||||
begin
|
||||
tz = TZInfo::Timezone.get(timezone)
|
||||
tz = TZInfo::Timezone.get(tz_identifier)
|
||||
rescue Exception => e
|
||||
@@log.error("unable to find timezone=#{tz_identifier}, e=#{e}")
|
||||
end
|
||||
|
|
|
|||
|
|
@ -94,11 +94,11 @@ module JamRuby
|
|||
end
|
||||
|
||||
def teacher_distribution
|
||||
teacher_distributions.where(education:false).where('retailer_id is null').first
|
||||
teacher_distributions.where(education: false).where('retailer_id is null').first
|
||||
end
|
||||
|
||||
def education_distribution
|
||||
teacher_distributions.where(education:true).first
|
||||
teacher_distributions.where(education: true).first
|
||||
end
|
||||
|
||||
def retailer_distribution
|
||||
|
|
@ -131,6 +131,7 @@ module JamRuby
|
|||
complete_sessions
|
||||
remind_counters
|
||||
remind_counters_recurring
|
||||
onboarding_email_reminders
|
||||
end
|
||||
|
||||
def self.minutely_check
|
||||
|
|
@ -144,9 +145,9 @@ module JamRuby
|
|||
.where("? > (COALESCE(lesson_sessions.sent_counter_reminder_at, lesson_sessions.countered_at, lesson_bookings.sent_notices_at) + (INTERVAL '24 hours'))", Time.now).each do |music_session|
|
||||
lesson_session = music_session.lesson_session
|
||||
if lesson_session.student_last_proposed?
|
||||
relevant_time = [lesson_session.countered_at, lesson_session.lesson_booking.sent_notices_at].find{|x|!x.nil?}
|
||||
relevant_time = [lesson_session.countered_at, lesson_session.lesson_booking.sent_notices_at].find { |x| !x.nil? }
|
||||
|
||||
UserMailer.student_no_comm_other(lesson_session.lesson_booking, relevant_time < Time.now - 3.days).deliver_now
|
||||
UserMailer.student_no_comm_other(lesson_session.lesson_booking, relevant_time < 3.days.ago).deliver_now
|
||||
UserMailer.teacher_counter_reminder(lesson_session).deliver_now
|
||||
else
|
||||
UserMailer.teacher_no_comm_other(lesson_session.lesson_booking).deliver_now
|
||||
|
|
@ -159,7 +160,7 @@ module JamRuby
|
|||
|
||||
def self.remind_counters_recurring
|
||||
MusicSession.joins(lesson_session: :lesson_booking)
|
||||
.where("lesson_bookings.status = ? AND lesson_bookings.sent_counter_reminder = false AND lesson_bookings.recurring = TRUE",LessonBooking::STATUS_COUNTERED)
|
||||
.where("lesson_bookings.status = ? AND lesson_bookings.sent_counter_reminder = false AND lesson_bookings.recurring = TRUE", LessonBooking::STATUS_COUNTERED)
|
||||
.where("? > (COALESCE(lesson_sessions.countered_at, lesson_bookings.sent_notices_at) + (INTERVAL '24 hours'))", Time.now).each do |music_session|
|
||||
lesson_session = music_session.lesson_session
|
||||
if lesson_session.student_last_proposed?
|
||||
|
|
@ -172,6 +173,51 @@ module JamRuby
|
|||
end
|
||||
end
|
||||
|
||||
def self.remindable_onboarding_users
|
||||
User.where('first_onboarding_paid_lesson_at IS NULL AND onboarding_onboarded_at IS NOT NULL')
|
||||
.where('stuck_take_flesson = FALSE and stuck_take_2nd_flesson = FALSE and stuck_take_plesson = FALSE')
|
||||
end
|
||||
|
||||
def self.onboarding_email_reminders
|
||||
remindable_onboarding_users.each do |user|
|
||||
if user.second_onboarding_free_lesson_at && user.sent_take_plesson_email_times < 4
|
||||
|
||||
last_sent = user.sent_take_plesson_email_at || user.second_onboarding_free_lesson_at
|
||||
if last_sent < 2.days.ago
|
||||
if user.sent_take_plesson_email_times == 3
|
||||
User.update_all(id: user.id, stuck_take_plesson: true)
|
||||
else
|
||||
UserMailer.take_paid_lesson(user).deliver_now
|
||||
User.update_all(id: user.id, sent_take_plesson_email_times: user.sent_take_plesson_email_times + 1, sent_take_plesson_email_at: Time.now)
|
||||
end
|
||||
end
|
||||
|
||||
elsif user.first_onboarding_free_lesson_at && user.sent_take_2nd_flesson_email_times < 4
|
||||
last_sent = user.sent_take_2nd_flesson_email_at || user.first_onboarding_free_lesson_at
|
||||
if last_sent < 2.days.ago
|
||||
if user.sent_take_2nd_flesson_email_times == 3
|
||||
User.update_all(id: user.id, stuck_take_2nd_flesson: true)
|
||||
else
|
||||
UserMailer.take_second_free_lesson(user).deliver_now
|
||||
User.update_all(id: user.id, sent_take_2nd_flesson_email_times: user.sent_take_2nd_flesson_email_times + 1, sent_take_2nd_flesson_email_at: Time.now)
|
||||
end
|
||||
end
|
||||
|
||||
elsif user.sent_take_flesson_email_times < 4
|
||||
last_sent = user.sent_take_flesson_email_at || user.onboarding_onboarded_at
|
||||
if last_sent < 2.days.ago
|
||||
if user.sent_take_flesson_email_times == 3
|
||||
User.update_all(id: user.id, stuck_take_flesson: true)
|
||||
else
|
||||
UserMailer.take_first_free_lesson(user).deliver_now
|
||||
User.update_all(id: user.id, sent_take_flesson_email_times: user.sent_take_flesson_email_times + 1, sent_take_flesson_email_at: Time.now)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# give 2 days to auto-cancel; this lets people just jump in a session and mark it done
|
||||
def self.auto_cancel
|
||||
MusicSession.joins(lesson_session: :lesson_booking).where('lesson_sessions.status = ? OR lesson_bookings.status = ?', LessonSession::STATUS_REQUESTED, LessonBooking::STATUS_COUNTERED).where("? > scheduled_start + (INTERVAL '2 days') + (INTERVAL '1 minutes' * (duration))", Time.now).each do |music_session|
|
||||
|
|
@ -319,15 +365,16 @@ module JamRuby
|
|||
if student.first_onboarding_free_lesson_at.nil?
|
||||
student.first_onboarding_free_lesson_at = Time.now
|
||||
student.save
|
||||
elsif student.second_onboarding_free_lesson_at.nil?
|
||||
student.second_onboarding_free_lesson_at = Time.now
|
||||
student.save
|
||||
end
|
||||
else
|
||||
if student.first_onboarding_paid_lesson_at.nil?
|
||||
student.first_onboarding_paid_lesson_at = Time.now
|
||||
student.save
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
mark_lesson(analysis[:bill])
|
||||
|
|
@ -399,6 +446,7 @@ module JamRuby
|
|||
student
|
||||
end
|
||||
end
|
||||
|
||||
def session_completed
|
||||
LessonSession.transaction do
|
||||
self.lock!
|
||||
|
|
@ -473,7 +521,7 @@ module JamRuby
|
|||
|
||||
if !sent_notices
|
||||
if success
|
||||
teacher_distributions.update_all(ready:true) # possibly there are 0 distributions on this lesson
|
||||
teacher_distributions.update_all(ready: true) # possibly there are 0 distributions on this lesson
|
||||
student.test_drive_succeeded(self)
|
||||
else
|
||||
student.test_drive_failed(self)
|
||||
|
|
@ -984,6 +1032,8 @@ module JamRuby
|
|||
|
||||
#end
|
||||
if self.save
|
||||
proposer.update_timezone(slot.timezone) if proposer
|
||||
|
||||
#if update_all && !lesson_booking.counter(self, proposer, slot)
|
||||
if !lesson_booking.counter(self, proposer, slot)
|
||||
response = lesson_booking
|
||||
|
|
@ -1135,6 +1185,7 @@ module JamRuby
|
|||
'TBD'
|
||||
end
|
||||
end
|
||||
|
||||
def timed_description
|
||||
if is_test_drive?
|
||||
"TestDrive session with #{self.lesson_booking.student.name} on #{time_for_admin}"
|
||||
|
|
@ -1149,11 +1200,11 @@ module JamRuby
|
|||
|
||||
def cancel_by_admin
|
||||
self.cancel({
|
||||
canceler: nil,
|
||||
canceled_by_admin: true,
|
||||
message: 'Canceled by JamKazam administrator',
|
||||
update_all: false
|
||||
})
|
||||
canceler: nil,
|
||||
canceled_by_admin: true,
|
||||
message: 'Canceled by JamKazam administrator',
|
||||
update_all: false
|
||||
})
|
||||
end
|
||||
|
||||
def intervened
|
||||
|
|
@ -1176,7 +1227,7 @@ module JamRuby
|
|||
end
|
||||
|
||||
def last_response_time
|
||||
[countered_at, lesson_booking.sent_notices_at].find{|x|!x.nil?}
|
||||
[countered_at, lesson_booking.sent_notices_at].find { |x| !x.nil? }
|
||||
end
|
||||
|
||||
def stripe_description(lesson_booking)
|
||||
|
|
|
|||
|
|
@ -1215,7 +1215,7 @@ SQL
|
|||
duration
|
||||
end
|
||||
|
||||
def pretty_scheduled_start(with_timezone = true, shorter = false)
|
||||
def pretty_scheduled_start(with_timezone = true, shorter = false, user_tz = nil)
|
||||
|
||||
if scheduled_start && scheduled_duration
|
||||
start_time = scheduled_start
|
||||
|
|
@ -1224,6 +1224,9 @@ SQL
|
|||
tz_identifier, tz_display = MusicSession.split_timezone(timezone)
|
||||
short_tz = 'GMT'
|
||||
|
||||
if user_tz
|
||||
tz_identifier = user_tz
|
||||
end
|
||||
begin
|
||||
tz = TZInfo::Timezone.get(tz_identifier)
|
||||
rescue Exception => e
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ module JamRuby
|
|||
# Real teachers who are marked as top.
|
||||
# Real teachers who are not marked as top.
|
||||
# Phantom teachers.
|
||||
query = query.order("top_rated DESC, phantom ASC")
|
||||
query = query.order("phantom ASC, random_order ASC")
|
||||
|
||||
current_page = params[:page].nil? ? 1 : params[:page].to_i
|
||||
next_page = current_page + 1
|
||||
|
|
@ -165,6 +165,10 @@ module JamRuby
|
|||
end
|
||||
end
|
||||
|
||||
def self.randomize_order
|
||||
self.connection.execute("update teachers set random_order = sub.row_number * random() * 1000 from (select id, row_number() over () from teachers) as sub ;")
|
||||
end
|
||||
|
||||
def self.save_teacher(user, params)
|
||||
teacher = nil
|
||||
Teacher.transaction do
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ module JamRuby
|
|||
ONBOARDING_STATUS_ONBOARDED = "Onboarded"
|
||||
ONBOARDING_STATUS_LOST = "Lost"
|
||||
ONBOARDING_STATUS_ESCALATED = "Escalated"
|
||||
ONBOARDING_STATUS_FREE_LESSON = "Free Lesson Taken"
|
||||
ONBOARDING_STATUS_FREE_LESSON = "One Free Lesson Taken"
|
||||
ONBOARDING_STATUS_PAID_LESSON = "Paid Lesson Taken"
|
||||
ONBOARDING_STATUES = [ONBOARDING_STATUS_UNASSIGNED, ONBOARDING_STATUS_ASSIGNED, ONBOARDING_STATUS_EMAILED, ONBOARDING_STATUS_ONBOARDED, ONBOARDING_STATUS_LOST, ONBOARDING_STATUS_ESCALATED, ONBOARDING_STATUS_FREE_LESSON, ONBOARDING_STATUS_PAID_LESSON ]
|
||||
SESSION_OUTCOME_SUCCESSFUL = "Successful"
|
||||
|
|
@ -136,7 +136,7 @@ module JamRuby
|
|||
|
||||
# notifications
|
||||
has_many :notifications, :class_name => "JamRuby::Notification", :foreign_key => "target_user_id"
|
||||
|
||||
|
||||
# chats
|
||||
has_many :chats, :class_name => "JamRuby::ChatMessage", :foreign_key => "user_id"
|
||||
|
||||
|
|
@ -328,16 +328,50 @@ module JamRuby
|
|||
onboarding_email_5_sent_at_changed? ||
|
||||
first_onboarding_free_lesson_at_changed? ||
|
||||
first_onboarding_paid_lesson_at_changed? ||
|
||||
second_onboarding_free_lesson_at? ||
|
||||
onboarding_onboarded_at
|
||||
User.where(id: self.id).update_all(onboarding_status: self.computed_onboarding_status)
|
||||
|
||||
updates = {onboarding_status: self.computed_onboarding_status}
|
||||
|
||||
if first_onboarding_free_lesson_at_changed? || first_onboarding_paid_lesson_at_changed? || second_onboarding_free_lesson_at?
|
||||
updates[:stuck_take_flesson] = false
|
||||
updates[:stuck_take_2nd_flesson] = false
|
||||
updates[:stuck_take_plesson] = false
|
||||
end
|
||||
|
||||
if updates[:onboarding_status] == ONBOARDING_STATUS_ONBOARDED || updates[:onboarding_status] == ONBOARDING_STATUS_LOST || updates[:onboarding_status] == ONBOARDING_STATUS_ESCALATED
|
||||
updates[:send_onboarding_survey] = true
|
||||
end
|
||||
|
||||
User.where(id: self.id).update_all(updates)
|
||||
end
|
||||
end
|
||||
|
||||
def self.hourly_check
|
||||
send_onboarding_surveys
|
||||
end
|
||||
|
||||
def self.send_onboarding_surveys
|
||||
User.where(send_onboarding_survey: true, sent_onboarding_survey_at: nil).each do |user|
|
||||
UserMailer.onboarding_survey(user).deliver_now
|
||||
User.where(id: user.id).update_all(sent_onboarding_survey_at: Time.now)
|
||||
end
|
||||
end
|
||||
|
||||
def update_teacher_pct
|
||||
if teacher
|
||||
teacher.update_profile_pct
|
||||
end
|
||||
end
|
||||
|
||||
def is_waiting_onboarding
|
||||
ONBOARDING_STATUS_UNASSIGNED
|
||||
end
|
||||
|
||||
def is_onboarding
|
||||
ONBOARDING_STATUS_ASSIGNED || ONBOARDING_STATUS_ESCALATED || ONBOARDING_STATUS_EMAILED
|
||||
end
|
||||
|
||||
def user_progression_fields
|
||||
@user_progression_fields ||= Set.new ["first_downloaded_client_at", "first_ran_client_at", "first_music_session_at", "first_real_music_session_at", "first_good_music_session_at", "first_certified_gear_at", "first_invited_at", "first_friended_at", "first_recording_at", "first_social_promoted_at", "first_played_jamtrack_at"]
|
||||
end
|
||||
|
|
@ -350,6 +384,18 @@ module JamRuby
|
|||
end
|
||||
end
|
||||
|
||||
def update_timezone(timezone)
|
||||
if timezone.nil?
|
||||
return
|
||||
|
||||
end
|
||||
begin
|
||||
TZInfo::Timezone.get(timezone)
|
||||
User.where(id: self.id).update_all(timezone: timezone)
|
||||
rescue Exception => e
|
||||
@@log.error("unable to find timezone=#{timezone}, e=#{e}")
|
||||
end
|
||||
end
|
||||
def has_any_free_jamtracks
|
||||
has_redeemable_jamtrack || gifted_jamtracks > 0
|
||||
end
|
||||
|
|
@ -1211,6 +1257,7 @@ module JamRuby
|
|||
origin = options[:origin]
|
||||
test_drive_package_details = options[:test_drive_package]
|
||||
under_13 = options[:under_13]
|
||||
timezone = options[:timezone]
|
||||
|
||||
test_drive_package = TestDrivePackage.find_by_name(test_drive_package_details[:name]) if test_drive_package_details
|
||||
|
||||
|
|
@ -1540,6 +1587,8 @@ module JamRuby
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
user.update_timezone(timezone)
|
||||
user.reload if user.id # gift card adding gifted_jamtracks doesn't reflect here until reload
|
||||
user
|
||||
end
|
||||
|
|
@ -1661,6 +1710,14 @@ module JamRuby
|
|||
"#{dir}/#{ERB::Util.url_encode(file)}"
|
||||
end
|
||||
|
||||
def permanently_delete
|
||||
original_email = self.email
|
||||
|
||||
AdminMailer.ugly({to: original_email, cc: 'support@jamkazam.com', subject:'Your account has been deleted!', body: "This will be the last email you receive from JamKazam.\n\nRegards,\nTeam JamKazam"}).deliver_now
|
||||
|
||||
User.where(id: self.id).update_all(encrypted_password: SecureRandom.uuid, email: "deleted+#{SecureRandom.uuid}@jamkazam.com", subscribe_email: false, remember_token: SecureRandom.uuid, deleted: true)
|
||||
end
|
||||
|
||||
def update_avatar(original_fpfile, cropped_fpfile, cropped_large_fpfile, crop_selection, aws_bucket)
|
||||
self.updating_avatar = true
|
||||
|
||||
|
|
@ -2479,6 +2536,35 @@ module JamRuby
|
|||
self.save!
|
||||
end
|
||||
|
||||
def mark_sent_paid_lesson
|
||||
self.stuck_take_plesson = false
|
||||
self.sent_admin_take_plesson_email_at = Time.now
|
||||
self.save!
|
||||
end
|
||||
|
||||
def mark_sent_2nd_free_lesson
|
||||
self.stuck_take_2nd_flesson = false
|
||||
self.sent_admin_take_2nd_flesson_email_at = Time.now
|
||||
self.save!
|
||||
end
|
||||
|
||||
def mark_sent_1st_free_lesson
|
||||
self.stuck_take_flesson = false
|
||||
self.sent_admin_take_flesson_email_at = Time.now
|
||||
self.save!
|
||||
end
|
||||
|
||||
def mark_onboarded
|
||||
self.onboarding_onboarded_at = Time.now
|
||||
self.save!
|
||||
end
|
||||
|
||||
def mark_lost(lost_reason = LOST_REASON_OTHER)
|
||||
self.onboarding_lost_at = Time.now
|
||||
self.onboarding_lost_reason = lost_reason
|
||||
self.save!
|
||||
end
|
||||
|
||||
def has_booked_with_student?(student, since_at = nil)
|
||||
LessonBooking.engaged_bookings(student, self, since_at).count > 0
|
||||
end
|
||||
|
|
@ -2494,7 +2580,7 @@ module JamRuby
|
|||
def computed_onboarding_status
|
||||
if first_onboarding_paid_lesson_at
|
||||
ONBOARDING_STATUS_PAID_LESSON
|
||||
elsif first_onboarding_free_lesson_at
|
||||
elsif second_onboarding_free_lesson_at || first_onboarding_free_lesson_at
|
||||
ONBOARDING_STATUS_FREE_LESSON
|
||||
elsif onboarding_onboarded_at
|
||||
ONBOARDING_STATUS_ONBOARDED
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ module JamRuby
|
|||
def self.perform
|
||||
@@log.debug("waking up")
|
||||
|
||||
Teacher.randomize_order
|
||||
|
||||
bounced_emails
|
||||
|
||||
calendar_manager = CalendarManager.new
|
||||
|
|
@ -15,6 +17,7 @@ module JamRuby
|
|||
|
||||
MusicSession.cleanup_old_sessions
|
||||
|
||||
|
||||
@@log.debug("done")
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ module JamRuby
|
|||
LessonBooking.hourly_check
|
||||
LessonSession.hourly_check
|
||||
TeacherPayment.hourly_check
|
||||
|
||||
User.hourly_check
|
||||
|
||||
@@log.debug("done")
|
||||
end
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ describe LessonSession do
|
|||
|
||||
let(:lesson_booking) { b = LessonBooking.book_normal(user, teacher, [slot1, slot2], "Hey I've heard of you before.", false, LessonBooking::PAYMENT_STYLE_SINGLE, 60); b.card_presumed_ok = true; b.save!; b }
|
||||
let(:lesson_session) { lesson_booking.lesson_sessions[0] }
|
||||
let(:td_lesson_booking) { b = LessonBooking.book_test_drive(user, teacher, [slot1, slot2], "Hey I've heard of you before."); b.card_presumed_ok = true; b.save!; b }
|
||||
let(:td_lesson_session) { td_lesson_booking.lesson_sessions[0] }
|
||||
|
||||
describe "counter" do
|
||||
describe "recurring" do
|
||||
|
|
@ -215,6 +217,21 @@ describe LessonSession do
|
|||
end
|
||||
|
||||
describe "autocancel" do
|
||||
it "returns credit" do
|
||||
|
||||
jamclass_credits = user.jamclass_credits
|
||||
|
||||
td_lesson_session.status.should eql LessonSession::STATUS_REQUESTED
|
||||
|
||||
Timecop.travel(Date.today + 10)
|
||||
|
||||
td_lesson_session.autocancel
|
||||
td_lesson_session.reload
|
||||
td_lesson_session.status.should eql LessonSession::STATUS_UNCONFIRMED
|
||||
td_lesson_session.lesson_booking.status.should eql LessonSession::STATUS_UNCONFIRMED
|
||||
user.reload
|
||||
user.jamclass_credits.should eql (jamclass_credits + 1)
|
||||
end
|
||||
it "can't autocancel in the past" do
|
||||
lesson_session.status.should eql LessonSession::STATUS_REQUESTED
|
||||
|
||||
|
|
@ -271,19 +288,6 @@ describe LessonSession do
|
|||
slow[1].should eql lesson_session1
|
||||
end
|
||||
end
|
||||
describe "least_time_left" do
|
||||
it "sorts correctly" do
|
||||
lesson_session1 = normal_lesson(user, teacher, {counter: true, counterer: user})
|
||||
lesson_session2 = normal_lesson(user, teacher, {counter: true, counterer: teacher}) # this shouldn't show up
|
||||
Timecop.travel(Date.today - 5)
|
||||
lesson_session3 = normal_lesson(user, teacher, {})
|
||||
|
||||
slow = LessonSession.unscoped.least_time_left
|
||||
slow.count.should eql 2
|
||||
slow[0].should eql lesson_session1
|
||||
slow[1].should eql lesson_session3
|
||||
end
|
||||
end
|
||||
|
||||
describe "remind_counters" do
|
||||
it "finds old requested and pokes teacher" do
|
||||
|
|
@ -472,9 +476,9 @@ describe LessonSession do
|
|||
first_lesson.is_canceled?.should be true
|
||||
second_lesson.is_canceled?.should be true
|
||||
booking.is_canceled?.should be true
|
||||
first_lesson.student_short_canceled.should be true
|
||||
first_lesson.student_canceled.should be true
|
||||
first_lesson.teacher_canceled.should be false
|
||||
first_lesson.student_short_canceled.should be true
|
||||
second_lesson.student_short_canceled.should be false
|
||||
second_lesson.student_canceled.should be true
|
||||
second_lesson.teacher_canceled.should be false
|
||||
|
|
@ -517,6 +521,226 @@ describe LessonSession do
|
|||
end
|
||||
end
|
||||
|
||||
describe "remindable_onboarding_users" do
|
||||
it "works" do
|
||||
LessonSession.remindable_onboarding_users.count.should eql 0
|
||||
|
||||
user.onboarding_onboarded_at = Time.now
|
||||
user.first_onboarding_paid_lesson_at = nil
|
||||
user.save!
|
||||
|
||||
LessonSession.remindable_onboarding_users.count.should eql 1
|
||||
|
||||
user.sent_take_plesson_email_times = 3
|
||||
user.sent_take_2nd_flesson_email_times = 3
|
||||
user.sent_take_plesson_email_times = 3
|
||||
user.save!
|
||||
|
||||
LessonSession.remindable_onboarding_users.count.should eql 0
|
||||
end
|
||||
end
|
||||
|
||||
describe "onboarding_email_reminders" do
|
||||
it "works" do
|
||||
user.onboarding_onboarded_at = Time.now
|
||||
user.first_onboarding_paid_lesson_at = nil
|
||||
user.save!
|
||||
|
||||
mailer = mock
|
||||
UserMailer.deliveries.clear
|
||||
|
||||
LessonSession.onboarding_email_reminders
|
||||
|
||||
Timecop.travel(Date.today + 3)
|
||||
mailer.should_receive(:deliver_now).once
|
||||
UserMailer.should_receive(:take_first_free_lesson).and_return(mailer)
|
||||
LessonSession.onboarding_email_reminders
|
||||
#UserMailer.deliveries.count.should eql 1
|
||||
user.reload
|
||||
user.sent_take_flesson_email_times.should eql 1
|
||||
user.sent_take_2nd_flesson_email_times.should eql 0
|
||||
user.sent_take_plesson_email_times.should eql 0
|
||||
user.stuck_take_flesson.should be_false
|
||||
user.stuck_take_2nd_flesson.should be_false
|
||||
user.stuck_take_plesson.should be_false
|
||||
#RSpec::Mocks.space.proxy_for(mailer).reset
|
||||
#RSpec::Mocks.space.proxy_for(UserMailer).reset
|
||||
UserMailer.deliveries.clear
|
||||
|
||||
LessonSession.onboarding_email_reminders
|
||||
user.reload
|
||||
user.sent_take_flesson_email_times.should eql 1
|
||||
user.sent_take_2nd_flesson_email_times.should eql 0
|
||||
user.sent_take_plesson_email_times.should eql 0
|
||||
user.stuck_take_flesson.should be_false
|
||||
user.stuck_take_2nd_flesson.should be_false
|
||||
user.stuck_take_plesson.should be_false
|
||||
#RSpec::Mocks.space.proxy_for(mailer).reset
|
||||
#RSpec::Mocks.space.proxy_for(UserMailer).reset
|
||||
UserMailer.deliveries.clear
|
||||
|
||||
Timecop.travel(Date.today + 3)
|
||||
mailer.should_receive(:deliver_now).once
|
||||
UserMailer.should_receive(:take_first_free_lesson).and_return(mailer)
|
||||
LessonSession.onboarding_email_reminders
|
||||
user.reload
|
||||
user.sent_take_flesson_email_times.should eql 2
|
||||
user.sent_take_2nd_flesson_email_times.should eql 0
|
||||
user.sent_take_plesson_email_times.should eql 0
|
||||
user.stuck_take_flesson.should be_false
|
||||
user.stuck_take_2nd_flesson.should be_false
|
||||
user.stuck_take_plesson.should be_false
|
||||
#RSpec::Mocks.space.proxy_for(mailer).reset
|
||||
#RSpec::Mocks.space.proxy_for(UserMailer).reset
|
||||
UserMailer.deliveries.clear
|
||||
|
||||
Timecop.travel(Date.today + 3)
|
||||
mailer.should_receive(:deliver_now).once
|
||||
UserMailer.should_receive(:take_first_free_lesson).and_return(mailer)
|
||||
LessonSession.onboarding_email_reminders
|
||||
user.reload
|
||||
user.sent_take_flesson_email_times.should eql 3
|
||||
user.sent_take_2nd_flesson_email_times.should eql 0
|
||||
user.sent_take_plesson_email_times.should eql 0
|
||||
user.stuck_take_flesson.should be_false
|
||||
user.stuck_take_2nd_flesson.should be_false
|
||||
user.stuck_take_plesson.should be_false
|
||||
#RSpec::Mocks.space.proxy_for(mailer).reset
|
||||
#RSpec::Mocks.space.proxy_for(UserMailer).reset
|
||||
UserMailer.deliveries.clear
|
||||
|
||||
Timecop.travel(Date.today + 3)
|
||||
LessonSession.onboarding_email_reminders
|
||||
user.reload
|
||||
user.sent_take_flesson_email_times.should eql 3
|
||||
user.sent_take_2nd_flesson_email_times.should eql 0
|
||||
user.sent_take_plesson_email_times.should eql 0
|
||||
user.stuck_take_flesson.should be_true
|
||||
user.stuck_take_2nd_flesson.should be_false
|
||||
user.stuck_take_plesson.should be_false
|
||||
#RSpec::Mocks.space.proxy_for(mailer).reset
|
||||
#RSpec::Mocks.space.proxy_for(UserMailer).reset
|
||||
UserMailer.deliveries.clear
|
||||
|
||||
user.first_onboarding_free_lesson_at = Time.now
|
||||
user.save!
|
||||
|
||||
LessonSession.onboarding_email_reminders
|
||||
user.reload
|
||||
user.sent_take_flesson_email_times.should eql 3
|
||||
user.sent_take_2nd_flesson_email_times.should eql 0
|
||||
user.sent_take_plesson_email_times.should eql 0
|
||||
user.stuck_take_flesson.should be_false
|
||||
user.stuck_take_2nd_flesson.should be_false
|
||||
user.stuck_take_plesson.should be_false
|
||||
|
||||
Timecop.travel(Date.today + 3)
|
||||
mailer.should_receive(:deliver_now).once
|
||||
UserMailer.should_receive(:take_second_free_lesson).and_return(mailer)
|
||||
LessonSession.onboarding_email_reminders
|
||||
user.reload
|
||||
user.sent_take_flesson_email_times.should eql 3
|
||||
user.sent_take_2nd_flesson_email_times.should eql 1
|
||||
user.sent_take_plesson_email_times.should eql 0
|
||||
user.stuck_take_flesson.should be_false
|
||||
user.stuck_take_2nd_flesson.should be_false
|
||||
user.stuck_take_plesson.should be_false
|
||||
|
||||
Timecop.travel(Date.today + 3)
|
||||
mailer.should_receive(:deliver_now).once
|
||||
UserMailer.should_receive(:take_second_free_lesson).and_return(mailer)
|
||||
LessonSession.onboarding_email_reminders
|
||||
user.reload
|
||||
user.sent_take_flesson_email_times.should eql 3
|
||||
user.sent_take_2nd_flesson_email_times.should eql 2
|
||||
user.sent_take_plesson_email_times.should eql 0
|
||||
user.stuck_take_flesson.should be_false
|
||||
user.stuck_take_2nd_flesson.should be_false
|
||||
user.stuck_take_plesson.should be_false
|
||||
|
||||
Timecop.travel(Date.today + 3)
|
||||
mailer.should_receive(:deliver_now).once
|
||||
UserMailer.should_receive(:take_second_free_lesson).and_return(mailer)
|
||||
LessonSession.onboarding_email_reminders
|
||||
user.reload
|
||||
user.sent_take_flesson_email_times.should eql 3
|
||||
user.sent_take_2nd_flesson_email_times.should eql 3
|
||||
user.sent_take_plesson_email_times.should eql 0
|
||||
user.stuck_take_flesson.should be_false
|
||||
user.stuck_take_2nd_flesson.should be_false
|
||||
user.stuck_take_plesson.should be_false
|
||||
|
||||
Timecop.travel(Date.today + 3)
|
||||
LessonSession.onboarding_email_reminders
|
||||
user.reload
|
||||
user.sent_take_flesson_email_times.should eql 3
|
||||
user.sent_take_2nd_flesson_email_times.should eql 3
|
||||
user.sent_take_plesson_email_times.should eql 0
|
||||
user.stuck_take_flesson.should be_false
|
||||
user.stuck_take_2nd_flesson.should be_true
|
||||
user.stuck_take_plesson.should be_false
|
||||
|
||||
user.second_onboarding_free_lesson_at = Time.now
|
||||
user.save!
|
||||
|
||||
LessonSession.onboarding_email_reminders
|
||||
user.reload
|
||||
user.sent_take_flesson_email_times.should eql 3
|
||||
user.sent_take_2nd_flesson_email_times.should eql 3
|
||||
user.sent_take_plesson_email_times.should eql 0
|
||||
user.stuck_take_flesson.should be_false
|
||||
user.stuck_take_2nd_flesson.should be_false
|
||||
user.stuck_take_plesson.should be_false
|
||||
|
||||
Timecop.travel(Date.today + 3)
|
||||
mailer.should_receive(:deliver_now).once
|
||||
UserMailer.should_receive(:take_paid_lesson).and_return(mailer)
|
||||
LessonSession.onboarding_email_reminders
|
||||
user.reload
|
||||
user.sent_take_flesson_email_times.should eql 3
|
||||
user.sent_take_2nd_flesson_email_times.should eql 3
|
||||
user.sent_take_plesson_email_times.should eql 1
|
||||
user.stuck_take_flesson.should be_false
|
||||
user.stuck_take_2nd_flesson.should be_false
|
||||
user.stuck_take_plesson.should be_false
|
||||
|
||||
Timecop.travel(Date.today + 3)
|
||||
mailer.should_receive(:deliver_now).once
|
||||
UserMailer.should_receive(:take_paid_lesson).and_return(mailer)
|
||||
LessonSession.onboarding_email_reminders
|
||||
user.reload
|
||||
user.sent_take_flesson_email_times.should eql 3
|
||||
user.sent_take_2nd_flesson_email_times.should eql 3
|
||||
user.sent_take_plesson_email_times.should eql 2
|
||||
user.stuck_take_flesson.should be_false
|
||||
user.stuck_take_2nd_flesson.should be_false
|
||||
user.stuck_take_plesson.should be_false
|
||||
|
||||
Timecop.travel(Date.today + 3)
|
||||
mailer.should_receive(:deliver_now).once
|
||||
UserMailer.should_receive(:take_paid_lesson).and_return(mailer)
|
||||
LessonSession.onboarding_email_reminders
|
||||
user.reload
|
||||
user.sent_take_flesson_email_times.should eql 3
|
||||
user.sent_take_2nd_flesson_email_times.should eql 3
|
||||
user.sent_take_plesson_email_times.should eql 3
|
||||
user.stuck_take_flesson.should be_false
|
||||
user.stuck_take_2nd_flesson.should be_false
|
||||
user.stuck_take_plesson.should be_false
|
||||
|
||||
Timecop.travel(Date.today + 3)
|
||||
LessonSession.onboarding_email_reminders
|
||||
user.reload
|
||||
user.sent_take_flesson_email_times.should eql 3
|
||||
user.sent_take_2nd_flesson_email_times.should eql 3
|
||||
user.sent_take_plesson_email_times.should eql 3
|
||||
user.stuck_take_flesson.should be_false
|
||||
user.stuck_take_2nd_flesson.should be_false
|
||||
user.stuck_take_plesson.should be_true
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
describe "index" do
|
||||
it "finds single lesson as student" do
|
||||
|
||||
|
|
|
|||
|
|
@ -28,18 +28,18 @@ describe Teacher do
|
|||
|
||||
|
||||
teacher2 = FactoryGirl.create(:teacher, ready_for_session_at: Time.now)
|
||||
teacher2.top_rated = false
|
||||
teacher2.random_order = 1
|
||||
teacher2.save!
|
||||
|
||||
|
||||
teacher1 = FactoryGirl.create(:teacher, ready_for_session_at: Time.now)
|
||||
teacher1.top_rated = true
|
||||
teacher1.random_order = 2
|
||||
teacher1.save!
|
||||
|
||||
query = Teacher.index(nil, {})[:query]
|
||||
query.count.should eql 3
|
||||
query[0].should eq(teacher1.user)
|
||||
query[1].should eq(teacher2.user)
|
||||
query[0].should eq(teacher2.user)
|
||||
query[1].should eq(teacher1.user)
|
||||
query[2].should eq(teacher3.user)
|
||||
end
|
||||
|
||||
|
|
@ -228,8 +228,8 @@ describe Teacher do
|
|||
end
|
||||
|
||||
it "student only sees guitar center teachers" do
|
||||
teacher = FactoryGirl.create(:teacher, ready_for_session_at: Time.now)
|
||||
gc_teacher = FactoryGirl.create(:teacher, school: @gc_school, ready_for_session_at: Time.now)
|
||||
teacher = FactoryGirl.create(:teacher, ready_for_session_at: Time.now, random_order: 1)
|
||||
gc_teacher = FactoryGirl.create(:teacher, school: @gc_school, ready_for_session_at: Time.now, random_order: 2)
|
||||
|
||||
# TODO: perhaps GC teachers should not come back to non-GC users. Not sure yet.
|
||||
query = Teacher.index(user, {})[:query]
|
||||
|
|
|
|||
|
|
@ -931,6 +931,78 @@ describe User do
|
|||
end
|
||||
end
|
||||
end
|
||||
describe "onboarding_status" do
|
||||
let(:user) {FactoryGirl.create(:user)}
|
||||
|
||||
it "onboarded" do
|
||||
user.send_onboarding_survey.should be_false
|
||||
user.onboarding_onboarded_at = Time.now
|
||||
user.save!
|
||||
user.send_onboarding_survey.should be_true
|
||||
user.onboarding_status = User::ONBOARDING_STATUS_ONBOARDED
|
||||
end
|
||||
|
||||
it "lost" do
|
||||
user.send_onboarding_survey.should be_false
|
||||
user.onboarding_lost_reason = User::LOST_REASON_NO_VIDEO_STREAM
|
||||
user.save!
|
||||
user.send_onboarding_survey.should be_true
|
||||
user.onboarding_status = User::ONBOARDING_STATUS_LOST
|
||||
end
|
||||
|
||||
it "escalated" do
|
||||
user.send_onboarding_survey.should be_false
|
||||
user.onboarding_escalation_reason = User::ESCALATION_REASON_NO_VIDEO_STREAM
|
||||
user.save!
|
||||
user.send_onboarding_survey.should be_true
|
||||
user.onboarding_status = User::ONBOARDING_STATUS_ESCALATED
|
||||
end
|
||||
|
||||
it "taken free lesson" do
|
||||
user.send_onboarding_survey.should be_false
|
||||
user.first_onboarding_free_lesson_at = Time.now
|
||||
user.save!
|
||||
user.send_onboarding_survey.should be_false
|
||||
user.onboarding_status = User::ONBOARDING_STATUS_FREE_LESSON
|
||||
end
|
||||
|
||||
it "paid lesson" do
|
||||
user.send_onboarding_survey.should be_false
|
||||
user.first_onboarding_paid_lesson_at = Time.now
|
||||
user.save!
|
||||
user.send_onboarding_survey.should be_false
|
||||
user.onboarding_status = User::ONBOARDING_STATUS_PAID_LESSON
|
||||
end
|
||||
|
||||
it "assigned" do
|
||||
user.send_onboarding_survey.should be_false
|
||||
user.onboarder = FactoryGirl.create(:user, is_onboarder:true)
|
||||
user.save!
|
||||
user.send_onboarding_survey.should be_false
|
||||
user.onboarding_status = User::ONBOARDING_STATUS_ASSIGNED
|
||||
end
|
||||
|
||||
end
|
||||
describe "send_onboarding_surveys" do
|
||||
let(:user) {FactoryGirl.create(:user)}
|
||||
|
||||
it "works" do
|
||||
UserMailer.deliveries.clear
|
||||
user.send_onboarding_survey = true
|
||||
user.save!
|
||||
|
||||
User.send_onboarding_surveys
|
||||
|
||||
UserMailer.deliveries.count.should eql 1
|
||||
user.reload
|
||||
user.send_onboarding_survey.should be_true
|
||||
user.sent_onboarding_survey_at.should_not be_nil
|
||||
|
||||
UserMailer.deliveries.clear
|
||||
User.send_onboarding_surveys
|
||||
UserMailer.deliveries.count.should eql 0
|
||||
end
|
||||
end
|
||||
=begin
|
||||
describe "update avatar" do
|
||||
|
||||
|
|
|
|||
|
|
@ -210,6 +210,119 @@ describe "RenderMailers", :slow => true do
|
|||
UserMailer.deliveries.clear
|
||||
UserMailer.student_no_comm_other(lesson.lesson_booking, true).deliver_now
|
||||
end
|
||||
|
||||
it "take_first_free_lesson 1" do
|
||||
@filename = "take_first_free_lesson_1"
|
||||
|
||||
user.sent_take_flesson_email_times = 0
|
||||
user.save!
|
||||
|
||||
UserMailer.deliveries.clear
|
||||
UserMailer.take_first_free_lesson(user).deliver_now
|
||||
end
|
||||
|
||||
it "take_first_free_lesson 2" do
|
||||
@filename = "take_first_free_lesson_2"
|
||||
|
||||
user.sent_take_flesson_email_times = 1
|
||||
user.save!
|
||||
|
||||
UserMailer.deliveries.clear
|
||||
UserMailer.take_first_free_lesson(user).deliver_now
|
||||
end
|
||||
|
||||
it "take_first_free_lesson 3" do
|
||||
@filename = "take_first_free_lesson_3"
|
||||
|
||||
user.sent_take_flesson_email_times = 2
|
||||
user.save!
|
||||
|
||||
UserMailer.deliveries.clear
|
||||
UserMailer.take_first_free_lesson(user).deliver_now
|
||||
end
|
||||
|
||||
it "take_second_free_lesson 1" do
|
||||
@filename = "take_second_free_lesson_1"
|
||||
|
||||
user.sent_take_2nd_flesson_email_times = 0
|
||||
user.save!
|
||||
|
||||
lesson = testdrive_lesson(user, teacher)
|
||||
|
||||
|
||||
UserMailer.deliveries.clear
|
||||
UserMailer.take_second_free_lesson(user).deliver_now
|
||||
end
|
||||
|
||||
it "take_second_free_lesson 2" do
|
||||
@filename = "take_second_free_lesson_2"
|
||||
|
||||
user.sent_take_2nd_flesson_email_times = 1
|
||||
user.save!
|
||||
|
||||
lesson = testdrive_lesson(user, teacher)
|
||||
|
||||
UserMailer.deliveries.clear
|
||||
UserMailer.take_second_free_lesson(user).deliver_now
|
||||
end
|
||||
|
||||
it "take_second_free_lesson 3" do
|
||||
@filename = "take_second_free_lesson_3"
|
||||
|
||||
user.sent_take_2nd_flesson_email_times = 2
|
||||
user.save!
|
||||
|
||||
lesson = testdrive_lesson(user, teacher)
|
||||
|
||||
UserMailer.deliveries.clear
|
||||
UserMailer.take_second_free_lesson(user).deliver_now
|
||||
end
|
||||
|
||||
it "take_paid_lesson 1" do
|
||||
@filename = "take_paid_lesson_1"
|
||||
|
||||
user.sent_take_plesson_email_times = 0
|
||||
user.save!
|
||||
|
||||
lesson = testdrive_lesson(user, teacher)
|
||||
lesson = testdrive_lesson(user, teacher)
|
||||
|
||||
|
||||
UserMailer.deliveries.clear
|
||||
UserMailer.take_paid_lesson(user).deliver_now
|
||||
end
|
||||
|
||||
it "take_paid_lesson 2" do
|
||||
@filename = "take_paid_lesson_2"
|
||||
|
||||
user.sent_take_plesson_email_times = 1
|
||||
user.save!
|
||||
|
||||
lesson = testdrive_lesson(user, teacher)
|
||||
lesson = testdrive_lesson(user, teacher)
|
||||
|
||||
UserMailer.deliveries.clear
|
||||
UserMailer.take_paid_lesson(user).deliver_now
|
||||
end
|
||||
|
||||
it "take_paid_lesson 3" do
|
||||
@filename = "take_paid_lesson_3"
|
||||
|
||||
user.sent_take_plesson_email_times = 2
|
||||
user.save!
|
||||
|
||||
lesson = testdrive_lesson(user, teacher)
|
||||
lesson = testdrive_lesson(user, teacher)
|
||||
|
||||
UserMailer.deliveries.clear
|
||||
UserMailer.take_paid_lesson(user).deliver_now
|
||||
end
|
||||
|
||||
it "onboarding_survey" do
|
||||
@filename = "onboarding_survey"
|
||||
UserMailer.deliveries.clear
|
||||
UserMailer.onboarding_survey(user).deliver_now
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
//= require jquery.monkeypatch
|
||||
//= require jquery_ujs
|
||||
//= require jquery.cookie
|
||||
//= require jstz
|
||||
//= require AAC_underscore
|
||||
//= require AAA_Log
|
||||
//= require globals
|
||||
|
|
|
|||
|
|
@ -45,8 +45,13 @@
|
|||
|
||||
trackScreenChanges();
|
||||
|
||||
setTimezone()
|
||||
})
|
||||
|
||||
function setTimezone() {
|
||||
$.cookie("browser.timezone", window.jstz.determine().name(), { expires: 365, path: '/' });
|
||||
}
|
||||
|
||||
$(document).on('JAMKAZAM_READY', function() {
|
||||
// this event is fired when context.app is initialized
|
||||
|
||||
|
|
@ -99,6 +104,10 @@
|
|||
|
||||
function initializeDialogs(app) {
|
||||
|
||||
if(!JK.Banner) {
|
||||
// we don't use dialogs everywhere (yes, ugly)
|
||||
return
|
||||
}
|
||||
var backendAlerts = new JK.BackendAlerts(app);
|
||||
backendAlerts.initialize();
|
||||
|
||||
|
|
|
|||
|
|
@ -495,7 +495,7 @@
|
|||
*/
|
||||
function loadAudioDrivers() {
|
||||
var drivers = context.jamClient.FTUEGetDevices(false);
|
||||
var chatDrivers = jamClient.FTUEGetChatInputs();
|
||||
var chatDrivers = jamClient.FTUEGetChatInputs(false, false);
|
||||
var optionsHtml = '<option selected="selected" value="">Choose...</option>';
|
||||
var chatOptionsHtml = '<option selected="selected" value="">Choose...</option>';
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
//= require jquery.manageVsts
|
||||
//= require jquery.lessonSessionActions
|
||||
//= require jquery.jamblasterOptions
|
||||
//= require jstz
|
||||
//= require ResizeSensor
|
||||
//= require AAA_Log
|
||||
//= require AAC_underscore
|
||||
|
|
|
|||
|
|
@ -149,8 +149,14 @@ profileUtils = context.JK.ProfileUtils
|
|||
value = $target.val()
|
||||
options = {id: id}
|
||||
options[field] = value
|
||||
@postUpdate(field, value)
|
||||
@queueUpdate(options)
|
||||
|
||||
postUpdate: (field, value) ->
|
||||
if field == 'onboarding_onboarded_at'
|
||||
console.log("onboarding onboarded at set")
|
||||
context.JK.Banner.showAlert({title: "One Last Thing", html: "Please send this student Email #5 right now.<br/><br/>This is a critical email, and if you don't send it now, you'll forget. Thanks!"});
|
||||
|
||||
queueUpdate: (update) ->
|
||||
@updates.push(update)
|
||||
@onUpdate()
|
||||
|
|
|
|||
|
|
@ -379,6 +379,7 @@ UserStore = context.UserStore
|
|||
<label>Time:</label>
|
||||
<select className="hour">{hours}</select> : <select className="minute">{minutes}</select> <select
|
||||
className="am_pm">{am_pm}</select>
|
||||
<span className="tz-notice">{window.JK.currentTimezone()}</span>
|
||||
</div>
|
||||
{slot1Errors}
|
||||
</div>
|
||||
|
|
@ -393,7 +394,9 @@ UserStore = context.UserStore
|
|||
<label>Time:</label>
|
||||
<select className="hour">{hours}</select> : <select className="minute">{minutes}</select> <select
|
||||
className="am_pm">{am_pm}</select>
|
||||
<span className="tz-notice">{window.JK.currentTimezone()}</span>
|
||||
</div>
|
||||
|
||||
{slot2Errors}
|
||||
</div>
|
||||
</div>`
|
||||
|
|
|
|||
|
|
@ -464,6 +464,10 @@ UserStore = context.UserStore
|
|||
isSuspended: () ->
|
||||
@state.booking?.status == 'suspended'
|
||||
|
||||
isUnconfirmed: () ->
|
||||
@state.booking?.status == 'unconfirmed'
|
||||
|
||||
|
||||
isStudentCountered: () ->
|
||||
@counteredSlot()?['is_student_created?']
|
||||
|
||||
|
|
@ -774,6 +778,11 @@ UserStore = context.UserStore
|
|||
header = 'This lesson has been suspended'
|
||||
content = @renderTeacherSuspended()
|
||||
|
||||
else if @isUnconfirmed()
|
||||
|
||||
header = 'This lesson has been automatically canceled'
|
||||
content = @renderTeacherUnconfirmed()
|
||||
|
||||
return `<div className="content-body-scroller">
|
||||
<Nav/>
|
||||
|
||||
|
|
@ -814,6 +823,10 @@ UserStore = context.UserStore
|
|||
|
||||
content = @renderStudentCanceled()
|
||||
|
||||
else if @isUnconfirmed()
|
||||
header = 'this lesson has been automatically canceled'
|
||||
content = @renderStudentUnconfirmed()
|
||||
|
||||
else if @isSuspended()
|
||||
|
||||
header = 'this lesson has been suspended'
|
||||
|
|
@ -961,6 +974,11 @@ UserStore = context.UserStore
|
|||
|
||||
# <p className="description">Message from {this.other().first_name}:</p>
|
||||
# <div className="message"></div>
|
||||
|
||||
renderStudentUnconfirmed: () ->
|
||||
@renderUnconfirmed()
|
||||
|
||||
|
||||
renderStudentCountered: () ->
|
||||
@renderCountered()
|
||||
|
||||
|
|
@ -1049,9 +1067,15 @@ UserStore = context.UserStore
|
|||
|
||||
renderTeacherSuspended: () ->
|
||||
|
||||
renderTeacherUnconfirmed: () ->
|
||||
@renderUnconfirmed()
|
||||
|
||||
renderTeacherCountered: () ->
|
||||
@renderCountered()
|
||||
|
||||
renderUnconfirmed: () ->
|
||||
action = `<p>The JamKazam system has canceled this request because it was never acknowledged after too long of a time.</p>`
|
||||
|
||||
renderCanceled: () ->
|
||||
canceler = @canceler()
|
||||
myself = @myself()
|
||||
|
|
@ -1071,6 +1095,7 @@ UserStore = context.UserStore
|
|||
else
|
||||
action = `<p>You declined this lesson request.</p>`
|
||||
|
||||
|
||||
if @studentViewing()
|
||||
|
||||
if @adminCanceled() || @studentCanceled()
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
//= require jquery.scrollTo
|
||||
//= require jquery.pulse
|
||||
//= require howler.core.js
|
||||
//= require jstz
|
||||
//= require ResizeSensor
|
||||
//= require AAA_Log
|
||||
//= require AAC_underscore
|
||||
|
|
|
|||
|
|
@ -354,7 +354,31 @@
|
|||
|
||||
var musicPorts = jamClient.FTUEGetChannels();
|
||||
//var chatsOnCurrentDevice = context.jamClient.FTUEGetChatInputs(true);
|
||||
var chatsOnOtherDevices = context.jamClient.FTUEGetChatInputs(false);
|
||||
var chatsOnOtherDevices = context.jamClient.FTUEGetChatInputs(false, true);
|
||||
|
||||
// remove all virtual/remote junk form chat inputs. Their key contains' JamKazam when it's Virtual Input or Remote
|
||||
Object.keys(chatsOnOtherDevices).forEach(function(key) {
|
||||
if(key.indexOf('JamKazam') > -1) {
|
||||
delete chatsOnOtherDevices[key]
|
||||
}
|
||||
} )
|
||||
|
||||
// this wasapi logic is this: if there are any non-WASAPI items, present only them, because WASAPI is very high latency and
|
||||
// highly desirable. But if the user ONLY has wasapi, then fine, we show them (by not deleting them from the list)
|
||||
var allWasapi = true;
|
||||
context._.each(chatsOnOtherDevices, function (chatChannelName, chatChannelId) {
|
||||
if(chatChannelName.indexOf('WASAPI') == -1) {
|
||||
allWasapi = false;
|
||||
return false
|
||||
}
|
||||
})
|
||||
if(!allWasapi) {
|
||||
Object.keys(chatsOnOtherDevices).forEach(function(key) {
|
||||
if(chatsOnOtherDevices[key].indexOf('WASAPI') > -1) {
|
||||
// delete chatsOnOtherDevices[key]
|
||||
}
|
||||
} )
|
||||
}
|
||||
|
||||
var chatInputs = [];
|
||||
//context._.each(musicPorts.inputs, function(input) {
|
||||
|
|
|
|||
|
|
@ -10,4 +10,5 @@ div[data-react-class="BookLesson"] {
|
|||
@include border_box_sizing;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,6 +67,10 @@
|
|||
input {
|
||||
display:inline-block;
|
||||
}
|
||||
|
||||
.tz-notice {
|
||||
margin-left: 15px;
|
||||
}
|
||||
textarea {
|
||||
width:100%;
|
||||
@include border_box_sizing;
|
||||
|
|
|
|||
|
|
@ -35,6 +35,34 @@
|
|||
transition: .4s;
|
||||
}
|
||||
|
||||
.slider .off-label {
|
||||
color:white;
|
||||
position: absolute;
|
||||
right: 4px;
|
||||
top: 4px;
|
||||
font-weight: bold;
|
||||
display:inline;
|
||||
-webkit-transition: .4s;
|
||||
transition: .4s;
|
||||
}
|
||||
.slider .on-label{
|
||||
position: absolute;
|
||||
left: 3px;
|
||||
top: 4px;
|
||||
display:none;
|
||||
-webkit-transition: .4s;
|
||||
transition: .4s;
|
||||
color:white;
|
||||
font-weight: bold;
|
||||
}
|
||||
input:checked + .slider .on-label {
|
||||
display:inline;
|
||||
}
|
||||
input:checked + .slider .off-label {
|
||||
display:none;
|
||||
}
|
||||
|
||||
|
||||
input:checked + .slider {
|
||||
background-color: $ColorScreenPrimary;
|
||||
}
|
||||
|
|
@ -49,6 +77,12 @@ input:checked + .slider:before {
|
|||
transform: translateX(26px);
|
||||
}
|
||||
|
||||
input:checked + .slider:before {
|
||||
-webkit-transform: translateX(26px);
|
||||
-ms-transform: translateX(26px);
|
||||
transform: translateX(26px);
|
||||
}
|
||||
|
||||
/* Rounded sliders */
|
||||
.slider.round {
|
||||
border-radius: 34px;
|
||||
|
|
|
|||
|
|
@ -40,7 +40,8 @@ class ApiRecurlyController < ApiController
|
|||
location: {:country => billing_info[:country], :state => billing_info[:state], :city => billing_info[:city]},
|
||||
reuse_card: reuse_card_next_time,
|
||||
affiliate_referral_id: cookies[:affiliate_visitor],
|
||||
origin: origin_cookie
|
||||
origin: origin_cookie,
|
||||
timezone: current_timezone
|
||||
}
|
||||
|
||||
options = User.musician_defaults(request.remote_ip, ApplicationHelper.base_uri(request) + "/confirm", any_user, options)
|
||||
|
|
|
|||
|
|
@ -124,7 +124,8 @@ class ApiUsersController < ApiController
|
|||
education_interest: params[:education_interest],
|
||||
affiliate_referral_id: cookies[:affiliate_visitor],
|
||||
origin: origin_cookie,
|
||||
test_drive_package: params[:test_drive_package]
|
||||
test_drive_package: params[:test_drive_package],
|
||||
timezone: current_timezone
|
||||
}
|
||||
|
||||
options = User.musician_defaults(request.remote_ip, ApplicationHelper.base_uri(request) + "/confirm", any_user, options)
|
||||
|
|
|
|||
|
|
@ -567,6 +567,7 @@ class LandingsController < ApplicationController
|
|||
render 'amazon_lessons_promo_2', layout: 'basic'
|
||||
else
|
||||
|
||||
@current_user.update_timezone(current_timezone)
|
||||
body = "Name: #{@current_user.name}\n"
|
||||
body << "Email: #{@current_user.email}\n"
|
||||
body << "Admin: #{@current_user.admin_onboarding_url}\n"
|
||||
|
|
@ -588,7 +589,6 @@ class LandingsController < ApplicationController
|
|||
@terms = terms_of_service ? "checked" : nil
|
||||
@under13 = under_13 ? "checked" : nil
|
||||
|
||||
|
||||
# try to signup now
|
||||
@user = UserManager.new.signup(remote_ip: request.remote_ip,
|
||||
email: params[:email],
|
||||
|
|
@ -599,6 +599,7 @@ class LandingsController < ApplicationController
|
|||
under_13: under_13,
|
||||
skip_recaptcha: true,
|
||||
musician: true,
|
||||
timezone: current_timezone,
|
||||
instruments: [{:instrument_id => 'other', :proficiency_level => 1, :priority => 1}])
|
||||
if @user.errors.any?
|
||||
first = @user.errors.first
|
||||
|
|
|
|||
|
|
@ -105,6 +105,7 @@ class SessionsController < ApplicationController
|
|||
first_name: auth_hash[:info][:first_name],
|
||||
last_name: auth_hash[:info][:last_name],
|
||||
email: auth_hash[:info][:email],
|
||||
timezone: current_timezone,
|
||||
affiliate_referral_id: cookies[:affiliate_visitor])
|
||||
|
||||
# Users who sign up using oauth are presumed to have valid email adddresses.
|
||||
|
|
@ -180,7 +181,8 @@ class SessionsController < ApplicationController
|
|||
terms_of_service: true,
|
||||
location: {:country => nil, :state => nil, :city => nil},
|
||||
affiliate_referral_id: cookies[:affiliate_visitor],
|
||||
origin: origin_cookie
|
||||
origin: origin_cookie,
|
||||
timezone: current_timezone
|
||||
}
|
||||
|
||||
options = User.musician_defaults(request.remote_ip, ApplicationHelper.base_uri(request) + "/confirm", any_user, options)
|
||||
|
|
|
|||
|
|
@ -172,6 +172,7 @@ class UsersController < ApplicationController
|
|||
signup_confirm_url: ApplicationHelper.base_uri(request) + "/confirm",
|
||||
affiliate_referral_id: cookies[:affiliate_visitor],
|
||||
affiliate_partner: @affiliate_partner,
|
||||
timezone: current_timezone,
|
||||
origin: origin_cookie)
|
||||
|
||||
# check for errors
|
||||
|
|
|
|||
|
|
@ -71,11 +71,11 @@ module MusicSessionHelper
|
|||
end
|
||||
|
||||
def pretty_scheduled_start(music_session, with_timezone, shorter = false)
|
||||
music_session.pretty_scheduled_start(with_timezone, shorter)
|
||||
music_session.pretty_scheduled_start(with_timezone, shorter, current_timezone)
|
||||
end
|
||||
|
||||
def pretty_scheduled_start_slot(slot, with_timezone)
|
||||
slot.pretty_scheduled_start(with_timezone)
|
||||
slot.pretty_scheduled_start(with_timezone, current_timezone)
|
||||
end
|
||||
|
||||
def timezone_options
|
||||
|
|
|
|||
|
|
@ -69,6 +69,10 @@ module SessionsHelper
|
|||
@current_user ||= User.find_by_remember_token(cookies[:remember_token])
|
||||
end
|
||||
|
||||
def current_timezone
|
||||
@current_timezone ||= cookies[:'browser.timezone'] || any_user.timezone
|
||||
end
|
||||
|
||||
def anonymous_user=(anonymous_user)
|
||||
@anonymous_user = anonymous_user
|
||||
end
|
||||
|
|
|
|||
|
|
@ -3,22 +3,48 @@ object @lesson_booking
|
|||
attributes :id, :status, :lesson_type, :payment_style, :recurring, :teacher_id, :description, :lesson_length, :created_at, :user_id, :active, :accepter_id, :canceler_id, :cancel_message, :booked_price, :card_presumed_ok, :no_slots, :posa_card_id, :posa_card_purchased, :remaining_roll_forward_amount_in_cents, :canceled_by_admin
|
||||
|
||||
child(:lesson_booking_slots => :slots) {
|
||||
attributes :id, :preferred_day, :day_of_week, :hour, :minute, :slot_type, :pretty_scheduled_start, :message, :pretty_start_time, :proposer_id, :is_student_created?, :is_teacher_created?, :timezone, :pretty_timezone, :from_package
|
||||
attributes :id, :preferred_day, :day_of_week, :hour, :minute, :slot_type, :message, :proposer_id, :is_student_created?, :is_teacher_created?, :timezone, :pretty_timezone, :from_package
|
||||
|
||||
node :pretty_start_time do |slot|
|
||||
slot.pretty_start_time(true, current_timezone)
|
||||
end
|
||||
|
||||
node :pretty_scheduled_start do |slot|
|
||||
slot.pretty_scheduled_start(true, current_timezone)
|
||||
end
|
||||
}
|
||||
|
||||
child(:default_slot => :default_slot) {
|
||||
attributes :id, :preferred_day, :day_of_week, :hour, :minute, :slot_type, :pretty_scheduled_start, :message, :pretty_start_time, :proposer_id, :is_student_created?, :is_teacher_created?, :timezone, :pretty_timezone, :from_package
|
||||
attributes :id, :preferred_day, :day_of_week, :hour, :minute, :slot_type, :message, :proposer_id, :is_student_created?, :is_teacher_created?, :timezone, :pretty_timezone, :from_package
|
||||
node :pretty_start_time do |slot|
|
||||
slot.pretty_start_time(true, current_timezone)
|
||||
end
|
||||
node :pretty_scheduled_start do |slot|
|
||||
slot.pretty_scheduled_start(true, current_timezone)
|
||||
end
|
||||
}
|
||||
|
||||
child(:alt_slot => :alt_slot) {
|
||||
attributes :id, :preferred_day, :day_of_week, :hour, :minute, :slot_type, :pretty_scheduled_start, :message, :pretty_start_time, :proposer_id, :is_student_created?, :is_teacher_created?, :timezone, :pretty_timezone, :from_package
|
||||
attributes :id, :preferred_day, :day_of_week, :hour, :minute, :slot_type, :message, :proposer_id, :is_student_created?, :is_teacher_created?, :timezone, :pretty_timezone, :from_package
|
||||
node :pretty_start_time do |slot|
|
||||
slot.pretty_start_time(true, current_timezone)
|
||||
end
|
||||
node :pretty_scheduled_start do |slot|
|
||||
slot.pretty_scheduled_start(true, current_timezone)
|
||||
end
|
||||
}
|
||||
|
||||
child(:counter_slot => :counter_slot) {
|
||||
attributes :id, :preferred_day, :day_of_week, :hour, :minute, :slot_type, :pretty_scheduled_start, :message, :pretty_start_time, :proposer_id, :is_student_created?, :is_teacher_created?, :timezone, :pretty_timezone, :from_package, :is_recurring?
|
||||
attributes :id, :preferred_day, :day_of_week, :hour, :minute, :slot_type, :message, :proposer_id, :is_student_created?, :is_teacher_created?, :timezone, :pretty_timezone, :from_package, :is_recurring?
|
||||
node :pretty_scheduled_start_with_timezone do |slot|
|
||||
pretty_scheduled_start_slot(slot, true)
|
||||
end
|
||||
pretty_scheduled_start_slot(slot, true)
|
||||
end
|
||||
node :pretty_start_time do |slot|
|
||||
slot.pretty_start_time(true, current_timezone)
|
||||
end
|
||||
node :pretty_scheduled_start do |slot|
|
||||
slot.pretty_scheduled_start(true, current_timezone)
|
||||
end
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -20,10 +20,16 @@ child(:lesson_booking => :lesson_booking) {
|
|||
|
||||
|
||||
child(:counter_slot => :counter_slot) {
|
||||
attributes :id, :preferred_day, :day_of_week, :hour, :minute, :slot_type, :pretty_scheduled_start, :message, :pretty_start_time, :proposer_id, :is_student_created?, :is_teacher_created?, :timezone, :pretty_timezone, :from_package, :is_recurring?
|
||||
attributes :id, :preferred_day, :day_of_week, :hour, :minute, :slot_type, :message, :proposer_id, :is_student_created?, :is_teacher_created?, :timezone, :pretty_timezone, :from_package, :is_recurring?
|
||||
node :pretty_scheduled_start_with_timezone do |slot|
|
||||
pretty_scheduled_start_slot(slot, true)
|
||||
end
|
||||
node :pretty_start_time do |slot|
|
||||
slot.pretty_start_time(true, current_timezone)
|
||||
end
|
||||
node :pretty_scheduled_start do |slot|
|
||||
slot.pretty_scheduled_start(true, current_timezone)
|
||||
end
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
object @user
|
||||
|
||||
attributes :id, :first_name, :last_name, :name, :city, :state, :country, :location, :online, :photo_url, :musician, :gender, :birth_date, :internet_service_provider, :friend_count, :liker_count, :like_count, :follower_count, :following_count,
|
||||
:recording_count, :session_count, :biography, :favorite_count, :audio_latency, :upcoming_session_count, :age, :website, :skill_level, :reuse_card, :email_needs_verification, :is_a_teacher, :is_a_student, :is_onboarder
|
||||
:recording_count, :session_count, :biography, :favorite_count, :audio_latency, :upcoming_session_count, :age, :website, :skill_level, :reuse_card, :email_needs_verification, :is_a_teacher, :is_a_student, :is_onboarder, :timezone
|
||||
|
||||
node :location do |user|
|
||||
if user.musician?
|
||||
|
|
|
|||
|
|
@ -73,7 +73,10 @@
|
|||
<span class="list-search-label">Let new students find me by search:</span>
|
||||
<label class="switch">
|
||||
<input type="checkbox">
|
||||
<span class="slider"></span>
|
||||
<span class="slider">
|
||||
<span class="on-label">YES</span>
|
||||
<span class="off-label">NO</span>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
<br clear="all" />
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ class UserManager < BaseManager
|
|||
origin = options[:origin]
|
||||
test_drive_package = options[:test_drive_package]
|
||||
under_13 = options[:under_13]
|
||||
timezone = options[:timezone]
|
||||
|
||||
recaptcha_failed = false
|
||||
unless options[:skip_recaptcha] # allow callers to opt-of recaptcha
|
||||
|
|
@ -102,7 +103,8 @@ class UserManager < BaseManager
|
|||
education_interest: education_interest,
|
||||
origin: origin,
|
||||
test_drive_package: test_drive_package,
|
||||
under_13: under_13)
|
||||
under_13: under_13,
|
||||
timezone: timezone)
|
||||
user
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -20,19 +20,20 @@ describe "Activate Account Card", :js => true, :type => :feature, :capybara_feat
|
|||
|
||||
amazon_2_free_card.credits.should eql 2
|
||||
|
||||
find('h2', text: 'Activate Account')
|
||||
find('.instructions', text: 'Paste or enter your promotional code so we can validate it and credit you with 2 free lessons.')
|
||||
fill_in "code", with: amazon_2_free_card.code
|
||||
find('a.amazon-a-button-text', text: 'Submit Code').trigger(:click)
|
||||
|
||||
find('.success-msg wbr', 'Your code has been validated!')
|
||||
fill_in "email", with: "amzposa1@jamkazam.com"
|
||||
fill_in "password", with: "jam123"
|
||||
find('.redeem-container ins', visible: false).trigger(:click)
|
||||
find('.checkbox-input input').trigger(:click)
|
||||
|
||||
find('button.redeem-giftcard', text: 'ACTIVATE ACCOUNT').trigger(:click)
|
||||
find('a.amazon-a-button-text', text: 'Create Account').trigger(:click)
|
||||
|
||||
find('.jam-class.all-done span.amount-gifted', text: amazon_2_free_card.credits)
|
||||
find('.done-action a.go-browse').trigger(:click)
|
||||
|
||||
find('h2', text: 'search teachers')
|
||||
find('.success-msg', "You're all set!")
|
||||
|
||||
sleep 3
|
||||
user = User.find_by_email("amzposa1@jamkazam.com")
|
||||
amazon_2_free_card.reload
|
||||
amazon_2_free_card.user.should eq(user)
|
||||
|
|
@ -40,29 +41,31 @@ describe "Activate Account Card", :js => true, :type => :feature, :capybara_feat
|
|||
amazon_2_free_card.purchased.should be true
|
||||
user.reload
|
||||
user.jamclass_credits.should eq(amazon_2_free_card.credits)
|
||||
user.timezone.should_not be_nil
|
||||
end
|
||||
|
||||
it "validates correctly" do
|
||||
visit '/account/activate/code'
|
||||
|
||||
find('h2', text: 'Activate Account')
|
||||
amazon_2_free_card.credits.should eql 2
|
||||
|
||||
find('button.redeem-giftcard', text: 'ACTIVATE ACCOUNT').trigger(:click)
|
||||
|
||||
find('.errors.active', text: "Email can't be blank")
|
||||
|
||||
find('h2', text: 'Activate Account')
|
||||
find('.instructions', text: 'Paste or enter your promotional code so we can validate it and credit you with 2 free lessons.')
|
||||
fill_in "code", with: amazon_2_free_card.code
|
||||
find('a.amazon-a-button-text', text: 'Submit Code').trigger(:click)
|
||||
|
||||
find('.success-msg wbr', 'Your code has been validated!')
|
||||
find('a.amazon-a-button-text', text: 'Create Account').trigger(:click)
|
||||
find('.error', text: "Email can't be blank")
|
||||
|
||||
fill_in "email", with: "amzpos2@jamkazam.com"
|
||||
fill_in "password", with: "jam123"
|
||||
find('.redeem-container ins', visible: false).trigger(:click)
|
||||
find('.checkbox-input input').trigger(:click)
|
||||
|
||||
find('button.redeem-giftcard', text: 'ACTIVATE ACCOUNT').trigger(:click)
|
||||
find('a.amazon-a-button-text', text: 'Create Account').trigger(:click)
|
||||
|
||||
find('.done-action a.go-browse').trigger(:click)
|
||||
|
||||
find('h2', text: 'search teachers')
|
||||
find('.success-msg', "You're all set!")
|
||||
|
||||
sleep 3
|
||||
user = User.find_by_email("amzpos2@jamkazam.com")
|
||||
amazon_2_free_card.reload
|
||||
amazon_2_free_card.user.should eq(user)
|
||||
|
|
@ -79,14 +82,15 @@ describe "Activate Account Card", :js => true, :type => :feature, :capybara_feat
|
|||
it "succeeds" do
|
||||
fast_signin(user1, '/account/activate/code')
|
||||
|
||||
find('h2', text: 'Activate Account')
|
||||
find('.instructions', text: 'Paste or enter your promotional code so we can validate it and credit you with 2 free lessons.')
|
||||
|
||||
fill_in "code", with: amazon_2_free_card.code
|
||||
|
||||
find('button.redeem-giftcard', text: 'ACTIVATE COUPON CODE').trigger(:click)
|
||||
find('a.amazon-a-button-text', text: 'Submit Code').trigger(:click)
|
||||
|
||||
find('.done-action a.go-browse').trigger(:click)
|
||||
find('a.amazon-a-button-text', text: 'Apply Credits').trigger(:click)
|
||||
|
||||
find('h2', text: 'search teachers')
|
||||
find('.success-msg', text: "You're all set!")
|
||||
|
||||
user1.reload
|
||||
amazon_2_free_card.reload
|
||||
|
|
@ -101,19 +105,19 @@ describe "Activate Account Card", :js => true, :type => :feature, :capybara_feat
|
|||
it "validates" do
|
||||
fast_signin(user1, '/account/activate/code')
|
||||
|
||||
find('h2', text: 'Activate Account')
|
||||
find('.instructions', text: 'Paste or enter your promotional code so we can validate it and credit you with 2 free lessons.')
|
||||
|
||||
find('button.redeem-giftcard').trigger(:click)
|
||||
find('.amazon-a-button-text', text: 'Submit Code').trigger(:click)
|
||||
|
||||
find('.errors.active', text: "This is not a valid code. Please carefully re-enter the code and try again. If it still does not work, please email us at support@jamkazam.com to report this problem.")
|
||||
find('.error', text: "Code not valid")
|
||||
|
||||
fill_in "code", with: amazon_2_free_card.code
|
||||
|
||||
find('button.redeem-giftcard').trigger(:click)
|
||||
find('a.amazon-a-button-text', text: 'Submit Code').trigger(:click)
|
||||
|
||||
find('.done-action a.go-browse').trigger(:click)
|
||||
find('a.amazon-a-button-text', text: 'Apply Credits').trigger(:click)
|
||||
|
||||
find('h2', text: 'search teachers')
|
||||
find('.success-msg', text: "You're all set!")
|
||||
|
||||
user1.reload
|
||||
amazon_2_free_card.reload
|
||||
|
|
@ -121,6 +125,7 @@ describe "Activate Account Card", :js => true, :type => :feature, :capybara_feat
|
|||
amazon_2_free_card.requires_purchase.should be false
|
||||
amazon_2_free_card.purchased.should be true
|
||||
user1.jamclass_credits.should eq(amazon_2_free_card.credits)
|
||||
user1.timezone.should_not be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -158,7 +158,7 @@ describe "Active Music Session API ", :type => :api do
|
|||
|
||||
it "successful" do
|
||||
put "/api/sessions/#{music_session.id}.json", {:description => "you!", :musician_access => false, :fan_chat => false, :fan_access => false, :approval_required => true}.to_json, "CONTENT_TYPE" => 'application/json'
|
||||
last_response.status.should eql(204)
|
||||
last_response.status.should eql(200)
|
||||
get "/api/sessions/#{music_session.id}.json", "CONTENT_TYPE" => 'application/json'
|
||||
updated_session = JSON.parse(last_response.body)
|
||||
updated_session["description"].should == "you!"
|
||||
|
|
@ -170,7 +170,7 @@ describe "Active Music Session API ", :type => :api do
|
|||
|
||||
it "string boolean value" do
|
||||
put "/api/sessions/#{music_session.id}.json", {:musician_access => "false"}.to_json, "CONTENT_TYPE" => 'application/json'
|
||||
last_response.status.should eql(204)
|
||||
last_response.status.should eql(200)
|
||||
get "/api/sessions/#{music_session.id}.json", "CONTENT_TYPE" => 'application/json'
|
||||
updated_session = JSON.parse(last_response.body)
|
||||
updated_session["musician_access"].should be false
|
||||
|
|
@ -184,7 +184,7 @@ describe "Active Music Session API ", :type => :api do
|
|||
|
||||
it "updated genres" do
|
||||
put "/api/sessions/#{music_session.id}.json", {:genre => "jazz"}.to_json, "CONTENT_TYPE" => 'application/json'
|
||||
last_response.status.should eql(204)
|
||||
last_response.status.should eql(200)
|
||||
get "/api/sessions/#{music_session.id}.json", "CONTENT_TYPE" => 'application/json'
|
||||
updated_session = JSON.parse(last_response.body)
|
||||
updated_session["genres"].should == ["Jazz"]
|
||||
|
|
@ -523,8 +523,6 @@ describe "Active Music Session API ", :type => :api do
|
|||
|
||||
join_request = JSON.parse(last_response.body)
|
||||
|
||||
puts "join_request #{join_request}"
|
||||
|
||||
# now join_requests should still be empty, because we don't share join_requests to people outside the session
|
||||
login(user2)
|
||||
get '/api/sessions.json'
|
||||
|
|
|
|||
Loading…
Reference in New Issue