diff --git a/app/controllers/notifications_controller.rb b/app/controllers/notifications_controller.rb index c27df96c7..deeb59e1b 100644 --- a/app/controllers/notifications_controller.rb +++ b/app/controllers/notifications_controller.rb @@ -11,8 +11,8 @@ class NotificationsController < VannaController def update(opts=params) note = Notification.where(:recipient_id => current_user.id, :id => opts[:id]).first if note - note.update_attributes(:unread => false) - {} + note.update_attributes(:unread => opts[:unread] == "true" ) + { :guid => note.id, :unread => note.unread } else Response.new :status => 404 end diff --git a/app/views/notifications/index.html.haml b/app/views/notifications/index.html.haml index 88a098ab2..0935dea0e 100644 --- a/app/views/notifications/index.html.haml +++ b/app/views/notifications/index.html.haml @@ -21,7 +21,7 @@ .span-8.notifications_for_day - notes.each do |note| - .stream_element{:data=>{:guid => note.id}, :class => "#{note.unread ? 'unread' : ''}"} + .stream_element{:data=>{:guid => note.id}, :class => "#{note.unread ? 'unread' : 'read'}"} - if note.type == "Notifications::StartedSharing" && contact = current_user.contact_for(note[:target]) .right = aspect_membership_dropdown(contact, note[:target], 'left') diff --git a/app/views/notifications/index.mobile.haml b/app/views/notifications/index.mobile.haml index 18ea33fef..3f27eb8bc 100644 --- a/app/views/notifications/index.mobile.haml +++ b/app/views/notifications/index.mobile.haml @@ -8,7 +8,7 @@ = day %ul.notifications_for_day - notes.each do |note| - .stream_element{:data=>{:guid => note.id}, :class => "#{note.unread ? 'unread' : ''}"} + .stream_element{:data=>{:guid => note.id}, :class => "#{note.unread ? 'unread' : 'read'}"} = person_image_link(note.actors.last) diff --git a/public/javascripts/widgets/notifications-badge.js b/public/javascripts/widgets/notifications-badge.js index e64d5da39..f8499ffce 100644 --- a/public/javascripts/widgets/notifications-badge.js +++ b/public/javascripts/widgets/notifications-badge.js @@ -63,6 +63,7 @@ $.each(notifications, function(index, notification) { var notificationElement = $("
") .addClass("notification_element") + .data( "guid", notification.id ) .html(notification.translation) .prepend($("", { src: notification.actors[0].avatar })) .append("
") @@ -73,16 +74,18 @@ .appendTo(self.dropdownNotifications); notificationElement.find("abbr.timeago").timeago(); + notificationElement.click(Diaspora.page.header.notifications.messageClick); if(notification.unread) { notificationElement.addClass("unread"); $.ajax({ url: "/notifications/" + notification.id, type: "PUT", - success: function() { - Diaspora.page.header.notifications.decrementCount(); - } + data: { unread: false }, + success: Diaspora.page.header.notifications.clickSuccess }); + } else { + notificationElement.addClass("read"); } }); }); diff --git a/public/javascripts/widgets/notifications.js b/public/javascripts/widgets/notifications.js index fff80b404..e16136d2a 100644 --- a/public/javascripts/widgets/notifications.js +++ b/public/javascripts/widgets/notifications.js @@ -15,14 +15,7 @@ notificationArea: notificationArea }); - $(".stream_element.unread").live("mousedown", function() { - self.decrementCount(); - - $.ajax({ - url: "notifications/" + $(this).removeClass("unread").data("guid"), - type: "PUT" - }); - }); + $(".stream_element.unread,.stream_element.read").live("mousedown", self.messageClick); $("a.more").live("click", function(evt) { evt.preventDefault(); @@ -31,7 +24,33 @@ .removeClass("hidden"); }); }); - + this.messageClick = function() { + $.ajax({ + url: "notifications/" + $(this).data("guid"), + data: { unread: $(this).hasClass("read") }, + type: "PUT", + success: self.clickSuccess + }); + }; + this.clickSuccess = function( data ) { + var jsList = jQuery.parseJSON(data); + var itemID = jsList["guid"] + var isUnread = jsList["unread"] + if ( isUnread ) { + self.incrementCount(); + }else{ + self.decrementCount(); + } + $('.read,.unread').each(function(index) { + if ( $(this).data("guid") == itemID ) { + if ( isUnread ) { + $(this).removeClass("read").addClass( "unread" ) + } else { + $(this).removeClass("unread").addClass( "read" ) + } + } + }); + }; this.showNotification = function(notification) { $(notification.html).prependTo(this.notificationArea) .fadeIn(200) @@ -50,12 +69,15 @@ if(self.badge.text() !== "") { self.badge.text(self.count); + $( ".notification_count" ).text(self.count); if(self.count === 0) { self.badge.addClass("hidden"); + $( ".notification_count" ).removeClass("unread"); } else if(self.count === 1) { self.badge.removeClass("hidden"); + $( ".notification_count" ).addClass("unread"); } } }; diff --git a/public/stylesheets/sass/application.sass b/public/stylesheets/sass/application.sass index 055205445..b7e83bde6 100644 --- a/public/stylesheets/sass/application.sass +++ b/public/stylesheets/sass/application.sass @@ -3138,6 +3138,8 @@ a.toggle_selector .notification_element :padding 10px :min-height 30px + &:hover + :background-color #FAFAFA > img :height 30px diff --git a/spec/controllers/notifications_controller_spec.rb b/spec/controllers/notifications_controller_spec.rb index 3f1e64b1f..d7dce0014 100644 --- a/spec/controllers/notifications_controller_spec.rb +++ b/spec/controllers/notifications_controller_spec.rb @@ -14,11 +14,32 @@ describe NotificationsController do end describe '#update' do - it 'marks a notification as read' do + it 'marks a notification as read if it gets no other information' do note = Factory(:notification, :recipient => @user) @controller.update :id => note.id Notification.first.unread.should == false end + it 'marks a notification as read if it is told to' do + note = Factory(:notification, :recipient => @user) + @controller.update :id => note.id, :unread => "false" + Notification.first.unread.should == false + end + it 'marks a notification as unread if it is told to' do + note = Factory(:notification, :recipient => @user) + @controller.update :id => note.id, :unread => "true" + Notification.first.unread.should == true + end + + it 'should return the item guid' do + note = Factory(:notification, :recipient => @user) + answer = @controller.update :id => note.id + answer[:guid].should == note.id + end + it 'should return the unread state' do + note = Factory(:notification, :recipient => @user) + answer = @controller.update :id => note.id, :unread => "true" + answer[:unread].should == true + end it 'only lets you read your own notifications' do user2 = bob diff --git a/spec/javascripts/widgets/notifications-spec.js b/spec/javascripts/widgets/notifications-spec.js index cbb962180..f9ae7ee80 100644 --- a/spec/javascripts/widgets/notifications-spec.js +++ b/spec/javascripts/widgets/notifications-spec.js @@ -3,13 +3,44 @@ * the COPYRIGHT file. */ describe("Diaspora.Widgets.Notifications", function() { - var changeNotificationCountSpy, notifications; + var changeNotificationCountSpy, notifications, incrementCountSpy, decrementCountSpy; beforeEach(function() { spec.loadFixture("aspects_index"); notifications = Diaspora.BaseWidget.instantiate("Notifications", $("#notifications"), $("#notification_badge .badge_count")); changeNotificationCountSpy = spyOn(notifications, "changeNotificationCount").andCallThrough(); + incrementCountSpy = spyOn(notifications, "incrementCount").andCallThrough(); + decrementCountSpy = spyOn(notifications, "decrementCount").andCallThrough(); + }); + + describe("clickSuccess", function(){ + it("changes the css to a read cell", function() { + $(".notifications").html( + '
' + + '
' + ); + notifications.clickSuccess(JSON.stringify({guid:2,unread:false})); + expect( $('.stream_element#2')).toHaveClass("read"); + }); + it("changes the css to an unread cell", function() { + $(".notifications").html( + '
' + + '
' + ); + notifications.clickSuccess(JSON.stringify({guid:1,unread:true})); + expect( $('.stream_element#1')).toHaveClass("unread"); + }); + + + it("calls Notifications.decrementCount on a read cell", function() { + notifications.clickSuccess(JSON.stringify({guid:1,unread:false})); + expect(notifications.decrementCount).toHaveBeenCalled(); + }); + it("calls Notifications.incrementCount on a unread cell", function() { + notifications.clickSuccess(JSON.stringify({guid:1,unread:true})); + expect(notifications.incrementCount).toHaveBeenCalled(); + }); }); describe("decrementCount", function() {