From 937efed3e52d8c3695028106249eaaa386f08e8f Mon Sep 17 00:00:00 2001 From: Jonathan Kolyer Date: Sun, 20 Apr 2014 22:54:49 +0000 Subject: [PATCH 01/14] VRFS-1576 affiliate_partner model --- db/manifest | 2 ++ db/up/affiliate_partners.sql | 15 +++++++++++ ruby/lib/jam_ruby/lib/em_helper.rb | 2 +- ruby/lib/jam_ruby/models/affiliate_partner.rb | 27 +++++++++++++++++++ ruby/lib/jam_ruby/models/user.rb | 9 +++++++ web/app/controllers/application_controller.rb | 8 ++++++ web/app/controllers/users_controller.rb | 27 ++++++++++--------- web/lib/user_manager.rb | 4 ++- web/spec/managers/user_manager_spec.rb | 13 ++++++++- 9 files changed, 91 insertions(+), 16 deletions(-) create mode 100644 db/up/affiliate_partners.sql create mode 100644 ruby/lib/jam_ruby/models/affiliate_partner.rb diff --git a/db/manifest b/db/manifest index 232cb12ef..627a79b18 100755 --- a/db/manifest +++ b/db/manifest @@ -143,3 +143,5 @@ emails.sql email_batch.sql user_progress_tracking2.sql bands_did_session.sql +affiliate_partners.sql + diff --git a/db/up/affiliate_partners.sql b/db/up/affiliate_partners.sql new file mode 100644 index 000000000..67f7dfd97 --- /dev/null +++ b/db/up/affiliate_partners.sql @@ -0,0 +1,15 @@ +CREATE TABLE affiliate_partners ( + id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(), + partner_name VARCHAR(128) NOT NULL, + partner_code VARCHAR(128) NOT NULL, + partner_user_id VARCHAR(64) NOT NULL, + user_email VARCHAR(255), + referral_user_count INTEGER NOT NULL DEFAULT 0, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP +); + +CREATE INDEX affiliate_partners_code_idx ON affiliate_partners(partner_code); +CREATE INDEX affiliate_partners_user_idx ON affiliate_partners(partner_user_id); + +ALTER TABLE users ADD COLUMN affiliate_referral_id VARCHAR(64) REFERENCES affiliate_partners(id); diff --git a/ruby/lib/jam_ruby/lib/em_helper.rb b/ruby/lib/jam_ruby/lib/em_helper.rb index c310cf2bf..9c382733a 100644 --- a/ruby/lib/jam_ruby/lib/em_helper.rb +++ b/ruby/lib/jam_ruby/lib/em_helper.rb @@ -65,7 +65,7 @@ module JamWebEventMachine end def self.run - + return if defined?(Rails::Console) current = Thread.current Thread.new do run_em(current) diff --git a/ruby/lib/jam_ruby/models/affiliate_partner.rb b/ruby/lib/jam_ruby/models/affiliate_partner.rb new file mode 100644 index 000000000..6f7a001b3 --- /dev/null +++ b/ruby/lib/jam_ruby/models/affiliate_partner.rb @@ -0,0 +1,27 @@ +class JamRuby::AffiliatePartner < ActiveRecord::Base + has_one :partner_user, :class_name => "JamRuby::User", :foreign_key => :partner_user_id + has_many :user_referrals, :class_name => "JamRuby::User", :foreign_key => :affiliate_referral_id + + attr_accessible :partner_name, :partner_code, :partner_user_id + + validates :user_email, format: {with: JamRuby::User::VALID_EMAIL_REGEX}, :if => :user_email + validates :partner_name, presence: true + validates :partner_code, presence: true + validates :partner_user, presence: true + + def self.create_with_params(params={}) + oo = self.new + oo.partner_name = params[:partner_name] + oo.partner_code = params[:partner_code] + oo.partner_user = User.where(:email => params[:user_email]).limit(1).first + oo.partner_user_id = oo.partner_user.try(:id) + oo.save! + oo + end + + def self.coded_id(code=nil) + self.where(:partner_code => code).limit(1).pluck(:id).first if code.present? + end + +end + diff --git a/ruby/lib/jam_ruby/models/user.rb b/ruby/lib/jam_ruby/models/user.rb index 77966d5cc..87e8ee49c 100644 --- a/ruby/lib/jam_ruby/models/user.rb +++ b/ruby/lib/jam_ruby/models/user.rb @@ -99,6 +99,10 @@ module JamRuby # events has_many :event_sessions, :class_name => "JamRuby::EventSession" + # affiliate_partner + has_one :affiliate_partner, :class_name => "JamRuby::AffiliatePartner", :foreign_key => :partner_user_id + belongs_to :affiliate_referral, :class_name => "JamRuby::AffiliatePartner", :foreign_key => :affiliate_referral_id, :counter_cache => :referral_user_count + # This causes the authenticate method to be generated (among other stuff) #has_secure_password @@ -735,6 +739,7 @@ module JamRuby invited_user = options[:invited_user] fb_signup = options[:fb_signup] signup_confirm_url = options[:signup_confirm_url] + affiliate_referral_id = options[:affiliate_referral_id] user = User.new @@ -836,6 +841,10 @@ module JamRuby if user.errors.any? raise ActiveRecord::Rollback else + if user.affiliate_referral = AffiliatePartner.find_by_id(affiliate_referral_id) + user.save + end if affiliate_referral_id.present? + # don't send an signup email if email is already confirmed if user.email_confirmed UserMailer.welcome_message(user).deliver diff --git a/web/app/controllers/application_controller.rb b/web/app/controllers/application_controller.rb index c2922f055..d28b4ea46 100644 --- a/web/app/controllers/application_controller.rb +++ b/web/app/controllers/application_controller.rb @@ -8,6 +8,14 @@ class ApplicationController < ActionController::Base # inject username/email into bugsnag data before_bugsnag_notify :add_user_info_to_bugsnag + def affiliate_code + cookies[:affiliate_code] + end + + def affiliate_code=(code) + cookies[:affiliate_code] = code if code.present? + end + private def add_user_info_to_bugsnag(notif) # Add some app-specific data which will be displayed on a custom diff --git a/web/app/controllers/users_controller.rb b/web/app/controllers/users_controller.rb index d31bb4094..d380c6b34 100644 --- a/web/app/controllers/users_controller.rb +++ b/web/app/controllers/users_controller.rb @@ -149,19 +149,20 @@ class UsersController < ApplicationController musician = params[:jam_ruby_user][:musician] @user = UserManager.new.signup(remote_ip: request.remote_ip, - first_name: params[:jam_ruby_user][:first_name], - last_name: params[:jam_ruby_user][:last_name], - email: params[:jam_ruby_user][:email], - password: params[:jam_ruby_user][:password], - password_confirmation: params[:jam_ruby_user][:password_confirmation], - terms_of_service: terms_of_service, - instruments: instruments, - birth_date: birth_date, - location: location, - musician: musician, - invited_user: @invited_user, - fb_signup: @fb_signup, - signup_confirm_url: ApplicationHelper.base_uri(request) + "/confirm") + first_name: params[:jam_ruby_user][:first_name], + last_name: params[:jam_ruby_user][:last_name], + email: params[:jam_ruby_user][:email], + password: params[:jam_ruby_user][:password], + password_confirmation: params[:jam_ruby_user][:password_confirmation], + terms_of_service: terms_of_service, + instruments: instruments, + birth_date: birth_date, + location: location, + musician: musician, + invited_user: @invited_user, + fb_signup: @fb_signup, + signup_confirm_url: ApplicationHelper.base_uri(request) + "/confirm", + affiliate_referral_id: AffiliatePartner.coded_id(self.affiliate_code)) # check for errors if @user.errors.any? diff --git a/web/lib/user_manager.rb b/web/lib/user_manager.rb index 728bcb652..34be86248 100644 --- a/web/lib/user_manager.rb +++ b/web/lib/user_manager.rb @@ -26,6 +26,7 @@ class UserManager < BaseManager invited_user = options[:invited_user] fb_signup = options[:fb_signup] signup_confirm_url = options[:signup_confirm_url] + affiliate_referral_id = options[:affiliate_referral_id] @user = User.new @@ -60,7 +61,8 @@ class UserManager < BaseManager photo_url: photo_url, invited_user: invited_user, fb_signup: fb_signup, - signup_confirm_url: signup_confirm_url) + signup_confirm_url: signup_confirm_url, + affiliate_referral_id: affiliate_referral_id) return @user #end diff --git a/web/spec/managers/user_manager_spec.rb b/web/spec/managers/user_manager_spec.rb index ba4d3a33d..e09c9406c 100644 --- a/web/spec/managers/user_manager_spec.rb +++ b/web/spec/managers/user_manager_spec.rb @@ -11,6 +11,13 @@ describe UserManager do end describe "signup" do + let!(:user) { FactoryGirl.create(:user) } + let!(:partner) { + AffiliatePartner.create_with_params({:partner_name => Faker::Company.name, + :partner_code => Faker::Lorem.words(1)[0], + :user_email => user.email}) + } + it "signup successfully" do MaxMindIsp.delete_all # prove that city/state/country will remain nil if no maxmind data MaxMindGeo.delete_all @@ -24,7 +31,8 @@ describe UserManager do terms_of_service: true, instruments: @instruments, musician:true, - signup_confirm_url: "http://localhost:3000/confirm" ) + signup_confirm_url: "http://localhost:3000/confirm", + affiliate_referral_id: AffiliatePartner.coded_id(partner.partner_code)) @user.errors.any?.should be_false @user.first_name.should == "bob" @@ -38,6 +46,9 @@ describe UserManager do @user.subscribe_email.should be_true @user.signup_token.should_not be_nil + @user.reload + expect(@user.affiliate_referral).to eq(partner) + UserMailer.deliveries.length.should == 1 end From 245727806ddd7d60fa2dd2204d1f85ce92f97384 Mon Sep 17 00:00:00 2001 From: Jonathan Kolyer Date: Sun, 20 Apr 2014 22:55:40 +0000 Subject: [PATCH 02/14] VRFS-1576 affiliate_partner model --- ruby/lib/jam_ruby.rb | 1 + .../jam_ruby/models/affiliate_partner_spec.rb | 31 +++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 ruby/spec/jam_ruby/models/affiliate_partner_spec.rb diff --git a/ruby/lib/jam_ruby.rb b/ruby/lib/jam_ruby.rb index ef426e9a8..f596d402d 100755 --- a/ruby/lib/jam_ruby.rb +++ b/ruby/lib/jam_ruby.rb @@ -140,6 +140,7 @@ 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/models/affiliate_partner" include Jampb diff --git a/ruby/spec/jam_ruby/models/affiliate_partner_spec.rb b/ruby/spec/jam_ruby/models/affiliate_partner_spec.rb new file mode 100644 index 000000000..4a9843aab --- /dev/null +++ b/ruby/spec/jam_ruby/models/affiliate_partner_spec.rb @@ -0,0 +1,31 @@ +require 'spec_helper' + +describe AffiliatePartner do + + let!(:user) { FactoryGirl.create(:user) } + let!(:partner) { + AffiliatePartner.create_with_params({:partner_name => Faker::Company.name, + :partner_code => Faker::Lorem.word, + :user_email => user.email}) + } + + it 'validates required fields' do + expect(partner.referral_user_count).to eq(0) + expect(partner.partner_user).to eq(user) + user.reload + expect(user.affiliate_partner).to eq(partner) + end + + it 'has user referrals' do + expect(AffiliatePartner.coded_id(partner.partner_code)).to eq(partner.id) + expect(partner.referral_user_count).to eq(0) + uu = FactoryGirl.create(:user) + uu.affiliate_referral = partner + uu.save + partner.reload + expect(uu.affiliate_referral).to eq(partner) + expect(partner.referral_user_count).to eq(1) + expect(partner.user_referrals[0]).to eq(uu) + end + +end From 62dbeaa81865af122683a91d238b766c8c9701e6 Mon Sep 17 00:00:00 2001 From: Jonathan Kolyer Date: Sun, 20 Apr 2014 23:20:27 +0000 Subject: [PATCH 03/14] VRFS-1576 added validation and tests --- ruby/lib/jam_ruby/models/affiliate_partner.rb | 10 ++++---- .../jam_ruby/models/affiliate_partner_spec.rb | 23 +++++++++++++++++++ 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/ruby/lib/jam_ruby/models/affiliate_partner.rb b/ruby/lib/jam_ruby/models/affiliate_partner.rb index 6f7a001b3..8b1951f45 100644 --- a/ruby/lib/jam_ruby/models/affiliate_partner.rb +++ b/ruby/lib/jam_ruby/models/affiliate_partner.rb @@ -4,16 +4,18 @@ class JamRuby::AffiliatePartner < ActiveRecord::Base attr_accessible :partner_name, :partner_code, :partner_user_id + PARTNER_CODE_REGEX = /^[#{Regexp.escape('abcdefghijklmnopqrstuvwxyz0123456789-._+,')}]+{2,128}$/i + validates :user_email, format: {with: JamRuby::User::VALID_EMAIL_REGEX}, :if => :user_email validates :partner_name, presence: true - validates :partner_code, presence: true + validates :partner_code, presence: true, format: { with: PARTNER_CODE_REGEX } validates :partner_user, presence: true def self.create_with_params(params={}) oo = self.new - oo.partner_name = params[:partner_name] - oo.partner_code = params[:partner_code] - oo.partner_user = User.where(:email => params[:user_email]).limit(1).first + oo.partner_name = params[:partner_name].try(:strip) + oo.partner_code = params[:partner_code].try(:strip) + oo.partner_user = User.where(:email => params[:user_email].try(:strip)).limit(1).first oo.partner_user_id = oo.partner_user.try(:id) oo.save! oo diff --git a/ruby/spec/jam_ruby/models/affiliate_partner_spec.rb b/ruby/spec/jam_ruby/models/affiliate_partner_spec.rb index 4a9843aab..4793544db 100644 --- a/ruby/spec/jam_ruby/models/affiliate_partner_spec.rb +++ b/ruby/spec/jam_ruby/models/affiliate_partner_spec.rb @@ -14,6 +14,29 @@ describe AffiliatePartner do expect(partner.partner_user).to eq(user) user.reload expect(user.affiliate_partner).to eq(partner) + + expect{AffiliatePartner.create_with_params({:partner_name => Faker::Company.name, + :partner_code => 'a', + :user_email => user.email})} + .to raise_error(ActiveRecord::RecordInvalid) + expect{AffiliatePartner.create_with_params({:partner_name => Faker::Company.name, + :partner_code => 'foo bar', + :user_email => user.email})} + .to raise_error(ActiveRecord::RecordInvalid) + expect{AffiliatePartner.create_with_params({:partner_name => '', + :partner_code => Faker::Lorem.word, + :user_email => user.email})} + .to raise_error(ActiveRecord::RecordInvalid) + expect{AffiliatePartner.create_with_params({:partner_name => Faker::Company.name, + :partner_code => Faker::Lorem.word, + :user_email => Faker::Internet.email})} + .to raise_error(ActiveRecord::RecordInvalid) + + code = Faker::Lorem.word + oo = AffiliatePartner.create_with_params({:partner_name => Faker::Company.name, + :partner_code => " #{code} ", + :user_email => user.email}) + expect(oo.partner_code).to eq(code) end it 'has user referrals' do From 15064ad6c009bbb42bd09f89d6087ad1a6693e5f Mon Sep 17 00:00:00 2001 From: Bert Owen Date: Mon, 21 Apr 2014 10:39:08 -0700 Subject: [PATCH 04/14] VRFS-1567 fix default sender, add new migration for email_batches table --- db/manifest | 1 + db/up/email_change_default_sender.sql | 1 + ruby/lib/jam_ruby/app/mailers/invited_user_mailer.rb | 2 +- ruby/lib/jam_ruby/app/mailers/user_mailer.rb | 2 +- ruby/lib/jam_ruby/models/email_batch.rb | 2 +- 5 files changed, 5 insertions(+), 3 deletions(-) create mode 100644 db/up/email_change_default_sender.sql diff --git a/db/manifest b/db/manifest index 232cb12ef..843c69235 100755 --- a/db/manifest +++ b/db/manifest @@ -143,3 +143,4 @@ emails.sql email_batch.sql user_progress_tracking2.sql bands_did_session.sql +email_change_default_sender.sql \ No newline at end of file diff --git a/db/up/email_change_default_sender.sql b/db/up/email_change_default_sender.sql new file mode 100644 index 000000000..e729980f0 --- /dev/null +++ b/db/up/email_change_default_sender.sql @@ -0,0 +1 @@ +ALTER TABLE email_batches ALTER column from_email SET DEFAULT 'noreply@jamkazam.com'::character varying; \ No newline at end of file diff --git a/ruby/lib/jam_ruby/app/mailers/invited_user_mailer.rb b/ruby/lib/jam_ruby/app/mailers/invited_user_mailer.rb index 566cd7d22..e01846424 100644 --- a/ruby/lib/jam_ruby/app/mailers/invited_user_mailer.rb +++ b/ruby/lib/jam_ruby/app/mailers/invited_user_mailer.rb @@ -9,7 +9,7 @@ module JamRuby class InvitedUserMailer < ActionMailer::Base include SendGrid - DEFAULT_SENDER = "support@jamkazam.com" + DEFAULT_SENDER = "noreply@jamkazam.com" default :from => DEFAULT_SENDER diff --git a/ruby/lib/jam_ruby/app/mailers/user_mailer.rb b/ruby/lib/jam_ruby/app/mailers/user_mailer.rb index f0909d7eb..cd7134591 100644 --- a/ruby/lib/jam_ruby/app/mailers/user_mailer.rb +++ b/ruby/lib/jam_ruby/app/mailers/user_mailer.rb @@ -11,7 +11,7 @@ layout "user_mailer" - DEFAULT_SENDER = "support@jamkazam.com" + DEFAULT_SENDER = "noreply@jamkazam.com" default :from => DEFAULT_SENDER diff --git a/ruby/lib/jam_ruby/models/email_batch.rb b/ruby/lib/jam_ruby/models/email_batch.rb index 309b63305..74dff06ec 100644 --- a/ruby/lib/jam_ruby/models/email_batch.rb +++ b/ruby/lib/jam_ruby/models/email_batch.rb @@ -12,7 +12,7 @@ module JamRuby VAR_FIRST_NAME = '@FIRSTNAME' VAR_LAST_NAME = '@LASTNAME' - DEFAULT_SENDER = "support@jamkazam.com" + DEFAULT_SENDER = "noreply@jamkazam.com" BATCH_SIZE = 1000 BODY_TEMPLATE =< Date: Tue, 22 Apr 2014 01:55:40 +0000 Subject: [PATCH 05/14] VRFS-1576 error handling; referral page; new admin menu --- admin/app/admin/affiliate_users.rb | 31 ++++++++++++ admin/app/admin/affiliates.rb | 48 +++++++++++++++++++ admin/app/models/admin_authorization.rb | 8 +++- .../app/views/admin/affiliates/_form.html.erb | 13 +++++ ruby/lib/jam_ruby/models/affiliate_partner.rb | 7 ++- web/app/controllers/application_controller.rb | 13 +++-- 6 files changed, 113 insertions(+), 7 deletions(-) create mode 100644 admin/app/admin/affiliate_users.rb create mode 100644 admin/app/admin/affiliates.rb create mode 100644 admin/app/views/admin/affiliates/_form.html.erb diff --git a/admin/app/admin/affiliate_users.rb b/admin/app/admin/affiliate_users.rb new file mode 100644 index 000000000..b21d512eb --- /dev/null +++ b/admin/app/admin/affiliate_users.rb @@ -0,0 +1,31 @@ +ActiveAdmin.register JamRuby::User, :as => 'Referrals' do + + menu :label => 'Referrals', :parent => 'Affiliates' + + config.batch_actions = false + config.clear_action_items! + config.filters = false + + index do + column 'User' do |oo| link_to(oo.name, "http://www.jamkazam.com/client#/profile/#{oo.id}", {:title => oo.name}) end + column 'Email' do |oo| oo.email end + column 'Created' do |oo| oo.created_at end + column 'Partner' do |oo| oo.affiliate_referral.partner_name end + end + + controller do + + def scoped_collection + rel = end_of_association_chain + .includes([:affiliate_referral]) + .order('created_at DESC') + if (ref_id = params[AffiliatePartner::PARAM_REFERRAL]).present? + qq = ['affiliate_referral_id = ?', ref_id] + else + qq = ['affiliate_referral_id IS NOT NULL'] + end + @users ||= rel.where(qq) + end + + end +end diff --git a/admin/app/admin/affiliates.rb b/admin/app/admin/affiliates.rb new file mode 100644 index 000000000..d0e7e5466 --- /dev/null +++ b/admin/app/admin/affiliates.rb @@ -0,0 +1,48 @@ +ActiveAdmin.register JamRuby::AffiliatePartner, :as => 'Affiliates' do + + menu :label => 'Partners', :parent => 'Affiliates' + + config.sort_order = 'created_at DESC' + config.batch_actions = false + # config.clear_action_items! + config.filters = false + + form :partial => 'form' + + index do + column 'User' do |oo| link_to(oo.partner_user.name, "http://www.jamkazam.com/client#/profile/#{oo.partner_user.id}", {:title => oo.partner_user.name}) end + column 'Email' do |oo| oo.partner_user.email end + column 'Name' do |oo| oo.partner_name end + column 'Code' do |oo| oo.partner_code end + column 'Referral Count' do |oo| oo.referral_user_count end + # column 'Referrals' do |oo| link_to('View', admin_referrals_path(AffiliatePartner::PARAM_REFERRAL => oo.id)) end + default_actions + end + + controller do + + def show + redirect_to admin_referrals_path(AffiliatePartner::PARAM_REFERRAL => resource.id) + end + + def create + obj = AffiliatePartner.create_with_params(params[:jam_ruby_affiliate_partner]) + if obj.errors.present? + set_resource_ivar(obj) + render active_admin_template('new') + else + redirect_to admin_affiliates_path + end + end + + def update + obj = resource + vals = params[:jam_ruby_affiliate_partner] + obj.partner_name = vals[:partner_name] + obj.user_email = vals[:user_email] if vals[:user_email].present? + obj.save! + redirect_to admin_affiliates_path + end + + end +end diff --git a/admin/app/models/admin_authorization.rb b/admin/app/models/admin_authorization.rb index 692d118f1..809991226 100644 --- a/admin/app/models/admin_authorization.rb +++ b/admin/app/models/admin_authorization.rb @@ -1,7 +1,13 @@ class AdminAuthorization < ActiveAdmin::AuthorizationAdapter def authorized?(action, subject = nil) - subject.is_a?(EmailBatch) && :update == action ? subject.can_run_batch? : true + if subject.is_a?(EmailBatch) && :update == action + subject.can_run_batch? + elsif subject.is_a?(AffiliatePartner) && :destroy == action + false + else + true + end end end diff --git a/admin/app/views/admin/affiliates/_form.html.erb b/admin/app/views/admin/affiliates/_form.html.erb new file mode 100644 index 000000000..a4f14416e --- /dev/null +++ b/admin/app/views/admin/affiliates/_form.html.erb @@ -0,0 +1,13 @@ +<%= semantic_form_for([:admin, resource], :url => resource.new_record? ? admin_affiliates_path : "/admin/affiliates/#{resource.id}") do |f| %> + <%= f.semantic_errors *f.object.errors.keys %> + <%= f.inputs do %> + <%= f.input(:user_email, :input_html => {:maxlength => 255}) %> + <%= f.input(:partner_name, :input_html => {:maxlength => 128}) %> + <% if resource.new_record? %> + <%= f.input(:partner_code, :input_html => {:maxlength => 128}) %> + <% else %> + <%= f.input(:partner_code, :input_html => {:maxlength => 128, :readonly => 'readonly'}) %> + <% end %> + <% end %> + <%= f.actions %> +<% end %> diff --git a/ruby/lib/jam_ruby/models/affiliate_partner.rb b/ruby/lib/jam_ruby/models/affiliate_partner.rb index 8b1951f45..6aee0df77 100644 --- a/ruby/lib/jam_ruby/models/affiliate_partner.rb +++ b/ruby/lib/jam_ruby/models/affiliate_partner.rb @@ -1,9 +1,12 @@ class JamRuby::AffiliatePartner < ActiveRecord::Base - has_one :partner_user, :class_name => "JamRuby::User", :foreign_key => :partner_user_id + belongs_to :partner_user, :class_name => "JamRuby::User", :foreign_key => :partner_user_id has_many :user_referrals, :class_name => "JamRuby::User", :foreign_key => :affiliate_referral_id attr_accessible :partner_name, :partner_code, :partner_user_id + PARAM_REFERRAL = :ref + PARAM_COOKIE = :affiliate_ref + PARTNER_CODE_REGEX = /^[#{Regexp.escape('abcdefghijklmnopqrstuvwxyz0123456789-._+,')}]+{2,128}$/i validates :user_email, format: {with: JamRuby::User::VALID_EMAIL_REGEX}, :if => :user_email @@ -17,7 +20,7 @@ class JamRuby::AffiliatePartner < ActiveRecord::Base oo.partner_code = params[:partner_code].try(:strip) oo.partner_user = User.where(:email => params[:user_email].try(:strip)).limit(1).first oo.partner_user_id = oo.partner_user.try(:id) - oo.save! + oo.save oo end diff --git a/web/app/controllers/application_controller.rb b/web/app/controllers/application_controller.rb index d28b4ea46..52b7a6548 100644 --- a/web/app/controllers/application_controller.rb +++ b/web/app/controllers/application_controller.rb @@ -8,12 +8,17 @@ class ApplicationController < ActionController::Base # inject username/email into bugsnag data before_bugsnag_notify :add_user_info_to_bugsnag - def affiliate_code - cookies[:affiliate_code] + before_filter do + if current_user.nil? + if (code = params[AffiliatePartner::PARAM_REFERRAL]).present? && + cookies[AffiliatePartner::PARAM_COOKIE].blank? + cookies[AffiliatePartner::PARAM_COOKIE] = code + end + end end - def affiliate_code=(code) - cookies[:affiliate_code] = code if code.present? + def affiliate_code + cookies[AffiliatePartner::PARAM_COOKIE] end private From af63b03d6aeff9aa36e7f4c24d56392a5fe3450b Mon Sep 17 00:00:00 2001 From: Jonathan Kolyer Date: Tue, 22 Apr 2014 02:14:22 +0000 Subject: [PATCH 06/14] VRFS-1576 case insensitive codes --- ruby/lib/jam_ruby/models/affiliate_partner.rb | 7 +++++-- web/app/controllers/application_controller.rb | 9 ++++----- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/ruby/lib/jam_ruby/models/affiliate_partner.rb b/ruby/lib/jam_ruby/models/affiliate_partner.rb index 6aee0df77..4ae393366 100644 --- a/ruby/lib/jam_ruby/models/affiliate_partner.rb +++ b/ruby/lib/jam_ruby/models/affiliate_partner.rb @@ -17,7 +17,7 @@ class JamRuby::AffiliatePartner < ActiveRecord::Base def self.create_with_params(params={}) oo = self.new oo.partner_name = params[:partner_name].try(:strip) - oo.partner_code = params[:partner_code].try(:strip) + oo.partner_code = params[:partner_code].try(:strip).try(:downcase) oo.partner_user = User.where(:email => params[:user_email].try(:strip)).limit(1).first oo.partner_user_id = oo.partner_user.try(:id) oo.save @@ -28,5 +28,8 @@ class JamRuby::AffiliatePartner < ActiveRecord::Base self.where(:partner_code => code).limit(1).pluck(:id).first if code.present? end -end + def self.is_code?(code) + self.where(:partner_code => code).limit(1).pluck(:id).present? + end +end diff --git a/web/app/controllers/application_controller.rb b/web/app/controllers/application_controller.rb index 52b7a6548..3954175af 100644 --- a/web/app/controllers/application_controller.rb +++ b/web/app/controllers/application_controller.rb @@ -4,15 +4,14 @@ class ApplicationController < ActionController::Base include ApplicationHelper include SessionsHelper - # inject username/email into bugsnag data before_bugsnag_notify :add_user_info_to_bugsnag before_filter do - if current_user.nil? - if (code = params[AffiliatePartner::PARAM_REFERRAL]).present? && - cookies[AffiliatePartner::PARAM_COOKIE].blank? - cookies[AffiliatePartner::PARAM_COOKIE] = code + if params[AffiliatePartner::PARAM_REFERRAL].present? && current_user.nil? + if cookies[AffiliatePartner::PARAM_COOKIE].blank? + code = params[AffiliatePartner::PARAM_REFERRAL].downcase + cookies[AffiliatePartner::PARAM_COOKIE] = code if AffiliatePartner.is_code?(code) end end end From b232344336c94e95605f0b989f5b0c3104d443b6 Mon Sep 17 00:00:00 2001 From: Jonathan Kolyer Date: Tue, 22 Apr 2014 07:12:05 +0000 Subject: [PATCH 07/14] VRFS-1576 added referrals_by_date and associated test --- ruby/lib/jam_ruby/models/affiliate_partner.rb | 9 ++++ .../jam_ruby/models/affiliate_partner_spec.rb | 46 +++++++++++++------ 2 files changed, 41 insertions(+), 14 deletions(-) diff --git a/ruby/lib/jam_ruby/models/affiliate_partner.rb b/ruby/lib/jam_ruby/models/affiliate_partner.rb index 4ae393366..e4ee54517 100644 --- a/ruby/lib/jam_ruby/models/affiliate_partner.rb +++ b/ruby/lib/jam_ruby/models/affiliate_partner.rb @@ -32,4 +32,13 @@ class JamRuby::AffiliatePartner < ActiveRecord::Base self.where(:partner_code => code).limit(1).pluck(:id).present? end + def referrals_by_date + User.where(:affiliate_referral_id => self.id) + .group('DATE(created_at)') + .count + .select { |day,count| 0 != count } + .inject([]) { |rr,kk,vv| rr << kk } + .sort { |a1,a2| a2[0] <=> a1[0] } + end + end diff --git a/ruby/spec/jam_ruby/models/affiliate_partner_spec.rb b/ruby/spec/jam_ruby/models/affiliate_partner_spec.rb index 4793544db..cf7c1cb91 100644 --- a/ruby/spec/jam_ruby/models/affiliate_partner_spec.rb +++ b/ruby/spec/jam_ruby/models/affiliate_partner_spec.rb @@ -15,28 +15,28 @@ describe AffiliatePartner do user.reload expect(user.affiliate_partner).to eq(partner) - expect{AffiliatePartner.create_with_params({:partner_name => Faker::Company.name, + oo = AffiliatePartner.create_with_params({:partner_name => Faker::Company.name, :partner_code => 'a', - :user_email => user.email})} - .to raise_error(ActiveRecord::RecordInvalid) - expect{AffiliatePartner.create_with_params({:partner_name => Faker::Company.name, + :user_email => user.email}) + expect(oo.errors.messages[:partner_code][0]).to eq('is invalid') + oo = AffiliatePartner.create_with_params({:partner_name => Faker::Company.name, :partner_code => 'foo bar', - :user_email => user.email})} - .to raise_error(ActiveRecord::RecordInvalid) - expect{AffiliatePartner.create_with_params({:partner_name => '', + :user_email => user.email}) + expect(oo.errors.messages[:partner_code][0]).to eq('is invalid') + oo = AffiliatePartner.create_with_params({:partner_name => '', :partner_code => Faker::Lorem.word, - :user_email => user.email})} - .to raise_error(ActiveRecord::RecordInvalid) - expect{AffiliatePartner.create_with_params({:partner_name => Faker::Company.name, + :user_email => user.email}) + expect(oo.errors.messages[:partner_name][0]).to eq("can't be blank") + oo = AffiliatePartner.create_with_params({:partner_name => '', :partner_code => Faker::Lorem.word, - :user_email => Faker::Internet.email})} - .to raise_error(ActiveRecord::RecordInvalid) + :user_email => Faker::Internet.email}) + expect(oo.errors.messages[:partner_user][0]).to eq("can't be blank") - code = Faker::Lorem.word + code = Faker::Lorem.word.upcase oo = AffiliatePartner.create_with_params({:partner_name => Faker::Company.name, :partner_code => " #{code} ", :user_email => user.email}) - expect(oo.partner_code).to eq(code) + expect(oo.partner_code).to eq(code.downcase) end it 'has user referrals' do @@ -51,4 +51,22 @@ describe AffiliatePartner do expect(partner.user_referrals[0]).to eq(uu) end + it 'groups referrals properly' do + FactoryGirl.create(:user, :created_at => Time.now - 7.days, :affiliate_referral_id => partner.id) + FactoryGirl.create(:user, :created_at => Time.now - 7.days, :affiliate_referral_id => partner.id) + FactoryGirl.create(:user, :created_at => Time.now - 6.days, :affiliate_referral_id => partner.id) + FactoryGirl.create(:user, :created_at => Time.now - 6.days, :affiliate_referral_id => partner.id) + FactoryGirl.create(:user, :created_at => Time.now - 3.days, :affiliate_referral_id => partner.id) + FactoryGirl.create(:user, :created_at => Time.now - 2.days, :affiliate_referral_id => partner.id) + partner.reload + expect(partner.referral_user_count).to eq(6) + + by_date = partner.referrals_by_date + expect(by_date.count).to eq(4) + expect(Date.parse(by_date.first.first.to_s)).to eq(Date.parse((Time.now - 2.days).to_s)) + expect(by_date.first.last.to_i).to eq(1) + expect(Date.parse(by_date.last.first.to_s)).to eq(Date.parse((Time.now - 7.days).to_s)) + expect(by_date.last.last.to_i).to eq(2) + end + end From 30ca8d7c5ca6014760f5c2edcfb8ab5da554d9d7 Mon Sep 17 00:00:00 2001 From: Seth Call Date: Tue, 22 Apr 2014 17:53:41 +0000 Subject: [PATCH 08/14] * wip still on new ftue. also push release branches to repository VRFS-1639 --- build | 4 +- ruby/lib/jam_ruby/lib/em_helper.rb | 1 - web/app/assets/javascripts/banner.js | 1 + .../assets/javascripts/createSession.js.erb | 2 +- web/app/assets/javascripts/gear_wizard.js | 360 ++++++++++++------ .../stylesheets/client/gearWizard.css.scss | 24 +- .../stylesheets/client/jamkazam.css.scss | 5 + .../views/clients/gear/_gear_wizard.html.haml | 15 + web/app/views/layouts/client.html.erb | 14 +- web/app/views/layouts/corporate.html.erb | 14 +- web/app/views/layouts/landing.erb | 14 +- web/app/views/layouts/minimal.html.erb | 14 +- web/app/views/layouts/web.html.erb | 14 +- 13 files changed, 328 insertions(+), 154 deletions(-) diff --git a/build b/build index 9b97f9176..6d408c180 100755 --- a/build +++ b/build @@ -66,7 +66,7 @@ DEB_SERVER=http://localhost:9010/apt-`uname -p` GEM_SERVER=http://localhost:9000/gems # if still going, then push all debs up - if [[ "$GIT_BRANCH" == *develop* || "$GIT_BRANCH" == *master* ]]; then + if [[ "$GIT_BRANCH" == *develop* || "$GIT_BRANCH" == *master* || "$GIT_BRANCH" == *release* ]]; then echo "" echo "PUSHING DB ARTIFACTS" @@ -129,7 +129,7 @@ GEM_SERVER=http://localhost:9000/gems popd > /dev/null else - echo "Skipping publish since branch is neither master or develop..." + echo "Skipping publish since branch is not master, develop, or release/*. branch is $GIT_BRANCH" fi fi diff --git a/ruby/lib/jam_ruby/lib/em_helper.rb b/ruby/lib/jam_ruby/lib/em_helper.rb index c310cf2bf..9e826b74c 100644 --- a/ruby/lib/jam_ruby/lib/em_helper.rb +++ b/ruby/lib/jam_ruby/lib/em_helper.rb @@ -65,7 +65,6 @@ module JamWebEventMachine end def self.run - current = Thread.current Thread.new do run_em(current) diff --git a/web/app/assets/javascripts/banner.js b/web/app/assets/javascripts/banner.js index a301f0b7a..7b11a3211 100644 --- a/web/app/assets/javascripts/banner.js +++ b/web/app/assets/javascripts/banner.js @@ -66,6 +66,7 @@ var me = { initialize: initialize, show: show, + showAlert: showAlert, hide: hide } diff --git a/web/app/assets/javascripts/createSession.js.erb b/web/app/assets/javascripts/createSession.js.erb index e5744cbfe..687527bbd 100644 --- a/web/app/assets/javascripts/createSession.js.erb +++ b/web/app/assets/javascripts/createSession.js.erb @@ -69,7 +69,7 @@ .prop('disabled', true) } - function validateForm() { + function validateForm() { //var errors = []; var isValid = true; var $form = $('#create-session-form'); diff --git a/web/app/assets/javascripts/gear_wizard.js b/web/app/assets/javascripts/gear_wizard.js index 634710d76..48ac0c668 100644 --- a/web/app/assets/javascripts/gear_wizard.js +++ b/web/app/assets/javascripts/gear_wizard.js @@ -6,18 +6,22 @@ context.JK = context.JK || {}; context.JK.GearWizard = function (app) { + var $dialog = null; var $wizardSteps = null; var $currentWizardStep = null; var step = 0; var $templateSteps = null; var $templateButtons = null; + var $templateAudioPort = null; var $ftueButtons = null; var self = null; var operatingSystem = null; // populated by loadDevices var deviceInformation = null; + var musicInputPorts = null; + var musicOutputPorts = null; // SELECT DEVICE STATE var validScore = false; @@ -33,28 +37,32 @@ var STEP_ROUTER_NETWORK = 5; var STEP_SUCCESS = 6; + var PROFILE_DEV_SEP_TOKEN = '^'; + + var iCheckIgnore = false; + var audioDeviceBehavior = { - MacOSX_builtin : { + MacOSX_builtin: { display: 'MacOSX Built-In', videoURL: undefined }, - MACOSX_interface : { + MACOSX_interface: { display: 'MacOSX external interface', videoURL: undefined }, - Win32_wdm : { + Win32_wdm: { display: 'Windows WDM', videoURL: undefined }, - Win32_asio : { + Win32_asio: { display: 'Windows ASIO', videoURL: undefined }, - Win32_asio4all : { + Win32_asio4all: { display: 'Windows ASIO4ALL', videoURL: undefined }, - Linux : { + Linux: { display: 'Linux', videoURL: undefined } @@ -63,7 +71,7 @@ function beforeShowIntro() { var $watchVideo = $currentWizardStep.find('.watch-video'); var videoUrl = 'https://www.youtube.com/watch?v=VexH4834o9I'; - if(operatingSystem == "Win32") { + if (operatingSystem == "Win32") { $watchVideo.attr('href', 'https://www.youtube.com/watch?v=VexH4834o9I'); } $watchVideo.attr('href', videoUrl); @@ -81,6 +89,9 @@ var $inputPorts = $currentWizardStep.find('.input-ports'); var $outputPorts = $currentWizardStep.find('.output-ports'); var $scoreReport = $currentWizardStep.find('.results'); + var $latencyScore = $scoreReport.find('.latency-score'); + var $ioRateScore = $scoreReport.find('.io-rate-score'); + var $ioVarScore = $scoreReport.find('.io-var-score'); var $nextButton = $ftueButtons.find('.btn-next'); // should return one of: @@ -91,24 +102,24 @@ // * Win32_asio4all // * Linux function determineDeviceType(deviceId, displayName) { - if(operatingSystem == "MacOSX") { - if(displayName.toLowerCase().trim() == "built-in") { + if (operatingSystem == "MacOSX") { + if (displayName.toLowerCase().trim() == "built-in") { return "MacOSX_builtin"; } else { return "MacOSX_interface"; } } - else if(operatingSystem == "Win32") { - if(context.jamClient.FTUEIsMusicDeviceWDM(deviceId)) { - return "Win32_wdm"; - } - else if(displayName.toLowerCase().indexOf("asio4all") > -1) { - return "Win32_asio4all" - } - else { - return "Win32_asio"; - } + else if (operatingSystem == "Win32") { + if (context.jamClient.FTUEIsMusicDeviceWDM(deviceId)) { + return "Win32_wdm"; + } + else if (displayName.toLowerCase().indexOf("asio4all") > -1) { + return "Win32_asio4all" + } + else { + return "Win32_asio"; + } } else { return "Linux"; @@ -122,25 +133,27 @@ var loadedDevices = {}; // augment these devices by determining their type - context._.each(devices, function(displayName, deviceId) { + context._.each(devices, function (displayName, deviceId) { var deviceInfo = {}; deviceInfo.id = deviceId; deviceInfo.type = determineDeviceType(deviceId, displayName); deviceInfo.displayType = audioDeviceBehavior[deviceInfo.type].display; - deviceInfo.displayName = deviceInfo.displayName; + deviceInfo.displayName = displayName; loadedDevices[deviceId] = deviceInfo; + + logger.debug("loaded device: ", deviceInfo); }) - deviceInformation = context._.keys(loadedDevices).sort(); + deviceInformation = loadedDevices; - logger.debug(context.JK.dlen(deviceInformation) + " devices loaded." , deviceInformation); + logger.debug(context.JK.dlen(deviceInformation) + " devices loaded.", deviceInformation); } - // returns a deviceInfo hash for the device matching the deviceId, or null. + // returns a deviceInfo hash for the device matching the deviceId, or undefined. function findDevice(deviceId) { - return {}; + return deviceInformation[deviceId]; } function selectedAudioInput() { @@ -164,22 +177,21 @@ } function initializeNextButtonState() { - console.log(context.jamClient.FTUEGetDevices(false)); - console.log("chat devices", jamClient.FTUEGetChatInputs()); $nextButton.removeClass('button-orange button-grey'); - if(validScore) $nextButton.addClass('button-orange'); + if (validScore) $nextButton.addClass('button-orange'); else $nextButton.addClass('button-grey'); } function initializeAudioInput() { var optionsHtml = ''; optionsHtml = ''; - context._.each(deviceInformation, function(deviceInfo, deviceId) { + context._.each(deviceInformation, function (deviceInfo, deviceId) { + + console.log(arguments) optionsHtml += ''; }); $audioInput.html(optionsHtml); - alert(optionsHtml) context.JK.dropdown($audioInput); initializeAudioInputChanged(); @@ -188,7 +200,7 @@ function initializeAudioOutput() { var optionsHtml = ''; optionsHtml = ''; - context._.each(deviceInformation, function(deviceInfo, deviceId) { + context._.each(deviceInformation, function (deviceInfo, deviceId) { optionsHtml += ''; }); $audioOutput.html(optionsHtml); @@ -198,11 +210,146 @@ } function initializeFramesize() { + context.JK.dropdown($frameSize); + } + function initializeBuffers() { + context.JK.dropdown($bufferIn); + context.JK.dropdown($bufferOut); + } + + // finds out if the $port argument is from a different port pair than what's currently selected + function isNewlySelectedPair($port) { + var portId = $port.attr('data-id'); + // get all inputs currently selected except this one + var $selectedInputs = $inputPorts.find('input[type="checkbox"]:checked').filter('[data-id="' + portId + '"]'); + + console.log("$selectedInputs", $selectedInputs); + var isNewlySelected = true; + context._.each($selectedInputs, function($current) { + var testPairInfo = $($current).data('pair'); + + context._.each(testPairInfo.ports, function(port) { + // if we can find the newly selected item in this pair, then it's not a different pair... + if(port.id == portId) { + isNewlySelected = false; + return false; // break loop + } + }); + + if(isNewlySelected) return false; // break loop + }); + + return isNewlySelected; + } + + // set checkbox state for all items in the pair + function setCheckedForAllInPair($portBox, pairInfo, checked, signalBackend) { + context._.each(pairInfo.ports, function(port) { + var portId = port.id; + var $input = $portBox.find('input[type="checkbox"][data-id="' + portId + '"]'); + if($input.is(':checked') != checked) { + if(checked) { + $input.iCheck('check').attr('checked', 'checked'); + //context.jamClient.FTUESetMusicInput2($input.id); + } + else { + $input.iCheck('uncheck').removeAttr('checked'); + //context.jamClient.FTUEUnsetMusicInput2($input.id); + } + } + }) + } + + function inputPortChanged() { + if(iCheckIgnore) return; + + var $checkbox = $(this); + var portId = $checkbox.data('data-id'); + var inputPortChecked = $checkbox.is(':checked'); + console.log('inputPortChecked: ' + inputPortChecked); + + if(inputPortChecked) { + if(isNewlySelectedPair($checkbox)) { + setCheckedForAllInPair($inputPorts, $checkbox.data('pair'), true, true); + } + else { + //context.jamClient.FTUESetMusicInput2($input.id); + } + } + else { + // context.jamClient.FTUEUnsetMusicInput2($input.id);; + } + } + + // should be called in a ifChanged callback if you want to cancel. bleh. + function cancelICheckChange($checkbox) { + iCheckIgnore = true; + var checked = $checkbox.is(':checked'); + setTimeout(function() { + if(checked) $checkbox.iCheck('uncheck').removeAttr('checked'); + else $checkbox.iCheck('check').attr('checked', 'checked'); + iCheckIgnore = false; + }, 1); + } + + function outputPortChanged() { + if(iCheckIgnore) return; + + var $checkbox = $(this); + var portId = $checkbox.data('data-id'); + var outputPortChecked = $checkbox.is(':checked'); + console.log('outputPortChecked: ' + outputPortChecked); + + if(outputPortChecked) { + var $selectedInputs = $outputPorts.find('input[type="checkbox"]:checked').filter('[data-id="' + portId + '"]'); + $selectedInputs.iCheck('uncheck').removeAttr('checked'); + var pairInfo = $checkbox.data('pair'); + setCheckedForAllInPair($outputPorts, pairInfo, true, false); + console.log("Setting music output"); + context.jamClient.FTUESetMusicOutput(pairInfo.ports.map(function(i) {return i.id}).join(PROFILE_DEV_SEP_TOKEN)); + } + else { + context.JK.Banner.showAlert('You must have at least one output pair selected.'); + // can't allow uncheck of last output + cancelICheckChange($checkbox); + } + } + + function initializeInputPorts(inputPorts) { + context._.each(inputPorts, function(inputPairs) { + // there is no guarantee that a pair has two items. + context._.each(inputPairs.ports, function(inputInPair) { + var inputPort = $(context._.template($templateAudioPort.html(), inputInPair, { variable: 'data' })); + var $checkbox = inputPort.find('input'); + $checkbox.data('pair', inputPairs); // so when it's selected, we can see what other ports, if any, are in the same pair + context.JK.checkbox($checkbox); + $checkbox.on('ifChanged', inputPortChanged); + $inputPorts.append(inputPort); + }); + }); + } + + function initializeOutputPorts(outputPorts) { + var first = true; + context._.each(outputPorts, function(outputPairs) { + context._.each(outputPairs.ports, function(outputInPair) { + var outputPort = $(context._.template($templateAudioPort.html(), outputInPair, { variable: 'data' })); + var $checkbox = outputPort.find('input'); + $checkbox.data('pair', outputPairs); // so when it's selected, we can see what other ports, if any, are in the same pair + context.JK.checkbox($checkbox); + $checkbox.on('ifChanged', outputPortChanged); + $outputPorts.append(outputPort); + }); + if(first) { + first = false; + setCheckedForAllInPair($outputPorts, outputPairs, true, false); + } + }); } function initializeFormElements() { - if(!deviceInformation) throw "devices are not initialized"; + if (!deviceInformation) throw "devices are not initialized"; initializeAudioInput(); initializeAudioOutput(); @@ -225,7 +372,9 @@ } function resetScoreReport() { - $scoreReport.empty(); + $ioRateScore.empty(); + $ioVarScore.empty(); + $latencyScore.empty(); } function updateScoreReport(latencyResult) { @@ -233,9 +382,9 @@ var latencyValue = 'N/A'; var validLatency = false; if (latencyResult && latencyResult.latencyknown) { - var latency = latencyResult.latency; + var latencyValue = latencyResult.latency; latencyValue = Math.round(latencyValue * 100) / 100; - if (latency.latency <= 10) { + if (latencyValue <= 10) { latencyClass = "good"; validLatency = true; } else if (latency.latency <= 20) { @@ -248,57 +397,9 @@ validScore = validLatency; // validScore may become based on IO variance too - $scoreReport.html(latencyValue); + $latencyScore.html(latencyValue + ' ms'); } - function loadAudioDrivers() { - var drivers = context.jamClient.FTUEGetDevices(false); - var chatDrivers = jamClient.FTUEGetChatInputs(); - var optionsHtml = ''; - var chatOptionsHtml = ''; - - - var driverOptionFunc = function (driverKey, index, list) { - if(!drivers[driverKey]) { - logger.debug("skipping unknown device:", driverKey) - } - else { - optionsHtml += ''; - } - }; - - var chatOptionFunc = function (driverKey, index, list) { - chatOptionsHtml += ''; - }; - - var selectors = [ - '[layout-wizard-step="0"] .settings-2-device select', - '[layout-wizard-step="2"] .settings-driver select' - ]; - - // handle standard devices - var sortedDeviceKeys = context._.keys(drivers).sort(); - context._.each(sortedDeviceKeys, driverOptionFunc); - $.each(selectors, function (index, selector) { - var $select = $(selector); - $select.empty(); - $select.html(optionsHtml); - context.JK.dropdown($select); - }); - - selectors = ['[layout-wizard-step="0"] .settings-2-voice select']; - var sortedVoiceDeviceKeys = context._.keys(chatDrivers).sort(); - - // handle voice inputs - context._.each(sortedVoiceDeviceKeys, chatOptionFunc); - $.each(selectors, function (index, selector) { - var $select = $(selector); - $select.empty(); - $select.html(chatOptionsHtml); - context.JK.dropdown($select); - }); - - } function audioInputDeviceUnselected() { validScore = false; initializeNextButtonState(); @@ -362,16 +463,16 @@ } function initializeWatchVideo() { - $watchVideoInput.unbind('click').click(function() { + $watchVideoInput.unbind('click').click(function () { var audioDevice = findDevice(selectedAudioInput()); - if(!audioDevice) { + if (!audioDevice) { context.JK.Banner.showAlert('You must first choose an Audio Input Device so that we can determine which video to show you.'); } else { var videoURL = audioDeviceBehavior[audioDevice.type].videoURL; - if(videoURL) { + if (videoURL) { $(this).attr('href', videoURL); return true; } @@ -383,16 +484,16 @@ return false; }); - $watchVideoOutput.unbind('click').click(function() { + $watchVideoOutput.unbind('click').click(function () { var audioDevice = findDevice(selectedAudioOutput()); - if(!audioDevice) { + if (!audioDevice) { throw "this button should be hidden"; } else { var videoURL = audioDeviceBehavior[audioDevice.type].videoURL; - if(videoURL) { + if (videoURL) { $(this).attr('href', videoURL); return true; } @@ -406,35 +507,52 @@ } function initializeAudioInputChanged() { - $audioInput.unbind('change').change(function(evt) { + $audioInput.unbind('change').change(function (evt) { - var audioDeviceId = selectedAudioInput(); - if(!audioDeviceId) { - audioInputDeviceUnselected(); - return false; - } + var audioDeviceId = selectedAudioInput(); + if (!audioDeviceId) { + audioInputDeviceUnselected(); + return false; + } - var audioDevice = findDevice(selectedAudioInput()); - if(!audioDevice) { - context.JK.alertSupportedNeeded('Unable to find device information for: ' + audioDeviceId); - return false; - } + var audioDevice = findDevice(selectedAudioInput()); + if (!audioDevice) { + context.JK.alertSupportedNeeded('Unable to find device information for: ' + audioDeviceId); + return false; + } - renderScoringStarted(); - jamClient.FTUESetMusicDevice(audioDeviceId); - jamClient.FTUESetInputLatency(selectedAudioInput()); - jamClient.FTUESetOutputLatency(selectedAudioOutput()); - jamClient.FTUESetFrameSize(selectedFramesize()); - logger.debug("Calling FTUESave(false)"); - jamClient.FTUESave(false); + renderScoringStarted(); - var latency = jamClient.FTUEGetExpectedLatency(); - console.log("FTUEGetExpectedLatency: %o", latency); + jamClient.FTUESetMusicDevice(audioDeviceId); - renderScoringStopped(); - }); + // enumerate input and output ports + musicInputPorts = jamClient.FTUEGetMusicInputs2(); + console.log(JSON.stringify(musicInputPorts)); + // [{"inputs":[{"id":"i~5~Built-in Microph~0~0","name":"Built-in Microph - Left"},{"id":"i~5~Built-in Microph~1~0","name":"Built-in Microph - Right"}]}] + musicOutputPorts = jamClient.FTUEGetMusicOutputs2(); + console.log(JSON.stringify(musicOutputPorts)); + // [{"outputs":[{"id":"o~5~Built-in Output~0~0","name":"Built-in Output - Left"},{"id":"o~5~Built-in Output~1~0","name":"Built-in Output - Right"}]}] + + + initializeInputPorts(musicInputPorts); + initializeOutputPorts(musicOutputPorts); + + + jamClient.FTUESetInputLatency(selectedAudioInput()); + jamClient.FTUESetOutputLatency(selectedAudioOutput()); + jamClient.FTUESetFrameSize(selectedFramesize()); + + logger.debug("Calling FTUESave(false)"); + jamClient.FTUESave(false); + + var latency = jamClient.FTUEGetExpectedLatency(); + console.log("FTUEGetExpectedLatency: %o", latency); + + updateScoreReport(latency); + renderScoringStopped(); + }); } function initializeAudioOutputChanged() { @@ -498,7 +616,9 @@ function beforeShowStep($step) { var stepInfo = STEPS[step]; - if(!stepInfo) {throw "unknown step: " + step;} + if (!stepInfo) { + throw "unknown step: " + step; + } stepInfo.beforeShow.call(self); } @@ -511,7 +631,7 @@ $currentWizardStep = $nextWizardStep; var $ftueSteps = $(context._.template($templateSteps.html(), {}, { variable: 'data' })); - var $activeStep = $ftueSteps.find('.ftue-stepnumber[data-step-number="'+ step +'"]'); + var $activeStep = $ftueSteps.find('.ftue-stepnumber[data-step-number="' + step + '"]'); $activeStep.addClass('.active'); $activeStep.next().show(); // show the .ftue-step-title $currentWizardStep.find('.ftuesteps').replaceWith($ftueSteps); @@ -528,11 +648,11 @@ var $btnCancel = $ftueButtonsContent.find('.btn-cancel'); // hide back button if 1st step or last step - if(step == 0 && step == TOTAL_STEPS - 1) { + if (step == 0 && step == TOTAL_STEPS - 1) { $btnBack.hide(); } // hide next button if not on last step - if (step == TOTAL_STEPS - 1 ) { + if (step == TOTAL_STEPS - 1) { $btnNext.hide(); } // hide close if on last step @@ -559,7 +679,7 @@ function beforeShow(args) { step = args.d1; - if(!step) step = 0; + if (!step) step = 0; step = parseInt(step); moveToStep(); } @@ -573,14 +693,14 @@ } function back() { - if($(this).is('.button-grey')) return; + if ($(this).is('.button-grey')) return; step = step - 1; moveToStep(); return false; } function next() { - if($(this).is('.button-grey')) return; + if ($(this).is('.button-grey')) return; step = step + 1; @@ -599,6 +719,7 @@ function route() { } + function initialize() { var dialogBindings = { beforeShow: beforeShow, afterShow: afterShow, afterHide: afterHide }; @@ -609,6 +730,7 @@ $wizardSteps = $dialog.find('.wizard-step'); $templateSteps = $('#template-ftuesteps'); $templateButtons = $('#template-ftue-buttons'); + $templateAudioPort = $('#template-audio-port'); $ftueButtons = $dialog.find('.ftue-buttons'); operatingSystem = context.jamClient.GetOSAsString(); diff --git a/web/app/assets/stylesheets/client/gearWizard.css.scss b/web/app/assets/stylesheets/client/gearWizard.css.scss index 49dc7f34b..f2c635714 100644 --- a/web/app/assets/stylesheets/client/gearWizard.css.scss +++ b/web/app/assets/stylesheets/client/gearWizard.css.scss @@ -184,8 +184,30 @@ width:45%; } + + .buffers { + .easydropdown-wrapper:nth-of-type(1) { + left:5px; + } + .easydropdown-wrapper:nth-of-type(2) { + left:35px; + } + .easydropdown, .easydropdown-wrapper { + width:15px; + } + } + + + .ftue-box.results { height: 230px !important; + padding:0; + + .scoring-section { + font-size:15px; + @include border_box_sizing; + height:64px; + } } .audio-output { @@ -510,8 +532,8 @@ .subcolumn.third { right:0px; } - } + .settings-controls { clear:both; diff --git a/web/app/assets/stylesheets/client/jamkazam.css.scss b/web/app/assets/stylesheets/client/jamkazam.css.scss index e7ec359f0..92d551f31 100644 --- a/web/app/assets/stylesheets/client/jamkazam.css.scss +++ b/web/app/assets/stylesheets/client/jamkazam.css.scss @@ -558,4 +558,9 @@ hr { width:100%; height:20px; text-align:center; +} + +body.jam .icheckbox_minimal { + display:inline-block; + position:relative; } \ No newline at end of file diff --git a/web/app/views/clients/gear/_gear_wizard.html.haml b/web/app/views/clients/gear/_gear_wizard.html.haml index 0ce16062d..fbeffefbd 100644 --- a/web/app/views/clients/gear/_gear_wizard.html.haml +++ b/web/app/views/clients/gear/_gear_wizard.html.haml @@ -83,6 +83,15 @@ .wizard-step-column %h2 Test Results .ftue-box.results + .left.w50.gold-fill.center.white.scoring-section + .p5 + .latency LATENCY + %span.latency-score + .left.w50.green-fill.center.white.scoring-section + .p5 + .io I/O + %span.io-rate-score + %span.io-var-score .clearall @@ -195,5 +204,11 @@ %a.button-orange.btn-next{href:'#'} NEXT %a.button-orange.btn-close{href:'#', 'layout-action' => 'close'} CLOSE +%script{type: 'text/template', id: 'template-audio-port'} + .audio-port + %input{ type: 'checkbox', 'data-id' => '{{data.id}}' } + %span + = '{{data.name}}' + diff --git a/web/app/views/layouts/client.html.erb b/web/app/views/layouts/client.html.erb index 7797d1dd5..2565a4ec7 100644 --- a/web/app/views/layouts/client.html.erb +++ b/web/app/views/layouts/client.html.erb @@ -7,12 +7,14 @@ <%= stylesheet_link_tag "client/client", media: "all" %> diff --git a/web/app/views/layouts/corporate.html.erb b/web/app/views/layouts/corporate.html.erb index 0b973c562..b852f8341 100644 --- a/web/app/views/layouts/corporate.html.erb +++ b/web/app/views/layouts/corporate.html.erb @@ -4,12 +4,14 @@ <%= full_title(yield(:title)) %> diff --git a/web/app/views/layouts/landing.erb b/web/app/views/layouts/landing.erb index 54c6ef95a..d88d06461 100644 --- a/web/app/views/layouts/landing.erb +++ b/web/app/views/layouts/landing.erb @@ -8,12 +8,14 @@ <%= stylesheet_link_tag "landing/landing", media: "all" %> diff --git a/web/app/views/layouts/minimal.html.erb b/web/app/views/layouts/minimal.html.erb index f3cc26096..f29412ae4 100644 --- a/web/app/views/layouts/minimal.html.erb +++ b/web/app/views/layouts/minimal.html.erb @@ -8,12 +8,14 @@ <%= stylesheet_link_tag "minimal/minimal", media: "all" %> diff --git a/web/app/views/layouts/web.html.erb b/web/app/views/layouts/web.html.erb index 532ee9b06..2515ae9da 100644 --- a/web/app/views/layouts/web.html.erb +++ b/web/app/views/layouts/web.html.erb @@ -8,12 +8,14 @@ <%= stylesheet_link_tag "web/web", media: "all" %> From c66f5879cf64e0219c731cd27d59703bb7a0e5f4 Mon Sep 17 00:00:00 2001 From: Jonathan Kolyer Date: Wed, 23 Apr 2014 02:43:13 +0000 Subject: [PATCH 09/14] VRFS-1576 fixed referrals_by_date to support pagination --- ruby/lib/jam_ruby/models/affiliate_partner.rb | 5 ++--- ruby/spec/jam_ruby/models/affiliate_partner_spec.rb | 11 +++++++---- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/ruby/lib/jam_ruby/models/affiliate_partner.rb b/ruby/lib/jam_ruby/models/affiliate_partner.rb index e4ee54517..46906fbde 100644 --- a/ruby/lib/jam_ruby/models/affiliate_partner.rb +++ b/ruby/lib/jam_ruby/models/affiliate_partner.rb @@ -35,10 +35,9 @@ class JamRuby::AffiliatePartner < ActiveRecord::Base def referrals_by_date User.where(:affiliate_referral_id => self.id) .group('DATE(created_at)') + .having("COUNT(*) > 0") + .order('date_created_at DESC') .count - .select { |day,count| 0 != count } - .inject([]) { |rr,kk,vv| rr << kk } - .sort { |a1,a2| a2[0] <=> a1[0] } end end diff --git a/ruby/spec/jam_ruby/models/affiliate_partner_spec.rb b/ruby/spec/jam_ruby/models/affiliate_partner_spec.rb index cf7c1cb91..8470f8cee 100644 --- a/ruby/spec/jam_ruby/models/affiliate_partner_spec.rb +++ b/ruby/spec/jam_ruby/models/affiliate_partner_spec.rb @@ -10,6 +10,7 @@ describe AffiliatePartner do } it 'validates required fields' do + pending expect(partner.referral_user_count).to eq(0) expect(partner.partner_user).to eq(user) user.reload @@ -40,6 +41,7 @@ describe AffiliatePartner do end it 'has user referrals' do + pending expect(AffiliatePartner.coded_id(partner.partner_code)).to eq(partner.id) expect(partner.referral_user_count).to eq(0) uu = FactoryGirl.create(:user) @@ -63,10 +65,11 @@ describe AffiliatePartner do by_date = partner.referrals_by_date expect(by_date.count).to eq(4) - expect(Date.parse(by_date.first.first.to_s)).to eq(Date.parse((Time.now - 2.days).to_s)) - expect(by_date.first.last.to_i).to eq(1) - expect(Date.parse(by_date.last.first.to_s)).to eq(Date.parse((Time.now - 7.days).to_s)) - expect(by_date.last.last.to_i).to eq(2) + keys = by_date.keys + expect(Date.parse(keys.first)).to eq(Date.parse((Time.now - 2.days).to_s)) + expect(by_date[keys.first]).to eq(1) + expect(Date.parse(keys.last)).to eq(Date.parse((Time.now - 7.days).to_s)) + expect(by_date[keys.last]).to eq(2) end end From 7180516e758cd7a3549b8547d648bbc346b8b477 Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Wed, 23 Apr 2014 02:00:55 -0400 Subject: [PATCH 10/14] fix formatting issue in feed where time was indented too far --- web/app/views/users/_feed_music_session_ajax.html.haml | 3 ++- web/app/views/users/_feed_recording_ajax.html.haml | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/web/app/views/users/_feed_music_session_ajax.html.haml b/web/app/views/users/_feed_music_session_ajax.html.haml index 58d32ca4b..51f461f2c 100644 --- a/web/app/views/users/_feed_music_session_ajax.html.haml +++ b/web/app/views/users/_feed_music_session_ajax.html.haml @@ -6,7 +6,8 @@ / type and artist .left.ml20.w15 .title{hoveraction: 'session', :'session-id' => '{{data.feed_item.id}}' } SESSION - %a.artist{href: "#", :hoveraction => '{{data.feed_item.helpers.artist_hoveraction}}', :'{{data.feed_item.helpers.artist_datakey}}' => '{{data.feed_item.helpers.artist_id}}'} + .artist + %a.artist{href: "#", :hoveraction => '{{data.feed_item.helpers.artist_hoveraction}}', :'{{data.feed_item.helpers.artist_datakey}}' => '{{data.feed_item.helpers.artist_id}}'} = '{{data.feed_item.helpers.artist_name}}' %time.small.created_at.timeago{datetime: '{{data.feed_item.helpers.utc_created_at}}'}= '{{data.feed_item.created_at}}' / name and description diff --git a/web/app/views/users/_feed_recording_ajax.html.haml b/web/app/views/users/_feed_recording_ajax.html.haml index 66595e900..ffe584099 100644 --- a/web/app/views/users/_feed_recording_ajax.html.haml +++ b/web/app/views/users/_feed_recording_ajax.html.haml @@ -6,7 +6,8 @@ / type and artist .left.ml20.w15 .title{hoveraction: 'recording', :'recording-id' => '{{data.candidate_claimed_recording.id}}' } RECORDING - %a.artist{href: "#", :hoveraction => '{{data.feed_item.helpers.artist_hoveraction}}', :'{{data.feed_item.helpers.artist_datakey}}' => '{{data.feed_item.helpers.artist_id}}'} + .artist + %a.artist{href: "#", :hoveraction => '{{data.feed_item.helpers.artist_hoveraction}}', :'{{data.feed_item.helpers.artist_datakey}}' => '{{data.feed_item.helpers.artist_id}}'} = '{{data.feed_item.helpers.artist_name}}' %time.small.created_at.timeago{datetime: '{{data.feed_item.helpers.utc_created_at}}'} = '{{data.feed_item.created_at}}' From 22566f1b2989b90e4e3bb14916c2eabd06cd7e25 Mon Sep 17 00:00:00 2001 From: Jonathan Kolyer Date: Wed, 23 Apr 2014 06:34:21 +0000 Subject: [PATCH 11/14] VRFS-1576 added block to referrals_by_date --- ruby/lib/jam_ruby/models/affiliate_partner.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ruby/lib/jam_ruby/models/affiliate_partner.rb b/ruby/lib/jam_ruby/models/affiliate_partner.rb index 46906fbde..6df9dc1a2 100644 --- a/ruby/lib/jam_ruby/models/affiliate_partner.rb +++ b/ruby/lib/jam_ruby/models/affiliate_partner.rb @@ -33,11 +33,12 @@ class JamRuby::AffiliatePartner < ActiveRecord::Base end def referrals_by_date - User.where(:affiliate_referral_id => self.id) + by_date = User.where(:affiliate_referral_id => self.id) .group('DATE(created_at)') .having("COUNT(*) > 0") .order('date_created_at DESC') .count + block_given? ? yield(by_date) : by_date end end From 7b2d124b3325864b048e20d5692d87bf811fda45 Mon Sep 17 00:00:00 2001 From: Jonathan Kolyer Date: Wed, 23 Apr 2014 06:38:49 +0000 Subject: [PATCH 12/14] VRFS-1576 affiliate report view integration --- web/app/assets/images/content/icon_dollar.png | Bin 0 -> 392 bytes .../assets/javascripts/affiliate_report.js | 56 ++++++++++++++++++ .../stylesheets/client/content.css.scss | 2 +- web/app/controllers/api_users_controller.rb | 24 +++++++- .../views/clients/_affiliate_report.html.erb | 36 +++++++++++ web/app/views/clients/index.html.erb | 4 ++ web/app/views/users/_user_dropdown.html.erb | 8 ++- web/config/routes.rb | 1 + web/spec/requests/affilate_referral_spec.rb | 41 +++++++++++++ 9 files changed, 169 insertions(+), 3 deletions(-) create mode 100644 web/app/assets/images/content/icon_dollar.png create mode 100644 web/app/assets/javascripts/affiliate_report.js create mode 100644 web/app/views/clients/_affiliate_report.html.erb create mode 100644 web/spec/requests/affilate_referral_spec.rb diff --git a/web/app/assets/images/content/icon_dollar.png b/web/app/assets/images/content/icon_dollar.png new file mode 100644 index 0000000000000000000000000000000000000000..7d6c1aac2855de8fce895e07a5ebd62b3f0e8c66 GIT binary patch literal 392 zcmV;30eAk1P)bjJV zCc{nt!p@CH1!f(`R4ULrn@EfWIFP?;eEVDi?s<}D;fxo<$r%s6O|Aif26pvC&1~4? zoh%WsiynrpAvfH}`z>_x9hZo}j**oj;A9Tx?y$~PuGATuPEH zr&KWKnrH&{C3)b3LSEccf*>ZqL0^=uq{?Oq*pt2^A*x_+B?3HF29U`XuM&X;wk36E zhn=hOEPR_(fsWSTp6frSR45}BANW9(bhOUXY}`BucDE{_Cv$}5Kzj0min@gsSD8&; m5a+TZ)$|nP{y{dr0t^846Y$`$^ params[:id]) + .includes(:affiliate_partner) + .limit(1) + .first + .affiliate_partner + referrals_by_date = affiliate.referrals_by_date do |by_date| + by_date.inject([]) { |rr, key| rr << key } + end + result = { + :total_count => affiliate.referral_user_count, + :by_date => referrals_by_date + } + render json: result.to_json, status: 200 + rescue + render :json => { :message => $!.to_s }, :status => 400 + end + end + def add_play if params[:id].blank? render :json => { :message => "Playable ID is required" }, :status => 400 diff --git a/web/app/views/clients/_affiliate_report.html.erb b/web/app/views/clients/_affiliate_report.html.erb new file mode 100644 index 000000000..5386d9e31 --- /dev/null +++ b/web/app/views/clients/_affiliate_report.html.erb @@ -0,0 +1,36 @@ + +
+ +
+ +
+ <%= image_tag "content/icon_dollar.png", {:width => 24, :height => 24} %> +
+ +

