From d4aa3bef2b3bfcb4f38b335e5b58f59255a6f43e Mon Sep 17 00:00:00 2001 From: Seth Call Date: Thu, 2 Jun 2016 09:04:56 -0500 Subject: [PATCH] bunch of jamclass fixes --- admin/app/admin/test_drive_packages.rb | 60 +- .../admin/test_drive_packages/_form.html.erb | 10 +- ...est_drive_package_teacher_fields.html.slim | 7 +- admin/config/initializers/jam_ruby_teacher.rb | 5 + admin/config/initializers/jam_ruby_user.rb | 4 +- db/up/packaged_test_drive.sql | 26 +- ruby/lib/jam_ruby.rb | 2 + .../user_mailer/confirm_email.html.erb | 2 +- .../user_mailer/confirm_email.text.erb | 2 +- .../student_welcome_message.html.erb | 59 +- .../student_welcome_message.text.erb | 2 +- .../models/lesson_package_purchase.rb | 3 + .../lib/jam_ruby/models/test_drive_package.rb | 10 + .../models/test_drive_package_choice.rb | 13 + .../test_drive_package_choice_teacher.rb | 12 + .../models/test_drive_package_teacher.rb | 19 +- ruby/lib/jam_ruby/models/user.rb | 2 +- ruby/spec/factories.rb | 438 +++++++------ .../models/test_drive_package_choice_spec.rb | 14 + ruby/spec/spec_helper.rb | 2 +- ruby/spec/support/utilities.rb | 3 + .../javascripts/everywhere/everywhere.js | 3 +- .../assets/javascripts/helpBubbleHelper.js | 5 +- .../TestDrivePackageDialog.js.jsx.coffee | 97 +++ ...JamClassAffiliateLandingPage.js.jsx.coffee | 2 +- ...lassStudentLandingMiddlePage.js.jsx.coffee | 143 +++++ .../JamClassStudentLandingPage.js.jsx.coffee | 4 +- .../ProductJamBlasterBottomPage.js.jsx.coffee | 4 +- .../stores/SessionStore.js.coffee | 14 +- web/app/assets/javascripts/web/web.js | 1 + .../landings/individual_jamtrack.css.scss | 579 ++++++++++-------- web/app/controllers/application_controller.rb | 18 +- web/app/controllers/landings_controller.rb | 23 +- web/app/views/clients/_help.html.slim | 11 +- web/app/views/dialogs/_dialogs.html.haml | 3 +- .../dialogs/_testDrivePackageDialog.html.slim | 2 + .../views/landings/buy_gift_card.html.slim | 5 +- .../landings/individual_jamtrack.html.slim | 5 +- .../landings/jam_class_students.html.slim | 15 +- .../landings/jam_class_teachers.html.slim | 5 +- web/app/views/layouts/web.html.erb | 2 + web/config/application.rb | 3 +- web/config/initializers/gon.rb | 1 + web/spec/features/student_landing_spec.rb | 9 +- web/spec/support/app_config.rb | 4 + 45 files changed, 1080 insertions(+), 573 deletions(-) create mode 100644 admin/config/initializers/jam_ruby_teacher.rb create mode 100644 ruby/lib/jam_ruby/models/test_drive_package_choice.rb create mode 100644 ruby/lib/jam_ruby/models/test_drive_package_choice_teacher.rb create mode 100644 ruby/spec/jam_ruby/models/test_drive_package_choice_spec.rb create mode 100644 web/app/assets/javascripts/react-components/TestDrivePackageDialog.js.jsx.coffee create mode 100644 web/app/assets/javascripts/react-components/landing/JamClassStudentLandingMiddlePage.js.jsx.coffee create mode 100644 web/app/views/dialogs/_testDrivePackageDialog.html.slim diff --git a/admin/app/admin/test_drive_packages.rb b/admin/app/admin/test_drive_packages.rb index f5e21b95b..ebd4c2268 100644 --- a/admin/app/admin/test_drive_packages.rb +++ b/admin/app/admin/test_drive_packages.rb @@ -1,4 +1,4 @@ -ActiveAdmin.register JamRuby::TestDrivePackage, :as => 'TestDrivePackages' do +ActiveAdmin.register JamRuby::TestDrivePackage, :as => 'TestDrivePackage' do menu :label => 'Test Drive Packages', :parent => 'JamClass' @@ -11,42 +11,88 @@ ActiveAdmin.register JamRuby::TestDrivePackage, :as => 'TestDrivePackages' do form :partial => 'form' + controller do +=begin + def new + test_drive_package = TestDrivePackage.new + t = TestDrivePackageTeacher.new + t.test_drive_package = test_drive_package + test_drive_package.test_drive_package_teachers << t + + t = TestDrivePackageTeacher.new + t.test_drive_package = test_drive_package + test_drive_package.test_drive_package_teachers << t + + @test_drive_package = test_drive_package + puts "OK #{test_drive_package.test_drive_package_teachers.length}" + super + end +=end + + + # def create + # puts params.inspect + # hash = params[:jam_ruby_test_drive_package] + # package = TestDrivePackage.new + # package.name = hash[:name] + # package.package_type = hash[:package_type] + # package.description = hash[:description] + # if package.save + # redirect_to admin_test_drive_package_path(package.id) + # else + # redirect_to admin_test_drive_packages_path, :notice => "Unable to create package. Error: #{package.errors.first[1][0]}" + # end + #end + end index do + column "Package ID" do |package| link_to package.name, "#{APP_CONFIG.external_root_url}/landing/jamclass/students?utm-teachers=#{package.name}" end + column "Package Type" do |package| package.package_type end + column "Teachers" do |package| - span do - package.test_drive_package_teachers.each do |package_teacher| - teacher = package_teacher + package.test_drive_package_teachers.each do |package_teacher| + + span do + teacher = package_teacher.user link_to "#{teacher.name} (#{teacher.email})", "#{Rails.application.config.external_root_url}/client#/profile/teacher/#{teacher.id}" end + br end end + column "Detail" do |package| link_to "Detail", admin_test_drive_package_path(package.id) end + end show do + attributes_table do row "Package ID" do |package| link_to package.name, "#{APP_CONFIG.external_root_url}/landing/jamclass/students?utm-teachers=#{package.name}" end + row "Package Type" do |package| package.package_type end + row "Teachers" do |package| - span do - package.test_drive_package_teachers.each do |package_teacher| - teacher = package_teacher + package.test_drive_package_teachers.each do |package_teacher| + + span do + teacher = package_teacher.user link_to "#{teacher.name} (#{teacher.email})", "#{Rails.application.config.external_root_url}/client#/profile/teacher/#{teacher.id}" end + br end end + row "Description" do |package| package.description end diff --git a/admin/app/views/admin/test_drive_packages/_form.html.erb b/admin/app/views/admin/test_drive_packages/_form.html.erb index 7ab34fe8d..65d00ccb1 100644 --- a/admin/app/views/admin/test_drive_packages/_form.html.erb +++ b/admin/app/views/admin/test_drive_packages/_form.html.erb @@ -1,15 +1,19 @@ -<%= semantic_form_for([:admin, resource], html: {:multipart => true}, url: resource.new_record? ? admin_test_drive_packages_path : "#{ENV['RAILS_RELATIVE_URL_ROOT']}/admin/test_drive_packages/#{resource.id}") do |f| %> +<%= semantic_form_for([:admin, @test_drive_package], html: {:multipart => true}, url: @test_drive_package.new_record? ? admin_test_drive_packages_path : "#{ENV['RAILS_RELATIVE_URL_ROOT']}/admin/test_drive_packages/#{@test_drive_package.id}") do |f| %> + <%= f.semantic_errors *f.object.errors.keys %> <%= f.inputs do %> - <%= f.input :name, label: "Package ID", hint: "The name to use as the utm-teachers parameter in the student landing URL" %> - <%= f.input :package_type, label: "Package Type", as: :select, collection: ['1', '2', '4'], hint: "TestDrive package type" %> + <%= f.input :name, required: true, label: "Package ID", hint: "The name to use as the utm-teachers parameter in the student landing URL" %> + <%= f.input :package_type, required: true, label: "Package Type", as: :select, collection: ['1', '2', '4'], hint: "TestDrive package type" %> <%= f.input :description, label: "Package Description", hint: "Admin-only friendly description of the package" %> <%= f.semantic_fields_for :test_drive_package_teachers do |teacher| %> <%= render 'test_drive_package_teacher_fields', f: teacher %> <% end %> + + <% if !@test_drive_package.new_record? %> + <% end %> <%= f.actions %> <% end %> diff --git a/admin/app/views/admin/test_drive_packages/_test_drive_package_teacher_fields.html.slim b/admin/app/views/admin/test_drive_packages/_test_drive_package_teacher_fields.html.slim index c8d2f78fc..40039250b 100644 --- a/admin/app/views/admin/test_drive_packages/_test_drive_package_teacher_fields.html.slim +++ b/admin/app/views/admin/test_drive_packages/_test_drive_package_teacher_fields.html.slim @@ -1,5 +1,8 @@ = f.inputs name: 'Teachers' do ol.nested-fields - = f.input :test_drive_package, :required=>true, collection: TestDrivePackage.all, include_blank: false - = f.input :user, :required=>true, collection: User.where(is_a_teacher: true, phantom: false), include_blank: false + //= f.input :test_drive_package, :required=>true, value: @test_drive_package, include_blank: true + = f.input :user, :required=>true, collection: User.where(is_a_teacher: true, phantom: false), include_blank: true + = f.input :short_bio + + = link_to_remove_association "Delete Teacher", f, class: 'button', style: 'margin-left:10px' diff --git a/admin/config/initializers/jam_ruby_teacher.rb b/admin/config/initializers/jam_ruby_teacher.rb new file mode 100644 index 000000000..f855ae238 --- /dev/null +++ b/admin/config/initializers/jam_ruby_teacher.rb @@ -0,0 +1,5 @@ + class JamRuby::Teacher + + attr_accessible :short_bio, as: :admin + +end diff --git a/admin/config/initializers/jam_ruby_user.rb b/admin/config/initializers/jam_ruby_user.rb index 57435d83f..5effb5420 100644 --- a/admin/config/initializers/jam_ruby_user.rb +++ b/admin/config/initializers/jam_ruby_user.rb @@ -1,6 +1,8 @@ class JamRuby::User - attr_accessible :admin, :raw_password, :musician, :can_invite, :photo_url, :session_settings, :confirm_url, :email_template # :invite_email + attr_accessible :admin, :raw_password, :musician, :can_invite, :photo_url, :session_settings, :confirm_url, :teacher_attributes, :email_template # :invite_email + + accepts_nested_attributes_for :teacher, allow_destroy: true def raw_password '' diff --git a/db/up/packaged_test_drive.sql b/db/up/packaged_test_drive.sql index 6b5c30ffe..fb1796448 100644 --- a/db/up/packaged_test_drive.sql +++ b/db/up/packaged_test_drive.sql @@ -9,10 +9,30 @@ CREATE TABLE test_drive_packages ( CREATE TABLE test_drive_package_teachers ( id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(), - user_id VARCHAR(64) NOT NULL REFERENCES users(id) ON DELETE CASCADE, - test_drive_package_id VARCHAR(64) NOT NULL REFERENCES test_drive_packages(id) ON DELETE CASCADE, + user_id VARCHAR(64) REFERENCES users(id) ON DELETE CASCADE, + test_drive_package_id VARCHAR(64) REFERENCES test_drive_packages(id) ON DELETE CASCADE, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ); -ALTER TABLE lesson_bookings ADD COLUMN test_drive_package_id VARCHAR(64) REFERENCES test_drive_packages(id); \ No newline at end of file +ALTER TABLE lesson_bookings ADD COLUMN test_drive_package_id VARCHAR(64) REFERENCES test_drive_packages(id); + +CREATE TABLE test_drive_package_choices ( + id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(), + test_drive_package_id VARCHAR(64) REFERENCES test_drive_packages(id) ON DELETE CASCADE, + user_id VARCHAR(64) REFERENCES users(id) ON DELETE CASCADE, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP +); + + +CREATE TABLE test_drive_package_choice_teachers ( + id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(), + test_drive_package_choice_id VARCHAR(64) REFERENCES test_drive_package_choices(id) ON DELETE CASCADE, + teacher_id VARCHAR(64) REFERENCES users(id) ON DELETE CASCADE, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP +); + +ALTER TABLE teachers ADD COLUMN short_bio VARCHAR; +ALTER TABLE test_drive_package_teachers ADD COLUMN short_bio VARCHAR; \ No newline at end of file diff --git a/ruby/lib/jam_ruby.rb b/ruby/lib/jam_ruby.rb index 2ee1f29a7..1e1aab60f 100755 --- a/ruby/lib/jam_ruby.rb +++ b/ruby/lib/jam_ruby.rb @@ -256,6 +256,8 @@ require "jam_ruby/models/broadcast_notification" require "jam_ruby/models/broadcast_notification_view" require "jam_ruby/models/test_drive_package" require "jam_ruby/models/test_drive_package_teacher" +require "jam_ruby/models/test_drive_package_choice" +require "jam_ruby/models/test_drive_package_choice_teacher" require "jam_ruby/calendar_manager" require "jam_ruby/jam_tracks_manager" require "jam_ruby/jam_track_importer" diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/confirm_email.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/confirm_email.html.erb index 03c75c0bc..358f0f2b1 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/confirm_email.html.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/confirm_email.html.erb @@ -1,6 +1,6 @@ <% provide(:title, 'Welcome to JamKazam!') %> -

