Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions engine/app/controllers/coplan/plans_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -630,6 +630,13 @@ def load_needs_attention
@attention_unread_counts = unread_by_plan
top_ids = unread_by_plan.sort_by { |_id, count| -count }
.first(ATTENTION_LIMIT).map(&:first)
# The plan view hides resolved threads by default. Route each inbox row
# through an unread notification so the destination marks it read and
# deep-links to the exact thread, even when that thread is resolved.
# This is deliberately bounded to ATTENTION_LIMIT indexed lookups.
@attention_notification_ids = top_ids.index_with do |plan_id|
current_user.notifications.unread.where(plan_id: plan_id).newest_first.pick(:id)
end
# Even an inbox routes through the discovery predicate — a stale
# notification must not resurface an archived plan or another user's
# unlisted draft.
Expand Down
2 changes: 1 addition & 1 deletion engine/app/views/coplan/plans/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@
<ul class="attention__list">
<% @attention_plans.each do |plan| %>
<li class="attention__item">
<%= link_to plan.title, plan_path(plan), class: "attention__link" %>
<%= link_to plan.title, notification_path(@attention_notification_ids.fetch(plan.id)), class: "attention__link", data: { turbo: false } %>
<span class="attention__unread"><%= pluralize(@attention_unread_counts[plan.id].to_i, "unread comment") %></span>
</li>
<% end %>
Expand Down
15 changes: 14 additions & 1 deletion spec/requests/plans_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -733,11 +733,24 @@
describe "needs attention strip" do
it "lists plans with unread comments for the current user" do
thread = create(:comment_thread, plan: plan, created_by_user: bob)
create(:notification, user: alice, plan: plan, comment_thread: thread)
notification = create(:notification, user: alice, plan: plan, comment_thread: thread)

get plans_path
expect(response.body).to include("Needs attention (1)")
expect(response.body).to include("1 unread comment")
attention_link = Nokogiri::HTML(response.body).at_css(".attention__link")
expect(attention_link["href"]).to eq(notification_path(notification))
expect(attention_link["data-turbo"]).to eq("false")
end

it "links resolved unread comments through their notification deep link" do
thread = create(:comment_thread, :resolved, plan: plan, created_by_user: bob)
notification = create(:notification, user: alice, plan: plan, comment_thread: thread)

get plans_path

expect(response.body).to include(notification_path(notification))
expect(response.body).not_to include(%(href="#{plan_path(plan)}" class="attention__link"))
end

it "is omitted when nothing is unread" do
Expand Down
Loading