Initial merge and manual conflict and fix for tests.
This commit is contained in:
parent
df9352d608
commit
433fe0be74
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Settings><!--This file was automatically generated by Ruby plugin.
|
||||||
|
You are allowed to:
|
||||||
|
1. Remove rake task
|
||||||
|
2. Add existing rake tasks
|
||||||
|
To add existing rake tasks automatically delete this file and reload the project.
|
||||||
|
--><RakeGroup description="" fullCmd="" taksId="rake" /></Settings>
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
ActiveAdmin.register JamRuby::JamTrackLicensor, :as => 'JamTrack Licensors' do
|
||||||
|
|
||||||
|
menu :label => 'JamTrack Licensors', :parent => 'JamTracks'
|
||||||
|
|
||||||
|
config.sort_order = 'name_asc'
|
||||||
|
config.batch_actions = false
|
||||||
|
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
ActiveAdmin.register JamRuby::JamTrack, :as => 'JamTracks' do
|
||||||
|
|
||||||
|
menu :label => 'JamTracks', :parent => 'JamTracks'
|
||||||
|
|
||||||
|
config.sort_order = 'name_asc'
|
||||||
|
config.batch_actions = false
|
||||||
|
|
||||||
|
filter :genre
|
||||||
|
filter :status, :as => :select, collection: JamRuby::JamTrack::STATUS
|
||||||
|
|
||||||
|
form :partial => 'form'
|
||||||
|
|
||||||
|
index do
|
||||||
|
column :id
|
||||||
|
column :name
|
||||||
|
column :description
|
||||||
|
column :bpm
|
||||||
|
column :time_signature
|
||||||
|
column :status
|
||||||
|
column :recording_type
|
||||||
|
column :original_artist
|
||||||
|
column :songwriter
|
||||||
|
column :publisher
|
||||||
|
column :licensor
|
||||||
|
column :pro
|
||||||
|
column :genre
|
||||||
|
column :sales_region
|
||||||
|
column :price
|
||||||
|
column :reproduction_royalty
|
||||||
|
column :public_performance_royalty
|
||||||
|
column :reproduction_royalty_amount
|
||||||
|
column :licensor_royalty_amount
|
||||||
|
column :pro_royalty_amount
|
||||||
|
column :url
|
||||||
|
column :created_at
|
||||||
|
|
||||||
|
column :jam_track_tracks do |jam_track|
|
||||||
|
table_for jam_track.jam_track_tracks.order('position ASC') do
|
||||||
|
column :id
|
||||||
|
column :track_type
|
||||||
|
column :instrument
|
||||||
|
column :part
|
||||||
|
column :track do |track|
|
||||||
|
link_to 'Play', '#'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# default_actions # use this for all view/edit/delete links
|
||||||
|
column "Actions" do |jam_track|
|
||||||
|
links = ''.html_safe
|
||||||
|
links << link_to("Show Tracks", '#', :class => "member_link view_link show_tracks")
|
||||||
|
links << link_to("Update", edit_resource_path(jam_track), :class => "member_link edit_link")
|
||||||
|
links
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
$(document).ready(function() {
|
||||||
|
$("th.jam_track_tracks").css('display', 'none');
|
||||||
|
$("td.jam_track_tracks").css('display', 'none');
|
||||||
|
|
||||||
|
$(".show_tracks").click(function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
var $rowJamTrack = $(this).parents('tr');
|
||||||
|
var $jamTrackTracks = $($rowJamTrack).find("td.jam_track_tracks");
|
||||||
|
|
||||||
|
var count = $jamTrackTracks.find("table tbody tr").length;
|
||||||
|
|
||||||
|
if ($rowJamTrack.next().attr('id') == "jam_track_tracks_detail") {
|
||||||
|
$(this).html("Show Tracks");
|
||||||
|
$rowJamTrack.next().remove();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$(this).html('Hide Tracks');
|
||||||
|
if (count == 0) {
|
||||||
|
$rowJamTrack.after(
|
||||||
|
$("<tr id=\"jam_track_tracks_detail\"></tr>").html(
|
||||||
|
$("<td colspan=\"18\"></td>")
|
||||||
|
).append(
|
||||||
|
$("<td colspan=\"4\"></td>").html(
|
||||||
|
"No Tracks"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$rowJamTrack.after(
|
||||||
|
$("<tr id=\"jam_track_tracks_detail\"></tr>").html(
|
||||||
|
$("<td colspan=\"18\"></td>")
|
||||||
|
).append(
|
||||||
|
$("<td colspan=\"4\"></td>").html(
|
||||||
|
$jamTrackTracks.html()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
= semantic_form_for([:admin, resource], :html => {:multipart => true}, :url => resource.new_record? ? admin_jam_tracks_path : "#{ENV['RAILS_RELATIVE_URL_ROOT']}/admin/jam_tracks/#{resource.id}") do |f|
|
||||||
|
= f.semantic_errors *f.object.errors.keys
|
||||||
|
= f.inputs name: 'JamTrack fields' do
|
||||||
|
|
||||||
|
= f.input :name
|
||||||
|
= f.input :description
|
||||||
|
= f.input :bpm
|
||||||
|
= f.input :time_signature, collection: JamRuby::JamTrack::TIME_SIGNATURES
|
||||||
|
= f.input :status, collection: JamRuby::JamTrack::STATUS
|
||||||
|
= f.input :recording_type, collection: JamRuby::JamTrack::RECORDING_TYPE
|
||||||
|
= f.input :original_artist
|
||||||
|
= f.input :songwriter
|
||||||
|
= f.input :publisher
|
||||||
|
= f.input :licensor, collection: JamRuby::JamTrackLicensor.all
|
||||||
|
= f.input :pro, collection: JamRuby::JamTrack::PRO
|
||||||
|
= f.input :genre, collection: JamRuby::Genre.all
|
||||||
|
= f.input :sales_region, collection: JamRuby::JamTrack::SALES_REGION
|
||||||
|
= f.input :price
|
||||||
|
= f.input :reproduction_royalty, :label => 'Reproduction Royalty'
|
||||||
|
= f.input :public_performance_royalty, :label => 'Public Performance Royalty'
|
||||||
|
= f.input :reproduction_royalty_amount
|
||||||
|
= f.input :licensor_royalty_amount
|
||||||
|
= f.input :pro_royalty_amount
|
||||||
|
= f.input :url, :as => :file, :label => 'Audio File'
|
||||||
|
|
||||||
|
= f.semantic_fields_for :jam_track_tracks do |track|
|
||||||
|
= render 'jam_track_track_fields', f: track
|
||||||
|
.links
|
||||||
|
= link_to_add_association 'Add Track', f, :jam_track_tracks, class: 'button', style: 'margin:20px;padding:10px 20px'
|
||||||
|
|
||||||
|
= f.actions
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
= f.inputs name: 'Track fields' do
|
||||||
|
|
||||||
|
%ol.nested-fields
|
||||||
|
= f.input :track_type, :as => :select, collection: JamRuby::JamTrackTrack::TRACK_TYPE
|
||||||
|
= f.input :instrument, collection: Instrument.all
|
||||||
|
= f.input :part
|
||||||
|
= f.input :position
|
||||||
|
|
||||||
|
- if f.object.new_record?
|
||||||
|
%p{style: 'margin-left:10px'}
|
||||||
|
%i before you can upload, you must select 'Update JamTrack'
|
||||||
|
- else
|
||||||
|
= f.input :url, :as => :file, :label => 'Track file'
|
||||||
|
- unless f.object.nil? || f.object[:url].nil?
|
||||||
|
.current_file_holder{style: 'margin-bottom:10px'}
|
||||||
|
%a{href: f.object.sign_url(3600), style: 'padding:0 0 0 20px'} Download
|
||||||
|
|
||||||
|
= link_to_remove_association "Delete Track", f, class: 'button', style: 'margin-left:10px'
|
||||||
|
|
@ -134,5 +134,10 @@ module JamAdmin
|
||||||
# recording upload/download configs
|
# recording upload/download configs
|
||||||
config.max_track_upload_failures = 10
|
config.max_track_upload_failures = 10
|
||||||
config.max_track_part_upload_failures = 3
|
config.max_track_part_upload_failures = 3
|
||||||
|
|
||||||
|
# Use Private API Keys to communicate with Recurly's API v2. See https://docs.recurly.com/api/basics/authentication to learn more.
|
||||||
|
config.recurly_private_api_key = '7d623daabfc2434fa2a893bb008eb3e6'
|
||||||
|
# Use Public Keys to identify your site when using Recurly.js. See https://docs.recurly.com/js/#include to learn more.
|
||||||
|
config.recurly_public_api_key = 'sc-SZlO11shkeA1WMGuISLGg5'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -42,4 +42,9 @@ JamAdmin::Application.configure do
|
||||||
config.twitter_app_secret = 'PfG1jAUMnyrimPcDooUVQaJrG1IuDjUyGg5KciOo'
|
config.twitter_app_secret = 'PfG1jAUMnyrimPcDooUVQaJrG1IuDjUyGg5KciOo'
|
||||||
|
|
||||||
config.redis_host = "localhost:6379:1" # go to another db to not cross pollute into dev/production redis dbs
|
config.redis_host = "localhost:6379:1" # go to another db to not cross pollute into dev/production redis dbs
|
||||||
|
|
||||||
|
# Use Private API Keys to communicate with Recurly's API v2. See https://docs.recurly.com/api/basics/authentication to learn more.
|
||||||
|
config.recurly_private_api_key = '4631527f203b41848523125b3ae51341'
|
||||||
|
# Use Public Keys to identify your site when using Recurly.js. See https://docs.recurly.com/js/#include to learn more.
|
||||||
|
config.recurly_public_api_key = 'sc-s6G2OA80Rwyvsb1RmS3mAE'
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -205,4 +205,54 @@ FactoryGirl.define do
|
||||||
latency_tester.save
|
latency_tester.save
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
factory :jam_track_licensor, :class => JamRuby::JamTrackLicensor do
|
||||||
|
sequence(:name) { |n| "licensor-#{n}" }
|
||||||
|
sequence(:description) { |n| "description-#{n}" }
|
||||||
|
sequence(:attention) { |n| "attention-#{n}" }
|
||||||
|
sequence(:address_line_1) { |n| "address1-#{n}" }
|
||||||
|
sequence(:address_line_2) { |n| "address2-#{n}" }
|
||||||
|
sequence(:city) { |n| "city-#{n}" }
|
||||||
|
sequence(:state) { |n| "state-#{n}" }
|
||||||
|
sequence(:zip_code) { |n| "zipcode-#{n}" }
|
||||||
|
sequence(:contact) { |n| "contact-#{n}" }
|
||||||
|
sequence(:email) { |n| "email-#{n}" }
|
||||||
|
sequence(:phone) { |n| "phone-#{n}" }
|
||||||
|
end
|
||||||
|
|
||||||
|
factory :jam_track, :class => JamRuby::JamTrack do
|
||||||
|
sequence(:name) { |n| "jam-track-#{n}" }
|
||||||
|
sequence(:description) { |n| "description-#{n}" }
|
||||||
|
bpm 100.1
|
||||||
|
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}" }
|
||||||
|
pro 'ASCAP'
|
||||||
|
sales_region 'United States'
|
||||||
|
price 1.99
|
||||||
|
reproduction_royalty true
|
||||||
|
public_performance_royalty true
|
||||||
|
reproduction_royalty_amount 0.999
|
||||||
|
licensor_royalty_amount 0.999
|
||||||
|
pro_royalty_amount 0.999
|
||||||
|
|
||||||
|
genre JamRuby::Genre.first
|
||||||
|
association :licensor, factory: :jam_track_licensor
|
||||||
|
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
|
||||||
|
end
|
||||||
|
|
||||||
|
factory :jam_track_right, :class => JamRuby::JamTrackRight do
|
||||||
|
association :jam_track, factory: :jam_track
|
||||||
|
association :user, factory: :user
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -225,3 +225,6 @@ add_youtube_flag_to_claimed_recordings.sql
|
||||||
add_session_create_type.sql
|
add_session_create_type.sql
|
||||||
user_syncs_and_quick_mix.sql
|
user_syncs_and_quick_mix.sql
|
||||||
user_syncs_fix_dup_tracks_2408.sql
|
user_syncs_fix_dup_tracks_2408.sql
|
||||||
|
jam_tracks.sql
|
||||||
|
shopping_carts.sql
|
||||||
|
recurly.sql
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
CREATE TABLE jam_track_licensors (
|
||||||
|
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4() NOT NULL,
|
||||||
|
name VARCHAR NOT NULL UNIQUE,
|
||||||
|
description TEXT,
|
||||||
|
attention TEXT,
|
||||||
|
address_line_1 VARCHAR,
|
||||||
|
address_line_2 VARCHAR,
|
||||||
|
city VARCHAR,
|
||||||
|
state VARCHAR,
|
||||||
|
zip_code VARCHAR,
|
||||||
|
contact VARCHAR,
|
||||||
|
email VARCHAR,
|
||||||
|
phone VARCHAR,
|
||||||
|
created_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL,
|
||||||
|
updated_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE jam_tracks (
|
||||||
|
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4() NOT NULL,
|
||||||
|
name VARCHAR NOT NULL UNIQUE,
|
||||||
|
description TEXT,
|
||||||
|
bpm decimal,
|
||||||
|
time_signature VARCHAR,
|
||||||
|
status VARCHAR,
|
||||||
|
recording_type VARCHAR,
|
||||||
|
original_artist TEXT,
|
||||||
|
songwriter TEXT,
|
||||||
|
publisher TEXT,
|
||||||
|
pro VARCHAR,
|
||||||
|
sales_region VARCHAR,
|
||||||
|
price decimal,
|
||||||
|
reproduction_royalty BOOLEAN,
|
||||||
|
public_performance_royalty BOOLEAN,
|
||||||
|
reproduction_royalty_amount DECIMAL,
|
||||||
|
licensor_royalty_amount DECIMAL,
|
||||||
|
pro_royalty_amount DECIMAL,
|
||||||
|
url VARCHAR,
|
||||||
|
md5 VARCHAR,
|
||||||
|
length BIGINT,
|
||||||
|
licensor_id VARCHAR(64) REFERENCES jam_track_licensors (id) ON DELETE SET NULL,
|
||||||
|
genre_id VARCHAR(64) REFERENCES genres (id) ON DELETE SET NULL,
|
||||||
|
created_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL,
|
||||||
|
updated_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE jam_track_tracks (
|
||||||
|
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4() NOT NULL,
|
||||||
|
position INTEGER,
|
||||||
|
track_type VARCHAR,
|
||||||
|
jam_track_id VARCHAR(64) REFERENCES jam_tracks(id) ON DELETE CASCADE,
|
||||||
|
instrument_id VARCHAR(64) REFERENCES instruments(id) ON DELETE SET NULL,
|
||||||
|
part VARCHAR,
|
||||||
|
url VARCHAR,
|
||||||
|
md5 VARCHAR,
|
||||||
|
length BIGINT,
|
||||||
|
created_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL,
|
||||||
|
updated_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX jam_track_tracks_position_uniqkey ON jam_track_tracks (position, jam_track_id);
|
||||||
|
|
||||||
|
CREATE TABLE jam_track_rights (
|
||||||
|
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4() NOT NULL,
|
||||||
|
user_id VARCHAR(64) NOT NULL REFERENCES users(id),
|
||||||
|
jam_track_id VARCHAR(64) NOT NULL REFERENCES jam_tracks(id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX jam_tracks_rights_uniqkey ON jam_track_rights (user_id, jam_track_id);
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
ALTER TABLE users ADD COLUMN recurly_code VARCHAR(50) DEFAULT NULL;
|
||||||
|
ALTER TABLE jam_tracks ADD COLUMN plan_code VARCHAR(50) DEFAULT NULL;
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
CREATE TABLE shopping_carts (
|
||||||
|
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||||
|
quantity INTEGER NOT NULL DEFAULT 1,
|
||||||
|
user_id VARCHAR(64) NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||||
|
cart_id VARCHAR(64) NOT NULL,
|
||||||
|
cart_class_name VARCHAR(64),
|
||||||
|
cart_type VARCHAR(64),
|
||||||
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
@ -71,6 +71,8 @@ require "jam_ruby/app/uploaders/perf_data_uploader"
|
||||||
require "jam_ruby/app/uploaders/recorded_track_uploader"
|
require "jam_ruby/app/uploaders/recorded_track_uploader"
|
||||||
require "jam_ruby/app/uploaders/mix_uploader"
|
require "jam_ruby/app/uploaders/mix_uploader"
|
||||||
require "jam_ruby/app/uploaders/music_notation_uploader"
|
require "jam_ruby/app/uploaders/music_notation_uploader"
|
||||||
|
require "jam_ruby/app/uploaders/jam_track_uploader"
|
||||||
|
require "jam_ruby/app/uploaders/jam_track_track_uploader"
|
||||||
require "jam_ruby/app/uploaders/max_mind_release_uploader"
|
require "jam_ruby/app/uploaders/max_mind_release_uploader"
|
||||||
require "jam_ruby/lib/desk_multipass"
|
require "jam_ruby/lib/desk_multipass"
|
||||||
require "jam_ruby/lib/ip"
|
require "jam_ruby/lib/ip"
|
||||||
|
|
@ -170,11 +172,16 @@ require "jam_ruby/models/email_batch_new_musician"
|
||||||
require "jam_ruby/models/email_batch_progression"
|
require "jam_ruby/models/email_batch_progression"
|
||||||
require "jam_ruby/models/email_batch_scheduled_sessions"
|
require "jam_ruby/models/email_batch_scheduled_sessions"
|
||||||
require "jam_ruby/models/email_batch_set"
|
require "jam_ruby/models/email_batch_set"
|
||||||
|
require "jam_ruby/models/jam_track_licensor"
|
||||||
|
require "jam_ruby/models/jam_track"
|
||||||
|
require "jam_ruby/models/jam_track_track"
|
||||||
|
require "jam_ruby/models/jam_track_right"
|
||||||
require "jam_ruby/app/mailers/async_mailer"
|
require "jam_ruby/app/mailers/async_mailer"
|
||||||
require "jam_ruby/app/mailers/batch_mailer"
|
require "jam_ruby/app/mailers/batch_mailer"
|
||||||
require "jam_ruby/app/mailers/progress_mailer"
|
require "jam_ruby/app/mailers/progress_mailer"
|
||||||
require "jam_ruby/models/affiliate_partner"
|
require "jam_ruby/models/affiliate_partner"
|
||||||
require "jam_ruby/models/chat_message"
|
require "jam_ruby/models/chat_message"
|
||||||
|
require "jam_ruby/models/shopping_cart"
|
||||||
require "jam_ruby/models/generic_state"
|
require "jam_ruby/models/generic_state"
|
||||||
require "jam_ruby/models/score_history"
|
require "jam_ruby/models/score_history"
|
||||||
require "jam_ruby/models/jam_company"
|
require "jam_ruby/models/jam_company"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
class JamTrackTrackUploader < CarrierWave::Uploader::Base
|
||||||
|
# include CarrierWaveDirect::Uploader
|
||||||
|
include CarrierWave::MimeTypes
|
||||||
|
|
||||||
|
process :set_content_type
|
||||||
|
|
||||||
|
def initialize(*)
|
||||||
|
super
|
||||||
|
JamRuby::UploaderConfiguration.set_aws_private_configuration(self)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Add a white list of extensions which are allowed to be uploaded.
|
||||||
|
def extension_white_list
|
||||||
|
%w(ogg)
|
||||||
|
end
|
||||||
|
|
||||||
|
def store_dir
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def md5
|
||||||
|
@md5 ||= ::Digest::MD5.file(current_path).hexdigest
|
||||||
|
end
|
||||||
|
|
||||||
|
def filename
|
||||||
|
"#{model.store_dir}/#{model.filename}" if model.id
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
class JamTrackUploader < CarrierWave::Uploader::Base
|
||||||
|
# include CarrierWaveDirect::Uploader
|
||||||
|
include CarrierWave::MimeTypes
|
||||||
|
|
||||||
|
process :set_content_type
|
||||||
|
|
||||||
|
def initialize(*)
|
||||||
|
super
|
||||||
|
JamRuby::UploaderConfiguration.set_aws_private_configuration(self)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Add a white list of extensions which are allowed to be uploaded.
|
||||||
|
def extension_white_list
|
||||||
|
%w(jka)
|
||||||
|
end
|
||||||
|
|
||||||
|
def store_dir
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def md5
|
||||||
|
@md5 ||= ::Digest::MD5.file(current_path).hexdigest
|
||||||
|
end
|
||||||
|
|
||||||
|
def filename
|
||||||
|
"#{model.store_dir}/#{model.filename}" if model.id
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -40,6 +40,11 @@ module ValidationMessages
|
||||||
EMAIL_MATCHES_CURRENT = "is same as your current email"
|
EMAIL_MATCHES_CURRENT = "is same as your current email"
|
||||||
INVALID_FPFILE = "is not valid"
|
INVALID_FPFILE = "is not valid"
|
||||||
|
|
||||||
|
# recurly
|
||||||
|
RECURLY_ERROR = "Error occurred during Recurly transaction."
|
||||||
|
RECURLY_ACCOUNT_ERROR = "You don't have Recurly account yet."
|
||||||
|
RECURLY_PARAMETER_ERROR = "You didn't input correct information for Recurly transaction."
|
||||||
|
|
||||||
#connection
|
#connection
|
||||||
USER_OR_LATENCY_TESTER_PRESENT = "user or latency_tester must be present"
|
USER_OR_LATENCY_TESTER_PRESENT = "user or latency_tester must be present"
|
||||||
SELECT_AT_LEAST_ONE = "Please select at least one track" # DO NOT CHANGE THIS TEXT MESSAGE UNLESS YOU CHANGE createSession.js.erb, which is looking for it
|
SELECT_AT_LEAST_ONE = "Please select at least one track" # DO NOT CHANGE THIS TEXT MESSAGE UNLESS YOU CHANGE createSession.js.erb, which is looking for it
|
||||||
|
|
|
||||||
|
|
@ -88,6 +88,14 @@ module JamRuby
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def exists?(filename)
|
||||||
|
s3_bucket.objects[filename].exists?
|
||||||
|
end
|
||||||
|
|
||||||
|
def length(filename)
|
||||||
|
s3_bucket.objects[filename].content_length
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def s3_bucket
|
def s3_bucket
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,8 @@ module JamRuby
|
||||||
# genres
|
# genres
|
||||||
has_and_belongs_to_many :recordings, :class_name => "JamRuby::Recording", :join_table => "recordings_genres"
|
has_and_belongs_to_many :recordings, :class_name => "JamRuby::Recording", :join_table => "recordings_genres"
|
||||||
|
|
||||||
|
# jam tracks
|
||||||
|
has_many :jam_tracks, :class_name => "JamRuby::JamTrack"
|
||||||
|
|
||||||
def to_s
|
def to_s
|
||||||
description
|
description
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,106 @@
|
||||||
|
module JamRuby
|
||||||
|
class JamTrack < ActiveRecord::Base
|
||||||
|
include JamRuby::S3ManagerMixin
|
||||||
|
|
||||||
|
TIME_SIGNATURES = %w{4/4 3/4 2/4 6/8 5/8'}
|
||||||
|
STATUS = %w{Staging Production Retired}
|
||||||
|
RECORDING_TYPE = %w{Cover Original}
|
||||||
|
PRO = %w{ASCAP BMI SESAC}
|
||||||
|
SALES_REGION = ['United States', 'Worldwide']
|
||||||
|
|
||||||
|
PRODUCT_TYPE = 'JamTrack'
|
||||||
|
|
||||||
|
mount_uploader :url, JamTrackUploader
|
||||||
|
|
||||||
|
attr_accessible :name, :description, :bpm, :time_signature, :status, :recording_type,
|
||||||
|
:original_artist, :songwriter, :publisher, :licensor, :licensor_id, :pro, :genre, :genre_id, :sales_region, :price,
|
||||||
|
:reproduction_royalty, :public_performance_royalty, :reproduction_royalty_amount,
|
||||||
|
:licensor_royalty_amount, :pro_royalty_amount, :jam_track_tracks_attributes, as: :admin
|
||||||
|
|
||||||
|
validates :name, presence: true, uniqueness: true, length: {maximum: 200}
|
||||||
|
validates :description, length: {maximum: 1000}
|
||||||
|
validates_format_of :bpm, with: /^\d+\.*\d{0,1}$/
|
||||||
|
validates :time_signature, inclusion: {in: [nil] + TIME_SIGNATURES}
|
||||||
|
validates :status, inclusion: {in: [nil] + STATUS}
|
||||||
|
validates :recording_type, inclusion: {in: [nil] + RECORDING_TYPE}
|
||||||
|
validates :original_artist, length: {maximum: 200}
|
||||||
|
validates :songwriter, length: {maximum: 1000}
|
||||||
|
validates :publisher, length: {maximum: 1000}
|
||||||
|
validates :pro, inclusion: {in: [nil] + PRO}
|
||||||
|
validates :sales_region, inclusion: {in: [nil] + SALES_REGION}
|
||||||
|
validates_format_of :price, with: /^\d+\.*\d{0,2}$/
|
||||||
|
|
||||||
|
validates :reproduction_royalty, inclusion: {in: [nil, true, false]}
|
||||||
|
validates :public_performance_royalty, inclusion: {in: [nil, true, false]}
|
||||||
|
validates_format_of :reproduction_royalty_amount, with: /^\d+\.*\d{0,3}$/
|
||||||
|
validates_format_of :licensor_royalty_amount, with: /^\d+\.*\d{0,3}$/
|
||||||
|
validates_format_of :pro_royalty_amount, with: /^\d+\.*\d{0,3}$/
|
||||||
|
|
||||||
|
before_save :sanitize_active_admin
|
||||||
|
|
||||||
|
belongs_to :genre, class_name: "JamRuby::Genre"
|
||||||
|
belongs_to :licensor , class_name: 'JamRuby::JamTrackLicensor', foreign_key: 'licensor_id'
|
||||||
|
|
||||||
|
has_many :jam_track_tracks, :class_name => "JamRuby::JamTrackTrack", order: 'position ASC'
|
||||||
|
|
||||||
|
has_many :jam_track_rights, :class_name => "JamRuby::JamTrackRight", inverse_of: 'jam_track', :foreign_key => "jam_track_id"
|
||||||
|
has_many :owners, :through => :jam_track_rights, :class_name => "JamRuby::User", :source => :user
|
||||||
|
|
||||||
|
accepts_nested_attributes_for :jam_track_tracks, allow_destroy: true
|
||||||
|
|
||||||
|
# create storage directory that will house this jam_track, as well as
|
||||||
|
def store_dir
|
||||||
|
"jam_tracks/#{created_at.strftime('%m-%d-%Y')}/#{id}"
|
||||||
|
end
|
||||||
|
|
||||||
|
# create name of the file
|
||||||
|
def filename
|
||||||
|
"#{name}.jka"
|
||||||
|
end
|
||||||
|
|
||||||
|
# creates a short-lived URL that has access to the object.
|
||||||
|
# the idea is that this is used when a user who has the rights to this tries to download this JamTrack
|
||||||
|
# we would verify their rights (can_download?), and generates a URL in response to the click so that they can download
|
||||||
|
# but the url is short lived enough so that it wouldn't be easily shared
|
||||||
|
def sign_url(expiration_time = 120)
|
||||||
|
s3_manager.sign_url(self[:url], {:expires => expiration_time, :response_content_type => 'audio/jka', :secure => false})
|
||||||
|
end
|
||||||
|
|
||||||
|
def can_download?(user)
|
||||||
|
owners.include?(user)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.index user, options = {}
|
||||||
|
limit = options[:limit]
|
||||||
|
limit ||= 20
|
||||||
|
limit = limit.to_i
|
||||||
|
|
||||||
|
start = options[:start].presence
|
||||||
|
start = start.to_i || 0
|
||||||
|
|
||||||
|
query = JamTrack.joins(:jam_track_tracks)
|
||||||
|
.offset(start)
|
||||||
|
.limit(limit)
|
||||||
|
|
||||||
|
query = query.where("jam_tracks.genre_id = '#{options[:genre]}'") unless options[:genre].blank?
|
||||||
|
query = query.where("jam_track_tracks.instrument_id = '#{options[:instrument]}'") unless options[:instrument].blank?
|
||||||
|
query = query.where("jam_tracks.sales_region = '#{options[:availability]}'") unless options[:availability].blank?
|
||||||
|
query = query.group("jam_tracks.id")
|
||||||
|
|
||||||
|
if query.length == 0
|
||||||
|
[query, nil]
|
||||||
|
elsif query.length < limit
|
||||||
|
[query, nil]
|
||||||
|
else
|
||||||
|
[query, start + limit]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def sanitize_active_admin
|
||||||
|
self.genre_id = nil if self.genre_id == ''
|
||||||
|
self.licensor_id = nil if self.licensor_id == ''
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
module JamRuby
|
||||||
|
class JamTrackLicensor < ActiveRecord::Base
|
||||||
|
|
||||||
|
attr_accessible :name, :description, :attention, :address_line_1, :address_line_2,
|
||||||
|
:city, :state, :zip_code, :contact, :email, :phone, as: :admin
|
||||||
|
|
||||||
|
validates :name, presence: true, uniqueness: true, length: {maximum: 200}
|
||||||
|
validates :description, length: {maximum: 1000}
|
||||||
|
validates :attention, length: {maximum: 200}
|
||||||
|
validates :address_line_1, length: {maximum: 200}
|
||||||
|
validates :address_line_2, length: {maximum: 200}
|
||||||
|
validates :city, length: {maximum: 200}
|
||||||
|
validates :state, length: {maximum: 200}
|
||||||
|
validates :zip_code, length: {maximum: 200}
|
||||||
|
validates :contact, length: {maximum: 200}
|
||||||
|
validates :email, length: {maximum: 200}
|
||||||
|
validates :phone, length: {maximum: 200}
|
||||||
|
|
||||||
|
has_many :jam_tracks, :class_name => "JamRuby::JamTrack", foreign_key: 'licensor_id'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
module JamRuby
|
||||||
|
|
||||||
|
# describes what users have rights to which tracks
|
||||||
|
class JamTrackRight < ActiveRecord::Base
|
||||||
|
|
||||||
|
belongs_to :user, class_name: "JamRuby::User" # the owner, or purchaser of the jam_track
|
||||||
|
belongs_to :jam_track, class_name: "JamRuby::JamTrack"
|
||||||
|
|
||||||
|
validates :user, presence:true
|
||||||
|
validates :jam_track, presence:true
|
||||||
|
|
||||||
|
validates_uniqueness_of :user_id, scope: :jam_track_id
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
module JamRuby
|
||||||
|
|
||||||
|
# describes an audio track (like the drums, or guitar) that comprises a JamTrack
|
||||||
|
class JamTrackTrack < ActiveRecord::Base
|
||||||
|
include JamRuby::S3ManagerMixin
|
||||||
|
|
||||||
|
# there should only be one Master per JamTrack, but there can be N Track per JamTrack
|
||||||
|
TRACK_TYPE = %w{Master Track}
|
||||||
|
|
||||||
|
mount_uploader :url, JamTrackTrackUploader
|
||||||
|
|
||||||
|
attr_accessible :track_type, :instrument, :instrument_id, :position, :part, :url, as: :admin
|
||||||
|
|
||||||
|
validates :position, presence: true, numericality: {only_integer: true}, length: {in: 1..1000}
|
||||||
|
validates :part, length: {maximum: 20}
|
||||||
|
validates :track_type, inclusion: {in: TRACK_TYPE }
|
||||||
|
validates_uniqueness_of :position, scope: :jam_track_id
|
||||||
|
validates_uniqueness_of :part, scope: :jam_track_id
|
||||||
|
# validates :jam_track, presence: true
|
||||||
|
|
||||||
|
belongs_to :instrument, class_name: "JamRuby::Instrument"
|
||||||
|
belongs_to :jam_track, class_name: "JamRuby::JamTrack"
|
||||||
|
|
||||||
|
# create storage directory that will house this jam_track, as well as
|
||||||
|
def store_dir
|
||||||
|
"#{jam_track.store_dir}/tracks"
|
||||||
|
end
|
||||||
|
|
||||||
|
# create name of the file
|
||||||
|
def filename
|
||||||
|
track_type == 'Master' ? 'master.ogg' : "#{part}.ogg"
|
||||||
|
end
|
||||||
|
|
||||||
|
# creates a short-lived URL that has access to the object.
|
||||||
|
# the idea is that this is used when a user who has the rights to this tries to download this JamTrack
|
||||||
|
# we would verify their rights (can_download?), and generates a URL in response to the click so that they can download
|
||||||
|
# but the url is short lived enough so that it wouldn't be easily shared
|
||||||
|
def sign_url(expiration_time = 120)
|
||||||
|
s3_manager.sign_url(self[:url], {:expires => expiration_time, :response_content_type => 'audio/ogg', :secure => false})
|
||||||
|
end
|
||||||
|
|
||||||
|
def can_download?(user)
|
||||||
|
# I think we have to make a special case for 'previews', but maybe that's just up to the controller to not check can_download?
|
||||||
|
jam_track.owners.include?(user)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -16,6 +16,7 @@ module JamRuby
|
||||||
attr_writer :is_skip_mount_uploader
|
attr_writer :is_skip_mount_uploader
|
||||||
|
|
||||||
attr_accessible :discard, :user, :user_id, :instrument_id, :sound, :client_id, :track_id, :client_track_id, :url, as: :admin
|
attr_accessible :discard, :user, :user_id, :instrument_id, :sound, :client_id, :track_id, :client_track_id, :url, as: :admin
|
||||||
|
|
||||||
attr_writer :current_user
|
attr_writer :current_user
|
||||||
|
|
||||||
SOUND = %w(mono stereo)
|
SOUND = %w(mono stereo)
|
||||||
|
|
|
||||||
|
|
@ -90,6 +90,7 @@ module JamRuby
|
||||||
PARAM_MUSICIAN = :srch_m
|
PARAM_MUSICIAN = :srch_m
|
||||||
PARAM_BAND = :srch_b
|
PARAM_BAND = :srch_b
|
||||||
PARAM_FEED = :srch_f
|
PARAM_FEED = :srch_f
|
||||||
|
PARAM_JAMTRACK = :srch_j
|
||||||
|
|
||||||
F_PER_PAGE = B_PER_PAGE = M_PER_PAGE = 20
|
F_PER_PAGE = B_PER_PAGE = M_PER_PAGE = 20
|
||||||
M_MILES_DEFAULT = 500
|
M_MILES_DEFAULT = 500
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
module JamRuby
|
||||||
|
class ShoppingCart < ActiveRecord::Base
|
||||||
|
|
||||||
|
attr_accessible :quantity, :cart_type, :product_info
|
||||||
|
|
||||||
|
belongs_to :user, :inverse_of => :shopping_carts, :class_name => "JamRuby::User", :foreign_key => "user_id"
|
||||||
|
|
||||||
|
validates :cart_id, presence: true
|
||||||
|
validates :cart_type, presence: true
|
||||||
|
validates :cart_class_name, presence: true
|
||||||
|
|
||||||
|
default_scope order('created_at DESC')
|
||||||
|
|
||||||
|
def product_info
|
||||||
|
product = self.cart_product
|
||||||
|
{name: product.name, price: product.price} unless product.nil?
|
||||||
|
end
|
||||||
|
|
||||||
|
def cart_product
|
||||||
|
self.cart_class_name.classify.constantize.find_by_id self.cart_id unless self.cart_class_name.blank?
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.create user, product, quantity = 1
|
||||||
|
cart = ShoppingCart.new
|
||||||
|
cart.user = user
|
||||||
|
cart.cart_type = product.class::PRODUCT_TYPE
|
||||||
|
cart.cart_class_name = product.class.name
|
||||||
|
cart.cart_id = product.id
|
||||||
|
cart.quantity = quantity
|
||||||
|
cart.save
|
||||||
|
cart
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -121,6 +121,13 @@ module JamRuby
|
||||||
# diagnostics
|
# diagnostics
|
||||||
has_many :diagnostics, :class_name => "JamRuby::Diagnostic"
|
has_many :diagnostics, :class_name => "JamRuby::Diagnostic"
|
||||||
|
|
||||||
|
# jam_tracks
|
||||||
|
has_many :jam_track_rights, :class_name => "JamRuby::JamTrackRight", :foreign_key => "user_id"
|
||||||
|
has_many :purchased_jam_tracks, :through => :jam_track_rights, :class_name => "JamRuby::JamTrack", :source => :jam_track, :order => :created_at
|
||||||
|
|
||||||
|
# Shopping carts
|
||||||
|
has_many :shopping_carts, :class_name => "JamRuby::ShoppingCart"
|
||||||
|
|
||||||
# score history
|
# score history
|
||||||
has_many :from_score_histories, :class_name => "JamRuby::ScoreHistory", foreign_key: 'from_user_id'
|
has_many :from_score_histories, :class_name => "JamRuby::ScoreHistory", foreign_key: 'from_user_id'
|
||||||
has_many :to_score_histories, :class_name => "JamRuby::ScoreHistory", foreign_key: 'to_user_id'
|
has_many :to_score_histories, :class_name => "JamRuby::ScoreHistory", foreign_key: 'to_user_id'
|
||||||
|
|
|
||||||
|
|
@ -650,4 +650,54 @@ FactoryGirl.define do
|
||||||
factory :max_mind_release, :class => JamRuby::MaxMindRelease do
|
factory :max_mind_release, :class => JamRuby::MaxMindRelease do
|
||||||
released_at Time.now.to_date
|
released_at Time.now.to_date
|
||||||
end
|
end
|
||||||
|
|
||||||
|
factory :jam_track_licensor, :class => JamRuby::JamTrackLicensor do
|
||||||
|
sequence(:name) { |n| "licensor-#{n}" }
|
||||||
|
sequence(:description) { |n| "description-#{n}" }
|
||||||
|
sequence(:attention) { |n| "attention-#{n}" }
|
||||||
|
sequence(:address_line_1) { |n| "address1-#{n}" }
|
||||||
|
sequence(:address_line_2) { |n| "address2-#{n}" }
|
||||||
|
sequence(:city) { |n| "city-#{n}" }
|
||||||
|
sequence(:state) { |n| "state-#{n}" }
|
||||||
|
sequence(:zip_code) { |n| "zipcode-#{n}" }
|
||||||
|
sequence(:contact) { |n| "contact-#{n}" }
|
||||||
|
sequence(:email) { |n| "email-#{n}" }
|
||||||
|
sequence(:phone) { |n| "phone-#{n}" }
|
||||||
|
end
|
||||||
|
|
||||||
|
factory :jam_track, :class => JamRuby::JamTrack do
|
||||||
|
sequence(:name) { |n| "jam-track-#{n}" }
|
||||||
|
sequence(:description) { |n| "description-#{n}" }
|
||||||
|
bpm 100.1
|
||||||
|
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}" }
|
||||||
|
pro 'ASCAP'
|
||||||
|
sales_region 'United States'
|
||||||
|
price 1.99
|
||||||
|
reproduction_royalty true
|
||||||
|
public_performance_royalty true
|
||||||
|
reproduction_royalty_amount 0.999
|
||||||
|
licensor_royalty_amount 0.999
|
||||||
|
pro_royalty_amount 0.999
|
||||||
|
|
||||||
|
genre JamRuby::Genre.first
|
||||||
|
association :licensor, factory: :jam_track_licensor
|
||||||
|
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
|
||||||
|
end
|
||||||
|
|
||||||
|
factory :jam_track_right, :class => JamRuby::JamTrackRight do
|
||||||
|
association :jam_track, factory: :jam_track
|
||||||
|
association :user, factory: :user
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe JamTrackLicensor do
|
||||||
|
|
||||||
|
it "created" do
|
||||||
|
FactoryGirl.create(:jam_track_licensor)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe JamTrackRight do
|
||||||
|
|
||||||
|
it "created" do
|
||||||
|
jam_track_right = FactoryGirl.create(:jam_track_right)
|
||||||
|
|
||||||
|
user = jam_track_right.user
|
||||||
|
jam_track = jam_track_right.jam_track
|
||||||
|
|
||||||
|
# verify that the user sees this as a purchased jam_track
|
||||||
|
user.purchased_jam_tracks.should == [jam_track]
|
||||||
|
|
||||||
|
# verify that the jam_track sees the user as an owner
|
||||||
|
jam_track.owners.should == [user]
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "validations" do
|
||||||
|
it "one purchase per user/jam_track combo" do
|
||||||
|
user = FactoryGirl.create(:user)
|
||||||
|
jam_track = FactoryGirl.create(:jam_track)
|
||||||
|
|
||||||
|
right_1 = FactoryGirl.create(:jam_track_right, user: user, jam_track: jam_track)
|
||||||
|
right_2 = FactoryGirl.build(:jam_track_right, user: user, jam_track: jam_track)
|
||||||
|
right_2.valid?.should be_false
|
||||||
|
right_2.errors[:user_id].should == ['has already been taken']
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
@ -0,0 +1,138 @@
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
require 'carrierwave/test/matchers'
|
||||||
|
|
||||||
|
describe JamTrack do
|
||||||
|
include CarrierWave::Test::Matchers
|
||||||
|
include UsesTempFiles
|
||||||
|
|
||||||
|
|
||||||
|
it "created" do
|
||||||
|
jam_track = FactoryGirl.create(:jam_track)
|
||||||
|
jam_track.licensor.should_not be_nil
|
||||||
|
jam_track.licensor.jam_tracks.should == [jam_track]
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "validations" do
|
||||||
|
describe "bpm" do
|
||||||
|
it "1" do
|
||||||
|
FactoryGirl.build(:jam_track, bpm: 1).valid?.should be_true
|
||||||
|
end
|
||||||
|
|
||||||
|
it "100" do
|
||||||
|
FactoryGirl.build(:jam_track, bpm: 100).valid?.should be_true
|
||||||
|
end
|
||||||
|
|
||||||
|
it "100.1" do
|
||||||
|
FactoryGirl.build(:jam_track, bpm: 100.1).valid?.should be_true
|
||||||
|
end
|
||||||
|
|
||||||
|
it "100.12" do
|
||||||
|
jam_track = FactoryGirl.build(:jam_track, bpm: 100.12)
|
||||||
|
jam_track.valid?.should be_false
|
||||||
|
jam_track.errors[:bpm].should == ['is invalid']
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "price" do
|
||||||
|
|
||||||
|
it "0.99" do
|
||||||
|
FactoryGirl.build(:jam_track, price: 0.99).valid?.should be_true
|
||||||
|
end
|
||||||
|
|
||||||
|
it "1" do
|
||||||
|
FactoryGirl.build(:jam_track, price: 1).valid?.should be_true
|
||||||
|
end
|
||||||
|
|
||||||
|
it "100" do
|
||||||
|
FactoryGirl.build(:jam_track, price: 100).valid?.should be_true
|
||||||
|
end
|
||||||
|
|
||||||
|
it "100.1" do
|
||||||
|
FactoryGirl.build(:jam_track, price: 100.1).valid?.should be_true
|
||||||
|
end
|
||||||
|
|
||||||
|
it "100.12" do
|
||||||
|
FactoryGirl.build(:jam_track, price: 100.12).valid?.should be_true
|
||||||
|
end
|
||||||
|
|
||||||
|
it "100.123" do
|
||||||
|
jam_track = FactoryGirl.build(:jam_track, price: 100.123)
|
||||||
|
jam_track.valid?.should be_false
|
||||||
|
jam_track.errors[:price].should == ['is invalid']
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "reproduction_royalty_amount" do
|
||||||
|
it "0.99" do
|
||||||
|
FactoryGirl.build(:jam_track, reproduction_royalty_amount: 0.99).valid?.should be_true
|
||||||
|
end
|
||||||
|
|
||||||
|
it "1" do
|
||||||
|
FactoryGirl.build(:jam_track, reproduction_royalty_amount: 1).valid?.should be_true
|
||||||
|
end
|
||||||
|
|
||||||
|
it "100" do
|
||||||
|
FactoryGirl.build(:jam_track, reproduction_royalty_amount: 100).valid?.should be_true
|
||||||
|
end
|
||||||
|
|
||||||
|
it "100.1" do
|
||||||
|
FactoryGirl.build(:jam_track, reproduction_royalty_amount: 100.1).valid?.should be_true
|
||||||
|
end
|
||||||
|
|
||||||
|
it "100.12" do
|
||||||
|
FactoryGirl.build(:jam_track, reproduction_royalty_amount: 100.12).valid?.should be_true
|
||||||
|
end
|
||||||
|
|
||||||
|
it "100.123" do
|
||||||
|
FactoryGirl.build(:jam_track, reproduction_royalty_amount: 100.123).valid?.should be_true
|
||||||
|
end
|
||||||
|
|
||||||
|
it "100.1234" do
|
||||||
|
jam_track = FactoryGirl.build(:jam_track, reproduction_royalty_amount: 100.1234)
|
||||||
|
jam_track.valid?.should be_false
|
||||||
|
jam_track.errors[:reproduction_royalty_amount].should == ['is invalid']
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "upload/download" do
|
||||||
|
JKA_NAME = 'blah.jka'
|
||||||
|
|
||||||
|
in_directory_with_file(JKA_NAME)
|
||||||
|
|
||||||
|
before(:all) do
|
||||||
|
original_storage = JamTrackUploader.storage = :fog
|
||||||
|
end
|
||||||
|
|
||||||
|
after(:all) do
|
||||||
|
JamTrackUploader.storage = @original_storage
|
||||||
|
end
|
||||||
|
|
||||||
|
before(:each) do
|
||||||
|
content_for_file('abc')
|
||||||
|
end
|
||||||
|
|
||||||
|
it "uploads to s3 with correct name, and then downloads via signed URL" do
|
||||||
|
jam_track = FactoryGirl.create(:jam_track)
|
||||||
|
uploader = JamTrackUploader.new(jam_track, :url)
|
||||||
|
uploader.store!(File.open(JKA_NAME)) # uploads file
|
||||||
|
jam_track.save!
|
||||||
|
|
||||||
|
# verify that the uploader stores the correct path
|
||||||
|
jam_track[:url].should == jam_track.store_dir + '/' + jam_track.filename
|
||||||
|
|
||||||
|
# verify it's on S3
|
||||||
|
s3 = S3Manager.new(APP_CONFIG.aws_bucket, APP_CONFIG.aws_access_key_id, APP_CONFIG.aws_secret_access_key)
|
||||||
|
s3.exists?(jam_track[:url]).should be_true
|
||||||
|
s3.length(jam_track[:url]).should == 'abc'.length
|
||||||
|
|
||||||
|
# download it via signed URL, and check contents
|
||||||
|
url = jam_track.sign_url
|
||||||
|
downloaded_contents = open(url).read
|
||||||
|
downloaded_contents.should == 'abc'
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe JamTrackTrack do
|
||||||
|
include CarrierWave::Test::Matchers
|
||||||
|
include UsesTempFiles
|
||||||
|
|
||||||
|
it "created" do
|
||||||
|
jam_track_track = FactoryGirl.create(:jam_track_track)
|
||||||
|
jam_track_track.jam_track.should_not be_nil
|
||||||
|
jam_track_track.jam_track.jam_track_tracks.should == [jam_track_track]
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "validations" do
|
||||||
|
it "position" do
|
||||||
|
jam_track = FactoryGirl.create(:jam_track)
|
||||||
|
jam_track_track_1 = FactoryGirl.create(:jam_track_track, position: 1, jam_track: jam_track)
|
||||||
|
jam_track_track_2 = FactoryGirl.build(:jam_track_track, position: 1, jam_track: jam_track)
|
||||||
|
jam_track_track_2.valid?.should == false
|
||||||
|
jam_track_track_2.errors[:position].should == ['has already been taken']
|
||||||
|
end
|
||||||
|
|
||||||
|
it "jam_track required" do
|
||||||
|
pending "Need to be not mandatory because of activeadmin"
|
||||||
|
jam_track = FactoryGirl.build(:jam_track_track, jam_track: nil)
|
||||||
|
jam_track.valid?.should be_false
|
||||||
|
jam_track.errors[:jam_track].should == ["can't be blank"]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
describe "upload/download" do
|
||||||
|
TRACK_NAME = 'lead guitar.ogg'
|
||||||
|
|
||||||
|
in_directory_with_file(TRACK_NAME)
|
||||||
|
|
||||||
|
before(:all) do
|
||||||
|
original_storage = JamTrackTrackUploader.storage = :fog
|
||||||
|
end
|
||||||
|
|
||||||
|
after(:all) do
|
||||||
|
JamTrackTrackUploader.storage = @original_storage
|
||||||
|
end
|
||||||
|
|
||||||
|
before(:each) do
|
||||||
|
content_for_file('abc')
|
||||||
|
end
|
||||||
|
|
||||||
|
it "uploads to s3 with correct name, and then downloads via signed URL" do
|
||||||
|
jam_track_track = FactoryGirl.create(:jam_track_track)
|
||||||
|
uploader = JamTrackTrackUploader.new(jam_track_track, :url)
|
||||||
|
uploader.store!(File.open(TRACK_NAME)) # uploads file
|
||||||
|
jam_track_track.save!
|
||||||
|
|
||||||
|
# verify that the uploader stores the correct path
|
||||||
|
jam_track_track[:url].should == jam_track_track.store_dir + '/' + jam_track_track.filename
|
||||||
|
|
||||||
|
# verify it's on S3
|
||||||
|
s3 = S3Manager.new(APP_CONFIG.aws_bucket, APP_CONFIG.aws_access_key_id, APP_CONFIG.aws_secret_access_key)
|
||||||
|
s3.exists?(jam_track_track[:url]).should be_true
|
||||||
|
s3.length(jam_track_track[:url]).should == 'abc'.length
|
||||||
|
|
||||||
|
# download it via signed URL, and check contents
|
||||||
|
url = jam_track_track.sign_url
|
||||||
|
downloaded_contents = open(url).read
|
||||||
|
downloaded_contents.should == 'abc'
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe ShoppingCart do
|
||||||
|
|
||||||
|
let(:user) { FactoryGirl.create(:user) }
|
||||||
|
let(:jam_track) {FactoryGirl.create(:jam_track) }
|
||||||
|
|
||||||
|
before(:each) do
|
||||||
|
ShoppingCart.delete_all
|
||||||
|
end
|
||||||
|
|
||||||
|
it "can reference a shopping cart" do
|
||||||
|
shopping_cart = ShoppingCart.create user, jam_track, 1
|
||||||
|
|
||||||
|
ShoppingCart.count.should == 1
|
||||||
|
user.shopping_carts.count.should == 1
|
||||||
|
user.shopping_carts[0].product_info[:name].should == jam_track.name
|
||||||
|
user.shopping_carts[0].product_info[:price].should == jam_track.price
|
||||||
|
user.shopping_carts[0].cart_type.should == jam_track.class::PRODUCT_TYPE
|
||||||
|
user.shopping_carts[0].quantity.should == 1
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
@ -5,9 +5,9 @@ require 'fileutils'
|
||||||
describe UnusedMusicNotationCleaner do
|
describe UnusedMusicNotationCleaner do
|
||||||
include UsesTempFiles
|
include UsesTempFiles
|
||||||
|
|
||||||
NOTATION_TEMP_FILE='detail.png'
|
UNUSED_NOTATION_TEMP_FILE='detail.png'
|
||||||
|
|
||||||
in_directory_with_file(NOTATION_TEMP_FILE)
|
in_directory_with_file(UNUSED_NOTATION_TEMP_FILE)
|
||||||
|
|
||||||
before do
|
before do
|
||||||
content_for_file("this is music notation test file")
|
content_for_file("this is music notation test file")
|
||||||
|
|
@ -30,7 +30,8 @@ describe UnusedMusicNotationCleaner do
|
||||||
|
|
||||||
it "find no music notataions if music_session_id is nil and created at 1 hour ago" do
|
it "find no music notataions if music_session_id is nil and created at 1 hour ago" do
|
||||||
notation = MusicNotation.new
|
notation = MusicNotation.new
|
||||||
notation.file_url = File.open(NOTATION_TEMP_FILE)
|
|
||||||
|
notation.file_url = File.open(UNUSED_NOTATION_TEMP_FILE)
|
||||||
notation.size = 10
|
notation.size = 10
|
||||||
notation.user = FactoryGirl.create(:user)
|
notation.user = FactoryGirl.create(:user)
|
||||||
notation.created_at = Time.now - 1.hours
|
notation.created_at = Time.now - 1.hours
|
||||||
|
|
@ -44,7 +45,7 @@ describe UnusedMusicNotationCleaner do
|
||||||
music_session = FactoryGirl.create(:music_session, :session_removed_at => Time.now - 1.hours)
|
music_session = FactoryGirl.create(:music_session, :session_removed_at => Time.now - 1.hours)
|
||||||
|
|
||||||
notation = MusicNotation.new
|
notation = MusicNotation.new
|
||||||
notation.file_url = File.open(NOTATION_TEMP_FILE)
|
notation.file_url = File.open(UNUSED_NOTATION_TEMP_FILE)
|
||||||
notation.size = 10
|
notation.size = 10
|
||||||
notation.user = FactoryGirl.create(:user)
|
notation.user = FactoryGirl.create(:user)
|
||||||
notation.created_at = Time.now - 1.hours
|
notation.created_at = Time.now - 1.hours
|
||||||
|
|
@ -56,7 +57,7 @@ describe UnusedMusicNotationCleaner do
|
||||||
|
|
||||||
it "find music notataions if music_session_id is nil and created at 2 days ago" do
|
it "find music notataions if music_session_id is nil and created at 2 days ago" do
|
||||||
notation = MusicNotation.new
|
notation = MusicNotation.new
|
||||||
notation.file_url = File.open(NOTATION_TEMP_FILE)
|
notation.file_url = File.open(UNUSED_NOTATION_TEMP_FILE)
|
||||||
notation.size = 10
|
notation.size = 10
|
||||||
notation.user = FactoryGirl.create(:user)
|
notation.user = FactoryGirl.create(:user)
|
||||||
notation.created_at = Time.now - 2.days
|
notation.created_at = Time.now - 2.days
|
||||||
|
|
@ -70,7 +71,7 @@ describe UnusedMusicNotationCleaner do
|
||||||
music_session = FactoryGirl.create(:music_session, :session_removed_at => Time.now - 2.days)
|
music_session = FactoryGirl.create(:music_session, :session_removed_at => Time.now - 2.days)
|
||||||
|
|
||||||
notation = MusicNotation.new
|
notation = MusicNotation.new
|
||||||
notation.file_url = File.open(NOTATION_TEMP_FILE)
|
notation.file_url = File.open(UNUSED_NOTATION_TEMP_FILE)
|
||||||
notation.size = 10
|
notation.size = 10
|
||||||
notation.user = FactoryGirl.create(:user)
|
notation.user = FactoryGirl.create(:user)
|
||||||
notation.created_at = Time.now - 3.days
|
notation.created_at = Time.now - 3.days
|
||||||
|
|
|
||||||
|
|
@ -83,6 +83,7 @@ gem 'rubyzip'
|
||||||
gem 'slim'
|
gem 'slim'
|
||||||
gem 'htmlentities'
|
gem 'htmlentities'
|
||||||
gem 'sanitize'
|
gem 'sanitize'
|
||||||
|
gem 'recurly'
|
||||||
|
|
||||||
group :development, :test do
|
group :development, :test do
|
||||||
gem 'rspec-rails', '2.14.2'
|
gem 'rspec-rails', '2.14.2'
|
||||||
|
|
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 2.7 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.8 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.8 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 779 B |
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 7.2 KiB |
|
|
@ -0,0 +1,106 @@
|
||||||
|
(function(context,$) {
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
context.JK = context.JK || {};
|
||||||
|
context.JK.CheckoutSignInScreen = function(app) {
|
||||||
|
|
||||||
|
var logger = context.JK.logger;
|
||||||
|
|
||||||
|
var $screen = null;
|
||||||
|
var $navigation = null;
|
||||||
|
var $signinForm = null;
|
||||||
|
var $self = $(this);
|
||||||
|
var $email = null;
|
||||||
|
var $password = null;
|
||||||
|
var $signinBtn = null;
|
||||||
|
var $signupBtn = null;
|
||||||
|
|
||||||
|
function beforeShow(data) {
|
||||||
|
renderNavigation();
|
||||||
|
}
|
||||||
|
|
||||||
|
function afterShow(data) {
|
||||||
|
}
|
||||||
|
|
||||||
|
function events() {
|
||||||
|
$signinBtn.on('click', login);
|
||||||
|
$signupBtn.on('click', signup);
|
||||||
|
}
|
||||||
|
|
||||||
|
function signup(e) {
|
||||||
|
app.layout.showDialog('signup-dialog');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function reset() {
|
||||||
|
$signinForm.removeClass('login-error');
|
||||||
|
|
||||||
|
$email.val('');
|
||||||
|
$password.val('');
|
||||||
|
}
|
||||||
|
|
||||||
|
function login() {
|
||||||
|
var email = $email.val();
|
||||||
|
var password = $password.val();
|
||||||
|
|
||||||
|
reset();
|
||||||
|
|
||||||
|
$signinBtn.text('TRYING...');
|
||||||
|
|
||||||
|
rest.login({email: email, password: password, remember_me: false})
|
||||||
|
.done(function() {
|
||||||
|
window.location = '/client#/order'
|
||||||
|
})
|
||||||
|
.fail(function(jqXHR) {
|
||||||
|
if(jqXHR.status == 422) {
|
||||||
|
$signinForm.addClass('login-error')
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
app.notifyServerError(jqXHR, "Unable to log in")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.always(function() {
|
||||||
|
$signinBtn.text('SIGN IN')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderNavigation() {
|
||||||
|
$navigation.html("");
|
||||||
|
|
||||||
|
var navigationHtml = $(
|
||||||
|
context._.template(
|
||||||
|
$('#template-checkout-navigation').html(),
|
||||||
|
{current: 1},
|
||||||
|
{variable: 'data'}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$navigation.append(navigationHtml);
|
||||||
|
}
|
||||||
|
|
||||||
|
function initialize() {
|
||||||
|
var screenBindings = {
|
||||||
|
'beforeShow': beforeShow,
|
||||||
|
'afterShow': afterShow
|
||||||
|
};
|
||||||
|
app.bindScreen('signin', screenBindings);
|
||||||
|
|
||||||
|
$screen = $("#signInScreen");
|
||||||
|
$navigation = $screen.find(".checkout-navigation-bar");
|
||||||
|
$signinForm = $screen.find(".signin-form");
|
||||||
|
$signinBtn = $signinForm.find('.signin-submit');
|
||||||
|
$email = $signinForm.find('input[name="session[email]"]');
|
||||||
|
$password = $signinForm.find('input[name="session[password]"]');
|
||||||
|
$signupBtn = $signinForm.find('.show-signup-dialog');
|
||||||
|
|
||||||
|
if($screen.length == 0) throw "$screen must be specified";
|
||||||
|
if($navigation.length == 0) throw "$navigation must be specified";
|
||||||
|
|
||||||
|
events();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.initialize = initialize;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
})(window,jQuery);
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
(function(context,$) {
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
context.JK = context.JK || {};
|
||||||
|
context.JK.JamtrackAvailabilityDialog = function(app) {
|
||||||
|
var logger = context.JK.logger;
|
||||||
|
var $dialog = null;
|
||||||
|
var dialogId = 'jamtrack-availability-dialog';
|
||||||
|
|
||||||
|
function beforeShow(data) {
|
||||||
|
}
|
||||||
|
|
||||||
|
function afterShow(data) {
|
||||||
|
}
|
||||||
|
|
||||||
|
function afterHide() {
|
||||||
|
}
|
||||||
|
|
||||||
|
function showDialog() {
|
||||||
|
return app.layout.showDialog(dialogId);
|
||||||
|
}
|
||||||
|
|
||||||
|
function events() {
|
||||||
|
}
|
||||||
|
|
||||||
|
function initialize() {
|
||||||
|
|
||||||
|
var dialogBindings = {
|
||||||
|
'beforeShow' : beforeShow,
|
||||||
|
'afterShow' : afterShow,
|
||||||
|
'afterHide': afterHide
|
||||||
|
};
|
||||||
|
|
||||||
|
app.bindDialog(dialogId, dialogBindings);
|
||||||
|
|
||||||
|
$dialog = $('[layout-id="' + dialogId + '"]');
|
||||||
|
|
||||||
|
events();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.initialize = initialize;
|
||||||
|
this.showDialog = showDialog;
|
||||||
|
};
|
||||||
|
|
||||||
|
return this;
|
||||||
|
})(window,jQuery);
|
||||||
|
|
@ -238,6 +238,10 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function cancelRsvpRequest(sessionId, rsvpRequestId, cancelAll) {
|
function cancelRsvpRequest(sessionId, rsvpRequestId, cancelAll) {
|
||||||
|
var cancel = "yes";
|
||||||
|
if (cancelAll) {
|
||||||
|
cancel = "all";
|
||||||
|
}
|
||||||
return $.ajax({
|
return $.ajax({
|
||||||
url: '/api/rsvp_requests/' + rsvpRequestId,
|
url: '/api/rsvp_requests/' + rsvpRequestId,
|
||||||
type: "DELETE",
|
type: "DELETE",
|
||||||
|
|
@ -939,7 +943,11 @@
|
||||||
dataType: "json",
|
dataType: "json",
|
||||||
contentType: 'application/json',
|
contentType: 'application/json',
|
||||||
url: "/api/users/progression/certified_gear",
|
url: "/api/users/progression/certified_gear",
|
||||||
data: JSON.stringify(options)
|
processData: false,
|
||||||
|
data: JSON.stringify({
|
||||||
|
success: options.success,
|
||||||
|
reason: options.reason
|
||||||
|
})
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1248,6 +1256,98 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateAudioLatency(options) {
|
||||||
|
var id = getId(options);
|
||||||
|
return $.ajax({
|
||||||
|
type: "POST",
|
||||||
|
url: '/api/users/' + id + '/audio_latency',
|
||||||
|
dataType: "json",
|
||||||
|
contentType: 'application/json',
|
||||||
|
data: options,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function getJamtracks(options) {
|
||||||
|
return $.ajax({
|
||||||
|
type: "GET",
|
||||||
|
url: '/api/jamtracks?' + $.param(options),
|
||||||
|
dataType: "json",
|
||||||
|
contentType: 'application/json'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function addJamtrackToShoppingCart(options) {
|
||||||
|
return $.ajax({
|
||||||
|
type: "POST",
|
||||||
|
url: '/api/shopping_carts/add_jamtrack?' + $.param(options),
|
||||||
|
dataType: "json",
|
||||||
|
contentType: 'applications/json'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function getShoppingCarts() {
|
||||||
|
return $.ajax({
|
||||||
|
type: "GET",
|
||||||
|
url: '/api/shopping_carts',
|
||||||
|
dataType: "json",
|
||||||
|
contentType: 'application/json'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeShoppingCart(options) {
|
||||||
|
return $.ajax({
|
||||||
|
type: "DELETE",
|
||||||
|
url: '/api/shopping_carts?' + $.param(options),
|
||||||
|
dataType: "json",
|
||||||
|
contentType: 'application/json'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRecurlyAccount() {
|
||||||
|
return $.ajax({
|
||||||
|
type: "GET",
|
||||||
|
url: '/api/recurly/get_account',
|
||||||
|
dataType: "json",
|
||||||
|
contentType: 'application/json'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function createRecurlyAccount(options) {
|
||||||
|
return $.ajax({
|
||||||
|
type: "POST",
|
||||||
|
url: '/api/recurly/create_account?' + $.param(options),
|
||||||
|
dataType: "json",
|
||||||
|
contentType: 'application/json'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function getBillingInfo() {
|
||||||
|
return $.ajax({
|
||||||
|
type: "GET",
|
||||||
|
url: '/api/recurly/billing_info',
|
||||||
|
dataType: "json",
|
||||||
|
contentType: 'application/json'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateBillingInfo(options) {
|
||||||
|
return $.ajax({
|
||||||
|
type: "PUT",
|
||||||
|
url: '/api/recurly/update_billing_info?' + $.param(options),
|
||||||
|
dataType: "json",
|
||||||
|
contentType: 'application/json'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function placeOrder(options) {
|
||||||
|
return $.ajax({
|
||||||
|
type: "PUT",
|
||||||
|
url: '/api/recurly/place_order?' + $.param(options),
|
||||||
|
dataType: "json",
|
||||||
|
contentType: 'application/json'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function searchMusicians(query) {
|
function searchMusicians(query) {
|
||||||
return $.ajax({
|
return $.ajax({
|
||||||
type: "GET",
|
type: "GET",
|
||||||
|
|
@ -1365,6 +1465,16 @@
|
||||||
this.getChatMessages = getChatMessages;
|
this.getChatMessages = getChatMessages;
|
||||||
this.createDiagnostic = createDiagnostic;
|
this.createDiagnostic = createDiagnostic;
|
||||||
this.getLatencyTester = getLatencyTester;
|
this.getLatencyTester = getLatencyTester;
|
||||||
|
this.updateAudioLatency = updateAudioLatency;
|
||||||
|
this.getJamtracks = getJamtracks;
|
||||||
|
this.addJamtrackToShoppingCart = addJamtrackToShoppingCart;
|
||||||
|
this.getShoppingCarts = getShoppingCarts;
|
||||||
|
this.removeShoppingCart = removeShoppingCart;
|
||||||
|
this.getRecurlyAccount = getRecurlyAccount;
|
||||||
|
this.createRecurlyAccount = createRecurlyAccount;
|
||||||
|
this.getBillingInfo = getBillingInfo;
|
||||||
|
this.updateBillingInfo = updateBillingInfo;
|
||||||
|
this.placeOrder = placeOrder;
|
||||||
this.searchMusicians = searchMusicians;
|
this.searchMusicians = searchMusicians;
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,256 @@
|
||||||
|
(function(context,$) {
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
context.JK = context.JK || {};
|
||||||
|
context.JK.JamTrackScreen = function(app) {
|
||||||
|
|
||||||
|
var logger = context.JK.logger;
|
||||||
|
|
||||||
|
var $screen = null;
|
||||||
|
var $content = null;
|
||||||
|
var $scroller = null;
|
||||||
|
var $genre = null;
|
||||||
|
var $instrument = null;
|
||||||
|
var $availability = null;
|
||||||
|
var $nextPager = null;
|
||||||
|
var $noMoreJamtracks = null;
|
||||||
|
|
||||||
|
var currentQuery = defaultQuery();
|
||||||
|
var currentPage = 0;
|
||||||
|
var LIMIT = 10;
|
||||||
|
var next = null;
|
||||||
|
var instrument_logo_map = context.JK.getInstrumentIconMap24();
|
||||||
|
|
||||||
|
function beforeShow(data) {
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
function afterShow(data) {
|
||||||
|
}
|
||||||
|
|
||||||
|
function events() {
|
||||||
|
$genre.on("change", search);
|
||||||
|
$instrument.on("change", search);
|
||||||
|
$availability.on("change", search);
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearResults() {
|
||||||
|
currentPage = 0;
|
||||||
|
$content.empty();
|
||||||
|
$noMoreJamtracks.hide();
|
||||||
|
next = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function refresh() {
|
||||||
|
clearResults();
|
||||||
|
|
||||||
|
currentQuery = buildQuery();
|
||||||
|
rest.getJamtracks(currentQuery)
|
||||||
|
.done(function(response) {
|
||||||
|
handleJamtrackResponse(response);
|
||||||
|
})
|
||||||
|
.fail(function(jqXHR) {
|
||||||
|
app.notifyServerError(jqXHR, 'Jamtrack Unavailable')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function search() {
|
||||||
|
logger.debug("Searching for jamtracks...");
|
||||||
|
refresh();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function defaultQuery() {
|
||||||
|
var query = { limit:LIMIT, page:currentPage};
|
||||||
|
|
||||||
|
if(next) {
|
||||||
|
query.since = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return query;
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildQuery() {
|
||||||
|
currentQuery = defaultQuery();
|
||||||
|
|
||||||
|
// genre filter
|
||||||
|
var genres = $screen.find('#jamtrack_genre').val();
|
||||||
|
if (genres !== undefined) {
|
||||||
|
currentQuery.genre = genres;
|
||||||
|
}
|
||||||
|
|
||||||
|
// instrument filter
|
||||||
|
var instrument = $instrument.val();
|
||||||
|
if (instrument !== undefined) {
|
||||||
|
currentQuery.instrument = instrument;
|
||||||
|
}
|
||||||
|
|
||||||
|
// availability filter
|
||||||
|
var availability = $availability.val();
|
||||||
|
if (availability !== undefined) {
|
||||||
|
currentQuery.availability = availability;
|
||||||
|
}
|
||||||
|
|
||||||
|
return currentQuery;
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleJamtrackResponse(response) {
|
||||||
|
next = response.next;
|
||||||
|
|
||||||
|
renderJamtracks(response);
|
||||||
|
|
||||||
|
if(response.next == null) {
|
||||||
|
// if we less results than asked for, end searching
|
||||||
|
$scroller.infinitescroll('pause');
|
||||||
|
logger.debug("end of jamtracks");
|
||||||
|
|
||||||
|
if(currentPage == 0 && response.jamtracks.length == 0) {
|
||||||
|
$content.append("<div class='no-jamtracks-msg'>There's no jamtracks.</div>") ;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(currentPage > 0) {
|
||||||
|
$noMoreJamtracks.show();
|
||||||
|
// there are bugs with infinitescroll not removing the 'loading'.
|
||||||
|
// it's most noticeable at the end of the list, so whack all such entries
|
||||||
|
$('.infinite-scroll-loader').remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
currentPage++;
|
||||||
|
buildQuery();
|
||||||
|
registerInfiniteScroll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function registerInfiniteScroll() {
|
||||||
|
$scroller.infinitescroll({
|
||||||
|
behavior: 'local',
|
||||||
|
navSelector: '#jamtrackScreen .btn-next-pager',
|
||||||
|
nextSelector: '#jamtrackScreen .btn-next-pager',
|
||||||
|
binder: $scroller,
|
||||||
|
dataType: 'json',
|
||||||
|
appendCallback: false,
|
||||||
|
prefill: false,
|
||||||
|
bufferPx: 100,
|
||||||
|
loading: {
|
||||||
|
msg: $('<div class="infinite-scroll-loader">Loading ...</div>'),
|
||||||
|
img: '/assets/shared/spinner.gif'
|
||||||
|
},
|
||||||
|
path: function(page) {
|
||||||
|
return '/api/jamtracks?' + $.param(buildQuery());
|
||||||
|
}
|
||||||
|
},function(json, opts) {
|
||||||
|
handleJamtrackResponse(json);
|
||||||
|
});
|
||||||
|
$scroller.infinitescroll('resume');
|
||||||
|
}
|
||||||
|
|
||||||
|
function playJamtrack(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
function addToCartJamtrack(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
var params = {id: $(e.target).attr("data-jamtrack-id")};
|
||||||
|
|
||||||
|
rest.addJamtrackToShoppingCart(params)
|
||||||
|
.done(function(response) {
|
||||||
|
context.location = "/client#/shoppingCart";
|
||||||
|
})
|
||||||
|
.fail(app.ajaxError);
|
||||||
|
}
|
||||||
|
|
||||||
|
function licenseUSWhy(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
app.layout.showDialog('jamtrack-availability-dialog');
|
||||||
|
}
|
||||||
|
|
||||||
|
function registerEvents() {
|
||||||
|
$screen.find('.jamtrack-detail-btn').on("click", showJamtrackDescription);
|
||||||
|
$screen.find('.play-button').on('click', playJamtrack);
|
||||||
|
$screen.find('.jamtrack-add-cart').on('click', addToCartJamtrack);
|
||||||
|
$screen.find('.license-us-why').on('click', licenseUSWhy);
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderJamtracks(data) {
|
||||||
|
$.each(data.jamtracks, function(i, jamtrack) {
|
||||||
|
$.each(jamtrack.tracks, function (index, track) {
|
||||||
|
var inst = '../assets/content/icon_instrument_default24.png';
|
||||||
|
if (track.instrument.id in instrument_logo_map) {
|
||||||
|
inst = instrument_logo_map[track.instrument.id].asset;
|
||||||
|
}
|
||||||
|
track.instrument_url = inst;
|
||||||
|
|
||||||
|
track.instrument_desc = track.instrument.description;
|
||||||
|
if (track.part != "") {
|
||||||
|
track.instrument_desc += " ( " + track.part + " )";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var options = {
|
||||||
|
jamtrack: jamtrack
|
||||||
|
};
|
||||||
|
|
||||||
|
var $jamtrackItem = $(
|
||||||
|
context._.template(
|
||||||
|
$('#template-jamtrack').html(),
|
||||||
|
options,
|
||||||
|
{variable: 'data'}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
renderJamtrack($jamtrackItem );
|
||||||
|
});
|
||||||
|
|
||||||
|
registerEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
function showJamtrackDescription(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
var $description = $(e.target).parent(".detail-arrow").next();
|
||||||
|
if ($description.css("display") == "none") {
|
||||||
|
$description.show();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$description.hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderJamtrack(jamtrack) {
|
||||||
|
$content.append(jamtrack);
|
||||||
|
}
|
||||||
|
|
||||||
|
function initialize() {
|
||||||
|
var screenBindings = {
|
||||||
|
'beforeShow': beforeShow,
|
||||||
|
'afterShow': afterShow
|
||||||
|
};
|
||||||
|
app.bindScreen('jamtrack', screenBindings);
|
||||||
|
|
||||||
|
$screen = $("#jamtrack-find-form");
|
||||||
|
$scroller = $screen.find('.content-body-scroller');
|
||||||
|
$content = $screen.find(".jamtrack-content");
|
||||||
|
$genre = $screen.find("#jamtrack_genre");
|
||||||
|
$instrument = $screen.find("#jamtrack_instrument");
|
||||||
|
$availability = $screen.find("#jamtrack_availability");
|
||||||
|
$nextPager = $screen.find("a.btn-next-pager");
|
||||||
|
$noMoreJamtracks = $screen.find("#end-of-jamtrack-list");
|
||||||
|
|
||||||
|
if($screen.length == 0) throw "$screen must be specified";
|
||||||
|
if($scroller.length == 0) throw "$scroller must be specified";
|
||||||
|
if($content.length == 0) throw "$content must be specified";
|
||||||
|
if($noMoreJamtracks.length == 0) throw "$noMoreJamtracks must be specified";
|
||||||
|
if($genre.length == 0) throw "$genre must be specified";
|
||||||
|
if($instrument.length == 0) throw "$instrument must be specified";
|
||||||
|
if($availability.length ==0) throw "$availability must be specified";
|
||||||
|
|
||||||
|
events();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.initialize = initialize;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
})(window,jQuery);
|
||||||
|
|
@ -0,0 +1,511 @@
|
||||||
|
(function(context,$) {
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
context.JK = context.JK || {};
|
||||||
|
context.JK.OrderScreen = function(app) {
|
||||||
|
|
||||||
|
var logger = context.JK.logger;
|
||||||
|
|
||||||
|
var $screen = null;
|
||||||
|
var $navigation = null;
|
||||||
|
var $billingInfo = null;
|
||||||
|
var $shippingInfo = null;
|
||||||
|
var $paymentMethod = null;
|
||||||
|
var $shippingAddress = null;
|
||||||
|
var $shippingAsBilling = null;
|
||||||
|
var $paymentInfoPanel = null;
|
||||||
|
var $orderPanel = null;
|
||||||
|
var $orderContent = null;
|
||||||
|
var userDetail = null;
|
||||||
|
var step = null;
|
||||||
|
var billing_info = null;
|
||||||
|
var shipping_info = null;
|
||||||
|
var shipping_as_billing = null;
|
||||||
|
|
||||||
|
function beforeShow() {
|
||||||
|
beforeShowPaymentInfo();
|
||||||
|
// moveToOrder();
|
||||||
|
}
|
||||||
|
|
||||||
|
function beforeShowPaymentInfo() {
|
||||||
|
step = 2;
|
||||||
|
renderNavigation();
|
||||||
|
renderAccountInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderAccountInfo() {
|
||||||
|
rest.getUserDetail()
|
||||||
|
.done(populateAccountInfo)
|
||||||
|
.error(app.ajaxError);
|
||||||
|
}
|
||||||
|
|
||||||
|
function populateAccountInfo(user) {
|
||||||
|
userDetail = user;
|
||||||
|
|
||||||
|
if (userDetail.has_recurly_account) {
|
||||||
|
rest.getBillingInfo()
|
||||||
|
.done(function(response) {
|
||||||
|
$billingInfo.find("#billing-first-name").val(response.first_name);
|
||||||
|
$billingInfo.find("#billing-last-name").val(response.last_name);
|
||||||
|
$billingInfo.find("#billing-address1").val(response.address1);
|
||||||
|
$billingInfo.find("#billing-address2").val(response.address2);
|
||||||
|
$billingInfo.find("#billing-city").val(response.city);
|
||||||
|
$billingInfo.find("#billing-state").val(response.state);
|
||||||
|
$billingInfo.find("#billing-zip").val(response.zip);
|
||||||
|
$billingInfo.find("#billing-country").val(response.country);
|
||||||
|
|
||||||
|
$shippingAddress.find("#shipping-first-name").val(response.first_name);
|
||||||
|
$shippingAddress.find("#shipping-last-name").val(response.last_name);
|
||||||
|
$shippingAddress.find("#shipping-address1").val(response.address1);
|
||||||
|
$shippingAddress.find("#shipping-address2").val(response.address2);
|
||||||
|
$shippingAddress.find("#shipping-city").val(response.city);
|
||||||
|
$shippingAddress.find("#shipping-state").val(response.state);
|
||||||
|
$shippingAddress.find("#shipping-zip").val(response.zip);
|
||||||
|
$shippingAddress.find("#shipping-country").val(response.country);
|
||||||
|
})
|
||||||
|
.error(app.ajaxError);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$billingInfo.find("#billing-first-name").val(userDetail.first_name);
|
||||||
|
$billingInfo.find("#billing-last-name").val(userDetail.last_name);
|
||||||
|
$billingInfo.find("#billing-city").val(userDetail.city);
|
||||||
|
$billingInfo.find("#billing-state").val(userDetail.state);
|
||||||
|
$billingInfo.find("#billing-country").val(userDetail.country);
|
||||||
|
|
||||||
|
$shippingAddress.find("#shipping-first-name").val(userDetail.first_name);
|
||||||
|
$shippingAddress.find("#shipping-last-name").val(userDetail.last_name);
|
||||||
|
$shippingAddress.find("#shipping-city").val(userDetail.city);
|
||||||
|
$shippingAddress.find("#shipping-state").val(userDetail.state);
|
||||||
|
$shippingAddress.find("#shipping-country").val(userDetail.country);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function afterShow(data) {
|
||||||
|
}
|
||||||
|
|
||||||
|
function next(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
// validation
|
||||||
|
var billing_first_name = $billingInfo.find("#billing-first-name").val();
|
||||||
|
var billing_last_name = $billingInfo.find("#billing-last-name").val();
|
||||||
|
var billing_address1 = $billingInfo.find("#billing-address1").val();
|
||||||
|
var billing_address2 = $billingInfo.find("#billing-address2").val();
|
||||||
|
var billing_city = $billingInfo.find("#billing-city").val();
|
||||||
|
var billing_state = $billingInfo.find("#billing-state").val();
|
||||||
|
var billing_zip = $billingInfo.find("#billing-zip").val();
|
||||||
|
var billing_country = $billingInfo.find("#billing-country").val();
|
||||||
|
|
||||||
|
if (!billing_first_name) {
|
||||||
|
$billingInfo.find('#divBillingFirstName .error-text').remove();
|
||||||
|
$billingInfo.find('#divBillingFirstName').addClass("error");
|
||||||
|
$billingInfo.find('#billing-first-name').after("<ul class='error-text'><li>First Name is required</li></ul>");
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$billingInfo.find('#divBillingFirstName').removeClass("error");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!billing_last_name) {
|
||||||
|
$billingInfo.find('#divBillingLastName .error-text').remove();
|
||||||
|
$billingInfo.find('#divBillingLastName').addClass("error");
|
||||||
|
$billingInfo.find('#billing-last-name').after("<ul class='error-text'><li>Last Name is required</li></ul>");
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$billingInfo.find('#divBillingLastName').removeClass("error");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!billing_address1) {
|
||||||
|
$billingInfo.find('#divBillingAddress1 .error-text').remove();
|
||||||
|
$billingInfo.find('#divBillingAddress1').addClass("error");
|
||||||
|
$billingInfo.find('#billing-address1').after("<ul class='error-text'><li>Address is required</li></ul>");
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$billingInfo.find('#divBillingAddress1').removeClass("error");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!billing_zip) {
|
||||||
|
$billingInfo.find('#divBillingZip .error-text').remove();
|
||||||
|
$billingInfo.find('#divBillingZip').addClass("error");
|
||||||
|
$billingInfo.find('#billing-zip').after("<ul class='error-text'><li>Zip code is required</li></ul>");
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$billingInfo.find('#divBillingZip').removeClass("error");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!billing_state) {
|
||||||
|
$billingInfo.find('#divBillingState .error-text').remove();
|
||||||
|
$billingInfo.find('#divBillingState').addClass("error");
|
||||||
|
$billingInfo.find('#billing-zip').after("<ul class='error-text'><li>State is required</li></ul>");
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$billingInfo.find('#divBillingState').removeClass("error");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!billing_city) {
|
||||||
|
$billingInfo.find('#divBillingCity .error-text').remove();
|
||||||
|
$billingInfo.find('#divBillingCity').addClass("error");
|
||||||
|
$billingInfo.find('#billing-city').after("<ul class='error-text'><li>City is required</li></ul>");
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$billingInfo.find('#divBillingCity').removeClass("error");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!billing_country) {
|
||||||
|
$billingInfo.find('#divBillingCountry .error-text').remove();
|
||||||
|
$billingInfo.find('#divBillingCountry').addClass("error");
|
||||||
|
$billingInfo.find('#billing-country').after("<ul class='error-text'><li>Country is required</li></ul>");
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$billingInfo.find('#divBillingCountry').removeClass("error");
|
||||||
|
}
|
||||||
|
|
||||||
|
shipping_as_billing = $shippingAsBilling.is(":checked");
|
||||||
|
var shipping_first_name, shipping_last_name, shipping_address1, shipping_address2;
|
||||||
|
var shipping_city, shipping_state, shipping_zip, shipping_country;
|
||||||
|
|
||||||
|
if (!shipping_as_billing) {
|
||||||
|
shipping_first_name = $shippingAddress.find("#shipping-first-name").val();
|
||||||
|
shipping_last_name = $shippingAddress.find("#shipping-last-name").val();
|
||||||
|
shipping_address1 = $shippingAddress.find("#shipping-address1").val();
|
||||||
|
shipping_address2 = $shippingAddress.find("#shipping-address2").val();
|
||||||
|
shipping_city = $shippingAddress.find("#shipping-city").val();
|
||||||
|
shipping_state = $shippingAddress.find("#shipping-state").val();
|
||||||
|
shipping_zip = $shippingAddress.find("#shipping-zip").val();
|
||||||
|
shipping_country = $shippingAddress.find("#shipping-country").val();
|
||||||
|
|
||||||
|
if (!shipping_first_name) {
|
||||||
|
$shippingAddress.find('#divShippingFirstName .error-text').remove();
|
||||||
|
$shippingAddress.find('#divShippingFirstName').addClass("error");
|
||||||
|
$shippingAddress.find('#shipping-first-name').after("<ul class='error-text'><li>First Name is required</li></ul>");
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$shippingInfo.find('#divShippingFirstName').removeClass("error");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!shipping_last_name) {
|
||||||
|
$shippingAddress.find('#divShippingLastName .error-text').remove();
|
||||||
|
$shippingAddress.find('#divShippingLastName').addClass("error");
|
||||||
|
$shippingAddress.find('#shipping-last-name').after("<ul class='error-text'><li>Last Name is required</li></ul>");
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$shippingInfo.find('#divShippingLastName').removeClass("error");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!shipping_address1) {
|
||||||
|
$shippingAddress.find('#divShippingAddress1 .error-text').remove();
|
||||||
|
$shippingAddress.find('#divShippingAddress1').addClass("error");
|
||||||
|
$shippingAddress.find('#shipping-address1').after("<ul class='error-text'><li>Address is required</li></ul>");
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$shippingInfo.find('#divShippingAddress1').removeClass("error");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!shipping_zip) {
|
||||||
|
$shippingAddress.find('#divShippingZip .error-text').remove();
|
||||||
|
$shippingAddress.find('#divShippingZip').addClass("error");
|
||||||
|
$shippingAddress.find('#shipping-zip').after("<ul class='error-text'><li>Zip code is required</li></ul>");
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$shippingInfo.find('#divShippingZip').removeClass("error");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!shipping_state) {
|
||||||
|
$shippingAddress.find('#divShippingState .error-text').remove();
|
||||||
|
$shippingAddress.find('#divShippingState').addClass("error");
|
||||||
|
$shippingAddress.find('#shipping-zip').after("<ul class='error-text'><li>State is required</li></ul>");
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$shippingInfo.find('#divShippingState').removeClass("error");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!shipping_city) {
|
||||||
|
$shippingAddress.find('#divShippingCity .error-text').remove();
|
||||||
|
$shippingAddress.find('#divShippingCity').addClass("error");
|
||||||
|
$shippingAddress.find('#shipping-city').after("<ul class='error-text'><li>City is required</li></ul>");
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$shippingInfo.find('#divShippingCity').removeClass("error");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!shipping_country) {
|
||||||
|
$shippingAddress.find('#divShippingCountry .error-text').remove();
|
||||||
|
$shippingAddress.find('#divShippingCountry').addClass("error");
|
||||||
|
$shippingAddress.find('#shipping-country').after("<ul class='error-text'><li>Country is required</li></ul>");
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$shippingAddress.find('#divShippingCountry').removeClass("error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var card_name = $paymentMethod.find("#card-name").val();
|
||||||
|
var card_number = $paymentMethod.find("#card-number").val();
|
||||||
|
var card_year = $paymentMethod.find("#card_expire-date_3i").val();
|
||||||
|
var card_month = $paymentMethod.find("#card_expire-date_2i").val();
|
||||||
|
var card_verify = $paymentMethod.find("#card-verify").val();
|
||||||
|
|
||||||
|
if (!card_name) {
|
||||||
|
$paymentMethod.find('#divCardName .error-text').remove();
|
||||||
|
$paymentMethod.find('#divCardName').addClass("error");
|
||||||
|
$paymentMethod.find('#card-name').after("<ul class='error-text'><li>Card Name is required</li></ul>");
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$paymentMethod.find('#divCardName').removeClass("error");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!card_number) {
|
||||||
|
$paymentMethod.find('#divCardNumber .error-text').remove();
|
||||||
|
$paymentMethod.find('#divCardNumber').addClass("error");
|
||||||
|
$paymentMethod.find('#card-number').after("<ul class='error-text'><li>Card Number is required</li></ul>");
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$paymentMethod.find('#divCardNumber').removeClass("error");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!card_verify) {
|
||||||
|
$paymentMethod.find('#divCardVerify .error-text').remove();
|
||||||
|
$paymentMethod.find('#divCardVerify').addClass("error");
|
||||||
|
$paymentMethod.find('#card_verify').after("<ul class='error-text'><li>Card Verification Value is required</li></ul>");
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$paymentMethod.find('#divCardVerify').removeClass("error");
|
||||||
|
}
|
||||||
|
|
||||||
|
billing_info = {};
|
||||||
|
shipping_info = {};
|
||||||
|
billing_info.first_name = billing_first_name;
|
||||||
|
billing_info.last_name = billing_last_name;
|
||||||
|
billing_info.address1 = billing_address1;
|
||||||
|
billing_info.address2 = billing_address2;
|
||||||
|
billing_info.city = billing_city;
|
||||||
|
billing_info.state = billing_state;
|
||||||
|
billing_info.country = billing_country;
|
||||||
|
billing_info.zip = billing_zip;
|
||||||
|
billing_info.number = card_number;
|
||||||
|
billing_info.month = card_month;
|
||||||
|
billing_info.year = card_year;
|
||||||
|
billing_info.verification_value = card_verify;
|
||||||
|
|
||||||
|
if (shipping_as_billing) {
|
||||||
|
shipping_info = billing_info;
|
||||||
|
delete shipping_info.number;
|
||||||
|
delete shipping_info.month;
|
||||||
|
delete shipping_info.year;
|
||||||
|
delete shipping_info.verification_value;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
shipping_info.first_name = shipping_first_name;
|
||||||
|
shipping_info.last_name = shipping_last_name;
|
||||||
|
shipping_info.address1 = shipping_address1;
|
||||||
|
shipping_info.address2 = shipping_address2;
|
||||||
|
shipping_info.city = shipping_city;
|
||||||
|
shipping_info.state = shipping_state;
|
||||||
|
shipping_info.country = shipping_country;
|
||||||
|
shipping_info.zip = shipping_zip;
|
||||||
|
}
|
||||||
|
|
||||||
|
$paymentInfoPanel.find("#payment-info-next").addClass("disabled");
|
||||||
|
$paymentInfoPanel.find("#payment-info-next").off("click");
|
||||||
|
|
||||||
|
if (userDetail.has_recurly_account) {
|
||||||
|
rest.updateBillingInfo(billing_info)
|
||||||
|
.done(function() {
|
||||||
|
})
|
||||||
|
.fail(errorHandling);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
rest.createRecurlyAccount({billing_info: billing_info})
|
||||||
|
.done(function() {
|
||||||
|
})
|
||||||
|
.fail(errorHandling);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function errorHandling(xhr, ajaxOptions, thrownError) {
|
||||||
|
$.each(xhr.responseJSON.errors, function(key, error) {
|
||||||
|
if (key == 'number') {
|
||||||
|
$paymentMethod.find('#divCardNumber .error-text').remove();
|
||||||
|
$paymentMethod.find('#divCardNumber').addClass("error");
|
||||||
|
$paymentMethod.find('#card-number').after("<ul class='error-text'><li>" + error + "</li></ul>");
|
||||||
|
}
|
||||||
|
else if (key == 'verification_value') {
|
||||||
|
$paymentMethod.find('#divCardVerify .error-text').remove();
|
||||||
|
$paymentMethod.find('#divCardVerify').addClass("error");
|
||||||
|
$paymentMethod.find('#card-verify').after("<ul class='error-text'><li>" + error + "</li></ul>");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$paymentInfoPanel.find("#payment-info-next").removeClass("disabled");
|
||||||
|
$paymentInfoPanel.find("#payment-info-next").on("click", next);
|
||||||
|
// moveToOrder();
|
||||||
|
}
|
||||||
|
|
||||||
|
function beforeShowOrder() {
|
||||||
|
step = 3;
|
||||||
|
renderNavigation();
|
||||||
|
populateOrderPage();
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearOrderPage() {
|
||||||
|
$orderContent.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
function populateOrderPage() {
|
||||||
|
clearOrderPage();
|
||||||
|
|
||||||
|
rest.getShoppingCarts()
|
||||||
|
.done(renderOrderPage)
|
||||||
|
.fail(app.ajaxError);
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderOrderPage(carts) {
|
||||||
|
var data = {};
|
||||||
|
|
||||||
|
var sub_total = 0;
|
||||||
|
$.each(carts, function(index, cart) {
|
||||||
|
sub_total += parseFloat(cart.product_info.price) * parseFloat(cart.quantity);
|
||||||
|
});
|
||||||
|
data.sub_total = sub_total.toFixed(2);
|
||||||
|
data.taxes = 12.01;
|
||||||
|
|
||||||
|
data.carts = carts;
|
||||||
|
data.billing_info = billing_info;
|
||||||
|
data.shipping_info = shipping_info;
|
||||||
|
data.shipping_as_billing = shipping_as_billing;
|
||||||
|
var orderContentHtml = $(
|
||||||
|
context._.template(
|
||||||
|
$('#template-order-content').html(),
|
||||||
|
data,
|
||||||
|
{variable: 'data'}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$orderContent.append(orderContentHtml);
|
||||||
|
|
||||||
|
$orderPanel.find(".change-payment-info").on('click', moveToPaymentInfo);
|
||||||
|
$orderContent.find(".place-order").on('click', placeOrder);
|
||||||
|
}
|
||||||
|
|
||||||
|
function moveToOrder() {
|
||||||
|
$paymentInfoPanel.addClass("hidden");
|
||||||
|
$orderPanel.removeClass("hidden");
|
||||||
|
beforeShowOrder();
|
||||||
|
}
|
||||||
|
|
||||||
|
function moveToPaymentInfo(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
$paymentInfoPanel.removeClass("hidden");
|
||||||
|
$orderPanel.addClass("hidden");
|
||||||
|
beforeShowPaymentInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleShippingAsBilling(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
var shipping_as_billing = $(e.target).is(':checked');
|
||||||
|
|
||||||
|
if (!shipping_as_billing) {
|
||||||
|
$shippingAddress.removeClass("hidden");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$shippingAddress.addClass("hidden");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function placeOrder(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
function events() {
|
||||||
|
$paymentInfoPanel.find("#payment-info-next").on('click', next);
|
||||||
|
$shippingAsBilling.on('ifChanged', toggleShippingAsBilling);
|
||||||
|
}
|
||||||
|
|
||||||
|
function reset() {
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderNavigation() {
|
||||||
|
$navigation.html("");
|
||||||
|
var navigationHtml = $(
|
||||||
|
context._.template(
|
||||||
|
$('#template-checkout-navigation').html(),
|
||||||
|
{current: step},
|
||||||
|
{variable: 'data'}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$navigation.append(navigationHtml);
|
||||||
|
}
|
||||||
|
|
||||||
|
function initializeControls() {
|
||||||
|
$("form.payment-info").iCheck({
|
||||||
|
checkboxClass: 'icheckbox_minimal',
|
||||||
|
radioClass: 'iradio_minimal',
|
||||||
|
inheritClass: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function initialize() {
|
||||||
|
var screenBindings = {
|
||||||
|
'beforeShow': beforeShow,
|
||||||
|
'afterShow': afterShow
|
||||||
|
};
|
||||||
|
app.bindScreen('order', screenBindings);
|
||||||
|
|
||||||
|
$screen = $("#orderScreen");
|
||||||
|
$paymentInfoPanel = $screen.find(".checkout-payment-info");
|
||||||
|
$orderPanel = $screen.find(".order-panel");
|
||||||
|
$navigation = $screen.find(".checkout-navigation-bar");
|
||||||
|
$billingInfo = $paymentInfoPanel.find(".billing-address");
|
||||||
|
$shippingInfo = $paymentInfoPanel.find(".shipping-address");
|
||||||
|
$paymentMethod = $paymentInfoPanel.find(".payment-method");
|
||||||
|
$shippingAddress = $paymentInfoPanel.find(".shipping-address-detail");
|
||||||
|
$shippingAsBilling = $paymentInfoPanel.find("#shipping-as-billing");
|
||||||
|
$orderContent = $orderPanel.find(".order-content");
|
||||||
|
|
||||||
|
if($screen.length == 0) throw "$screen must be specified";
|
||||||
|
if($navigation.length == 0) throw "$navigation must be specified";
|
||||||
|
|
||||||
|
initializeControls();
|
||||||
|
|
||||||
|
events();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.initialize = initialize;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
})(window,jQuery);
|
||||||
|
|
@ -862,7 +862,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function onEditSessions(event) {
|
function onEditSessions(event) {
|
||||||
window.location = "/client#/account/sessions"
|
window.location = "/client#/account/sessions";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,112 @@
|
||||||
|
(function(context,$) {
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
context.JK = context.JK || {};
|
||||||
|
context.JK.ShoppingCartScreen = function(app) {
|
||||||
|
|
||||||
|
var logger = context.JK.logger;
|
||||||
|
|
||||||
|
var $screen = null;
|
||||||
|
var $content = null;
|
||||||
|
|
||||||
|
function beforeShow(data) {
|
||||||
|
loadShoppingCarts();
|
||||||
|
}
|
||||||
|
|
||||||
|
function afterShow(data) {
|
||||||
|
}
|
||||||
|
|
||||||
|
function events() {
|
||||||
|
$screen.find("a.remove-cart").on('click', removeCart);
|
||||||
|
$screen.find("a.proceed-checkout").on('click', proceedCheckout);
|
||||||
|
}
|
||||||
|
|
||||||
|
function proceedCheckout(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
if (!context.JK.currentUserId) {
|
||||||
|
window.location = '/client#/signin';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
window.location = '/client#/order';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeCart(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
var options = {};
|
||||||
|
options.id = $(e.target).attr("cart-id");
|
||||||
|
|
||||||
|
rest.removeShoppingCart(options)
|
||||||
|
.done(loadShoppingCarts)
|
||||||
|
.fail(app.ajaxError);
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearContent() {
|
||||||
|
$content.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadShoppingCarts() {
|
||||||
|
clearContent();
|
||||||
|
|
||||||
|
rest.getShoppingCarts()
|
||||||
|
.done(renderShoppingCarts)
|
||||||
|
.fail(app.ajaxError);
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderShoppingCarts(carts) {
|
||||||
|
var data = {};
|
||||||
|
var latest_cart = carts[carts.length - 1];
|
||||||
|
|
||||||
|
var $latestCartHtml = "";
|
||||||
|
|
||||||
|
if (latest_cart) {
|
||||||
|
$latestCartHtml = $(
|
||||||
|
context._.template(
|
||||||
|
$('#template-shopping-cart-header').html(),
|
||||||
|
latest_cart,
|
||||||
|
{variable: 'data'}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
var sub_total = 0;
|
||||||
|
$.each(carts, function(index, cart) {
|
||||||
|
sub_total += parseFloat(cart.product_info.price) * parseFloat(cart.quantity);
|
||||||
|
});
|
||||||
|
data.sub_total = sub_total.toFixed(2);
|
||||||
|
|
||||||
|
data.carts = carts;
|
||||||
|
var $cartsHtml = $(
|
||||||
|
context._.template(
|
||||||
|
$('#template-shopping-cart-body').html(),
|
||||||
|
data,
|
||||||
|
{variable: 'data'}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$content.append($latestCartHtml).append($cartsHtml);
|
||||||
|
|
||||||
|
events();
|
||||||
|
}
|
||||||
|
|
||||||
|
function initialize() {
|
||||||
|
var screenBindings = {
|
||||||
|
'beforeShow': beforeShow,
|
||||||
|
'afterShow': afterShow
|
||||||
|
};
|
||||||
|
app.bindScreen('shoppingCart', screenBindings);
|
||||||
|
|
||||||
|
$screen = $("#shoppingCartScreen");
|
||||||
|
$content = $screen.find(".shopping-cart-content");
|
||||||
|
|
||||||
|
if($screen.length == 0) throw "$screen must be specified";
|
||||||
|
if($content.length == 0) throw "$content must be specified";
|
||||||
|
}
|
||||||
|
|
||||||
|
this.initialize = initialize;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
})(window,jQuery);
|
||||||
|
|
@ -19,10 +19,9 @@
|
||||||
var $password = null;
|
var $password = null;
|
||||||
var $rememberMe = null;
|
var $rememberMe = null;
|
||||||
var useAjax = false;
|
var useAjax = false;
|
||||||
var EVENTS = context.JK.EVENTS;
|
|
||||||
|
|
||||||
function reset() {
|
function reset() {
|
||||||
$signinForm.removeClass('login-error')
|
$signinForm.removeClass('login-error');
|
||||||
|
|
||||||
$email.val('');
|
$email.val('');
|
||||||
$password.val('');
|
$password.val('');
|
||||||
|
|
@ -32,7 +31,6 @@
|
||||||
function login() {
|
function login() {
|
||||||
var email = $email.val();
|
var email = $email.val();
|
||||||
var password = $password.val();
|
var password = $password.val();
|
||||||
var rememberMe = $rememberMe.is(':checked')
|
|
||||||
|
|
||||||
reset();
|
reset();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,252 @@
|
||||||
|
.checkout-navigation {
|
||||||
|
padding: 20px 0px;
|
||||||
|
.nav-signin, .nav-payment-info, .nav-place-order {
|
||||||
|
width: 30%;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-signin {
|
||||||
|
margin-left: 5%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-place-order {
|
||||||
|
margin-right: 5%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-text {
|
||||||
|
font-size: 17px;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-text.selected {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-arrow {
|
||||||
|
float: left;
|
||||||
|
margin-left: 30px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkout-signin, .checkout-payment-info, .checkout-place-order {
|
||||||
|
padding: 30px;
|
||||||
|
|
||||||
|
.signin-form {
|
||||||
|
padding: 10px;
|
||||||
|
|
||||||
|
strong {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.signin-password {
|
||||||
|
margin-left: 33px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-error {
|
||||||
|
background-color: #330000;
|
||||||
|
border: 1px solid #990000;
|
||||||
|
padding:4px;
|
||||||
|
|
||||||
|
div.actions {
|
||||||
|
margin-top:10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-error-msg {
|
||||||
|
display:none;
|
||||||
|
margin-top:10px;
|
||||||
|
text-align:center;
|
||||||
|
color:#F00;
|
||||||
|
font-size:11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-error .login-error-msg {
|
||||||
|
display:block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
form.payment-info {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
input[type="text"] {
|
||||||
|
width: 90%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.billing-address {
|
||||||
|
float: left;
|
||||||
|
width: 50%;
|
||||||
|
|
||||||
|
h2.billing-caption {
|
||||||
|
margin: 20px 5px;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.billing-label {
|
||||||
|
padding-top: 8px;
|
||||||
|
width: 30%;
|
||||||
|
float: left;
|
||||||
|
text-align: right;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.billing-value {
|
||||||
|
width: 65%;
|
||||||
|
text-align: left;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.payment-method {
|
||||||
|
float: left;
|
||||||
|
width: 50%;
|
||||||
|
|
||||||
|
h2.payment-method-caption {
|
||||||
|
margin: 20px 5px;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-label {
|
||||||
|
padding-top: 8px;
|
||||||
|
width: 35%;
|
||||||
|
float: left;
|
||||||
|
text-align: right;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-value {
|
||||||
|
width: 60%;
|
||||||
|
text-align: left;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.save-card-checkbox {
|
||||||
|
float:left;
|
||||||
|
display:block;
|
||||||
|
margin-right:5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.shipping-address {
|
||||||
|
float: left;
|
||||||
|
width: 50%;
|
||||||
|
|
||||||
|
h2.shipping-address-label {
|
||||||
|
margin: 20px 5px;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shipping-as-billing {
|
||||||
|
float:left;
|
||||||
|
display:block;
|
||||||
|
margin-right:5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.divBillingHelper {
|
||||||
|
padding-top: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shipping-label {
|
||||||
|
padding-top: 8px;
|
||||||
|
width: 30%;
|
||||||
|
float: left;
|
||||||
|
text-align: right;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shipping-value {
|
||||||
|
width: 65%;
|
||||||
|
text-align: left;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.order-panel {
|
||||||
|
padding: 30px;
|
||||||
|
|
||||||
|
.order-header {
|
||||||
|
h2 {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.order-content {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.order-left-page {
|
||||||
|
float: left;
|
||||||
|
width: 60%;
|
||||||
|
|
||||||
|
.payment-info-page {
|
||||||
|
padding: 5px;
|
||||||
|
|
||||||
|
.info-caption-link {
|
||||||
|
.caption-text {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
.caption-link {
|
||||||
|
float: left;
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.address-info {
|
||||||
|
width: 50%;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.payment-method-info {
|
||||||
|
width: 50%;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.order-items-page {
|
||||||
|
padding: 5px;
|
||||||
|
|
||||||
|
.cart-item-caption {
|
||||||
|
width: 50%;
|
||||||
|
text-align: left;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cart-item-caption#header {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cart-item-price {
|
||||||
|
width: 25%;
|
||||||
|
text-align: right;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cart-item-quantity {
|
||||||
|
width: 25%;
|
||||||
|
text-align: right;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cart-items {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cart-item {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.order-right-page {
|
||||||
|
float: right;
|
||||||
|
width: 35%;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
.order-total {
|
||||||
|
color: #ed3618;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -48,6 +48,9 @@
|
||||||
*= require ./terms
|
*= require ./terms
|
||||||
*= require ./createSession
|
*= require ./createSession
|
||||||
*= require ./feed
|
*= require ./feed
|
||||||
|
*= require ./jamtrack
|
||||||
|
*= require ./shoppingCart
|
||||||
|
*= require ./checkout
|
||||||
*= require ./genreSelector
|
*= require ./genreSelector
|
||||||
*= require ./sessionList
|
*= require ./sessionList
|
||||||
*= require ./searchResults
|
*= require ./searchResults
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,15 @@
|
||||||
z-index:5;
|
z-index:5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.header-shopping-cart {
|
||||||
|
float: right;
|
||||||
|
margin-right: 20px;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 60px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
div[layout="header"] h1 {
|
div[layout="header"] h1 {
|
||||||
cursor:pointer;
|
cursor:pointer;
|
||||||
width: 247px;
|
width: 247px;
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,9 @@
|
||||||
.homecard.musicians {
|
.homecard.musicians {
|
||||||
background-image: url(/assets/content/bkg_home_musicians.jpg);
|
background-image: url(/assets/content/bkg_home_musicians.jpg);
|
||||||
}
|
}
|
||||||
|
.homecard.jamtrack {
|
||||||
|
background-image: url(/assets/content/bkg_home_jamtracks.jpg);
|
||||||
|
}
|
||||||
|
|
||||||
.homebox-info {
|
.homebox-info {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|
@ -93,6 +96,9 @@
|
||||||
.homecard.musicians.hover {
|
.homecard.musicians.hover {
|
||||||
background-image: url(/assets/content/bkg_home_musicians_x.jpg);
|
background-image: url(/assets/content/bkg_home_musicians_x.jpg);
|
||||||
}
|
}
|
||||||
|
.homecard.jamtrack.hover {
|
||||||
|
background-image: url(/assets/content/bkg_home_jamtracks_x.jpg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,116 @@
|
||||||
|
#jamtrackScreen {
|
||||||
|
a.jamtrack_help {
|
||||||
|
color: #fff;
|
||||||
|
text-decoration: none;
|
||||||
|
margin: 4px 0px 0px 60px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.jamtrack-content {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-jamtracks-msg {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jamtrack-record {
|
||||||
|
border-bottom: 1px solid black;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jamtrack-detail {
|
||||||
|
float: left;
|
||||||
|
width: 50%;
|
||||||
|
padding: 10px 0px;
|
||||||
|
|
||||||
|
.detail-label {
|
||||||
|
width: 40%;
|
||||||
|
float: left;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-value {
|
||||||
|
width: 50%;
|
||||||
|
float: left;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyright-value {
|
||||||
|
width: 40%;
|
||||||
|
float: left;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-arrow {
|
||||||
|
float: left;
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jamtrack-description {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jamtrack-detail-btn {
|
||||||
|
cursor: pointer;
|
||||||
|
margin-top: 5px;
|
||||||
|
margin-right: 5px;
|
||||||
|
padding-top: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.jamtrack-tracks {
|
||||||
|
float: left;
|
||||||
|
width: 25%;
|
||||||
|
padding: 10px 0px;
|
||||||
|
|
||||||
|
.tracks-caption {
|
||||||
|
margin-top: 5px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.track-instrument {
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.instrument-image {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.instrument-desc {
|
||||||
|
margin-top: 6px;
|
||||||
|
float: left;
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.jamtrack-action {
|
||||||
|
float: left;
|
||||||
|
width: 25%;
|
||||||
|
padding: 10px 0px;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
.play-button {
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jamtrack-price {
|
||||||
|
margin-top: 5px;
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jamtrack-add-cart, .jamtrack-add-cart-disabled {
|
||||||
|
margin: 8px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jamtrack-license {
|
||||||
|
margin-left: 20%;
|
||||||
|
margin-right: 20%;
|
||||||
|
font-size: 13px;
|
||||||
|
width: 60%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,78 @@
|
||||||
|
#shoppingCartScreen {
|
||||||
|
|
||||||
|
.content-body {
|
||||||
|
padding: 50px 20px 20px 20px;
|
||||||
|
|
||||||
|
.checkout-image {
|
||||||
|
width: 10%;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkout-desc {
|
||||||
|
width: 90%;
|
||||||
|
float: left;
|
||||||
|
|
||||||
|
div {
|
||||||
|
margin-bottom: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div#note {
|
||||||
|
font-style: italic;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cart-item-caption {
|
||||||
|
width: 50%;
|
||||||
|
text-align: left;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cart-item-caption#header {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cart-item-price {
|
||||||
|
width: 15%;
|
||||||
|
text-align: right;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cart-item-quantity {
|
||||||
|
width: 15%;
|
||||||
|
text-align: right;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cart-item-actions {
|
||||||
|
width: 20%;
|
||||||
|
text-align: center;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cart-items {
|
||||||
|
width: 100%;
|
||||||
|
height: 300px;
|
||||||
|
overflow: auto;
|
||||||
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cart-item {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shopping-sub-total {
|
||||||
|
width: 65%;
|
||||||
|
float: left;
|
||||||
|
text-align: right;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 17px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-cart-items {
|
||||||
|
margin-top: 30px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
class ApiJamtracksController < ApiController
|
||||||
|
|
||||||
|
# have to be signed in currently to see this screen
|
||||||
|
before_filter :api_signed_in_user
|
||||||
|
|
||||||
|
respond_to :json
|
||||||
|
|
||||||
|
def index
|
||||||
|
data = JamTrack.index current_user, params
|
||||||
|
|
||||||
|
@jamtracks = data[0]
|
||||||
|
@next = data[1]
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,155 @@
|
||||||
|
class ApiRecurlyController < ApiController
|
||||||
|
|
||||||
|
before_filter :api_signed_in_user
|
||||||
|
respond_to :json
|
||||||
|
|
||||||
|
# create Recurly account
|
||||||
|
def create_account
|
||||||
|
logger.debug(params[:billing_info])
|
||||||
|
if current_user.recurly_code.nil?
|
||||||
|
@account = Recurly::Account.create(
|
||||||
|
account_code: current_user.id,
|
||||||
|
email: current_user.email,
|
||||||
|
first_name: current_user.first_name,
|
||||||
|
last_name: current_user.last_name,
|
||||||
|
address: {
|
||||||
|
city: current_user.city,
|
||||||
|
state: current_user.state,
|
||||||
|
country: current_user.country
|
||||||
|
}
|
||||||
|
)
|
||||||
|
else
|
||||||
|
@account = Recurly::Account.find(current_user.recurly_code)
|
||||||
|
end
|
||||||
|
|
||||||
|
if @account.errors.any?
|
||||||
|
response.status = 404
|
||||||
|
else
|
||||||
|
current_user.recurly_code = @account.account_code
|
||||||
|
current_user.save
|
||||||
|
|
||||||
|
@account.billing_info = params[:billing_info]
|
||||||
|
@account.billing_info.save
|
||||||
|
|
||||||
|
logger.debug @account
|
||||||
|
end
|
||||||
|
respond_with @account
|
||||||
|
|
||||||
|
rescue Recurly::Error, NoMethodError => e
|
||||||
|
render :json => { :message => e.inspect }, :status => 404
|
||||||
|
end
|
||||||
|
|
||||||
|
# get Recurly account
|
||||||
|
def get_account
|
||||||
|
@account = Recurly::Account.find(current_user.reculry_code)
|
||||||
|
respond_with @account
|
||||||
|
rescue Recurly::Error, NoMethodError => e
|
||||||
|
render :json => { message: ValidationMessages::RECURLY_ERROR}, :status => 404
|
||||||
|
end
|
||||||
|
|
||||||
|
# update Recurly account
|
||||||
|
def update_account
|
||||||
|
if current_user.recurly_code.nil?
|
||||||
|
@account = Recurly::Account.create(
|
||||||
|
account_code: current_user.id,
|
||||||
|
email: current_user.email,
|
||||||
|
first_name: current_user.first_name,
|
||||||
|
last_name: current_user.last_name,
|
||||||
|
address: {
|
||||||
|
city: current_user.city,
|
||||||
|
state: current_user.state,
|
||||||
|
country: current_user.country
|
||||||
|
}
|
||||||
|
)
|
||||||
|
else
|
||||||
|
@account = Recurly::Account.get(current_user.recurly_code)
|
||||||
|
end
|
||||||
|
|
||||||
|
@account.first_name = current_user.first_name
|
||||||
|
@account.last_name = current_user.last_name
|
||||||
|
@account.email = current_user.email
|
||||||
|
@account.update
|
||||||
|
|
||||||
|
if @account.errors.any?
|
||||||
|
response.status = 404
|
||||||
|
else
|
||||||
|
current_user.recurly_code = @account.account_code
|
||||||
|
current_user.save
|
||||||
|
end
|
||||||
|
respond_with @account
|
||||||
|
|
||||||
|
rescue Recurly::Error, NoMethodError => e
|
||||||
|
render :json => { message: ValidationMessages::RECURLY_ERROR}, :status => 404
|
||||||
|
end
|
||||||
|
|
||||||
|
# get subscription
|
||||||
|
def get_subscription
|
||||||
|
@account = Recurly::Acount.find(current_user.reculry_code)
|
||||||
|
respond_with @account.subscriptions.last
|
||||||
|
rescue Recurly::Error, NoMethodError => e
|
||||||
|
render :json => { message: ValidationMessages::RECURLY_GET_ACCOUNT_ERROR}, :status => 404
|
||||||
|
end
|
||||||
|
|
||||||
|
# create subscription
|
||||||
|
def create_subscription
|
||||||
|
end
|
||||||
|
|
||||||
|
# get Billing Information
|
||||||
|
def billing_info
|
||||||
|
if current_user.recurly_code.nil?
|
||||||
|
render :json => { message: ValidationMessages::RECURLY_ACCOUNT_ERROR }, :status => 404 and return
|
||||||
|
else
|
||||||
|
@account = Recurly::Account.find(current_user.recurly_code)
|
||||||
|
logger.debug @account
|
||||||
|
respond_with @account.billing_info
|
||||||
|
end
|
||||||
|
rescue Recurly::Error, NoMethodError => e
|
||||||
|
render :json => { message: ValidationMessages::RECURLY_ERROR}, :status => 404
|
||||||
|
end
|
||||||
|
|
||||||
|
# update Billing Information
|
||||||
|
def update_billing_info
|
||||||
|
if current_user.recurly_code.nil?
|
||||||
|
render :json => { message: ValidationMessages::RECURLY_ACCOUNT_ERROR }, :status => 404 and return
|
||||||
|
else
|
||||||
|
if params[:first_name].blank? or params[:last_name].blank? or params[:number].blank? or params[:year].blank? or params[:month].blank? or params[:verification_value].blank?
|
||||||
|
render :json => { message: ValidationMessages::RECURLY_PARAMETER_ERROR }, :status => 404 and return
|
||||||
|
end
|
||||||
|
@account = Recurly::Acount.find(current_user.reculry_code)
|
||||||
|
@account.billing_info = params
|
||||||
|
@account.billing_info.save
|
||||||
|
|
||||||
|
if @account.erros.any?
|
||||||
|
response.status = :unprocessable_entity
|
||||||
|
end
|
||||||
|
|
||||||
|
respond_with @account
|
||||||
|
end
|
||||||
|
rescue Recurly::Error, NoMethodError => e
|
||||||
|
render :json => { message: ValidationMessages::RECURLY_ERROR}, :status => 404
|
||||||
|
end
|
||||||
|
|
||||||
|
def place_order
|
||||||
|
if current_user.recurly_code.nil?
|
||||||
|
render :json => { message: ValidationMessages::RECURLY_ACCOUNT_ERROR }, :status => 404 and return
|
||||||
|
else
|
||||||
|
if params[:first_name].blank? or params[:last_name].blank? or params[:number].blank? or params[:year].blank? or params[:month].blank? or params[:verification_value].blank?
|
||||||
|
render :json => { message: ValidationMessages::RECURLY_PARAMETER_ERROR }, :status => 404 and return
|
||||||
|
end
|
||||||
|
@account = Recurly::Account.find(current_user.recurly_code)
|
||||||
|
@account.billing_info = params
|
||||||
|
@account.billing_info.save
|
||||||
|
|
||||||
|
# create subscription.
|
||||||
|
|
||||||
|
if @account.erros.any?
|
||||||
|
response.status = :unprocessable_entity
|
||||||
|
end
|
||||||
|
|
||||||
|
respond_with @account
|
||||||
|
end
|
||||||
|
rescue Recurly::Error, NoMethodError => e
|
||||||
|
render :json => { message: ValidationMessages::RECURLY_ERROR}, :status => 404
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
class ApiShoppingCartsController < ApiController
|
||||||
|
|
||||||
|
before_filter :api_signed_in_user
|
||||||
|
|
||||||
|
respond_to :json
|
||||||
|
|
||||||
|
def index
|
||||||
|
@carts = current_user.shopping_carts
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_jamtrack
|
||||||
|
jam_track = JamTrack.find_by_id(params[:id])
|
||||||
|
|
||||||
|
# verify JamTrack exists
|
||||||
|
if jam_track.nil?
|
||||||
|
raise StateError, "Invalid JamTrack."
|
||||||
|
end
|
||||||
|
|
||||||
|
@cart = ShoppingCart.create current_user, jam_track
|
||||||
|
|
||||||
|
if @cart.errors.any?
|
||||||
|
response.status = :unprocessable_entity
|
||||||
|
respond_with @cart
|
||||||
|
else
|
||||||
|
respond_with @cart, responder: ApiResponder, :statue => 201
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def update_cart
|
||||||
|
@cart = ShoppingCart.find_by_id params[:id]
|
||||||
|
|
||||||
|
#verify Cart exists
|
||||||
|
raise StateError, "Invalid Cart." if @cart.nil?
|
||||||
|
|
||||||
|
@cart.quantity = params[:quantity]
|
||||||
|
|
||||||
|
if @cart.errors.any?
|
||||||
|
response.statue = :unprocessable_entity
|
||||||
|
respond_with @cart
|
||||||
|
else
|
||||||
|
respond_with @cart, responder: ApiResponder, :status => 200
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def remove_cart
|
||||||
|
@cart = current_user.shopping_carts.find_by_id(params[:id])
|
||||||
|
raise StateError, "Invalid Cart." if @cart.nil?
|
||||||
|
|
||||||
|
@cart.destroy
|
||||||
|
respond_with responder: ApiResponder, :status => 204
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
node :next do |page|
|
||||||
|
@next
|
||||||
|
end
|
||||||
|
|
||||||
|
node :jamtracks do |page|
|
||||||
|
partial "api_jamtracks/show", object: @jamtracks
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
object @jamtrack
|
||||||
|
|
||||||
|
attributes :id, :name, :description, :recording_type, :original_artist, :songwriter, :publisher, :sales_region, :price
|
||||||
|
|
||||||
|
node :genres do |item|
|
||||||
|
[item.genre.description] # XXX: need to return single genre; not array
|
||||||
|
end
|
||||||
|
|
||||||
|
node :added_cart do |item|
|
||||||
|
current_user.shopping_carts.map(&:cart_id).include? item.id
|
||||||
|
end
|
||||||
|
|
||||||
|
child(:jam_track_tracks => :tracks) {
|
||||||
|
attributes :id, :part, :instrument
|
||||||
|
}
|
||||||
|
|
||||||
|
child(:licensor => :licensor) {
|
||||||
|
attributes :id, :name
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
extends "api_shopping_carts/show"
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
object @carts
|
||||||
|
|
||||||
|
extends "api_shopping_carts/show"
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
object @cart
|
||||||
|
|
||||||
|
attributes :id, :quantity, :cart_type, :product_info
|
||||||
|
|
@ -17,6 +17,8 @@ if @user == current_user
|
||||||
geoiplocation.info if geoiplocation
|
geoiplocation.info if geoiplocation
|
||||||
end
|
end
|
||||||
|
|
||||||
|
node :has_recurly_account do @user.recurly_code == @user.id end
|
||||||
|
|
||||||
elsif current_user
|
elsif current_user
|
||||||
node :is_friend do |uu|
|
node :is_friend do |uu|
|
||||||
current_user.friends?(@user)
|
current_user.friends?(@user)
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,11 @@
|
||||||
|
|
||||||
<%= render "users/user_dropdown" %>
|
<%= render "users/user_dropdown" %>
|
||||||
|
|
||||||
|
<!-- shopping cart -->
|
||||||
|
<a href="/client#/shoppingCart" class="header-shopping-cart">
|
||||||
|
<img id="header-shopping-cart" src="/assets/content/shopping-cart.png"/>
|
||||||
|
</a>
|
||||||
|
|
||||||
<!-- Templates -->
|
<!-- Templates -->
|
||||||
<script type="text/template" id="template-search-section">
|
<script type="text/template" id="template-search-section">
|
||||||
<h2>{section}</h2>
|
<h2>{section}</h2>
|
||||||
|
|
|
||||||
|
|
@ -21,25 +21,31 @@
|
||||||
|
|
||||||
<div class="homebox-info"><!-- 4 friends online, 2 currently in sessions --></div>
|
<div class="homebox-info"><!-- 4 friends online, 2 currently in sessions --></div>
|
||||||
</div>
|
</div>
|
||||||
<div layout-grid-position="0,1" layout-grid-rows="1" layout-grid-columns="3"
|
<div layout-grid-position="0,1" layout-grid-rows="1" layout-grid-columns="2.4"
|
||||||
layout-link="musicians" class="homecard musicians">
|
layout-link="musicians" class="homecard musicians">
|
||||||
<h2>musicians</h2>
|
<h2>musicians</h2>
|
||||||
|
|
||||||
<div class="homebox-info"><!-- 5 followers, 3 following --></div>
|
<div class="homebox-info"><!-- 5 followers, 3 following --></div>
|
||||||
</div>
|
</div>
|
||||||
<div layout-grid-position="3,1" layout-grid-rows="1" layout-grid-columns="3"
|
<div layout-grid-position="2.4,1" layout-grid-rows="1" layout-grid-columns="2.4"
|
||||||
layout-link="bands" class="homecard bands">
|
layout-link="bands" class="homecard bands">
|
||||||
<h2>bands</h2>
|
<h2>bands</h2>
|
||||||
|
|
||||||
<div class="homebox-info"><!-- 1 session invitation, 19 public sessions active --></div>
|
<div class="homebox-info"><!-- 1 session invitation, 19 public sessions active --></div>
|
||||||
</div>
|
</div>
|
||||||
<div layout-grid-position="6,1" layout-grid-rows="1" layout-grid-columns="3"
|
<div layout-grid-position="4.8,1" layout-grid-rows="1" layout-grid-columns="2.4"
|
||||||
|
layout-link="jamtrack" class="homecard jamtrack">
|
||||||
|
<h2>jamtracks</h2>
|
||||||
|
|
||||||
|
<div class="homebox-info"><!-- 5 followers, 3 following --></div>
|
||||||
|
</div>
|
||||||
|
<div layout-grid-position="7.2,1" layout-grid-rows="1" layout-grid-columns="2.4"
|
||||||
class="homecard profile">
|
class="homecard profile">
|
||||||
<h2>profile</h2>
|
<h2>profile</h2>
|
||||||
|
|
||||||
<div class="homebox-info"><!-- 5 followers, 3 following --></div>
|
<div class="homebox-info"><!-- 5 followers, 3 following --></div>
|
||||||
</div>
|
</div>
|
||||||
<div layout-grid-position="9,1" layout-grid-rows="1" layout-grid-columns="3"
|
<div layout-grid-position="9.6,1" layout-grid-rows="1" layout-grid-columns="2.4"
|
||||||
layout-link="account" class="homecard account">
|
layout-link="account" class="homecard account">
|
||||||
<h2>account</h2>
|
<h2>account</h2>
|
||||||
|
|
||||||
|
|
@ -65,25 +71,31 @@
|
||||||
|
|
||||||
<div class="homebox-info"><!-- 4 friends online, 2 currently in sessions --></div>
|
<div class="homebox-info"><!-- 4 friends online, 2 currently in sessions --></div>
|
||||||
</div>
|
</div>
|
||||||
<div layout-grid-position="0,1" layout-grid-rows="1" layout-grid-columns="3"
|
<div layout-grid-position="0,1" layout-grid-rows="1" layout-grid-columns="2.4"
|
||||||
layout-link="musicians" class="homecard musicians">
|
layout-link="musicians" class="homecard musicians">
|
||||||
<h2>musicians</h2>
|
<h2>musicians</h2>
|
||||||
|
|
||||||
<div class="homebox-info"><!-- 5 followers, 3 following --></div>
|
<div class="homebox-info"><!-- 5 followers, 3 following --></div>
|
||||||
</div>
|
</div>
|
||||||
<div layout-grid-position="3,1" layout-grid-rows="1" layout-grid-columns="3"
|
<div layout-grid-position="2.4,1" layout-grid-rows="1" layout-grid-columns="2.4"
|
||||||
layout-link="bands" class="homecard bands">
|
layout-link="bands" class="homecard bands">
|
||||||
<h2>bands</h2>
|
<h2>bands</h2>
|
||||||
|
|
||||||
<div class="homebox-info"><!-- 1 session invitation, 19 public sessions active --></div>
|
<div class="homebox-info"><!-- 1 session invitation, 19 public sessions active --></div>
|
||||||
</div>
|
</div>
|
||||||
<div layout-grid-position="6,1" layout-grid-rows="1" layout-grid-columns="3"
|
<div layout-grid-position="4.8,1" layout-grid-rows="1" layout-grid-columns="2.4"
|
||||||
|
layout-link="jamtrack" class="homecard jamtrack">
|
||||||
|
<h2>jamtracks</h2>
|
||||||
|
|
||||||
|
<div class="homebox-info"><!-- 5 followers, 3 following --></div>
|
||||||
|
</div>
|
||||||
|
<div layout-grid-position="7.2,1" layout-grid-rows="1" layout-grid-columns="2.4"
|
||||||
class="homecard profile">
|
class="homecard profile">
|
||||||
<h2>profile</h2>
|
<h2>profile</h2>
|
||||||
|
|
||||||
<div class="homebox-info"><!-- 5 followers, 3 following --></div>
|
<div class="homebox-info"><!-- 5 followers, 3 following --></div>
|
||||||
</div>
|
</div>
|
||||||
<div layout-grid-position="9,1" layout-grid-rows="1" layout-grid-columns="3"
|
<div layout-grid-position="9.6,1" layout-grid-rows="1" layout-grid-columns="2.4"
|
||||||
layout-link="account" class="homecard account">
|
layout-link="account" class="homecard account">
|
||||||
<h2>account</h2>
|
<h2>account</h2>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,81 @@
|
||||||
|
%div{ layout: 'screen', :'layout-id' => 'jamtrack', id: 'jamtrackScreen', :class => 'screen secondary'}
|
||||||
|
.content
|
||||||
|
.content-head
|
||||||
|
.content-icon= image_tag("content/icon_jamtracks.png", {:height => 19, :width => 19})
|
||||||
|
%h1 jamtracks
|
||||||
|
%a{href: "#", class: "jamtrack_help"} What is a JamTrack?
|
||||||
|
= render "screen_navigation"
|
||||||
|
.content-body
|
||||||
|
= form_tag('', {:id => 'jamtrack-find-form', :class => 'inner-content'}) do
|
||||||
|
= render(:partial => "web_filter", :locals => {:search_type => Search::PARAM_JAMTRACK})
|
||||||
|
.filter-body
|
||||||
|
.content-body-scroller
|
||||||
|
.profile-wrapper
|
||||||
|
.jamtrack-content
|
||||||
|
%a{href: "/api/jamtracks?page=1", class: "btn-next-pager"}= 'Next'
|
||||||
|
%div{id: 'end-of-jamtrack-list', class: 'end-of-list'}= 'No more Jamtracks'
|
||||||
|
|
||||||
|
%script{type: 'text/template', id: 'template-jamtrack'}
|
||||||
|
.jamtrack-record{"jamtrack-id" => "{{data.jamtrack.id}}"}
|
||||||
|
.jamtrack-detail
|
||||||
|
.detail-label
|
||||||
|
Name:
|
||||||
|
.detail-value
|
||||||
|
{{data.jamtrack.name}}
|
||||||
|
.clearall.detail-label
|
||||||
|
Type:
|
||||||
|
.detail-value
|
||||||
|
{{data.jamtrack.recording_type}}
|
||||||
|
.clearall.detail-label
|
||||||
|
Original Artist:
|
||||||
|
.detail-value
|
||||||
|
{{data.jamtrack.original_artist}}
|
||||||
|
.clearall.detail-label
|
||||||
|
Genre:
|
||||||
|
.detail-value
|
||||||
|
{{data.jamtrack.genres[0]}}
|
||||||
|
.clearall.detail-label
|
||||||
|
Writer/Composer:
|
||||||
|
.detail-value
|
||||||
|
{{[data.jamtrack.songwriter, data.jamtrack.publisher].join(", ")}}
|
||||||
|
.clearall.detail-label
|
||||||
|
Copyright:
|
||||||
|
.copyright-value
|
||||||
|
= "{% if (data.jamtrack.licensor != null) { %}"
|
||||||
|
{{data.jamtrack.licensor.name}}
|
||||||
|
="{% }; %}"
|
||||||
|
.detail-arrow
|
||||||
|
= image_tag 'down_arrow.png', class: 'jamtrack-detail-btn'
|
||||||
|
.clearall.jamtrack-description
|
||||||
|
.detail-label
|
||||||
|
Description
|
||||||
|
.detail-value
|
||||||
|
{{data.jamtrack.description}}
|
||||||
|
.clearall
|
||||||
|
.jamtrack-tracks
|
||||||
|
.tracks-caption
|
||||||
|
Tracks in This Recording:
|
||||||
|
= "{% _.each(data.jamtrack.tracks, function(track) { %}"
|
||||||
|
.track-instrument
|
||||||
|
.instrument-image
|
||||||
|
%img{src: "{{track.instrument_url}}", width: 24, height: 24}
|
||||||
|
.instrument-desc
|
||||||
|
{{track.instrument_desc}}
|
||||||
|
.clearall
|
||||||
|
= "{% }); %}"
|
||||||
|
.jamtrack-action
|
||||||
|
%a{href: "#", class: 'play-button', "data-jamtrack-id" => "{{data.jamtrack.id}}"}
|
||||||
|
= image_tag 'shared/play_button.png'
|
||||||
|
.jamtrack-price
|
||||||
|
{{"$ " + data.jamtrack.price}}
|
||||||
|
= "{% if (data.jamtrack.added_cart) { %}"
|
||||||
|
%a.jamtrack-add-cart-disabled.button-grey.button-disabled{href: "javascript:void(0)"} Added to Cart
|
||||||
|
= "{% } else { %}"
|
||||||
|
%a.jamtrack-add-cart.button-orange{href: "#", "data-jamtrack-id" => "{{data.jamtrack.id}}"} Add to Cart
|
||||||
|
= "{% }; %}"
|
||||||
|
= "{% if (data.jamtrack.sales_region == 'United States') { %}"
|
||||||
|
.jamtrack-license
|
||||||
|
This JamTrack available only to US customers.
|
||||||
|
%a{href: "#", class: 'license-us-why'} why?
|
||||||
|
= "{% }; %}"
|
||||||
|
.clearall
|
||||||
|
|
@ -0,0 +1,268 @@
|
||||||
|
div layout="screen" layout-id="order" id="orderScreen" class="screen secondary"
|
||||||
|
.content
|
||||||
|
.content-head
|
||||||
|
.content-icon= image_tag("content/icon_shopping_cart.png", {:height => 19, :width => 19})
|
||||||
|
h1 check out
|
||||||
|
= render "screen_navigation"
|
||||||
|
.content-body
|
||||||
|
.content-body-scroller
|
||||||
|
.content-wrapper
|
||||||
|
.checkout-navigation-bar
|
||||||
|
.checkout-payment-info
|
||||||
|
form class="payment-info" id="checkout-payment-info"
|
||||||
|
.billing-address
|
||||||
|
h2.billing-caption Billing Address
|
||||||
|
#divBillingFirstName
|
||||||
|
.billing-label
|
||||||
|
label for="billing-first-name" First Name:
|
||||||
|
.billing-value
|
||||||
|
input type="text" id="billing-first-name"
|
||||||
|
.clearall
|
||||||
|
#divBillingLastName
|
||||||
|
.billing-label
|
||||||
|
label for="billing-last-name" Last Name:
|
||||||
|
.billing-value
|
||||||
|
input type="text" id="billing-last-name"
|
||||||
|
.clearall
|
||||||
|
#divBillingAddress1
|
||||||
|
.billing-label
|
||||||
|
label for="billing-address1" Address 1:
|
||||||
|
.billing-value
|
||||||
|
input type="text" id="billing-address1"
|
||||||
|
.clearall
|
||||||
|
.billing-label
|
||||||
|
label for="billing-address2" Address 2:
|
||||||
|
.billing-value
|
||||||
|
input type="text" id="billing-address2"
|
||||||
|
.clearall
|
||||||
|
#divBillingCity
|
||||||
|
.billing-label
|
||||||
|
label for="billing-city" City:
|
||||||
|
.billing-value
|
||||||
|
input type="text" id="billing-city"
|
||||||
|
.clearall
|
||||||
|
#divBillingState
|
||||||
|
.billing-label
|
||||||
|
label for="billing-state" State/Region:
|
||||||
|
.billing-value
|
||||||
|
input type="text" id="billing-state"
|
||||||
|
.clearall
|
||||||
|
#divBillingZip
|
||||||
|
.billing-label
|
||||||
|
label for="billing-zip" Zip:
|
||||||
|
.billing-value
|
||||||
|
input type="text" id="billing-zip"
|
||||||
|
.clearall
|
||||||
|
#divBillingCountry
|
||||||
|
.billing-label
|
||||||
|
label for="billing-country" Country:
|
||||||
|
.billing-value
|
||||||
|
input type="text" id="billing-country"
|
||||||
|
.clearall
|
||||||
|
.payment-method
|
||||||
|
h2.payment-method-caption Payment Method
|
||||||
|
b Enter Card Information
|
||||||
|
br
|
||||||
|
#divCardName
|
||||||
|
.card-label.mt10
|
||||||
|
label for="card-name" Name of Card:
|
||||||
|
.card-value.mt10
|
||||||
|
input type="text" id="card-name"
|
||||||
|
.clearall
|
||||||
|
#divCardNumber
|
||||||
|
.card-label
|
||||||
|
label for="card-number" Card Number:
|
||||||
|
.card-value
|
||||||
|
input type="text" id="card-number"
|
||||||
|
.clearall
|
||||||
|
.card-label Expiration Date:
|
||||||
|
.card-value
|
||||||
|
= date_select("card", "expire-date", use_two_digit_numbers: true, discard_day: true, :start_year => Time.now.year, :end_year => Time.now.year + 18, :order => [:month, :day, :year], :default => -25.years.from_now, :html=>{:class => "account-profile-birthdate"} )
|
||||||
|
.clearall
|
||||||
|
#divCardVerify
|
||||||
|
.card-label
|
||||||
|
label for="card-verify" Verification Value:
|
||||||
|
.card-value
|
||||||
|
input type="text" id="card-verify"
|
||||||
|
.clearall
|
||||||
|
.card-label.mt15
|
||||||
|
.card-value.mt15
|
||||||
|
.save-card-checkbox.ichecbuttons
|
||||||
|
input type="checkbox" id="save-card" name="save-card" checked="checked"
|
||||||
|
.divSaveCardHelper
|
||||||
|
label for="save-card" Save card for future use
|
||||||
|
.clearall
|
||||||
|
.clearall
|
||||||
|
.clearall
|
||||||
|
|
||||||
|
.action-bar.mt15
|
||||||
|
.shipping-address
|
||||||
|
h2.shipping-address-label Shipping Address
|
||||||
|
.shipping-as-billing.ichecbuttons
|
||||||
|
input type="checkbox" id="shipping-as-billing" name="shipping-as-billing" checked="checked"
|
||||||
|
.divBillingHelper
|
||||||
|
label for="shipping-as-billing" Same as billing address
|
||||||
|
.clearall
|
||||||
|
.shipping-address-detail.hidden
|
||||||
|
#divShippingFirstName
|
||||||
|
.shipping-label
|
||||||
|
label for="shipping-first-name" First Name:
|
||||||
|
.shipping-value
|
||||||
|
input type="text" id="shipping-first-name"
|
||||||
|
.clearall
|
||||||
|
#divShippingLastName
|
||||||
|
.shipping-label
|
||||||
|
label for="shipping-last-name" Last Name:
|
||||||
|
.shipping-value
|
||||||
|
input type="text" id="shipping-last-name"
|
||||||
|
.clearall
|
||||||
|
#divShippingAddress1
|
||||||
|
.shipping-label
|
||||||
|
label for="shipping-address1" Address 1:
|
||||||
|
.shipping-value
|
||||||
|
input type="text" id="shipping-address1"
|
||||||
|
.clearall
|
||||||
|
.shipping-label
|
||||||
|
label for="shipping-address2" Address 2:
|
||||||
|
.shipping-value
|
||||||
|
input type="text" id="shipping-address2"
|
||||||
|
.clearall
|
||||||
|
#divShippingCity
|
||||||
|
.shipping-label
|
||||||
|
label for="shipping-city" City:
|
||||||
|
.shipping-value
|
||||||
|
input type="text" id="shipping-city"
|
||||||
|
.clearall
|
||||||
|
#divShippingState
|
||||||
|
.shipping-label
|
||||||
|
label for="shipping-state" State/Region:
|
||||||
|
.shipping-value
|
||||||
|
input type="text" id="shipping-state"
|
||||||
|
.clearall
|
||||||
|
#divShippingZip
|
||||||
|
.shipping-label
|
||||||
|
label for="shipping-zip" Zip:
|
||||||
|
.shipping-value
|
||||||
|
input type="text" id="shipping-zip"
|
||||||
|
.clearall
|
||||||
|
#divShippingCountry
|
||||||
|
.shipping-label
|
||||||
|
label for="shipping-country" Country:
|
||||||
|
.shipping-value
|
||||||
|
input type="text" id="shipping-country"
|
||||||
|
.clearall
|
||||||
|
.right.mt30
|
||||||
|
a href="#" id="payment-info-help" class="button-grey" HELP
|
||||||
|
a href="#" id="payment-info-next" class="button-orange" NEXT
|
||||||
|
.clearall
|
||||||
|
.order-panel.hidden
|
||||||
|
.order-header.left
|
||||||
|
h2 Review Your Order
|
||||||
|
.mt5
|
||||||
|
span By placing your order, you agree to JamKazam's
|
||||||
|
'
|
||||||
|
a href="http://www.jamkazam.com/corp/terms" terms of service
|
||||||
|
'
|
||||||
|
span and
|
||||||
|
'
|
||||||
|
a href="http://www.jamkazam.com/corp/returns" returns policy
|
||||||
|
span .
|
||||||
|
.right.mt10
|
||||||
|
a href="#" class="button-grey" HELP
|
||||||
|
.clearall
|
||||||
|
|
||||||
|
.order-content
|
||||||
|
|
||||||
|
script type='text/template' id='template-order-content'
|
||||||
|
.order-left-page
|
||||||
|
.payment-info-page
|
||||||
|
.address-info
|
||||||
|
b.left Billing Address
|
||||||
|
a.left.ml5.change-payment-info href="#" change
|
||||||
|
.clearall
|
||||||
|
span.mt5= "{{data.billing_info.first_name}} {{data.billing_info.last_name}}"
|
||||||
|
br
|
||||||
|
span.mt5= "{{data.billing_info.address1}}"
|
||||||
|
br
|
||||||
|
span.mt5= "{{data.billing_info.address2}}"
|
||||||
|
br
|
||||||
|
br
|
||||||
|
b.left Shipping Address
|
||||||
|
a.left.ml5.change-payment-info href="#" change
|
||||||
|
.clearall
|
||||||
|
= "{% if (data.shipping_as_billing) { %}"
|
||||||
|
span.mt5 same as billing address
|
||||||
|
= "{% } else { %}"
|
||||||
|
span.mt5= "{{data.shipping_info.first_name}} {{data.shipping_info.last_name}}"
|
||||||
|
br
|
||||||
|
span.mt5= "{{data.shipping_info.address1}}"
|
||||||
|
br
|
||||||
|
span.mt5= "{{data.shipping_info.address2}}"
|
||||||
|
= "{% } %}"
|
||||||
|
br
|
||||||
|
.payment-method-info
|
||||||
|
b.left Payment Method
|
||||||
|
a.left.ml5.change-payment-info href="#" change
|
||||||
|
.clearall
|
||||||
|
|
||||||
|
/= image_tag ''
|
||||||
|
| ending in 1234
|
||||||
|
.clearall
|
||||||
|
.order-items-page
|
||||||
|
.cart-items
|
||||||
|
.cart-item-caption#header
|
||||||
|
span Your order includes:
|
||||||
|
.cart-item-price
|
||||||
|
span style="text-decoration: underline;" Price
|
||||||
|
.cart-item-quantity
|
||||||
|
span style="text-decoration: underline;" Quantity
|
||||||
|
.clearall
|
||||||
|
= "{% if (data.carts.length == 0) { %}"
|
||||||
|
.no-cart-items You have no orders now.
|
||||||
|
= "{% } %}"
|
||||||
|
= "{% _.each(data.carts, function(cart) { %}"
|
||||||
|
.cart-item cart-id="{{cart.id}}"
|
||||||
|
.cart-item-caption
|
||||||
|
= "{{cart.cart_type}}: {{cart.product_info.name}}"
|
||||||
|
.cart-item-price
|
||||||
|
= "$ {{cart.product_info.price}}"
|
||||||
|
.cart-item-quantity
|
||||||
|
= "{{cart.quantity}}"
|
||||||
|
.clearall
|
||||||
|
= "{% }); %}"
|
||||||
|
.clearall
|
||||||
|
.order-right-page
|
||||||
|
a href="#" class="button-orange place-order" PLACE YOUR ORDER
|
||||||
|
br
|
||||||
|
br
|
||||||
|
b.mt10 Order Summary:
|
||||||
|
br
|
||||||
|
.left Items:
|
||||||
|
.right= "${{data.sub_total}}"
|
||||||
|
.clearall
|
||||||
|
.left Shipping & handling
|
||||||
|
.right $0.00
|
||||||
|
br
|
||||||
|
hr
|
||||||
|
.left Total before Tax:
|
||||||
|
.right= "${{data.sub_total}}"
|
||||||
|
.clearall
|
||||||
|
.left Taxes:
|
||||||
|
.right= "${{data.taxes}}"
|
||||||
|
.clearall
|
||||||
|
br
|
||||||
|
hr
|
||||||
|
b.order-total
|
||||||
|
.left Order Total:
|
||||||
|
.right= "${{data.sub_total + data.taxes}}}"
|
||||||
|
.clearall
|
||||||
|
br
|
||||||
|
div style="text-align: left;"
|
||||||
|
span By placing your order, you agree to JamKazam's
|
||||||
|
'
|
||||||
|
a href="http://www.jamkazam.com/corp/terms" terms of service
|
||||||
|
'
|
||||||
|
span and
|
||||||
|
'
|
||||||
|
a href="http://www.jamkazam.com/corp/returns" returns policy
|
||||||
|
span .
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
%div{ layout: 'screen', :'layout-id' => 'shoppingCart', id: 'shoppingCartScreen', :class => 'screen secondary'}
|
||||||
|
.content
|
||||||
|
.content-head
|
||||||
|
.content-icon= image_tag("content/icon_shopping_cart.png", {:height => 19, :width => 19})
|
||||||
|
%h1 shopping cart
|
||||||
|
= render "screen_navigation"
|
||||||
|
.content-body
|
||||||
|
.shopping-cart-content
|
||||||
|
|
||||||
|
%script{type: 'text/template', id: 'template-shopping-cart-header'}
|
||||||
|
.checkout-image= image_tag "content/checkmark.png", {:height => 32}
|
||||||
|
.checkout-desc
|
||||||
|
%div
|
||||||
|
1 item added to shopping cart
|
||||||
|
%div
|
||||||
|
{{data.cart_type}}: {{data.product_info.name}}
|
||||||
|
#note
|
||||||
|
Note: You must be in the United States to purchase this {{data.type}} due to licensing constraints.
|
||||||
|
.clearall
|
||||||
|
|
||||||
|
%script{type: 'text/template', id: 'template-shopping-cart-body'}
|
||||||
|
.cart-items
|
||||||
|
.cart-item-caption#header
|
||||||
|
Your shopping cart now contains:
|
||||||
|
.cart-item-price
|
||||||
|
%span{style: "text-decoration: underline;"} Price
|
||||||
|
.cart-item-quantity
|
||||||
|
%span{style: "text-decoration: underline;"} Quantity
|
||||||
|
.clearall
|
||||||
|
= "{% if (data.carts.length == 0) { %}"
|
||||||
|
.no-cart-items You have no carts now.
|
||||||
|
= "{% } %}"
|
||||||
|
= "{% _.each(data.carts, function(cart) { %}"
|
||||||
|
.cart-item{"cart-id" => "{{cart.id}}"}
|
||||||
|
.cart-item-caption
|
||||||
|
{{cart.cart_type}}: {{cart.product_info.name}}
|
||||||
|
.cart-item-price
|
||||||
|
$ {{cart.product_info.price}}
|
||||||
|
.cart-item-quantity
|
||||||
|
{{cart.quantity}}
|
||||||
|
.cart-item-actions
|
||||||
|
%a.button-grey.remove-cart{href: "#", "cart-id" => "{{cart.id}}"} DELETE
|
||||||
|
.clearall
|
||||||
|
= "{% }); %}"
|
||||||
|
.shopping-sub-total
|
||||||
|
Subtotal: $ {{data.sub_total}}
|
||||||
|
.clearall
|
||||||
|
.left
|
||||||
|
%a.button-grey{href: "#"} HELP
|
||||||
|
.right
|
||||||
|
%a.button-orange{href: "/client#/jamtrack"} CONTINUE SHOPPING
|
||||||
|
%a.button-orange.proceed-checkout{href: "#"} PROCEED TO CHECKOUT
|
||||||
|
.clearall
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
div layout="screen" layout-id="signin" id="signInScreen" class="screen secondary signin-common"
|
||||||
|
.content
|
||||||
|
.content-head
|
||||||
|
.content-icon= image_tag("content/icon_shopping_cart.png", {:height => 19, :width => 19})
|
||||||
|
h1 check out
|
||||||
|
= render "screen_navigation"
|
||||||
|
.content-body
|
||||||
|
.checkout-signin
|
||||||
|
.checkout-navigation-bar
|
||||||
|
|
||||||
|
.signin-form
|
||||||
|
= link_to image_tag("content/button_facebook_signin.png", {:width => 249, :height => 46}), '/auth/facebook', class: "signin-facebook"
|
||||||
|
|
||||||
|
br
|
||||||
|
br
|
||||||
|
br
|
||||||
|
strong.white Or sign in with JamKazam Account
|
||||||
|
br
|
||||||
|
br
|
||||||
|
|
||||||
|
= form_for(:session, url: signin_path('redirect-to' => '/client#/payment_config') + (request.query_string.blank? ? '' : '?' + request.query_string), html: {class:"signin-form #{'login-error' if @login_error}"}) do |f|
|
||||||
|
.email
|
||||||
|
= f.label :email, "Email Address:", class: 'inline'
|
||||||
|
= f.text_field :email, autofocus: true
|
||||||
|
|
||||||
|
.password
|
||||||
|
= f.label :password, "Password:", class: 'inline'
|
||||||
|
= f.password_field :password, autofocus: true, class: 'signin-password'
|
||||||
|
.login-error-msg Invalid login
|
||||||
|
|
||||||
|
br clear='all'
|
||||||
|
|
||||||
|
.actions align='center'
|
||||||
|
= link_to "SIGN IN", '#', class: 'button-orange signin-submit'
|
||||||
|
| or
|
||||||
|
'
|
||||||
|
a.show-signup-dialog href='#' Sign Up
|
||||||
|
br
|
||||||
|
br
|
||||||
|
small
|
||||||
|
a.forgot-password href='/request_reset_password' Forgot Password?
|
||||||
|
|
||||||
|
|
||||||
|
script type='text/template' id='template-checkout-navigation'
|
||||||
|
.checkout-navigation
|
||||||
|
.nav-signin
|
||||||
|
= "{% if (data.current == 1) { %}"
|
||||||
|
.nav-text.selected Sign In
|
||||||
|
= "{% } else { %}"
|
||||||
|
.nav-text Sign In
|
||||||
|
= "{% } %}"
|
||||||
|
.nav-arrow ->
|
||||||
|
.clearall
|
||||||
|
.nav-payment-info
|
||||||
|
= "{% if (data.current == 2) { %}"
|
||||||
|
.nav-text.selected Address & Payment
|
||||||
|
= "{% } else { %}"
|
||||||
|
.nav-text Address & Payment
|
||||||
|
= "{% } %}"
|
||||||
|
.nav-arrow ->
|
||||||
|
.clearall
|
||||||
|
.nav-signin
|
||||||
|
= "{% if (data.current == 3) { %}"
|
||||||
|
.nav-text.selected Place Order
|
||||||
|
= "{% } else { %}"
|
||||||
|
.nav-text Place Order
|
||||||
|
= "{% } %}"
|
||||||
|
.clearall
|
||||||
|
|
@ -6,6 +6,8 @@
|
||||||
filter_label = :musician
|
filter_label = :musician
|
||||||
when Search::PARAM_FEED
|
when Search::PARAM_FEED
|
||||||
filter_label = :feed
|
filter_label = :feed
|
||||||
|
when Search::PARAM_JAMTRACK
|
||||||
|
filter_label = :jamtrack
|
||||||
end %>
|
end %>
|
||||||
<%= content_tag(:div, :id => defined?(id) ? id : 'session-controls', :class => "#{filter_label}-filter filter-head") do %>
|
<%= content_tag(:div, :id => defined?(id) ? id : 'session-controls', :class => "#{filter_label}-filter filter-head") do %>
|
||||||
<%= content_tag(:div, :class => "filter-element wrapper") do -%>
|
<%= content_tag(:div, :class => "filter-element wrapper") do -%>
|
||||||
|
|
@ -14,27 +16,29 @@
|
||||||
<%= content_tag(:div, 'Sort Feed by:', :class => 'filter-element desc') %>
|
<%= content_tag(:div, 'Sort Feed by:', :class => 'filter-element desc') %>
|
||||||
<%= select_tag("#{filter_label}_order_by", options_for_select(Search::F_SORT_OPTS), {:class => "#{filter_label}-order-by easydropdown" } ) %>
|
<%= select_tag("#{filter_label}_order_by", options_for_select(Search::F_SORT_OPTS), {:class => "#{filter_label}-order-by easydropdown" } ) %>
|
||||||
<!-- @end sort filter -->
|
<!-- @end sort filter -->
|
||||||
<% else %>
|
<% elsif :jamtrack != filter_label %>
|
||||||
<!-- @begin order by filter -->
|
<!-- @begin order by filter -->
|
||||||
<%= content_tag(:div, 'Order By:', :class => 'filter-element desc') %>
|
<%= content_tag(:div, 'Filter By:', :class => 'filter-element desc') %>
|
||||||
<%= select_tag("#{filter_label}_order_by", options_for_select(Search::M_ORDERINGS), {:class => "#{filter_label}-order-by easydropdown"} ) %>
|
<%= select_tag("#{filter_label}_order_by", options_for_select(Search::ORDERINGS), {:class => "#{filter_label}-order-by easydropdown"} ) %>
|
||||||
<!-- @end order by filter -->
|
<!-- @end order by filter -->
|
||||||
<% end %>
|
<% end %>
|
||||||
<% end -%>
|
<% end -%>
|
||||||
<%= content_tag(:div, :class => 'filter-element wrapper') do -%>
|
<%= content_tag(:div, :class => 'filter-element wrapper') do -%>
|
||||||
<% if :musician == filter_label %>
|
<% if :band == filter_label || :jamtrack == filter_label %>
|
||||||
<!-- @begin instrument filter -->
|
|
||||||
<%= content_tag(:div, 'Instrument:', :class => 'filter-element desc instrument-selector') %>
|
|
||||||
<%= select_tag("#{filter_label}_instrument",
|
|
||||||
options_for_select([['Any', '']].concat(JamRuby::Instrument.all.collect { |ii| [ii.description, ii.id] })), {:class=> "easydropdown"}) %>
|
|
||||||
<!-- @end instrument filter -->
|
|
||||||
<% elsif :band == filter_label %>
|
|
||||||
<!-- @begin genre filter -->
|
<!-- @begin genre filter -->
|
||||||
<%= content_tag(:div, 'Genre:', :class => 'filter-element desc') %>
|
<%= content_tag(:div, 'Genre:', :class => 'filter-element desc') %>
|
||||||
<%= select_tag("#{filter_label}_genre",
|
<%= select_tag("#{filter_label}_genre",
|
||||||
options_for_select([['Any', '']].concat(JamRuby::Genre.all.collect { |ii| [ii.description, ii.id] })), {:class => 'easydropdown'}) %>
|
options_for_select([['Any', '']].concat(JamRuby::Genre.all.collect { |ii| [ii.description, ii.id] })), {:class => 'easydropdown'}) %>
|
||||||
<!-- @end genre filter -->
|
<!-- @end genre filter -->
|
||||||
<% elsif :feed == filter_label %>
|
<% end %>
|
||||||
|
<% if :musician == filter_label || :jamtrack == filter_label %>
|
||||||
|
<!-- @begin instrument filter -->
|
||||||
|
<%= content_tag(:div, 'Instrument:', :class => 'filter-element desc') %>
|
||||||
|
<%= select_tag("#{filter_label}_instrument",
|
||||||
|
options_for_select([['Any', '']].concat(JamRuby::Instrument.all.collect { |ii| [ii.description, ii.id] })), {:class=> "easydropdown"}) %>
|
||||||
|
<!-- @end instrument filter -->
|
||||||
|
<% end %>
|
||||||
|
<% if :feed == filter_label %>
|
||||||
<!-- @begin date filter -->
|
<!-- @begin date filter -->
|
||||||
<%= content_tag(:div, 'Include Dates:', :class => 'filter-element desc') %>
|
<%= content_tag(:div, 'Include Dates:', :class => 'filter-element desc') %>
|
||||||
<%= select_tag("#{filter_label}_date", options_for_select(Search::DATE_OPTS), {:class => "easydropdown"}) %>
|
<%= select_tag("#{filter_label}_date", options_for_select(Search::DATE_OPTS), {:class => "easydropdown"}) %>
|
||||||
|
|
@ -58,6 +62,11 @@
|
||||||
to <a href="#" id="musician-change-filter-city"><span id="musician-filter-city"></span></a>
|
to <a href="#" id="musician-change-filter-city"><span id="musician-filter-city"></span></a>
|
||||||
</div>
|
</div>
|
||||||
<!-- @end score filter -->
|
<!-- @end score filter -->
|
||||||
|
<% elsif :jamtrack == filter_label %>
|
||||||
|
<!-- @begin availability filter -->
|
||||||
|
<%= content_tag(:div, 'Availability:', :class => 'filter-element desc') %>
|
||||||
|
<%= select_tag("#{filter_label}_availability", options_for_select([['Any', '']].concat(JamRuby::JamTrack::SALES_REGION), 'United States'), {:class => "easydropdown"}) %>
|
||||||
|
<!-- @end availability filter -->
|
||||||
<% else %>
|
<% else %>
|
||||||
<!-- @begin distance filter -->
|
<!-- @begin distance filter -->
|
||||||
<%= content_tag(:div, 'Within', :class => 'filter-element desc') %>
|
<%= content_tag(:div, 'Within', :class => 'filter-element desc') %>
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,10 @@
|
||||||
<%= render "band_setup_photo" %>
|
<%= render "band_setup_photo" %>
|
||||||
<%= render "users/feed_music_session_ajax" %>
|
<%= render "users/feed_music_session_ajax" %>
|
||||||
<%= render "users/feed_recording_ajax" %>
|
<%= render "users/feed_recording_ajax" %>
|
||||||
|
<%= render "jamtrack" %>
|
||||||
|
<%= render "shopping_cart" %>
|
||||||
|
<%= render "signin" %>
|
||||||
|
<%= render "order" %>
|
||||||
<%= render "feed" %>
|
<%= render "feed" %>
|
||||||
<%= render "bands" %>
|
<%= render "bands" %>
|
||||||
<%= render "musicians" %>
|
<%= render "musicians" %>
|
||||||
|
|
@ -152,6 +156,8 @@
|
||||||
var networkTestDialog = new JK.NetworkTestDialog(JK.app);
|
var networkTestDialog = new JK.NetworkTestDialog(JK.app);
|
||||||
networkTestDialog.initialize();
|
networkTestDialog.initialize();
|
||||||
|
|
||||||
|
var jamtrackAvailabilityDialog = new JK.JamtrackAvailabilityDialog(JK.app);
|
||||||
|
jamtrackAvailabilityDialog.initialize();
|
||||||
var audioProfileInvalidDialog = new JK.AudioProfileInvalidDialog(JK.app);
|
var audioProfileInvalidDialog = new JK.AudioProfileInvalidDialog(JK.app);
|
||||||
audioProfileInvalidDialog.initialize();
|
audioProfileInvalidDialog.initialize();
|
||||||
|
|
||||||
|
|
@ -227,6 +233,18 @@
|
||||||
// }
|
// }
|
||||||
// findSessionScreen.initialize(sessionLatency);
|
// findSessionScreen.initialize(sessionLatency);
|
||||||
|
|
||||||
|
var jamtrackScreen = new JK.JamTrackScreen(JK.app);
|
||||||
|
jamtrackScreen.initialize();
|
||||||
|
|
||||||
|
var shoppingCartScreen = new JK.ShoppingCartScreen(JK.app);
|
||||||
|
shoppingCartScreen.initialize();
|
||||||
|
|
||||||
|
var checkoutSignInScreen = new JK.CheckoutSignInScreen(JK.app);
|
||||||
|
checkoutSignInScreen.initialize();
|
||||||
|
|
||||||
|
var OrderScreen = new JK.OrderScreen(JK.app);
|
||||||
|
OrderScreen.initialize();
|
||||||
|
|
||||||
var findMusicianScreen = new JK.FindMusicianScreen(JK.app);
|
var findMusicianScreen = new JK.FindMusicianScreen(JK.app);
|
||||||
findMusicianScreen.initialize(JK.TextMessageDialogInstance);
|
findMusicianScreen.initialize(JK.TextMessageDialogInstance);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@
|
||||||
= render 'dialogs/signupDialog'
|
= render 'dialogs/signupDialog'
|
||||||
= render 'dialogs/videoDialog'
|
= render 'dialogs/videoDialog'
|
||||||
= render 'dialogs/friendSelectorDialog'
|
= render 'dialogs/friendSelectorDialog'
|
||||||
|
= render 'dialogs/jamtrackAvailabilityDialog'
|
||||||
= render 'dialogs/clientPreferencesDialog'
|
= render 'dialogs/clientPreferencesDialog'
|
||||||
= render 'dialogs/audioProfileInvalidDialog'
|
= render 'dialogs/audioProfileInvalidDialog'
|
||||||
= render 'dialogs/gettingStartedDialog'
|
= render 'dialogs/gettingStartedDialog'
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
.dialog.dialog-overlay-sm{layout: 'dialog', 'layout-id' => 'jamtrack-availability-dialog', id: 'jamtrack-availability-dialog'}
|
||||||
|
.content-head
|
||||||
|
%h1 JamTrack Availability:
|
||||||
|
.dialog-inner
|
||||||
|
.left
|
||||||
|
%span JamKazam has not yet secured license rights to sell this JamTrack to customers outside the United States.
|
||||||
|
.right
|
||||||
|
%a.button-orange{id: 'dialog-close-button', 'layout-action' => 'close'} X CLOSE
|
||||||
|
.clearall
|
||||||
|
|
@ -143,7 +143,6 @@ if defined?(Bundler)
|
||||||
# google api keys
|
# google api keys
|
||||||
config.google_client_id = '785931784279-gd0g8on6sc0tuesj7cu763pitaiv2la8.apps.googleusercontent.com'
|
config.google_client_id = '785931784279-gd0g8on6sc0tuesj7cu763pitaiv2la8.apps.googleusercontent.com'
|
||||||
config.google_secret = 'UwzIcvtErv9c2-GIsNfIo7bA'
|
config.google_secret = 'UwzIcvtErv9c2-GIsNfIo7bA'
|
||||||
config.google_email = '785931784279-gd0g8on6sc0tuesj7cu763pitaiv2la8@developer.gserviceaccount.com'
|
|
||||||
|
|
||||||
if Rails.env == 'production'
|
if Rails.env == 'production'
|
||||||
config.desk_url = 'https://jamkazam.desk.com'
|
config.desk_url = 'https://jamkazam.desk.com'
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,8 @@ SampleApp::Application.configure do
|
||||||
|
|
||||||
# set CREATE_SESSION_AGREEMENT=0 if you don't want the autoclick behavior
|
# set CREATE_SESSION_AGREEMENT=0 if you don't want the autoclick behavior
|
||||||
config.autocheck_create_session_agreement = ENV['CREATE_SESSION_AGREEMENT'] ? ENV['CREATE_SESSION_AGREEMENT'] == "1" : true
|
config.autocheck_create_session_agreement = ENV['CREATE_SESSION_AGREEMENT'] ? ENV['CREATE_SESSION_AGREEMENT'] == "1" : true
|
||||||
|
config.twitter_public_account = ""
|
||||||
|
config.recurly_subdomain = 'jamkazam-development'
|
||||||
|
|
||||||
config.send_join_session_email_notifications = true
|
config.send_join_session_email_notifications = true
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -92,5 +92,11 @@ SampleApp::Application.configure do
|
||||||
config.ftue_io_wait_time = 1
|
config.ftue_io_wait_time = 1
|
||||||
config.ftue_network_test_duration = 1
|
config.ftue_network_test_duration = 1
|
||||||
config.ftue_network_test_max_clients = 5
|
config.ftue_network_test_max_clients = 5
|
||||||
|
|
||||||
|
# Use Private API Keys to communicate with Recurly's API v2. See https://docs.recurly.com/api/basics/authentication to learn more.
|
||||||
|
config.recurly_private_api_key = '4631527f203b41848523125b3ae51341'
|
||||||
|
# Use Public Keys to identify your site when using Recurly.js. See https://docs.recurly.com/js/#include to learn more.
|
||||||
|
config.recurly_public_api_key = 'sc-s6G2OA80Rwyvsb1RmS3mAE'
|
||||||
|
config.recurly_subdomain = 'jamkazam-test'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
Recurly.api_key = Rails.configuration.recurly_private_api_key
|
||||||
|
Recurly.subdomain = Rails.configuration.recurly_subdomain
|
||||||
|
|
@ -188,6 +188,14 @@ SampleApp::Application.routes.draw do
|
||||||
match '/music_notations' => 'api_music_notations#create', :via => :post
|
match '/music_notations' => 'api_music_notations#create', :via => :post
|
||||||
match '/music_notations/:id' => 'api_music_notations#download', :via => :get, :as => :download_music_notation
|
match '/music_notations/:id' => 'api_music_notations#download', :via => :get, :as => :download_music_notation
|
||||||
|
|
||||||
|
# Jamtracks
|
||||||
|
match '/jamtracks' => 'api_jamtracks#index', :via => :get
|
||||||
|
|
||||||
|
# Shopping carts
|
||||||
|
match '/shopping_carts/add_jamtrack' => 'api_shopping_carts#add_jamtrack', :via => :post
|
||||||
|
match '/shopping_carts' => 'api_shopping_carts#index', :via => :get
|
||||||
|
match '/shopping_carts' => 'api_shopping_carts#remove_cart', :via => :delete
|
||||||
|
|
||||||
# RSVP requests
|
# RSVP requests
|
||||||
match '/rsvp_requests' => 'api_rsvp_requests#index', :via => :get
|
match '/rsvp_requests' => 'api_rsvp_requests#index', :via => :get
|
||||||
match '/rsvp_requests' => 'api_rsvp_requests#create', :via => :post
|
match '/rsvp_requests' => 'api_rsvp_requests#create', :via => :post
|
||||||
|
|
@ -222,6 +230,13 @@ SampleApp::Application.routes.draw do
|
||||||
|
|
||||||
match '/users/:id/set_password' => 'api_users#set_password', :via => :post
|
match '/users/:id/set_password' => 'api_users#set_password', :via => :post
|
||||||
|
|
||||||
|
# recurly
|
||||||
|
match '/recurly/create_account' => 'api_recurly#create_account', :via => :post
|
||||||
|
match '/recurly/get_account' => 'api_recurly#get_account', :via => :get
|
||||||
|
match '/recurly/billing_info' => 'api_recurly#billing_info', :via => :get
|
||||||
|
match '/recurly/update_billing_info' => 'api_recurly#update_billing_info', :via => :put
|
||||||
|
match '/recurly/place_order' => 'api_recurly#place_order', :via => :put
|
||||||
|
|
||||||
# login/logout
|
# login/logout
|
||||||
match '/auth_session' => 'api_users#auth_session_create', :via => :post
|
match '/auth_session' => 'api_users#auth_session_create', :via => :post
|
||||||
match '/auth_session' => 'api_users#auth_session_delete', :via => :delete
|
match '/auth_session' => 'api_users#auth_session_delete', :via => :delete
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,10 @@ namespace :db do
|
||||||
make_recording
|
make_recording
|
||||||
end
|
end
|
||||||
|
|
||||||
|
task populate_jam_track: :environment do
|
||||||
|
make_jam_track
|
||||||
|
end
|
||||||
|
|
||||||
# takes command line args: http://davidlesches.com/blog/passing-arguments-to-a-rails-rake-task
|
# takes command line args: http://davidlesches.com/blog/passing-arguments-to-a-rails-rake-task
|
||||||
task :populate_conversation, [:target_email] => :environment do |task, args|
|
task :populate_conversation, [:target_email] => :environment do |task, args|
|
||||||
populate_conversation(args.target_email)
|
populate_conversation(args.target_email)
|
||||||
|
|
@ -279,6 +283,10 @@ def make_recording
|
||||||
recording.save!(validate:false)
|
recording.save!(validate:false)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def make_jam_track
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
def populate_conversation(target_email)
|
def populate_conversation(target_email)
|
||||||
all_users = User.all
|
all_users = User.all
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
# require 'spec_helper'
|
||||||
|
#
|
||||||
|
# describe ApiRecurlyController do
|
||||||
|
# render_views
|
||||||
|
#
|
||||||
|
# let(:user) { FactoryGirl.create(:user) }
|
||||||
|
# let(:jamtrack) { FactoryGirl.create(:jam_track) }
|
||||||
|
#
|
||||||
|
# before(:each) do
|
||||||
|
# @billing_info = {}
|
||||||
|
# @billing_info[:first_name] = user.first_name
|
||||||
|
# @billing_info[:last_name] = user.last_name
|
||||||
|
# @billing_info[:address1] = 'Test Address 1'
|
||||||
|
# @billing_info[:address2] = 'Test Address 2'
|
||||||
|
# @billing_info[:city] = user.city
|
||||||
|
# @billing_info[:state] = user.state
|
||||||
|
# @billing_info[:country] = user.country
|
||||||
|
# @billing_info[:zip] = '12345'
|
||||||
|
# @billing_info[:number] = '4111-1111-1111-1111'
|
||||||
|
# @billing_info[:month] = '08'
|
||||||
|
# @billing_info[:year] = '2017'
|
||||||
|
# @billing_info[:verification_value] = '1111'
|
||||||
|
# controller.current_user = user
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# describe "start" do
|
||||||
|
# it "should create recurly account" do
|
||||||
|
# post :create_account, { :format => 'json', :billing_info => @billing_info}
|
||||||
|
# response_body = JSON.parse(response.body)
|
||||||
|
# puts response_body
|
||||||
|
# response.should be_success
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
|
@ -676,4 +676,62 @@ FactoryGirl.define do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
factory :jam_track_licensor, :class => JamRuby::JamTrackLicensor do
|
||||||
|
sequence(:name) { |n| "licensor-#{n}" }
|
||||||
|
sequence(:description) { |n| "description-#{n}" }
|
||||||
|
sequence(:attention) { |n| "attention-#{n}" }
|
||||||
|
sequence(:address_line_1) { |n| "address1-#{n}" }
|
||||||
|
sequence(:address_line_2) { |n| "address2-#{n}" }
|
||||||
|
sequence(:city) { |n| "city-#{n}" }
|
||||||
|
sequence(:state) { |n| "state-#{n}" }
|
||||||
|
sequence(:zip_code) { |n| "zipcode-#{n}" }
|
||||||
|
sequence(:contact) { |n| "contact-#{n}" }
|
||||||
|
sequence(:email) { |n| "email-#{n}" }
|
||||||
|
sequence(:phone) { |n| "phone-#{n}" }
|
||||||
|
end
|
||||||
|
|
||||||
|
factory :jam_track, :class => JamRuby::JamTrack do
|
||||||
|
sequence(:name) { |n| "jam-track-#{n}" }
|
||||||
|
sequence(:description) { |n| "description-#{n}" }
|
||||||
|
bpm 100.1
|
||||||
|
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}" }
|
||||||
|
pro 'ASCAP'
|
||||||
|
sales_region 'United States'
|
||||||
|
price 1.99
|
||||||
|
reproduction_royalty true
|
||||||
|
public_performance_royalty true
|
||||||
|
reproduction_royalty_amount 0.999
|
||||||
|
licensor_royalty_amount 0.999
|
||||||
|
pro_royalty_amount 0.999
|
||||||
|
|
||||||
|
ignore do
|
||||||
|
make_track true
|
||||||
|
end
|
||||||
|
|
||||||
|
genre JamRuby::Genre.first
|
||||||
|
association :licensor, factory: :jam_track_licensor
|
||||||
|
|
||||||
|
after(:create) do |jam_track, evaluator|
|
||||||
|
FactoryGirl.create(:jam_track_track, jam_track: jam_track) if evaluator.make_track
|
||||||
|
end
|
||||||
|
|
||||||
|
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
|
||||||
|
end
|
||||||
|
|
||||||
|
factory :jam_track_right, :class => JamRuby::JamTrackRight do
|
||||||
|
association :jam_track, factory: :jam_track
|
||||||
|
association :user, factory: :user
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,133 @@
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe "JamTrack Shopping", :js => true, :type => :feature, :capybara_feature => true do
|
||||||
|
|
||||||
|
let(:user) { FactoryGirl.create(:user) }
|
||||||
|
let(:jt_us) { FactoryGirl.create(:jam_track, sales_region: 'United States', make_track: true) }
|
||||||
|
let(:jt_ww) { FactoryGirl.create(:jam_track, sales_region: 'Worldwide', make_track: true) }
|
||||||
|
let(:jt_rock) { FactoryGirl.create(:jam_track, genre: JamRuby::Genre.find('rock'), make_track: true) }
|
||||||
|
|
||||||
|
before(:each) do
|
||||||
|
ShoppingCart.delete_all
|
||||||
|
JamTrack.delete_all
|
||||||
|
JamTrackTrack.delete_all
|
||||||
|
JamTrackLicensor.delete_all
|
||||||
|
|
||||||
|
jt_us.touch
|
||||||
|
jt_ww.touch
|
||||||
|
jt_rock.touch
|
||||||
|
|
||||||
|
stub_const("APP_CONFIG", web_config)
|
||||||
|
|
||||||
|
fast_signin user, "/client#/home"
|
||||||
|
find('.homecard.jamtrack h2', text: 'jamtracks')
|
||||||
|
end
|
||||||
|
|
||||||
|
def find_jamtrack jamtrack, options = {}
|
||||||
|
jamtrack_record = find(".jamtrack-record[jamtrack-id=\"#{jamtrack.id}\"]")
|
||||||
|
jamtrack_record.find('.detail-value', text: jamtrack.name)
|
||||||
|
jamtrack_record.find('.detail-value', text: jamtrack.recording_type)
|
||||||
|
jamtrack_record.find('.detail-value', text: jamtrack.original_artist)
|
||||||
|
jamtrack_record.find('.detail-value', text: jamtrack.genre.description)
|
||||||
|
jamtrack_record.find('.detail-value', text: [jamtrack.songwriter, jamtrack.publisher].join(', '))
|
||||||
|
jamtrack_record.find('.copyright-value', text: jamtrack.licensor.name)
|
||||||
|
jamtrack_record.find('.jamtrack-price', text: "$ #{jamtrack.price}")
|
||||||
|
|
||||||
|
if jamtrack.sales_region == 'United States'
|
||||||
|
jamtrack_record.find('a.license-us-why', text: 'why?').trigger(:click)
|
||||||
|
find('#jamtrack-availability-dialog h1', text: 'JamTrack Availability:')
|
||||||
|
find('#jamtrack-availability-dialog #dialog-close-button').trigger(:click)
|
||||||
|
end
|
||||||
|
|
||||||
|
jamtrack.jam_track_tracks.each do |track|
|
||||||
|
jamtrack_record.find('.instrument-desc', "#{track.instrument.description} ( #{track.part} }")
|
||||||
|
end
|
||||||
|
|
||||||
|
if options[:added_cart]
|
||||||
|
jamtrack_record.find('a.jamtrack-add-cart-disabled', text: 'Added to Cart')
|
||||||
|
else
|
||||||
|
jamtrack_record.find('a.jamtrack-add-cart.button-orange', text: 'Add to Cart')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def not_find_jamtrack jamtrack
|
||||||
|
should_not have_selector(".jamtrack-record[jamtrack-id=\"#{jamtrack.id}\"]")
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "Shopping" do
|
||||||
|
|
||||||
|
before(:each) do
|
||||||
|
visit "/client#/jamtrack"
|
||||||
|
find('h1', text: 'jamtracks')
|
||||||
|
find('a', text: 'What is a JamTrack?')
|
||||||
|
|
||||||
|
jk_select('Any', '#jamtrack-find-form #jamtrack_availability')
|
||||||
|
end
|
||||||
|
|
||||||
|
it "shows all JamTracks" do
|
||||||
|
find_jamtrack jt_us
|
||||||
|
find_jamtrack jt_ww
|
||||||
|
find_jamtrack jt_rock
|
||||||
|
end
|
||||||
|
|
||||||
|
it "filters with availability" do
|
||||||
|
jk_select('Worldwide', '#jamtrack-find-form #jamtrack_availability')
|
||||||
|
find_jamtrack jt_ww
|
||||||
|
not_find_jamtrack jt_us
|
||||||
|
not_find_jamtrack jt_rock
|
||||||
|
end
|
||||||
|
|
||||||
|
it "filters with genre" do
|
||||||
|
jk_select('Rock', '#jamtrack-find-form #jamtrack_genre')
|
||||||
|
find_jamtrack jt_rock
|
||||||
|
not_find_jamtrack jt_us
|
||||||
|
not_find_jamtrack jt_ww
|
||||||
|
end
|
||||||
|
|
||||||
|
it "filters with instrument" do
|
||||||
|
jk_select('Electric Guitar', '#jamtrack-find-form #jamtrack_instrument')
|
||||||
|
find_jamtrack jt_us
|
||||||
|
find_jamtrack jt_ww
|
||||||
|
find_jamtrack jt_rock
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "Shopping Carts" do
|
||||||
|
|
||||||
|
before(:each) do
|
||||||
|
visit "/client#/jamtrack"
|
||||||
|
find('h1', text: 'jamtracks')
|
||||||
|
find('a', text: 'What is a JamTrack?')
|
||||||
|
|
||||||
|
jk_select('Any', '#jamtrack-find-form #jamtrack_availability')
|
||||||
|
end
|
||||||
|
|
||||||
|
it "adds/deletes JamTrack to/from Cart" do
|
||||||
|
find("a.jamtrack-add-cart[data-jamtrack-id=\"#{jt_us.id}\"]").trigger(:click)
|
||||||
|
|
||||||
|
find('h1', text: 'shopping cart')
|
||||||
|
find('.cart-item-caption', text: "JamTrack: #{jt_us.name}")
|
||||||
|
find('.cart-item-price', text: "$ #{jt_us.price}")
|
||||||
|
|
||||||
|
find('a.button-orange', text: 'CONTINUE SHOPPING').trigger(:click)
|
||||||
|
jk_select('Any', '#jamtrack-find-form #jamtrack_availability')
|
||||||
|
find_jamtrack jt_us, {added_cart: true}
|
||||||
|
|
||||||
|
find('a.header-shopping-cart').trigger(:click)
|
||||||
|
find("a.remove-cart").trigger(:click)
|
||||||
|
find('a.button-orange', text: 'CONTINUE SHOPPING').trigger(:click)
|
||||||
|
jk_select('Any', '#jamtrack-find-form #jamtrack_availability')
|
||||||
|
|
||||||
|
find_jamtrack jt_us
|
||||||
|
|
||||||
|
find("a.jamtrack-add-cart[data-jamtrack-id=\"#{jt_us.id}\"]").trigger(:click)
|
||||||
|
find('a.button-orange', text: 'CONTINUE SHOPPING').trigger(:click)
|
||||||
|
find("a.jamtrack-add-cart[data-jamtrack-id=\"#{jt_ww.id}\"]").trigger(:click)
|
||||||
|
find('a.button-orange', text: 'CONTINUE SHOPPING').trigger(:click)
|
||||||
|
|
||||||
|
find('.shopping-sub-total', text: "Subtotal: $ #{jt_us.price + jt_ww.price}")
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -120,4 +120,54 @@ FactoryGirl.define do
|
||||||
latency_tester.save
|
latency_tester.save
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
factory :jam_track_licensor, :class => JamRuby::JamTrackLicensor do
|
||||||
|
sequence(:name) { |n| "licensor-#{n}" }
|
||||||
|
sequence(:description) { |n| "description-#{n}" }
|
||||||
|
sequence(:attention) { |n| "attention-#{n}" }
|
||||||
|
sequence(:address_line_1) { |n| "address1-#{n}" }
|
||||||
|
sequence(:address_line_2) { |n| "address2-#{n}" }
|
||||||
|
sequence(:city) { |n| "city-#{n}" }
|
||||||
|
sequence(:state) { |n| "state-#{n}" }
|
||||||
|
sequence(:zip_code) { |n| "zipcode-#{n}" }
|
||||||
|
sequence(:contact) { |n| "contact-#{n}" }
|
||||||
|
sequence(:email) { |n| "email-#{n}" }
|
||||||
|
sequence(:phone) { |n| "phone-#{n}" }
|
||||||
|
end
|
||||||
|
|
||||||
|
factory :jam_track, :class => JamRuby::JamTrack do
|
||||||
|
sequence(:name) { |n| "jam-track-#{n}" }
|
||||||
|
sequence(:description) { |n| "description-#{n}" }
|
||||||
|
bpm 100.1
|
||||||
|
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}" }
|
||||||
|
pro 'ASCAP'
|
||||||
|
sales_region 'United States'
|
||||||
|
price 1.99
|
||||||
|
reproduction_royalty true
|
||||||
|
public_performance_royalty true
|
||||||
|
reproduction_royalty_amount 0.999
|
||||||
|
licensor_royalty_amount 0.999
|
||||||
|
pro_royalty_amount 0.999
|
||||||
|
|
||||||
|
genre JamRuby::Genre.first
|
||||||
|
association :licensor, factory: :jam_track_licensor
|
||||||
|
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
|
||||||
|
end
|
||||||
|
|
||||||
|
factory :jam_track_right, :class => JamRuby::JamTrackRight do
|
||||||
|
association :jam_track, factory: :jam_track
|
||||||
|
association :user, factory: :user
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue