diff --git a/ruby/lib/jam_ruby/models/notification.rb b/ruby/lib/jam_ruby/models/notification.rb index 6bb3ec67a..3acda624f 100644 --- a/ruby/lib/jam_ruby/models/notification.rb +++ b/ruby/lib/jam_ruby/models/notification.rb @@ -1,6 +1,8 @@ module JamRuby class Notification < ActiveRecord::Base + @@log = Logging.logger[Notification] + self.primary_key = 'id' default_scope order('created_at DESC') @@ -504,7 +506,11 @@ module JamRuby # send email notifications unless offline_ff.empty? - UserMailer.musician_session_join(offline_ff.map! {|f| f.email}, notification_msg).deliver + begin + UserMailer.musician_session_join(offline_ff.map! {|f| f.email}, notification_msg).deliver if APP_CONFIG.send_join_session_email_notifications + rescue => e + @@log.error("unable to send email to offline participants #{e}") + end end end end diff --git a/ruby/spec/support/utilities.rb b/ruby/spec/support/utilities.rb index ab6c023f3..564ec7b34 100644 --- a/ruby/spec/support/utilities.rb +++ b/ruby/spec/support/utilities.rb @@ -105,6 +105,10 @@ def app_config 100 end + def send_join_session_email_notifications + true + end + private def audiomixer_workspace_path diff --git a/web/app/assets/javascripts/layout.js b/web/app/assets/javascripts/layout.js index d8d164ac5..aa24db43e 100644 --- a/web/app/assets/javascripts/layout.js +++ b/web/app/assets/javascripts/layout.js @@ -456,6 +456,8 @@ function onHashChange(e, postFunction) { + if(currentHash == context.location.hash) { return } + if(resettingHash) { resettingHash = false; e.preventDefault(); @@ -474,7 +476,7 @@ var accepted = screenEvent(currentScreen, 'beforeLeave', {screen:screen, hash: context.location.hash}); if(accepted === false) { console.log("navigation to " + context.location.hash + " rejected by " + currentScreen); - resettingHash = true; + //resettingHash = true; // reset the hash to where it just was context.location.hash = currentHash; } diff --git a/web/app/assets/javascripts/profile.js b/web/app/assets/javascripts/profile.js index 8924d9ae5..569cbdb03 100644 --- a/web/app/assets/javascripts/profile.js +++ b/web/app/assets/javascripts/profile.js @@ -11,6 +11,7 @@ var rest = context.JK.Rest(); var decrementedFriendCountOnce = false; var sentFriendRequest = false; + var profileScreen = null; var instrument_logo_map = context.JK.getInstrumentIconMap24(); @@ -307,6 +308,7 @@ } function bindAbout() { + $('#profile-instruments').empty(); // name @@ -359,61 +361,93 @@ $('#profile-favorite-stats').html(user.favorite_count + text); } - if(isCurrentUser) { + renderBio(); + } + + /** The biography show/edit functionality */ + function renderBio() { + + + function initializeBioVisibility() { + + $showBio.hide(); + $noBio.hide(); + $biographyEditor.hide(); + + $bioTextArea.val(user.biography); + if(user.biography) { - $('#profile-biography').text(user.biography); + $showBio.show(); + if(isCurrentUser()) { + $editBiographyButton.show(); + } + $biographyText.text(user.biography).show(); } else { - var createBio = $(context._.template($('#template-add-user-profile').html(), {}, { variable: 'data' })); - $('a.enter-bio', createBio).click(function() { - $('.update-biography').show(); - return false; - }); - - $('#btn-update-user-biography', createBio).click(function() { - var $bio = $('#profile-biography .user-biography'); - var bio = $bio.val(); - $bio.closest('div.field').removeClass('error'); - $('.error-text', $bio.closest('div.field')).remove(); - rest.updateUser({ - biography: bio - }) - .done(function(response) { - if(response.biography){ - $('#profile-biography').text(response.biography); - } else { - $('.update-biography').hide(); - } - }) - .fail(function(jqXHR) { - if(jqXHR.status == 422) { - var errors = JSON.parse(jqXHR.responseText) - var biography = context.JK.format_errors("biography", errors); - if(biography != null) { - $bio.closest('div.field').addClass('error').end().after(biography); - } - else { - app.notifyServerError(jqXHR, "Unable to update biography") - } - } - else { - app.notifyServerError(jqXHR, "Unable to update biography") - } - }) - return false; - }); - - $('#btn-cancel-user-biography', createBio).click(function() { - $('.update-biography').hide(); - return false; - }); - $('#profile-biography').html(createBio); + if(isCurrentUser()) { + $noBio.show(); + } } } - else { - $('#profile-biography').text(user.biography); - } + var $bioTextArea = $('.user-biography', profileScreen); + var $showBio = $('.have-bio', profileScreen); + var $noBio = $('.no-bio', profileScreen); + var $biographyEditor = $('.update-biography', profileScreen); + var $addBiographyButton = $('a.enter-bio', profileScreen); + var $editBiographyButton = $('#profile-edit-biography', profileScreen); + var $submitBiographyButton = $('#btn-update-user-biography', profileScreen); + var $cancelBiographyButton = $('#btn-cancel-user-biography', profileScreen); + var $biographyText = $('#profile-biography', profileScreen); + + initializeBioVisibility(); + + $addBiographyButton.unbind('click').click(function() { + $biographyEditor.val(user.biography).show(); + return false; + }); + + $editBiographyButton.unbind('click').click(function() { + $editBiographyButton.hide(); + $biographyText.hide(); + $bioTextArea.val(user.biography); + $biographyEditor.show(); + return false; + }) + + $submitBiographyButton.unbind('click').click(function() { + var bio = $bioTextArea.val(); + $bioTextArea.closest('div.field').removeClass('error'); + $('.error-text', $bioTextArea.closest('div.field')).remove(); + userDefer = rest.updateUser({ + biography: bio + }) + .done(function(response) { + user = response; + initializeBioVisibility(); + }) + .fail(function(jqXHR) { + if(jqXHR.status == 422) { + var errors = JSON.parse(jqXHR.responseText) + var biography = context.JK.format_errors("biography", errors); + if(biography != null) { + $bioTextArea.closest('div.field').addClass('error').end().after(biography); + } + else { + app.notifyServerError(jqXHR, "Unable to update biography") + } + } + else { + app.notifyServerError(jqXHR, "Unable to update biography") + } + }) + return false; + }) + + $cancelBiographyButton.unbind('click').click(function() { + initializeBioVisibility(); + return false; + }) } /****************** SOCIAL TAB *****************/ @@ -696,7 +730,7 @@ 'afterShow': afterShow }; app.bindScreen('profile', screenBindings); - + profileScreen = $('#user-profile'); events(); } diff --git a/web/app/assets/javascripts/session.js b/web/app/assets/javascripts/session.js index 768004dae..5b99f3b15 100644 --- a/web/app/assets/javascripts/session.js +++ b/web/app/assets/javascripts/session.js @@ -279,6 +279,10 @@ // a client can only be in one session at a time, // and other parts of the code want to know at any certain times // about the current session, if any (for example, reconnect logic) + if(context.JK.CurrentSessionModel) { + context.JK.CurrentSessionModel.unsubscribe(); + } + context.JK.CurrentSessionModel = sessionModel = new context.JK.SessionModel( context.JK.app, context.JK.JamServer, @@ -442,6 +446,7 @@ app.layout.showDialog('leave-session-warning'); return false; } + return true; } function beforeHide(data) { diff --git a/web/app/assets/javascripts/sessionModel.js b/web/app/assets/javascripts/sessionModel.js index 6c975cdb1..d80436f8a 100644 --- a/web/app/assets/javascripts/sessionModel.js +++ b/web/app/assets/javascripts/sessionModel.js @@ -100,7 +100,10 @@ logger.debug("SessionModel.leaveCurrentSession()"); // TODO - sessionChanged will be called with currentSession = null server.unregisterMessageCallback(context.JK.MessageType.MUSICIAN_SESSION_JOIN, refreshCurrentSession); - server.unregisterMessageCallback(context.JK.MessageType.MUSICIAN_SESSION_DEPART, refreshCurrentSession); + server.unregisterMessageCallback(context.JK.MessageType.SESSION_JOIN, refreshCurrentSession); + server.unregisterMessageCallback(context.JK.MessageType.SESSION_DEPART, refreshCurrentSession); + + //server.unregisterMessageCallback(context.JK.MessageType.MUSICIAN_SESSION_DEPART, refreshCurrentSession); // leave the session right away without waiting on REST. Why? If you can't contact the server, or if it takes a long // time, for that entire duration you'll still be sending voice data to the other users. // this may be bad if someone decides to badmouth others in the left-session during this time @@ -143,7 +146,7 @@ */ function refreshCurrentSession() { // XXX use backend instead: https://jamkazam.atlassian.net/browse/VRFS-854 - logger.debug("SessionModel.refreshCurrentSession()"); + logger.debug("SessionModel.refreshCurrentSession(" + currentSessionId +")"); refreshCurrentSessionRest(sessionChanged); } @@ -171,6 +174,7 @@ if(sessionData != null) { currentOrLastSession = sessionData; } + currentSession = sessionData; } @@ -189,7 +193,6 @@ $.ajax({ type: "GET", url: url, - async: false, success: function(response) { sendClientParticipantChanges(currentSession, response); updateCurrentSession(response); @@ -378,8 +381,7 @@ var url = "/api/participants/" + clientId; return $.ajax({ type: "DELETE", - url: url, - async: true + url: url }); } @@ -489,6 +491,12 @@ this.getCurrentOrLastSession = function() { return currentOrLastSession; }; + this.unsubscribe = function() { + server.unregisterMessageCallback(context.JK.MessageType.MUSICIAN_SESSION_JOIN, refreshCurrentSession); + server.unregisterMessageCallback(context.JK.MessageType.SESSION_JOIN, refreshCurrentSession); + server.unregisterMessageCallback(context.JK.MessageType.SESSION_DEPART, refreshCurrentSession); + } + }; })(window,jQuery); \ No newline at end of file diff --git a/web/app/assets/javascripts/utils.js b/web/app/assets/javascripts/utils.js index e0cd22df3..098ce3fb3 100644 --- a/web/app/assets/javascripts/utils.js +++ b/web/app/assets/javascripts/utils.js @@ -248,6 +248,7 @@ // // use context._.template for something more powerful context.JK.fillTemplate = function(template, vals) { + if(template == null) throw 'null template in fillTemplate' for(var val in vals) template=template.replace(new RegExp('{'+val+'}','g'), vals[val]); return template; diff --git a/web/app/assets/stylesheets/client/profile.css.scss b/web/app/assets/stylesheets/client/profile.css.scss index 8a93e1872..f1c207801 100644 --- a/web/app/assets/stylesheets/client/profile.css.scss +++ b/web/app/assets/stylesheets/client/profile.css.scss @@ -1,20 +1,13 @@ @import "client/common.css.scss"; #user-profile { - #profile-biography { - a.enter-bio { - - } + .profile-about-right { textarea { width:100%; height:150px; padding:0; } - - .update-biography { - display:none; - } } } diff --git a/web/app/views/clients/_profile.html.erb b/web/app/views/clients/_profile.html.erb index 908b44667..8df180292 100644 --- a/web/app/views/clients/_profile.html.erb +++ b/web/app/views/clients/_profile.html.erb @@ -61,8 +61,27 @@
-


