Merge pull request #2874 from cpradio/clear-notifications

FEATURE: Mark All as Read button for Notifications page
This commit is contained in:
Robin Ward 2014-10-16 15:57:19 -04:00
commit f3a67a48a3
11 changed files with 88 additions and 1 deletions

View File

@ -1,9 +1,20 @@
export default Ember.ArrayController.extend({ export default Ember.ArrayController.extend({
needs: ['user-notifications'],
canLoadMore: true, canLoadMore: true,
loading: false, loading: false,
showDismissButton: function() {
return this.get('user').total_unread_notifications > 0;
}.property('user'),
actions: { actions: {
resetNew: function() {
var self = this;
Discourse.NotificationContainer.resetNew().then(function() {
self.get('controllers.user-notifications').setEach('read', true);
});
},
loadMore: function() { loadMore: function() {
if (this.get('canLoadMore') && !this.get('loading')) { if (this.get('canLoadMore') && !this.get('loading')) {
this.set('loading', true); this.set('loading', true);

View File

@ -46,5 +46,9 @@ Discourse.NotificationContainer.reopenClass({
}).catch(function(error) { }).catch(function(error) {
return Discourse.NotificationContainer.createFromError(error); return Discourse.NotificationContainer.createFromError(error);
}); });
},
resetNew: function() {
return Discourse.ajax("/notifications/reset-new", {type: 'PUT'});
} }
}); });

View File

@ -7,6 +7,11 @@
{{/if}} {{/if}}
</div> </div>
{{/if}} {{/if}}
{{#if showDismissButton}}
<div class='notification-buttons'>
<button title="{{i18n user.dismiss_notifications_tooltip}}" id='dismiss-notifications-top' class='btn notifications-read' {{action "resetNew"}}>{{i18n user.dismiss_notifications}}</button>
</div>
{{/if}}
{{#each itemController="notification"}} {{#each itemController="notification"}}
<div {{bind-attr class=":item :notification read::unread"}}> <div {{bind-attr class=":item :notification read::unread"}}>
@ -16,9 +21,15 @@
</span> </span>
</div> </div>
{{/each}} {{/each}}
{{#if loading}} {{#if loading}}
<div class='spinner'></div> <div class='spinner'></div>
{{/if}} {{/if}}
{{#unless canLoadMore}} {{#unless canLoadMore}}
<div class='end-of-stream'></div> <div class='end-of-stream'></div>
{{#if showDismissButton}}
<div class='notification-buttons'>
<button title="{{i18n user.dismiss_notifications_tooltip}}" id='dismiss-notifications' class='btn notifications-read' {{action "resetNew"}}>{{i18n user.dismiss_notifications}}</button>
</div>
{{/if}}
{{/unless}} {{/unless}}

View File

@ -29,6 +29,11 @@
width: 100%; width: 100%;
} }
.notification-buttons {
margin: 10px 0;
text-align: right;
}
.user-navigation { .user-navigation {
.map { .map {

View File

@ -37,4 +37,21 @@ class NotificationsController < ApplicationController
render_serialized(notifications, NotificationSerializer) render_serialized(notifications, NotificationSerializer)
end end
def reset_new
params.permit(:user)
user = current_user
if params[:user]
user = User.find_by_username(params[:user].to_s)
end
Notification.where(user_id: user.id).includes(:topic).where(read: false).update_all(read: true)
current_user.saw_notification_id(Notification.recent_report(current_user, 1).max)
current_user.reload
current_user.publish_notifications_state
render nothing: true
end
end end

View File

@ -242,6 +242,7 @@ class User < ActiveRecord::Base
def reload def reload
@unread_notifications_by_type = nil @unread_notifications_by_type = nil
@unread_total_notifications = nil
@unread_pms = nil @unread_pms = nil
super super
end end
@ -254,6 +255,10 @@ class User < ActiveRecord::Base
unread_notifications_by_type.except(Notification.types[:private_message]).values.sum unread_notifications_by_type.except(Notification.types[:private_message]).values.sum
end end
def total_unread_notifications
@unread_total_notifications ||= notifications.where("read = false").count
end
def saw_notification_id(notification_id) def saw_notification_id(notification_id)
User.where("id = ? and seen_notification_id < ?", id, notification_id) User.where("id = ? and seen_notification_id < ?", id, notification_id)
.update_all ["seen_notification_id = ?", notification_id] .update_all ["seen_notification_id = ?", notification_id]
@ -266,7 +271,8 @@ class User < ActiveRecord::Base
def publish_notifications_state def publish_notifications_state
MessageBus.publish("/notification/#{id}", MessageBus.publish("/notification/#{id}",
{unread_notifications: unread_notifications, {unread_notifications: unread_notifications,
unread_private_messages: unread_private_messages}, unread_private_messages: unread_private_messages,
total_unread_notifications: total_unread_notifications},
user_ids: [id] # only publish the notification to this user user_ids: [id] # only publish the notification to this user
) )
end end

View File

@ -1,6 +1,7 @@
class CurrentUserSerializer < BasicUserSerializer class CurrentUserSerializer < BasicUserSerializer
attributes :name, attributes :name,
:total_unread_notifications,
:unread_notifications, :unread_notifications,
:unread_private_messages, :unread_private_messages,
:admin?, :admin?,

View File

@ -295,6 +295,8 @@ en:
invited_by: "Invited By" invited_by: "Invited By"
trust_level: "Trust Level" trust_level: "Trust Level"
notifications: "Notifications" notifications: "Notifications"
dismiss_notifications: "Mark all as Read"
dismiss_notifications_tooltip: "Mark all unread notifications as read"
disable_jump_reply: "Don't jump to your new post after replying" disable_jump_reply: "Don't jump to your new post after replying"
dynamic_favicon: "Show incoming message notifications on favicon (experimental)" dynamic_favicon: "Show incoming message notifications on favicon (experimental)"
edit_history_public: "Let other users view my post revisions" edit_history_public: "Let other users view my post revisions"

View File

@ -291,6 +291,7 @@ Discourse::Application.routes.draw do
get "notifications" => "notifications#recent" get "notifications" => "notifications#recent"
get "notifications/history" => "notifications#history" get "notifications/history" => "notifications#history"
put "notifications/reset-new" => 'notifications#reset_new'
match "/auth/:provider/callback", to: "users/omniauth_callbacks#complete", via: [:get, :post] match "/auth/:provider/callback", to: "users/omniauth_callbacks#complete", via: [:get, :post]
match "/auth/failure", to: "users/omniauth_callbacks#failure", via: [:get, :post] match "/auth/failure", to: "users/omniauth_callbacks#failure", via: [:get, :post]

View File

@ -15,18 +15,37 @@ describe NotificationsController do
response.should be_success response.should be_success
end end
it 'should succeed for history' do
xhr :get, :reset_new
response.should be_success
end
it 'should mark notifications as viewed' do it 'should mark notifications as viewed' do
notification = Fabricate(:notification, user: user) notification = Fabricate(:notification, user: user)
user.reload.unread_notifications.should == 1 user.reload.unread_notifications.should == 1
user.reload.total_unread_notifications.should == 1
xhr :get, :recent xhr :get, :recent
user.reload.unread_notifications.should == 0 user.reload.unread_notifications.should == 0
user.reload.total_unread_notifications.should == 1
end end
it 'should not mark notifications as viewed if silent param is present' do it 'should not mark notifications as viewed if silent param is present' do
notification = Fabricate(:notification, user: user) notification = Fabricate(:notification, user: user)
user.reload.unread_notifications.should == 1 user.reload.unread_notifications.should == 1
user.reload.total_unread_notifications.should == 1
xhr :get, :recent, silent: true xhr :get, :recent, silent: true
user.reload.unread_notifications.should == 1 user.reload.unread_notifications.should == 1
user.reload.total_unread_notifications.should == 1
end
it "updates the `read` status" do
notification = Fabricate(:notification, user: user)
user.reload.unread_notifications.should == 1
user.reload.total_unread_notifications.should == 1
xhr :put, :reset_new
user.reload
user.reload.unread_notifications.should == 0
user.reload.total_unread_notifications.should == 0
end end
end end

View File

@ -78,6 +78,10 @@ describe Notification do
lambda { Fabricate(:notification, user: user); user.reload }.should change(user, :unread_notifications) lambda { Fabricate(:notification, user: user); user.reload }.should change(user, :unread_notifications)
end end
it 'increases total_unread_notifications' do
lambda { Fabricate(:notification, user: user); user.reload }.should change(user, :total_unread_notifications)
end
it "doesn't increase unread_private_messages" do it "doesn't increase unread_private_messages" do
lambda { Fabricate(:notification, user: user); user.reload }.should_not change(user, :unread_private_messages) lambda { Fabricate(:notification, user: user); user.reload }.should_not change(user, :unread_private_messages)
end end
@ -88,6 +92,10 @@ describe Notification do
lambda { Fabricate(:private_message_notification, user: user); user.reload }.should_not change(user, :unread_notifications) lambda { Fabricate(:private_message_notification, user: user); user.reload }.should_not change(user, :unread_notifications)
end end
it 'increases total_unread_notifications' do
lambda { Fabricate(:notification, user: user); user.reload }.should change(user, :total_unread_notifications)
end
it "increases unread_private_messages" do it "increases unread_private_messages" do
lambda { Fabricate(:private_message_notification, user: user); user.reload }.should change(user, :unread_private_messages) lambda { Fabricate(:private_message_notification, user: user); user.reload }.should change(user, :unread_private_messages)
end end
@ -141,6 +149,7 @@ describe Notification do
it 'should create and rollup private message notifications' do it 'should create and rollup private message notifications' do
@target.notifications.first.notification_type.should == Notification.types[:private_message] @target.notifications.first.notification_type.should == Notification.types[:private_message]
@post.user.unread_notifications.should == 0 @post.user.unread_notifications.should == 0
@post.user.total_unread_notifications.should == 0
@target.unread_private_messages.should == 1 @target.unread_private_messages.should == 1
Fabricate(:post, topic: @topic, user: @topic.user) Fabricate(:post, topic: @topic, user: @topic.user)
@ -197,6 +206,7 @@ describe Notification do
user.reload user.reload
user.unread_notifications.should == 0 user.unread_notifications.should == 0
user.total_unread_notifications.should == 2
user.unread_private_messages.should == 1 user.unread_private_messages.should == 1
end end
end end