This commit is contained in:
Seth Call 2016-01-29 15:16:35 -06:00
parent a327412a88
commit 93880bddf0
28 changed files with 1728 additions and 369 deletions

View File

@ -1,8 +1,43 @@
CREATE TABLE lesson_package_types (
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
name VARCHAR NOT NULL,
description VARCHAR NOT NULL,
package_type VARCHAR(64) NOT NULL,
price NUMERIC(8,2),
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE lesson_package_purchases (
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
lesson_package_type_id VARCHAR(64) REFERENCES lesson_package_types(id) NOT NULL,
user_id VARCHAR(64) REFERENCES users(id) NOT NULL,
teacher_id VARCHAR(64) REFERENCES teachers(id),
price NUMERIC(8,2),
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE lesson_sessions (
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
music_session_id VARCHAR(64) FOREIGN KEY ON REFERENCES music_sessions(id) NOT NULL,
music_session_id VARCHAR(64) REFERENCES music_sessions(id) NOT NULL,
lesson_type VARCHAR(64) NOT NULL,
teacher_id VARCHAR(64) REFERENCES teachers(id) NOT NULL,
lesson_package_purchase_id VARCHAR(64) REFERENCES lesson_package_purchases(id),
duration INTEGER NOT NULL,
price NUMERIC(8,2) NOT NULL,
)
teacher_complete BOOLEAN DEFAULT FALSE NOT NULL,
student_complete BOOLEAN DEFAULT FALSE NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
ALTER TABLE notifications ADD COLUMN lesson_session_id VARCHAR(64) REFERENCES lesson_sessions(id);
ALTER TABLE users ADD COLUMN is_a_student BOOLEAN NOT NULL DEFAULT FALSE;
ALTER TABLE users ADD COLUMN is_a_teacher BOOLEAN NOT NULL DEFAULT FALSE;
INSERT INTO lesson_package_types (id, name, description, package_type, price) VALUES ('single', 'Single Lesson', 'A single lesson purchased at the teacher''s price.', 'single', 0.00);
INSERT INTO lesson_package_types (id, name, description, package_type, price) VALUES ('single-free', 'Free Lesson', 'A free, single lesson.', 'single-free', 0.00);
INSERT INTO lesson_package_types (id, name, description, package_type, price) VALUES ('test-drive', 'Test Drive', 'Four reduced-price lessons which you can use to find that ideal teacher.', 'test-drive', 49.99);

View File

@ -264,7 +264,9 @@ require "jam_ruby/models/gift_card"
require "jam_ruby/models/gift_card_purchase"
require "jam_ruby/models/gift_card_type"
require "jam_ruby/models/jam_track_session"
require "jam_ruby/models/lesson_package_type"
require "jam_ruby/models/lesson_package_purchase"
require "jam_ruby/models/lesson_session"
include Jampb
module JamRuby

View File

@ -49,6 +49,36 @@
end
end
def student_welcome_message(user)
@user = user
sendgrid_category "Welcome"
sendgrid_unique_args :type => "welcome_message"
sendgrid_recipients([user.email])
sendgrid_substitute('@USERID', [user.id])
sendgrid_substitute(EmailBatchProgression::VAR_FIRST_NAME, [user.first_name])
mail(:to => user.email, :subject => "Welcome to JamKazam") do |format|
format.text
format.html
end
end
def teacher_welcome_message(user)
@user = user
sendgrid_category "Welcome"
sendgrid_unique_args :type => "welcome_message"
sendgrid_recipients([user.email])
sendgrid_substitute('@USERID', [user.id])
sendgrid_substitute(EmailBatchProgression::VAR_FIRST_NAME, [user.first_name])
mail(:to => user.email, :subject => "Welcome to JamKazam") do |format|
format.text
format.html
end
end
def password_changed(user)
@user = user

View File

@ -0,0 +1,119 @@
<% provide(:title, 'Welcome to JamKazam!') %>
<% if !@user.anonymous? %>
<p>Hello <%= EmailBatchProgression::VAR_FIRST_NAME %> --
</p>
<% end %>
<p> We're delighted you have decided to join the JamKazam community of musicians, and we hope
you will enjoy using JamKazam and JamTracks to play more music. Following are some
resources and some things you can do to get the most out of JamKazam.
</p>
<p><b style="color: white;">Playing With JamTracks</b><br/>
JamTracks are the best way to play along with your favorite songs. Far better and different than
traditional backing tracks, our JamTracks are complete multi-track professional recordings, with
fully isolated tracks for each part of the music. And our free app and Internet service are packed
with features that give you unmatched creative freedom to learn, practice, record, play with
others, and share your performances. Here are some great JamTracks resources:
</p>
<ul>
<li><a style="color:#fc0" href="https://www.youtube.com/watch?v=07zJC7C2ICA">JamTracks Overview Video</a> - See all the great things you can do with JamTracks.</li>
<li><a style="color:#fc0" href="https://jamkazam.desk.com/customer/en/portal/articles/2124663-playing-with-jamtracks">JamTracks User Guide</a> - A set of articles that explain how to use all the JamTracks
features.</li>
<li><a style="color:#fc0" href="https://www.jamkazam.com/client#/jamtrack">Get a JamTrack Free</a> - A web page you can visit to search our catalog of JamTracks.
When you find a song you like, click the Get It Free button, and your first one is free! If
you already redeemed a free JamTrack or purchased JamTracks, you can also access
them on this page from your web browser.</li>
<li><a style="color:#fc0" href="https://www.jamkazam.com/downloads">JamKazam Application</a> - A web page where you can download our free Mac or Windows
app. The app lets you do a lot more with JamTracks than you can do in a browser.</li>
</ul>
<p><b style="color: white;">Play Live With Others from Different Locations on JamKazam</b><br/>
JamKazams free app lets musicians play together live and in sync from different locations over
the Internet. Kind of like Skype on super audio steroids, with ultra low latency and terrific audio
quality. You can set up online sessions that are public or private, for you alone or for others to
join. You can find and join others sessions, use backing tracks and loops in sessions, make
audio and video recordings of session performances, and more. <a style="color:#fc0" href="https://jamkazam.desk.com/customer/en/portal/topics/673198-tutorials-on-major-features/articles">Click here for a set of tutorial
videos that show how to use these features</a>.
</p>
<p><b style="color: white;">Teach or Take Online Music Lessons</b><br/>
If you teach music lessons and have tried to give lessons using Skype, youll know how
unsatisfactory that experience is. Audio quality is poor, and latency prohibits teacher and
student playing together at all. JamKazam is a terrific service for teaching and taking online
music lessons. If you want to use JamKazam for lessons, well be happy to support both you and
your students in getting set up and ready to go.
</p>
<p><b style="color: white;">Complete Your Profile</b><br/>
Every member of our community has a profile. Its a great way to share a little bit about who
you are as a musician, as well as your musical interests. For example, what instruments do you
play? What musical genres do you like best? Are you interested in getting into a virtual/online
or a real-world band? And so on. Filling out your profile will help you connect with others with
common interests. To do this, go to <a style="color:#fc0" href="https://www.jamkazam.com/client">www.jamkazam.com</a> or launch the JamKazam app. Then
click on the Profile tile, and click the Edit Profile button.
</p>
<p><b style="color: white;">Invite Your Friends</b><br/>
Have friends who are musicians? Invite them to join you to play together on JamKazam. To do
this, go to <a style="color:#fc0" href="https://www.jamkazam.com/client">www.jamkazam.com</a> or launch the JamKazam app. Then move your mouse over the
user icon in the top right corner of the screen. A menu will be displayed. Click Invite Friends in
this menu, and you can then use the options to invite your friends using their email addresses,
or via Facebook, or using your Google contacts.
<p>
<p><b style="color: white;">Get Help</b><br/>
If you run into trouble and need help, please reach out to us. We will be glad to do everything
we can to answer your questions and get you up and running. You can visit our <a style="color:#fc0" href="https://jamkazam.desk.com/">Support Portal</a>
to find knowledge base articles and post questions that have not already been answered. You
can email us at <a style="color:#fc0" href="mailto:support@jamkazam.com">support@jamkazam.com</a>. And if you just want to chat, share tips and war
stories, and hang out with fellow JamKazamers, you can visit our <a style="color:#fc0" href="http://forums.jamkazam.com/">Community Forum</a>.
<p>
<p>
<br/>
<br/>
Again, welcome to JamKazam, and we hope you have a great time here!
</p>
<p>Best Regards,<br/>
Team JamKazam</p>

View File

@ -0,0 +1,43 @@
<% if !@user.anonymous? %>Hello <%= EmailBatchProgression::VAR_FIRST_NAME %> --<% end %>
We're delighted that you have decided to try the JamKazam service, and we hope that you will enjoy using JamKazam to play music with others. Following are some resources that can help you get oriented and get the most out of JamKazam.
Getting Started
---------------
There are basically three kinds of setups you can use to play on JamKazam.
* Built-In Audio on Your Computer - You can use a Windows or Mac computer, and just use the built-in mic and headphone jack to handle your audio. This is cheap and easy, but your audio quality will suffer, and it will also process audio very slowly, creating problems with latency, or lag, in your sessions. Still, you can at least start experimenting with JamKazam in this way.
* Computer with External Audio Interface - - You can use a Windows or Mac computer with an external audio interface that you already own and use for recording, if you happen to have one already. If you are going to do this, or use the built-in mic/headphones on your computer, please refer to our Minimum System Requirements at https://jamkazam.desk.com/customer/portal/articles/1288274-minimum-system-requirements to make sure your computer will work. These requirements were on the download page for the app, but you may have sped by them. Also, we'd recommend watching our Getting Started Video at https://www.youtube.com/watch?v=DBo--aj_P1w to learn more about your options here.
* The JamBlaster - JamKazam has designed a new product from the ground up to be the best way to play music online in real time. It's called the JamBlaster. It processes audio faster than any of the thousands of combinations of computers and interfaces in use on JamKazam today, which means you can play with musicians who are farther away from you, and closer sessions will feel/sound tighter. The JamBlaster is both a computer and an audio interface, so it also eliminates the system requirements worries, and it "just works" so you don't have to be an audio and computer genius to get it working. This is a great product - available only through a Kickstarter program running during a 30-day window during parts of February and March 2015. You can watch the JamBlaster Video at https://www.youtube.com/watch?v=gAJAIHMyois to learn more about this amazing new product.
JamKazam Features
-----------------
JamKazam offers a very robust and exciting set of features for playing online and sharing your performances with others. Here are some videos you can watch to easily get up to speed on some of the things you can do with JamKazam:
* Creating a Session - https://www.youtube.com/watch?v=EZZuGcDUoWk
* Finding a Session - https://www.youtube.com/watch?v=xWponSJo-GU
* Playing in a Session - https://www.youtube.com/watch?v=zJ68hA8-fLA
* Connecting with Other Musicians - https://www.youtube.com/watch?v=4KWklSZZxRc
* Working with Recordings - https://www.youtube.com/watch?v=Gn-dOqnNLoY
Getting Help
------------
If you run into trouble and need help, please reach out to us. We will be glad to do everything we can to answer your questions and get you up and running. You can visit our Support Portal at https://jamkazam.desk.com/ to find knowledge base articles and post questions that have not already been answered. You can email us at support@jamkazam.com. And if you just want to chat, share tips and war stories, and hang out with fellow JamKazamers, you can visit our Community Forum at http://forums.jamkazam.com/.
Again, welcome to JamKazam, and we look forward to seeing and hearing you online soon!
Best Regards,
Team JamKazam

View File

@ -0,0 +1,119 @@
<% provide(:title, 'Welcome to JamKazam!') %>
<% if !@user.anonymous? %>
<p>Hello <%= EmailBatchProgression::VAR_FIRST_NAME %> --
</p>
<% end %>
<p> We're delighted you have decided to join the JamKazam community of musicians, and we hope
you will enjoy using JamKazam and JamTracks to play more music. Following are some
resources and some things you can do to get the most out of JamKazam.
</p>
<p><b style="color: white;">Playing With JamTracks</b><br/>
JamTracks are the best way to play along with your favorite songs. Far better and different than
traditional backing tracks, our JamTracks are complete multi-track professional recordings, with
fully isolated tracks for each part of the music. And our free app and Internet service are packed
with features that give you unmatched creative freedom to learn, practice, record, play with
others, and share your performances. Here are some great JamTracks resources:
</p>
<ul>
<li><a style="color:#fc0" href="https://www.youtube.com/watch?v=07zJC7C2ICA">JamTracks Overview Video</a> - See all the great things you can do with JamTracks.</li>
<li><a style="color:#fc0" href="https://jamkazam.desk.com/customer/en/portal/articles/2124663-playing-with-jamtracks">JamTracks User Guide</a> - A set of articles that explain how to use all the JamTracks
features.</li>
<li><a style="color:#fc0" href="https://www.jamkazam.com/client#/jamtrack">Get a JamTrack Free</a> - A web page you can visit to search our catalog of JamTracks.
When you find a song you like, click the Get It Free button, and your first one is free! If
you already redeemed a free JamTrack or purchased JamTracks, you can also access
them on this page from your web browser.</li>
<li><a style="color:#fc0" href="https://www.jamkazam.com/downloads">JamKazam Application</a> - A web page where you can download our free Mac or Windows
app. The app lets you do a lot more with JamTracks than you can do in a browser.</li>
</ul>
<p><b style="color: white;">Play Live With Others from Different Locations on JamKazam</b><br/>
JamKazams free app lets musicians play together live and in sync from different locations over
the Internet. Kind of like Skype on super audio steroids, with ultra low latency and terrific audio
quality. You can set up online sessions that are public or private, for you alone or for others to
join. You can find and join others sessions, use backing tracks and loops in sessions, make
audio and video recordings of session performances, and more. <a style="color:#fc0" href="https://jamkazam.desk.com/customer/en/portal/topics/673198-tutorials-on-major-features/articles">Click here for a set of tutorial
videos that show how to use these features</a>.
</p>
<p><b style="color: white;">Teach or Take Online Music Lessons</b><br/>
If you teach music lessons and have tried to give lessons using Skype, youll know how
unsatisfactory that experience is. Audio quality is poor, and latency prohibits teacher and
student playing together at all. JamKazam is a terrific service for teaching and taking online
music lessons. If you want to use JamKazam for lessons, well be happy to support both you and
your students in getting set up and ready to go.
</p>
<p><b style="color: white;">Complete Your Profile</b><br/>
Every member of our community has a profile. Its a great way to share a little bit about who
you are as a musician, as well as your musical interests. For example, what instruments do you
play? What musical genres do you like best? Are you interested in getting into a virtual/online
or a real-world band? And so on. Filling out your profile will help you connect with others with
common interests. To do this, go to <a style="color:#fc0" href="https://www.jamkazam.com/client">www.jamkazam.com</a> or launch the JamKazam app. Then
click on the Profile tile, and click the Edit Profile button.
</p>
<p><b style="color: white;">Invite Your Friends</b><br/>
Have friends who are musicians? Invite them to join you to play together on JamKazam. To do
this, go to <a style="color:#fc0" href="https://www.jamkazam.com/client">www.jamkazam.com</a> or launch the JamKazam app. Then move your mouse over the
user icon in the top right corner of the screen. A menu will be displayed. Click Invite Friends in
this menu, and you can then use the options to invite your friends using their email addresses,
or via Facebook, or using your Google contacts.
<p>
<p><b style="color: white;">Get Help</b><br/>
If you run into trouble and need help, please reach out to us. We will be glad to do everything
we can to answer your questions and get you up and running. You can visit our <a style="color:#fc0" href="https://jamkazam.desk.com/">Support Portal</a>
to find knowledge base articles and post questions that have not already been answered. You
can email us at <a style="color:#fc0" href="mailto:support@jamkazam.com">support@jamkazam.com</a>. And if you just want to chat, share tips and war
stories, and hang out with fellow JamKazamers, you can visit our <a style="color:#fc0" href="http://forums.jamkazam.com/">Community Forum</a>.
<p>
<p>
<br/>
<br/>
Again, welcome to JamKazam, and we hope you have a great time here!
</p>
<p>Best Regards,<br/>
Team JamKazam</p>

View File

@ -0,0 +1,43 @@
<% if !@user.anonymous? %>Hello <%= EmailBatchProgression::VAR_FIRST_NAME %> --<% end %>
We're delighted that you have decided to try the JamKazam service, and we hope that you will enjoy using JamKazam to play music with others. Following are some resources that can help you get oriented and get the most out of JamKazam.
Getting Started
---------------
There are basically three kinds of setups you can use to play on JamKazam.
* Built-In Audio on Your Computer - You can use a Windows or Mac computer, and just use the built-in mic and headphone jack to handle your audio. This is cheap and easy, but your audio quality will suffer, and it will also process audio very slowly, creating problems with latency, or lag, in your sessions. Still, you can at least start experimenting with JamKazam in this way.
* Computer with External Audio Interface - - You can use a Windows or Mac computer with an external audio interface that you already own and use for recording, if you happen to have one already. If you are going to do this, or use the built-in mic/headphones on your computer, please refer to our Minimum System Requirements at https://jamkazam.desk.com/customer/portal/articles/1288274-minimum-system-requirements to make sure your computer will work. These requirements were on the download page for the app, but you may have sped by them. Also, we'd recommend watching our Getting Started Video at https://www.youtube.com/watch?v=DBo--aj_P1w to learn more about your options here.
* The JamBlaster - JamKazam has designed a new product from the ground up to be the best way to play music online in real time. It's called the JamBlaster. It processes audio faster than any of the thousands of combinations of computers and interfaces in use on JamKazam today, which means you can play with musicians who are farther away from you, and closer sessions will feel/sound tighter. The JamBlaster is both a computer and an audio interface, so it also eliminates the system requirements worries, and it "just works" so you don't have to be an audio and computer genius to get it working. This is a great product - available only through a Kickstarter program running during a 30-day window during parts of February and March 2015. You can watch the JamBlaster Video at https://www.youtube.com/watch?v=gAJAIHMyois to learn more about this amazing new product.
JamKazam Features
-----------------
JamKazam offers a very robust and exciting set of features for playing online and sharing your performances with others. Here are some videos you can watch to easily get up to speed on some of the things you can do with JamKazam:
* Creating a Session - https://www.youtube.com/watch?v=EZZuGcDUoWk
* Finding a Session - https://www.youtube.com/watch?v=xWponSJo-GU
* Playing in a Session - https://www.youtube.com/watch?v=zJ68hA8-fLA
* Connecting with Other Musicians - https://www.youtube.com/watch?v=4KWklSZZxRc
* Working with Recordings - https://www.youtube.com/watch?v=Gn-dOqnNLoY
Getting Help
------------
If you run into trouble and need help, please reach out to us. We will be glad to do everything we can to answer your questions and get you up and running. You can visit our Support Portal at https://jamkazam.desk.com/ to find knowledge base articles and post questions that have not already been answered. You can email us at support@jamkazam.com. And if you just want to chat, share tips and war stories, and hang out with fellow JamKazamers, you can visit our Community Forum at http://forums.jamkazam.com/.
Again, welcome to JamKazam, and we look forward to seeing and hearing you online soon!
Best Regards,
Team JamKazam

View File

@ -0,0 +1,24 @@
# represents the purchase of a LessonPackage
module JamRuby
class LessonPackagePurchase < ActiveRecord::Base
@@log = Logging.logger[LessonPackagePurchase]
def name
lesson_package_type.sale_display
end
# who purchased the lesson package?
belongs_to :user, class_name: "JamRuby::User"
belongs_to :lesson_package_type, class_name: "JamRuby::LessonPackageType"
belongs_to :teacher, class_name: "JamRuby::Teacher"
def self.create(user, lesson_package_type)
purchase = LessonPackagePurchase.new
purchase.user = user
purchase.lesson_package_type = lesson_package_type
purchase.save
purchase
end
end
end

View File

@ -0,0 +1,62 @@
# represenst the type of lesson package
module JamRuby
class LessonPackageType < ActiveRecord::Base
@@log = Logging.logger[LessonPackageType]
PRODUCT_TYPE = 'LessonPackageType'
SINGLE_FREE = 'single-free'
TEST_DRIVE = 'test-drive'
SINGLE = 'single'
LESSON_PACKAGE_TYPES =
[
SINGLE_FREE,
TEST_DRIVE,
SINGLE
]
validates :name, presence: true
validates :description, presence: true
validates :price, presence: true
validates :package_type, presence: true, inclusion: {in: LESSON_PACKAGE_TYPES}
def self.single_free
LessonPackageType.find(SINGLE_FREE)
end
def self.test_drive
LessonPackageType.find(TEST_DRIVE)
end
def self.single
LessonPackageType.find(SINGLE)
end
def sale_display
name
end
def plan_code
if package_type == SINGLE_FREE
"lesson-package-single-free"
elsif package_type == TEST_DRIVE
"lesson-package-test-drive"
elsif package_type == SINGLE
"lesson-package-single"
else
raise "unknown lesson package type #{package_type}"
end
end
def sales_region
'Worldwide'
end
def to_s
sale_display
end
end
end

View File

@ -0,0 +1,23 @@
# represenst the type of lesson package
module JamRuby
class LessonSession < ActiveRecord::Base
@@log = Logging.logger[LessonSession]
LESSON_TYPE_SINGLE = 'single'
LESSON_TYPE_SINGLE_FREE = 'single-free'
LESSON_TYPE_TEST_DRIVE = 'test-drive'
LESSON_TYPES = [LESSON_TYPE_SINGLE, LESSON_TYPE_SINGLE_FREE, LESSON_TYPE_TEST_DRIVE]
belongs_to :music_session, class_name: "JamRuby::MusicSession"
belongs_to :teacher, class_name: "JamRuby::Teacher"
belongs_to :lesson_package_purchase, class_name: "JamRuby::LessonPackagePurchase"
validates :duration, presence: true, numericality: {only_integer: true}
validates :lesson_type, inclusion: {in: LESSON_TYPES}
validates :price, presence: true
validates :teacher_complete, inclusion: {in: [true, false]}
validates :student_complete, inclusion: {in: [true, false]}
end
end

View File

@ -13,6 +13,8 @@ module JamRuby
has_many :experiences_education, :class_name => "JamRuby::TeacherExperience", conditions: {experience_type: 'education'}
has_many :experiences_award, :class_name => "JamRuby::TeacherExperience", conditions: {experience_type: 'award'}
has_many :reviews, :class_name => "JamRuby::Review", as: :target
has_many :lesson_sessions, :class_name => "JamRuby::LessonSession"
has_many :lesson_package_purchases, :class_name => "JamRuby::LessonPackagePurchase"
has_one :review_summary, :class_name => "JamRuby::ReviewSummary", as: :target
has_one :user, :class_name => 'JamRuby::User'

View File

@ -208,6 +208,8 @@ module JamRuby
validates :terms_of_service, :acceptance => {:accept => true, :on => :create, :allow_nil => false}
validates :reuse_card, :inclusion => {:in => [true, false]}
validates :is_a_student, :inclusion => {:in => [true, false]}
validates :is_a_teacher, :inclusion => {:in => [true, false]}
validates :has_redeemable_jamtrack, :inclusion => {:in => [true, false]}
validates :gifted_jamtracks, presence: true, :numericality => {:less_than_or_equal_to => 100}
validates :subscribe_email, :inclusion => {:in => [nil, true, false]}
@ -1063,20 +1065,26 @@ module JamRuby
signup_hint = options[:signup_hint]
affiliate_partner = options[:affiliate_partner]
gift_card = options[:gift_card]
student = options[:student]
teacher = options[:teacher]
user = User.new
UserManager.active_record_transaction do |user_manager|
user.first_name = first_name
user.last_name = last_name
user.first_name = first_name if first_name.present?
user.last_name = last_name if last_name.present?
user.email = email
user.subscribe_email = true
user.terms_of_service = terms_of_service
user.musician = musician
user.reuse_card unless reuse_card.nil?
user.gifted_jamtracks = 0
user.has_redeemable_jamtrack = true
user.is_a_student = !!student
user.is_a_teacher = !!teacher
if user.is_a_student || user.is_a_teacher
musician = true
end
user.musician = !!musician
# FIXME: Setting random password for social network logins. This
# is because we have validations all over the place on this.
@ -1255,10 +1263,21 @@ module JamRuby
user.save
end if affiliate_referral_id.present?
# don't send an signup email if email is already confirmed
if user.email_confirmed
if user.is_a_student
UserMailer.student_welcome_message(user).deliver
end
if user.is_a_teacher
UserMailer.teacher_welcome_message(user).deliver
end
if !user.is_a_teacher && !user.is_a_student
UserMailer.welcome_message(user).deliver
else
end
if !user.email_confirmed
# any errors here should also rollback the transaction; that's OK. If emails aren't going to be delivered,
# it's already a really bad situation; make user signup again
UserMailer.confirm_email(user, signup_confirm_url.nil? ? nil : (signup_confirm_url + "/" + user.signup_token)).deliver

View File

@ -0,0 +1,11 @@
require 'spec_helper'
describe LessonPackagePurchase do
let(:user) {FactoryGirl.create(:user)}
it "creates" do
purchase = LessonPackagePurchase.create(user, LessonPackageType.single_free)
purchase.valid?.should be_true
end
end

View File

@ -95,13 +95,13 @@ end
config.before(:suite) do
DatabaseCleaner.strategy = :transaction
DatabaseCleaner.clean_with(:deletion, {pre_count: true, reset_ids:false, :except => %w[gift_card_types instruments languages subjects genres icecast_server_groups jamcompany jamisp geoipblocks geoipisp geoiplocations cities regions countries generic_state spatial_ref_sys] })
DatabaseCleaner.clean_with(:deletion, {pre_count: true, reset_ids:false, :except => %w[gift_card_types lesson_package_types instruments languages subjects genres icecast_server_groups jamcompany jamisp geoipblocks geoipisp geoiplocations cities regions countries generic_state spatial_ref_sys] })
end
config.around(:each) do |example|
# set no_transaction: true as metadata on your test to use deletion strategy instead
if example.metadata[:no_transaction]
DatabaseCleaner.strategy = :deletion, {pre_count: true, reset_ids:false, :except => %w[gift_card_types instruments languages subjects genres icecast_server_groups jamcompany jamisp geoipblocks geoipisp geoiplocations cities regions countries generic_state spatial_ref_sys] }
DatabaseCleaner.strategy = :deletion, {pre_count: true, reset_ids:false, :except => %w[gift_card_types lesson_package_types instruments languages subjects genres icecast_server_groups jamcompany jamisp geoipblocks geoipisp geoiplocations cities regions countries generic_state spatial_ref_sys] }
else
DatabaseCleaner.strategy = :transaction
end

View File

@ -0,0 +1,394 @@
context = window
rest = context.JK.Rest()
@JamClassAffiliateLandingBottomPage = React.createClass({
render: () ->
`<div className="top-container">
<div className="row awesome jam-class">
<h2 className="awesome">What Is The JamKazam Affiliate Program?</h2>
<p>If youre a music store and you sell products like instruments and accessories to musicians,
JamKazam can add value to every sale you make to customers by enabling you to bundle high-value digital music products and services that are highly complementary to the products you
are selling at no additional cost to your customers. For example, you can bundle full
multitrack recordings from our catalog of 4,000+ popular songs that let your customers play
along with their favorite songs in <a href="#jamtracks">incredibly innovative and fun ways</a>, and you can
bundle free
online music lessons that really work (unlike Skype, which is great for voice chat but horrible for
music lessons) to help your customers connect with great teachers and stay better engaged
with their instruments, so theyll keep coming back for more music products from your store.
Additionally, when your customers love these digital products and services and choose to buy
more, we pay you a share of all revenues we earn from these sales, boosting your revenue and
profit per sale, while simultaneously delivering greater value to your customer.</p>
<p>If youre a music school, JamKazam represents a platform far superior to Skype that you can use
freely to teach your existing students online, both in your area and across the country to reach
new markets and students. Skypes audio quality for music is very poor. Its latency is so high
that teacher and student cannot play together, and it suffers from a number of other critical
limitations for music lessons, as it was built for voice chat not music. In addition to delivering
online music lessons <a href="#jamclass"> that really work</a>, JamKazam can drive more students to your school
and
your teachers from our online lesson marketplace, helping you build your business faster and
bigger.</p>
<p>And if youre both a music store and school, we can help you win in all these ways together. If
this sounds interesting, read on to learn more about some of the unique things weve done and
how they can help to grow your business.</p>
<div className="testimonials jamtracks-affiliate">
<h3>JamTracks Kudos</h3>
<div className="testimonial">
<img src="/assets/landing/Andy Crowley - Speech Bubble.png" className="testimonial-speech-bubble" />
<img src="/assets/landing/Andy Crowley - Avatar.png" className="testimonial-avatar" />
<a rel="external" href="https://www.youtube.com/user/andycrowley"><img src="/assets/landing/Andy Crowley - YouTube.png" className="testimonial-youtube" /></a>
<h4><strong>Andy Crowley</strong> of AndyGuitar</h4>
</div>
<div className="testimonial">
<img src="/assets/landing/Ryan Jones - Speech Bubble.png" className="testimonial-speech-bubble" />
<img src="/assets/landing/Ryan Jones - Avatar.png" className="testimonial-avatar" />
<a rel="external" href="https://www.youtube.com/user/gotitans999"><img src="/assets/landing/Ryan Jones - PianoKeyz - YouTube.png" className="testimonial-youtube" /></a>
<h4><strong>Ryan Jones</strong> of PianoKeyz</h4>
</div>
<div className="testimonial">
<img src="/assets/landing/Carl Brown - Speech Bubble.png" className="testimonial-speech-bubble" />
<img src="/assets/landing/Carl Brown - Avatar.png" className="testimonial-avatar" />
<a rel="external" href="https://www.youtube.com/channel/UCvnfBBzEizi1T5unOXNCxdQ"><img src="/assets/landing/Carl Brown - YouTube.png" className="testimonial-youtube" /></a>
<h4><strong>Carl Brown</strong> of GuitarLessions365</h4>
</div>
</div>
</div>
<div className="row awesome jam-class thin">
<h2 id="jamtracks" className="awesome">JamTracks The Best Way To Play With Your Favorite Songs</h2>
<p>
JamTracks are full multitrack recordings of 4,000+ popular songs that deliver amazing fun and
flexibility for musicians to play with their favorite artists and tunes. With JamTracks, you can:
</p>
<ul>
<li>Listen to just a single isolated part to learn it</li>
<li>Mute the part you want to play, and play along with the rest of the band</li>
<li>Slow down playback to practice without changing the pitch</li>
<li>Change the song key by raising or lowering pitch in half steps</li>
<li>Save custom mixes for easy access, and export them to use anywhere</li>
<li>Make audio and video recordings to share via Facebook, YouTube, etc.</li>
<li>Play online live and in sync with others from different locations</li>
<li>Apply VST & AU audio plugin effects to your live performance</li>
<li>Use MIDI with VST & AU instruments for keys, electronic drums, etc.</li>
<li>And more</li>
</ul>
<p>
JamTracks sell for $1.99 each. Musicians love to play with these, and typically buy a few at a
time. Imagine that you are selling a set of guitar strings to an electric guitar player. As a
JamKazam affiliate, you can bundle free JamTracks with the strings sale, delighting your
customer with the added value. And then when he/she buys more JamTracks, we pay you a
share of that revenue, adding to your revenues, and improving your margin on your sales. This
can be applied to just about anything you sell, as we have JamTracks with parts for almost every
instrument, as well as vocals. And its easy to bundle, as you dont have to specify particular
songs per product that you sell. You can just give your customer a free JamTracks credit with
each sale, and your customer can then redeem this credit online to choose their favorite songs.
</p>
<p>
Here is a video that shows more about how JamTracks work.
<div className="video-wrapper affiliate-info-video">
<div className="video-container">
<iframe src="//www.youtube.com/embed/07zJC7C2ICA" frameborder="0" allowfullscreen="allowfullscreen"/>
</div>
</div>
</p>
<div className="testimonials jamclass-affiliate">
<h3>JamClass Kudos</h3>
<div className="testimonial">
<img src="/assets/landing/Dave Sebree - Jam Class - Speech Bubble.png" className="testimonial-speech-bubble"/>
<img src="/assets/landing/Dave Sebree - Avatar.png" className="testimonial-avatar"/>
<h4><strong>Dave Sebree</strong></h4>
<div className="testiminal-background">
Founder of Austin School of Music, Gibson-endorsed guitarist, touring musician
</div>
</div>
<div className="testimonial">
<img src="/assets/landing/Justin Pierce - Jam Class - Speech Bubble.png" className="testimonial-speech-bubble"/>
<img src="/assets/landing/Justin Pierce - Avatar.png" className="testimonial-avatar"/>
<h4><strong>Justin Pierce</strong></h4>
<div className="testiminal-background">
Masters degree in jazz studies, performer in multiple bands, saxophone instructor
</div>
</div>
<div className="testimonial">
<img src="/assets/landing/Julie Bonk - Jam Class - Speech Bubble.png" className="testimonial-speech-bubble"/>
<img src="/assets/landing/Julie Bonk - Avatar.png" className="testimonial-avatar"/>
<h4><strong>Julie Bonk</strong></h4>
<div className="testiminal-background">
Oft-recorded pianist, teacher, mentor to Grammy winner Norah Jones and Scott Hoying of Pentatonix
</div>
</div>
</div>
</div>
<div className="row awesome jam-class thin">
<h2 id="jamclass" className="awesome">JamClass Online Music Lessons That Work</h2>
<p>
Where JamTracks are incredibly fun and versatile, JamClass is flat out amazing and mind
blowing. Weve spent the last 3 years building technology specifically to let musicians play
together live in sync over the Internet from different locations with very high quality audio. And
now we are using this technology to enable online music lessons in a very powerful way.
</p>
<p>
For the last several years, instructors have been experimenting with using Skype to teach online
music lessons. But if you have tried this yourself or spoken with someone who has, you know
that audio quality is extremely poor, and latency is far too high for a teacher and student to
play together in lessons. The reason is that Skype was built for voice conferencing i.e. for
people to talk with each other not for music. Skype uses a voice codec that processes all
audio as if it were a human voice speaking, which crushes music audio. And voice conferencing
apps like Skype work fine with 150 to 200 milliseconds of latency (lag), whereas for music you
need latency far lower, in the 20 to 40 millisecond range.
</p>
<p>
In addition to audio quality and latency, JamKazams technology lets teacher and student
record lessons and performances for later reference, open backing tracks in sessions to play
with, use an in-session metronome, and other music-specific important features.
</p>
<p>
Here is a video that shows more about how JamKazams technology works for lessons.
<div className="video-wrapper affiliate-info-video">
<div className="video-container">
<iframe src="//www.youtube.com/embed/07zJC7C2ICA" frameborder="0" allowfullscreen="allowfullscreen"/>
</div>
</div>
</p>
</div>
<div className="row awesome jam-class">
<h2 id="how-does-it-work" className="awesome">How Does The Affiliate Program Work?</h2>
<p>The affiliate program for music stores and schools is really simple. Its free to sign up. Once
youve signed up, you are assigned a JamKazam affiliate ID, which tracks your affiliate activities
automatically. Today there are 3 ways to benefit from the affiliate program:</p>
<ul>
<li>
<div className="definition">Bundle Free JamTracks and/or Lessons</div>
If you bundle free JamTracks or free lessons with the products you sell, your customers
redeem these free offers from a web page that is co-branded with your store or schools
logo. When they redeem the free offer, they are tagged as having come from your store
or school. For the next two years from this redemption date, we will pay you 10% of all
JamTracks revenues and 25% of all JamClass revenues earned by JamKazam that are generated from these referred customers. For purposes of illustration, if you own a store and refer a student
into our lesson marketplace who takes lessons at $30/lesson for a year with one of our
instructors, you would earn close to $100 in revenues just from that single referred
student.
</li>
<li>
<div className="definition">Sign Up Teachers to Deliver Lessons</div>
If you are a store or school that delivers music lessons yourself, you can have the
teachers in your school sign up to teach using the JamKazam platform. This is a smart
move to grow your online lesson business because the user experience is so superior to
Skype. If you use JamKazam to teach students who you have attracted through your
own marketing initiatives, its free to use our technology to deliver those lessons. You
can also opt to enable JamKazam to drive new students to your teachers through our
own network and marketing investments. If you opt in, JamKazam can help build your
business, and then we simply agree together how to split the revenue held back from
the lesson payment for delivering the student to the teacher.
</li>
<li>
<div className="definition">Sign Up Students to Take Lessons</div>
If you are a store or school that delivers music lessons, if you deliver online lessons to
your own students (not sourced from the JamKazam marketplace), then when those
students sign up to use JamKazam, well also tag these students as having been referred
by you, so that if they choose to buy any other JamKazam products like JamTracks, well
pay you a revenue share on these purchases.
</li>
</ul>
</div>
<div className="row awesome jam-class">
<h2 className="awesome">What Do You Need To Offer JamClass Lessons From Your School?</h2>
<p>
In order to teach lessons using JamClass by JamKazam from your school facilities, in each room
where you want to be able to teach online lessons you will need the following:</p>
<ul>
<li>A computer running either
<ul>
<li>Windows 7 or a later version (32-bit or 64-bit)
</li>
<li>Mac OS X 10.7 or a later version (64-bit)<br/>
<a className="how-do-i" href="https://support.apple.com/en-us/HT201948" target="_blank">how do I know
which version I'm running and if it's 64-bit on Mac?</a>
</li>
</ul>
</li>
<li>A built-in microphone and built-in webcam on your computer</li>
<li>Internet service with at least 500kbps upload bandwidth<br/>
<a className="how-do-i" href="http://www.speedtest.net/" target="_blank">how do I know how much upload
bandwidth my Internet service delivers?</a></li>
</ul>
<p>
To have very high quality audio in your sessions, rather than using the built-in microphone on
your computer to capture your instrumental and/or vocal audio, we strongly recommend using
an external audio interface. An audio interface is a hardware product that connects to your
computer and processes audio better than your computer alone. If you already own/use an
audio interface, you can use the one you have. And if you don't, please <a
href="https://jamkazam.desk.com/customer/portal/articles/1292412-choosing-an-audio-device"
target="_blank">read this help article on audio interfaces</a> that can guide you to get what you need. You
can pick up a perfectly good
interface very inexpensively, typically for less than $50. And you can use your new interface not
just for JamClass, but also to make recordings of performances, etc. So it's a great thing to have
for any music school in general.
</p>
<p>
Also, if possible, youll get the best audio quality and lowest latency if you can connect your
computer to your Internet service using an Ethernet cable rather than a WiFi connection. In any
application (including ours), WiFi is not great for low latency media streaming. If you have to
use WiFi, it will be OK for 1:1 lessons, and still far, far better than Skype. But youll get the best
performance if you can use a wired vs. wireless connection.
</p>
<p>
If you feel worried or confused about getting set up because you're not a "tech genius", we are
happy to work with you 1:1 to answer your questions, and walk you through picking gear and
setting it up. We'll even hop into an online test session with you, show you around the key
features, and make sure you're ready to rock and roll online! Just email us at
support@jamkazam.com, and tell us you need help getting set up for JamClass. We do this all
the time.
</p>
<p>
Here is a video that shows more about how JamClass works from a teacher's perspective:
<div className="video-wrapper">
<div className="video-container">
<iframe src="//www.youtube.com/embed/07zJC7C2ICA" frameborder="0" allowfullscreen="allowfullscreen"/>
</div>
</div>
</p>
</div>
<div id="what-now" className="row awesome jam-class">
<h2 className="awesome">What Now?</h2>
<p>If you're ready to sign up to join our affiliate program, just scroll back up to the top of this page,
and enter your email address and a password to sign up. Once you've done this, we'll provide
instructions and engage with you to do the following:</p>
<ol>
<li>Set up your music store or school as an affiliate, and execute the simple online affiliate
agreement.
</li>
<li>Learn how to share URLs with your customers and students that help them redeem free
JamKazam products so that you are credited with the referrals.
</li>
<li>Set up the gear you need, and participate in an online session with JamKazam staff to
ensure everything is working properly and that you are comfortable with how to use the
features of the service.
</li>
<li>If your store/school teaches, sign up your teachers to use the service, and schedule a
teacher training class to get everyone comfortable.
</li>
</ol>
<p>
Our JamKazam staff will give you all the 1:1 help you need to get your gear set up for online
lessons. Once youve started bundling free products and/or teaching, well also need to set you
up for direct deposit so we can deposit funds as they are earned through the program.
</p>
<p>
All of us here at JamKazam look forward to partnering with you to help both you and your
customers and students succeed in both your musical and business endeavors!
</p>
</div>
</div>`
})

View File

@ -0,0 +1,139 @@
context = window
rest = context.JK.Rest()
@JamClassAffiliateLandingPage = React.createClass({
render: () ->
loggedIn = context.JK.currentUserId?
if this.state.done
ctaButtonText = 'sending you in...'
else if this.state.processing
ctaButtonText = 'hold on...'
else
if loggedIn
ctaButtonText = "SIGN UP, IT'S FREE"
else
ctaButtonText = "SIGN UP, IT'S FREE"
if loggedIn
register = `<button className={classNames({'cta-button' : true, 'processing': this.state.processing})} onClick={this.ctaClick}>{ctaButtonText}</button>`
else
if this.state.loginErrors?
for key, value of this.state.loginErrors
break
errorText = context.JK.getFullFirstError(key, this.state.loginErrors, {email: 'Email', password: 'Password', 'terms_of_service' : 'The terms of service'})
register = `<div className="register-area jam-class">
<div className={classNames({'errors': true, 'active': this.state.loginErrors})}>
{errorText}
</div>
<form className="jamtrack-signup-form">
<label>Email: </label><input type="text" name="email" />
<label>Password: </label><input type="password" name="password" />
<div className="clearall"/>
<input className="terms-checkbox" type="checkbox" name="terms" /><label className="terms-help">I have read and agree to the JamKazam <a href="/corp/terms" onClick={this.termsClicked}>terms of service</a></label>
<div className="clearall"/>
<button className={classNames({'cta-button' : true, 'processing': this.state.processing})} onClick={this.ctaClick}>{ctaButtonText}</button>
</form>
</div>`
`<div className="top-container">
<div className="full-row name-and-artist">
<div>
<img className="jam-class-teacher" width="340" height="178" src="/assets/landing/JK_FBAd_Guitar_with_Keys.png" alt="screenshot of app"/>
<h1 className="jam-track-name">FOR MUSIC STORES & SCHOOLS</h1>
<h2 className="original-artist">Do you own or operate a music store or school?</h2>
<div className="clearall"/>
</div>
<div className="preview-and-action-box jamclass">
<img src="/assets/landing/arrow-1-student.png" className="arrow1-jamclass" />
<div className="preview-jamtrack-header">
Sign Up as Affiliate
</div>
<div className={classNames({'preview-area': true, 'jam-class': true})}>
<p>Sign up to enroll your store or school in our affiliate program.</p>
<p>Well follow up to answer your questions and give you all the 1:1 help you need to get up and running. Its easy, and your customers will love the added value.</p>
<p>We will not share your email. See our <a href="/corp/privacy" onClick={this.privacyPolicy}>privacy policy</a></p>
{register}
<p>See for yourself how we can help you deliver greater value to your customers while increasing your revenues.</p>
</div>
</div>
</div>
<div className="row summary-text">
<p className="top-summary">
Founded by a team that has built and sold companies to Google, eBay, GameStop and more,
JamKazam has developed incredibly unique and engaging digital music technologies, content,
and marketplaces used by our rapidly growing community of 30,000+ musicians. Now weve
crafted an affiliate program specifically for music stores and music schools to increase your
revenues while delighting your customers. Best of all, its free and easy to integrate into your
business.
</p>
</div>
</div>`
getInitialState: () ->
{loginErrors: null, processing:false}
privacyPolicy: (e) ->
e.preventDefault()
context.JK.popExternalLink('/corp/privacy')
termsClicked: (e) ->
e.preventDefault()
context.JK.popExternalLink('/corp/terms')
componentDidMount:() ->
$root = $(this.getDOMNode())
$checkbox = $root.find('.terms-checkbox')
context.JK.checkbox($checkbox)
# add item to cart, create the user if necessary, and then place the order to get the free JamTrack.
ctaClick: (e) ->
e.preventDefault()
return if @state.processing
@setState({loginErrors: null})
loggedIn = context.JK.currentUserId?
createUser: () ->
$form = $('.jamtrack-signup-form')
email = $form.find('input[name="email"]').val()
password = $form.find('input[name="password"]').val()
terms = $form.find('input[name="terms"]').is(':checked')
rest.signup({email: email, password: password, first_name: null, last_name: null, terms:terms})
.done((response) =>
).fail((jqXHR) =>
@setState({processing:false})
if jqXHR.status == 422
response = JSON.parse(jqXHR.responseText)
if response.errors
@setState({loginErrors: response.errors})
else
context.JK.app.notify({title: 'Unknown Signup Error', text: jqXHR.responseText})
else
context.JK.app.notifyServerError(jqXHR, "Unable to Sign Up")
)
@setState({processing:true})
})

View File

@ -101,7 +101,23 @@ rest = context.JK.Rest()
loggedIn = context.JK.currentUserId?
if loggedIn
@markStudent()
else
@createUser()
@setState({processing:true})
markStudent: () ->
rest.updateUser({student: true})
.done((response) =>
this.setState({done: true})
context.location = '/client#/home'
)
.fail((jqXHR) =>
this.setState({processing: false})
context.JK.app.notifyServerError(jqXHR, "Unable to Mark As Student")
)
createUser: () ->
$form = $('.jamtrack-signup-form')
@ -109,10 +125,10 @@ rest = context.JK.Rest()
password = $form.find('input[name="password"]').val()
terms = $form.find('input[name="terms"]').is(':checked')
rest.signup({email: email, password: password, first_name: null, last_name: null, terms:terms})
rest.signup({email: email, password: password, first_name: null, last_name: null, terms:terms, student: true})
.done((response) =>
@setState({done: true})
context.location = '/client#/home'
).fail((jqXHR) =>
@setState({processing:false})
if jqXHR.status == 422
@ -125,6 +141,4 @@ rest = context.JK.Rest()
context.JK.app.notifyServerError(jqXHR, "Unable to Sign Up")
)
@setState({processing:true})
})