We’re delighted you have joined our community of 30,000+ musicians. We’d like to send you an orientation email with information and resource links that will help you get the most out of JamKazam. Please click here to confirm this email has reached you successfully and we will then send the orientation email.

+

We’re delighted you have joined our community of <%= APP_CONFIG.musician_count %> musicians. We’d like to send you an orientation email with information and resource links that will help you get the most out of JamKazam. Please click here to confirm this email has reached you successfully and we will then send the orientation email.

If you have received this email but aren’t familiar with JamKazam or JamTracks, then someone has registered at our website using your email address, and you can just ignore and delete this email.

diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/confirm_email.text.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/confirm_email.text.erb index 07bce8391..129da288d 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/confirm_email.text.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/confirm_email.text.erb @@ -1,6 +1,6 @@ Welcome to JamKazam! -We’re delighted you have joined our community of 30,000+ musicians. We’d like to send you an orientation email with information and resource links that will help you get the most out of JamKazam. Please click <%= @signup_confirm_url %> to confirm this email has reached you successfully and we will then send the orientation email. +We’re delighted you have joined our community of <%= APP_CONFIG.musician_count %> musicians. We’d like to send you an orientation email with information and resource links that will help you get the most out of JamKazam. Please click <%= @signup_confirm_url %> to confirm this email has reached you successfully and we will then send the orientation email. If you have received this email but aren’t familiar with JamKazam or JamTracks, then someone has registered at our website using your email address, and you can just ignore and delete this email. diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/student_welcome_message.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/student_welcome_message.html.erb index 574aa3885..b332c29f1 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/student_welcome_message.html.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/student_welcome_message.html.erb @@ -11,7 +11,7 @@ Thank you for signing up to take online music lessons using the JamClass service by JamKazam. JamKazam technology was built from the ground up for playing music live in sync with high quality audio from different locations over the Internet. Unlike other lesson services, this means we can deliver a massively better online music lesson experience - than voice/chat apps like Skype, etc. Our rapidly growing community of 35,000+ musicians will attest to this. + than voice/chat apps like Skype, etc. Our rapidly growing community of <%= APP_CONFIG.musician_count %> musicians will attest to this.

@@ -20,58 +20,31 @@

1. Find a Teacher & Book Lessons
- If you already know the teacher from whom you want to learn, then you can simply - use this link to search for - them, and - click the Book Lesson button to get started. But if you're like most of us, you don't know. In this case, we strongly - advise signing up for our unique TestDrive service. -
-
+ If you haven't done so already, use this link to search our teachers, and click to book a TestDrive with a teacher who looks good for you. When you do this, you'll be given the option to take full 30-minute TestDrive lessons: - TestDrive lets you take 4 full lessons (30 minutes each) from 4 different teachers for just $49.99 to find the best - teacher for you. Finding the right teacher is the single most important determinant of success in your lessons. Would - you marry the first person you ever dated? No? Same here. Pick 4 teachers who look great, and then see who you click - with. It's a phenomenal value, and then you can stick with the best teacher for you. - Click this link - to sign up now - for TestDrive. Then you can book 4 TestDrive lessons to get rolling. +

+

+ Pick whichever option you prefer. TestDrive lets you safely and easily try multiple teachers to find the one who is best specifically for you, which is a great way to maximize the benefit from your lessons. And TestDrive lessons are heavily discounted to give you a risk-free way to get started. We'd suggest scheduling your first lesson for about a week in the future to give you plenty of time to get up and running with our free app. +

2. Set Up Your Gear
- Use this link to a set of - help - articles on how to set up your gear to be ready to teach online. After you have signed - up, someone from JamKazam will contact you to schedule a test online session, in which we will make sure your audio - and video gear are working properly in an online session, and to make sure you feel comfortable with the key features - you will be using in sessions with teachers. + Please review our help articles on gear recommendations + to make sure you have everything you need to get set up properly for best results in your online lessons. + If you have everything you need, then you can follow the instructions on our setup help articles to download and install our free app and set it up with your audio gear and webcam. Please email us at support@jamkazam.com or call us at 1-877-376-8742 any time so that we can help you with these steps. We are very happy to help, and we also strongly suggest that you let one of our staff get into an online session with you to make sure everything is working properly and to make sure you're comfortable with the app and ready for your first lesson.

3. Learn About JamClass Features
- Use this link to a set of - help - articles for students on JamClass to familiarize yourself with the most useful features - for online lessons. This includes how to search for the best teacher for you, how to request/book lessons, how to join - your teacher in online lessons, features you can use while in lessons, and much more. There is very important basic - information, plus some really nifty stuff here, so be sure to look through it at least briefly to see how we can - turbocharge your online lessons! -

- -

4. Play With Other Musicians Online - It's Free!
- With JamKazam, you can use the things you're learning in lessons to play with other amateur musicians in online - sessions, free! Or just play for fun. Once you've set up your gear for lessons, you can - create - online music sessions - that others can join, or find other musicians' online music sessions and hop into those to play with others. If you - want to take advantage of this part of the JamKazam platform, we'd advise that you edit your musician profile to make - it easier to connect with other musicians in our community to expand your set of musician friends. It's a ton of fun, - so give it a try! + Please review our JamClass user guide for students to familiarize yourself with the features and resources available to you through our JamClass lesson service. This includes how to search for the best teacher for you, how to request/book lessons, how to join your teacher in online lessons, features you can use while in lessons, and much more.

- As you work through these things, if you ever get stuck or have questions, please don't hesitate to reach out for - help. You can email us any time at support@jamkazam.com. We are happy to - help you, and we look forward to helping you - learn and grow as a musician, and expand your musical universe! + + Again, welcome to JamKazam and our JamClass online music lesson service, and we look forward to helping you learn and grow as a musician!

diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/student_welcome_message.text.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/student_welcome_message.text.erb index 0cff2ed3e..b16eef375 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/student_welcome_message.text.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/student_welcome_message.text.erb @@ -3,7 +3,7 @@ Thank you for signing up to take online music lessons using the JamClass service by JamKazam. JamKazam technology was built from the ground up for playing music live in sync with high quality audio from different locations over the Internet. Unlike other lesson services, this means we can deliver a massively better online music lesson experience -than voice/chat apps like Skype, etc. Our rapidly growing community of 35,000+ musicians will attest to this. +than voice/chat apps like Skype, etc. Our rapidly growing community of <%= APP_CONFIG.musician_count %> musicians will attest to this. To get ready to take JamClass lessons online, here are the things you'll want to do: diff --git a/ruby/lib/jam_ruby/models/lesson_package_purchase.rb b/ruby/lib/jam_ruby/models/lesson_package_purchase.rb index f036572f1..d0e592358 100644 --- a/ruby/lib/jam_ruby/models/lesson_package_purchase.rb +++ b/ruby/lib/jam_ruby/models/lesson_package_purchase.rb @@ -54,6 +54,9 @@ module JamRuby end + def to_s + "#{name} (#{amount_charged})" + end def name lesson_package_type.sale_display diff --git a/ruby/lib/jam_ruby/models/test_drive_package.rb b/ruby/lib/jam_ruby/models/test_drive_package.rb index 98c3c3964..d85f1b086 100644 --- a/ruby/lib/jam_ruby/models/test_drive_package.rb +++ b/ruby/lib/jam_ruby/models/test_drive_package.rb @@ -10,6 +10,16 @@ module JamRuby validates :name, presence: true, uniqueness: true validates :package_type, presence: true + + #validate :teacher_count + + def teacher_count + if package_type != test_drive_package_teachers.length + self.errors.add(:test_drive_package_teachers, "wrong number of teachers specified for the given package type #{package_type}") + end + end + + accepts_nested_attributes_for :test_drive_package_teachers, allow_destroy: true end end diff --git a/ruby/lib/jam_ruby/models/test_drive_package_choice.rb b/ruby/lib/jam_ruby/models/test_drive_package_choice.rb new file mode 100644 index 000000000..569e1e352 --- /dev/null +++ b/ruby/lib/jam_ruby/models/test_drive_package_choice.rb @@ -0,0 +1,13 @@ +# when a user picks a package, we mark which teachers they actually went with from the package +module JamRuby + class TestDrivePackageChoice < ActiveRecord::Base + + @@log = Logging.logger[TestDrivePackageChoice] + + belongs_to :test_drive_package, class_name: "JamRuby::TestDrivePackage" + belongs_to :user, class_name: "JamRuby::User" + has_many :test_drive_package_choice_teachers, class_name: "JamRuby::TestDrivePackageChoiceTeacher", foreign_key: :teacher_id + + end +end + diff --git a/ruby/lib/jam_ruby/models/test_drive_package_choice_teacher.rb b/ruby/lib/jam_ruby/models/test_drive_package_choice_teacher.rb new file mode 100644 index 000000000..02397f886 --- /dev/null +++ b/ruby/lib/jam_ruby/models/test_drive_package_choice_teacher.rb @@ -0,0 +1,12 @@ +# when a user picks a package, we mark which teachers they actually went with from the package +module JamRuby + class TestDrivePackageChoiceTeacher < ActiveRecord::Base + + @@log = Logging.logger[TestDrivePackageChoiceTeacher] + + belongs_to :test_drive_package_choice, class_name: "JamRuby::TestDrivePackageChoice" + belongs_to :teacher, class_name: "JamRuby::User", foreign_key: :teacher_id + + end +end + diff --git a/ruby/lib/jam_ruby/models/test_drive_package_teacher.rb b/ruby/lib/jam_ruby/models/test_drive_package_teacher.rb index eb232d194..ab5d29fcf 100644 --- a/ruby/lib/jam_ruby/models/test_drive_package_teacher.rb +++ b/ruby/lib/jam_ruby/models/test_drive_package_teacher.rb @@ -4,13 +4,30 @@ module JamRuby @@log = Logging.logger[TestDrivePackageTeacher] - attr_accessible :user_id, :test_drive_package_id, as: :admin + attr_accessor :short_bio_temp + attr_accessible :user_id, :test_drive_package_id, :short_bio, as: :admin belongs_to :test_drive_package, class_name: "JamRuby::TestDrivePackage" belongs_to :user, class_name: "JamRuby::User" validates :user, presence: true validates :test_drive_package, presence: true + + after_save :after_save + + # silly pass through for activeadmin. We pass short_bio set here on to teacher + def after_save + if user && user.teacher + user.teacher.short_bio = short_bio + user.teacher.save! + end + end + + def short_bio + if user && user.teacher + user.teacher.short_bio + end + end end end diff --git a/ruby/lib/jam_ruby/models/user.rb b/ruby/lib/jam_ruby/models/user.rb index 93b19b48f..ad92ac057 100644 --- a/ruby/lib/jam_ruby/models/user.rb +++ b/ruby/lib/jam_ruby/models/user.rb @@ -1159,7 +1159,7 @@ module JamRuby elsif user.is_a_teacher school = School.find_by_id(school_id) school_name = school ? school.name : 'a music school' - user.teacher = Teacher.build_teacher(user, validate_introduction: true, biography: "Teaches for #{school_name}", school_id: school_id) + user.teacher = Teacher.build_teacher(user, validate_introduction: true, biography: "Empty biography", school_id: school_id) user.affiliate_referral = school.affiliate_partner end else diff --git a/ruby/spec/factories.rb b/ruby/spec/factories.rb index 8cde0eff7..893a4a2b5 100644 --- a/ruby/spec/factories.rb +++ b/ruby/spec/factories.rb @@ -6,9 +6,9 @@ FactoryGirl.define do specific_instruments nil end - sequence(:email) { |n| "person_#{n}@example.com"} - sequence(:first_name) { |n| "Person" } - sequence(:last_name) { |n| "#{n}" } + sequence(:email) { |n| "person_#{n}@example.com" } + sequence(:first_name) { |n| "Person" } + sequence(:last_name) { |n| "#{n}" } password "foobar" password_confirmation "foobar" email_confirmed true @@ -47,7 +47,7 @@ FactoryGirl.define do factory :austin_user do first_name 'Austin' - sequence(:last_name) { |n| "#{n}" } + sequence(:last_name) { |n| "#{n}" } state 'TX' city 'Austin' last_jam_locidispid { austin_geoip[:locidispid] } @@ -56,7 +56,7 @@ FactoryGirl.define do factory :dallas_user do first_name 'Dallas' - sequence(:last_name) { |n| "#{n}" } + sequence(:last_name) { |n| "#{n}" } state 'TX' city 'Dallas' last_jam_locidispid { dallas_geoip[:locidispid] } @@ -65,7 +65,7 @@ FactoryGirl.define do factory :houston_user do first_name 'Houston' - sequence(:last_name) { |n| "#{n}" } + sequence(:last_name) { |n| "#{n}" } state 'TX' city 'Houston' last_jam_locidispid { houston_geoip[:locidispid] } @@ -74,7 +74,7 @@ FactoryGirl.define do factory :miami_user do first_name 'Miami' - sequence(:last_name) { |n| "#{n}" } + sequence(:last_name) { |n| "#{n}" } state 'FL' city 'Miami' last_jam_locidispid { miami_geoip[:locidispid] } @@ -83,7 +83,7 @@ FactoryGirl.define do factory :seattle_user do first_name 'Seattle' - sequence(:last_name) { |n| "#{n}" } + sequence(:last_name) { |n| "#{n}" } state 'WA' city 'Seattle' last_jam_locidispid { seattle_geoip[:locidispid] } @@ -106,7 +106,7 @@ FactoryGirl.define do factory :teacher, :class => JamRuby::Teacher do association :user, factory: :user - price_per_lesson_60_cents 3000 + price_per_lesson_60_cents 3000 price_per_month_60_cents 3000 end @@ -156,7 +156,7 @@ FactoryGirl.define do end end end - + factory :music_session, :class => JamRuby::MusicSession do ignore do student nil @@ -208,7 +208,7 @@ FactoryGirl.define do client_type 'client' gateway 'gateway1' last_jam_audio_latency { user.last_jam_audio_latency if user } - sequence(:channel_id) { |n| "Channel#{n}"} + sequence(:channel_id) { |n| "Channel#{n}" } association :user, factory: :user scoring_timeout Time.now end @@ -230,7 +230,7 @@ FactoryGirl.define do end factory :band, :class => JamRuby::Band do - sequence(:name) { |n| "Band" } + sequence(:name) { |n| "Band" } biography "My Biography" city "Apex" state "NC" @@ -260,57 +260,57 @@ FactoryGirl.define do factory :track, :class => JamRuby::Track do sound "mono" - sequence(:client_track_id) { |n| "client_track_id#{n}"} - sequence(:client_resource_id) { |n| "resource_id#{n}"} + sequence(:client_track_id) { |n| "client_track_id#{n}" } + sequence(:client_resource_id) { |n| "resource_id#{n}" } end factory :backing_track, :class => JamRuby::BackingTrack do - sequence(:client_track_id) { |n| "client_track_id#{n}"} + sequence(:client_track_id) { |n| "client_track_id#{n}" } filename 'foo.mp3' end factory :video_source, :class => JamRuby::VideoSource do #client_video_source_id "test_source_id" - sequence(:client_video_source_id) { |n| "client_video_source_id#{n}"} + sequence(:client_video_source_id) { |n| "client_video_source_id#{n}" } end factory :recorded_track, :class => JamRuby::RecordedTrack do instrument JamRuby::Instrument.first sound 'stereo' - sequence(:client_id) { |n| "client_id-#{n}"} - sequence(:track_id) { |n| "track_id-#{n}"} - sequence(:client_track_id) { |n| "client_track_id-#{n}"} + sequence(:client_id) { |n| "client_id-#{n}" } + sequence(:track_id) { |n| "track_id-#{n}" } + sequence(:client_track_id) { |n| "client_track_id-#{n}" } md5 'abc' length 1 fully_uploaded true - association :user, factory: :user - association :recording, factory: :recording + association :user, factory: :user + association :recording, factory: :recording end factory :recorded_backing_track, :class => JamRuby::RecordedBackingTrack do - sequence(:client_id) { |n| "client_id-#{n}"} - sequence(:backing_track_id) { |n| "track_id-#{n}"} - sequence(:client_track_id) { |n| "client_track_id-#{n}"} - sequence(:filename) { |n| "filename-{#n}"} - sequence(:url) { |n| "/recordings/blah/#{n}"} + sequence(:client_id) { |n| "client_id-#{n}" } + sequence(:backing_track_id) { |n| "track_id-#{n}" } + sequence(:client_track_id) { |n| "client_track_id-#{n}" } + sequence(:filename) { |n| "filename-{#n}" } + sequence(:url) { |n| "/recordings/blah/#{n}" } md5 'abc' length 1 fully_uploaded true - association :user, factory: :user - association :recording, factory: :recording + association :user, factory: :user + association :recording, factory: :recording end factory :recorded_video, :class => JamRuby::RecordedVideo do - sequence(:client_video_source_id) { |n| "client_video_source_id-#{n}"} + sequence(:client_video_source_id) { |n| "client_video_source_id-#{n}" } fully_uploaded true length 1 - association :user, factory: :user - association :recording, factory: :recording + association :user, factory: :user + association :recording, factory: :recording end factory :recorded_jam_track_track, :class => JamRuby::RecordedJamTrackTrack do - association :user, factory: :user - association :recording, factory: :recording + association :user, factory: :user + association :recording, factory: :recording association :jam_track_track, factory: :jam_track_track end @@ -320,9 +320,9 @@ FactoryGirl.define do factory :recording, :class => JamRuby::Recording do - association :owner, factory: :user - association :music_session, factory: :active_music_session - association :band, factory: :band + association :owner, factory: :user + association :music_session, factory: :active_music_session + association :band, factory: :band factory :recording_with_track do before(:create) { |recording| @@ -335,8 +335,8 @@ FactoryGirl.define do sequence(:name) { |n| "name-#{n}" } sequence(:description) { |n| "description-#{n}" } is_public true - association :genre, factory: :genre - association :user, factory: :user + association :genre, factory: :genre + association :user, factory: :user before(:create) { |claimed_recording, evaluator| claimed_recording.recording = FactoryGirl.create(:recording_with_track, owner: claimed_recording.user) unless evaluator.recording @@ -359,7 +359,7 @@ FactoryGirl.define do sequence(:mp3_url) { |n| "recordings/mp3/#{n}" } completed true - before(:create) {|mix, evaluator| + before(:create) { |mix, evaluator| if evaluator.autowire user = FactoryGirl.create(:user) mix.recording = FactoryGirl.create(:recording_with_track, owner: user) @@ -382,7 +382,7 @@ FactoryGirl.define do mp3_url nil completed false - before(:create) {|mix, evaluator| + before(:create) { |mix, evaluator| if evaluator.autowire user = FactoryGirl.create(:user) mix.user = user @@ -434,63 +434,63 @@ FactoryGirl.define do end factory :icecast_admin_authentication, :class => JamRuby::IcecastAdminAuthentication do - source_pass Faker::Lorem.characters(10) - admin_user Faker::Lorem.characters(10) - admin_pass Faker::Lorem.characters(10) - relay_user Faker::Lorem.characters(10) - relay_pass Faker::Lorem.characters(10) + source_pass Faker::Lorem.characters(10) + admin_user Faker::Lorem.characters(10) + admin_pass Faker::Lorem.characters(10) + relay_user Faker::Lorem.characters(10) + relay_pass Faker::Lorem.characters(10) end factory :icecast_directory, :class => JamRuby::IcecastDirectory do - yp_url_timeout 15 - yp_url Faker::Lorem.characters(10) + yp_url_timeout 15 + yp_url Faker::Lorem.characters(10) end factory :icecast_master_server_relay, :class => JamRuby::IcecastMasterServerRelay do - master_server Faker::Lorem.characters(10) - master_server_port 8000 + master_server Faker::Lorem.characters(10) + master_server_port 8000 master_update_interval 120 - master_username Faker::Lorem.characters(10) - master_pass Faker::Lorem.characters(10) - relays_on_demand 1 + master_username Faker::Lorem.characters(10) + master_pass Faker::Lorem.characters(10) + relays_on_demand 1 end factory :icecast_path, :class => JamRuby::IcecastPath do - base_dir Faker::Lorem.characters(10) - log_dir Faker::Lorem.characters(10) - pid_file Faker::Lorem.characters(10) - web_root Faker::Lorem.characters(10) - admin_root Faker::Lorem.characters(10) + base_dir Faker::Lorem.characters(10) + log_dir Faker::Lorem.characters(10) + pid_file Faker::Lorem.characters(10) + web_root Faker::Lorem.characters(10) + admin_root Faker::Lorem.characters(10) end factory :icecast_logging, :class => JamRuby::IcecastLogging do - access_log Faker::Lorem.characters(10) - error_log Faker::Lorem.characters(10) - log_level 3 - log_archive nil - log_size 10000 + access_log Faker::Lorem.characters(10) + error_log Faker::Lorem.characters(10) + log_level 3 + log_archive nil + log_size 10000 end factory :icecast_security, :class => JamRuby::IcecastSecurity do - chroot 0 + chroot 0 end factory :icecast_mount, :class => JamRuby::IcecastMount do - sequence(:name) { |n| "/mount_#{n}" } - source_username Faker::Lorem.characters(10) - source_pass Faker::Lorem.characters(10) - max_listeners 100 + sequence(:name) { |n| "/mount_#{n}" } + source_username Faker::Lorem.characters(10) + source_pass Faker::Lorem.characters(10) + max_listeners 100 max_listener_duration 3600 - fallback_mount Faker::Lorem.characters(10) - fallback_override 1 - fallback_when_full 1 - is_public -1 - stream_name Faker::Lorem.characters(10) - stream_description Faker::Lorem.characters(10) - stream_url Faker::Lorem.characters(10) - genre Faker::Lorem.characters(10) - hidden 0 - association :server, factory: :icecast_server_with_overrides + fallback_mount Faker::Lorem.characters(10) + fallback_override 1 + fallback_when_full 1 + is_public -1 + stream_name Faker::Lorem.characters(10) + stream_description Faker::Lorem.characters(10) + stream_url Faker::Lorem.characters(10) + genre Faker::Lorem.characters(10) + hidden 0 + association :server, factory: :icecast_server_with_overrides factory :icecast_mount_with_auth do association :authentication, :factory => :icecast_user_authentication @@ -508,39 +508,39 @@ FactoryGirl.define do factory :icecast_source_change, :class => JamRuby::IcecastSourceChange do source_direction true success true - sequence(:client_id) { |n| "client_id#{n}" } + sequence(:client_id) { |n| "client_id#{n}" } change_type JamRuby::IcecastSourceChange::CHANGE_TYPE_CLIENT - association :user, :factory => :user - association :mount, :factory => :iceast_mount_with_music_session + association :user, :factory => :user + association :mount, :factory => :iceast_mount_with_music_session end factory :icecast_listen_socket, :class => JamRuby::IcecastListenSocket do - port 8000 + port 8000 end factory :icecast_relay, :class => JamRuby::IcecastRelay do - port 8000 - mount Faker::Lorem.characters(10) - server Faker::Lorem.characters(10) - on_demand 1 + port 8000 + mount Faker::Lorem.characters(10) + server Faker::Lorem.characters(10) + on_demand 1 end factory :icecast_user_authentication, :class => JamRuby::IcecastUserAuthentication do authentication_type 'url' - unused_username Faker::Lorem.characters(10) - unused_pass Faker::Lorem.characters(10) - mount_add Faker::Lorem.characters(10) - mount_remove Faker::Lorem.characters(10) - listener_add Faker::Lorem.characters(10) - listener_remove Faker::Lorem.characters(10) - auth_header 'icecast-auth-user: 1' - timelimit_header 'icecast-auth-timelimit:' + unused_username Faker::Lorem.characters(10) + unused_pass Faker::Lorem.characters(10) + mount_add Faker::Lorem.characters(10) + mount_remove Faker::Lorem.characters(10) + listener_add Faker::Lorem.characters(10) + listener_remove Faker::Lorem.characters(10) + auth_header 'icecast-auth-user: 1' + timelimit_header 'icecast-auth-timelimit:' end factory :icecast_server, :class => JamRuby::IcecastServer do - sequence(:hostname) { |n| "hostname-#{n}"} - sequence(:server_id) { |n| "test-server-#{n}"} + sequence(:hostname) { |n| "hostname-#{n}" } + sequence(:server_id) { |n| "test-server-#{n}" } factory :icecast_server_minimal do association :template, :factory => :icecast_template_minimal @@ -561,27 +561,27 @@ FactoryGirl.define do end factory :icecast_mount_template, :class => JamRuby::IcecastMountTemplate do - sequence(:name) { |n| "name-#{n}"} - source_username Faker::Lorem.characters(10) - source_pass Faker::Lorem.characters(10) - max_listeners 100 + sequence(:name) { |n| "name-#{n}" } + source_username Faker::Lorem.characters(10) + source_pass Faker::Lorem.characters(10) + max_listeners 100 max_listener_duration 3600 - fallback_mount Faker::Lorem.characters(10) - fallback_override 1 - fallback_when_full 1 - is_public -1 - stream_name Faker::Lorem.characters(10) - stream_description Faker::Lorem.characters(10) - stream_url Faker::Lorem.characters(10) - genre Faker::Lorem.characters(10) - hidden 0 - association :authentication, :factory => :icecast_user_authentication + fallback_mount Faker::Lorem.characters(10) + fallback_override 1 + fallback_when_full 1 + is_public -1 + stream_name Faker::Lorem.characters(10) + stream_description Faker::Lorem.characters(10) + stream_url Faker::Lorem.characters(10) + genre Faker::Lorem.characters(10) + hidden 0 + association :authentication, :factory => :icecast_user_authentication end factory :icecast_template, :class => JamRuby::IcecastTemplate do - sequence(:name) { |n| "name-#{n}"} - sequence(:location) { |n| "location-#{n}"} + sequence(:name) { |n| "name-#{n}" } + sequence(:location) { |n| "location-#{n}" } factory :icecast_template_minimal do association :limit, :factory => :icecast_limit @@ -597,25 +597,25 @@ FactoryGirl.define do end factory :facebook_signup, :class => JamRuby::FacebookSignup do - sequence(:lookup_id) { |n| "lookup-#{n}"} - sequence(:first_name) { |n| "first-#{n}"} - sequence(:last_name) { |n| "last-#{n}"} - gender 'M' - sequence(:email) { |n| "jammin-#{n}@jamkazam.com"} - sequence(:uid) { |n| "uid-#{n}"} - sequence(:token) { |n| "token-#{n}"} - token_expires_at Time.now + sequence(:lookup_id) { |n| "lookup-#{n}" } + sequence(:first_name) { |n| "first-#{n}" } + sequence(:last_name) { |n| "last-#{n}" } + gender 'M' + sequence(:email) { |n| "jammin-#{n}@jamkazam.com" } + sequence(:uid) { |n| "uid-#{n}" } + sequence(:token) { |n| "token-#{n}" } + token_expires_at Time.now end factory :recording_comment, :class => JamRuby::RecordingComment do sequence(:comment) { |n| "comment-#{n}" } - association :recording, factory: :recording - association :user, factory: :recording + association :recording, factory: :recording + association :user, factory: :recording end factory :playable_play, :class => JamRuby::PlayablePlay do - association :user, factory: :user + association :user, factory: :user end factory :recording_like, :class => JamRuby::RecordingLiker do @@ -627,9 +627,9 @@ FactoryGirl.define do end factory :event, :class => JamRuby::Event do - sequence(:slug) { |n| "slug-#{n}" } - title 'event title' - description 'event description' + sequence(:slug) { |n| "slug-#{n}" } + title 'event title' + description 'event description' end factory :event_session, :class => JamRuby::EventSession do @@ -676,7 +676,7 @@ FactoryGirl.define do after(:create) do |rsvp_slot, evaluator| rsvp_request = FactoryGirl.create(:rsvp_request, user: evaluator.user) - rsvp_request_rsvp_slot = FactoryGirl.create(:rsvp_request_rsvp_slot, chosen:true, rsvp_request: rsvp_request, rsvp_slot:rsvp_slot) + rsvp_request_rsvp_slot = FactoryGirl.create(:rsvp_request_rsvp_slot, chosen: true, rsvp_request: rsvp_request, rsvp_slot: rsvp_slot) end end end @@ -694,10 +694,10 @@ FactoryGirl.define do chosen nil end - after(:create) { |rsvp_request, evaluator | + after(:create) { |rsvp_request, evaluator| evaluator.number.times do |i| slot = FactoryGirl.create(:rsvp_slot, music_session: evaluator.music_session, instrument: Instrument.order(:id).limit(1).offset(i).first, proficiency_level: 1) - FactoryGirl.create(:rsvp_request_rsvp_slot, chosen: evaluator.chosen, rsvp_request: rsvp_request, rsvp_slot:slot) + FactoryGirl.create(:rsvp_request_rsvp_slot, chosen: evaluator.chosen, rsvp_request: rsvp_request, rsvp_slot: slot) end } end @@ -709,9 +709,9 @@ FactoryGirl.define do chosen nil end - after(:create) { |rsvp_request, evaluator | + after(:create) { |rsvp_request, evaluator| evaluator.slots.each do |slot| - FactoryGirl.create(:rsvp_request_rsvp_slot, chosen:evaluator.chosen, rsvp_request: rsvp_request, rsvp_slot:slot) + FactoryGirl.create(:rsvp_request_rsvp_slot, chosen: evaluator.chosen, rsvp_request: rsvp_request, rsvp_slot: slot) end } end @@ -724,7 +724,7 @@ FactoryGirl.define do factory :latency_tester, :class => JamRuby::LatencyTester do ignore do connection nil - make_connection true + make_connection true end sequence(:client_id) { |n| "LatencyTesterClientId-#{n}" } @@ -755,19 +755,19 @@ FactoryGirl.define do end factory :jam_track_mixdown, :class => JamRuby::JamTrackMixdown do - association :user, factory: :user - association :jam_track, factory: :jam_track - sequence(:name) { |n| "mixdown-#{n}"} - settings '{"speed":5}' + association :user, factory: :user + association :jam_track, factory: :jam_track + sequence(:name) { |n| "mixdown-#{n}" } + settings '{"speed":5}' end factory :jam_track_mixdown_package, :class => JamRuby::JamTrackMixdownPackage do - file_type JamRuby::JamTrackMixdownPackage::FILE_TYPE_OGG - sample_rate 48 - signing false - signed false + file_type JamRuby::JamTrackMixdownPackage::FILE_TYPE_OGG + sample_rate 48 + signing false + signed false - association :jam_track_mixdown, factory: :jam_track_mixdown + association :jam_track_mixdown, factory: :jam_track_mixdown end @@ -775,22 +775,22 @@ FactoryGirl.define do sequence(:name) { |n| "jam-track-#{n}" } sequence(:description) { |n| "description-#{n}" } sequence(:slug) { |n| "slug-#{n}" } - time_signature '4/4' - status 'Production' - recording_type 'Cover' + time_signature '4/4' + status 'Production' + recording_type 'Cover' sequence(:original_artist) { |n| "original-artist-#{n}" } sequence(:songwriter) { |n| "songwriter-#{n}" } sequence(:publisher) { |n| "publisher-#{n}" } - sales_region 'United States' - price 1.99 - reproduction_royalty true + sales_region 'United States' + price 1.99 + reproduction_royalty true public_performance_royalty true reproduction_royalty_amount 0.999 licensor_royalty_amount 0.999 - sequence(:plan_code) { |n| "jamtrack-#{n}" } + sequence(:plan_code) { |n| "jamtrack-#{n}" } - genres [JamRuby::Genre.first] - association :licensor, factory: :jam_track_licensor + genres [JamRuby::Genre.first] + association :licensor, factory: :jam_track_licensor factory :jam_track_with_tracks do after(:create) do |jam_track, evaluator| @@ -800,46 +800,46 @@ FactoryGirl.define do end factory :jam_track_track, :class => JamRuby::JamTrackTrack do - position 1 - part 'lead guitar' - track_type 'Track' - instrument JamRuby::Instrument.find('electric guitar') - association :jam_track, factory: :jam_track + position 1 + part 'lead guitar' + track_type 'Track' + instrument JamRuby::Instrument.find('electric guitar') + association :jam_track, factory: :jam_track end factory :jam_track_right, :class => JamRuby::JamTrackRight do - association :jam_track, factory: :jam_track - association :user, factory: :user + association :jam_track, factory: :jam_track + association :user, factory: :user signing_44 false signing_48 false end factory :jam_track_tap_in, :class => JamRuby::JamTrackTapIn do - association :jam_track, factory: :jam_track - offset_time 0 - bpm 120 - tap_in_count 3 + association :jam_track, factory: :jam_track + offset_time 0 + bpm 120 + tap_in_count 3 end factory :download_tracker, :class => JamRuby::DownloadTracker do - remote_ip '1.1.1.1' - paid false + remote_ip '1.1.1.1' + paid false association :user, factory: :user association :jam_track, factory: :jam_track end factory :sale, :class => JamRuby::Sale do order_total 0 - association :user, factory:user + association :user, factory: user end factory :recurly_transaction_web_hook, :class => JamRuby::RecurlyTransactionWebHook do transaction_type JamRuby::RecurlyTransactionWebHook::SUCCESSFUL_PAYMENT - sequence(:recurly_transaction_id ) { |n| "recurly-transaction-id-#{n}" } - sequence(:subscription_id ) { |n| "subscription-id-#{n}" } - sequence(:invoice_id ) { |n| "invoice-id-#{n}" } - sequence(:invoice_number ) { |n| 1000 + n } + sequence(:recurly_transaction_id) { |n| "recurly-transaction-id-#{n}" } + sequence(:subscription_id) { |n| "subscription-id-#{n}" } + sequence(:invoice_id) { |n| "invoice-id-#{n}" } + sequence(:invoice_number) { |n| 1000 + n } invoice_number_prefix nil action 'purchase' status 'success' @@ -890,12 +890,12 @@ FactoryGirl.define do end factory :gift_card, class: 'JamRuby::GiftCard' do - sequence(:code) {n.to_s} - card_type JamRuby::GiftCardType::JAM_TRACKS_5 + sequence(:code) { n.to_s } + card_type JamRuby::GiftCardType::JAM_TRACKS_5 end factory :gift_card_type, class: 'JamRuby::GiftCardType' do - card_type JamRuby::GiftCardType::JAM_TRACKS_5 + card_type JamRuby::GiftCardType::JAM_TRACKS_5 end factory :gift_card_purchase, class: 'JamRuby::GiftCardPurchase' do @@ -907,8 +907,8 @@ FactoryGirl.define do association :user, factory: :user - sequence(:serial_no ) { |n| "serial_no#{n}" } - sequence(:client_id ) { |n| "client_id#{n}" } + sequence(:serial_no) { |n| "serial_no#{n}" } + sequence(:client_id) { |n| "client_id#{n}" } end factory :jamblaster_pairing_request, class: 'JamRuby::JamblasterPairingRequest' do @@ -916,13 +916,13 @@ FactoryGirl.define do association :user, factory: :user association :jamblaster, factory: :jamblaster - sequence(:jamblaster_client_id ) { |n| "jamblaster_client_id#{n}" } - sequence(:sibling_key ) { |n| "sibling_key#{n}" } + sequence(:jamblaster_client_id) { |n| "jamblaster_client_id#{n}" } + sequence(:sibling_key) { |n| "sibling_key#{n}" } end factory :school, class: 'JamRuby::School' do association :user, factory: :user - sequence(:name) {|n| "Dat Music School"} + sequence(:name) { |n| "Dat Music School" } enabled true scheduling_communication 'teacher' end @@ -931,16 +931,16 @@ FactoryGirl.define do association :school, factory: :school note "hey come in in" as_teacher true - sequence(:email) {|n| "school_person#{n}@example.com"} - sequence(:first_name) {|n| "FirstName"} - sequence(:last_name) {|n| "LastName"} + sequence(:email) { |n| "school_person#{n}@example.com" } + sequence(:first_name) { |n| "FirstName" } + sequence(:last_name) { |n| "LastName" } accepted false end factory :lesson_booking_slot, class: 'JamRuby::LessonBookingSlot' do factory :lesson_booking_slot_single do slot_type 'single' - preferred_day {Date.today + 3} + preferred_day { Date.today + 3 } day_of_week nil hour 12 minute 30 @@ -960,14 +960,14 @@ FactoryGirl.define do factory :lesson_booking, class: 'JamRuby::LessonBooking' do association :user, factory: :user association :teacher, factory: :teacher_user - card_presumed_ok false - sent_notices false - recurring false - lesson_length 30 - lesson_type JamRuby::LessonBooking::LESSON_TYPE_FREE - payment_style JamRuby::LessonBooking::PAYMENT_STYLE_ELSEWHERE - description "Oh my goodness!" - status JamRuby::LessonBooking::STATUS_REQUESTED + card_presumed_ok false + sent_notices false + recurring false + lesson_length 30 + lesson_type JamRuby::LessonBooking::LESSON_TYPE_FREE + payment_style JamRuby::LessonBooking::PAYMENT_STYLE_ELSEWHERE + description "Oh my goodness!" + status JamRuby::LessonBooking::STATUS_REQUESTED before(:create) do |lesson_booking, evaluator| lesson_booking.lesson_booking_slots = [FactoryGirl.build(:lesson_booking_slot_single, lesson_booking: lesson_booking), FactoryGirl.build(:lesson_booking_slot_single, lesson_booking: lesson_booking)] @@ -994,8 +994,8 @@ FactoryGirl.define do student nil end - music_session {FactoryGirl.create(:music_session, creator: student)} - lesson_booking {FactoryGirl.create(:lesson_booking, user: student, teacher: teacher)} + music_session { FactoryGirl.create(:music_session, creator: student) } + lesson_booking { FactoryGirl.create(:lesson_booking, user: student, teacher: teacher) } association :teacher, factory: :teacher_user lesson_type JamRuby::LessonSession::LESSON_TYPE_SINGLE duration 30 @@ -1006,18 +1006,18 @@ FactoryGirl.define do end factory :charge, class: 'JamRuby::Charge' do - type 'JamRuby::Charge' + type 'JamRuby::Charge' amount_in_cents 1000 end factory :teacher_payment_charge, parent: :charge, class: 'JamRuby::TeacherPaymentCharge' do - type 'JamRuby::TeacherPaymentCharge' + type 'JamRuby::TeacherPaymentCharge' association :user, factory: :user end factory :lesson_payment_charge, parent: :charge, class: 'JamRuby::LessonPaymentCharge' do - type 'JamRuby::LessonPaymentCharge' + type 'JamRuby::LessonPaymentCharge' association :user, factory: :user end @@ -1037,7 +1037,7 @@ FactoryGirl.define do amount_in_cents 1000 end - + factory :ip_blacklist, class: "JamRuby::IpBlacklist" do remote_ip '1.1.1.1' end @@ -1055,15 +1055,63 @@ FactoryGirl.define do end factory :email_blacklist, class: "JamRuby::EmailBlacklist" do - sequence(:email) { |n| "person_#{n}@example.com"} + sequence(:email) { |n| "person_#{n}@example.com" } end factory :music_notation, class: "JamRuby::MusicNotation" do - attachment_type {JamRuby::MusicNotation::TYPE_NOTATION} + attachment_type { JamRuby::MusicNotation::TYPE_NOTATION } association :user, factory: :user file_url 'abc' size 100 file_name 'some_file.jpg' end + + factory :test_drive_package, class: "JamRuby::TestDrivePackage" do + + sequence(:name) { |n| "package-#{n}" } + + trait :one_pack do + package_type 1 + after(:create) do |package, evaluator| + 1.times.each do + FactoryGirl.create(:test_drive_package_teachers, test_drive_package: package) + end + end + end + + trait :two_pack do + package_type 2 + after(:create) do |package, evaluator| + 2.times.each do + FactoryGirl.create(:test_drive_package_teachers, test_drive_package: package) + end + end + end + + trait :four_pack do + package_type 4 + after(:create) do |package, evaluator| + 4.times.each do + FactoryGirl.create(:test_drive_package_teachers, test_drive_package: package) + end + end + end + + end + + factory :test_drive_package_teachers, class: "JamRuby::TestDrivePackageTeacher" do + association :user, factory: :teacher_user + association :test_drive_package, factory: [:test_drive_package, :four_pack] + end + + factory :test_drive_package_choice, class: "JamRuby::TestDrivePackageChoice" do + association :user, factory: :user + association :test_drive_package, factory: [:test_drive_package, :four_pack] + end + + factory :test_drive_package_choice_teacher, class: "JamRuby::TestDrivePackageChoiceTeacher" do + association :teacher, factory: :teacher_user + association :test_drive_package_choice, factory: :test_drive_package_choice + end end diff --git a/ruby/spec/jam_ruby/models/test_drive_package_choice_spec.rb b/ruby/spec/jam_ruby/models/test_drive_package_choice_spec.rb new file mode 100644 index 000000000..564ffd1d3 --- /dev/null +++ b/ruby/spec/jam_ruby/models/test_drive_package_choice_spec.rb @@ -0,0 +1,14 @@ +require 'spec_helper' + +describe TestDrivePackageChoice do + + it "works" do + + choice = FactoryGirl.create(:test_drive_package_choice) + choice.test_drive_package.package_type.should eql 4 + choice.test_drive_package.test_drive_package_teachers.count.should eql 4 + + teacher_choice = FactoryGirl.create(:test_drive_package_choice_teacher, test_drive_package_choice: choice) + teacher_choice.test_drive_package_choice.should eql choice + end +end \ No newline at end of file diff --git a/ruby/spec/spec_helper.rb b/ruby/spec/spec_helper.rb index bc1163e38..911452807 100644 --- a/ruby/spec/spec_helper.rb +++ b/ruby/spec/spec_helper.rb @@ -38,7 +38,7 @@ require 'timecop' require 'resque_spec/scheduler' # uncomment this to see active record logs -ActiveRecord::Base.logger = Logger.new(STDOUT) if defined?(ActiveRecord::Base) +# ActiveRecord::Base.logger = Logger.new(STDOUT) if defined?(ActiveRecord::Base) include JamRuby diff --git a/ruby/spec/support/utilities.rb b/ruby/spec/support/utilities.rb index b058ea23e..ca203612f 100644 --- a/ruby/spec/support/utilities.rb +++ b/ruby/spec/support/utilities.rb @@ -305,6 +305,9 @@ def app_config :ach_pct => 0.008 } end + def musician_count + '40,000+' + end private def audiomixer_workspace_path diff --git a/web/app/assets/javascripts/everywhere/everywhere.js b/web/app/assets/javascripts/everywhere/everywhere.js index 234b7d105..a6e5a721d 100644 --- a/web/app/assets/javascripts/everywhere/everywhere.js +++ b/web/app/assets/javascripts/everywhere/everywhere.js @@ -213,6 +213,7 @@ } function handleGettingStarted(app) { + /** var user = app.user() if(user) { user.done(function(userProfile) { @@ -226,7 +227,7 @@ app.layout.showDialog('getting-started'); } }) - } + }*/ } function initShoppingCart(app) { diff --git a/web/app/assets/javascripts/helpBubbleHelper.js b/web/app/assets/javascripts/helpBubbleHelper.js index 0c7c05f65..df99b0bac 100644 --- a/web/app/assets/javascripts/helpBubbleHelper.js +++ b/web/app/assets/javascripts/helpBubbleHelper.js @@ -233,7 +233,10 @@ callback(container.find('.note').val(), container.find('.email').val(), container.find('.phonenumber').val()) return false; }) - console.log("hehelllo!") }}) } + + helpBubble.testDrivePackageGo = function($element, $offsetParent, package_type) { + return context.JK.prodBubble($element, 'test-drive-package-go', {plural: package_type != '1'}, bigHelpDarkOptions({offsetParent:$offsetParent, width:260, positions:['bottom']})) + } })(window, jQuery); \ No newline at end of file diff --git a/web/app/assets/javascripts/react-components/TestDrivePackageDialog.js.jsx.coffee b/web/app/assets/javascripts/react-components/TestDrivePackageDialog.js.jsx.coffee new file mode 100644 index 000000000..cc40d30fb --- /dev/null +++ b/web/app/assets/javascripts/react-components/TestDrivePackageDialog.js.jsx.coffee @@ -0,0 +1,97 @@ +context = window +@TestDrivePackageDialog = React.createClass({ + + mixins: [Reflux.listenTo(@AppStore, "onAppInit")] + teacher: null + + beforeShow: (args) -> + # d1 should be a teacher ID (vs a user ID that happens to be a teacher) + logger.debug("TestDrivePackageDialog.beforeShow", args.d1) + @setState({target: args.d1, page_data: window.page_data}) + + + afterHide: () -> + + onAppInit: (@app) -> + dialogBindings = { + 'beforeShow': @beforeShow, + 'afterHide': @afterHide + }; + + @app.bindDialog('test-drive-package-dialog', dialogBindings); + + getInitialState: () -> + { + target: null, + page_data: null + } + + + componentDidMount: () -> + @root = $(@getDOMNode()) + + doCancel: (e) -> + e.preventDefault() + @app.layout.closeDialog('test-drive-package-dialog', true); + + selectTeachers: (e) -> + e.preventDefault() + + # validate + + if @state.target == '2' + checked = @root.find('input[type="checkbox"]:checked') + + if checked.length != 2 + context.JK.Banner.showNotice('hold on there', 'Please select 2 teachers.') + return + + if @state.target == '1' + checked = @root.find('input[type="checkbox"]:checked') + + if checked.length != 1 + context.JK.Banner.showNotice('hold on there', 'Please select a teacher.') + return + + teachers = [] + $.each(checked, (i, node) => ( + $node = $(node) + teachers.push($node.data('teacher')) + )) + @root.data('result', { package_type: @state.target, teachers: teachers }) + render: () -> + + if @state.target == '2' + help = + `

