Skip to content

Commit b9f4276

Browse files
committed
allowed inbox notifications to be filtered by status
1 parent 2a5a639 commit b9f4276

6 files changed

Lines changed: 71 additions & 10 deletions

File tree

app/assets/stylesheets/notifications.scss

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
@import 'variables';
22

3+
.notifications-list-header {
4+
display: flex;
5+
justify-content: space-between;
6+
}
7+
38
.notification {
49
border-top: 1px solid $muted-graphic;
510
padding: 0.5em;

app/controllers/notifications_controller.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ def index
1010
.paginate(page: params[:page], per_page: 100)
1111
.order(Arel.sql('is_read ASC, created_at DESC'))
1212

13+
if params[:status].present?
14+
@notifications = @notifications.where(is_read: params[:status] == 'read')
15+
end
16+
1317
if stale?(@notifications)
1418
respond_to do |format|
1519
format.html { render :index, layout: 'without_sidebar' }

app/models/notification.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,16 @@ class Notification < ApplicationRecord
33
belongs_to :user
44

55
delegate :name, to: :community, prefix: true
6+
7+
# Is the notification marked as read?
8+
# @return [Boolean] check result
9+
def read?
10+
is_read
11+
end
12+
13+
# Is the notification not marked as read? The inverse of +read?+
14+
# @return [Boolean] check result
15+
def unread?
16+
!read?
17+
end
618
end

app/views/notifications/index.html.erb

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,23 @@
11
<%= render 'users/tabs', user: current_user %>
22

3+
<%
4+
status = params[:status].presence || 'all'
5+
%>
6+
37
<h1>Your Inbox</h1>
48
<p>You'll find all your inbox messages here, as far back as your account goes.</p>
59

10+
<div class="notifications-list-header has-margin-bottom-2">
11+
<div class="button-list is-gutterless">
12+
<%= link_to 'All', notifications_path,
13+
class: "button is-muted is-outlined #{'is-active' if status == 'all'}" %>
14+
<%= link_to 'Read', query_url(status: 'read'),
15+
class: "button is-muted is-outlined #{'is-active' if status == 'read'}" %>
16+
<%= link_to 'Unread', query_url(status: 'unread'),
17+
class: "button is-muted is-outlined #{'is-active' if status == 'unread'}" %>
18+
</div>
19+
</div>
20+
621
<% @notifications.each do |notif| %>
722
<div class="notification">
823
<div class="form-caption"><%= CGI.unescape_html(notif.created_at.strftime('%b&nbsp;%-d,&nbsp;%Y&nbsp;at&nbsp;%H:%M')).html_safe %></div>

test/controllers/notifications_controller_test.rb

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ class NotificationsControllerTest < ActionController::TestCase
77
sign_in users(:standard_user)
88

99
[:json, :html].each do |format|
10-
try_index(format: format)
10+
try_notifications(format: format)
1111

1212
assert_response(:success)
1313

@@ -27,9 +27,30 @@ class NotificationsControllerTest < ActionController::TestCase
2727
end
2828
end
2929

30+
test ':index should correctly filter notifications' do
31+
sign_in users(:standard_user)
32+
33+
['any', 'read', 'unread'].each do |status|
34+
try_notifications(format: :html, status: status)
35+
36+
assert_response(:success)
37+
38+
@notifications = assigns(:notifications)
39+
assert @notifications&.any?, "Expected at least one #{status} notification"
40+
41+
if status == 'read'
42+
assert @notifications.none?(&:unread?)
43+
elsif status == 'unread'
44+
assert @notifications.none?(&:read?)
45+
end
46+
end
47+
end
48+
3049
test 'should mark notification as read' do
3150
sign_in users(:standard_user)
32-
post :read, params: { id: notifications(:one).id, format: :json }
51+
52+
post :read, params: { id: notifications(:unread).id, format: :json }
53+
3354
assert_not_nil assigns(:notification)
3455
assert_equal true, assigns(:notification).is_read
3556
assert_equal 'success', JSON.parse(response.body)['status']
@@ -38,7 +59,9 @@ class NotificationsControllerTest < ActionController::TestCase
3859

3960
test 'should mark all notifications as read' do
4061
sign_in users(:standard_user)
62+
4163
post :read_all, params: { format: :json }
64+
4265
assert_not_nil assigns(:notifications)
4366
assigns(:notifications).each do |notification|
4467
assert_equal true, notification.is_read
@@ -49,19 +72,19 @@ class NotificationsControllerTest < ActionController::TestCase
4972

5073
test 'should prevent users marking others notifications read' do
5174
sign_in users(:editor)
52-
post :read, params: { id: notifications(:one).id, format: :json }
75+
post :read, params: { id: notifications(:unread).id, format: :json }
5376
assert_response(:forbidden)
5477
end
5578

5679
test 'should require authentication to get index' do
5780
sign_out :user
58-
get :index, params: { format: :json }
81+
try_notifications
5982
assert_response(:unauthorized) # Devise seems to respond 401 for JSON requests.
6083
end
6184

6285
private
6386

64-
def try_index(format: :json)
65-
get :index, params: { format: format }
87+
def try_notifications(**opts)
88+
get :index, params: { format: :json }.merge(opts)
6689
end
6790
end

test/fixtures/notifications.yml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1-
one:
2-
content: ABCDEF GHIJKL MNOPQR STUVWX YZ
1+
read:
2+
content: This is a test notification that is marked as read
33
link: /
44
user: standard_user
55
community: sample
6+
is_read: true
67

7-
two:
8-
content: ABCDEF GHIJKL MNOPQR STUVWX
8+
unread:
9+
content: This is a test notification that is NOT marked as read
910
link: /
1011
user: standard_user
1112
community: sample
13+
is_read: false

0 commit comments

Comments
 (0)