View File

@ -14,7 +14,7 @@ rest = context.JK.Rest()
ctaButtonText = 'hold on...'
else
if loggedIn
ctaButtonText = 'TRY TESTDRIVE'
ctaButtonText = 'BECOME A TEACHER'
else
ctaButtonText = 'SIGN UP'
@ -54,7 +54,7 @@ rest = context.JK.Rest()
<div className="preview-and-action-box jamclass">
<img src="/assets/landing/arrow-1-student.png" className="arrow1-jamclass" />
<div className="preview-jamtrack-header">
Sign Up for TestDrive
Sign Up To Teach
</div>
<div className={classNames({'preview-area': true, 'jam-class': true})}>
<p>Sign up and start getting students referred from our marketplace.</p>
@ -100,7 +100,23 @@ rest = context.JK.Rest()
loggedIn = context.JK.currentUserId?
if loggedIn
@markTeacher()
else
@createUser()
@setState({processing:true})
markTeacher: () ->
rest.updateUser({teacher: true})
.done((response) =>
this.setState({done: true})
context.location = '/client#/home'
)
.fail((jqXHR) =>
this.setState({processing: false})
context.JK.app.notifyServerError(jqXHR, "Unable to Mark As Teacher")
)
createUser: () ->
$form = $('.jamtrack-signup-form')
@ -108,10 +124,10 @@ rest = context.JK.Rest()
password = $form.find('input[name="password"]').val()
terms = $form.find('input[name="terms"]').is(':checked')
rest.signup({email: email, password: password, first_name: null, last_name: null, terms:terms})
rest.signup({email: email, password: password, first_name: null, last_name: null, terms:terms, teacher : true})
.done((response) =>
@setState({done: true})
context.location = '/client#/home'
).fail((jqXHR) =>
@setState({processing:false})
if jqXHR.status == 422
@ -124,6 +140,4 @@ rest = context.JK.Rest()
context.JK.app.notifyServerError(jqXHR, "Unable to Sign Up")
)
@setState({processing:true})
})