+ Check the boxes under the 2 instructors you want to select for your TestDrive package. Then click the Select button below. +

` + else + help = + `

+ Check the box under the instructor you want to select for your TestDrive package. Then click the Select button below. +

` + + teachers = [] + + + `
+
+ + +

select instructors

+
+
+ + {help} + + {teachers} + +
+ CANCEL + SELECT +
+
+
` + +}) \ No newline at end of file diff --git a/web/app/assets/javascripts/react-components/landing/JamClassAffiliateLandingPage.js.jsx.coffee b/web/app/assets/javascripts/react-components/landing/JamClassAffiliateLandingPage.js.jsx.coffee index 379a8d79f..3bd61abf5 100644 --- a/web/app/assets/javascripts/react-components/landing/JamClassAffiliateLandingPage.js.jsx.coffee +++ b/web/app/assets/javascripts/react-components/landing/JamClassAffiliateLandingPage.js.jsx.coffee @@ -72,7 +72,7 @@ rest = context.JK.Rest() JamKazam has developed incredibly unique and engaging digital music technologies, content, - and marketplaces used by our rapidly growing community of 30,000+ musicians. Now we’ve + and marketplaces used by our rapidly growing community of {gon.global.musician_count} musicians. Now we’ve crafted an affiliate program specifically for music stores and music schools to increase your diff --git a/web/app/assets/javascripts/react-components/landing/JamClassStudentLandingMiddlePage.js.jsx.coffee b/web/app/assets/javascripts/react-components/landing/JamClassStudentLandingMiddlePage.js.jsx.coffee new file mode 100644 index 000000000..bb1d8366a --- /dev/null +++ b/web/app/assets/javascripts/react-components/landing/JamClassStudentLandingMiddlePage.js.jsx.coffee @@ -0,0 +1,143 @@ +@JamClassStudentLandingMiddlePage = React.createClass({ + + avatar: (name = 'your choice', photo_url = '/assets/shared/avatar_generic.png') -> + `
+
+ +
+
+ {name} +
+
` + + getInitialState: () -> + { + modified: false + package_type: null + teachers: null + } + + selector: (count, e) -> + e.preventDefault() + + context.JK.app.layout.showDialog('test-drive-package-dialog').one(contexnt.JK.EVENTS.DIALOG_CLOSED, (e, data) => + #... code + if !data.canceled + console.log("dialog closed. result", data.result) + # dialog wasn't cancelled, so let's check the value of our result: + @setState(data.result) + + + setTimeout((() => context.JK.prodBubble($('.preview-area.jam-class'), 'body', data.result.package_type)), 1500) + ) + + componentDidMount: () -> + @root = $(@getDOMNode()) + @root.find('.bio p').dotdotdot() + + componentDidUpdate:( ) -> + + @root.find('.bio p').dotdotdot() + render: () -> + + if this.props.package? + + package_type = this.state.package_type || this.props.package.package_type + + if package_type == '4' + description = + `
+

