From d6210c0b2f09afa7bd6146d5a6f4a302682b9447 Mon Sep 17 00:00:00 2001 From: Seth Call Date: Tue, 25 Mar 2014 15:29:08 +0000 Subject: [PATCH 1/3] * VRFS-1474 - link in friend invite --- ruby/lib/jam_ruby.rb | 1 + ruby/lib/jam_ruby/app/mailers/user_mailer.rb | 7 +- .../user_mailer/friend_request.html.erb | 4 +- .../user_mailer/friend_request.text.erb | 4 +- .../user_mailer/text_message.html.erb | 2 +- .../user_mailer/text_message.text.erb | 2 +- ruby/lib/jam_ruby/lib/nav.rb | 36 ++++ ruby/lib/jam_ruby/models/friend_request.rb | 4 +- ruby/lib/jam_ruby/models/notification.rb | 4 +- ruby/lib/jam_ruby/models/user.rb | 3 +- ruby/spec/factories.rb | 4 + .../spec/jam_ruby/models/notification_spec.rb | 120 +++++------ ruby/spec/mailers/render_emails_spec.rb | 6 +- .../javascripts/acceptFriendRequestDialog.js | 186 ++++++++++++++++++ web/app/assets/javascripts/jam_rest.js | 20 +- web/app/assets/javascripts/jamkazam.js | 4 + web/app/assets/javascripts/layout.js | 1 - .../assets/javascripts/textMessageDialog.js | 4 +- .../client/acceptFriendRequestDialog.css.scss | 59 ++++++ web/app/assets/stylesheets/client/client.css | 1 + web/app/controllers/api_users_controller.rb | 2 + .../views/api_users/friend_request_show.rabl | 10 +- .../_acceptFriendRequestDialog.html.haml | 49 +++++ web/app/views/clients/index.html.erb | 4 + web/spec/factories.rb | 4 + .../accept_friend_request_dialog_spec.rb | 80 ++++++++ web/spec/features/profile_menu_spec.rb | 2 +- web/spec/support/app_config.rb | 22 +++ web/spec/support/utilities.rb | 4 +- 29 files changed, 566 insertions(+), 83 deletions(-) create mode 100644 ruby/lib/jam_ruby/lib/nav.rb create mode 100644 web/app/assets/javascripts/acceptFriendRequestDialog.js create mode 100644 web/app/assets/stylesheets/client/acceptFriendRequestDialog.css.scss create mode 100644 web/app/views/clients/_acceptFriendRequestDialog.html.haml create mode 100644 web/spec/features/accept_friend_request_dialog_spec.rb create mode 100644 web/spec/support/app_config.rb diff --git a/ruby/lib/jam_ruby.rb b/ruby/lib/jam_ruby.rb index b6103cd16..da72d911b 100755 --- a/ruby/lib/jam_ruby.rb +++ b/ruby/lib/jam_ruby.rb @@ -30,6 +30,7 @@ require "jam_ruby/lib/s3_util" require "jam_ruby/lib/s3_manager" require "jam_ruby/lib/profanity" require "jam_ruby/lib/em_helper.rb" +require "jam_ruby/lib/nav.rb" require "jam_ruby/resque/audiomixer" require "jam_ruby/resque/icecast_config_writer" require "jam_ruby/resque/resque_hooks" diff --git a/ruby/lib/jam_ruby/app/mailers/user_mailer.rb b/ruby/lib/jam_ruby/app/mailers/user_mailer.rb index 4b196e569..0340fdf04 100644 --- a/ruby/lib/jam_ruby/app/mailers/user_mailer.rb +++ b/ruby/lib/jam_ruby/app/mailers/user_mailer.rb @@ -89,10 +89,11 @@ end #################################### NOTIFICATION EMAILS #################################### - def friend_request(email, msg) + def friend_request(email, msg, friend_request_id) subject = "You have a new friend request on JamKazam" unique_args = {:type => "friend_request"} - + + @url = Nav.accept_friend_request_dialog(friend_request_id) @body = msg sendgrid_category "Notification" sendgrid_unique_args :type => unique_args[:type] @@ -239,7 +240,7 @@ unique_args = {:type => "text_message"} @note = message - @root_url = APP_CONFIG.external_root_url + @url = Nav.home(dialog: 'text-message', dialog_opts: {d1: sender_id}) @sender_id = sender_id @sender_name = sender_name @sender_photo_url = sender_photo_url 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 ccfdaf529..81de23226 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 @@ -1,3 +1,5 @@ <% provide(:title, 'New JamKazam Friend Request') %> -

<%= @body %>

\ No newline at end of file +

<%= @body %>

+ +

To accept this friend request, click here.

