Merge pull request #269 from basecamp/mark-single-notification-read

Mark individual notifications as read
This commit is contained in:
Jason Zimdars
2025-02-21 16:46:00 -06:00
committed by GitHub
7 changed files with 84 additions and 31 deletions
+2 -1
View File
@@ -24,7 +24,8 @@
border var( --transition),
color var( --transition),
filter var( --transition),
opacity var( --transition);
opacity var( --transition),
scale var( --transition);
img {
-webkit-touch-callout: none;
+24 -9
View File
@@ -157,17 +157,32 @@
}
.notification__unread_indicator {
--size: 0.8em;
--btn-background: var(--color-marker);
--btn-border-color: var(--color-bg);
--btn-icon-size: 0.7em;
--btn-padding: 0;
--btn-size: 1.2em;
--hover-size: 0;
padding-block-start: var(--size);
inset: var(--block-space) var(--inline-space) auto auto;
position: absolute;
scale: 0.7;
.dot {
aspect-ratio: 1;
background-color: var(--color-marker);
border-radius: 50%;
block-size: var(--size);
inline-size: var(--size);
margin-inline-end: var(--inline-space-half);
img {
visibility: hidden;
}
@media (hover: hover) {
.notification:hover & {
--btn-background: var(--color-subtle-dark);
--btn-border-color: var(--color-subtle-dark);
scale: 1;
img {
visibility: unset;
}
}
}
.notificiations-list--read & {
@@ -6,4 +6,14 @@ class NotificationsController < ApplicationController
@unread = Current.user.notifications.unread.ordered
end
end
def mark_read
@notification = Current.user.notifications.find(params[:id])
@notification.update!(read_at: Time.current)
respond_to do |format|
format.html { redirect_back fallback_location: notifications_path }
format.turbo_stream
end
end
end
+19 -2
View File
@@ -22,8 +22,25 @@ module NotificationsHelper
end
def notification_tag(notification, &)
link_to notification.resource, id: dom_id(notification), class: "notification border-radius",
data: { action: "click->dialog#close", turbo_frame: "_top" }, &
tag.div id: dom_id(notification), class: "notification border-radius flex position-relative" do
concat(
link_to(notification.resource,
class: "notification__content border-radius pad shadow fill-white flex align-start txt-align-start gap flex-item-grow",
data: { action: "click->dialog#close", turbo_frame: "_top" },
&)
)
concat(notification_mark_read_button(notification))
end
end
def notification_mark_read_button(notification)
button_to mark_read_notification_path(notification),
class: "notification__unread_indicator btn borderless",
title: "Mark as read",
data: { turbo_frame: "_top" } do
concat(image_tag("remove-med.svg", class: "unread_icon", size: 12, aria: { hidden: true }))
concat(tag.span("Mark as read", class: "for-screen-reader"))
end
end
def notifications_next_page_link(page)
+13 -19
View File
@@ -1,25 +1,19 @@
<% cache notification do %>
<%= notification_tag notification do %>
<div class="notification__content border-radius pad shadow fill-white flex align-start txt-align-start gap">
<div class="avatar txt-small flex-item-no-shrink">
<%= avatar_image_tag(notification.creator) %>
</div>
<div class="avatar txt-small flex-item-no-shrink">
<%= avatar_image_tag(notification.creator) %>
</div>
<div class="flex flex-column txt-tight-lines min-width flex-item-grow">
<strong class="overflow-ellipsis"><%= notification_title(notification) %></strong>
<div class="overflow-ellipsis">
<% if notification.event.action == "commented" %>
<%= "#{ strip_tags(notification.event.comment.body_html).blank? ? "#{ notification.event.creator.name } replied" : "#{ notification.event.creator.name }:" } #{ strip_tags(notification.event.comment.body_html).truncate(200) }" %>
<% else %>
<%= notification_body(notification) %>
<% end %>
</div>
<div class="overflow-ellipsis translucent"><%= notification.bubble.bucket.name %> · <%= local_datetime_tag(notification.created_at, style: :ago) %></div>
</div>
<div class="notification__unread_indicator flex flex-column flex-item-justify-end">
<div class="dot flex-item-no-shrink"></div>
</div>
<div class="flex flex-column txt-tight-lines min-width flex-item-grow">
<strong class="overflow-ellipsis"><%= notification_title(notification) %></strong>
<div class="overflow-ellipsis">
<% if notification.event.action == "commented" %>
<%= "#{ strip_tags(notification.event.comment.body_html).blank? ? "#{ notification.event.creator.name } replied" : "#{ notification.event.creator.name }:" } #{ strip_tags(notification.event.comment.body_html).truncate(200) }" %>
<% else %>
<%= notification_body(notification) %>
<% end %>
</div>
<div class="overflow-ellipsis translucent"><%= notification.bubble.bucket.name %> · <%= local_datetime_tag(notification.created_at, style: :ago) %></div>
</div>
<% end %>
<% end %>
@@ -0,0 +1,9 @@
<%= turbo_stream.remove @notification %>
<% if Current.user.notifications.unread.none? %>
<%= turbo_stream.update "notifications_list" do %>
<div class="pad border-radius border translucent" style="--border-style: dashed; --border-color: var(--color-ink);">
<strong>Nothing new for you.</strong>
</div>
<% end %>
<% end %>
+7
View File
@@ -22,6 +22,13 @@ Rails.application.routes.draw do
namespace :notifications do
resource :tray, only: :show
resource :mark_all_read, only: :create
resources :mark_read, only: :create
end
resources :notifications do
member do
post :mark_read
end
end
resources :buckets do