View File

@ -43,27 +43,31 @@ body.web.individual_jamtrack {
&.jam-class {
padding:20px 0;
&.thin {
width:663px;
}
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 {
@ -73,7 +77,7 @@ body.web.individual_jamtrack {
list-style-type: disc;
}
li {
margin-left:20px;
margin-left: 20px;
margin-bottom: 10px;
}
@ -82,15 +86,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;
}
}
}
@ -105,78 +109,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;
}
}
@ -191,12 +195,12 @@ body.web.individual_jamtrack {
.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;
@ -211,7 +215,7 @@ body.web.individual_jamtrack {
}
.edit-link {
font-size:12px;
font-size: 12px;
}
.video-container {
@ -300,7 +304,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;
@ -308,15 +312,15 @@ 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 {
@ -345,11 +349,11 @@ body.web.individual_jamtrack {
}
.cta-button {
cursor:pointer;
cursor: pointer;
background-color: $cta-color;
&.processing {
background-color:gray;
background-color: gray;
}
}
@ -378,15 +382,15 @@ body.web.individual_jamtrack {
}
.arrow1 {
position:absolute;
position: absolute;
left: -371px;
top: -80px;
}
.arrow2 {
position:absolute;
left:-230px;
top:373px;
position: absolute;
left: -230px;
top: 373px;
}
.arrow1-jamclass {
@ -396,30 +400,44 @@ 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;
&.jamtracks-affiliate {
top:597px;
h3 {
color: $cta-color;
}
}
&.jamclass-affiliate {
top:1708px;
h3 {
color: $cta-color;
}
}
&.jam-class {
top:557px;
top: 557px;
h3 {
color:$cta-color;
color: $cta-color;
}
&.teachers {
top:618px;
top: 618px;
}
}
.jamtrack-overview-video {
h3 {
font-size:21px;
width:400px;
font-size: 21px;
width: 400px;
}
.video-wrapper {
@ -432,43 +450,43 @@ body.web.individual_jamtrack {
}
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%;
}
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;
}
.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;
@ -476,7 +494,7 @@ body.web.individual_jamtrack {
left: 174px;
top: 181px;
font-size: 12px;
color:$copy-color-on-white;
color: $copy-color-on-white;
}
}
.preview-and-action-box {
@ -492,7 +510,7 @@ body.web.individual_jamtrack {
z-index: 1;
&.jamclass {
top:209px;
top: 209px;
}
.preview-jamtrack-header {
@ -506,11 +524,11 @@ body.web.individual_jamtrack {
border-color: $copy-color-on-dark;
&.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;
}
}
@ -525,8 +543,8 @@ body.web.individual_jamtrack {
&.jam-class {
border-width: 0 0 2px;
p {
padding:8px 10px;
text-align:center;
padding: 8px 10px;
text-align: center;
@include border_box_sizing;
}
}
@ -535,22 +553,22 @@ 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;
}
.cta-buttons {
text-align:center;
text-align: center;
}
.cta-button {
font-size: 24px;
@ -564,22 +582,22 @@ body.web.individual_jamtrack {
font-family: Raleway, Arial, Helvetica, sans-serif;
&.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 {
&.jam-class {
padding:0;
padding: 0;
}
padding: 10px;
input {
@ -588,15 +606,15 @@ body.web.individual_jamtrack {
font-size: 16px;
&[name="terms"] {
width:auto;
line-height:24px;
vertical-align:middle;
width: auto;
line-height: 24px;
vertical-align: middle;
}
}
.icheckbox_minimal {
float: left;
top: 6px;
margin-left:64px;
margin-left: 64px;
}
.cta-button {
font-size: 24px;
@ -618,9 +636,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;
@ -639,10 +657,10 @@ 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;
}
}
input {
@ -663,7 +681,7 @@ body.web.individual_jamtrack {
.jam-track-preview-holder {
margin-bottom: 7px;
float:left;
float: left;
&[data-track-type="Master"] {
width: 100%;
}
@ -674,25 +692,33 @@ body.web.individual_jamtrack {
}
.jam-track-preview {
font-size:12px;
font-size: 12px;
.instrument-part {
width:175px
width: 175px
}
.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;
}
.affiliate-info-video.video-wrapper {
.video-container {
width: 600px !important;
padding-bottom: 53.33%;
}
}
}

View File

@ -87,6 +87,8 @@ ApiUsersController < ApiController
location: {:country => nil, :state => nil, :city => nil},
signup_hint: signup_hint,
gift_card: params[:gift_card],
student: params[:student],
teacher: params[:teacher],
affiliate_referral_id: cookies[:affiliate_visitor]
}
@ -169,6 +171,8 @@ ApiUsersController < ApiController
@user.update_online_presences(params[:online_presences]) if params.has_key?(:online_presences)
@user.update_performance_samples(params[:performance_samples]) if params.has_key?(:performance_samples)
@user.update_calendars(params[:calendars]) if params.has_key?(:calendars)
@user.is_a_student = params[:student] if params.has_key?(:student)
@user.is_a_teacher = params[:teacher] if params.has_key?(:teacher)
@user.save
if @user.errors.any?

View File

@ -85,6 +85,14 @@ class LandingsController < ApplicationController
render 'jam_class_teachers', layout: 'web'
end
def jam_class_affiliates
@olark_enabled = true
@no_landing_tag = true
@landing_tag_play_learn_earn = true
@show_after_black_bar_border = true
render 'jam_class_affiliates', layout: 'web'
end
def individual_jamtrack

View File

@ -219,7 +219,7 @@ class UsersController < ApplicationController
@user = UserManager.new.signup_confirm(signup_token, request.remote_ip)
if !@user.nil? && !@user.errors.any?
UserMailer.welcome_message(@user).deliver
#UserMailer.welcome_message(@user).deliver
elsif !@user.nil?
# new user with validation errors;
logger.debug("#{@user} has errors. can not sign in until remedied. #{@user.errors.inspect}")

View File

@ -0,0 +1,18 @@
- provide(:page_name, 'landing_page full individual_jamtrack')
- provide(:description, @description)
- provide(:title, @title)
= react_component 'JamClassAffiliateLandingPage', @page_data.to_json
- content_for :after_black_bar do
.row.cta-row
h2 SIGN UP AS AFFILIATE NOW, ITS FREE!
p And deliver more value to your customers while increasing revenue.
p.cta-text Not sure if the affiliate program is for you? Scroll down to learn more.
- content_for :white_bar do
= react_component 'JamClassAffiliateLandingBottomPage', @page_data.to_json
- content_for :red_bar do
.full-row
| Sign up for the JamKazam affiliate program today!

View File

@ -44,6 +44,7 @@ SampleApp::Application.routes.draw do
match '/landing/gift-card', to: 'landings#buy_gift_card', via: :get, as: 'buy_gift_card'
match '/landing/jamclass/students', to: 'landings#jam_class_students', via: :get
match '/landing/jamclass/teachers', to: 'landings#jam_class_teachers', via: :get
match '/landing/jamclass/affiliates', to: 'landings#jam_class_affiliates', via: :get
match '/affiliateProgram', to: 'landings#affiliate_program', via: :get, as: 'affiliate_program'

View File

@ -30,6 +30,8 @@ class UserManager < BaseManager
signup_hint = options[:signup_hint]
affiliate_partner = options[:affiliate_partner]
gift_card = options[:gift_card]
student = options[:student]
teacher = options[:teacher]
recaptcha_failed = false
unless options[:skip_recaptcha] # allow callers to opt-of recaptcha
@ -74,7 +76,9 @@ class UserManager < BaseManager
any_user: any_user,
signup_hint: signup_hint,
affiliate_partner: affiliate_partner,
gift_card: gift_card)
gift_card: gift_card,
student: student,
teacher: teacher)
user
end

View File

@ -0,0 +1,61 @@
require 'spec_helper'
describe "Student Landing", :js => true, :type => :feature, :capybara_feature => true do
subject { page }
before(:all) do
ShoppingCart.delete_all
JamTrackRight.delete_all
JamTrack.delete_all
JamTrackTrack.delete_all
JamTrackLicensor.delete_all
end
let(:user) { FactoryGirl.create(:user, country: 'US') }
it "logged out" do
visit "/landing/jamclass/students"
find('h1.jam-track-name', 'JAMCLASS')
find('h2.original-artist', 'Finally, online music lessons that really work!')
find('button.cta-button', text: 'SIGN UP').trigger(:click)
# should fail because we haven't filled out email/password/terms
find('.register-area .errors', text: "Email can't be blank")
fill_in "email", with: 'student_123@jamkazam.com'
fill_in "password", with: 'jam123'
find('.register-area ins', visible: false) .trigger(:click)
find('button.cta-button', text: 'SIGN UP').trigger(:click)
# this should show on the /client#/home page (WILL CHANGE)
find('h2', text: 'create session')
user = User.find_by_email('student_123@jamkazam.com')
user.is_a_student.should be true
user.is_a_teacher.should be false
user.musician.should be true
end
it "logged in" do
fast_signin(user,"/landing/jamclass/students")
find('h1.jam-track-name', 'JAMCLASS')
find('h2.original-artist', 'Finally, online music lessons that really work!')
find('button.cta-button', text: 'TRY TESTDRIVE').trigger(:click)
# this should show on the /client#/home page (WILL CHANGE)
find('h2', text: 'create session')
user.reload
user.is_a_student.should be true
user.is_a_teacher.should be false
user.musician.should be true
end
end

View File

@ -0,0 +1,61 @@
require 'spec_helper'
describe "Student Landing", :js => true, :type => :feature, :capybara_feature => true do
subject { page }
before(:all) do
ShoppingCart.delete_all
JamTrackRight.delete_all
JamTrack.delete_all
JamTrackTrack.delete_all
JamTrackLicensor.delete_all
end
let(:user) { FactoryGirl.create(:user, country: 'US') }
it "logged out" do
visit "/landing/jamclass/teachers"
find('h1.jam-track-name', 'JAMCLASS')
find('h2.original-artist', 'Finally, online music lessons that really work!')
find('button.cta-button', text: 'SIGN UP').trigger(:click)
# should fail because we haven't filled out email/password/terms
find('.register-area .errors', text: "Email can't be blank")
fill_in "email", with: 'teacher_123@jamkazam.com'
fill_in "password", with: 'jam123'
find('.register-area ins', visible: false).trigger(:click)
find('button.cta-button', text: 'SIGN UP').trigger(:click)
# this should show on the /client#/home page (WILL CHANGE)
find('h2', text: 'create session')
user = User.find_by_email('teacher_123@jamkazam.com')
user.is_a_student.should be false
user.is_a_teacher.should be true
user.musician.should be true
end
it "logged in" do
fast_signin(user,"/landing/jamclass/teachers")
find('h1.jam-track-name', 'JAMCLASS')
find('h2.original-artist', 'Finally, online music lessons that really work!')
find('button.cta-button', text: 'BECOME A TEACHER').trigger(:click)
# this should show on the /client#/home page (WILL CHANGE)
find('h2', text: 'create session')
user.reload
user.is_a_student.should be false
user.is_a_teacher.should be true
user.musician.should be true
end
end

View File

@ -4,14 +4,14 @@ require 'spec_helper'
describe UserManager do
before(:each) do
Rails.application.config.recaptcha_enable=false
Rails.application.config.recaptcha_enable=false
@user_manager = UserManager.new(:conn => @conn)
UserMailer.deliveries.clear
@location = { :country => "US", :state => "Arkansas", :city => "Little Rock" }
@loca = { :country => "US", :state => "Arkansas", :city => "Texarkana" }
@locb = { :country => "US", :state => "Texas", :city => "Longview" }
@locc = { }
@instruments = [ { :instrument_id=>"electric guitar", :proficiency_level => '1', :priority=>0 }]
@location = {:country => "US", :state => "Arkansas", :city => "Little Rock"}
@loca = {:country => "US", :state => "Arkansas", :city => "Texarkana"}
@locb = {:country => "US", :state => "Texas", :city => "Longview"}
@locc = {}
@instruments = [{:instrument_id => "electric guitar", :proficiency_level => '1', :priority => 0}]
end
describe 'better signup' do
@ -181,24 +181,24 @@ describe UserManager do
describe "signup" do
let!(:user) { FactoryGirl.create(:user) }
let!(:partner) {
AffiliatePartner.create_with_web_params(user, {:partner_name => Faker::Company.name, entity_type:'Individual'})
let!(:partner) {
AffiliatePartner.create_with_web_params(user, {:partner_name => Faker::Company.name, entity_type: 'Individual'})
}
it "signup successfully" do
GeoIpLocations.delete_all # prove that city/state/country will remain nil if no maxmind data
user = @user_manager.signup(remote_ip: "127.0.0.1",
first_name: "bob",
last_name: "smith",
email: "userman1@jamkazam.com",
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
musician:true,
signup_confirm_url: "http://localhost:3000/confirm",
affiliate_referral_id: partner.id)
first_name: "bob",
last_name: "smith",
email: "userman1@jamkazam.com",
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
musician: true,
signup_confirm_url: "http://localhost:3000/confirm",
affiliate_referral_id: partner.id)
user.errors.any?.should be_false
user.first_name.should == "bob"
@ -220,15 +220,15 @@ describe UserManager do
it "signup successfully with instruments" do
user = @user_manager.signup(remote_ip: "127.0.0.1",
first_name: "bob",
last_name: "smith",
email: "userman2@jamkazam.com",
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
musician: true,
signup_confirm_url: "http://localhost:3000/confirm")
first_name: "bob",
last_name: "smith",
email: "userman2@jamkazam.com",
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
musician: true,
signup_confirm_url: "http://localhost:3000/confirm")
user.errors.any?.should be_false
user.instruments.length.should == 1
@ -239,14 +239,14 @@ describe UserManager do
it "doesnt fail if ip address is nil" do
user = @user_manager.signup(first_name: "bob",
last_name: "smith",
email: "userman3@jamkazam.com",
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
musician: true,
signup_confirm_url: "http://localhost:3000/confirm" )
last_name: "smith",
email: "userman3@jamkazam.com",
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
musician: true,
signup_confirm_url: "http://localhost:3000/confirm")
user.errors.any?.should be_false
user.city.should be_nil
@ -257,15 +257,15 @@ describe UserManager do
it "sets the location properly from maxmind" do
MaxMindManager.create_phony_database
user = @user_manager.signup(remote_ip: "127.0.0.1",
first_name: "bob",
last_name: "smith",
email: "userman4@jamkazam.com",
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
musician: true,
signup_confirm_url: "http://localhost:3000/confirm" )
first_name: "bob",
last_name: "smith",
email: "userman4@jamkazam.com",
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
musician: true,
signup_confirm_url: "http://localhost:3000/confirm")
user.errors.any?.should be_false
user.city.should == 'Boston'
@ -276,16 +276,16 @@ describe UserManager do
it "accepts location if specified" do
MaxMindManager.create_phony_database
user = @user_manager.signup(remote_ip: "127.0.0.1",
first_name: "bob",
last_name: "smith",
email: "userman5@jamkazam.com",
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
location: @location,
musician: true,
signup_confirm_url: "http://localhost:3000/confirm" )
first_name: "bob",
last_name: "smith",
email: "userman5@jamkazam.com",
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
location: @location,
musician: true,
signup_confirm_url: "http://localhost:3000/confirm")
user.errors.any?.should be_false
user.city.should == 'Little Rock'
@ -296,16 +296,16 @@ describe UserManager do
it "accepts a nil location, if specified" do
MaxMindManager.create_phony_database
user = @user_manager.signup(remote_ip: "127.0.0.1",
first_name: "bob",
last_name: "smith",
email: "userman6@jamkazam.com",
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
location: {},
musician: true,
signup_confirm_url: "http://localhost:3000/confirm" )
first_name: "bob",
last_name: "smith",
email: "userman6@jamkazam.com",
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
location: {},
musician: true,
signup_confirm_url: "http://localhost:3000/confirm")
user.errors.any?.should be_false
user.city.should be_nil
@ -317,16 +317,16 @@ describe UserManager do
it "accepts birth_date if specified" do
MaxMindManager.create_phony_database
user = @user_manager.signup(remote_ip: "127.0.0.1",
first_name: "bob",
last_name: "smith",
email: "userman7@jamkazam.com",
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
birth_date: Date.new(2001, 1, 1),
musician: true,
signup_confirm_url: "http://localhost:3000/confirm" )
first_name: "bob",
last_name: "smith",
email: "userman7@jamkazam.com",
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
birth_date: Date.new(2001, 1, 1),
musician: true,
signup_confirm_url: "http://localhost:3000/confirm")
user.errors.any?.should be_false
user.birth_date.should == Date.new(2001, 1, 1)
@ -335,62 +335,62 @@ describe UserManager do
it "duplicate signup failure" do
user = @user_manager.signup(remote_ip: "127.0.0.1",
first_name: "bob",
last_name: "smith",
email: "userman8@jamkazam.com",
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
musician: true,
signup_confirm_url: "http://localhost:3000/confirm")
first_name: "bob",
last_name: "smith",
email: "userman8@jamkazam.com",
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
musician: true,
signup_confirm_url: "http://localhost:3000/confirm")
UserMailer.deliveries.length.should == 1
user.errors.any?.should be_false
# exactly the same parameters; should dup on email, and send no email
user = @user_manager.signup(remote_ip: "127.0.0.1",
first_name: "bob",
last_name: "smith",
email: "userman8@jamkazam.com",
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
musician: true,
signup_confirm_url: "http://localhost:3000/confirm")
first_name: "bob",
last_name: "smith",
email: "userman8@jamkazam.com",
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
musician: true,
signup_confirm_url: "http://localhost:3000/confirm")
UserMailer.deliveries.length.should == 1
user.errors.any?.should be_true
user.errors[:email][0].should == "has already been taken"
end
it "fail on no first_name/last_name" do
it "is OK with no first_name/last_name" do
user = @user_manager.signup(remote_ip: "127.0.0.1",
first_name: "",
last_name: "",
email: "userman10@jamkazam.com",
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
musician: true,
signup_confirm_url: "http://localhost:3000/confirm")
UserMailer.deliveries.length.should == 0
user.errors.any?.should be_true
user.errors[:first_name][0].should == "can't be blank"
first_name: "",
last_name: "",
email: "userman10@jamkazam.com",
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
musician: true,
signup_confirm_url: "http://localhost:3000/confirm")
UserMailer.deliveries.length.should == 1
user.errors.any?.should be_false
user.name.should eq 'Anonymous'
end
it "fail on no email" do
user = @user_manager.signup(remote_ip: "127.0.0.1",
first_name: "murp",
last_name: "blurp",
email: "",
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
musician: true,
signup_confirm_url: "http://localhost:3000/confirm")
first_name: "murp",
last_name: "blurp",
email: "",
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
musician: true,
signup_confirm_url: "http://localhost:3000/confirm")
UserMailer.deliveries.length.should == 0
user.errors.any?.should be_true
@ -401,22 +401,22 @@ describe UserManager do
describe "signup_confirm" do
it "fail on no username" do
user = @user_manager.signup(remote_ip: "127.0.0.1",
first_name: "bob",
last_name: "smith",
email: "userman11@jamkazam.com",
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
musician: true,
signup_confirm_url: "http://localhost:3000/confirm")
user = @user_manager.signup_confirm(user.signup_token)
user.email_confirmed.should be_true
user = @user_manager.signup(remote_ip: "127.0.0.1",
first_name: "bob",
last_name: "smith",
email: "userman11@jamkazam.com",
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
musician: true,
signup_confirm_url: "http://localhost:3000/confirm")
user = @user_manager.signup_confirm(user.signup_token)
user.email_confirmed.should be_true
end
it "fail to confirm bogus signup_confirmnup token" do
@user_manager.signup_confirm("murp").should be_nil
@user_manager.signup_confirm("murp").should be_nil
end
it "fail to confirm empty signup token" do
@ -437,16 +437,16 @@ describe UserManager do
invitation.accepted.should be_false
user = @user_manager.signup(remote_ip: "127.0.0.1",
first_name: "bob",
last_name: "smith",
email: invitation.email,
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
musician: true,
invited_user: invitation,
signup_confirm_url: "http://localhost:3000/confirm")
first_name: "bob",
last_name: "smith",
email: invitation.email,
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
musician: true,
invited_user: invitation,
signup_confirm_url: "http://localhost:3000/confirm")
user.errors.any?.should be_false
user.email_confirmed.should be_true
@ -466,16 +466,16 @@ describe UserManager do
user = @user_manager.signup(remote_ip: "127.0.0.1",
first_name: "bob",
last_name: "smith",
email: invitation.email,
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
musician: true,
invited_user: invitation,
signup_confirm_url: "http://localhost:3000/confirm")
first_name: "bob",
last_name: "smith",
email: invitation.email,
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
musician: true,
invited_user: invitation,
signup_confirm_url: "http://localhost:3000/confirm")
user.errors.any?.should be_false
user.email_confirmed.should be_true
@ -495,16 +495,16 @@ describe UserManager do
user = @user_manager.signup(remote_ip: "127.0.0.1",
first_name: "bob",
last_name: "smith",
email: invitation.email,
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
musician: true,
invited_user: invitation,
signup_confirm_url: "http://localhost:3000/confirm")
first_name: "bob",
last_name: "smith",
email: invitation.email,
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
musician: true,
invited_user: invitation,
signup_confirm_url: "http://localhost:3000/confirm")
user.errors.any?.should be_false
user.email_confirmed.should be_true
@ -526,16 +526,16 @@ describe UserManager do
user = @user_manager.signup(remote_ip: "127.0.0.1",
first_name: "bob",
last_name: "smith",
email: "userman12@jamkazam.com",
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
musician: true,
invited_user: invitation,
signup_confirm_url: "http://localhost:3000/confirm")
first_name: "bob",
last_name: "smith",
email: "userman12@jamkazam.com",
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
musician: true,
invited_user: invitation,
signup_confirm_url: "http://localhost:3000/confirm")
user.errors.any?.should be_false
user.email_confirmed.should be_false
@ -555,16 +555,16 @@ describe UserManager do
user = @user_manager.signup(remote_ip: "127.0.0.1",
first_name: "bob",
last_name: "smith",
email: fb_signup.email,
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
musician: true,
fb_signup: fb_signup,
signup_confirm_url: "http://localhost:3000/confirm")
first_name: "bob",
last_name: "smith",
email: fb_signup.email,
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
musician: true,
fb_signup: fb_signup,
signup_confirm_url: "http://localhost:3000/confirm")
user.errors.any?.should be_false
user.email_confirmed.should be_true
@ -584,16 +584,16 @@ describe UserManager do
user = @user_manager.signup(remote_ip: "127.0.0.1",
first_name: "bob",
last_name: "smith",
email: "userman13@jamkazam.com",
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
musician: true,
fb_signup: fb_signup,
signup_confirm_url: "http://localhost:3000/confirm")
first_name: "bob",
last_name: "smith",
email: "userman13@jamkazam.com",
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
musician: true,
fb_signup: fb_signup,
signup_confirm_url: "http://localhost:3000/confirm")
user.errors.any?.should be_false
user.email_confirmed.should be_false
@ -616,16 +616,16 @@ describe UserManager do
UserMailer.deliveries.clear
user = @user_manager.signup(remote_ip: "127.0.0.1",
first_name: "bob",
last_name: "smith",
email: "userman13@jamkazam.com",
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
musician: true,
fb_signup: fb_signup,
signup_confirm_url: "http://localhost:3000/confirm")
first_name: "bob",
last_name: "smith",
email: "userman13@jamkazam.com",
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
musician: true,
fb_signup: fb_signup,
signup_confirm_url: "http://localhost:3000/confirm")
user.errors.any?.should be_true
user.errors[:user_authorizations].should == ['is invalid']
@ -656,10 +656,10 @@ describe UserManager do
location: @loca,
recaptcha_failed: true,
signup_confirm_url: "http://localhost:3000/confirm")
user.errors.any?.should be_false
user.errors.any?.should be_false
end # it "passes even with true recaptcha"
end # describe "without nocaptcha"
describe "with nocaptcha" do
before(:each) do
@old_recaptcha=Rails.application.config.recaptcha_enable
@ -671,7 +671,7 @@ describe UserManager do
Rails.application.config.recaptcha_enable=@old_recaptcha
end
it "fails when nocaptcha fails" do
it "fails when nocaptcha fails" do
user = @user_manager.signup(remote_ip: "1.2.3.4",
first_name: "bob",
last_name: "smith",
@ -685,7 +685,7 @@ describe UserManager do
recaptcha_response: nil,
signup_confirm_url: "http://localhost:3000/confirm")
user.errors.any?.should be_true
user.errors.any?.should be_true
UserMailer.deliveries.should have(0).items
end
@ -704,13 +704,96 @@ describe UserManager do
location: @loca,
signup_confirm_url: "http://localhost:3000/confirm")
user.errors.any?.should be_false
user.errors.any?.should be_false
end # it "passes when facebook signup"
end # describe "with nocaptcha"
describe "student/teacher" do
it "accepts student" do
user = @user_manager.signup(remote_ip: "1.2.3.4",
first_name: "bob",
last_name: "smith",
email: "student1@jamkazam.com",
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
location: @loca,
student: true,
signup_confirm_url: "http://localhost:3000/confirm")
UserMailer.deliveries.length.should == 1
user.errors.any?.should be_false
user = User.find(user.id)
user.has_redeemable_jamtrack.should be_true
user.is_a_student.should be_true
user.is_a_teacher.should be_false
user.musician.should be_true
end
it "accepts teacher" do
user = @user_manager.signup(remote_ip: "1.2.3.4",
first_name: "bob",
last_name: "smith",
email: "student2@jamkazam.com",
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
location: @loca,
teacher: true,
signup_confirm_url: "http://localhost:3000/confirm")
UserMailer.deliveries.length.should == 1
user.errors.any?.should be_false
user = User.find(user.id)
user.has_redeemable_jamtrack.should be_true
user.is_a_student.should be_false
user.is_a_teacher.should be_true
user.musician.should be_true
end
it "accepts teacher and student" do
user = @user_manager.signup(remote_ip: "1.2.3.4",
first_name: "bob",
last_name: "smith",
email: "student3@jamkazam.com",
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
location: @loca,
teacher: true,
signup_confirm_url: "http://localhost:3000/confirm")
UserMailer.deliveries.length.should == 1
user.errors.any?.should be_false
user = User.find(user.id)
user.has_redeemable_jamtrack.should be_true
user.is_a_student.should be_false
user.is_a_teacher.should be_true
user.musician.should be_true
end
it "lets user be a fan if nothing if musician/student/teacher is true" do
user = @user_manager.signup(remote_ip: "1.2.3.4",
first_name: "bob",
last_name: "smith",
email: "student4@jamkazam.com",
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
location: @loca,
signup_confirm_url: "http://localhost:3000/confirm")
UserMailer.deliveries.length.should == 1
user.errors.any?.should be_false
user = User.find(user.id)
user.has_redeemable_jamtrack.should be_true
user.is_a_student.should be_false
user.is_a_teacher.should be_false
user.musician.should be_false
end
end
describe "gift_card" do
let(:gift_card) {FactoryGirl.create(:gift_card)}
let(:gift_card) { FactoryGirl.create(:gift_card) }
it "can succeed when specified" do
user = @user_manager.signup(remote_ip: "1.2.3.4",