From c57ea372ac3e6dcb8cf457775d21fc11cc920695 Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Sat, 25 Oct 2014 22:23:52 -0400 Subject: [PATCH 01/15] VRFS-2311 allow session creator to add and approve slots on the fly when there are no available slots --- ruby/lib/jam_ruby.rb | 1 + ruby/lib/jam_ruby/errors/conflict_error.rb | 5 + ruby/lib/jam_ruby/models/music_session.rb | 2 +- ruby/lib/jam_ruby/models/rsvp_request.rb | 31 +++++- .../spec/jam_ruby/models/rsvp_request_spec.rb | 47 ++++++++- .../javascripts/accounts_session_detail.js | 54 ++++++++++- .../javascripts/dialog/rsvpCancelDialog.js | 4 +- .../dialog/rsvpCreateSlotDialog.js | 64 ++++++++++++ .../javascripts/dialog/rsvpSubmitDialog.js | 26 +++-- .../assets/javascripts/notificationPanel.js | 97 ++++++++++++------- web/app/assets/javascripts/ui_helper.js | 7 ++ web/app/assets/javascripts/web/sessions.js | 2 +- web/app/controllers/api_controller.rb | 4 + .../clients/_account_session_detail.html.haml | 2 +- web/app/views/dialogs/_dialogs.html.haml | 1 + .../dialogs/_rsvpCreateSlotDialog.html.slim | 13 +++ .../views/dialogs/_rsvpSubmitDialog.html.haml | 2 +- web/app/views/errors/conflict_error.rabl | 7 ++ 18 files changed, 309 insertions(+), 60 deletions(-) create mode 100644 ruby/lib/jam_ruby/errors/conflict_error.rb create mode 100644 web/app/assets/javascripts/dialog/rsvpCreateSlotDialog.js create mode 100644 web/app/views/dialogs/_rsvpCreateSlotDialog.html.slim create mode 100644 web/app/views/errors/conflict_error.rabl diff --git a/ruby/lib/jam_ruby.rb b/ruby/lib/jam_ruby.rb index 98b93a4c1..649dc40e6 100755 --- a/ruby/lib/jam_ruby.rb +++ b/ruby/lib/jam_ruby.rb @@ -27,6 +27,7 @@ require "jam_ruby/constants/validation_messages" require "jam_ruby/errors/permission_error" require "jam_ruby/errors/state_error" require "jam_ruby/errors/jam_argument_error" +require "jam_ruby/errors/conflict_error" require "jam_ruby/lib/app_config" require "jam_ruby/lib/s3_manager_mixin" require "jam_ruby/lib/module_overrides" diff --git a/ruby/lib/jam_ruby/errors/conflict_error.rb b/ruby/lib/jam_ruby/errors/conflict_error.rb new file mode 100644 index 000000000..5fe2e2491 --- /dev/null +++ b/ruby/lib/jam_ruby/errors/conflict_error.rb @@ -0,0 +1,5 @@ +module JamRuby + class ConflictError < Exception + + end +end \ No newline at end of file diff --git a/ruby/lib/jam_ruby/models/music_session.rb b/ruby/lib/jam_ruby/models/music_session.rb index 376a104e9..750ddf462 100644 --- a/ruby/lib/jam_ruby/models/music_session.rb +++ b/ruby/lib/jam_ruby/models/music_session.rb @@ -724,7 +724,7 @@ module JamRuby query = query.offset(offset) query = query.limit(limit) - query = query.where("music_sessions.create_type IS NULL OR music_sessions.create_type != ?", MusicSession::CREATE_TYPE_QUICK_START) + query = query.where("music_sessions.create_type IS NULL OR (music_sessions.create_type != ? AND music_sessions.create_type != ?)", MusicSession::CREATE_TYPE_QUICK_START, MusicSession::CREATE_TYPE_IMMEDIATE) query = query.where("music_sessions.genre_id = ?", genre) unless genre.blank? query = query.where('music_sessions.language = ?', lang) unless lang.blank? query = query.where("(description_tsv @@ to_tsquery('jamenglish', ?))", ActiveRecord::Base.connection.quote(keyword) + ':*') unless keyword.blank? diff --git a/ruby/lib/jam_ruby/models/rsvp_request.rb b/ruby/lib/jam_ruby/models/rsvp_request.rb index f30851efe..9f233b973 100644 --- a/ruby/lib/jam_ruby/models/rsvp_request.rb +++ b/ruby/lib/jam_ruby/models/rsvp_request.rb @@ -154,7 +154,7 @@ module JamRuby # authorize the user attempting to respond to the RSVP request if music_session.creator.id != user.id - raise PermissionError, "Only the session organizer can accept or decline and RSVP request." + raise PermissionError, "Only the session organizer can accept or decline an RSVP request." end rsvp_request = RsvpRequest.find_by_id(rsvp_request_id) @@ -181,8 +181,35 @@ module JamRuby raise StateError, "Slot does not exist" end + # slot has already been accepted if rsvp_slot.chosen && r[:accept] - raise StateError, "All RSVP slots for the #{rsvp_slot.instrument_id} have been already approved." + # get the instrument and skill level for this slot and see if there are others available + # and auto-reassign the request_slot to the open rsvp_slot + open_slots = music_session.open_slots + + # don't worry about matching proficiency if the user RSVPed to "Any Skill Level" + if rsvp_slot.proficiency_level == 0 + open_slots = open_slots.select { |slot| slot.instrument_id == rsvp_slot.instrument_id } + else + open_slots = open_slots.select { |slot| slot.instrument_id == rsvp_slot.instrument_id && slot.proficiency_level == rsvp_slot.proficiency_level } + end + + # (1) another available slot exists matching this instrument and proficiency + unless open_slots.blank? + rsvp_slot = open_slots.first + request_slot.rsvp_slot_id = rsvp_slot.id # this links the RsvpRequestRsvpSlot to the available open slot matching this instrument and proficiency level + + # (2) no identical slots available => create a new one on the fly + else + new_slot = RsvpSlot.new + new_slot.instrument_id = rsvp_slot.instrument_id + new_slot.proficiency_level = rsvp_slot.proficiency_level + new_slot.music_session_id = rsvp_slot.music_session_id + new_slot.is_unstructured_rsvp = rsvp_slot.is_unstructured_rsvp + new_slot.save! + + request_slot.rsvp_slot_id = new_slot.id # saved below on line 218 + end end if r[:accept] diff --git a/ruby/spec/jam_ruby/models/rsvp_request_spec.rb b/ruby/spec/jam_ruby/models/rsvp_request_spec.rb index 26ddd1c22..0f8aa5874 100644 --- a/ruby/spec/jam_ruby/models/rsvp_request_spec.rb +++ b/ruby/spec/jam_ruby/models/rsvp_request_spec.rb @@ -228,7 +228,47 @@ describe RsvpRequest do n.description.should == NotificationTypes::SCHEDULED_SESSION_RSVP_APPROVED end - it "should not allow approval of RSVP for a slot that has already been approved" do + it "should allow approval of multiple RSVPs to same slot ID when multiple slots exist for same instrument and proficiency level" do + @music_session.open_rsvps = true + @music_session.save! + + @slot2.delete + + slot2 = FactoryGirl.build(:rsvp_slot, :music_session => @music_session, :instrument => JamRuby::Instrument.find('electric guitar')) + slot2.save! + + rsvp1 = RsvpRequest.create({:session_id => @music_session.id, :rsvp_slots => [@slot1.id], :message => "Let's Jam!"}, @session_invitee) + rsvp2 = RsvpRequest.create({:session_id => @music_session.id, :rsvp_slots => [@slot1.id], :message => "Let's Jam!"}, @non_session_invitee) + + rs1 = RsvpRequestRsvpSlot.find_by_rsvp_request_id(rsvp1.id) + rs1.rsvp_slot_id.should == @slot1.id + + # approve RSVP 1 + RsvpRequest.update({:id => rsvp1.id, :session_id => @music_session.id, :rsvp_responses => [{:request_slot_id => rs1.id, :accept => true}]}, @session_creator) + + # ensure slot ID didn't change + rs1 = RsvpRequestRsvpSlot.find_by_rsvp_request_id(rsvp1.id) + rs1.rsvp_slot_id.should == @slot1.id + + # check before approving + rs2 = RsvpRequestRsvpSlot.find_by_rsvp_request_id(rsvp2.id) + rs2.rsvp_slot_id.should == @slot1.id + + # approve RSVP 2 (same slot ID, but slot2 is same instrument + proficiency level) + RsvpRequest.update({:id => rsvp2.id, :session_id => @music_session.id, :rsvp_responses => [{:request_slot_id => rs2.id, :accept => true}]}, @session_creator) + + # should have linked the RsvpRequestRsvpSlot record to the second slot + rs2 = RsvpRequestRsvpSlot.find_by_rsvp_request_id(rsvp2.id) + rs2.rsvp_slot_id.should == slot2.id + + slots = RsvpSlot.where("music_session_id = ?", @music_session.id) + slots.count.should == 2 + + request_slots = RsvpRequestRsvpSlot.where("chosen=true") + request_slots.count.should == 2 + end + + it "should create a new slot for an RSVP for a slot that has already been approved" do rsvp = RsvpRequest.create({:session_id => @music_session.id, :rsvp_slots => [@slot1.id, @slot2.id], :message => "Let's Jam!"}, @session_invitee) # approve @@ -239,7 +279,10 @@ describe RsvpRequest do # approve again rs1 = RsvpRequestRsvpSlot.find_by_rsvp_slot_id(@slot1.id) rs2 = RsvpRequestRsvpSlot.find_by_rsvp_slot_id(@slot2.id) - expect {RsvpRequest.update({:id => rsvp.id, :session_id => @music_session.id, :rsvp_responses => [{:request_slot_id => rs1.id, :accept => true}, {:request_slot_id => rs2.id, :accept => true}]}, @session_creator)}.to raise_error(StateError) + RsvpRequest.update({:id => rsvp.id, :session_id => @music_session.id, :rsvp_responses => [{:request_slot_id => rs1.id, :accept => true}, {:request_slot_id => rs2.id, :accept => true}]}, @session_creator) + + slots = RsvpSlot.where("music_session_id = ?", @music_session.id) + slots.count.should == 4 end end diff --git a/web/app/assets/javascripts/accounts_session_detail.js b/web/app/assets/javascripts/accounts_session_detail.js index 3ff0981be..53eb195f7 100644 --- a/web/app/assets/javascripts/accounts_session_detail.js +++ b/web/app/assets/javascripts/accounts_session_detail.js @@ -31,7 +31,6 @@ function beforeShow(data) { sessionId = data.id; - console.log("sessionId=%o", sessionId); loadSessionData(); } @@ -41,8 +40,7 @@ function inviteMusicians(e) { e.preventDefault(); - friendInput = inviteMusiciansUtil.inviteSessionUpdate('#update-session-invite-musicians', - sessionId); + friendInput = inviteMusiciansUtil.inviteSessionUpdate('#update-session-invite-musicians', sessionId); inviteMusiciansUtil.loadFriends(); $(friendInput).show(); // invitationDialog.showEmailDialog(); @@ -85,12 +83,55 @@ e.preventDefault(); var rsvpId = $(e.target).attr('request-id'); + var userName = $(e.target).attr('user-name'); + var instrumentIds = $(e.target).attr('data-instrument-text'); var params = buildRsvpRequestActionParams(rsvpId, true); + // first check if any open slots exist for these instruments + rest.getOpenSessionSlots(sessionData.id, true) + .done(function(openSlots) { + if (openSlots) { + if (openSlots.length === 0) { + ui.launchRsvpCreateSlotDialog(sessionData.id, instrumentIds.split('|'), userName); + } + else { + var arrInstrumentIds = instrumentIds.split('|'); + var openSlotInstrumentIds = []; + var unavailableSlotInstrumentIds = []; + + // ensure each instrument in the user's list is available in the open slots list + $.each(openSlots, function(index, slot) { + openSlotInstrumentIds.push(slot.instrument_id); + }); + + // build list of instrument IDs in the RSVP request for which there are no open slots + for (var i=0; i < arrInstrumentIds.length; i++) { + if ($.inArray(arrInstrumentIds[i], openSlotInstrumentIds) === -1) { + unavailableSlotInstrumentIds.push(arrInstrumentIds[i]); + } + } + + if (unavailableSlotInstrumentIds.length > 0) { + ui.launchRsvpCreateSlotDialog(sessionData.id, unavailableSlotInstrumentIds, userName, function() { + approve(rsvpId, params); + }); + } + else { + approve(rsvpId, params); + } + } + } + else { + ui.launchRsvpCreateSlotDialog(sessionData.id, instrumentIds.split('|'), userName); + } + }); + } + + function approve(rsvpId, params) { rest.updateRsvpRequest(rsvpId, params) .done(refreshSessionDetail) .fail(function(jqXHR, textStatus, errorMessage) { - if (jqXHR.status === 400) { + if (jqXHR.status === 409) { app.notify( { title: "Unable to Approve RSVP", @@ -284,11 +325,14 @@ var latencyHtml = ""; $.each(sessionData.pending_rsvp_requests, function(index, pending_rsvp_request) { if (pending_rsvp_request.user_id != context.JK.currentUserId) { + var instrumentDesc = []; + if ("instrument_list" in pending_rsvp_request && pending_rsvp_request.instrument_list != null) { $.each(pending_rsvp_request.instrument_list, function (index, instrument) { var instrumentId = instrument == null ? null : instrument.id; var inst = context.JK.getInstrumentIcon24(instrumentId); instrumentLogoHtml += ' '; + instrumentDesc.push(instrumentId); }) } @@ -304,7 +348,7 @@ $templateAccountPendingRsvp.html(), {user_id: pending_rsvp_request.user_id, avatar_url: avatar_url, user_name: pending_rsvp_request.user.name, instruments: instrumentLogoHtml, - latency: latencyHtml, request_id: pending_rsvp_request.id}, + latency: latencyHtml, request_id: pending_rsvp_request.id, instrument_text: instrumentDesc.join('|')}, {variable: 'data'} ); diff --git a/web/app/assets/javascripts/dialog/rsvpCancelDialog.js b/web/app/assets/javascripts/dialog/rsvpCancelDialog.js index c2efb6822..bd0079bf3 100644 --- a/web/app/assets/javascripts/dialog/rsvpCancelDialog.js +++ b/web/app/assets/javascripts/dialog/rsvpCancelDialog.js @@ -35,7 +35,7 @@ } function showDialog() { - return app.layout.showDialog('rsvp-cancel-dialog'); + return app.layout.showDialog(dialogId); } function events() { @@ -99,7 +99,7 @@ $dialog = $('[layout-id="' + dialogId + '"]'); - $("#rsvp-cancel-dialog").iCheck({ + $dialog.iCheck({ checkboxClass: 'icheckbox_minimal', radioClass: 'iradio_minimal', inheritClass: true diff --git a/web/app/assets/javascripts/dialog/rsvpCreateSlotDialog.js b/web/app/assets/javascripts/dialog/rsvpCreateSlotDialog.js new file mode 100644 index 000000000..dcf5fd500 --- /dev/null +++ b/web/app/assets/javascripts/dialog/rsvpCreateSlotDialog.js @@ -0,0 +1,64 @@ +(function(context,$) { + + "use strict"; + context.JK = context.JK || {}; + context.JK.RsvpCreateSlotDialog = function(app, sessionId, instrumentIds, rsvpRequesterName, createSlotsCallback) { + var EVENTS = context.JK.EVENTS; + var logger = context.JK.logger; + var rest = context.JK.Rest(); + var $dialog = null; + var dialogId = 'rsvp-create-slot-dialog'; + var $btnSave = null; + + function beforeShow(data) { + } + + function afterShow(data) { + var instructions = "All RSVP slots for the instruments below have already been filled. Would you like to open up a new RSVP slot for " + rsvpRequesterName + " so that they can join your session too?"; + var instruments = instrumentIds.join("
"); + + $('.instructions', $dialog).html(instructions); + $('.instruments', $dialog).html(instruments); + } + + function afterHide() { + } + + function showDialog() { + return app.layout.showDialog(dialogId); + } + + function events() { + $btnSave.unbind('click'); + $btnSave.click(function(e) { + e.preventDefault(); + + if (createSlotsCallback) { + createSlotsCallback(); + app.layout.closeDialog(dialogId); + } + }); + } + + function initialize() { + + var dialogBindings = { + 'beforeShow' : beforeShow, + 'afterShow' : afterShow, + 'afterHide': afterHide + }; + + app.bindDialog(dialogId, dialogBindings); + + $dialog = $('[layout-id="' + dialogId + '"]'); + $btnSave = $dialog.find('.btnSave'); + + events(); + } + + this.initialize = initialize; + this.showDialog = showDialog; + } + + return this; +})(window,jQuery); \ No newline at end of file diff --git a/web/app/assets/javascripts/dialog/rsvpSubmitDialog.js b/web/app/assets/javascripts/dialog/rsvpSubmitDialog.js index be8bf3afa..03ccb6a5f 100644 --- a/web/app/assets/javascripts/dialog/rsvpSubmitDialog.js +++ b/web/app/assets/javascripts/dialog/rsvpSubmitDialog.js @@ -30,17 +30,14 @@ var hasOpenSlots = response.open_slots && response.open_slots.length > 0; - if (response['is_unstructured_rsvp?']) { var checkedState = hasOpenSlots ? '' : 'checked="checked"' - $('.rsvp-instruments', $dialog).append('Play Any Instrument You Like
'); + $('.rsvp-instruments', $dialog).append('Play Any Instrument You Like
'); } if (hasOpenSlots) { $.each(response.open_slots, function(index, val) { - var instrument = val.instrument_id; - - $('.rsvp-instruments', $dialog).append('' + val.description + " (" + val.proficiency_desc + ")
"); + $('.rsvp-instruments', $dialog).append('' + val.description + " (" + val.proficiency_desc + ")
"); }); } } @@ -60,18 +57,28 @@ $btnSubmit.click(function(e) { e.preventDefault(); + var error = false; var slotIds = []; + var selectedSlots = []; $("input:checked", '.rsvp-instruments').each(function(index) { + var selection = $(this).attr('data-instrument-id'); + + if ($.inArray(selection, selectedSlots) > -1) { + $('.error', $dialog).html('You have selected the same instrument twice.').show(); + error = true; + return; + } + selectedSlots.push(selection); slotIds.push($(this).val()); }); + if (error) return; + if (slotIds.length === 0) { - $('.error', $dialog).show(); + $('.error', $dialog).html('You must select at least 1 instrument.').show(); return; } - var error = false; - // TODO: show spinner?? rest.submitRsvpRequest(sessionId, slotIds) .done(function(response) { @@ -83,8 +90,7 @@ }) .fail(function(xhr, textStatus, errorMessage) { error = true; - $('.error', $dialog).html("Unexpected error occurred while saving message (" + xhr.status + ")"); - $('.error', $dialog).show(); + $('.error', $dialog).html("Unexpected error occurred while saving message (" + xhr.status + ")").show(); }); } diff --git a/web/app/assets/javascripts/notificationPanel.js b/web/app/assets/javascripts/notificationPanel.js index 1e56483f3..5be367d2a 100644 --- a/web/app/assets/javascripts/notificationPanel.js +++ b/web/app/assets/javascripts/notificationPanel.js @@ -422,7 +422,7 @@ var $action_btn = $notification.find($btnNotificationAction); $action_btn.text('SESSION DETAILS'); $action_btn.click(function() { - context.JK.popExternalLink('/sessions/' + payload.session_id + '/details'); + openSessionInfoWebPage({"session_id": payload.session_id}); }); } @@ -843,10 +843,12 @@ }, [{ id: "btn-more-info", text: "MORE INFO", - "layout-action": "close", - href: JK.root_url + "/sessions/" + payload.session_id + "/details", rel: "external", - "class": "button-orange" + "class": "button-orange", + callback: openSessionInfoWebPage, + callback_args: { + "session_id": payload.session_id + } }] ); }); @@ -865,10 +867,12 @@ "icon_url": context.JK.resolveAvatarUrl(payload.photo_url) }, [{ id: "btn-manage-rsvp", - text: "Manage RSVP", - "layout-action": "close", - href: "/client#/account/sessionDetail/" + payload.session_id, - "class": "button-orange" + text: "MANAGE RSVP", + "class": "button-orange", + callback: navigateToSessionDetails, + callback_args: { + "session_id": payload.session_id + } }] ); }); @@ -886,11 +890,14 @@ "icon_url": context.JK.resolveAvatarUrl(payload.photo_url) }, [{ id: "btn-session-details", - text: "Session Details", + text: "SESSION DETAILS", "layout-action": "close", - href: JK.root_url + "/sessions/" + payload.session_id + "/details", rel: "external", - "class": "button-orange" + "class": "button-orange", + callback: openSessionInfoWebPage, + callback_args: { + "session_id": payload.session_id + } }] ); }); @@ -908,11 +915,13 @@ "icon_url": context.JK.resolveAvatarUrl(payload.photo_url) }, [{ id: "btn-session-details", - text: "Session Details", - "layout-action": "close", - href: JK.root_url + "/sessions/" + payload.session_id + "/details", + text: "SESSION DETAILS", rel: "external", - "class": "button-orange" + "class": "button-orange", + callback: openSessionInfoWebPage, + callback_args: { + "session_id": payload.session_id + } }] ); }); @@ -930,11 +939,13 @@ "icon_url": context.JK.resolveAvatarUrl(payload.photo_url) }, [{ id: "btn-session-details", - text: "Session Details", - "layout-action": "close", - href: JK.root_url + "/sessions/" + payload.session_id + "/details", + text: "SESSION DETAILS", rel: "external", - "class": "button-orange" + "class": "button-orange", + callback: openSessionInfoWebPage, + callback_args: { + "session_id": payload.session_id + } }] ); }); @@ -952,11 +963,13 @@ "icon_url": context.JK.resolveAvatarUrl(payload.photo_url) }, [{ id: "btn-session-details", - text: "Session Details", - "layout-action": "close", - href: JK.root_url + "/sessions/" + payload.session_id + "/details", + text: "SESSION DETAILS", rel: "external", - "class": "button-orange" + "class": "button-orange", + callback: openSessionInfoWebPage, + callback_args: { + "session_id": payload.session_id + } }] ); }); @@ -974,11 +987,13 @@ "icon_url": context.JK.resolveAvatarUrl(payload.photo_url) }, [{ id: "btn-session-details", - text: "Session Details", - "layout-action": "close", - href: JK.root_url + "/sessions/" + payload.session_id + "/details", + text: "SESSION DETAILS", rel: "external", - "class": "button-orange" + "class": "button-orange", + callback: openSessionInfoWebPage, + callback_args: { + "session_id": payload.session_id + } }] ); }); @@ -996,11 +1011,13 @@ "icon_url": context.JK.resolveAvatarUrl(payload.photo_url) }, [{ id: "btn-session-details", - text: "Session Details", - "layout-action": "close", - href: JK.root_url + "/sessions/" + payload.session_id + "/details", + text: "SESSION DETAILS", rel: "external", - "class": "button-orange" + "class": "button-orange", + callback: openSessionInfoWebPage, + callback_args: { + "session_id": payload.session_id + } }] ); }); @@ -1019,11 +1036,13 @@ "icon_url": context.JK.resolveAvatarUrl(payload.photo_url) }, [{ id: "btn-session-details", - text: "Session Details", - "layout-action": "close", - href: JK.root_url + "/sessions/" + payload.session_id + "/details", + text: "SESSION DETAILS", rel: "external", - "class": "button-orange" + "class": "button-orange", + callback: openSessionInfoWebPage, + callback_args: { + "session_id": payload.session_id + } }] ); }); @@ -1231,6 +1250,14 @@ context.JK.popExternalLink('/recordings/' + args.recording_id); } + function navigateToSessionDetails(args) { + context.location = '/client#/account/sessionDetail/' + args.session_id; + } + + function openSessionInfoWebPage(args) { + context.JK.popExternalLink('/sessions/' + args.session_id + '/details'); + } + function deleteNotificationHandler(evt) { evt.stopPropagation(); var notificationId = $(this).attr('notification-id'); diff --git a/web/app/assets/javascripts/ui_helper.js b/web/app/assets/javascripts/ui_helper.js index 0ed51e8d0..167855b30 100644 --- a/web/app/assets/javascripts/ui_helper.js +++ b/web/app/assets/javascripts/ui_helper.js @@ -47,12 +47,19 @@ return rsvpDialog.showDialog(); } + function launchRsvpCreateSlotDialog(sessionId, instrumentIds, rsvpRequesterName, createSlotsCallback) { + var rsvpDialog = new JK.RsvpCreateSlotDialog(JK.app, sessionId, instrumentIds, rsvpRequesterName, createSlotsCallback); + rsvpDialog.initialize(); + return rsvpDialog.showDialog(); + } + this.addSessionLike = addSessionLike; this.addRecordingLike = addRecordingLike; this.launchCommentDialog = launchCommentDialog; this.launchShareDialog = launchShareDialog; this.launchRsvpSubmitDialog = launchRsvpSubmitDialog; this.launchRsvpCancelDialog = launchRsvpCancelDialog; + this.launchRsvpCreateSlotDialog = launchRsvpCreateSlotDialog; return this; }; diff --git a/web/app/assets/javascripts/web/sessions.js b/web/app/assets/javascripts/web/sessions.js index e6727fb91..95e64ca71 100644 --- a/web/app/assets/javascripts/web/sessions.js +++ b/web/app/assets/javascripts/web/sessions.js @@ -88,7 +88,7 @@ function togglePlay() { if(playing) { - $status.text('SESSION IN PROGRESS'); + $status.text('LIVE SESSION IN PROGRESS'); stopPlay(); } else { diff --git a/web/app/controllers/api_controller.rb b/web/app/controllers/api_controller.rb index b27e41e9b..d05413842 100644 --- a/web/app/controllers/api_controller.rb +++ b/web/app/controllers/api_controller.rb @@ -16,6 +16,10 @@ class ApiController < ApplicationController @exception = exception render "errors/permission_error", :status => 403 end + rescue_from 'JamRuby::ConflictError' do |exception| + @exception = exception + render "errors/conflict_error", :status => 409 + end rescue_from 'ActiveRecord::RecordNotFound' do |exception| @@log.debug(exception) render :json => { :errors => { :resource => ["record not found"] } }, :status => 404 diff --git a/web/app/views/clients/_account_session_detail.html.haml b/web/app/views/clients/_account_session_detail.html.haml index 28fc61218..0b62b7217 100644 --- a/web/app/views/clients/_account_session_detail.html.haml +++ b/web/app/views/clients/_account_session_detail.html.haml @@ -95,7 +95,7 @@ {{data.latency}} %td.rsvp-buttons %a{href: "/client#/profile/{{data.user_id}}", class: 'button-orange left', 'user-id' => "{{data.user_id}}"} PROFILE - %a{href: "#", class: 'button-orange left approveRsvpRequest', 'user-id' => "{{data.user_id}}", 'request-id' => "{{data.request_id}}"} APPROVE + %a{href: "#", class: 'button-orange left approveRsvpRequest', 'data-instrument-text' => "{{data.instrument_text}}", 'user-id' => "{{data.user_id}}", 'request-id' => "{{data.request_id}}", 'user-name' => "{{data.user_name}}"} APPROVE %a{href: "#", class: 'button-orange left declineRsvpRequest', 'user-id' => "{{data.user_id}}", 'request-id' => "{{data.request_id}}"} DECLINE .clearall .clearall diff --git a/web/app/views/dialogs/_dialogs.html.haml b/web/app/views/dialogs/_dialogs.html.haml index 69c332a5c..7ab177b1d 100644 --- a/web/app/views/dialogs/_dialogs.html.haml +++ b/web/app/views/dialogs/_dialogs.html.haml @@ -17,6 +17,7 @@ = render 'dialogs/commentDialog' = render 'dialogs/rsvpSubmitDialog' = render 'dialogs/rsvpCancelDialog' += render 'dialogs/rsvpCreateSlotDialog' = render 'dialogs/sessionCancelDialog' = render 'dialogs/signinDialog' = render 'dialogs/signupDialog' diff --git a/web/app/views/dialogs/_rsvpCreateSlotDialog.html.slim b/web/app/views/dialogs/_rsvpCreateSlotDialog.html.slim new file mode 100644 index 000000000..47bbfeec8 --- /dev/null +++ b/web/app/views/dialogs/_rsvpCreateSlotDialog.html.slim @@ -0,0 +1,13 @@ +.dialog.dialog-overlay-sm layout='dialog' layout-id='rsvp-create-slot-dialog' id='rsvp-create-slot-dialog' + .content-head + = image_tag "content/icon_alert.png", {:width => 24, :height => 24, :class => 'content-icon' } + h1 RSVP Slot Already Filled + + .dialog-inner + div.instructions + br + div.instruments + .buttons + .right + a.button-grey class='btnCancel' layout-action='cancel' NO + a.button-orange class='btnSave' YES \ No newline at end of file diff --git a/web/app/views/dialogs/_rsvpSubmitDialog.html.haml b/web/app/views/dialogs/_rsvpSubmitDialog.html.haml index b27837203..1135fde57 100644 --- a/web/app/views/dialogs/_rsvpSubmitDialog.html.haml +++ b/web/app/views/dialogs/_rsvpSubmitDialog.html.haml @@ -9,7 +9,7 @@ .schedule-recurrence .part .slot-instructions Check the box(es) next to the track(s) you want to play in the session: - .error{:style => 'display:none'} You must select at least 1 instrument. + .error{:style => 'display:none'} .rsvp-instruments .comment-instructions Enter a message to the other musicians in the session (optional): diff --git a/web/app/views/errors/conflict_error.rabl b/web/app/views/errors/conflict_error.rabl new file mode 100644 index 000000000..fd3151a24 --- /dev/null +++ b/web/app/views/errors/conflict_error.rabl @@ -0,0 +1,7 @@ +object @exception + +attributes :message + +node "type" do + "ConflictError" +end \ No newline at end of file From f6f79acddde030b320cc920b2c8ab7feb9784edc Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Sun, 26 Oct 2014 19:45:29 -0400 Subject: [PATCH 02/15] VRFS-2358 fixed notation upload and display issues --- .../accounts_session_properties.js | 25 ++++--- .../dialog/sessionSettingsDialog.js | 72 +++++++++---------- .../javascripts/scheduled_session.js.erb | 12 ++-- .../stylesheets/client/account.css.scss | 19 +++++ .../api_music_sessions_controller.rb | 15 ++-- .../_account_session_properties.html.haml | 8 +-- .../views/clients/_sessionSettings.html.haml | 2 +- 7 files changed, 90 insertions(+), 63 deletions(-) diff --git a/web/app/assets/javascripts/accounts_session_properties.js b/web/app/assets/javascripts/accounts_session_properties.js index d86698bcb..0a0f1ca34 100644 --- a/web/app/assets/javascripts/accounts_session_properties.js +++ b/web/app/assets/javascripts/accounts_session_properties.js @@ -9,7 +9,9 @@ var rest = context.JK.Rest(); var sessionId = null; var sessionData = null; - var $screen = null; + var $screen = $("#account-session-properties"); + var $inputFiles = $screen.find('#session-select-files'); + var $selectedFilenames = $screen.find('#selected-filenames'); var $propertiesBody = null; var $languageList = null; var $recurringModeList = null; @@ -62,10 +64,11 @@ function events() { $startTimeList.on('change', toggleStartTime); - $btnSelectFiles.on('click', toggleSelectFiles); $dateTimeTBD.on('ifChanged', toggleDateTBD); $screen.find("#session-update").on('click', updateSessionProperties); - $screen.find('#session-prop-select-files').on('change', changeSelectedFiles); + + $inputFiles.on('change', changeSelectedFiles); + $btnSelectFiles.on('click', toggleSelectFiles); } function toggleStartTime() { @@ -252,7 +255,8 @@ // } } data.recurring_mode = $recurringModeList.val(); - data.music_notations = sessionData.music_notations; + data.music_notations = JSON.stringify(sessionData.music_notations); + console.log("data.music_notations=%o", data.music_notations); data.timezone = $timezoneList.val(); data.open_rsvps = $screen.find("#open-rsvp")[0].checked; @@ -306,6 +310,7 @@ function uploadNotations(notations) { var formData = new FormData(); var maxExceeded = false; + $.each(notations, function(i, file) { var max = 10 * 1024 * 1024; if(file.size > max) { @@ -326,6 +331,7 @@ } formData.append('client_id', app.clientId); + //formData.append('session_id', sessionId); $btnSelectFiles.text('UPLOADING...').data('uploading', true) $uploadSpinner.show(); return rest.uploadMusicNotations(formData) @@ -362,7 +368,6 @@ } function changeSelectedFiles() { - var $inputFiles = $screen.find('#session-prop-select-files'); var fileNames = []; var files = $inputFiles.get(0).files; var error = false; @@ -400,7 +405,7 @@ } event.preventDefault(); - $('#session-select-files').trigger('click'); + $inputFiles.trigger('click'); return false; } @@ -457,9 +462,10 @@ $fansAccess.val(sessionData.fans_access_value); $screen.find('#session-policy').val(sessionData.legal_policy); + $selectedFilenames.empty(); context._.each(sessionData.music_notations, function(notation) { - var $link = $('').text(notation.file_name); - var $text = $('').text($link); + var $link = notation.viewable ? $('').html(notation.file_name) : '#'; + var $text = $('').html($link); var $file = $('
  • ').append($text); $musicNotations.append($file); }) @@ -473,7 +479,6 @@ app.bindScreen('account/sessionProperties', screenBindings); - $screen = $(".account-session-properties"); $propertiesBody = $screen.find("#account-session-properties-div"); $recurringModeList = $screen.find("#recurring-mode-prop-list"); $languageList = $screen.find("#session-prop-lang-list"); @@ -485,7 +490,7 @@ $musicianAccess = $screen.find("#session-prop-musician-access"); $fansAccess = $screen.find("#session-prop-fans-access"); $musicNotations = $screen.find("#selected-filenames"); - $btnSelectFiles = $screen.find("#select-notation-files"); + $btnSelectFiles = $screen.find(".btn-select-files"); $uploadSpinner = $screen.find(".upload-spinner"); $dateTimeTBD = $screen.find("#date_time_tbd"); diff --git a/web/app/assets/javascripts/dialog/sessionSettingsDialog.js b/web/app/assets/javascripts/dialog/sessionSettingsDialog.js index 3aa5c6f3c..ea18fcd01 100644 --- a/web/app/assets/javascripts/dialog/sessionSettingsDialog.js +++ b/web/app/assets/javascripts/dialog/sessionSettingsDialog.js @@ -8,7 +8,7 @@ var $selectedFilenames = $screen.find('#selected-filenames'); var $uploadSpinner = $screen.find('.upload-spinner'); var $selectedFilenames = $('#settings-selected-filenames'); - var $inputFiles = $('#settings-select-files'); + var $inputFiles = $screen.find('#session-select-files'); var $btnSelectFiles = $screen.find('.btn-select-files'); var rest = new JK.Rest(); var sessionId; @@ -116,37 +116,7 @@ rest.updateSession($('#session-settings-id').val(), data).done(settingsSaved); } - function changeSettingsSelectedFiles() { - var fileNames = []; - var files = $inputFiles.get(0).files; - var error = false; - for (var i = 0; i < files.length; ++i) { - var name = files.item(i).name; - var ext = name.split('.').pop().toLowerCase(); - if ($.inArray(ext, ["pdf", "png", "jpg", "jpeg", "gif", "xml", "mxl", "txt"]) == -1) { - error = true; - break; - } - fileNames.push(name); - } - - if (error) { - app.notifyAlert("Error", "We're sorry, but you can only upload images (.png .jpg .jpeg .gif), text (.txt), PDFs (.pdf), and XML files (.xml .mxl)."); - $inputFiles.replaceWith($inputFiles.clone(true)); - } - else { - // upload as soon as user picks their files. - uploadSettingsNotations($inputFiles.get(0).files) - .done(function() { - context._.each(fileNames, function(fileName) { - var $text = $('').text(fileName); - $selectedFilenames.append($text); - }) - }) - } - } - - function uploadSettingsNotations(notations) { + function uploadNotations(notations) { var formData = new FormData(); var maxExceeded = false; @@ -205,14 +175,44 @@ }); } - function toggleSettingsSelectFiles(event) { + function changeSelectedFiles() { + var fileNames = []; + var files = $inputFiles.get(0).files; + var error = false; + for (var i = 0; i < files.length; ++i) { + var name = files.item(i).name; + var ext = name.split('.').pop().toLowerCase(); + if ($.inArray(ext, ["pdf", "png", "jpg", "jpeg", "gif", "xml", "mxl", "txt"]) == -1) { + error = true; + break; + } + fileNames.push(name); + } + + if (error) { + app.notifyAlert("Error", "We're sorry, but you can only upload images (.png .jpg .jpeg .gif), text (.txt), PDFs (.pdf), and XML files (.xml .mxl)."); + $inputFiles.replaceWith($inputFiles.clone(true)); + } + else { + // upload as soon as user picks their files. + uploadNotations($inputFiles.get(0).files) + .done(function() { + context._.each(fileNames, function(fileName) { + var $text = $('').text(fileName); + $selectedFilenames.append($text); + }) + }) + } + } + + function toggleSelectFiles(event) { if($btnSelectFiles.data('uploading')) { logger.debug("ignoring click of SELECT FILES... while uploading") return false; } event.preventDefault(); - $('#settings-select-files').trigger('click'); + $inputFiles.trigger('click'); return false; } @@ -225,8 +225,8 @@ function events() { $('#session-settings-dialog-submit').on('click', saveSettings); - $inputFiles.on('change', changeSettingsSelectedFiles); - $btnSelectFiles.on('click', toggleSettingsSelectFiles); + $inputFiles.on('change', changeSelectedFiles); + $btnSelectFiles.on('click', toggleSelectFiles); } this.initialize = function() { diff --git a/web/app/assets/javascripts/scheduled_session.js.erb b/web/app/assets/javascripts/scheduled_session.js.erb index e45059c72..e113e4b86 100644 --- a/web/app/assets/javascripts/scheduled_session.js.erb +++ b/web/app/assets/javascripts/scheduled_session.js.erb @@ -28,7 +28,7 @@ var friendInput = null; // Main layout - var $screen = null; + var $screen = $('#create-session-layout'); var $wizardSteps = null; var $currentWizardStep = null; var step = 0; @@ -42,6 +42,7 @@ var $languageList = null; var $sessionPlusMusiciansLabel = null; var $editScheduledSessions = null; + var $inputFiles = $screen.find('#session-select-files'); var $btnSelectFiles = null; var $selectedFilenames = null; var $uploadSpinner = null; @@ -1032,7 +1033,6 @@ } function changeSelectedFiles() { - var $inputFiles = $('#session-step-2 #session-select-files'); var fileNames = []; var files = $inputFiles.get(0).files; var error = false; @@ -1070,7 +1070,7 @@ } event.preventDefault(); - $('#session-select-files').trigger('click'); + $inputFiles.trigger('click'); return false; } @@ -1186,8 +1186,6 @@ function events() { $createTypes.on("ifChanged", toggleCreateType); $startTimeList.on('change', function() { toggleStartTime(); }); - $btnSelectFiles.on('click', toggleSelectFiles); - $('#session-step-2 #session-select-files').on('change', changeSelectedFiles); $policyTypes.on("ifChanged", togglePolicyTypeChanged); $('#session-step-4 #session-musician-access').on('change', toggleMusicianAccessTypes); $('#session-step-4 #session-fans-access').on('change', toggleFanAccessTypes); @@ -1205,6 +1203,9 @@ }); $(friendInput).focus(function() { $(this).val(''); }) + + $inputFiles.on('change', changeSelectedFiles); + $btnSelectFiles.on('click', toggleSelectFiles); } function initialize(invitationDialogInstance, friendSelectorDialog, instrumentSelectorInstance, instrumentRSVPSelectorInstance) { @@ -1221,7 +1222,6 @@ var screenBindings = {'beforeShow': beforeShow, 'afterShow': afterShow}; app.bindScreen('createSession', screenBindings); - $screen = $('#create-session-layout'); $wizardSteps = $screen.find('.create-session-wizard'); $templateSteps = $('#template-session-steps'); $templateButtons = $('#template-session-buttons'); diff --git a/web/app/assets/stylesheets/client/account.css.scss b/web/app/assets/stylesheets/client/account.css.scss index 74183442c..c34722147 100644 --- a/web/app/assets/stylesheets/client/account.css.scss +++ b/web/app/assets/stylesheets/client/account.css.scss @@ -452,6 +452,25 @@ .action-bar { margin-top: 20px; } + + #selected-filenames { + margin-top:10px; + font-size:12px; + + margin-left: 5px; + li { + margin-bottom:1px; + white-space:nowrap; + line-height:14px; + } + + li span { + white-space:nowrap; + text-overflow:ellipsis; + overflow:hidden; + display:block; + } + } } /** account sessions */ diff --git a/web/app/controllers/api_music_sessions_controller.rb b/web/app/controllers/api_music_sessions_controller.rb index c10e79020..c8457d959 100644 --- a/web/app/controllers/api_music_sessions_controller.rb +++ b/web/app/controllers/api_music_sessions_controller.rb @@ -212,13 +212,16 @@ class ApiMusicSessionsController < ApiController @music_session.band = (params[:band] ? Band.find(params[:band]) : nil) if params.include? :band @music_session.save - params[:music_notations].each do |notation_id| - notation = MusicNotation.find(notation_id) - notation.music_session = ms - notation.save + if params.include? :music_notations + notations = JSON.parse(params[:music_notations]) + notations.each do |n| + notation = MusicNotation.find(n["id"]) + notation.music_session = @music_session + notation.save - ms.music_notations << notation - end if params.include? :music_notations + @music_session.music_notations << notation + end + end if @music_session.errors.any? response.status = :unprocessable_entity diff --git a/web/app/views/clients/_account_session_properties.html.haml b/web/app/views/clients/_account_session_properties.html.haml index 69a6364d5..f50398b23 100644 --- a/web/app/views/clients/_account_session_properties.html.haml +++ b/web/app/views/clients/_account_session_properties.html.haml @@ -98,12 +98,12 @@ Notation Files: .right-column .spinner-small.upload-spinner - .selected-files-section - %ul#selected-filenames .select-files-section - %a{href: "#", class: "button-orange btn-select-files", id: "select-notation-files"} SELECT FILES... - %input{type: "file", class: "hidden", id: "session-prop-select-files", value: "Select Files...", + %a.button-orange.btn-select-files SELECT FILES... + %input{type: "file", class: "hidden", id: "session-select-files", value: "Select Files...", accept: ".pdf, .png, .jpg, .jpeg, .gif, .xml, .mxl, .txt", multiple: "true"} + .selected-files-section + %ul#selected-filenames .clearall .clearall .clearall diff --git a/web/app/views/clients/_sessionSettings.html.haml b/web/app/views/clients/_sessionSettings.html.haml index 5a3523c13..3a115260a 100644 --- a/web/app/views/clients/_sessionSettings.html.haml +++ b/web/app/views/clients/_sessionSettings.html.haml @@ -59,7 +59,7 @@ %div{:id => "settings-selected-filenames"} .right.ib.mb10 %a.button-orange.btn-select-files SELECT FILES... - %input.hidden{:type => "file", :id => "settings-select-files", :value => "Select Files...", :accept => ".pdf, .png, .jpg, .jpeg, .gif, .xml, .mxl, .txt"} + %input.hidden{:type => "file", :id => "session-select-files", :value => "Select Files...", :accept => ".pdf, .png, .jpg, .jpeg, .gif, .xml, .mxl, .txt"} .spinner-small.upload-spinner .clearall.right.mt10 From cf4827ba4a829533b8c841b130c33bfaef59204c Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Mon, 27 Oct 2014 21:20:42 -0400 Subject: [PATCH 03/15] VRFS-2337 fix latency calculation for hover bubble --- web/app/assets/javascripts/hoverMusician.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/app/assets/javascripts/hoverMusician.js b/web/app/assets/javascripts/hoverMusician.js index f5f69440a..25ca4ff1b 100644 --- a/web/app/assets/javascripts/hoverMusician.js +++ b/web/app/assets/javascripts/hoverMusician.js @@ -89,7 +89,7 @@ var fullScore = null; if (response.internet_score) { - fullScore = response.last_jam_audio_latency + calculateAudioLatency(response.my_audio_latency) + calculateAudioLatency(response.internet_score); + fullScore = (response.internet_score + calculateAudioLatency(response.my_audio_latency) + calculateAudioLatency(response.last_jam_audio_latency)) / 2; } // latency badge template needs these 2 properties From 8bff2f2692a029b0cc3be818b789a8050744c4e5 Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Mon, 27 Oct 2014 21:35:18 -0400 Subject: [PATCH 04/15] VRFS-2337 fix latency calculation for hover bubble --- web/app/assets/javascripts/hoverMusician.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/web/app/assets/javascripts/hoverMusician.js b/web/app/assets/javascripts/hoverMusician.js index 25ca4ff1b..815cd2f8b 100644 --- a/web/app/assets/javascripts/hoverMusician.js +++ b/web/app/assets/javascripts/hoverMusician.js @@ -88,8 +88,11 @@ var fullScore = null; - if (response.internet_score) { - fullScore = (response.internet_score + calculateAudioLatency(response.my_audio_latency) + calculateAudioLatency(response.last_jam_audio_latency)) / 2; + if (response.internet_score && response.internet_score.length > 0) { + if (response.internet_score[0].score && !isNaN(response.internet_score[0].score)) { + var internetScore = parseInt(response.internet_score[0].score); + fullScore = (response.internet_score + calculateAudioLatency(response.my_audio_latency) + calculateAudioLatency(response.last_jam_audio_latency)) / 2; + } } // latency badge template needs these 2 properties From 2c66aceea88b5984b61e4924d0bd97fe97947777 Mon Sep 17 00:00:00 2001 From: Seth Call Date: Tue, 28 Oct 2014 09:39:39 -0500 Subject: [PATCH 05/15] * VRFS-2407 - show discarded correctly instead of unknown --- web/app/assets/javascripts/sync_viewer.js.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/app/assets/javascripts/sync_viewer.js.coffee b/web/app/assets/javascripts/sync_viewer.js.coffee index 02fd55c1d..51dd2637f 100644 --- a/web/app/assets/javascripts/sync_viewer.js.coffee +++ b/web/app/assets/javascripts/sync_viewer.js.coffee @@ -246,7 +246,7 @@ context.JK.SyncViewer = class SyncViewer clientStateClass = 'missing' clientState = @clientStates.missing else - clientStateClass = 'DISCARDED' + clientStateMsg = 'DISCARDED' clientStateClass = 'discarded' clientState = @clientStates.discarded From 84ee43cdb879da73477b932584c7fde178ae57b5 Mon Sep 17 00:00:00 2001 From: Seth Call Date: Tue, 28 Oct 2014 10:17:28 -0500 Subject: [PATCH 06/15] * VRFS-2409 - detect if the mix is discarded in case of a virtual mix --- .../javascripts/recording_utils.js.coffee | 21 ++++++++++++++----- .../assets/javascripts/sync_viewer.js.coffee | 9 +++++++- .../assets/stylesheets/client/common.css.scss | 2 +- 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/web/app/assets/javascripts/recording_utils.js.coffee b/web/app/assets/javascripts/recording_utils.js.coffee index 3a6dbd002..925029c7d 100644 --- a/web/app/assets/javascripts/recording_utils.js.coffee +++ b/web/app/assets/javascripts/recording_utils.js.coffee @@ -84,17 +84,25 @@ class RecordingUtils mixStateClass = 'discarded' mixState = 'discarded' else - mixStateMsg = 'STILL UPLOADING' - mixStateClass = 'still-uploading' - mixState = 'still-uploading' - return { + if mix.fake and mix.discarded + mixStateMsg = 'DISCARDED' + mixStateClass = 'discarded' + mixState = 'discarded' + else + mixStateMsg = 'STILL UPLOADING' + mixStateClass = 'still-uploading' + mixState = 'still-uploading' + + result = { mixStateMsg: mixStateMsg, mixStateClass: mixStateClass, mixState: mixState, isError: mixState == 'error' } + result + onMixHover: () -> $mix = $(this).closest('.mix') mixStateInfo = $mix.data('mix-state') @@ -114,7 +122,10 @@ class RecordingUtils serverInfo = $mix.data('server-info') # lie if this is a virtualized mix (i.e., mix is created after recording is made) - mixState = 'still-uploading' if !serverInfo? or serverInfo.fake + if !serverInfo? + mixState = 'still-uploading' + else if serverInfo.fake + mixState = if serverInfo.discarded then 'discarded' else 'still-uploading' summary = '' if mixState == 'still-uploading' diff --git a/web/app/assets/javascripts/sync_viewer.js.coffee b/web/app/assets/javascripts/sync_viewer.js.coffee index 51dd2637f..1a749aa3d 100644 --- a/web/app/assets/javascripts/sync_viewer.js.coffee +++ b/web/app/assets/javascripts/sync_viewer.js.coffee @@ -485,7 +485,14 @@ context.JK.SyncViewer = class SyncViewer recordingInfo = null if userSync == 'fake' recordingInfo = arguments[1] - userSync = { recording_id: recordingInfo.id, duration: recordingInfo.duration, fake:true } + # sift through the recorded_tracks in here; if they are marked discarded, then we can also mark this one discarded too + discarded = true + for claim in recordingInfo.claimed_recordings + if claim.user_id == context.JK.currentUserId + discarded = false + break + + userSync = { recording_id: recordingInfo.id, duration: recordingInfo.duration, fake:true, discarded: discarded } $mix = $(context._.template(@templateMix.html(), userSync, {variable: 'data'})) else $mix = $(context._.template(@templateMix.html(), userSync, {variable: 'data'})) diff --git a/web/app/assets/stylesheets/client/common.css.scss b/web/app/assets/stylesheets/client/common.css.scss index 856ad5f21..93183a836 100644 --- a/web/app/assets/stylesheets/client/common.css.scss +++ b/web/app/assets/stylesheets/client/common.css.scss @@ -278,7 +278,7 @@ $fair: #cc9900; color:white; &.still-uploading { background-color: $fair; } - &.discard {background-color: $unknown; } + &.discarded {background-color: $unknown; } &.unknown { background-color: $unknown; } &.error { background-color: $error; } &.mixed { background-color: $good; } From dac291000885f4461bbaf3435fb00f2bd081085d Mon Sep 17 00:00:00 2001 From: Seth Call Date: Tue, 28 Oct 2014 21:16:54 -0500 Subject: [PATCH 07/15] * VRFS-2400 - show retry button only in the correct conditions * VRFS-2425 - make sure threads don't die on exception, but report up --- .../assets/javascripts/sync_viewer.js.coffee | 43 +++++++++++++++---- .../assets/stylesheets/client/common.css.scss | 6 +-- .../lib/jam_websockets/server.rb | 21 +++++++-- 3 files changed, 53 insertions(+), 17 deletions(-) diff --git a/web/app/assets/javascripts/sync_viewer.js.coffee b/web/app/assets/javascripts/sync_viewer.js.coffee index 1a749aa3d..4be93ba13 100644 --- a/web/app/assets/javascripts/sync_viewer.js.coffee +++ b/web/app/assets/javascripts/sync_viewer.js.coffee @@ -220,6 +220,7 @@ context.JK.SyncViewer = class SyncViewer updateTrackState: ($track) => clientInfo = $track.data('client-info') serverInfo = $track.data('server-info') + myTrack = serverInfo.user.id == context.JK.currentUserId # determine client state clientStateMsg = 'UNKNOWN' @@ -261,7 +262,7 @@ context.JK.SyncViewer = class SyncViewer uploadStateClass = 'error' uploadState = @uploadStates.too_many_upload_failures else - if serverInfo.user.id == context.JK.currentUserId + if myTrack if clientInfo? if clientInfo.local_state == 'HQ' uploadStateMsg = 'PENDING UPLOAD' @@ -282,7 +283,7 @@ context.JK.SyncViewer = class SyncViewer else uploadStateMsg = 'UPLOADED' uploadStateClass = 'uploaded' - if serverInfo.user.id == context.JK.currentUserId + if myTrack uploadState = @uploadStates.me_uploaded else uploadState = @uploadStates.them_uploaded @@ -301,6 +302,30 @@ context.JK.SyncViewer = class SyncViewer $uploadStateMsg.text(uploadStateMsg) $uploadStateProgress.css('width', '0') + # this allows us to make styling decisions based on the combination of both client and upload state. + $track.addClass("clientState-#{clientStateClass}").addClass("uploadState-#{uploadStateClass}") + + $clientRetry = $clientState.find('.retry') + $uploadRetry = $uploadState.find('.retry') + + if gon.isNativeClient + # handle client state + + # only show RETRY button if you have a SQ or if it's missing, and it's been uploaded already + if (clientState == @clientStates.sq or clientState == @clientStates.missing) and (uploadState == @uploadStates.me_uploaded or uploadState == @uploadStates.them_uploaded) + $clientRetry.show() + else + $clientRetry.hide() + + # only show RETRY button if you have the HQ track, it's your track, and the server doesn't yet have it + if myTrack and @clientStates.hq and (uploadState == @uploadStates.error or uploadState == @uploadStates.me_upload_soon) + $uploadRetry.show() + else + $uploadRetry.hide() + else + $clientRetry.hide() + $uploadRetry.hide() + associateClientInfo: (recording) => for clientInfo in recording.local_tracks $track = @list.find(".recorded-track[data-recording-id='#{recording.recording_id}'][data-client-track-id='#{clientInfo.client_track_id}']") @@ -511,14 +536,16 @@ context.JK.SyncViewer = class SyncViewer $track.data('sync-viewer', this) $clientState = $track.find('.client-state') $uploadState = $track.find('.upload-state') - $clientState.find('.retry').click(this.retryDownloadRecordedTrack) - $uploadState.find('.retry').click(this.retryUploadRecordedTrack) + $clientStateRetry = $clientState.find('.retry') + $clientStateRetry.click(this.retryDownloadRecordedTrack) + $uploadStateRetry = $uploadState.find('.retry') + $uploadStateRetry.click(this.retryUploadRecordedTrack) context.JK.bindHoverEvents($track) context.JK.bindInstrumentHover($track, {positions:['top'], shrinkToFit: true}); context.JK.hoverBubble($clientState, this.onHoverOfStateIndicator, {width:'450px', closeWhenOthersOpen: true, positions:['left']}) context.JK.hoverBubble($uploadState, this.onHoverOfStateIndicator, {width:'450px', closeWhenOthersOpen: true, positions:['right']}) - $clientState.addClass('is-native-client') if context.jamClient.IsNativeClient() - $uploadState.addClass('is-native-client') if context.jamClient.IsNativeClient() + $clientState.addClass('is-native-client') if gon.isNativeClient + $uploadState.addClass('is-native-client') if gon.isNativeClient $track createStreamMix: (userSync) => @@ -530,8 +557,8 @@ context.JK.SyncViewer = class SyncViewer $uploadState.find('.retry').click(this.retryUploadRecordedTrack) context.JK.hoverBubble($clientState, this.onStreamMixHover, {width:'450px', closeWhenOthersOpen: true, positions:['left']}) context.JK.hoverBubble($uploadState, this.onStreamMixHover, {width:'450px', closeWhenOthersOpen: true, positions:['right']}) - $clientState.addClass('is-native-client') if context.jamClient.IsNativeClient() - $uploadState.addClass('is-native-client') if context.jamClient.IsNativeClient() + $clientState.addClass('is-native-client') if gon.isNativeClient + $uploadState.addClass('is-native-client') if gon.isNativeClient $track exportRecording: (e) => diff --git a/web/app/assets/stylesheets/client/common.css.scss b/web/app/assets/stylesheets/client/common.css.scss index 93183a836..e2f174fe0 100644 --- a/web/app/assets/stylesheets/client/common.css.scss +++ b/web/app/assets/stylesheets/client/common.css.scss @@ -180,6 +180,7 @@ $fair: #cc9900; @mixin client-state-box { + .client-state { position:relative; text-align:center; @@ -193,7 +194,6 @@ $fair: #cc9900; &.error { background-color: $error; - &.is-native-client { .retry { display:inline-block; } } } &.hq { @@ -202,12 +202,10 @@ $fair: #cc9900; &.sq { background-color: $good; - &.is-native-client { .retry { display:inline-block; } } } &.missing { background-color: $error; - &.is-native-client { .retry { display:inline-block; } } } &.discarded { @@ -240,7 +238,6 @@ $fair: #cc9900; &.error { background-color: $error; - &.is-native-client { .retry { display:inline-block; } } } &.missing { @@ -249,7 +246,6 @@ $fair: #cc9900; &.upload-soon { background-color: $fair; - &.is-native-client { .retry { display:inline-block; } } } &.uploaded { diff --git a/websocket-gateway/lib/jam_websockets/server.rb b/websocket-gateway/lib/jam_websockets/server.rb index f03ecf11e..9d27ea040 100644 --- a/websocket-gateway/lib/jam_websockets/server.rb +++ b/websocket-gateway/lib/jam_websockets/server.rb @@ -80,7 +80,7 @@ module JamWebsockets @router.periodical_check_connections EventMachine::PeriodicTimer.new(2) do - sane_logging { @router.periodical_check_connections } + safety_net { sane_logging { @router.periodical_check_connections } } end end @@ -89,7 +89,7 @@ module JamWebsockets @router.periodical_check_clients EventMachine::PeriodicTimer.new(30) do - sane_logging { @router.periodical_check_clients } + safety_net { sane_logging { @router.periodical_check_clients } } end end @@ -98,16 +98,29 @@ module JamWebsockets @router.periodical_flag_connections EventMachine::PeriodicTimer.new(2) do - sane_logging { @router.periodical_flag_connections } + safety_net { sane_logging { @router.periodical_flag_connections } } end end def start_stats_dump EventMachine::PeriodicTimer.new(60) do - @router.periodical_stats_dump + safety_net { @router.periodical_stats_dump } end end + # this was added for this reason: https://jamkazam.atlassian.net/browse/VRFS-2425 + # if an unhandled exception occurs in PeriodicTimer, it just kills all future timers; doesn't kill the app. + # not really what you want. + + # so, we signal to Bugsnag, so we know really bad stuff is happening, but we also move + def safety_net(&blk) + begin + blk.call + rescue => e + Bugsnag.notify(e) + @log.error("unhandled exception in EM Timer #{e}") + end + end def sane_logging(&blk) # used around repeated transactions that cause too much ActiveRecord::Base logging # example is handling heartbeats From 92956c4ee72fe5ad96c2ab725a3ba02d673f13ac Mon Sep 17 00:00:00 2001 From: Seth Call Date: Tue, 28 Oct 2014 22:08:22 -0500 Subject: [PATCH 08/15] * VRFS-2429 - remove empty session; VRFS-1344 - prompt when joining session that is currently recording --- web/app/assets/javascripts/session.js | 15 ++++++++++++++- web/app/assets/javascripts/sessionModel.js | 4 ++-- web/app/assets/javascripts/session_utils.js | 5 +++++ 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/web/app/assets/javascripts/session.js b/web/app/assets/javascripts/session.js index a49148209..c3dbad3b9 100644 --- a/web/app/assets/javascripts/session.js +++ b/web/app/assets/javascripts/session.js @@ -371,6 +371,14 @@ if(response["errors"] && response["errors"]["tracks"] && response["errors"]["tracks"][0] == "Please select at least one track") { app.notifyAlert("No Inputs Configured", $('You will need to reconfigure your audio device.')); } + else if(response["errors"] && response["errors"]["music_session"] && response["errors"]["music_session"][0] == ["is currently recording"]) { + promptLeave = false; + context.window.location = "/client#/findSession"; + app.notify( { title: "Unable to Join Session", text: "The session is currently recording." }, null, true); + } + else { + app.notifyServerError(xhr, 'Unable to Join Session'); + } } else { app.notifyServerError(xhr, 'Unable to Join Session'); @@ -396,7 +404,12 @@ if(screenActive) { // this path is possible if FTUE is invoked on session page, and they cancel sessionModel.leaveCurrentSession() - .fail(app.ajaxError); + .fail(function(jqXHR) { + if(jqXHR.status != 404) { + logger.debug("leave session failed"); + app.ajaxError(arguments) + } + }); } screenActive = false; diff --git a/web/app/assets/javascripts/sessionModel.js b/web/app/assets/javascripts/sessionModel.js index 9bfb3409d..60d8862b8 100644 --- a/web/app/assets/javascripts/sessionModel.js +++ b/web/app/assets/javascripts/sessionModel.js @@ -184,10 +184,10 @@ leaveSessionRest(currentSessionId) .done(function() { sessionChanged(); - deferred.resolve(arguments); + deferred.resolve(arguments[0], arguments[1], arguments[2]); }) .fail(function() { - deferred.reject(arguments); + deferred.reject(arguments[0], arguments[1], arguments[2]); }); // 'unregister' for callbacks diff --git a/web/app/assets/javascripts/session_utils.js b/web/app/assets/javascripts/session_utils.js index 482aaeab1..0c22b0108 100644 --- a/web/app/assets/javascripts/session_utils.js +++ b/web/app/assets/javascripts/session_utils.js @@ -133,6 +133,11 @@ rest.getSession(sessionId) .done(function(response) { session = response; + if(session && session.recording) { + context.JK.app.notify( { title: "Unable to Join Session", text: "The session is currently recording." }, null, true); + return; + } + if ("invitations" in session) { var invitation; // user has invitations for this session From eb5c84c5bce66c4a8d4cdf41222e9f3a23d14ac7 Mon Sep 17 00:00:00 2001 From: Seth Call Date: Tue, 28 Oct 2014 22:25:55 -0500 Subject: [PATCH 09/15] * VRFS-1344 - adding a spec test for it --- web/spec/features/music_sessions_spec.rb | 20 ++++++++++++++++++++ web/spec/support/utilities.rb | 8 +++++--- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/web/spec/features/music_sessions_spec.rb b/web/spec/features/music_sessions_spec.rb index ee22f4158..4f7fba61e 100644 --- a/web/spec/features/music_sessions_spec.rb +++ b/web/spec/features/music_sessions_spec.rb @@ -11,6 +11,26 @@ describe "Music Session", :js => true, :type => :feature, :capybara_feature => t subject { page } + describe "recorded session" do + + before(:each) do + ActiveMusicSession.delete_all + MusicSession.delete_all + end + + let(:searcher) { FactoryGirl.create(:user) } + let(:creator) { FactoryGirl.create(:user) } + let(:conn) { FactoryGirl.create(:connection, :user => creator) } + let(:description) {'hot recordings in here'} + let(:session) {FactoryGirl.create(:active_music_session, creator:creator, description: description)} + let(:recording) {FactoryGirl.create(:recording, music_session: session, owner: creator)} + + it "won't let user join" do + recording.touch + join_session(searcher, description:'hot recordings in here', no_verify:true) + find('#notification p').text('The session is currently recording.') + end + end context "last person" do before(:each) do diff --git a/web/spec/support/utilities.rb b/web/spec/support/utilities.rb index e57f78fc7..e459ac8b0 100644 --- a/web/spec/support/utilities.rb +++ b/web/spec/support/utilities.rb @@ -417,9 +417,11 @@ def join_session(joiner, options) # verify the session description is seen by second client expect(page).to have_text(description) find('.join-link').trigger(:click) - find('#btn-accept-terms').trigger(:click) - expect(page).to have_selector('h2', text: 'my tracks') - find('#session-screen .session-mytracks .session-track') + unless options[:no_verify] + find('#btn-accept-terms').trigger(:click) + expect(page).to have_selector('h2', text: 'my tracks') + find('#session-screen .session-mytracks .session-track') + end end end From 6d8ec70087e67557997615dcb1baab6bc5c0840f Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Wed, 29 Oct 2014 07:12:43 -0400 Subject: [PATCH 10/15] VRFS-2401 text links in emails should be yellow --- .../app/views/jam_ruby/corp_mailer/feedback.html.erb | 2 +- .../invited_user_mailer/friend_invitation.html.erb | 2 +- .../invited_user_mailer/welcome_betauser.html.erb | 2 +- .../jam_ruby/progress_mailer/client_dl_notrun.html.erb | 2 +- .../jam_ruby/progress_mailer/client_notdl.html.erb | 4 ++-- .../progress_mailer/client_run_notgear.html.erb | 4 ++-- .../jam_ruby/progress_mailer/gear_notsess.html.erb | 4 ++-- .../jam_ruby/progress_mailer/reg_notconnect.html.erb | 4 ++-- .../jam_ruby/progress_mailer/reg_notinvite.html.erb | 2 +- .../jam_ruby/progress_mailer/sess_notgood.html.erb | 2 +- .../jam_ruby/user_mailer/band_session_join.html.erb | 2 +- .../views/jam_ruby/user_mailer/confirm_email.html.erb | 2 +- .../views/jam_ruby/user_mailer/friend_request.html.erb | 2 +- .../user_mailer/musician_session_join.html.erb | 2 +- .../views/jam_ruby/user_mailer/new_musicians.html.erb | 2 +- .../views/jam_ruby/user_mailer/password_reset.html.erb | 2 +- .../user_mailer/scheduled_session_cancelled.html.erb | 2 +- .../user_mailer/scheduled_session_comment.html.erb | 2 +- .../user_mailer/scheduled_session_daily.html.erb | 4 ++-- .../user_mailer/scheduled_session_invitation.html.erb | 2 +- .../user_mailer/scheduled_session_reminder.html.erb | 2 +- .../user_mailer/scheduled_session_rescheduled.html.erb | 2 +- .../user_mailer/scheduled_session_rsvp.html.erb | 2 +- .../scheduled_session_rsvp_approved.html.erb | 2 +- .../scheduled_session_rsvp_cancelled.html.erb | 2 +- .../scheduled_session_rsvp_cancelled_org.html.erb | 2 +- .../views/jam_ruby/user_mailer/text_message.html.erb | 2 +- .../views/jam_ruby/user_mailer/updating_email.html.erb | 2 +- .../jam_ruby/user_mailer/welcome_message.html.erb | 10 +++++----- .../app/views/layouts/from_user_mailer.html.erb | 5 ++++- .../jam_ruby/app/views/layouts/user_mailer.html.erb | 6 ++++-- 31 files changed, 46 insertions(+), 41 deletions(-) diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/corp_mailer/feedback.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/corp_mailer/feedback.html.erb index 611a9891b..7daab2af6 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/corp_mailer/feedback.html.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/corp_mailer/feedback.html.erb @@ -8,7 +8,7 @@

    -This email was received because someone left feedback at http://www.jamkazam.com/corp/contact +This email was received because someone left feedback at http://www.jamkazam.com/corp/contact

    diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/invited_user_mailer/friend_invitation.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/invited_user_mailer/friend_invitation.html.erb index 7667ae9fd..11c4bffd7 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/invited_user_mailer/friend_invitation.html.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/invited_user_mailer/friend_invitation.html.erb @@ -1,7 +1,7 @@ <% provide(:title, "You've been invited to JamKazam by #{@sender.name}!") %> <% provide(:photo_url, @sender.resolved_photo_url) %> -To signup, please go to the create account page. +To signup, please go to the create account page. <% content_for :note do %> <% if @note %> diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/invited_user_mailer/welcome_betauser.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/invited_user_mailer/welcome_betauser.html.erb index 8cc412c4f..c1aafeaee 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/invited_user_mailer/welcome_betauser.html.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/invited_user_mailer/welcome_betauser.html.erb @@ -1,3 +1,3 @@ <% provide(:title, 'Welcome to the JamKazam Beta!') %> -To signup, please go to the create account page. \ No newline at end of file +To signup, please go to the create account page. \ No newline at end of file diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/client_dl_notrun.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/client_dl_notrun.html.erb index 50719e908..88d388512 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/client_dl_notrun.html.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/client_dl_notrun.html.erb @@ -7,7 +7,7 @@

    -https://jamkazam.desk.com +https://jamkazam.desk.com

    -- Team JamKazam diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/client_notdl.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/client_notdl.html.erb index cb221e5c9..500479365 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/client_notdl.html.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/client_notdl.html.erb @@ -7,11 +7,11 @@

    -Go to Download Page +Go to Download Page

    -Go to Support Center +Go to Support Center

    -- Team JamKazam diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/client_run_notgear.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/client_run_notgear.html.erb index c561dd267..a06990e41 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/client_run_notgear.html.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/client_run_notgear.html.erb @@ -6,13 +6,13 @@

    We noticed that you have not yet successfully set up your audio gear and passed the JamKazam latency and input/output audio gear tests. This means that you cannot yet play in online sessions with other musicians. If you are having trouble with this step, please click the link below for a knowledge base article that can help you get past this hurdle. If the test says your audio gear is not fast enough, or if your audio quality sounds poor, or if you are just confused, it’s very likely the tips in this article will help you get things set up and optimized so you can start playing online.

    -

    http://bit.ly/1i4Uul4 +

    http://bit.ly/1i4Uul4

    And if this knowledge base article does not get you fixed up, please visit our JamKazam support center at the link below, and post a request for assistance so that we can help you get up and running:

    -

    https://jamkazam.desk.com +

    https://jamkazam.desk.com

    -- Team JamKazam diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/gear_notsess.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/gear_notsess.html.erb index 75b82aa15..3d96ac749 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/gear_notsess.html.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/gear_notsess.html.erb @@ -10,7 +10,7 @@ It’s still very early in our company’s development, so we don’t have zillions of users online on our service yet. If you click Find Session, you will often not find a good session to join, both due to the number of musicians online at any given time, and also because you won’t see private sessions where groups of musicians don’t want to be interrupted in their sessions.

    -

    If you are having trouble getting into sessions, we’d suggest you click the Musicians tile on the home screen of the app or the website: Go To Musicians Page +

    If you are having trouble getting into sessions, we’d suggest you click the Musicians tile on the home screen of the app or the website: Go To Musicians Page

    This will display the JamKazam musicians sorted by latency to you - in other words, you can see which musicians have good network connections to you. Any musicians with green and yellow latency scores have good enough connections to support a play session with you. We recommend that read the profiles of these musicians to find others with shared musical interests and good network connections to you, and then use the Message button to say hi and see if they are interested in playing with you. If they are, use the Connect button to “friend” them on JamKazam, and use the Message button to set up a time to meet online for a session. @@ -24,7 +24,7 @@ One of the best ways to connect and play with others is to invite your friends f If you are having audio quality problems or other issues when you get into a session, please click the link below to visit our support center, and check the knowledge base articles under the Troubleshooting header to find solutions. And if that doesn’t work, please post a request for assistance in the support center so that we can help you get up and running:

    -

    https://jamkazam.desk.com +

    https://jamkazam.desk.com

    -- Team JamKazam diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/reg_notconnect.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/reg_notconnect.html.erb index 59254f3ab..0751b7388 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/reg_notconnect.html.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/reg_notconnect.html.erb @@ -7,7 +7,7 @@

    Find Other Musicians on JamKazam
    -To find and connect with other musicians who are already on JamKazam, we’d suggest you click the Musicians tile on the home screen of the app or the website: Go To Musicians Page +To find and connect with other musicians who are already on JamKazam, we’d suggest you click the Musicians tile on the home screen of the app or the website: Go To Musicians Page

    This will display the JamKazam musicians sorted by latency to you - in other words, you can see which musicians have good network connections to you. Any musicians with green and yellow latency scores have good enough connections to support a play session with you. We recommend that you read the profiles of these musicians to find others with shared musical interests and good network connections to you, and then use the Message button to say hi and see if they are interested in playing with you. If they are, use the Connect button to “friend” them on JamKazam, and use the Message button to set up a time to meet online for a session. @@ -20,7 +20,7 @@ One of the best ways to connect and play with others is to invite your friends f

    If you have any trouble, please visit our support center at the link below any time to get help:

    -

    https://jamkazam.desk.com +

    https://jamkazam.desk.com

    -- Team JamKazam diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/reg_notinvite.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/reg_notinvite.html.erb index ef9bba2bc..0794830df 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/reg_notinvite.html.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/reg_notinvite.html.erb @@ -9,7 +9,7 @@

    If you have any trouble, please visit our support center at the link below any time to get help:

    -

    https://jamkazam.desk.com +

    https://jamkazam.desk.com

    -- Team JamKazam diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/sess_notgood.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/sess_notgood.html.erb index 60ed88c69..adc2dc5c1 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/sess_notgood.html.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/progress_mailer/sess_notgood.html.erb @@ -9,7 +9,7 @@

    If you are having audio quality problems or other issues when you get into a session, please click the link below to visit our support center, and check the knowledge base articles under the Troubleshooting header to find solutions. And if that doesn’t work, please post a request for assistance in the support center so that we can help you get up and running:

    -

    https://jamkazam.desk.com +

    https://jamkazam.desk.com

    We really want you to be successful and have fun with this new way of playing music with others, so please reach out and let us help you! diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/band_session_join.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/band_session_join.html.erb index 3106f63df..276ae4fcc 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/band_session_join.html.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/band_session_join.html.erb @@ -1,3 +1,3 @@ <% provide(:title, 'New Band Session') %> -

    <%= @body %> Listen in.

    \ No newline at end of file +

    <%= @body %> Listen in.

    \ No newline at end of file diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/confirm_email.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/confirm_email.html.erb index 7c85b9df4..651d1c236 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/confirm_email.html.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/confirm_email.html.erb @@ -2,4 +2,4 @@

    Welcome to JamKazam, <%= @user.first_name %>!

    -

    To confirm this email address, please go to the signup confirmation page.

    +

    To confirm this email address, please go to the signup confirmation page.

    diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/friend_request.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/friend_request.html.erb index 56b9c3623..cf9df2fe2 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/friend_request.html.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/friend_request.html.erb @@ -2,4 +2,4 @@

    <%= @body %>

    -

    To accept this friend request, click here.

    +

    To accept this friend request, click here.

    diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/musician_session_join.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/musician_session_join.html.erb index 97a709a97..de2b7e43c 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/musician_session_join.html.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/musician_session_join.html.erb @@ -1,3 +1,3 @@ <% provide(:title, 'Musician in Session') %> -

    <%= @body %> Listen in.

    \ No newline at end of file +

    <%= @body %> Listen in.

    \ No newline at end of file diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/new_musicians.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/new_musicians.html.erb index bf5f12c0e..8551c23df 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/new_musicians.html.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/new_musicians.html.erb @@ -24,7 +24,7 @@ Hi <%= @user.first_name %>, <% end %>

    -

    There are currently <%= @new_musicians.size%> musicians on JamKazam with low enough latency Internet connections to you to support a good online session. To see ALL the JamKazam musicians with whom you may want to connect and play, view our Musicians page at: http://www.jamkazam.com/client#/musicians. +

    There are currently <%= @new_musicians.size%> musicians on JamKazam with low enough latency Internet connections to you to support a good online session. To see ALL the JamKazam musicians with whom you may want to connect and play, view our Musicians page at: http://www.jamkazam.com/client#/musicians.

    Best Regards,

    diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/password_reset.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/password_reset.html.erb index 49a0a90bd..2ac4845c6 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/password_reset.html.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/password_reset.html.erb @@ -1,3 +1,3 @@ <% provide(:title, 'JamKazam Password Reset') %> -Visit this link so that you can change your JamKazam password: reset password. \ No newline at end of file +Visit this link so that you can change your JamKazam password: reset password. \ No newline at end of file diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_cancelled.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_cancelled.html.erb index d0ff59dc2..4fa8eb0f9 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_cancelled.html.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_cancelled.html.erb @@ -2,4 +2,4 @@

    <%= @body %>

    -

    View Session Details

    \ No newline at end of file +

    View Session Details

    \ No newline at end of file diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_comment.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_comment.html.erb index a367a7444..af6bac519 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_comment.html.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_comment.html.erb @@ -7,5 +7,5 @@

    <%= @session_name %>

    <%= @session_date %>

    -

    View Session Details

    +

    View Session Details

    <% end %> \ No newline at end of file diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_daily.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_daily.html.erb index 5fb602b24..221c06839 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_daily.html.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_daily.html.erb @@ -68,7 +68,7 @@ <%= sess.genre.description %> <%= sess.name %>
    - ">Details + ">Details <%= sess.description %> @@ -86,7 +86,7 @@ -

    To see ALL the scheduled sessions that you might be interested in joining, view our Find Session page.

    +

    To see ALL the scheduled sessions that you might be interested in joining, view our Find Session page.

    Best Regards,

    diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_invitation.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_invitation.html.erb index 7e62e683a..a3e774395 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_invitation.html.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_invitation.html.erb @@ -7,4 +7,4 @@ <%= @session_date %>

    -

    View Session Details

    \ No newline at end of file +

    View Session Details

    \ No newline at end of file diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_reminder.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_reminder.html.erb index 1521bd74a..c8514b939 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_reminder.html.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_reminder.html.erb @@ -7,4 +7,4 @@ <%= @session_date %>

    -

    View Session Details

    \ No newline at end of file +

    View Session Details

    \ No newline at end of file diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_rescheduled.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_rescheduled.html.erb index e0e534018..9331036ca 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_rescheduled.html.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_rescheduled.html.erb @@ -7,4 +7,4 @@ <%= @session_date %>

    -

    View Session Details

    \ No newline at end of file +

    View Session Details

    \ No newline at end of file diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_rsvp.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_rsvp.html.erb index c615903a8..046f1847f 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_rsvp.html.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_rsvp.html.erb @@ -7,4 +7,4 @@ <%= @session_date %>

    -

    View Session Details

    \ No newline at end of file +

    View Session Details

    \ No newline at end of file diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_rsvp_approved.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_rsvp_approved.html.erb index 03305ce72..e12cab821 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_rsvp_approved.html.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_rsvp_approved.html.erb @@ -7,4 +7,4 @@ <%= @session_date %>

    -

    View Session Details

    \ No newline at end of file +

    View Session Details

    \ No newline at end of file diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_rsvp_cancelled.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_rsvp_cancelled.html.erb index b7740ea1a..0c996aa5d 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_rsvp_cancelled.html.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_rsvp_cancelled.html.erb @@ -7,4 +7,4 @@ <%= @session_date %>

    -

    View Session Details

    \ No newline at end of file +

    View Session Details

    \ No newline at end of file diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_rsvp_cancelled_org.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_rsvp_cancelled_org.html.erb index 3cfa830d0..05ce13a7e 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_rsvp_cancelled_org.html.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_rsvp_cancelled_org.html.erb @@ -7,4 +7,4 @@ <%= @session_date %>

    -

    View Session Details

    \ No newline at end of file +

    View Session Details

    \ No newline at end of file diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/text_message.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/text_message.html.erb index cb083ca1b..879c27c2c 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/text_message.html.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/text_message.html.erb @@ -4,5 +4,5 @@ <% content_for :note do %> <%= @note %> -

    To reply to this message, click here.

    +

    To reply to this message, click here.

    <% end %> diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/updating_email.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/updating_email.html.erb index 0617f81ae..b0792e217 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/updating_email.html.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/updating_email.html.erb @@ -1,3 +1,3 @@ <% provide(:title, 'Please Confirm New JamKazam Email') %> -Please click the following link to confirm your change in email: confirm email. \ No newline at end of file +Please click the following link to confirm your change in email: confirm email. \ No newline at end of file diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/welcome_message.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/welcome_message.html.erb index b74876e92..5b663b7ee 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/welcome_message.html.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/welcome_message.html.erb @@ -11,31 +11,31 @@

    Getting Started Video
    We recommend watching this video before you jump into the service just to get oriented. It will really help you hit the ground running: -https://www.youtube.com/watch?v=VexH4834o9I +https://www.youtube.com/watch?v=VexH4834o9I

    Other Great Tutorial Videos
    There are several other very great videos that will help you understand how to find and connect with other musicians on the service, create your own sessions or find and join other musicians’ sessions, play in sessions, record and share your performances, and even live broadcast your sessions to family, friends, and fans. Check these helpful videos out here: -https://jamkazam.desk.com/customer/portal/articles/1304097-tutorial-videos +https://jamkazam.desk.com/customer/portal/articles/1304097-tutorial-videos

    Knowledge Base Articles
    You can find Getting Started knowledge base articles on things like frequently asked questions (FAQ), minimum system requirements for your Windows or Mac computer, how to troubleshoot audio problems in sessions, and more here: -https://jamkazam.desk.com/customer/portal/topics/564807-getting-started/articles +https://jamkazam.desk.com/customer/portal/topics/564807-getting-started/articles

    JamKazam Support Portal
    If you run into trouble and need help, please reach out to us. We will be glad to do everything we can to get you up and running. You can find our support portal here: -https://jamkazam.desk.com/ +https://jamkazam.desk.com/

    JamKazam Community Forum
    And if you just want to chat, share tips and war stories, and hang out with fellow JamKazamers, you can visit our community forum here: -http://forums.jamkazam.com/ +http://forums.jamkazam.com/

    diff --git a/ruby/lib/jam_ruby/app/views/layouts/from_user_mailer.html.erb b/ruby/lib/jam_ruby/app/views/layouts/from_user_mailer.html.erb index 8ce59bc6b..aa1d520f8 100644 --- a/ruby/lib/jam_ruby/app/views/layouts/from_user_mailer.html.erb +++ b/ruby/lib/jam_ruby/app/views/layouts/from_user_mailer.html.erb @@ -9,6 +9,9 @@ margin-bottom:0px; line-height:140%; } + a { + color: #ffcc00 !important; + } @@ -48,7 +51,7 @@

    -

    This email was sent to you because you have an account at JamKazam. +

    This email was sent to you because you have an account at JamKazam. diff --git a/ruby/lib/jam_ruby/app/views/layouts/user_mailer.html.erb b/ruby/lib/jam_ruby/app/views/layouts/user_mailer.html.erb index 3509aa0bc..7e411bbc9 100644 --- a/ruby/lib/jam_ruby/app/views/layouts/user_mailer.html.erb +++ b/ruby/lib/jam_ruby/app/views/layouts/user_mailer.html.erb @@ -9,7 +9,9 @@ margin-bottom:0px; line-height:140%; } - + a { + color: #ffcc00 !important; + } @@ -37,7 +39,7 @@ -

    This email was sent to you because you have an account at JamKazam.  Click here to unsubscribe and update your profile settings. +

    This email was sent to you because you have an account at JamKazam.  Click here to unsubscribe and update your profile settings.

    From 28e752629a6be749972efc663e1bc0de216d7562 Mon Sep 17 00:00:00 2001 From: Seth Call Date: Wed, 29 Oct 2014 07:22:45 -0500 Subject: [PATCH 11/15] * show private recording on recording landing page to someone who was in the session --- ruby/lib/jam_ruby/lib/nav.rb | 4 ++ web/app/views/recordings/show.html.erb | 4 +- web/spec/features/recording_landing_spec.rb | 79 ++++++++++++++------- 3 files changed, 60 insertions(+), 27 deletions(-) diff --git a/ruby/lib/jam_ruby/lib/nav.rb b/ruby/lib/jam_ruby/lib/nav.rb index 7f58dad61..bfc788471 100644 --- a/ruby/lib/jam_ruby/lib/nav.rb +++ b/ruby/lib/jam_ruby/lib/nav.rb @@ -27,6 +27,10 @@ module JamRuby "#{base_url}/findSession" end + def self.session(session) + "#{base_url}/session/#{session.id}" + end + private def self.base_url diff --git a/web/app/views/recordings/show.html.erb b/web/app/views/recordings/show.html.erb index 747f6c383..b8e2bf74a 100644 --- a/web/app/views/recordings/show.html.erb +++ b/web/app/views/recordings/show.html.erb @@ -18,7 +18,7 @@ <% end %>
    -<% if @claimed_recording.is_public %> +<% if @claimed_recording.is_public || @claimed_recording.recording.has_access?(current_user) %>
    <% unless @claimed_recording.recording.band.blank? %>
    @@ -97,7 +97,7 @@ <% end %>
    -<% if @claimed_recording.is_public %> +<% if @claimed_recording.is_public || @claimed_recording.recording.has_access?(current_user) %> <% if signed_in? %> <% unless @claimed_recording.recording.band.nil? %> <%= render :partial => "shared/landing_sidebar", :locals => {:user => @claimed_recording.recording.band, :recent_history => @claimed_recording.recording.band.recent_history} %> diff --git a/web/spec/features/recording_landing_spec.rb b/web/spec/features/recording_landing_spec.rb index 45875b53b..6bf9f7beb 100644 --- a/web/spec/features/recording_landing_spec.rb +++ b/web/spec/features/recording_landing_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe "Landing", :js => true, :type => :feature, :capybara_feature => true do +describe "Landing" do let (:user) { FactoryGirl.create(:user) } @@ -10,41 +10,70 @@ describe "Landing", :js => true, :type => :feature, :capybara_feature => true do Recording.delete_all end - before(:each) do - MusicSession.delete_all - sign_in_poltergeist(user) - end let (:claimed_recording) { FactoryGirl.create(:claimed_recording) } + let (:recording) { claimed_recording.recording } - it "should render comments" do + describe "no js required" do - recording = ClaimedRecording.first - comment = "test comment" - timestamp = "less than a minute ago" - url = "/recordings/#{claimed_recording.id}" - visit url + it "shows private recording to someone who was in the session" do + # make the session hidden + claimed_recording.is_public = false + claimed_recording.save! - fill_in "txtRecordingComment", with: comment - find('#btnPostComment').trigger(:click) + visit "/recordings/#{claimed_recording.id}" - # (1) Test a user creating a comment and ensure it displays. + # and verify that after we visit the page, we can see the name of it + find('strong', text: 'RECORDING NOT FOUND') - # comment body - find('div.comment-text', text: comment) + # log in the user who was a part of the session + sign_in(claimed_recording.user) - # timestamp - find('div.comment-timestamp', text: timestamp) + visit "/recordings/#{claimed_recording.id}" - # (2) Test a user visiting a landing page with an existing comment. + # and verify that after we visit the page, we can see the name of it + find('h2', text: claimed_recording.name) + end + end - # re-visit page to reload from database - visit url - # comment body - find('div.comment-text', text: comment) + describe "js required", :js => true, :type => :feature, :capybara_feature => true do - # timestamp - find('div.comment-timestamp', text: timestamp) + before(:each) do + MusicSession.delete_all + sign_in_poltergeist(user) + end + + + it "should render comments" do + + recording = ClaimedRecording.first + comment = "test comment" + timestamp = "less than a minute ago" + url = "/recordings/#{claimed_recording.id}" + visit url + + fill_in "txtRecordingComment", with: comment + find('#btnPostComment').trigger(:click) + + # (1) Test a user creating a comment and ensure it displays. + + # comment body + find('div.comment-text', text: comment) + + # timestamp + find('div.comment-timestamp', text: timestamp) + + # (2) Test a user visiting a landing page with an existing comment. + + # re-visit page to reload from database + visit url + + # comment body + find('div.comment-text', text: comment) + + # timestamp + find('div.comment-timestamp', text: timestamp) + end end end \ No newline at end of file From 149967f87748cd932c5d82f218fbe71d2bd52fe8 Mon Sep 17 00:00:00 2001 From: Seth Call Date: Wed, 29 Oct 2014 10:27:29 -0500 Subject: [PATCH 12/15] * VRFS-2375 - share button works now in master mix complete msg --- pb/src/client_container.proto | 1 + ruby/lib/jam_ruby/message_factory.rb | 3 ++- ruby/lib/jam_ruby/models/notification.rb | 1 + web/app/assets/javascripts/notificationPanel.js | 7 +++++-- 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/pb/src/client_container.proto b/pb/src/client_container.proto index b9a7aeba0..5515757d9 100644 --- a/pb/src/client_container.proto +++ b/pb/src/client_container.proto @@ -481,6 +481,7 @@ message RecordingMasterMixComplete { optional string msg = 3; optional string notification_id = 4; optional string created_at = 5; + optional string claimed_recording_id = 6; } message DownloadAvailable { diff --git a/ruby/lib/jam_ruby/message_factory.rb b/ruby/lib/jam_ruby/message_factory.rb index 7ece76e28..f5666089a 100644 --- a/ruby/lib/jam_ruby/message_factory.rb +++ b/ruby/lib/jam_ruby/message_factory.rb @@ -712,9 +712,10 @@ module JamRuby ) end - def recording_master_mix_complete(receiver_id, recording_id, band_id, msg, notification_id, created_at) + def recording_master_mix_complete(receiver_id, recording_id, claimed_recording_id, band_id, msg, notification_id, created_at) recording_master_mix_complete = Jampb::RecordingMasterMixComplete.new( :recording_id => recording_id, + :claimed_recording_id => claimed_recording_id, :band_id => band_id, :msg => msg, :notification_id => notification_id, diff --git a/ruby/lib/jam_ruby/models/notification.rb b/ruby/lib/jam_ruby/models/notification.rb index 77b2c2394..adb481c81 100644 --- a/ruby/lib/jam_ruby/models/notification.rb +++ b/ruby/lib/jam_ruby/models/notification.rb @@ -1147,6 +1147,7 @@ module JamRuby msg = @@message_factory.recording_master_mix_complete( claimed_recording.user_id, recording.id, + claimed_recording.id, notification.band_id, notification_msg, notification.id, diff --git a/web/app/assets/javascripts/notificationPanel.js b/web/app/assets/javascripts/notificationPanel.js index 1e56483f3..e91e049b8 100644 --- a/web/app/assets/javascripts/notificationPanel.js +++ b/web/app/assets/javascripts/notificationPanel.js @@ -25,6 +25,7 @@ var notificationBatchSize = 20; var currentNotificationPage = 0; var didLoadAllNotifications = false, isLoading = false; + var ui = new context.JK.UIHelper(JK.app); function isNotificationsPanelVisible() { return $contents.is(':visible') @@ -1101,7 +1102,7 @@ "class": "button-orange", callback: shareRecording, callback_args: { - "recording_id": payload.recording_id + "claimed_recording_id": payload.claimed_recording_id } }] ); @@ -1109,7 +1110,9 @@ } function shareRecording(args) { - var recordingId = args.recording_id; + var claimedRecordingId = args.claimed_recording_id; + + ui.launchShareDialog(claimedRecordingId, 'recording'); } function registerBandInvitation() { From 62833198b30a72e5407cc4b379885c82673a1ac0 Mon Sep 17 00:00:00 2001 From: Seth Call Date: Wed, 29 Oct 2014 11:28:13 -0500 Subject: [PATCH 13/15] * VRFS-2431 - run normalize-ogg and normalize-mp3 to bump up master mix --- admin/config/application.rb | 2 ++ ruby/lib/jam_ruby/resque/audiomixer.rb | 24 ++++++++++++++++++++++++ ruby/spec/support/utilities.rb | 8 ++++++++ web/config/application.rb | 2 ++ 4 files changed, 36 insertions(+) diff --git a/admin/config/application.rb b/admin/config/application.rb index 573e946f0..08b11d58c 100644 --- a/admin/config/application.rb +++ b/admin/config/application.rb @@ -126,6 +126,8 @@ module JamAdmin config.twitter_app_secret = ENV['TWITTER_APP_SECRET'] || 'Azcy3QqfzYzn2fsojFPYXcn72yfwa0vG6wWDrZ3KT8' config.ffmpeg_path = ENV['FFMPEG_PATH'] || (File.exist?('/usr/local/bin/ffmpeg') ? '/usr/local/bin/ffmpeg' : '/usr/bin/ffmpeg') + config.normalize_ogg_path = ENV['NORMALIZE_OGG_PATH'] || (File.exist?('/usr/local/bin/normalize-ogg') ? '/usr/local/bin/normalize-ogg' : '/usr/bin/normalize-ogg') + config.normalize_mp3_path = ENV['NORMALIZE_MP3_PATH'] || (File.exist?('/usr/local/bin/normalize-mp3') ? '/usr/local/bin/normalize-mp3' : '/usr/bin/normalize-mp3') config.max_audio_downloads = 100 diff --git a/ruby/lib/jam_ruby/resque/audiomixer.rb b/ruby/lib/jam_ruby/resque/audiomixer.rb index 66973b12a..8d9ded366 100644 --- a/ruby/lib/jam_ruby/resque/audiomixer.rb +++ b/ruby/lib/jam_ruby/resque/audiomixer.rb @@ -335,6 +335,30 @@ module JamRuby end raise "no output mp3 file after conversion" unless File.exist? @output_mp3_filename + + # time to normalize both mp3 and ogg files + + normalize_ogg_cmd = "#{APP_CONFIG.normalize_ogg_path} --bitrate 128 -i \"#{@output_ogg_filename}\"" + system(normalize_ogg_cmd) + unless $? == 0 + @error_reason = 'normalize-ogg-failed' + @error_detail = $?.to_s + error_msg = "normalize-ogg failed status=#{$?} error_reason=#{@error_reason} error_detail=#{@error_detail}" + @@log.info(error_msg) + raise error_msg + end + raise "no output ogg file after normalization" unless File.exist? @output_ogg_filename + + normalize_mp3_cmd = "#{APP_CONFIG.normalize_mp3_path} --bitrate 128 -i \"#{@output_mp3_filename}\"" + system(normalize_mp3_cmd) + unless $? == 0 + @error_reason = 'normalize-mp3-failed' + @error_detail = $?.to_s + error_msg = "normalize-mp3 failed status=#{$?} error_reason=#{@error_reason} error_detail=#{@error_detail}" + @@log.info(error_msg) + raise error_msg + end + raise "no output mp3 file after conversion" unless File.exist? @output_mp3_filename end def symbolize_keys(obj) diff --git a/ruby/spec/support/utilities.rb b/ruby/spec/support/utilities.rb index 7c625ed78..0ed42f4d9 100644 --- a/ruby/spec/support/utilities.rb +++ b/ruby/spec/support/utilities.rb @@ -38,6 +38,14 @@ def app_config ENV['FFMPEG_PATH'] || '/usr/local/bin/ffmpeg' end + def normalize_ogg_path + ENV['NORMALIZE_OGG_PATH'] || '/usr/local/bin/normalize-ogg' + end + + def normalize_mp3_path + ENV['NORMALIZE_MP3_PATH'] || '/usr/local/bin/normalize-mp3' + end + def icecast_reload_cmd 'true' # as in, /bin/true end diff --git a/web/config/application.rb b/web/config/application.rb index ed7798fbf..b15e13426 100644 --- a/web/config/application.rb +++ b/web/config/application.rb @@ -178,6 +178,8 @@ if defined?(Bundler) config.audiomixer_path = "/var/lib/audiomixer/audiomixer/audiomixerapp" config.ffmpeg_path = ENV['FFMPEG_PATH'] || (File.exist?('/usr/local/bin/ffmpeg') ? '/usr/local/bin/ffmpeg' : '/usr/bin/ffmpeg') + config.normalize_ogg_path = ENV['NORMALIZE_OGG_PATH'] || (File.exist?('/usr/local/bin/normalize-ogg') ? '/usr/local/bin/normalize-ogg' : '/usr/bin/normalize-ogg') + config.normalize_mp3_path = ENV['NORMALIZE_MP3_PATH'] || (File.exist?('/usr/local/bin/normalize-mp3') ? '/usr/local/bin/normalize-mp3' : '/usr/bin/normalize-mp3') # if it looks like linux, use init.d script; otherwise use kill config.icecast_reload_cmd = ENV['ICECAST_RELOAD_CMD'] || (File.exist?('/usr/local/bin/icecast2') ? "bash -l -c #{Shellwords.escape("sudo /etc/init.d/icecast2 reload")}" : "bash -l -c #{Shellwords.escape("kill -1 `ps -f | grep /usr/local/bin/icecast | grep -v grep | awk \'{print $2}\'`")}") From 4ee75adcf204f06f0bb10b5566b2cc6d05062629 Mon Sep 17 00:00:00 2001 From: Seth Call Date: Wed, 29 Oct 2014 13:51:33 -0500 Subject: [PATCH 14/15] * make intermediary mp3 higher bitrate --- ruby/lib/jam_ruby/resque/audiomixer.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruby/lib/jam_ruby/resque/audiomixer.rb b/ruby/lib/jam_ruby/resque/audiomixer.rb index 8d9ded366..da3038622 100644 --- a/ruby/lib/jam_ruby/resque/audiomixer.rb +++ b/ruby/lib/jam_ruby/resque/audiomixer.rb @@ -322,7 +322,7 @@ module JamRuby raise "no output ogg file after mix" unless File.exist? @output_ogg_filename - ffmpeg_cmd = "#{APP_CONFIG.ffmpeg_path} -i \"#{@output_ogg_filename}\" -ab 128k -metadata JamRecordingId=#{@manifest[:recording_id]} -metadata JamMixId=#{@mix_id} -metadata JamType=Mix \"#{@output_mp3_filename}\"" + ffmpeg_cmd = "#{APP_CONFIG.ffmpeg_path} -i \"#{@output_ogg_filename}\" -ab 192k -metadata JamRecordingId=#{@manifest[:recording_id]} -metadata JamMixId=#{@mix_id} -metadata JamType=Mix \"#{@output_mp3_filename}\"" system(ffmpeg_cmd) From 3898857dbfbdb96df6ac06eb240b4ca741f64cec Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Wed, 29 Oct 2014 23:33:48 -0400 Subject: [PATCH 15/15] VRFS-2128 use recording owner for displaying name and hover in feed to ensure it matches avatar --- web/app/helpers/feeds_helper.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/app/helpers/feeds_helper.rb b/web/app/helpers/feeds_helper.rb index 38abfff85..d86ee3253 100644 --- a/web/app/helpers/feeds_helper.rb +++ b/web/app/helpers/feeds_helper.rb @@ -75,11 +75,11 @@ module FeedsHelper end def recording_artist_name(recording) - (recording.band.nil? ? nil : recording.band.name) || recording.candidate_claimed_recording.user.name + (recording.band.nil? ? nil : recording.band.name) || recording.owner.name end def recording_artist_id(recording) - (recording.band.nil? ? nil : recording.band.id) || recording.candidate_claimed_recording.user.id + (recording.band.nil? ? nil : recording.band.id) || recording.owner.id end def recording_artist_hoveraction(recording)