-
+
+ You have no bio to describe yourself as a musician. Enter one now! +
+
+

Edit Bio +
+
+
+ +
+

+
+ OK +
+
+ CANCEL +
+
+
+
+

@@ -192,24 +211,3 @@
{location}
- - - - diff --git a/web/config/application.rb b/web/config/application.rb index 71a3114be..b5429213e 100644 --- a/web/config/application.rb +++ b/web/config/application.rb @@ -207,5 +207,7 @@ if defined?(Bundler) config.autocheck_create_session_agreement = false config.max_audio_downloads = 100 + + config.send_join_session_email_notifications = true end end diff --git a/web/config/environments/development.rb b/web/config/environments/development.rb index 548d9cb19..ebb9ba61e 100644 --- a/web/config/environments/development.rb +++ b/web/config/environments/development.rb @@ -45,7 +45,7 @@ SampleApp::Application.configure do config.assets.compress = false # Expands the lines which load the assets - config.assets.debug = false + config.assets.debug = true # Set the logging destination(s) config.log_to = %w[stdout file] @@ -55,6 +55,7 @@ SampleApp::Application.configure do config.websocket_gateway_enable = true + TEST_CONNECT_STATES = false # Overloaded value to match production for using cloudfront in dev mode @@ -77,4 +78,6 @@ SampleApp::Application.configure do # set CREATE_SESSION_AGREEMENT=0 if you don't want the autoclick behavior config.autocheck_create_session_agreement = ENV['CREATE_SESSION_AGREEMENT'] ? ENV['CREATE_SESSION_AGREEMENT'] == "1" : true + + config.send_join_session_email_notifications = false end