\ No newline at end of file diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/friend_request.text.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/friend_request.text.erb index 2f21cf84a..0f21a3033 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/friend_request.text.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/friend_request.text.erb @@ -1 +1,3 @@ -<%= @body %> \ No newline at end of file +<%= @body %> + +To accept this friend request, click here: <%= @url %> \ 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 83329d84d..e18666bf3 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 %> \ No newline at end of file diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/text_message.text.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/text_message.text.erb index 2df23f22b..d456e7191 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/text_message.text.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/text_message.text.erb @@ -1,3 +1,3 @@ <%= @sender_name %> says: <%= @note %> -To reply to this message, click here: <%= @root_url %>/client#/home/text-message/d1=<%= @sender_id %> \ No newline at end of file +To reply to this message, click here: <%= @url %> \ No newline at end of file diff --git a/ruby/lib/jam_ruby/lib/nav.rb b/ruby/lib/jam_ruby/lib/nav.rb new file mode 100644 index 000000000..56a7a09af --- /dev/null +++ b/ruby/lib/jam_ruby/lib/nav.rb @@ -0,0 +1,36 @@ +module JamRuby + + class Nav + + def self.home(options ={}) + "#{APP_CONFIG.external_root_url}/client#/home#{dialog(options)}" + end + + def self.accept_friend_request_dialog(friend_request_id) + Nav.home(dialog: 'accept-friend-request', dialog_opts: {d1: friend_request_id}) + end + + private + + def self.dialog(options) + dialog = '' + if options[:dialog] + dialog = "/#{options[:dialog]}" + + if options[:dialog_opts] + dialog = dialog + '/' + + options[:dialog_opts].each do|key, value| + dialog = dialog + ERB::Util.url_encode(key) + '=' + ERB::Util.url_encode(value) + '&' + end + + if options[:dialog_opts].length > 0 + dialog = dialog[0..-2] # trim off trailing '&' + end + end + end + + dialog + end + end +end \ No newline at end of file diff --git a/ruby/lib/jam_ruby/models/friend_request.rb b/ruby/lib/jam_ruby/models/friend_request.rb index fa15e36e8..b2fe2f5ba 100644 --- a/ruby/lib/jam_ruby/models/friend_request.rb +++ b/ruby/lib/jam_ruby/models/friend_request.rb @@ -5,8 +5,8 @@ module JamRuby STATUS = %w(accept block spam ignore) - belongs_to :user, :class_name => "JamRuby::User" - belongs_to :friend, :class_name => "JamRuby::User" + belongs_to :user, :class_name => "JamRuby::User", :foreign_key => 'user_id' + belongs_to :friend, :class_name => "JamRuby::User", :foreign_key => 'friend_id' validates :user_id, :presence => true validates :friend_id, :presence => true diff --git a/ruby/lib/jam_ruby/models/notification.rb b/ruby/lib/jam_ruby/models/notification.rb index ae3450c79..37180190d 100644 --- a/ruby/lib/jam_ruby/models/notification.rb +++ b/ruby/lib/jam_ruby/models/notification.rb @@ -240,10 +240,10 @@ module JamRuby ) @@mq_router.publish_to_user(friend_id, msg) - else - UserMailer.friend_request(friend.email, notification_msg).deliver + UserMailer.friend_request(friend.email, notification_msg, friend_request_id).deliver end + notification end def send_friend_request_accepted(user_id, friend_id) diff --git a/ruby/lib/jam_ruby/models/user.rb b/ruby/lib/jam_ruby/models/user.rb index 6b83dc815..93f73d829 100644 --- a/ruby/lib/jam_ruby/models/user.rb +++ b/ruby/lib/jam_ruby/models/user.rb @@ -27,7 +27,8 @@ module JamRuby has_many :connections, :class_name => "JamRuby::Connection" # friend requests - has_many :friend_requests, :class_name => "JamRuby::FriendRequest" + has_many :sent_friend_requests, :class_name => "JamRuby::FriendRequest", :foreign_key => 'user_id' + has_many :received_friend_requests, :class_name => "JamRuby::FriendRequest", :foreign_key => 'friend_id' # instruments has_many :musician_instruments, :class_name => "JamRuby::MusicianInstrument" diff --git a/ruby/spec/factories.rb b/ruby/spec/factories.rb index c79a12c87..80d337abc 100644 --- a/ruby/spec/factories.rb +++ b/ruby/spec/factories.rb @@ -107,6 +107,10 @@ FactoryGirl.define do end + factory :friend_request, :class => JamRuby::FriendRequest do + + end + factory :band_musician, :class => JamRuby::BandMusician do end diff --git a/ruby/spec/jam_ruby/models/notification_spec.rb b/ruby/spec/jam_ruby/models/notification_spec.rb index bff5e5b02..1e6d26751 100644 --- a/ruby/spec/jam_ruby/models/notification_spec.rb +++ b/ruby/spec/jam_ruby/models/notification_spec.rb @@ -7,22 +7,53 @@ describe Notification do end + def count_publish_to_user_calls + result = {count: 0} + MQRouter.any_instance.stub(:publish_to_user) do |receiver_id, msg| + result[:count] += 1 + result[:msg] = msg + end + result + end + + describe "send friend request" do + + let(:receiver) {FactoryGirl.create(:user)} + let(:sender) {FactoryGirl.create(:user)} + let(:friend_request) {FactoryGirl.create(:friend_request, user:sender, friend:receiver)} + + it "success when offline" do + calls = count_publish_to_user_calls + notification = Notification.send_friend_request(friend_request.id, sender.id, receiver.id) + + notification.errors.any?.should be_false + UserMailer.deliveries.length.should == 1 + calls[:count].should == 0 + end + + + it "success when online" do + receiver_connection = FactoryGirl.create(:connection, user: receiver) + calls = count_publish_to_user_calls + notification = Notification.send_friend_request(friend_request.id, sender.id, receiver.id) + + notification.errors.any?.should be_false + UserMailer.deliveries.length.should == 0 + calls[:count].should == 1 + end + end + describe "send_text_message" do it "success when offline" do receiver = FactoryGirl.create(:user) sender = FactoryGirl.create(:user) message = "Just a test message!" - - called_count = 0 - MQRouter.any_instance.stub(:publish_to_user) do |receiver_id, msg| - called_count += 1 - end - + calls = count_publish_to_user_calls notification = Notification.send_text_message(message, sender, receiver) notification.errors.any?.should be_false UserMailer.deliveries.length.should == 1 - called_count.should == 0 + calls[:count].should == 0 end @@ -30,108 +61,77 @@ describe Notification do receiver = FactoryGirl.create(:user) receiver_connection = FactoryGirl.create(:connection, user: receiver) sender = FactoryGirl.create(:user) - message = "Just a test message!" - - called_count = 0 - saved_msg = nil - MQRouter.any_instance.stub(:publish_to_user) do |receiver_id, msg| - saved_msg = msg - called_count += 1 - end - + calls = count_publish_to_user_calls notification = Notification.send_text_message(message, sender, receiver) notification.errors.any?.should be_false UserMailer.deliveries.length.should == 0 - called_count.should == 1 - saved_msg.text_message.msg.should == message - saved_msg.text_message.photo_url.should == '' - saved_msg.text_message.sender_name.should == sender.name - saved_msg.text_message.notification_id.should == notification.id - saved_msg.text_message.created_at = notification.created_date - saved_msg.text_message.clipped_msg.should be_false + calls[:count].should == 1 + calls[:msg].text_message.msg.should == message + calls[:msg].text_message.photo_url.should == '' + calls[:msg].text_message.sender_name.should == sender.name + calls[:msg].text_message.notification_id.should == notification.id + calls[:msg].text_message.created_at = notification.created_date + calls[:msg].text_message.clipped_msg.should be_false end it "success when online with long message" do receiver = FactoryGirl.create(:user) receiver_connection = FactoryGirl.create(:connection, user: receiver) sender = FactoryGirl.create(:user) - message = "0" * 203 # 200 is clip size - - called_count = 0 - saved_msg = nil - MQRouter.any_instance.stub(:publish_to_user) do |receiver_id, msg| - saved_msg = msg - called_count += 1 - end - + calls = count_publish_to_user_calls notification = Notification.send_text_message(message, sender, receiver) notification.errors.any?.should be_false UserMailer.deliveries.length.should == 0 - called_count.should == 1 - saved_msg.text_message.msg.should == "0" * 200 - saved_msg.text_message.photo_url.should == '' - saved_msg.text_message.sender_name.should == sender.name - saved_msg.text_message.notification_id.should == notification.id - saved_msg.text_message.created_at = notification.created_date - saved_msg.text_message.clipped_msg.should be_true + calls[:count].should == 1 + calls[:msg].text_message.msg.should == "0" * 200 + calls[:msg].text_message.photo_url.should == '' + calls[:msg].text_message.sender_name.should == sender.name + calls[:msg].text_message.notification_id.should == notification.id + calls[:msg].text_message.created_at = notification.created_date + calls[:msg].text_message.clipped_msg.should be_true end it "fails with profanity" do receiver = FactoryGirl.create(:user) sender = FactoryGirl.create(:user) message = "ass" - - called_count = 0 - MQRouter.any_instance.stub(:publish_to_user) do |receiver_id, msg| - called_count += 1 - end - + calls = count_publish_to_user_calls notification = Notification.send_text_message(message, sender, receiver) notification.errors.any?.should be_true notification.errors[:message].should == ['cannot contain profanity'] UserMailer.deliveries.length.should == 0 - called_count.should == 0 + calls[:count].should == 0 end it "fails when target is same as receiver" do receiver = FactoryGirl.create(:user) sender = FactoryGirl.create(:user) message = "yo" - - called_count = 0 - MQRouter.any_instance.stub(:publish_to_user) do |receiver_id, msg| - called_count += 1 - end - + calls = count_publish_to_user_calls notification = Notification.send_text_message(message, sender, sender) notification.errors.any?.should be_true notification.errors[:target_user].should == [ValidationMessages::DIFFERENT_SOURCE_TARGET] UserMailer.deliveries.length.should == 0 - called_count.should == 0 + calls[:count].should == 0 end it "fails when there is no message" do receiver = FactoryGirl.create(:user) sender = FactoryGirl.create(:user) message = '' - - called_count = 0 - MQRouter.any_instance.stub(:publish_to_user) do |receiver_id, msg| - called_count += 1 - end - + calls = count_publish_to_user_calls notification = Notification.send_text_message(message, sender, receiver) notification.errors.any?.should be_true notification.errors[:message].should == ['is too short (minimum is 1 characters)'] UserMailer.deliveries.length.should == 0 - called_count.should == 0 + calls[:count].should == 0 end end end diff --git a/ruby/spec/mailers/render_emails_spec.rb b/ruby/spec/mailers/render_emails_spec.rb index 3d80b32cc..9e505d2d1 100644 --- a/ruby/spec/mailers/render_emails_spec.rb +++ b/ruby/spec/mailers/render_emails_spec.rb @@ -34,9 +34,11 @@ describe "RenderMailers", :slow => true do describe "has sending user" do let(:user2) { FactoryGirl.create(:user) } - it { @filename="text_message"; UserMailer.text_message(user.email, user2.id, user2.name, user2.resolved_photo_url, 'Get online!!').deliver } - end + let(:friend_request) {FactoryGirl.create(:friend_request, user:user, friend: user2)} + it { @filename="text_message"; UserMailer.text_message(user.email, user2.id, user2.name, user2.resolved_photo_url, 'Get online!!').deliver } + it { @filename="friend_request"; UserMailer.friend_request(user.email, 'So and so has sent you a friend request.', friend_request.id).deliver} + end end describe "InvitedUserMailer emails" do diff --git a/web/app/assets/javascripts/acceptFriendRequestDialog.js b/web/app/assets/javascripts/acceptFriendRequestDialog.js new file mode 100644 index 000000000..701e905c8 --- /dev/null +++ b/web/app/assets/javascripts/acceptFriendRequestDialog.js @@ -0,0 +1,186 @@ +(function(context,$) { + + "use strict"; + context.JK = context.JK || {}; + context.JK.AcceptFriendRequestDialog = function(app) { + var logger = context.JK.logger; + var rest = context.JK.Rest(); + var $dialog = null; + var $dialogContents = null; + var $notFriendsTemplate = null; + var $alreadyFriendsTemplate = null; + var $genericErrorTemplate = null; + var $alreadyProcessedTemplate = null; + var $acceptBtn = null; + var $closeBtn = null; + var $cancelBtn = null; + var $actionBtns = null; + var friendRequestId = null; + var user = null; + var sending = false; + var friendRequest = null; + + function reset() { + sending = false; + friendRequest = null; + $dialogContents.empty(); + $actionBtns.hide(); + $actionBtns.find('a').hide(); + $acceptBtn.text('ACCEPT'); + } + + function buildShowRequest() { + return {friend_request_id: friendRequestId}; + } + + function buildAcceptRequest() { + var message = {}; + + message['friend_request_id'] = friendRequest.id; + message['status'] = 'accept'; + + return message; + } + + function acceptRequest(e) { + + if(!sending) { + sending = true; + + $acceptBtn.text('ACCEPTING...') + + rest.acceptFriendRequest(buildAcceptRequest()) + .done(function() { + app.layout.closeDialog('accept-friend-request') + }) + .fail(function(jqXHR) { + app.notifyServerError(jqXHR, 'Unable to Accept Friend Request'); + }) + .always(function() { + sending = false; + $acceptBtn.text('ACCEPT'); + }) + + } + return false; + } + + + function modifyResponseWithUIData() { + friendRequest.friend.user_type = friendRequest.friend.musician ? 'musician' : 'fan' + friendRequest.user.user_type = friendRequest.user.musician ? 'musician' : 'fan' + friendRequest.friend.photo_url = context.JK.resolveAvatarUrl(friendRequest.friend.photo_url); + friendRequest.user.photo_url = context.JK.resolveAvatarUrl(friendRequest.user.photo_url); + } + + function renderNoActionPossibleBtns() { + $closeBtn.show(); + $actionBtns.show(); + } + + function renderDefaultBtns() { + $cancelBtn.show(); + $acceptBtn.show(); + $actionBtns.show(); + } + function renderAlreadyFriends(options) { + return $(context._.template($alreadyFriendsTemplate.html(), options, { variable: 'data' })); + } + + function renderAlreadyProcessed(options) { + return $(context._.template($alreadyProcessedTemplate.html(), options, { variable: 'data' })); + } + + function renderNotFriends(options) { + return $(context._.template($notFriendsTemplate.html(), options, { variable: 'data' })); + } + + function renderGenericError(options) { + return $(context._.template($genericErrorTemplate.html(), options, { variable: 'data' })); + } + + function beforeShow(args) { + + app.layout.closeDialog('accept-friend-request') // ensure no others are showing. this is a singleton dialog + + app.user() + .done(function(userDetail) { + user = userDetail; + + friendRequestId = args.d1; + + if(!friendRequestId) throw "friend request must be specified in AcceptFriendRequestDialog" + + rest.getFriendRequest(buildShowRequest()) + .done(function(response) { + friendRequest = response; + modifyResponseWithUIData(); + var options = friendRequest; + + var contents = null; + + if(friendRequest.user_id == user.id) { + contents = renderGenericError({error_message: 'You can\'t become friends with yourself.'}) + renderNoActionPossibleBtns(); + } + else if(friendRequest.user.is_friend) { + // already friends + contents = renderAlreadyFriends(options); + renderNoActionPossibleBtns(); + } + else if(friendRequest.status) { + contents = renderAlreadyProcessed(options); + renderNoActionPossibleBtns(); + } + else { + contents = renderNotFriends(options); + renderDefaultBtns(); + } + + $dialogContents.append(contents); + + context.JK.bindHoverEvents(contents); + }) + .fail(function(jqXHR) { + app.notifyServerError(jqXHR, 'Unable to Load Friend Request') + renderNoActionPossibleBtns(); + }) + }) + } + + function events() { + $acceptBtn.click(acceptRequest); + } + + function afterHide() { + reset(); + } + + function initialize() { + var dialogBindings = { + 'beforeShow' : beforeShow, + 'afterHide': afterHide + }; + + + app.bindDialog('accept-friend-request', dialogBindings); + + $dialog = $('#accept-friend-request-dialog'); + $dialogContents = $dialog.find('.dialog-inner'); + $notFriendsTemplate = $('#template-friend-request-not-friends'); + $alreadyFriendsTemplate = $('#template-friend-request-already-friends'); + $alreadyProcessedTemplate = $('#template-friend-request-already-processed') + $genericErrorTemplate = $('#template-friend-generic-error'); + $acceptBtn = $dialog.find('.btn-accept-friend-request'); + $cancelBtn = $dialog.find('.btn-cancel-dialog'); + $closeBtn = $dialog.find('.btn-close-dialog'); + $actionBtns = $dialog.find('.action-buttons'); + + events(); + } + + this.initialize = initialize; + } + + return this; +})(window,jQuery); diff --git a/web/app/assets/javascripts/jam_rest.js b/web/app/assets/javascripts/jam_rest.js index c6b6468b5..2b19b5d44 100644 --- a/web/app/assets/javascripts/jam_rest.js +++ b/web/app/assets/javascripts/jam_rest.js @@ -655,9 +655,24 @@ }); } + function getFriendRequest(options) { + var id = getId(options); + var friendRequestId = options["friend_request_id"]; + + var deferred = $.ajax({ + type: "GET", + dataType: "json", + contentType: 'application/json', + url: "/api/users/" + id + "/friend_requests/" + friendRequestId, + processData: false + }); + + return deferred; + } + function acceptFriendRequest(options) { var id = getId(options); - var friend_request_id = options["friend_request_id"]; + var friendRequestId = options["friend_request_id"]; var status = options["status"]; var friend_request = { status: status }; @@ -666,7 +681,7 @@ type: "POST", dataType: "json", contentType: 'application/json', - url: "/api/users/" + id + "/friend_requests/" + friend_request_id, + url: "/api/users/" + id + "/friend_requests/" + friendRequestId, data: JSON.stringify(friend_request), processData: false }); @@ -972,6 +987,7 @@ this.getFeeds = getFeeds; this.serverHealthCheck = serverHealthCheck; this.sendFriendRequest = sendFriendRequest; + this.getFriendRequest = getFriendRequest; this.acceptFriendRequest = acceptFriendRequest; this.signout = signout; this.userDownloadedClient = userDownloadedClient; diff --git a/web/app/assets/javascripts/jamkazam.js b/web/app/assets/javascripts/jamkazam.js index 08f681978..ea0a39710 100644 --- a/web/app/assets/javascripts/jamkazam.js +++ b/web/app/assets/javascripts/jamkazam.js @@ -305,6 +305,10 @@ logger.debug("Unprocessable entity sent from server:", errors) this.notify({title: title, text: $errors, icon_url: "/assets/content/icon_alert_big.png"}) } + else if(jqXHR.status == 403) { + logger.debug("permission error sent from server:", jqXHR.responseText) + this.notify({title: 'Permission Error', text: 'You do not have permission to access this information', icon_url: "/assets/content/icon_alert_big.png"}) + } else { if (jqXHR.responseText.indexOf('') == 0 || jqXHR.responseText.indexOf(' 200 end diff --git a/web/app/views/api_users/friend_request_show.rabl b/web/app/views/api_users/friend_request_show.rabl index a0bb6df49..7dce1579b 100644 --- a/web/app/views/api_users/friend_request_show.rabl +++ b/web/app/views/api_users/friend_request_show.rabl @@ -1,3 +1,11 @@ object @friend_request -attributes :id, :user_id, :friend_id, :status, :message, :created_at \ No newline at end of file +attributes :id, :user_id, :friend_id, :status, :message, :created_at + +node :friend do |friend_request| +{ :id => friend_request.friend.id, :musician => friend_request.friend.musician, :photo_url => friend_request.friend.photo_url, :name => friend_request.user.name } +end + +node :user do |friend_request| +{ :id => friend_request.user.id, :musician => friend_request.user.musician, :photo_url => friend_request.user.photo_url, :name => friend_request.user.name, :is_friend => friend_request.user.friends?(current_user) } +end diff --git a/web/app/views/clients/_acceptFriendRequestDialog.html.haml b/web/app/views/clients/_acceptFriendRequestDialog.html.haml new file mode 100644 index 000000000..bedd461ad --- /dev/null +++ b/web/app/views/clients/_acceptFriendRequestDialog.html.haml @@ -0,0 +1,49 @@ + +.dialog.textMessage-overlay.ftue-overlay.tall{ layout: 'dialog', 'layout-id' => 'accept-friend-request', id: 'accept-friend-request-dialog'} + .content-head + = image_tag "content/icon_friend.png", {:width => 14, :height => 14, :class => 'content-icon' } + %h1 + = 'friend request' + .dialog-inner + + .right.action-buttons + %a.button-grey.btn-close-dialog{href:'#', 'layout-action' => 'close'} CLOSE + %a.button-grey.btn-cancel-dialog{href:'#', 'layout-action' => 'close'} CANCEL + %a.button-orange.btn-accept-friend-request{href:'#'} ACCEPT + +%script{type: 'text/template', id: 'template-friend-request-not-friends'} + .dialog-content-scroller + %a{'user-id' => '{{data.user.id}}', hoveraction: '{{data.user.user_type}}', class: 'avatar-small'} + %img{src: '{{data.user.photo_url}}' } + %p.accept-friend-msg Become friends with {{data.user.name}} ? + {% if(data.message) { %} + .sender + %span.sender-name= '{{data.user.name}}' + %span.says says: + %div.sender-msg '{{data.message}}' + {% } %} + %br{clear:'all'} + %br{clear:'all'} + +%script{type: 'text/template', id: 'template-friend-request-already-friends'} + .dialog-content-scroller + %a{'user-id' => '{{data.user.id}}', hoveraction: '{{data.user.user_type}}', class: 'avatar-small'} + %img{src: '{{data.user.photo_url}}' } + %p.accept-friend-msg You are already friends with {{data.user.name}}. + %br{clear:'all'} + %br{clear:'all'} + + +%script{type: 'text/template', id: 'template-friend-request-already-processed'} + .dialog-content-scroller + %a{'user-id' => '{{data.user.id}}', hoveraction: '{{data.user.user_type}}', class: 'avatar-small'} + %img{src: '{{data.user.photo_url}}' } + %p.accept-friend-msg This friend request from {{data.user.name}} is no longer valid. + %br{clear:'all'} + %br{clear:'all'} + +%script{type: 'text/template', id: 'template-friend-generic-error'} + .dialog-content-scroller + %p.generic-error-msg {{data.error_message}} + %br{clear:'all'} + diff --git a/web/app/views/clients/index.html.erb b/web/app/views/clients/index.html.erb index a20b3ee54..d28fd6ae5 100644 --- a/web/app/views/clients/index.html.erb +++ b/web/app/views/clients/index.html.erb @@ -50,6 +50,7 @@ <%= render "localRecordingsDialog" %> <%= render "showServerErrorDialog" %> <%= render "textMessageDialog" %> +<%= render "acceptFriendRequestDialog" %> <%= render "notify" %> <%= render "client_update" %> <%= render "banner" %> @@ -133,6 +134,9 @@ JK.TextMessageDialogInstance = textMessageDialog; textMessageDialog.initialize(); + var acceptFriendRequestDialog = new JK.AcceptFriendRequestDialog(JK.app); + acceptFriendRequestDialog.initialize(); + var localRecordingsDialog = new JK.LocalRecordingsDialog(JK.app); localRecordingsDialog.initialize(); diff --git a/web/spec/factories.rb b/web/spec/factories.rb index 3e37a8ba2..d1c1c2976 100644 --- a/web/spec/factories.rb +++ b/web/spec/factories.rb @@ -91,6 +91,10 @@ FactoryGirl.define do end + factory :friend_request, :class => JamRuby::FriendRequest do + + end + factory :band, :class => JamRuby::Band do sequence(:name) { |n| "Band" } biography "Established 1978" diff --git a/web/spec/features/accept_friend_request_dialog_spec.rb b/web/spec/features/accept_friend_request_dialog_spec.rb new file mode 100644 index 000000000..bfd924efb --- /dev/null +++ b/web/spec/features/accept_friend_request_dialog_spec.rb @@ -0,0 +1,80 @@ +require 'spec_helper' + +describe "Accept Friend Request", :js => true, :type => :feature, :capybara_feature => true do + + before(:all) do + User.delete_all # we delete all users due to the use of find_musician() helper method, which scrolls through all users + end + + let (:friend_request) { FactoryGirl.create(:friend_request, user: @user2, friend: @user1) } + + before(:each) do + @user1 = FactoryGirl.create(:user) + @user2 = FactoryGirl.create(:user, first_name: 'bone_crusher') + sign_in_poltergeist(@user1) + stub_const("APP_CONFIG", web_config) + end + + describe "dialog behavior" do + + describe "launch states" do + + it "happy path" do + # users are not friends yet, and this request has not been dealt with + visit '/' + should_be_at_root + visit Nav.accept_friend_request_dialog(friend_request.id) + + find('h1', text: 'friend request') + find('#accept-friend-request-dialog .btn-accept-friend-request', text: 'ACCEPT').trigger(:click) + page.should_not have_selector('h1', text: 'friend request') + friend_request.reload + friend_request.status.should == 'accept' + end + + it "already accepted" do + # users are not friends yet, and this request has not been dealt with + friend_request.status = 'accept' + friend_request.save! + visit '/' + should_be_at_root + visit Nav.accept_friend_request_dialog(friend_request.id) + + find('h1', text: 'friend request') + find('.accept-friend-msg', text: "This friend request from #{@user2.name} is no longer valid.") + find('#accept-friend-request-dialog .btn-close-dialog', text: 'CLOSE').trigger(:click) + page.should_not have_selector('h1', text: 'friend request') + end + + it "already friends" do + FactoryGirl.create(:friendship, user: @user1, friend: @user2) + FactoryGirl.create(:friendship, user: @user2, friend: @user1) + + visit '/' + should_be_at_root + visit Nav.accept_friend_request_dialog(friend_request.id) + + find('h1', text: 'friend request') + find('.accept-friend-msg', text: "You are already friends with #{@user2.name}.") + find('#accept-friend-request-dialog .btn-close-dialog', text: 'CLOSE').trigger(:click) + page.should_not have_selector('h1', text: 'friend request') + end + + it "same user seeing own friend request" do + user3 = FactoryGirl.create(:user) + friend_request.friend = @user2 + friend_request.user = @user1 + friend_request.save! + + visit '/' + should_be_at_root + visit Nav.accept_friend_request_dialog(friend_request.id) + + find('h1', text: 'friend request') + find('.generic-error-msg', 'You can\'t become friends with yourself.') + find('#accept-friend-request-dialog .btn-close-dialog', text: 'CLOSE').trigger(:click) + page.should_not have_selector('h1', text: 'friend request') + end + end + end +end diff --git a/web/spec/features/profile_menu_spec.rb b/web/spec/features/profile_menu_spec.rb index c4204c4f3..292deb340 100644 --- a/web/spec/features/profile_menu_spec.rb +++ b/web/spec/features/profile_menu_spec.rb @@ -58,7 +58,7 @@ describe "Profile Menu", :js => true, :type => :feature, :capybara_feature => tr click_link 'Sign Out' end - it { should_be_logged_out } + it { should_be_at_root } end describe "Download App link" do diff --git a/web/spec/support/app_config.rb b/web/spec/support/app_config.rb new file mode 100644 index 000000000..5f124e9a9 --- /dev/null +++ b/web/spec/support/app_config.rb @@ -0,0 +1,22 @@ + +def web_config + klass = Class.new do + + def external_hostname + Capybara.current_session.server.host + end + + def external_protocol + 'http://' + end + + def external_port + Capybara.current_session.server.port + end + + def external_root_url + "#{external_protocol}#{external_hostname}#{(external_port == 80 || external_port == 443) ? '' : ':' + external_port.to_s}" + end + end + klass.new +end diff --git a/web/spec/support/utilities.rb b/web/spec/support/utilities.rb index 1cbf3e96b..c184dfbb2 100644 --- a/web/spec/support/utilities.rb +++ b/web/spec/support/utilities.rb @@ -107,10 +107,10 @@ end def sign_out_poltergeist(options = {}) find('.userinfo').hover() click_link 'Sign Out' - should_be_logged_out if options[:validate] + should_be_at_root if options[:validate] end -def should_be_logged_out +def should_be_at_root find('h1', text: 'Play music together over the Internet as if in the same room') end From 1aef96b697d88e55dac2577da059d30cbd3f9048 Mon Sep 17 00:00:00 2001 From: Seth Call Date: Tue, 25 Mar 2014 16:30:22 +0000 Subject: [PATCH 2/3] * VRFS-1474 cleaned up some error case dialogs --- .../javascripts/acceptFriendRequestDialog.js | 15 +++++++++-- .../accept_friend_request_dialog_spec.rb | 26 +++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/web/app/assets/javascripts/acceptFriendRequestDialog.js b/web/app/assets/javascripts/acceptFriendRequestDialog.js index 701e905c8..4706105ca 100644 --- a/web/app/assets/javascripts/acceptFriendRequestDialog.js +++ b/web/app/assets/javascripts/acceptFriendRequestDialog.js @@ -138,11 +138,22 @@ } $dialogContents.append(contents); - context.JK.bindHoverEvents(contents); }) .fail(function(jqXHR) { - app.notifyServerError(jqXHR, 'Unable to Load Friend Request') + if(jqXHR.status == 403) { + var contents = renderGenericError({error_message: 'You do not have permission to access this information.'}) + $dialogContents.append(contents); + context.JK.bindHoverEvents(contents); + } + else if(jqXHR.status == 404) { + var contents = renderGenericError({error_message: 'This friend request no longer exists.'}) + $dialogContents.append(contents); + context.JK.bindHoverEvents(contents); + } + else { + app.notifyServerError(jqXHR, 'Unable to Load Friend Request'); + } renderNoActionPossibleBtns(); }) }) diff --git a/web/spec/features/accept_friend_request_dialog_spec.rb b/web/spec/features/accept_friend_request_dialog_spec.rb index bfd924efb..dd9376da5 100644 --- a/web/spec/features/accept_friend_request_dialog_spec.rb +++ b/web/spec/features/accept_friend_request_dialog_spec.rb @@ -75,6 +75,32 @@ describe "Accept Friend Request", :js => true, :type => :feature, :capybara_feat find('#accept-friend-request-dialog .btn-close-dialog', text: 'CLOSE').trigger(:click) page.should_not have_selector('h1', text: 'friend request') end + + it "no longer exists" do + visit '/' + should_be_at_root + visit Nav.accept_friend_request_dialog('junk') + + find('h1', text: 'friend request') + find('.generic-error-msg', 'This friend request no longer exists.') + find('#accept-friend-request-dialog .btn-close-dialog', text: 'CLOSE').trigger(:click) + page.should_not have_selector('h1', text: 'friend request') + end + + it "no permission" do + user3 = FactoryGirl.create(:user) + friend_request.friend = user3 + friend_request.save! + + visit '/' + should_be_at_root + visit Nav.accept_friend_request_dialog(friend_request.id) + + find('h1', text: 'friend request') + find('.generic-error-msg', 'You do not have permission to access this information.') + find('#accept-friend-request-dialog .btn-close-dialog', text: 'CLOSE').trigger(:click) + page.should_not have_selector('h1', text: 'friend request') + end end end end From d365054237c05a942b3e6fff98a0c7daefa50be0 Mon Sep 17 00:00:00 2001 From: Seth Call Date: Tue, 25 Mar 2014 22:42:15 +0000 Subject: [PATCH 3/3] * VRFS-1533 - track in success path, not failure path of download GA info --- web/app/assets/javascripts/web/downloads.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/app/assets/javascripts/web/downloads.js b/web/app/assets/javascripts/web/downloads.js index a060e8e7e..1c3976f90 100644 --- a/web/app/assets/javascripts/web/downloads.js +++ b/web/app/assets/javascripts/web/downloads.js @@ -79,11 +79,11 @@ var href = clicked.attr('href'); if(href != "#") { rest.userDownloadedClient().always(function() { - $('body').append('