diff --git a/ruby/Gemfile b/ruby/Gemfile index cd4bca5ec..b9ebfbded 100644 --- a/ruby/Gemfile +++ b/ruby/Gemfile @@ -29,7 +29,7 @@ gem 'will_paginate' gem 'actionmailer', '3.2.13' gem 'sendgrid', '1.2.0' gem 'aws-sdk', '1.29.1' -gem 'carrierwave' +gem 'carrierwave', '0.9.0' gem 'aasm', '3.0.16' gem 'devise', '>= 1.1.2' gem 'postgres-copy' diff --git a/ruby/lib/jam_ruby/models/email_batch.rb b/ruby/lib/jam_ruby/models/email_batch.rb index a7e2ae9df..0d59a187e 100644 --- a/ruby/lib/jam_ruby/models/email_batch.rb +++ b/ruby/lib/jam_ruby/models/email_batch.rb @@ -70,7 +70,6 @@ FOO User.email_opt_in.find_in_batches(batch_size: 1000) do |users| self.email_batch_sets << EmailBatchSet.deliver_set(self, users.map(&:id)) # BatchMailer.send_batch_email(self.id, users.map(&:id)).deliver - end end def test_count diff --git a/ruby/lib/jam_ruby/models/music_session.rb b/ruby/lib/jam_ruby/models/music_session.rb index 899f738fe..5a1090b28 100644 --- a/ruby/lib/jam_ruby/models/music_session.rb +++ b/ruby/lib/jam_ruby/models/music_session.rb @@ -270,6 +270,8 @@ module JamRuby query = query.where( %Q{ musician_access = true + OR + music_sessions.user_id = '#{current_user.id}' OR invitations.id IS NOT NULL } diff --git a/ruby/spec/mailers/batch_mailer_spec.rb b/ruby/spec/mailers/batch_mailer_spec.rb index 688e3a481..62bdb7d9a 100644 --- a/ruby/spec/mailers/batch_mailer_spec.rb +++ b/ruby/spec/mailers/batch_mailer_spec.rb @@ -7,7 +7,6 @@ describe BatchMailer do batch = FactoryGirl.create(:email_batch) batch.send_test_batch - sleep(3) batch.email_batch_sets.count.should == 1 diff --git a/web/Gemfile b/web/Gemfile index f2cdab689..27471d0a7 100644 --- a/web/Gemfile +++ b/web/Gemfile @@ -22,7 +22,7 @@ end gem 'oj' gem 'builder' gem 'rails', '~>3.2.11' -gem 'jquery-rails', '2.0.2' +gem 'jquery-rails' gem 'jquery-ui-rails' gem 'bootstrap-sass', '2.0.4' gem 'bcrypt-ruby', '3.0.1' @@ -50,7 +50,7 @@ gem 'recaptcha', '0.3.4' gem 'filepicker-rails', '0.1.0' gem 'aws-sdk', '1.29.1' gem 'aasm', '3.0.16' -gem 'carrierwave' +gem 'carrierwave', '0.9.0' gem 'carrierwave_direct' gem 'fog' gem 'haml-rails' @@ -68,6 +68,9 @@ gem 'resque-failed-job-mailer' gem 'resque-dynamic-queues' gem 'resque-lonely_job', '~> 1.0.0' gem 'resque_mailer' +#gem 'typescript-src', path: '../../typescript-src-ruby' +#gem 'typescript-node', path: '../../typescript-node-ruby' +#gem 'typescript-rails', path: '../../typescript-rails' gem 'quiet_assets', :group => :development gem 'bugsnag' diff --git a/web/app/assets/javascripts/bandProfile.js b/web/app/assets/javascripts/bandProfile.js index 2fc6a68b6..dbd840463 100644 --- a/web/app/assets/javascripts/bandProfile.js +++ b/web/app/assets/javascripts/bandProfile.js @@ -41,7 +41,7 @@ $('#band-profile-social').hide(); $('.band-profile-nav a.active').removeClass('active'); - $('.band-profile-nav a.#band-profile-about-link').addClass('active'); + $('.band-profile-nav a#band-profile-about-link').addClass('active'); } /****************** MAIN PORTION OF SCREEN *****************/ @@ -170,7 +170,7 @@ $('#band-profile-social').hide(); $('.band-profile-nav a.active').removeClass('active'); - $('.band-profile-nav a.#band-profile-about-link').addClass('active'); + $('.band-profile-nav a#band-profile-about-link').addClass('active'); bindAbout(); } diff --git a/web/app/assets/javascripts/findSession.js b/web/app/assets/javascripts/findSession.js index a684081cb..11001f3e3 100644 --- a/web/app/assets/javascripts/findSession.js +++ b/web/app/assets/javascripts/findSession.js @@ -36,13 +36,13 @@ } function removeSpinner() { - $('') + $('div[layout-id=findSession] .content').append('
') } function loadSessionsOriginal() { diff --git a/web/app/assets/javascripts/ftue.js b/web/app/assets/javascripts/ftue.js index 698a3995d..a82b8885e 100644 --- a/web/app/assets/javascripts/ftue.js +++ b/web/app/assets/javascripts/ftue.js @@ -497,7 +497,7 @@ * Load available drivers and populate the driver select box. */ function loadAudioDrivers() { - var drivers = jamClient.FTUEGetDevices(false); + var drivers = context.jamClient.FTUEGetDevices(false); var chatDrivers = jamClient.FTUEGetChatInputs(); var optionsHtml = ''; var chatOptionsHtml = ''; diff --git a/web/app/assets/javascripts/gear_wizard.js b/web/app/assets/javascripts/gear_wizard.js new file mode 100644 index 000000000..d77dfe0c0 --- /dev/null +++ b/web/app/assets/javascripts/gear_wizard.js @@ -0,0 +1,82 @@ +(function (context, $) { + + "use strict"; + + + context.JK = context.JK || {}; + context.JK.GearWizard = function (app) { + + var $dialog = null; + var $wizardSteps = null; + var $currentWizardStep = null; + var step = 0; + + function moveToStep() { + var $nextWizardStep = $wizardSteps.filter($('[layout-wizard-step=' + step + ']')); + + $wizardSteps.hide(); + + $currentWizardStep = $nextWizardStep; + $currentWizardStep.show(); + } + + function reset() { + $currentWizardStep = null; + } + + function beforeShow(args) { + step = args.d1; + if(!step) step = 0; + + + moveToStep(); + } + + function afterShow() { + + } + + function afterHide() { + + } + + function back() { + var currentStep = parseInt($(this).closest('.wizard-step').attr('layout-wizard-step')); + step = currentStep - 1; + moveToStep(); + return false; + } + + function next() { + var currentStep = parseInt($(this).closest('.wizard-step').attr('layout-wizard-step')); + step = currentStep + 1; + moveToStep(); + return false; + } + + function events() { + $('.btn-next').on('click', next); + $('.btn-back').on('click', back); + } + + function route() { + + } + function initialize() { + + var dialogBindings = { beforeShow: beforeShow, afterShow: afterShow, afterHide: afterHide }; + + app.bindDialog('gear-wizard', dialogBindings); + + $dialog = $('#gear-wizard-dialog'); + $wizardSteps = $dialog.find('.wizard-step'); + + events(); + } + + this.initialize = initialize; + + return this; + }; + +})(window, jQuery); \ No newline at end of file diff --git a/web/app/assets/javascripts/jquery.listenRecording.js b/web/app/assets/javascripts/jquery.listenRecording.js index 6bd55e648..84a7628f7 100644 --- a/web/app/assets/javascripts/jquery.listenRecording.js +++ b/web/app/assets/javascripts/jquery.listenRecording.js @@ -52,7 +52,7 @@ else { audioDomElement.play(); audioDomElement.pause(); - //loaded.resolve(); + //loaded.resolve(); // will be resolved by 'canplay' even } } diff --git a/web/app/assets/javascripts/layout.js b/web/app/assets/javascripts/layout.js index 555cc0d6d..0d4ec3dbe 100644 --- a/web/app/assets/javascripts/layout.js +++ b/web/app/assets/javascripts/layout.js @@ -552,6 +552,19 @@ } } + // payload is a notification event from websocket gateway + function isNoisyNotification(payload) { + var openDialog = currentDialog(); + if(!openDialog) return false; + + if(typeof openDialog.isNoisyNotification === 'function') { + return !openDialog.isNoisyNotification(payload); + } + else { + return true; + } + } + /** * Responsible for keeping N dialogs in correct stacked order, * also moves the .dialog-overlay such that it hides/obscures all dialogs except the highest one @@ -875,8 +888,12 @@ showDialog(dialog, options); }; - this.dialogObscuredNotification = function() { - return dialogObscuredNotification(); + this.dialogObscuredNotification = function(payload) { + return dialogObscuredNotification(payload); + } + + this.isNoisyNotification= function(payload) { + return isNoisyNotification(payload); } this.isDialogShowing = function() { diff --git a/web/app/assets/javascripts/notificationPanel.js b/web/app/assets/javascripts/notificationPanel.js index 90e9d5d5c..9e183324b 100644 --- a/web/app/assets/javascripts/notificationPanel.js +++ b/web/app/assets/javascripts/notificationPanel.js @@ -52,7 +52,7 @@ $count.addClass('highlighted'); } - function queueNotificationSeen(notificationId, notificationCreatedAt) { + function queueNotificationSeen(notificationId, notificationCreatedAt, type) { var time = new Date(notificationCreatedAt); @@ -80,10 +80,17 @@ app.updateNotificationSeen(payload.notification_id, payload.created_at); } else { - queueNotificationSeen(payload.notification_id, payload.created_at); - highlightCount(); - incrementNotificationCount(); - missedNotificationsWhileAway = true; + if(app.layout.isNoisyNotification(payload) && !missedNotificationsWhileAway) { + // this handles a special case--if a notification is too noisy while away, then don't bother + // incrementing anything on the sidebar or otherwise distracting the user + app.updateNotificationSeen(payload.notification_id, payload.created_at); + } + else { + queueNotificationSeen(payload.notification_id, payload.created_at, payload.description); + highlightCount(); + incrementNotificationCount(); + missedNotificationsWhileAway = true; + } } } diff --git a/web/app/assets/javascripts/searchResults.js b/web/app/assets/javascripts/searchResults.js index 975da29e3..7cb7a0f9d 100644 --- a/web/app/assets/javascripts/searchResults.js +++ b/web/app/assets/javascripts/searchResults.js @@ -67,8 +67,8 @@ function resultDivVisibility(val, isSidebar) { if (isSidebar) { - $('div[layout=sidebar user-id=' + val.id + '].sidebar-search-connected').hide(); - $('div[layout=sidebar user-id=' + val.id + '].sidebar-search-result').show(); + $('div[layout="sidebar"][user-id="' + val.id + '"].sidebar-search-connected').hide(); + $('div[layout="sidebar"][user-id="' + val.id + '"].sidebar-search-result').show(); } else { $('div[user-id=' + val.id + '].search-connected').hide(); @@ -202,8 +202,8 @@ function friendRequestCallbackSidebar(userId) { // toggle the pre-click and post-click divs - $('div[layout=sidebar] div[user-id=' + userId + '].sidebar-search-connected').show(); - $('div[layout=sidebar] div[user-id=' + userId + '].sidebar-search-result').hide(); + $('div[layout=sidebar] div[user-id="' + userId + '"].sidebar-search-connected').show(); + $('div[layout=sidebar] div[user-id="' + userId + '"].sidebar-search-result').hide(); } function friendRequestCallbackSearchResults(userId) { diff --git a/web/app/assets/javascripts/sessionList.js b/web/app/assets/javascripts/sessionList.js index 81dfc77b3..37539b3b0 100644 --- a/web/app/assets/javascripts/sessionList.js +++ b/web/app/assets/javascripts/sessionList.js @@ -190,7 +190,10 @@ openTerms(sessionId); } else { - if (session.musician_access) { + if(session.user_id == JK.currentUserId) { + openTerms(sessionId); + } + else if (session.musician_access) { if (session.approval_required) { openAlert(sessionId); } diff --git a/web/app/assets/javascripts/textMessageDialog.js b/web/app/assets/javascripts/textMessageDialog.js index 3bcc2c5c2..3e3049880 100644 --- a/web/app/assets/javascripts/textMessageDialog.js +++ b/web/app/assets/javascripts/textMessageDialog.js @@ -128,6 +128,10 @@ return showing && payload.description == "TEXT_MESSAGE" && payload.sender_id == otherId; } + function isNoisyNotification(payload) { + return handledNotification(payload); + } + function afterShow(args) { $textBox.focus(); } diff --git a/web/app/assets/stylesheets/client/client.css b/web/app/assets/stylesheets/client/client.css index e69b9848b..acdbd914a 100644 --- a/web/app/assets/stylesheets/client/client.css +++ b/web/app/assets/stylesheets/client/client.css @@ -33,6 +33,7 @@ *= require ./account *= require ./search *= require ./ftue + *= require ./gearWizard *= require ./whatsNextDialog *= require ./invitationDialog *= require ./shareDialog diff --git a/web/app/assets/stylesheets/client/gearWizard.css.scss b/web/app/assets/stylesheets/client/gearWizard.css.scss new file mode 100644 index 000000000..f6c469d7f --- /dev/null +++ b/web/app/assets/stylesheets/client/gearWizard.css.scss @@ -0,0 +1,368 @@ +/* Custom Styles for the FTUE Dialogs */ + +@import "client/common.css.scss"; +@charset "UTF-8"; + + +.dialog.gear-wizard { + min-width: 800px; + max-width: 800px; + min-height: 400px; + max-height: 400px; + + .ftue-inner { + line-height: 1.3em; + width:750px; + padding:25px; + font-size:15px; + color:#aaa; + + .wizard-step { + display:none; + } + + a { + text-decoration: underline; + } + + p { + margin-top: 12px; + } + + .device_type ul { + list-style:disc; + } + + .device_type li { + margin: 15px 12px 15px 36px; + } + + select { + max-width: 220px; + } + + .settings-profile { + margin-top: 12px; + } + + p.intro { + margin-top:0px; + } + + .easydropdown-wrapper { + width:100%; + max-width:220px; + } + .ftue-new { + clear:both; + position:relative; + width:100%; + height: 54px; + margin-top: 12px; + select { + font-size: 15px; + padding: 3px; + } + .latency { + position: absolute; + top: 120px; + font-size: 12px; + .report { + color:#fff; + position: absolute; + top: 20px; + left: 0px; + width: 105px; + height: 50px; + background-color: #72a43b; + padding: 10px; + text-align: center; + .ms-label { + padding-top: 10px; + font-size: 34px; + font-family: Arial, sans-serif; + } + p { + margin-top: 4px; + } + } + .report.neutral, .report.start, .report.unknown { + background-color: #666; + } + .report.good { + background-color: #72a43b; + } + .report.acceptable { + background-color: #D6A800; + } + .report.bad { + background-color: #7B0C00; + } + .instructions { + color:#fff; + position: absolute; + top: 20px; + left: 125px; + width: 595px; + height: 50px; + padding: 10px; + background-color: #666; + } + .instructions p.start, .instructions p.neutral { + padding-top: 4px; + } + .instructions p.unknown { + margin-top:0px; + padding-top: 4px; + } + .instructions p.good { + padding-top: 4px; + } + .instructions p.acceptable { + margin-top: -6px; + } + .instructions p.bad { + margin-top: -6px; + line-height: 16px; + } + .instructions p a { + font-weight: bold; + } + } + .column { + position:absolute; + width: 220px; + height: 50px; + margin-right:8px; + } + .settings-2-device { + left:0px; + } + .settings-2-center { + left:50%; + margin-left: -110px; + .buttons { + margin-top: 14px; + a { + margin-right: 0px; + } + } + } + .settings-2-voice { + top: 0px; + right:0px; + } + .controls { + margin-top: 16px; + background-color: #222; + height: 48px; + width: 220px; + } + .ftue-vu-left { + position:relative; + top: 0px; + } + .ftue-vu-right { + position:relative; + top: 22px; + } + .ftue-fader { + position:relative; + top: 14px; + left: 8px; + } + .gain-label { + color: $ColorScreenPrimary; + position:absolute; + top: 76px; + right: 6px; + } + + .subcolumn { + position:absolute; + top: 60px; + font-size: 12px !important; + width: 68px; + height: 48px; + } + .subcolumn select { + width: 68px; + } + .subcolumn.first { + left:0px; + } + .subcolumn.second { + left:50%; + margin-left:-34px; + } + .subcolumn.third { + right:0px; + } + } + + .asio-settings { + clear:both; + position:relative; + width:100%; + height: 54px; + margin-top: 8px; + .column { + position:absolute; + width: 220px; + height: 50px; + margin-right:8px; + } + .settings-driver { + left:0px; + } + .settings-asio { + left:50%; + margin-left: -110px; + } + .settings-asio.mac { + left:0px; + margin-left: 0px; + } + .settings-asio-button { + right:0px; + height: 45px; + .bottom { + position:absolute; + bottom:0px; + } + } + .settings-asio-button.mac { + right:auto; + left:50%; + margin-left: -110px; + } + .subcolumn { + position:absolute; + width: 68px; + height: 48px; + } + .subcolumn select { + width: 68px; + } + .subcolumn.first { + left:0px; + } + .subcolumn.second { + left:50%; + margin-left:-34px; + } + .subcolumn.third { + right:0px; + } + + } + .settings-controls { + + clear:both; + position:relative; + width: 100%; + height: 100px; + + div.section { + position:absolute; + width: 220px; + height: 100px; + + select { + display:block; + width: 100%; + } + } + .audio-input { + left:0px; + } + .voice-chat-input { + left:50%; + margin-left: -110px; + } + .audio-output { + right:0px; + } + .ftue-controls { + margin-top: 16px; + position:relative; + height: 48px; + width: 220px; + background-color: #222; + } + .ftue-vu-left { + position:relative; + top: 0px; + } + .ftue-vu-right { + position:relative; + top: 22px; + } + .ftue-fader { + position:relative; + top: 14px; + left: 8px; + } + .gain-label { + color: $ColorScreenPrimary; + position:absolute; + top: 14px; + right: 6px; + } + } + + .buttonbar { + position:absolute; + bottom: 24px; + right: 0px; + a { + color: darken(#fff, 5); + text-decoration: none; + } + + .spinner-small { + display:none; + margin-top: 3px; + position: relative; + top: 12px; + } + } + + input[type=text], input[type=password] { + padding:3px; + font-size:13px; + width:145px; + } + + select.audiodropdown { + width:223px; + color:#666; + } + + a { + color:#ccc; + } + + a:hover { + color:#fff; + } + + .ftue-instrumentlist { + width:340px; + height:178px; + background-color:#c5c5c5; + border:none; + -webkit-box-shadow: inset 2px 2px 3px 0px #888; + box-shadow: inset 2px 2px 3px 0px #888; + color:#666; + overflow:auto; + font-size:14px; + } + + .ftue-instrumentlist select, .ftue-instrumentlist .easydropdown { + width:100%; + color:#666; + } + + } +} \ No newline at end of file diff --git a/web/app/assets/stylesheets/minimal/minimal.css.scss b/web/app/assets/stylesheets/minimal/minimal.css.scss new file mode 100644 index 000000000..ad673a435 --- /dev/null +++ b/web/app/assets/stylesheets/minimal/minimal.css.scss @@ -0,0 +1,8 @@ +/** +*= require client/ie +*= require client/jamkazam +*= require client/screen_common +*= require client/content +*= require client/ftue +*= require minimal/minimial_main +*/ \ No newline at end of file diff --git a/web/app/assets/stylesheets/minimal/minimal_main.css.scss b/web/app/assets/stylesheets/minimal/minimal_main.css.scss new file mode 100644 index 000000000..5a170e128 --- /dev/null +++ b/web/app/assets/stylesheets/minimal/minimal_main.css.scss @@ -0,0 +1,11 @@ +html { + height:100%; +} + +body { + //position:absolute !important; + padding:0 !important; + overflow: visible !important; + height:100%; + margin:0 !important; +} diff --git a/web/app/controllers/videos_controller.rb b/web/app/controllers/videos_controller.rb new file mode 100644 index 000000000..a63343776 --- /dev/null +++ b/web/app/controllers/videos_controller.rb @@ -0,0 +1,8 @@ + +class VideosController < ApplicationController + + def show_dialog + @video_id = @params[:video_id] + end + +end \ No newline at end of file diff --git a/web/app/views/clients/_account_identity.html.erb b/web/app/views/clients/_account_identity.html.erb index 439ae6138..9b8866b96 100644 --- a/web/app/views/clients/_account_identity.html.erb +++ b/web/app/views/clients/_account_identity.html.erb @@ -74,6 +74,7 @@ +
diff --git a/web/app/views/clients/gear/_buttons.html.haml b/web/app/views/clients/gear/_buttons.html.haml new file mode 100644 index 000000000..3e547d4b0 --- /dev/null +++ b/web/app/views/clients/gear/_buttons.html.haml @@ -0,0 +1,16 @@ + +- show_back ||= local_assigns[:show_back] = local_assigns.fetch(:show_back, true) +- show_next ||= local_assigns[:show_next] = local_assigns.fetch(:show_next, true) + +- total_steps = 7 + +.buttons + - if step > 0 && step != total_steps + %a.button-orange.btn-back{href:'#'} BACK + - if step != total_steps + %a.button-orange.btn-next{href:'#'} NEXT + - if step == total_steps + %a.button-orange.btn-close{href:'#', 'layout-action' => 'close'} CLOSE + + + diff --git a/web/app/views/clients/gear/_gear_wizard.html.haml b/web/app/views/clients/gear/_gear_wizard.html.haml new file mode 100644 index 000000000..07998175a --- /dev/null +++ b/web/app/views/clients/gear/_gear_wizard.html.haml @@ -0,0 +1,43 @@ +.dialog.gear-wizard{ layout: 'dialog', 'layout-id' => 'gear-wizard', id: 'gear-wizard-dialog'} + .content-head + %h1 audio gear setup + + .ftue-inner{ 'layout-wizard' => 'gear-wizard' } + .wizard-step{ 'layout-wizard-step' => "0", 'dialog-title' => "Understand Your Gear", 'dialog-purpose' => "Intro"} + read this + + = render :partial => "clients/gear/buttons", locals: { step: 0 } + + .wizard-step{ 'layout-wizard-step' => "1", 'dialog-title' => "Select & Test Audio Gear", 'dialog-purpose' => "SelectAudioGear" } + select audio gear + + = render :partial => "clients/gear/buttons", locals: { step: 1 } + + .wizard-step{ 'layout-wizard-step' => "2", 'dialog-title' => "Configure Tracks", 'dialog-purpose' => "ConfigureTracks" } + configure tracks + + = render :partial => "clients/gear/buttons", locals: { step: 2 } + + .wizard-step{ 'layout-wizard-step' => "3", 'dialog-title' => "Configure Voice Chat", 'dialog-purpose' => "ConfigureVoiceChat" } + configure voice chat + + = render :partial => "clients/gear/buttons", locals: { step: 3 } + + .wizard-step{ 'layout-wizard-step' => "4", 'dialog-title' => "Turn Off Direct Monitoring", 'dialog-purpose' => "DirectMonitoring" } + turn off direct monitoring + + = render :partial => "clients/gear/buttons", locals: { step: 4 } + + .wizard-step{ 'layout-wizard-step' => "5", 'dialog-title' => "Test Router & Network", 'dialog-purpose' => "TestRouterNetwork" } + test router network + + = render :partial => "clients/gear/buttons", locals: { step: 5 } + + .wizard-step{ 'layout-wizard-step' => "6", 'dialog-title' => "Success!", 'dialog-purpose' => "Success" } + success! + + = render :partial => "clients/gear/buttons", locals: { step: 6 } + + + + diff --git a/web/app/views/clients/index.html.erb b/web/app/views/clients/index.html.erb index be7ba434c..e3e56221c 100644 --- a/web/app/views/clients/index.html.erb +++ b/web/app/views/clients/index.html.erb @@ -14,6 +14,7 @@ <%= render "faders" %> <%= render "vu_meters" %> <%= render "ftue" %> +<%= render "clients/gear/gear_wizard" %> <%= render "terms" %> <%= render "leaveSessionWarning" %> <%= render "alert" %> @@ -235,6 +236,9 @@ var ftueWizard = new JK.FtueWizard(JK.app); ftueWizard.initialize(); + var gearWizard = new JK.GearWizard(JK.app); + gearWizard.initialize(); + var testBridgeScreen = new JK.TestBridgeScreen(JK.app); testBridgeScreen.initialize(); @@ -263,10 +267,15 @@ interceptedJamClient[jsKey] = function() { var original = originalJamClient[key] var start = new Date(); - var returnVal = original.apply(originalJamClient, arguments) + if(key == "FTUEGetDevices()") { + var returnVal = eval('originalJamClient.FTUEGetDevices(' + arguments[0] + ')'); + } + else { + var returnVal = original.apply(originalJamClient, arguments); + } var time = new Date().getTime() - start.getTime(); - if(time > 0) { // if 0, you'll see ALL bridge calls. If you set it to a higher value, you'll only see calls that are beyond that threshold - console.error(time + "ms jamClient." + jsKey); + if(time >= 0) { // if 0, you'll see ALL bridge calls. If you set it to a higher value, you'll only see calls that are beyond that threshold + console.error(time + "ms jamClient." + jsKey + ' returns=', returnVal); } return returnVal; diff --git a/web/app/views/layouts/minimal.html.erb b/web/app/views/layouts/minimal.html.erb new file mode 100644 index 000000000..e0f490bab --- /dev/null +++ b/web/app/views/layouts/minimal.html.erb @@ -0,0 +1,60 @@ + + + + <%= full_title(yield(:title)) %> + + + + + + <%= stylesheet_link_tag "minimal/minimal", media: "all" %> + <% if bugsnag? %> + + + <% end %> + <%= include_gon(:init => true) %> + <%= csrf_meta_tags %> + <% if content_for?(:social_meta) %> + <%= yield(:social_meta) %> + <% else %> + <%= render "layouts/social_meta" %> + <% end %> + + +
+ <%= javascript_include_tag "minimal/minimal" %> + <%= yield %> +
+ + + + <%= render "shared/ga" %> + + + +c \ No newline at end of file diff --git a/web/app/views/videos/show_dialog.html.haml b/web/app/views/videos/show_dialog.html.haml new file mode 100644 index 000000000..e69de29bb diff --git a/web/config/application.rb b/web/config/application.rb index 5f1e18959..5175e0e1d 100644 --- a/web/config/application.rb +++ b/web/config/application.rb @@ -83,6 +83,7 @@ if defined?(Bundler) config.assets.precompile += %w( landing/landing.js landing/landing.css ) config.assets.precompile += %w( corp/corporate.js corp/corporate.css ) config.assets.precompile += %w( web/web.js web/web.css ) + config.assets.precompile += %w( minimal/minimal.js minimal/minimal.css ) # where is rabbitmq? diff --git a/web/config/routes.rb b/web/config/routes.rb index 9f95134a5..7408b0f1e 100644 --- a/web/config/routes.rb +++ b/web/config/routes.rb @@ -63,6 +63,8 @@ SampleApp::Application.routes.draw do match '/events/:slug', to: 'events#show', :via => :get, :as => 'event' + match '/video/dialog/:id', to: 'videos#show', :via => :get + # temporarily allow for debugging--only allows admini n match '/listen_in', to: 'spikes#listen_in' diff --git a/web/spec/features/feed_spec.rb b/web/spec/features/feed_spec.rb index 49c98b9d0..343d26bb7 100644 --- a/web/spec/features/feed_spec.rb +++ b/web/spec/features/feed_spec.rb @@ -3,12 +3,17 @@ require 'spec_helper' describe "Feed", :js => true, :type => :feature, :capybara_feature => true do let (:user) { FactoryGirl.create(:user) } - + + before(:all) do + MusicSessionHistory.delete_all + Recording.delete_all + end + describe "sessions" do before(:each) do - create_session(user) + create_session(creator: user) formal_leave_by(user) end diff --git a/web/spec/features/home_spec.rb b/web/spec/features/home_spec.rb index b4a529407..31abb2387 100644 --- a/web/spec/features/home_spec.rb +++ b/web/spec/features/home_spec.rb @@ -114,7 +114,7 @@ describe "Home Screen", :js => true, :type => :feature, :capybara_feature => tru describe 'Home Screen while in Native Client' do before(:each) do UserMailer.deliveries.clear - page.driver.headers = { 'User-Agent' => ' JamKazam ' } + emulate_client sign_in_poltergeist user visit "/client" end diff --git a/web/spec/features/in_session_spec.rb b/web/spec/features/in_session_spec.rb index 992e459a9..bb24708da 100644 --- a/web/spec/features/in_session_spec.rb +++ b/web/spec/features/in_session_spec.rb @@ -5,8 +5,6 @@ describe "In a Session", :js => true, :type => :feature, :capybara_feature => tr subject { page } before(:all) do - Capybara.javascript_driver = :poltergeist - Capybara.current_driver = Capybara.javascript_driver Capybara.default_wait_time = 15 end @@ -20,26 +18,29 @@ describe "In a Session", :js => true, :type => :feature, :capybara_feature => tr it "can't see a private session until it is made public", :slow => true do - pending "fails on build server" - create_session(user, description = "Public or private, I cant decide!") + description = "Public or private, I cant decide!" + create_session(creator: user, description: description) in_client(user) do set_session_as_private end in_client(finder) do + emulate_client sign_in_poltergeist finder visit "/client#/findSession" expect(page).to have_selector('#sessions-none-found') # verify private session is not found + sign_out_poltergeist(validate: true) end in_client(user) do set_session_as_public end - join_session(finder, description) # verify the public session is able to be joined + join_session(finder, description: description) # verify the public session is able to be joined end it "can open the Configure Tracks modal, and Add New Audio Gear", :slow => true do - create_session(user, description = "I'm gonna bail at some point!") - join_session(finder, description) + description = "I'm gonna bail at some point!" + create_session(creator: user, description: description) + join_session(finder, description: description) assert_all_tracks_seen(users=[user, finder]) @@ -72,7 +73,7 @@ describe "In a Session", :js => true, :type => :feature, :capybara_feature => tr end it "a user can change the genre and the Find Session screen will be updated" do - create_session(user) + create_session(creator: user) in_client(finder) { sign_in_poltergeist finder } 2.times do in_client(user) do @@ -83,4 +84,16 @@ describe "In a Session", :js => true, :type => :feature, :capybara_feature => tr end end end + + it "can rejoin private session as creator" do + creator, description = create_join_session(user, [finder]) + + in_client(user) do + set_session_as_private + formal_leave_by user + sign_out_poltergeist user + end + + join_session(user, description: description) + end end diff --git a/web/spec/features/twitter_auth_spec.rb b/web/spec/features/twitter_auth_spec.rb index 5c20e5076..40962ef94 100644 --- a/web/spec/features/twitter_auth_spec.rb +++ b/web/spec/features/twitter_auth_spec.rb @@ -25,7 +25,7 @@ describe "Welcome", :js => true, :type => :feature, :capybara_feature => true d User.where(email: 'twitter_user1@jamkazam.com').delete_all User.where(email: 'twitter_user2@jamkazam.com').delete_all - page.driver.headers = { 'User-Agent' => ' JamKazam ' } + emulate_client sign_in_poltergeist user visit "/" find('h1', text: 'Play music together over the Internet as if in the same room') diff --git a/web/spec/features/welcome_spec.rb b/web/spec/features/welcome_spec.rb index 355593c3d..7c23d26e7 100644 --- a/web/spec/features/welcome_spec.rb +++ b/web/spec/features/welcome_spec.rb @@ -16,7 +16,7 @@ describe "Welcome", :js => true, :type => :feature, :capybara_feature => true d MusicSessionHistory.delete_all Recording.delete_all - page.driver.headers = { 'User-Agent' => ' JamKazam ' } + emulate_client visit "/" find('h1', text: 'Play music together over the Internet as if in the same room') diff --git a/web/spec/features/whats_next_spec.rb b/web/spec/features/whats_next_spec.rb index 4562dbdb3..9073e09ce 100644 --- a/web/spec/features/whats_next_spec.rb +++ b/web/spec/features/whats_next_spec.rb @@ -12,7 +12,7 @@ describe "Home Screen", :js => true, :type => :feature, :capybara_feature => tru before(:each) do sign_in_poltergeist user - page.driver.headers = { 'User-Agent' => ' JamKazam ' } + emulate_client visit "/client" end @@ -62,7 +62,7 @@ describe "Home Screen", :js => true, :type => :feature, :capybara_feature => tru # needed because we poke the server with an updateUser call, but their is no indication in the UI that it's done wait_for_ajax - page.driver.headers = { 'User-Agent' => ' JamKazam ' } + emulate_client sleep 1 visit "/client" wait_until_curtain_gone diff --git a/web/spec/support/utilities.rb b/web/spec/support/utilities.rb index 8529365e1..74474cc65 100644 --- a/web/spec/support/utilities.rb +++ b/web/spec/support/utilities.rb @@ -187,14 +187,17 @@ 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(creator = FactoryGirl.create(:user), unique_session_desc = nil, genre = nil) - unique_session_desc ||= "create_join_session #{SecureRandom.urlsafe_base64}" - genre ||= 'Rock' +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 - page.driver.headers = { 'User-Agent' => ' JamKazam ' } + emulate_client sign_in_poltergeist creator wait_until_curtain_gone visit "/client#/createSession" @@ -204,8 +207,9 @@ def create_session(creator = FactoryGirl.create(:user), unique_session_desc = ni 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('Public', '#create-session-form select#musician-access') - jk_select('Public', '#create-session-form select#fan-access') + + 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 @@ -220,18 +224,20 @@ def create_session(creator = FactoryGirl.create(:user), unique_session_desc = ni 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, unique_session_desc) +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(unique_session_desc) + 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') @@ -240,13 +246,21 @@ def join_session(joiner, unique_session_desc) end -def create_join_session(creator, joiners=[], genre=nil) - creator, unique_session_desc = create_session(creator, nil, genre) + +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, unique_session_desc) + join_session(joiner, description: unique_session_desc) end + + return creator, unique_session_desc end def formal_leave_by user @@ -258,7 +272,7 @@ def formal_leave_by user end def start_recording_with(creator, joiners=[], genre=nil) - create_join_session(creator, joiners, genre) + 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' @@ -299,15 +313,17 @@ end def set_session_as_private() find('#session-settings-button').trigger(:click) within('#session-settings-dialog') do - select('Private', :from => 'session-settings-musician-access') - find('#session-settings-dialog-submit').trigger(:click) + 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 end def set_session_as_public() find('#session-settings-button').trigger(:click) within('#session-settings-dialog') do - select('Public', :from => 'session-settings-musician-access') + 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 end