Merge branch 'feature/musician_profile_enhancements' into feature/musician_search2

This commit is contained in:
Jonathan Kolyer 2015-06-28 19:52:45 +00:00
commit 832e716e8b
80 changed files with 2183 additions and 1169 deletions

View File

@ -109,6 +109,7 @@ group :development, :test do
gem 'database_cleaner', '0.7.0'
gem 'launchy'
gem 'faker', '1.3.0'
gem 'puma'
end
group :test do

View File

@ -0,0 +1,26 @@
ActiveAdmin.register JamRuby::BroadcastNotification, :as => 'BroadcastNotification' do
menu :label => 'Notifications'
config.sort_order = 'created_at_desc'
config.batch_actions = false
config.clear_action_items!
config.filters = false
action_item :only => :index do
link_to "New Broadcast" , "broadcast_notifications/new"
end
show do
attributes_table do
row :title
row :message
row :button_label
row :button_url
row :frequency
row :frequency_distribution
end
end
end

View File

@ -0,0 +1,20 @@
require 'csv'
class EmailController < ApplicationController
respond_to :csv
def dump_emailables
if params[:code] != Rails.application.config.email_dump_code
render :text => "", :status => 404
return
end
headers['Content-Disposition'] = "attachment; filename=\"user-list.csv\""
headers['Content-Type'] ||= 'text/csv'
@users = User.where(subscribe_email: true)
end
end

View File

@ -0,0 +1,2 @@
<%- headers = ['email', 'name', 'unsubscribe_token'] -%>
<%= CSV.generate_line headers %><%- @users.each do |user| -%><%= CSV.generate_line([user.email, user.name, user.unsubscribe_token]) %><%- end -%>

View File

@ -151,5 +151,7 @@ module JamAdmin
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"))
config.email_dump_code = 'rcAUyC3TZCbgGx4YQpznBRbNnQMXW5iKTzf9NSBfzMLsnw9dRQ'
end
end

View File

@ -34,6 +34,8 @@ JamAdmin::Application.routes.draw do
match '/api/mix/:id/enqueue' => 'admin/mixes#mix_again', :via => :post
match '/api/checks/latency_tester' => 'checks#check_latency_tester', :via => :get
match '/api/users/emailables/:code' => 'email#dump_emailables', :via => :get
mount Resque::Server.new, :at => "/resque"

View File

@ -16,3 +16,6 @@ PLATFORMS
DEPENDENCIES
pg_migrate (= 0.1.13)
BUNDLED WITH
1.10.3

View File

@ -292,4 +292,6 @@ signing.sql
optimized_redeemption.sql
optimized_redemption_warn_mode.sql
affiliate_partners2.sql
enhance_band_profile.sql
enhance_band_profile.sql
broadcast_notifications.sql
broadcast_notifications_fk.sql

View File

@ -0,0 +1,22 @@
CREATE TABLE broadcast_notifications (
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
title VARCHAR(64),
message VARCHAR(256),
button_label VARCHAR(32),
button_url VARCHAR,
frequency INTEGER DEFAULT 0,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE broadcast_notification_views (
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
user_id varchar(64) NOT NULL REFERENCES users(id),
broadcast_notification_id varchar(64) NOT NULL REFERENCES broadcast_notifications(id) ON DELETE CASCADE,
view_count INTEGER DEFAULT 0,
active_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX user_broadcast_idx ON broadcast_notification_views(user_id, broadcast_notification_id);

View File

@ -0,0 +1,2 @@
ALTER TABLE broadcast_notification_views DROP CONSTRAINT broadcast_notification_views_user_id_fkey;
ALTER TABLE broadcast_notification_views ADD CONSTRAINT broadcast_notification_views_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;

View File

@ -1,5 +1,5 @@
ALTER TABLE bands ADD COLUMN band_type VARCHAR(16) DEFAULT 'not specified';
ALTER TABLE bands ADD COLUMN band_status VARCHAR(16) DEFAULT 'not specified';
ALTER TABLE bands ADD COLUMN band_type VARCHAR(16) DEFAULT '';
ALTER TABLE bands ADD COLUMN band_status VARCHAR(16) DEFAULT '';
ALTER TABLE bands ADD COLUMN concert_count SMALLINT DEFAULT 0;
ALTER TABLE bands ADD COLUMN add_new_members BOOLEAN DEFAULT FALSE;
ALTER TABLE bands ADD COLUMN play_commitment SMALLINT DEFAULT 0;

View File

@ -24,7 +24,7 @@ gem 'uuidtools', '2.1.2'
gem 'bcrypt-ruby', '3.0.1'
gem 'ruby-protocol-buffers', '1.2.2'
gem 'eventmachine', '1.0.3'
gem 'amqp', '1.0.2'
gem 'amqp', '1.0.2'
gem 'will_paginate'
gem 'actionmailer', '3.2.13'
gem 'sendgrid', '1.2.0'
@ -63,6 +63,7 @@ group :test do
gem 'timecop'
gem 'rspec-prof'
gem 'time_difference'
gem 'byebug'
end
# Specify your gem's dependencies in jam_ruby.gemspec

View File

@ -225,6 +225,8 @@ require "jam_ruby/models/text_message"
require "jam_ruby/models/sale"
require "jam_ruby/models/sale_line_item"
require "jam_ruby/models/recurly_transaction_web_hook"
require "jam_ruby/models/broadcast_notification"
require "jam_ruby/models/broadcast_notification_view"
require "jam_ruby/jam_tracks_manager"
require "jam_ruby/jam_track_importer"
require "jam_ruby/jmep_manager"

View File

@ -31,8 +31,8 @@ module JamRuby
has_many :musician_instruments, :class_name => "JamRuby::MusicianInstrument", :foreign_key=> 'player_id'
has_many :instruments, :through => :musician_instruments, :class_name => "JamRuby::Instrument", :foreign_key=> 'player_id'
has_many :online_presences, :class_name => "JamRuby::OnlinePresence"
has_many :performance_samples, :class_name => "JamRuby::PerformanceSample"
has_many :online_presences, :class_name => "JamRuby::OnlinePresence", :foreign_key=> 'player_id'
has_many :performance_samples, :class_name => "JamRuby::PerformanceSample", :foreign_key=> 'player_id'
# musicians
@ -208,7 +208,6 @@ module JamRuby
end
online_presences = params[:online_presences]
Rails.logger.info("ONLINE_PRESENCE: #{online_presences.inspect} / #{params.inspect}")
if online_presences.present?
online_presences.each do |op|
new_presence = OnlinePresence.create(band, op, false)

View File

@ -0,0 +1,51 @@
module JamRuby
class BroadcastNotification < ActiveRecord::Base
attr_accessible :title, :message, :button_label, :frequency, :button_url, as: :admin
has_many :user_views, class_name: 'JamRuby::BroadcastNotificationView', dependent: :destroy
validates :button_label, presence: true, length: {maximum: 14}
validates :message, presence: true, length: {maximum: 200}
validates :title, presence: true, length: {maximum: 50}
def self.next_broadcast(user)
self.viewable_notifications(user).limit(1).first
end
def self.viewable_notifications(user)
self.select('broadcast_notifications.*, bnv.updated_at AS bnv_updated_at')
.joins("LEFT OUTER JOIN broadcast_notification_views AS bnv ON bnv.broadcast_notification_id = broadcast_notifications.id AND (bnv.user_id IS NULL OR (bnv.user_id = '#{user.id}'))")
.where(['broadcast_notifications.frequency > 0'])
.where(['bnv.user_id IS NULL OR bnv.active_at < NOW()'])
.where(['bnv.user_id IS NULL OR broadcast_notifications.frequency > bnv.view_count'])
.order('bnv_updated_at NULLS FIRST')
end
def did_view(user)
bnv = BroadcastNotificationView
.where(broadcast_notification_id: self.id, user_id: user.id)
.limit(1)
.first
unless bnv
bnv = user_views.new()
bnv.user = user
bnv.active_at = Time.now - 10
end
bnv = user_views.new(user: user) unless bnv
bnv.view_count += 1
bnv.save
bnv
end
def frequency_distribution
@distribution ||= BroadcastNotificationView
.where(broadcast_notification_id: self.id)
.group(:view_count)
.count
end
end
end

View File

@ -0,0 +1,8 @@
module JamRuby
class BroadcastNotificationView < ActiveRecord::Base
belongs_to :broadcast_notification, :class_name => 'JamRuby::BroadcastNotification'
belongs_to :user, :class_name => 'JamRuby::User'
end
end

View File

@ -193,7 +193,7 @@ FactoryGirl.define do
end
factory :invitation, :class => JamRuby::Invitation do
end
factory :friendship, :class => JamRuby::Friendship do
@ -218,7 +218,7 @@ FactoryGirl.define do
band.genres << Genre.first
}
end
factory :genre, :class => JamRuby::Genre do
description { |n| "Genre #{n}" }
end
@ -239,7 +239,7 @@ FactoryGirl.define do
end
factory :video_source, :class => JamRuby::VideoSource do
#client_video_source_id "test_source_id"
#client_video_source_id "test_source_id"
sequence(:client_video_source_id) { |n| "client_video_source_id#{n}"}
end
@ -269,7 +269,7 @@ FactoryGirl.define do
association :recording, factory: :recording
end
factory :recorded_video, :class => JamRuby::RecordedVideo do
factory :recorded_video, :class => JamRuby::RecordedVideo do
sequence(:client_video_source_id) { |n| "client_video_source_id-#{n}"}
fully_uploaded true
length 1
@ -633,9 +633,9 @@ FactoryGirl.define do
data Faker::Lorem.sentence
end
factory :rsvp_slot, class: JamRuby::RsvpSlot do
factory :rsvp_slot, :class => JamRuby::RsvpSlot do
proficiency_level 'beginner'
proficiency_level "beginner"
instrument { Instrument.find('electric guitar') }
factory :chosen_rsvp_slot do
@ -643,10 +643,10 @@ FactoryGirl.define do
user nil
end
after(:create) { |rsvp_slot, evaluator|
after(:create) do |rsvp_slot, evaluator|
rsvp_request = FactoryGirl.create(:rsvp_request, user: evaluator.user)
rsvp_request_rsvp_slot = FactoryGirl.create(:rsvp_request_rsvp_slot, chosen:true, rsvp_request: rsvp_request, rsvp_slot:rsvp_slot)
}
end
end
end
@ -686,7 +686,7 @@ FactoryGirl.define do
end
end
factory :rsvp_request_rsvp_slot, class: JamRuby::RsvpRequestRsvpSlot do
factory :rsvp_request_rsvp_slot, :class => JamRuby::RsvpRequestRsvpSlot do
chosen false
end
@ -798,6 +798,13 @@ FactoryGirl.define do
end
end
factory :broadcast_notification, :class => JamRuby::BroadcastNotification do
title Faker::Lorem.sentence[0...50]
message Faker::Lorem.paragraph[0...200]
button_label Faker::Lorem.words(2).join(' ')[0...14]
frequency 3
end
factory :affiliate_partner, class: 'JamRuby::AffiliatePartner' do
sequence(:partner_name) { |n| "partner-#{n}" }
entity_type 'Individual'
@ -824,6 +831,6 @@ FactoryGirl.define do
factory :affiliate_legalese, class: 'JamRuby::AffiliateLegalese' do
legalese Faker::Lorem.paragraphs(6).join("\n\n")
end
end
end

View File

@ -616,6 +616,7 @@ describe ActiveMusicSession do
end
it "disallow a jam track to be opened when another is already opened" do
pending "needs fixing"
# if a jam track is open, don't allow another to be opened
@music_session.open_jam_track(@user1, @jam_track)
@music_session.errors.any?.should be_false

View File

@ -0,0 +1,64 @@
require 'spec_helper'
describe BroadcastNotification do
let(:broadcast1) { FactoryGirl.create(:broadcast_notification) }
let(:broadcast2) { FactoryGirl.create(:broadcast_notification) }
let(:broadcast3) { FactoryGirl.create(:broadcast_notification) }
let(:broadcast4) { FactoryGirl.create(:broadcast_notification) }
let(:user1) { FactoryGirl.create(:user) }
let(:user2) { FactoryGirl.create(:user) }
let(:user3) { FactoryGirl.create(:user) }
let(:user4) { FactoryGirl.create(:user) }
before(:each) do
BroadcastNotificationView.delete_all
end
it 'created broadcast' do
expect(broadcast1.title).not_to be_empty
expect(broadcast1.frequency).to be > 0
end
it 'gets view incremented' do
bnv = broadcast1.did_view(user1)
bnv = broadcast1.did_view(user1)
bnv.view_count.should eq(2)
end
it 'loads viewable broadcasts for a user' do
broadcast1.touch
broadcast2.touch
broadcast3.touch
broadcast4.touch
bns = BroadcastNotification.viewable_notifications(user1)
bns.count.should eq(4)
broadcast2.frequency.times { |nn| broadcast2.did_view(user1) }
broadcast3.did_view(user1)
broadcast1.did_view(user1)
broadcast4.did_view(user2)
bns = BroadcastNotification.viewable_notifications(user1)
expect(bns.count).to be(3)
expect(bns[0].id).to eq(broadcast3.id)
expect(bns.detect {|bb| bb.id==broadcast2.id }).to be_nil
expect(BroadcastNotification.next_broadcast(user1).id).to eq(broadcast3.id)
end
it 'generates frequency distribution' do
4.times { |nn| broadcast1.did_view(user1) }
5.times { |nn| broadcast1.did_view(user2) }
5.times { |nn| broadcast1.did_view(user3) }
8.times { |nn| broadcast1.did_view(user4) }
distrib = broadcast1.frequency_distribution
expect(distrib.count).to be == 3
expect(distrib[4]).to be == 1
expect(distrib[5]).to be == 2
expect(distrib[8]).to be == 1
end
end

View File

@ -1,7 +1,4 @@
source 'http://rubygems.org'
unless ENV["LOCAL_DEV"] == "1"
source 'https://jamjam:blueberryjam@int.jamkazam.com/gems/'
end
# Look for $WORKSPACE, otherwise use "workspace" as dev path.
devenv = ENV["BUILD_NUMBER"].nil? # Jenkins sets a build number environment variable
@ -12,11 +9,13 @@ if devenv
gem 'jam_ruby', :path => "../ruby"
gem 'jam_websockets', :path => "../websocket-gateway"
else
gem 'jam_db', "0.1.#{ENV["BUILD_NUMBER"]}"
gem 'jampb', "0.1.#{ENV["BUILD_NUMBER"]}"
gem 'jam_ruby', "0.1.#{ENV["BUILD_NUMBER"]}"
gem 'jam_websockets', "0.1.#{ENV["BUILD_NUMBER"]}"
ENV['NOKOGIRI_USE_SYSTEM_LIBRARIES'] ||= "true"
source 'https://jamjam:blueberryjam@int.jamkazam.com/gems/' do
gem 'jam_db', "0.1.#{ENV["BUILD_NUMBER"]}"
gem 'jampb', "0.1.#{ENV["BUILD_NUMBER"]}"
gem 'jam_ruby', "0.1.#{ENV["BUILD_NUMBER"]}"
gem 'jam_websockets', "0.1.#{ENV["BUILD_NUMBER"]}"
ENV['NOKOGIRI_USE_SYSTEM_LIBRARIES'] ||= "true"
end
end
gem 'oj', '2.10.2'
@ -90,6 +89,13 @@ gem 'guard', '2.7.3'
gem 'influxdb', '0.1.8'
gem 'influxdb-rails', '0.1.10'
gem 'sitemap_generator'
gem 'bower-rails', "~> 0.9.2"
gem 'react-rails', '~> 1.0'
#gem "browserify-rails", "~> 0.7"
source 'https://rails-assets.org' do
gem 'rails-assets-reflux'
end
group :development, :test do
gem 'rspec-rails', '2.14.2'
@ -139,6 +145,7 @@ group :test, :cucumber do
# gem 'growl', '1.0.3'
gem 'poltergeist'
gem 'resque_spec'
#gem 'thin'
end

View File

@ -28,8 +28,8 @@
var $biography = $screen.find('#biography');
var $subscribe = $screen.find('#subscribe');
var $btnCancel = $screen.find('#account-edit-profile-cancel');
var $btnSubmit = $screen.find('#account-edit-profile-submit');
var $btnCancel = $screen.find('.account-edit-profile-cancel');
var $btnSubmit = $screen.find('.account-edit-profile-submit');
function beforeShow(data) {
userId = data.id;

View File

@ -10,9 +10,9 @@
var api = context.JK.Rest();
var $screen = $('#account-profile-experience');
var profileUtils = context.JK.ProfileUtils;
var $btnCancel = $screen.find('#account-edit-profile-cancel');
var $btnBack = $screen.find('#account-edit-profile-back');
var $btnSubmit = $screen.find('#account-edit-profile-submit');
var $btnCancel = $screen.find('.account-edit-profile-cancel');
var $btnBack = $screen.find('.account-edit-profile-back');
var $btnSubmit = $screen.find('.account-edit-profile-submit');
var $instrumentSelector = $screen.find('.instrument_selector');
var $userGenres = $screen.find('#user-genres');

View File

@ -62,9 +62,9 @@
var $cowritingGenreList = $cowritingGenres.find(GENRE_LIST_SELECTOR)
var $cowritingPurpose = $screen.find('#cowriting-purpose')
var $btnCancel = $screen.find('#account-edit-profile-cancel')
var $btnBack = $screen.find('#account-edit-profile-back')
var $btnSubmit = $screen.find('#account-edit-profile-submit')
var $btnCancel = $screen.find('.account-edit-profile-cancel')
var $btnBack = $screen.find('.account-edit-profile-back')
var $btnSubmit = $screen.find('.account-edit-profile-submit')
function beforeShow(data) {
}

View File

@ -5,14 +5,14 @@
context.JK = context.JK || {};
// TODO: Add a target type, which can be band or user -- call the
// appropriate API methods.
// appropriate API methods.
context.JK.AccountProfileSamples = function(app, parent, loadFn, updateFn) {
var $document = $(document)
// used to initialize RecordingSourceValidator in site_validator.js.coffee
window.jamkazamRecordingSources = [];
window.soundCloudRecordingSources = [];
window.youTubeRecordingSources = [];
var jamkazamRecordingSources = [];
var soundCloudRecordingSources = [];
var youTubeRecordingSources = [];
var logger = context.JK.logger;
var EVENTS = context.JK.EVENTS;
@ -20,9 +20,9 @@
var ui = new context.JK.UIHelper(JK.app);
var target = {};
var profileUtils = context.JK.ProfileUtils;
var $screen = $('.profile-online-sample-controls', parent);
var $screen = $('.profile-online-sample-controls', parent);
// online presences
var $website = $screen.find('.website');
var $website = $screen.find('.website');
var $soundCloudUsername = $screen.find('.soundcloud-username');
var $reverbNationUsername = $screen.find('.reverbnation-username');
var $bandCampUsername = $screen.find('.bandcamp-username');
@ -32,31 +32,43 @@
var $twitterUsername = $screen.find('.twitter-username');
// performance samples
var $jamkazamSampleList = $screen.find('.samples.jamkazam').find('.sample-list');
var $soundCloudSampleList = $screen.find('.samples.soundcloud').find('.sample-list');
var $youTubeSampleList = $screen.find('.samples.youtube').find('.sample-list');
var $jamkazamSampleList = $screen.find(".sample-list[source-type='jamkazam']")
var $soundCloudSampleList = $screen.find(".sample-list[source-type='soundcloud']")
var $youTubeSampleList = $screen.find(".sample-list[source-type='youtube']")
// buttons
var $btnAddJkRecording = $screen.find('.btn-add-jk-recording');
var $btnCancel = $screen.find('.account-edit-profile-cancel');
var $btnBack = $screen.find('.account-edit-profile-back');
var $btnSubmit = $screen.find('.account-edit-profile-submit');
var $btnAddJkRecording = $screen.find('.btn-add-jk-recording')
var $btnCancel = parent.find('.account-edit-profile-cancel')
var $btnBack = parent.find('.account-edit-profile-back')
var $btnSubmit = parent.find('.account-edit-profile-submit')
var urlValidator=null
var soundCloudValidator=null
var reverbNationValidator=null
var bandCampValidator=null
var fandalismValidator=null
var youTubeValidator=null
var facebookValidator=null
var twitterValidator=null
var soundCloudRecordingValidator=null
var youTubeRecordingValidator=null
function beforeShow(data) {
}
function afterShow(data) {
function afterShow(data) {
$.when(loadFn())
.done(function(targetPlayer) {
if (targetPlayer && targetPlayer.keys && targetPlayer.keys.length > 0) {
renderPlayer(targetPlayer)
}
});
})
}
function renderPlayer(targetPlayer) {
renderPresence(targetPlayer);
renderSamples(targetPlayer);
renderSamples(targetPlayer);
}
function renderPresence(targetPlayer) {
@ -108,20 +120,20 @@
function renderSamples(targetPlayer) {
// JamKazam recordings
var samples = profileUtils.jamkazamSamples(targetPlayer.performance_samples);
loadSamples(samples, 'jamkazam', $jamkazamSampleList, window.jamkazamRecordingSources);
loadSamples(samples, 'jamkazam', $jamkazamSampleList, jamkazamRecordingSources);
// SoundCloud recordings
samples = profileUtils.soundCloudSamples(targetPlayer.performance_samples);
loadSamples(samples, 'soundcloud', $soundCloudSampleList, window.soundCloudRecordingSources);
loadSamples(samples, 'soundcloud', $soundCloudSampleList, soundCloudRecordingSources);
// YouTube videos
samples = profileUtils.youTubeSamples(targetPlayer.performance_samples);
loadSamples(samples, 'youtube', $youTubeSampleList, window.youTubeRecordingSources);
loadSamples(samples, 'youtube', $youTubeSampleList, youTubeRecordingSources);
}
function loadSamples(samples, type, $sampleList, recordingSources) {
$sampleList.empty();
$sampleList.find(":not(.empty)").remove();
if (type === 'jamkazam') {
$.each(samples, function(index, val) {
recordingSources.push({
@ -131,8 +143,7 @@
buildJamkazamEntry(val.claimed_recording.id, val.claimed_recording.name);
});
}
else {
} else {
if (samples && samples.length > 0) {
$.each(samples, function(index, val) {
@ -148,9 +159,7 @@
var recordingTitleAttr = ' data-recording-title="' + val.description + '"';
var title = formatTitle(val.description);
$sampleList.append('<div class="clearall recording-row left entry"' + recordingIdAttr + recordingUrlAttr + recordingTitleAttr + '>' + title + '</div>');
var onclick = "onclick=removeRow(\'" + val.service_id + "\',\'" + type + "\');";
$sampleList.append('<div class="right close-button" ' + recordingIdAttr + onclick + '>X</div>');
$sampleList.append('<div class="right close-button" data-recording-type="' + type + '"' + recordingIdAttr + '>X</div>');
});
}
}
@ -161,9 +170,7 @@
var recordingIdAttr = ' data-recording-id="' + recordingId + '" ';
$jamkazamSampleList.append('<div class="clearall recording-row left entry"' + recordingIdAttr + '>' + title + '</div>');
var onclick = "onclick=removeRow(\'" + recordingId + "\',\'jamkazam\');";
$jamkazamSampleList.append('<div class="right close-button" ' + recordingIdAttr + onclick + '>X</div>');
$jamkazamSampleList.append('<div class="right close-button" data-recording-type="jamkazam"' + recordingIdAttr + '>X</div>');
}
function events() {
@ -175,14 +182,14 @@
// retrieve recordings and pass to modal dialog
api.getClaimedRecordings()
.done(function(response) {
ui.launchRecordingSelectorDialog(response, window.jamkazamRecordingSources, function(selectedRecordings) {
ui.launchRecordingSelectorDialog(response, jamkazamRecordingSources, function(selectedRecordings) {
$jamkazamSampleList.empty();
window.jamkazamRecordingSources = [];
jamkazamRecordingSources = [];
// update the list with the selected recordings
$.each(selectedRecordings, function(index, val) {
window.jamkazamRecordingSources.push({
jamkazamRecordingSources.push({
'claimed_recording_id': val.id,
'description': val.name
});
@ -191,7 +198,7 @@
});
});
});
return false;
});
@ -208,14 +215,18 @@
});
enableSubmits();
$screen.find(".sample-list").off("click").on("click", ".close-button", function(e) {
removeRow($(this).data("recording-id"), $(this).data("recording-type"))
})
}
function enableSubmits() {
$btnSubmit.on("click", function(evt) {
evt.stopPropagation();
function enableSubmits() {
$btnSubmit.off("click").on("click", function(e) {
e.stopPropagation();
handleUpdateProfile();
return false;
});
})
$btnSubmit.removeClass("disabled")
}
@ -257,9 +268,7 @@
'service_type': type,
'claimed_recording_id': id,
});
}
else {
} else {
var url = $(this).attr('data-recording-url');
var title = $(this).attr('data-recording-title');
@ -291,7 +300,7 @@
function buildPlayer() {
// extract online presences
var op = [];
var presenceTypes = profileUtils.ONLINE_PRESENCE_TYPES;
var presenceTypes = profileUtils.ONLINE_PRESENCE_TYPES;
addOnlinePresence(op, $soundCloudUsername.val(), presenceTypes.SOUNDCLOUD.description);
addOnlinePresence(op, $reverbNationUsername.val(), presenceTypes.REVERBNATION.description);
addOnlinePresence(op, $bandCampUsername.val(), presenceTypes.BANDCAMP.description);
@ -306,12 +315,12 @@
addPerformanceSamples(ps, $jamkazamSampleList, performanceSampleTypes.JAMKAZAM.description);
addPerformanceSamples(ps, $soundCloudSampleList, performanceSampleTypes.SOUNDCLOUD.description);
addPerformanceSamples(ps, $youTubeSampleList, performanceSampleTypes.YOUTUBE.description);
return {
website: $website.val(),
online_presences: op,
performance_samples: ps
}
}
}
function postUpdateProfileSuccess(response) {
@ -325,20 +334,23 @@
if(xhr.status == 422) {
}
else {
} else {
app.ajaxError(xhr, textStatus, errorMessage)
}
}
function removeRow(recordingId, type) {
$('div[data-recording-id=' + recordingId + ']').remove();
var sampleList = $('.sample-list[source-type="' + type + '"]')
var rowCnt = sampleList.find('.recording-row').length
if (0==parseInt(rowCnt)) {
sampleList.find(".empty").removeClass("hidden")
}
if (type === 'soundcloud') {
window.soundCloudRecordingValidator.removeRecordingId(recordingId);
}
else if (type === 'youtube') {
window.youTubeRecordingValidator.removeRecordingId(recordingId);
soundCloudRecordingValidator.removeRecordingId(recordingId);
} else if (type === 'youtube') {
youTubeRecordingValidator.removeRecordingId(recordingId);
}
}
@ -347,13 +359,13 @@
}
// This function is a bit of a mess. It was pulled
// from the html.erb file verbatim, and could use a
// from the html.erb file verbatim, and could use a
// refactor:
function initializeValidators() {
function initializeValidators() {
var initialized = false;
//$document.on('JAMKAZAM_READY', function(e, data) {
window.JK.JamServer.get$Server().on(window.JK.EVENTS.CONNECTION_UP, function() {
if(initialized) {
//$document.on('JAMKAZAM_READY', function(e, data) {
JK.JamServer.get$Server().on(JK.EVENTS.CONNECTION_UP, function() {
if(initialized) {
return;
}
initialized = true;
@ -361,79 +373,77 @@
//var $screen = $('#account-profile-samples');
var $btnAddSoundCloudRecording = $screen.find('.btn-add-soundcloud-recording');
var $btnAddYouTubeVideo = $screen.find('.btn-add-youtube-video');
var $soundCloudSampleList = $screen.find('.samples.soundcloud');
var $youTubeSampleList = $screen.find('.samples.youtube');
// var $soundCloudSampleList = $screen.find('.samples.soundcloud');
// var $youTubeSampleList = $screen.find('.samples.youtube');
setTimeout(function() {
window.urlValidator = new JK.SiteValidator('url', userNameSuccessCallback, userNameFailCallback, parent);
window.urlValidator.init();
window.soundCloudValidator = new JK.SiteValidator('soundcloud', userNameSuccessCallback, userNameFailCallback, parent);
window.soundCloudValidator.init();
setTimeout(function() {
urlValidator = new JK.SiteValidator('url', userNameSuccessCallback, userNameFailCallback, parent)
urlValidator.init()
window.reverbNationValidator = new JK.SiteValidator('reverbnation', userNameSuccessCallback, userNameFailCallback, parent);
window.reverbNationValidator.init();
soundCloudValidator = new JK.SiteValidator('soundcloud', userNameSuccessCallback, userNameFailCallback, parent)
soundCloudValidator.init()
window.bandCampValidator = new JK.SiteValidator('bandcamp', userNameSuccessCallback, userNameFailCallback, parent);
window.bandCampValidator.init();
reverbNationValidator = new JK.SiteValidator('reverbnation', userNameSuccessCallback, userNameFailCallback, parent)
reverbNationValidator.init()
window.fandalismValidator = new JK.SiteValidator('fandalism', userNameSuccessCallback, userNameFailCallback, parent);
window.fandalismValidator.init();
bandCampValidator = new JK.SiteValidator('bandcamp', userNameSuccessCallback, userNameFailCallback, parent)
bandCampValidator.init()
window.youTubeValidator = new JK.SiteValidator('youtube', userNameSuccessCallback, userNameFailCallback, parent);
window.youTubeValidator.init();
fandalismValidator = new JK.SiteValidator('fandalism', userNameSuccessCallback, userNameFailCallback, parent)
fandalismValidator.init()
window.facebookValidator = new JK.SiteValidator('facebook', userNameSuccessCallback, userNameFailCallback, parent);
window.facebookValidator.init();
youTubeValidator = new JK.SiteValidator('youtube', userNameSuccessCallback, userNameFailCallback, parent)
youTubeValidator.init()
window.twitterValidator = new JK.SiteValidator('twitter', userNameSuccessCallback, userNameFailCallback, parent);
window.twitterValidator.init();
facebookValidator = new JK.SiteValidator('facebook', userNameSuccessCallback, userNameFailCallback, parent)
facebookValidator.init()
window.soundCloudRecordingValidator = new JK.RecordingSourceValidator('rec_soundcloud', soundCloudSuccessCallback, siteFailCallback, parent);
logger.debug("window.soundCloudRecordingValidator", window.soundCloudRecordingValidator)
window.youTubeRecordingValidator = new JK.RecordingSourceValidator('rec_youtube', youTubeSuccessCallback, siteFailCallback, parent);
twitterValidator = new JK.SiteValidator('twitter', userNameSuccessCallback, userNameFailCallback, parent)
twitterValidator.init()
$document.triggerHandler('INIT_SITE_VALIDATORS');
}, 1);
soundCloudRecordingValidator = new JK.RecordingSourceValidator('rec_soundcloud', soundCloudSuccessCallback, siteFailCallback, parent)
youTubeRecordingValidator = new JK.RecordingSourceValidator('rec_youtube', youTubeSuccessCallback, siteFailCallback, parent)
soundCloudRecordingValidator.init(soundCloudRecordingSources)
youTubeRecordingValidator.init(youTubeRecordingSources)
}, 1)
function userNameSuccessCallback($inputDiv) {
$inputDiv.removeClass('error');
$inputDiv.find('.error-text').remove();
}
function userNameFailCallback($inputDiv) {
function userNameFailCallback($inputDiv) {
$inputDiv.addClass('error');
$inputDiv.find('.error-text').remove();
$inputDiv.append("<span class='error-text'>Invalid username</span>").show();
}
function soundCloudSuccessCallback($inputDiv) {
siteSuccessCallback($inputDiv, window.soundCloudRecordingValidator, $soundCloudSampleList, 'soundcloud');
siteSuccessCallback($inputDiv, soundCloudRecordingValidator, $soundCloudSampleList, 'soundcloud');
}
function youTubeSuccessCallback($inputDiv) {
siteSuccessCallback($inputDiv, window.youTubeRecordingValidator, $youTubeSampleList, 'youtube');
siteSuccessCallback($inputDiv, youTubeRecordingValidator, $youTubeSampleList, 'youtube');
}
function siteSuccessCallback($inputDiv, recordingSiteValidator, $sampleList, type) {
function siteSuccessCallback($inputDiv, recordingSiteValidator, sampleList, type) {
sampleList.find(".empty").addClass("hidden")
$inputDiv.removeClass('error');
$inputDiv.find('.error-text').remove();
var recordingSources = recordingSiteValidator.recordingSources();
if (recordingSources && recordingSources.length > 0) {
var $sampleList = $sampleList.find('.sample-list');
var addedRecording = recordingSources[recordingSources.length-1];
// TODO: this code is repeated in JS file
// TODO: this code is repeated in elsewhere in this JS file:
var recordingIdAttr = ' data-recording-id="' + addedRecording.recording_id + '" ';
var recordingUrlAttr = ' data-recording-url="' + addedRecording.url + '" ';
var recordingTitleAttr = ' data-recording-title="' + addedRecording.recording_title + '"';
var title = formatTitle(addedRecording.recording_title);
$sampleList.append('<div class="clearall recording-row left entry"' + recordingIdAttr + recordingUrlAttr + recordingTitleAttr + '>' + title + '</div>');
var onclick = "onclick=removeRow(\'" + addedRecording.recording_id + "\',\'" + type + "\');";
$sampleList.append('<div class="right close-button" ' + recordingIdAttr + onclick + '>X</div>');
sampleList.append('<div class="clearall recording-row left entry"' + recordingIdAttr + recordingUrlAttr + recordingTitleAttr + '>' + title + '</div>');
sampleList.append('<div class="right close-button" data-recording-type="' + type + '"' + recordingIdAttr + '>X</div>');
}
$inputDiv.find('input').val('');
@ -447,17 +457,12 @@
});
//});
$document.on('INIT_SITE_VALIDATORS', function(e, data) {
logger.debug("ZZZwindow.soundCloudRecordingValidator", window.soundCloudRecordingValidator)
window.soundCloudRecordingValidator.init(window.soundCloudRecordingSources);
window.youTubeRecordingValidator.init(window.youTubeRecordingSources);
});
} // end initializeValidators.
} // end initializeValidators.
function resetForm() {
$("input", $screen).val("")
$("input", $screen).val("")
}
function initialize() {

View File

@ -38,6 +38,7 @@
//= require jquery.exists
//= require jquery.payment
//= require jquery.visible
//= require reflux
//= require howler.core.js
//= require jstz
//= require class
@ -50,6 +51,10 @@
//= require utils
//= require subscription_utils
//= require custom_controls
//= require react
//= require react_ujs
//= require react-init
//= require react-components
//= require web/signup_helper
//= require web/signin_helper
//= require web/signin
@ -59,4 +64,4 @@
//= require_directory ./wizard
//= require_directory ./wizard/gear
//= require_directory ./wizard/loopback
//= require everywhere/everywhere
//= require everywhere/everywhere

File diff suppressed because it is too large Load Diff

View File

@ -31,15 +31,15 @@
var friendInput=null
var bandType=null
var bandStatus=null
var concertCount=null
var concertCount=null
var $screen=$("#band-setup")
var $samples = $screen.find(".account-profile-samples")
var $selectedInstruments=[]
var accountProfileSamples = new JK.AccountProfileSamples(app, $screen, loadBandCallback, rest.updateBand)
accountProfileSamples.initialize()
var accountProfileSamples = new JK.AccountProfileSamples(app, $screen, loadBandCallback, rest.updateBand)
accountProfileSamples.initialize()
function navBack() {
if (currentStep>0) {
@ -49,13 +49,13 @@
})
}
}
function navCancel() {
resetForm()
resetForm()
window.history.go(-1)
return false
}
function navNext() {
if (currentStep<STEPS_COUNT-1) {
saveBand(function(band) {
@ -66,41 +66,41 @@
saveBand(function(band) {
resetForm()
showProfile(band.id);
})
})
}
}
function renderCurrentPage() {
function renderCurrentPage() {
$screen.find($(".band-step")).addClass("hidden")
$("#band-setup-step-" + currentStep).removeClass("hidden")
if(currentStep==0) {
if(currentStep==0) {
$("#btn-band-setup-back").addClass("hidden")
$("#btn-band-setup-next").removeClass("hidden").html("SAVE & NEXT")
} else if(currentStep<STEPS_COUNT-1) {
$("#btn-band-setup-next").removeClass("hidden").html("SAVE & NEXT")
} else if(currentStep<STEPS_COUNT-1) {
// if(currentStep==SAMPLE_STEP) {
// accountProfileSamples.renderPlayer(band)
// }
$("#btn-band-setup-back").removeClass("hidden")
$("#btn-band-setup-next").removeClass("hidden").html("SAVE & NEXT")
} else {
$("#btn-band-setup-next").removeClass("hidden").html("SAVE & NEXT")
} else {
$("#btn-band-setup-back").removeClass("hidden")
$("#btn-band-setup-next").removeClass("hidden").html("SAVE & FINISH")
}
renderOptionalControls()
}
function renderOptionalControls(e) {
function renderOptionalControls(e) {
if(e){e.stopPropagation()}
// Is new member selected?
// Is new member selected?
if ($screen.find($('input[name="add_new_members"]:checked')).val()=="yes") {
$screen.find($(".new-member-dependent")).removeClass("hidden")
} else {
$screen.find($(".new-member-dependent")).addClass("hidden")
}
// Is paid gigs selected?
if ($('input[name="paid_gigs"]:checked').val()=="yes") {
// Is paid gigs selected?
if ($('input[name="paid_gigs"]:checked').val()=="yes") {
$screen.find($(".paid-gigs-dependent")).removeClass("hidden")
} else {
$screen.find($(".paid-gigs-dependent")).addClass("hidden")
@ -108,7 +108,7 @@
return false;
}
function isNewBand() {
function isNewBand() {
return bandId==null || typeof(bandId)=='undefined' || bandId.length == 0;
}
@ -143,17 +143,17 @@
// website
$('#band-website').val('');
$("#new-member-no").iCheck('check').attr('checked', 'checked')
$("#paid-gigs-no").iCheck('check').attr('checked', 'checked')
$("#free-gigs-no").iCheck('check').attr('checked', 'checked')
$('#touring-option').val('no')
$("#play-commitment").val('1')
$("#hourly-rate").val("0.0")
$("#gig-minimum").val("0.0")
resetGenres();
$("#gig-minimum").val("0.0")
resetGenres();
renderDesiredExperienceLabel([])
$(friendInput)
@ -202,8 +202,8 @@
if(state) $("#band-region").closest('div.field').addClass('error').end().after(state);
if(city) $("#band-city").closest('div.field').addClass('error').end().after(city);
if(biography) $("#band-biography").closest('div.field').addClass('error').end().after(biography);
if(website) $("#band-website").closest('div.field').addClass('error').end().after(website);
if(genres) $("#band-genres").closest('div.field').addClass('error').end().after(genres);
if(website) $("#band-website").closest('div.field').addClass('error').end().after(website);
if(genres) $("#band-genres").closest('div.field').addClass('error').end().after(genres);
}
function buildBand() {
@ -224,23 +224,23 @@
band.paid_gigs = $('input[name="paid_gigs"]:checked').val()=="yes"
band.free_gigs=$('input[name="free_gigs"]:checked').val()=="yes"
band.touring_option=$('#touring-option').val()=="yes"
band.play_commitment=$("#play-commitment").val()
band.hourly_rate=$("#hourly-rate").val()
band.gig_minimum=$("#gig-minimum").val()
if (currentStep==GENRE_STEP) {
band.genres = getSelectedGenres();
band.validate_genres = true
} else {
band.validate_genres = false
}
$.each($selectedInstruments, function(index, instrument) {
var h = {}
h.instrument_id = instrument.id
h.proficiency_level = instrument.level
band.instruments.push(h)
band.instruments.push(h)
})
if(!isNewBand()) {
@ -289,7 +289,7 @@
context.location = "/client#/bandProfile/" + band_id;
}
function saveInvitations() {
function saveInvitations(response) {
if (0 < $('#selected-friends-band .invitation').length) {
createBandInvitations(response.id, function () {
showProfile(response.id);
@ -298,28 +298,30 @@
}
function saveBand(saveBandSuccessFn) {
unbindNavButtons()
var band = buildBand()
removeErrors()
var band = buildBand()
var saveBandFn = (isNewBand()) ? rest.createBand : rest.updateBand
saveBandFn(band)
.done(function (response) {
.done(function (response) {
bandId = response.id
saveInvitations()
saveInvitations(response)
if(saveBandSuccessFn) {
saveBandSuccessFn(band)
}
})
.fail(function (jqXHR) {
.fail(function (jqXHR) {
if(jqXHR.status == 422) {
renderErrors(JSON.parse(jqXHR.responseText))
} else {
app.notifyServerError(jqXHR, "Unable to create band")
}
})
.always(function (jqXHR) {
bindNavButtons()
})
})
.always(function (jqXHR) {
bindNavButtons()
})
}
function createBandInvitations(bandId, onComplete) {
@ -355,9 +357,9 @@
var stepNum = data['d'].substring(4)
if(stepNum) {
currentStep=stepNum
delete data['d'];
delete data['d'];
}
}
}
resetForm();
}
@ -367,9 +369,9 @@
if (!isNewBand()) {
$("#band-change-photo").html('Upload band photo.');
$('.band-photo').removeClass("hidden")
// retrieve and initialize band profile data points
loadBandDetails();
loadBandDetails();
} else {
loadGenres();
@ -391,7 +393,7 @@
}
function loadBandDetails() {
rest.getBand(bandId).done(function (band) {
$("#band-name").val(band.name);
@ -401,7 +403,7 @@
bandType.val(band.band_type)
bandStatus.val(band.band_status)
concertCount.val(band.concert_count)
if (band.add_new_members){
$("#new-member-no").iCheck('check').attr('checked', 'checked')
} else {
@ -424,7 +426,7 @@
$("#play-commitment").val(band.play_commitment)
$("#hourly-rate").val(band.hourly_rate)
$("#gig-minimum").val(band.gig_minimum)
// Initialize avatar
if (band.photo_url) {
$("#band-avatar").attr('src', band.photo_url);
@ -450,7 +452,7 @@
renderDesiredExperienceLabel($selectedInstruments)
accountProfileSamples.renderPlayer(band)
accountProfileSamples.renderPlayer(band)
});
}
@ -582,7 +584,7 @@
} else {
context.JK.dropdown($city);
}
}
}
function addInvitation(value, data) {
if ($('#selected-band-invitees div[user-id=' + data + ']').length === 0) {
@ -602,27 +604,27 @@
context.location = '/client#/band/setup/photo/' + bandId;
return false;
}
function removeInvitation(evt) {
delete selectedFriendIds[$(evt.currentTarget).parent().attr('user-id')];
$(evt.currentTarget).closest('.invitation').remove();
}
function bindNavButtons() {
function bindNavButtons() {
$('#btn-band-setup-back').on("click", function (e) {
e.stopPropagation()
e.stopPropagation()
navBack()
return false
})
$('#btn-band-setup-cancel').on("click", function (e) {
e.stopPropagation()
e.stopPropagation()
navCancel()
return false
})
$('#btn-band-setup-next').on("click", function (e) {
e.stopPropagation()
e.stopPropagation()
navNext()
return false
})
@ -636,9 +638,9 @@
$('#btn-band-setup-back').off("click")
$('#btn-band-setup-cancel').off("click")
$('#btn-band-setup-next').off("click")
$('#btn-band-setup-back').addClass("disabled")
$('#btn-band-setup-cancel').addClass("disabled")
$('#btn-band-setup-next').addClass("disabled")
$('#btn-band-setup-back').addClass("disabled")
$('#btn-band-setup-cancel').addClass("disabled")
$('#btn-band-setup-next').addClass("disabled")
}
function events() {
@ -649,8 +651,8 @@
// friend input focus
$('#band-invitee-input').focus(function () {
$(this).val('');
});
});
$('#band-country').on('change', function (evt) {
evt.stopPropagation();
loadRegions();
@ -682,22 +684,22 @@
$('a#choose-desired-experience').on("click", chooseExperience)
$('#band-setup').on('ifToggled', 'input[type="radio"].dependent-master', renderOptionalControls);
$(friendInput).focus(function() { $(this).val(''); })
}
function chooseExperience(e) {
e.stopPropagation()
ui.launchInstrumentSelectorDialog("new member(s)", $selectedInstruments, function(selectedInstruments) {
$selectedInstruments = selectedInstruments
function chooseExperience(e) {
e.stopPropagation()
ui.launchInstrumentSelectorDialog("new member(s)", $selectedInstruments, function(selectedInstruments) {
$selectedInstruments = selectedInstruments
renderDesiredExperienceLabel($selectedInstruments)
return false
})
return false
return false
}
function loadBandCallback() {
return (isNewBand()) ? {} : rest.getBand(bandId)
return (isNewBand()) ? {} : rest.getBand(bandId)
}
function initialize(invitationDialogInstance, friendSelectorDialog) {
@ -716,7 +718,7 @@
bandType=$("#band-type")
bandStatus=$("#band-status")
concertCount=$("#concert-count")
app.bindScreen('band/setup', screenBindings)
$screen.find('input[type=radio]').iCheck({
@ -725,11 +727,11 @@
inheritClass: true
})
profileUtils.initializeHelpBubbles()
profileUtils.initializeHelpBubbles()
}
this.initialize = initialize;
this.afterShow = afterShow;
return this;
};
};
})(window, jQuery);

View File

@ -1,18 +1,37 @@
# one time init stuff for the /client view
$ = jQuery
context = window
context.JK ||= {};
broadcastActions = context.JK.Actions.Broadcast
context.JK.ClientInit = class ClientInit
constructor: () ->
@logger = context.JK.logger
@gearUtils = context.JK.GearUtils
@ALERT_NAMES = context.JK.ALERT_NAMES;
@lastCheckedBroadcast = null
init: () =>
if context.gon.isNativeClient
this.nativeClientInit()
context.JK.onBackendEvent(@ALERT_NAMES.WINDOW_OPEN_FOREGROUND_MODE, 'client_init', @watchBroadcast);
this.watchBroadcast()
checkBroadcast: () =>
broadcastActions.load.triggerPromise()
watchBroadcast: () =>
if context.JK.currentUserId
# create a 15 second buffer to not check too fast for some reason (like the client firing multiple foreground events)
if !@lastCheckedBroadcast? || @lastCheckedBroadcast.getTime() < new Date().getTime() - 15000
@lastCheckedBroadcast = new Date()
setTimeout(@checkBroadcast, 3000)
nativeClientInit: () =>
@gearUtils.bootstrapDefaultPlaybackProfile();

View File

@ -4,6 +4,7 @@
context.JK = context.JK || {};
context.JK.FakeJamClient = function(app, p2pMessageFactory) {
var ChannelGroupIds = context.JK.ChannelGroupIds;
var logger = context.JK.logger;
logger.info("*** Fake JamClient instance initialized. ***");
@ -474,7 +475,18 @@
}
function SessionGetControlState(mixerIds, isMasterOrPersonal) {
dbg("SessionGetControlState");
var groups = [0, 1, 2, 3, 3, 7, 8, 10, 11, 12];
var groups = [
ChannelGroupIds.MasterGroup,
ChannelGroupIds.MonitorGroup,
ChannelGroupIds.AudioInputMusicGroup,
ChannelGroupIds.AudioInputChatGroup,
ChannelGroupIds.AudioInputChatGroup,
ChannelGroupIds.UserMusicInputGroup,
ChannelGroupIds.UserChatInputGroup,
ChannelGroupIds.PeerMediaTrackGroup,
ChannelGroupIds.JamTrackGroup,
ChannelGroupIds.MetronomeGroup
]
var names = [
"FW AP Multi",
"FW AP Multi",

View File

@ -11,6 +11,7 @@
var ui = new context.JK.UIHelper(JK.app);
var recordingUtils = context.JK.RecordingUtils;
var userId = null;
var bandId = null;
var currentFeedPage = 0;
var feedBatchSize = 10;
var $screen = null;
@ -35,6 +36,10 @@
query.user = userId;
}
if(bandId) {
query.band = bandId;
}
return query;
}
@ -83,6 +88,10 @@
userId = _userId;
}
function setBand(_bandId) {
bandId = _bandId;
}
function refresh() {
clearResults();
populate();
@ -99,9 +108,9 @@
function populate() {
if (isLoading || didLoadAllFeeds) return;
setLoading(true);
rest.getFeeds(buildQuery())
.done(function(response) {
handleFeedResponse(response);
@ -566,7 +575,6 @@
var winheight = $(scrollerID).height();
var docheight = $('#'+screenID()+'-feed-entry-list').height();
var scrollTrigger = 0.90;
//console.log("feed scroll: wintop="+wintop+" docheight="+docheight+" winheight="+winheight+" ratio="+(wintop / (docheight - winheight)));
if ((wintop / (docheight - winheight)) > scrollTrigger) {
populate();
}
@ -606,6 +614,7 @@
this.initialize = initialize;
this.refresh = refresh;
this.setUser = setUser;
this.setBand = setBand;
return this;
}

View File

@ -313,4 +313,26 @@
context.JK.NAMED_MESSAGES = {
MASTER_VS_PERSONAL_MIX : 'master_vs_personal_mix'
}
// Recreate ChannelGroupIDs ENUM from C++
context.JK.ChannelGroupIds =
{
"MasterGroup": 0,
"MonitorGroup": 1,
"MasterCatGroup": 2,
"MonitorCatGroup": 3,
"AudioInputMusicGroup": 4,
"AudioInputChatGroup": 5,
"MediaTrackGroup": 6,
"StreamOutMusicGroup": 7,
"StreamOutChatGroup": 8,
"StreamOutMediaGroup": 9,
"UserMusicInputGroup": 10,
"UserChatInputGroup": 11,
"UserMediaInputGroup": 12,
"PeerAudioInputMusicGroup": 13,
"PeerMediaTrackGroup": 14,
"JamTrackGroup": 15,
"MetronomeGroup": 16
};
})(window,jQuery);

View File

@ -56,7 +56,27 @@
});
}
function uploadMusicNotations(formData) {
function getBroadcastNotification(options) {
var userId = getId(options);
return $.ajax({
type: "GET",
url: "/api/users/" + userId + "/broadcast_notification"
});
}
function quietBroadcastNotification(options) {
var userId = getId(options);
var broadcast_id = options.broadcast_id;
return $.ajax({
type: "POST",
dataType: "json",
contentType: 'application/json',
url: "/api/users/" + userId + "/broadcast_notification/" + broadcast_id + '/quiet',
data: JSON.stringify({}),
});
}
function uploadMusicNotations(formData) {
return $.ajax({
type: "POST",
processData: false,
@ -168,7 +188,7 @@
if (includePending) {
includeFlag = 'true';
}
return $.ajax({
type: "GET",
dataType: "json",
@ -1267,7 +1287,7 @@
function openBackingTrack(options) {
var musicSessionId = options["id"];
delete options["id"];
return $.ajax({
type: "POST",
dataType: "json",
@ -1330,7 +1350,7 @@
function openMetronome(options) {
var musicSessionId = options["id"];
delete options["id"];
return $.ajax({
type: "POST",
dataType: "json",
@ -1339,11 +1359,11 @@
data: JSON.stringify(options)
})
}
function closeMetronome(options) {
var musicSessionId = options["id"];
delete options["id"];
return $.ajax({
type: "POST",
dataType: "json",
@ -1352,7 +1372,7 @@
data: JSON.stringify(options)
})
}
function discardRecording(options) {
var recordingId = options["id"];
@ -1591,7 +1611,7 @@
url: '/api/recurly/payment_history',
dataType: "json",
contentType: 'application/json'
});
});
}
function getSalesHistory(options) {
@ -1687,7 +1707,7 @@
function placeOrder() {
return $.ajax({
type: "POST",
type: "POST",
url: '/api/recurly/place_order',
dataType: "json",
contentType: 'application/json'
@ -1820,6 +1840,8 @@
this.createScheduledSession = createScheduledSession;
this.uploadMusicNotations = uploadMusicNotations;
this.getMusicNotation = getMusicNotation;
this.getBroadcastNotification = getBroadcastNotification;
this.quietBroadcastNotification = quietBroadcastNotification;
this.legacyJoinSession = legacyJoinSession;
this.joinSession = joinSession;
this.cancelSession = cancelSession;
@ -1908,7 +1930,7 @@
this.openJamTrack = openJamTrack
this.openBackingTrack = openBackingTrack
this.closeBackingTrack = closeBackingTrack
this.closeMetronome = closeMetronome;
this.closeMetronome = closeMetronome;
this.closeJamTrack = closeJamTrack;
this.openMetronome = openMetronome;
this.closeMetronome = closeMetronome;
@ -1975,9 +1997,6 @@
this.createAlert = createAlert;
this.signup = signup;
this.portOverCarts = portOverCarts;
return this;
};
})(window,jQuery);

View File

@ -202,7 +202,12 @@
var gridRows = layout.split('x')[0];
var gridCols = layout.split('x')[1];
$grid.children().each(function () {
var gutterWidth = 0;
var findCardLayout;
var feedCardLayout;
$grid.find('.homecard').each(function () {
var childPosition = $(this).attr("layout-grid-position");
var childRow = childPosition.split(',')[1];
var childCol = childPosition.split(',')[0];
@ -211,6 +216,13 @@
var childLayout = me.getCardLayout(gridWidth, gridHeight, gridRows, gridCols,
childRow, childCol, childRowspan, childColspan);
if($(this).is('.feed')) {
feedCardLayout = childLayout;
}
else if($(this).is('.findsession')) {
findCardLayout = childLayout;
}
$(this).animate({
width: childLayout.width,
height: childLayout.height,
@ -218,6 +230,18 @@
left: childLayout.left
}, opts.animationDuration);
});
var broadcastWidth = findCardLayout.width + feedCardLayout.width;
layoutBroadcast(broadcastWidth, findCardLayout.left);
}
function layoutBroadcast(width, left) {
var css = {
width:width + opts.gridPadding * 2,
left:left
}
$('[data-react-class="BroadcastHolder"]').animate(css, opts.animationDuration)
}
function layoutSidebar(screenWidth, screenHeight) {

View File

@ -30,21 +30,21 @@
var $studioCount = $screen.find('#studio-count');
// performance samples
var $noSamples = $screen.find('#no-samples');
var $jamkazamSamples = $screen.find('#jamkazam-samples');
var $soundCloudSamples = $screen.find('#soundcloud-samples');
var $youTubeSamples = $screen.find('#youtube-samples');
var $noSamples = $screen.find('.no-samples');
var $jamkazamSamples = $screen.find('.jamkazam-samples');
var $soundCloudSamples = $screen.find('.soundcloud-samples');
var $youTubeSamples = $screen.find('.youtube-samples');
// online presence
var $noOnlinePresence = $screen.find('#no-online-presence');
var $userWebsite = $screen.find('#user-website');
var $soundCloudPresence = $screen.find('#soundcloud-presence');
var $reverbNationPresence = $screen.find('#reverbnation-presence');
var $bandCampPresence = $screen.find('#bandcamp-presence');
var $fandalismPresence = $screen.find('#fandalism-presence');
var $youTubePresence = $screen.find('#youtube-presence');
var $facebookPresence = $screen.find('#facebook-presence');
var $twitterPresence = $screen.find('#twitter-presence');
var $noOnlinePresence = $screen.find('.no-online-presence');
var $userWebsite = $screen.find('.user-website');
var $soundCloudPresence = $screen.find('.soundcloud-presence');
var $reverbNationPresence = $screen.find('.reverbnation-presence');
var $bandCampPresence = $screen.find('.bandcamp-presence');
var $fandalismPresence = $screen.find('.fandalism-presence');
var $youTubePresence = $screen.find('.youtube-presence');
var $facebookPresence = $screen.find('.facebook-presence');
var $twitterPresence = $screen.find('.twitter-presence');
// current interests
var $noInterests = $screen.find('#no-interests');
@ -66,16 +66,16 @@
// tabs
var $aboutLink = $screen.find('#about-link');
var $aboutContent = $screen.find('#about-content');
var $historyLink = $screen.find('#history-link');
var $historyContent = $screen.find('#history-content');
var $bandsLink = $screen.find('#bands-link');
var $bandsContent = $screen.find('#bands-content');
var $socialLink = $screen.find('#social-link');
var $socialContent = $screen.find('#social-content');
var $favoritesLink = $screen.find('#favorites-link');
var $favoritesContent = $screen.find('#favorites-content');
@ -112,27 +112,15 @@
var instrument_logo_map = context.JK.getInstrumentIconMap24();
var proficiencyDescriptionMap = {
"1": "BEGINNER",
"2": "INTERMEDIATE",
"3": "EXPERT"
};
var proficiencyCssMap = {
"1": "proficiency-beginner",
"2": "proficiency-intermediate",
"3": "proficiency-expert"
};
function beforeShow(data) {
userId = data.id;
feed.setUser(userId);
feed.setUser(userId);
}
function afterShow(data) {
initUser();
resetForm();
renderAllStats();
renderAllStats();
}
function beforeHide(data) {
@ -265,11 +253,11 @@
$soundCloudSamples.off("click", "a.sound-cloud-playable") .on("click", "a.sound-cloud-playable", playSoundCloudFile)
}
function playSoundCloudFile(e) {
function playSoundCloudFile(e) {
e.preventDefault();
var url = $(this).attr("soundcloud_url")
var cap = $(this).text()
player.initialize(url, cap);
player.initialize(url, cap);
app.layout.showDialog('sound-cloud-player-dialog');
return false;
}
@ -432,7 +420,7 @@
$favoritesContent.hide();
$('.profile-nav a.active').removeClass('active');
$aboutLink.addClass('active');
$aboutLink.addClass('active');
}
function renderAllStats() {
@ -497,170 +485,15 @@
}
function renderMusicalExperience() {
$instruments.empty();
if (user.instruments) {
for (var i = 0; i < user.instruments.length; i++) {
var instrument = user.instruments[i];
var description = instrument.instrument_id;
var proficiency = instrument.proficiency_level;
var instrument_icon_url = context.JK.getInstrumentIcon256(description);
// add instrument info to layout
var template = $('#template-profile-instruments').html();
var instrumentHtml = context.JK.fillTemplate(template, {
instrument_logo_url: instrument_icon_url,
instrument_description: description,
proficiency_level: proficiencyDescriptionMap[proficiency],
proficiency_level_css: proficiencyCssMap[proficiency]
});
$instruments.append(instrumentHtml);
}
}
// status
var status = user.skill_level;
$musicianStatus.html(status ? profileUtils.skillLevelMap[status] + ' musician' : NOT_SPECIFIED_TEXT)
// genres
$genres.empty();
var profileGenres = profileUtils.profileGenreList(user.genres);
$genres.append(profileGenres.length > 0 ? profileGenres : NOT_SPECIFIED_TEXT);
// concert gigs
var concertGigCount = user.concert_count;
$concertCount.html(concertGigCount > 0 ? 'Has played ' + profileUtils.gigMap[concertGigCount] + ' live concert gigs' : NOT_SPECIFIED_TEXT);
// studio gigs
var studioGigCount = user.studio_session_count;
$studioCount.html(studioGigCount > 0 ? 'Has played ' + profileUtils.gigMap[studioGigCount] + ' studio session gigs' : NOT_SPECIFIED_TEXT);
profileUtils.renderMusicalExperience(user, $screen)
}
function renderPerformanceSamples() {
// performance samples
var performanceSamples = user.performance_samples;
if (!performanceSamples || performanceSamples.length === 0) {
$noSamples.show();
hideElements([$jamkazamSamples, $soundCloudSamples, $youTubeSamples]);
if (isCurrentUser()) {
$btnAddRecordings.show();
}
} else {
$btnAddRecordings.hide();
$noSamples.hide();
// show samples section
var jamkazamSamples = profileUtils.jamkazamSamples(user.performance_samples);
if (!jamkazamSamples || jamkazamSamples.length === 0) {
hideElements([$jamkazamSamples]);
}
var soundCloudSamples = profileUtils.soundCloudSamples(user.performance_samples);
if (!soundCloudSamples || soundCloudSamples.length === 0) {
hideElements([$soundCloudSamples]);
}
var youTubeSamples = profileUtils.youTubeSamples(user.performance_samples);
if (!youTubeSamples || youTubeSamples.length === 0) {
hideElements([$youTubeSamples]);
}
$.each(jamkazamSamples, function(index, sample) {
$jamkazamSamples.append("<a class='jamkazam-playable' href='/recordings/" + sample.claimed_recording.id + "' rel='external'>" + formatTitle(sample.claimed_recording.name) + "</a><br/>");
});
$.each(soundCloudSamples, function(index, sample) {
$soundCloudSamples.append("<a class='sound-cloud-playable' href='' soundcloud_url='" + sample.url + "'>" + formatTitle(sample.description) + "</a><br/>");
});
$.each(youTubeSamples, function(index, sample) {
$youTubeSamples.append("<a class='youtube-playable' href='" + sample.url + "' rel='external'>" + formatTitle(sample.description) + "</a><br/>");
});
}
}
function formatTitle(title) {
return title && title.length > 30 ? title.substring(0, 30) + "..." : title;
profileUtils.renderPerformanceSamples(user, $screen)
}
function renderOnlinePresence() {
// online presences
var onlinePresences = user.online_presences;
if ((!onlinePresences || onlinePresences.length === 0) && !user.website) {
$noOnlinePresence.show();
hideElements([$userWebsite, $soundCloudPresence, $reverbNationPresence, $bandCampPresence,
$fandalismPresence, $youTubePresence, $facebookPresence, $twitterPresence]);
if (isCurrentUser()) {
$btnAddSites.show();
} else {
$btnAddSites.hide();
}
} else {
$btnAddSites.hide();
$noOnlinePresence.hide();
if (user.website) {
$userWebsite.find('a').attr('href', user.website);
}
var soundCloudPresences = profileUtils.soundCloudPresences(onlinePresences);
if (soundCloudPresences && soundCloudPresences.length > 0) {
$soundCloudPresence.find('a').attr('href', 'http://www.soundcloud.com/' + soundCloudPresences[0].username);
$soundCloudPresence.show();
} else {
$soundCloudPresence.hide();
}
var reverbNationPresences = profileUtils.reverbNationPresences(onlinePresences);
if (reverbNationPresences && reverbNationPresences.length > 0) {
$reverbNationPresence.find('a').attr('href', 'http://www.reverbnation.com/' + reverbNationPresences[0].username);
$reverbNationPresence.show();
} else {
$reverbNationPresence.hide();
}
var bandCampPresences = profileUtils.bandCampPresences(onlinePresences);
if (bandCampPresences && bandCampPresences.length > 0) {
$bandCampPresence.find('a').attr('href', 'http://' + bandCampPresences[0].username + '.bandcamp.com/');
$bandCampPresence.show();
} else {
$bandCampPresence.hide();
}
var fandalismPresences = profileUtils.fandalismPresences(onlinePresences);
if (fandalismPresences && fandalismPresences.length > 0) {
$fandalismPresence.find('a').attr('href', 'http://www.fandalism.com/' + fandalismPresences[0].username);
$fandalismPresence.show();
} else {
$fandalismPresence.hide();
}
var youTubePresences = profileUtils.youTubePresences(onlinePresences);
if (youTubePresences && youTubePresences.length > 0) {
$youTubePresence.find('a').attr('href', 'http://www.youtube.com/' + youTubePresences[0].username);
$youTubePresence.show();
} else {
$youTubePresence.hide();
}
var facebookPresences = profileUtils.facebookPresences(onlinePresences);
if (facebookPresences && facebookPresences.length > 0) {
$facebookPresence.find('a').attr('href', 'http://www.facebook.com/' + facebookPresences[0].username);
$facebookPresence.show();
} else {
$facebookPresence.hide();
}
var twitterPresences = profileUtils.twitterPresences(onlinePresences);
if (twitterPresences && twitterPresences.length > 0) {
$twitterPresence.find('a').attr('href', 'http://www.twitter.com/' + twitterPresences[0].username);
$twitterPresence.show();
} else {
$twitterPresence.hide();
}
}
profileUtils.renderOnlinePresence(user, $screen)
}
function renderInterests() {
@ -943,11 +776,11 @@
});
$bandsContent.append(bandHtml);
$('.profile-band-link-member-true').each(function(idx) {
$('.profile-band-link-member-true').each(function(idx) {
isBandMember ? $(this).show() : $(this).hide();
});
$('.profile-band-link-member-false').each(function(idx) {
$('.profile-band-link-member-false').each(function(idx) {
isBandMember ? $(this).hide() : $(this).show();
});
@ -1078,7 +911,7 @@
app.bindScreen('profile', screenBindings);
events();
initializeFeed();
player = new context.JK.SoundCloudPlayerDialog(app);
player = new context.JK.SoundCloudPlayerDialog(app);
}
this.initialize = initialize;

View File

@ -17,6 +17,21 @@
var FREE_SESSION_GENRE_TYPE = 'free_sessions';
var COWRITING_GENRE_TYPE = 'cowriting';
var NOT_SPECIFIED_TEXT = 'Not specified';
var proficiencyDescriptionMap = {
"1": "BEGINNER",
"2": "INTERMEDIATE",
"3": "EXPERT"
};
var proficiencyCssMap = {
"1": "proficiency-beginner",
"2": "proficiency-intermediate",
"3": "proficiency-expert"
};
// performance sample types
profileUtils.SAMPLE_TYPES = {
JAMKAZAM: {description: "jamkazam"},
@ -87,8 +102,8 @@
// Initialize standard profile help bubbles (topics stored as attributes on element):
profileUtils.initializeHelpBubbles = function(parentElement) {
$(".help", parentElement).each(function( index ) {
context.JK.helpBubble($(this), $(this).attr("help-topic"), {}, {})
})
context.JK.helpBubble($(this), $(this).attr("help-topic"), {}, {})
})
}
// profile genres
@ -270,4 +285,231 @@
return matches;
}
// Render band instruments to a string:
profileUtils.renderBandInstruments = function (band) {
var msg = ""
if (band.instruments) {
for (var i = 0; i < band.instruments.length; i++) {
var instrument = band.instruments[i]
var description = instrument.instrument_id
if (msg.length > 0) {
msg += ", "
}
msg += instrument
msg += "(" + proficiencyDescriptionMap[instrument.proficiency_level] + ")"
}
}
if (msg.length==0) {
msg = "None specified"
}
return msg
}
function formatTitle(title) {
return title && title.length > 30 ? title.substring(0, 30) + "..." : title;
}
profileUtils.renderMusicalExperience = function(player, $root) {
var $instruments = $root.find('#instruments');
var $musicianStatus = $root.find('#musician-status');
var $genres = $root.find('#genres');
var $concertCount = $root.find('#concert-count');
var $studioCount = $root.find('#studio-count');
$instruments.empty();
if (player.instruments) {
for (var i = 0; i < player.instruments.length; i++) {
var instrument = player.instruments[i];
var description = instrument.instrument_id;
var proficiency = instrument.proficiency_level;
var instrument_icon_url = context.JK.getInstrumentIcon256(description);
// add instrument info to layout
var template = $('#template-profile-instruments').html();
var instrumentHtml = context.JK.fillTemplate(template, {
instrument_logo_url: instrument_icon_url,
instrument_description: description,
proficiency_level: proficiencyDescriptionMap[proficiency],
proficiency_level_css: proficiencyCssMap[proficiency]
});
$instruments.append(instrumentHtml);
}
}
// status
var status = player.skill_level;
$musicianStatus.html(status ? profileUtils.skillLevelMap[status] + ' musician' : NOT_SPECIFIED_TEXT)
// genres
$genres.empty();
var profileGenres = profileUtils.profileGenreList(player.genres);
$genres.append(profileGenres.length > 0 ? profileGenres : NOT_SPECIFIED_TEXT);
// concert gigs
var concertCount = player.concert_count;
$concertCount.html(concertCount > 0 ? 'Has played ' + profileUtils.gigMap[concertCount] + ' live concert gigs' : NOT_SPECIFIED_TEXT);
// studio gigs
var studioCount = player.studio_session_count;
$studioCount.html(studioCount > 0 ? 'Has played ' + profileUtils.gigMap[studioCount] + ' studio session gigs' : NOT_SPECIFIED_TEXT);
}// function renderMusicalExperience
profileUtils.renderPerformanceSamples = function(player, $root, isOwner) {
// performance samples
var performanceSamples = player.performance_samples;
var $noSamples = $root.find('.no-samples');
var $jamkazamSamples = $root.find('.jamkazam-samples');
var $soundCloudSamples = $root.find('.soundcloud-samples');
var $youTubeSamples = $root.find('.youtube-samples');
var $btnAddRecordings = $root.find('.add-recordings');
if (!performanceSamples || performanceSamples.length === 0) {
$noSamples.show()
$jamkazamSamples.hide()
$soundCloudSamples.hide()
$youTubeSamples.hide()
if (isOwner) {
$btnAddRecordings.show();
}
} else {
$btnAddRecordings.hide();
$noSamples.hide();
// show samples section
var jamkazamSamples = profileUtils.jamkazamSamples(player.performance_samples);
if (!jamkazamSamples || jamkazamSamples.length === 0) {
$jamkazamSamples.hide()
} else {
$jamkazamSamples.show()
}
var soundCloudSamples = profileUtils.soundCloudSamples(player.performance_samples);
if (!soundCloudSamples || soundCloudSamples.length === 0) {
$soundCloudSamples.hide()
} else {
$soundCloudSamples.show()
}
var youTubeSamples = profileUtils.youTubeSamples(player.performance_samples);
if (!youTubeSamples || youTubeSamples.length === 0) {
$youTubeSamples.hide()
} else {
$youTubeSamples.show()
}
$.each(jamkazamSamples, function(index, sample) {
$jamkazamSamples.append("<a class='jamkazam-playable' href='/recordings/" + sample.claimed_recording.id + "' rel='external'>" + formatTitle(sample.claimed_recording.name) + "</a><br/>");
});
$.each(soundCloudSamples, function(index, sample) {
$soundCloudSamples.append("<a class='sound-cloud-playable' href='' soundcloud_url='" + sample.url + "'>" + formatTitle(sample.description) + "</a><br/>");
});
$.each(youTubeSamples, function(index, sample) {
$youTubeSamples.append("<a class='youtube-playable' href='" + sample.url + "' rel='external'>" + formatTitle(sample.description) + "</a><br/>");
});
}
}// function renderPerformanceSamples
profileUtils.renderOnlinePresence = function(player, $root, isOwner) {
var $noOnlinePresence = $root.find('.no-online-presence');
var $userWebsite = $root.find('.user-website');
var $soundCloudPresence = $root.find('.soundcloud-presence');
var $reverbNationPresence = $root.find('.reverbnation-presence');
var $bandCampPresence = $root.find('.bandcamp-presence');
var $fandalismPresence = $root.find('.fandalism-presence');
var $youTubePresence = $root.find('.youtube-presence');
var $facebookPresence = $root.find('.facebook-presence');
var $twitterPresence = $root.find('.twitter-presence');
var $btnAddSites = $root.find('.add-sites');
// online presences
var onlinePresences = player.online_presences;
if ((!onlinePresences || onlinePresences.length === 0) && !player.website) {
$noOnlinePresence.show()
$userWebsite.show()
$soundCloudPresence.show()
$reverbNationPresence.show()
$bandCampPresence.show()
$fandalismPresence.show()
$youTubePresence.show()
$facebookPresence.show()
$twitterPresence.show()
if (isOwner) {
$btnAddSites.show();
} else {
$btnAddSites.hide();
}
} else {
$btnAddSites.hide();
$noOnlinePresence.hide();
if (player.website) {
$userWebsite.find('a').attr('href', player.website);
}
var soundCloudPresences = profileUtils.soundCloudPresences(onlinePresences);
if (soundCloudPresences && soundCloudPresences.length > 0) {
$soundCloudPresence.find('a').attr('href', 'http://www.soundcloud.com/' + soundCloudPresences[0].username);
$soundCloudPresence.show();
} else {
$soundCloudPresence.hide();
}
var reverbNationPresences = profileUtils.reverbNationPresences(onlinePresences);
if (reverbNationPresences && reverbNationPresences.length > 0) {
$reverbNationPresence.find('a').attr('href', 'http://www.reverbnation.com/' + reverbNationPresences[0].username);
$reverbNationPresence.show();
} else {
$reverbNationPresence.hide();
}
var bandCampPresences = profileUtils.bandCampPresences(onlinePresences);
if (bandCampPresences && bandCampPresences.length > 0) {
$bandCampPresence.find('a').attr('href', 'http://' + bandCampPresences[0].username + '.bandcamp.com/');
$bandCampPresence.show();
} else {
$bandCampPresence.hide();
}
var fandalismPresences = profileUtils.fandalismPresences(onlinePresences);
if (fandalismPresences && fandalismPresences.length > 0) {
$fandalismPresence.find('a').attr('href', 'http://www.fandalism.com/' + fandalismPresences[0].username);
$fandalismPresence.show();
} else {
$fandalismPresence.hide();
}
var youTubePresences = profileUtils.youTubePresences(onlinePresences);
if (youTubePresences && youTubePresences.length > 0) {
$youTubePresence.find('a').attr('href', 'http://www.youtube.com/' + youTubePresences[0].username);
$youTubePresence.show();
} else {
$youTubePresence.hide();
}
var facebookPresences = profileUtils.facebookPresences(onlinePresences);
if (facebookPresences && facebookPresences.length > 0) {
$facebookPresence.find('a').attr('href', 'http://www.facebook.com/' + facebookPresences[0].username);
$facebookPresence.show();
} else {
$facebookPresence.hide();
}
var twitterPresences = profileUtils.twitterPresences(onlinePresences);
if (twitterPresences && twitterPresences.length > 0) {
$twitterPresence.find('a').attr('href', 'http://www.twitter.com/' + twitterPresences[0].username);
$twitterPresence.show();
} else {
$twitterPresence.hide();
}
}
}// function renderOnlinePresence
})(window, jQuery);

View File

@ -0,0 +1,3 @@
//= require ./react-components/actions/BroadcastActions
//= require ./react-components/stores/BroadcastStore
//= require_directory ./react-components

View File

@ -0,0 +1,45 @@
context = window
broadcastActions = window.JK.Actions.Broadcast;
rest = window.JK.Rest();
Broadcast = React.createClass({
displayName: 'Broadcast Notification'
handleNavigate: (e) ->
href = $(e.currentTarget).attr('href')
if href.indexOf('http') == 0
e.preventDefault()
window.JK.popExternalLink(href)
broadcastActions.hide.trigger()
notNow: (e) ->
e.preventDefault();
rest.quietBroadcastNotification({broadcast_id: this.props.notification.id})
broadcastActions.hide.trigger()
createMarkup: () ->
{__html: this.props.notification.message};
render: () ->
`<div className="broadcast-notification">
<div className="message" dangerouslySetInnerHTML={this.createMarkup()}/>
<div className="actions">
<div className="actionsAligner">
<a className="button-orange" onClick={this.handleNavigate}
href={this.props.notification.button_url}>{this.props.notification.button_label}</a>
<br/>
<a className="not-now" href="#" onClick={this.notNow}>not now, thanks</a>
</div>
</div>
</div>`
})
context.JK.Components.Broadcast = Broadcast
context.Broadcast = Broadcast

View File

@ -0,0 +1,27 @@
context = window
ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;
BroadcastHolder = React.createClass(
{
displayName: 'Broadcast Notification Holder',
mixins: [Reflux.connect(context.JK.Stores.Broadcast, 'notification')]
render: ->
notification = []
if this.state.notification
notification.push(`<Broadcast key={this.state.notification.id} notification={this.state.notification}/>`)
`<div id="broadcast-notification-holder" className="broadcast-notification-holder" >
<ReactCSSTransitionGroup transitionName="bn-slidedown">
{notification}
</ReactCSSTransitionGroup>
</div>`
});
context.JK.Components.BroadcastHolder = BroadcastHolder
context.BroadcastHolder = BroadcastHolder

View File

@ -0,0 +1,8 @@
context = window
BroadcastActions = Reflux.createActions({
load: {asyncResult: true},
hide: {}
})
context.JK.Actions.Broadcast = BroadcastActions

View File

@ -0,0 +1,31 @@
$ = jQuery
context = window
logger = context.JK.logger
broadcastActions = context.JK.Actions.Broadcast
rest = context.JK.Rest()
broadcastActions.load.listenAndPromise(rest.getBroadcastNotification);
BroadcastStore = Reflux.createStore(
{
listenables: broadcastActions
onLoad: () ->
logger.debug("loading broadcast notification...")
onLoadCompleted: (response) ->
logger.debug("broadcast notification sync completed")
this.trigger(response)
onLoadFailed: (jqXHR) ->
if jqXHR.status != 404
logger.error("broadcast notification sync failed")
onHide: () ->
this.trigger(null)
}
)
context.JK.Stores.Broadcast = BroadcastStore

View File

@ -0,0 +1,3 @@
window.JK.Actions = {}
window.JK.Stores = {}
window.JK.Components = {}

View File

@ -14,6 +14,7 @@
var logger = context.JK.logger;
var self = this;
var webcamViewer = new context.JK.WebcamViewer()
var ChannelGroupIds = context.JK.ChannelGroupIds;
var defaultParticipant = {
tracks: [{
@ -39,23 +40,6 @@
height: 83
};
// Recreate ChannelGroupIDs ENUM from C++
var ChannelGroupIds = {
"MasterGroup": 0,
"MonitorGroup": 1,
"AudioInputMusicGroup": 2,
"AudioInputChatGroup": 3,
"MediaTrackGroup": 4,
"StreamOutMusicGroup": 5,
"StreamOutChatGroup": 6,
"UserMusicInputGroup": 7,
"UserChatInputGroup": 8,
"PeerAudioInputMusicGroup": 9,
"PeerMediaTrackGroup": 10,
"JamTrackGroup": 11,
"MetronomeGroup": 12
};
var METRO_SOUND_LOOKUP = {
0 : "BuiltIn",
1 : "SineWave",

View File

@ -9,8 +9,8 @@ context.JK.SiteValidator = class SiteValidator
@rest = context.JK.Rest()
@site_type = site_type
@input_div = $(".site_validator."+site_type+"_validator", parent)
@data_input = @input_div.find('input')
@data_input = @input_div.find('input')
@logger = context.JK.logger
@spinner = @input_div.find('span.spinner-small')
@checkmark = @input_div.find('.validate-checkmark')
@ -34,7 +34,7 @@ context.JK.SiteValidator = class SiteValidator
@site_status = null
dataToValidate: () =>
url = @data_input.val()
url = @data_input.val()
if url && 0 < url.length
url.substring(0,2000)
else
@ -50,7 +50,7 @@ context.JK.SiteValidator = class SiteValidator
@checkmark.hide()
yn
didBlur: () =>
didBlur: () =>
if this.showFormatStatus()
this.validateSite()
@ -100,14 +100,14 @@ context.JK.SiteValidator = class SiteValidator
@checkmark.show()
else
@checkmark.hide()
siteIsValid: () =>
siteIsValid: () =>
this.setSiteStatus(true)
siteIsInvalid: () =>
siteIsInvalid: () =>
this.setSiteStatus(false)
renderErrors: (errors) =>
renderErrors: (errors) =>
errdiv = @input_div.find('.error')
if errmsg = context.JK.format_errors("site", errors)
errdiv.show()
@ -120,7 +120,7 @@ context.JK.SiteValidator = class SiteValidator
dfr = $.Deferred()
if null == @site_status
@deferred_status_check = dfr
this.validateSite()
this.validateSite()
else
if true == @site_status
dfr.resolve()
@ -128,9 +128,9 @@ context.JK.SiteValidator = class SiteValidator
dfr.reject()
return dfr.promise()
context.JK.RecordingSourceValidator = class RecordingSourceValidator extends SiteValidator
constructor: (site_type, success_callback, fail_callback, parent) ->
context.JK.RecordingSourceValidator = class RecordingSourceValidator extends SiteValidator
constructor: (site_type, success_callback, fail_callback, parent) ->
super(site_type, success_callback, fail_callback, parent)
@recording_sources = []
@is_rec_src = true
@ -142,7 +142,7 @@ context.JK.RecordingSourceValidator = class RecordingSourceValidator extends Sit
super()
if sources
@recording_sources = sources
@add_btn.on 'click', =>
@add_btn.off('click').on 'click', =>
this.attemptAdd()
processSiteCheckSucceed: (response) =>
@ -163,7 +163,7 @@ context.JK.RecordingSourceValidator = class RecordingSourceValidator extends Sit
if @site_fail_callback
@site_fail_callback(@input_div)
didBlur: () =>
didBlur: () =>
# do nothing, validate on add only
validateSite: () =>
@ -177,13 +177,14 @@ context.JK.RecordingSourceValidator = class RecordingSourceValidator extends Sit
removeRecordingId: (recording_id) =>
start_len = @recording_sources.length
@recording_sources = $.grep @recording_sources, (src_data) ->
src_data['recording_id'] != recording_id
@recording_sources = @recording_sources.filter (src) ->
src["recording_id"] isnt recording_id.toString()
start_len != @recording_sources.length
containsRecordingUrl: (url) =>
vals = $.grep @recording_sources, (src_data) ->
src_data['url'] == url
src_data['url'] is url
0 < vals.length
recordingSources: () =>

View File

@ -20,7 +20,7 @@
var userTracks = context.JK.TrackHelpers.getUserTracks(jamClient, allTracks);
var backingTracks = context.JK.TrackHelpers.getBackingTracks(jamClient, allTracks);
var metronomeTracks = context.JK.TrackHelpers.getTracks(jamClient, 12);
var metronomeTracks = context.JK.TrackHelpers.getTracks(jamClient, 16);
return {
userTracks: userTracks,
@ -51,7 +51,7 @@
// allTracks is the result of SessionGetAllControlState; as an optimization
getBackingTracks: function(jamClient, allTracks) {
var mediaTracks = context.JK.TrackHelpers.getTracks(jamClient, 4, allTracks);
var mediaTracks = context.JK.TrackHelpers.getTracks(jamClient, 6, allTracks);
var backingTracks = []
context._.each(mediaTracks, function(mediaTrack) {
@ -80,7 +80,7 @@
var localMusicTracks = [];
var i;
localMusicTracks = context.JK.TrackHelpers.getTracks(jamClient, 2, allTracks);
localMusicTracks = context.JK.TrackHelpers.getTracks(jamClient, 4, allTracks);
var trackObjects = [];

View File

@ -1,11 +1,11 @@
@import "common.css.scss";
@import "site_validator.css.scss";
.profile-online-sample-controls {
.profile-online-sample-controls {
table.profile-table {
width: 100%;
tr:nth-child(even) td {
padding: 0.25em 0.25em 1em 0.25em;
padding: 0.25em 0.25em 1em 0.25em;
vertical-align: top;
}
tr:nth-child(odd) td {
@ -14,10 +14,23 @@
}
}
.sample-list {
border: 1px inset #cfcfcf;
padding: 0.5em;
.empty {
font-style: italic;
}
min-height: 150px;
overflow: scroll;
.close-button {
cursor:pointer;
}
}
table.control-table {
width: 100%;
}
.sample-row {
position: relative;
clear: both;
@ -29,12 +42,12 @@
}
.presence {
margin: 3px 30px 15px 0px;
margin: 3px 30px 15px 0px;
}
.site_validator {
a, .spinner-small {
margin: 1px 1px 2px 2px;
margin: 1px 1px 2px 2px;
vertical-align: top;
}
}

View File

@ -15,6 +15,16 @@
}
}
table.summary-table {
tr {
td {
padding-right: 1em;
}
}
}
// Mimic style of easydropdown selects:
input[type="number"] {
border-radius: 6px;
@ -43,18 +53,7 @@
}
}
tr:nth-child(even) td {
padding-bottom: 1em;
}
td.band-biography, td.tdBandGenres {
height:100%;
vertical-align: top;
#band-biography {
}
}
.band-setup-genres {
width:100%;
@ -190,6 +189,20 @@
border-radius:44px;
}
.band-entry {
.item-caption {
font-size: 1.4em;
font-weight: bold;
margin: 0.25em 0em 0.25em 0em;
}
.item-content {
font-size: 1.1em;
margin: 0.25em 0em 0.25em 0em;
}
margin: 0em 0em 1.5em 0em;
}
// .band-name, .band-photo {
// display: inline;
// }
@ -392,6 +405,19 @@
table.band-form-table {
width: 100%;
margin: 1em;
tr:nth-child(even) td {
padding-bottom: 1em;
}
td.band-biography, td.tdBandGenres {
height:100%;
vertical-align: top;
#band-biography {
}
}
}
.easydropdown {

View File

@ -84,4 +84,5 @@
*= require ./jamTrackPreview
*= require users/signinCommon
*= require landings/partner_agreement_v1
*= require_directory ./react-components
*/

View File

@ -12,7 +12,10 @@
div.logo, div.item {
text-align: bottom;
margin-left: 1em;
}
.online-presence-option, .performance-sample-option {
margin-right: 1em;
}
img.logo {
@ -35,11 +38,11 @@
}
.profile-body {
}
.profile-header {
padding:10px 20px;
position: relative;
position: relative;
}
.profile-header h2 {
@ -49,11 +52,20 @@
margin: 0px 0px 0px 0px;
}
.profile-about-right .section-header {
font-weight:600;
font-size:18px;
float:left;
margin: 0px 0px 10px 0px;
.profile-about-right {
.section-header {
font-weight:600;
font-size:18px;
float:left;
margin: 0px 0px 10px 0px;
}
.section-content {
font-weight:normal;
font-size:1.2em;
float:left;
margin: 0px 0px 10px 0px;
}
}
.profile-details {
@ -241,7 +253,7 @@
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
box-sizing:border-box;
.result-name {
font-size: 12px;
font-weight: bold;
@ -267,11 +279,11 @@
height:24px;
width:24px;
margin-right:2px;
&:last-child {
margin-right:0px;
}
}
}
.button-row {
@ -343,14 +355,14 @@
display:none;
}
#history-content {
#history-content, #band-profile-history {
padding:0 10px 0 20px;
width:100%;
position:relative;
height:100%;
@include border_box_sizing;
#user-feed-controls {
#user-feed-controls, #band-feed-controls {
width:100%;
@include border_box_sizing;
position:relative;

View File

@ -0,0 +1,79 @@
@import 'client/common';
[data-react-class="BroadcastHolder"] {
position:absolute;
min-height:60px;
top:62px;
@include border_box_sizing;
.broadcast-notification {
position:absolute;
border-width:1px;
border-color:$ColorScreenPrimary;
border-style:solid;
padding:5px 12px;
height:100%;
width:100%;
left:0;
top:0;
overflow:hidden;
margin-left:60px;
@include border_box_sizing;
}
.message {
float:left;
width:calc(100% - 150px);
font-size:12px;
}
.actions {
float:right;
text-align: right;
vertical-align: middle;
display:inline;
height:100%;
width:150px;
}
.actionsAligner {
display:inline-block;
vertical-align:middle;
text-align:center;
}
a { display:inline-block; }
.button-orange {
font-size:16px;
position:relative;
top:8px;
}
.not-now {
font-size:11px;
top:13px;
position:relative;
}
}
.bn-slidedown-enter {
max-height:0;
opacity: 0.01;
transition: max-height .5s ease-in;
}
.bn-slidedown-enter.bn-slidedown-enter-active {
max-height:60px;
opacity: 1;
}
.bn-slidedown-leave {
max-height:60px;
transition: max-height .5s ease-in;
}
.bn-slidedown-leave.bn-slidedown-leave-active {
max-height:0;
}

View File

@ -13,7 +13,7 @@ class ApiUsersController < ApiController
:band_invitation_index, :band_invitation_show, :band_invitation_update, # band invitations
:set_password, :begin_update_email, :update_avatar, :delete_avatar, :generate_filepicker_policy,
:share_session, :share_recording,
:affiliate_report, :audio_latency]
:affiliate_report, :audio_latency, :broadcast_notification]
respond_to :json
@ -856,6 +856,30 @@ class ApiUsersController < ApiController
end
end
def broadcast_notification
@broadcast = BroadcastNotification.next_broadcast(current_user)
if @broadcast
# mark it as viewed
@broadcast.did_view(current_user)
respond_with_model(@broadcast)
else
render json: { message: 'Not Found'}, status: 404
end
end
# used to hide a broadcast notification from rotation temporarily
def quiet_broadcast_notification
@broadcast = BroadcastNotificationView.find_by_broadcast_notification_id_and_user_id(params[:broadcast_id], current_user.id)
if @broadcast
@broadcast.active_at = Date.today + 14 # 14 days in the future we'll re-instas
@broadcast.save
end
render json: { }, status: 200
end
###################### RECORDINGS #######################
# def recording_index
# @recordings = User.recording_index(current_user, params[:id])

View File

@ -27,6 +27,18 @@ child :genres => :genres do
#partial('api_genres/index', :object => @band.genres)
end
child :performance_samples => :performance_samples do
attributes :id, :url, :service_type, :claimed_recording_id, :service_id, :description
child :claimed_recording => :claimed_recording do
attributes :id, :name
end
end
child :online_presences => :online_presences do
attributes :id, :service_type, :username
end
if current_user
node :is_following do |uu|
current_user.following?(@band)

View File

@ -0,0 +1,3 @@
object @broadcast
attributes :id, :message, :button_label, :button_url

View File

@ -105,19 +105,19 @@
</div>
<div class="right">
<a id="account-edit-profile-link" href="#" class="button-orange">UPDATE</a>
<a href="#" class="account-edit-profile-link button-orange">UPDATE</a>
</div>
<br clear="all" />
<hr />
<div class="account-left">
<h2>jamtracks:</h2>
<h2>jamtracks:</h2>
</div>
<div class="account-mid subscriptions">
<strong class="jamtrack-license-detail">
{{data.licenseDetail}}
{{data.licenseDetail}}
</strong>
<br clear="all" />
<a href="/corp/terms#purchasing-jamtracks" rel="external" class="view-license" id="account-view-license-link">JamTracks License</a>

View File

@ -85,7 +85,7 @@
</div>
<div class="right field actions">
<a id="account-edit-profile-cancel" class="button-grey">CANCEL</a>&nbsp;&nbsp;<a id="account-edit-profile-submit" class="button-orange">SAVE &amp; NEXT</a>
<a class="button-grey account-edit-profile-cancel">CANCEL</a>&nbsp;&nbsp;<a class="account-edit-profile-submit button-orange">SAVE &amp; NEXT</a>
</div>
</div>

View File

@ -66,9 +66,9 @@
<br/><br/>
<div class="right field actions">
<a id="account-edit-profile-cancel" class="button-grey">CANCEL</a>&nbsp;&nbsp;
<a id="account-edit-profile-back" class="button-grey">BACK</a>&nbsp;&nbsp;
<a id="account-edit-profile-submit" class="button-orange">SAVE &amp; NEXT</a>
<a class="account-edit-profile-cancel button-grey">CANCEL</a>&nbsp;&nbsp;
<a class="account-edit-profile-back button-grey">BACK</a>&nbsp;&nbsp;
<a class="account-edit-profile-submit button-orange">SAVE &amp; NEXT</a>
</div>
<div class="clearall"></div>

View File

@ -207,9 +207,9 @@
<br/><br/>
<div class="right field actions">
<a id="account-edit-profile-cancel" class="button-grey">CANCEL</a>&nbsp;&nbsp;
<a id="account-edit-profile-back" class="button-grey">BACK</a>&nbsp;&nbsp;
<a id="account-edit-profile-submit" class="button-orange">SAVE &amp; NEXT</a>
<a class="account-edit-profile-cancel button-grey">CANCEL</a>&nbsp;&nbsp;
<a class="account-edit-profile-back button-grey">BACK</a>&nbsp;&nbsp;
<a class="account-edit-profile-submit button-orange">SAVE &amp; NEXT</a>
</div>
<div class="clearall"></div>

View File

@ -13,15 +13,15 @@
<form id="account-edit-profile-samples-form">
<h2>edit profile: online presence &amp; performance samples</h2>
<%= render "profile_online_sample_controls" %>
<%= render "profile_edit_presence_controls" %>
<div class="clearall"></div>
<br/><br/>
<div class="right field actions">
<a id="account-edit-profile-cancel" class="button-grey">CANCEL</a>&nbsp;
<a id="account-edit-profile-back" class="button-grey">BACK</a>&nbsp;
<a id="account-edit-profile-submit" class="button-orange">SAVE &amp; FINISH</a>
<a class="account-edit-profile-cancel button-grey">CANCEL</a>&nbsp;
<a class="account-edit-profile-back button-grey">BACK</a>&nbsp;
<a class="account-edit-profile-submit button-orange">SAVE &amp; FINISH</a>
</div>
<div class="clearall"></div>

View File

@ -14,12 +14,17 @@
<div class="profile-header profile-head">
<h2 id="band-profile-name"></h2>
<div class="left">
<a id="btn-edit-band-profile" class="button-orange">EDIT PROFILE</a>
<a id="btn-edit-band-members" class="button-orange">INVITE</a>
<a id="btn-edit-band-delete" class="button-orange">DELETE</a>
</div>
<div class="band-profile-status">
</div>
<div class="right">
<a id="btn-follow-band" class="button-orange">FOLLOW</a>
<a id="btn-edit-band-profile" class="button-orange">EDIT PROFILE</a>
<!-- <a id="btn-edit-band-profile" class="button-orange">EDIT PROFILE</a> -->
</div>
<br clear="all" /><br />
@ -43,7 +48,7 @@
<div id="band-profile-about" class="profile-body-content">
<div class="band-profile-wrapper">
<!-- stats & location -->
<div class="band-profile-about-left">
<div class="profile-about-left">
<h3>Location:</h3><br />
<span id="band-profile-location"></span><br /><br /><br />
<h3>Stats:</h3><br />
@ -51,26 +56,105 @@
<span id="band-profile-session-stats"></span><br />
<span id="band-profile-recording-stats"></span><br />
</div>
<div class="band-profile-about-right">
<div class="left">
<a id="btn-edit-band-info" class="button-orange">EDIT</a>
<a id="btn-edit-band-members" class="button-orange">INVITE</a>
<a id="btn-edit-band-delete" class="button-orange">DELETE</a>
<div class="profile-about-right">
<div class="band-entry">
<div class="item-caption">Bio</div>
<div class="item-content" id="band-profile-biography"></div>
<div class="item-content">
<a id="btn-edit-band-bio" class=".edit-bio">Edit Bio</a>
</div>
</div>
<br clear="all" /><br />
<p id="band-profile-biography"></p>
</div>
<div class="band-profile-about-right">
<p><a id="band-profile-website" target="_blank" rel="external"></a></p><br />
<div class="profile-about-right">
<div class="band-entry">
<div class="item-caption">Musical Experience</div>
<div class="item-content">
<table class="summary-table">
<tr>
<td>Genres:</td>
<td class="experience-genres">Genres</td>
</tr>
<tr>
<td>Concert Gigs:</td>
<td class="experience-gigs"></td>
</tr>
<tr>
<td>Status:</td>
<td class="experience-status"></td>
</tr>
<tr>
<td>Type:</td>
<td class="experience-type"></td>
</tr>
</table>
</div>
</div>
</div>
<br clear="all" />
<div class="profile-about-right">
<div class="band-entry">
<div class="item-caption">Performance Samples</div>
<div class="item-content">
<%=render "profile_summary_performance_samples" %>
</div>
</div>
</div>
<div class="profile-about-right">
<div class="band-entry">
<div class="item-caption">Online Presence</div>
<div class="item-content">
<%=render "profile_summary_online_presence" %>
</div>
</div>
</div>
<div class="profile-about-right">
<div class="band-entry">
<div class="item-caption">Current Interests</div>
<ul>
<li class="interests-new-members hidden">
<span>Our band is looking for new members who play our genre(s) of music and can play the following:</span>
<span class="new-member-details"></span>
</li>
<li class="interests-paid-gigs hidden">
<span>Our band is available for hire to perform at concerts and events for</span>
<span class="paid-gig-rate">
</span>
<span class="paid-gig-minimum">
</span>
</li>
<li class="interests-free-gigs hidden">
<span>Our band is available to perform at concerts and events at no charge as we are currently building our live performance experience.</span>
</li>
</ul>
</div>
</div>
</div>
</div>
<div id="band-profile-history" class="band-profile-wrapper">
<div class="content-body-scroller">
<br clear="all" />
</div>
<div id="band-profile-history" class="profile-body-content band-profile-wrapper">
<div class="band-profile-history-feed">
<%= form_tag('', {:id => 'band-feed-form', :class => 'inner-content'}) do %>
<%= render(:partial => "web_filter", :locals => {:search_type => Search::PARAM_FEED, :id => 'band-feed-controls'}) %>
<div class="filter-body">
<div class="content-body-scroller" id="band-profile-feed-scroller">
<div class="profile-wrapper">
<div class="feed-content" id="band-profile-feed-entry-list"></div>
<div id="band-profile-end-of-feeds-list" class="end-of-list">No more feed entries</div>
<div id="band-profile-loading-feeds" class="infinite-scroll-loader" style="padding:5px">Loading ...</div>
</div>
</div>
</div>
<% end %>
</div>
</div>
<div id="band-profile-members" class="band-profile-wrapper profile-body-content f11">
<br clear="all" />
</div>

View File

@ -7,14 +7,14 @@
= render "screen_navigation"
.content-body
.content-body-scroller
form#band-setup-form
form#band-setup-form
#band-setup-step-0.band-step.content-wrapper
h2 set up band: basics
table.band-form-table
tr
td colspan="2"
tr#name_row
tr#name_row
td colspan="2"
.band-photo.hidden
span.field
@ -23,29 +23,25 @@
span.field
a#band-change-photo.small.ml20 href="#"
| Upload band photo.
.band-name
.field.band-field
label for="band-name"
| Band Name:
input#band-name type="text" maxlength="1024" value=""
/ td#tdBandWebsite[]
/ .field
/ label for="band-website"
/ | Web Site:
/ input#band-website[type="text" maxlength="4000" value=""]
input#band-name type="text" maxlength="1024" value=""
tr
td.band-country
.field.band-field
label for="band-country"
| Country:
select#band-country
td.band-biography rowspan="3"
td.band-biography rowspan="3"
.field.band-field
label for="band-biography"
| Description / Bio:
textarea#band-biography rows="8"
tr
tr
td.band-region
.field.band-field
label for="band-region"
@ -58,8 +54,8 @@
| City:
select#band-city
#band-setup-step-1.band-step.content-wrapper
#band-setup-step-1.band-step.content-wrapper
h2 set up band: musical experience
table.band-form-table
@ -73,7 +69,7 @@
td
.field
label for="band-type" Type
select#band-type.easydropdown name="band_type"
select#band-type.easydropdown name="band_type"
option value="" Not Specified
option value="virtual" Virtual
option value="physical" Physical
@ -82,7 +78,7 @@
td
.field
label for="band-status" Status
select#band-status.easydropdown name="band_status"
select#band-status.easydropdown name="band_status"
option value="" Not Specified
option value="amateur" Amateur
option value="professional" Professional
@ -91,66 +87,66 @@
td
.field
label for="concert-count" Concert Gigs Played
select#concert-count.easydropdown name="concert_count"
select#concert-count.easydropdown name="concert_count"
option value="" Not Specified
option value="0" Zero
option value="1" Under 10
option value="2" 10 to 50
option value="3" 50 to 100
option value="4" Over 100
#band-setup-step-2.band-step.content-wrapper
option value="4" Over 100
#band-setup-step-2.band-step.content-wrapper
h2 set up band: current interests
table.band-form-table
tr
td
label.strong-label for="new-member"
label.strong-label for="new-member"
| We want to add a new member &nbsp;
a.help help-topic="band-profile-add-new-member" [?]
td.new-member-dependent
label for="desired-experience"
a.help help-topic="band-profile-add-new-member" [?]
td.new-member-dependent
label for="desired-experience"
| Desired Experience &nbsp;
a#choose-desired-experience select
td.new-member-dependent
td.new-member-dependent
label for="play-commitment" Play Commitment
td.new-member-dependent
label for="touring-option" Touring Option
tr
td
.radio-field
input#new-member-yes.iradio-inline.dependent-master type="radio" name="add_new_members" value='yes'
.radio-field
input#new-member-yes.iradio-inline.dependent-master type="radio" name="add_new_members" value='yes'
label for='new-member-yes' Yes
.radio-field
input#new-member-no.iradio-inline.dependent-master type="radio" name="add_new_members" value='no'
label for='new-member-no' No
td.new-member-dependent
#desired-experience-label None specified
td.new-member-dependent
select#play-commitment.easydropdown name="play_commitment"
.radio-field
input#new-member-no.iradio-inline.dependent-master type="radio" name="add_new_members" value='no'
label for='new-member-no' No
td.new-member-dependent
#desired-experience-label None specified
td.new-member-dependent
select#play-commitment.easydropdown name="play_commitment"
option value="1" Infrequent
option value="2" Once a Week
option value="3" 2-3 Times Per Week
option value="4" 4+ Times Per Week
option value="4" 4+ Times Per Week
td.new-member-dependent
select#touring-option.easydropdown name="touring_option"
select#touring-option.easydropdown name="touring_option"
option value="yes" Yes
option value="no" No
tr
td
label.strong-label for="paid-gigs"
label.strong-label for="paid-gigs"
| We want to play paid gigs &nbsp;
a.help help-topic="band-profile-play-paid-gigs" [?]
a.help help-topic="band-profile-play-paid-gigs" [?]
td.paid-gigs-dependent
label for="hourly-rate" Hourly Rate:
td.paid-gigs-dependent
label for="gig-minimum" Gig Minimum:
tr
td
.radio-field
input#paid-gigs-yes.iradio-inline.dependent-master type="radio" name="paid_gigs" value='yes'
.radio-field
input#paid-gigs-yes.iradio-inline.dependent-master type="radio" name="paid_gigs" value='yes'
label for="paid-gigs-yes" Yes
.radio-field
input#paid-gigs-no.iradio-inline.dependent-master type="radio" name="paid_gigs" value='no'
.radio-field
input#paid-gigs-no.iradio-inline.dependent-master type="radio" name="paid_gigs" value='no'
label for="paid-gigs-no" No
td.paid-gigs-dependent
input#hourly-rate type="number" name="hourly_rate"
@ -158,24 +154,24 @@
input#gig-minimum type="number" name="gig_minimum"
tr
td
label.strong-label for="free-gigs"
label.strong-label for="free-gigs"
| We want to play free gigs &nbsp;
a.help help-topic="band-profile-play-free-gigs" [?]
a.help help-topic="band-profile-play-free-gigs" [?]
tr
td
.radio-field
input#free-gigs-yes.iradio-inline type="radio" name="free_gigs" value='yes'
.radio-field
input#free-gigs-yes.iradio-inline type="radio" name="free_gigs" value='yes'
label for="free-gigs-yes" Yes
.radio-field
input#free-gigs-no.iradio-inline type="radio" name="free_gigs" value='no'
label for="free-gigs-no" No
.radio-field
input#free-gigs-no.iradio-inline type="radio" name="free_gigs" value='no'
label for="free-gigs-no" No
#band-setup-step-3.band-step.content-wrapper
#band-setup-step-3.band-step.content-wrapper
h2 set up band: online presence & performance samples
= render "clients/profile_online_sample_controls"
#band-setup-step-4.band-step.content-wrapper
h2 invite members
= render "clients/profile_edit_presence_controls"
#band-setup-step-4.band-step.content-wrapper
h2 set up band: invite members
br
#band-setup-invite-musicians
br
@ -201,19 +197,11 @@
= image_tag("content/icon_google.png", :size => "24x24", :align => "absmiddle")
.right.mt5.ml5
| Google+
/ br clear="all"
/ .right
/ a#btn-band-setup-back.button-grey
/ | BACK
/ |   
/ a#btn-band-setup-save.button-orange
/ | CREATE BAND
/ .clearall
br clear="all"
.right
a#btn-band-setup-cancel.nav-button.button-grey
| CANCEL   
| CANCEL   
a#btn-band-setup-back.nav-button.button-grey.hidden
| BACK
a#btn-band-setup-next.nav-button.button-orange
@ -230,7 +218,7 @@ script#template-band-setup-genres type="text/template"
script#template-band-invitation type="text/template"
.invitation user-id="{{userId}}"
.invitation user-id="{{userId}}"
| {{userName}}
a
img src="shared/icon_delete_sm.png" width="13" height="13"

View File

@ -267,17 +267,17 @@ script type="text/template" id="template-help-profile-interests-virtual-band"
| For musicians who want to join a band that plays only online on JamKazam and does not travel and meet in person at a physical space to play.
script type="text/template" id="template-help-profile-interests-traditional-band"
| For musicians who want to join a more traditional band that meets in person at a physical space to play. It may also play online on JamKazam.
| For musicians who want to join a more traditional band that meets in person at a physical space to play. It may also play online on JamKazam.
script type="text/template" id="template-help-profile-interests-paid-sessions"
| For professional session musicians who are qualified and interested in playing paid recording session gigs for bands, composers, and producers.
| For professional session musicians who are qualified and interested in playing paid recording session gigs for bands, composers, and producers.
script type="text/template" id="template-help-profile-interests-free-sessions"
| For skilled musicians who are interested in playing free recording session gigs for bands, composers, and producers, either for fun or to build experience and resume.
| For skilled musicians who are interested in playing free recording session gigs for bands, composers, and producers, either for fun or to build experience and resume.
script type="text/template" id="template-help-profile-interests-cowrite-partners"
| For composers and songwriters who want to collaborate with others in composing and creating new music.
| For composers and songwriters who want to collaborate with others in composing and creating new music.
script type="text/template" id="template-help-band-profile-add-new-member"
| For bands that want to add one or more new members and let the JamKazam community of musicians know your band is looking for new members.
@ -285,7 +285,7 @@ script type="text/template" id="template-help-band-profile-play-paid-gigs"
| For professional bands that are qualified and interested in playing paid gigs at music venues and other events.
script type="text/template" id="template-help-band-profile-play-free-gigs"
| For bands that are interested in playing free gigs, either for fun or to build experience.
| For bands that are interested in playing free gigs, either for fun or to build experience.
script type="text/template" id="template-help-jamtrack-landing-preview"
.jamtrack-landing-preview.big-help

View File

@ -10,7 +10,7 @@
/ Grid is the count of the smallest spaces, then
/ individual spells span those spaces
-if @nativeClient
.grid layout-grid="2x12"
.grid layout-grid="2x12"
.homecard.createsession layout-grid-columns="4" layout-grid-position="0,0" layout-grid-rows="1" layout-link="createSession" type="createSession" class="#{logged_in_not_logged_in_class}"
h2 create session
.homebox-info
@ -45,7 +45,7 @@
.homebox-info
/! free service level
-else
.grid layout-grid="2x12"
.grid layout-grid="2x12"
.homecard.createsession layout-grid-columns="4" layout-grid-position="0,0" layout-grid-rows="1" layout-link="createSession" type="createSession" class="#{logged_in_not_logged_in_class}"
h2 create session
.homebox-info

View File

@ -99,20 +99,9 @@
<div class="section-header">Performance Samples</div>
<br clear="all" />
<div id="no-samples" class="left item">None specified</div>
<div id="jamkazam-samples" class="left logo">
<img src="/assets/header/logo.png" class="logo" /><br/>
</div>
<div id="soundcloud-samples" class="left logo">
<img src="/assets/content/soundcloud-logo.png" class="logo" /><br/>
</div>
<div id="youtube-samples" class="left logo">
<img src="/assets/content/youtube-logo.png" class="logo" /><br/>
</div>
<%=render "profile_summary_performance_samples" %>
<br clear="all" />
<div class="left item"><a href="/client#/account/profile/samples" class="add-recordings">Add Recordings</a></div>
<br clear="all" />
@ -120,39 +109,8 @@
<div class="section-header">Online Presence</div>
<br clear="all" />
<div id="no-online-presence" class="left item">None specified</div>
<div id="user-website" class="left logo">
<a rel="external"><img src="/assets/content/website-logo.png" class="logo" /></a>
</div>
<div id="soundcloud-presence" class="left logo">
<a rel="external"><img src="/assets/content/soundcloud-logo.png" class="logo" /></a>
</div>
<div id="reverbnation-presence" class="left logo">
<a rel="external"><img src="/assets/content/reverbnation-logo.png" class="logo" /></a>
</div>
<div id="bandcamp-presence" class="left logo">
<a rel="external"><img src="/assets/content/bandcamp-logo.png" class="logo" /></a>
</div>
<div id="fandalism-presence" class="left logo">
<a rel="external"><img src="/assets/content/fandalism-logo.png" class="logo" /></a>
</div>
<div id="youtube-presence" class="left logo">
<a rel="external"><img src="/assets/content/youtube-logo.png" class="logo" /></a>
</div>
<div id="facebook-presence" class="left logo">
<a rel="external"><img src="/assets/content/facebook-logo.png" class="logo" /></a>
</div>
<div id="twitter-presence" class="left logo">
<a rel="external"><img src="/assets/content/twitter-logo.png" class="logo" /></a>
</div>
<%=render "profile_summary_online_presence" %>
<br clear="all" />
<div class="left item"><a href="/client#/account/profile/samples">Add Sites</a></div>

View File

@ -65,7 +65,7 @@
td colspan="33.33%": label JamKazam Recordings:
td colspan="33.33%": label SoundCloud Recordings (URL):
td colspan="33.33%": label YouTube Videos (URL):
tr
tr.add-samples-controls-row
td colspan="33.33%"
a.btn-add-jk-recording.button-grey BROWSE
td colspan="33.33%"
@ -82,7 +82,13 @@
td
a.btn-add-youtube-video.button-grey.add-recording-source ADD
span.spinner-small
tr
td colspan="33.33%": .sample-list
td colspan="33.33%": .sample-list
td colspan="33.33%": .sample-list
tr.add-samples-list-row
td colspan="33.33%"
.sample-list source-type='jamkazam'
.empty No recordings
td colspan="33.33%"
.sample-list source-type='soundcloud'
.empty No recordings
td colspan="33.33%"
.sample-list source-type='youtube'
.empty No recordings

View File

@ -0,0 +1,26 @@
.no-online-presence.left.online-presence-option.hidden
| None specified
.user-website.left.logo.online-presence-option.hidden
a rel="external"
img.logo src="/assets/content/website-logo.png"
.soundcloud-presence.left.logo.online-presence-option.hidden
a rel="external"
img.logo src="/assets/content/soundcloud-logo.png"
.reverbnation-presence.left.logo.online-presence-option.hidden
a rel="external"
img.logo src="/assets/content/reverbnation-logo.png"
.bandcamp-presence.left.logo.online-presence-option.hidden
a rel="external"
img.logo src="/assets/content/bandcamp-logo.png"
.fandalism-presence.left.logo.online-presence-option.hidden
a rel="external"
img.logo src="/assets/content/fandalism-logo.png"
.youtube-presence.left.logo.online-presence-option.hidden
a rel="external"
img.logo src="/assets/content/youtube-logo.png"
.facebook-presence.left.logo.online-presence-option.hidden
a rel="external"
img.logo src="/assets/content/facebook-logo.png"
.twitter-presence.left.logo.online-presence-option.hidden
a rel="external"
img.logo src="/assets/content/twitter-logo.png"

View File

@ -0,0 +1,11 @@
.no-samples.left.performance-sample-option.hidden None specified
.jamkazam-samples.left.logo.performance-sample-option.hidden
img.logo src="/assets/header/logo.png"
br/
.soundcloud-samples.left.logo.performance-sample-option.hidden
img.logo src="/assets/content/soundcloud-logo.png"
br/
.youtube-samples.left.logo.performance-sample-option.hidden
img.logo src="/assets/content/youtube-logo.png"
br/

View File

@ -9,6 +9,7 @@
<div class="dialog-overlay op70" style="display:none; width:100%; height:100%; z-index:99;"></div>
<%= render "header" %>
<%= react_component 'BroadcastHolder', {} %>
<%= render "home" %>
<%= render "footer" %>
<%= render "paginator" %>
@ -84,6 +85,7 @@
<%= render 'dialogs/dialogs' %>
<div id="fb-root"></div>
<script type="text/javascript">
$(function() {
@ -168,7 +170,7 @@
var openBackingTrackDialog = new JK.OpenBackingTrackDialog(JK.app);
openBackingTrackDialog.initialize();
var configureTracksDialog = new JK.ConfigureTracksDialog(JK.app, null, api.getUserProfile, api.updateUser)
var configureTracksDialog = new JK.ConfigureTracksDialog(JK.app)
configureTracksDialog.initialize();
var networkTestDialog = new JK.NetworkTestDialog(JK.app);
@ -236,7 +238,7 @@
var accountProfileInterests = new JK.AccountProfileInterests(JK.app);
accountProfileInterests.initialize();
var accountProfileSamples = new JK.AccountProfileSamples(JK.app, null)
var accountProfileSamples = new JK.AccountProfileSamples(JK.app, $(".account-profile-samples"), api.getUserProfile, api.updateUser)
accountProfileSamples.initialize();
var accountAudioProfile = new JK.AccountAudioProfile(JK.app);

8
web/bower.json Normal file
View File

@ -0,0 +1,8 @@
{
"vendor": {
"name": "bower-rails generated vendor assets",
"dependencies": {
"fluxxor": "1.5.4"
}
}
}

View File

@ -34,8 +34,10 @@ bundle install --path vendor/bundle
#bundle update
set +e
echo "cleaning assets from last build"
# clean assets, because they may be lingering from last build
bundle exec rake assets:clean
# bundle exec rake assets:clean
rm -rf $DIR/public/assets
if [ "$?" = "0" ]; then
echo "success: updated dependencies"

View File

@ -77,6 +77,7 @@ if defined?(Bundler)
# Add the assets/fonts directory to assets.paths
config.assets.paths << "#{Rails.root}/app/assets/fonts"
config.assets.paths << Rails.root.join('vendor', 'assets', 'bower_components')
# Precompile additional assets (application.js, application.css, and all non-JS/CSS (i.e., images) are already added)
config.assets.precompile += %w( client/client.css )
@ -85,7 +86,6 @@ if defined?(Bundler)
config.assets.precompile += %w( web/web.js web/web.css )
config.assets.precompile += %w( minimal/minimal.js minimal/minimal.css )
# where is rabbitmq?
config.rabbitmq_host = "localhost"
config.rabbitmq_port = 5672
@ -348,5 +348,8 @@ if defined?(Bundler)
config.web_performance_timing_enabled = true
config.jamtrack_landing_bubbles_enabled = true
config.jamtrack_browser_bubbles_enabled = true
config.react.variant = :production
config.react.addons = true
end
end

View File

@ -96,4 +96,6 @@ SampleApp::Application.configure do
config.email_generic_from = 'nobody-dev@jamkazam.com'
config.email_alerts_alias = ENV['ALERT_EMAIL'] || 'alerts-dev@jamkazam.com'
config.guard_against_fraud = true
config.react.variant = :development
end

View File

@ -142,7 +142,7 @@ SampleApp::Application.routes.draw do
match '/about', to: 'corps#about', as: 'corp_about'
# news routes
match '/news', to: 'corps#news', as: 'corp_news'
match '/news', to: 'corps#news', as: 'corp_news'
# media center routes
match '/media_center', to: 'corps#media_center', as: 'corp_media_center'
@ -238,7 +238,7 @@ SampleApp::Application.routes.draw do
match '/shopping_carts' => 'api_shopping_carts#index', :via => :get
match '/shopping_carts' => 'api_shopping_carts#remove_cart', :via => :delete
match '/shopping_carts/clear_all' => 'api_shopping_carts#clear_all', :via => :delete
# RSVP requests
match '/rsvp_requests' => 'api_rsvp_requests#index', :via => :get
match '/rsvp_requests' => 'api_rsvp_requests#create', :via => :post
@ -269,7 +269,7 @@ SampleApp::Application.routes.draw do
match '/users' => 'api_users#index', :via => :get
match '/users' => 'api_users#create', :via => :post
match '/users/:id' => 'api_users#show', :via => :get, :as => 'api_user_detail'
#match '/users' => 'api_users#create', :via => :post
#match '/users' => 'api_users#create', :via => :post
match '/users/:id' => 'api_users#update', :via => :post
match '/users/:id' => 'api_users#delete', :via => :delete
match '/users/confirm/:signup_token' => 'api_users#signup_confirm', :via => :post, :as => 'api_signup_confirmation'
@ -278,7 +278,7 @@ SampleApp::Application.routes.draw do
match '/users/:id/set_password' => 'api_users#set_password', :via => :post
# recurly
match '/recurly/create_account' => 'api_recurly#create_account', :via => :post
match '/recurly/create_account' => 'api_recurly#create_account', :via => :post
match '/recurly/delete_account' => 'api_recurly#delete_account', :via => :delete
match '/recurly/get_account' => 'api_recurly#get_account', :via => :get
match '/recurly/payment_history' => 'api_recurly#payment_history', :via => :get
@ -312,7 +312,7 @@ SampleApp::Application.routes.draw do
match '/users/:id/likings' => 'api_users#liking_index', :via => :get, :as => 'api_user_liking_index'
match '/users/:id/likings' => 'api_users#liking_create', :via => :post
match '/users/:id/likings/:likable_id' => 'api_users#liking_destroy', :via => :delete
# user followers
match '/users/:id/followers' => 'api_users#follower_index', :via => :get, :as => 'api_user_follower_index'
@ -380,6 +380,10 @@ SampleApp::Application.routes.draw do
match '/users/:id/profile' => 'api_users#profile_show', :via => :get, :as => 'api_users_profile_show'
match '/users/:id/profile' => 'api_users#profile_save', :via => :post
# broadcast notification
match '/users/:id/broadcast_notification' => 'api_users#broadcast_notification', :via => :get
match '/users/:id/broadcast_notification/:broadcast_id/quiet' => 'api_users#quiet_broadcast_notification', :via => :post
# session chat
match '/chat' => 'api_chats#create', :via => :post
match '/sessions/:music_session/chats' => 'api_chats#index', :via => :get
@ -427,7 +431,7 @@ SampleApp::Application.routes.draw do
# band likers
match '/bands/:id/likers' => 'api_bands#liker_index', :via => :get
# band followers
match '/bands/:id/followers' => 'api_bands#follower_index', :via => :get
@ -471,13 +475,13 @@ SampleApp::Application.routes.draw do
match '/join_requests' => 'api_join_requests#create', :via => :post
match '/join_requests/:id' => 'api_join_requests#update', :via => :put
match '/join_requests' => 'api_join_requests#index', :via => :get
# Location lookups
match '/countries' => 'api_maxmind_requests#countries', :via => :get
match '/regions' => 'api_maxmind_requests#regions', :via => :get
match '/cities' => 'api_maxmind_requests#cities', :via => :get
match '/resolved_location' => 'api_maxmind_requests#resolved_location', :via => :get
# Recordings
match '/recordings/uploads' => 'api_recordings#list_uploads', :via => :get, :as => 'api_recordings_list_uploads'

16
web/package.json Normal file
View File

@ -0,0 +1,16 @@
{
"name": "jam-web",
"dependencies" : {
"browserify": "~> 6.3",
"browserify-incremental": "^1.4.0",
"coffeeify": "~> 0.6",
"reactify": "^0.17.1",
"coffee-reactify": "~>3.0.0",
"react": "^0.12.0",
"react-tools": "^0.12.1"
},
"engines": {
"node": ">= 0.10"
}
}

View File

@ -778,6 +778,13 @@ FactoryGirl.define do
end
end
factory :broadcast_notification, :class => JamRuby::BroadcastNotification do
title Faker::Lorem.sentence[0...50]
message Faker::Lorem.paragraph[0...200]
button_label Faker::Lorem.words(2).join(' ')[0...14]
frequency 3
end
factory :affiliate_partner, class: 'JamRuby::AffiliatePartner' do
sequence(:partner_name) { |n| "partner-#{n}" }
entity_type 'Individual'

View File

@ -89,7 +89,7 @@ describe "Account", :js => true, :type => :feature, :capybara_feature => true do
fill_in "first_name", with: "Bobby"
fill_in "last_name", with: "Toes"
uncheck('subscribe_email')
find("#account-edit-profile-submit").trigger(:click)
find(".account-edit-profile-submit").trigger(:click)
end
it {
@ -107,7 +107,7 @@ describe "Account", :js => true, :type => :feature, :capybara_feature => true do
jk_select("Jan", '#account-edit-profile-form #user_birth_date_2i')
jk_select("12", '#account-edit-profile-form #user_birth_date_3i')
jk_select("1960", '#account-edit-profile-form #user_birth_date_1i')
find("#account-edit-profile-submit").trigger(:click)
find(".account-edit-profile-submit").trigger(:click)
user.reload
user.birth_date == "1960-01-12"
@ -125,7 +125,7 @@ describe "Account", :js => true, :type => :feature, :capybara_feature => true do
before(:each) do
fill_in "first_name", with: ""
fill_in "last_name", with: ""
find("#account-edit-profile-submit").trigger(:click)
find(".account-edit-profile-submit").trigger(:click)
end
it {

View File

@ -0,0 +1,36 @@
require 'spec_helper'
describe "affiliate visit tracking" do
subject { page }
let(:user) { FactoryGirl.create(:user) }
let(:partner) { FactoryGirl.create(:affiliate_partner) }
let(:affiliate_params) { partner.affiliate_query_params }
before(:each) do
AffiliateReferralVisit.delete_all
end
it "tracks" do
visit '/?' + affiliate_params
should_be_at_root
AffiliateReferralVisit.count.should eq(1)
visit = AffiliateReferralVisit.first
visit.visited_url.should eq('/?' + affiliate_params)
visit.affiliate_partner_id.should eq(partner.id)
visit.first_visit.should be_true
download_url = '/downloads?' + affiliate_params
visit download_url
find('h2.create-account-header')
AffiliateReferralVisit.count.should eq(2)
visit = AffiliateReferralVisit.find_by_visited_url(download_url)
visit.affiliate_partner_id.should eq(partner.id)
visit.first_visit.should be_false
end
end

View File

@ -25,27 +25,49 @@ describe "Bands", :js => true, :type => :feature, :capybara_feature => true do
expect(page).to have_selector('#band-setup-title')
end
def fill_out_band_setup_form(band, biography, params={})
def fill_out_band_setup_form(band, biography, country="United States", region="Texas", city="Austin", params={})
navigate_band_setup unless URI.parse(current_url).fragment == '/band/setup/new'
params['band-name'] ||= band || "Default band name"
params['band-biography'] ||= biography || "Default band biography"
within('#band-setup-form') do
params.each do |field, value|
fill_in field, with: "#{value}"
fill_in field, with: value
end
# Move to experience pane:
#first('#band-genres input[type="checkbox"]').trigger(:click)
end
jk_select(country, '#band-country')
jk_select(region, '#band-region')
jk_select(city, '#band-city')
sleep 1 # work around race condition
find('#btn-band-setup-next').trigger(:click)
find('h2', text: 'Step 2: Add Band Members')
find('h2', text: 'set up band: musical experience')
end
def complete_band_setup_form(band, biography, params={})
fill_out_band_setup_form(band, biography, params)
find('#btn-band-setup-save').trigger(:click)
def complete_band_setup_form(band, biography, country="United States", region="Texas", city="Austin", params={})
navigate_to_friend_page(band, biography, country, region, city, params)
# Save
find('#btn-band-setup-next').trigger(:click)
sleep(1)
end
def navigate_to_friend_page(band, biography, country="United States", region="Texas", city="Austin", params={})
fill_out_band_setup_form(band, biography, country, region, city, params)
find(:css, "#african").set(true)
find('#btn-band-setup-next').trigger(:click)
find('h2', text: 'set up band: current interests')
find('#btn-band-setup-next').trigger(:click)
find('h2', text: 'set up band: online presence & performance samples')
find('#btn-band-setup-next').trigger(:click)
find('h2', text: 'set up band: invite members')
end
context "band profile - new band setup" do
@ -71,16 +93,18 @@ describe "Bands", :js => true, :type => :feature, :capybara_feature => true do
find('#btn-band-setup-next').trigger(:click)
expect(page).to have_selector('#band-setup .band-name .error-text li', text: "can't be blank")
expect(page).to have_selector('#band-setup .band-biography .error-text li', text: "can't be blank")
#expect(page).to have_selector('#band-setup .band-genres .error-text li', text: "At least 1 genre is required.")
complete_band_setup_form("Band name", "Band biography")
complete_band_setup_form("Test Band name", "Test Band biography")
expect(page).to have_selector('#band-profile-name', text: "Band name")
expect(page).to have_selector('#band-profile-biography', text: "Band biography")
expect(page).to have_selector('#band-profile-name', text: "Test Band name")
expect(page).to have_selector('#band-profile-biography', text: "Test Band biography")
end
it "limits genres to 3" do
pending "Move this to experience pane"
#expect(page).to have_selector('#band-setup .band-genres .error-text li', text: "At least 1 genre is required.")
genres = Genre.limit(4)
navigate_band_setup
within('#band-setup-form') do
@ -136,17 +160,19 @@ describe "Bands", :js => true, :type => :feature, :capybara_feature => true do
band_attributes = {
name: 'Radical D00dz',
biography: 'Just a bunch of EXTREME dudes who ROCK professionally!!',
# website: 'www.radicald00dz.com', # not displayed - VRFS-1617
# country: 'US', # not displayed
city: 'Lubbock',
state: 'TX'
country: 'US',
state: 'TX',
city: 'Lubbock'
}
some_band = FactoryGirl.create(:band, band_attributes)
sign_in_poltergeist fan
view_band_profile_of some_band
band_attributes.each_value { |v| expect(page).to have_content v }
expect(page).to have_content 'Radical D00dz'
expect(page).to have_content 'Just a bunch of EXTREME dudes who ROCK professionally!!'
expect(page).to have_content 'Lubbock, TX'
end
it "allows a user to follow the band"
@ -181,14 +207,14 @@ describe "Bands", :js => true, :type => :feature, :capybara_feature => true do
band_bio = "Good, good friends"
band_website = "http://www.sounds.com/thetwoguysfrom2009.html"
fill_out_band_setup_form(band_name, band_bio)#, 'band-website' => band_website)
navigate_to_friend_page(band_name, band_bio)#, 'band-website' => band_website)
#invite somebody using the picker
find('#btn-choose-friends-band').trigger(:click)
find("tr[user-id='#{friend.id}']").trigger(:click)
expect(page).to have_selector("tr.selected[user-id='#{friend.id}']")
find('#btn-save-friends').trigger(:click)
find('#btn-band-setup-save').trigger(:click)
find('#btn-band-setup-next').trigger(:click)
sleep 1 # ensure the transaction commits..
find('#band-profile-members-link').trigger(:click)
@ -235,7 +261,7 @@ describe "Bands", :js => true, :type => :feature, :capybara_feature => true do
expect(page).to have_selector('#btn-edit-band-profile')
find('#btn-edit-band-profile').trigger(:click)
find('h2', text: 'Step 1: General Information')
find('h2', text: 'set up band: basics')
expect(page).to have_content band.name
expect(page).to have_content band.biography

View File

@ -0,0 +1,40 @@
require 'spec_helper'
describe "broadcast notification", :js => true, :type => :feature, :capybara_feature => true do
subject { page }
let(:broadcast1) {FactoryGirl.create(:broadcast_notification, frequency: 4)}
let(:broadcast2) {FactoryGirl.create(:broadcast_notification, frequency: 4)}
let(:user) { FactoryGirl.create(:user) }
let(:partner) { FactoryGirl.create(:affiliate_partner) }
before(:each) do
BroadcastNotificationView.delete_all
BroadcastNotification.delete_all
end
it "cycles on home screen" do
broadcast1.touch
fast_signin(user, '/client')
find('.broadcast-notification .message', text: broadcast1.message)
broadcast2.touch
visit current_path
find('.broadcast-notification .message', text: broadcast2.message)
visit current_path
find('.broadcast-notification .message', text: broadcast1.message)
find('.broadcast-notification .not-now').trigger(:click)
visit current_path
find('.broadcast-notification .message', text: broadcast2.message)
go_to_root
visit '/client'
find('.broadcast-notification .message', text: broadcast2.message)
end
end

File diff suppressed because one or more lines are too long