Merge pull request #2547 from stwf/unread_notifications
Allow users to click on read notifications to mark them as unread
This commit is contained in:
commit
c61e84bc50
8 changed files with 97 additions and 18 deletions
|
|
@ -11,8 +11,8 @@ class NotificationsController < VannaController
|
||||||
def update(opts=params)
|
def update(opts=params)
|
||||||
note = Notification.where(:recipient_id => current_user.id, :id => opts[:id]).first
|
note = Notification.where(:recipient_id => current_user.id, :id => opts[:id]).first
|
||||||
if note
|
if note
|
||||||
note.update_attributes(:unread => false)
|
note.update_attributes(:unread => opts[:unread] == "true" )
|
||||||
{}
|
{ :guid => note.id, :unread => note.unread }
|
||||||
else
|
else
|
||||||
Response.new :status => 404
|
Response.new :status => 404
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
.span-8.notifications_for_day
|
.span-8.notifications_for_day
|
||||||
- notes.each do |note|
|
- 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])
|
- if note.type == "Notifications::StartedSharing" && contact = current_user.contact_for(note[:target])
|
||||||
.right
|
.right
|
||||||
= aspect_membership_dropdown(contact, note[:target], 'left')
|
= aspect_membership_dropdown(contact, note[:target], 'left')
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
= day
|
= day
|
||||||
%ul.notifications_for_day
|
%ul.notifications_for_day
|
||||||
- notes.each do |note|
|
- 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)
|
= person_image_link(note.actors.last)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,7 @@
|
||||||
$.each(notifications, function(index, notification) {
|
$.each(notifications, function(index, notification) {
|
||||||
var notificationElement = $("<div/>")
|
var notificationElement = $("<div/>")
|
||||||
.addClass("notification_element")
|
.addClass("notification_element")
|
||||||
|
.data( "guid", notification.id )
|
||||||
.html(notification.translation)
|
.html(notification.translation)
|
||||||
.prepend($("<img/>", { src: notification.actors[0].avatar }))
|
.prepend($("<img/>", { src: notification.actors[0].avatar }))
|
||||||
.append("<br />")
|
.append("<br />")
|
||||||
|
|
@ -73,16 +74,18 @@
|
||||||
.appendTo(self.dropdownNotifications);
|
.appendTo(self.dropdownNotifications);
|
||||||
|
|
||||||
notificationElement.find("abbr.timeago").timeago();
|
notificationElement.find("abbr.timeago").timeago();
|
||||||
|
notificationElement.click(Diaspora.page.header.notifications.messageClick);
|
||||||
|
|
||||||
if(notification.unread) {
|
if(notification.unread) {
|
||||||
notificationElement.addClass("unread");
|
notificationElement.addClass("unread");
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: "/notifications/" + notification.id,
|
url: "/notifications/" + notification.id,
|
||||||
type: "PUT",
|
type: "PUT",
|
||||||
success: function() {
|
data: { unread: false },
|
||||||
Diaspora.page.header.notifications.decrementCount();
|
success: Diaspora.page.header.notifications.clickSuccess
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
notificationElement.addClass("read");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -15,14 +15,7 @@
|
||||||
notificationArea: notificationArea
|
notificationArea: notificationArea
|
||||||
});
|
});
|
||||||
|
|
||||||
$(".stream_element.unread").live("mousedown", function() {
|
$(".stream_element.unread,.stream_element.read").live("mousedown", self.messageClick);
|
||||||
self.decrementCount();
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
url: "notifications/" + $(this).removeClass("unread").data("guid"),
|
|
||||||
type: "PUT"
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
$("a.more").live("click", function(evt) {
|
$("a.more").live("click", function(evt) {
|
||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
|
|
@ -31,7 +24,33 @@
|
||||||
.removeClass("hidden");
|
.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) {
|
this.showNotification = function(notification) {
|
||||||
$(notification.html).prependTo(this.notificationArea)
|
$(notification.html).prependTo(this.notificationArea)
|
||||||
.fadeIn(200)
|
.fadeIn(200)
|
||||||
|
|
@ -50,12 +69,15 @@
|
||||||
|
|
||||||
if(self.badge.text() !== "") {
|
if(self.badge.text() !== "") {
|
||||||
self.badge.text(self.count);
|
self.badge.text(self.count);
|
||||||
|
$( ".notification_count" ).text(self.count);
|
||||||
|
|
||||||
if(self.count === 0) {
|
if(self.count === 0) {
|
||||||
self.badge.addClass("hidden");
|
self.badge.addClass("hidden");
|
||||||
|
$( ".notification_count" ).removeClass("unread");
|
||||||
}
|
}
|
||||||
else if(self.count === 1) {
|
else if(self.count === 1) {
|
||||||
self.badge.removeClass("hidden");
|
self.badge.removeClass("hidden");
|
||||||
|
$( ".notification_count" ).addClass("unread");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -3138,6 +3138,8 @@ a.toggle_selector
|
||||||
.notification_element
|
.notification_element
|
||||||
:padding 10px
|
:padding 10px
|
||||||
:min-height 30px
|
:min-height 30px
|
||||||
|
&:hover
|
||||||
|
:background-color #FAFAFA
|
||||||
|
|
||||||
> img
|
> img
|
||||||
:height 30px
|
:height 30px
|
||||||
|
|
|
||||||
|
|
@ -14,11 +14,32 @@ describe NotificationsController do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#update' do
|
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)
|
note = Factory(:notification, :recipient => @user)
|
||||||
@controller.update :id => note.id
|
@controller.update :id => note.id
|
||||||
Notification.first.unread.should == false
|
Notification.first.unread.should == false
|
||||||
end
|
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
|
it 'only lets you read your own notifications' do
|
||||||
user2 = bob
|
user2 = bob
|
||||||
|
|
|
||||||
|
|
@ -3,13 +3,44 @@
|
||||||
* the COPYRIGHT file.
|
* the COPYRIGHT file.
|
||||||
*/
|
*/
|
||||||
describe("Diaspora.Widgets.Notifications", function() {
|
describe("Diaspora.Widgets.Notifications", function() {
|
||||||
var changeNotificationCountSpy, notifications;
|
var changeNotificationCountSpy, notifications, incrementCountSpy, decrementCountSpy;
|
||||||
|
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
spec.loadFixture("aspects_index");
|
spec.loadFixture("aspects_index");
|
||||||
notifications = Diaspora.BaseWidget.instantiate("Notifications", $("#notifications"), $("#notification_badge .badge_count"));
|
notifications = Diaspora.BaseWidget.instantiate("Notifications", $("#notifications"), $("#notification_badge .badge_count"));
|
||||||
|
|
||||||
changeNotificationCountSpy = spyOn(notifications, "changeNotificationCount").andCallThrough();
|
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(
|
||||||
|
'<div id="1" class="stream_element read" data-guid=1></div>' +
|
||||||
|
'<div id="2" class="stream_element unread" data-guid=2></div>'
|
||||||
|
);
|
||||||
|
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(
|
||||||
|
'<div id="1" class="stream_element read" data-guid=1></div>' +
|
||||||
|
'<div id="2" class="stream_element unread" data-guid=2></div>'
|
||||||
|
);
|
||||||
|
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() {
|
describe("decrementCount", function() {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue