diff --git a/app/assets/javascripts/discourse/controllers/user-notifications.js.es6 b/app/assets/javascripts/discourse/controllers/user-notifications.js.es6 index 43394e6453c..45f3c22f69f 100644 --- a/app/assets/javascripts/discourse/controllers/user-notifications.js.es6 +++ b/app/assets/javascripts/discourse/controllers/user-notifications.js.es6 @@ -2,8 +2,18 @@ export default Ember.ArrayController.extend({ canLoadMore: true, loading: false, + showDismissButton: function() { + return this.get('user').total_unread_notifications > 0; + }.property('user'), actions: { + resetNew: function() { + Discourse.NotificationContainer.resetNew().then(function() { + var c = Discourse.__container__.lookup("controller:UserNotifications") + c.setEach("read", true) + }); + }, + loadMore: function() { if (this.get('canLoadMore') && !this.get('loading')) { this.set('loading', true); diff --git a/app/assets/javascripts/discourse/models/notification.js b/app/assets/javascripts/discourse/models/notification.js index 8fcb2742700..469a1f2db04 100644 --- a/app/assets/javascripts/discourse/models/notification.js +++ b/app/assets/javascripts/discourse/models/notification.js @@ -46,5 +46,9 @@ Discourse.NotificationContainer.reopenClass({ }).catch(function(error) { return Discourse.NotificationContainer.createFromError(error); }); + }, + + resetNew: function() { + return Discourse.ajax("/notifications/reset-new", {type: 'PUT'}); } }); diff --git a/app/assets/javascripts/discourse/templates/user/notifications.hbs b/app/assets/javascripts/discourse/templates/user/notifications.hbs index d0c6a2bfde6..e1c280b530e 100644 --- a/app/assets/javascripts/discourse/templates/user/notifications.hbs +++ b/app/assets/javascripts/discourse/templates/user/notifications.hbs @@ -7,6 +7,11 @@ {{/if}} {{/if}} +{{#if showDismissButton}} +
+ +
+{{/if}} {{#each itemController="notification"}}
@@ -16,9 +21,15 @@
{{/each}} + {{#if loading}}
{{/if}} {{#unless canLoadMore}}
+ {{#if showDismissButton}} +
+ +
+ {{/if}} {{/unless}} diff --git a/app/assets/stylesheets/common/base/user.scss b/app/assets/stylesheets/common/base/user.scss index 910cabc5d0a..5d60437f411 100644 --- a/app/assets/stylesheets/common/base/user.scss +++ b/app/assets/stylesheets/common/base/user.scss @@ -29,6 +29,11 @@ width: 100%; } +.notification-buttons { + margin: 10px 0; + text-align: right; +} + .user-navigation { .map { diff --git a/app/controllers/notifications_controller.rb b/app/controllers/notifications_controller.rb index 40c0b6227e6..c011b742f26 100644 --- a/app/controllers/notifications_controller.rb +++ b/app/controllers/notifications_controller.rb @@ -37,4 +37,21 @@ class NotificationsController < ApplicationController render_serialized(notifications, NotificationSerializer) 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 diff --git a/app/models/user.rb b/app/models/user.rb index 0413e007211..5c5de05877c 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -242,6 +242,7 @@ class User < ActiveRecord::Base def reload @unread_notifications_by_type = nil + @unread_total_notifications = nil @unread_pms = nil super end @@ -254,6 +255,10 @@ class User < ActiveRecord::Base unread_notifications_by_type.except(Notification.types[:private_message]).values.sum end + def total_unread_notifications + @unread_total_notifications ||= notifications.where("read = false").count + end + def saw_notification_id(notification_id) User.where("id = ? and seen_notification_id < ?", id, notification_id) .update_all ["seen_notification_id = ?", notification_id] @@ -266,7 +271,8 @@ class User < ActiveRecord::Base def publish_notifications_state MessageBus.publish("/notification/#{id}", {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 ) end diff --git a/app/serializers/current_user_serializer.rb b/app/serializers/current_user_serializer.rb index 31bb74bed9a..7264c65a315 100644 --- a/app/serializers/current_user_serializer.rb +++ b/app/serializers/current_user_serializer.rb @@ -1,6 +1,7 @@ class CurrentUserSerializer < BasicUserSerializer attributes :name, + :total_unread_notifications, :unread_notifications, :unread_private_messages, :admin?, diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index c2a709d8026..f9ff3d74b76 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -308,6 +308,8 @@ en: invited_by: "Invited By" trust_level: "Trust Level" 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" dynamic_favicon: "Show incoming message notifications on favicon (experimental)" edit_history_public: "Let other users view my post revisions" diff --git a/config/routes.rb b/config/routes.rb index 66c373631bc..989408649bc 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -285,6 +285,7 @@ Discourse::Application.routes.draw do get "notifications" => "notifications#recent" 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/failure", to: "users/omniauth_callbacks#failure", via: [:get, :post] diff --git a/spec/controllers/notifications_controller_spec.rb b/spec/controllers/notifications_controller_spec.rb index 71326786866..d326c8c8e9a 100644 --- a/spec/controllers/notifications_controller_spec.rb +++ b/spec/controllers/notifications_controller_spec.rb @@ -15,18 +15,37 @@ describe NotificationsController do response.should be_success end + it 'should succeed for history' do + xhr :get, :reset_new + response.should be_success + end + it 'should mark notifications as viewed' do notification = Fabricate(:notification, user: user) user.reload.unread_notifications.should == 1 + user.reload.total_unread_notifications.should == 1 xhr :get, :recent user.reload.unread_notifications.should == 0 + user.reload.total_unread_notifications.should == 1 end it 'should not mark notifications as viewed if silent param is present' do notification = Fabricate(:notification, user: user) user.reload.unread_notifications.should == 1 + user.reload.total_unread_notifications.should == 1 xhr :get, :recent, silent: true 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 diff --git a/spec/models/notification_spec.rb b/spec/models/notification_spec.rb index 57aa05957bf..2f688b89d9c 100644 --- a/spec/models/notification_spec.rb +++ b/spec/models/notification_spec.rb @@ -78,6 +78,10 @@ describe Notification do lambda { Fabricate(:notification, user: user); user.reload }.should change(user, :unread_notifications) 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 lambda { Fabricate(:notification, user: user); user.reload }.should_not change(user, :unread_private_messages) end @@ -88,6 +92,10 @@ describe Notification do lambda { Fabricate(:private_message_notification, user: user); user.reload }.should_not change(user, :unread_notifications) 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 lambda { Fabricate(:private_message_notification, user: user); user.reload }.should change(user, :unread_private_messages) end @@ -141,6 +149,7 @@ describe Notification do it 'should create and rollup private message notifications' do @target.notifications.first.notification_type.should == Notification.types[:private_message] @post.user.unread_notifications.should == 0 + @post.user.total_unread_notifications.should == 0 @target.unread_private_messages.should == 1 Fabricate(:post, topic: @topic, user: @topic.user) @@ -197,6 +206,7 @@ describe Notification do user.reload user.unread_notifications.should == 0 + user.total_unread_notifications.should == 2 user.unread_private_messages.should == 1 end end