The single most important factor in the success of your music lessons is your teacher. You wouldn't marry + the first person you date, right?

+ +

Take full 30-minute lessons from each of these 4 amazing teachers for just $12.50 each - a total of + $49.99. Then you can pick the one who is best for you to continue your musical journey, with the + confidence that your investment in lessons will deliver maximum growth!

+
` + + options = + `
+

Like the TestDrive concept, but 4 teachers is too many for you?

+ +
` + else if package_type == '2' + description = + `
+

The single most important factor in the success of your music lessons is your teacher. You wouldn't marry + the first person you date, right?

+ +

Take full 30-minute lessons from each of these 2 amazing teachers for just $14.99 each - a total of + $29.99. Then you can pick the one who is best for you to continue your musical journey, with the + confidence that your investment in lessons will deliver maximum growth!

+
` + + options = + `
+

Like the TestDrive concept, but prefer not to try 2 different teachers?

+ +
` + else + description = + `
+

Take a full 30-minute lesson from this great teacher for just $14.99 - half the cost of a typical music + lesson. You can make sure everything is working great, and then continue your musical journey with the + confidence that your investment in lessons will deliver maximum growth!

+
` + options = + `
+

You can book a TestDrive lesson with this awesome teacher now!

+

Or you can search all of our teachers and then book a TestDrive package.

