diff --git a/admin/app/admin/jam_track_right.rb b/admin/app/admin/jam_track_right.rb
index 48da8231a..e2cc0bbe9 100644
--- a/admin/app/admin/jam_track_right.rb
+++ b/admin/app/admin/jam_track_right.rb
@@ -1,20 +1,29 @@
require 'jam_ruby/recurly_client'
ActiveAdmin.register JamRuby::JamTrackRight, :as => 'JamTrackRights' do
- menu :label => 'Purchased JamTracks', :parent => 'JamTracks'
+ menu :label => 'Purchased JamTracks', :parent => 'Purchases'
- config.sort_order = 'updated_at DESC'
+ config.sort_order = 'created_at DESC'
config.batch_actions = false
#form :partial => 'form'
+ filter :user_id
+
+ filter :user_id,
+ :label => "USER ID", :required => false,
+ :wrapper_html => { :style => "list-style: none" }
+
+
+ filter :jam_track
+
index do
default_actions
- column "Order" do |right|
- link_to("Place", order_admin_jam_track_right_path(right)) + " | " +
- link_to("Refund", refund_admin_jam_track_right_path(right))
- end
+ #column "Order" do |right|
+ #link_to("Place", order_admin_jam_track_right_path(right)) + " | " +
+ # link_to("Refund", refund_admin_jam_track_right_path(right))
+ #end
column "Last Name" do |right|
right.user.last_name
@@ -23,13 +32,15 @@ ActiveAdmin.register JamRuby::JamTrackRight, :as => 'JamTrackRights' do
right.user.first_name
end
column "Jam Track" do |right|
- link_to(right.jam_track.name, admin_jam_track_right_path(right.jam_track))
+ link_to(right.jam_track.name, admin_jam_track_path(right.jam_track))
# right.jam_track
end
column "Plan Code" do |right|
-
right.jam_track.plan_code
end
+ column "Redeemed" do |right|
+ right.redeemed ? 'Y' : 'N'
+ end
end
@@ -42,6 +53,9 @@ ActiveAdmin.register JamRuby::JamTrackRight, :as => 'JamTrackRights' do
f.actions
end
+=begin
+
+
member_action :order, :method => :get do
right = JamTrackRight.where("id=?",params[:id]).first
user = right.user
@@ -84,4 +98,5 @@ ActiveAdmin.register JamRuby::JamTrackRight, :as => 'JamTrackRights' do
redirect_to admin_jam_track_rights_path, notice: "Issued full refund on #{right.jam_track} for #{right.user.to_s}"
end
end
+=end
end
\ No newline at end of file
diff --git a/admin/app/admin/recurly_transaction_web_hook.rb b/admin/app/admin/recurly_transaction_web_hook.rb
new file mode 100644
index 000000000..0c6942d82
--- /dev/null
+++ b/admin/app/admin/recurly_transaction_web_hook.rb
@@ -0,0 +1,40 @@
+ActiveAdmin.register JamRuby::RecurlyTransactionWebHook, :as => 'RecurlyHooks' do
+
+ menu :label => 'Recurly Transaction Hooks', :parent => 'Purchases'
+
+ config.sort_order = 'created_at DESC'
+ config.batch_actions = false
+
+ actions :all, :except => [:destroy]
+
+ #form :partial => 'form'
+
+
+ filter :transaction_type, :as => :select, :collection => JamRuby::RecurlyTransactionWebHook::HOOK_TYPES
+ filter :user_id,
+ :label => "USER ID", :required => false,
+ :wrapper_html => { :style => "list-style: none" }
+
+ filter :invoice_id
+
+ form :partial => 'form'
+
+ index do
+
+ default_actions
+
+ column :transaction_type
+ column :transaction_at
+ column :amount_in_cents
+ column 'Transaction' do |hook| link_to('Go to Recurly', Rails.application.config.recurly_root_url + "/transactions/#{hook.recurly_transaction_id}") end
+ column 'Invoice' do |hook| link_to(hook.invoice_number, Rails.application.config.recurly_root_url + "/invoices/#{hook.invoice_number}") end
+ column :admin_description
+ column 'User' do |hook| link_to("#{hook.user.email} (#{hook.user.name})", admin_user_path(hook.user.id)) end
+
+ #column "Order" do |right|
+ #link_to("Place", order_admin_jam_track_right_path(right)) + " | " +
+ # link_to("Refund", refund_admin_jam_track_right_path(right))
+ #end
+ end
+
+end
\ No newline at end of file
diff --git a/admin/app/views/admin/recurly_hooks/_form.html.slim b/admin/app/views/admin/recurly_hooks/_form.html.slim
new file mode 100644
index 000000000..3e1305e23
--- /dev/null
+++ b/admin/app/views/admin/recurly_hooks/_form.html.slim
@@ -0,0 +1,6 @@
+= semantic_form_for([:admin, resource], :html => {:multipart => true}, :url => resource.new_record? ? admin_recurly_transaction_web_hooks_path : "#{ENV['RAILS_RELATIVE_URL_ROOT']}/admin/recurly_hooks/#{resource.id}") do |f|
+ = f.semantic_errors *f.object.errors.keys
+ = f.inputs name: 'Recurly Web Hook fields' do
+ = f.input :admin_description, :input_html => { :rows=>1, :maxlength=>200, }, hint: "this will display on the user's payment history page"
+ = f.input :jam_track, collection: JamRuby::JamTrack.all, include_blank: true, hint: "Please indicate which JamTrack this refund for, if not set"
+ = f.actions
\ No newline at end of file
diff --git a/admin/config/application.rb b/admin/config/application.rb
index 102a03176..9add98380 100644
--- a/admin/config/application.rb
+++ b/admin/config/application.rb
@@ -83,6 +83,7 @@ module JamAdmin
config.external_port = ENV['EXTERNAL_PORT'] || 3000
config.external_protocol = ENV['EXTERNAL_PROTOCOL'] || 'http://'
config.external_root_url = "#{config.external_protocol}#{config.external_hostname}#{(config.external_port == 80 || config.external_port == 443) ? '' : ':' + config.external_port.to_s}"
+ config.recurly_root_url = 'https://jamkazam-development.recurly.com'
# where is rabbitmq?
config.rabbitmq_host = "localhost"
@@ -116,7 +117,7 @@ module JamAdmin
config.email_smtp_domain = 'www.jamkazam.com'
config.email_smtp_authentication = :plain
config.email_smtp_user_name = 'jamkazam'
- config.email_smtp_password = 'jamjamblueberryjam'
+ config.email_smtp_password = 'snorkeltoesniffyfarce1'
config.email_smtp_starttls_auto = true
config.facebook_app_id = ENV['FACEBOOK_APP_ID'] || '468555793186398'
diff --git a/admin/config/environments/development.rb b/admin/config/environments/development.rb
index ffd6b0e8f..b449898e8 100644
--- a/admin/config/environments/development.rb
+++ b/admin/config/environments/development.rb
@@ -43,4 +43,7 @@ JamAdmin::Application.configure do
# Show the logging configuration on STDOUT
config.show_log_configuration = true
+
+ config.email_generic_from = 'nobody-dev@jamkazam.com'
+ config.email_alerts_alias = 'alerts-dev@jamkazam.com'
end
diff --git a/db/manifest b/db/manifest
index bff3d4df6..074c9df06 100755
--- a/db/manifest
+++ b/db/manifest
@@ -282,3 +282,7 @@ add_genre_type.sql
add_description_to_perf_samples.sql
alter_genre_player_unique_constraint.sql
musician_search.sql
+signup_hints.sql
+packaging_notices.sql
+first_played_jamtrack_at.sql
+payment_history.sql
\ No newline at end of file
diff --git a/db/up/first_played_jamtrack_at.sql b/db/up/first_played_jamtrack_at.sql
new file mode 100644
index 000000000..aeddf7757
--- /dev/null
+++ b/db/up/first_played_jamtrack_at.sql
@@ -0,0 +1 @@
+ALTER TABLE users ADD COLUMN first_played_jamtrack_at TIMESTAMP;
\ No newline at end of file
diff --git a/db/up/jam_track_duration.sql b/db/up/jam_track_duration.sql
index a4dbee409..7c39e03ca 100644
--- a/db/up/jam_track_duration.sql
+++ b/db/up/jam_track_duration.sql
@@ -1 +1,9 @@
-ALTER TABLE jam_tracks ADD COLUMN duration INTEGER;
\ No newline at end of file
+DO $$
+ BEGIN
+ BEGIN
+ ALTER TABLE jam_tracks ADD COLUMN duration INTEGER;
+ EXCEPTION
+ WHEN duplicate_column THEN RAISE NOTICE 'column duration already exists in jam_tracks.';
+ END;
+ END;
+$$ LANGUAGE plpgsql;
\ No newline at end of file
diff --git a/db/up/packaging_notices.sql b/db/up/packaging_notices.sql
new file mode 100644
index 000000000..d3a5de551
--- /dev/null
+++ b/db/up/packaging_notices.sql
@@ -0,0 +1,3 @@
+ALTER TABLE jam_track_rights ADD COLUMN packaging_steps INTEGER;
+ALTER TABLE jam_track_rights ADD COLUMN current_packaging_step INTEGER;
+ALTER TABLE jam_track_rights ADD COLUMN last_step_at TIMESTAMP;
diff --git a/db/up/payment_history.sql b/db/up/payment_history.sql
new file mode 100644
index 000000000..cb350c61d
--- /dev/null
+++ b/db/up/payment_history.sql
@@ -0,0 +1,17 @@
+ALTER TABLE recurly_transaction_web_hooks ADD COLUMN admin_description VARCHAR;
+ALTER TABLE recurly_transaction_web_hooks ADD COLUMN jam_track_id VARCHAR(64) REFERENCES jam_tracks(id);
+
+CREATE VIEW payment_histories AS
+ SELECT id AS sale_id,
+ CAST(NULL as VARCHAR) AS recurly_transaction_web_hook_id,
+ user_id,
+ created_at,
+ 'sale' AS transaction_type
+ FROM sales s
+ UNION ALL
+ SELECT CAST(NULL as VARCHAR) AS sale_id,
+ id AS recurly_transaction_web_hook_id,
+ user_id,
+ transaction_at AS created_at,
+ transaction_type
+ FROM recurly_transaction_web_hooks;
\ No newline at end of file
diff --git a/db/up/preview_support_mp3.sql b/db/up/preview_support_mp3.sql
index 90dd1c642..8417e221b 100644
--- a/db/up/preview_support_mp3.sql
+++ b/db/up/preview_support_mp3.sql
@@ -1,4 +1,11 @@
-ALTER TABLE jam_track_tracks ADD COLUMN preview_mp3_url VARCHAR;
-ALTER TABLE jam_track_tracks ADD COLUMN preview_mp3_md5 VARCHAR;
-ALTER TABLE jam_track_tracks ADD COLUMN preview_mp3_length BIGINT;
-UPDATE jam_track_tracks SET preview_url = NULL where track_type = 'Master';
\ No newline at end of file
+DO $$
+ BEGIN
+ BEGIN
+ ALTER TABLE jam_track_tracks ADD COLUMN preview_mp3_url VARCHAR;
+ ALTER TABLE jam_track_tracks ADD COLUMN preview_mp3_md5 VARCHAR;
+ ALTER TABLE jam_track_tracks ADD COLUMN preview_mp3_length BIGINT;
+ EXCEPTION
+ WHEN duplicate_column THEN RAISE NOTICE 'preview mp3 columns already exist in jam_tracks';
+ END;
+ END;
+$$ LANGUAGE plpgsql;
\ No newline at end of file
diff --git a/db/up/signup_hints.sql b/db/up/signup_hints.sql
new file mode 100644
index 000000000..9a079e216
--- /dev/null
+++ b/db/up/signup_hints.sql
@@ -0,0 +1,12 @@
+CREATE TABLE signup_hints (
+ id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
+ anonymous_user_id VARCHAR(64) UNIQUE,
+ redirect_location VARCHAR,
+ want_jamblaster BOOLEAN NOT NULL DEFAULT FALSE,
+ user_id VARCHAR(64) REFERENCES users(id) ON DELETE CASCADE,
+ expires_at TIMESTAMP,
+ created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
+);
+
+ALTER TABLE users ADD COLUMN want_jamblaster BOOLEAN NOT NULL DEFAULT FALSE;
\ No newline at end of file
diff --git a/ruby/jt_metadata.json b/ruby/jt_metadata.json
new file mode 100644
index 000000000..9cf0ba195
--- /dev/null
+++ b/ruby/jt_metadata.json
@@ -0,0 +1 @@
+{"container_file": "/var/folders/fk/0ckzmddd4tq28kxbb09vckbr0000gn/T/d20150428-83245-1alsyg1/jam-track-19.jkz", "version": "0", "coverart": null, "rsa_priv_file": "/var/folders/fk/0ckzmddd4tq28kxbb09vckbr0000gn/T/d20150428-83245-1alsyg1/skey.pem", "tracks": [{"name": "/var/folders/fk/0ckzmddd4tq28kxbb09vckbr0000gn/T/d20150428-83245-1alsyg1/9599b114-0f66-4140-ae3a-078a4e0c0767.ogg", "trackName": "track_00"}], "rsa_pub_file": "/var/folders/fk/0ckzmddd4tq28kxbb09vckbr0000gn/T/d20150428-83245-1alsyg1/pkey.pem", "jamktrack_info": "/var/folders/fk/0ckzmddd4tq28kxbb09vckbr0000gn/T/tmp9PHU_9"}
\ No newline at end of file
diff --git a/ruby/lib/jam_ruby.rb b/ruby/lib/jam_ruby.rb
index 579068623..8fbdb9efd 100755
--- a/ruby/lib/jam_ruby.rb
+++ b/ruby/lib/jam_ruby.rb
@@ -20,11 +20,12 @@ require 'resque_mailer'
require 'rest-client'
require 'zip'
require 'csv'
+require 'tzinfo'
require "jam_ruby/constants/limits"
require "jam_ruby/constants/notification_types"
require "jam_ruby/constants/validation_messages"
-require "jam_ruby/errors/permission_error"
+require "jam_ruby/errors/jam_permission_error"
require "jam_ruby/errors/state_error"
require "jam_ruby/errors/jam_argument_error"
require "jam_ruby/errors/conflict_error"
@@ -100,6 +101,7 @@ require "jam_ruby/models/genre_player"
require "jam_ruby/models/genre"
require "jam_ruby/models/user"
require "jam_ruby/models/anonymous_user"
+require "jam_ruby/models/signup_hint"
require "jam_ruby/models/rsvp_request"
require "jam_ruby/models/rsvp_slot"
require "jam_ruby/models/rsvp_request_rsvp_slot"
@@ -205,6 +207,7 @@ require "jam_ruby/models/generic_state"
require "jam_ruby/models/score_history"
require "jam_ruby/models/jam_company"
require "jam_ruby/models/user_sync"
+require "jam_ruby/models/payment_history"
require "jam_ruby/models/video_source"
require "jam_ruby/models/text_message"
require "jam_ruby/models/sale"
diff --git a/ruby/lib/jam_ruby/app/mailers/admin_mailer.rb b/ruby/lib/jam_ruby/app/mailers/admin_mailer.rb
index c4addb5cc..f14d8e424 100644
--- a/ruby/lib/jam_ruby/app/mailers/admin_mailer.rb
+++ b/ruby/lib/jam_ruby/app/mailers/admin_mailer.rb
@@ -1,6 +1,6 @@
module JamRuby
# sends out a boring ale
- class AdminMailer < ActionMailer::Base
+ class AdminMailer < ActionMailer::Base
include SendGrid
@@ -14,9 +14,24 @@ module JamRuby
def alerts(options)
mail(to: APP_CONFIG.email_alerts_alias,
+ from: APP_CONFIG.email_generic_from,
body: options[:body],
content_type: "text/plain",
subject: options[:subject])
end
+
+ def recurly_alerts(user, options)
+
+ body = options[:body]
+ body << "\n\n"
+ body << "User " << user.admin_url + "\n"
+ body << "User's JamTracks " << user.jam_track_rights_admin_url + "\n"
+
+ mail(to: APP_CONFIG.email_recurly_notice,
+ from: APP_CONFIG.email_generic_from,
+ body: body,
+ content_type: "text/plain",
+ subject: options[:subject])
+ end
end
end
diff --git a/ruby/lib/jam_ruby/app/views/layouts/user_mailer.text.erb b/ruby/lib/jam_ruby/app/views/layouts/user_mailer.text.erb
index 78d40b50c..49655e237 100644
--- a/ruby/lib/jam_ruby/app/views/layouts/user_mailer.text.erb
+++ b/ruby/lib/jam_ruby/app/views/layouts/user_mailer.text.erb
@@ -4,8 +4,8 @@
<%= yield %>
<% end %>
-<% unless @suppress_user_has_account_footer == true %>
-This email was sent to you because you have an account at JamKazam / http://www.jamkazam.com. Visit your profile page to unsubscribe: http://www.jamkazam.com/unsubscribe/<%=@user.unsubscribe_token%>.
+<% unless @user.nil? || @suppress_user_has_account_footer == true %>
+This email was sent to you because you have an account at JamKazam / http://www.jamkazam.com. To unsubscribe: http://www.jamkazam.com/unsubscribe/<%=@user.unsubscribe_token%>.
<% end %>
Copyright <%= Time.now.year %> JamKazam, Inc. All rights reserved.
diff --git a/ruby/lib/jam_ruby/errors/jam_permission_error.rb b/ruby/lib/jam_ruby/errors/jam_permission_error.rb
new file mode 100644
index 000000000..531791df1
--- /dev/null
+++ b/ruby/lib/jam_ruby/errors/jam_permission_error.rb
@@ -0,0 +1,5 @@
+module JamRuby
+ class JamPermissionError < Exception
+
+ end
+end
\ No newline at end of file
diff --git a/ruby/lib/jam_ruby/errors/permission_error.rb b/ruby/lib/jam_ruby/errors/permission_error.rb
deleted file mode 100644
index f0b4e3a2f..000000000
--- a/ruby/lib/jam_ruby/errors/permission_error.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-module JamRuby
- class PermissionError < Exception
-
- end
-end
\ No newline at end of file
diff --git a/ruby/lib/jam_ruby/jam_track_importer.rb b/ruby/lib/jam_ruby/jam_track_importer.rb
index 5535f6e08..f4ce1e6de 100644
--- a/ruby/lib/jam_ruby/jam_track_importer.rb
+++ b/ruby/lib/jam_ruby/jam_track_importer.rb
@@ -91,13 +91,15 @@ module JamRuby
true
end
- def synchronize_metadata(jam_track, metadata, metalocation, original_artist, name)
+ def synchronize_metadata(jam_track, metadata, metalocation, original_artist, name, options)
metadata ||= {}
self.name = metadata["name"] || name
if jam_track.new_record?
- jam_track.id = "#{JamTrack.count + 1}" # default is UUID, but the initial import was based on auto-increment ID, so we'll maintain that
+ latest_jamtrack = JamTrack.order('created_at desc').first
+ id = latest_jamtrack.nil? ? 1 : latest_jamtrack.id.to_i + 1
+ jam_track.id = "#{id}" # default is UUID, but the initial import was based on auto-increment ID, so we'll maintain that
jam_track.status = 'Staging'
jam_track.metalocation = metalocation
jam_track.original_artist = metadata["original_artist"] || original_artist
@@ -107,13 +109,20 @@ module JamRuby
jam_track.price = 1.99
jam_track.reproduction_royalty_amount = 0
jam_track.licensor_royalty_amount = 0
- jam_track.sales_region = 'United States'
+ jam_track.sales_region = 'Worldwide'
jam_track.recording_type = 'Cover'
jam_track.description = "This is a JamTrack audio file for use exclusively with the JamKazam service. This JamTrack is a high quality cover of the #{jam_track.original_artist} song \"#{jam_track.name}\"."
else
- #@@log.debug("#{self.name} skipped because it already exists in database")
- finish("jam_track_exists", "")
- return false
+ if !options[:resync_audio]
+ #@@log.debug("#{self.name} skipped because it already exists in database")
+ finish("jam_track_exists", "")
+ return false
+ else
+ # jamtrack exists, leave it be
+ return true
+ end
+
+
end
saved = jam_track.save
@@ -318,24 +327,31 @@ module JamRuby
def set_custom_weight(track)
weight = 5
- case track.instrument_id
- when 'electric guitar'
- weight = 1
- when 'acoustic guitar'
- weight = 2
- when 'drums'
- weight = 3
- when 'keys'
- weight = 4
- when 'computer'
- weight = 10
- else
- weight = 5
- end
- if track.track_type == 'Master'
- weight = 1000
+ # if there are any persisted tracks, do not sort from scratch; just stick new stuff at the end
+
+ if track.persisted?
+ weight = track.position
+ else
+ case track.instrument_id
+ when 'electric guitar'
+ weight = 100
+ when 'acoustic guitar'
+ weight = 200
+ when 'drums'
+ weight = 300
+ when 'keys'
+ weight = 400
+ when 'computer'
+ weight = 600
+ else
+ weight = 500
+ end
+ if track.track_type == 'Master'
+ weight = 1000
+ end
end
+
weight
end
@@ -346,10 +362,19 @@ module JamRuby
a_weight <=> b_weight
end
+ # default to 1, but if there are any persisted tracks, this will get manipulated to be +1 the highest persisted track
position = 1
sorted_tracks.each do |track|
- track.position = position
- position = position + 1
+ if track.persisted?
+ # persisted tracks should be sorted at the beginning of the sorted_tracks,
+ # so this just keeps moving the 'position builder' up to +1 of the last persisted track
+ position = track.position + 1
+ else
+ track.position = position
+ position = position + 1
+ end
+
+
end
sorted_tracks[sorted_tracks.length - 1].position = 1000
@@ -359,11 +384,40 @@ module JamRuby
def synchronize_audio(jam_track, metadata, s3_path, skip_audio_upload)
+ attempt_to_match_existing_tracks = true
+
+ # find all wav files in the JamTracks s3 bucket
wav_files = fetch_wav_files(s3_path)
tracks = []
wav_files.each do |wav_file|
+
+ if attempt_to_match_existing_tracks
+ # try to find a matching track from the JamTrack based on the name of the 44.1 path
+ basename = File.basename(wav_file)
+ ogg_44100_filename = File.basename(basename, ".wav") + "-44100.ogg"
+
+ found_track = nil
+ jam_track.jam_track_tracks.each do |jam_track_track|
+
+ if jam_track_track["url_44"] && jam_track_track["url_44"].end_with?(ogg_44100_filename)
+ # found a match!
+ found_track = jam_track_track
+ break
+ end
+ end
+
+ if found_track
+ @@log.debug("found a existing track to reuse")
+ found_track.original_audio_s3_path = wav_file
+ tracks << found_track
+ next
+ end
+ end
+
+ @@log.debug("no existing track found; creating a new one")
+
track = JamTrackTrack.new
track.original_audio_s3_path = wav_file
@@ -388,6 +442,15 @@ module JamRuby
tracks << track
end
+ jam_track.jam_track_tracks.each do |jam_track_track|
+ # delete all jam_track_tracks not in the tracks array
+ unless tracks.include?(jam_track_track)
+ @@log.info("destroying removed JamTrackTrack #{jam_track_track.inspect}")
+ jam_track_track.destroy # should also delete s3 files associated with this jamtrack
+ end
+ end
+
+ @@log.info("sorting tracks")
tracks = sort_tracks(tracks)
jam_track.jam_track_tracks = tracks
@@ -481,15 +544,16 @@ module JamRuby
track["length_48"] = File.new(ogg_48000).size
synchronize_duration(jam_track, ogg_44100)
+ jam_track.save!
# convert entire master ogg file to mp3, and push both to public destination
- preview_succeeded = synchronize_master_preview(track, tmp_dir, ogg_44100, ogg_44100_digest) if track.track_type == 'Master'
+ if track.track_type == 'Master'
+ preview_succeeded = synchronize_master_preview(track, tmp_dir, ogg_44100, ogg_44100_digest)
- if !preview_succeeded
- return false
+ if !preview_succeeded
+ return false
+ end
end
-
-
end
track.save!
@@ -596,7 +660,7 @@ module JamRuby
original_artist = parsed_metalocation[1]
name = parsed_metalocation[2]
- success = synchronize_metadata(jam_track, metadata, metalocation, original_artist, name)
+ success = synchronize_metadata(jam_track, metadata, metalocation, original_artist, name, options)
return unless success
@@ -614,8 +678,8 @@ module JamRuby
def synchronize_recurly(jam_track)
begin
recurly = RecurlyClient.new
- # no longer create JamTrack plans: VRFS-3028
- # recurly.create_jam_track_plan(jam_track) unless recurly.find_jam_track_plan(jam_track)
+ # no longer create JamTrack plans: VRFS-3028
+ # recurly.create_jam_track_plan(jam_track) unless recurly.find_jam_track_plan(jam_track)
rescue RecurlyClientError => x
finish('recurly_create_plan', x.errors.to_s)
return false
diff --git a/ruby/lib/jam_ruby/jam_tracks_manager.rb b/ruby/lib/jam_ruby/jam_tracks_manager.rb
index 9322c3dbd..36a19c960 100644
--- a/ruby/lib/jam_ruby/jam_tracks_manager.rb
+++ b/ruby/lib/jam_ruby/jam_tracks_manager.rb
@@ -22,9 +22,21 @@ module JamRuby
save_jam_track_right_jkz(jam_track_right, sample_rate)
end
+ # increment the step, which causes a notification to be sent to the client so it can keep the UI fresh as the packaging step goes on
+ def bump_step(jam_track_right, step)
+ last_step_at = Time.now
+ jam_track_right.current_packaging_step = step
+ jam_track_right.last_step_at = Time.now
+ JamTrackRight.where(:id => jam_track_right.id).update_all(last_step_at: last_step_at, current_packaging_step: step)
+ SubscriptionMessage.jam_track_signing_job_change(jam_track_right)
+ step = step + 1
+ step
+ end
+
def save_jam_track_right_jkz(jam_track_right, sample_rate=48)
jam_track = jam_track_right.jam_track
py_root = APP_CONFIG.jamtracks_dir
+ step = 0
Dir.mktmpdir do |tmp_dir|
jam_file_opts=""
jam_track.jam_track_tracks.each do |jam_track_track|
@@ -36,6 +48,9 @@ module JamRuby
track_filename = File.join(tmp_dir, nm)
track_url = jam_track_track.sign_url(120, sample_rate)
@@log.info("downloading #{track_url} to #{track_filename}")
+
+ step = bump_step(jam_track_right, step)
+
copy_url_to_file(track_url, track_filename)
jam_file_opts << " -i #{Shellwords.escape("#{track_filename}+#{jam_track_track.part}")}"
end
@@ -48,6 +63,8 @@ module JamRuby
version = jam_track.version
@@log.info "Executing python source in #{py_file}, outputting to #{tmp_dir} (#{output_jkz})"
+ step = bump_step(jam_track_right, step)
+
# From http://stackoverflow.com/questions/690151/getting-output-of-system-calls-in-ruby/5970819#5970819:
cli = "python #{py_file} -D -k #{sku} -p #{Shellwords.escape(tmp_dir)}/pkey.pem -s #{Shellwords.escape(tmp_dir)}/skey.pem #{jam_file_opts} -o #{Shellwords.escape(output_jkz)} -t #{Shellwords.escape(title)} -V #{Shellwords.escape(version)}"
Open3.popen3(cli) do |stdin, stdout, stderr, wait_thr|
diff --git a/ruby/lib/jam_ruby/lib/subscription_message.rb b/ruby/lib/jam_ruby/lib/subscription_message.rb
index ec161ec8f..6be9f7d16 100644
--- a/ruby/lib/jam_ruby/lib/subscription_message.rb
+++ b/ruby/lib/jam_ruby/lib/subscription_message.rb
@@ -22,7 +22,7 @@ module JamRuby
end
def self.jam_track_signing_job_change(jam_track_right)
- Notification.send_subscription_message('jam_track_right', jam_track_right.id.to_s, {signing_state: jam_track_right.signing_state}.to_json )
+ Notification.send_subscription_message('jam_track_right', jam_track_right.id.to_s, {signing_state: jam_track_right.signing_state, current_packaging_step: jam_track_right.current_packaging_step, packaging_steps: jam_track_right.packaging_steps}.to_json )
end
end
end
diff --git a/ruby/lib/jam_ruby/models/active_music_session.rb b/ruby/lib/jam_ruby/models/active_music_session.rb
index 04724695c..2addd2266 100644
--- a/ruby/lib/jam_ruby/models/active_music_session.rb
+++ b/ruby/lib/jam_ruby/models/active_music_session.rb
@@ -7,7 +7,7 @@ module JamRuby
self.table_name = 'active_music_sessions'
- attr_accessor :legal_terms, :max_score, :opening_jam_track, :opening_recording, :opening_backing_track, :opening_metronome
+ attr_accessor :legal_terms, :max_score, :opening_jam_track, :opening_recording, :opening_backing_track, :opening_metronome, :jam_track_id
belongs_to :claimed_recording, :class_name => "JamRuby::ClaimedRecording", :foreign_key => "claimed_recording_id", :inverse_of => :playing_sessions
belongs_to :claimed_recording_initiator, :class_name => "JamRuby::User", :inverse_of => :playing_claimed_recordings, :foreign_key => "claimed_recording_initiator_id"
diff --git a/ruby/lib/jam_ruby/models/after_signup_hint.rb b/ruby/lib/jam_ruby/models/after_signup_hint.rb
deleted file mode 100644
index e5c364e7e..000000000
--- a/ruby/lib/jam_ruby/models/after_signup_hint.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-module JamRuby
- class AfterSignupHint < ActiveRecord::Base
-
- before_create :generate_lookup_id
-
- def self.delete_old
- FacebookSignup.where("created_at < :week", {:week => 1.week.ago}).delete_all
- end
-
- private
- def generate_lookup_id
- self.lookup_id = SecureRandom.urlsafe_base64
- end
- end
-end
diff --git a/ruby/lib/jam_ruby/models/anonymous_user.rb b/ruby/lib/jam_ruby/models/anonymous_user.rb
index 0a843185a..bd3037922 100644
--- a/ruby/lib/jam_ruby/models/anonymous_user.rb
+++ b/ruby/lib/jam_ruby/models/anonymous_user.rb
@@ -11,7 +11,7 @@ module JamRuby
end
def shopping_carts
- ShoppingCart.where(anonymous_user_id: @id)
+ ShoppingCart.where(anonymous_user_id: @id).order('created_at DESC')
end
def destroy_all_shopping_carts
diff --git a/ruby/lib/jam_ruby/models/band.rb b/ruby/lib/jam_ruby/models/band.rb
index cfd554d2b..b4232553f 100644
--- a/ruby/lib/jam_ruby/models/band.rb
+++ b/ruby/lib/jam_ruby/models/band.rb
@@ -163,14 +163,14 @@ module JamRuby
# ensure person creating this Band is a Musician
unless user.musician?
- raise PermissionError, "must be a musician"
+ raise JamPermissionError, "must be a musician"
end
band = id.blank? ? Band.new : Band.find(id)
# ensure user updating Band details is a Band member
unless band.new_record? || band.users.exists?(user)
- raise PermissionError, ValidationMessages::USER_NOT_BAND_MEMBER_VALIDATION_ERROR
+ raise JamPermissionError, ValidationMessages::USER_NOT_BAND_MEMBER_VALIDATION_ERROR
end
band.name = params[:name] if params.has_key?(:name)
diff --git a/ruby/lib/jam_ruby/models/claimed_recording.rb b/ruby/lib/jam_ruby/models/claimed_recording.rb
index 7aa73440a..462ce6b58 100644
--- a/ruby/lib/jam_ruby/models/claimed_recording.rb
+++ b/ruby/lib/jam_ruby/models/claimed_recording.rb
@@ -41,7 +41,7 @@ module JamRuby
# params is a hash, and everything is optional
def update_fields(user, params)
if user != self.user
- raise PermissionError, "user doesn't own claimed_recording"
+ raise JamPermissionError, "user doesn't own claimed_recording"
end
self.name = params[:name]
@@ -53,7 +53,7 @@ module JamRuby
def discard(user)
if user != self.user
- raise PermissionError, "user doesn't own claimed_recording"
+ raise JamPermissionError, "user doesn't own claimed_recording"
end
ClaimedRecording.where(:id => id).update_all(:discarded => true )
@@ -96,11 +96,11 @@ module JamRuby
target_user = params[:user]
- raise PermissionError, "must specify current user" unless user
+ raise JamPermissionError, "must specify current user" unless user
raise "user must be specified" unless target_user
if target_user != user.id
- raise PermissionError, "unable to view another user's favorites"
+ raise JamPermissionError, "unable to view another user's favorites"
end
query = ClaimedRecording.limit(limit).order('created_at DESC').offset(start)
diff --git a/ruby/lib/jam_ruby/models/jam_track.rb b/ruby/lib/jam_ruby/models/jam_track.rb
index b08533c1e..594358ee3 100644
--- a/ruby/lib/jam_ruby/models/jam_track.rb
+++ b/ruby/lib/jam_ruby/models/jam_track.rb
@@ -60,7 +60,10 @@ module JamRuby
# has_many :plays, :class_name => "JamRuby::PlayablePlay", :foreign_key => :jam_track_id, :dependent => :destroy
# VRFS-2916 jam_tracks.id is varchar: ADD
has_many :plays, :class_name => "JamRuby::PlayablePlay", :as => :playable, :dependent => :destroy
-
+
+ # when we know what JamTrack this refund is related to, these are associated
+ belongs_to :recurly_transactions, class_name: 'JamRuby::RecurlyTransactionWebHook'
+
accepts_nested_attributes_for :jam_track_tracks, allow_destroy: true
accepts_nested_attributes_for :jam_track_tap_ins, allow_destroy: true
@@ -161,21 +164,75 @@ module JamRuby
query = query.where("original_artist=?", options[:artist])
end
+ if options[:id].present?
+ query = query.where("jam_tracks.id=?", options[:id])
+ end
if options[:group_artist]
query = query.select("original_artist, array_agg(jam_tracks.id) AS id, MIN(name) AS name, MIN(description) AS description, MIN(recording_type) AS recording_type, MIN(original_artist) AS original_artist, MIN(songwriter) AS songwriter, MIN(publisher) AS publisher, MIN(sales_region) AS sales_region, MIN(price) AS price, MIN(version) AS version, MIN(genre_id) AS genre_id")
query = query.group("original_artist")
query = query.order('jam_tracks.original_artist')
else
- query = query.group("jam_tracks.id")
- query = query.order('jam_tracks.name')
+ query = query.group("jam_tracks.id")
+ query = query.order('jam_tracks.original_artist, jam_tracks.name')
end
-
+
query = query.where("jam_tracks.status = ?", 'Production') unless user.admin
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.where("jam_tracks.sales_region = '#{options[:availability]}'") unless options[:availability].blank?
+
+
+ if query.length == 0
+ [query, nil]
+ elsif query.length < limit
+ [query, nil]
+ else
+ [query, start + limit]
+ end
+ end
+
+
+ # provides artist names and how many jamtracks are available for each
+ def artist_index(options, user)
+ if options[:page]
+ page = options[:page].to_i
+ per_page = options[:per_page].to_i
+
+ if per_page == 0
+ # try and see if limit was specified
+ limit = options[:limit]
+ limit ||= 100
+ limit = limit.to_i
+ else
+ limit = per_page
+ end
+
+ start = (page -1 )* per_page
+ limit = per_page
+ else
+ limit = options[:limit]
+ limit ||= 100
+ limit = limit.to_i
+
+ start = options[:start].presence
+ start = start.to_i || 0
+
+ page = 1 + start/limit
+ per_page = limit
+ end
+
+
+ query = JamTrack.paginate(page: page, per_page: per_page)
+ query = query.select("original_artist, count(original_artist) AS song_count")
+ query = query.group("original_artist")
+ query = query.order('jam_tracks.original_artist')
+
+ query = query.where("jam_tracks.status = ?", 'Production') unless user.admin
+ 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?
+
if query.length == 0
[query, nil]
@@ -192,6 +249,10 @@ module JamRuby
JamTrackTrack.where(jam_track_id: self.id).where(track_type: 'Master').first
end
+ def stem_tracks
+ JamTrackTrack.where(jam_track_id: self.id).where(track_type: 'Track')
+ end
+
def can_download?(user)
owners.include?(user)
end
diff --git a/ruby/lib/jam_ruby/models/jam_track_right.rb b/ruby/lib/jam_ruby/models/jam_track_right.rb
index f5abb1353..a5e127d78 100644
--- a/ruby/lib/jam_ruby/models/jam_track_right.rb
+++ b/ruby/lib/jam_ruby/models/jam_track_right.rb
@@ -29,7 +29,7 @@ module JamRuby
# try to catch major transitions:
# if just queue time changes, start time changes, or signed time changes, send out a notice
- if signing_queued_at_was != signing_queued_at || signing_started_at_was != signing_started_at || last_signed_at_was != last_signed_at
+ if signing_queued_at_was != signing_queued_at || signing_started_at_was != signing_started_at || last_signed_at_was != last_signed_at || current_packaging_step != current_packaging_step_was || packaging_steps != packaging_steps_was
SubscriptionMessage.jam_track_signing_job_change(self)
end
end
@@ -148,7 +148,11 @@ module JamRuby
if signed
state = 'SIGNED'
elsif signing_started_at
- if Time.now - signing_started_at > APP_CONFIG.signing_job_run_max_time
+ # the maximum amount of time the packaging job can take is 10 seconds * num steps. For a 10 track song, this will be 110 seconds. It's a bit long.
+ signing_job_run_max_time = packaging_steps * 10
+ if Time.now - signing_started_at > signing_job_run_max_time
+ state = 'SIGNING_TIMEOUT'
+ elsif Time.now - last_step_at > APP_CONFIG.signing_step_max_time
state = 'SIGNING_TIMEOUT'
else
state = 'SIGNING'
@@ -169,6 +173,10 @@ module JamRuby
def update_download_count(count=1)
self.download_count = self.download_count + count
self.last_downloaded_at = Time.now
+
+ if self.signed
+ self.downloaded_since_sign = true
+ end
end
def self.list_keys(user, jamtracks)
diff --git a/ruby/lib/jam_ruby/models/jam_track_track.rb b/ruby/lib/jam_ruby/models/jam_track_track.rb
index 41514b2f8..2b74a5c53 100644
--- a/ruby/lib/jam_ruby/models/jam_track_track.rb
+++ b/ruby/lib/jam_ruby/models/jam_track_track.rb
@@ -10,6 +10,7 @@ module JamRuby
@@log = Logging.logger[JamTrackTrack]
+ before_destroy :delete_s3_files
# Because JamTrackImporter imports audio files now, and because also the mere presence of this causes serious issues when updating the model (because reset of url_44 to something bogus), I've removed these
#mount_uploader :url_48, JamTrackTrackUploader
@@ -20,6 +21,8 @@ module JamRuby
attr_accessor :original_audio_s3_path, :skip_uploader
+ before_destroy :delete_s3_files
+
validates :position, presence: true, numericality: {only_integer: true}, length: {in: 1..1000}
validates :part, length: {maximum: 25}
validates :track_type, inclusion: {in: TRACK_TYPE }
@@ -120,6 +123,13 @@ module JamRuby
end
end
+ def delete_s3_files
+ s3_manager.delete(self[:url_44]) if self[:url_44] && s3_manager.exists?(self[:url_44])
+ s3_manager.delete(self[:url_48]) if self[:url_48] && s3_manager.exists?(self[:url_48])
+ s3_public_manager.delete(self[:preview_url]) if self[:preview_url] && s3_public_manager.exists?(self[:preview_url])
+ s3_public_manager.delete(self[:preview_mp3_url]) if self[:preview_mp3_url] && s3_public_manager.exists?(self[:preview_mp3_url])
+ end
+
private
def normalize_position
parent = self.jam_track
diff --git a/ruby/lib/jam_ruby/models/mix.rb b/ruby/lib/jam_ruby/models/mix.rb
index d5c7bd364..6e894561a 100644
--- a/ruby/lib/jam_ruby/models/mix.rb
+++ b/ruby/lib/jam_ruby/models/mix.rb
@@ -4,6 +4,8 @@ module JamRuby
MAX_MIX_TIME = 7200 # 2 hours
+ @@log = Logging.logger[Mix]
+
before_destroy :delete_s3_files
self.primary_key = 'id'
@@ -137,15 +139,67 @@ module JamRuby
one_day = 60 * 60 * 24
jam_track_offset = 0
+ jam_track_seek = 0
+
+ was_jamtrack_played = false
if recording.timeline
recording_timeline_data = JSON.parse(recording.timeline)
+ # did the jam track play at all?
+ jam_track_isplaying = recording_timeline_data["jam_track_isplaying"]
recording_start_time = recording_timeline_data["recording_start_time"]
jam_track_play_start_time = recording_timeline_data["jam_track_play_start_time"]
jam_track_recording_start_play_offset = recording_timeline_data["jam_track_recording_start_play_offset"]
- jam_track_offset = -jam_track_recording_start_play_offset
+ if jam_track_play_start_time != 0
+ was_jamtrack_played = true
+
+ # how long did the JamTrack play? not needed because we limit on the input tracks, which represents how long the recording is, too
+ jam_track_play_time = recording_timeline_data["jam_track_play_time"]
+
+
+ offset = jam_track_play_start_time - recording_start_time
+
+ @@log.debug("base offset = #{offset}")
+ if offset >= 0
+ # jamtrack started after recording, so buffer with silence as necessary\
+
+ if jam_track_recording_start_play_offset < 0
+ @@log.info("prelude captured. offsetting further by #{-jam_track_recording_start_play_offset}")
+ # a negative jam_track_recording_start_play_offset indicates prelude, i.e., silence
+ # so add it to the offset to add more silence as necessary
+ offset = offset + -jam_track_recording_start_play_offset
+ jam_track_offset = offset
+ else
+ @@log.info("positive jamtrack offset; seeking into jamtrack by #{jam_track_recording_start_play_offset}")
+ # a positive jam_track_recording_start_play_offset means we need to cut into the jamtrack
+ jam_track_seek = jam_track_recording_start_play_offset
+ jam_track_offset = offset
+ end
+ else
+ # jamtrack started before recording, so we can seek into it to make up for the missing parts
+
+ if jam_track_recording_start_play_offset < 0
+ @@log.info("partial prelude captured. offset becomes jamtrack offset#{-jam_track_recording_start_play_offset}")
+ # a negative jam_track_recording_start_play_offset indicates prelude, i.e., silence
+ # so add it to the offset to add more silence as necessary
+ jam_track_offset = -jam_track_recording_start_play_offset
+ else
+ @@log.info("no prelude captured. offset becomes jamtrack offset=#{jam_track_recording_start_play_offset}")
+
+ jam_track_offset = 0
+ jam_track_seek = jam_track_recording_start_play_offset
+ end
+
+
+ # also, ignore jam_track_recording_start_play_offset - it simply matches the offset in this case
+ end
+
+ @@log.info("computed values. jam_track_offset=#{jam_track_offset} jam_track_seek=#{jam_track_seek}")
+
+
+ end
end
manifest = { "files" => [], "timeline" => [] }
@@ -154,7 +208,7 @@ module JamRuby
# this 'pick limiter' logic will ensure that we set a limiter on the 1st recorded_track we come across.
pick_limiter = false
- if recording.is_jamtrack_recording?
+ if was_jamtrack_played
# we only use the limiter feature if this is a JamTrack recording
# by setting this to true, the 1st recorded_track in the database will be the limiter
pick_limiter = true
@@ -171,27 +225,29 @@ module JamRuby
mix_params << { "level" => 1.0, "balance" => 0 }
end
- recording.recorded_jam_track_tracks.each do |recorded_jam_track_track|
- manifest["files"] << { "filename" => recorded_jam_track_track.jam_track_track.sign_url(one_day), "codec" => "vorbis", "offset" => jam_track_offset }
- # let's look for level info from the client
- level = 1.0 # default value - means no effect
- if recorded_jam_track_track.timeline
+ if was_jamtrack_played
+ recording.recorded_jam_track_tracks.each do |recorded_jam_track_track|
+ manifest["files"] << { "filename" => recorded_jam_track_track.jam_track_track.sign_url(one_day, sample_rate=44), "codec" => "vorbis", "offset" => jam_track_offset, "seek" => jam_track_seek }
+ # let's look for level info from the client
+ level = 1.0 # default value - means no effect
+ if recorded_jam_track_track.timeline
- timeline_data = JSON.parse(recorded_jam_track_track.timeline)
+ timeline_data = JSON.parse(recorded_jam_track_track.timeline)
- # always take the 1st entry for now
- first = timeline_data[0]
+ # always take the 1st entry for now
+ first = timeline_data[0]
- if first["mute"]
- # mute equates to no noise
- level = 0.0
- else
- # otherwise grab the left channel...
- level = first["vol_l"]
+ if first["mute"]
+ # mute equates to no noise
+ level = 0.0
+ else
+ # otherwise grab the left channel...
+ level = first["vol_l"]
+ end
end
- end
- mix_params << { "level" => level, "balance" => 0 }
+ mix_params << { "level" => level, "balance" => 0 }
+ end
end
manifest["timeline"] << { "timestamp" => 0, "mix" => mix_params }
diff --git a/ruby/lib/jam_ruby/models/notification.rb b/ruby/lib/jam_ruby/models/notification.rb
index b0cb8a3bb..db4018ab8 100644
--- a/ruby/lib/jam_ruby/models/notification.rb
+++ b/ruby/lib/jam_ruby/models/notification.rb
@@ -210,7 +210,7 @@ module JamRuby
return "New message about session."
when NotificationTypes::JAM_TRACK_SIGN_COMPLETE
- return "Jam Track is ready for download."
+ return "JamTrack is ready for download."
# recording notifications
when NotificationTypes::MUSICIAN_RECORDING_SAVED
diff --git a/ruby/lib/jam_ruby/models/payment_history.rb b/ruby/lib/jam_ruby/models/payment_history.rb
new file mode 100644
index 000000000..4862e4dd1
--- /dev/null
+++ b/ruby/lib/jam_ruby/models/payment_history.rb
@@ -0,0 +1,39 @@
+module JamRuby
+ class PaymentHistory < ActiveRecord::Base
+
+ self.table_name = 'payment_histories'
+
+ belongs_to :sale
+ belongs_to :recurly_transaction_web_hook
+
+
+ def self.index(user, params = {})
+
+ limit = params[:per_page]
+ limit ||= 20
+ limit = limit.to_i
+
+ query = PaymentHistory.limit(limit)
+ .includes(sale: [:sale_line_items], recurly_transaction_web_hook:[])
+ .where(user_id: user.id)
+ .where("transaction_type = 'sale' OR transaction_type = 'refund' OR transaction_type = 'void'")
+ .order('created_at DESC')
+
+
+ current_page = params[:page].nil? ? 1 : params[:page].to_i
+ next_page = current_page + 1
+
+ # will_paginate gem
+ query = query.paginate(:page => current_page, :per_page => limit)
+
+ if query.length == 0 # no more results
+ { query: query, next_page: nil}
+ elsif query.length < limit # no more results
+ { query: query, next_page: nil}
+ else
+ { query: query, next_page: next_page }
+ end
+
+ end
+ end
+end
\ No newline at end of file
diff --git a/ruby/lib/jam_ruby/models/recording.rb b/ruby/lib/jam_ruby/models/recording.rb
index cdb72816a..99f21c09e 100644
--- a/ruby/lib/jam_ruby/models/recording.rb
+++ b/ruby/lib/jam_ruby/models/recording.rb
@@ -3,7 +3,7 @@ module JamRuby
@@log = Logging.logger[Recording]
- attr_accessible :owner, :owner_id, :band, :band_id, :recorded_tracks_attributes, :mixes_attributes, :claimed_recordings_attributes, :name, :description, :genre, :is_public, :duration, as: :admin
+ attr_accessible :owner, :owner_id, :band, :band_id, :recorded_tracks_attributes, :mixes_attributes, :claimed_recordings_attributes, :name, :description, :genre, :is_public, :duration, :jam_track_id, as: :admin
has_many :users, :through => :recorded_tracks, :class_name => "JamRuby::User"
has_many :claimed_recordings, :class_name => "JamRuby::ClaimedRecording", :inverse_of => :recording, :foreign_key => 'recording_id', :dependent => :destroy
@@ -21,6 +21,7 @@ module JamRuby
belongs_to :owner, :class_name => "JamRuby::User", :inverse_of => :owned_recordings, :foreign_key => 'owner_id'
belongs_to :band, :class_name => "JamRuby::Band", :inverse_of => :recordings
belongs_to :music_session, :class_name => "JamRuby::ActiveMusicSession", :inverse_of => :recordings, foreign_key: :music_session_id
+ belongs_to :non_active_music_session, :class_name => "JamRuby::MusicSession", foreign_key: :music_session_id
belongs_to :jam_track, :class_name => "JamRuby::JamTrack", :inverse_of => :recordings, :foreign_key => 'jam_track_id'
belongs_to :jam_track_initiator, :class_name => "JamRuby::User", :inverse_of => :initiated_jam_track_recordings, :foreign_key => 'jam_track_initiator_id'
@@ -50,7 +51,11 @@ module JamRuby
end
def is_jamtrack_recording?
- !jam_track_id.nil?
+ !jam_track_id.nil? && parsed_timeline['jam_track_isplaying']
+ end
+
+ def parsed_timeline
+ timeline ? JSON.parse(timeline) : {}
end
def high_quality_mix?
@@ -182,21 +187,21 @@ module JamRuby
def recorded_tracks_for_user(user)
unless self.users.exists?(user)
- raise PermissionError, "user was not in this session"
+ raise JamPermissionError, "user was not in this session"
end
recorded_tracks.where(:user_id => user.id)
end
def recorded_backing_tracks_for_user(user)
unless self.users.exists?(user)
- raise PermissionError, "user was not in this session"
+ raise JamPermissionError, "user was not in this session"
end
recorded_backing_tracks.where(:user_id => user.id)
end
def has_access?(user)
- users.exists?(user)
+ users.exists?(user) || plays.where("player_id=?", user).count != 0
end
# Start recording a session.
@@ -264,7 +269,7 @@ module JamRuby
def claim(user, name, description, genre, is_public, upload_to_youtube=false)
upload_to_youtube = !!upload_to_youtube # Correct where nil is borking save
unless self.users.exists?(user)
- raise PermissionError, "user was not in this session"
+ raise JamPermissionError, "user was not in this session"
end
claimed_recording = ClaimedRecording.new
@@ -710,23 +715,26 @@ module JamRuby
end
end
+ def self.popular_recordings(limit = 100)
+ Recording.select('recordings.id').joins('inner join claimed_recordings ON claimed_recordings.recording_id = recordings.id AND claimed_recordings.is_public = TRUE').where(all_discarded: false).where(is_done: true).where(deleted: false).order('play_count DESC').limit(limit).group('recordings.id')
+ end
private
def self.validate_user_is_band_member(user, band)
unless band.users.exists? user
- raise PermissionError, ValidationMessages::USER_NOT_BAND_MEMBER_VALIDATION_ERROR
+ raise JamPermissionError, ValidationMessages::USER_NOT_BAND_MEMBER_VALIDATION_ERROR
end
end
def self.validate_user_is_creator(user, creator)
unless user.id == creator.id
- raise PermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
+ raise JamPermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
end
end
def self.validate_user_is_musician(user)
unless user.musician?
- raise PermissionError, ValidationMessages::USER_NOT_MUSICIAN_VALIDATION_ERROR
+ raise JamPermissionError, ValidationMessages::USER_NOT_MUSICIAN_VALIDATION_ERROR
end
end
diff --git a/ruby/lib/jam_ruby/models/recurly_transaction_web_hook.rb b/ruby/lib/jam_ruby/models/recurly_transaction_web_hook.rb
index d94dca2e0..05824e322 100644
--- a/ruby/lib/jam_ruby/models/recurly_transaction_web_hook.rb
+++ b/ruby/lib/jam_ruby/models/recurly_transaction_web_hook.rb
@@ -1,10 +1,15 @@
module JamRuby
- class RecurlyTransactionWebHook < ActiveRecord::Base
+ class RecurlyTransactionWebHook < ActiveRecord::Base
+
+ attr_accessible :admin_description, :jam_track_id, as: :admin
belongs_to :user, class_name: 'JamRuby::User'
belongs_to :sale_line_item, class_name: 'JamRuby::SaleLineItem', foreign_key: 'subscription_id', primary_key: 'recurly_subscription_uuid', inverse_of: :recurly_transactions
belongs_to :sale, class_name: 'JamRuby::Sale', foreign_key: 'invoice_id', primary_key: 'recurly_invoice_id', inverse_of: :recurly_transactions
+ # when we know what JamTrack this refund is related to, we set this value
+ belongs_to :jam_track, class_name: 'JamRuby::JamTrack'
+
validates :recurly_transaction_id, presence: true
validates :action, presence: true
validates :status, presence: true
@@ -17,6 +22,9 @@ module JamRuby
REFUND = 'refund'
VOID = 'void'
+
+ HOOK_TYPES = [SUCCESSFUL_PAYMENT, FAILED_PAYMENT, REFUND, VOID]
+
def is_credit_type?
transaction_type == REFUND || transaction_type == VOID
end
@@ -46,6 +54,10 @@ module JamRuby
end
end
+ def admin_url
+ APP_CONFIG.admin_root_url + "/admin/recurly_hooks/" + id
+ end
+
# see spec for examples of XML
def self.create_from_xml(document)
@@ -81,6 +93,7 @@ module JamRuby
# now that we have the transaction saved, we also need to delete the jam_track_right if this is a refund, or voided
+
if transaction.transaction_type == 'refund' || transaction.transaction_type == 'void'
sale = Sale.find_by_recurly_invoice_id(transaction.invoice_id)
@@ -91,33 +104,44 @@ module JamRuby
jam_track_right = jam_track.right_for_user(transaction.user) if jam_track
if jam_track_right
jam_track_right.destroy
- AdminMailer.alerts({
- subject:"NOTICE: #{transaction.user.email} has had JamTrack: #{jam_track.name} revoked",
- body: "A void event came from Recurly for sale with Recurly invoice ID #{sale.recurly_invoice_id}. We deleted their right to the track in our own database as a result."
- }).deliver
+
+ # associate which JamTrack we assume this is related to in this one success case
+ transaction.jam_track = jam_track
+ transaction.save!
+
+ AdminMailer.recurly_alerts(transaction.user, {
+ subject: "NOTICE: #{transaction.user.email} has had JamTrack: #{jam_track.name} revoked",
+ body: "A #{transaction.transaction_type} event came from Recurly for sale with Recurly invoice ID #{sale.recurly_invoice_id}. We deleted their right to the track in our own database as a result."
+ }).deliver
else
- AdminMailer.alerts({
- subject:"NOTICE: #{transaction.user.email} got a refund, but unable to find JamTrackRight to delete",
- body: "This should just mean the user already has no rights to the JamTrackRight when the refund came in. Not a big deal, but sort of weird..."
- }).deliver
+ AdminMailer.recurly_alerts(transaction.user, {
+ subject: "NOTICE: #{transaction.user.email} got a refund, but unable to find JamTrackRight to delete",
+ body: "This should just mean the user already has no rights to the JamTrackRight when the refund came in. Not a big deal, but sort of weird..."
+ }).deliver
end
else
- AdminMailer.alerts({
- subject:"ACTION REQUIRED: #{transaction.user.email} got a refund it was not for total value of a JamTrack sale",
- body: "We received a refund notice for an amount that was not the same as the original sale. So, no action was taken in the database. sale total: #{sale.recurly_total_in_cents}, refund amount: #{transaction.amount_in_cents}"
- }).deliver
+ AdminMailer.recurly_alerts(transaction.user, {
+ subject: "ACTION REQUIRED: #{transaction.user.email} got a refund it was not for total value of a JamTrack sale",
+ body: "We received a #{transaction.transaction_type} notice for an amount that was not the same as the original sale. So, no action was taken in the database. sale total: #{sale.recurly_total_in_cents}, refund amount: #{transaction.amount_in_cents}"
+ }).deliver
end
else
- AdminMailer.alerts({
- subject: "ACTION REQUIRED: #{transaction.user.email} has refund on invoice with multiple JamTracks",
- body: "You will have to manually revoke any JamTrackRights in our database for the appropriate JamTracks"
- }).deliver
+ AdminMailer.recurly_alerts(transaction.user, {
+ subject: "ACTION REQUIRED: #{transaction.user.email} has refund on invoice with multiple JamTracks",
+ body: "You will have to manually revoke any JamTrackRights in our database for the appropriate JamTracks"
+ }).deliver
end
+ else
+ AdminMailer.recurly_alerts(transaction.user, {
+ subject: "ACTION REQUIRED: #{transaction.user.email} has refund with no correlator to sales",
+ body: "You will have to manually revoke any JamTrackRights in our database for the appropriate JamTracks"
+ }).deliver
end
+
end
transaction
end
diff --git a/ruby/lib/jam_ruby/models/rsvp_request.rb b/ruby/lib/jam_ruby/models/rsvp_request.rb
index 9f233b973..f416640bf 100644
--- a/ruby/lib/jam_ruby/models/rsvp_request.rb
+++ b/ruby/lib/jam_ruby/models/rsvp_request.rb
@@ -62,7 +62,7 @@ module JamRuby
invitation = Invitation.where("music_session_id = ? AND receiver_id = ?", music_session.id, user.id)
if invitation.first.nil? && !music_session.open_rsvps && music_session.creator.id != user.id
- raise PermissionError, "Only a session invitee can create an RSVP for this session."
+ raise JamPermissionError, "Only a session invitee can create an RSVP for this session."
end
RsvpRequest.transaction do
@@ -154,7 +154,7 @@ module JamRuby
# authorize the user attempting to respond to the RSVP request
if music_session.creator.id != user.id
- raise PermissionError, "Only the session organizer can accept or decline an RSVP request."
+ raise JamPermissionError, "Only the session organizer can accept or decline an RSVP request."
end
rsvp_request = RsvpRequest.find_by_id(rsvp_request_id)
@@ -249,7 +249,7 @@ module JamRuby
rsvp_request = RsvpRequest.find(params[:id])
if music_session.creator.id != user.id && rsvp_request.user_id != user.id
- raise PermissionError, "Only the session organizer or RSVP creator can cancel the RSVP."
+ raise JamPermissionError, "Only the session organizer or RSVP creator can cancel the RSVP."
end
RsvpRequest.transaction do
diff --git a/ruby/lib/jam_ruby/models/shopping_cart.rb b/ruby/lib/jam_ruby/models/shopping_cart.rb
index ed74d2490..dc975bd40 100644
--- a/ruby/lib/jam_ruby/models/shopping_cart.rb
+++ b/ruby/lib/jam_ruby/models/shopping_cart.rb
@@ -12,7 +12,7 @@ module JamRuby
attr_accessible :quantity, :cart_type, :product_info
- validates_uniqueness_of :cart_id, scope: :cart_type
+ validates_uniqueness_of :cart_id, scope: [:cart_type, :user_id, :anonymous_user_id]
belongs_to :user, :inverse_of => :shopping_carts, :class_name => "JamRuby::User", :foreign_key => "user_id"
@@ -25,7 +25,7 @@ module JamRuby
def product_info
product = self.cart_product
- {name: product.name, price: product.price, product_id: cart_id, plan_code: product.plan_code, real_price: real_price(product), total_price: total_price(product), quantity: quantity, marked_for_redeem: marked_for_redeem} unless product.nil?
+ {name: product.name, price: product.price, product_id: cart_id, plan_code: product.plan_code, real_price: real_price(product), total_price: total_price(product), quantity: quantity, marked_for_redeem: marked_for_redeem, free: free?, sales_region: product.sales_region} unless product.nil?
end
# multiply quantity by price
@@ -111,6 +111,15 @@ module JamRuby
end
end
+ def self.move_to_user(user, anonymous_user, shopping_carts)
+ shopping_carts.each do |shopping_cart|
+ mark_redeem = ShoppingCart.user_has_redeemable_jam_track?(user)
+ cart = ShoppingCart.create(user, shopping_cart.cart_product, shopping_cart.quantity, mark_redeem)
+ end
+
+ anonymous_user.destroy_all_shopping_carts
+ end
+
def self.is_product_purchase?(adjustment)
(adjustment[:accounting_code].include?(PURCHASE_FREE) || adjustment[:accounting_code].include?(PURCHASE_NORMAL)) && !adjustment[:accounting_code].include?(PURCHASE_FREE_CREDIT)
end
diff --git a/ruby/lib/jam_ruby/models/signup_hint.rb b/ruby/lib/jam_ruby/models/signup_hint.rb
new file mode 100644
index 000000000..b415d45a4
--- /dev/null
+++ b/ruby/lib/jam_ruby/models/signup_hint.rb
@@ -0,0 +1,36 @@
+module JamRuby
+
+ # some times someone comes to signup as a new user, but there is context to preserve.
+ # the AnyUser cookie is one way that we can track the user from pre-signup to post-signup
+ # anyway, once the signup is done, we check to see if there is a SignupHint, and if so,
+ # we use it to figure out what to do with the user after they signup
+ class SignupHint < ActiveRecord::Base
+
+
+ belongs_to :user, class_name: 'JamRuby::User'
+
+ validates :redirect_location, length: {maximum: 1000}
+ validates :want_jamblaster, inclusion: {in: [nil, true, false]}
+
+ def self.refresh_by_anoymous_user(anonymous_user, options = {})
+
+ hint = SignupHint.find_by_anonymous_user_id(anonymous_user.id)
+
+ unless hint
+ hint = SignupHint.new
+ end
+
+ hint.anonymous_user_id = anonymous_user.id
+ hint.redirect_location = options[:redirect_location] if options.has_key?(:redirect_location)
+ hint.want_jamblaster = options[:want_jamblaster] if options.has_key?(:want_jamblaster)
+ hint.expires_at = 15.minutes.from_now
+ hint.save
+ hint
+ end
+
+ def self.delete_old
+ SignupHint.where("created_at < :week", {:week => 1.week.ago}).delete_all
+ end
+
+ end
+end
diff --git a/ruby/lib/jam_ruby/models/track.rb b/ruby/lib/jam_ruby/models/track.rb
index e430edb2d..1a8db2047 100644
--- a/ruby/lib/jam_ruby/models/track.rb
+++ b/ruby/lib/jam_ruby/models/track.rb
@@ -113,6 +113,7 @@ module JamRuby
result = {}
backing_tracks = [] unless backing_tracks
+ tracks = [] unless tracks
Track.transaction do
connection = Connection.find_by_client_id!(clientId)
diff --git a/ruby/lib/jam_ruby/models/user.rb b/ruby/lib/jam_ruby/models/user.rb
index 4183b8b8c..73689167b 100644
--- a/ruby/lib/jam_ruby/models/user.rb
+++ b/ruby/lib/jam_ruby/models/user.rb
@@ -209,7 +209,7 @@ module JamRuby
scope :email_opt_in, where(:subscribe_email => true)
def user_progression_fields
- @user_progression_fields ||= Set.new ["first_downloaded_client_at", "first_ran_client_at", "first_music_session_at", "first_real_music_session_at", "first_good_music_session_at", "first_certified_gear_at", "first_invited_at", "first_friended_at", "first_recording_at", "first_social_promoted_at" ]
+ @user_progression_fields ||= Set.new ["first_downloaded_client_at", "first_ran_client_at", "first_music_session_at", "first_real_music_session_at", "first_good_music_session_at", "first_certified_gear_at", "first_invited_at", "first_friended_at", "first_recording_at", "first_social_promoted_at", "first_played_jamtrack_at" ]
end
def update_progression_field(field_name, time = DateTime.now)
@@ -812,7 +812,7 @@ module JamRuby
end
if user.id != updater_id
- raise PermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
+ raise JamPermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
end
user.easy_save(first_name, last_name, email, password, password_confirmation, musician, gender,
@@ -1046,7 +1046,16 @@ module JamRuby
user.photo_url = photo_url
# copy over the shopping cart to the new user, if a shopping cart is provided
- user.shopping_carts = any_user.shopping_carts if any_user
+ if any_user
+ user.shopping_carts = any_user.shopping_carts
+ if user.shopping_carts
+ user.shopping_carts.each do |shopping_cart|
+ shopping_cart.anonymous_user_id = nil # nil out the anonymous user ID; required for uniqeness constraint on ShoppingCart
+ end
+ end
+ end
+
+
unless fb_signup.nil?
user.update_fb_authorization(fb_signup)
@@ -1596,6 +1605,15 @@ module JamRuby
verifier.generate(user.id)
end
+ # URL to jam-admin
+ def admin_url
+ APP_CONFIG.admin_root_url + "/admin/users/" + id
+ end
+
+ def jam_track_rights_admin_url
+ APP_CONFIG.admin_root_url + "/admin/jam_track_rights?q[user_id_equals]=#{id}&commit=Filter&order=created_at DESC"
+ end
+
private
def create_remember_token
self.remember_token = SecureRandom.urlsafe_base64
diff --git a/ruby/lib/jam_ruby/mq_router.rb b/ruby/lib/jam_ruby/mq_router.rb
index 826eb1ace..8aec53cde 100644
--- a/ruby/lib/jam_ruby/mq_router.rb
+++ b/ruby/lib/jam_ruby/mq_router.rb
@@ -17,7 +17,7 @@ class MQRouter
end
if !music_session.access? user
- raise PermissionError, 'not allowed to join the specified session'
+ raise JamPermissionError, 'not allowed to join the specified session'
end
return music_session
diff --git a/ruby/lib/jam_ruby/resque/audiomixer.rb b/ruby/lib/jam_ruby/resque/audiomixer.rb
index fa987b69f..b03bad875 100644
--- a/ruby/lib/jam_ruby/resque/audiomixer.rb
+++ b/ruby/lib/jam_ruby/resque/audiomixer.rb
@@ -263,6 +263,7 @@ module JamRuby
@@log.debug("manifest")
@@log.debug("--------")
@@log.debug(JSON.pretty_generate(@manifest))
+ @@log.debug("--------")
@manifest[:mix_id] = mix_id # slip in the mix_id so that the job can add it to the ogg comments
diff --git a/ruby/lib/jam_ruby/resque/google_analytics_event.rb b/ruby/lib/jam_ruby/resque/google_analytics_event.rb
index 0c1cbbf06..5394744f2 100644
--- a/ruby/lib/jam_ruby/resque/google_analytics_event.rb
+++ b/ruby/lib/jam_ruby/resque/google_analytics_event.rb
@@ -101,7 +101,9 @@ module JamRuby
el: 'data',
ev: data.to_s
}
+
RestClient.post(APP_CONFIG.ga_endpoint, params: params, timeout: 8, open_timeout: 8)
+
@@log.info("done (#{category}, #{action})")
end
diff --git a/ruby/lib/jam_ruby/resque/jam_tracks_builder.rb b/ruby/lib/jam_ruby/resque/jam_tracks_builder.rb
index 395d12084..329a52b4d 100644
--- a/ruby/lib/jam_ruby/resque/jam_tracks_builder.rb
+++ b/ruby/lib/jam_ruby/resque/jam_tracks_builder.rb
@@ -34,8 +34,20 @@ module JamRuby
return
end
+ # compute the step count
+ total_steps = @jam_track_right.jam_track.stem_tracks.count + 1 # the '1' represents the jkz.py invocation
+
# track that it's started ( and avoid db validations )
- JamTrackRight.where(:id => @jam_track_right.id).update_all(:signing_started_at => Time.now, :should_retry => false)
+ signing_started_at = Time.now
+ last_step_at = Time.now
+ JamTrackRight.where(:id => @jam_track_right.id).update_all(:signing_started_at => signing_started_at, :should_retry => false, packaging_steps: total_steps, current_packaging_step: 0, last_step_at: last_step_at)
+ # because we are skiping after_save, we have to keep the model current for the notification. A bit ugly...
+ @jam_track_right.current_packaging_step = 0
+ @jam_track_right.packaging_steps = total_steps
+ @jam_track_right.signing_started_at = signing_started_at
+ @jam_track_right.should_retry = false
+ @jam_track_right.last_step_at = Time.now
+ SubscriptionMessage.jam_track_signing_job_change(@jam_track_right)
JamRuby::JamTracksManager.save_jam_track_right_jkz(@jam_track_right, self.bitrate)
# If bitrate is 48 (the default), use that URL. Otherwise, use 44kHz:
diff --git a/ruby/lib/jam_ruby/resque/scheduled/cleanup_facebook_signup.rb b/ruby/lib/jam_ruby/resque/scheduled/cleanup_facebook_signup.rb
index ddfb6b28f..f46946886 100644
--- a/ruby/lib/jam_ruby/resque/scheduled/cleanup_facebook_signup.rb
+++ b/ruby/lib/jam_ruby/resque/scheduled/cleanup_facebook_signup.rb
@@ -11,6 +11,7 @@ module JamRuby
@@log.debug("waking up")
FacebookSignup.delete_old
+ SignupHint.delete_old
@@log.debug("done")
end
diff --git a/ruby/spec/jam_ruby/jam_track_importer_spec.rb b/ruby/spec/jam_ruby/jam_track_importer_spec.rb
index 5a0a89cf4..a2cf96620 100644
--- a/ruby/spec/jam_ruby/jam_track_importer_spec.rb
+++ b/ruby/spec/jam_ruby/jam_track_importer_spec.rb
@@ -46,7 +46,7 @@ describe JamTrackImporter do
let(:options) {{ skip_audio_upload:true }}
it "bare minimum specification" do
- importer.synchronize_metadata(jam_track, minimum_meta, metalocation, 'Artist 1', 'Song 1')
+ importer.synchronize_metadata(jam_track, minimum_meta, metalocation, 'Artist 1', 'Song 1', options)
jam_track.plan_code.should eq('jamtrack-artist1-song1')
jam_track.name.should eq("Song 1")
@@ -57,7 +57,7 @@ describe JamTrackImporter do
jam_track.original_artist.should eq('Artist 1')
jam_track.songwriter.should be_nil
jam_track.publisher.should be_nil
- jam_track.sales_region.should eq('United States')
+ jam_track.sales_region.should eq('Worldwide')
jam_track.price.should eq(1.99)
end
end
diff --git a/ruby/spec/jam_ruby/models/jam_track_right_spec.rb b/ruby/spec/jam_ruby/models/jam_track_right_spec.rb
index 530535f8c..0977703ff 100644
--- a/ruby/spec/jam_ruby/models/jam_track_right_spec.rb
+++ b/ruby/spec/jam_ruby/models/jam_track_right_spec.rb
@@ -134,12 +134,12 @@ describe JamTrackRight do
end
it "signing" do
- right = FactoryGirl.create(:jam_track_right, signing_started_at: Time.now)
+ right = FactoryGirl.create(:jam_track_right, signing_started_at: Time.now, packaging_steps: 3, current_packaging_step:0, last_step_at:Time.now)
right.signing_state.should eq('SIGNING')
end
it "signing timeout" do
- right = FactoryGirl.create(:jam_track_right, signing_started_at: Time.now - (APP_CONFIG.signing_job_run_max_time + 1))
+ right = FactoryGirl.create(:jam_track_right, signing_started_at: Time.now - 100, packaging_steps: 3, current_packaging_step:0, last_step_at:Time.now)
right.signing_state.should eq('SIGNING_TIMEOUT')
end
diff --git a/ruby/spec/jam_ruby/models/jam_track_spec.rb b/ruby/spec/jam_ruby/models/jam_track_spec.rb
index 10cec40cd..d17019df7 100644
--- a/ruby/spec/jam_ruby/models/jam_track_spec.rb
+++ b/ruby/spec/jam_ruby/models/jam_track_spec.rb
@@ -38,6 +38,41 @@ describe JamTrack do
end
end
+ describe "artist_index" do
+ before :each do
+ JamTrack.delete_all
+ end
+
+ it "empty query" do
+ query, pager = JamTrack.artist_index({}, user)
+ query.size.should == 0
+ end
+
+ it "groups" do
+ jam_track1 = FactoryGirl.create(:jam_track_with_tracks, original_artist: 'artist', name: 'a')
+ jam_track2 = FactoryGirl.create(:jam_track_with_tracks, original_artist: 'artist', name: 'b')
+
+ query, pager = JamTrack.artist_index({}, user)
+ query.size.should == 1
+
+ query[0].original_artist.should eq('artist')
+ query[0]['song_count'].should eq('2')
+ end
+
+ it "sorts by name" do
+ jam_track1 = FactoryGirl.create(:jam_track_with_tracks, original_artist: 'blartist', name: 'a')
+ jam_track2 = FactoryGirl.create(:jam_track_with_tracks, original_artist: 'artist', name: 'b')
+
+ query, pager = JamTrack.artist_index({}, user)
+ query.size.should == 2
+
+ query[0].original_artist.should eq('artist')
+ query[0]['song_count'].should eq('1')
+ query[1].original_artist.should eq('blartist')
+ query[1]['song_count'].should eq('1')
+ end
+ end
+
describe "index" do
it "empty query" do
query, pager = JamTrack.index({}, user)
@@ -45,8 +80,8 @@ describe JamTrack do
end
it "sorts by name" do
- jam_track1 = FactoryGirl.create(:jam_track_with_tracks, name: 'a')
- jam_track2 = FactoryGirl.create(:jam_track_with_tracks, name: 'b')
+ jam_track1 = FactoryGirl.create(:jam_track_with_tracks, original_artist: 'artist', name: 'a')
+ jam_track2 = FactoryGirl.create(:jam_track_with_tracks, original_artist: 'artist', name: 'b')
query, pager = JamTrack.index({}, user)
query.size.should == 2
@@ -141,5 +176,4 @@ describe JamTrack do
end
end
end
-end
-
+end
\ No newline at end of file
diff --git a/ruby/spec/jam_ruby/models/payment_history_spec.rb b/ruby/spec/jam_ruby/models/payment_history_spec.rb
new file mode 100644
index 000000000..b28cffec3
--- /dev/null
+++ b/ruby/spec/jam_ruby/models/payment_history_spec.rb
@@ -0,0 +1,48 @@
+require 'spec_helper'
+
+describe PaymentHistory do
+
+ let(:user) {FactoryGirl.create(:user)}
+ let(:user2) {FactoryGirl.create(:user)}
+ let(:jam_track) {FactoryGirl.create(:jam_track)}
+
+ before(:each) do
+
+ end
+
+ describe "index" do
+ it "empty" do
+ result = PaymentHistory.index(user)
+ result[:query].length.should eq(0)
+ result[:next].should eq(nil)
+ end
+
+ it "one" do
+ sale = Sale.create_jam_track_sale(user)
+ shopping_cart = ShoppingCart.create(user, jam_track)
+ sale_line_item = SaleLineItem.create_from_shopping_cart(sale, shopping_cart, nil, 'some_adjustment_uuid', nil)
+
+ result = PaymentHistory.index(user)
+ result[:query].length.should eq(1)
+ result[:next].should eq(nil)
+ end
+
+ it "user filtered correctly" do
+ sale = Sale.create_jam_track_sale(user)
+ shopping_cart = ShoppingCart.create(user, jam_track)
+ sale_line_item = SaleLineItem.create_from_shopping_cart(sale, shopping_cart, nil, 'some_adjustment_uuid', nil)
+
+ result = PaymentHistory.index(user)
+ result[:query].length.should eq(1)
+ result[:next].should eq(nil)
+
+ sale2 = Sale.create_jam_track_sale(user2)
+ shopping_cart = ShoppingCart.create(user2, jam_track)
+ sale_line_item2 = SaleLineItem.create_from_shopping_cart(sale2, shopping_cart, nil, 'some_adjustment_uuid', nil)
+
+ result = PaymentHistory.index(user)
+ result[:query].length.should eq(1)
+ result[:next].should eq(nil)
+ end
+ end
+end
diff --git a/ruby/spec/jam_ruby/models/recording_spec.rb b/ruby/spec/jam_ruby/models/recording_spec.rb
index 7b64b2144..3de7d09e1 100644
--- a/ruby/spec/jam_ruby/models/recording_spec.rb
+++ b/ruby/spec/jam_ruby/models/recording_spec.rb
@@ -15,6 +15,29 @@ describe Recording do
@track = FactoryGirl.create(:track, :connection => @connection, :instrument => @instrument)
end
+ describe "popular_recordings" do
+ it "empty" do
+ Recording.popular_recordings.length.should eq(0)
+ end
+
+ it "one public recording" do
+ claim = FactoryGirl.create(:claimed_recording)
+
+ claim.recording.is_done = true
+ claim.recording.save!
+ recordings = Recording.popular_recordings
+ recordings.length.should eq(1)
+ recordings[0].id.should eq(claim.recording.id)
+ end
+
+ it "one private recording" do
+ claim = FactoryGirl.create(:claimed_recording, is_public: true)
+
+ recordings = Recording.popular_recordings
+ recordings.length.should eq(0)
+ end
+ end
+
describe "cleanup_excessive_storage" do
sample_audio='sample.file'
diff --git a/ruby/spec/jam_ruby/models/rsvp_request_spec.rb b/ruby/spec/jam_ruby/models/rsvp_request_spec.rb
index 0f8aa5874..f93501647 100644
--- a/ruby/spec/jam_ruby/models/rsvp_request_spec.rb
+++ b/ruby/spec/jam_ruby/models/rsvp_request_spec.rb
@@ -104,7 +104,7 @@ describe RsvpRequest do
it "should not allow non-invitee to RSVP to session with closed RSVPs" do
@music_session.open_rsvps = false
@music_session.save!
- expect {RsvpRequest.create({:session_id => @music_session.id, :rsvp_slots => [@slot1.id, @slot2.id]}, @non_session_invitee)}.to raise_error(JamRuby::PermissionError)
+ expect {RsvpRequest.create({:session_id => @music_session.id, :rsvp_slots => [@slot1.id, @slot2.id]}, @non_session_invitee)}.to raise_error(JamRuby::JamPermissionError)
end
it "should allow RSVP creation with autoapprove option for open RSVP sessions" do
@@ -216,7 +216,7 @@ describe RsvpRequest do
# attempt to approve with non-organizer
rs1 = RsvpRequestRsvpSlot.find_by_rsvp_slot_id(@slot1.id)
rs2 = RsvpRequestRsvpSlot.find_by_rsvp_slot_id(@slot2.id)
- expect {RsvpRequest.update({:id => rsvp.id, :session_id => @music_session.id, :rsvp_responses => [{:request_slot_id => rs1.id, :accept => true}, {:request_slot_id => rs2.id, :accept => true}]}, @session_invitee)}.to raise_error(PermissionError)
+ expect {RsvpRequest.update({:id => rsvp.id, :session_id => @music_session.id, :rsvp_responses => [{:request_slot_id => rs1.id, :accept => true}, {:request_slot_id => rs2.id, :accept => true}]}, @session_invitee)}.to raise_error(JamPermissionError)
# approve with organizer
rs1 = RsvpRequestRsvpSlot.find_by_rsvp_slot_id(@slot1.id)
@@ -402,7 +402,7 @@ describe RsvpRequest do
comment.comment.should == "Let's Jam!"
# cancel
- expect {RsvpRequest.cancel({:id => rsvp.id, :session_id => @music_session.id, :cancelled => "all", :message => "I'm gonna cancel all your RSVPs"}, user)}.to raise_error(PermissionError)
+ expect {RsvpRequest.cancel({:id => rsvp.id, :session_id => @music_session.id, :cancelled => "all", :message => "I'm gonna cancel all your RSVPs"}, user)}.to raise_error(JamPermissionError)
end
end
diff --git a/ruby/spec/jam_ruby/models/signup_hint_spec.rb b/ruby/spec/jam_ruby/models/signup_hint_spec.rb
new file mode 100644
index 000000000..1ec79efef
--- /dev/null
+++ b/ruby/spec/jam_ruby/models/signup_hint_spec.rb
@@ -0,0 +1,24 @@
+require 'spec_helper'
+
+describe SignupHint do
+
+ let(:user) {AnonymousUser.new(SecureRandom.uuid)}
+
+ describe "refresh_by_anoymous_user" do
+ it "creates" do
+ hint = SignupHint.refresh_by_anoymous_user(user, {redirect_location: 'abc'})
+ hint.errors.any?.should be_false
+ hint.redirect_location.should eq('abc')
+ hint.want_jamblaster.should be_false
+ end
+
+ it "updated" do
+ SignupHint.refresh_by_anoymous_user(user, {redirect_location: 'abc'})
+
+ hint = SignupHint.refresh_by_anoymous_user(user, {redirect_location: nil, want_jamblaster: true})
+ hint.errors.any?.should be_false
+ hint.redirect_location.should be_nil
+ hint.want_jamblaster.should be_true
+ end
+ end
+end
diff --git a/ruby/spec/support/utilities.rb b/ruby/spec/support/utilities.rb
index 93222cf6c..c033de858 100644
--- a/ruby/spec/support/utilities.rb
+++ b/ruby/spec/support/utilities.rb
@@ -3,10 +3,18 @@ JAMKAZAM_TESTING_BUCKET = 'jamkazam-testing' # cuz i'm not comfortable using aws
def app_config
klass = Class.new do
+ def admin_root_url
+ 'http://localhost:3333'
+ end
+
def email_alerts_alias
'alerts@jamkazam.com'
end
+ def email_recurly_notice
+ 'recurly-alerts@jamkazam.com'
+ end
+
def email_generic_from
'nobody@jamkazam.com'
end
@@ -166,8 +174,8 @@ def app_config
false
end
- def signing_job_run_max_time
- 60 # 1 minute
+ def signing_step_max_time
+ 40 # 40 seconds
end
def signing_job_queue_max_time
@@ -182,6 +190,9 @@ def app_config
'foobar'
end
+ def unsubscribe_token
+ 'blah'
+ end
private
diff --git a/web/.gitignore b/web/.gitignore
index 48289754a..e305498b8 100644
--- a/web/.gitignore
+++ b/web/.gitignore
@@ -23,6 +23,7 @@ doc/
.idea
*.iml
+jt_metadata.json
artifacts
diff --git a/web/Gemfile b/web/Gemfile
index 73bbc90f9..e53c64492 100644
--- a/web/Gemfile
+++ b/web/Gemfile
@@ -87,6 +87,7 @@ gem 'recurly'
gem 'guard', '2.7.3'
gem 'influxdb', '0.1.8'
gem 'influxdb-rails', '0.1.10'
+gem 'sitemap_generator'
group :development, :test do
gem 'rspec-rails', '2.14.2'
diff --git a/web/Rakefile b/web/Rakefile
index f4019acfc..882005f42 100644
--- a/web/Rakefile
+++ b/web/Rakefile
@@ -6,6 +6,7 @@
#require 'resque/scheduler/tasks'
require 'resque/tasks'
require 'resque/scheduler/tasks'
+require 'sitemap_generator/tasks'
require File.expand_path('../config/application', __FILE__)
SampleApp::Application.load_tasks
diff --git a/web/app/assets/images/content/icon-pause-24-black.png b/web/app/assets/images/content/icon-pause-24-black.png
new file mode 100644
index 000000000..2f719e15d
Binary files /dev/null and b/web/app/assets/images/content/icon-pause-24-black.png differ
diff --git a/web/app/assets/images/content/icon-pause-24-gray.png b/web/app/assets/images/content/icon-pause-24-gray.png
new file mode 100644
index 000000000..38237b3ad
Binary files /dev/null and b/web/app/assets/images/content/icon-pause-24-gray.png differ
diff --git a/web/app/assets/images/content/icon-play-24-black.png b/web/app/assets/images/content/icon-play-24-black.png
new file mode 100644
index 000000000..e21b8b5f9
Binary files /dev/null and b/web/app/assets/images/content/icon-play-24-black.png differ
diff --git a/web/app/assets/images/content/icon-play-24-gray.png b/web/app/assets/images/content/icon-play-24-gray.png
new file mode 100644
index 000000000..88c9c10ef
Binary files /dev/null and b/web/app/assets/images/content/icon-play-24-gray.png differ
diff --git a/web/app/assets/images/content/icon_cam.png b/web/app/assets/images/content/icon_cam.png
new file mode 100644
index 000000000..e32bede67
Binary files /dev/null and b/web/app/assets/images/content/icon_cam.png differ
diff --git a/web/app/assets/images/content/icon_stopbutton.png b/web/app/assets/images/content/icon_stopbutton.png
new file mode 100644
index 000000000..37d19e686
Binary files /dev/null and b/web/app/assets/images/content/icon_stopbutton.png differ
diff --git a/web/app/assets/images/web/generic_button_cta.png b/web/app/assets/images/web/generic_button_cta.png
new file mode 100644
index 000000000..c0691f343
Binary files /dev/null and b/web/app/assets/images/web/generic_button_cta.png differ
diff --git a/web/app/assets/javascripts/accounts.js b/web/app/assets/javascripts/accounts.js
index b7af8f033..91454c046 100644
--- a/web/app/assets/javascripts/accounts.js
+++ b/web/app/assets/javascripts/accounts.js
@@ -8,8 +8,10 @@
var rest = context.JK.Rest();
var userId;
var user = {};
+
function beforeShow(data) {
+ console.log("beforeShow", data)
userId = data.id;
}
@@ -43,6 +45,19 @@
var invalidProfiles = prettyPrintAudioProfiles(context.JK.getBadConfigMap());
var sessionSummary = summarizeSession(userDetail);
+ if(gon.global.video_available && gon.global.video_available!="none" ) {
+ var webcamName;
+ var webcam = context.jamClient.FTUECurrentSelectedVideoDevice()
+ if (webcam == null || typeof(webcam) == "undefined" || Object.keys(webcam).length == 0) {
+ webcamName = "None Configured"
+ } else {
+ webcamName = _.values(webcam)[0]
+ }
+ }
+ else {
+ webcamName = 'video unavailable'
+ }
+
var $template = $(context._.template($('#template-account-main').html(), {
email: userDetail.email,
name: userDetail.name,
@@ -56,6 +71,7 @@
invalidProfiles : invalidProfiles,
isNativeClient: gon.isNativeClient,
musician: context.JK.currentUserMusician,
+ webcamName: webcamName,
sales_count: userDetail.sales_count
} , { variable: 'data' }));
@@ -65,8 +81,9 @@
$('#account-scheduled-sessions-link').show();
} else {
$('#account-scheduled-sessions-link').hide();
- }
- }
+ }
+
+ }// function
function prettyPrintAudioProfiles(profileMap) {
var profiles = "";
@@ -110,6 +127,7 @@
$('#account-content-scroller').on('click', '#account-edit-subscriptions-link', function(evt) { evt.stopPropagation(); navToEditSubscriptions(); return false; } );
$('#account-content-scroller').on('click', '#account-edit-payments-link', function(evt) { evt.stopPropagation(); navToEditPayments(); return false; } );
$('#account-content-scroller').on('click', '#account-edit-audio-link', function(evt) { evt.stopPropagation(); navToEditAudio(); return false; } );
+ $('#account-content-scroller').on('click', '#account-edit-video-link', function(evt) { evt.stopPropagation(); navToEditVideo(); return false; } );
$('#account-content-scroller').on('avatar_changed', '#profile-avatar', function(evt, newAvatarUrl) { evt.stopPropagation(); updateAvatar(newAvatarUrl); return false; })
// License dialog:
@@ -158,6 +176,11 @@
window.location = "/client#/account/audio"
}
+ function navToEditVideo() {
+ resetForm()
+ window.location = "/client#/account/video"
+ }
+
function navToPaymentHistory() {
window.location = '/client#/account/paymentHistory'
}
@@ -178,6 +201,7 @@
}
function initialize() {
+
var screenBindings = {
'beforeShow': beforeShow,
'afterShow': afterShow
diff --git a/web/app/assets/javascripts/accounts_audio_profile.js b/web/app/assets/javascripts/accounts_audio_profile.js
index 1e646a4cf..915383acc 100644
--- a/web/app/assets/javascripts/accounts_audio_profile.js
+++ b/web/app/assets/javascripts/accounts_audio_profile.js
@@ -163,6 +163,13 @@
function handleConfigureAudioProfile(audioProfileId) {
+ if(!gearUtils.canBeConfigured(audioProfileId)) {
+
+ context.JK.Banner.showAlert("The System Default (Playback Only) profile can not currently be configured.");
+ return;
+ }
+
+ if(audioProfileId == gearUtils.GearUtil)
if(audioProfileId != context.jamClient.FTUEGetMusicProfileName()) {
logger.debug("activating " + audioProfileId);
var result = context.jamClient.FTUELoadAudioConfiguration(audioProfileId);
diff --git a/web/app/assets/javascripts/accounts_payment_history_screen.js.coffee b/web/app/assets/javascripts/accounts_payment_history_screen.js.coffee
index 2f20246cf..82dbe73eb 100644
--- a/web/app/assets/javascripts/accounts_payment_history_screen.js.coffee
+++ b/web/app/assets/javascripts/accounts_payment_history_screen.js.coffee
@@ -51,41 +51,33 @@ context.JK.AccountPaymentHistoryScreen = class AccountPaymentHistoryScreen
renderPayments:(response) =>
if response.entries? && response.entries.length > 0
- for sale in response.entries
- amt = sale.recurly_total_in_cents
- amt = 0 if !amt?
-
- original_total = sale.state.original_total
- refund_total = sale.state.refund_total
-
- refund_state = null
- if original_total != 0 # the enclosed logic does not work for free purchases
- if refund_total == original_total
- refund_state = 'refunded'
- else if refund_total != 0 and refund_total < original_total
- refund_state = 'partial refund'
-
-
- displayAmount = (amt/100).toFixed(2)
- status = 'paid'
-
- if sale.state.voided
- status = 'voided'
- displayAmount = (0).toFixed(2)
- else if refund_state?
- status = refund_state
- displayAmount = (amt/100).toFixed(2) + " (refunded: #{(refund_total/100).toFixed(2)})"
-
- description = []
- for line_item in sale.line_items
- description.push(line_item.product_info?.name)
+ for paymentHistory in response.entries
+ if paymentHistory.sale?
+ # this is a sale
+ sale = paymentHistory.sale
+ amt = sale.recurly_total_in_cents
+ status = 'paid'
+ displayAmount = ' $' + (amt/100).toFixed(2)
+ date = context.JK.formatDate(sale.created_at, true)
+ items = []
+ for line_item in sale.line_items
+ items.push(line_item.product_info?.name)
+ description = items.join(', ')
+ else
+ # this is a recurly webhook
+ transaction = paymentHistory.transaction
+ amt = transaction.amount_in_cents
+ status = transaction.transaction_type
+ displayAmount = '($' + (amt/100).toFixed(2) + ')'
+ date = context.JK.formatDate(transaction.transaction_at, true)
+ description = transaction.admin_description
payment = {
- date: context.JK.formatDate(sale.created_at, true)
+ date: date
amount: displayAmount
status: status
- payment_method: 'Credit Card',
- description: description.join(', ')
+ payment_method: 'Credit Card'
+ description: description
}
tr = $(context._.template(@rowTemplate, payment, { variable: 'data' }));
@@ -98,10 +90,9 @@ context.JK.AccountPaymentHistoryScreen = class AccountPaymentHistoryScreen
# Turn in to HTML rows and append:
#@tbody.html("")
- console.log("response.next", response)
- @next = response.next_page
+ @next = response.next
@renderPayments(response)
- if response.next_page == null
+ if response.next == null
# if we less results than asked for, end searching
@scroller.infinitescroll 'pause'
@logger.debug("end of history")
@@ -147,7 +138,7 @@ context.JK.AccountPaymentHistoryScreen = class AccountPaymentHistoryScreen
msg: $('
Loading ...
')
img: '/assets/shared/spinner.gif'
path: (page) =>
- '/api/sales?' + $.param(that.buildQuery())
+ '/api/payment_histories?' + $.param(that.buildQuery())
}, (json, opts) =>
this.salesHistoryDone(json)
diff --git a/web/app/assets/javascripts/accounts_video_profile.js b/web/app/assets/javascripts/accounts_video_profile.js
new file mode 100644
index 000000000..fbb1a6d53
--- /dev/null
+++ b/web/app/assets/javascripts/accounts_video_profile.js
@@ -0,0 +1,32 @@
+(function (context, $) {
+
+ "use strict";
+
+ context.JK = context.JK || {};
+ context.JK.AccountVideoProfile = function (app) {
+ var $webcamViewer = new context.JK.WebcamViewer()
+ function initialize() {
+ var screenBindings = {
+ 'beforeShow': beforeShow,
+ 'beforeHide':beforeHide
+ };
+ app.bindScreen('account/video', screenBindings);
+
+ $webcamViewer.init($(".webcam-container"))
+ }
+
+ function beforeShow() {
+ $webcamViewer.beforeShow()
+ }
+
+ function beforeHide() {
+ $webcamViewer.setVideoOff()
+ }
+
+ this.beforeShow = beforeShow
+ this.beforeHide = beforeHide
+ this.initialize = initialize
+ return this;
+ };
+
+})(window, jQuery);
\ No newline at end of file
diff --git a/web/app/assets/javascripts/application.js b/web/app/assets/javascripts/application.js
index bc065cf22..030fd6e88 100644
--- a/web/app/assets/javascripts/application.js
+++ b/web/app/assets/javascripts/application.js
@@ -44,6 +44,7 @@
//= require globals
//= require AAB_message_factory
//= require jam_rest
+//= require ga
//= require utils
//= require subscription_utils
//= require custom_controls
diff --git a/web/app/assets/javascripts/checkout_order.js b/web/app/assets/javascripts/checkout_order.js
index fbe41c665..523c02691 100644
--- a/web/app/assets/javascripts/checkout_order.js
+++ b/web/app/assets/javascripts/checkout_order.js
@@ -30,15 +30,16 @@
var $orderPrompt = null;
var $emptyCartPrompt = null;
var $noAccountInfoPrompt = null;
+ var $downloadApplicationLink = null;
function beforeShow() {
- beforeShowOrder();
+
}
function afterShow(data) {
-
+ beforeShowOrder();
}
@@ -56,11 +57,13 @@
}
function beforeShowOrder() {
+ $purchasedJamTracks.empty()
$orderPrompt.addClass('hidden')
$emptyCartPrompt.addClass('hidden')
$noAccountInfoPrompt.addClass('hidden')
$orderPanel.removeClass("hidden")
$thanksPanel.addClass("hidden")
+ $purchasedJamTrackHeader.attr('status', 'in-progress')
$screen.find(".place-order").addClass('disabled').off('click', placeOrder)
$("#order_error").text('').addClass("hidden")
step = 3;
@@ -225,6 +228,7 @@
$orderPanel.addClass("hidden")
$thanksPanel.removeClass("hidden")
jamTrackUtils.checkShoppingCart()
+ app.refreshUser()
handleJamTracksPurchased(purchaseResponse.jam_tracks)
}
@@ -237,6 +241,11 @@
}
else {
$jamTrackInBrowser.removeClass('hidden');
+ app.user().done(function(user) {
+ if(!user.first_downloaded_client_at) {
+ $downloadApplicationLink.removeClass('hidden')
+ }
+ })
}
}
}
@@ -297,7 +306,7 @@
}
else {
logger.debug("done iterating over purchased JamTracks")
- $purchasedJamTrackHeader.text('All purchased JamTracks have been downloaded successfully! You can now play them in a session.')
+ $purchasedJamTrackHeader.attr('status', 'done')
}
}
@@ -349,6 +358,7 @@
$emptyCartPrompt = $screen.find('.empty-cart-prompt');
$noAccountInfoPrompt = $screen.find('.no-account-info-prompt');
$orderContent = $orderPanel.find(".order-content");
+ $downloadApplicationLink = $screen.find('.download-jamkazam-wrapper');
if ($screen.length == 0) throw "$screen must be specified";
if ($navigation.length == 0) throw "$navigation must be specified";
diff --git a/web/app/assets/javascripts/checkout_signin.js b/web/app/assets/javascripts/checkout_signin.js
index 22ee88060..2416375c4 100644
--- a/web/app/assets/javascripts/checkout_signin.js
+++ b/web/app/assets/javascripts/checkout_signin.js
@@ -5,6 +5,7 @@
context.JK.CheckoutSignInScreen = function(app) {
var logger = context.JK.logger;
+ var rest = context.JK.Rest();
var $screen = null;
var $navigation = null;
@@ -17,6 +18,7 @@
var $inputElements = null;
var $contentHolder = null;
var $btnNext = null;
+ var $btnFacebook = null;
function beforeShow(data) {
renderNavigation();
@@ -44,6 +46,7 @@
$signinForm.on('submit', login);
$signinBtn.on('click', login);
$btnNext.on('click', moveNext);
+ $btnFacebook.on('click', facebookSignup);
}
function reset() {
@@ -55,6 +58,31 @@
return false;
}
+
+ function facebookSignup() {
+
+ var $btn = $(this);
+
+ if($btn.is('.disabled')) {
+ logger.debug("ignoring fast attempt at facebook signup")
+ return false;
+ }
+
+ $btn.addClass('disabled')
+
+ rest.createSignupHint({redirect_location: '/client#/checkoutPayment'})
+ .done(function() {
+ // send the user on to facebook signin
+ window.location = $btn.attr('href');
+ })
+ .fail(function() {
+ app.notify({text:"Facebook Signup is not working properly"});
+ })
+ .always(function() {
+ $btn.removeClass('disabled')
+ })
+ return false;
+ }
function login() {
if($signinBtn.is('.disabled')) {
return false;
@@ -117,6 +145,7 @@
$inputElements = $signinForm.find('.input-elements');
$contentHolder = $screen.find('.content-holder');
$btnNext = $screen.find('.btnNext');
+ $btnFacebook = $screen.find('.signin-facebook')
if($screen.length == 0) throw "$screen must be specified";
if($navigation.length == 0) throw "$navigation must be specified";
diff --git a/web/app/assets/javascripts/checkout_utils.js.coffee b/web/app/assets/javascripts/checkout_utils.js.coffee
index ec6f8bb98..4505725ad 100644
--- a/web/app/assets/javascripts/checkout_utils.js.coffee
+++ b/web/app/assets/javascripts/checkout_utils.js.coffee
@@ -16,7 +16,7 @@ class CheckoutUtils
setPreserveBillingInfo:() =>
date = new Date();
- minutes = 1;
+ minutes = 10;
date.setTime(date.getTime() + (minutes * 60 * 1000))
$.removeCookie(@cookie_name, { path: '/' })
$.cookie(@cookie_name, "jam", { expires: date, path: '/' })
diff --git a/web/app/assets/javascripts/corp/corporate.js b/web/app/assets/javascripts/corp/corporate.js
index 60cef8df2..989e7bb85 100644
--- a/web/app/assets/javascripts/corp/corporate.js
+++ b/web/app/assets/javascripts/corp/corporate.js
@@ -5,7 +5,7 @@
//= require globals
//= require jamkazam
//= require utils
-//= require ga
//= require jam_rest
+//= require ga
//= require corp/init
//= require_directory ../corp
\ No newline at end of file
diff --git a/web/app/assets/javascripts/dialog/banner.js b/web/app/assets/javascripts/dialog/banner.js
index 2ced92f0c..7e0fc0f12 100644
--- a/web/app/assets/javascripts/dialog/banner.js
+++ b/web/app/assets/javascripts/dialog/banner.js
@@ -135,7 +135,11 @@
if(!button.name) throw "button.name must be specified";
if(!button.click) throw "button.click must be specified";
- var buttonStyle = options.buttons.length == i + 1 ? 'button-orange' : 'button-grey';
+ var buttonStyle = button.buttonStyle;
+ if(!buttonStyle) {
+ buttonStyle = options.buttons.length == i + 1 ? 'button-orange' : 'button-grey';
+ }
+
var $btn = $('' + button.name + ' ');
$btn.click(function() {
diff --git a/web/app/assets/javascripts/dialog/clientPreferencesDialog.js b/web/app/assets/javascripts/dialog/clientPreferencesDialog.js
index 308006d3e..9b4f0fa72 100644
--- a/web/app/assets/javascripts/dialog/clientPreferencesDialog.js
+++ b/web/app/assets/javascripts/dialog/clientPreferencesDialog.js
@@ -21,6 +21,7 @@
var autostart = $autoStartField.find('.icheckbox_minimal').is('.checked');
context.jamClient.SetAutoStart(autostart);
app.layout.closeDialog('client-preferences-dialog')
+ context.jamClient.SaveSettings();
return false;
})
}
@@ -54,4 +55,4 @@
this.initialize = initialize;
}
-})(window, jQuery);
\ No newline at end of file
+})(window, jQuery);
diff --git a/web/app/assets/javascripts/dialog/gettingStartedDialog.js b/web/app/assets/javascripts/dialog/gettingStartedDialog.js
index db80c15ad..0faa28699 100644
--- a/web/app/assets/javascripts/dialog/gettingStartedDialog.js
+++ b/web/app/assets/javascripts/dialog/gettingStartedDialog.js
@@ -50,7 +50,7 @@
$browserJamTrackBtn.click(function() {
app.layout.closeDialog('getting-started')
- window.location = '/client#/jamtrack'
+ window.location = '/client#/jamtrackBrowse'
return false;
})
diff --git a/web/app/assets/javascripts/dialog/openBackingTrackDialog.js b/web/app/assets/javascripts/dialog/openBackingTrackDialog.js
index 87150456f..bd0d136aa 100644
--- a/web/app/assets/javascripts/dialog/openBackingTrackDialog.js
+++ b/web/app/assets/javascripts/dialog/openBackingTrackDialog.js
@@ -49,7 +49,6 @@
function getBackingTracks(page) {
var result = context.jamClient.getBackingTrackList();
- console.log("result", result)
var backingTracks = result.backing_tracks;
if (!backingTracks || backingTracks.length == 0) {
@@ -89,8 +88,7 @@
rest.openBackingTrack({id: context.JK.CurrentSessionModel.id(), backing_track_path: backingTrack.name})
.done(function(response) {
var result = context.jamClient.SessionOpenBackingTrackFile(backingTrack.name, false);
- console.log("BackingTrackPlay response: %o", result);
-
+
// TODO: Possibly actually check the result. Investigate
// what real client returns:
// // if(result) {
diff --git a/web/app/assets/javascripts/dialog/recordingFinishedDialog.js b/web/app/assets/javascripts/dialog/recordingFinishedDialog.js
index f78022877..866e460a1 100644
--- a/web/app/assets/javascripts/dialog/recordingFinishedDialog.js
+++ b/web/app/assets/javascripts/dialog/recordingFinishedDialog.js
@@ -10,10 +10,10 @@
var $dialog = null;
function resetForm() {
-
// remove all display errors
$('#recording-finished-dialog form .error-text').remove()
$('#recording-finished-dialog form .error').removeClass("error")
+ removeGoogleLoginErrors()
}
function beforeShow() {
@@ -130,11 +130,47 @@
return false;
}
+ function startGoogleLogin(e) {
+ e.preventDefault()
+ logger.debug("Starting google login")
+ window._oauth_win = window.open("/auth/google_login", "Log In to Google", "height=500,width=500,menubar=no,resizable=no,status=no");
+
+ window._oauth_callback = function() {
+ window._oauth_win.close()
+ setGoogleAuthState()
+ }
+ return false;
+ }
+
function claimRecording(e) {
-
resetForm();
- registerClaimRecordingHandlers(false);
+ registerClaimRecordingHandlers(false)
+ var upload_to_youtube = $('#recording-finished-dialog form input[name=upload_to_youtube]').is(':checked')
+
+ if (upload_to_youtube) {
+ $.ajax({
+ type: "GET",
+ dataType: "json",
+ url: "/auth/has_google_auth"
+ }).success(function(data) {
+ if(data.has_google_auth) {
+ performClaim()
+ } else {
+ var error_ul = $('You must sign in to YouTube ')
+ $('#recording-finished-dialog form [purpose=upload_to_youtube]').addClass('error').append(error_ul)
+ }
+ }).always(function () {
+ registerClaimRecordingHandlers(true);
+ })
+ } else {
+ performClaim()
+ }
+
+ return false;
+ }
+
+ function performClaim() {
var name = $('#recording-finished-dialog form input[name=name]').val();
var description = $('#recording-finished-dialog form textarea[name=description]').val();
var genre = $('#recording-finished-dialog form select[name=genre]').val();
@@ -151,59 +187,53 @@
save_video: save_video,
upload_to_youtube: upload_to_youtube
})
- .done(function () {
- $dialog.data('result', {keep:true});
- app.layout.closeDialog('recordingFinished');
- context.JK.GA.trackMakeRecording();
- })
- .fail(function (jqXHR) {
- if (jqXHR.status == 422) {
- var errors = JSON.parse(jqXHR.responseText);
+ .done(function () {
+ $dialog.data('result', {keep:true});
+ app.layout.closeDialog('recordingFinished');
+ context.JK.GA.trackMakeRecording();
+ })
+ .fail(function (jqXHR) {
+ if (jqXHR.status == 422) {
+ var errors = JSON.parse(jqXHR.responseText);
- var $name_errors = context.JK.format_errors('name', errors);
- if ($name_errors) $('#recording-finished-dialog form input[name=name]').closest('div.field').addClass('error').end().after($name_errors);
+ var $name_errors = context.JK.format_errors('name', errors);
+ if ($name_errors) $('#recording-finished-dialog form input[name=name]').closest('div.field').addClass('error').end().after($name_errors);
- var $description_errors = context.JK.format_errors('description', errors);
- if ($description_errors) $('#recording-finished-dialog form input[name=description]').closest('div.field').addClass('error').end().after($description_errors);
+ var $description_errors = context.JK.format_errors('description', errors);
+ if ($description_errors) $('#recording-finished-dialog form input[name=description]').closest('div.field').addClass('error').end().after($description_errors);
- var $genre_errors = context.JK.format_errors('genre', errors);
- if ($genre_errors) $('#recording-finished-dialog form select[name=genre]').closest('div.field').addClass('error').end().after($genre_errors);
+ var $genre_errors = context.JK.format_errors('genre', errors);
+ if ($genre_errors) $('#recording-finished-dialog form select[name=genre]').closest('div.field').addClass('error').end().after($genre_errors);
- var $is_public_errors = context.JK.format_errors('is_public', errors);
- if ($is_public_errors) $('#recording-finished-dialog form input[name=is_public]').closest('div.field').addClass('error').end().after($is_public_errors);
+ var $is_public_errors = context.JK.format_errors('is_public', errors);
+ if ($is_public_errors) $('#recording-finished-dialog form input[name=is_public]').closest('div.field').addClass('error').end().after($is_public_errors);
- var $save_video_errors = context.JK.format_errors('save_video', errors);
- if ($save_video_errors) $('#recording-finished-dialog form input[name=save_video]').closest('div.field').addClass('error').end().after($save_video_errors);
+ var $save_video_errors = context.JK.format_errors('save_video', errors);
+ if ($save_video_errors) $('#recording-finished-dialog form input[name=save_video]').closest('div.field').addClass('error').end().after($save_video_errors);
+
+ var recording_error = context.JK.get_first_error('recording_id', errors);
- var $upload_to_youtube_errors = context.JK.format_errors('upload_to_youtube', errors);
- if ($upload_to_youtube_errors) $('#recording-finished-dialog form input[name=upload_to_youtube]').closest('div.field').addClass('error').end().after($upload_to_youtube_errors);
+ if (recording_error) context.JK.showErrorDialog(app, "Unable to claim recording.", recording_error);
+ }
+ else {
+ logger.error("unable to claim recording %o", arguments);
- var recording_error = context.JK.get_first_error('recording_id', errors);
-
- if (recording_error) context.JK.showErrorDialog(app, "Unable to claim recording.", recording_error);
- }
- else {
- logger.error("unable to claim recording %o", arguments);
-
- context.JK.showErrorDialog(app, "Unable to claim recording.", jqXHR.responseText);
- }
- })
- .always(function () {
- registerClaimRecordingHandlers(true);
- });
- return false;
+ context.JK.showErrorDialog(app, "Unable to claim recording.", jqXHR.responseText);
+ }
+ })
+ .always(function () {
+ registerClaimRecordingHandlers(true);
+ });
}
function registerClaimRecordingHandlers(onOff) {
+ $('#keep-session-recording').off('click', claimRecording)
+ $('#recording-finished-dialog form').off('submit', claimRecording);
+
if (onOff) {
$('#keep-session-recording').on('click', claimRecording);
$('#recording-finished-dialog form').on('submit', claimRecording);
}
- else {
- $('#keep-session-recording').off('click', claimRecording)
- $('#recording-finished-dialog form').off('submit', claimRecording);
- }
-
}
function registerDiscardRecordingHandlers(onOff) {
@@ -216,6 +246,11 @@
}
function onPause() {
+ logger.debug("calling jamClient.SessionPausePlay");
+ context.jamClient.SessionPausePlay();
+ }
+
+ function onStop() {
logger.debug("calling jamClient.SessionStopPlay");
context.jamClient.SessionStopPlay();
}
@@ -234,9 +269,39 @@
registerClaimRecordingHandlers(true);
registerDiscardRecordingHandlers(true);
$(playbackControls)
+ .on('stop', onStop)
.on('pause', onPause)
.on('play', onPlay)
.on('change-position', onChangePlayPosition);
+ $dialog.find(".google_login_button").on('click', startGoogleLogin);
+
+ // Check for google authorization using AJAX and show/hide the
+ // google login button / "signed in" label as appropriate:
+ $(window).on('focus', function() {
+ setGoogleAuthState();
+ });
+ }
+
+ function setGoogleAuthState() {
+ $.ajax({
+ type: "GET",
+ dataType: "json",
+ url: "/auth/has_google_auth"
+ }).success(function(data) {
+ if(data.has_google_auth) {
+ $("input.google_login_button").addClass("hidden")
+ $("span.signed_in_to_google").removeClass("hidden")
+ removeGoogleLoginErrors()
+ } else {
+ $("span.signed_in_to_google").addClass("hidden")
+ $("input.google_login_button").removeClass("hidden")
+ }
+ })
+ }
+
+ function removeGoogleLoginErrors() {
+ $("ul.error-text.upload_to_youtube").remove()
+ $('#recording-finished-dialog form div[purpose=upload_to_youtube]').removeClass('error')
}
function setRecording(recordingData) {
@@ -267,7 +332,6 @@
playbackControls = new context.JK.PlaybackControls($('#recording-finished-dialog .recording-controls'));
registerStaticEvents();
-
initializeButtons();
};
diff --git a/web/app/assets/javascripts/dialog/singlePlayerProfileGuard.js.coffee b/web/app/assets/javascripts/dialog/singlePlayerProfileGuard.js.coffee
index d94a21d6a..4c54d1a06 100644
--- a/web/app/assets/javascripts/dialog/singlePlayerProfileGuard.js.coffee
+++ b/web/app/assets/javascripts/dialog/singlePlayerProfileGuard.js.coffee
@@ -42,7 +42,7 @@ context.JK.SinglePlayerProfileGuardDialog = class SinglePlayerProfileGuardDialog
latency = '?'
if canPlayWithOthers.audioLatency?
- latency = canPlayWithOthers.audioLatency
+ latency = canPlayWithOthers.audioLatency.toFixed(2)
@audioLatency.text("#{latency} milliseconds.")
diff --git a/web/app/assets/javascripts/download_jamtrack.js.coffee b/web/app/assets/javascripts/download_jamtrack.js.coffee
index 8442fec02..634d1b9ae 100644
--- a/web/app/assets/javascripts/download_jamtrack.js.coffee
+++ b/web/app/assets/javascripts/download_jamtrack.js.coffee
@@ -48,6 +48,8 @@ context.JK.DownloadJamTrack = class DownloadJamTrack
@tracked = false
@ajaxEnqueueAborted = false
@ajaxGetJamTrackRightAborted = false
+ @currentPackagingStep = null
+ @totalSteps = null
throw "no JamTrack specified" unless @jamTrack?
throw "invalid size" if @size != 'large' && @size != 'small'
@@ -174,6 +176,7 @@ context.JK.DownloadJamTrack = class DownloadJamTrack
if @state == @states.errored
data.result = 'error'
data.detail = @errorReason
+ @rest.createAlert("JamTrack Sync failed for #{context.JK.currentUserName}", data)
else
data.result = 'success'
@@ -187,7 +190,10 @@ context.JK.DownloadJamTrack = class DownloadJamTrack
showDownloading: () =>
@logger.debug("showing #{@state.name}")
# while downloading, we don't run the transition timer, because the download API is guaranteed to call success, or failure, eventually
- context.jamClient.JamTrackDownload(@jamTrack.id, this.makeDownloadSuccessCallback(), this.makeDownloadFailureCallback())
+ context.jamClient.JamTrackDownload(@jamTrack.id, context.JK.currentUserId,
+ this.makeDownloadProgressCallback(),
+ this.makeDownloadSuccessCallback(),
+ this.makeDownloadFailureCallback())
showKeying: () =>
@logger.debug("showing #{@state.name}")
@@ -374,8 +380,22 @@ context.JK.DownloadJamTrack = class DownloadJamTrack
.done(this.processJamTrackRight)
.fail(this.processJamTrackRightFail)
+ # update progress indicator for packaging step
+ updateSteps: () =>
+ if @currentPackagingStep? and @totalSteps?
+ progress = "#{Math.round(@currentPackagingStep/@totalSteps * 100)}%"
+ else
+ progress = '...'
+
+ @root.find('.state-packaging .progress').text(progress)
+
+ processSigningState: (jamTrackRight) =>
+ signingState = jamTrackRight.signing_state
+ @totalSteps = jamTrackRight.packaging_steps
+ @currentPackagingStep = jamTrackRight.current_packaging_step
+
+ @updateSteps()
- processSigningState: (signingState) =>
@logger.debug("DownloadJamTrack: processSigningState: " + signingState)
switch signingState
@@ -435,8 +455,9 @@ context.JK.DownloadJamTrack = class DownloadJamTrack
processJamTrackRight: (myJamTrack) =>
+ @logger.debug("processJamTrackRight", myJamTrack)
unless @ajaxGetJamTrackRightAborted
- this.processSigningState(myJamTrack.signing_state)
+ this.processSigningState(myJamTrack)
else
@logger.debug("DownloadJamTrack: ignoring processJamTrackRight response")
@@ -459,16 +480,26 @@ context.JK.DownloadJamTrack = class DownloadJamTrack
@logger.debug("DownloadJamTrack: ignoring processEnqueueJamTrackFail response")
onJamTrackRightEvent: (e, data) =>
- @logger.debug("DownloadJamTrack: subscription notification received: type:" + data.type)
+ @logger.debug("DownloadJamTrack: subscription notification received: type:" + data.type, data)
this.expectTransition()
- this.processSigningState(data.body.signing_state)
+ this.processSigningState(data.body)
- downloadProgressCallback: (bytesReceived, bytesTotal, downloadSpeedMegSec, timeRemaining) =>
- bytesReceived = Number(bytesReceived)
- bytesTotal = Number(bytesTotal)
- # bytesTotal from Qt is not trust worthy; trust server's answer instead
- #progressWidth = ((bytesReceived / updateSize) * 100).toString() + "%";
- # $('#progress-bar').width(progressWidth)
+ updateDownloadProgress: () =>
+
+ if @bytesReceived? and @bytesTotal?
+ progress = "#{Math.round(@bytesReceived/@bytesTotal * 100)}%"
+ else
+ progress = '0%'
+
+ @root.find('.state-downloading .progress').text(progress)
+
+ downloadProgressCallback: (bytesReceived, bytesTotal) =>
+ @logger.debug("download #{bytesReceived}/#{bytesTotal}")
+
+ @bytesReceived = Number(bytesReceived)
+ @bytesTotal = Number(bytesTotal)
+
+ setTimeout(this.updateDownloadProgress, 100)
downloadSuccessCallback: (updateLocation) =>
# is the package loadable yet?
diff --git a/web/app/assets/javascripts/everywhere/everywhere.js b/web/app/assets/javascripts/everywhere/everywhere.js
index 2c010bac2..741f70b3b 100644
--- a/web/app/assets/javascripts/everywhere/everywhere.js
+++ b/web/app/assets/javascripts/everywhere/everywhere.js
@@ -20,6 +20,7 @@
var stun = null;
var rest = context.JK.Rest();
+
$(document).on('JAMKAZAM_CONSTRUCTED', function(e, data) {
var app = data.app;
@@ -31,6 +32,8 @@
updateScoringIntervals();
initializeInfluxDB();
+
+ trackNewUser();
})
$(document).on('JAMKAZAM_READY', function() {
@@ -204,9 +207,9 @@
var user = app.user()
if(user) {
user.done(function(userProfile) {
- if (userProfile.show_whats_next && userProfile.show_whats_next_count < 10 &&
+ if (!userProfile.show_jamtrack_guide && userProfile.show_whats_next && userProfile.show_whats_next_count < 10 &&
window.location.pathname.indexOf(gon.client_path) == 0 &&
- window.location.pathname.indexOf('/checkout') == -1 &&
+ window.location.hash.indexOf('/checkout') == -1 &&
!app.layout.isDialogShowing('getting-started'))
{
app.layout.showDialog('getting-started');
@@ -219,4 +222,26 @@
context.JK.JamTrackUtils.checkShoppingCart();
}
+ function trackNewUser() {
+ var cookie = $.cookie('new_user')
+
+ if(cookie) {
+ try {
+ cookie = JSON.parse(cookie)
+
+ context.JK.signup = {}
+ context.JK.signup = cookie
+
+ $(function() {
+ // ga() object isn't ready until the page is loaded
+ $.removeCookie('new_user')
+ context.JK.GA.trackRegister(cookie.musician, cookie.registrationType);
+ });
+ }
+ catch(e) {
+ logger.error("unable to deserialize new_user cookie")
+ }
+ }
+ }
+
})(window, jQuery);
diff --git a/web/app/assets/javascripts/fakeJamClient.js b/web/app/assets/javascripts/fakeJamClient.js
index 732547d19..98468defb 100644
--- a/web/app/assets/javascripts/fakeJamClient.js
+++ b/web/app/assets/javascripts/fakeJamClient.js
@@ -21,6 +21,7 @@
var frameSize = 2.5;
var fakeJamClientRecordings = null;
var p2pCallbacks = null;
+ var videoShared = false;
var metronomeActive=false;
var metronomeBPM=false;
var metronomeSound=false;
@@ -59,6 +60,45 @@
function FTUESetMusicProfileName() {
}
+
+ function FTUESelectVideoCaptureDevice(device, settings) {
+
+ }
+ function FTUESetVideoEncodeResolution(resolution) {
+
+ }
+ function FTUEGetVideoCaptureDeviceNames() {
+ return ["Built-in Webcam HD"]
+ }
+ function FTUECurrentSelectedVideoDevice() {
+ return {"xy323ss": "Built-in Webcam HD"}
+ }
+ function FTUEGetAvailableEncodeVideoResolutions() {
+ return {
+ 1: "1024x768",
+ 2: "800x600"
+ }
+ }
+
+ function FTUEGetVideoCaptureDeviceCapabilities() {
+ return {}
+ }
+
+ function isSessVideoShared() {
+ return videoShared;
+ }
+
+ function SessStopVideoSharing() {
+ videoShared=false;
+ }
+
+ function SessStartVideoSharing(bitrate) {
+ if (!bitrate || typeof(bitrate)=="undefined") {
+ bitrate = 0
+ }
+ videoShared=true;
+ }
+
function FTUEGetInputLatency() {
dbg("FTUEGetInputLatency");
return 2;
@@ -403,6 +443,14 @@
}
// Session Functions
+
+ function SessionCurrrentJamTrackPlayPosMs() {
+ return 0;
+ }
+
+ function SessionGetJamTracksPlayDurationMs() {
+ return 60000;
+ }
function SessionAddTrack() {}
function SessionAudioResync() {
@@ -931,6 +979,7 @@
function LeaveSessionAndMinimize() {}
function SetAutoStart() {}
function GetAutoStart() { return true; }
+ function SaveSettings() {}
// Javascript Bridge seems to camel-case
// Set the instance functions:
@@ -1031,6 +1080,8 @@
// Session
this.SessionAddTrack = SessionAddTrack;
+ this.SessionCurrrentJamTrackPlayPosMs = SessionCurrrentJamTrackPlayPosMs;
+ this.SessionGetJamTracksPlayDurationMs = SessionGetJamTracksPlayDurationMs;
this.SessionGetControlState = SessionGetControlState;
this.SessionGetAllControlState = SessionGetAllControlState;
this.SessionSetUserName = SessionSetUserName;
@@ -1140,6 +1191,19 @@
this.ClosePreviewRecording = ClosePreviewRecording;
this.OnDownloadAvailable = OnDownloadAvailable;
+ // Video functionality:
+ this.FTUESelectVideoCaptureDevice = FTUESelectVideoCaptureDevice
+ this.FTUESetVideoEncodeResolution = FTUESetVideoEncodeResolution;
+ this.FTUEGetVideoCaptureDeviceNames = FTUEGetVideoCaptureDeviceNames;
+ this.FTUECurrentSelectedVideoDevice = FTUECurrentSelectedVideoDevice;
+ this.FTUEGetAvailableEncodeVideoResolutions = FTUEGetAvailableEncodeVideoResolutions;
+ this.FTUEGetVideoCaptureDeviceCapabilities = FTUEGetVideoCaptureDeviceCapabilities;
+
+
+ this.isSessVideoShared = isSessVideoShared;
+ this.SessStopVideoSharing = SessStopVideoSharing;
+ this.SessStartVideoSharing = SessStartVideoSharing;
+
// Clipboard
this.SaveToClipboard = SaveToClipboard;
@@ -1169,4 +1233,4 @@
this.clientID = "devtester";
};
- })(window,jQuery);
\ No newline at end of file
+ })(window,jQuery);
diff --git a/web/app/assets/javascripts/ga.js b/web/app/assets/javascripts/ga.js
index 4fe5e565d..8e51a081e 100644
--- a/web/app/assets/javascripts/ga.js
+++ b/web/app/assets/javascripts/ga.js
@@ -6,6 +6,7 @@
"use strict";
context.JK = context.JK || {};
+ var rest = context.JK.Rest();
var logger = context.JK.logger;
// types
@@ -130,6 +131,20 @@
jkComment : 'jkComment'
};
+ // JamTrack categories and actions:
+ var jamTrackAvailabilityTypes = {
+ worldwide: 'JamTrackGlobal',
+ usa: 'JamTrackUSA'
+ }
+ var jamTrackActions = {
+ isPublic: 'PublicPerformance',
+ isPrivate: 'PrivateUse'
+ }
+ var jamTrackSessionLabels = {
+ nonSession: 'NonSession',
+ inSession: 'InSession'
+ }
+
function translatePlatformForGA(platform) {
assertOneOf(platform, context.JK.OS);
@@ -239,6 +254,36 @@
context.ga('send', 'event', categories.findSession, sessionCountRollup, numSessionsFound);
}
+ function trackJamTrackPlaySession(sessionId, inSession) {
+ rest.getSession(sessionId).done(function(session) {
+ if (session && session.jam_track ) {
+ rest.getJamTracks({id:session.jam_track.id}).done(function(response) {
+ if (response.jamtracks && response.jamtracks.length!=0) {
+ var jamtrack = response.jamtracks[0]
+ trackJamTrackPlay(
+ jamtrack.sales_region!=context.JK.AVAILABILITY_US,
+ session.participants.length > 1,
+ inSession);
+ }// if
+ })// rest.getJamTracks
+ }// if
+ })// rest.getSession
+ }
+
+ function trackJamTrackPlay(isGlobal, isPublic, inSession) {
+ assertBoolean(isGlobal)
+ assertBoolean(isPublic)
+ assertBoolean(inSession)
+ context.ga(
+ 'send',
+ 'event',
+ (isGlobal) ? jamTrackAvailabilityTypes.worldwide : jamTrackAvailabilityTypes.usa,
+ (isPublic) ? jamTrackActions.isPublic : jamTrackActions.isPrivate,
+ (inSession) ? jamTrackSessionLabels.inSession : jamTrackSessionLabels.nonSession
+ )
+ logger.debug("Tracked Jam Track Play")
+ }
+
// if you want to pass in no title, either omit it from the arg list when u invoke virtualPageView, or pass in undefined, NOT null
function virtualPageView(page, title) {
@@ -271,7 +316,8 @@
}
// when someone plays a recording
- function trackRecordingPlay(recordingAction) {
+ function trackRecordingPlay(recording, recordingAction) {
+
if (!recordingAction) {
recordingAction = _defaultPlayAction();
}
@@ -279,10 +325,20 @@
var label = JK.currentUserId ? userLabels.registeredUser : userLabels.visitor;
context.ga('send', 'event', categories.recordingPlay, recordingAction, label);
+
+ if (recording.jam_track) {
+ rest.getJamTracks({id:recording.jam_track_id}).done(function(response) {
+ if (response.jamtracks && response.jamtracks.length==1) {
+ var jamtrack = response.jamtracks[0]
+ trackJamTrackPlay(jamtrack.sales_region!=context.JK.AVAILABILITY_US, recording.fan_access, false);
+ }
+ })
+ }
}
// when someone plays a live session broadcast
- function trackSessionPlay(recordingAction) {
+ function trackSessionPlay(session, recordingAction) {
+ logger.debug("Tracking session play: ", session)
if (!recordingAction) {
recordingAction = _defaultPlayAction();
}
@@ -379,7 +435,8 @@
GA.trackSessionQuality = trackSessionQuality;
GA.trackServiceInvitations = trackServiceInvitations;
GA.trackFindSessions = trackFindSessions;
- GA.virtualPageView = virtualPageView;
+ GA.trackJamTrackPlay = trackJamTrackPlay;
+ GA.trackJamTrackPlaySession = trackJamTrackPlaySession;
GA.trackFriendConnect = trackFriendConnect;
GA.trackMakeRecording = trackMakeRecording;
GA.trackShareRecording = trackShareRecording;
@@ -387,8 +444,8 @@
GA.trackSessionPlay = trackSessionPlay;
GA.trackBand = trackBand;
GA.trackJKSocial = trackJKSocial;
-
-
+ GA.virtualPageView = virtualPageView;
+
context.JK.GA = GA;
})(window,jQuery);
\ No newline at end of file
diff --git a/web/app/assets/javascripts/helpBubbleHelper.js b/web/app/assets/javascripts/helpBubbleHelper.js
index 9c9a05bd5..eb68a4a6c 100644
--- a/web/app/assets/javascripts/helpBubbleHelper.js
+++ b/web/app/assets/javascripts/helpBubbleHelper.js
@@ -10,6 +10,7 @@
var rest = new context.JK.Rest();
context.JK.HelpBubbleHelper = helpBubble;
var logger = context.JK.logger;
+ var jamTrackGuideTimeout = null;
var defaultScoreBreakDownOptions = {positions: ['right', 'top', 'bottom', 'left'], width:'600px', closeWhenOthersOpen: true };
helpBubble.scoreBreakdown = function($element, isCurrentUser, full_score, myAudioLatency, otherAudioLatency, internetScore, options) {
@@ -26,4 +27,59 @@
}
}
+ function bigHelpOptions(options) {
+ return {positions: options.positions, offsetParent: options.offsetParent,
+ spikeGirth: 15,
+ spikeLength: 20,
+ fill: 'white',
+ cornerRadius:8,
+ strokeWidth: 2,
+ cssStyles: {
+ fontWeight:'bold',
+ fontSize: '20px',
+ backgroundColor:'transparent',
+ color:'#ed3618'}}
+ }
+
+ function clearJamTrackGuideTimeout() {
+ if(jamTrackGuideTimeout) {
+ clearTimeout(jamTrackGuideTimeout);
+ jamTrackGuideTimeout = null;
+ }
+ }
+
+ function jamTrackGuide(callback) {
+ if(gon.isNativeClient) {
+ context.JK.app.user().done(function(user) {
+ if(user.show_jamtrack_guide) {
+ clearJamTrackGuideTimeout();
+ jamTrackGuideTimeout = setTimeout(function() {
+ callback()
+ }, 1000)
+
+ }
+ })
+ }
+ }
+
+ helpBubble.clearJamTrackGuide = clearJamTrackGuideTimeout;
+
+ helpBubble.jamtrackGuideTile = function ($element, $offsetParent) {
+ jamTrackGuide(function() {
+ context.JK.prodBubble($element, 'jamtrack-guide-tile', {}, bigHelpOptions({positions:['top'], offsetParent: $offsetParent}))
+ })
+ }
+
+ helpBubble.jamtrackGuidePrivate = function ($element, $offsetParent) {
+ jamTrackGuide(function() {
+ context.JK.prodBubble($element, 'jamtrack-guide-private', {}, bigHelpOptions({positions:['right'], offsetParent: $offsetParent}))
+ })
+ }
+
+ helpBubble.jamtrackGuideSession = function ($element, $offsetParent) {
+ jamTrackGuide(function() {
+ context.JK.prodBubble($element, 'jamtrack-guide-session', {}, bigHelpOptions({positions:['left'], offsetParent: $offsetParent}))
+ })
+ }
+
})(window, jQuery);
\ No newline at end of file
diff --git a/web/app/assets/javascripts/homeScreen.js b/web/app/assets/javascripts/homeScreen.js
index ec7b86d50..a96075b47 100644
--- a/web/app/assets/javascripts/homeScreen.js
+++ b/web/app/assets/javascripts/homeScreen.js
@@ -11,6 +11,14 @@
function beforeShow(data) {
}
+ function afterShow(data) {
+ context.JK.HelpBubbleHelper.jamtrackGuideTile($('.homecard.createsession'), $screen.find('.createsession'));
+ }
+
+ function beforeHide() {
+ context.JK.HelpBubbleHelper.clearJamTrackGuide();
+ }
+
function mouseenterTile() {
$(this).addClass('hover');
}
@@ -84,7 +92,7 @@
}
this.initialize = function() {
- var screenBindings = { 'beforeShow': beforeShow };
+ var screenBindings = { 'beforeShow': beforeShow, 'afterShow': afterShow, 'beforeHide' : beforeHide };
app.bindScreen('home', screenBindings);
events();
$screen = $('.screen[layout-id="home"]')
diff --git a/web/app/assets/javascripts/jam_rest.js b/web/app/assets/javascripts/jam_rest.js
index 82afb1fc5..6c3cce4f0 100644
--- a/web/app/assets/javascripts/jam_rest.js
+++ b/web/app/assets/javascripts/jam_rest.js
@@ -287,11 +287,6 @@
}
function addPlayablePlay(playableId, playableType, claimedRecordingId, userId) {
- if (playableType == 'JamRuby::Recording') {
- context.JK.GA.trackRecordingPlay();
- } else if (playableType == 'JamRuby::MusicSession') {
- context.JK.GA.trackSessionPlay();
- }
return $.ajax({
url: '/api/users/' + playableId + "/plays",
type: "POST",
@@ -1466,7 +1461,7 @@
});
}
- function getJamtracks(options) {
+ function getJamTracks(options) {
return $.ajax({
type: "GET",
url: '/api/jamtracks?' + $.param(options),
@@ -1475,6 +1470,15 @@
});
}
+ function getJamTrackArtists(options) {
+ return $.ajax({
+ type: "GET",
+ url: '/api/jamtracks/artists?' + $.param(options),
+ dataType: "json",
+ contentType: 'application/json'
+ });
+ }
+
function getJamTrackRight(options) {
var jamTrackId = options['id'];
@@ -1518,7 +1522,7 @@
function getSalesHistory(options) {
return $.ajax({
type: "GET",
- url: '/api/sales?' + $.param(options),
+ url: '/api/payment_histories?' + $.param(options),
dataType: "json",
contentType: 'application/json'
});
@@ -1675,7 +1679,30 @@
});
}
- function initialize() {
+ function createSignupHint(data) {
+ return $.ajax({
+ type: "POST",
+ url: '/api/signup_hints',
+ dataType: "json",
+ contentType: 'application/json',
+ data: JSON.stringify(data),
+ });
+ }
+
+ function createAlert(subject, data) {
+ var message = {subject:subject};
+ $.extend(message, data);
+ console.log("message", message)
+ return $.ajax({
+ type: "POST",
+ url: '/api/alerts',
+ dataType: "json",
+ contentType: 'application/json',
+ data: JSON.stringify(message),
+ });
+ }
+
+ function initialize() {
return self;
}
@@ -1799,7 +1826,8 @@
this.updateAudioLatency = updateAudioLatency;
this.getJamTrack = getJamTrack;
this.getJamTrackWithArtistInfo = getJamTrackWithArtistInfo;
- this.getJamtracks = getJamtracks;
+ this.getJamTracks = getJamTracks;
+ this.getJamTrackArtists = getJamTrackArtists;
this.getPurchasedJamTracks = getPurchasedJamTracks;
this.getPaymentHistory = getPaymentHistory;
this.getSalesHistory = getSalesHistory;
@@ -1825,6 +1853,8 @@
this.getMusicianSearchFilter = getMusicianSearchFilter;
this.postMusicianSearchFilter = postMusicianSearchFilter;
this.playJamTrack = playJamTrack;
+ this.createSignupHint = createSignupHint;
+ this.createAlert = createAlert;
return this;
};
diff --git a/web/app/assets/javascripts/jam_track_preview.js.coffee b/web/app/assets/javascripts/jam_track_preview.js.coffee
index 926a8d824..78a3d97dd 100644
--- a/web/app/assets/javascripts/jam_track_preview.js.coffee
+++ b/web/app/assets/javascripts/jam_track_preview.js.coffee
@@ -9,7 +9,7 @@ context.JK.JamTrackPreview = class JamTrackPreview
@EVENTS = context.JK.EVENTS
@rest = context.JK.Rest()
@logger = context.JK.logger
- @options = options || {master_shows_duration: false}
+ @options = options || {master_shows_duration: false, color:'gray'}
@app = app
@jamTrack = jamTrack
@jamTrackTrack = jamTrackTrack
@@ -23,7 +23,7 @@ context.JK.JamTrackPreview = class JamTrackPreview
template = $('#template-jam-track-preview')
throw "no jam track preview template" if not template.exists()
- @root.html($(template.html()))
+ @root.html(context._.template(template.html(), @options, {variable:'data'}))
@playButton = @root.find('.play-button')
@stopButton = @root.find('.stop-button')
@instrumentIcon = @root.find('.instrument-icon')
diff --git a/web/app/assets/javascripts/jam_track_screen.js.coffee b/web/app/assets/javascripts/jam_track_screen.js.coffee
index 6cea8e994..8247fbaeb 100644
--- a/web/app/assets/javascripts/jam_track_screen.js.coffee
+++ b/web/app/assets/javascripts/jam_track_screen.js.coffee
@@ -50,7 +50,7 @@ context.JK.JamTrackScreen=class JamTrackScreen
@instrument.val(parms.instrument)
if(parms.availability?)
@availability.val(parms.availability)
- window.history.replaceState({}, "", "/client#/jamtrack")
+ window.history.replaceState({}, "", "/client#/jamtrackBrowse")
getParams:() =>
params = {}
@@ -63,16 +63,31 @@ context.JK.JamTrackScreen=class JamTrackScreen
params[key] = decodeURIComponent(val)
params
+ setFilterState: (state) =>
+ if state
+ @genre.easyDropDown('enable').removeAttr('disabled')
+ @artist.easyDropDown('enable').removeAttr('disabled')
+ @instrument.easyDropDown('enable').removeAttr('disabled')
+ @availability.easyDropDown('enable').removeAttr('disabled')
+ else
+ @genre.easyDropDown('disable').attr('disabled', 'disabled')
+ @artist.easyDropDown('disable').attr('disabled', 'disabled')
+ @instrument.easyDropDown('disable').attr('disabled', 'disabled')
+ @availability.easyDropDown('disable').attr('disabled', 'disabled')
+
refresh:() =>
+ this.clearResults()
@currentQuery = this.buildQuery()
that = this
- rest.getJamtracks(@currentQuery).done((response) =>
- that.clearResults()
+ this.setFilterState(false)
+ rest.getJamTracks(@currentQuery).done((response) =>
that.handleJamtrackResponse(response)
- ).fail (jqXHR) =>
+ ).fail( (jqXHR) =>
that.clearResults()
that.noMoreJamtracks.show()
- that.app.notifyServerError jqXHR, 'Jamtrack Unavailable'
+ that.app.notifyServerError jqXHR, 'Jamtrack Unavailable'
+ ).always () =>
+ that.setFilterState(true)
search:() =>
this.refresh()
@@ -117,7 +132,7 @@ context.JK.JamTrackScreen=class JamTrackScreen
# if we less results than asked for, end searching
@scroller.infinitescroll 'pause'
if @currentPage == 0 and response.jamtracks.length == 0
- @content.append 'No JamTracks found.
'
+ @content.append '')
+ for track in jamTrack.tracks
+ trackElement.find("[jamtrack-track-id='#{track.id}']").removeClass('hidden')
+ else
+ trackElement.find('.extra').addClass('hidden')
+ detailArrow.html('preview all tracks ')
+ count = 0
+ for track in jamTrack.tracks
+ if count < 2
+ trackElement.find("[jamtrack-track-id='#{track.id}']").removeClass('hidden')
+ else
+ trackElement.find("[jamtrack-track-id='#{track.id}']").addClass('hidden')
+ count++
+
+
+ registerEvents:(parent) =>
#@screen.find('.jamtrack-detail-btn').on 'click', this.showJamtrackDescription
- @screen.find('.play-button').on 'click', this.playJamtrack
- @screen.find('.jamtrack-add-cart').on 'click', this.addToCartJamtrack
- @screen.find('.license-us-why').on 'click', this.licenseUSWhy
- @screen.find('.jamtrack-detail-btn').on 'click', this.toggleExpanded
+ parent.find('.play-button').on 'click', this.playJamtrack
+ parent.find('.jamtrack-add-cart').on 'click', this.addToCartJamtrack
+ parent.find('.license-us-why').on 'click', this.licenseUSWhy
+ parent.find('.jamtrack-detail-btn').on 'click', this.toggleExpanded
# @screen.find('.jamtrack-preview').each (index, element) =>
# new JK.JamTrackPreview(data.app, $element, jamTrack, track, {master_shows_duration: true})
@@ -188,37 +228,41 @@ context.JK.JamTrackScreen=class JamTrackScreen
trackRow.track_cnt = jamtrack.tracks.length
trackRow.tracks = []
for track in jamtrack.tracks
- if track.track_type != 'Master'
- trackRow.tracks.push(track)
- if track.track_type=='Master'
- track.instrument_desc = "Master"
- else
- inst = '../assets/content/icon_instrument_default24.png'
- if track.instrument?
- if track.instrument.id in instrument_logo_map
- inst = instrument_logo_map[track.instrument.id].asset
- track.instrument_desc = track.instrument.description
- track.instrument_url = inst
-
- if track.part != ''
- track.instrument_desc += ' (' + track.part + ')'
+ trackRow.tracks.push(track)
+ if track.track_type=='Master'
+ track.instrument_desc = "Master"
+ else
+ inst = '../assets/content/icon_instrument_default24.png'
+ if track.instrument?
+ if track.instrument.id in instrument_logo_map
+ inst = instrument_logo_map[track.instrument.id].asset
+ track.instrument_desc = track.instrument.description
+ track.instrument_url = inst
+
+ if track.part != ''
+ track.instrument_desc += ' (' + track.part + ')'
options =
jamtrack: trackRow
- expanded: jamtrackExpanded
+ expanded: false
@jamtrackItem = $(context._.template($('#template-jamtrack').html(), options, variable: 'data'))
that.renderJamtrack(@jamtrackItem, jamtrack)
-
- this.registerEvents()
+ that.registerEvents(@jamtrackItem)
+
renderJamtrack:(jamtrackElement, jamTrack) =>
+ jamtrackElement.data('jamTrack', jamTrack)
+ jamtrackElement.data('expanded', true)
+
@content.append jamtrackElement
- if this.expanded==jamTrack.id
- for track in jamTrack.tracks
- trackRow = jamtrackElement.find("[jamtrack-track-id='#{track.id}']")
- previewElement = trackRow.find(".jamtrack-preview")
- new JK.JamTrackPreview(@app, previewElement, jamTrack, track, {master_shows_duration: false})
+ #if this.expanded==jamTrack.id
+ for track in jamTrack.tracks
+ trackRow = jamtrackElement.find("[jamtrack-track-id='#{track.id}']")
+ previewElement = trackRow.find(".jamtrack-preview")
+ new JK.JamTrackPreview(@app, previewElement, jamTrack, track, {master_shows_duration: true, color:'gray'})
+
+ this.handleExpanded(jamtrackElement, false)
showJamtrackDescription:(e) =>
e.preventDefault()
@@ -232,17 +276,14 @@ context.JK.JamTrackScreen=class JamTrackScreen
e.preventDefault()
jamtrackRecord = $(e.target).parents('.jamtrack-record')
jamTrackId = jamtrackRecord.attr("jamtrack-id")
- if this.expanded==jamTrackId
- this.expanded = null
- else
- this.expanded = jamTrackId
- this.rerenderJamtracks()
+
+ this.handleExpanded(jamtrackRecord)
initialize:() =>
screenBindings =
'beforeShow': this.beforeShow
'afterShow': this.afterShow
- @app.bindScreen 'jamtrack', screenBindings
+ @app.bindScreen 'jamtrackBrowse', screenBindings
@screen = $('#jamtrack-find-form')
@scroller = @screen.find('.content-body-scroller')
@content = @screen.find('.jamtrack-content')
diff --git a/web/app/assets/javascripts/jamkazam.js b/web/app/assets/javascripts/jamkazam.js
index 2bc31b957..d1b41d451 100644
--- a/web/app/assets/javascripts/jamkazam.js
+++ b/web/app/assets/javascripts/jamkazam.js
@@ -344,6 +344,18 @@
return userData;
}
+ this.refreshUser = function() {
+ userDeferred = rest.getUserDetail();
+ if (userDeferred) {
+ userDeferred.done(this.updateUserCache)
+ }
+ else {
+ userDeferred = new $.Deferred();
+ userDeferred.reject('not_logged_in');
+ }
+ return userDeferred;
+ }
+
this.activeElementEvent = function(evtName, data) {
return this.layout.activeElementEvent(evtName, data);
}
diff --git a/web/app/assets/javascripts/jamtrack_landing.js.coffee b/web/app/assets/javascripts/jamtrack_landing.js.coffee
index 760744e9f..2fb470923 100644
--- a/web/app/assets/javascripts/jamtrack_landing.js.coffee
+++ b/web/app/assets/javascripts/jamtrack_landing.js.coffee
@@ -8,45 +8,70 @@ context.JK.JamTrackLanding = class JamTrackLanding
@client = context.jamClient
@logger = context.JK.logger
@screen = null
+ @noFreeJamTrack = null
+ @freeJamTrack = null
+ @bandList = null
+ @noBandsFound = null
initialize:() =>
screenBindings =
'beforeShow': @beforeShow
'afterShow': @afterShow
@app.bindScreen('jamtrackLanding', screenBindings)
- @screen = $('#jamtrackLanding')
-
+ @screen = $('#jamtrackLanding')
+ @noFreeJamTrack = @screen.find('.no-free-jamtrack')
+ @freeJamTrack = @screen.find('.free-jamtrack')
+ @bandList = @screen.find('#band_list')
+ @noBandsFound = @screen.find('#no_bands_found')
+
beforeShow:() =>
+
+ @noFreeJamTrack.addClass('hidden')
+ @freeJamTrack.addClass('hidden')
+
+ afterShow:() =>
+
+ if context.JK.currentUserId
+ @app.user().done(@onUser)
+ else
+ @onUser({free_jamtrack: gon.global.one_free_jamtrack_per_user})
+
+ onUser:(user) =>
+ if user.free_jamtrack
+ @freeJamTrack.removeClass('hidden')
+ else
+ @noFreeJamTrack.removeClass('hidden')
+
# Get artist names and build links
- @rest.getJamtracks({group_artist: true})
- .done(this.buildArtistLinks)
- .fail(this.handleFailure)
+ @rest.getJamTrackArtists({group_artist: true, per_page:100})
+ .done(this.buildArtistLinks)
+ .fail(this.handleFailure)
# Bind links to action that will open the jam_tracks list view filtered to given artist_name:
# artist_name
this.bindArtistLinks()
- afterShow:() =>
buildArtistLinks:(response) =>
- # Get artist names and build links
- jamtracks = response.jamtracks
+ # Get artist names and build links
+ @logger.debug("buildArtest links response", response)
+
+ artists = response.artists
$("#band_list>li:not('#no_bands_found')").remove()
- if jamtracks.length==0
- $("#no_bands_found").removeClass("hidden")
+ if artists.length==0
+ @noBandsFound.removeClass("hidden")
else
- $("#no_bands_found").addClass("hidden")
+ @noBandsFound.addClass("hidden")
# client#/jamtrack
- for jamtrack in jamtracks
- artistLink = "#{jamtrack.original_artist} "
- $("#band_list").append("#{artistLink} ")
+ for artist in artists
+ artistLink = "#{artist.original_artist} (#{artist.song_count}) "
+ @bandList.append("#{artistLink} ")
# We don't want to do a full page load if this is clicked on here:
bindArtistLinks:() =>
- band_list=$("ul#band_list")
that=this
- band_list.on "click", "a.artist-link", (event)->
- context.location="client#/jamtrack"
+ @bandList.on "click", "a.artist-link", (event)->
+ context.location="client#/jamtrackBrowse"
window.history.replaceState({}, "", this.href)
event.preventDefault()
diff --git a/web/app/assets/javascripts/jquery.listenRecording.js b/web/app/assets/javascripts/jquery.listenRecording.js
index 84a7628f7..1303f50f7 100644
--- a/web/app/assets/javascripts/jquery.listenRecording.js
+++ b/web/app/assets/javascripts/jquery.listenRecording.js
@@ -78,6 +78,10 @@
audioDomElement.play();
isPlaying = true;
rest.addPlayablePlay(recordingId, 'JamRuby::Recording', claimedRecordingId, context.JK.currentUserId);
+ rest.getRecording({id: recordingId})
+ .done(function(recording) {
+ context.JK.GA.trackRecordingPlay(recording);
+ })
})
}
diff --git a/web/app/assets/javascripts/jquery.listenbroadcast.js b/web/app/assets/javascripts/jquery.listenbroadcast.js
index f6964cd60..89c5184dd 100644
--- a/web/app/assets/javascripts/jquery.listenbroadcast.js
+++ b/web/app/assets/javascripts/jquery.listenbroadcast.js
@@ -112,7 +112,8 @@
waitForBufferingTimeout = setTimeout(noBuffer, WAIT_FOR_BUFFER_TIMEOUT);
logger.debug("setting buffering timeout");
rest.addPlayablePlay(musicSessionId, 'JamRuby::MusicSession', null, context.JK.currentUserId);
-
+ context.JK.GA.trackJamTrackPlaySession(musicSessionId, false)
+
if(needsCanPlayGuard()) {
$audio.bind('canplay', function() {
audioDomElement.play();
diff --git a/web/app/assets/javascripts/landing/landing.js b/web/app/assets/javascripts/landing/landing.js
index 0afe196f0..19034e53c 100644
--- a/web/app/assets/javascripts/landing/landing.js
+++ b/web/app/assets/javascripts/landing/landing.js
@@ -32,8 +32,8 @@
//= require jamkazam
//= require utils
//= require ui_helper
-//= require ga
//= require jam_rest
+//= require ga
//= require web/signup_helper
//= require web/signin_helper
//= require web/signin
diff --git a/web/app/assets/javascripts/playbackControls.js b/web/app/assets/javascripts/playbackControls.js
index 1a90712a6..fb82ab0c6 100644
--- a/web/app/assets/javascripts/playbackControls.js
+++ b/web/app/assets/javascripts/playbackControls.js
@@ -29,6 +29,7 @@
var $playButton = $('.play-button img.playbutton', $parentElement);
var $pauseButton = $('.play-button img.pausebutton', $parentElement);
+ var $stopButton = $('.stop-button img.stopbutton', $parentElement);
var $currentTime = $('.recording-current', $parentElement);
var $duration = $('.duration-time', $parentElement);
var $sliderBar = $('.recording-playback', $parentElement);
@@ -42,6 +43,7 @@
var playbackDurationMs = 0;
var playbackPositionMs = 0;
var durationChanged = false;
+ var seenActivity = false;
var endReached = false;
var dragging = false;
@@ -53,16 +55,28 @@
var playbackMonitorMode = PLAYBACK_MONITOR_MODE.MEDIA_FILE;
function startPlay() {
+ seenActivity = false;
updateIsPlaying(true);
if(endReached) {
update(0, playbackDurationMs, playbackPlaying);
}
$self.triggerHandler('play', {playbackMode: playbackMode, playbackMonitorMode: playbackMonitorMode});
+
+
+ if(playbackMonitorMode == PLAYBACK_MONITOR_MODE.JAMTRACK) {
+ var sessionModel = context.JK.CurrentSessionModel || null;
+ context.JK.GA.trackJamTrackPlaySession(sessionModel.id(), true)
+ }
}
function stopPlay(endReached) {
updateIsPlaying(false);
- $self.triggerHandler('pause', {playbackMode: playbackMode, playbackMonitorMode: playbackMonitorMode, endReached : endReached});
+ $self.triggerHandler('stop', {playbackMode: playbackMode, playbackMonitorMode: playbackMonitorMode, endReached : endReached});
+ }
+
+ function pausePlay(endReached) {
+ updateIsPlaying(false);
+ $self.triggerHandler('pause', {playbackMode: playbackMode, playbackMonitorMode: playbackMonitorMode, endReached : endReached});
}
function updateOffsetBasedOnPosition(offsetLeft) {
@@ -121,6 +135,17 @@
// return false;
//}
+ pausePlay();
+ return false;
+ });
+
+ $stopButton.on('click', function(e) {
+ var sessionModel = context.JK.CurrentSessionModel || null;
+ //if(sessionModel && sessionModel.areControlsLockedForJamTrackRecording() && $parentElement.closest('.session-track').data('track_data').type == 'jam_track') {
+ // context.JK.prodBubble($pauseButton, 'jamtrack-controls-disabled', {}, {positions:['top'], offsetParent: $pauseButton})
+ // return false;
+ //}
+
stopPlay();
return false;
});
@@ -182,8 +207,7 @@
var positionMs = context.jamClient.SessionCurrrentJamTrackPlayPosMs();
var duration = context.jamClient.SessionGetJamTracksPlayDurationMs();
var durationMs = duration.media_len;
- var start = duration.start; // needed to understand start offset, and prevent slider from moving in tapins
- //console.log("JamTrack start: " + start)
+ var start = duration.start; // needed to understand start offset, and prevent slider from moving in tapins
}
else {
var positionMs = context.jamClient.SessionCurrrentPlayPosMs();
@@ -197,18 +221,11 @@
positionMs = 0;
}
- if(playbackMonitorMode = PLAYBACK_MONITOR_MODE.JAMTRACK) {
-
- if(isPlaying) {
- $jamTrackGetReady.attr('data-current-time', positionMs)
- }
- else {
- // this is so the jamtrack 'Get Ready!' stays hidden when it's not playing
- $jamTrackGetReady.attr('data-current-time', -1)
- }
-
+ if(positionMs > 0) {
+ seenActivity = true;
}
+
if(playbackMonitorMode == PLAYBACK_MONITOR_MODE.METRONOME) {
updateIsPlaying(isPlaying);
}
@@ -216,6 +233,17 @@
update(positionMs, durationMs, isPlaying);
}
+ if(playbackMonitorMode == PLAYBACK_MONITOR_MODE.JAMTRACK) {
+
+ if(playbackPlaying) {
+ $jamTrackGetReady.attr('data-current-time', positionMs)
+ }
+ else {
+ // this is so the jamtrack 'Get Ready!' stays hidden when it's not playing
+ $jamTrackGetReady.attr('data-current-time', -1)
+ }
+
+ }
monitorPlaybackTimeout = setTimeout(monitorRecordingPlayback, 500);
}
@@ -227,9 +255,9 @@
}
// at the end of the play, the duration sets to 0, as does currentTime. but isPlaying does not reset to
- logger.debug("currentTimeMs, durationTimeMs", currentTimeMs, durationTimeMs);
- if(currentTimeMs == 0 && durationTimeMs == 0) {
- if(isPlaying) {
+ //logger.debug("currentTimeMs, durationTimeMs, mode", currentTimeMs, durationTimeMs, playbackMonitorMode);
+ if(currentTimeMs == 0 && seenActivity) {
+ if(playbackPlaying) {
isPlaying = false;
durationTimeMs = playbackDurationMs;
currentTimeMs = playbackDurationMs;
@@ -293,6 +321,7 @@
$pauseButton.hide();
}
+ logger.debug("updating is playing: " + isPlaying)
playbackPlaying = isPlaying;
}
}
diff --git a/web/app/assets/javascripts/scheduled_session.js.erb b/web/app/assets/javascripts/scheduled_session.js.erb
index a9ab74fa2..f2c07b7bc 100644
--- a/web/app/assets/javascripts/scheduled_session.js.erb
+++ b/web/app/assets/javascripts/scheduled_session.js.erb
@@ -922,6 +922,19 @@
if(!context.JK.guardAgainstBrowser(app)) {
return false;
}
+
+ if(createSessionSettings.createType == '<%= MusicSession::CREATE_TYPE_QUICK_START %>') {
+ // short-cut added for private sessions; just get it going
+ beforeMoveStep1(); // this will populate the createSessionSettings structure
+ startSessionClicked(); // and this will create the session
+ return false;
+ }
+ }
+
+ if(optionRequiresMultiplayerProfile()) {
+ if(context.JK.guardAgainstSinglePlayerProfile(app).canPlay == false) {
+ return false;
+ }
}
if(optionRequiresMultiplayerProfile()) {
@@ -986,7 +999,11 @@
}
function afterShow() {
+ context.JK.HelpBubbleHelper.jamtrackGuidePrivate($screen.find('li[create-type="quick-start"] label'), $screen.find('.content-body-scroller'))
+ }
+ function beforeHide() {
+ context.JK.HelpBubbleHelper.clearJamTrackGuide();
}
function toggleDate(dontRebuildDropdowns) {
@@ -1293,7 +1310,7 @@
instrumentSelector = instrumentSelectorInstance;
instrumentRSVP = instrumentRSVPSelectorInstance;
- var screenBindings = {'beforeShow': beforeShow, 'afterShow': afterShow};
+ var screenBindings = {'beforeShow': beforeShow, 'afterShow': afterShow, 'beforeHide' : beforeHide};
app.bindScreen('createSession', screenBindings);
$wizardSteps = $screen.find('.create-session-wizard');
diff --git a/web/app/assets/javascripts/session.js b/web/app/assets/javascripts/session.js
index dfa76dc65..d7246dd5d 100644
--- a/web/app/assets/javascripts/session.js
+++ b/web/app/assets/javascripts/session.js
@@ -13,7 +13,8 @@
var modUtils = context.JK.ModUtils;
var logger = context.JK.logger;
var self = this;
-
+ var webcamViewer = new context.JK.WebcamViewer()
+
var defaultParticipant = {
tracks: [{
instrument_id: "unknown"
@@ -133,16 +134,19 @@
var RENDER_SESSION_DELAY = 750; // When I need to render a session, I have to wait a bit for the mixers to be there.
function beforeShow(data) {
- sessionId = data.id;
- if(!sessionId) {
- window.location = '/client#/home';
- }
- promptLeave = true;
- $myTracksContainer.empty();
- displayDoneRecording(); // assumption is that you can't join a recording session, so this should be safe
+ sessionId = data.id;
+ if(!sessionId) {
+ window.location = '/client#/home';
+ }
+ promptLeave = true;
+ $myTracksContainer.empty();
+ displayDoneRecording(); // assumption is that you can't join a recording session, so this should be safe
- var shareDialog = new JK.ShareDialog(context.JK.app, sessionId, "session");
- shareDialog.initialize(context.JK.FacebookHelperInstance);
+ var shareDialog = new JK.ShareDialog(context.JK.app, sessionId, "session");
+ shareDialog.initialize(context.JK.FacebookHelperInstance);
+ if(gon.global.video_available && gon.global.video_available!="none") {
+ webcamViewer.beforeShow()
+ }
}
function beforeDisconnect() {
@@ -168,10 +172,13 @@
}
}
checkForCurrentUser();
+
+ context.JK.HelpBubbleHelper.jamtrackGuideSession($screen.find('li.open-a-jamtrack'), $screen)
}
function afterShow(data) {
+ $fluidTracks.addClass('showing');
$openBackingTrack.removeClass('disabled');
if(!context.JK.JamServer.connected) {
@@ -207,7 +214,6 @@
var singlePlayerCheckOK = true;
// to know whether we are allowed to be in this session, we have to check if we are the creator when checking against single player functionality
if(musicSession.user_id != context.JK.currentUserId) {
-
var canPlay = context.JK.guardAgainstSinglePlayerProfile(app, function () {
promptLeave = false;
});
@@ -413,7 +419,7 @@
}
else {
displayDoneRecording();
- promptUserToSave(data.recordingId);
+ promptUserToSave(data.recordingId, timeline);
}
})
@@ -501,6 +507,13 @@
function beforeHide(data) {
+ context.JK.HelpBubbleHelper.clearJamTrackGuide();
+
+ if(gon.global.video_available && gon.global.video_available!="none") {
+ webcamViewer.setVideoOff()
+ }
+
+ $fluidTracks.removeClass('showing');
if(screenActive) {
// this path is possible if FTUE is invoked on session page, and they cancel
sessionModel.leaveCurrentSession()
@@ -532,6 +545,7 @@
var metronomeMasterMixers = getMetronomeMasterMixers();
if (metronomeMixer == null && metronomeMasterMixers.length > 0) {
+ logger.debug("monitoring metronome")
playbackControls.startMonitor(context.JK.PLAYBACK_MONITOR_MODE.METRONOME)
}
else if (metronomeMixer != null && metronomeMasterMixers.length == 0) {
@@ -542,10 +556,14 @@
function checkJamTrackTransition(currentSession) {
// handle jam tracks
- if (jamTrack == null && (currentSession && currentSession.jam_track != null)) {
+
+ // if we have a recording open, then don't go into JamTrack monitor mode even if a JamTrack is open
+ if (jamTrack == null && (currentSession && currentSession.jam_track != null && currentSession.claimed_recording == null)) {
+ logger.debug("monitoring jamtrack")
playbackControls.startMonitor(context.JK.PLAYBACK_MONITOR_MODE.JAMTRACK);
}
- else if (jamTrack && (currentSession == null || currentSession.jam_track == null)) {
+ else if (jamTrack && (currentSession == null || (currentSession.jam_track == null && currentSession.claimed_recording == null))) {
+ logger.debug("stop monitoring jamtrack")
playbackControls.stopMonitor();
}
jamTrack = currentSession == null ? null : currentSession.jam_track;
@@ -554,9 +572,11 @@
function checkBackingTrackTransition(currentSession) {
// handle backing tracks
if (backing_track_path == null && (currentSession && currentSession.backing_track_path != null)) {
+ logger.debug("monitoring backing track")
playbackControls.startMonitor();
}
else if (backing_track_path && (currentSession == null || currentSession.backing_track_path == null)) {
+ logger.debug("stop monitoring backing track")
playbackControls.stopMonitor();
}
backing_track_path = currentSession == null ? null : currentSession.backing_track_path;
@@ -568,9 +588,11 @@
if (claimedRecording == null && (currentSession && currentSession.claimed_recording != null)) {
// this is a 'started with a claimed_recording' transition.
// we need to start a timer to watch for the state of the play session
+ logger.debug("monitoring recording")
playbackControls.startMonitor();
}
else if (claimedRecording && (currentSession == null || currentSession.claimed_recording == null)) {
+ logger.debug("stop monitoring recording")
playbackControls.stopMonitor();
}
claimedRecording = currentSession == null ? null : currentSession.claimed_recording;
@@ -709,7 +731,7 @@
function _initDialogs() {
configureTrackDialog.initialize();
- addNewGearDialog.initialize();
+ addNewGearDialog.initialize();
}
// Get the latest list of underlying audio mixer channels, and populates:
@@ -1278,13 +1300,15 @@
$('.session-recording-name').text(jamTrackName);
var noCorrespondingTracks = false;
- $.each(jamTrackMixers, function(index, mixer) {
+ $.each(jamTracks, function(index, jamTrack) {
+ var mixer = null;
var preMasteredClass = "";
// find the track or tracks that correspond to the mixer
var correspondingTracks = []
- $.each(jamTracks, function(i, jamTrack) {
- if(mixer.id == jamTrack.id) {
+ $.each(jamTrackMixers, function(i, matchMixer) {
+ if(matchMixer.id == jamTrack.id) {
correspondingTracks.push(jamTrack);
+ mixer = matchMixer;
}
});
@@ -1692,9 +1716,11 @@
// special case; if it's me and I have no tracks, show info about this sort of use of the app
if (myTrack && participant.tracks.length == 0) {
$tracksHolder.addClass('no-local-tracks')
+ $liveTracksContainer.addClass('no-local-tracks')
}
else {
$tracksHolder.removeClass('no-local-tracks')
+ $liveTracksContainer.removeClass('no-local-tracks')
}
// loop through all tracks for each participant
@@ -2003,16 +2029,13 @@
var otherAudioWidthPct = Math.floor(100 * otherAudioWidth/totalWidth);
var liveTrackWidthPct = Math.ceil(100 * liveTrackWidth/totalWidth);
- logger.debug("resizeFluid: ", minimumLiveTrackWidth, otherAudioWidth, otherAudioWidthPct, liveTrackWidthPct, liveTrackWidthPct)
-
+ //logger.debug("resizeFluid: ", minimumLiveTrackWidth, otherAudioWidth, otherAudioWidthPct, liveTrackWidthPct, liveTrackWidthPct)
$audioTracks.css('width', otherAudioWidthPct + '%');
$liveTracks.css('width', liveTrackWidthPct + '%');
}
function _addRecordingTrack(trackData, mixer, oppositeMixer) {
-
otherAudioFilled();
-
$('.session-recordings .recording-controls').show();
var parentSelector = '#session-recordedtracks-container';
@@ -2472,6 +2495,18 @@
return false;
}
+ function sessionWebCam(e) {
+ e.preventDefault();
+ if(webcamViewer.isVideoShared()) {
+ $('#session-webcam').removeClass("selected")
+ } else {
+ $('#session-webcam').addClass("selected")
+ }
+
+ webcamViewer.toggleWebcam()
+ return false;
+ }
+
// http://stackoverflow.com/questions/2604450/how-to-create-a-jquery-clock-timer
function updateRecordingTimer() {
@@ -2511,11 +2546,12 @@
}
function displayStartedRecording() {
+ // the commented out code reflects dropping the counter as your recording to save space
startTimeDate = new Date;
- $recordingTimer = $("(0:00) ");
- var $recordingStatus = $(' ').append("Stop Recording ").append($recordingTimer);
+ //$recordingTimer = $("(0:00) ");
+ var $recordingStatus = $(' ').append("Stop Recording ")//.append($recordingTimer);
$('#recording-status').html( $recordingStatus );
- recordingTimerInterval = setInterval(updateRecordingTimer, 1000);
+ //recordingTimerInterval = setInterval(updateRecordingTimer, 1000);
}
function displayStoppingRecording(data) {
@@ -2542,7 +2578,7 @@
$recordingTimer = null;
$('#recording-start-stop').removeClass('currently-recording');
- $('#recording-status').text("Make a Recording");
+ $('#recording-status').text("Make Recording");
}
function lockControlsforJamTrackRecording() {
@@ -2573,9 +2609,12 @@
}
}
- function promptUserToSave(recordingId) {
+ function promptUserToSave(recordingId, timeline) {
rest.getRecording( {id: recordingId} )
.done(function(recording) {
+ if(timeline) {
+ recording.timeline = timeline.global
+ }
recordingFinishedDialog.setRecording(recording);
app.layout.showDialog('recordingFinished').one(EVENTS.DIALOG_CLOSED, function(e, data) {
if(data.result && data.result.keep){
@@ -2587,7 +2626,7 @@
}
function checkPendingMetronome() {
- logger.debug("checkPendingMetronome", sessionModel.isMetronomeOpen(), getMetronomeMasterMixers().length)
+ //logger.debug("checkPendingMetronome", sessionModel.isMetronomeOpen(), getMetronomeMasterMixers().length)
if(sessionModel.isMetronomeOpen() && getMetronomeMasterMixers().length == 0) {
var pendingMetronome = $($templatePendingMetronome.html())
@@ -2695,7 +2734,7 @@
text: "Unable to open your JamTrack. Please contact support@jamkazam.com"
}, null, true);
} else {
- rest.playJamTrack(jamTrack.id);
+ playJamTrack(jamTrack.id);
}
}
})
@@ -2714,8 +2753,21 @@
return false;
}
- function openBackingTrackFile(e) {
+ function playJamTrack(jamTrackId) {
+ var participantCnt=sessionModel.participants().length
+ rest.playJamTrack(jamTrackId)
+ .done(function() {
+ app.refreshUser();
+ })
+ context.stats.write('web.jamtrack.open', {
+ value: 1,
+ session_size: participantCnt,
+ user_id: context.JK.currentUserId,
+ user_name: context.JK.currentUserName
+ })
+ }// function
+ function openBackingTrackFile(e) {
// just ignore the click if they are currently recording for now
if(sessionModel.recordingModel.isRecording()) {
app.notify({
@@ -2726,6 +2778,12 @@
return false;
} else {
context.jamClient.openBackingTrackFile(sessionModel.backing_track)
+ context.stats.write('web.backingtrack.open', {
+ value: 1,
+ session_size: participantCnt,
+ user_id: context.JK.currentUserId,
+ user_name: context.JK.currentUserName
+ })
//context.JK.CurrentSessionModel.refreshCurrentSession(true);
}
return false;
@@ -2852,6 +2910,12 @@
}
function closeBackingTrack() {
+
+ if (sessionModel.recordingModel.isRecording()) {
+ logger.debug("can't close backing track while recording")
+ return false;
+ }
+
rest.closeBackingTrack({id: sessionModel.id()})
.done(function() {
//sessionModel.refreshCurrentSession(true);
@@ -2872,9 +2936,13 @@
}
function closeJamTrack() {
-
logger.debug("closing recording");
+ if (sessionModel.recordingModel.isRecording()) {
+ logger.debug("can't close jamtrack while recording")
+ return false;
+ }
+
if(downloadJamTrack) {
logger.debug("closing DownloadJamTrack widget")
downloadJamTrack.root.remove();
@@ -2942,13 +3010,31 @@
}
function onPause(e, data) {
- logger.debug("calling jamClient.SessionStopPlay. endReached:", data.endReached);
+ logger.debug("calling jamClient.SessionPausePlay. endReached:", data.endReached);
+
+ // if a JamTrack is open, and the user hits 'pause' or 'stop', we need to automatically stop the recording
+ if(sessionModel.jamTracks() && sessionModel.recordingModel.isRecording()) {
+ startStopRecording();
+ }
if(!data.endReached) {
- context.jamClient.SessionStopPlay();
+ context.jamClient.SessionPausePlay();
}
}
+ function onStop(e, data) {
+ logger.debug("calling jamClient.SessionStopPlay. endReached:", data.endReached);
+
+ // if a JamTrack is open, and the user hits 'pause' or 'stop', we need to automatically stop the recording
+ if(sessionModel.jamTracks() && sessionModel.recordingModel.isRecording()) {
+ startStopRecording();
+ }
+
+ if(!data.endReached) {
+ context.jamClient.SessionStopPlay();
+ }
+ }
+
function onPlay(e, data) {
logger.debug("calling jamClient.SessionStartPlay");
context.jamClient.SessionStartPlay(data.playbackMode);
@@ -3045,7 +3131,6 @@
var mode = data.playbackMode; // will be either 'self' or 'cricket'
logger.debug("setting metronome playback mode: ", mode)
-
var isCricket = mode == 'cricket';
context.jamClient.setMetronomeCricketTestState(isCricket);
}
@@ -3078,6 +3163,7 @@
function events() {
$('#session-leave').on('click', sessionLeave);
$('#session-resync').on('click', sessionResync);
+ $('#session-webcam').on('click', sessionWebCam);
$('#session-contents').on("click", '[action="delete"]', deleteSession);
$tracksHolder.on('click', 'div[control="mute"]', toggleMute);
$('#recording-start-stop').on('click', startStopRecording);
@@ -3109,6 +3195,7 @@
$closePlaybackRecording.on('click', closeOpenMedia);
$(playbackControls)
.on('pause', onPause)
+ .on('stop', onStop)
.on('play', onPlay)
.on('change-position', onChangePlayPosition);
$(friendInput).focus(function() { $(this).val(''); })
@@ -3161,7 +3248,10 @@
$fluidTracks = $screen.find('.session-fluidtracks');
$voiceChat = $screen.find('#voice-chat');
$tracksHolder = $screen.find('#tracks')
-
+ if(gon.global.video_available && gon.global.video_available!="none") {
+ webcamViewer.init($(".webcam-container"))
+ webcamViewer.setVideoOff()
+ }
events();
diff --git a/web/app/assets/javascripts/sessionModel.js b/web/app/assets/javascripts/sessionModel.js
index 3c0afa636..ceb4b70b6 100644
--- a/web/app/assets/javascripts/sessionModel.js
+++ b/web/app/assets/javascripts/sessionModel.js
@@ -215,6 +215,7 @@
// see if we already have tracks; if so, we need to run with these
var inputTracks = context.JK.TrackHelpers.getUserTracks(context.jamClient);
+ logger.debug("isNoInputProfile", gearUtils.isNoInputProfile())
if(inputTracks.length > 0 || gearUtils.isNoInputProfile() ) {
logger.debug("on page enter, tracks are already available")
sessionPageEnterDeferred.resolve(inputTracks);
diff --git a/web/app/assets/javascripts/shopping_cart.js b/web/app/assets/javascripts/shopping_cart.js
index 86157b96d..ac115f175 100644
--- a/web/app/assets/javascripts/shopping_cart.js
+++ b/web/app/assets/javascripts/shopping_cart.js
@@ -11,10 +11,11 @@
var $content = null;
function beforeShow(data) {
- loadShoppingCarts();
+
}
function afterShow(data) {
+ loadShoppingCarts();
}
function afterHide() {
@@ -29,18 +30,22 @@
function proceedCheckout(e) {
e.preventDefault();
+ logger.debug("proceedCheckout")
if (!context.JK.currentUserId) {
+ logger.debug("proceeding to signin screen because there is no user")
window.location = '/client#/checkoutSignin';
}
else {
- app.user().done(function(user) {
- if(user.has_recurly_account && user.reuse_card) {
- window.location = '/client#/checkoutOrder';
- }
- else {
- window.location = '/client#/checkoutPayment';
- }
- })
+ var user = app.currentUser();
+
+ if(user.has_recurly_account && user.reuse_card) {
+ logger.debug("proceeding to checkout order screen because we have card info already")
+ window.location = '/client#/checkoutOrder';
+ }
+ else {
+ logger.debug("proceeding to checkout payment screen because we do not have card info")
+ window.location = '/client#/checkoutPayment';
+ }
}
}
@@ -55,6 +60,7 @@
.fail(app.ajaxError);
}
+
function clearContent() {
$content.empty();
}
@@ -69,11 +75,24 @@
function renderShoppingCarts(carts) {
var data = {};
- var latest_cart = carts[carts.length - 1];
+
+ if(carts.length > 0) {
+ var latest_cart = carts[0];
+ }
var $latestCartHtml = "";
+ var any_in_us = false
+ context._.each(carts, function(cart) {
+ if(cart.product_info.sales_region == 'United States') {
+ any_in_us = true
+ }
+ })
+
if (latest_cart) {
+
+ latest_cart.any_in_us = any_in_us
+
$latestCartHtml = $(
context._.template(
$('#template-shopping-cart-header').html(),
@@ -85,9 +104,9 @@
var sub_total = 0;
$.each(carts, function(index, cart) {
- sub_total += parseFloat(cart.product_info.price) * parseFloat(cart.quantity);
+ sub_total += parseFloat(cart.product_info.real_price);
});
- data.sub_total = sub_total.toFixed(2);
+ data.sub_total = sub_total;
data.carts = carts;
var $cartsHtml = $(
diff --git a/web/app/assets/javascripts/web/congratulations.js b/web/app/assets/javascripts/web/congratulations.js
index 576759f17..31ddf40d4 100644
--- a/web/app/assets/javascripts/web/congratulations.js
+++ b/web/app/assets/javascripts/web/congratulations.js
@@ -8,13 +8,6 @@
if(musician) {
context.JK.Downloads.listClients(true);
}
-
- if(registrationType) {
- $(function() {
- // ga() object isn't ready until the page is loaded
- context.JK.GA.trackRegister(musician, registrationType);
- });
- }
}
context.congratulations = congratulations;
diff --git a/web/app/assets/javascripts/web/individual_jamtrack.js b/web/app/assets/javascripts/web/individual_jamtrack.js
index bbfd05896..2d33e9c5d 100644
--- a/web/app/assets/javascripts/web/individual_jamtrack.js
+++ b/web/app/assets/javascripts/web/individual_jamtrack.js
@@ -26,7 +26,7 @@
else {
$individualizedHeader.removeClass('hidden')
$jamtrack_name.text(jam_track.name);
- $jamTracksButton.attr('href', '/client?artist=' + jam_track.original_artist + '#/jamtrack')
+ $jamTracksButton.attr('href', '/client?artist=' + jam_track.original_artist + '#/jamtrackBrowse')
}
}
@@ -36,7 +36,7 @@
$previews.append($element);
- new context.JK.JamTrackPreview(app, $element, jam_track, track, {master_shows_duration: false})
+ new context.JK.JamTrackPreview(app, $element, jam_track, track, {master_shows_duration: false, color:'black'})
})
$previews.append(' ')
diff --git a/web/app/assets/javascripts/web/individual_jamtrack_band.js b/web/app/assets/javascripts/web/individual_jamtrack_band.js
index 0de60a2e7..df08517c9 100644
--- a/web/app/assets/javascripts/web/individual_jamtrack_band.js
+++ b/web/app/assets/javascripts/web/individual_jamtrack_band.js
@@ -21,7 +21,7 @@
logger.debug("jam_track", jam_track)
$jamTrackBandInfo.text(jam_track.band_jam_track_count + ' ' + jam_track.original_artist);
- $jamTracksButton.attr('href', '/client?artist=' + jam_track.original_artist + '#/jamtrack')
+ $jamTracksButton.attr('href', '/client?artist=' + jam_track.original_artist + '#/jamtrackBrowse')
if(jam_track.band_jam_track_count == 1) {
$jamTrackNoun.text('JamTrack')
@@ -33,7 +33,7 @@
$previews.append($element);
- new context.JK.JamTrackPreview(app, $element, jam_track, track, {master_shows_duration: false})
+ new context.JK.JamTrackPreview(app, $element, jam_track, track, {master_shows_duration: false, color:'black'})
})
$previews.append(' ')
diff --git a/web/app/assets/javascripts/web/web.js b/web/app/assets/javascripts/web/web.js
index 7f128d092..b4e835dbe 100644
--- a/web/app/assets/javascripts/web/web.js
+++ b/web/app/assets/javascripts/web/web.js
@@ -47,8 +47,8 @@
//= require subscription_utils
//= require ui_helper
//= require custom_controls
-//= require ga
//= require jam_rest
+//= require ga
//= require session_utils
//= require recording_utils
//= require helpBubbleHelper
diff --git a/web/app/assets/javascripts/webcam_viewer.js.coffee b/web/app/assets/javascripts/webcam_viewer.js.coffee
new file mode 100644
index 000000000..ed2b1d772
--- /dev/null
+++ b/web/app/assets/javascripts/webcam_viewer.js.coffee
@@ -0,0 +1,115 @@
+$ = jQuery
+context = window
+context.JK ||= {};
+
+context.JK.WebcamViewer = class WebcamViewer
+ constructor: (@root) ->
+ @client = context.jamClient
+ @logger = context.JK.logger
+ @initialScan = false
+ @toggleBtn = null
+ @webcamSelect = null
+ @resolutionSelect = null
+ @videoShared=false
+ @resolution=null
+
+ init: (root) =>
+ @root = root
+ @toggleBtn = @root.find(".webcam-test-btn")
+ @webcamSelect = @root.find(".webcam-select-container select")
+ @resolutionSelect = @root.find(".webcam-resolution-select-container select")
+ @webcamSelect.on("change", this.selectWebcam)
+ @toggleBtn.on 'click', @toggleWebcam
+
+ beforeShow:() =>
+ this.loadWebCams()
+ this.selectWebcam()
+ this.loadResolutions()
+ this.selectResolution()
+ @initialScan = true
+ @client.SessStopVideoSharing()
+ #client.SessSetInsetPosition(5)
+ #client.SessSetInsetSize(1)
+ #client.FTUESetAutoSelectVideoLayout(false)
+ #client.SessSelectVideoDisplayLayoutGroup(1)
+
+
+ selectWebcam:(e, data) =>
+ device = @webcamSelect.val()
+ if device?
+ caps = @client.FTUEGetVideoCaptureDeviceCapabilities(device)
+ @logger.debug("Got capabilities from device", caps, device)
+ @client.FTUESelectVideoCaptureDevice(device, caps)
+
+ selectResolution:() =>
+ @logger.debug 'Selecting res control: ', @resolutionSelect
+ @resolution = @resolutionSelect.val()
+ if @resolution?
+ @logger.debug 'Selecting res: ', @resolution
+ @client.FTUESetVideoEncodeResolution @resolution
+ # if @isVideoShared
+ # this.setVideoOff()
+ # this.toggleWebcam()
+
+ setVideoOff:() =>
+ if this.isVideoShared()
+ @client.SessStopVideoSharing()
+
+ isVideoShared:() =>
+ @videoShared
+
+ setToggleState:() =>
+ available = @webcamSelect.find('option').size() > 0
+ shared = this.isVideoShared()
+ @toggleBtn.prop 'disabled', true
+ @toggleBtn.prop 'disabled', !available
+
+ toggleWebcam:() =>
+ @logger.debug 'Toggling webcam from: ', this.isVideoShared()
+ if this.isVideoShared()
+ @toggleBtn.removeClass("selected")
+ @client.SessStopVideoSharing()
+ @videoShared = false
+ else
+ @toggleBtn.addClass("selected")
+ @client.SessStartVideoSharing 0
+ @videoShared = true
+
+ selectedDeviceName:() =>
+ webcamName="None Configured"
+ webcam = @client.FTUECurrentSelectedVideoDevice()
+ if (webcam? && Object.keys(webcam).length>0)
+ webcamName = _.values(webcam)[0]
+
+ webcamName
+
+ loadWebCams:() =>
+ devices = @client.FTUEGetVideoCaptureDeviceNames()
+ selectedDevice = this.selectedDeviceName()
+ selectControl = @webcamSelect
+ context._.each devices, (device) ->
+ selected = device == selectedDevice
+ option = $(' ',
+ id: device
+ value: device
+ text: device)
+ selectControl.append option
+ selectControl.val selectedDevice
+
+ if devices.length == 0
+ @root.find('.no-webcam-msg').removeClass 'hidden'
+ else
+ @root.find('.no-webcam-msg').addClass 'hidden'
+
+ loadResolutions:() =>
+ resolutions = @client.FTUEGetAvailableEncodeVideoResolutions()
+ selectControl = @resolutionSelect
+ @logger.debug 'FOUND THESE RESOLUTIONS', resolutions, selectControl
+ context._.each resolutions, (value, key, obj) ->
+ option = $(' ',
+ value: value
+ text: value)
+ selectControl.append option
+
+ if @resolution != null and @resolution != ''
+ selectControl.val(@resolution)
diff --git a/web/app/assets/javascripts/wizard/gear/gear_wizard.js b/web/app/assets/javascripts/wizard/gear/gear_wizard.js
index 218ad8b8f..f80a5fe0a 100644
--- a/web/app/assets/javascripts/wizard/gear/gear_wizard.js
+++ b/web/app/assets/javascripts/wizard/gear/gear_wizard.js
@@ -23,14 +23,16 @@
var STEP_SELECT_TRACKS = 2;
var STEP_SELECT_CHAT = 3;
var STEP_DIRECT_MONITOR = 4;
- var STEP_ROUTER_NETWORK = 5;
- var STEP_SUCCESS = 6;
+ var STEP_VIDEO_GEAR = 5;
+ var STEP_ROUTER_NETWORK = 6;
+ var STEP_SUCCESS = 7;
var stepUnderstandGear = new context.JK.StepUnderstandGear(app, this);
var stepSelectGear = new context.JK.StepSelectGear(app, this);
var stepConfigureTracks = new context.JK.StepConfigureTracks(app, this);
var stepConfigureVoiceChat = new context.JK.StepConfigureVoiceChat(app, this);
var stepDirectMonitoring = new context.JK.StepDirectMonitoring(app, this);
+ var stepVideoGear = new context.JK.StepVideoGear(app, this);
var stepNetworkTest = new context.JK.StepNetworkTest(app, this);
var stepSuccess = new context.JK.StepSuccess(app, this);
@@ -39,9 +41,7 @@
1: stepSelectGear,
2: stepConfigureTracks,
3: stepConfigureVoiceChat,
- 4: stepDirectMonitoring,
- 5: stepNetworkTest,
- 6: stepSuccess
+ 4: stepDirectMonitoring
}
function newSession() {
@@ -206,7 +206,7 @@
$dialog = $('#gear-wizard-dialog');
$wizardSteps = $dialog.find('.wizard-step');
$templateSteps = $('#template-ftuesteps');
-
+ var videoGear = $wizardSteps.filter($('.video-gear'))
wizard = new context.JK.Wizard(app);
stepUnderstandGear.initialize($wizardSteps.filter($('[layout-wizard-step=0]')), self);
@@ -214,11 +214,20 @@
stepConfigureTracks.initialize($wizardSteps.filter($('[layout-wizard-step=2]')), self);
stepConfigureVoiceChat.initialize($wizardSteps.filter($('[layout-wizard-step=3]')), self);
stepDirectMonitoring.initialize($wizardSteps.filter($('[layout-wizard-step=4]')), self);
- stepNetworkTest.initialize($wizardSteps.filter($('[layout-wizard-step=5]')), self);
- stepSuccess.initialize($wizardSteps.filter($('[layout-wizard-step=6]')), self);
-
+ stepNetworkTest.initialize($wizardSteps.filter($('.network-test')), self);
+ stepSuccess.initialize($wizardSteps.filter($('.success')), self);
+
+ if(videoGear.length) {
+ stepVideoGear.initialize(videoGear, self);
+ STEPS[5]=stepVideoGear
+ STEPS[6]=stepNetworkTest
+ STEPS[7]=stepSuccess
+ } else {
+ STEPS[5]=stepNetworkTest
+ STEPS[6]=stepSuccess
+ }
+
wizard.initialize($dialog, $wizardSteps, STEPS);
-
events();
}
diff --git a/web/app/assets/javascripts/wizard/gear/step_video_gear.js b/web/app/assets/javascripts/wizard/gear/step_video_gear.js
new file mode 100644
index 000000000..90fabdeaa
--- /dev/null
+++ b/web/app/assets/javascripts/wizard/gear/step_video_gear.js
@@ -0,0 +1,28 @@
+(function (context, $) {
+
+ "use strict"
+
+ context.JK = context.JK || {}
+ context.JK.StepVideoGear = function (app, $dialog) {
+ var $step = null
+ var $webcamViewer = new context.JK.WebcamViewer()
+ function initialize(_$step) {
+ $step = _$step
+ $webcamViewer.init($step)
+ }
+
+ function beforeShow() {
+ $webcamViewer.beforeShow()
+ }
+
+ function beforeHide() {
+ $webcamViewer.setVideoOff()
+ }
+
+ this.beforeShow = beforeShow
+ this.beforeHide = beforeHide
+ this.initialize = initialize
+
+ return this
+ }
+})(window, jQuery)
\ No newline at end of file
diff --git a/web/app/assets/javascripts/wizard/gear_utils.js b/web/app/assets/javascripts/wizard/gear_utils.js
index 051ca1949..a68a07894 100644
--- a/web/app/assets/javascripts/wizard/gear_utils.js
+++ b/web/app/assets/javascripts/wizard/gear_utils.js
@@ -37,10 +37,19 @@
var isNoInputProfile = gearUtils.isNoInputProfile(profile);
var expectedLatency = context.jamClient.FTUEGetExpectedLatency();
var audioLatency = expectedLatency ? expectedLatency.latency : null;
- var highLatency = audioLatency > 20;
+
+ // only compute high latency if the value is known. Also don't accept insanely largue values
+ var highLatency = false;
+ if(audioLatency) {
+ highLatency = audioLatency > 20 && audioLatency < 1000;
+ }
+
var networkScore = context.jamClient.GetNetworkTestScore();
var badNetworkScore = networkScore < 2;
+ // for now, ignore latency
+ highLatency = false
+
return {
canPlay: !isNoInputProfile && !highLatency,
isNoInputProfile: isNoInputProfile,
@@ -52,13 +61,16 @@
}
gearUtils.isNoInputProfile = function(profile) {
+
if (profile === undefined) {
- profile = context.jamClient.FTUEGetMusicProfileName();
+ profile = context.jamClient.LastUsedProfileName();
}
- if(profile == SYSTEM_DEFAULT_PLAYBACK_ONLY) {
- return true;
- }
+ return profile == SYSTEM_DEFAULT_PLAYBACK_ONLY;
+ }
+
+ gearUtils.canBeConfigured = function(profile) {
+ return profile != SYSTEM_DEFAULT_PLAYBACK_ONLY;
}
gearUtils.createProfileName = function (deviceInfo, chatName) {
diff --git a/web/app/assets/stylesheets/client/account.css.scss b/web/app/assets/stylesheets/client/account.css.scss
index 49bbb7c33..d37147db9 100644
--- a/web/app/assets/stylesheets/client/account.css.scss
+++ b/web/app/assets/stylesheets/client/account.css.scss
@@ -49,6 +49,22 @@
width: 20%;
}
+ .wizard_control {
+ margin-bottom: 10px;
+ }
+
+ .content-wrapper .account-video {
+
+ .subcaption {
+ margin-bottom: 4px;
+ }
+ }
+
+ .webcam-container {
+ margin-top: 10px;
+ }
+
+
.account-left h2 {
color: #FFFFFF;
font-size: 23px;
@@ -115,7 +131,7 @@
}
}
- .audio .audio-profiles-short{
+ .audio .audio-profiles-short, .video .video-profiles-short {
white-space: normal;
}
@@ -140,7 +156,6 @@
}
.account-audio {
-
table.generaltable td {
vertical-align:middle;
}
@@ -149,7 +164,6 @@
margin-bottom:9px;
}
-
.rescanning-notice {
display:none;
@@ -200,7 +214,6 @@
}
}
-
.spinner-large {
width:300px;
height:300px;
diff --git a/web/app/assets/stylesheets/client/accountPaymentHistory.css.scss b/web/app/assets/stylesheets/client/accountPaymentHistory.css.scss
index f0a7c1fdf..2ef59a48c 100644
--- a/web/app/assets/stylesheets/client/accountPaymentHistory.css.scss
+++ b/web/app/assets/stylesheets/client/accountPaymentHistory.css.scss
@@ -20,8 +20,6 @@
}
&.voided {
-
- text-decoration:line-through;
}
}
diff --git a/web/app/assets/stylesheets/client/checkout.css.scss b/web/app/assets/stylesheets/client/checkout.css.scss
index 7d5190ad8..9aa7d1040 100644
--- a/web/app/assets/stylesheets/client/checkout.css.scss
+++ b/web/app/assets/stylesheets/client/checkout.css.scss
@@ -40,6 +40,27 @@
margin-bottom:20px;
}
+ .thanks-detail {
+ .download-jamkazam {
+ color:$ColorLink;
+ border-radius: 4px;
+ border-style:solid;
+ border-color:#AAA;
+ border-width:1px;
+ padding:10px;
+ margin-top:20px;
+ display:inline-block;
+ }
+
+ .download-jamkazam-wrapper {
+ text-align:center;
+ display:block;
+
+ &.hidden {
+ display:none;
+ }
+ }
+ }
.thanks-detail.purchased-jam-track {
margin-top:20px;
@@ -47,6 +68,22 @@
.purchased-jam-track-header {
font-size: 15px;
margin-bottom:10px;
+
+ span {
+ display:none;
+ }
+
+ &[status="in-progress"] {
+ span.in-progress-msg {
+ display:inline;
+ }
+ }
+
+ &[status="done"] {
+ span.done-msg {
+ display:inline;
+ }
+ }
}
ul.purchased-list {
diff --git a/web/app/assets/stylesheets/client/checkout_order.css.scss b/web/app/assets/stylesheets/client/checkout_order.css.scss
index 22a208ce0..456bfaafd 100644
--- a/web/app/assets/stylesheets/client/checkout_order.css.scss
+++ b/web/app/assets/stylesheets/client/checkout_order.css.scss
@@ -2,7 +2,7 @@
#checkoutOrderScreen {
p {
- font-size:12px;
+ font-size:14px;
margin:0;
}
@@ -155,6 +155,12 @@
@include border_box_sizing;
}
+ .first-one-free {
+ font-size:14px;
+ font-style:italic;
+ margin-left:15px;
+ }
+
.cart-item-price {
width: 25%;
text-align: right;
diff --git a/web/app/assets/stylesheets/client/client.css b/web/app/assets/stylesheets/client/client.css
index 261be8b00..9ade671f2 100644
--- a/web/app/assets/stylesheets/client/client.css
+++ b/web/app/assets/stylesheets/client/client.css
@@ -55,6 +55,7 @@
*= require ./createSession
*= require ./feed
*= require ./jamtrack
+ *= require ./jamtrack_landing
*= require ./shoppingCart
*= require ./checkout
*= require ./checkout_signin
diff --git a/web/app/assets/stylesheets/client/content.css.scss b/web/app/assets/stylesheets/client/content.css.scss
index f5bad0e14..1d859879d 100644
--- a/web/app/assets/stylesheets/client/content.css.scss
+++ b/web/app/assets/stylesheets/client/content.css.scss
@@ -467,6 +467,8 @@ table.generaltable {
ul.shortcuts {
border:1px solid #ED3618;
+ width:175px;
+ float:right;
li {
margin:0;
diff --git a/web/app/assets/stylesheets/client/header.css.scss b/web/app/assets/stylesheets/client/header.css.scss
index 8bdedd4ea..17b70bfe7 100644
--- a/web/app/assets/stylesheets/client/header.css.scss
+++ b/web/app/assets/stylesheets/client/header.css.scss
@@ -8,11 +8,12 @@
}
.header-shopping-cart {
- float: right;
- margin-right: 20px;
+ margin-top:27px;
+ position:absolute;
+ left:0;
img {
- width: 60px;
+ width: 36px;
}
}
@@ -23,3 +24,4 @@ div[layout="header"] h1 {
@include replace-text(image-url("header/logo.png"));
float:left;
}
+
diff --git a/web/app/assets/stylesheets/client/help.css.scss b/web/app/assets/stylesheets/client/help.css.scss
index 6dbfa7149..b5c3cf17b 100644
--- a/web/app/assets/stylesheets/client/help.css.scss
+++ b/web/app/assets/stylesheets/client/help.css.scss
@@ -3,7 +3,6 @@
body.jam, body.web, .dialog{
.bt-wrapper {
.bt-content {
-
color:#cccccc;
font-size:14px;
@@ -49,6 +48,10 @@ body.jam, body.web, .dialog{
width:400px;
}
+ .big-help {
+ font-size:20px;
+ }
+
.help-hover-recorded-tracks, .help-hover-stream-mix, .help-hover-recorded-backing-tracks {
font-size:12px;
diff --git a/web/app/assets/stylesheets/client/jamTrackPreview.css.scss b/web/app/assets/stylesheets/client/jamTrackPreview.css.scss
index 28213d8b4..cd1ef99d8 100644
--- a/web/app/assets/stylesheets/client/jamTrackPreview.css.scss
+++ b/web/app/assets/stylesheets/client/jamTrackPreview.css.scss
@@ -24,7 +24,6 @@
display:inline;
vertical-align: middle;
margin-left:10px;
-
}
.part {
@@ -32,4 +31,30 @@
vertical-align: middle;
margin-left:4px;
}
+ .play-button, .stop-button {
+ vertical-align:middle;
+ height:24px;
+ line-height:24px;
+ width:24px;
+ background-repeat:no-repeat;
+ background-position:center;
+ }
+
+ .play-button {
+ &.gray {
+ background-image: url('/assets/content/icon-play-24-gray.png');
+ }
+ &.black {
+ background-image: url('/assets/content/icon-play-24-black.png');
+ }
+ }
+
+ .stop-button {
+ &.gray {
+ background-image: url('/assets/content/icon-pause-24-gray.png');
+ }
+ &.black {
+ background-image: url('/assets/content/icon-pause-24-black.png');
+ }
+ }
}
\ No newline at end of file
diff --git a/web/app/assets/stylesheets/client/jamkazam.css.scss b/web/app/assets/stylesheets/client/jamkazam.css.scss
index d1e2b4192..8996764e9 100644
--- a/web/app/assets/stylesheets/client/jamkazam.css.scss
+++ b/web/app/assets/stylesheets/client/jamkazam.css.scss
@@ -154,10 +154,15 @@ input[type="button"] {
}
.curtain {
- background-color: $ColorScreenBackground;
- position:absolute;
- top:0px;
- left:0px;
+
+ &.minimal {
+ display:none
+ }
+
+ background-color: $ColorScreenBackground;
+ position:absolute;
+ top:0px;
+ left:0px;
}
.curtain .splash {
position:absolute;
diff --git a/web/app/assets/stylesheets/client/jamtrack.css.scss b/web/app/assets/stylesheets/client/jamtrack.css.scss
index 979ac5377..7e1e28e11 100644
--- a/web/app/assets/stylesheets/client/jamtrack.css.scss
+++ b/web/app/assets/stylesheets/client/jamtrack.css.scss
@@ -1,91 +1,18 @@
@import 'common';
-#jamtrackLanding {
- font-family: verdana;
- .two-column-list-container {
- -moz-column-count: 2;
- -moz-column-gap: 20px;
- -webkit-column-count: 2;
- -webkit-column-gap: 20px;
- column-count: 2;
- column-gap: 20px;
- margin-left: 0px;
- ul {
- list-style-type: none;
- li {
- margin: 1px 4px 1px 0px;
- font-size:11px;
- }
- }
- }
-
- ul {
- li {
- margin: 1px 4px 1px 4px;
- font-size:11px;
- }
- }
-
- .browse-header {
- padding: 4px 0 4px 0;
- }
-
- .list-columns {
- padding: 4px;
- h2 {
- font-size: 16pt;
- font-weight:600;
- font-style: bolder;
- font-family: verdana;
- text-transform: lowercase;
- margin-bottom: 2em;
- }
-
- .free-jamtrack {
- font-size: 11pt;
- padding: 3px;
- @include border-radius(7px);
- background-color:$ColorScreenPrimary;
- color: white !important;
- text-align: center;
- vertical-align: center;
- }
-
- .what, .howto {
- margin-bottom: 2em;
- * {
- font-family: arial;
- font-size: 11pt;
- font-weight: 200;
- line-height: 17px;
- color: #cccccc;
- }
- }
-
- .details {
- margin-bottom: 4px !important;
- }
-
- .about {
- @include border_box_sizing;
- float: left;
- width: 50%;
- > * {
- margin: 4px;
- }
- }
- .browse {
- @include border_box_sizing;
- float: left;
- width: 50%;
- > * {
- margin: 4px;
- }
- }
- }
-}
-
#jamtrackScreen {
+
+ .filter-element.desc {
+ margin-left:15px;
+ }
+
+ h2 {
+ font-size: 20px;
+ color: white;
+ font-weight: bold;
+ margin-bottom:10px;
+ }
+
.jamtrack-header {
background-color: #4c4c4c;
font-weight: bold;
@@ -111,7 +38,8 @@
}
.no-jamtracks-msg {
- margin-top: 10px;
+ margin: 10px 0;
+ text-align:center;
}
.jamtrack-record {
@@ -120,22 +48,22 @@
}
.jamtrack-detail {
- width: 35%;
@include border_box_sizing;
- width: 30%;
- padding: 10px 0px;
+ width: 35%;
+ padding: 10px 0 0 10px;
.detail-label {
width: 40%;
float: left;
margin-top: 5px;
font-weight: 400;
- font-size: 11pt;
+ font-size: 11px;
}
.detail-value {
width: 50%;
float: left;
margin-top: 5px;
+ font-size:11px;
}
.copyright-value {
@@ -144,11 +72,6 @@
margin-top: 5px;
}
- .detail-arrow {
- float: left;
- margin-left: 10px;
- }
-
.jamtrack-description {
display: none;
}
@@ -157,7 +80,7 @@
.jamtrack-detail-btn {
cursor: pointer;
- margin-top: 7px;
+ margin-top: 29px;
margin-right: 5px;
padding-top: 5px;
vertical-align: bottom;
@@ -165,7 +88,7 @@
.jamtrack-tracks {
@include border_box_sizing;
- width: 35%;
+ width: 45%;
padding: 10px 0px;
.tracks-caption {
margin-top: 5px;
@@ -186,15 +109,33 @@
float: left;
margin-left: 10px;
}
+
+ .instrument-name {
+ color:white;
+ }
+ }
+
+
+ .detail-arrow {
+ float: right;
+ margin-right: 10px;
}
.jamtrack-track {
- margin-left: 7px;
+ margin:0 0 8px 7px;
+
+ &.hidden {
+ display:none;
+ }
}
-
+
+ .jam-track-preview {
+ font-size:11px;
+ }
+
.jamtrack-action {
@include border_box_sizing;
- width: 35%;
+ width: 20%;
// padding: 0px 0px;
text-align: center;
// vertical-align: top;
@@ -218,6 +159,10 @@
width: 60%;
}
}
+
+ .end-of-jamtrack-list {
+ margin-top:20px;
+ }
}
#jamtrack-license-dialog {
diff --git a/web/app/assets/stylesheets/client/jamtrack_landing.css.scss b/web/app/assets/stylesheets/client/jamtrack_landing.css.scss
new file mode 100644
index 000000000..26821d7c8
--- /dev/null
+++ b/web/app/assets/stylesheets/client/jamtrack_landing.css.scss
@@ -0,0 +1,101 @@
+@import 'common';
+
+#jamtrackLanding {
+ //font-family: verdana;
+ .two-column-list-container {
+ -moz-column-count: 2;
+ -moz-column-gap: 20px;
+ -webkit-column-count: 2;
+ -webkit-column-gap: 20px;
+ column-count: 2;
+ column-gap: 20px;
+ margin-left: 0;
+ ul {
+ list-style-type: none;
+ li {
+ margin: 1px 4px 1px 0;
+ font-size:12px;
+ line-height:14px;
+ }
+ }
+ }
+
+ ul {
+ li {
+ margin: 1px 4px 1px 4px;
+ font-size:12px;
+ line-height:14px ;
+ }
+ }
+
+ #band_list {
+ margin-top:10px;
+ margin-left:0;
+
+ li {
+ font-size:12px;
+ }
+ }
+ .browse-header {
+ padding: 4px 0 4px 0;
+ color:#ccc;
+ }
+
+ .list-columns {
+ h2 {
+
+ font-size: 20px;
+ font-weight:700;
+ text-transform: lowercase;
+ margin-bottom: 10px !important;
+ }
+
+ .free-jamtrack {
+ font-size: 11pt;
+ padding: 3px;
+ @include border-radius(7px);
+ background-color:$ColorScreenPrimary;
+ color: white !important;
+ text-align: center;
+ vertical-align: center;
+ }
+
+ .what, .howto {
+ margin-bottom: 2em;
+ font-size: 14px;
+ line-height: 19px;
+ color: #cccccc;
+ }
+
+ .what ul {
+ margin-top:20px;
+ }
+
+ .details {
+ margin-bottom: 4px !important;
+ }
+
+ .about {
+ @include border_box_sizing;
+ float: left;
+ width: 50%;
+ padding:20px 20px 0 20px;
+ > * {
+ margin: 4px;
+ }
+ }
+ .browse {
+ @include border_box_sizing;
+ float: left;
+ width: 50%;
+ padding:20px 20px 0 20px;
+ > * {
+ margin: 4px;
+ }
+
+ h2.browse-jamtracks {
+ margin-top:30px;
+ }
+ }
+ }
+}
diff --git a/web/app/assets/stylesheets/client/screen_common.css.scss b/web/app/assets/stylesheets/client/screen_common.css.scss
index 5f8247d2d..755332e7f 100644
--- a/web/app/assets/stylesheets/client/screen_common.css.scss
+++ b/web/app/assets/stylesheets/client/screen_common.css.scss
@@ -170,8 +170,21 @@ a img {border:none;}
small, .small {font-size:11px;}
.bold {font-weight:bold;}
+.button-grey-toggle.selected {
+ background-color: #999;
+ text-decoration:none;
+ &:hover {
+ background-color: #999;
+ color:#ccc;
+ text-decoration:none;
+ }
+}
-.button-grey {
+.button-grey-toggle:hover {
+ text-decoration:none;
+}
+
+.button-grey, .button-grey-toggle {
margin:0px 8px 0px 8px;
background-color:#666;
border: solid 1px #868686;
diff --git a/web/app/assets/stylesheets/client/session.css.scss b/web/app/assets/stylesheets/client/session.css.scss
index 94228e6f0..b400ecbc4 100644
--- a/web/app/assets/stylesheets/client/session.css.scss
+++ b/web/app/assets/stylesheets/client/session.css.scss
@@ -56,11 +56,11 @@
.recording-position {
display:inline-block;
- width:calc(100% - 27px - 47px); // 27 accounts for play arrow, 47px acconts for the total time (0:00)
+ width:calc(100% - 127px); // 27 accounts for play arrow, 20 for stop, 47px acconts for the total time (0:00), and then some extra
position:absolute;
left:0;
- margin-left:27px;
+ margin-left:55px;
font-family:Arial, Helvetica, sans-serif;
font-size:11px;
@@ -78,7 +78,7 @@
bottom: 0;
height: 25px;
- .play-button {
+ .play-buttons {
top:2px;
}
.recording-current {
@@ -258,10 +258,13 @@
}
.session-fluidtracks {
- width:calc(100% - #{$mytracks-minwidth});
position:relative;
float:left;
@include border_box_sizing;
+
+ &.showing {
+ width:calc(100% - #{$mytracks-minwidth}); // VRFS-3034
+ }
}
.session-livetracks {
@@ -281,6 +284,11 @@
min-width:#{$livetracks-minwidth};
}
+ &.no-local-tracks {
+ .recording {
+ display:none;
+ }
+ }
.recording {
left: 50%;
margin-left: -67px;
diff --git a/web/app/assets/stylesheets/client/shoppingCart.css.scss b/web/app/assets/stylesheets/client/shoppingCart.css.scss
index ba3b31146..7621c93ee 100644
--- a/web/app/assets/stylesheets/client/shoppingCart.css.scss
+++ b/web/app/assets/stylesheets/client/shoppingCart.css.scss
@@ -1,16 +1,14 @@
#shoppingCartScreen {
.content-body {
- padding: 50px 20px 20px 20px;
- overflow: scroll;
.shopping-cart-content {
- //padding-top: 20px;
+ padding: 50px 20px 20px 20px;
margin-bottom: 20px;
- overflow: scroll;
+ overflow: hidden;
}
.checkout-image {
- width: 10%;
+ margin-right:20px;
float: left;
}
@@ -22,7 +20,7 @@
margin-bottom: 7px;
}
- div#note {
+ .note {
font-style: italic;
font-size: 13px;
}
@@ -37,22 +35,43 @@
}
.cart-item-price {
- text-align: right;
+ text-align: right;
+ width:120px;
}
.cart-item-quantity {
- text-align: right;
+ text-align: left;
+ width:150px;
}
.cart-item-actions {
//text-align: center;
}
+
+ .cart-item-price {
+ padding-right:11px;
+ }
+
+ th.cart-item-quantity {
+ padding-left:15px;
+ }
+
+ .remove-cart {
+ color:#fc0;
+ float:right;
+ margin-right:20px;
+ }
+
+ .cart-value {
+ margin-left:63px;
+ }
+
.cart-items {
- width: 100%;
- min-height: 200px;
+ width: 80%;
// overflow: auto;
margin-top: 30px;
+ margin-bottom:20px;
}
.cart-item {
@@ -60,12 +79,17 @@
}
.shopping-sub-total {
- width: 65%;
- float: left;
- text-align: right;
- margin-bottom: 20px;
- font-weight: bold;
- font-size: 17px;
+ margin-top:30px;
+
+ .sub-total-text {
+ color:white;
+ float:left;
+ margin-left:10px;
+ }
+
+ .sub-total-value {
+ color:white;
+ }
}
.no-cart-items {
@@ -75,5 +99,13 @@
font-weight: bold;
font-size: 15px;
}
+
+ .actions {
+ margin-right:20%;
+ }
+
+ .proceed-checkout {
+ margin-right:2px;
+ }
}
}
\ No newline at end of file
diff --git a/web/app/assets/stylesheets/client/user_dropdown.css.scss b/web/app/assets/stylesheets/client/user_dropdown.css.scss
index 79096c8b8..b7adaacae 100644
--- a/web/app/assets/stylesheets/client/user_dropdown.css.scss
+++ b/web/app/assets/stylesheets/client/user_dropdown.css.scss
@@ -10,6 +10,8 @@
float: right;
height: 54px;
text-align: right;
+ min-width:300px;
+ position:relative;
ul {
margin-bottom:0;
@@ -21,6 +23,13 @@
}
}
+#profile {
+ .avatar_large {
+ margin-left:40px;
+ float:right;
+ }
+}
+
.avatar_large {
float:left;
padding:2px;
@@ -45,11 +54,11 @@
font-size:20px;
font-weight:200;
color:#ccc;
- float:left;
+ float:right;
}
.arrow-down {
- float:left;
+ float:right;
cursor:pointer;
margin-left:16px;
margin-top:26px;
diff --git a/web/app/assets/stylesheets/client/wizard/gearWizard.css.scss b/web/app/assets/stylesheets/client/wizard/gearWizard.css.scss
index 5692b085b..c8161d018 100644
--- a/web/app/assets/stylesheets/client/wizard/gearWizard.css.scss
+++ b/web/app/assets/stylesheets/client/wizard/gearWizard.css.scss
@@ -315,7 +315,46 @@
}
}
- .wizard-step[layout-wizard-step="5"], .network-test {
+ // Video Gear:
+ .wizard-step.video-gear {
+ .wizard-step-content .wizard-step-column {
+ &:nth-of-type(1) {
+ width: 50%;
+ height: 350px;
+ }
+ &:nth-of-type(2) {
+ width: 50%;
+ }
+
+ .webcam-preview {
+ .webcam-content {
+ min-width: 200px;
+ min-height: 200px;
+ }
+ width: auto;
+ height: auto;
+ overflow: scroll;
+ }
+
+ .wizard_control {
+ margin-bottom: 10px;
+ }
+
+ ul {
+ margin-bottom: 20px;
+
+ a {
+ color:$ColorLink;
+ }
+
+ a:hover {
+ color:$ColorLinkHover;
+ }
+ }
+ }
+ }
+
+ .wizard-step.network-test {
.wizard-step-content .wizard-step-column {
&:nth-of-type(1) {
@@ -477,7 +516,7 @@
}
}
- .wizard-step[layout-wizard-step="6"] {
+ .wizard-step.success {
.wizard-step-content .wizard-step-column {
&:nth-of-type(1) {
width: 50%;
diff --git a/web/app/assets/stylesheets/corp/corporate.css.scss.erb b/web/app/assets/stylesheets/corp/corporate.css.scss.erb
index a492f717c..640360bd1 100644
--- a/web/app/assets/stylesheets/corp/corporate.css.scss.erb
+++ b/web/app/assets/stylesheets/corp/corporate.css.scss.erb
@@ -178,4 +178,47 @@ body.corporate .media_center {
margin-bottom:10px;
}
}
+}
+
+body.corporate {
+ ul {
+ li {
+ margin-left:20px;
+ }
+ }
+ ol {
+ margin-bottom:20px;
+
+ .item-header {
+ text-decoration:underline;
+ }
+ }
+ ol.lower-alpha {
+ list-style-type:lower-alpha;
+ li {
+ margin-left:40px;
+ }
+ }
+
+ ol.numeric-list {
+ list-style-type:decimal;
+ li {
+ margin-left:40px;
+ }
+ }
+ ol.roman-numeral {
+ list-style-type:lower-roman;
+ li {
+ margin-left:40px;
+ }
+ }
+}
+
+.term {
+ font-weight:bold;
+ text-decoration:underline;
+}
+
+.min-term {
+ font-weight:bold;
}
\ No newline at end of file
diff --git a/web/app/assets/stylesheets/dialogs/openJamTrackDialog.css.scss b/web/app/assets/stylesheets/dialogs/openJamTrackDialog.css.scss
index b13355afe..da7f63854 100644
--- a/web/app/assets/stylesheets/dialogs/openJamTrackDialog.css.scss
+++ b/web/app/assets/stylesheets/dialogs/openJamTrackDialog.css.scss
@@ -31,7 +31,8 @@
left: 15%;
font-size: 12px;
padding-top:5px;
- z-index:-1;
+ z-index:0;
+ margin-top:-18px;
a {
margin:0 10px;
diff --git a/web/app/assets/stylesheets/dialogs/recordingFinishedDialog.css.scss b/web/app/assets/stylesheets/dialogs/recordingFinishedDialog.css.scss
index b8f27aede..22c66dd7b 100644
--- a/web/app/assets/stylesheets/dialogs/recordingFinishedDialog.css.scss
+++ b/web/app/assets/stylesheets/dialogs/recordingFinishedDialog.css.scss
@@ -11,7 +11,7 @@
}
.recording-position {
- margin: 5px 0 0 -15px;
+ margin: 5px 0 0 11px;
width: 95%;
display:inline-block;
}
@@ -20,6 +20,11 @@
position:absolute;
}
+
+ .jam-track-get-ready {
+ display:none;
+ }
+
.icheckbuttons {
margin-top:20px;
}
diff --git a/web/app/assets/stylesheets/web/audioWidgets.css.scss b/web/app/assets/stylesheets/web/audioWidgets.css.scss
index 4c044f8b7..abfb0dba3 100644
--- a/web/app/assets/stylesheets/web/audioWidgets.css.scss
+++ b/web/app/assets/stylesheets/web/audioWidgets.css.scss
@@ -90,12 +90,17 @@
display:none;
}
- .play-button {
+ .play-buttons {
+ display:inline-block;
outline: 0;
// the following 3 properties were to make safari on iOS not wrap text after the .play-button float:left was preferred
position:absolute;
left:5px;
top:7px;
+
+ a {
+ outline: 0;
+ }
}
&.no-mount{
diff --git a/web/app/assets/stylesheets/web/downloads.css.scss b/web/app/assets/stylesheets/web/downloads.css.scss
index 4634d2f04..d18132b35 100644
--- a/web/app/assets/stylesheets/web/downloads.css.scss
+++ b/web/app/assets/stylesheets/web/downloads.css.scss
@@ -1,7 +1,24 @@
@import "client/common.css.scss";
+
body.downloads {
+ &.standalone {
+ .jamtracks {
+ display:none;
+ }
+ .download-content {
+ border-width:0;
+ }
+ .badge-number {
+ display:none;
+ }
+ .download-app {
+ left:22.5%;
+ float:none;
+ position:relative;
+ }
+ }
h2 {
font-size:22px;
diff --git a/web/app/controllers/api_alerts_controller.rb b/web/app/controllers/api_alerts_controller.rb
new file mode 100644
index 000000000..0dad78499
--- /dev/null
+++ b/web/app/controllers/api_alerts_controller.rb
@@ -0,0 +1,39 @@
+
+class ApiAlertsController < ApiController
+
+ before_filter :api_signed_in_user
+
+
+ def log
+ @log || Logging.logger[ApiAlertsController]
+ end
+
+
+ def create
+
+ if Rails.application.config.alerts_api_enabled
+
+ result = params[:result]
+ detail = params[:detail]
+
+ body = ""
+ body << "User: " + current_user.admin_url + "\n"
+ body << "Reason: #{result}\n" if result
+ body << "Detail: #{detail}\n" if detail
+ body << "\n\n\ndata:\n-----\n"
+ body << JSON.pretty_generate(params)
+
+ AdminMailer.alerts({
+ subject:params[:subject] || 'Alerts API (no subject)',
+ body:body
+ }).deliver
+
+
+ end
+
+ render json: {}, :status => :ok
+
+
+ end
+
+end
diff --git a/web/app/controllers/api_auths_controller.rb b/web/app/controllers/api_auths_controller.rb
index 00001a7e4..b7868e7ce 100644
--- a/web/app/controllers/api_auths_controller.rb
+++ b/web/app/controllers/api_auths_controller.rb
@@ -14,7 +14,7 @@ class ApiAuthsController < ApiController
@session_only_cookie = !jkclient_agent? && !params[:remember_me]
- sign_in user
+ complete_sign_in(user, redirect=false)
render :json => {}, :status => :ok
end
diff --git a/web/app/controllers/api_backing_tracks_controller.rb b/web/app/controllers/api_backing_tracks_controller.rb
index 9ed591422..c9135cf97 100644
--- a/web/app/controllers/api_backing_tracks_controller.rb
+++ b/web/app/controllers/api_backing_tracks_controller.rb
@@ -26,7 +26,7 @@ class ApiBackingTracksController < ApiController
def lookup_recorded_backing_track
@recorded_backing_track = RecordedBackingTrack.find_by_recording_id_and_client_track_id!(params[:id], params[:track_id])
- raise PermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR unless @recorded_backing_track.recording.has_access?(current_user)
+ raise JamPermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR unless @recorded_backing_track.recording.has_access?(current_user)
end
end # class ApiBackingTracksController
diff --git a/web/app/controllers/api_bands_controller.rb b/web/app/controllers/api_bands_controller.rb
index cd800aa61..8b0c83ccd 100644
--- a/web/app/controllers/api_bands_controller.rb
+++ b/web/app/controllers/api_bands_controller.rb
@@ -250,14 +250,14 @@ class ApiBandsController < ApiController
def auth_band_member
@band = Band.find(params[:id])
unless @band.users.exists? current_user
- raise PermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
+ raise JamPermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
end
end
def auth_band_admin
uid = current_user.id
@band = Band.find(params[:id])
unless @band.band_musicians.detect { |bm| bm.user_id == uid && bm.admin? }
- raise PermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
+ raise JamPermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
end
end
end
diff --git a/web/app/controllers/api_chats_controller.rb b/web/app/controllers/api_chats_controller.rb
index 4a58fd164..70988b845 100644
--- a/web/app/controllers/api_chats_controller.rb
+++ b/web/app/controllers/api_chats_controller.rb
@@ -31,7 +31,7 @@ class ApiChatsController < ApiController
end
unless @music_session.access? current_user
- raise PermissionError, 'not allowed to join the specified session'
+ raise JamPermissionError, 'not allowed to join the specified session'
end
end
diff --git a/web/app/controllers/api_claimed_recordings_controller.rb b/web/app/controllers/api_claimed_recordings_controller.rb
index 60acb0eb4..ec6796ec2 100644
--- a/web/app/controllers/api_claimed_recordings_controller.rb
+++ b/web/app/controllers/api_claimed_recordings_controller.rb
@@ -12,13 +12,13 @@ class ApiClaimedRecordingsController < ApiController
def show
if !@claimed_recording.is_public && @claimed_recording.user_id != current_user.id
- raise PermissionError, 'this claimed recording is not public'
+ raise JamPermissionError, 'this claimed recording is not public'
end
end
def update
if @claimed_recording.user_id != current_user.id
- raise PermissionError, 'only owner of claimed_recording can update it'
+ raise JamPermissionError, 'only owner of claimed_recording can update it'
end
@claimed_recording.update_fields(current_user, params)
@@ -27,15 +27,17 @@ class ApiClaimedRecordingsController < ApiController
def delete
if @claimed_recording.user_id != current_user.id
- raise PermissionError, 'only owner of claimed_recording can update it'
+ raise JamPermissionError, 'only owner of claimed_recording can update it'
end
@claimed_recording.discard(current_user)
respond_with @claimed_recording
end
def download
- if !@claimed_recording.is_public && @claimed_recording.user_id != current_user.id
- raise PermissionError, 'this claimed recording is not public'
+ unless @claimed_recording.is_public
+ if current_user.nil? || @claimed_recording.user_id != current_user.id
+ raise JamPermissionError, 'this claimed recording is not public'
+ end
end
params[:type] ||= 'ogg'
diff --git a/web/app/controllers/api_controller.rb b/web/app/controllers/api_controller.rb
index c42f138b1..ce17dbd9c 100644
--- a/web/app/controllers/api_controller.rb
+++ b/web/app/controllers/api_controller.rb
@@ -15,7 +15,7 @@ class ApiController < ApplicationController
@exception = exception
render "errors/jam_argument_error", :status => 422
end
- rescue_from 'JamRuby::PermissionError' do |exception|
+ rescue_from 'JamRuby::JamPermissionError' do |exception|
@exception = exception
render "errors/permission_error", :status => 403
end
@@ -57,7 +57,7 @@ class ApiController < ApplicationController
def auth_user
unless current_user.id == params[:id]
- raise PermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
+ raise JamPermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
end
@user = User.find(params[:id])
diff --git a/web/app/controllers/api_invitations_controller.rb b/web/app/controllers/api_invitations_controller.rb
index b1c91ddb5..b916da143 100644
--- a/web/app/controllers/api_invitations_controller.rb
+++ b/web/app/controllers/api_invitations_controller.rb
@@ -12,7 +12,7 @@ class ApiInvitationsController < ApiController
if !sender_id.nil?
if current_user.id != sender_id
- raise PermissionError, "You can only ask for your own sent invitations"
+ raise JamPermissionError, "You can only ask for your own sent invitations"
end
if session_id = params[:session_id]
@invitations = Invitation.where(:sender_id => sender_id, :music_session_id => session_id).uniq_by { |i| i.receiver_id }
@@ -21,7 +21,7 @@ class ApiInvitationsController < ApiController
end
elsif !receiver_id.nil?
if current_user.id != receiver_id
- raise PermissionError, "You can only ask for your own received invitations"
+ raise JamPermissionError, "You can only ask for your own received invitations"
end
@invitations = Invitation.where(:receiver_id => current_user.id).uniq_by { |i| i.receiver_id }
diff --git a/web/app/controllers/api_jam_tracks_controller.rb b/web/app/controllers/api_jam_tracks_controller.rb
index fd8019462..f7dbc3b18 100644
--- a/web/app/controllers/api_jam_tracks_controller.rb
+++ b/web/app/controllers/api_jam_tracks_controller.rb
@@ -1,8 +1,8 @@
class ApiJamTracksController < ApiController
# have to be signed in currently to see this screen
- before_filter :api_signed_in_user, :except => [:index, :show, :show_with_artist_info]
- before_filter :api_any_user, :only => [:index, :show, :show_with_artist_info]
+ before_filter :api_signed_in_user, :except => [:index, :show, :show_with_artist_info, :artist_index]
+ before_filter :api_any_user, :only => [:index, :show, :show_with_artist_info, :artist_index]
before_filter :lookup_jam_track_right, :only => [:download,:enqueue, :show_jam_track_right]
respond_to :json
@@ -22,6 +22,13 @@ class ApiJamTracksController < ApiController
render "api_jam_tracks/index", :layout => nil
end
+ def artist_index
+ data = JamTrack.artist_index(params, any_user)
+ @artists, @next = data[0], data[1]
+
+ render "api_jam_tracks/artist_index", :layout => nil
+ end
+
def played
if params[:id].blank?
render(:json => { :message => "JamTrack ID required" }, :status => 400) and return
@@ -29,7 +36,12 @@ class ApiJamTracksController < ApiController
play = PlayablePlay.new
play.player_id = current_user.id
play.ip_address = request.remote_ip
-
+
+ unless current_user.first_played_jamtrack_at
+ User.where(id: current_user.id).update_all(first_played_jamtrack_at: Time.now)
+ current_user.first_played_jamtrack_at = Time.now
+ end
+
# VRFS-2916 jam_tracks.id is varchar: REMOVE
# play.jam_track = JamTrack.where(id: params[:id].to_i).first
# VRFS-2916 jam_tracks.id is varchar: ADD
@@ -103,7 +115,7 @@ class ApiJamTracksController < ApiController
private
def lookup_jam_track_right
@jam_track_right = JamTrackRight.where("jam_track_id=? AND user_id=?", params[:id], current_user.id).first
- raise PermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR unless @jam_track_right
+ raise JamPermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR unless @jam_track_right
end
end # class ApiJamTracksController
diff --git a/web/app/controllers/api_mixes_controller.rb b/web/app/controllers/api_mixes_controller.rb
index 2ec820a7a..af1f9e382 100644
--- a/web/app/controllers/api_mixes_controller.rb
+++ b/web/app/controllers/api_mixes_controller.rb
@@ -24,7 +24,7 @@ class ApiMixesController < ApiController
def download
@mix = Mix.find(params[:id])
- raise PermissionError, "You can only download a mix you have claimed" unless @mix.can_download? current_user
+ raise JamPermissionError, "You can only download a mix you have claimed" unless @mix.can_download? current_user
@mix.current_user = current_user
@mix.update_download_count
diff --git a/web/app/controllers/api_music_sessions_controller.rb b/web/app/controllers/api_music_sessions_controller.rb
index 50100a0a2..366469aad 100644
--- a/web/app/controllers/api_music_sessions_controller.rb
+++ b/web/app/controllers/api_music_sessions_controller.rb
@@ -573,13 +573,13 @@ class ApiMusicSessionsController < ApiController
def jam_track_open
unless @music_session.users.exists?(current_user)
- raise PermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
+ raise JamPermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
end
@jam_track = JamTrack.find(params[:jam_track_id])
unless @jam_track.right_for_user(current_user)
- raise PermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
+ raise JamPermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
end
@music_session.open_jam_track(current_user, @jam_track)
@@ -589,7 +589,7 @@ class ApiMusicSessionsController < ApiController
def jam_track_close
unless @music_session.users.exists?(current_user)
- raise PermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
+ raise JamPermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
end
@music_session.close_jam_track
@@ -599,7 +599,7 @@ class ApiMusicSessionsController < ApiController
def backing_track_open
unless @music_session.users.exists?(current_user)
- raise PermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
+ raise JamPermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
end
@backing_track_path = params[:backing_track_path]
@@ -609,7 +609,7 @@ class ApiMusicSessionsController < ApiController
def backing_track_close
unless @music_session.users.exists?(current_user)
- raise PermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
+ raise JamPermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
end
@music_session.close_backing_track()
@@ -618,7 +618,7 @@ class ApiMusicSessionsController < ApiController
def metronome_open
unless @music_session.users.exists?(current_user)
- raise PermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
+ raise JamPermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
end
@music_session.open_metronome(current_user)
@@ -627,7 +627,7 @@ class ApiMusicSessionsController < ApiController
def metronome_close
unless @music_session.users.exists?(current_user)
- raise PermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
+ raise JamPermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
end
@music_session.close_metronome()
diff --git a/web/app/controllers/api_payment_histories_controller.rb b/web/app/controllers/api_payment_histories_controller.rb
new file mode 100644
index 000000000..6e8080f98
--- /dev/null
+++ b/web/app/controllers/api_payment_histories_controller.rb
@@ -0,0 +1,18 @@
+class ApiPaymentHistoriesController < ApiController
+
+ before_filter :api_signed_in_user
+
+ respond_to :json
+
+ def index
+ data = PaymentHistory.index(current_user,
+ page: params[:page],
+ per_page: params[:per_page])
+
+
+ @payment_histories = data[:query]
+
+ @next = data[:next_page]
+ render "api_payment_histories/index", :layout => nil
+ end
+end
\ No newline at end of file
diff --git a/web/app/controllers/api_recordings_controller.rb b/web/app/controllers/api_recordings_controller.rb
index 27eb6c856..b4012be5d 100644
--- a/web/app/controllers/api_recordings_controller.rb
+++ b/web/app/controllers/api_recordings_controller.rb
@@ -49,7 +49,7 @@ class ApiRecordingsController < ApiController
end
def download # track
- raise PermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR unless @recorded_track.can_download?(current_user)
+ raise JamPermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR unless @recorded_track.can_download?(current_user)
@recorded_track.current_user = current_user
@recorded_track.update_download_count
@@ -64,7 +64,7 @@ class ApiRecordingsController < ApiController
end
def backing_track_download
- raise PermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR unless @recorded_backing_track.can_download?(current_user)
+ raise JamPermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR unless @recorded_backing_track.can_download?(current_user)
@recorded_backing_track.current_user = current_user
@recorded_backing_track.update_download_count
@@ -81,7 +81,7 @@ class ApiRecordingsController < ApiController
def start
music_session = ActiveMusicSession.find(params[:music_session_id])
- raise PermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR unless music_session.users.exists?(current_user)
+ raise JamPermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR unless music_session.users.exists?(current_user)
@recording = Recording.start(music_session, current_user)
@@ -388,27 +388,27 @@ class ApiRecordingsController < ApiController
def lookup_recording
@recording = Recording.find(params[:id])
- raise PermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR unless @recording.has_access?(current_user)
+ raise JamPermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR unless @recording.has_access?(current_user)
end
def lookup_recorded_track
@recorded_track = RecordedTrack.find_by_recording_id_and_client_track_id!(params[:id], params[:track_id])
- raise PermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR unless @recorded_track.recording.has_access?(current_user)
+ raise JamPermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR unless @recorded_track.recording.has_access?(current_user)
end
def lookup_recorded_backing_track
@recorded_backing_track = RecordedBackingTrack.find_by_recording_id_and_client_track_id!(params[:id], params[:track_id])
- raise PermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR unless @recorded_backing_track.recording.has_access?(current_user)
+ raise JamPermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR unless @recorded_backing_track.recording.has_access?(current_user)
end
def lookup_stream_mix
@quick_mix = QuickMix.find_by_recording_id_and_user_id!(params[:id], current_user.id)
- raise PermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR unless @quick_mix.recording.has_access?(current_user)
+ raise JamPermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR unless @quick_mix.recording.has_access?(current_user)
end
def lookup_recorded_video
@recorded_video = RecordedVideo.find_by_recording_id_and_client_video_source_id!(params[:id], params[:video_id])
- raise PermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR unless @recorded_video.recording.has_access?(current_user)
+ raise JamPermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR unless @recorded_video.recording.has_access?(current_user)
end
end # class
diff --git a/web/app/controllers/api_rsvp_requests_controller.rb b/web/app/controllers/api_rsvp_requests_controller.rb
index b4fd641cb..78e9feb88 100644
--- a/web/app/controllers/api_rsvp_requests_controller.rb
+++ b/web/app/controllers/api_rsvp_requests_controller.rb
@@ -1,6 +1,6 @@
class ApiRsvpRequestsController < ApiController
- # before_filter :auth_user
+ before_filter :api_signed_in_user
respond_to :json
diff --git a/web/app/controllers/api_sales_controller.rb b/web/app/controllers/api_sales_controller.rb
index 8886ba6bd..972384d76 100644
--- a/web/app/controllers/api_sales_controller.rb
+++ b/web/app/controllers/api_sales_controller.rb
@@ -1,7 +1,10 @@
class ApiSalesController < ApiController
+ before_filter :api_signed_in_user
+
respond_to :json
+ # deprecated in favor of ApiPaymentHistoriesController
def index
data = Sale.index(current_user,
page: params[:page],
diff --git a/web/app/controllers/api_sessions_controller.rb b/web/app/controllers/api_sessions_controller.rb
index 95e24d563..ae4a67fc2 100644
--- a/web/app/controllers/api_sessions_controller.rb
+++ b/web/app/controllers/api_sessions_controller.rb
@@ -12,7 +12,7 @@ class ApiSessionsController < ApiController
@session_only_cookie = !jkclient_agent? && 0 == params[:remember_me].to_i
- sign_in user
+ complete_sign_in(user, redirect=false)
render :json => {}, :status => :ok
end
diff --git a/web/app/controllers/api_signup_hints_controller.rb b/web/app/controllers/api_signup_hints_controller.rb
new file mode 100644
index 000000000..8d9e6ef31
--- /dev/null
+++ b/web/app/controllers/api_signup_hints_controller.rb
@@ -0,0 +1,19 @@
+class ApiSignupHintsController < ApiController
+
+ before_filter :api_anonymous_user
+
+ respond_to :json
+
+ def show
+ @signup_hint = SignupHint.find(params[:id])
+ respond_with_model(@signup_hint)
+ end
+
+ def create
+ @signup_hint = SignupHint.refresh_by_anoymous_user(anonymous_user, params)
+
+ respond_with_model(@signup_hint, new: true, location: lambda { return api_signup_hint_detail_url(@signup_hint.id) })
+ end
+end
+
+
diff --git a/web/app/controllers/api_twitters_controller.rb b/web/app/controllers/api_twitters_controller.rb
index b75fc8bd2..a56ebc660 100644
--- a/web/app/controllers/api_twitters_controller.rb
+++ b/web/app/controllers/api_twitters_controller.rb
@@ -20,7 +20,7 @@ class ApiTwittersController < ApiController
twitter_auth = current_user.user_authorization('twitter')
- raise JamRuby::PermissionError unless twitter_auth
+ raise JamRuby::JamPermissionError unless twitter_auth
client = Twitter::REST::Client.new do |config|
config.consumer_key = Rails.application.config.twitter_app_id
diff --git a/web/app/controllers/api_users_controller.rb b/web/app/controllers/api_users_controller.rb
index fcb03267d..d8d2ad0da 100644
--- a/web/app/controllers/api_users_controller.rb
+++ b/web/app/controllers/api_users_controller.rb
@@ -98,6 +98,7 @@ class ApiUsersController < ApiController
@user.cowriting = params[:cowriting] if params.has_key?(:cowriting)
@user.cowriting_purpose = params[:cowriting_purpose] if params.has_key?(:cowriting_purpose)
+ @user.want_jamblaster = params[:want_jamblaster] if params.has_key?(:want_jamblaster)
@user.mod_merge(params[:mods]) if params[:mods]
# allow keyword of 'LATEST' to mean set the notification_seen_at to the most recent notification for this user
@@ -324,7 +325,7 @@ class ApiUsersController < ApiController
def friend_request_show
@friend_request = FriendRequest.find(params[:friend_request_id])
- raise JamRuby::PermissionError, 'not allowed to view someone else\'s friend request' if @friend_request.friend_id != @user.id && @friend_request.user_id != @user.id
+ raise JamRuby::JamPermissionError, 'not allowed to view someone else\'s friend request' if @friend_request.friend_id != @user.id && @friend_request.user_id != @user.id
respond_with @friend_request, responder: ApiResponder, :status => 200
end
diff --git a/web/app/controllers/clients_controller.rb b/web/app/controllers/clients_controller.rb
index 51813a8d3..d05fd60bd 100644
--- a/web/app/controllers/clients_controller.rb
+++ b/web/app/controllers/clients_controller.rb
@@ -16,6 +16,7 @@ class ClientsController < ApplicationController
return
end
+ @minimal_curtain = Rails.application.config.minimal_curtain
gon.recurly_tax_estimate_jam_track_plan = Rails.application.config.recurly_tax_estimate_jam_track_plan
render :layout => 'client'
end
diff --git a/web/app/controllers/landings_controller.rb b/web/app/controllers/landings_controller.rb
index cd1038904..e7e7150ca 100644
--- a/web/app/controllers/landings_controller.rb
+++ b/web/app/controllers/landings_controller.rb
@@ -67,12 +67,14 @@ class LandingsController < ApplicationController
end
def individual_jamtrack
+ @jam_track = JamTrack.find_by_plan_code("jamtrack-" + params[:plan_code])
gon.jam_track_plan_code = params[:plan_code] ? "jamtrack-" + params[:plan_code] : nil
gon.generic = params[:generic]
render 'individual_jamtrack', layout: 'web'
end
def individual_jamtrack_band
+ @jam_track = JamTrack.find_by_plan_code("jamtrack-" + params[:plan_code])
gon.jam_track_plan_code = params[:plan_code] ? "jamtrack-" + params[:plan_code] : nil
render 'individual_jamtrack_band', layout: 'web'
diff --git a/web/app/controllers/sessions_controller.rb b/web/app/controllers/sessions_controller.rb
index 6c772cd4a..7118cc953 100644
--- a/web/app/controllers/sessions_controller.rb
+++ b/web/app/controllers/sessions_controller.rb
@@ -169,17 +169,6 @@ class SessionsController < ApplicationController
redirect_to "#{callback_url}?multipass=#{multipass.token}&signature=#{multipass.signature}"
end
- def complete_sign_in(user)
- sign_in user
-
- if params[:sso] == "desk"
- redirect_to_support_after_signin(user)
- elsif params[:sso] == 'forums'
- redirect_to_forums_after_signin
- else
- redirect_after_signin(client_path)
- end
- end
def destroy
# earlier, code here would delete the connection using client_id from cookies
diff --git a/web/app/controllers/spikes_controller.rb b/web/app/controllers/spikes_controller.rb
index c5f6aa645..0edce85ce 100644
--- a/web/app/controllers/spikes_controller.rb
+++ b/web/app/controllers/spikes_controller.rb
@@ -14,7 +14,7 @@ class SpikesController < ApplicationController
def listen_in
if !current_user.admin
- raise PermissionError "must be administrator"
+ raise JamPermissionError "must be administrator"
end
#as_musician = false is the critical search criteria for sessions to list correctly
diff --git a/web/app/controllers/users_controller.rb b/web/app/controllers/users_controller.rb
index f8269db5a..f41b17d86 100644
--- a/web/app/controllers/users_controller.rb
+++ b/web/app/controllers/users_controller.rb
@@ -104,6 +104,8 @@ class UsersController < ApplicationController
return
end
+ signup_hint = SignupHint.where(anonymous_user_id: anonymous_user.id).where('expires_at > ?', Time.now).first if anonymous_user
+
@fb_signup = load_facebook_signup(params)
# check if the email specified by @fb_signup already exists in the database--if so, log them in and redirect
@@ -113,7 +115,8 @@ class UsersController < ApplicationController
# update user_authorization for user because this is fresher
user.update_fb_authorization(@fb_signup)
sign_in(user)
- redirect_to client_url
+ redirect_url = handle_signup_hint(user, signup_hint, client_url)
+ redirect_to redirect_url
return
end
end
@@ -125,10 +128,11 @@ class UsersController < ApplicationController
if user_authorization
user_authorization.user.update_fb_authorization(@fb_signup)
sign_in(user_authorization.user)
- redirect_to client_url
+
+ redirect_url = handle_signup_hint(user_authorization.user, signup_hint, client_url)
+ redirect_to redirect_url
return
end
-
end
@invited_user = load_invited_user(params)
@@ -169,12 +173,30 @@ class UsersController < ApplicationController
else
sign_in @user
+ new_user(@user, signup_hint) # sets a cookie used for GA analytics (one-time new user stuff in JavaScript)
destination = @user.musician ? :congratulations_musician : :congratulations_fan
-
- redirect_to :action => destination, :type => @user.user_authorization('facebook') ? 'Facebook' : 'Native'
+ redirect_url = handle_signup_hint(@user, signup_hint, {:action => destination, :type => @user.user_authorization('facebook') ? 'Facebook' : 'Native'})
+ redirect_to redirect_url
end
end
+ # given the current user, and any signup hint (can be nil)
+ # handle the final destination of the user
+ def handle_signup_hint(user, signup_hint, default_redirect)
+ redirect_url = default_redirect
+ if signup_hint
+ if signup_hint.want_jamblaster
+ User.where(id: user.id).update_all(want_jamblaster: true)
+ end
+
+ if signup_hint.redirect_location
+ redirect_url = signup_hint.redirect_location
+ end
+ end
+
+ redirect_url
+ end
+
def congratulations_fan
@no_user_dropdown = true
render :layout => "web"
@@ -187,35 +209,7 @@ class UsersController < ApplicationController
def downloads
@no_user_dropdown = true
- render :layout => "web"
- end
-
- # DO NOT USE CURRENT_USER IN THIS ROUTINE. IT'S CACHED FOR THE WHOLE SITE
- def welcome
-
- @slides = [
- Slide.new("JamKazam Overview", "web/carousel_overview.png", "http://www.youtube.com/embed/ylYcvTY9CVo?autoplay=1"),
- Slide.new("The Revolutionary New JamBlaster!", "web/carousel_jamblaster.png", "http://www.youtube.com/embed/gAJAIHMyois?autoplay=1"),
- Slide.new("Kudos From Our Community", "web/carousel_community.png", "http://www.youtube.com/embed/_7qj5RXyHCo?autoplay=1"),
- Slide.new("JamKazam Overview", "web/carousel_overview.png", "http://www.youtube.com/embed/ylYcvTY9CVo?autoplay=1"),
- Slide.new("The Revolutionary New JamBlaster!", "web/carousel_fans.jpg", "http://www.youtube.com/embed/gAJAIHMyois?autoplay=1"),
- Slide.new("Kudos From Our Community", "web/carousel_community.png", "http://www.youtube.com/embed/_7qj5RXyHCo?autoplay=1")
- ]
-
- @promo_buzz = PromoBuzz.active
-
- if Rails.application.config.use_promos_on_homepage
- @promo_latest = PromoLatest.active
- else
- @promo_latest, start = Feed.index(nil, limit: 10)
- end
-
- # temporary--will go away soon
- #@jamfest_2014 = Event.find_by_id('80bb6acf-3ddc-4305-9442-75e6ec047c27') # production ID
- #@jamfest_2014 = Event.find_by_id('a2dfbd26-9b17-4446-8c61-b67a542ea6ee') unless @jamfest_2014 # development ID
- # temporary--end
-
- #@welcome_page = true
+ @page_context = 'standalone'
render :layout => "web"
end
diff --git a/web/app/helpers/application_helper.rb b/web/app/helpers/application_helper.rb
index 827379344..160a1b3cf 100644
--- a/web/app/helpers/application_helper.rb
+++ b/web/app/helpers/application_helper.rb
@@ -10,6 +10,14 @@ module ApplicationHelper
end
end
+ def meta_description(description)
+ if description
+ description
+ else
+ 'JamKazam'
+ end
+ end
+
def self.base_uri(request)
(request.ssl? ? "https://" : "http://") + request.host_with_port
end
diff --git a/web/app/helpers/recording_helper.rb b/web/app/helpers/recording_helper.rb
index 3d8a6eeec..8eb09f158 100644
--- a/web/app/helpers/recording_helper.rb
+++ b/web/app/helpers/recording_helper.rb
@@ -49,8 +49,8 @@ module RecordingHelper
end
end
- def description_for_claimed_recording(claimed_recording)
- truncate(claimed_recording.name, length:250)
+ def description_for_claimed_recording(claimed_recording, length = 250)
+ truncate(claimed_recording.name, length:length)
end
def listen_mix_url(recording)
diff --git a/web/app/helpers/sessions_helper.rb b/web/app/helpers/sessions_helper.rb
index 5232fc24c..f9599bdef 100644
--- a/web/app/helpers/sessions_helper.rb
+++ b/web/app/helpers/sessions_helper.rb
@@ -21,6 +21,26 @@ module SessionsHelper
end
end
+ def complete_sign_in(user, redirect=true)
+ sign_in user
+
+ # port over any shopping cart items
+ if has_anonymous_user?
+ shopping_carts = anonymous_user.shopping_carts
+
+ ShoppingCart.move_to_user(user, anonymous_user, shopping_carts)
+ end
+
+ if redirect
+ if params[:sso] == "desk"
+ redirect_to_support_after_signin(user)
+ elsif params[:sso] == 'forums'
+ redirect_to_forums_after_signin
+ else
+ redirect_after_signin(client_path)
+ end
+ end
+ end
def signed_in?
!current_user.nil?
@@ -59,6 +79,18 @@ module SessionsHelper
@anon_cookie ||= cookies[:user_uuid]
end
+ def new_user(user, signup_hint)
+
+ want_jamblaster = false
+ redirect_location = nil
+ if signup_hint
+ want_jamblaster = signup_hint.want_jamblaster
+ redirect_location = signup_hint.redirect_location
+ end
+
+ cookies[:new_user] = { musician: user.musician, registrationType: user.user_authorization('facebook') ? 'Facebook' : 'Native', want_jamblaster: want_jamblaster, redirect_location: redirect_location }.to_json
+ end
+
def current_user?(user)
user == current_user
end
@@ -83,6 +115,12 @@ module SessionsHelper
end
end
+ def api_anonymous_user
+ unless has_anonymous_user?
+ render :json => { :errors => {:user_uuid => ['not specified']}}, :status => 422
+ end
+
+ end
def sign_out
current_user = nil
cookies.delete(:remember_token, domain: Rails.application.config.session_cookie_domain)
diff --git a/web/app/views/api_jam_tracks/artist_index.rabl b/web/app/views/api_jam_tracks/artist_index.rabl
new file mode 100644
index 000000000..d994d6b82
--- /dev/null
+++ b/web/app/views/api_jam_tracks/artist_index.rabl
@@ -0,0 +1,7 @@
+node :next do |page|
+ @next
+end
+
+node :artists do |page|
+ partial "api_jam_tracks/show_artist", object: @artists
+end
\ No newline at end of file
diff --git a/web/app/views/api_jam_tracks/show.rabl b/web/app/views/api_jam_tracks/show.rabl
index 65d887ea8..e616306e2 100644
--- a/web/app/views/api_jam_tracks/show.rabl
+++ b/web/app/views/api_jam_tracks/show.rabl
@@ -1,6 +1,6 @@
object @jam_track
-attributes :id, :name, :description, :recording_type, :original_artist, :songwriter, :publisher, :sales_region, :price, :version
+attributes :id, :name, :description, :recording_type, :original_artist, :songwriter, :publisher, :sales_region, :price, :version, :duration
node :genres do |item|
[item.genre.description] # XXX: need to return single genre; not array
diff --git a/web/app/views/api_jam_tracks/show_artist.rabl b/web/app/views/api_jam_tracks/show_artist.rabl
new file mode 100644
index 000000000..68839c3f3
--- /dev/null
+++ b/web/app/views/api_jam_tracks/show_artist.rabl
@@ -0,0 +1,3 @@
+object @artist
+
+attributes :original_artist, :song_count
\ No newline at end of file
diff --git a/web/app/views/api_jam_tracks/show_jam_track_right.rabl b/web/app/views/api_jam_tracks/show_jam_track_right.rabl
index e72c3f5b4..365730236 100644
--- a/web/app/views/api_jam_tracks/show_jam_track_right.rabl
+++ b/web/app/views/api_jam_tracks/show_jam_track_right.rabl
@@ -1,3 +1,3 @@
object @jam_track_right
-attributes :id, :signing_state, :error_count, :error_reason, :error_detail
\ No newline at end of file
+attributes :id, :error_count, :error_reason, :error_detail, :signing_state, :packaging_steps, :current_packaging_step
\ No newline at end of file
diff --git a/web/app/views/api_music_sessions/show.rabl b/web/app/views/api_music_sessions/show.rabl
index 093e47077..771933fbd 100644
--- a/web/app/views/api_music_sessions/show.rabl
+++ b/web/app/views/api_music_sessions/show.rabl
@@ -13,7 +13,7 @@ if !current_user
}
else
- attributes :id, :name, :description, :musician_access, :approval_required, :fan_access, :fan_chat, :band_id, :user_id, :claimed_recording_initiator_id, :track_changes_counter, :max_score, :backing_track_path, :metronome_active, :jam_track_initiator_id
+ attributes :id, :name, :description, :musician_access, :approval_required, :fan_access, :fan_chat, :band_id, :user_id, :claimed_recording_initiator_id, :track_changes_counter, :max_score, :backing_track_path, :metronome_active, :jam_track_initiator_id, :jam_track_id
node :can_join do |session|
session.can_join?(current_user, true)
diff --git a/web/app/views/api_payment_histories/index.rabl b/web/app/views/api_payment_histories/index.rabl
new file mode 100644
index 000000000..69c416183
--- /dev/null
+++ b/web/app/views/api_payment_histories/index.rabl
@@ -0,0 +1,11 @@
+node :next do |page|
+ @next
+end
+
+node :entries do |page|
+ partial "api_payment_histories/show", object: @payment_histories
+end
+
+node :total_entries do |page|
+ @payment_histories.total_entries
+end
diff --git a/web/app/views/api_payment_histories/show.rabl b/web/app/views/api_payment_histories/show.rabl
new file mode 100644
index 000000000..f86cf10b4
--- /dev/null
+++ b/web/app/views/api_payment_histories/show.rabl
@@ -0,0 +1,14 @@
+object @payment_history
+
+child :sale do
+ attributes :id, :recurly_invoice_id, :recurly_subtotal_in_cents, :recurly_tax_in_cents, :recurly_total_in_cents, :recurly_currency, :sale_type, :recurly_invoice_number, :state, :created_at
+
+ child(:sale_line_items => :line_items) {
+ attributes :id, :product_info
+ }
+
+end
+
+child(:recurly_transaction_web_hook => :transaction) do
+ attributes :id, :transaction_type, :subscription_id, :amount_in_cents, :invoice_id, :admin_description, :message, :transaction_at, :admin_description
+end
diff --git a/web/app/views/api_recordings/show.rabl b/web/app/views/api_recordings/show.rabl
index 330f12f7b..d59732cb3 100644
--- a/web/app/views/api_recordings/show.rabl
+++ b/web/app/views/api_recordings/show.rabl
@@ -1,6 +1,10 @@
object @recording
-attributes :id, :band, :created_at, :duration, :comment_count, :like_count, :play_count, :when_will_be_discarded?, :jam_track_id, :jam_track_initiator_id
+attributes :id, :band, :created_at, :duration, :comment_count, :like_count, :play_count, :when_will_be_discarded?, :jam_track_id, :jam_track_initiator_id, :music_session_id, :music_session
+
+node :fan_access do |recording|
+ recording.non_active_music_session.fan_access
+end
node :mix do |recording|
if recording.mix
diff --git a/web/app/views/api_signup_hints/show.rabl b/web/app/views/api_signup_hints/show.rabl
new file mode 100644
index 000000000..6c72b2273
--- /dev/null
+++ b/web/app/views/api_signup_hints/show.rabl
@@ -0,0 +1,3 @@
+object @signup_hint
+
+attributes :id, :redirect_location, :want_jamblaster
\ No newline at end of file
diff --git a/web/app/views/api_users/show.rabl b/web/app/views/api_users/show.rabl
index 6f6dc378a..4d3026685 100644
--- a/web/app/views/api_users/show.rabl
+++ b/web/app/views/api_users/show.rabl
@@ -11,7 +11,7 @@ end
# give back more info if the user being fetched is yourself
if @user == current_user
- attributes :email, :original_fpfile, :cropped_fpfile, :crop_selection, :session_settings, :show_whats_next, :show_whats_next_count, :subscribe_email, :auth_twitter, :new_notifications, :sales_count, :reuse_card, :purchased_jamtracks_count
+ attributes :email, :original_fpfile, :cropped_fpfile, :crop_selection, :session_settings, :show_whats_next, :show_whats_next_count, :subscribe_email, :auth_twitter, :new_notifications, :sales_count, :reuse_card, :purchased_jamtracks_count, :first_downloaded_client_at
node :geoiplocation do |user|
geoiplocation = current_user.geoiplocation
@@ -22,6 +22,10 @@ if @user == current_user
Rails.application.config.one_free_jamtrack_per_user && user.has_redeemable_jamtrack
end
+ node :show_jamtrack_guide do |user|
+ !user.first_played_jamtrack_at && user.jam_track_rights.count > 0
+ end
+
node :mods do |user|
user.mods_json
end
diff --git a/web/app/views/clients/_account.html.erb b/web/app/views/clients/_account.html.erb
index ceb703681..aff5520fc 100644
--- a/web/app/views/clients/_account.html.erb
+++ b/web/app/views/clients/_account.html.erb
@@ -38,22 +38,40 @@
{% if (data.isNativeClient) { %}
-
-
audio gear:
-
+
+
audio gear:
+
-
- Profiles: {{data.validProfiles}}
-
+
+ Profiles: {{data.validProfiles}}
+
-
-
+
+
+
-
{% } %}
+ <% if (Rails.application.config.video_available && Rails.application.config.video_available != "none") || (current_user && current_user.admin) %>
+
+
+
video gear:
+
+
+
+ webcam: {{data.webcamName}}
+
+
+
+
+
+ <% end %>
+
+
identity:
diff --git a/web/app/views/clients/_account_jamtracks.html.slim b/web/app/views/clients/_account_jamtracks.html.slim
index c04de8d3c..3ae1a39d0 100644
--- a/web/app/views/clients/_account_jamtracks.html.slim
+++ b/web/app/views/clients/_account_jamtracks.html.slim
@@ -25,9 +25,9 @@
tr.no-jamtracks-found.hidden
td colspan="3"
| You don't currently own any JamTracks.
- a.orange href="/client#/jamtracks" Browse JamTracks Now
+ a.orange href="/client#/jamtrackBrowse" Browse JamTracks Now
.right
- a.button-orange href="/client#/jamtracks" JAMTRACKS
+ a.button-orange href="/client#/jamtrackBrowse" JAMTRACKS
a.button-grey href="javascript:history.go(-1)" BACK
script#template-account-jamtrack type='text/template'
diff --git a/web/app/views/clients/_account_payment_history.html.slim b/web/app/views/clients/_account_payment_history.html.slim
index 5a31dffaf..e430bc90d 100644
--- a/web/app/views/clients/_account_payment_history.html.slim
+++ b/web/app/views/clients/_account_payment_history.html.slim
@@ -41,4 +41,4 @@ script#template-payment-history-row type="text/template"
td.capitalize
| {{data.status}}
td.amount class="{{data.status}}"
- | ${{data.amount}}
+ | {{data.amount}}
diff --git a/web/app/views/clients/_account_video_profile.html.erb b/web/app/views/clients/_account_video_profile.html.erb
new file mode 100644
index 000000000..31b2d20c0
--- /dev/null
+++ b/web/app/views/clients/_account_video_profile.html.erb
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+ <%= image_tag "content/icon_account.png", {:width => 27, :height => 20} %>
+
+
+
my account
+
+ <%= render "screen_navigation" %>
+
+
+
+
+
+
+
+
+
+
+
+ <%= render 'webcam' %>
+
+
+
+
+
+
+
+
diff --git a/web/app/views/clients/_checkout_order.html.slim b/web/app/views/clients/_checkout_order.html.slim
index ed3578d68..795e9f715 100644
--- a/web/app/views/clients/_checkout_order.html.slim
+++ b/web/app/views/clients/_checkout_order.html.slim
@@ -14,7 +14,7 @@ div layout="screen" layout-id="checkoutOrder" id="checkoutOrderScreen" class="sc
| Please review your order, and if everything looks correct, click the PLACE YOUR ORDER button. Thank you!
p.empty-cart-prompt.hidden
| You have nothing in your cart. You can go browse for JamTracks
- a href="/client#/jamtrack" here
+ a href="/client#/jamtrackBrowse" here
| .
p.no-account-info-prompt.hidden
| You have no billing info. Please go back to the
@@ -37,9 +37,14 @@ div layout="screen" layout-id="checkoutOrder" id="checkoutOrderScreen" class="sc
.thanks-detail We'll send you an email confirming your order shortly.
br
.thanks-detail.jam-tracks-in-browser.hidden
- | To play your purchased JamTrack, launch the JamKazam application and open the JamTrack while in a session.
+ p To play your purchased JamTrack, launch the JamKazam application and open the JamTrack while in a session.
+ a.download-jamkazam-wrapper.hidden href="/downloads" rel="external"
+ .download-jamkazam
+ | Click Here to Get the Free JamKazam Application
.thanks-detail.purchased-jam-track.hidden
- h2.purchased-jam-track-header Downloading Your Purchased JamTracks
+ h2.purchased-jam-track-header status="in-progress"
+ span.in-progress-msg Downloading Your Purchased JamTracks
+ span.done-msg All purchased JamTracks have been downloaded successfully! You can now play them in a session.
span Each JamTrack will be downloaded sequentially.
br
span.notice Note that you do not have to wait for this to complete in order to use your JamTrack later.
@@ -105,8 +110,13 @@ script type='text/template' id='template-order-content'
.cart-item cart-id="{{cart.id}}"
.cart-item-caption
= "{{cart.cart_type}}: {{cart.product_info.name}}"
+ = "{% if (cart.product_info.free) { %}"
+ span.first-one-free
+ | (first one free)
+ = "{% } %}"
+
.cart-item-price
- = "$ {{Number(cart.product_info.total_price).toFixed(2)}}"
+ = "$ {{Number(cart.product_info.real_price).toFixed(2)}}"
.cart-item-quantity
= "{{cart.quantity}}"
.clearall
@@ -143,11 +153,11 @@ script type='text/template' id='template-order-content'
.order-help
span By placing your order, you agree to JamKazam's
'
- a href="http://www.jamkazam.com/corp/terms" rel="external" terms of service
+ a href="/corp/terms" rel="external" terms of service
+ span
+ | , including the
'
- span and
- '
- a href="http://www.jamkazam.com/corp/returns" rel="external" returns policy
+ a href="/corp/terms#purchasing-jamtracks" rel="external" JamTracks purchase terms
span .
.clearall
diff --git a/web/app/views/clients/_download_jamtrack_templates.html.slim b/web/app/views/clients/_download_jamtrack_templates.html.slim
index fef7f2cd8..ace417584 100644
--- a/web/app/views/clients/_download_jamtrack_templates.html.slim
+++ b/web/app/views/clients/_download_jamtrack_templates.html.slim
@@ -24,22 +24,30 @@ script type="text/template" id="template-download-jamtrack-state-packaging"
.state-packaging
.large.hidden
.msg
- | Your JamTrack is currently being created on the JamKazam server.
+ | Your JamTrack is currently being created on the JamKazam server. (
+ span.progress
+ | )
.spinner-large
.small.hidden
.msg
- | {{data.name}} (packaging)
+ | {{data.name}} (packaging -
+ span.progress
+ | )
.spinner-small
script type="text/template" id="template-download-jamtrack-state-downloading"
.state-downloading
.large.hidden
.msg
- | Your JamTrack is currently being downloaded.
+ | Your JamTrack is currently being downloaded. (
+ span.progress 0%
+ | )
.spinner-large
.small.hidden
.msg
- | {{data.name}} (downloading)
+ | {{data.name}} (downloading -
+ span.progress 0%
+ | )
.spinner-small
script type="text/template" id="template-download-jamtrack-state-keying"
diff --git a/web/app/views/clients/_header.html.erb b/web/app/views/clients/_header.html.erb
index de9015e66..3873a6100 100644
--- a/web/app/views/clients/_header.html.erb
+++ b/web/app/views/clients/_header.html.erb
@@ -11,12 +11,6 @@
<%= render "users/user_dropdown" %>
-
- <% if Rails.application.config.jam_tracks_available %>
-
- <% end %>
<% end %>
+
<%= include_gon %>
<%= csrf_meta_tags %>
diff --git a/web/app/views/layouts/client.html.erb b/web/app/views/layouts/client.html.erb
index adee2a9d7..518c775c6 100644
--- a/web/app/views/layouts/client.html.erb
+++ b/web/app/views/layouts/client.html.erb
@@ -2,6 +2,7 @@
<%= full_title(yield(:title)) %>
+
@@ -25,6 +26,7 @@
<%= include_gon %>
<%= javascript_include_tag "application" %>
<%= csrf_meta_tags %>
+
<% if content_for?(:social_meta) %>
<%= yield(:social_meta) %>
<% else %>
diff --git a/web/app/views/layouts/corporate.html.erb b/web/app/views/layouts/corporate.html.erb
index b852f8341..0e7e8fb1a 100644
--- a/web/app/views/layouts/corporate.html.erb
+++ b/web/app/views/layouts/corporate.html.erb
@@ -23,6 +23,7 @@
<%= include_gon(:init => true) %>
<%= javascript_include_tag "corp/corporate" %>
<%= csrf_meta_tags %>
+ ">
<% if content_for?(:social_meta) %>
<%= yield(:social_meta) %>
<% else %>
diff --git a/web/app/views/layouts/landing.html.erb b/web/app/views/layouts/landing.html.erb
index df95fab81..dc4482b47 100644
--- a/web/app/views/layouts/landing.html.erb
+++ b/web/app/views/layouts/landing.html.erb
@@ -25,6 +25,7 @@
<% end %>
<%= include_gon(:init => true) %>
<%= csrf_meta_tags %>
+
<% if content_for?(:social_meta) %>
<%= yield(:social_meta) %>
<% else %>
diff --git a/web/app/views/layouts/minimal.html.erb b/web/app/views/layouts/minimal.html.erb
index f29412ae4..7c021b2b0 100644
--- a/web/app/views/layouts/minimal.html.erb
+++ b/web/app/views/layouts/minimal.html.erb
@@ -25,6 +25,7 @@
<% end %>
<%= include_gon(:init => true) %>
<%= csrf_meta_tags %>
+
<% if content_for?(:social_meta) %>
<%= yield(:social_meta) %>
<% else %>
diff --git a/web/app/views/layouts/web.html.erb b/web/app/views/layouts/web.html.erb
index 8c13c4a5d..6896b1aac 100644
--- a/web/app/views/layouts/web.html.erb
+++ b/web/app/views/layouts/web.html.erb
@@ -25,6 +25,7 @@
<% end %>
<%= include_gon(:init => true) %>
<%= csrf_meta_tags %>
+
<% if content_for?(:social_meta) %>
<%= yield(:social_meta) %>
<% else %>
diff --git a/web/app/views/music_sessions/session_info.html.haml b/web/app/views/music_sessions/session_info.html.haml
index 7c7e359d7..e49bc10f7 100644
--- a/web/app/views/music_sessions/session_info.html.haml
+++ b/web/app/views/music_sessions/session_info.html.haml
@@ -1,4 +1,19 @@
- provide(:page_name, 'session_info')
+- provide(:description, description_for_music_session(@music_session))
+
+- content_for :social_meta do
+ %meta {property: "fb:app_id", content: Rails.application.config.facebook_app_id}
+ %meta {property: "og:title", content: title_for_music_session(@music_session)}
+ %meta {property: "og:url", content: request.original_url}
+ %meta {property: "og:description", content: description_for_music_session(@music_session)}
+ %meta {property: "og:image", content: facebook_image_for_music_session(@music_session)}
+ %meta {property: "og:image:width", content: facebook_image_size_for_music_session(@music_session)}
+ %meta {property: "og:image:height", content: facebook_image_size_for_music_session(@music_session)}
+ %meta {property: "og:type", content: 'website'}
+ %meta {property: "twitter:card", content: 'summary'}
+ %meta {property: "twitter:site", content: '@jamkazam'}
+ %meta {property: "twitter:title", content: title_for_music_session(@music_session)}
+ %meta {property: "twitter:description", content: description_for_music_session(@music_session)}
- unless @music_session.nil?
- provide(:title, @music_session.name)
diff --git a/web/app/views/music_sessions/show.html.erb b/web/app/views/music_sessions/show.html.erb
index 8256193fe..c0ed420ee 100644
--- a/web/app/views/music_sessions/show.html.erb
+++ b/web/app/views/music_sessions/show.html.erb
@@ -1,4 +1,5 @@
<% provide(:title, "#{@music_session.description}") %>
+<% provide(:description, description_for_music_session(@music_session)) %>
<% content_for :social_meta do %>
diff --git a/web/app/views/recordings/show.html.erb b/web/app/views/recordings/show.html.erb
index 5bdda20f9..34eccd73e 100644
--- a/web/app/views/recordings/show.html.erb
+++ b/web/app/views/recordings/show.html.erb
@@ -1,4 +1,5 @@
<% provide(:title, "#{@claimed_recording.name}") %>
+<% provide(:description, description_for_claimed_recording(@claimed_recording)) %>
<% content_for :social_meta do %>
diff --git a/web/app/views/sessions/oauth_complete.erb b/web/app/views/sessions/oauth_complete.erb
index a6c22d587..e8c16289b 100644
--- a/web/app/views/sessions/oauth_complete.erb
+++ b/web/app/views/sessions/oauth_complete.erb
@@ -1,3 +1,5 @@
+<% provide(:description, 'Finished authorization') %>
+
diff --git a/web/app/views/sessions/signin.html.haml b/web/app/views/sessions/signin.html.haml
index e20fa396e..a326d9148 100644
--- a/web/app/views/sessions/signin.html.haml
+++ b/web/app/views/sessions/signin.html.haml
@@ -1,5 +1,6 @@
- provide(:title, 'Sign in')
- provide(:page_name, 'signin')
+- provide(:description, 'Sign in to your JamKazam account to connect and play with other musicians.')
.signin-overlay.signin-page
.content-head
diff --git a/web/app/views/sessions/twitter_oauth_failure.html.erb b/web/app/views/sessions/twitter_oauth_failure.html.erb
index 9ec6255b6..2eb8f45e6 100644
--- a/web/app/views/sessions/twitter_oauth_failure.html.erb
+++ b/web/app/views/sessions/twitter_oauth_failure.html.erb
@@ -1,3 +1,5 @@
+<% provide(:description, 'Unable to authorize twitter') %>
+
Unable to authorize application. Reasons:
diff --git a/web/app/views/shared/_google_login.html.slim b/web/app/views/shared/_google_login.html.slim
index a190c6366..d248a4c80 100644
--- a/web/app/views/shared/_google_login.html.slim
+++ b/web/app/views/shared/_google_login.html.slim
@@ -1,26 +1,3 @@
--content_for :extra_js do
- javascript:
- // Check for google authorization using AJAX and show/hide the
- // google login button / "signed in" label as appropriate:
- $(window).on('focus', function() {
- $.ajax({
- type: "GET",
- dataType: "json",
- url: "/auth/has_google_auth"
- }).success(function(data) {
- if(data.has_google_auth) {
- $("input.google_login_button").addClass("hidden")
- $("span.signed_in_to_google").removeClass("hidden")
- if (window._oauth_win) {
- window._oauth_win.close()
- }
- } else {
- $("span.signed_in_to_google").addClass("hidden")
- $("input.google_login_button").removeClass("hidden")
- }
- })
- });
-
-google_auth = (current_user.nil?) ? nil : !!JamRuby::UserAuthorization.google_auth(current_user).first
span.signed_in_to_google class=((!google_auth) ? "hidden" : "") ="(Signed in)"
-input.google_login_button class=((google_auth) ? "hidden" : "") type='image' onclick='window._oauth_win = window.open("/auth/google_login", "_blank", "height=500,width=500,menubar=no,resizable=no,status=no");' src="/assets/google_signin.png" height="30px"
+input.google_login_button class=((google_auth) ? "hidden" : "") type='image' src="/assets/google_signin.png" height="30px"
diff --git a/web/app/views/spikes/jam_track_preview.html.slim b/web/app/views/spikes/jam_track_preview.html.slim
index 3ea46c7d3..c5c2106c4 100644
--- a/web/app/views/spikes/jam_track_preview.html.slim
+++ b/web/app/views/spikes/jam_track_preview.html.slim
@@ -24,7 +24,7 @@ javascript:
$players.append($element);
- new JK.JamTrackPreview(data.app, $element, jamTrack, track, {master_shows_duration: true})
+ new JK.JamTrackPreview(data.app, $element, jamTrack, track, {master_shows_duration: true,color:'black'})
})
})
.fail(function() {
diff --git a/web/app/views/users/_downloads.html.slim b/web/app/views/users/_downloads.html.slim
index 9323df562..76f9c33d7 100644
--- a/web/app/views/users/_downloads.html.slim
+++ b/web/app/views/users/_downloads.html.slim
@@ -1,8 +1,8 @@
// used by congrats_musician, and downloads
-- provide(:page_name, 'downloads')
+- provide(:page_name, "downloads #{@page_context}")
- provide(:title, 'Download')
-.w100
+.w100.download-container
.download-app
.spinner-large
@@ -15,11 +15,11 @@
p You need the JamKazam application to:
ul
+ li Play and control your JamTracks multi-track recordings
li Play music with others in real time on the JamKazam platform
li Make audio recordings and share them via Facebook or URL
li Make video recordings and share them via YouTube or URL
li Live broadcast your sessions to family, friends, and fans
- li Have full control over your JamTracks multi-track recordings
p.click-to-download Click the button below to download the JamKazam application installer.
.downloads-blurb
@@ -50,7 +50,7 @@
.video-container
iframe src="//www.youtube.com/embed/gAJAIHMyois" frameborder="0" allowfullscreen
- a.go-jamtrack-shopping href="/client#/jamtrack" rel="external"
+ a.go-jamtrack-shopping href="/client#/jamtrackBrowse" rel="external"
| Shop for free
br
| JamTrack now!
diff --git a/web/app/views/users/_user_dropdown.html.erb b/web/app/views/users/_user_dropdown.html.erb
index dd694bdb8..5bcd80778 100644
--- a/web/app/views/users/_user_dropdown.html.erb
+++ b/web/app/views/users/_user_dropdown.html.erb
@@ -1,54 +1,69 @@
-
-
-
-
+
+<% if Rails.application.config.jam_tracks_available %>
+
+<% end %>
+
+
<% if signed_in? %>
-
-
-
-
- <%= link_to "Account Home", '/client#/account' %>
- <%= link_to "Identity", '/client#/account/identity' %>
- <%= link_to "Profile", '/client#/account/profile' %>
-
-
- <% if current_user && current_user.musician? %>
- <% class_val = current_user.affiliate_partner.present? ? 'audio' : 'audio account-menu-group' %>
- <%= link_to "Audio Gear", '/client#/account/audio' %>
- <% end %>
- <% if current_user && current_user.affiliate_partner.present? %>
-
- <% end %>
- <% if current_user && current_user.musician? %>
- <%= link_to "Band Setup", '/client#/band/setup/new' %>
- <% end %>
-
-
-
- <%= link_to "Download App", downloads_path, :rel => "external" %>
- <% if @nativeClient %>
- <%= link_to "Test Network", '#' %>
- <% end %>
-
- <%= link_to "Get Help", 'https://jamkazam.desk.com/', :rel => "external" %>
- <%= link_to "Sign Out", signout_path, method: "delete" %>
-
+
+
+
<% else %>
<% end %>
+
+
+
+
+
+
+
+ <%= link_to "Account Home", '/client#/account' %>
+ <%= link_to "Identity", '/client#/account/identity' %>
+ <%= link_to "Profile", '/client#/account/profile' %>
+
+
+ <% if current_user && current_user.musician? %>
+ <% class_val = current_user.affiliate_partner.present? ? 'audio' : 'audio account-menu-group' %>
+ <%= link_to "Audio Gear", '/client#/account/audio' %>
+ <% if (Rails.application.config.video_available && Rails.application.config.video_available!="none") || (current_user && current_user.admin) %>
+ <%= link_to "Video Gear", '/client#/account/video' %>
+ <% end %>
+ <% end %>
+ <% if current_user && current_user.affiliate_partner.present? %>
+
+ <% end %>
+ <% if current_user && current_user.musician? %>
+ <%= link_to "Band Setup", '/client#/band/setup/new' %>
+ <% end %>
+
+
+
+ <%= link_to "Download App", downloads_path, :rel => "external" %>
+ <% if @nativeClient %>
+ <%= link_to "Test Network", '#' %>
+ <% end %>
+
+ <%= link_to "Get Help", 'https://jamkazam.desk.com/', :rel => "external" %>
+ <%= link_to "Sign Out", signout_path, method: "delete" %>
+
+
+
diff --git a/web/app/views/users/already_signed_up.html.erb b/web/app/views/users/already_signed_up.html.erb
index e0cf7635a..cff7f1479 100644
--- a/web/app/views/users/already_signed_up.html.erb
+++ b/web/app/views/users/already_signed_up.html.erb
@@ -1,4 +1,5 @@
<% provide(:title, 'Already Signed Up') %>
+<% provide(:description, 'You have already signed up with JamKazam') %>
diff --git a/web/app/views/users/congratulations_fan.html.erb b/web/app/views/users/congratulations_fan.html.erb
index 9fb302af9..77a714e10 100644
--- a/web/app/views/users/congratulations_fan.html.erb
+++ b/web/app/views/users/congratulations_fan.html.erb
@@ -1,5 +1,5 @@
<% provide(:title, 'Congratulations') %>
-
+<% provide(:description, 'Congratulations on becoming a new JamKazam member!') %>
<%= render "users/downloads" %>
JamKazam Internet Latency Test: Select your Internet Service Provider
Java must be installed to run this tool. Please select logo corresponding to your ISP, or if you're not sure, choose "Other". OSX not currently supported.
diff --git a/web/app/views/users/new.html.erb b/web/app/views/users/new.html.erb
index 357155e7b..83a2c5c0c 100644
--- a/web/app/views/users/new.html.erb
+++ b/web/app/views/users/new.html.erb
@@ -1,5 +1,6 @@
<% provide(:page_name, 'register') %>
<% provide(:title, 'Register') %>
+<% provide(:description, 'Sign up for your JamKazam account to play music with others online in real time and network with musicians.') %>
diff --git a/web/app/views/users/request_reset_password.erb b/web/app/views/users/request_reset_password.erb
index a9b049d37..8051bf627 100644
--- a/web/app/views/users/request_reset_password.erb
+++ b/web/app/views/users/request_reset_password.erb
@@ -1,5 +1,6 @@
<% provide(:title, "Reset password") %>
<% provide(:page_name, "request-reset-password") %>
+<% provide(:description, 'Reset your password') %>
diff --git a/web/app/views/users/reset_password_complete.erb b/web/app/views/users/reset_password_complete.erb
index d2eb99320..b69bc21fd 100644
--- a/web/app/views/users/reset_password_complete.erb
+++ b/web/app/views/users/reset_password_complete.erb
@@ -1,4 +1,5 @@
<% provide(:title, "Reset password") %>
+<% provide(:description, 'You have reset your password successfully') %>
diff --git a/web/app/views/users/reset_password_token.erb b/web/app/views/users/reset_password_token.erb
index b6a0376a4..21b02768b 100644
--- a/web/app/views/users/reset_password_token.erb
+++ b/web/app/views/users/reset_password_token.erb
@@ -1,4 +1,5 @@
-<% provide(:title, "Reset password") %>
+<% provide(:title, "Reset password") %>
+<% provide(:description, 'Enter your new password') %>
diff --git a/web/app/views/users/sent_reset_password.erb b/web/app/views/users/sent_reset_password.erb
index ce773e174..f3cbc1af6 100644
--- a/web/app/views/users/sent_reset_password.erb
+++ b/web/app/views/users/sent_reset_password.erb
@@ -1,4 +1,5 @@
-<% provide(:title, "Reset password") %>
+<% provide(:title, "Reset password") %>
+<% provide(:description, 'You have reset your password. Check your email') %>
diff --git a/web/app/views/users/signup_confirm.html.erb b/web/app/views/users/signup_confirm.html.erb
index 7fdb14f82..df0915155 100644
--- a/web/app/views/users/signup_confirm.html.erb
+++ b/web/app/views/users/signup_confirm.html.erb
@@ -1,4 +1,5 @@
<% provide(:title, 'Signup Confirmation') %>
+<% provide(:description, 'Confirm your JamKazam account') %>
<% if @user.nil? %>
Signup Already Confirmed
diff --git a/web/config/application.rb b/web/config/application.rb
index 173220b55..63dd5400c 100644
--- a/web/config/application.rb
+++ b/web/config/application.rb
@@ -126,7 +126,8 @@ if defined?(Bundler)
config.external_port = ENV['EXTERNAL_PORT'] || 3000
config.external_protocol = ENV['EXTERNAL_PROTOCOL'] || 'http://'
config.external_root_url = "#{config.external_protocol}#{config.external_hostname}#{(config.external_port == 80 || config.external_port == 443) ? '' : ':' + config.external_port.to_s}"
-
+ config.admin_port = ENV['ADMIN_PORT'] || 3333
+ config.admin_root_url = "#{config.external_protocol}#{config.external_hostname}#{(config.admin_port == 80 || config.admin_port == 443) ? '' : ':' + config.admin_port.to_s}"
# set this to false if you want to disable signups (lock down public user creation)
config.signup_enabled = true
@@ -215,19 +216,20 @@ if defined?(Bundler)
config.jamtracks_dir = ENV['JAMTRACKS_DIR'] || File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "..", "jamtracks"))
config.jmep_dir = ENV['JMEP_DIR'] || File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "..", "jmep"))
- # amount of time before we think packaging job is broken
- config.signing_job_run_max_time = 60 # 1 minute
# amount of time before we think the queue is stuck
config.signing_job_queue_max_time = 20 # 20 seconds
+ # amount of time to allow before giving up on a single step in packaging job
+ config.signing_step_max_time = 40; # 40 seconds
config.email_alerts_alias = 'alerts@jamkazam.com' # should be used for 'oh no' server down/service down sorts of emails
config.email_generic_from = 'nobody@jamkazam.com'
+ config.email_recurly_notice = 'recurly-alerts@jamkazam.com'
config.email_smtp_address = 'smtp.sendgrid.net'
config.email_smtp_port = 587
config.email_smtp_domain = 'www.jamkazam.com'
config.email_smtp_authentication = :plain
config.email_smtp_user_name = 'jamkazam'
- config.email_smtp_password = 'jamjamblueberryjam'
+ config.email_smtp_password = 'snorkeltoesniffyfarce1'
config.email_smtp_starttls_auto = true
config.facebook_app_id = ENV['FACEBOOK_APP_ID'] || '468555793186398'
@@ -324,5 +326,9 @@ if defined?(Bundler)
config.nominated_jam_track = 'jamtrack-pearljam-alive'
config.recurly_tax_estimate_jam_track_plan = 'jamtrack-acdc-backinblack'
+
+ config.minimal_curtain = false
+ config.video_available = "none"
+ config.alerts_api_enabled = true
end
end
diff --git a/web/config/environments/development.rb b/web/config/environments/development.rb
index 4485f6795..cc13d2955 100644
--- a/web/config/environments/development.rb
+++ b/web/config/environments/development.rb
@@ -90,4 +90,8 @@ SampleApp::Application.configure do
config.youtube_developer_key = "AI39si5bPqiNc5GQHscWJh9Wl1WTAr9aZqr_YncUvaR7Kz0rgPdBVWVubHZ94xZ3KLIBqtE9mu3VZe-UpMU80QxXoC66kBNp7A"
config.youtube_app_name = "JamKazamDev"
config.jam_tracks_available=true
+ config.minimal_curtain = true
+ config.video_available= ENV['VIDEO_AVAILABILITY'] || "none"
+ config.email_generic_from = 'nobody-dev@jamkazam.com'
+ config.email_alerts_alias = ENV['ALERT_EMAIL'] || 'alerts-dev@jamkazam.com'
end
diff --git a/web/config/environments/test.rb b/web/config/environments/test.rb
index 4b5c92b6f..565634690 100644
--- a/web/config/environments/test.rb
+++ b/web/config/environments/test.rb
@@ -20,6 +20,7 @@ SampleApp::Application.configure do
config.assets.compress = true # Compress precompiled assets
config.assets.compile = true # Refuse to compile assets on-the-fly
config.assets.digest = true
+ #config.assets.debug = true
# Show full error reports and disable caching
config.consider_all_requests_local = true
@@ -105,5 +106,6 @@ SampleApp::Application.configure do
config.recurly_subdomain = 'jamkazam-test'
config.log_level = :debug
config.jam_tracks_available = true
+ config.video_available = "full"
end
diff --git a/web/config/initializers/gon.rb b/web/config/initializers/gon.rb
index ed4f92a4f..9e222bf5b 100644
--- a/web/config/initializers/gon.rb
+++ b/web/config/initializers/gon.rb
@@ -12,4 +12,5 @@ Gon.global.influxdb_username = Rails.application.config.influxdb_unsafe_username
Gon.global.influxdb_password = Rails.application.config.influxdb_unsafe_password
Gon.global.recurly_public_api_key = Rails.application.config.recurly_public_api_key
Gon.global.one_free_jamtrack_per_user = Rails.application.config.one_free_jamtrack_per_user
+Gon.global.video_available = Rails.application.config.video_available
Gon.global.env = Rails.env
diff --git a/web/config/routes.rb b/web/config/routes.rb
index fe00765f3..0fcc2b9c9 100644
--- a/web/config/routes.rb
+++ b/web/config/routes.rb
@@ -216,6 +216,7 @@ SampleApp::Application.routes.draw do
# Jamtracks
match '/jamtracks/purchased' => 'api_jam_tracks#purchased', :via => :get, :as => 'api_jam_tracks_purchased'
+ match '/jamtracks/artists' => 'api_jam_tracks#artist_index', :via => :get, :as => 'api_jam_tracks_list_artists'
match '/jamtracks/:plan_code' => 'api_jam_tracks#show', :via => :get, :as => 'api_jam_tracks_show'
match '/jamtracks/band/:plan_code' => 'api_jam_tracks#show_with_artist_info', :via => :get, :as => 'api_jam_tracks_show_with_artist_info'
match '/jamtracks' => 'api_jam_tracks#index', :via => :get, :as => 'api_jam_tracks_list'
@@ -280,7 +281,7 @@ SampleApp::Application.routes.draw do
match '/recurly/place_order' => 'api_recurly#place_order', :via => :post
# sale info
- match '/sales' => 'api_sales#index', :via => :get
+ match '/payment_histories' => 'api_payment_histories#index', :via => :get
# login/logout
match '/auth_session' => 'api_users#auth_session_create', :via => :post
@@ -566,6 +567,9 @@ SampleApp::Application.routes.draw do
match '/recurly/webhook' => 'api_recurly_web_hook#on_hook', :via => :post
- end
+ match '/signup_hints' => 'api_signup_hints#create', :via => :post
+ match '/signup_hints/:id' => 'api_signup_hints#show', :via => :get, :as => :api_signup_hint_detail
+ match '/alerts' => 'api_alerts#create', :via => :post
+ end
end
diff --git a/web/config/sitemap.rb b/web/config/sitemap.rb
new file mode 100644
index 000000000..2c2518ce3
--- /dev/null
+++ b/web/config/sitemap.rb
@@ -0,0 +1,64 @@
+# Set the host name for URL creation
+SitemapGenerator::Sitemap.default_host = Rails.application.config.external_root_url
+
+SitemapGenerator::Sitemap.create do
+ # Put links creation logic here.
+ #
+ # The root path '/' and sitemap index file are added automatically for you.
+ # Links are added to the Sitemap in the order they are specified.
+ #
+ # Usage: add(path, options={})
+ # (default options are used if you don't specify)
+ #
+ # Defaults: :priority => 0.5, :changefreq => 'weekly',
+ # :lastmod => Time.now, :host => default_host
+ #
+ # Examples:
+ #
+ # Add '/articles'
+ #
+ # add articles_path, :priority => 0.7, :changefreq => 'daily'
+ #
+ # Add all articles:
+ #
+ # Article.find_each do |article|
+ # add article_path(article), :lastmod => article.updated_at
+ # end
+
+ add(signup_path, priority: 0.9)
+ add(signin_path, priority: 0.9)
+ add(downloads_path, priority: 0.9)
+ add(product_jamblaster_path, priority: 0.9)
+ add(product_platform_path, priority: 0.9)
+ add(product_jamtracks_path, priority: 0.9)
+ add(corp_about_path, priority: 0.9)
+
+ JamTrack.all.each do |jam_track|
+ shortened_plan_code = jam_track.plan_code["jamtrack-".length..-1]
+ add(individual_jamtrack_path(shortened_plan_code), priority:0.9)
+ add(individual_jamtrack_band_path(shortened_plan_code), priority:0.9)
+ end
+
+ Recording.popular_recordings.each do |recording|
+ add(recording_detail_path(recording.id), priority:0.8)
+ end
+
+ add(reset_password_path)
+ add(corp_news_path)
+ add(corp_media_center_path)
+ add(corp_overview_path)
+ add(corp_features_path)
+ add(corp_faqs_path)
+ add(corp_screenshots_path)
+ add(corp_photos_path)
+ add(corp_logos_path)
+ add(corp_testimonials_path)
+ add(corp_audio_path)
+ add(corp_videos_path)
+ add(corp_contact_path)
+ add(corp_privacy_path)
+ add(corp_terms_path)
+ add(corp_help_path)
+ add(corp_cookie_policy_path)
+
+end
diff --git a/web/lib/music_session_manager.rb b/web/lib/music_session_manager.rb
index ac10e6d20..792fe1200 100644
--- a/web/lib/music_session_manager.rb
+++ b/web/lib/music_session_manager.rb
@@ -124,7 +124,7 @@ class MusicSessionManager < BaseManager
def participant_delete(user, connection, active_music_session)
if connection.user.id != user.id
- raise PermissionError, "you do not own this connection"
+ raise JamPermissionError, "you do not own this connection"
end
recordingId = nil
diff --git a/web/lib/tasks/jam_tracks.rake b/web/lib/tasks/jam_tracks.rake
index dfdb0c9d8..ef15aee85 100644
--- a/web/lib/tasks/jam_tracks.rake
+++ b/web/lib/tasks/jam_tracks.rake
@@ -15,13 +15,22 @@ namespace :jam_tracks do
JamTrackImporter.synchronize_from_meta("audio/#{path}/meta.yml", skip_audio_upload:false)
end
- task sync_all: :environment do |task, args|
+ task resync_audio: :environment do |task, args|
+ path = ENV['TRACK_PATH']
+ if !path
+ puts "TRACK_PATH must be set to something like AD DC/Back in Black"
+ exit(1)
+ end
+
+ JamTrackImporter.synchronize_from_meta("audio/#{path}/meta.yml", resync_audio:true, skip_audio_upload:false)
+ end
+
+ task sync_all: :environment do |task, args|
JamTrackImporter.synchronize_all(skip_audio_upload:false)
end
task sync_all_dev: :environment do |task, args|
-
JamTrackImporter.synchronize_all(skip_audio_upload:true)
end
@@ -51,7 +60,6 @@ namespace :jam_tracks do
end
end
-
task sync_duration_all: :environment do |task, args|
importer = JamTrackImporter.synchronize_durations
end
diff --git a/web/lib/user_manager.rb b/web/lib/user_manager.rb
index 75ce77b07..b94c1c1c8 100644
--- a/web/lib/user_manager.rb
+++ b/web/lib/user_manager.rb
@@ -36,7 +36,7 @@ class UserManager < BaseManager
# check if we have disabled open signup for this site. open == invited users can still get in
if !SampleApp::Application.config.signup_enabled && invited_user.nil?
- raise PermissionError, "Signups are currently disabled"
+ raise JamPermissionError, "Signups are currently disabled"
end
loc = GeoIpLocations.lookup(remote_ip)
diff --git a/web/public/robots.txt b/web/public/robots.txt
index 085187fa5..64907a2ac 100644
--- a/web/public/robots.txt
+++ b/web/public/robots.txt
@@ -3,3 +3,4 @@
# To ban all spiders from the entire site uncomment the next two lines:
# User-Agent: *
# Disallow: /
+Sitemap: http://www.jamkazam.com/sitemap.xml.gz
\ No newline at end of file
diff --git a/web/spec/controllers/api_sales_controller_spec.rb b/web/spec/controllers/api_payment_histories_controller_spec.rb
similarity index 65%
rename from web/spec/controllers/api_sales_controller_spec.rb
rename to web/spec/controllers/api_payment_histories_controller_spec.rb
index e1e39bf32..92c5417cb 100644
--- a/web/spec/controllers/api_sales_controller_spec.rb
+++ b/web/spec/controllers/api_payment_histories_controller_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe ApiSalesController do
+describe ApiPaymentHistoriesController do
render_views
let(:user) {FactoryGirl.create(:user)}
@@ -19,6 +19,7 @@ describe ApiSalesController do
body = JSON.parse(response.body)
body['next_page'].should be_nil
body['entries'].should eq([])
+ body['total_entries'].should eq(0)
end
it "one item" do
@@ -36,21 +37,28 @@ describe ApiSalesController do
entries = body['entries']
entries.should have(1).items
sale_entry = entries[0]
- sale_entry["line_items"].should have(1).items
- sale_entry["recurly_transactions"].should have(0).items
+ sale_entry['recurly_total_in_cents'].should eq(sale.recurly_total_in_cents)
+ sale_json = sale_entry['sale']
+ sale_json.should_not be_nil
+ sale_json["line_items"].should have(1).items
- transaction = FactoryGirl.create(:recurly_transaction_web_hook, invoice_id: sale.recurly_invoice_id, transaction_type: RecurlyTransactionWebHook::VOID)
+ transaction = FactoryGirl.create(:recurly_transaction_web_hook, invoice_id: sale.recurly_invoice_id, transaction_type: RecurlyTransactionWebHook::VOID, user: user, transaction_at: 1.minute.from_now)
get :index, { :format => 'json'}
response.should be_success
body = JSON.parse(response.body)
body['next_page'].should be_nil
entries = body['entries']
- entries.should have(1).items
- sale_entry = entries[0]
- sale_entry["line_items"].should have(1).items
- sale_entry["recurly_transactions"].should have(1).items
+ entries.should have(2).items
+ void_entry = entries[0]
+ void = void_entry['transaction']
+ void.should_not be_nil
+ void['amount_in_cents'].should eq(199)
+ sale_entry = entries[1]
+ sale_json = sale_entry['sale']
+ sale_json.should_not be_nil
+ sale_json["line_items"].should have(1).items
end
end
diff --git a/web/spec/controllers/api_signup_hint_spec.rb b/web/spec/controllers/api_signup_hint_spec.rb
new file mode 100644
index 000000000..ac9a4e323
--- /dev/null
+++ b/web/spec/controllers/api_signup_hint_spec.rb
@@ -0,0 +1,40 @@
+require 'spec_helper'
+
+describe ApiSignupHintsController, :type=>:controller do
+ render_views
+
+ let(:user) {AnonymousUser.new(SecureRandom.uuid)}
+
+ before(:each) do
+ SignupHint.delete_all
+ controller.anonymous_user = user
+ end
+
+ it "creates" do
+ post :create, {format: :json}
+
+ response.should be_success
+ body = JSON.parse(response.body)
+ body["id"].should_not be_nil
+
+ SignupHint.count.should eq(1)
+ end
+
+ it "updates" do
+ post :create, {format: :json, redirect_location: 'hi'}
+
+ response.should be_success
+ body = JSON.parse(response.body)
+ body["redirect_location"].should eq('hi')
+ body["want_jamblaster"].should eq(false)
+
+ post :create, {format: :json, redirect_location: 'bye', want_jamblaster: true}
+
+ response.should be_success
+ body = JSON.parse(response.body)
+ body["redirect_location"].should eq('bye')
+ body["want_jamblaster"].should eq(true)
+
+ SignupHint.count.should eq(1)
+ end
+end
diff --git a/web/spec/features/checkout_spec.rb b/web/spec/features/checkout_spec.rb
index 18017ae46..53163d0aa 100644
--- a/web/spec/features/checkout_spec.rb
+++ b/web/spec/features/checkout_spec.rb
@@ -548,6 +548,10 @@ describe "Checkout", :js => true, :type => :feature, :capybara_feature => true d
# and now we should see confirmation, and a notice that we are in a normal browser
find('.thanks-detail.jam-tracks-in-browser')
+ # find the 'go download jamkazam button' that shows if your first_download_client_at is null
+ find('.thanks-detail .download-jamkazam-wrapper').trigger(:click)
+ find('.download-jamkazam', text: 'Click Here to Get the Free JamKazam Application')
+
acdc = jamtrack_acdc_backinblack.right_for_user(user)
acdc.redeemed.should be_false
@@ -602,18 +606,24 @@ describe "Checkout", :js => true, :type => :feature, :capybara_feature => true d
describe "Complete Checkout Flow" do
it "for anonymous user" do
- visit "/client#/jamtrack"
+ visit "/client#/jamtrackBrowse"
find('h1', text: 'jamtracks')
#find('a', text: 'What is a JamTrack?')
find("a.jamtrack-add-cart[data-jamtrack-id=\"#{jamtrack_acdc_backinblack.id}\"]").trigger(:click)
find('h1', text: 'shopping cart')
find('.cart-item-caption', text: "JamTrack: #{jamtrack_acdc_backinblack.name}")
- find('.cart-item-price', text: "$ #{jamtrack_acdc_backinblack.price}")
+ find('.cart-item-price', text: "$ #{0.00}") # 1st one is free!
+ find('.shopping-sub-total', text:"Subtotal:$ 0.00")
# attempt to checkout
find('a.button-orange', text: 'PROCEED TO CHECKOUT').trigger(:click)
+ shopping_carts = ShoppingCart.all
+ shopping_carts.count.should eq(1)
+ shopping_cart = shopping_carts[0]
+ shopping_cart.anonymous_user_id.should_not be_nil
+ shopping_cart.user_id.should be_nil
# we should now be on checkoutSignin
find('h3', text: 'ALREADY A MEMBER OF THE JAMKAZAM COMMUNITY?')
@@ -650,13 +660,25 @@ describe "Checkout", :js => true, :type => :feature, :capybara_feature => true d
find('.order-items-value.taxes', text:'$0.00')
find('.order-items-value.grand-total', text:'$0.00')
+
+ guy = User.find_by_email('guy@jamkazam.com')
+
+ # verify that the shopping cart has user_id info updated
+ shopping_cart.reload
+ shopping_cart.anonymous_user_id.should be_nil
+ shopping_cart.user.should eq(guy)
+
+ # also verify that there is still only one shopping cart, implying we deleted the anonymous user's shopping cart
+ shopping_carts = ShoppingCart.all
+ shopping_carts.count.should eq(1)
+
# click the ORDER button
find('.place-order-center a.button-orange.place-order').trigger(:click)
# and now we should see confirmation, and a notice that we are in a normal browser
find('.thanks-detail.jam-tracks-in-browser')
- guy = User.find_by_email('guy@jamkazam.com')
+ guy.reload
jam_track_right = jamtrack_acdc_backinblack.right_for_user(guy)
# make sure it appears the user actually bought the jamtrack!
jam_track_right.should_not be_nil
@@ -679,19 +701,20 @@ describe "Checkout", :js => true, :type => :feature, :capybara_feature => true d
# now, go back to checkout flow again, and make sure we are told there are no free jam tracks
- visit "/client#/jamtrack"
+ visit "/client#/jamtrackBrowse"
find("a.jamtrack-add-cart[data-jamtrack-id=\"#{jamtrack_pearljam_evenflow.id}\"]").trigger(:click)
find('h1', text: 'shopping cart')
find('.cart-item-caption', text: "JamTrack: #{jamtrack_pearljam_evenflow.name}")
find('.cart-item-price', text: "$ #{jamtrack_pearljam_evenflow.price}")
+ find('.shopping-sub-total', text:"Subtotal:$ #{jamtrack_pearljam_evenflow.price}")
# attempt to checkout
find('a.button-orange', text: 'PROCEED TO CHECKOUT').trigger(:click)
# should be taken straight to order page
- # now see order page, and everything should appear free
+ # now see order page, and everything should no longer appear free
find('p.order-prompt')
find('.order-items-value.order-total', text:'$1.99')
find('.order-items-value.shipping-handling', text:'$0.00')
@@ -730,14 +753,15 @@ describe "Checkout", :js => true, :type => :feature, :capybara_feature => true d
end
it "for existing user" do
- fast_signin(user, "/client#/jamtrack")
+ fast_signin(user, "/client#/jamtrackBrowse")
find('h1', text: 'jamtracks')
#find('a', text: 'What is a JamTrack?')
find("a.jamtrack-add-cart[data-jamtrack-id=\"#{jamtrack_acdc_backinblack.id}\"]").trigger(:click)
find('h1', text: 'shopping cart')
find('.cart-item-caption', text: "JamTrack: #{jamtrack_acdc_backinblack.name}")
- find('.cart-item-price', text: "$ #{jamtrack_acdc_backinblack.price}")
+ find('.cart-item-price', text: "$ #{0.00}") # 1st one is free!
+ find('.shopping-sub-total', text:"Subtotal:$ 0.00")
# attempt to checkout
find('a.button-orange', text: 'PROCEED TO CHECKOUT').trigger(:click)
@@ -781,5 +805,100 @@ describe "Checkout", :js => true, :type => :feature, :capybara_feature => true d
jam_track_right.redeemed.should be_true
user.has_redeemable_jamtrack.should be_false
end
+
+ it "for redeemable user that starts shopping anonymously" do
+ user.has_redeemable_jamtrack = true
+ user.save!
+
+ # the point of this is to also prove that the free jamtrack does not carry over to the existing user, once they log in
+ visit "/client#/jamtrackBrowse"
+ find('h1', text: 'jamtracks')
+ #find('a', text: 'What is a JamTrack?')
+
+ find("a.jamtrack-add-cart[data-jamtrack-id=\"#{jamtrack_acdc_backinblack.id}\"]").trigger(:click)
+ find('h1', text: 'shopping cart')
+ find('.cart-item-caption', text: "JamTrack: #{jamtrack_acdc_backinblack.name}")
+ find('.cart-item-price', text: "$ #{0.00}") # 1st one is free!
+ find('.shopping-sub-total', text:"Subtotal:$ 0.00")
+
+ # attempt to checkout
+ find('a.button-orange', text: 'PROCEED TO CHECKOUT').trigger(:click)
+
+ shopping_carts = ShoppingCart.all
+ shopping_carts.count.should eq(1)
+ shopping_cart = shopping_carts[0]
+ shopping_cart.anonymous_user_id.should_not be_nil
+ shopping_cart.user_id.should be_nil
+
+ # we should now be on checkoutSignin
+ find('h3', text: 'ALREADY A MEMBER OF THE JAMKAZAM COMMUNITY?')
+ verify_nav(1)
+
+ # try a bogus user/pass first
+ fill_in "email", with: user.email
+ fill_in "password", with: user.password
+ find('.signin-submit').trigger(:click)
+
+ # this should take us to the payment screen
+ find('p.payment-prompt')
+
+ # fill out all billing info and account info
+ fill_in 'billing-first-name', with: 'Seth'
+ fill_in 'billing-last-name', with: 'Call'
+ fill_in 'billing-address1', with: '10704 Buckthorn Drive'
+ fill_in 'billing-city', with: 'Austin'
+ fill_in 'billing-state', with: 'Texas'
+ fill_in 'billing-zip', with: '78759'
+ fill_in 'card-number', with: '4111111111111111'
+ fill_in 'card-verify', with: '012'
+
+ # try to submit, and see order page
+ find('#payment-info-next').trigger(:click)
+
+ # now see order page, and everything should appear free
+ find('p.order-prompt')
+ find('.order-items-value.order-total', text:'$0.00')
+ find('.order-items-value.shipping-handling', text:'$0.00')
+ find('.order-items-value.sub-total', text:'$0.00')
+ find('.order-items-value.taxes', text:'$0.00')
+ find('.order-items-value.grand-total', text:'$0.00')
+
+ user.reload
+
+ # verify that the shopping cart has user_id info updated
+ shopping_carts = ShoppingCart.all
+ shopping_carts.count.should eq(1)
+ shopping_cart = shopping_carts[0]
+
+ shopping_cart.anonymous_user_id.should be_nil
+ shopping_cart.user.should eq(user)
+
+
+ # click the ORDER button
+ find('.place-order-center a.button-orange.place-order').trigger(:click)
+
+ # and now we should see confirmation, and a notice that we are in a normal browser
+ find('.thanks-detail.jam-tracks-in-browser')
+
+ user.reload
+ jam_track_right = jamtrack_acdc_backinblack.right_for_user(user)
+ # make sure it appears the user actually bought the jamtrack!
+ jam_track_right.should_not be_nil
+ jam_track_right.redeemed.should be_true
+ user.has_redeemable_jamtrack.should be_false
+
+ # verify sales data
+ user.sales.length.should eq(1)
+ sale = user.sales.first
+ sale.sale_line_items.length.should eq(1)
+ acdc_sale = SaleLineItem.find_by_recurly_adjustment_uuid(jam_track_right.recurly_adjustment_uuid)
+ acdc_sale.recurly_plan_code.should eq(jamtrack_acdc_backinblack.plan_code)
+ acdc_sale.product_type.should eq('JamTrack')
+ acdc_sale.product_id.should eq(jamtrack_acdc_backinblack.id)
+ acdc_sale.quantity.should eq(1)
+ acdc_sale.free.should eq(1)
+ acdc_sale.unit_price.should eq(1.99)
+ acdc_sale.sale.should eq(sale)
+ end
end
end
diff --git a/web/spec/features/gear_wizard_spec.rb b/web/spec/features/gear_wizard_spec.rb
index 6edc6bd59..fc9b401b6 100644
--- a/web/spec/features/gear_wizard_spec.rb
+++ b/web/spec/features/gear_wizard_spec.rb
@@ -1,21 +1,82 @@
require 'spec_helper'
-describe "Gear Wizard", :js => true, :type => :feature, :capybara_feature => true, :slow => true do
+describe "Gear Wizard", :js => true, :type => :feature, :capybara_feature => true do
subject { page }
let(:user) { FactoryGirl.create(:user) }
before(:each) do
+ emulate_client
LatencyTester.delete_all
-
end
- it "success path" do
+ before(:all) do
+ @old_video_available=Rails.application.config.video_available
+ end
+
+ after(:all) do
+ Rails.application.config.video_available=@old_video_available
+ end
+
+ def walk_wizard(has_video=false)
FactoryGirl.create(:latency_tester)
fast_signin user, '/client#/account/audio'
find("div.account-audio a[data-purpose='add-profile']").trigger(:click)
- walk_gear_wizard
+
+ # step 1 - intro
+ find('.btn-next').trigger(:click)
+
+ # step 2 - select gear
+ find('.ftue-step-title', text: 'Select & Test Audio Gear')
+ should_not have_selector('.resync-status') # when you enter this step,
+ jk_select('Built-in', 'div[layout-wizard-step="1"] select.select-audio-input-device')
+ find('.btn-next.button-orange:not(.disabled)').trigger(:click)
+
+ # step 3 - configure tracks
+ find('.ftue-step-title', text: 'Configure Tracks')
+
+ # drag one input over to tracks area http://rubydoc.info/github/jnicklas/capybara/master/Capybara/Node/Element#drag_to-instance_method
+ input = first('.ftue-input')
+ track_slot = first('.track-target')
+ input.drag_to(track_slot)
+
+ find('.btn-next.button-orange:not(.disabled)').trigger(:click)
+
+ # step 4 - configure voice chat
+ find('.ftue-step-title', text: 'Configure Voice Chat')
+ find('.btn-next.button-orange:not(.disabled)').trigger(:click)
+
+ # step 5 - configure direct monitoring
+ find('.ftue-step-title', text: 'Turn Off Direct Monitoring')
+
+ # make a diversion into the 'adjust gear speed' dialog
+ find('.adjust-settings-direct-monitor').trigger(:click)
+ # should see dialog header
+ find('h1', text: 'Adjust Gear Speed')
+ # change to 'moderate' speed
+ find('.speed-option.setting-fair ins').trigger(:click)
+ # should cause a spinner/io test, and then save button comes up as clickable
+ find('.btnSave.button-orange:not(.disabled)').trigger(:click)
+
+ find('.btn-next.button-orange:not(.disabled)').trigger(:click)
+
+ # Optional step 6 - configure video
+ if(has_video)
+ #find('.ftue-step-title', text: 'Select Video Gear')
+ find('.btn-next.button-orange:not(.disabled)').trigger(:click)
+ end
+
+ # step 6 - Test Router & Network
+ find('.ftue-step-title', text: 'Test Router & Network')
+ find('.button-orange.start-network-test').trigger(:click)
+ find('.user-btn', text: 'RUN NETWORK TEST ANYWAY').trigger(:click)
+ find('.button-orange.start-network-test')
+ find('.btn-next.button-orange:not(.disabled)').trigger(:click)
+
+ # step 7 - Success
+ find('.ftue-step-title', text: 'Success!')
+ find('.btn-close.button-orange').trigger(:click)
# should see prompt afterwards about joining a test session
find('h1', text: 'join test session')
@@ -24,5 +85,15 @@ describe "Gear Wizard", :js => true, :type => :feature, :capybara_feature => tru
# and should now be in session
find('h2', text: 'my tracks')
end
+
+ it "success path" do
+ Rails.application.config.video_available="none"
+ walk_wizard(false)
+ end
+
+ it "success path with video" do
+ Rails.application.config.video_available="mvp"
+ walk_wizard(true)
+ end
end
diff --git a/web/spec/features/individual_jamtrack_band_spec.rb b/web/spec/features/individual_jamtrack_band_spec.rb
index b72e10982..9fa47b3b2 100644
--- a/web/spec/features/individual_jamtrack_band_spec.rb
+++ b/web/spec/features/individual_jamtrack_band_spec.rb
@@ -78,7 +78,7 @@ describe "Individual JamTrack Band", :js => true, :type => :feature, :capybara_f
find('.jam-track-preview-holder[data-id="' + track.id + '"] .instrument-name', text:track.instrument.description)
end
end
- find('a.white-bordered-button')['href'].should eq("/client?artist=#{jamtrack_acdc_backinblack.original_artist}#/jamtrack")
+ find('a.white-bordered-button')['href'].should eq("/client?artist=#{jamtrack_acdc_backinblack.original_artist}#/jamtrackBrowse")
find('a.white-bordered-button').trigger(:click)
find('h1', text: 'jamtracks')
@@ -97,7 +97,7 @@ describe "Individual JamTrack Band", :js => true, :type => :feature, :capybara_f
find('.jam-track-preview-holder[data-id="' + track.id + '"] .instrument-name', text:track.instrument.description)
end
end
- find('a.white-bordered-button')['href'].should eq("/client?artist=#{jamtrack_acdc_backinblack.original_artist}#/jamtrack")
+ find('a.white-bordered-button')['href'].should eq("/client?artist=#{jamtrack_acdc_backinblack.original_artist}#/jamtrackBrowse")
find('a.white-bordered-button').trigger(:click)
find('h1', text: 'jamtracks')
diff --git a/web/spec/features/individual_jamtrack_spec.rb b/web/spec/features/individual_jamtrack_spec.rb
index 7aa9db507..3483a8b86 100644
--- a/web/spec/features/individual_jamtrack_spec.rb
+++ b/web/spec/features/individual_jamtrack_spec.rb
@@ -78,7 +78,7 @@ describe "Individual JamTrack", :js => true, :type => :feature, :capybara_featur
find('.jam-track-preview-holder[data-id="' + track.id + '"] .instrument-name', text:track.instrument.description)
end
end
- find('a.white-bordered-button')['href'].should eq("/client?artist=#{jamtrack_acdc_backinblack.original_artist}#/jamtrack")
+ find('a.white-bordered-button')['href'].should eq("/client?artist=#{jamtrack_acdc_backinblack.original_artist}#/jamtrackBrowse")
find('a.white-bordered-button').trigger(:click)
find('h1', text: 'jamtracks')
@@ -97,7 +97,7 @@ describe "Individual JamTrack", :js => true, :type => :feature, :capybara_featur
find('.jam-track-preview-holder[data-id="' + track.id + '"] .instrument-name', text:track.instrument.description)
end
end
- find('a.white-bordered-button')['href'].should eq("/client?artist=#{jamtrack_acdc_backinblack.original_artist}#/jamtrack")
+ find('a.white-bordered-button')['href'].should eq("/client?artist=#{jamtrack_acdc_backinblack.original_artist}#/jamtrackBrowse")
find('a.white-bordered-button').trigger(:click)
find('h1', text: 'jamtracks')
@@ -116,7 +116,7 @@ describe "Individual JamTrack", :js => true, :type => :feature, :capybara_featur
find('.jam-track-preview-holder[data-id="' + track.id + '"] .instrument-name', text:track.instrument.description)
end
end
- find('a.white-bordered-button')['href'].should eq("/client#/jamtrack")
+ find('a.white-bordered-button')['href'].should eq("/client#/jamtrackBrowse")
find('a.white-bordered-button').trigger(:click)
find('h1', text: 'jamtracks')
diff --git a/web/spec/features/jamtrack_landing_spec.rb b/web/spec/features/jamtrack_landing_spec.rb
new file mode 100644
index 000000000..0cd33d0e8
--- /dev/null
+++ b/web/spec/features/jamtrack_landing_spec.rb
@@ -0,0 +1,71 @@
+require 'spec_helper'
+
+describe "JamTrack Landing", :js => true, :type => :feature, :capybara_feature => true do
+
+ let(:user) { FactoryGirl.create(:user, has_redeemable_jamtrack: true) }
+ let(:jt_us) { FactoryGirl.create(:jam_track, :name=>'jt_us', sales_region: 'United States', make_track: true, original_artist: "foobar") }
+ let(:jt_ww) { FactoryGirl.create(:jam_track, :name=>'jt_ww', sales_region: 'Worldwide', make_track: true, original_artist: "barfoo") }
+ let(:jt_rock) { FactoryGirl.create(:jam_track, :name=>'jt_rock', genre: JamRuby::Genre.find('rock'), make_track: true, original_artist: "badfood") }
+ let(:jt_blues) { FactoryGirl.create(:jam_track, :name=>'jt_blues', genre: JamRuby::Genre.find('blues'), make_track: true, original_artist: "foodbart") }
+
+ before(:all) do
+ Capybara.javascript_driver = :poltergeist
+ Capybara.current_driver = Capybara.javascript_driver
+ Capybara.default_wait_time = 30 # these tests are SLOOOOOW
+ end
+
+
+ before(:each) do
+ ShoppingCart.delete_all
+ JamTrackRight.delete_all
+ JamTrack.delete_all
+ JamTrackTrack.delete_all
+ JamTrackLicensor.delete_all
+
+
+ stub_const("APP_CONFIG", web_config)
+ end
+
+ it "not logged in" do
+ jt_us.touch
+ jt_ww.touch
+
+ visit '/client#/jamtrackLanding'
+
+ find('h2', text: 'what are jamtracks?')
+ if web_config.one_free_jamtrack_per_user
+ find('.free-jamtrack')
+ else
+ find('.no-free-jamtrack')
+ end
+
+ find("a[artist='#{jt_us.original_artist}']", text: 'foobar (1)')
+ find("a[artist='#{jt_ww.original_artist}']", text: 'barfoo (1)')
+ end
+
+ it "logged in and has redeemable track" do
+ jt_us.touch
+ jt_ww.touch
+
+ fast_signin(user, '/client#/jamtrackLanding')
+
+ find('h2', text: 'what are jamtracks?')
+ find('.free-jamtrack')
+ find("a[artist='#{jt_us.original_artist}']", text: 'foobar (1)')
+ find("a[artist='#{jt_ww.original_artist}']", text: 'barfoo (1)')
+ end
+
+ it "logged in and does not have redeemable track" do
+ jt_us.touch
+ jt_ww.touch
+ user.has_redeemable_jamtrack = false
+ user.save!
+
+ fast_signin(user, '/client#/jamtrackLanding')
+
+ find('h2', text: 'what are jamtracks?')
+ find('.no-free-jamtrack')
+ find("a[artist='#{jt_us.original_artist}']", text: 'foobar (1)')
+ find("a[artist='#{jt_ww.original_artist}']", text: 'barfoo (1)')
+ end
+end
diff --git a/web/spec/features/jamtrack_shopping_spec.rb b/web/spec/features/jamtrack_shopping_spec.rb
index 95f887979..4dd20a058 100644
--- a/web/spec/features/jamtrack_shopping_spec.rb
+++ b/web/spec/features/jamtrack_shopping_spec.rb
@@ -2,7 +2,7 @@ require 'spec_helper'
describe "JamTrack Shopping", :js => true, :type => :feature, :capybara_feature => true do
- let(:user) { FactoryGirl.create(:user) }
+ let(:user) { FactoryGirl.create(:user, has_redeemable_jamtrack: false) }
let(:jt_us) { FactoryGirl.create(:jam_track, :name=>'jt_us', sales_region: 'United States', make_track: true, original_artist: "foobar") }
let(:jt_ww) { FactoryGirl.create(:jam_track, :name=>'jt_ww', sales_region: 'Worldwide', make_track: true, original_artist: "barfoo") }
let(:jt_rock) { FactoryGirl.create(:jam_track, :name=>'jt_rock', genre: JamRuby::Genre.find('rock'), make_track: true, original_artist: "badfood") }
@@ -50,9 +50,9 @@ describe "JamTrack Shopping", :js => true, :type => :feature, :capybara_feature
end
if options[:added_cart]
- jamtrack_record.find('a.jamtrack-add-cart-disabled', text: 'Already In Cart')
+ jamtrack_record.find('a.jamtrack-add-cart-disabled', text: 'ALREADY IN CART')
else
- jamtrack_record.find('a.jamtrack-add-cart.button-orange', text: 'Add to Cart')
+ jamtrack_record.find('a.jamtrack-add-cart.button-orange', text: 'ADD TO CART')
end
jamtrack_record
end
@@ -64,7 +64,7 @@ describe "JamTrack Shopping", :js => true, :type => :feature, :capybara_feature
describe "Shopping" do
before(:each) do
- visit "/client#/jamtrack"
+ visit "/client#/jamtrackBrowse"
find('h1', text: 'jamtracks')
jk_select('Any', '#jamtrack-find-form #jamtrack_availability')
@@ -102,7 +102,7 @@ describe "JamTrack Shopping", :js => true, :type => :feature, :capybara_feature
it "sets artist filter" do
pending "The item is clearly present, so not currently sure why capybar can't find it"
- visit "/client?artist=foobar#/jamtrack"
+ visit "/client?artist=foobar#/jamtrackBrowse"
art = find('#jamtrack_artist')
puts "art: #{art}"
end
@@ -110,7 +110,7 @@ describe "JamTrack Shopping", :js => true, :type => :feature, :capybara_feature
describe "Shopping Carts" do
before(:each) do
- visit "/client#/jamtrack"
+ visit "/client#/jamtrackBrowse"
find('h1', text: 'jamtracks')
jk_select('Any', '#jamtrack-find-form #jamtrack_availability')
diff --git a/web/spec/features/products_spec.rb b/web/spec/features/products_spec.rb
index 634d768f3..4fecc2703 100644
--- a/web/spec/features/products_spec.rb
+++ b/web/spec/features/products_spec.rb
@@ -64,19 +64,82 @@ describe "Product Pages", :js => true, :type => :feature, :capybara_feature => t
end
describe "JamBlaster" do
- it "logged out" do
+
+ before(:all) do
+ @old_recaptcha=Rails.application.config.recaptcha_enable
+ Rails.application.config.recaptcha_enable=false
+ end
+
+ after(:all) do
+ Rails.application.config.recaptcha_enable=@old_recaptcha
+ end
+
+ it "logged out and then request jamblaster via sign in" do
visit "/products/jamblaster"
find('h1', text: 'The JamBlaster by JamKazam')
- find('a.white-bordered-button')['href'].should eq("#") # nowhere to go yet
+
+ find('a.white-bordered-button').trigger(:click)
+ find('#banner h1', text: 'please sign in or sign up').trigger(:click)
+ find("#banner a", text: 'SIGN IN').trigger(:click)
+
+
+ # now we are at the sign in page
+ page.should have_selector('form.signin-form')
+ within('form.signin-form') do
+ fill_in "Email Address:", with: user.email
+ fill_in "Password:", with: user.password
+ click_button "SIGN IN"
+ end
+
+ # should be back at the jamblaster product page, and told we placed our order
+ find('h1', text: 'The JamBlaster by JamKazam')
+ find('#banner h1', text: 'virtual order placed')
+
+ user.reload
+ user.want_jamblaster.should be_true
+ end
+
+ it "logged out and then request jamblaster via sign up" do
+ visit "/products/jamblaster"
+
+ find('h1', text: 'The JamBlaster by JamKazam')
+
+ find('a.white-bordered-button').trigger(:click)
+ find('#banner h1', text: 'please sign in or sign up').trigger(:click)
+ find("#banner a", text: 'SIGN UP').trigger(:click)
+
+ # we are now at the sign up page
+ fill_in "jam_ruby_user[first_name]", with: "Mike"
+ fill_in "jam_ruby_user[last_name]", with: "Jones"
+ fill_in "jam_ruby_user[email]", with: "jamblaster_lover@jamkazam.com"
+ fill_in "jam_ruby_user[password]", with: "jam123"
+ fill_in "jam_ruby_user[password_confirmation]", with: "jam123"
+ check("jam_ruby_user[instruments][drums][selected]")
+ check("jam_ruby_user[terms_of_service]")
+ click_button "CREATE ACCOUNT"
+
+ # should be back at the jamblaster product page, and told we placed our order
+ find('h1', text: 'The JamBlaster by JamKazam')
+ find('#banner h1', text: 'virtual order placed')
+
+ some_user = User.find_by_email!('jamblaster_lover@jamkazam.com')
+ some_user.want_jamblaster.should be_true
end
it "logged in" do
fast_signin(user, "/products/jamblaster")
find('h1', text: 'The JamBlaster by JamKazam')
- find('a.white-bordered-button')['href'].should eq("#") # nowhere to go yet
+ find('a.white-bordered-button').trigger(:click)
+ find('#banner', text: 'please confirm')
+ find('#banner a.yes-btn').trigger(:click)
+ find('#banner h1', text: 'virtual order placed')
+
+ user.reload
+ user.want_jamblaster.should be_true
end
+
end
describe "Platform" do
diff --git a/web/spec/features/recordings_spec.rb b/web/spec/features/recordings_spec.rb
index 9abc9b282..d005456a7 100644
--- a/web/spec/features/recordings_spec.rb
+++ b/web/spec/features/recordings_spec.rb
@@ -57,7 +57,7 @@ describe "Session Recordings", :js => true, :type => :feature, :capybara_feature
in_client(joiner1) do
find('#notification').should have_content 'Recording Discarded'
find('#notification').should have_content 'did not respond to the stop signal'
- find('#recording-status').should have_content 'Make a Recording'
+ find('#recording-status').should have_content 'Make Recording'
end
end
@@ -91,13 +91,13 @@ describe "Session Recordings", :js => true, :type => :feature, :capybara_feature
in_client(joiner1) do
find('#notification').should have_content 'Recording Discarded'
find('#notification').should have_content 'did not respond to the stop signal'
- find('#recording-status').should have_content 'Make a Recording'
+ find('#recording-status').should have_content 'Make Recording'
end
in_client(joiner2) do
find('#notification').should have_content 'Recording Discarded'
find('#notification').should have_content 'did not respond to the stop signal'
- find('#recording-status').should have_content 'Make a Recording'
+ find('#recording-status').should have_content 'Make Recording'
end
end
diff --git a/web/spec/features/signup_spec.rb b/web/spec/features/signup_spec.rb
index 126a116a2..3b1ff4400 100644
--- a/web/spec/features/signup_spec.rb
+++ b/web/spec/features/signup_spec.rb
@@ -282,7 +282,66 @@ describe "Signup", :js => true, :type => :feature, :capybara_feature => true do
visit "#{signup_path}?invitation_code=#{@invited_user.invitation_code}"
should have_selector('h1', text: "You have already signed up with this invitation")
}
+ end
+ describe "signup_hints" do
+ it "redirects to custom location on matched signup_hint" do
+
+ # causes anon cookie to show
+ visit '/'
+ find('h3', text: 'Complete, Multi-Track Backing Tracks')
+
+ # get a anonymous cookie set up
+ anon_user_id = page.driver.cookies["user_uuid"]
+ anon_user = AnonymousUser.new(anon_user_id.value)
+ SignupHint.refresh_by_anoymous_user(anon_user, {redirect_location: '/products/jamblaster', want_jamblaster: true})
+
+ visit signup_path
+
+ fill_in "jam_ruby_user[first_name]", with: "Mike"
+ fill_in "jam_ruby_user[last_name]", with: "Jones"
+ fill_in "jam_ruby_user[email]", with: "signup_hint_guy@jamkazam.com"
+ fill_in "jam_ruby_user[password]", with: "jam123"
+ fill_in "jam_ruby_user[password_confirmation]", with: "jam123"
+ check("jam_ruby_user[instruments][drums][selected]")
+ check("jam_ruby_user[terms_of_service]")
+ click_button "CREATE ACCOUNT"
+
+ find('h1.product-headline', text:'The JamBlaster by JamKazam')
+
+ user = User.find_by_email('signup_hint_guy@jamkazam.com')
+ user.want_jamblaster.should be_true
+ end
+
+ it "ignores expired_at signup_hint" do
+
+ # causes anon cookie to show
+ visit '/'
+ find('h3', text: 'Complete, Multi-Track Backing Tracks')
+
+ # get a anonymous cookie set up
+ anon_user_id = page.driver.cookies["user_uuid"]
+ anon_user = AnonymousUser.new(anon_user_id.value)
+ hint = SignupHint.refresh_by_anoymous_user(anon_user, {redirect_location: '/products/jamblaster', want_jamblaster: true})
+ hint.expires_at = 1.day.ago
+ hint.save!
+
+ visit signup_path
+
+ fill_in "jam_ruby_user[first_name]", with: "Mike"
+ fill_in "jam_ruby_user[last_name]", with: "Jones"
+ fill_in "jam_ruby_user[email]", with: "signup_hint_guy2@jamkazam.com"
+ fill_in "jam_ruby_user[password]", with: "jam123"
+ fill_in "jam_ruby_user[password_confirmation]", with: "jam123"
+ check("jam_ruby_user[instruments][drums][selected]")
+ check("jam_ruby_user[terms_of_service]")
+ click_button "CREATE ACCOUNT"
+
+ should have_title("JamKazam | Congratulations")
+
+ user = User.find_by_email('signup_hint_guy2@jamkazam.com')
+ user.want_jamblaster.should be_false
+ end
end
end
diff --git a/web/spec/support/app_config.rb b/web/spec/support/app_config.rb
index 645562f90..b7cc08d89 100644
--- a/web/spec/support/app_config.rb
+++ b/web/spec/support/app_config.rb
@@ -2,6 +2,14 @@
def web_config
klass = Class.new do
+ def email_recurly_notice
+ 'recurly-alerts@jamkazam.com'
+ end
+
+ def email_generic_from
+ 'nobody@jamkazam.com'
+ end
+
def external_hostname
Capybara.current_session.server.host
end
@@ -71,8 +79,8 @@ def web_config
100
end
- def signing_job_run_max_time
- 60 # 1 minute
+ def signing_step_max_time
+ 40 # 40 seconds
end
def signing_job_queue_max_time
diff --git a/web/spec/support/client_interactions.rb b/web/spec/support/client_interactions.rb
index 330e3bf95..2798f394a 100644
--- a/web/spec/support/client_interactions.rb
+++ b/web/spec/support/client_interactions.rb
@@ -125,53 +125,3 @@ def close_websocket
page.evaluate_script("window.JK.JamServer.close(true)")
end
-# does not launch it; expects that to have just been done
-def walk_gear_wizard
- # step 1 - intro
- find('.btn-next').trigger(:click)
-
- # step 2 - select gear
- find('.ftue-step-title', text: 'Select & Test Audio Gear')
- should_not have_selector('.resync-status') # when you enter this step,
- jk_select('Built-in', 'div[layout-wizard-step="1"] select.select-audio-input-device')
- find('.btn-next.button-orange:not(.disabled)').trigger(:click)
-
- # step 3 - configure tracks
- find('.ftue-step-title', text: 'Configure Tracks')
-
- # drag one input over to tracks area http://rubydoc.info/github/jnicklas/capybara/master/Capybara/Node/Element#drag_to-instance_method
- input = first('.ftue-input')
- track_slot = first('.track-target')
- input.drag_to(track_slot)
-
- find('.btn-next.button-orange:not(.disabled)').trigger(:click)
-
- # step 4 - configure voice chat
- find('.ftue-step-title', text: 'Configure Voice Chat')
- find('.btn-next.button-orange:not(.disabled)').trigger(:click)
-
- # step 5 - configure direct monitoring
- find('.ftue-step-title', text: 'Turn Off Direct Monitoring')
-
- # make a diversion into the 'adjust gear speed' dialog
- find('.adjust-settings-direct-monitor').trigger(:click)
- # should see dialog header
- find('h1', text: 'Adjust Gear Speed')
- # change to 'moderate' speed
- find('.speed-option.setting-fair ins').trigger(:click)
- # should cause a spinner/io test, and then save button comes up as clickable
- find('.btnSave.button-orange:not(.disabled)').trigger(:click)
-
- find('.btn-next.button-orange:not(.disabled)').trigger(:click)
-
- # step 6 - Test Router & Network
- find('.ftue-step-title', text: 'Test Router & Network')
- find('.button-orange.start-network-test').trigger(:click)
- find('.user-btn', text: 'RUN NETWORK TEST ANYWAY').trigger(:click)
- find('.button-orange.start-network-test')
- find('.btn-next.button-orange:not(.disabled)').trigger(:click)
-
- # step 7 - Success
- find('.ftue-step-title', text: 'Success!')
- find('.btn-close.button-orange').trigger(:click)
-end
\ No newline at end of file
diff --git a/web/spec/support/utilities.rb b/web/spec/support/utilities.rb
index 8248cfbae..8c06407da 100644
--- a/web/spec/support/utilities.rb
+++ b/web/spec/support/utilities.rb
@@ -325,8 +325,8 @@ end
# will select the value from a easydropdown'ed select element
def jk_select(text, select)
# the approach here is to find the hidden select element, and work way back up to the elements that need to be interacted with
- find(select, :visible => false).find(:xpath, 'ancestor::div[contains(@class, "dropdown easydropdown")]').trigger(:click)
- find(select, :visible => false).find(:xpath, 'ancestor::div[contains(@class, "dropdown-wrapper") and contains(@class, "easydropdown-wrapper") and contains(@class, "open")]').find('li', text: text).trigger(:click)
+ find(select, :visible => false).find(:xpath, 'ancestor::div[contains(@class, "dropdown easydropdown") and not(contains(@class, "disabled"))]').trigger(:click)
+ find(select, :visible => false).find(:xpath, 'ancestor::div[contains(@class, "dropdown-wrapper") and contains(@class, "easydropdown-wrapper") and contains(@class, "open") ]').find('li', text: text).trigger(:click)
# works, but is 'cheating' because of visible = false
#select(genre, :from => 'genres', :visible => false)
@@ -460,10 +460,10 @@ def schedule_session(options = {})
find('.btn-next').trigger(:click)
end
- unless quickstart || immediate
- find('.btn-next', text: 'PUBLISH SESSION').trigger(:click)
- else
+ if immediate
find('.btn-next', text: 'START SESSION').trigger(:click)
+ elsif !quickstart
+ find('.btn-next', text: 'PUBLISH SESSION').trigger(:click)
end
end
@@ -562,7 +562,7 @@ def stop_recording
end
def assert_recording_finished
- find('#recording-status').should have_content 'Make a Recording'
+ find('#recording-status').should have_content 'Make Recording'
should have_selector('h1', text: 'recording finished')
end
diff --git a/websocket-gateway/lib/jam_websockets.rb b/websocket-gateway/lib/jam_websockets.rb
index 5fbd91abb..80514657d 100644
--- a/websocket-gateway/lib/jam_websockets.rb
+++ b/websocket-gateway/lib/jam_websockets.rb
@@ -1,6 +1,6 @@
require "logging"
-require "jam_ruby"
require "bugsnag"
+require "jam_ruby"
require "jam_websockets/version"
require "jam_websockets/session_error"
require "jam_websockets/permission_error"
diff --git a/websocket-gateway/lib/jam_websockets/router.rb b/websocket-gateway/lib/jam_websockets/router.rb
index c68de654a..4d79c3647 100644
--- a/websocket-gateway/lib/jam_websockets/router.rb
+++ b/websocket-gateway/lib/jam_websockets/router.rb
@@ -348,7 +348,7 @@ module JamWebsockets
ensure
cleanup_client(client)
end
- rescue PermissionError => e
+ rescue JamPermissionError => e
@log.info "permission error. reason=#{e.to_s}"
@log.info e
@@ -971,7 +971,7 @@ module JamWebsockets
client_connection = Connection.find_by_client_id(client_id)
if client_connection.nil?
- raise PermissionError, 'specified client not found'
+ raise JamPermissionError, 'specified client not found'
end
if !client_connection.access_p2p? user