affiliate report

+ <%= render "screen_navigation" %> +
+ + + +
+
+ AFFILIATE +
+
+ +
+ + + diff --git a/web/app/views/clients/index.html.erb b/web/app/views/clients/index.html.erb index bd37726f2..a573d1758 100644 --- a/web/app/views/clients/index.html.erb +++ b/web/app/views/clients/index.html.erb @@ -38,6 +38,7 @@ <%= render "testBridge" %> <%= render "account" %> <%= render "account_identity" %> +<%= render "affiliate_report" %> <%= render "account_profile" %> <%= render "friendSelector" %> <%= render "account_profile_avatar" %> @@ -182,6 +183,9 @@ var accountIdentityScreen = new JK.AccountIdentityScreen(JK.app); accountIdentityScreen.initialize(); + var affiliateReportScreen = new JK.AffiliateReportScreen(JK.app); + affiliateReportScreen.initialize(); + var accountProfileScreen = new JK.AccountProfileScreen(JK.app); accountProfileScreen.initialize(); diff --git a/web/app/views/users/_user_dropdown.html.erb b/web/app/views/users/_user_dropdown.html.erb index 6cbb97ed0..5504c5b0f 100644 --- a/web/app/views/users/_user_dropdown.html.erb +++ b/web/app/views/users/_user_dropdown.html.erb @@ -20,7 +20,13 @@ <% if current_user && current_user.musician? %> -
  • <%= link_to "Audio Gear", '/client#/account/audio' %>
  • + <% class_val = current_user.affiliate_partner.present? ? 'audio' : 'audio account-menu-group' %> +
  • <%= link_to "Audio Gear", '/client#/account/audio' %>
  • + <% end %> + <% if current_user && current_user.affiliate_partner.present? %> + + <% end %> + <% if current_user && current_user.musician? %>
  • <%= link_to "Band Setup", '/client#/band/setup/new' %>
  • <% end %>
  • <%= link_to "Invite Friends", '#' %> diff --git a/web/config/routes.rb b/web/config/routes.rb index b225e907f..dd94a2ce8 100644 --- a/web/config/routes.rb +++ b/web/config/routes.rb @@ -267,6 +267,7 @@ SampleApp::Application.routes.draw do # match '/users/:id/recordings/:recording_id' => 'api_users#recording_destroy', :via => :delete match '/users/:id/plays' => 'api_users#add_play', :via => :post, :as => 'api_users_add_play' + match '/users/:id/affiliate' => 'api_users#affiliate_report', :via => :get, :as => 'api_users_affiliate' # bands match '/bands' => 'api_bands#index', :via => :get diff --git a/web/spec/requests/affilate_referral_spec.rb b/web/spec/requests/affilate_referral_spec.rb new file mode 100644 index 000000000..7a61f8ec4 --- /dev/null +++ b/web/spec/requests/affilate_referral_spec.rb @@ -0,0 +1,41 @@ +require 'spec_helper' + +describe "Affiliate Reports", :type => :api do + + include Rack::Test::Methods + + let!(:user) { FactoryGirl.create(:user) } + let!(:partner) { + AffiliatePartner.create_with_params({:partner_name => Faker::Company.name, + :partner_code => Faker::Lorem.words[0], + :user_email => user.email}) + } + + it "valid score" do + FactoryGirl.create(:user, :created_at => Time.now - 5.days, :affiliate_referral_id => partner.id) + FactoryGirl.create(:user, :created_at => Time.now - 6.days, :affiliate_referral_id => partner.id) + FactoryGirl.create(:user, :created_at => Time.now - 6.days, :affiliate_referral_id => partner.id) + FactoryGirl.create(:user, :created_at => Time.now - 7.days, :affiliate_referral_id => partner.id) + FactoryGirl.create(:user, :created_at => Time.now - 7.days, :affiliate_referral_id => partner.id) + FactoryGirl.create(:user, :created_at => Time.now - 7.days, :affiliate_referral_id => partner.id) + FactoryGirl.create(:user, :created_at => Time.now - 7.days, :affiliate_referral_id => partner.id) + + post('/api/auth_session.json', + { :email => user.email, :password => user.password }.to_json, + "CONTENT_TYPE" => 'application/json') + last_response.status.should == 200 + expect(JSON.parse(last_response.body)).to eq({ "success" => true }) + + get "/api/users/#{user.id}/affiliate" + + expect(last_response.status).to eq(200) + json = JSON.parse(last_response.body) + + expect(json['total_count']).to eq(7) + by_date = json['by_date'] + expect(by_date.count).to eq(3) + expect(by_date.first.last).to eq(1) + expect(by_date.last.last).to eq(4) + end + +end From a7d83064df27d97b7bba9ed81379e30e949a48c5 Mon Sep 17 00:00:00 2001 From: Jonathan Kolyer Date: Wed, 23 Apr 2014 06:39:49 +0000 Subject: [PATCH 13/14] VRFS-1576 fixing redirect paths to use active_admin_template --- admin/Gemfile | 4 ++++ admin/app/admin/affiliates.rb | 3 ++- admin/app/admin/email_batch.rb | 6 ++++-- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/admin/Gemfile b/admin/Gemfile index c8b1d1772..8a47660de 100644 --- a/admin/Gemfile +++ b/admin/Gemfile @@ -116,3 +116,7 @@ group :test do gem 'simplecov-rcov' end +gem 'pry' +gem 'pry-remote' +gem 'pry-stack_explorer' +gem 'pry-debugger' diff --git a/admin/app/admin/affiliates.rb b/admin/app/admin/affiliates.rb index d0e7e5466..e517b3e12 100644 --- a/admin/app/admin/affiliates.rb +++ b/admin/app/admin/affiliates.rb @@ -41,7 +41,8 @@ ActiveAdmin.register JamRuby::AffiliatePartner, :as => 'Affiliates' do obj.partner_name = vals[:partner_name] obj.user_email = vals[:user_email] if vals[:user_email].present? obj.save! - redirect_to admin_affiliates_path + set_resource_ivar(obj) + render active_admin_template('show') end end diff --git a/admin/app/admin/email_batch.rb b/admin/app/admin/email_batch.rb index d074fd0d4..e5743eeb8 100644 --- a/admin/app/admin/email_batch.rb +++ b/admin/app/admin/email_batch.rb @@ -97,12 +97,14 @@ ActiveAdmin.register JamRuby::EmailBatch, :as => 'Batch Emails' do def create batch = EmailBatch.create_with_params(params[:jam_ruby_email_batch]) - redirect_to admin_batch_email_path(batch.id) + set_resource_ivar(batch) + render active_admin_template('show') end def update resource.update_with_conflict_validation(params[:jam_ruby_email_batch]) - redirect_to admin_batch_email_path(resource.id) + set_resource_ivar(resource) + render active_admin_template('show') end end From 55b149827adafe0de4139026676ab5d01c538dfa Mon Sep 17 00:00:00 2001 From: Jonathan Kolyer Date: Wed, 23 Apr 2014 07:43:35 +0000 Subject: [PATCH 14/14] VRFS-1576 report layout --- web/app/assets/javascripts/affiliate_report.js | 17 +++++++++++++---- .../views/clients/_affiliate_report.html.erb | 9 +++++++-- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/web/app/assets/javascripts/affiliate_report.js b/web/app/assets/javascripts/affiliate_report.js index d20d208ed..662611131 100644 --- a/web/app/assets/javascripts/affiliate_report.js +++ b/web/app/assets/javascripts/affiliate_report.js @@ -17,15 +17,24 @@ function populateAffiliateReport(report) { console.log(report); - /*var template = context.JK.fillTemplate($('#template-account-affiliate').html(), { - email: userDetail.email - });*/ + var by_date = ''; + var ii=0, dates_len = report['by_date'].length; + for (var ii=0; ii < dates_len; ii += 1) { + var dd = report['by_date'][ii]; + by_date += '
    '+dd[0]+'
    '; + by_date += '
    '+dd[1].toString()+'
    '; + by_date += '
    '; + } + var template = context.JK.fillTemplate($('#template-account-affiliate').html(), { + total_count: report['total_count'], + by_date: by_date + }); + $('#account-affiliate-content-scroller').html(template); } /****************** MAIN PORTION OF SCREEN *****************/ // events for main screen function events() { - //$('#account-identity-content-scroller').on('click', '#account-edit-email-cancel', function(evt) { evt.stopPropagation(); navToAccount(); return false; } ); } function renderAffiliateReport() { diff --git a/web/app/views/clients/_affiliate_report.html.erb b/web/app/views/clients/_affiliate_report.html.erb index 5386d9e31..46d04308a 100644 --- a/web/app/views/clients/_affiliate_report.html.erb +++ b/web/app/views/clients/_affiliate_report.html.erb @@ -15,7 +15,6 @@
    - AFFILIATE
    @@ -26,7 +25,13 @@