merge develop
This commit is contained in:
commit
7a4ad83cef
|
|
@ -1,7 +1,7 @@
|
|||
source 'http://rubygems.org'
|
||||
|
||||
source 'https://jamjam:blueberryjam@int.jamkazam.com/gems/'
|
||||
devenv = ENV["BUILD_NUMBER"].nil? || ENV["TEST_WWW"] == "1"
|
||||
devenv = ENV["BUILD_NUMBER"].nil?
|
||||
|
||||
if devenv
|
||||
gem 'jam_db', :path=> "../db/target/ruby_package"
|
||||
|
|
@ -72,9 +72,6 @@ gem 'postgres_ext', '1.0.0'
|
|||
gem 'resque_mailer'
|
||||
gem 'rest-client'
|
||||
|
||||
gem 'geokit-rails'
|
||||
gem 'postgres_ext', '1.0.0'
|
||||
|
||||
group :libv8 do
|
||||
gem 'libv8', "~> 3.11.8"
|
||||
end
|
||||
|
|
@ -105,10 +102,6 @@ group :development, :test do
|
|||
gem 'rspec-rails'
|
||||
gem 'guard-rspec', '0.5.5'
|
||||
gem 'jasmine', '1.3.1'
|
||||
gem 'pry'
|
||||
gem 'pry-remote'
|
||||
gem 'pry-stack_explorer'
|
||||
gem 'pry-debugger'
|
||||
gem 'execjs', '1.4.0'
|
||||
gem 'therubyracer' #, '0.11.0beta8'
|
||||
gem 'factory_girl_rails', '4.1.0'
|
||||
|
|
@ -120,4 +113,12 @@ end
|
|||
group :test do
|
||||
gem 'simplecov', '~> 0.7.1'
|
||||
gem 'simplecov-rcov'
|
||||
gem 'capybara-webkit'
|
||||
gem 'capybara-screenshot'
|
||||
gem 'poltergeist'
|
||||
end
|
||||
|
||||
gem 'pry'
|
||||
gem 'pry-remote'
|
||||
gem 'pry-stack_explorer'
|
||||
gem 'pry-debugger'
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ ActiveAdmin.register_page "Dashboard" do
|
|||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# column do
|
||||
|
|
|
|||
|
|
@ -0,0 +1,221 @@
|
|||
ActiveAdmin.register_page 'Feed' do
|
||||
content do
|
||||
|
||||
# get user information via params
|
||||
user_id = nil
|
||||
user_id = params[:feed][:user_id] if params[:feed] && params[:feed][:user_id] != ''
|
||||
user_name = 'All'
|
||||
user_name = User.find(user_id).to_label if user_id
|
||||
|
||||
render :partial => 'form', locals: {user_name: user_name, user_id: user_id }
|
||||
|
||||
page = (params[:page] ||= 1).to_i
|
||||
per_page = 10
|
||||
offset = (page - 1) * per_page
|
||||
|
||||
# get feed ids
|
||||
where_sql = ''
|
||||
where_sql = "where user_id = '#{user_id}'" if user_id
|
||||
sql_feed_ids = "SELECT id, 'music_sessions' as type, created_at FROM music_sessions #{where_sql}
|
||||
UNION ALL
|
||||
SELECT DISTINCT recording_id as id, 'recordings' as type, created_at FROM recorded_tracks #{where_sql}
|
||||
UNION ALL
|
||||
SELECT id, 'diagnostics' as type, created_at FROM diagnostics #{where_sql}
|
||||
ORDER BY created_at DESC
|
||||
OFFSET #{offset}
|
||||
LIMIT #{per_page};"
|
||||
|
||||
sql_feed_count = "SELECT COUNT(*) FROM (
|
||||
SELECT id, 'music_sessions' as type, created_at FROM music_sessions #{where_sql}
|
||||
UNION ALL
|
||||
SELECT DISTINCT recording_id as id, 'recordings' as type, created_at FROM recorded_tracks #{where_sql}
|
||||
UNION ALL
|
||||
SELECT id, 'diagnostics' as type, created_at FROM diagnostics #{where_sql}
|
||||
ORDER BY created_at DESC
|
||||
) AS IDS;"
|
||||
feed_count = ActiveRecord::Base.connection.execute(sql_feed_count).values[0][0].to_i
|
||||
id_types = ActiveRecord::Base.connection.execute(sql_feed_ids).values
|
||||
|
||||
@feed_pages = WillPaginate::Collection.create(page, per_page) do |pager|
|
||||
pager.total_entries = feed_count
|
||||
pager.replace(id_types)
|
||||
end
|
||||
|
||||
div class: 'feed-pagination' do
|
||||
will_paginate @feed_pages
|
||||
end
|
||||
|
||||
recordings = []
|
||||
sessions = []
|
||||
diagnostics = []
|
||||
id_types.each do |id_and_type|
|
||||
if id_and_type[1] == "music_sessions"
|
||||
sessions << JamRuby::MusicSession.find(id_and_type[0])
|
||||
elsif id_and_type[1] == "recordings"
|
||||
recordings << JamRuby::Recording.find(id_and_type[0])
|
||||
elsif id_and_type[1] == "diagnostics"
|
||||
diagnostics << JamRuby::Diagnostic.find(id_and_type[0])
|
||||
else
|
||||
raise "Unknown type returned from feed ids"
|
||||
end
|
||||
end
|
||||
|
||||
columns do
|
||||
column do
|
||||
panel "Music Sessions - #{user_name}" do
|
||||
if sessions.count > 0
|
||||
table_for(sessions) do
|
||||
column :creator do |msh|
|
||||
link_to msh.creator.to_label, admin_feed_path({feed: {user_id: msh.creator.id}})
|
||||
end
|
||||
column :created_at do |msh| msh.created_at.strftime('%b %d %Y, %H:%M') end
|
||||
column :duration do |msh| "#{msh.duration_minutes.round(2)} minutes" end
|
||||
column :members do |msh|
|
||||
uu = msh.unique_users
|
||||
if uu.length > 0
|
||||
uu.each do |u|
|
||||
span link_to u.to_label + ', ', admin_feed_path({feed: {user_id: u.id}})
|
||||
end
|
||||
else
|
||||
span para 'No members'
|
||||
end
|
||||
end
|
||||
|
||||
column :band do |msh| auto_link(msh.band, msh.band.try(:name)) end
|
||||
column :fan_access do |msh| msh.fan_access end
|
||||
column :plays do |msh| msh.plays.count end
|
||||
column :likes do |msh| msh.likes.count end
|
||||
column :comments do |msh|
|
||||
if msh.comment_count > 0
|
||||
text_node "(#{msh.comment_count}) "
|
||||
msh.comments.each do |comment|
|
||||
text_node comment.user.to_label + ', '
|
||||
end
|
||||
else
|
||||
span para 'No comments'
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
span class: 'text-center' do
|
||||
para 'No session activities.'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
panel "Recordings - #{user_name}" do
|
||||
if recordings.count > 0
|
||||
table_for(recordings) do
|
||||
column :starter do |rec|
|
||||
link_to rec.owner.to_label, admin_feed_path({feed: {user_id: rec.owner.id}})
|
||||
end
|
||||
column :mixes do |rec|
|
||||
ul do
|
||||
mixes = rec.mixes
|
||||
if mixes.count > 0
|
||||
mixes.each do |mix|
|
||||
li do
|
||||
text_node "Created At: #{mix.created_at.strftime('%b %d %Y, %H:%M')}, "
|
||||
text_node "Started At: #{mix.started_at.strftime('%b %d %Y, %H:%M')}, "
|
||||
text_node "Completed At: #{mix.completed_at.strftime('%b %d %Y, %H:%M')}, "
|
||||
text_node "Error Count: #{mix.error_count}, "
|
||||
text_node "Error Reason: #{mix.error_reason}, "
|
||||
text_node "Error Detail: #{mix.error_detail}, "
|
||||
text_node "Download Count: #{mix.download_count}, "
|
||||
if !mix.nil? && !mix[:ogg_url].nil?
|
||||
span link_to 'Download OGG', mix.sign_url(3600, 'ogg')
|
||||
else
|
||||
text_node 'OGG download not available'
|
||||
end
|
||||
if !mix.nil? && !mix[:mp3_url].nil?
|
||||
span link_to 'Download MP3', mix.sign_url(3600, 'mp3')
|
||||
else
|
||||
text_node 'MP3 download not available'
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
span para 'No mixes'
|
||||
end
|
||||
end
|
||||
end
|
||||
column :recorded_tracks do |rec|
|
||||
ul do
|
||||
rts = rec.recorded_tracks
|
||||
if rts.count > 0
|
||||
rts.each do |gt|
|
||||
li do
|
||||
span link_to gt.musician.to_label, admin_feed_path({feed: {user_id: gt.musician.id}})
|
||||
span ", #{gt.instrument_id}, "
|
||||
span "Download Count: #{gt.download_count}, "
|
||||
span "Fully uploaded: #{gt.fully_uploaded}, "
|
||||
span "Upload failures: #{gt.upload_failures}, "
|
||||
span "Part failures: #{gt.part_failures}, "
|
||||
if gt[:url]
|
||||
# span link_to 'Download', gt.sign_url(3600)
|
||||
else
|
||||
span 'No track available'
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
span para 'No recorded tracks'
|
||||
end
|
||||
end
|
||||
end
|
||||
column :claimed_recordings do |rec|
|
||||
ul do
|
||||
crs = rec.claimed_recordings
|
||||
if crs.count > 0
|
||||
crs.each do |cr|
|
||||
li do
|
||||
span cr.name
|
||||
span link_to cr.user.to_label, admin_feed_path({feed: {user_id: cr.user.id}})
|
||||
span ", Public: #{cr.is_public}"
|
||||
end
|
||||
end
|
||||
else
|
||||
span para 'No claimed recordings'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
span class: 'text-center' do
|
||||
para 'No recording activities.'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
panel "Diagnostics - #{user_name}" do
|
||||
if diagnostics.count > 0 then
|
||||
table_for(diagnostics) do
|
||||
column :user do |d|
|
||||
span link_to d.user.to_label, admin_feed_path({feed: {user_id: d.user.id}})
|
||||
end
|
||||
column :created_at do |d| d.created_at.strftime('%b %d %Y, %H:%M') end
|
||||
column :type
|
||||
column :creator
|
||||
column :data do |d|
|
||||
span style: "white-space: pre;" do
|
||||
begin
|
||||
JSON.pretty_generate(JSON.parse(d.data))
|
||||
rescue
|
||||
d.data
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
span class: 'text-center' do
|
||||
para 'No diagnostic activities.'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
div class: 'feed-pagination' do
|
||||
will_paginate @feed_pages
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -103,7 +103,7 @@ ActiveAdmin.register JamRuby::User, :as => 'Users' do
|
|||
autocomplete :user, :email, :full => true, :display_value => :autocomplete_display_name
|
||||
|
||||
def get_autocomplete_items(parameters)
|
||||
items = User.select("DISTINCT email, first_name, last_name, id").where(["email ILIKE ? OR first_name ILIKE ? OR last_name ILIKE ?", "%#{parameters[:term]}%", "%#{parameters[:term]}%", "%#{parameters[:term]}%"])
|
||||
User.select("email, first_name, last_name, id").where(["email ILIKE ? OR first_name ILIKE ? OR last_name ILIKE ?", "%#{parameters[:term]}%", "%#{parameters[:term]}%", "%#{parameters[:term]}%"])
|
||||
end
|
||||
|
||||
def create
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
/*
|
||||
*= require jquery.ui.all
|
||||
*= require custom
|
||||
*/
|
||||
// Active Admin's got SASS!
|
||||
@import "active_admin/mixins";
|
||||
|
|
|
|||
|
|
@ -3,3 +3,23 @@
|
|||
font-size:small;
|
||||
color:lightgray;
|
||||
}
|
||||
|
||||
.text-center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.feed-pagination {
|
||||
height: 20px;
|
||||
margin-bottom: 15px;
|
||||
.pagination {
|
||||
float: left !important;
|
||||
|
||||
ul {
|
||||
list-style-type: none;
|
||||
|
||||
li {
|
||||
float: left;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
<%= semantic_form_for :feed, url: admin_feed_path, method: :get do |f| %>
|
||||
<%= f.inputs do %>
|
||||
<%= f.input :user, :as => :autocomplete, :url => autocomplete_user_email_admin_users_path, :input_html => { :id_element => "#feed_user_id" } %>
|
||||
<%= f.input :user_id, :as => :hidden %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
|
@ -46,4 +46,131 @@ FactoryGirl.define do
|
|||
description { |n| "Instrument #{n}" }
|
||||
end
|
||||
|
||||
factory :genre, :class => JamRuby::Genre do
|
||||
description { |n| "Genre #{n}" }
|
||||
end
|
||||
|
||||
factory :music_session, :class => JamRuby::MusicSession do
|
||||
sequence(:name) { |n| "Music Session #{n}" }
|
||||
sequence(:description) { |n| "Music Session Description #{n}" }
|
||||
fan_chat true
|
||||
fan_access true
|
||||
approval_required false
|
||||
musician_access true
|
||||
legal_terms true
|
||||
language 'english'
|
||||
legal_policy 'standard'
|
||||
genre JamRuby::Genre.first
|
||||
association :creator, :factory => :user
|
||||
end
|
||||
|
||||
factory :music_session_user_history, :class => JamRuby::MusicSessionUserHistory do
|
||||
ignore do
|
||||
history nil
|
||||
user nil
|
||||
end
|
||||
|
||||
music_session_id { history.id }
|
||||
user_id { user.id }
|
||||
sequence(:client_id) { |n| "Connection #{n}" }
|
||||
end
|
||||
|
||||
factory :recorded_track, :class => JamRuby::RecordedTrack do
|
||||
instrument JamRuby::Instrument.first
|
||||
sound 'stereo'
|
||||
sequence(:client_id) { |n| "client_id-#{n}"}
|
||||
sequence(:track_id) { |n| "track_id-#{n}"}
|
||||
sequence(:client_track_id) { |n| "client_track_id-#{n}"}
|
||||
md5 'abc'
|
||||
length 1
|
||||
fully_uploaded true
|
||||
association :user, factory: :user
|
||||
association :recording, factory: :recording
|
||||
end
|
||||
|
||||
factory :recording, :class => JamRuby::Recording do
|
||||
|
||||
association :owner, factory: :user
|
||||
association :music_session, factory: :active_music_session
|
||||
|
||||
factory :recording_with_track do
|
||||
before(:create) { |recording, evaluator|
|
||||
recording.recorded_tracks << FactoryGirl.create(:recorded_track, recording: recording, user: evaluator.owner)
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
factory :claimed_recording, :class => JamRuby::ClaimedRecording do
|
||||
sequence(:name) { |n| "name-#{n}" }
|
||||
sequence(:description) { |n| "description-#{n}" }
|
||||
is_public true
|
||||
association :genre, factory: :genre
|
||||
association :user, factory: :user
|
||||
|
||||
before(:create) { |claimed_recording|
|
||||
claimed_recording.recording = FactoryGirl.create(:recording_with_track, owner: claimed_recording.user)
|
||||
}
|
||||
|
||||
end
|
||||
|
||||
factory :mix, :class => JamRuby::Mix do
|
||||
started_at Time.now
|
||||
completed_at Time.now
|
||||
ogg_md5 'abc'
|
||||
ogg_length 1
|
||||
sequence(:ogg_url) { |n| "recordings/ogg/#{n}" }
|
||||
mp3_md5 'abc'
|
||||
mp3_length 1
|
||||
sequence(:mp3_url) { |n| "recordings/mp3/#{n}" }
|
||||
completed true
|
||||
|
||||
before(:create) {|mix|
|
||||
user = FactoryGirl.create(:user)
|
||||
mix.recording = FactoryGirl.create(:recording_with_track, owner: user)
|
||||
mix.recording.claimed_recordings << FactoryGirl.create(:claimed_recording, user: user, recording: mix.recording)
|
||||
}
|
||||
end
|
||||
|
||||
factory :diagnostic, :class => JamRuby::Diagnostic do
|
||||
type JamRuby::Diagnostic::NO_HEARTBEAT_ACK
|
||||
creator JamRuby::Diagnostic::CLIENT
|
||||
data Faker::Lorem.sentence
|
||||
association :user, factory: :user
|
||||
end
|
||||
|
||||
factory :active_music_session_no_user_history, :class => JamRuby::ActiveMusicSession do
|
||||
|
||||
association :creator, factory: :user
|
||||
|
||||
ignore do
|
||||
name "My Music Session"
|
||||
description "Come Music Session"
|
||||
fan_chat true
|
||||
fan_access true
|
||||
approval_required false
|
||||
musician_access true
|
||||
legal_terms true
|
||||
genre JamRuby::Genre.first
|
||||
band nil
|
||||
end
|
||||
|
||||
|
||||
before(:create) do |session, evaluator|
|
||||
music_session = FactoryGirl.create(:music_session, name: evaluator.name, description: evaluator.description, fan_chat: evaluator.fan_chat,
|
||||
fan_access: evaluator.fan_access, approval_required: evaluator.approval_required, musician_access: evaluator.musician_access,
|
||||
genre: evaluator.genre, creator: evaluator.creator, band: evaluator.band)
|
||||
session.id = music_session.id
|
||||
end
|
||||
|
||||
factory :active_music_session do
|
||||
after(:create) { |session|
|
||||
FactoryGirl.create(:music_session_user_history, :history => session.music_session, :user => session.creator)
|
||||
}
|
||||
|
||||
factory :music_session_with_mount do
|
||||
association :mount, :factory => :icecast_mount
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,88 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe 'Feeds' do
|
||||
|
||||
subject { page }
|
||||
|
||||
before(:each) do
|
||||
MusicSession.delete_all
|
||||
Recording.delete_all
|
||||
Diagnostic.delete_all
|
||||
User.delete_all
|
||||
end
|
||||
|
||||
let(:admin) { FactoryGirl.create(:admin) }
|
||||
let(:user) { FactoryGirl.create(:user) }
|
||||
|
||||
let(:music_session) { FactoryGirl.create(:music_session, :creator => user) }
|
||||
let(:recording) { FactoryGirl.create(:recording_with_track, :owner => user) }
|
||||
let(:diagnostic) { FactoryGirl.create(:diagnostic, :user => user) }
|
||||
|
||||
context 'empty dashboard' do
|
||||
before(:each) do
|
||||
visit admin_feed_path
|
||||
end
|
||||
|
||||
it { should have_selector('h2', text: 'Feed') }
|
||||
|
||||
it 'has no feeds' do
|
||||
should have_selector('p', text: 'No session activities.')
|
||||
should have_selector('p', text: 'No recording activities.')
|
||||
should have_selector('p', text: 'No diagnostic activities.')
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
context 'admin enters a user name' do
|
||||
before(:each) do
|
||||
user.touch
|
||||
visit admin_feed_path
|
||||
end
|
||||
|
||||
it 'auto-completes with email + full name', :js => true do
|
||||
|
||||
within('form.feed') do
|
||||
fill_in 'feed_user', with: user.email[0..3]
|
||||
end
|
||||
|
||||
page.execute_script %Q{ $('form.feed input#feed_user').trigger('focus') }
|
||||
page.execute_script %Q{ $('form.feed input#feed_user').trigger('keydown') }
|
||||
find('a.ui-corner-all', text: user.to_label).trigger(:click)
|
||||
should have_selector('form.feed #feed_user', user.to_label)
|
||||
should have_selector('form.feed #feed_user_id[value="' + user.id + '"]', visible:false)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with existing activities' do
|
||||
before(:each) do
|
||||
music_session.touch
|
||||
recording.touch
|
||||
diagnostic.touch
|
||||
visit admin_feed_path
|
||||
end
|
||||
|
||||
it 'shows session, recording, diagnostic' do
|
||||
should have_selector("tr#jam_ruby_music_session_#{music_session.id}")
|
||||
should have_selector("tr#jam_ruby_recording_#{recording.id}")
|
||||
should have_selector("tr#jam_ruby_diagnostic_#{diagnostic.id}")
|
||||
end
|
||||
|
||||
it 'shows activities for one user', :js => true do
|
||||
within('form.feed') do
|
||||
fill_in 'feed_user', with: user.email[0..3]
|
||||
end
|
||||
|
||||
page.execute_script %Q{ $('form.feed input#feed_user').trigger('focus') }
|
||||
page.execute_script %Q{ $('form.feed input#feed_user').trigger('keydown') }
|
||||
find('a.ui-corner-all', text: user.to_label).trigger(:click)
|
||||
should have_selector('form.feed #feed_user', user.to_label)
|
||||
should have_selector('form.feed #feed_user_id[value="' + user.id + '"]', visible:false)
|
||||
|
||||
page.execute_script %Q{ $('form.feed').trigger('submit') }
|
||||
|
||||
should have_selector("tr#jam_ruby_music_session_#{music_session.id}")
|
||||
should have_selector("tr#jam_ruby_recording_#{recording.id}")
|
||||
should have_selector("tr#jam_ruby_diagnostic_#{diagnostic.id}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -22,6 +22,9 @@ require 'rspec/autorun'
|
|||
|
||||
# load capybara
|
||||
require 'capybara/rails'
|
||||
require 'capybara/rspec'
|
||||
require 'capybara-screenshot/rspec'
|
||||
require 'capybara/poltergeist'
|
||||
|
||||
#include Rails.application.routes.url_helpers
|
||||
|
||||
|
|
@ -30,6 +33,11 @@ require 'capybara/rails'
|
|||
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
|
||||
|
||||
|
||||
Capybara.register_driver :poltergeist do |app|
|
||||
driver = Capybara::Poltergeist::Driver.new(app, { debug: false, phantomjs_logger: File.open('log/phantomjs.out', 'w') })
|
||||
end
|
||||
Capybara.javascript_driver = :poltergeist
|
||||
Capybara.default_wait_time = 10
|
||||
|
||||
RSpec.configure do |config|
|
||||
# ## Mock Framework
|
||||
|
|
@ -46,7 +54,7 @@ RSpec.configure do |config|
|
|||
# If you're not using ActiveRecord, or you'd prefer not to run each of your
|
||||
# examples within a transaction, remove the following line or assign false
|
||||
# instead of true.
|
||||
config.use_transactional_fixtures = true
|
||||
config.use_transactional_fixtures = false
|
||||
|
||||
# If true, the base class of anonymous controllers will be inferred
|
||||
# automatically. This will be the default behavior in future versions of
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
module Snapshot
|
||||
|
||||
SS_PATH = 'snapshots.html'
|
||||
|
||||
def set_up_snapshot(filepath = SS_PATH)
|
||||
@size = [1280, 720] #arbitrary
|
||||
@file = File.new(filepath, "w+")
|
||||
@file.puts "<HTML><BODY BGCOLOR=grey>"
|
||||
@file.puts "<H1>Snapshot #{ENV["BUILD_NUMBER"]} - #{@size[0]}x#{@size[1]}</H1>"
|
||||
end
|
||||
|
||||
def snapshot_example
|
||||
page.driver.resize(@size[0], @size[1])
|
||||
@file.puts "<H3>Example name: #{get_description}</H3><BR><BR>"
|
||||
end
|
||||
|
||||
def snap!(title = get_description)
|
||||
base64 = page.driver.render_base64(:png)
|
||||
@file.puts '<H3>' + title + '</H3>'
|
||||
@file.puts '<img alt="' + title +'" src="data:image/png;base64,' + base64 + '" />'
|
||||
@file.puts '<BR><BR><BR>'
|
||||
end
|
||||
|
||||
def tear_down_snapshot
|
||||
@file.puts "</BODY></HTML>"
|
||||
@file.close()
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
<atlassian-ide-plugin>
|
||||
<project-configuration id="1">
|
||||
<servers id="2" />
|
||||
</project-configuration>
|
||||
</atlassian-ide-plugin>
|
||||
|
|
@ -1 +1,10 @@
|
|||
this is just for getting this maxmind data over there so i can use it.
|
||||
|
||||
source for iso3166-1 data:
|
||||
|
||||
http://dev.maxmind.com/static/csv/codes/iso3166.csv
|
||||
|
||||
source for iso3166-2 data (compatible):
|
||||
|
||||
http://geolite.maxmind.com/download/geoip/misc/region_codes.csv
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +0,0 @@
|
|||
AB,Alberta
|
||||
BC,British Columbia
|
||||
MB,Manitoba
|
||||
NB,New Brunswick
|
||||
NL,Newfoundland and Labrador
|
||||
NS,Nova Scotia
|
||||
NT,Northwest Territories
|
||||
NU,Nunavut
|
||||
ON,Ontario
|
||||
PE,Prince Edward Island
|
||||
QC,Quebec
|
||||
SK,Saskatchewan
|
||||
YT,Yukon
|
||||
|
File diff suppressed because it is too large
Load Diff
|
|
@ -1,57 +0,0 @@
|
|||
AA,Armed Forces America
|
||||
AE,Armed Forces
|
||||
AP,Armed Forces Pacific
|
||||
AK,Alaska
|
||||
AL,Alabama
|
||||
AR,Arkansas
|
||||
AZ,Arizona
|
||||
CA,California
|
||||
CO,Colorado
|
||||
CT,Connecticut
|
||||
DC,District of Columbia
|
||||
DE,Delaware
|
||||
FL,Florida
|
||||
GA,Georgia
|
||||
GU,Guam
|
||||
HI,Hawaii
|
||||
IA,Iowa
|
||||
ID,Idaho
|
||||
IL,Illinois
|
||||
IN,Indiana
|
||||
KS,Kansas
|
||||
KY,Kentucky
|
||||
LA,Louisiana
|
||||
MA,Massachusetts
|
||||
MD,Maryland
|
||||
ME,Maine
|
||||
MI,Michigan
|
||||
MN,Minnesota
|
||||
MO,Missouri
|
||||
MS,Mississippi
|
||||
MT,Montana
|
||||
NC,North Carolina
|
||||
ND,North Dakota
|
||||
NE,Nebraska
|
||||
NH,New Hampshire
|
||||
NJ,New Jersey
|
||||
NM,New Mexico
|
||||
NV,Nevada
|
||||
NY,New York
|
||||
OH,Ohio
|
||||
OK,Oklahoma
|
||||
OR,Oregon
|
||||
PA,Pennsylvania
|
||||
PR,Puerto Rico
|
||||
RI,Rhode Island
|
||||
SC,South Carolina
|
||||
SD,South Dakota
|
||||
TN,Tennessee
|
||||
TX,Texas
|
||||
UT,Utah
|
||||
VA,Virginia
|
||||
VI,Virgin Islands
|
||||
VT,Vermont
|
||||
WA,Washington
|
||||
WI,Wisconsin
|
||||
WV,West Virginia
|
||||
WY,Wyoming
|
||||
|
|
|
@ -162,3 +162,9 @@ scheduled_sessions_3.sql
|
|||
scheduled_sessions_cancel_all.sql
|
||||
scheduled_sessions_started_at.sql
|
||||
scheduled_sessions_open_rsvps.sql
|
||||
add_last_jam_user_fields.sql
|
||||
remove_lat_lng_user_fields.sql
|
||||
update_get_work_for_larger_radius.sql
|
||||
periodic_emails.sql
|
||||
remember_extra_scoring_data.sql
|
||||
indexing_for_regions.sql
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
ALTER TABLE users ADD COLUMN last_jam_addr BIGINT;
|
||||
|
||||
ALTER TABLE users ADD COLUMN last_jam_locidispid BIGINT;
|
||||
|
||||
-- (j)oin session as musician, (r)egister, (f)tue, (n)etwork test
|
||||
ALTER TABLE users ADD COLUMN last_jam_updated_reason CHAR(1);
|
||||
|
||||
ALTER TABLE users ADD COLUMN last_jam_updated_at TIMESTAMP;
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
create index regions_countrycode_ndx on regions (countrycode);
|
||||
create unique index regions_countrycode_region_ndx on regions (countrycode, region);
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
ALTER TABLE email_batches ADD COLUMN type VARCHAR(64) NOT NULL DEFAULT 'JamRuby::EmailBatch';
|
||||
ALTER TABLE email_batches ADD COLUMN sub_type VARCHAR(64);
|
||||
|
||||
ALTER TABLE email_batches ALTER COLUMN body DROP NOT NULL;
|
||||
ALTER TABLE email_batches ALTER COLUMN subject DROP NOT NULL;
|
||||
|
||||
ALTER TABLE email_batch_sets ADD COLUMN trigger_index INTEGER NOT NULL DEFAULT 0;
|
||||
ALTER TABLE email_batch_sets ADD COLUMN sub_type VARCHAR(64);
|
||||
ALTER TABLE email_batch_sets ADD COLUMN user_id VARCHAR(64);
|
||||
|
||||
CREATE INDEX email_batch_sets_progress_idx ON email_batch_sets(user_id, sub_type);
|
||||
CREATE INDEX users_musician_email_idx ON users(subscribe_email, musician);
|
||||
|
||||
UPDATE users set first_social_promoted_at = first_liked_us;
|
||||
ALTER TABLE users DROP column first_liked_us;
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
-- add column to hold the raw scoring data that the client posted.
|
||||
|
||||
alter table scores add column scoring_data varchar(4000);
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
alter table users drop column lat;
|
||||
alter table users drop column lng;
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
DROP FUNCTION get_work (mylocidispid BIGINT);
|
||||
CREATE FUNCTION get_work (mylocidispid BIGINT, myaddr BIGINT) RETURNS TABLE (client_id VARCHAR(64)) ROWS 5 VOLATILE AS $$
|
||||
BEGIN
|
||||
CREATE TEMPORARY TABLE foo (locidispid BIGINT, locid INT);
|
||||
INSERT INTO foo SELECT DISTINCT locidispid, locidispid/1000000 FROM connections WHERE client_type = 'client';
|
||||
DELETE FROM foo WHERE locidispid IN (SELECT DISTINCT blocidispid FROM current_scores WHERE alocidispid = mylocidispid AND (current_timestamp - score_dt) < INTERVAL '24 hours');
|
||||
DELETE FROM foo WHERE locid NOT IN (SELECT locid FROM geoiplocations WHERE geog && st_buffer((SELECT geog FROM geoiplocations WHERE locid = mylocidispid/1000000), 4023360));
|
||||
CREATE TEMPORARY TABLE bar (client_id VARCHAR(64), locidispid BIGINT, r DOUBLE PRECISION);
|
||||
INSERT INTO bar SELECT l.client_id, l.locidispid, random() FROM connections l, foo f WHERE l.locidispid = f.locidispid AND l.client_type = 'client' AND addr != myaddr;
|
||||
DROP TABLE foo;
|
||||
DELETE FROM bar b WHERE r != (SELECT MAX(r) FROM bar b0 WHERE b0.locidispid = b.locidispid);
|
||||
RETURN QUERY SELECT b.client_id FROM bar b ORDER BY r LIMIT 5;
|
||||
DROP TABLE bar;
|
||||
RETURN;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
--color
|
||||
--format progress
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
source "https://rubygems.org"
|
||||
|
||||
gem "rspec"
|
||||
gem "capybara"
|
||||
gem "capybara-screenshot"
|
||||
gem "poltergeist"
|
||||
gem "launchy" # used for opening pages/screenshots when debugging
|
||||
|
||||
# these used only for the Fixnum#seconds method :-/
|
||||
gem "i18n"
|
||||
gem "activesupport"
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
activesupport (3.1.12)
|
||||
multi_json (~> 1.0)
|
||||
addressable (2.3.6)
|
||||
capybara (2.2.1)
|
||||
mime-types (>= 1.16)
|
||||
nokogiri (>= 1.3.3)
|
||||
rack (>= 1.0.0)
|
||||
rack-test (>= 0.5.4)
|
||||
xpath (~> 2.0)
|
||||
capybara-screenshot (0.3.19)
|
||||
capybara (>= 1.0, < 3)
|
||||
launchy
|
||||
cliver (0.3.2)
|
||||
diff-lcs (1.2.5)
|
||||
i18n (0.6.9)
|
||||
launchy (2.4.2)
|
||||
addressable (~> 2.3)
|
||||
mime-types (2.2)
|
||||
mini_portile (0.5.3)
|
||||
multi_json (1.10.0)
|
||||
nokogiri (1.6.1)
|
||||
mini_portile (~> 0.5.0)
|
||||
nokogiri (1.6.1-x86-mingw32)
|
||||
mini_portile (~> 0.5.0)
|
||||
poltergeist (1.5.0)
|
||||
capybara (~> 2.1)
|
||||
cliver (~> 0.3.1)
|
||||
multi_json (~> 1.0)
|
||||
websocket-driver (>= 0.2.0)
|
||||
rack (1.5.2)
|
||||
rack-test (0.6.2)
|
||||
rack (>= 1.0)
|
||||
rspec (2.14.1)
|
||||
rspec-core (~> 2.14.0)
|
||||
rspec-expectations (~> 2.14.0)
|
||||
rspec-mocks (~> 2.14.0)
|
||||
rspec-core (2.14.8)
|
||||
rspec-expectations (2.14.5)
|
||||
diff-lcs (>= 1.1.3, < 2.0)
|
||||
rspec-mocks (2.14.6)
|
||||
websocket-driver (0.3.3)
|
||||
xpath (2.0.0)
|
||||
nokogiri (~> 1.3)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
x86-mingw32
|
||||
|
||||
DEPENDENCIES
|
||||
activesupport
|
||||
capybara
|
||||
capybara-screenshot
|
||||
i18n
|
||||
launchy
|
||||
poltergeist
|
||||
rspec
|
||||
15
web/spec/features/production_spec.rb → monitor/spec/production_spec.rb
Normal file → Executable file
15
web/spec/features/production_spec.rb → monitor/spec/production_spec.rb
Normal file → Executable file
|
|
@ -1,9 +1,14 @@
|
|||
require 'spec_helper'
|
||||
|
||||
# these tests MUST be idempotent and DO use actual production user accounts on www
|
||||
www = 'http://www.jamkazam.com'
|
||||
# these tests should be idempotent, and not spammy to other JK users
|
||||
# because they DO use actual production user accounts on www (see the TestUsers below)
|
||||
|
||||
describe "Production site at #{www}", :test_www => true, :js => true, :type => :feature, :capybara_feature => true do
|
||||
# Jenkins executes rspec on this folder every 15 minutes or so.
|
||||
# SO don't use this to test something like a public session unless you want all the world to see
|
||||
|
||||
www = ENV['MONITOR_URL'] || 'http://www.jamkazam.com'
|
||||
|
||||
describe "Deployed site at #{www}", :js => true, :type => :feature, :capybara_feature => true do
|
||||
|
||||
subject { page }
|
||||
|
||||
|
|
@ -28,7 +33,6 @@ describe "Production site at #{www}", :test_www => true, :js => true, :type =>
|
|||
first_name + ' ' + last_name
|
||||
end
|
||||
end
|
||||
|
||||
user1 = TestUser.new({ email: 'anthony+jim@jamkazam.com', password: 'j4m!t3st3r', first_name: 'Jim', last_name: 'Smith', id: '68e8eea2-140d-44c1-b711-10d07ce70f96' })
|
||||
user2 = TestUser.new({ email: 'anthony+john@jamkazam.com', password: 'j4m!t3st3r', first_name: 'John', last_name: 'Jones', id: '5bbcf689-2f73-452d-815a-c4f44e9e7f3e' })
|
||||
|
||||
|
|
@ -46,7 +50,7 @@ describe "Production site at #{www}", :test_www => true, :js => true, :type =>
|
|||
end
|
||||
|
||||
it "is possible for #{user1} and #{user2} to see each other online, and to send messages" do
|
||||
# this example heavily based on text_message_spec.rb
|
||||
# this example heavily based on text_message_spec.rb in 'web'
|
||||
|
||||
in_client(user1) do
|
||||
sign_in_poltergeist(user1)
|
||||
|
|
@ -89,4 +93,3 @@ describe "Production site at #{www}", :test_www => true, :js => true, :type =>
|
|||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
require 'rubygems'
|
||||
require 'active_support/time'
|
||||
require 'capybara'
|
||||
require 'capybara/rspec'
|
||||
require 'capybara-screenshot'
|
||||
require 'capybara-screenshot/rspec'
|
||||
require 'capybara/poltergeist'
|
||||
|
||||
require 'support/client_interactions' #TODO: Strip out the helper methods that production_spec does not use
|
||||
require 'support/utilities'
|
||||
require 'support/stubs' # to make the JamXXXX warnings go away
|
||||
|
||||
# This file was generated by the `rspec --init` command. Conventionally, all
|
||||
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
||||
# Require this file using `require "spec_helper"` to ensure that it is only
|
||||
# loaded once.
|
||||
#
|
||||
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
||||
RSpec.configure do |config|
|
||||
config.treat_symbols_as_metadata_keys_with_true_values = true
|
||||
config.run_all_when_everything_filtered = true
|
||||
config.filter_run :focus
|
||||
|
||||
# Run specs in random order to surface order dependencies. If you find an
|
||||
# order dependency and want to debug it, you can fix the order by providing
|
||||
# the seed, which is printed after each run.
|
||||
# --seed 1234
|
||||
config.order = 'random'
|
||||
|
||||
config.include Capybara::DSL
|
||||
end
|
||||
|
||||
Capybara.javascript_driver = :poltergeist
|
||||
Capybara.default_driver = :poltergeist
|
||||
Capybara.run_server = false # since we're testing an app outside this project
|
||||
Capybara.default_wait_time = 15 # ^^ ditto
|
||||
|
||||
Capybara.configure do |config|
|
||||
config.match = :one
|
||||
config.exact_options = true
|
||||
config.ignore_hidden_elements = true
|
||||
config.visible_text_only = true
|
||||
end
|
||||
|
|
@ -0,0 +1,126 @@
|
|||
|
||||
# methods here all assume you are in /client
|
||||
|
||||
NOTIFICATION_PANEL = '[layout-id="panelNotifications"]'
|
||||
|
||||
# enters text into the search sidebar
|
||||
def site_search(text, options = {})
|
||||
within('#searchForm') do
|
||||
fill_in "search-input", with: text
|
||||
end
|
||||
|
||||
if options[:expand]
|
||||
page.driver.execute_script("jQuery('#searchForm').submit()")
|
||||
find('h1', text:'search results')
|
||||
end
|
||||
end
|
||||
|
||||
# goes to the musician tile, and tries to find a musician
|
||||
def find_musician(user)
|
||||
visit "/client#/musicians"
|
||||
|
||||
timeout = 30
|
||||
|
||||
start = Time.now
|
||||
# scroll by 100px until we find a user with the right id
|
||||
while page.all('#end-of-musician-list').length == 0
|
||||
page.execute_script('jQuery("#musician-filter-results").scrollTo("+=100px", 0, {axis:"y"})')
|
||||
found = page.all(".result-list-button-wrapper[data-musician-id='#{user.id}']")
|
||||
if found.length == 1
|
||||
return found[0]
|
||||
elsif found.length > 1
|
||||
raise "ambiguous results in musician list"
|
||||
end
|
||||
|
||||
if Time.now - start > timeout
|
||||
raise "unable to find musician #{user} within #{timeout} seconds"
|
||||
end
|
||||
end
|
||||
|
||||
raise "unable to find musician #{user}"
|
||||
end
|
||||
|
||||
def initiate_text_dialog(user)
|
||||
|
||||
# verify that the chat window is grayed out
|
||||
site_search(user.first_name, expand: true)
|
||||
|
||||
find("#search-results a[user-id=\"#{user.id}\"][hoveraction=\"musician\"]", text: user.name).hover_intent
|
||||
find('#musician-hover #btnMessage').trigger(:click)
|
||||
find('h1', text: 'conversation with ' + user.name)
|
||||
end
|
||||
|
||||
# sends a text message in the chat interface.
|
||||
def send_text_message(msg, options={})
|
||||
find('#text-message-dialog') # assert that the dialog is showing already
|
||||
|
||||
within('#text-message-dialog form.text-message-box') do
|
||||
fill_in 'new-text-message', with: msg
|
||||
end
|
||||
find('#text-message-dialog .btn-send-text-message').trigger(:click)
|
||||
find('#text-message-dialog .previous-message-text', text: msg) unless options[:should_fail]
|
||||
|
||||
# close the dialog if caller specified close_on_send
|
||||
if options[:close_on_send]
|
||||
find('#text-message-dialog .btn-close-dialog', text: 'CLOSE').trigger(:click) if options[:close_on_send]
|
||||
page.should have_no_selector('#text-message-dialog')
|
||||
end
|
||||
|
||||
if options[:should_fail]
|
||||
find('#notification').should have_text(options[:should_fail])
|
||||
end
|
||||
end
|
||||
|
||||
# sends a chat message during session
|
||||
def send_chat_message(msg)
|
||||
find("[layout-id=\"panelChat\"] .chat-sender").should be_visible
|
||||
|
||||
within("[layout-id=\"panelChat\"] .chat-sender form.chat-message-form") do
|
||||
fill_in 'new-chat-message', with: msg
|
||||
end
|
||||
find("[layout-id=\"panelChat\"] .chat-sender .btn-send-chat-message").trigger(:click)
|
||||
end
|
||||
|
||||
def open_notifications
|
||||
find("#{NOTIFICATION_PANEL} .panel-header").trigger(:click)
|
||||
end
|
||||
|
||||
|
||||
def hover_intent(element)
|
||||
element.hover
|
||||
element.hover
|
||||
end
|
||||
|
||||
# forces document.hasFocus() to return false
|
||||
def document_blur
|
||||
page.evaluate_script(%{(function() {
|
||||
// save original
|
||||
if(!window.documentFocus) { window.documentFocus = window.document.hasFocus; }
|
||||
|
||||
window.document.hasFocus = function() {
|
||||
console.log("document.hasFocus() returns false");
|
||||
return false;
|
||||
}
|
||||
})()})
|
||||
end
|
||||
|
||||
def document_focus
|
||||
page.evaluate_script(%{(function() {
|
||||
// save original
|
||||
if(!window.documentFocus) { window.documentFocus = window.document.hasFocus; }
|
||||
|
||||
window.document.hasFocus = function() {
|
||||
console.log("document.hasFocus() returns true");
|
||||
return true;
|
||||
}
|
||||
})()})
|
||||
end
|
||||
|
||||
# simulates focus event on window
|
||||
def window_focus
|
||||
page.evaluate_script(%{window.jQuery(window).trigger('focus');})
|
||||
end
|
||||
|
||||
def close_websocket
|
||||
page.evaluate_script("window.JK.JamServer.close(true)")
|
||||
end
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
module JamRuby
|
||||
class User
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
def signin_path
|
||||
'/signin'
|
||||
end
|
||||
|
|
@ -0,0 +1,481 @@
|
|||
|
||||
# add a hover_intent method to element, so that you can do find(selector).hover_intent
|
||||
module Capybara
|
||||
module Node
|
||||
class Element
|
||||
|
||||
def attempt_hover
|
||||
begin
|
||||
hover
|
||||
rescue => e
|
||||
end
|
||||
end
|
||||
def hover_intent
|
||||
hover
|
||||
sleep 0.3
|
||||
attempt_hover
|
||||
sleep 0.3
|
||||
attempt_hover
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
# holds a single test's session name's, mapped to pooled session names
|
||||
$capybara_session_mapper = {}
|
||||
|
||||
# called in before (or after) test, to make sure each test run has it's own map of session names
|
||||
def reset_session_mapper
|
||||
$capybara_session_mapper.clear
|
||||
|
||||
Capybara.session_name = :default
|
||||
end
|
||||
|
||||
# manages the mapped session name
|
||||
def mapped_session_name(session_name)
|
||||
return :default if session_name == :default # special treatment for the built-in session
|
||||
$capybara_session_mapper[session_name] ||= 'session_' + $capybara_session_mapper.length.to_s
|
||||
end
|
||||
|
||||
# in place of ever using Capybara.session_name directly,
|
||||
# this utility is used to handle the mapping of session names in a way across all tests runs
|
||||
def in_client(name)
|
||||
session_name = name.class == JamRuby::User ? name.id : name
|
||||
|
||||
Capybara.session_name = mapped_session_name(session_name)
|
||||
|
||||
yield
|
||||
end
|
||||
|
||||
|
||||
def cookie_jar
|
||||
Capybara.current_session.driver.browser.current_session.instance_variable_get(:@rack_mock_session).cookie_jar
|
||||
end
|
||||
|
||||
|
||||
#see also ruby/spec/support/utilities.rb
|
||||
JAMKAZAM_TESTING_BUCKET = 'jamkazam-testing' #at least, this is the name given in jam-ruby
|
||||
def wipe_s3_test_bucket
|
||||
s3 = AWS::S3.new(:access_key_id => Rails.application.config.aws_access_key_id,
|
||||
:secret_access_key => Rails.application.config.aws_secret_access_key)
|
||||
test_bucket = s3.buckets[JAMKAZAM_TESTING_BUCKET]
|
||||
if test_bucket.name == JAMKAZAM_TESTING_BUCKET
|
||||
test_bucket.objects.each do |obj|
|
||||
obj.delete
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def sign_in(user)
|
||||
visit signin_path
|
||||
fill_in "Email", with: user.email
|
||||
fill_in "Password", with: user.password
|
||||
click_button "SIGN IN"
|
||||
# Sign in when not using Capybara as well.
|
||||
cookie_jar[:remember_token] = user.remember_token
|
||||
end
|
||||
|
||||
def set_cookie(k, v)
|
||||
case Capybara.current_session.driver
|
||||
when Capybara::Poltergeist::Driver
|
||||
page.driver.set_cookie(k,v)
|
||||
when Capybara::RackTest::Driver
|
||||
headers = {}
|
||||
Rack::Utils.set_cookie_header!(headers,k,v)
|
||||
cookie_string = headers['Set-Cookie']
|
||||
Capybara.current_session.driver.browser.set_cookie(cookie_string)
|
||||
when Capybara::Selenium::Driver
|
||||
page.driver.browser.manage.add_cookie(:name=>k, :value=>v)
|
||||
else
|
||||
raise "no cookie-setter implemented for driver #{Capybara.current_session.driver.class.name}"
|
||||
end
|
||||
end
|
||||
|
||||
def sign_in_poltergeist(user, options = {})
|
||||
validate = options[:validate]
|
||||
validate = true if validate.nil?
|
||||
|
||||
visit signin_path
|
||||
fill_in "Email Address:", with: user.email
|
||||
fill_in "Password:", with: user.password
|
||||
click_button "SIGN IN"
|
||||
|
||||
wait_until_curtain_gone
|
||||
|
||||
# presence of this means websocket gateway is not working
|
||||
page.should have_no_selector('.no-websocket-connection') if validate
|
||||
end
|
||||
|
||||
|
||||
def sign_out()
|
||||
if Capybara.javascript_driver == :poltergeist
|
||||
page.driver.remove_cookie(:remember_token)
|
||||
else
|
||||
page.driver.browser.manage.remove_cookie :name => :remember_token
|
||||
end
|
||||
end
|
||||
|
||||
def sign_out_poltergeist(options = {})
|
||||
find('.userinfo').hover()
|
||||
click_link 'Sign Out'
|
||||
should_be_at_root if options[:validate]
|
||||
end
|
||||
|
||||
def should_be_at_root
|
||||
find('h1', text: 'Play music together over the Internet as if in the same room')
|
||||
end
|
||||
|
||||
def leave_music_session_sleep_delay
|
||||
# add a buffer to ensure WSG has enough time to expire
|
||||
sleep_dur = (Rails.application.config.websocket_gateway_connect_time_stale_browser +
|
||||
Rails.application.config.websocket_gateway_connect_time_expire_browser) * 1.4
|
||||
sleep sleep_dur
|
||||
end
|
||||
|
||||
|
||||
def wait_for_ajax(wait=Capybara.default_wait_time)
|
||||
wait = wait * 10 #(because we sleep .1)
|
||||
|
||||
counter = 0
|
||||
while page.execute_script("$.active").to_i > 0
|
||||
counter += 1
|
||||
sleep(0.1)
|
||||
raise "AJAX request took longer than #{wait} seconds." if counter >= wait
|
||||
end
|
||||
end
|
||||
|
||||
# waits until the user object has been requested, which comes after the 'curtain' is lifted
|
||||
# and after a call to /api/user/:id for the current user is called initially
|
||||
def wait_until_user(wait=Capybara.default_wait_time)
|
||||
wait = wait * 10 #(because we sleep .1)
|
||||
|
||||
counter = 0
|
||||
# while page.execute_script("$('.curtain').is(:visible)") == "true"
|
||||
# counter += 1
|
||||
# sleep(0.1)
|
||||
# raise "Waiting for user to populate took longer than #{wait} seconds." if counter >= wait
|
||||
# end
|
||||
end
|
||||
|
||||
def wait_until_curtain_gone
|
||||
page.should have_no_selector('.curtain')
|
||||
end
|
||||
|
||||
def wait_to_see_my_track
|
||||
within('div.session-mytracks') {first('div.session-track.track')}
|
||||
end
|
||||
|
||||
def repeat_for(duration=Capybara.default_wait_time)
|
||||
finish_time = Time.now + duration.seconds
|
||||
loop do
|
||||
yield
|
||||
sleep 1 # by default this will execute the block every 1 second
|
||||
break if (Time.now > finish_time)
|
||||
end
|
||||
end
|
||||
|
||||
def determine_test_name(metadata, test_name_buffer = '')
|
||||
description = metadata[:description_args]
|
||||
if description.kind_of?(Array)
|
||||
description = description[0]
|
||||
end
|
||||
if metadata.has_key? :example_group
|
||||
return determine_test_name(metadata[:example_group], "#{description} #{test_name_buffer}")
|
||||
else
|
||||
return "#{description} #{test_name_buffer}"
|
||||
end
|
||||
end
|
||||
|
||||
def get_description
|
||||
description = example.metadata[:description_args]
|
||||
if description.kind_of?(Array)
|
||||
description = description[0]
|
||||
end
|
||||
return description
|
||||
end
|
||||
|
||||
# will select the value from a easydropdown'ed select element
|
||||
def jk_select(text, select)
|
||||
|
||||
# the approach here is to find the hidden select element, and work way back up to the elements that need to be interacted with
|
||||
find(select, :visible => false).find(:xpath, 'ancestor::div[contains(@class, "dropdown easydropdown")]').trigger(:click)
|
||||
find(select, :visible => false).find(:xpath, 'ancestor::div[contains(@class, "dropdown-wrapper") and contains(@class, "easydropdown-wrapper") and contains(@class, "open")]').find('li', text: text).trigger(:click)
|
||||
|
||||
# works, but is 'cheating' because of visible = false
|
||||
#select(genre, :from => 'genres', :visible => false)
|
||||
end
|
||||
|
||||
# takes, or creates, a unique session description which is returned for subsequent calls to join_session to use
|
||||
# in finding this session)
|
||||
def create_session(options={})
|
||||
creator = options[:creator] || FactoryGirl.create(:user)
|
||||
unique_session_desc = options[:description] || "create_join_session #{SecureRandom.urlsafe_base64}"
|
||||
genre = options[:genre] || 'Rock'
|
||||
musician_access = options[:musician_access].nil? ? true : options[:musician_access]
|
||||
fan_access = options[:fan_access].nil? ? true : options[:fan_access]
|
||||
|
||||
# create session in one client
|
||||
in_client(creator) do
|
||||
page.driver.resize(1500, 800) # makes sure all the elements are visible
|
||||
emulate_client
|
||||
sign_in_poltergeist creator
|
||||
wait_until_curtain_gone
|
||||
visit "/client#/createSession"
|
||||
expect(page).to have_selector('h2', text: 'session info')
|
||||
|
||||
within('#create-session-form') do
|
||||
fill_in('description', :with => unique_session_desc)
|
||||
#select(genre, :from => 'genres', :visible => false) # this works, but is 'cheating' because easydropdown hides the native select element
|
||||
jk_select(genre, '#create-session-form select[name="genres"]')
|
||||
|
||||
jk_select(musician_access ? 'Public' : 'Private', '#create-session-form select#musician-access')
|
||||
jk_select(fan_access ? 'Public' : 'Private', '#create-session-form select#fan-access')
|
||||
find('#create-session-form div.musician-access-false.iradio_minimal').trigger(:click)
|
||||
find('div.intellectual-property ins').trigger(:click)
|
||||
find('#btn-create-session').trigger(:click) # fails if page width is low
|
||||
end
|
||||
|
||||
# verify that the in-session page is showing
|
||||
expect(page).to have_selector('h2', text: 'my tracks')
|
||||
find('#session-screen .session-mytracks .session-track')
|
||||
end
|
||||
|
||||
return creator, unique_session_desc, genre
|
||||
|
||||
end
|
||||
|
||||
# this code assumes that there are no music sessions in the database. it should fail on the
|
||||
# find('.join-link') call if > 1 session exists because capybara will complain of multiple matches
|
||||
def join_session(joiner, options)
|
||||
description = options[:description]
|
||||
|
||||
in_client(joiner) do
|
||||
page.driver.resize(1500, 800) # makes sure all the elements are visible
|
||||
emulate_client
|
||||
sign_in_poltergeist joiner
|
||||
wait_until_curtain_gone
|
||||
visit "/client#/findSession"
|
||||
|
||||
# verify the session description is seen by second client
|
||||
expect(page).to have_text(description)
|
||||
find('.join-link').trigger(:click)
|
||||
find('#btn-accept-terms').trigger(:click)
|
||||
expect(page).to have_selector('h2', text: 'my tracks')
|
||||
find('#session-screen .session-mytracks .session-track')
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
def emulate_client
|
||||
page.driver.headers = { 'User-Agent' => ' JamKazam ' }
|
||||
end
|
||||
|
||||
def create_join_session(creator, joiners=[], options={})
|
||||
options[:creator] = creator
|
||||
creator, unique_session_desc = create_session(options)
|
||||
|
||||
# find session in second client
|
||||
joiners.each do |joiner|
|
||||
join_session(joiner, description: unique_session_desc)
|
||||
end
|
||||
|
||||
return creator, unique_session_desc
|
||||
end
|
||||
|
||||
def formal_leave_by user
|
||||
in_client(user) do
|
||||
find('#session-leave').trigger(:click)
|
||||
#find('#btn-accept-leave-session').trigger(:click)
|
||||
expect(page).to have_selector('h2', text: 'feed')
|
||||
end
|
||||
end
|
||||
|
||||
def start_recording_with(creator, joiners=[], genre=nil)
|
||||
create_join_session(creator, joiners, {genre: genre})
|
||||
in_client(creator) do
|
||||
find('#recording-start-stop').trigger(:click)
|
||||
find('#recording-status').should have_content 'Stop Recording'
|
||||
end
|
||||
joiners.each do |joiner|
|
||||
in_client(joiner) do
|
||||
find('#notification').should have_content 'started a recording'
|
||||
find('#recording-status').should have_content 'Stop Recording'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def stop_recording
|
||||
find('#recording-start-stop').trigger(:click)
|
||||
end
|
||||
|
||||
def assert_recording_finished
|
||||
find('#recording-status').should have_content 'Make a Recording'
|
||||
should have_selector('h1', text: 'recording finished')
|
||||
end
|
||||
|
||||
def check_recording_finished_for(users=[])
|
||||
users.each do |user|
|
||||
in_client(user) do
|
||||
assert_recording_finished
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def claim_recording(name, description)
|
||||
find('#recording-finished-dialog h1')
|
||||
fill_in "claim-recording-name", with: name
|
||||
fill_in "claim-recording-description", with: description
|
||||
find('#keep-session-recording').trigger(:click)
|
||||
page.should have_no_selector('h1', text: 'recording finished')
|
||||
end
|
||||
|
||||
def set_session_as_private()
|
||||
find('#session-settings-button').trigger(:click)
|
||||
within('#session-settings-dialog') do
|
||||
jk_select("Private", '#session-settings-dialog #session-settings-musician-access')
|
||||
#select('Private', :from => 'session-settings-musician-access')
|
||||
find('#session-settings-dialog-submit').trigger(:click)
|
||||
end
|
||||
# verify it's dismissed
|
||||
page.should have_no_selector('h1', text: 'update session settings')
|
||||
end
|
||||
|
||||
def set_session_as_public()
|
||||
find('#session-settings-button').trigger(:click)
|
||||
within('#session-settings-dialog') do
|
||||
jk_select("Public", '#session-settings-dialog #session-settings-musician-access')
|
||||
# select('Public', :from => 'session-settings-musician-access')
|
||||
find('#session-settings-dialog-submit').trigger(:click)
|
||||
end
|
||||
# verify it's dismissed
|
||||
page.should have_no_selector('h1', text: 'update session settings')
|
||||
end
|
||||
|
||||
def get_options(selector)
|
||||
find(selector, :visible => false).all('option', :visible => false).collect(&:text).uniq
|
||||
end
|
||||
|
||||
def selected_genres(selector='#session-settings-genre')
|
||||
page.evaluate_script("JK.GenreSelectorHelper.getSelectedGenres('#{selector}')")
|
||||
end
|
||||
|
||||
def random_genre
|
||||
['African',
|
||||
'Ambient',
|
||||
'Asian',
|
||||
'Blues',
|
||||
'Classical',
|
||||
'Country',
|
||||
'Electronic',
|
||||
'Folk',
|
||||
'Hip Hop',
|
||||
'Jazz',
|
||||
'Latin',
|
||||
'Metal',
|
||||
'Pop',
|
||||
'R&B',
|
||||
'Reggae',
|
||||
'Religious',
|
||||
'Rock',
|
||||
'Ska',
|
||||
'Other'].sample
|
||||
end
|
||||
|
||||
def change_session_genre #randomly just change it
|
||||
here = 'select.genre-list'
|
||||
#wait_for_ajax
|
||||
find('#session-settings-button').trigger(:click)
|
||||
find('#session-settings-dialog') # ensure the dialog is visible
|
||||
within('#session-settings-dialog') do
|
||||
wait_for_ajax
|
||||
@new_genre = get_options(here).-(["Select Genre"]).-(selected_genres).sample.to_s
|
||||
jk_select(@new_genre, '#session-settings-dialog select[name="genres"]')
|
||||
wait_for_ajax
|
||||
find('#session-settings-dialog-submit').trigger(:click)
|
||||
end
|
||||
return @new_genre
|
||||
end
|
||||
|
||||
def get_session_genre
|
||||
here = 'select.genre-list'
|
||||
find('#session-settings-button').trigger(:click)
|
||||
wait_for_ajax
|
||||
@current_genres = selected_genres
|
||||
find('#session-settings-dialog-submit').trigger(:click)
|
||||
return @current_genres.join(" ")
|
||||
end
|
||||
|
||||
def find_session_contains?(text)
|
||||
visit "/client#/findSession"
|
||||
wait_for_ajax
|
||||
within('#find-session-form') do
|
||||
expect(page).to have_text(text)
|
||||
end
|
||||
end
|
||||
|
||||
def assert_all_tracks_seen(users=[])
|
||||
users.each do |user|
|
||||
in_client(user) do
|
||||
users.reject {|u| u==user}.each do |other|
|
||||
find('div.track-label', text: other.name)
|
||||
#puts user.name + " is able to see " + other.name + "\'s track"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def view_profile_of user
|
||||
id = user.kind_of?(JamRuby::User) ? user.id : user
|
||||
# assume some user signed in already
|
||||
visit "/client#/profile/#{id}"
|
||||
wait_until_curtain_gone
|
||||
end
|
||||
|
||||
def view_band_profile_of band
|
||||
id = band.kind_of?(JamRuby::Band) ? band.id :
|
||||
band.kind_of?(JamRuby::BandMusician) ? band.bands.first.id : band
|
||||
visit "/client#/bandProfile/#{id}"
|
||||
wait_until_curtain_gone
|
||||
end
|
||||
|
||||
def sidebar_search_for string, category
|
||||
visit "/client#/home"
|
||||
find('#search-input')
|
||||
fill_in "search", with: string
|
||||
sleep 1
|
||||
page.execute_script("JK.Sidebar.searchForInput()")
|
||||
wait_for_ajax
|
||||
jk_select(category, "search_text_type")
|
||||
wait_for_ajax
|
||||
end
|
||||
|
||||
def show_user_menu
|
||||
page.execute_script("$('ul.shortcuts').show()")
|
||||
#page.execute_script("JK.UserDropdown.menuHoverIn()")
|
||||
end
|
||||
|
||||
# wait for the easydropdown version of the specified select element to become visible
|
||||
def wait_for_easydropdown(select)
|
||||
find(select, :visible => false).find(:xpath, 'ancestor::div[contains(@class, "dropdown easydropdown")]')
|
||||
end
|
||||
|
||||
# defaults to enter key (13)
|
||||
def send_key(selector, keycode = 13)
|
||||
keypress_script = "var e = $.Event('keyup', { keyCode: #{keycode} }); jQuery('#{selector}').trigger(e);"
|
||||
page.driver.execute_script(keypress_script)
|
||||
|
||||
end
|
||||
|
||||
def special_characters
|
||||
["?", "[", "]", "/", "\\", "=", "<", ">", ":", ";", ",", "'", "\"", "&", "$", "#", "*", "(", ")", "|", "~", "`", "!", "{", "}"]
|
||||
end
|
||||
|
||||
def garbage length
|
||||
output = ''
|
||||
length.times { output << special_characters.sample }
|
||||
output.slice(0, length)
|
||||
end
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
#!/bin/sh -x
|
||||
dropdb --if-exists jam
|
||||
dropdb --if-exists jam_db_build
|
||||
dropdb --if-exists jam_ruby_test
|
||||
dropdb --if-exists jam_web_test
|
||||
dropdb --if-exists jam_websockets_test
|
||||
createdb -Upostgres jam || sudo su postgres -c "createdb jam"
|
||||
|
||||
|
|
@ -4,7 +4,7 @@ unless ENV["LOCAL_DEV"] == "1"
|
|||
source 'https://jamjam:blueberryjam@int.jamkazam.com/gems/'
|
||||
end
|
||||
|
||||
devenv = ENV["BUILD_NUMBER"].nil? || ENV["TEST_WWW"] == "1"
|
||||
devenv = ENV["BUILD_NUMBER"].nil?
|
||||
|
||||
if devenv
|
||||
gem 'jam_db', :path=> "../db/target/ruby_package"
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ require "jam_ruby/resque/scheduled/icecast_config_retry"
|
|||
require "jam_ruby/resque/scheduled/icecast_source_check"
|
||||
require "jam_ruby/resque/scheduled/cleanup_facebook_signup"
|
||||
require "jam_ruby/resque/scheduled/unused_music_notation_cleaner"
|
||||
require "jam_ruby/resque/scheduled/user_progress_emailer"
|
||||
require "jam_ruby/resque/google_analytics_event"
|
||||
require "jam_ruby/mq_router"
|
||||
require "jam_ruby/base_manager"
|
||||
|
|
@ -145,10 +146,14 @@ require "jam_ruby/models/country"
|
|||
require "jam_ruby/models/region"
|
||||
require "jam_ruby/models/city"
|
||||
require "jam_ruby/models/email_batch"
|
||||
require "jam_ruby/models/email_batch_periodic"
|
||||
require "jam_ruby/models/email_batch_new_musician"
|
||||
require "jam_ruby/models/email_batch_progression"
|
||||
require "jam_ruby/models/email_batch_set"
|
||||
require "jam_ruby/models/email_error"
|
||||
require "jam_ruby/app/mailers/async_mailer"
|
||||
require "jam_ruby/app/mailers/batch_mailer"
|
||||
require "jam_ruby/app/mailers/progress_mailer"
|
||||
require "jam_ruby/models/affiliate_partner"
|
||||
require "jam_ruby/models/chat_message"
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
module JamRuby
|
||||
class ProgressMailer < ActionMailer::Base
|
||||
include SendGrid
|
||||
layout "user_mailer"
|
||||
|
||||
sendgrid_category :use_subject_lines
|
||||
sendgrid_unique_args :env => Environment.mode
|
||||
default :from => UserMailer::DEFAULT_SENDER
|
||||
|
||||
def send_reminder(batch_set)
|
||||
user = batch_set.user
|
||||
|
||||
sendgrid_recipients([user.email])
|
||||
sendgrid_substitute('@USERID', [user.id])
|
||||
sendgrid_substitute(EmailBatchProgression::VAR_FIRST_NAME, [user.first_name])
|
||||
|
||||
mail(:to => user.email,
|
||||
:subject => batch_set.subject,
|
||||
:title => batch_set.title) do |format|
|
||||
format.text { render batch_set.sub_type }
|
||||
format.html { render batch_set.sub_type }
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
@ -41,6 +41,7 @@
|
|||
|
||||
sendgrid_recipients([user.email])
|
||||
sendgrid_substitute('@USERID', [user.id])
|
||||
sendgrid_substitute(EmailBatchProgression::VAR_FIRST_NAME, [user.first_name])
|
||||
|
||||
mail(:to => user.email, :subject => "Welcome to JamKazam") do |format|
|
||||
format.text
|
||||
|
|
@ -106,9 +107,9 @@
|
|||
|
||||
sendgrid_recipients([user.email])
|
||||
sendgrid_substitute('@USERID', [user.id])
|
||||
|
||||
sendgrid_unique_args :type => "new_musicians"
|
||||
mail(:to => user.email, :subject => "JamKazam New Musicians in Your Area") do |format|
|
||||
|
||||
mail(:to => user.email, :subject => EmailBatchNewMusician.subject) do |format|
|
||||
format.text
|
||||
format.html
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
<% provide(:title, @title) %>
|
||||
|
||||
<p>Hello <%= EmailBatchProgression::VAR_FIRST_NAME %> --
|
||||
</p>
|
||||
|
||||
<p>We noticed that you have downloaded the free JamKazam application, but you have not yet run the app. You can find other musicians and listen to sessions and recordings on our website, but you need to run the JamKazam application to play with other musicians online. If you are having trouble installing or running the app, please visit our JamKazam support center at the link below, and post a request for assistance so that we can help you get up and running.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a style="color: #588C98;" href="https://jamkazam.desk.com/">https://jamkazam.desk.com</a>
|
||||
</p>
|
||||
|
||||
<p>-- Team JamKazam
|
||||
</p>
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<% provide(:title, @title) %>
|
||||
|
||||
Hello <%= EmailBatchProgression::VAR_FIRST_NAME %> --
|
||||
|
||||
We noticed that you have downloaded the free JamKazam application, but you have not yet run the app. You can find other musicians and listen to sessions and recordings on our website, but you need to run the JamKazam application to play with other musicians online. If you are having trouble installing or running the app, please visit our JamKazam support center at the link below, and post a request for assistance so that we can help you get up and running.
|
||||
|
||||
-- Team JamKazam
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
<% provide(:title, @title) %>
|
||||
|
||||
<p>Hello <%= EmailBatchProgression::VAR_FIRST_NAME %> --
|
||||
</p>
|
||||
|
||||
<p>We noticed that you have registered as a JamKazam musician, but you have not yet downloaded and started using the free JamKazam application. You can find other musicians and listen to sessions and recordings on our website, but you need the free JamKazam application to play with other musicians online. Please click the link below to go to the download page for the free JamKazam application, or visit our JamKazam support center so that we can help you get up and running.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a style="color: #588C98;" href="http://www.jamkazam.com/downloads">Go to Download Page</a>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a style="color: #588C98;" href="https://jamkazam.desk.com">Go to Support Center</a>
|
||||
</p>
|
||||
|
||||
<p>-- Team JamKazam
|
||||
</p>
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<% provide(:title, @title) %>
|
||||
|
||||
Hello <%= EmailBatchProgression::VAR_FIRST_NAME %> --
|
||||
|
||||
We noticed that you have registered as a JamKazam musician, but you have not yet downloaded and started using the free JamKazam application. You can find other musicians and listen to sessions and recordings on our website, but you need the free JamKazam application to play with other musicians online. Please click the link below to go to the download page for the free JamKazam application, or visit our JamKazam support center so that we can help you get up and running.
|
||||
|
||||
Go to Download Page: http://www.jamkazam.com/downloads
|
||||
|
||||
Go to Support Center: https://jamkazam.desk.com
|
||||
|
||||
-- Team JamKazam
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
<% provide(:title, @title) %>
|
||||
|
||||
<p>Hello <%= EmailBatchProgression::VAR_FIRST_NAME %> --
|
||||
</p>
|
||||
|
||||
<p>We noticed that you have not yet successfully set up your audio gear and passed the JamKazam latency and input/output audio gear tests. This means that you cannot yet play in online sessions with other musicians. If you are having trouble with this step, please click the link below for a knowledge base article that can help you get past this hurdle. If the test says your audio gear is not fast enough, or if your audio quality sounds poor, or if you are just confused, it’s very likely the tips in this article will help you get things set up and optimized so you can start playing online.
|
||||
</p>
|
||||
|
||||
<p><a style="color: #588C98;" href="http://bit.ly/1i4Uul4">http://bit.ly/1i4Uul4</a>
|
||||
</p>
|
||||
|
||||
<p>And if this knowledge base article does not get you fixed up, please visit our JamKazam support center at the link below, and post a request for assistance so that we can help you get up and running:
|
||||
</p>
|
||||
|
||||
<p><a style="color: #588C98;" href="https://jamkazam.desk.com">https://jamkazam.desk.com</a>
|
||||
</p>
|
||||
|
||||
<p>-- Team JamKazam
|
||||
</p>
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
<% provide(:title, @title) %>
|
||||
|
||||
Hello <%= EmailBatchProgression::VAR_FIRST_NAME %> --
|
||||
|
||||
We noticed that you have not yet successfully set up your audio gear and passed the JamKazam latency and input/output audio gear tests. This means that you cannot yet play in online sessions with other musicians. If you are having trouble with this step, please click the link below for a knowledge base article that can help you get past this hurdle. If the test says your audio gear is not fast enough, or if your audio quality sounds poor, or if you are just confused, it’s very likely the tips in this article will help you get things set up and optimized so you can start playing online.
|
||||
|
||||
http://bit.ly/1i4Uul4
|
||||
|
||||
And if this knowledge base article does not get you fixed up, please visit our JamKazam support center at the link below, and post a request for assistance so that we can help you get up and running:
|
||||
|
||||
https://jamkazam.desk.com
|
||||
|
||||
-- Team JamKazam
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
<% provide(:title, @title) %>
|
||||
|
||||
<p>Hello <%= EmailBatchProgression::VAR_FIRST_NAME %> --
|
||||
</p>
|
||||
|
||||
<p>We noticed that you haven’t yet played in a JamKazam session with multiple musicians that lasted long enough to be productive or fun. Since that’s the whole point of the service, we wanted to reach out to see if we can help you. Please take a quick look at the suggestions below to see if they help you!
|
||||
</p>
|
||||
|
||||
<p>Find Other Musicians on JamKazam<br />
|
||||
It’s still very early in our company’s development, so we don’t have zillions of users online on our service yet. If you click Find Session, you will often not find a good session to join, both due to the number of musicians online at any given time, and also because you won’t see private sessions where groups of musicians don’t want to be interrupted in their sessions.
|
||||
</p>
|
||||
|
||||
<p>If you are having trouble getting into sessions, we’d suggest you click the Musicians tile on the home screen of the app or the website: <a href="http://www.jamkazam.com/client#/musicians">Go To Musicians Page</a>
|
||||
</p>
|
||||
|
||||
<p>This will display the JamKazam musicians sorted by latency to you - in other words, you can see which musicians have good network connections to you. Any musicians with green and yellow latency scores have good enough connections to support a play session with you. We recommend that read the profiles of these musicians to find others with shared musical interests and good network connections to you, and then use the Message button to say hi and see if they are interested in playing with you. If they are, use the Connect button to “friend” them on JamKazam, and use the Message button to set up a time to meet online for a session.
|
||||
</p>
|
||||
|
||||
<p>Invite Your Friends to Play<br />
|
||||
One of the best ways to connect and play with others is to invite your friends from the “real world” to join you on JamKazam, and then set up a time to meet online and get into a session together. To do this, just go to www.jamkazam.com and sign in. Then move your mouse over your picture or name in the upper right corner of the screen. A menu will be displayed. Click the Invite Friends option, and then you can click Facebook, Google, or Email to easily invite your friends from different services to join you on JamKazam.
|
||||
</p>
|
||||
|
||||
<p>Troubleshoot Session Problems<br />
|
||||
If you are having audio quality problems or other issues when you get into a session, please click the link below to visit our support center, and check the knowledge base articles under the Troubleshooting header to find solutions. And if that doesn’t work, please post a request for assistance in the support center so that we can help you get up and running:
|
||||
</p>
|
||||
|
||||
<p><a style="color: #588C98;" href="https://jamkazam.desk.com">https://jamkazam.desk.com</a>
|
||||
</p>
|
||||
|
||||
<p>-- Team JamKazam
|
||||
</p>
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
<% provide(:title, @title) %>
|
||||
|
||||
Hello <%= EmailBatchProgression::VAR_FIRST_NAME %> --
|
||||
|
||||
We noticed that you haven’t yet played in a JamKazam session with multiple musicians that lasted long enough to be productive or fun. Since that’s the whole point of the service, we wanted to reach out to see if we can help you. Please take a quick look at the suggestions below to see if they help you!
|
||||
|
||||
Find Other Musicians on JamKazam
|
||||
It’s still very early in our company’s development, so we don’t have zillions of users online on our service yet. If you click Find Session, you will often not find a good session to join, both due to the number of musicians online at any given time, and also because you won’t see private sessions where groups of musicians don’t want to be interrupted in their sessions.
|
||||
|
||||
If you are having trouble getting into sessions, we’d suggest you click the Musicians tile on the home screen of the app or the website: http://www.jamkazam.com/client#/musicians
|
||||
|
||||
This will display the JamKazam musicians sorted by latency to you - in other words, you can see which musicians have good network connections to you. Any musicians with green and yellow latency scores have good enough connections to support a play session with you. We recommend that read the profiles of these musicians to find others with shared musical interests and good network connections to you, and then use the Message button to say hi and see if they are interested in playing with you. If they are, use the Connect button to “friend” them on JamKazam, and use the Message button to set up a time to meet online for a session.
|
||||
|
||||
Invite Your Friends to Play
|
||||
One of the best ways to connect and play with others is to invite your friends from the “real world” to join you on JamKazam, and then set up a time to meet online and get into a session together. To do this, just go to www.jamkazam.com and sign in. Then move your mouse over your picture or name in the upper right corner of the screen. A menu will be displayed. Click the Invite Friends option, and then you can click Facebook, Google, or Email to easily invite your friends from different services to join you on JamKazam.
|
||||
|
||||
Troubleshoot Session Problems
|
||||
If you are having audio quality problems or other issues when you get into a session, please click the link below to visit our support center, and check the knowledge base articles under the Troubleshooting header to find solutions. And if that doesn’t work, please post a request for assistance in the support center so that we can help you get up and running:
|
||||
|
||||
https://jamkazam.desk.com
|
||||
|
||||
-- Team JamKazam
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
<% provide(:title, @title) %>
|
||||
|
||||
<p>Hello <%= EmailBatchProgression::VAR_FIRST_NAME %> --
|
||||
</p>
|
||||
|
||||
<p>We noticed that you haven’t yet connected with any friends on JamKazam. Connecting with friends is the best way to help you get into sessions with other musicians on JamKazam. Here are a couple of good ways to connect with others.
|
||||
</p>
|
||||
|
||||
<p>Find Other Musicians on JamKazam<br />
|
||||
To find and connect with other musicians who are already on JamKazam, we’d suggest you click the Musicians tile on the home screen of the app or the website: <a href="http://www.jamkazam.com/client#/musicians">Go To Musicians Page</a>
|
||||
</p>
|
||||
|
||||
<p>This will display the JamKazam musicians sorted by latency to you - in other words, you can see which musicians have good network connections to you. Any musicians with green and yellow latency scores have good enough connections to support a play session with you. We recommend that you read the profiles of these musicians to find others with shared musical interests and good network connections to you, and then use the Message button to say hi and see if they are interested in playing with you. If they are, use the Connect button to “friend” them on JamKazam, and use the Message button to set up a time to meet online for a session.
|
||||
</p>
|
||||
|
||||
<p>Invite Your Friends to Play<br >
|
||||
One of the best ways to connect and play with others is to invite your friends from the “real world” to join you on JamKazam, and then set up a time to meet online and get into a session together. To do this, just go to www.jamkazam.com and sign in. Then move your mouse over your picture or name in the upper right corner of the screen. A menu will be displayed. Click the Invite Friends option, and then you can click Facebook, Google, or Email to easily invite your friends from different services to join you on JamKazam.
|
||||
</p>
|
||||
|
||||
<p>If you have any trouble, please visit our support center at the link below any time to get help:
|
||||
</p>
|
||||
|
||||
<p><a style="color: #588C98;" href="https://jamkazam.desk.com/">https://jamkazam.desk.com</a>
|
||||
</p>
|
||||
|
||||
<p>-- Team JamKazam
|
||||
</p>
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
<% provide(:title, @title) %>
|
||||
|
||||
Hello <%= EmailBatchProgression::VAR_FIRST_NAME %> --
|
||||
|
||||
We noticed that you haven’t yet connected with any friends on JamKazam. Connecting with friends is the best way to help you get into sessions with other musicians on JamKazam. Here are a couple of good ways to connect with others.
|
||||
|
||||
Find Other Musicians on JamKazam
|
||||
To find and connect with other musicians who are already on JamKazam, we’d suggest you click the Musicians tile on the home screen of the app or the website: http://www.jamkazam.com/client#/musicians
|
||||
|
||||
This will display the JamKazam musicians sorted by latency to you - in other words, you can see which musicians have good network connections to you. Any musicians with green and yellow latency scores have good enough connections to support a play session with you. We recommend that you read the profiles of these musicians to find others with shared musical interests and good network connections to you, and then use the Message button to say hi and see if they are interested in playing with you. If they are, use the Connect button to “friend” them on JamKazam, and use the Message button to set up a time to meet online for a session.
|
||||
|
||||
Invite Your Friends to Play
|
||||
One of the best ways to connect and play with others is to invite your friends from the “real world” to join you on JamKazam, and then set up a time to meet online and get into a session together. To do this, just go to www.jamkazam.com and sign in. Then move your mouse over your picture or name in the upper right corner of the screen. A menu will be displayed. Click the Invite Friends option, and then you can click Facebook, Google, or Email to easily invite your friends from different services to join you on JamKazam.
|
||||
|
||||
If you have any trouble, please visit our support center at the link below any time to get help:
|
||||
|
||||
https://jamkazam.desk.com
|
||||
|
||||
|
||||
-- Team JamKazam
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<% provide(:title, @title) %>
|
||||
|
||||
<p>Hello <%= EmailBatchProgression::VAR_FIRST_NAME %> --
|
||||
</p>
|
||||
|
||||
<p>We noticed that you have not invited any of your friends to join you to play together on JamKazam. It’s still very early in our company’s development, so we don’t have zillions of users online on our service yet. One of the best ways to connect and play with others is to invite your friends from the “real world” to join you on JamKazam, and then set up a time to meet online and get into a session together. To do this, just go to www.jamkazam.com and sign in. Then move your mouse over your picture or name in the upper right corner of the screen. A menu will be displayed. Click the Invite Friends option, and then you can click Facebook, Google, or Email to easily invite your friends from different services to join you on JamKazam.
|
||||
</p>
|
||||
|
||||
<p>If you have any trouble, please visit our support center at the link below any time to get help:
|
||||
</p>
|
||||
|
||||
<p><a style="color: #588C98;" href="https://jamkazam.desk.com">https://jamkazam.desk.com</a>
|
||||
</p>
|
||||
|
||||
<p>-- Team JamKazam
|
||||
</p>
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<% provide(:title, @title) %>
|
||||
|
||||
Hello <%= EmailBatchProgression::VAR_FIRST_NAME %> --
|
||||
|
||||
We noticed that you have not invited any of your friends to join you to play together on JamKazam. It’s still very early in our company’s development, so we don’t have zillions of users online on our service yet. One of the best ways to connect and play with others is to invite your friends from the “real world” to join you on JamKazam, and then set up a time to meet online and get into a session together. To do this, just go to www.jamkazam.com and sign in. Then move your mouse over your picture or name in the upper right corner of the screen. A menu will be displayed. Click the Invite Friends option, and then you can click Facebook, Google, or Email to easily invite your friends from different services to join you on JamKazam.
|
||||
|
||||
If you have any trouble, please visit our support center at the link below any time to get help:
|
||||
|
||||
https://jamkazam.desk.com
|
||||
|
||||
-- Team JamKazam
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<% provide(:title, @title) %>
|
||||
|
||||
<p>Hello <%= EmailBatchProgression::VAR_FIRST_NAME %> --
|
||||
</p>
|
||||
|
||||
<p>JamKazam is a young company/service built through the sweat and commitment of a small group of music-loving techies. Please help us continue to grow the service and attract more musicians to play online by liking and/or following us on Facebook, Twitter, and Google+. Just click the icons below to give us little push, thanks!
|
||||
</p>
|
||||
|
||||
<% [:twitter, :facebook, :google].each do |site| %>
|
||||
<%= link_to(image_tag("http://www.jamkazam.com/assets/content/icon_#{site}.png", :style => "vertical-align:top"), "http://www.jamkazam.com/endorse/@USERID/#{site}?src=email") %>
|
||||
<% end %>
|
||||
|
||||
<p>-- Team JamKazam
|
||||
</p>
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
<% provide(:title, @title) %>
|
||||
|
||||
Hello <%= EmailBatchProgression::VAR_FIRST_NAME %> --
|
||||
|
||||
JamKazam is a young company/service built through the sweat and commitment of a small group of music-loving techies. Please help us continue to grow the service and attract more musicians to play online by liking and/or following us on Facebook, Twitter, and Google+. Just click the icons below to give us little push, thanks!
|
||||
|
||||
<% [:twitter, :facebook, :google].each do |site| %>
|
||||
http://www.jamkazam.com/endorse/@USERID/#{site}?src=email
|
||||
|
||||
<% end %>
|
||||
|
||||
-- Team JamKazam
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
<% provide(:title, @title) %>
|
||||
|
||||
<p>Hello <%= EmailBatchProgression::VAR_FIRST_NAME %> --
|
||||
</p>
|
||||
|
||||
<p>We noticed that you haven’t yet rated any of your JamKazam sessions as “good”. It may be that you just are not a “rater”, and that is totally fine. But if you are not having good, high quality, productive and fun sessions, we want to help you get there!
|
||||
</p>
|
||||
|
||||
<p>If you are having audio quality problems or other issues when you get into a session, please click the link below to visit our support center, and check the knowledge base articles under the Troubleshooting header to find solutions. And if that doesn’t work, please post a request for assistance in the support center so that we can help you get up and running:
|
||||
</p>
|
||||
|
||||
<p><a style="color: #588C98;" href="https://jamkazam.desk.com">https://jamkazam.desk.com</a>
|
||||
</p>
|
||||
|
||||
<p>We really want you to be successful and have fun with this new way of playing music with others, so please reach out and let us help you!
|
||||
</p>
|
||||
|
||||
<p>-- Team JamKazam
|
||||
</p>
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
<% provide(:title, @title) %>
|
||||
|
||||
Hello <%= EmailBatchProgression::VAR_FIRST_NAME %> --
|
||||
|
||||
We noticed that you haven’t yet rated any of your JamKazam sessions as “good”. It may be that you just are not a “rater”, and that is totally fine. But if you are not having good, high quality, productive and fun sessions, we want to help you get there!
|
||||
|
||||
If you are having audio quality problems or other issues when you get into a session, please click the link below to visit our support center, and check the knowledge base articles under the Troubleshooting header to find solutions. And if that doesn’t work, please post a request for assistance in the support center so that we can help you get up and running:
|
||||
|
||||
https://jamkazam.desk.com
|
||||
|
||||
We really want you to be successful and have fun with this new way of playing music with others, so please reach out and let us help you!
|
||||
|
||||
-- Team JamKazam
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
<% provide(:title, @title) %>
|
||||
|
||||
<p>Hello <%= EmailBatchProgression::VAR_FIRST_NAME %> --
|
||||
</p>
|
||||
|
||||
<p>We noticed that you haven’t yet made a recording during any of your JamKazam sessions. Recordings are extra special on JamKazam because:
|
||||
</p>
|
||||
|
||||
<ul><li>Recordings are made both as a master mix and at the track/stem level.</li>
|
||||
<li>You can easily play along with your recordings when your friends aren’t available.</li>
|
||||
<li>You can share your recordings with family, friends and fans via Facebook, Twitter, etc.</li>
|
||||
</ul>
|
||||
|
||||
<!--<p>To understand all of the things you can do with recordings on JamKazam, watch this YouTube tutorial video:<br />
|
||||
www.youtube.com/blahblahblah
|
||||
</p>-->
|
||||
|
||||
<p>-- Team JamKazam
|
||||
</p>
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<% provide(:title, @title) %>
|
||||
|
||||
Hello <%= EmailBatchProgression::VAR_FIRST_NAME %> --
|
||||
|
||||
We noticed that you haven’t yet made a recording during any of your JamKazam sessions. Recordings are extra special on JamKazam because:
|
||||
|
||||
- Recordings are made both as a master mix and at the track/stem level.
|
||||
- You can easily play along with your recordings when your friends aren’t available.
|
||||
- You can share your recordings with family, friends and fans via Facebook, Twitter, etc.
|
||||
|
||||
-- Team JamKazam
|
||||
|
|
@ -1,4 +1,8 @@
|
|||
<% provide(:title, 'New JamKazam Musicians in your Area') %>
|
||||
Hi <%= @user.first_name %>,
|
||||
|
||||
<p>The following new musicians have joined JamKazam within the last week, and have Internet connections with low enough latency to you that you can have a good online session together. We'd suggest that you look through the new musicians listed below to see if any match your musical interests, and if so, click through to their profile page on the JamKazam website to send them a message or a request to connect as a JamKazam friend:
|
||||
</p>
|
||||
|
||||
<% link_style = "background-color:#ED3618; margin:0px 8px 0px 8px; border: solid 1px #F27861; outline: solid 2px #ED3618; padding:3px 10px; font-family:Raleway, Arial, Helvetica, sans-serif; font-size:12px; font-weight:300; cursor:pointer; color:#FC9; text-decoration:none;" %>
|
||||
<p>
|
||||
|
|
@ -20,3 +24,8 @@
|
|||
<% end %>
|
||||
</table>
|
||||
</p>
|
||||
<p>There are currently <%= @new_nearby.size%> musicians on JamKazam with low enough latency Internet connections to you to support a good online session. To see ALL the JamKazam musicians with whom you may want to connect and play, view our Musicians page at: <a href="http://www.jamkazam.com/client#/musicians">http://www.jamkazam.com/client#/musicians</a>.
|
||||
</p>
|
||||
|
||||
<p>Best Regards,</p>
|
||||
Team JamKazam
|
||||
|
|
|
|||
|
|
@ -1,9 +1,17 @@
|
|||
New JamKazam Musicians in your Area
|
||||
|
||||
Hi <%= @user.first_name %>,
|
||||
|
||||
The following new musicians have joined JamKazam within the last week, and have Internet connections with low enough latency to you that you can have a good online session together. We'd suggest that you look through the new musicians listed below to see if any match your musical interests, and if so, click through to their profile page on the JamKazam website to send them a message or a request to connect as a JamKazam friend:
|
||||
|
||||
<% @new_nearby.each do |user| %>
|
||||
<%= user.name %> (http://<%= @host %>/client#/profile/<%= user.id %>)
|
||||
<%= user.location %>
|
||||
<% user.instruments.collect { |inst| inst.description }.join(', ') %>
|
||||
<%= user.biography %>
|
||||
|
||||
<% end %>
|
||||
|
||||
There are currently <%= @new_nearby.size%> musicians on JamKazam with low enough latency Internet connections to you to support a good online session. To see ALL the JamKazam musicians with whom you may want to connect and play, view our Musicians page at: http://www.jamkazam.com/client#/musicians.
|
||||
|
||||
Best Regards,
|
||||
Team JamKazam
|
||||
|
|
|
|||
|
|
@ -1,27 +1,45 @@
|
|||
<% provide(:title, 'Welcome to JamKazam!') %>
|
||||
|
||||
<p>Hello <%= EmailBatchProgression::VAR_FIRST_NAME %> --
|
||||
</p>
|
||||
|
||||
<p> We're delighted that you have decided to try the JamKazam service,
|
||||
and we hope that you will enjoy using JamKazam to play music with others.
|
||||
Following are links to some resources that can help to get you up and running quickly.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Tutorial videos that show you how to use the key features of the product:</br>
|
||||
Getting Started Video<br/>
|
||||
We recommend watching this video before you jump into the service just to get oriented. It will really help you hit the ground running:
|
||||
<a style="color: #588C98;" href="https://www.youtube.com/watch?v=VexH4834o9I">https://www.youtube.com/watch?v=VexH4834o9I</a>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Other Great Tutorial Videos<br />
|
||||
There are several other very great videos that will help you understand how to find and connect with other musicians on the service, create your own sessions or find and join other musicians’ sessions, play in sessions, record and share your performances, and even live broadcast your sessions to family, friends, and fans. Check these helpful videos out here:
|
||||
<a style="color: #588C98;" href="https://jamkazam.desk.com/customer/portal/articles/1304097-tutorial-videos">https://jamkazam.desk.com/customer/portal/articles/1304097-tutorial-videos</a>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Getting Started knowledge base articles:</br>
|
||||
Knowledge Base Articles<br />
|
||||
You can find Getting Started knowledge base articles on things like frequently asked questions (FAQ), minimum system requirements for your Windows or Mac computer, how to troubleshoot audio problems in sessions, and more here:
|
||||
<a style="color: #588C98;" href="https://jamkazam.desk.com/customer/portal/topics/564807-getting-started/articles">https://jamkazam.desk.com/customer/portal/topics/564807-getting-started/articles</a>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Support Portal in case you run into trouble and need help:</br>
|
||||
JamKazam Support Portal<br />
|
||||
If you run into trouble and need help, please reach out to us. We will be glad to do everything we can to get you up and running. You can find our support portal here:
|
||||
<a style="color: #588C98;" href="https://jamkazam.desk.com/">https://jamkazam.desk.com/</a>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
We look forward to seeing - and hearing - you online soon!
|
||||
JamKazam Community Forum<br />
|
||||
And if you just want to chat, share tips and war stories, and hang out with fellow JamKazamers, you can visit our community forum here:
|
||||
<a style="color: #588C98;" href="http://forums.jamkazam.com/">http://forums.jamkazam.com/</a>
|
||||
</p>
|
||||
|
||||
- Team JamKazam
|
||||
<p>
|
||||
Please take a moment to like or follow us by clicking the icons below, and we look forward to seeing – and hearing – you online soon!
|
||||
</p>
|
||||
|
||||
-- Team JamKazam
|
||||
|
|
|
|||
|
|
@ -1,16 +1,27 @@
|
|||
We're delighted that you have decided to try the JamKazam service,
|
||||
and we hope that you will enjoy using JamKazam to play music with others.
|
||||
Following are links to some resources that can help to get you up and running quickly.
|
||||
Hello <%= EmailBatchProgression::VAR_FIRST_NAME %> --
|
||||
|
||||
Tutorial videos that show you how to use the key features of the product:
|
||||
We're delighted that you have decided to try the JamKazam service, and we hope that you will enjoy using JamKazam to play music with others. Following are links to some resources that can help to get you up and running quickly.
|
||||
|
||||
Getting Started Video
|
||||
We recommend watching this video before you jump into the service just to get oriented. It will really help you hit the ground running:
|
||||
https://www.youtube.com/watch?v=VexH4834o9I
|
||||
|
||||
Other Great Tutorial Videos
|
||||
There are several other very great videos that will help you understand how to find and connect with other musicians on the service, create your own sessions or find and join other musicians’ sessions, play in sessions, record and share your performances, and even live broadcast your sessions to family, friends, and fans. Check these helpful videos out here:
|
||||
https://jamkazam.desk.com/customer/portal/articles/1304097-tutorial-videos
|
||||
|
||||
Getting Started knowledge base articles:
|
||||
Knowledge Base Articles
|
||||
You can find Getting Started knowledge base articles on things like frequently asked questions (FAQ), minimum system requirements for your Windows or Mac computer, how to troubleshoot audio problems in sessions, and more here:
|
||||
https://jamkazam.desk.com/customer/portal/topics/564807-getting-started/articles
|
||||
|
||||
Support Portal in case you run into trouble and need help:
|
||||
https://jamkazam.desk.com/
|
||||
JamKazam Support Portal
|
||||
If you run into trouble and need help, please reach out to us. We will be glad to do everything we can to get you up and running. You can find our support portal here:
|
||||
https://jamkazam.desk.com
|
||||
|
||||
We look forward to seeing - and hearing - you online soon!
|
||||
JamKazam Community Forum
|
||||
And if you just want to chat, share tips and war stories, and hang out with fellow JamKazamers, you can visit our community forum here:
|
||||
http://forums.jamkazam.com
|
||||
|
||||
- Team JamKazam
|
||||
Please take a moment to like or follow us by clicking the icons below, and we look forward to seeing – and hearing – you online soon!
|
||||
|
||||
-- Team JamKazam
|
||||
|
|
|
|||
|
|
@ -49,8 +49,8 @@
|
|||
<table align="center" width="650" cellpadding="10" bgcolor="#156572" cellspacing="0">
|
||||
<tr>
|
||||
<td align="center" valign="top">
|
||||
<% [:twitter, :facebook, :google].each do |src| %>
|
||||
<%= link_to(image_tag("http://www.jamkazam.com/assets/content/icon_#{src}.png", :style => "vertical-align:top"), "http://www.jamkazam.com/endorse/@USERID/#{src}") %>
|
||||
<% [:twitter, :facebook, :google].each do |site| %>
|
||||
<%= link_to(image_tag("http://www.jamkazam.com/assets/content/icon_#{site}.png", :style => "vertical-align:top"), "http://www.jamkazam.com/endorse/@USERID/#{site}?src=email") %>
|
||||
<% end %>
|
||||
</td>
|
||||
</tr>
|
||||
|
|
|
|||
|
|
@ -347,7 +347,7 @@ SQL
|
|||
|
||||
connection = Connection.find_by_client_id_and_user_id!(client_id, user.id)
|
||||
|
||||
connection.join_the_session(music_session, as_musician, tracks)
|
||||
connection.join_the_session(music_session, as_musician, tracks, user)
|
||||
# connection.music_session_id = music_session.id
|
||||
# connection.as_musician = as_musician
|
||||
# connection.joining_session = true
|
||||
|
|
|
|||
|
|
@ -27,7 +27,10 @@ module JamRuby
|
|||
start = params[:start].presence
|
||||
start = start.to_i || 0
|
||||
|
||||
query = ChatMessage.offset(start).limit(limit)
|
||||
music_session_id = params[:music_session]
|
||||
|
||||
query = ChatMessage.where('music_session_id = ?', music_session_id)
|
||||
.offset(start).limit(limit)
|
||||
|
||||
if query.length == 0
|
||||
[query, nil]
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ module JamRuby
|
|||
end
|
||||
|
||||
def did_create
|
||||
self.user.update_lat_lng(self.ip_address) if self.user && self.ip_address
|
||||
# self.user.update_lat_lng(self.ip_address) if self.user && self.ip_address
|
||||
end
|
||||
|
||||
def report_add_participant
|
||||
|
|
@ -148,13 +148,18 @@ module JamRuby
|
|||
true
|
||||
end
|
||||
|
||||
def join_the_session(music_session, as_musician, tracks)
|
||||
def join_the_session(music_session, as_musician, tracks, user)
|
||||
self.music_session_id = music_session.id
|
||||
self.as_musician = as_musician
|
||||
self.joining_session = true
|
||||
self.joined_session_at = Time.now
|
||||
associate_tracks(tracks) unless tracks.nil?
|
||||
self.save
|
||||
|
||||
# if user joins the session as a musician, update their addr and location
|
||||
if as_musician
|
||||
user.update_addr_loc(self, 'j')
|
||||
end
|
||||
end
|
||||
|
||||
def associate_tracks(tracks)
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ module JamRuby
|
|||
VAR_LAST_NAME = '@LASTNAME'
|
||||
|
||||
DEFAULT_SENDER = "noreply@jamkazam.com"
|
||||
BATCH_SIZE = 5
|
||||
BATCH_SIZE = 500
|
||||
|
||||
BODY_TEMPLATE =<<FOO
|
||||
Hello #{VAR_FIRST_NAME},
|
||||
|
|
@ -78,11 +78,20 @@ FOO
|
|||
self.test_emails.present? && (self.tested? || self.pending?)
|
||||
end
|
||||
|
||||
def deliver_batch_sets!
|
||||
User.email_opt_in.find_in_batches(batch_size: BATCH_SIZE) do |users|
|
||||
self.email_batch_sets << (bset = EmailBatchSet.load_set(self, users.map(&:id)))
|
||||
if 'test' == Rails.env
|
||||
BatchMailer.send_batch_email(self.id, bset.user_ids).deliver!
|
||||
else
|
||||
BatchMailer.send_batch_email(self.id, bset.user_ids).deliver
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def deliver_batch
|
||||
self.perform_event('do_batch_run!')
|
||||
User.email_opt_in.find_in_batches(batch_size: BATCH_SIZE) do |users|
|
||||
self.email_batch_sets << EmailBatchSet.deliver_set(self.id, users.map(&:id))
|
||||
end
|
||||
self.deliver_batch_sets!
|
||||
end
|
||||
|
||||
def test_count
|
||||
|
|
@ -195,5 +204,13 @@ FOO
|
|||
})
|
||||
end
|
||||
|
||||
def batch_substitutions(users=[])
|
||||
{}
|
||||
end
|
||||
|
||||
def body_for_users(users=[])
|
||||
self.body
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
module JamRuby
|
||||
class EmailBatchNewMusician < EmailBatchPeriodic
|
||||
|
||||
BATCH_SIZE = 500
|
||||
|
||||
SINCE_WEEKS = 2
|
||||
|
||||
VAR_MUSICIAN_COUNT = "@MUSICIAN_COUNT"
|
||||
VAR_MUSICIAN_TABLE = "@MUSICIAN_TABLE"
|
||||
|
||||
def self.subject
|
||||
"New musicians with good Internet connections to you have joined JamKazam!"
|
||||
end
|
||||
|
||||
def fetch_recipients(since=nil)
|
||||
since ||= Time.now - SINCE_WEEKS.weeks
|
||||
User.geocoded_users
|
||||
.email_opt_in
|
||||
.where(['created_at < ?', since])
|
||||
.find_in_batches(batch_size: EmailBatchNewMusician::BATCH_SIZE) do |users|
|
||||
new_musicians = users.inject({}) do |hh, uu|
|
||||
if 0 < (nearby = uu.nearest_musicians).count
|
||||
hh[uu] = nearby
|
||||
end
|
||||
hh
|
||||
end
|
||||
yield(new_musicians) if block_given?
|
||||
end
|
||||
end
|
||||
|
||||
def deliver_batch_sets!
|
||||
self.opt_in_count = 0
|
||||
sent = 0
|
||||
self.fetch_recipients(self.time_since_last_batch(SINCE_WEEKS)) do |new_musicians|
|
||||
self.opt_in_count += new_musicians.count
|
||||
self.email_batch_sets << (bset = EmailBatchSet.load_set(self, new_musicians.keys.map(&:id)))
|
||||
new_musicians.each do |uu, nearby|
|
||||
UserMailer.new_musicians(uu, nearby).deliver
|
||||
sent += 1
|
||||
end
|
||||
end
|
||||
self.sent_count = sent
|
||||
self.save
|
||||
self.did_batch_run!
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
module JamRuby
|
||||
class EmailBatchPeriodic < EmailBatch
|
||||
self.abstract_class = true
|
||||
|
||||
def time_since_last_batch_query
|
||||
self.class
|
||||
.where(['created_at < ?', self.created_at])
|
||||
.order('created_at DESC')
|
||||
.limit(1)
|
||||
end
|
||||
|
||||
def time_since_last_batch(default_weeks=2)
|
||||
if previous = self.time_since_last_batch_query.first
|
||||
return previous.created_at
|
||||
end
|
||||
Time.now - default_weeks.weeks
|
||||
end
|
||||
|
||||
def fetch_recipients(since=nil)
|
||||
yield([]) if block_given?
|
||||
end
|
||||
|
||||
def self.subject(subtype=nil)
|
||||
''
|
||||
end
|
||||
|
||||
def self.body
|
||||
''
|
||||
end
|
||||
|
||||
def self.new(*args)
|
||||
oo = super
|
||||
oo.body = ''
|
||||
oo.subject = self.subject
|
||||
oo
|
||||
end
|
||||
|
||||
def deliver_batch_sets!
|
||||
end
|
||||
|
||||
def clear_batch_sets!
|
||||
self.email_batch_sets.map(&:destroy)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,227 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
module JamRuby
|
||||
class EmailBatchProgression < EmailBatchPeriodic
|
||||
|
||||
BATCH_SIZE = 500
|
||||
SINCE_WEEKS = 2
|
||||
|
||||
SUBTYPES = [:client_notdl, # Registered Musician Has Not Downloaded Client
|
||||
:client_dl_notrun, # Registered Musician Has Downloaded Client But Not Yet Run It
|
||||
:client_run_notgear, # Registered Musician Has Run Client But Not Successfully Qualified Audio Gear
|
||||
:gear_notsess, # Registered Musician Has Successfully Qualified Audio Gear But Has Not Participated in a ‘Real’ Session
|
||||
:sess_notgood, # Registered Musician Has Participated In a "Real" Session But Has Not Had a "Good" Session
|
||||
:sess_notrecord, # Registered Musician Has Participated In a "Real" Session But Has Not Made a Recording
|
||||
:reg_notinvite, # Registered Musician Has Not Invited Friends to Join JamKazam
|
||||
:reg_notconnect, # Registered Musician Has Not Connected with any Friends on JamKazam
|
||||
:reg_notlike, # Registered Musician Has Not Liked Jamkazam
|
||||
]
|
||||
|
||||
SUBTYPE_METADATA = {
|
||||
:client_notdl => {
|
||||
:subject => "Get the free JamKazam app now and start playing with others!",
|
||||
:title => "Download the Free JamKazam App"
|
||||
},
|
||||
:client_dl_notrun => {
|
||||
:subject => "Having trouble running the JamKazam application?",
|
||||
:title => "Running the JamKazam App"
|
||||
},
|
||||
:client_run_notgear => {
|
||||
:subject => "Having trouble setting up your audio gear for JamKazam?",
|
||||
:title => "Setting Up and Qualifying Your Audio Gear on JamKazam"
|
||||
},
|
||||
:gear_notsess => {
|
||||
:subject => "Having trouble getting into a session with other musicians?",
|
||||
:title => "Tips on Getting into Sessions with Other Musicians"
|
||||
},
|
||||
:sess_notgood => {
|
||||
:subject => "Have you played in a “good” session on JamKazam yet?",
|
||||
:title => "Having a Good Session on JamKazam"
|
||||
},
|
||||
:reg_notinvite => {
|
||||
:subject => "Invite your friends to JamKazam, best way to play online!",
|
||||
:title => "Invite Your Friends to Come and Play with You"
|
||||
},
|
||||
:reg_notconnect => {
|
||||
:subject => "Make friends on JamKazam and play more music!",
|
||||
:title => "Connecting with Friends on JamKazam"
|
||||
},
|
||||
:reg_notlike => {
|
||||
:subject => "Please give us a LIKE!",
|
||||
:title => "Like/Follow JamKazam"
|
||||
},
|
||||
:sess_notrecord => {
|
||||
:subject => "Want to make recordings during your JamKazam sessions?",
|
||||
:title => "Making & Sharing Recordings on JamKazam"
|
||||
},
|
||||
}
|
||||
|
||||
def self.subject(subtype=nil)
|
||||
SUBTYPE_METADATA[subtype][:subject] if subtype
|
||||
end
|
||||
|
||||
def self.title(subtype=nil)
|
||||
SUBTYPE_METADATA[subtype][:title] if subtype
|
||||
end
|
||||
|
||||
def self.subtype_trigger_interval(subtype)
|
||||
[:reg_notlike, :sess_notrecord].include?(subtype) ? [7,14,21] : [2,5,14]
|
||||
end
|
||||
|
||||
def self.days_past_for_trigger_index(subtype, idx)
|
||||
self.subtype_trigger_interval(subtype)[idx]
|
||||
end
|
||||
|
||||
def days_diff(tidx)
|
||||
self.class.days_past_for_trigger_index(self.sub_type,tidx) - self.class.days_past_for_trigger_index(self.sub_type, tidx - 1)
|
||||
end
|
||||
|
||||
def days_past_for_trigger_index(idx)
|
||||
self.class.subtype_trigger_interval(self.sub_type)[idx]
|
||||
end
|
||||
|
||||
def make_set(uu, trigger_idx)
|
||||
EmailBatchSet.progress_set(self, uu, trigger_idx)
|
||||
end
|
||||
|
||||
def trigger_date_constraint(trigger_idx, tbl='tt')
|
||||
intervals = self.class.subtype_trigger_interval(self.sub_type)
|
||||
date_constraint = (Time.now - intervals[trigger_idx].days + 1.hour).strftime('%Y-%m-%d %H:%M:%S')
|
||||
|
||||
case self.sub_type.to_sym
|
||||
when :client_notdl, :reg_notconnect, :reg_notinvite, :reg_notlike
|
||||
return "#{tbl}.created_at < '#{date_constraint}'"
|
||||
when :client_dl_notrun
|
||||
return "#{tbl}.first_downloaded_client_at < '#{date_constraint}'"
|
||||
when :client_run_notgear
|
||||
return "#{tbl}.first_ran_client_at < '#{date_constraint}'"
|
||||
when :gear_notsess
|
||||
return "#{tbl}.first_certified_gear_at < '#{date_constraint}'"
|
||||
when :sess_notgood
|
||||
return "#{tbl}.first_real_music_session_at < '#{date_constraint}'"
|
||||
when :sess_notrecord
|
||||
return "#{tbl}.first_real_music_session_at < '#{date_constraint}'"
|
||||
end
|
||||
end
|
||||
|
||||
def progress_column_constraint(tbl='tt')
|
||||
case self.sub_type.to_sym
|
||||
when :client_notdl
|
||||
return "#{tbl}.first_downloaded_client_at IS NULL"
|
||||
when :client_dl_notrun
|
||||
return "#{tbl}.first_downloaded_client_at IS NOT NULL AND #{tbl}.first_ran_client_at IS NULL"
|
||||
when :client_run_notgear
|
||||
return "#{tbl}.first_ran_client_at IS NOT NULL AND #{tbl}.first_certified_gear_at IS NULL"
|
||||
when :gear_notsess
|
||||
return "#{tbl}.first_certified_gear_at IS NOT NULL AND #{tbl}.first_real_music_session_at IS NULL"
|
||||
when :sess_notgood
|
||||
return "#{tbl}.first_real_music_session_at IS NOT NULL AND #{tbl}.first_good_music_session_at IS NULL"
|
||||
when :sess_notrecord
|
||||
return "#{tbl}.first_real_music_session_at IS NOT NULL AND #{tbl}.first_recording_at IS NULL"
|
||||
when :reg_notinvite
|
||||
return "#{tbl}.first_invited_at IS NULL"
|
||||
when :reg_notconnect
|
||||
return "#{tbl}.first_friended_at IS NULL"
|
||||
when :reg_notlike
|
||||
return "#{tbl}.first_social_promoted_at IS NULL"
|
||||
end
|
||||
''
|
||||
end
|
||||
|
||||
def fetch_recipients(trigger_idx=0, per_page=BATCH_SIZE)
|
||||
fetched = []
|
||||
offset = 0
|
||||
if 0==trigger_idx
|
||||
prev_date_sql = 'tt.prev_trigger_date IS NULL'
|
||||
else
|
||||
prev_date_sql = "tt.prev_trigger_date + interval '#{self.days_diff(trigger_idx)} days' <= '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}'"
|
||||
end
|
||||
countsql =<<SQL
|
||||
SELECT COUNT(*)
|
||||
FROM (SELECT "users".*,
|
||||
(SELECT COALESCE(MAX(ebs.trigger_index),-1)
|
||||
FROM email_batch_sets ebs
|
||||
WHERE
|
||||
ebs.sub_type = '#{self.sub_type}' AND
|
||||
ebs.user_id = users.id
|
||||
) AS tidx,
|
||||
(SELECT created_at
|
||||
FROM email_batch_sets ebs
|
||||
WHERE
|
||||
ebs.sub_type = '#{self.sub_type}' AND
|
||||
ebs.user_id = users.id AND trigger_index = #{trigger_idx - 1}
|
||||
) AS prev_trigger_date
|
||||
FROM users) tt
|
||||
WHERE
|
||||
tt."subscribe_email" = 't' AND
|
||||
tt."musician" = 't' AND
|
||||
(#{progress_column_constraint}) AND
|
||||
(#{self.trigger_date_constraint(trigger_idx)}) AND
|
||||
tt.tidx = #{trigger_idx - 1} AND
|
||||
#{prev_date_sql}
|
||||
SQL
|
||||
num_users = User.count_by_sql(countsql)
|
||||
loops = (num_users / per_page) + (num_users % per_page) - 1
|
||||
0.upto(loops) do |nn|
|
||||
offset = nn * per_page
|
||||
sql =<<SQL
|
||||
SELECT tt.*
|
||||
FROM (SELECT "users".*,
|
||||
(SELECT COALESCE(MAX(ebs.trigger_index),-1)
|
||||
FROM email_batch_sets ebs
|
||||
WHERE
|
||||
ebs.sub_type = '#{self.sub_type}' AND
|
||||
ebs.user_id = users.id
|
||||
) AS tidx,
|
||||
(SELECT created_at
|
||||
FROM email_batch_sets ebs
|
||||
WHERE
|
||||
ebs.sub_type = '#{self.sub_type}' AND
|
||||
ebs.user_id = users.id AND trigger_index = #{trigger_idx - 1}
|
||||
) AS prev_trigger_date
|
||||
FROM users) tt
|
||||
WHERE
|
||||
tt."subscribe_email" = 't' AND
|
||||
tt."musician" = 't' AND
|
||||
(#{progress_column_constraint}) AND
|
||||
(#{self.trigger_date_constraint(trigger_idx)}) AND
|
||||
tt.tidx = #{trigger_idx - 1} AND
|
||||
#{prev_date_sql}
|
||||
ORDER BY tt.id
|
||||
ASC LIMIT #{per_page}
|
||||
OFFSET #{offset}
|
||||
SQL
|
||||
users = User.find_by_sql(sql)
|
||||
block_given? ? yield(users) : fetched.concat(users)
|
||||
end
|
||||
fetched
|
||||
end
|
||||
|
||||
def deliver_batch_sets!
|
||||
self.opt_in_count = 0
|
||||
sent = 0
|
||||
3.times do |trigger_idx|
|
||||
self.fetch_recipients(trigger_idx) do |users|
|
||||
users.each do |uu|
|
||||
self.email_batch_sets << (bset = self.make_set(uu, trigger_idx))
|
||||
ProgressMailer.send_reminder(bset).deliver
|
||||
sent += 1
|
||||
end
|
||||
end
|
||||
end
|
||||
self.sent_count = sent
|
||||
self.save
|
||||
self.did_batch_run!
|
||||
end
|
||||
|
||||
def self.send_progress_batch
|
||||
self::SUBTYPES.collect do |stype|
|
||||
ebatch = self.create
|
||||
ebatch.update_attribute(:sub_type, stype.to_s)
|
||||
ebatch
|
||||
end.each do |ebatch|
|
||||
ebatch.deliver_batch
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
@ -3,21 +3,53 @@ module JamRuby
|
|||
self.table_name = "email_batch_sets"
|
||||
|
||||
belongs_to :email_batch, :class_name => 'JamRuby::EmailBatch'
|
||||
belongs_to :user, :class_name => 'JamRuby::User'
|
||||
|
||||
def self.deliver_set(batch_id, user_ids)
|
||||
def self.load_set(batch, user_ids)
|
||||
bset = self.new
|
||||
bset.email_batch_id = batch_id
|
||||
bset.email_batch_id = batch.id
|
||||
bset.user_ids = user_ids.join(',')
|
||||
bset.started_at = Time.now
|
||||
bset.batch_count = user_ids.size
|
||||
bset.save!
|
||||
|
||||
if 'test' == Rails.env
|
||||
BatchMailer.send_batch_email(bset.email_batch_id, user_ids).deliver!
|
||||
else
|
||||
BatchMailer.send_batch_email(bset.email_batch_id, user_ids).deliver
|
||||
end
|
||||
bset
|
||||
end
|
||||
|
||||
def self.progress_set(batch, user, trigger_idx)
|
||||
bset = self.new
|
||||
bset.email_batch = batch
|
||||
bset.user = user
|
||||
bset.started_at = Time.now
|
||||
bset.batch_count = 1
|
||||
bset.trigger_index = trigger_idx
|
||||
bset.sub_type = batch.sub_type
|
||||
bset.save!
|
||||
bset
|
||||
end
|
||||
|
||||
def subject
|
||||
unless sub_type.blank?
|
||||
return EmailBatchProgression.subject(self.sub_type.to_sym)
|
||||
end
|
||||
''
|
||||
end
|
||||
|
||||
def title
|
||||
unless sub_type.blank?
|
||||
return EmailBatchProgression.title(self.sub_type.to_sym)
|
||||
end
|
||||
''
|
||||
end
|
||||
|
||||
def previous_trigger_date
|
||||
return nil if 0 == self.trigger_index.to_i || self.user_id.nil?
|
||||
self.class
|
||||
.where(['email_batch__id = ? AND user_id = ? AND sub_type = ? AND trigger_index = ?',
|
||||
self.email_batch_id, self.user_id, self.sub_type, self.trigger_index - 1])
|
||||
.pluck(:created_at)
|
||||
.limit(1)
|
||||
.first
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -3,15 +3,15 @@ module JamRuby
|
|||
|
||||
self.table_name = "connections"
|
||||
|
||||
def self.get_work(mylocidispid)
|
||||
list = self.get_work_list(mylocidispid)
|
||||
def self.get_work(mylocidispid, myaddr)
|
||||
list = self.get_work_list(mylocidispid, myaddr)
|
||||
return nil if list.nil?
|
||||
return nil if list.length == 0
|
||||
return list[0]
|
||||
end
|
||||
|
||||
def self.get_work_list(mylocidispid)
|
||||
r = GetWork.select(:client_id).find_by_sql("select get_work(#{mylocidispid}) as client_id")
|
||||
def self.get_work_list(mylocidispid, myaddr)
|
||||
r = GetWork.select(:client_id).find_by_sql("select get_work(#{mylocidispid}, #{myaddr}) as client_id")
|
||||
#puts("r = #{r}")
|
||||
a = r.map {|i| i.client_id}
|
||||
#puts("a = #{a}")
|
||||
|
|
|
|||
|
|
@ -88,35 +88,42 @@ module JamRuby
|
|||
end
|
||||
end
|
||||
end
|
||||
User.find_each { |usr| usr.update_lat_lng }
|
||||
# User.find_each { |usr| usr.update_lat_lng }
|
||||
Band.find_each { |bnd| bnd.update_lat_lng }
|
||||
end
|
||||
|
||||
def self.where_latlng(relation, params, current_user=nil)
|
||||
if 0 < (distance = params[:distance].to_i)
|
||||
latlng = []
|
||||
if location_city = params[:city]
|
||||
if geo = self.where(:city => params[:city]).limit(1).first
|
||||
# this is only valid to call when relation is about bands
|
||||
distance = params[:distance].to_i
|
||||
if distance > 0
|
||||
latlng = nil
|
||||
location_city = params[:city]
|
||||
location_state = params[:state]
|
||||
location_country = params[:country]
|
||||
remote_ip = params[:remote_ip]
|
||||
|
||||
if location_city and location_state and location_country
|
||||
geo = self.where(city: location_city, region: location_state, country: location_country).limit(1).first
|
||||
if geo and geo.lat and geo.lng and (geo.lat != 0 or geo.lng != 0)
|
||||
# it isn't reasonable for both to be 0...
|
||||
latlng = [geo.lat, geo.lng]
|
||||
end
|
||||
elsif current_user
|
||||
if current_user.lat.nil? || current_user.lng.nil?
|
||||
if params[:remote_ip] && (geo = self.ip_lookup(params[:remote_ip]))
|
||||
geo.lat = nil if geo.lat = 0
|
||||
geo.lng = nil if geo.lng = 0
|
||||
latlng = [geo.lat, geo.lng] if geo.lat && geo.lng
|
||||
end
|
||||
else
|
||||
latlng = [current_user.lat, current_user.lng]
|
||||
elsif current_user and current_user.locidispid and current_user.locidispid != 0
|
||||
location = GeoIpLocations.lookup(current_user.locidispid/1000000)
|
||||
if location and location.latitude and location.longitude and (location.latitude != 0 or location.longitude != 0)
|
||||
# it isn't reasonable for both to be 0...
|
||||
latlng = [location.latitude, location.longitude]
|
||||
end
|
||||
elsif remote_ip
|
||||
geo = self.ip_lookup(remote_ip)
|
||||
if geo and geo.lat and geo.lng and (geo.lat != 0 or geo.lng != 0)
|
||||
# it isn't reasonable for both to be 0...
|
||||
latlng = [geo.lat, geo.lng]
|
||||
end
|
||||
elsif params[:remote_ip] && (geo = self.ip_lookup(params[:remote_ip]))
|
||||
geo.lat = nil if geo.lat = 0
|
||||
geo.lng = nil if geo.lng = 0
|
||||
latlng = [geo.lat, geo.lng] if geo.lat && geo.lng
|
||||
end
|
||||
if latlng.present?
|
||||
relation = relation.where(['lat IS NOT NULL AND lng IS NOT NULL'])
|
||||
.within(distance, :origin => latlng)
|
||||
|
||||
if latlng
|
||||
relation = relation.where(['lat IS NOT NULL AND lng IS NOT NULL']).within(distance, origin: latlng)
|
||||
end
|
||||
end
|
||||
relation
|
||||
|
|
|
|||
|
|
@ -7,47 +7,50 @@ module JamRuby
|
|||
self.where(countrycode: country).order('regionname asc').all
|
||||
end
|
||||
|
||||
def self.import_from_xx_region(countrycode, file)
|
||||
def self.import_from_region_codes(file)
|
||||
|
||||
# File xx_region.csv
|
||||
# File region_codes.csv
|
||||
# Format:
|
||||
# region,regionname
|
||||
# countrycode,region,regionname
|
||||
|
||||
# what this does is not replace the contents of the table, but rather update the specifies rows with the names.
|
||||
# any rows not specified are left alone. the parameter countrycode denote the country of the region (when uppercased)
|
||||
|
||||
raise "countrycode (#{MaxMindIsp.quote_value(countrycode)}) is missing or invalid (it must be two characters)" unless countrycode and countrycode.length == 2
|
||||
countrycode = countrycode.upcase
|
||||
# what this does is replace the contents of the table with the new data.
|
||||
|
||||
self.transaction do
|
||||
self.connection.execute "update #{self.table_name} set regionname = region where countrycode = #{MaxMindIsp.quote_value(countrycode)}"
|
||||
self.connection.execute "delete from #{self.table_name}"
|
||||
|
||||
File.open(file, 'r:ISO-8859-1') do |io|
|
||||
saved_level = ActiveRecord::Base.logger ? ActiveRecord::Base.logger.level : 0
|
||||
saved_level = ActiveRecord::Base.logger ? ActiveRecord::Base.logger.level : -1
|
||||
count = 0
|
||||
|
||||
ncols = 2
|
||||
errors = 0
|
||||
ncols = 3
|
||||
|
||||
csv = ::CSV.new(io, {encoding: 'ISO-8859-1', headers: false})
|
||||
csv.each do |row|
|
||||
raise "file does not have expected number of columns (#{ncols}): #{row.length}" unless row.length == ncols
|
||||
|
||||
region = row[0]
|
||||
regionname = row[1]
|
||||
countrycode = row[0]
|
||||
region = row[1]
|
||||
regionname = row[2]
|
||||
|
||||
stmt = "UPDATE #{self.table_name} SET regionname = #{MaxMindIsp.quote_value(regionname)} WHERE countrycode = #{MaxMindIsp.quote_value(countrycode)} AND region = #{MaxMindIsp.quote_value(region)}"
|
||||
self.connection.execute stmt
|
||||
count += 1
|
||||
if countrycode.length == 2 and region.length == 2 and regionname.length >= 2 and regionname.length <= 64
|
||||
|
||||
if ActiveRecord::Base.logger and ActiveRecord::Base.logger.level < Logger::INFO
|
||||
ActiveRecord::Base.logger.debug "... logging updates to #{self.table_name} suspended ..."
|
||||
ActiveRecord::Base.logger.level = Logger::INFO
|
||||
stmt = "INSERT INTO #{self.table_name} (countrycode, region, regionname) VALUES (#{self.connection.quote(countrycode)}, #{self.connection.quote(region)}, #{self.connection.quote(regionname)})"
|
||||
self.connection.execute stmt
|
||||
count += 1
|
||||
|
||||
if ActiveRecord::Base.logger and ActiveRecord::Base.logger.level < Logger::INFO
|
||||
ActiveRecord::Base.logger.debug "... logging updates to #{self.table_name} suspended ..."
|
||||
ActiveRecord::Base.logger.level = Logger::INFO
|
||||
end
|
||||
else
|
||||
ActiveRecord::Base.logger.warn("bogus region_codes record '#{countrycode}', '#{region}', '#{regionname}'") if ActiveRecord::Base.logger
|
||||
errors += 1
|
||||
end
|
||||
end
|
||||
|
||||
if ActiveRecord::Base.logger
|
||||
ActiveRecord::Base.logger.level = saved_level
|
||||
ActiveRecord::Base.logger.debug "updated #{count} records in #{self.table_name}"
|
||||
ActiveRecord::Base.logger.debug "inserted #{count} records into #{self.table_name}, #{errors} errors"
|
||||
end
|
||||
end # file
|
||||
end # transaction
|
||||
|
|
|
|||
|
|
@ -5,13 +5,15 @@ module JamRuby
|
|||
|
||||
self.table_name = 'scores'
|
||||
|
||||
attr_accessible :alocidispid, :anodeid, :aaddr, :blocidispid, :bnodeid, :baddr, :score, :score_dt, :scorer
|
||||
attr_accessible :alocidispid, :anodeid, :aaddr, :blocidispid, :bnodeid, :baddr, :score, :score_dt, :scorer, :scoring_data
|
||||
|
||||
default_scope order('score_dt desc')
|
||||
|
||||
def self.createx(alocidispid, anodeid, aaddr, blocidispid, bnodeid, baddr, score, score_dt)
|
||||
def self.createx(alocidispid, anodeid, aaddr, blocidispid, bnodeid, baddr, score, score_dt=nil, score_data=nil)
|
||||
score_dt = Time.new.utc if score_dt.nil?
|
||||
Score.create(alocidispid: alocidispid, anodeid: anodeid, aaddr: aaddr, blocidispid: blocidispid, bnodeid: bnodeid, baddr: baddr, score: score, scorer: 0, score_dt: score_dt)
|
||||
score = score.ceil
|
||||
raise "score must be positive" if score <= 0
|
||||
Score.create(alocidispid: alocidispid, anodeid: anodeid, aaddr: aaddr, blocidispid: blocidispid, bnodeid: bnodeid, baddr: baddr, score: score, scorer: 0, score_dt: score_dt, scoring_data: score_data)
|
||||
Score.create(alocidispid: blocidispid, anodeid: bnodeid, aaddr: baddr, blocidispid: alocidispid, bnodeid: anodeid, baddr: aaddr, score: score, scorer: 1, score_dt: score_dt) if alocidispid != blocidispid
|
||||
end
|
||||
|
||||
|
|
@ -25,5 +27,9 @@ module JamRuby
|
|||
return -1 if s.nil?
|
||||
return s.score
|
||||
end
|
||||
|
||||
def self.score_conns(c1, c2, score)
|
||||
self.createx(c1.locidispid, c1.client_id, c1.addr, c2.locidispid, c2.client_id, c2.addr, score)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -120,44 +120,95 @@ module JamRuby
|
|||
ordering.blank? ? keys[0] : keys.detect { |oo| oo.to_s == ordering }
|
||||
end
|
||||
|
||||
def self.musician_filter(params={}, current_user=nil)
|
||||
rel = User.musicians
|
||||
# produce a list of musicians (users where musician is true)
|
||||
# params:
|
||||
# instrument - instrument to search for or blank
|
||||
# score_limit - score must be <= this to be included in the result
|
||||
# handled by relation_pagination:
|
||||
# page - page number to fetch (origin 1)
|
||||
# per_page - number of entries per page
|
||||
# handled by order_param:
|
||||
# orderby - ??? (followed, plays, playing)
|
||||
# handled by where_latlng:
|
||||
# distance - defunct
|
||||
# city - defunct
|
||||
# remote_ip - defunct
|
||||
def self.musician_filter(params={}, user=nil, conn=nil)
|
||||
# puts "================ params #{params.inspect}"
|
||||
# puts "================ user #{user.inspect}"
|
||||
# puts "================ conn #{conn.inspect}"
|
||||
|
||||
rel = User.musicians_geocoded
|
||||
rel = rel.select('users.*')
|
||||
rel = rel.group('users.id')
|
||||
|
||||
unless (instrument = params[:instrument]).blank?
|
||||
rel = rel.joins("RIGHT JOIN musicians_instruments AS minst ON minst.user_id = users.id")
|
||||
.where(['minst.instrument_id = ? AND users.id IS NOT NULL', instrument])
|
||||
rel = rel.joins("inner JOIN musicians_instruments AS minst ON minst.user_id = users.id")
|
||||
.where(['minst.instrument_id = ?', instrument])
|
||||
end
|
||||
|
||||
rel = MaxMindGeo.where_latlng(rel, params, current_user)
|
||||
# to find appropriate musicians we need to join users with scores to get to those with no scores or bad scores
|
||||
# weeded out
|
||||
|
||||
sel_str = 'users.*'
|
||||
case ordering = self.order_param(params)
|
||||
when :plays # FIXME: double counting?
|
||||
sel_str = "COUNT(records)+COUNT(sessions) AS play_count, #{sel_str}"
|
||||
rel = rel.joins("LEFT JOIN music_sessions AS sessions ON sessions.user_id = users.id")
|
||||
.joins("LEFT JOIN recordings AS records ON records.owner_id = users.id")
|
||||
.group("users.id")
|
||||
.order("play_count DESC, users.created_at DESC")
|
||||
when :followed
|
||||
sel_str = "COUNT(follows) AS search_follow_count, #{sel_str}"
|
||||
rel = rel.joins("LEFT JOIN follows ON follows.followable_id = users.id")
|
||||
.group("users.id")
|
||||
.order("COUNT(follows) DESC, users.created_at DESC")
|
||||
when :playing
|
||||
rel = rel.joins("LEFT JOIN connections ON connections.user_id = users.id")
|
||||
.where(['connections.music_session_id IS NOT NULL AND connections.aasm_state != ?',
|
||||
'expired'])
|
||||
.order("users.created_at DESC")
|
||||
# filter on scores using selections from params
|
||||
# todo scott what is the real limit?
|
||||
score_limit = 60
|
||||
l = params[:score_limit]
|
||||
unless l.nil? or l.to_i <= 0
|
||||
score_limit = l.to_i
|
||||
end
|
||||
|
||||
rel = rel.select(sel_str)
|
||||
# puts "================ score_limit #{score_limit}"
|
||||
|
||||
locidispid = ((conn and conn.client_type == 'client') ? conn.locidispid : ((user and user.musician) ? user.last_jam_locidispid : nil))
|
||||
|
||||
# puts "================ locidispid #{locidispid}"
|
||||
|
||||
unless locidispid.nil?
|
||||
rel = rel.joins('inner join scores on scores.alocidispid = users.last_jam_locidispid')
|
||||
.where(['scores.blocidispid = ?', locidispid])
|
||||
.where(['scores.score <= ?', score_limit])
|
||||
|
||||
rel = rel.select('scores.score')
|
||||
rel = rel.group('scores.score')
|
||||
end
|
||||
|
||||
ordering = self.order_param(params)
|
||||
# puts "================ ordering #{ordering}"
|
||||
case ordering
|
||||
when :plays # FIXME: double counting?
|
||||
# sel_str = "COUNT(records)+COUNT(sessions) AS play_count, #{sel_str}"
|
||||
rel = rel.select('COUNT(records.id)+COUNT(sessions.id) AS play_count')
|
||||
rel = rel.joins("LEFT JOIN music_sessions AS sessions ON sessions.user_id = users.id")
|
||||
rel = rel.joins("LEFT JOIN recordings AS records ON records.owner_id = users.id")
|
||||
rel = rel.order("play_count DESC")
|
||||
when :followed
|
||||
rel = rel.joins('left outer join follows on follows.followable_id = users.id')
|
||||
rel = rel.select('count(follows.user_id) as search_follow_count')
|
||||
rel = rel.order('search_follow_count DESC')
|
||||
when :playing
|
||||
rel = rel.joins("inner JOIN connections ON connections.user_id = users.id")
|
||||
rel = rel.where(['connections.aasm_state != ?', 'expired'])
|
||||
end
|
||||
|
||||
unless locidispid.nil?
|
||||
rel = rel.order('scores.score')
|
||||
end
|
||||
|
||||
rel = rel.order('users.created_at DESC')
|
||||
|
||||
# rel = rel.select(sel_str)
|
||||
rel, page = self.relation_pagination(rel, params)
|
||||
rel = rel.includes([:instruments, :followings, :friends])
|
||||
|
||||
objs = rel.all
|
||||
|
||||
# puts "======================== objs #{objs.inspect}"
|
||||
|
||||
srch = Search.new
|
||||
srch.search_type = :musicians_filter
|
||||
srch.page_num, srch.page_count = page, objs.total_pages
|
||||
srch.musician_results_for_user(objs, current_user)
|
||||
srch.musician_results_for_user(objs, user)
|
||||
end
|
||||
|
||||
def self.relation_pagination(rel, params)
|
||||
|
|
@ -273,13 +324,28 @@ module JamRuby
|
|||
false
|
||||
end
|
||||
|
||||
def self.new_musicians(usr, since_date=Time.now - 1.week, max_count=50, radius=M_MILES_DEFAULT)
|
||||
rel = User.musicians
|
||||
def self.new_musicians(usr, since_date)
|
||||
# this attempts to find interesting musicians to tell another musician about where interesting
|
||||
# is "has a good score and was created recently"
|
||||
# we're sort of depending upon usr being a musicians_geocoded as well...
|
||||
# this appears to only be called from EmailBatchNewMusician#deliver_batch_sets! which is
|
||||
# an offline process and thus uses the last jam location as "home base"
|
||||
|
||||
locidispid = usr.last_jam_locidispid
|
||||
score_limit = 60
|
||||
limit = 50
|
||||
|
||||
rel = User.musicians_geocoded
|
||||
.where(['created_at >= ? AND users.id != ?', since_date, usr.id])
|
||||
.within(radius, :origin => [usr.lat, usr.lng])
|
||||
.order('created_at DESC')
|
||||
.limit(max_count)
|
||||
.joins('inner join scores on users.last_jam_locidispid = scores.alocidispid')
|
||||
.where(['scores.blocidispid = ?', locidispid])
|
||||
.where(['scores.score <= ?', score_limit])
|
||||
.order('scores.score') # best scores first
|
||||
.order('users.created_at DESC') # then most recent
|
||||
.limit(limit)
|
||||
|
||||
objs = rel.all.to_a
|
||||
|
||||
if block_given?
|
||||
yield(objs) if 0 < objs.count
|
||||
else
|
||||
|
|
|
|||
|
|
@ -12,9 +12,9 @@ module JamRuby
|
|||
include Geokit::ActsAsMappable::Glue unless defined?(acts_as_mappable)
|
||||
acts_as_mappable
|
||||
|
||||
after_save :check_lat_lng
|
||||
# after_save :check_lat_lng
|
||||
|
||||
attr_accessible :first_name, :last_name, :email, :city, :password, :password_confirmation, :state, :country, :birth_date, :subscribe_email, :terms_of_service, :original_fpfile, :cropped_fpfile, :cropped_large_fpfile, :cropped_s3_path, :cropped_large_s3_path, :photo_url, :large_photo_url, :crop_selection, :lat, :lng
|
||||
attr_accessible :first_name, :last_name, :email, :city, :password, :password_confirmation, :state, :country, :birth_date, :subscribe_email, :terms_of_service, :original_fpfile, :cropped_fpfile, :cropped_large_fpfile, :cropped_s3_path, :cropped_large_s3_path, :photo_url, :large_photo_url, :crop_selection
|
||||
|
||||
# updating_password corresponds to a lost_password
|
||||
attr_accessor :updating_password, :updating_email, :updated_email, :update_email_confirmation_url, :administratively_created, :current_password, :setting_password, :confirm_current_password, :updating_avatar, :updating_progression_field, :mods_json
|
||||
|
|
@ -140,7 +140,7 @@ module JamRuby
|
|||
|
||||
scope :musicians, where(:musician => true)
|
||||
scope :fans, where(:musician => false)
|
||||
scope :geocoded_users, where(['lat IS NOT NULL AND lng IS NOT NULL'])
|
||||
scope :geocoded_users, where(User.arel_table[:last_jam_locidispid].not_eq(nil))
|
||||
scope :musicians_geocoded, musicians.geocoded_users
|
||||
scope :email_opt_in, where(:subscribe_email => true)
|
||||
|
||||
|
|
@ -221,11 +221,11 @@ module JamRuby
|
|||
end
|
||||
|
||||
def location= location_hash
|
||||
unless location_hash.blank?
|
||||
unless location_hash.nil?
|
||||
self.city = location_hash[:city]
|
||||
self.state = location_hash[:state]
|
||||
self.country = location_hash[:country]
|
||||
end if self.city.blank?
|
||||
end
|
||||
end
|
||||
|
||||
def musician?
|
||||
|
|
@ -776,12 +776,20 @@ module JamRuby
|
|||
end
|
||||
|
||||
user.admin = false
|
||||
user.city = location[:city]
|
||||
user.state = location[:state]
|
||||
user.country = location[:country]
|
||||
user.location = location
|
||||
# user.city = location[:city]
|
||||
# user.state = location[:state]
|
||||
# user.country = location[:country]
|
||||
user.birth_date = birth_date
|
||||
|
||||
if user.musician # only update instruments if the user is a musician
|
||||
if musician
|
||||
user.last_jam_addr = location[:addr]
|
||||
user.last_jam_locidispid = location[:locidispid]
|
||||
user.last_jam_updated_reason = 'r'
|
||||
user.last_jam_updated_at = Time.now
|
||||
end
|
||||
|
||||
if musician # only update instruments if the user is a musician
|
||||
unless instruments.nil?
|
||||
instruments.each do |musician_instrument_param|
|
||||
instrument = Instrument.find(musician_instrument_param[:instrument_id])
|
||||
|
|
@ -1095,55 +1103,64 @@ module JamRuby
|
|||
!self.city.blank? && (!self.state.blank? || !self.country.blank?)
|
||||
end
|
||||
|
||||
def check_lat_lng
|
||||
if (city_changed? || state_changed? || country_changed?) && !lat_changed? && !lng_changed?
|
||||
update_lat_lng
|
||||
end
|
||||
end
|
||||
# def check_lat_lng
|
||||
# if (city_changed? || state_changed? || country_changed?) && !lat_changed? && !lng_changed?
|
||||
# update_lat_lng
|
||||
# end
|
||||
# end
|
||||
|
||||
def update_lat_lng(ip_addy=nil)
|
||||
if provides_location? # ip_addy argument ignored in this case
|
||||
return false unless ip_addy.nil? # do nothing if attempting to set latlng from an ip address
|
||||
query = { :city => self.city }
|
||||
query[:region] = self.state unless self.state.blank?
|
||||
query[:country] = self.country unless self.country.blank?
|
||||
if geo = MaxMindGeo.where(query).limit(1).first
|
||||
geo.lat = nil if geo.lat = 0
|
||||
geo.lng = nil if geo.lng = 0
|
||||
if geo.lat && geo.lng && (self.lat != geo.lat || self.lng != geo.lng)
|
||||
self.update_attributes({ :lat => geo.lat, :lng => geo.lng })
|
||||
return true
|
||||
end
|
||||
end
|
||||
elsif ip_addy
|
||||
if geo = MaxMindGeo.ip_lookup(ip_addy)
|
||||
geo.lat = nil if geo.lat = 0
|
||||
geo.lng = nil if geo.lng = 0
|
||||
if self.lat != geo.lat || self.lng != geo.lng
|
||||
self.update_attributes({ :lat => geo.lat, :lng => geo.lng })
|
||||
return true
|
||||
end
|
||||
end
|
||||
else
|
||||
if self.lat || self.lng
|
||||
self.update_attributes({ :lat => nil, :lng => nil })
|
||||
return true
|
||||
end
|
||||
end
|
||||
false
|
||||
end
|
||||
# def update_lat_lng(ip_addy=nil)
|
||||
# if provides_location? # ip_addy argument ignored in this case
|
||||
# return false unless ip_addy.nil? # do nothing if attempting to set latlng from an ip address
|
||||
# query = { :city => self.city }
|
||||
# query[:region] = self.state unless self.state.blank?
|
||||
# query[:country] = self.country unless self.country.blank?
|
||||
# if geo = MaxMindGeo.where(query).limit(1).first
|
||||
# geo.lat = nil if geo.lat = 0
|
||||
# geo.lng = nil if geo.lng = 0
|
||||
# if geo.lat && geo.lng && (self.lat != geo.lat || self.lng != geo.lng)
|
||||
# self.update_attributes({ :lat => geo.lat, :lng => geo.lng })
|
||||
# return true
|
||||
# end
|
||||
# end
|
||||
# elsif ip_addy
|
||||
# if geo = MaxMindGeo.ip_lookup(ip_addy)
|
||||
# geo.lat = nil if geo.lat = 0
|
||||
# geo.lng = nil if geo.lng = 0
|
||||
# if self.lat != geo.lat || self.lng != geo.lng
|
||||
# self.update_attributes({ :lat => geo.lat, :lng => geo.lng })
|
||||
# return true
|
||||
# end
|
||||
# end
|
||||
# else
|
||||
# if self.lat || self.lng
|
||||
# self.update_attributes({ :lat => nil, :lng => nil })
|
||||
# return true
|
||||
# end
|
||||
# end
|
||||
# false
|
||||
# end
|
||||
|
||||
def current_city(ip_addy=nil)
|
||||
unless self.city
|
||||
if self.lat && self.lng
|
||||
# todo this is really dumb, you can't compare lat lng for equality
|
||||
return MaxMindGeo.where(['lat = ? AND lng = ?',self.lat,self.lng]).limit(1).first.try(:city)
|
||||
elsif ip_addy
|
||||
return MaxMindGeo.ip_lookup(ip_addy).try(:city)
|
||||
end
|
||||
else
|
||||
return self.city
|
||||
end
|
||||
# unless self.city
|
||||
# if self.lat && self.lng
|
||||
# # todo this is really dumb, you can't compare lat lng for equality
|
||||
# return MaxMindGeo.where(['lat = ? AND lng = ?',self.lat,self.lng]).limit(1).first.try(:city)
|
||||
# elsif ip_addy
|
||||
# return MaxMindGeo.ip_lookup(ip_addy).try(:city)
|
||||
# end
|
||||
# else
|
||||
# return self.city
|
||||
# end
|
||||
self.city
|
||||
end
|
||||
|
||||
def update_addr_loc(connection, reason)
|
||||
self.last_jam_addr = connection.addr
|
||||
self.last_jam_locidispid = connection.locidispid
|
||||
self.last_jam_updated_reason = reason
|
||||
self.last_jam_updated_at = Time.now
|
||||
self.save
|
||||
end
|
||||
|
||||
def top_followings
|
||||
|
|
@ -1153,9 +1170,15 @@ module JamRuby
|
|||
.limit(3)
|
||||
end
|
||||
|
||||
def nearest_musicians
|
||||
# FIXME: replace with Scotts scoring query
|
||||
Search.new_musicians(self, Time.now - 1.week)
|
||||
end
|
||||
|
||||
def self.deliver_new_musician_notifications(since_date=nil)
|
||||
since_date ||= Time.now-1.week
|
||||
self.geocoded_users.find_each do |usr|
|
||||
# return musicians with locidispid not null
|
||||
self.musicians_geocoded.find_each do |usr|
|
||||
Search.new_musicians(usr, since_date) do |new_nearby|
|
||||
UserMailer.new_musicians(usr, new_nearby).deliver
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
module JamRuby
|
||||
class UserProgressEmailer
|
||||
extend Resque::Plugins::LonelyJob
|
||||
|
||||
@queue = :scheduled_user_progress_emailer
|
||||
@@log = Logging.logger[UserProgressEmailer]
|
||||
|
||||
def self.perform
|
||||
@@log.debug("waking up")
|
||||
EmailBatchProgression.send_progress_batch
|
||||
@@log.debug("done")
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
@ -451,6 +451,12 @@ FactoryGirl.define do
|
|||
test_emails 4.times.collect { Faker::Internet.safe_email }.join(',')
|
||||
end
|
||||
|
||||
factory :email_batch_new_musician, :class => JamRuby::EmailBatchNewMusician do
|
||||
end
|
||||
|
||||
factory :email_batch_progression, :class => JamRuby::EmailBatchProgression do
|
||||
end
|
||||
|
||||
factory :notification, :class => JamRuby::Notification do
|
||||
|
||||
factory :notification_text_message do
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ describe ClaimedRecording do
|
|||
@music_session = FactoryGirl.create(:active_music_session, :creator => @user, :musician_access => true)
|
||||
# @music_session.connections << @connection
|
||||
@music_session.save
|
||||
@connection.join_the_session(@music_session, true, nil)
|
||||
@connection.join_the_session(@music_session, true, nil, @user)
|
||||
@recording = Recording.start(@music_session, @user)
|
||||
@recording.stop
|
||||
@recording.reload
|
||||
|
|
|
|||
|
|
@ -1,18 +1,464 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe EmailBatch do
|
||||
let (:email_batch) { FactoryGirl.create(:email_batch) }
|
||||
|
||||
before(:each) do
|
||||
BatchMailer.deliveries.clear
|
||||
after(:each) do
|
||||
Timecop.return
|
||||
end
|
||||
|
||||
it 'has test emails setup' do
|
||||
expect(email_batch.test_emails.present?).to be true
|
||||
expect(email_batch.pending?).to be true
|
||||
describe 'all users' do
|
||||
|
||||
users = email_batch.test_users
|
||||
expect(email_batch.test_count).to eq(users.count)
|
||||
# before { pending }
|
||||
|
||||
let (:email_batch) { FactoryGirl.create(:email_batch) }
|
||||
|
||||
before(:each) do
|
||||
BatchMailer.deliveries.clear
|
||||
end
|
||||
|
||||
it 'has test emails setup' do
|
||||
|
||||
expect(email_batch.test_emails.present?).to be true
|
||||
expect(email_batch.pending?).to be true
|
||||
|
||||
users = email_batch.test_users
|
||||
expect(email_batch.test_count).to eq(users.count)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'new musician' do
|
||||
before { pending }
|
||||
|
||||
let (:new_musician_batch) { FactoryGirl.create(:email_batch_new_musician) }
|
||||
|
||||
before(:each) do
|
||||
@u1 = FactoryGirl.create(:user, :lat => 37.791649, :lng => -122.394395, :email => 'jonathan@jamkazam.com', :subscribe_email => true, :created_at => Time.now - 3.weeks)
|
||||
@u2 = FactoryGirl.create(:user, :lat => 37.791649, :lng => -122.394395, :subscribe_email => true)
|
||||
@u3 = FactoryGirl.create(:user, :lat => 37.791649, :lng => -122.394395, :subscribe_email => false, :created_at => Time.now - 3.weeks)
|
||||
@u4 = FactoryGirl.create(:user, :lat => 37.791649, :lng => -122.394395, :subscribe_email => true, :created_at => Time.now - 3.weeks)
|
||||
end
|
||||
|
||||
it 'find new musicians with good score' do
|
||||
new_musician_batch.fetch_recipients do |new_musicians|
|
||||
expect(new_musicians.count).to eq(2)
|
||||
num = (new_musicians.keys.map(&:id) - [@u1.id, @u4.id]).count
|
||||
expect(num).to eq(0)
|
||||
end
|
||||
end
|
||||
|
||||
it 'cycles through states properly' do
|
||||
new_musician_batch.deliver_batch
|
||||
expect(UserMailer.deliveries.length).to eq(2)
|
||||
new_musician_batch.reload
|
||||
expect(new_musician_batch.delivered?).to eq(true)
|
||||
expect(new_musician_batch.sent_count).to eq(2)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
context 'user progress' do
|
||||
|
||||
# before { pending }
|
||||
|
||||
def handles_new_users(ebatch, user)
|
||||
3.times { |nn| expect(ebatch.fetch_recipients(nn).count).to eq(0) }
|
||||
|
||||
dd = user.created_at + ebatch.days_past_for_trigger_index(0).days
|
||||
Timecop.travel(dd)
|
||||
vals = [1,0,0]
|
||||
3.times { |nn| expect(ebatch.fetch_recipients(nn).count).to eq(vals[nn]) }
|
||||
ebatch.make_set(user, 0)
|
||||
3.times { |nn| expect(ebatch.fetch_recipients(nn).count).to eq(0) }
|
||||
|
||||
dd = dd + ebatch.days_past_for_trigger_index(1).days
|
||||
Timecop.travel(dd)
|
||||
vals = [0,1,0]
|
||||
3.times { |nn| expect(ebatch.fetch_recipients(nn).count).to eq(vals[nn]) }
|
||||
ebatch.make_set(user, 1)
|
||||
3.times { |nn| expect(ebatch.fetch_recipients(nn).count).to eq(0) }
|
||||
|
||||
dd = dd + ebatch.days_past_for_trigger_index(2).days
|
||||
Timecop.travel(dd)
|
||||
vals = [0,0,1]
|
||||
3.times { |nn| expect(ebatch.fetch_recipients(nn).count).to eq(vals[nn]) }
|
||||
ebatch.make_set(user, 2)
|
||||
3.times { |nn| expect(ebatch.fetch_recipients(nn).count).to eq(0) }
|
||||
end
|
||||
|
||||
def handles_existing_users(ebatch, user)
|
||||
vals = [1,0,0]
|
||||
3.times { |nn| expect(ebatch.fetch_recipients(nn).count).to eq(vals[nn]) }
|
||||
|
||||
dd = user.created_at + ebatch.days_past_for_trigger_index(0).days
|
||||
Timecop.travel(dd)
|
||||
ebatch.make_set(user, 0)
|
||||
3.times { |nn| expect(ebatch.fetch_recipients(nn).count).to eq(0) }
|
||||
|
||||
dd = dd + ebatch.days_past_for_trigger_index(1).days
|
||||
Timecop.travel(dd)
|
||||
vals = [0,1,0]
|
||||
3.times { |nn| expect(ebatch.fetch_recipients(nn).count).to eq(vals[nn]) }
|
||||
ebatch.make_set(user, 1)
|
||||
|
||||
dd = dd + ebatch.days_past_for_trigger_index(2).days
|
||||
Timecop.travel(dd)
|
||||
expect(ebatch.fetch_recipients(2).count).to eq(1)
|
||||
ebatch.make_set(user, 2)
|
||||
expect(ebatch.fetch_recipients(2).count).to eq(0)
|
||||
|
||||
dd = dd + 1
|
||||
Timecop.travel(dd)
|
||||
expect(ebatch.fetch_recipients(2).count).to eq(0)
|
||||
end
|
||||
|
||||
def skips_some_days(ebatch, user)
|
||||
dd = user.created_at + ebatch.days_past_for_trigger_index(1).days
|
||||
Timecop.travel(dd)
|
||||
vals = [1,0,0]
|
||||
3.times { |nn| expect(ebatch.fetch_recipients(nn).count).to eq(vals[nn]) }
|
||||
ebatch.make_set(user, 0)
|
||||
2.times { |nn| expect(ebatch.fetch_recipients(nn).count).to eq(0) }
|
||||
|
||||
dd = dd + ebatch.days_past_for_trigger_index(1).days
|
||||
Timecop.travel(dd)
|
||||
vals = [0,1,0]
|
||||
3.times { |nn| expect(ebatch.fetch_recipients(nn).count).to eq(vals[nn]) }
|
||||
ebatch.make_set(user, 1)
|
||||
expect(ebatch.fetch_recipients(2).count).to eq(0)
|
||||
|
||||
dd = dd + ebatch.days_past_for_trigger_index(2).days
|
||||
Timecop.travel(dd)
|
||||
vals = [0,0,1]
|
||||
3.times { |nn| expect(ebatch.fetch_recipients(nn).count).to eq(vals[nn]) }
|
||||
ebatch.make_set(user, 2)
|
||||
expect(ebatch.fetch_recipients(2).count).to eq(0)
|
||||
end
|
||||
|
||||
def loops_bunch_of_users(ebatch, users)
|
||||
expect(ebatch.fetch_recipients(0,5).count).to eq(0)
|
||||
dd = users[0].created_at + ebatch.days_past_for_trigger_index(0).days
|
||||
Timecop.travel(dd)
|
||||
expect(ebatch.fetch_recipients(0,5).count).to eq(20)
|
||||
users.each { |uu| ebatch.make_set(uu, 0) }
|
||||
expect(ebatch.fetch_recipients(0,5).count).to eq(0)
|
||||
users.map &:destroy
|
||||
end
|
||||
|
||||
def sends_one_email(existing_user, ebatch)
|
||||
ProgressMailer.deliveries.clear
|
||||
ebatch.deliver_batch
|
||||
expect(ProgressMailer.deliveries.length).to eq(1)
|
||||
end
|
||||
|
||||
describe 'client_notdl' do
|
||||
# before { pending }
|
||||
let(:batchp) {
|
||||
FactoryGirl.create(:email_batch_progression, :sub_type => :client_notdl)
|
||||
}
|
||||
let(:user_) { FactoryGirl.create(:user) }
|
||||
let(:user_existing) {
|
||||
FactoryGirl.create(:user,
|
||||
:created_at => Time.now - (2 * batchp.days_past_for_trigger_index(2)).days)
|
||||
}
|
||||
after(:each) do
|
||||
batchp.clear_batch_sets!
|
||||
Timecop.return
|
||||
end
|
||||
it 'sends one email' do
|
||||
sends_one_email(user_existing, batchp)
|
||||
end
|
||||
it 'handles new users' do
|
||||
handles_new_users(batchp, user_)
|
||||
end
|
||||
it 'handles existing users' do
|
||||
handles_existing_users(batchp, user_existing)
|
||||
end
|
||||
it 'skips some days' do
|
||||
skips_some_days(batchp, user_)
|
||||
end
|
||||
it 'loops bunch of users' do
|
||||
users = []
|
||||
20.times { |nn| users << FactoryGirl.create(:user) }
|
||||
loops_bunch_of_users(batchp, users)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'client_dl_notrun' do
|
||||
# before { pending }
|
||||
let(:batchp) {
|
||||
FactoryGirl.create(:email_batch_progression, :sub_type => :client_dl_notrun)
|
||||
}
|
||||
let(:user_) { FactoryGirl.create(:user, :first_downloaded_client_at => Time.now) }
|
||||
let(:date_in_past) { Time.now - (2 * batchp.days_past_for_trigger_index(2)).days }
|
||||
let(:user_existing) {
|
||||
FactoryGirl.create(:user,
|
||||
:created_at => date_in_past,
|
||||
:first_downloaded_client_at => date_in_past)
|
||||
}
|
||||
after(:each) do
|
||||
batchp.clear_batch_sets!
|
||||
Timecop.return
|
||||
end
|
||||
it 'sends one email' do
|
||||
sends_one_email(user_existing, batchp)
|
||||
end
|
||||
it 'handles new users' do
|
||||
handles_new_users(batchp, user_)
|
||||
end
|
||||
it 'handles existing users' do
|
||||
handles_existing_users(batchp, user_existing)
|
||||
end
|
||||
it 'skips some days' do
|
||||
skips_some_days(batchp, user_)
|
||||
end
|
||||
it 'loops bunch of users' do
|
||||
users = []
|
||||
20.times { |nn| users << FactoryGirl.create(:user, :first_downloaded_client_at => Time.now) }
|
||||
loops_bunch_of_users(batchp, users)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'client_run_notgear' do
|
||||
# before { pending }
|
||||
let(:batchp) {
|
||||
FactoryGirl.create(:email_batch_progression, :sub_type => :client_run_notgear)
|
||||
}
|
||||
let(:user_) { FactoryGirl.create(:user, :first_ran_client_at => Time.now) }
|
||||
let(:date_in_past) { Time.now - (2 * batchp.days_past_for_trigger_index(2)).days }
|
||||
let(:user_existing) {
|
||||
FactoryGirl.create(:user,
|
||||
:created_at => date_in_past,
|
||||
:first_ran_client_at => date_in_past)
|
||||
}
|
||||
after(:each) do
|
||||
batchp.clear_batch_sets!
|
||||
Timecop.return
|
||||
end
|
||||
it 'sends one email' do
|
||||
sends_one_email(user_existing, batchp)
|
||||
end
|
||||
it 'handles new users' do
|
||||
handles_new_users(batchp, user_)
|
||||
end
|
||||
it 'handles existing users' do
|
||||
handles_existing_users(batchp, user_existing)
|
||||
end
|
||||
it 'skips some days' do
|
||||
skips_some_days(batchp, user_)
|
||||
end
|
||||
it 'loops bunch of users' do
|
||||
users = []
|
||||
20.times { |nn| users << FactoryGirl.create(:user, :first_ran_client_at => Time.now) }
|
||||
loops_bunch_of_users(batchp, users)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'gear_notsess' do
|
||||
# before { pending }
|
||||
let(:batchp) {
|
||||
FactoryGirl.create(:email_batch_progression, :sub_type => :gear_notsess)
|
||||
}
|
||||
let(:user_) { FactoryGirl.create(:user, :first_certified_gear_at => Time.now) }
|
||||
let(:date_in_past) { Time.now - (2 * batchp.days_past_for_trigger_index(2)).days }
|
||||
let(:user_existing) {
|
||||
FactoryGirl.create(:user,
|
||||
:created_at => date_in_past,
|
||||
:first_certified_gear_at => date_in_past)
|
||||
}
|
||||
after(:each) do
|
||||
batchp.clear_batch_sets!
|
||||
Timecop.return
|
||||
end
|
||||
it 'sends one email' do
|
||||
sends_one_email(user_existing, batchp)
|
||||
end
|
||||
it 'handles new users' do
|
||||
handles_new_users(batchp, user_)
|
||||
end
|
||||
it 'handles existing users' do
|
||||
handles_existing_users(batchp, user_existing)
|
||||
end
|
||||
it 'skips some days' do
|
||||
skips_some_days(batchp, user_)
|
||||
end
|
||||
it 'loops bunch of users' do
|
||||
users = []
|
||||
20.times { |nn| users << FactoryGirl.create(:user, :first_certified_gear_at => Time.now) }
|
||||
loops_bunch_of_users(batchp, users)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'sess_notgood' do
|
||||
# before { pending }
|
||||
let(:batchp) {
|
||||
FactoryGirl.create(:email_batch_progression, :sub_type => :sess_notgood)
|
||||
}
|
||||
let(:user_) { FactoryGirl.create(:user, :first_real_music_session_at => Time.now) }
|
||||
let(:date_in_past) { Time.now - (2 * batchp.days_past_for_trigger_index(2)).days }
|
||||
let(:user_existing) {
|
||||
FactoryGirl.create(:user,
|
||||
:created_at => date_in_past,
|
||||
:first_real_music_session_at => date_in_past)
|
||||
}
|
||||
after(:each) do
|
||||
batchp.clear_batch_sets!
|
||||
Timecop.return
|
||||
end
|
||||
it 'sends one email' do
|
||||
sends_one_email(user_existing, batchp)
|
||||
end
|
||||
it 'handles new users' do
|
||||
handles_new_users(batchp, user_)
|
||||
end
|
||||
it 'handles existing users' do
|
||||
handles_existing_users(batchp, user_existing)
|
||||
end
|
||||
it 'skips some days' do
|
||||
skips_some_days(batchp, user_)
|
||||
end
|
||||
it 'loops bunch of users' do
|
||||
users = []
|
||||
20.times { |nn| users << FactoryGirl.create(:user, :first_real_music_session_at => Time.now) }
|
||||
loops_bunch_of_users(batchp, users)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'sess_notrecord' do
|
||||
# before { pending }
|
||||
let(:batchp) {
|
||||
FactoryGirl.create(:email_batch_progression, :sub_type => :sess_notrecord)
|
||||
}
|
||||
let(:user_) { FactoryGirl.create(:user, :first_real_music_session_at => Time.now) }
|
||||
let(:date_in_past) { Time.now - (2 * batchp.days_past_for_trigger_index(2)).days }
|
||||
let(:user_existing) {
|
||||
FactoryGirl.create(:user,
|
||||
:created_at => date_in_past,
|
||||
:first_real_music_session_at => date_in_past)
|
||||
}
|
||||
after(:each) do
|
||||
batchp.clear_batch_sets!
|
||||
Timecop.return
|
||||
end
|
||||
it 'sends one email' do
|
||||
sends_one_email(user_existing, batchp)
|
||||
end
|
||||
it 'handles new users' do
|
||||
handles_new_users(batchp, user_)
|
||||
end
|
||||
it 'handles existing users' do
|
||||
handles_existing_users(batchp, user_existing)
|
||||
end
|
||||
it 'skips some days' do
|
||||
skips_some_days(batchp, user_)
|
||||
end
|
||||
it 'loops bunch of users' do
|
||||
users = []
|
||||
20.times { |nn| users << FactoryGirl.create(:user, :first_real_music_session_at => Time.now) }
|
||||
loops_bunch_of_users(batchp, users)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'reg_notinvite' do
|
||||
# before { pending }
|
||||
let(:batchp) {
|
||||
FactoryGirl.create(:email_batch_progression, :sub_type => :reg_notinvite)
|
||||
}
|
||||
let(:user_) { FactoryGirl.create(:user) }
|
||||
let(:date_in_past) { Time.now - (2 * batchp.days_past_for_trigger_index(2)).days }
|
||||
let(:user_existing) {
|
||||
FactoryGirl.create(:user,
|
||||
:created_at => date_in_past)
|
||||
}
|
||||
after(:each) do
|
||||
batchp.clear_batch_sets!
|
||||
Timecop.return
|
||||
end
|
||||
it 'sends one email' do
|
||||
sends_one_email(user_existing, batchp)
|
||||
end
|
||||
it 'handles new users' do
|
||||
handles_new_users(batchp, user_)
|
||||
end
|
||||
it 'handles existing users' do
|
||||
handles_existing_users(batchp, user_existing)
|
||||
end
|
||||
it 'skips some days' do
|
||||
skips_some_days(batchp, user_)
|
||||
end
|
||||
it 'loops bunch of users' do
|
||||
users = []
|
||||
20.times { |nn| users << FactoryGirl.create(:user) }
|
||||
loops_bunch_of_users(batchp, users)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'reg_notconnect' do
|
||||
# before { pending }
|
||||
let(:batchp) {
|
||||
FactoryGirl.create(:email_batch_progression, :sub_type => :reg_notconnect)
|
||||
}
|
||||
let(:user_) { FactoryGirl.create(:user) }
|
||||
let(:date_in_past) { Time.now - (2 * batchp.days_past_for_trigger_index(2)).days }
|
||||
let(:user_existing) {
|
||||
FactoryGirl.create(:user,
|
||||
:created_at => date_in_past)
|
||||
}
|
||||
after(:each) do
|
||||
batchp.clear_batch_sets!
|
||||
Timecop.return
|
||||
end
|
||||
it 'sends one email' do
|
||||
sends_one_email(user_existing, batchp)
|
||||
end
|
||||
it 'handles new users' do
|
||||
handles_new_users(batchp, user_)
|
||||
end
|
||||
it 'handles existing users' do
|
||||
handles_existing_users(batchp, user_existing)
|
||||
end
|
||||
it 'skips some days' do
|
||||
skips_some_days(batchp, user_)
|
||||
end
|
||||
it 'loops bunch of users' do
|
||||
users = []
|
||||
20.times { |nn| users << FactoryGirl.create(:user) }
|
||||
loops_bunch_of_users(batchp, users)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'reg_notlike' do
|
||||
# before { pending }
|
||||
let(:batchp) {
|
||||
FactoryGirl.create(:email_batch_progression, :sub_type => :reg_notlike)
|
||||
}
|
||||
let(:user_) { FactoryGirl.create(:user) }
|
||||
let(:date_in_past) { Time.now - (2 * batchp.days_past_for_trigger_index(2)).days }
|
||||
let(:user_existing) {
|
||||
FactoryGirl.create(:user,
|
||||
:created_at => date_in_past)
|
||||
}
|
||||
after(:each) do
|
||||
batchp.clear_batch_sets!
|
||||
Timecop.return
|
||||
end
|
||||
it 'sends one email' do
|
||||
sends_one_email(user_existing, batchp)
|
||||
end
|
||||
it 'handles new users' do
|
||||
handles_new_users(batchp, user_)
|
||||
end
|
||||
it 'handles existing users' do
|
||||
handles_existing_users(batchp, user_existing)
|
||||
end
|
||||
it 'skips some days' do
|
||||
skips_some_days(batchp, user_)
|
||||
end
|
||||
it 'loops bunch of users' do
|
||||
users = []
|
||||
20.times { |nn| users << FactoryGirl.create(:user) }
|
||||
loops_bunch_of_users(batchp, users)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -7,13 +7,13 @@ describe GetWork do
|
|||
end
|
||||
|
||||
it "get_work_1" do
|
||||
x = GetWork.get_work(1)
|
||||
x = GetWork.get_work(1, 0)
|
||||
#puts x.inspect
|
||||
x.should be_nil
|
||||
end
|
||||
|
||||
it "get_work_list_1" do
|
||||
x = GetWork.get_work_list(1)
|
||||
x = GetWork.get_work_list(1, 0)
|
||||
#puts x.inspect
|
||||
x.should eql([])
|
||||
end
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ describe Mix do
|
|||
@music_session = FactoryGirl.create(:active_music_session, :creator => @user, :musician_access => true)
|
||||
# @music_session.connections << @connection
|
||||
@music_session.save
|
||||
@connection.join_the_session(@music_session, true, nil)
|
||||
@connection.join_the_session(@music_session, true, nil, @user)
|
||||
@recording = Recording.start(@music_session, @user)
|
||||
@recording.stop
|
||||
@recording.claim(@user, "name", "description", Genre.first, true)
|
||||
|
|
|
|||
|
|
@ -46,7 +46,6 @@ describe MusicSession do
|
|||
music_session.valid?.should be_false
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -3,32 +3,88 @@ require 'spec_helper'
|
|||
describe 'Musician search' do
|
||||
|
||||
before(:each) do
|
||||
@geocode1 = FactoryGirl.create(:geocoder)
|
||||
@geocode2 = FactoryGirl.create(:geocoder)
|
||||
@users = []
|
||||
@users << @user1 = FactoryGirl.create(:user)
|
||||
@users << @user2 = FactoryGirl.create(:user)
|
||||
@users << @user3 = FactoryGirl.create(:user)
|
||||
@users << @user4 = FactoryGirl.create(:user)
|
||||
# @geocode1 = FactoryGirl.create(:geocoder)
|
||||
# @geocode2 = FactoryGirl.create(:geocoder)
|
||||
t = Time.now - 10.minute
|
||||
|
||||
@user1 = FactoryGirl.create(:user, created_at: t+1.minute, last_jam_locidispid: 1)
|
||||
@user2 = FactoryGirl.create(:user, created_at: t+2.minute, last_jam_locidispid: 2)
|
||||
@user3 = FactoryGirl.create(:user, created_at: t+3.minute, last_jam_locidispid: 3)
|
||||
@user4 = FactoryGirl.create(:user, created_at: t+4.minute, last_jam_locidispid: 4)
|
||||
@user5 = FactoryGirl.create(:user, created_at: t+5.minute, last_jam_locidispid: 5)
|
||||
@user6 = FactoryGirl.create(:user, created_at: t+6.minute) # not geocoded
|
||||
@user7 = FactoryGirl.create(:user, created_at: t+7.minute, musician: false) # not musician
|
||||
|
||||
@musicians = []
|
||||
@musicians << @user1
|
||||
@musicians << @user2
|
||||
@musicians << @user3
|
||||
@musicians << @user4
|
||||
@musicians << @user5
|
||||
@musicians << @user6
|
||||
|
||||
@geomusicians = []
|
||||
@geomusicians << @user1
|
||||
@geomusicians << @user2
|
||||
@geomusicians << @user3
|
||||
@geomusicians << @user4
|
||||
@geomusicians << @user5
|
||||
|
||||
Score.delete_all
|
||||
Score.createx(1, 'a', 1, 1, 'a', 1, 10)
|
||||
Score.createx(1, 'a', 1, 2, 'b', 2, 20)
|
||||
Score.createx(1, 'a', 1, 3, 'c', 3, 30)
|
||||
Score.createx(1, 'a', 1, 4, 'd', 4, 40)
|
||||
Score.createx(2, 'b', 2, 3, 'c', 3, 15)
|
||||
Score.createx(2, 'b', 2, 4, 'd', 4, 70)
|
||||
end
|
||||
|
||||
context 'default filter settings' do
|
||||
|
||||
it "finds all musicians" do
|
||||
# expects all the users
|
||||
num = User.musicians.count
|
||||
results = Search.musician_filter({ :per_page => num })
|
||||
expect(results.results.count).to eq(num)
|
||||
expect(results.search_type).to be(:musicians_filter)
|
||||
# expects all the musicians (geocoded)
|
||||
results = Search.musician_filter
|
||||
results.search_type.should == :musicians_filter
|
||||
results.results.count.should == @geomusicians.length
|
||||
results.results.should eq @geomusicians.reverse
|
||||
end
|
||||
|
||||
it "finds musicians with proper ordering" do
|
||||
# the ordering should be create_at since no followers exist
|
||||
expect(Follow.count).to eq(0)
|
||||
results = Search.musician_filter({ :per_page => User.musicians.count })
|
||||
results.results.each_with_index do |uu, idx|
|
||||
expect(uu.id).to eq(@users.reverse[idx].id)
|
||||
end
|
||||
it "finds all musicians page 1" do
|
||||
# expects all the musicians
|
||||
results = Search.musician_filter({page: 1})
|
||||
results.search_type.should == :musicians_filter
|
||||
results.results.count.should == @geomusicians.length
|
||||
results.results.should eq @geomusicians.reverse
|
||||
end
|
||||
|
||||
it "finds all musicians page 2" do
|
||||
# expects no musicians (all fit on page 1)
|
||||
results = Search.musician_filter({page: 2})
|
||||
results.search_type.should == :musicians_filter
|
||||
results.results.count.should == 0
|
||||
end
|
||||
|
||||
it "finds all musicians page 1 per_page 3" do
|
||||
# expects three of the musicians
|
||||
results = Search.musician_filter({per_page: 3})
|
||||
results.search_type.should == :musicians_filter
|
||||
results.results.count.should == 3
|
||||
results.results.should eq @geomusicians.reverse.slice(0, 3)
|
||||
end
|
||||
|
||||
it "finds all musicians page 2 per_page 3" do
|
||||
# expects two of the musicians
|
||||
results = Search.musician_filter({page: 2, per_page: 3})
|
||||
results.search_type.should == :musicians_filter
|
||||
results.results.count.should == 2
|
||||
results.results.should eq @geomusicians.reverse.slice(3, 3)
|
||||
end
|
||||
|
||||
it "finds all musicians page 3 per_page 3" do
|
||||
# expects two of the musicians
|
||||
results = Search.musician_filter({page: 3, per_page: 3})
|
||||
results.search_type.should == :musicians_filter
|
||||
results.results.count.should == 0
|
||||
end
|
||||
|
||||
it "sorts musicians by followers" do
|
||||
|
|
@ -90,7 +146,7 @@ describe 'Musician search' do
|
|||
f3.save
|
||||
|
||||
# @user2.followers.concat([@user3, @user4, @user2])
|
||||
results = Search.musician_filter({ :per_page => @users.size }, @user3)
|
||||
results = Search.musician_filter({ :per_page => @musicians.size }, @user3)
|
||||
expect(results.results[0].id).to eq(@user2.id)
|
||||
|
||||
# check the follower count for given entry
|
||||
|
|
@ -109,13 +165,13 @@ describe 'Musician search' do
|
|||
end
|
||||
|
||||
def make_recording(usr)
|
||||
connection = FactoryGirl.create(:connection, :user => usr)
|
||||
connection = FactoryGirl.create(:connection, :user => usr, locidispid: usr.last_jam_locidispid)
|
||||
instrument = FactoryGirl.create(:instrument, :description => 'a great instrument')
|
||||
track = FactoryGirl.create(:track, :connection => connection, :instrument => instrument)
|
||||
music_session = FactoryGirl.create(:active_music_session, :creator => usr, :musician_access => true)
|
||||
# music_session.connections << connection
|
||||
music_session.save
|
||||
connection.join_the_session(music_session, true, nil)
|
||||
# music_session.save
|
||||
connection.join_the_session(music_session, true, nil, usr)
|
||||
recording = Recording.start(music_session, usr)
|
||||
recording.stop
|
||||
recording.reload
|
||||
|
|
@ -126,11 +182,11 @@ describe 'Musician search' do
|
|||
end
|
||||
|
||||
def make_session(usr)
|
||||
connection = FactoryGirl.create(:connection, :user => usr)
|
||||
connection = FactoryGirl.create(:connection, :user => usr, locidispid: usr.last_jam_locidispid)
|
||||
music_session = FactoryGirl.create(:active_music_session, :creator => usr, :musician_access => true)
|
||||
# music_session.connections << connection
|
||||
music_session.save
|
||||
connection.join_the_session(music_session, true, nil)
|
||||
# music_session.save
|
||||
connection.join_the_session(music_session, true, nil, usr)
|
||||
end
|
||||
|
||||
context 'musician stat counters' do
|
||||
|
|
@ -154,8 +210,8 @@ describe 'Musician search' do
|
|||
# @user4.followers.concat([@user4])
|
||||
# @user3.followers.concat([@user4])
|
||||
# @user2.followers.concat([@user4])
|
||||
expect(@user4.top_followings.count).to be 3
|
||||
expect(@user4.top_followings.map(&:id)).to match_array((@users - [@user1]).map(&:id))
|
||||
expect(@user4.top_followings.count).to eq 3
|
||||
expect(@user4.top_followings.map(&:id)).to match_array((@musicians - [@user1, @user5, @user6]).map(&:id))
|
||||
end
|
||||
|
||||
it "friends stat shows friend count" do
|
||||
|
|
@ -172,6 +228,8 @@ describe 'Musician search' do
|
|||
end
|
||||
|
||||
it "recording stat shows recording count" do
|
||||
Recording.delete_all
|
||||
|
||||
recording = make_recording(@user1)
|
||||
expect(recording.users.length).to be 1
|
||||
expect(recording.users.first).to eq(@user1)
|
||||
|
|
@ -182,6 +240,7 @@ describe 'Musician search' do
|
|||
expect(@user1.recordings.detect { |rr| rr == recording }).to_not be_nil
|
||||
|
||||
results = Search.musician_filter({},@user1)
|
||||
# puts "====================== results #{results.inspect}"
|
||||
uu = results.results.detect { |mm| mm.id == @user1.id }
|
||||
expect(uu).to_not be_nil
|
||||
|
||||
|
|
@ -194,31 +253,39 @@ describe 'Musician search' do
|
|||
context 'musician sorting' do
|
||||
|
||||
it "by plays" do
|
||||
Recording.delete_all
|
||||
|
||||
make_recording(@user1)
|
||||
# order results by num recordings
|
||||
results = Search.musician_filter({ :orderby => 'plays' }, @user2)
|
||||
# puts "========= results #{results.inspect}"
|
||||
expect(results.results.length).to eq(2)
|
||||
expect(results.results[0].id).to eq(@user1.id)
|
||||
expect(results.results[1].id).to eq(@user3.id)
|
||||
|
||||
# add more data and make sure order still correct
|
||||
make_recording(@user2); make_recording(@user2)
|
||||
make_recording(@user3)
|
||||
make_recording(@user3)
|
||||
results = Search.musician_filter({ :orderby => 'plays' }, @user2)
|
||||
expect(results.results[0].id).to eq(@user2.id)
|
||||
expect(results.results.length).to eq(2)
|
||||
expect(results.results[0].id).to eq(@user3.id)
|
||||
expect(results.results[1].id).to eq(@user1.id)
|
||||
end
|
||||
|
||||
it "by now playing" do
|
||||
# should get 1 result with 1 active session
|
||||
make_session(@user3)
|
||||
make_session(@user1)
|
||||
results = Search.musician_filter({ :orderby => 'playing' }, @user2)
|
||||
expect(results.results.count).to be 1
|
||||
expect(results.results.first.id).to eq(@user3.id)
|
||||
expect(results.results.first.id).to eq(@user1.id)
|
||||
|
||||
# should get 2 results with 2 active sessions
|
||||
# sort order should be created_at DESC
|
||||
make_session(@user4)
|
||||
make_session(@user3)
|
||||
results = Search.musician_filter({ :orderby => 'playing' }, @user2)
|
||||
expect(results.results.count).to be 2
|
||||
expect(results.results[0].id).to eq(@user4.id)
|
||||
expect(results.results[1].id).to eq(@user3.id)
|
||||
expect(results.results[0].id).to eq(@user3.id)
|
||||
expect(results.results[1].id).to eq(@user1.id)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -275,28 +342,43 @@ describe 'Musician search' do
|
|||
|
||||
context 'new users' do
|
||||
|
||||
it "find nearby" do
|
||||
# create new user outside 500 from Apex to ensure its excluded from results
|
||||
FactoryGirl.create(:user, {city: "Austin", state: "TX", country: "US"})
|
||||
User.geocoded_users.find_each do |usr|
|
||||
Search.new_musicians(usr) do |new_usrs|
|
||||
# the newly created user is not nearby the existing users (which are in Apex, NC)
|
||||
# and that user is not included in query
|
||||
expect(new_usrs.count).to eq(User.musicians.count - 1)
|
||||
end
|
||||
end
|
||||
it "find three for user1" do
|
||||
# user2..4 are scored against user1
|
||||
ms = Search.new_musicians(@user1, Time.now - 1.week)
|
||||
ms.should_not be_nil
|
||||
ms.length.should == 3
|
||||
ms.should eq [@user2, @user3, @user4]
|
||||
end
|
||||
|
||||
it "sends new musician email" do
|
||||
# create new user outside 500 from Apex to ensure its excluded from results
|
||||
FactoryGirl.create(:user, {city: "Austin", state: "TX", country: "US"})
|
||||
User.geocoded_users.find_each do |usr|
|
||||
Search.new_musicians(usr) do |new_usrs|
|
||||
# the newly created user is not nearby the existing users (which are in Apex, NC)
|
||||
# and that user is not included in query
|
||||
expect(new_usrs.count).to eq(User.musicians.count - 1)
|
||||
end
|
||||
end
|
||||
it "find two for user2" do
|
||||
# user1,3,4 are scored against user1, but user4 is bad
|
||||
ms = Search.new_musicians(@user2, Time.now - 1.week)
|
||||
ms.should_not be_nil
|
||||
ms.length.should == 2
|
||||
ms.should eq [@user3, @user1]
|
||||
end
|
||||
|
||||
it "find two for user3" do
|
||||
# user1..2 are scored against user3
|
||||
ms = Search.new_musicians(@user3, Time.now - 1.week)
|
||||
ms.should_not be_nil
|
||||
ms.length.should == 2
|
||||
ms.should eq [@user2, @user1]
|
||||
end
|
||||
|
||||
it "find one for user4" do
|
||||
# user1..2 are scored against user4, but user2 is bad
|
||||
ms = Search.new_musicians(@user4, Time.now - 1.week)
|
||||
ms.should_not be_nil
|
||||
ms.length.should == 1
|
||||
ms.should eq [@user1]
|
||||
end
|
||||
|
||||
it "find none for user5" do
|
||||
# user1..4 are not scored against user5
|
||||
ms = Search.new_musicians(@user5, Time.now - 1.week)
|
||||
ms.should_not be_nil
|
||||
ms.length.should == 0
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ describe Recording do
|
|||
@track2 = FactoryGirl.create(:track, :connection => @connection2, :instrument => @instrument2)
|
||||
|
||||
# @music_session.connections << @connection2
|
||||
@connection2.join_the_session(@music_session, true, nil)
|
||||
@connection2.join_the_session(@music_session, true, nil, @user2)
|
||||
|
||||
@recording = Recording.start(@music_session, @user)
|
||||
@user.recordings.length.should == 0
|
||||
|
|
@ -179,7 +179,7 @@ describe Recording do
|
|||
@track = FactoryGirl.create(:track, :connection => @connection2, :instrument => @instrument)
|
||||
# @music_session.connections << @connection2
|
||||
@music_session.save
|
||||
@connection2.join_the_session(@music_session, true, nil)
|
||||
@connection2.join_the_session(@music_session, true, nil, @user2)
|
||||
@recording = Recording.start(@music_session, @user)
|
||||
@recording.stop
|
||||
@recording.reload
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ describe Score do
|
|||
|
||||
before do
|
||||
Score.delete_all
|
||||
Score.createx(1234, 'anodeid', 0x01020304, 2345, 'bnodeid', 0x02030405, 20, nil)
|
||||
Score.createx(1234, 'anodeid', 0x01020304, 2345, 'bnodeid', 0x02030405, 20, nil, 'foo')
|
||||
Score.createx(1234, 'anodeid', 0x01020304, 3456, 'cnodeid', 0x03040506, 30, nil)
|
||||
Score.createx(1234, 'anodeid', 0x01020304, 3456, 'cnodeid', 0x03040506, 40, Time.new.utc-3600)
|
||||
end
|
||||
|
|
@ -25,6 +25,7 @@ describe Score do
|
|||
s.score.should == 20
|
||||
s.scorer.should == 0
|
||||
s.score_dt.should_not be_nil
|
||||
s.scoring_data.should eq('foo')
|
||||
end
|
||||
|
||||
it 'b to a' do
|
||||
|
|
@ -39,6 +40,7 @@ describe Score do
|
|||
s.score.should == 20
|
||||
s.scorer.should == 1
|
||||
s.score_dt.should_not be_nil
|
||||
s.scoring_data.should be_nil
|
||||
end
|
||||
|
||||
it 'a to c' do
|
||||
|
|
@ -53,6 +55,7 @@ describe Score do
|
|||
s.score.should == 30
|
||||
s.scorer.should == 0
|
||||
s.score_dt.should_not be_nil
|
||||
s.scoring_data.should be_nil
|
||||
end
|
||||
|
||||
it 'c to a' do
|
||||
|
|
@ -67,6 +70,7 @@ describe Score do
|
|||
s.score.should == 30
|
||||
s.scorer.should == 1
|
||||
s.score_dt.should_not be_nil
|
||||
s.scoring_data.should be_nil
|
||||
end
|
||||
|
||||
it 'delete a to c' do
|
||||
|
|
@ -92,4 +96,31 @@ describe Score do
|
|||
Score.findx(3456, 3456).should == -1
|
||||
end
|
||||
|
||||
it "test shortcut for making scores from connections" do
|
||||
user1 = FactoryGirl.create(:user)
|
||||
conn1 = FactoryGirl.create(:connection, user: user1, addr: 0x01020304, locidispid: 5)
|
||||
user2 = FactoryGirl.create(:user)
|
||||
conn2 = FactoryGirl.create(:connection, user: user2, addr: 0x11121314, locidispid: 6)
|
||||
user3 = FactoryGirl.create(:user)
|
||||
conn3 = FactoryGirl.create(:connection, user: user3, addr: 0x21222324, locidispid: 7)
|
||||
|
||||
Score.findx(5, 6).should == -1
|
||||
Score.findx(6, 5).should == -1
|
||||
Score.findx(5, 7).should == -1
|
||||
Score.findx(7, 5).should == -1
|
||||
Score.findx(6, 7).should == -1
|
||||
Score.findx(7, 6).should == -1
|
||||
|
||||
Score.score_conns(conn1, conn2, 12)
|
||||
Score.score_conns(conn1, conn3, 13)
|
||||
Score.score_conns(conn2, conn3, 23)
|
||||
|
||||
Score.findx(5, 6).should == 12
|
||||
Score.findx(6, 5).should == 12
|
||||
Score.findx(5, 7).should == 13
|
||||
Score.findx(7, 5).should == 13
|
||||
Score.findx(6, 7).should == 23
|
||||
Score.findx(7, 6).should == 23
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -10,13 +10,13 @@ X If no profile location is provided, and the user creates/joins a music session
|
|||
=end
|
||||
|
||||
before do
|
||||
@geocode1 = FactoryGirl.create(:geocoder)
|
||||
@geocode2 = FactoryGirl.create(:geocoder)
|
||||
@user = User.new(first_name: "Example", last_name: "User", email: "user@example.com",
|
||||
password: "foobar", password_confirmation: "foobar",
|
||||
city: "Apex", state: "NC", country: "US",
|
||||
terms_of_service: true, musician: true)
|
||||
@user.save!
|
||||
# @geocode1 = FactoryGirl.create(:geocoder)
|
||||
# @geocode2 = FactoryGirl.create(:geocoder)
|
||||
# @user = User.new(first_name: "Example", last_name: "User", email: "user@example.com",
|
||||
# password: "foobar", password_confirmation: "foobar",
|
||||
# city: "Apex", state: "NC", country: "US",
|
||||
# terms_of_service: true, musician: true)
|
||||
# @user.save!
|
||||
end
|
||||
|
||||
describe "with profile location data" do
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ require 'timecop'
|
|||
require 'resque_spec/scheduler'
|
||||
|
||||
# uncomment this to see active record logs
|
||||
#ActiveRecord::Base.logger = Logger.new(STDOUT) if defined?(ActiveRecord::Base)
|
||||
# ActiveRecord::Base.logger = Logger.new(STDOUT) if defined?(ActiveRecord::Base)
|
||||
|
||||
include JamRuby
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ unless ENV["LOCAL_DEV"] == "1"
|
|||
end
|
||||
# Look for $WORKSPACE, otherwise use "workspace" as dev path.
|
||||
|
||||
devenv = ENV["BUILD_NUMBER"].nil? || ENV["TEST_WWW"] == "1"
|
||||
devenv = ENV["BUILD_NUMBER"].nil? # Jenkins sets a build number environment variable
|
||||
|
||||
if devenv
|
||||
gem 'jam_db', :path=> "../db/target/ruby_package"
|
||||
|
|
|
|||
|
|
@ -139,14 +139,14 @@
|
|||
$form.submit(sendMessage);
|
||||
$textBox.keydown(handleEnter);
|
||||
$sendChatMessageBtn.click(sendMessage);
|
||||
|
||||
registerChatMessage(bind);
|
||||
}
|
||||
else {
|
||||
$form.submit(null);
|
||||
$textBox.keydown(null);
|
||||
$sendChatMessageBtn.click(null);
|
||||
}
|
||||
|
||||
registerChatMessage(bind);
|
||||
}
|
||||
|
||||
// called from sidebar when messages come in
|
||||
|
|
|
|||
|
|
@ -34,8 +34,8 @@
|
|||
function StartRecording(recordingId, clients) {
|
||||
startingSessionState = {};
|
||||
|
||||
// we expect all clients to respond within 3 seconds to mimic the reliable UDP layer
|
||||
startingSessionState.aggegratingStartResultsTimer = setTimeout(timeoutStartRecordingTimer, 3000);
|
||||
// we expect all clients to respond within 1 seconds to mimic the reliable UDP layer
|
||||
startingSessionState.aggegratingStartResultsTimer = setTimeout(timeoutStartRecordingTimer, 1000);
|
||||
startingSessionState.recordingId = recordingId;
|
||||
startingSessionState.groupedClientTracks = copyClientIds(clients, app.clientId); // we will manipulate this new one
|
||||
|
||||
|
|
@ -70,8 +70,8 @@
|
|||
|
||||
stoppingSessionState = {};
|
||||
|
||||
// we expect all clients to respond within 3 seconds to mimic the reliable UDP layer
|
||||
stoppingSessionState.aggegratingStopResultsTimer = setTimeout(timeoutStopRecordingTimer, 3000);
|
||||
// we expect all clients to respond within 1 seconds to mimic the reliable UDP layer
|
||||
stoppingSessionState.aggegratingStopResultsTimer = setTimeout(timeoutStopRecordingTimer, 1000);
|
||||
stoppingSessionState.recordingId = recordingId;
|
||||
stoppingSessionState.groupedClientTracks = copyClientIds(clients, app.clientId);
|
||||
|
||||
|
|
|
|||
|
|
@ -79,7 +79,10 @@
|
|||
band : 'Band',
|
||||
fan : 'Fan',
|
||||
recording : 'Recording',
|
||||
session : 'Session'
|
||||
session : 'Session',
|
||||
facebook: 'facebook',
|
||||
twitter: 'twitter',
|
||||
google: 'google',
|
||||
};
|
||||
|
||||
var categories = {
|
||||
|
|
@ -271,11 +274,11 @@
|
|||
context.ga('send', 'event', categories.band, bandAction);
|
||||
}
|
||||
|
||||
function trackJKSocial(category, target) {
|
||||
function trackJKSocial(category, target, data) {
|
||||
assertOneOf(category, categories);
|
||||
assertOneOf(target, jkSocialTargets);
|
||||
|
||||
context.ga('send', 'event', category, target);
|
||||
context.ga('send', 'event', category, target, data);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -385,6 +385,7 @@
|
|||
})
|
||||
.on('stoppedRecording', function(e, data) {
|
||||
if(data.reason) {
|
||||
logger.warn("Recording Discarded: ", data);
|
||||
var reason = data.reason;
|
||||
var detail = data.detail;
|
||||
|
||||
|
|
|
|||
|
|
@ -657,7 +657,10 @@
|
|||
|
||||
}
|
||||
context.JK.clientType = function () {
|
||||
return context.jamClient.IsNativeClient() ? 'client' : 'browser';
|
||||
if (context.jamClient) {
|
||||
return context.jamClient.IsNativeClient() ? 'client' : 'browser';
|
||||
}
|
||||
return 'browser';
|
||||
}
|
||||
/**
|
||||
* Returns 'MacOSX' if the os appears to be macintosh,
|
||||
|
|
|
|||
|
|
@ -13,6 +13,12 @@ body.web {
|
|||
}
|
||||
}
|
||||
}
|
||||
.share_links {
|
||||
position: absolute;
|
||||
top: 116px;
|
||||
left: 1100px;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.buzz {
|
||||
width: 300px;
|
||||
|
|
|
|||
|
|
@ -7,13 +7,12 @@ class ApiScoringController < ApiController
|
|||
clientid = params[:clientid]
|
||||
if clientid.nil? then render :json => {message: 'clientid not specified'}, :status => 400; return end
|
||||
|
||||
conn = Connection.where(client_id: clientid).first
|
||||
conn = Connection.where(client_id: clientid, user_id: current_user.id).first
|
||||
if conn.nil? then render :json => {message: 'session not found'}, :status => 404; return end
|
||||
if !current_user.id.eql?(conn.user.id) then render :json => {message: 'session not owned by user'}, :status => 403; return end
|
||||
# if !current_user.id.eql?(conn.user.id) then render :json => {message: 'session not owned by user'}, :status => 403; return end
|
||||
|
||||
# todo this method is a stub
|
||||
#puts "ApiScoringController#work(#{clientid}) => locidispid #{c.locidispid}"
|
||||
result_client_id = JamRuby::GetWork.get_work(conn.locidispid)
|
||||
result_client_id = JamRuby::GetWork.get_work(conn.locidispid, conn.addr)
|
||||
#result_client_id = clientid+'peer'
|
||||
|
||||
render :json => {:clientid => result_client_id}, :status => 200
|
||||
|
|
@ -23,12 +22,11 @@ class ApiScoringController < ApiController
|
|||
clientid = params[:clientid]
|
||||
if clientid.nil? then render :json => {message: 'clientid not specified'}, :status => 400; return end
|
||||
|
||||
conn = Connection.where(client_id: clientid).first
|
||||
conn = Connection.where(client_id: clientid, user_id: current_user.id).first
|
||||
if conn.nil? then render :json => {message: 'session not found'}, :status => 404; return end
|
||||
if !current_user.id.eql?(conn.user.id) then render :json => {message: 'session not owned by user'}, :status => 403; return end
|
||||
# if !current_user.id.eql?(conn.user.id) then render :json => {message: 'session not owned by user'}, :status => 403; return end
|
||||
|
||||
# todo this method is a stub
|
||||
result_client_ids = JamRuby::GetWork.get_work_list(conn.locidispid)
|
||||
result_client_ids = JamRuby::GetWork.get_work_list(conn.locidispid, conn.addr)
|
||||
#result_client_ids = [clientid+'peer1', clientid+'peer2']
|
||||
|
||||
render :json => {:clientids => result_client_ids}, :status => 200
|
||||
|
|
@ -37,11 +35,13 @@ class ApiScoringController < ApiController
|
|||
def record # aclientid, aAddr, bclientid, bAddr, score returns nothing
|
||||
|
||||
#puts "================= record #{params.inspect}"
|
||||
|
||||
aclientid = params[:aclientid]
|
||||
aip_address = params[:aAddr]
|
||||
bclientid = params[:bclientid]
|
||||
bip_address = params[:bAddr]
|
||||
score = params[:score]
|
||||
score_data = params.to_s
|
||||
|
||||
if aclientid.nil? then render :json => {message: 'aclientid not specified'}, :status => 400; return end
|
||||
if aip_address.nil? then render :json => {message: 'aAddr not specified'}, :status => 400; return end
|
||||
|
|
@ -61,10 +61,10 @@ class ApiScoringController < ApiController
|
|||
|
||||
if !score.is_a? Numeric then render :json => {message: 'score not valid numeric'}, :status => 400; return end
|
||||
|
||||
aconn = Connection.where(client_id: aclientid).first
|
||||
aconn = Connection.where(client_id: aclientid, user_id: current_user.id).first
|
||||
if aconn.nil? then render :json => {message: 'a\'s session not found'}, :status => 404; return end
|
||||
if aAddr != aconn.addr then render :json => {message: 'a\'s session addr does not match aAddr'}, :status => 403; return end
|
||||
if !current_user.id.eql?(aconn.user.id) then render :json => {message: 'a\'s session not owned by user'}, :status => 403; return end
|
||||
# if !current_user.id.eql?(aconn.user.id) then render :json => {message: 'a\'s session not found'}, :status => 403; return end
|
||||
|
||||
bconn = Connection.where(client_id: bclientid).first
|
||||
if bconn.nil? then render :json => {message: 'b\'s session not found'}, :status => 404; return end
|
||||
|
|
@ -82,7 +82,7 @@ class ApiScoringController < ApiController
|
|||
if bisp.nil? or bloc.nil? then render :json => {message: 'b\'s location or isp not found'}, :status => 404; return end
|
||||
blocidispid = bloc.locid*1000000+bisp.coid
|
||||
|
||||
JamRuby::Score.createx(alocidispid, aclientid, aAddr, blocidispid, bclientid, bAddr, score.ceil, nil)
|
||||
JamRuby::Score.createx(alocidispid, aclientid, aAddr, blocidispid, bclientid, bAddr, score.ceil, nil, score_data)
|
||||
|
||||
render :json => {}, :status => 200
|
||||
end
|
||||
|
|
|
|||
|
|
@ -7,15 +7,17 @@ class ApiSearchController < ApiController
|
|||
|
||||
def index
|
||||
if 1 == params[Search::PARAM_MUSICIAN].to_i || 1 == params[Search::PARAM_BAND].to_i
|
||||
# puts "================== params #{params.to_s}"
|
||||
query = params.clone
|
||||
query[:remote_ip] = request.remote_ip
|
||||
if 1 == params[Search::PARAM_MUSICIAN].to_i
|
||||
@search = Search.musician_filter(query, current_user)
|
||||
if 1 == query[Search::PARAM_MUSICIAN].to_i
|
||||
clientid = query[:clientid]
|
||||
conn = (clientid ? Connection.where(client_id: clientid, user_id: current_user.id).first : nil)
|
||||
@search = Search.musician_filter(query, current_user, conn)
|
||||
else
|
||||
@search = Search.band_filter(query, current_user)
|
||||
end
|
||||
respond_with @search, responder: ApiResponder, :status => 200
|
||||
|
||||
elsif 1 == params[Search::PARAM_SESSION_INVITE].to_i
|
||||
@search = Search.session_invite_search(params[:query], current_user)
|
||||
else
|
||||
|
|
|
|||
|
|
@ -370,20 +370,35 @@ class UsersController < ApplicationController
|
|||
end
|
||||
|
||||
def endorse
|
||||
if uu = User.where(['id = ? AND first_liked_us IS NULL',params[:id]]).limit(1).first
|
||||
uu.first_liked_us = Time.now
|
||||
if uu = current_user ||
|
||||
uu = User.where(['id = ? AND first_social_promoted_at IS NULL',params[:id]]).limit(1).first
|
||||
uu.first_social_promoted_at = Time.now
|
||||
uu.save!
|
||||
end if params[:id].present?
|
||||
end if params[:id].present? && (service=params[:service]).present?
|
||||
|
||||
url, service = 'http://www.jamkazam.com', params[:service]
|
||||
service ||= 'facebook'
|
||||
url = CGI::escape('http://www.jamkazam.com')
|
||||
txt = CGI::escape('Check out JamKazam -- Play music together over the Internet as if in the same room')
|
||||
if 'twitter'==service
|
||||
url = 'https://twitter.com/jamkazam'
|
||||
url = "https://twitter.com/intent/tweet?text=#{txt}&url=#{url}"
|
||||
elsif 'facebook'==service
|
||||
url = 'https://www.facebook.com/JamKazam'
|
||||
url = "http://www.facebook.com/sharer/sharer.php?u=#{url}&t=#{txt}"
|
||||
elsif 'google'==service
|
||||
url = 'https://plus.google.com/u/0/106619885929396862606/about'
|
||||
url = "https://plus.google.com/share?url=#{url}"
|
||||
end
|
||||
if 'email'==params[:src]
|
||||
js =<<JS
|
||||
<script type="text/javascript">
|
||||
$(function() {
|
||||
JK.GA.trackJKSocial(JK.GA.Categories.jkLike, '#{service}', 'email');
|
||||
window.location = "#{url}";
|
||||
});
|
||||
</script>
|
||||
JS
|
||||
render :inline => js, :layout => 'landing'
|
||||
else
|
||||
redirect_to url
|
||||
end
|
||||
redirect_to url
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
<!-- start footer -->
|
||||
<div id="footer">
|
||||
|
||||
<!-- copyright -->
|
||||
<div id="copyright">Copyright © <%= Time.now.year %> JamKazam, Inc. All Rights Reserved</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<div class="dialog-overlay-sm" layout="dialog" layout-id="rate-session-dialog" id="rate-session-dialog">
|
||||
<div class="dialog" layout="dialog" layout-id="rate-session-dialog" id="rate-session-dialog">
|
||||
<!-- dialog header -->
|
||||
<div class="content-head">
|
||||
<%= image_tag "shared/icon_session.png", {:height => 19, :width => 19, :class => "content-icon"} %>
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@
|
|||
</div>
|
||||
<div layout-panel="contents" class="chatcontents">
|
||||
<div class="chat-status">
|
||||
<span>Chat is available during session is connected.</span>
|
||||
<span>Chat is available when session is connected.</span>
|
||||
</div>
|
||||
<div class="chat-list-scroller">
|
||||
<div class="previous-chat-list">
|
||||
|
|
|
|||
|
|
@ -5,6 +5,10 @@
|
|||
= link_to image_tag("web/cta_button.png", :alt => "Sign up now for your free account!"), signup_path, class: "signup", id: "signup"
|
||||
.clearleft
|
||||
= link_to "Already have an account?", signin_path, class: "signin", id: "signin"
|
||||
.share_links
|
||||
- [:twitter, :facebook, :google].each do |site|
|
||||
= link_to(image_tag("content/icon_#{site}.png", :style => "vertical-align:top"), "javascript:void(0)", {'data-site' => site, :class => 'like-link'})
|
||||
= ' '
|
||||
|
||||
- content_for :after_black_bar do
|
||||
- if @jamfest_2014
|
||||
|
|
@ -24,6 +28,12 @@
|
|||
:javascript
|
||||
$(function () {
|
||||
window.JK.WelcomePage();
|
||||
|
||||
$('.like-link').click(function() {
|
||||
var like_site = $(this).data('site');
|
||||
JK.GA.trackJKSocial(JK.GA.Categories.jkLike, like_site, JK.clientType());
|
||||
window.open("/endorse/0/"+like_site, '_blank');
|
||||
});
|
||||
})
|
||||
|
||||
- content_for :extra_dialogs do
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue