From a11c8d8a964e94a0546ed5117b1a0e970bd2b811 Mon Sep 17 00:00:00 2001 From: Steven Fuchs Date: Tue, 17 Jan 2012 19:20:42 -0500 Subject: [PATCH] javascripts for marking notifications items as unread on both the notifications page and popup menu. --- public/javascripts/widgets/header.js | 4 +- .../widgets/notifications-badge.js | 13 +- public/javascripts/widgets/notifications.js | 114 +++++++++++++++--- .../javascripts/widgets/notifications-spec.js | 45 ++++++- spec/models/notification_spec.rb | 15 +++ 5 files changed, 155 insertions(+), 36 deletions(-) diff --git a/public/javascripts/widgets/header.js b/public/javascripts/widgets/header.js index 208c5cd84..10fd0d996 100644 --- a/public/javascripts/widgets/header.js +++ b/public/javascripts/widgets/header.js @@ -4,8 +4,8 @@ this.subscribe("widget/ready", function(evt, header) { self.notifications = self.instantiate("Notifications", - header.find("#notifications"), - header.find("#notification_badge .badge_count") + header.find("#notification_badge .badge_count"), + header.find(".notifications") ); self.notificationsDropdown = self.instantiate("NotificationsDropdown", diff --git a/public/javascripts/widgets/notifications-badge.js b/public/javascripts/widgets/notifications-badge.js index e64d5da39..d69666fe3 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("
") @@ -70,19 +71,15 @@ "class": "timeago", "title": notification.created_at })) + .append('mark unread') .appendTo(self.dropdownNotifications); notificationElement.find("abbr.timeago").timeago(); if(notification.unread) { - notificationElement.addClass("unread"); - $.ajax({ - url: "/notifications/" + notification.id, - type: "PUT", - success: function() { - Diaspora.page.header.notifications.decrementCount(); - } - }); + Diaspora.page.header.notifications.setUpUnread( notificationElement ); + }else{ + Diaspora.page.header.notifications.setUpRead( notificationElement ); } }); }); diff --git a/public/javascripts/widgets/notifications.js b/public/javascripts/widgets/notifications.js index fff80b404..ce59e0895 100644 --- a/public/javascripts/widgets/notifications.js +++ b/public/javascripts/widgets/notifications.js @@ -8,32 +8,99 @@ var Notifications = function() { var self = this; - this.subscribe("widget/ready", function(evt, notificationArea, badge) { + this.subscribe("widget/ready", function(evt, badge, notificationMenu) { $.extend(self, { badge: badge, count: parseInt(badge.html()) || 0, - notificationArea: notificationArea + notificationArea: null, + notificationMenu: notificationMenu }); - $(".stream_element.unread").live("mousedown", function() { - self.decrementCount(); - - $.ajax({ - url: "notifications/" + $(this).removeClass("unread").data("guid"), - type: "PUT" - }); - }); - - $("a.more").live("click", function(evt) { + $("a.more").click( function(evt) { evt.preventDefault(); $(this).hide() .next(".hidden") .removeClass("hidden"); }); }); - + this.setUpNotificationPage = function( contentArea ) { + self.notificationArea = contentArea; + contentArea.find(".unread,.read").each(function(index) { + if ( $(this).hasClass("unread") ) { + self.setUpUnread( $(this) ); + } else { + self.setUpRead( $(this) ); + } + }); + } + this.unreadClick = function() { + $.ajax({ + url: "/notifications/" + $(this).parent().data("guid"), + data: { set_unread: true }, + type: "PUT", + success: self.clickSuccess + }); + }; + this.readClick = function() { + $.ajax({ + url: "/notifications/" + $(this).data("guid"), + data: { set_unread: false }, + type: "PUT", + success: self.clickSuccess + }); + }; + this.setUpUnread = function( an_obj ) { + an_obj.removeClass("read").addClass( "unread" ); + an_obj.find('.unread-setter').hide(); + an_obj.find('.unread-setter').unbind("click"); + an_obj.unbind( "mouseenter mouseleave" ); + an_obj.click(self.readClick); + } + this.setUpRead = function( an_obj ) { + an_obj.removeClass("unread").addClass( "read" ); + an_obj.unbind( "click" ); + an_obj.find(".unread-setter").click(Diaspora.page.header.notifications.unreadClick); + an_obj.hover( + function () { + $(this).find(".unread-setter").show(); + }, + function () { + $(this).find(".unread-setter").hide(); + } + ); + } + this.clickSuccess = function( data ) { + var jsList = jQuery.parseJSON(data); + var itemID = jsList["guid"] + var isUnread = jsList["unread"] + if ( isUnread ) { + self.incrementCount(); + }else{ + self.decrementCount(); + } + self.notificationMenu.find('.read,.unread').each(function(index) { + if ( $(this).data("guid") == itemID ) { + if ( isUnread ) { + self.setUpUnread( $(this) ) + } else { + self.setUpRead( $(this) ) + } + } + }); + if ( self.notificationArea ) { + self.notificationArea.find('.read,.unread').each(function(index) { + if ( $(this).data("guid") == itemID ) { + if ( isUnread ) { + self.setUpUnread( $(this) ) + } else { + self.setUpRead( $(this) ) + } + } + }); + } + }; this.showNotification = function(notification) { - $(notification.html).prependTo(this.notificationArea) + $(notification.html).prependTo(this.notificationMenu) .fadeIn(200) .delay(8000) .fadeOut(200, function() { @@ -50,13 +117,20 @@ if(self.badge.text() !== "") { self.badge.text(self.count); + if ( self.notificationArea ) { + self.notificationArea.find( ".notification_count" ).text(self.count); - if(self.count === 0) { - self.badge.addClass("hidden"); - } - else if(self.count === 1) { - self.badge.removeClass("hidden"); - } + if(self.count === 0) { + self.badge.addClass("hidden"); + if ( self.notificationArea ) + self.notificationArea.find( ".notification_count" ).removeClass("unread"); + } + else if(self.count === 1) { + self.badge.removeClass("hidden"); + if ( self.notificationArea ) + self.notificationArea.find( ".notification_count" ).addClass("unread"); + } + } } }; diff --git a/spec/javascripts/widgets/notifications-spec.js b/spec/javascripts/widgets/notifications-spec.js index cbb962180..628bc413b 100644 --- a/spec/javascripts/widgets/notifications-spec.js +++ b/spec/javascripts/widgets/notifications-spec.js @@ -3,13 +3,46 @@ * 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")); + this.view = new app.views.Header().render(); + + notifications = Diaspora.BaseWidget.instantiate("Notifications", this.view.$("#notification_badge .badge_count"), this.view.$(".notifications")); 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() { + this.view.$(".notifications").html( + '
' + + '
' + ); + notifications.clickSuccess(JSON.stringify({guid:2,unread:false})); + expect( this.view.$('.stream_element#2')).toHaveClass("read"); + }); + it("changes the css to an unread cell", function() { + this.view.$(".notifications").html( + '
' + + '
' + ); + notifications.clickSuccess(JSON.stringify({guid:1,unread:true})); + expect( this.view.$('.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() { @@ -40,13 +73,13 @@ describe("Diaspora.Widgets.Notifications", function() { describe("showNotification", function() { it("prepends a div to div#notifications", function() { - expect($("#notifications div").length).toEqual(0); + expect(this.view.$(".notifications div").length).toEqual(1); notifications.showNotification({ - html: '
' + html: '
' }); - expect($("#notifications div").length).toEqual(1); + expect(this.view.$(".notifications div").length).toEqual(2); }); it("only increments the notification count if specified to do so", function() { @@ -61,4 +94,4 @@ describe("Diaspora.Widgets.Notifications", function() { }); }); -}); +}); \ No newline at end of file diff --git a/spec/models/notification_spec.rb b/spec/models/notification_spec.rb index a619bb7ef..eb478784d 100644 --- a/spec/models/notification_spec.rb +++ b/spec/models/notification_spec.rb @@ -40,6 +40,21 @@ describe Notification do end end + describe 'set_read_state method' do + it "should set an unread notification to read" do + @note.unread = true + @note.set_read_state( true ) + @note.unread.should == false + end + it "should set an read notification to unread" do + @note.unread = false + @note.set_read_state( false ) + @note.unread.should == true + end + + end + + describe '.concatenate_or_create' do it 'creates a new notificiation if the notification does not exist, or if it is unread' do @note.unread = false