+
` + + teacherList = @state.teachers || this.props.package.teachers + + if @state.modified + options = null + + teachers = [] + for teacher in teacherList + biography = teacher.biography + biography = biography.replace(/\n/g, "
") + teachers.push( + `
+ {this.avatar(teacher.name, teacher.photo_url)} +
+

+
+
`) + + `
+

SIGN UP FOR TESTDRIVE NOW!

+ {description} + + {teachers} + + {options} +
` + else + `
+

SIGN UP FOR TESTDRIVE NOW!

+ +

The single most important factor in the success of your music lessons is your teacher. You wouldn't marry the + first person you date, right? Our TestDrive program lets you:

+ + +

Then continue your lessons with the best teacher for you!

+ +

Join 40,000+ other musicians in the JamKazam community. Sign up for TestDrive today, and + you'll be eligible for any of the three special offers above!

+ +

Not sure if this is for you? Scroll down to learn more...

+
` +}) \ No newline at end of file diff --git a/web/app/assets/javascripts/react-components/landing/JamClassStudentLandingPage.js.jsx.coffee b/web/app/assets/javascripts/react-components/landing/JamClassStudentLandingPage.js.jsx.coffee index f854d5e2a..1b7130f5b 100644 --- a/web/app/assets/javascripts/react-components/landing/JamClassStudentLandingPage.js.jsx.coffee +++ b/web/app/assets/javascripts/react-components/landing/JamClassStudentLandingPage.js.jsx.coffee @@ -143,7 +143,7 @@ rest = context.JK.Rest() rest.updateUser({student: true}) .done((response) => this.setState({done: true}) - context.location = '/client#/profile/' + context.JK.currentUserId + context.location = '/client#/jamclass/searchOptions' ) .fail((jqXHR) => this.setState({processing: false}) @@ -159,7 +159,7 @@ rest = context.JK.Rest() rest.signup({email: email, password: password, first_name: null, last_name: null, terms: terms, student: true}) .done((response) => @setState({done: true}) - context.location = '/client#/profile/' + response.id + context.location = '/client#/jamclass/searchOptions' ).fail((jqXHR) => @setState({processing: false}) if jqXHR.status == 422 diff --git a/web/app/assets/javascripts/react-components/landing/ProductJamBlasterBottomPage.js.jsx.coffee b/web/app/assets/javascripts/react-components/landing/ProductJamBlasterBottomPage.js.jsx.coffee index c06cb2ba9..44fae616f 100644 --- a/web/app/assets/javascripts/react-components/landing/ProductJamBlasterBottomPage.js.jsx.coffee +++ b/web/app/assets/javascripts/react-components/landing/ProductJamBlasterBottomPage.js.jsx.coffee @@ -143,7 +143,7 @@ context = window

Why Did We Design and Build the JamBlaster?

Speed

-

When we initially built the free JamKazam service to let musicians play together live over the Internet, we started by having musicians use the Mac and Windows computers and audio interfaces they already own. We've signed up 30,000+ musicians along the way. We've analyzed data from more than 100,000 online sessions. And we've collected audio processing latency data on thousands of combinations of computers and interfaces, as well as 10 million Internet latency measurements between unique pairs of locations and ISPs. We've learned a lot from all this data.

+

When we initially built the free JamKazam service to let musicians play together live over the Internet, we started by having musicians use the Mac and Windows computers and audio interfaces they already own. We've signed up {gon.global.musician_count} musicians along the way. We've analyzed data from more than 100,000 online sessions. And we've collected audio processing latency data on thousands of combinations of computers and interfaces, as well as 10 million Internet latency measurements between unique pairs of locations and ISPs. We've learned a lot from all this data.

Typically you need to keep total one way latency down to 30 to 35 milliseconds or less in an online session, or the session will get too sloppy and fall apart. We found that the average audio processing latency of industry standard gear is 14 milliseconds (full round trip including analog-to-digital and digital-to-analog conversions). So just processing the audio eats up half of your total latency budget!

We designed the JamBlaster from the ground up to be the fastest audio processing device possible, and we have the JamBlaster running at 2.8 milliseconds of latency full round trip - a massive latency savings. Every one millisecond saved on audio processing is worth about 100 miles of range on the Internet backbone. The JamBlaster also reduces something called audio processing jitter, which delivers additional latency savings. The result is that the JamBlaster saves audio latency equivalent to about 1,500 miles of distance compared to today's standard computers and interfaces.

Looking at it another way, using JamKazam with standard computers and interfaces, a musician in the U.S. can play effectively with about 10% of the other musicians in the U.S. With the JamBlaster, that same musician can now play with about 35% of the other musicians in the U.S.

@@ -206,7 +206,7 @@ context = window

The JamBlaster Plugs Into The JamKazam Platform And Community

-

JamKazam has already signed up 30,000+ musicians who play in thousands of online sessions per month using their computers and audio interfaces. The JamBlaster interoperates seamlessly with other musicians who are running Mac and Windows PC setups, so you can jump right in and start playing with other musicians in the community using your JamBlaster from day one.

+

JamKazam has already signed up {gon.global.musician_count} musicians who play in thousands of online sessions per month using their computers and audio interfaces. The JamBlaster interoperates seamlessly with other musicians who are running Mac and Windows PC setups, so you can jump right in and start playing with other musicians in the community using your JamBlaster from day one.

diff --git a/web/app/assets/javascripts/react-components/stores/SessionStore.js.coffee b/web/app/assets/javascripts/react-components/stores/SessionStore.js.coffee index f8504382a..d1886455e 100644 --- a/web/app/assets/javascripts/react-components/stores/SessionStore.js.coffee +++ b/web/app/assets/javascripts/react-components/stores/SessionStore.js.coffee @@ -82,13 +82,13 @@ ConfigureTracksActions = @ConfigureTracksActions this.trigger(@helper) onWindowBackgrounded: () -> - @app.user() - .done((userProfile) => - if userProfile.show_whats_next && - window.location.pathname.indexOf(gon.client_path) == 0 && - !@app.layout.isDialogShowing('getting-started') - @app.layout.showDialog('getting-started') - ) + #@app.user() + #.done((userProfile) => + #if userProfile.show_whats_next && + # window.location.pathname.indexOf(gon.client_path) == 0 && + # !@app.layout.isDialogShowing('getting-started') + # @app.layout.showDialog('getting-started') + #) return unless @inSession() diff --git a/web/app/assets/javascripts/web/web.js b/web/app/assets/javascripts/web/web.js index 561e44bf9..a5ec3c545 100644 --- a/web/app/assets/javascripts/web/web.js +++ b/web/app/assets/javascripts/web/web.js @@ -22,6 +22,7 @@ //= require jquery.bt //= require jquery.exists //= require jquery.visible +//= require jquery.lessonSessionActions //= require howler.core.js //= require AAA_Log //= require AAC_underscore diff --git a/web/app/assets/stylesheets/landings/individual_jamtrack.css.scss b/web/app/assets/stylesheets/landings/individual_jamtrack.css.scss index 3c3c3b67b..dce28bbb0 100644 --- a/web/app/assets/stylesheets/landings/individual_jamtrack.css.scss +++ b/web/app/assets/stylesheets/landings/individual_jamtrack.css.scss @@ -13,17 +13,16 @@ $fluid-break: 1100px; } } - body.web.individual_jamtrack { h1.web-tagline { @include layout-small { - display:none; + display: none; } } .wrapper { @include layout-small { - width:auto; + width: auto; } } $copy-color-on-dark: #b9b9b9; @@ -33,12 +32,12 @@ body.web.individual_jamtrack { [data-react-class="JamClassStudentLandingPage"] { h2.future-header { - color:white; - margin-bottom:20px; + color: white; + margin-bottom: 20px; } ol, ul, li { - font-size:16px; - line-height:75%; + font-size: 16px; + line-height: 75%; color: $copy-color-on-dark; } ol { @@ -48,33 +47,33 @@ body.web.individual_jamtrack { list-style-type: disc; } li { - margin-left:20px; + margin-left: 20px; margin-bottom: 10px; } } .logo-home { @include layout-small { - margin-left:20px !important; + margin-left: 20px !important; } } .full-row { width: 100%; @include layout-small { - padding-left:20px !important; - padding-right:20px !important; + padding-left: 20px !important; + padding-right: 20px !important; } } .row { width: 663px; @include layout-small { - padding-left:20px !important; - padding-right:20px !important; + padding-left: 20px !important; + padding-right: 20px !important; } @include layout-small { - width:auto; + width: auto; } } @@ -82,21 +81,21 @@ body.web.individual_jamtrack { position: relative; top: -150px; right: 107px; - background-color:black; + background-color: black; &.student { - top:-13px; + top: -13px; } } .name-and-artist { padding-top: 60px; .ios-appstore-badge { - display:inline !important; + display: inline !important; img { - width:33%; + width: 33%; } - font-size:40pt; + font-size: 40pt; } } @@ -109,8 +108,8 @@ body.web.individual_jamtrack { line-height: 175%; @include layout-small { - font-size:40pt; - line-height:150%; + font-size: 40pt; + line-height: 150%; } } } @@ -129,33 +128,33 @@ body.web.individual_jamtrack { @include layout-small { h2 { - text-align:center; + text-align: center; } } &.jam-class { - padding:20px 0; + padding: 20px 0; &:nth-of-type(1) { - padding-top:80px; + padding-top: 80px; &.teachers { - padding-top:100px; + padding-top: 100px; } } - width:1050px; + width: 1050px; p { - line-height:125%; - margin-bottom:20px; + line-height: 125%; + margin-bottom: 20px; } a { - color:$cta-color; + color: $cta-color; } ol, ul, li { - font-size:16px; - line-height:125%; + font-size: 16px; + line-height: 125%; color: $copy-color-on-white; } ol { @@ -165,7 +164,7 @@ body.web.individual_jamtrack { list-style-type: disc; } li { - margin-left:20px; + margin-left: 20px; margin-bottom: 10px; } @@ -174,15 +173,15 @@ body.web.individual_jamtrack { padding-bottom: 40%; } .tab-and-return { - margin-top:20px; - font-size:12px; - color:$copy-color-on-white; + margin-top: 20px; + font-size: 12px; + color: $copy-color-on-white; } .search-area { - text-align:center; + text-align: center; a { color: $cta-color; - font-size:30px; + font-size: 30px; } } } @@ -197,78 +196,78 @@ body.web.individual_jamtrack { &.multi-para { p:nth-of-type(2) { - margin-bottom:20px; + margin-bottom: 20px; } } .video-wrapper { - margin-bottom:10px; + margin-bottom: 10px; &.bottomed { - margin-bottom:80px; + margin-bottom: 80px; } &.longbottomed { - margin-bottom:110px; + margin-bottom: 110px; } .cta-text { - color:$copy-color-on-dark; + color: $copy-color-on-dark; } } a { - color:blue; - text-decoration:underline; + color: blue; + text-decoration: underline; } .teacher-icons { - float:right; - max-width:250px; - margin-left:20px; + float: right; + max-width: 250px; + margin-left: 20px; .top-left { - margin-right:15px; - float:left; + margin-right: 15px; + float: left; } .top-right { - float:right; + float: right; } .bottom-left { - float:left; - margin-right:15px; + float: left; + margin-right: 15px; } .bottom-right { - float:right; + float: right; } .top-teacher-row { } .bottom-teacher-row { } .testdrive-note { - font-style:italic; - text-align:center; - margin-top:20px; + font-style: italic; + text-align: center; + margin-top: 20px; } } } .audio-wrapper { - float:left; - padding:10px 20px 20px; - text-align:center; - width:200px; + float: left; + padding: 10px 20px 20px; + text-align: center; + width: 200px; a { - display:inline-block; - margin-top:20px; + display: inline-block; + margin-top: 20px; color: $cta-color; - text-decoration:none; + text-decoration: none; } .sample-audio-text { - margin-top:3px; - text-align:center; + margin-top: 3px; + text-align: center; } .listening-note { - margin-top:20px; - font-style:italic; - font-size:12px; + margin-top: 20px; + font-style: italic; + font-size: 12px; } } @@ -279,19 +278,19 @@ body.web.individual_jamtrack { @include border_box_sizing; width: 663px; @include layout-small { - width:auto; + width: auto; } } .video-wrapper { float: right; margin-left: 10px; - margin-bottom:80px; + margin-bottom: 80px; .cta-text { margin-left: 10px; - text-align:center; - margin-top:20px; + text-align: center; + margin-top: 20px; } &.left { float: left; @@ -306,7 +305,7 @@ body.web.individual_jamtrack { } .edit-link { - font-size:12px; + font-size: 12px; } .video-container { @@ -314,7 +313,7 @@ body.web.individual_jamtrack { padding-bottom: 53.33%; @include layout-small { - width:200px; + width: 200px; } } @@ -378,28 +377,28 @@ body.web.individual_jamtrack { color: $copy-color-on-dark; } @include layout-small { - text-align:center; + text-align: center; } - ol, ul, li { - font-size:16px; - line-height:100%; - color: $copy-color-on-dark; - } - ol { - list-style-type: decimal; - } - p.bump { - margin-bottom:20px; + ol, ul, li { + font-size: 16px; + line-height: 100%; + color: $copy-color-on-dark; + } + ol { + list-style-type: decimal; + } + p.bump { + margin-bottom: 20px; + } + ul { + margin: 20px 0; + list-style-type: disc; + } + li { + margin-left: 20px; + margin-bottom: 10px; } - ul { - margin:20px 0; - list-style-type: disc; - } - li { - margin-left:20px; - margin-bottom: 10px; - } } @@ -423,7 +422,7 @@ body.web.individual_jamtrack { } img.gift-card-preview { - width:300px; + width: 300px; float: left; margin-left: -15px; // because image has black on the left, which you can't see on back background margin-right: 20px; @@ -431,27 +430,27 @@ body.web.individual_jamtrack { } img.jam-class-teacher { - width:375px; - height:215px; - float:left; + width: 375px; + height: 215px; + float: left; margin-right: 20px; margin-bottom: 20px; } p.gift-getter { - margin-top:20px; - line-height:125%; + margin-top: 20px; + line-height: 125%; } img.app-preview { width: 340px; - height:178px; + height: 178px; float: left; margin-left: -15px; // because image has black on the left, which you can't see on back background margin-right: 20px; margin-bottom: 30px; @include layout-small { - width:33%; + width: 33%; } } h1.jam-track-name { @@ -461,7 +460,7 @@ body.web.individual_jamtrack { margin-left: 35px; @include layout-small { - font-size:45pt !important; + font-size: 45pt !important; } } @@ -472,11 +471,11 @@ body.web.individual_jamtrack { margin-left: 35px; @include layout-small { - font-size:40pt !important; + font-size: 40pt !important; } @include layout-small { - margin-bottom:20px; + margin-bottom: 20px; } } @@ -485,11 +484,11 @@ body.web.individual_jamtrack { } .cta-button { - cursor:pointer; + cursor: pointer; background-color: $cta-color; &.processing { - background-color:gray; + background-color: gray; } } @@ -500,7 +499,7 @@ body.web.individual_jamtrack { .privacy-policy { color: #ffcf00; @include layout-small { - font-size:30pt; + font-size: 30pt; } } @@ -521,22 +520,22 @@ body.web.individual_jamtrack { } .arrow1 { - position:absolute; + position: absolute; left: -371px; top: -80px; @include layout-small { - display:none; + display: none; } } .arrow2 { - position:absolute; - left:-230px; - top:373px; + position: absolute; + left: -230px; + top: 373px; @include layout-small { - display:none; + display: none; } } @@ -548,38 +547,38 @@ body.web.individual_jamtrack { } .testimonials { - background-color:white; - position:absolute; - width:350px; - right:55px; - top:287px; + background-color: white; + position: absolute; + width: 350px; + right: 55px; + top: 287px; @include border_box_sizing; - z-index:1; + z-index: 1; @include layout-small { - width:auto; - position:static; + width: auto; + position: static; } &.jam-class { - top:557px; + top: 557px; h3 { - color:$cta-color; + color: $cta-color; } &.teachers { - top:729px; + top: 729px; } } .jamtrack-overview-video { h3 { - font-size:21px; - width:400px; + font-size: 21px; + width: 400px; } .video-wrapper { - float:left; + float: left; .video-container { width: 400px; padding-bottom: 53.33%; @@ -590,65 +589,65 @@ body.web.individual_jamtrack { @include layout-small { display: inline-block; width: 100%; - text-align:center; + text-align: center; h3 { - width:auto; - text-align:center; + width: auto; + text-align: center; } - .video-wrapper{ - float:none; - display:inline-block; - margin:auto; + .video-wrapper { + float: none; + display: inline-block; + margin: auto; } } } h3 { - color:$copy-color-on-white; - text-align:left; - margin-bottom:20px; - font-size:30px; - line-height:125%; + color: $copy-color-on-white; + text-align: left; + margin-bottom: 20px; + font-size: 30px; + line-height: 125%; @include layout-small { - text-align:center; + text-align: center; } } h4 { - position:absolute; + position: absolute; top: 161px; left: 173px; - font-size:14px; - color:$copy-color-on-white; + font-size: 14px; + color: $copy-color-on-white; strong { - font-weight:bold; + font-weight: bold; } - white-space:nowrap; + white-space: nowrap; } .testimonial { - position:relative; - width:350px; - margin-bottom:40px; + position: relative; + width: 350px; + margin-bottom: 40px; @include layout-small { - margin:0 auto 40px; + margin: 0 auto 40px; } } .testimonial-speech-bubble { - width:350px; + width: 350px; } .testimonial-avatar { - width:60px; - position:relative; - top:5px; - left:92px; + width: 60px; + position: relative; + top: 5px; + left: 92px; } .testimonial-youtube { - width:143px; - position:relative; - left:112px; - top:0; + width: 143px; + position: relative; + left: 112px; + top: 0; } .testiminal-background { width: 200px; @@ -656,7 +655,7 @@ body.web.individual_jamtrack { left: 174px; top: 181px; font-size: 12px; - color:$copy-color-on-white; + color: $copy-color-on-white; } } @@ -666,7 +665,7 @@ body.web.individual_jamtrack { } .jamclass-h2 { - margin:10px 0 20px; + margin: 10px 0 20px; color: #8d8d8d; font-size: 20px; } @@ -690,8 +689,8 @@ body.web.individual_jamtrack { @include border_box_sizing; } .logo-composite-header { - text-align:center; - color:$ColorTextTypical; + text-align: center; + color: $ColorTextTypical; } .preview-and-action-box { background-color: black; @@ -706,21 +705,21 @@ body.web.individual_jamtrack { z-index: 1; @include layout-small { - margin:20px 20px; - position:static; - width:calc(100% - 40px); - max-width:calc(100% - 40px); + margin: 20px 20px; + position: static; + width: calc(100% - 40px); + max-width: calc(100% - 40px); } &.jamclass { - top:209px; + top: 209px; &.student { - top:541px; + top: 541px; .cta-button { - width:70%; - margin-left:15%; + width: 70%; + margin-left: 15%; } } } @@ -736,14 +735,14 @@ body.web.individual_jamtrack { border-color: $copy-color-on-dark; @include layout-small { - font-size:40pt; + font-size: 40pt; } &.gift-card { - padding:20px 0 10px; + padding: 20px 0 10px; .jamtrack-title { - margin-top:10px; - font-size:18px; - font-style:italic; + margin-top: 10px; + font-size: 18px; + font-style: italic; } } @@ -756,13 +755,13 @@ body.web.individual_jamtrack { border-width: 0 0 $chunkyBorderWidth; @include layout-small { - font-size:20px; + font-size: 20px; } &.jam-class { border-width: 0 0 2px; p { - padding:8px 10px; - text-align:center; + padding: 8px 10px; + text-align: center; @include border_box_sizing; } } @@ -771,27 +770,27 @@ body.web.individual_jamtrack { border-color: $copy-color-on-dark; &.logged-in { - border-width:0; + border-width: 0; .tracks { - height:258px; + height: 258px; } } .tracks { - padding:10px 0 20px; - margin-top:10px; + padding: 10px 0 20px; + margin-top: 10px; overflow-y: scroll; height: 160px; - margin-bottom:10px; + margin-bottom: 10px; @include layout-small { - max-height:13em; - height:auto; + max-height: 13em; + height: auto; } } .cta-buttons { - text-align:center; + text-align: center; } .cta-button { font-size: 24px; @@ -801,67 +800,67 @@ body.web.individual_jamtrack { padding: 10px; display: block; width: 100%; - border-radius:8px; + border-radius: 8px; border: 1px outset buttonface; font-family: Raleway, Arial, Helvetica, sans-serif; @include layout-small { - font-size:30pt; + font-size: 30pt; } &.gift-card { - font-size:16px; - width:138px; - margin:15px 5px; - display:inline-block; + font-size: 16px; + width: 138px; + margin: 15px 5px; + display: inline-block; } } } .terms-help { - float:left; - margin-top:2px; - font-size:12px; + float: left; + margin-top: 2px; + font-size: 12px; } .register-area { @include layout-small { label { - width:40% !important; - text-align:right; - padding-right:20px; + width: 40% !important; + text-align: right; + padding-right: 20px; &.terms-help { - height:auto !important; + height: auto !important; } @include layout-small { - height:40pt; - font-size:30pt; + height: 40pt; + font-size: 30pt; } } input { - width:60% !important; + width: 60% !important; @include layout-small { - height:40pt; - font-size:30pt; + height: 40pt; + font-size: 30pt; } } } &.jam-class { - padding:0; + padding: 0; } &.ios { - background-color:$cta-color; - font-size:40pt; + background-color: $cta-color; + font-size: 40pt; .ios-appstore-badge { - display:inline-block; - text-align:center; - margin-left:20px; - margin-top:30px; + display: inline-block; + text-align: center; + margin-left: 20px; + margin-top: 30px; width: 100%; img { - width:50%; + width: 50%; } } } @@ -872,35 +871,35 @@ body.web.individual_jamtrack { font-size: 16px; @include layout-small { - font-size:30pt; + font-size: 30pt; } &[name="terms"] { - width:auto; - line-height:24px; - vertical-align:middle; + width: auto; + line-height: 24px; + vertical-align: middle; @include layout-small { - line-height:125%; + line-height: 125%; } } } .checkbox-wrap { float: left; margin-top: 6px; - margin-left:64px; + margin-left: 64px; @include border_box_sizing; - text-align:right; + text-align: right; input { - height:auto; + height: auto; @include layout-small { height: 30pt !important; width: 30pt !important; } } @include layout-small { - width:40%; - margin-left:0; + width: 40%; + margin-left: 0; .icheckbox_minimal { right: -18px; } @@ -910,7 +909,6 @@ body.web.individual_jamtrack { } } - .privacy-policy { text-decoration: underline; @@ -920,9 +918,9 @@ body.web.individual_jamtrack { margin: 0 0 10px; } .errors { - font-size:12px; - height:20px; - margin:0; + font-size: 12px; + height: 20px; + margin: 0; visibility: hidden; text-align: center; color: red; @@ -933,8 +931,8 @@ body.web.individual_jamtrack { } @include layout-small { - font-size:20pt; - height:32pt; + font-size: 20pt; + height: 32pt; } } label { @@ -946,17 +944,17 @@ body.web.individual_jamtrack { @include border-box_sizing; &.terms-help { - width:205px; - height:28px; - line-height:14px; - float:right; + width: 205px; + height: 28px; + line-height: 14px; + float: right; @include layout-small { - line-height:125%; + line-height: 125%; } } @include layout-small { - height:40pt; - font-size:30pt; + height: 40pt; + font-size: 30pt; } } input { @@ -967,8 +965,8 @@ body.web.individual_jamtrack { @include border-box_sizing; @include layout-small { - height:40pt; - font-size:30pt; + height: 40pt; + font-size: 30pt; } } } @@ -977,8 +975,8 @@ body.web.individual_jamtrack { color: white; font-size: 14px; @include layout-small { - font-size:40pt; - line-height:125%; + font-size: 40pt; + line-height: 125%; } } @@ -987,7 +985,7 @@ body.web.individual_jamtrack { .jam-track-preview-holder { margin-bottom: 7px; - float:left; + float: left; &[data-track-type="Master"] { width: 100%; } @@ -998,56 +996,111 @@ body.web.individual_jamtrack { } .jam-track-preview { - font-size:12px; - + font-size: 12px; @include layout-small { - font-size:40pt; - line-height:40pt; - width:100%; + font-size: 40pt; + line-height: 40pt; + width: 100%; .instrument-part { - width:auto; + width: auto; } - .instrument-icon{ - height:40pt; - width:40pt; + .instrument-icon { + height: 40pt; + width: 40pt; } .actions { .play-button, .stop-button { - height:40pt; - width:40pt; + height: 40pt; + width: 40pt; background-size: contain; } } } .instrument-part { - width:175px; + width: 175px; @include layout-small { width: calc(100% - 100pt); //font-size: 35px; } } - .instrument-name,.part { - display:none; + .instrument-name, .part { + display: none; } .loading-text { - right:-1px; - background-color:black; + right: -1px; + background-color: black; } } .price-advisory { - font-size:14px; - text-align:center; - color:white; - margin-top:10px; + font-size: 14px; + text-align: center; + color: white; + margin-top: 10px; @include layout-small { - font-size:20pt; + font-size: 20pt; } } .ios-appstore-badge { - display:block; - text-align:center; + display: block; + text-align: center; + } + + .packaged { + p { + margin-bottom:20px; + line-height:120%; + color:$copy-color-on-dark; + } + + } + .teacher-option { + margin-bottom:20px; + height: 98px; + .bio { + display: inline-block; + width: 423px; + height: 98px; + vertical-align: top; + font-style: italic; + + p { + display:inline-block; + width: 423px; + height: 98px; + margin-bottom:0; + overflow:hidden; + } + } + .avatar-header { + display: inline-block; + width: 140px; + margin-right: 20px; + } + + .avatar { + display: inline-block; + text-align:center; + padding: 1px; + width: 64px; + height: 64px; + background-color: #ed4818; + margin: 4px 8px 7px 0; + -webkit-border-radius: 32px; + -moz-border-radius: 32px; + border-radius: 32px; + float: none; + + } + .avatar img { + width: 64px; + height: 64px; + -webkit-border-radius: 32px; + -moz-border-radius: 32px; + border-radius: 32px; + + } } } \ No newline at end of file diff --git a/web/app/controllers/application_controller.rb b/web/app/controllers/application_controller.rb index 462876eaa..71783e4a4 100644 --- a/web/app/controllers/application_controller.rb +++ b/web/app/controllers/application_controller.rb @@ -18,17 +18,17 @@ class ApplicationController < ActionController::Base before_filter :track_affiliate_visits before_filter :track_origin - before_filter do - if params[AffiliatePartner::PARAM_REFERRAL].present? && current_user.nil? - if cookies[AffiliatePartner::PARAM_COOKIE].blank? - code = params[AffiliatePartner::PARAM_REFERRAL].downcase - cookies[AffiliatePartner::PARAM_COOKIE] = code if AffiliatePartner.is_code?(code) - end - end - end + #before_filter do + # if params[AffiliatePartner::PARAM_REFERRAL].present? && current_user.nil? + # if cookies[AffiliatePartner::PARAM_COOKIE].blank? + # code = params[AffiliatePartner::PARAM_REFERRAL].downcase + # cookies[AffiliatePartner::PARAM_COOKIE] = code if AffiliatePartner.is_code?(code) + # end + # end + #end def affiliate_code - cookies[AffiliatePartner::PARAM_COOKIE] + #cookies[AffiliatePartner::PARAM_COOKIE] end diff --git a/web/app/controllers/landings_controller.rb b/web/app/controllers/landings_controller.rb index 470a90dd8..50f8fd109 100644 --- a/web/app/controllers/landings_controller.rb +++ b/web/app/controllers/landings_controller.rb @@ -75,7 +75,28 @@ class LandingsController < ApplicationController @show_after_black_bar_border = true @free = false - @page_data = {free: @free} + package_name = params['utm-teachers'] + if package_name + package = TestDrivePackage.find_by_name(package_name) + + if package + package_data = {} + package_data[:id] = package.id + package_data[:name] = package.name + package_data[:package_type] = package.package_type + teachers = [] + package.test_drive_package_teachers.each do |package_teacher| + teacher = package_teacher.user + teachers.push({id: teacher.id, name: teacher.name, biography: teacher.teacher.biography, photo_url: teacher.photo_url}) + end + package_data[:teachers] = teachers + + @package_data = package_data + end + + end + + @page_data = {free: @free, package: @package_data} render 'jam_class_students', layout: 'web' end diff --git a/web/app/views/clients/_help.html.slim b/web/app/views/clients/_help.html.slim index d2c9455d9..1bb3e8cdd 100644 --- a/web/app/views/clients/_help.html.slim +++ b/web/app/views/clients/_help.html.slim @@ -464,4 +464,13 @@ script type="text/template" id="template-help-ftue-step-4-instructions" script type="text/template" id="template-help-ftue-step-5-instructions" .ftue-step-5-instructions.big-dark-help - p Please click here for detailed instructions to successfully complete this setup step. \ No newline at end of file + p Please click here for detailed instructions to successfully complete this setup step. + +script type="text/template" id="template-help-test-drive-package-go" + .test-drive-package-go + p + | {% if(data.plural) { %} + | Enter your email and a password, and click Sign Up to pay for and book your lesson with these awesome teachers! + | {% } else { %} + | Enter your email and a password, and click Sign Up to pay for and book your lesson with this awesome teacher! + | {% } %} \ No newline at end of file diff --git a/web/app/views/dialogs/_dialogs.html.haml b/web/app/views/dialogs/_dialogs.html.haml index 6d51c6828..5cc2b9531 100644 --- a/web/app/views/dialogs/_dialogs.html.haml +++ b/web/app/views/dialogs/_dialogs.html.haml @@ -54,4 +54,5 @@ = render 'dialogs/cancelLessonDialog' = render 'dialogs/rescheduleLessonDialog' = render 'dialogs/rateUserDialog' -= render 'dialogs/musicNotationUploadDialog' \ No newline at end of file += render 'dialogs/musicNotationUploadDialog' += render 'dialogs/testDrivePackageDialog' \ No newline at end of file diff --git a/web/app/views/dialogs/_testDrivePackageDialog.html.slim b/web/app/views/dialogs/_testDrivePackageDialog.html.slim new file mode 100644 index 000000000..b4007dbb5 --- /dev/null +++ b/web/app/views/dialogs/_testDrivePackageDialog.html.slim @@ -0,0 +1,2 @@ +.dialog.dialog-overlay-sm.top-parent layout='dialog' layout-id='test-drive-package-dialog' id='test-drive-package-dialog' + = react_component 'TestDrivePackageDialog', {} diff --git a/web/app/views/landings/buy_gift_card.html.slim b/web/app/views/landings/buy_gift_card.html.slim index d45cd2204..55f517598 100644 --- a/web/app/views/landings/buy_gift_card.html.slim +++ b/web/app/views/landings/buy_gift_card.html.slim @@ -7,7 +7,10 @@ - content_for :after_black_bar do .row.cta-row h2 GET YOUR GIFT CARD NOW! - p And join 30,000+ other musicians who love our JamTracks. + p + | And join  + = APP_CONFIG.musician_count + |  other musicians who love our JamTracks. p.cta-text Not sure if JamTracks are for you? Scroll down to learn more. - content_for :white_bar do diff --git a/web/app/views/landings/individual_jamtrack.html.slim b/web/app/views/landings/individual_jamtrack.html.slim index aed4d9205..47b250277 100644 --- a/web/app/views/landings/individual_jamtrack.html.slim +++ b/web/app/views/landings/individual_jamtrack.html.slim @@ -7,7 +7,10 @@ - content_for :after_black_bar do .row.cta-row h2 GET THIS JAMTRACK FREE NOW! - p And join 30,000+ other musicians who love our JamTracks. + p + | And join  + = APP_CONFIG.musician_count + |  other musicians who love our JamTracks. p.cta-text Not sure if JamTracks are for you? Scroll down to learn more. - content_for :white_bar do diff --git a/web/app/views/landings/jam_class_students.html.slim b/web/app/views/landings/jam_class_students.html.slim index 473636cb6..db57a5e97 100644 --- a/web/app/views/landings/jam_class_students.html.slim +++ b/web/app/views/landings/jam_class_students.html.slim @@ -5,20 +5,7 @@ = react_component 'JamClassStudentLandingPage', @page_data.to_json - content_for :after_black_bar do - .row.cta-row - - if @free - h2 SIGN UP FOR YOUR FREE LESSON NOW! - - else - h2 SIGN UP FOR TESTDRIVE NOW! - p - | The single most important factor in the success of your music lessons is your teacher. You wouldn't marry the first person you date, right? Our TestDrive program lets you: - ul - li Take a full lesson from 4 different teachers for just $12.49 each, or - li Take a full lesson from 2 different teachers for just $14.99 each, or - li Take a full lesson from 1 teacher for just $14.99 - p.bump Then continue your lessons with the best teacher for you! - p.bump Join 40,000+ other musicians in the JamKazam community. Sign up for TestDrive today, and you'll be eligible for any of the three special offers above! - p.cta-text Not sure if this is for you? Scroll down to learn more... + = react_component 'JamClassStudentLandingMiddlePage', @page_data.to_json - content_for :white_bar do = react_component 'JamClassStudentLandingBottomPage', @page_data.to_json diff --git a/web/app/views/landings/jam_class_teachers.html.slim b/web/app/views/landings/jam_class_teachers.html.slim index 6259abef9..15a2e6d35 100644 --- a/web/app/views/landings/jam_class_teachers.html.slim +++ b/web/app/views/landings/jam_class_teachers.html.slim @@ -7,7 +7,10 @@ - content_for :after_black_bar do .row.cta-row h2 SIGN UP TO TEACH NOW, IT'S FREE! - p And join 30,000+ other musicians in the JamKazam community. + p + | And join  + = APP_CONFIG.musician_count + |  other musicians in the JamKazam community. p.cta-text Not sure if JamClass is for you? Scroll down to learn more. - content_for :white_bar do diff --git a/web/app/views/layouts/web.html.erb b/web/app/views/layouts/web.html.erb index c53eceadd..ca7a619da 100644 --- a/web/app/views/layouts/web.html.erb +++ b/web/app/views/layouts/web.html.erb @@ -101,6 +101,8 @@ <%= render "clients/listenBroadcast" %> <%= render "clients/flash" %> <%= render "clients/jam_track_preview" %> + <%= render "clients/help" %> + <%= render "clients/lessonSessionActions" %> <%= render 'dialogs/dialogs' %>