Merge pull request #2398 from basecamp/notifications-tray-api
Add JSON response support for `notifications/tray`
This commit is contained in:
@@ -1,9 +1,27 @@
|
||||
class Notifications::TraysController < ApplicationController
|
||||
MAX_ENTRIES_LIMIT = 100
|
||||
|
||||
def show
|
||||
@notifications = Current.user.notifications.unread.preloaded.ordered.limit(100)
|
||||
@notifications = unread_notifications
|
||||
if include_read?
|
||||
@notifications += read_notifications
|
||||
end
|
||||
|
||||
# Invalidate on the whole set instead of the unread set since the max updated at in the unread set
|
||||
# can stay the same when reading old notifications.
|
||||
fresh_when Current.user.notifications
|
||||
fresh_when etag: [ Current.user.notifications, include_read? ]
|
||||
end
|
||||
|
||||
private
|
||||
def unread_notifications
|
||||
Current.user.notifications.unread.preloaded.ordered.limit(MAX_ENTRIES_LIMIT)
|
||||
end
|
||||
|
||||
def read_notifications
|
||||
Current.user.notifications.read.preloaded.ordered.limit(MAX_ENTRIES_LIMIT)
|
||||
end
|
||||
|
||||
def include_read?
|
||||
ActiveModel::Type::Boolean.new.cast(params[:include_read])
|
||||
end
|
||||
end
|
||||
|
||||
@@ -10,7 +10,13 @@ class Notification < ApplicationRecord
|
||||
scope :unread, -> { where(read_at: nil) }
|
||||
scope :read, -> { where.not(read_at: nil) }
|
||||
scope :ordered, -> { order(read_at: :desc, updated_at: :desc) }
|
||||
scope :preloaded, -> { preload(:card, :creator, :account, source: [ :board, :creator, { eventable: [ :closure, :board, :assignments ] } ]) }
|
||||
scope :preloaded, -> {
|
||||
preload(
|
||||
:creator, :account,
|
||||
card: [ :board, :column, :closure, :not_now ],
|
||||
source: [ :board, :creator, { eventable: [ :closure, :board, :assignments ] } ]
|
||||
)
|
||||
}
|
||||
|
||||
before_validation :set_card
|
||||
after_create :bundle
|
||||
|
||||
@@ -8,6 +8,7 @@ json.cache! card do
|
||||
json.tags card.tags.pluck(:title).sort
|
||||
|
||||
json.closed card.closed?
|
||||
json.postponed card.postponed?
|
||||
json.golden card.golden?
|
||||
json.last_active_at card.last_active_at.utc
|
||||
json.created_at card.created_at.utc
|
||||
|
||||
@@ -3,14 +3,19 @@ json.cache! notification do
|
||||
json.read notification.read?
|
||||
json.read_at notification.read_at&.utc
|
||||
json.created_at notification.created_at.utc
|
||||
json.source_type notification.source_type.underscore
|
||||
|
||||
json.partial! "notifications/notification/#{notification.source_type.underscore}/body", notification: notification
|
||||
|
||||
json.creator notification.creator, partial: "users/user", as: :user
|
||||
|
||||
json.card do
|
||||
json.(notification.card, :id, :title, :status)
|
||||
json.(notification.card, :id, :number, :title, :status)
|
||||
json.board_name notification.card.board.name
|
||||
json.closed notification.card.closed?
|
||||
json.postponed notification.card.postponed?
|
||||
json.url card_url(notification.card)
|
||||
json.column notification.card.column, partial: "columns/column", as: :column if notification.card.column
|
||||
end
|
||||
|
||||
json.url notification_url(notification)
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
json.array! @notifications, partial: "notifications/notification", as: :notification
|
||||
@@ -5,4 +5,5 @@ json.cache! user do
|
||||
json.created_at user.created_at.utc
|
||||
|
||||
json.url user_url(user)
|
||||
json.avatar_url user_avatar_url(user)
|
||||
end
|
||||
|
||||
@@ -176,6 +176,7 @@ class CardsControllerTest < ActionDispatch::IntegrationTest
|
||||
|
||||
assert_equal card.title, @response.parsed_body["title"]
|
||||
assert_equal card.closed?, @response.parsed_body["closed"]
|
||||
assert_equal card.postponed?, @response.parsed_body["postponed"]
|
||||
assert_equal 2, @response.parsed_body["steps"].size
|
||||
assert_equal card_comments_url(card), @response.parsed_body["comments_url"]
|
||||
assert_equal card_reactions_url(card), @response.parsed_body["reactions_url"]
|
||||
|
||||
@@ -11,4 +11,24 @@ class Notifications::TraysControllerTest < ActionDispatch::IntegrationTest
|
||||
assert_response :success
|
||||
assert_select "div", text: /Layout is broken/
|
||||
end
|
||||
|
||||
test "show as JSON" do
|
||||
expected_ids = users(:kevin).notifications.unread.ordered.limit(100).pluck(:id)
|
||||
|
||||
get tray_notifications_path(format: :json)
|
||||
|
||||
assert_response :success
|
||||
assert_equal expected_ids, @response.parsed_body.map { |s| s["id"] }
|
||||
end
|
||||
|
||||
test "show as JSON with include_read includes read notifications" do
|
||||
notifications = users(:kevin).notifications
|
||||
expected_ids = notifications.unread.ordered.limit(100).pluck(:id) +
|
||||
notifications.read.ordered.limit(100).pluck(:id)
|
||||
|
||||
get tray_notifications_path(format: :json, include_read: true)
|
||||
|
||||
assert_response :success
|
||||
assert_equal expected_ids, @response.parsed_body.map { |s| s["id"] }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -22,5 +22,13 @@ class NotificationsControllerTest < ActionDispatch::IntegrationTest
|
||||
assert_not_nil notification["card"]
|
||||
assert_not_nil notification["creator"]
|
||||
assert_not_nil notification["unread_count"]
|
||||
assert_not_nil notification.dig("creator", "avatar_url")
|
||||
assert_not_nil notification.dig("card", "number")
|
||||
assert_not_nil notification.dig("card", "board_name")
|
||||
assert_not_nil notification.dig("card", "column")
|
||||
|
||||
card = notifications(:logo_assignment_kevin).card
|
||||
assert_equal card.closed?, notification.dig("card", "closed")
|
||||
assert_equal card.postponed?, notification.dig("card", "postponed")
|
||||
end
|
||||
end
|
||||
|
||||
Vendored
+3
@@ -5,6 +5,7 @@ logo_assignment_kevin:
|
||||
card: logo_uuid
|
||||
unread_count: 2
|
||||
created_at: <%= 1.week.ago %>
|
||||
updated_at: <%= 1.week.ago + 1.second %>
|
||||
creator: david_uuid
|
||||
account: 37s_uuid
|
||||
|
||||
@@ -15,6 +16,7 @@ layout_commented_kevin:
|
||||
card: layout_uuid
|
||||
unread_count: 1
|
||||
created_at: <%= 1.week.ago %>
|
||||
updated_at: <%= 1.week.ago + 2.seconds %>
|
||||
creator: david_uuid
|
||||
account: 37s_uuid
|
||||
|
||||
@@ -25,5 +27,6 @@ logo_mentioned_david:
|
||||
card: logo_uuid
|
||||
unread_count: 2
|
||||
created_at: <%= 1.week.ago %>
|
||||
updated_at: <%= 1.week.ago + 3.seconds %>
|
||||
creator: david_uuid
|
||||
account: 37s_uuid
|
||||
|
||||
Reference in New Issue
Block a user