Group notifications for the same card as they show up
This commit is contained in:
@@ -40,6 +40,13 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* Grouped notifications
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
.notification--grouped {
|
||||
border: 3px solid red;
|
||||
}
|
||||
|
||||
/* Read items
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
|
||||
@@ -20,7 +20,10 @@ module NotificationsHelper
|
||||
end
|
||||
|
||||
def notification_tag(notification, &)
|
||||
tag.div id: dom_id(notification), class: "tray__item tray__item--notification", data: { navigable_list_target: "item" } do
|
||||
tag.div id: dom_id(notification), class: "tray__item tray__item--notification", data: {
|
||||
navigable_list_target: "item",
|
||||
notifications_tray_target: "notification",
|
||||
card_id: notification.card.id, timestamp: notification.created_at.to_i } do
|
||||
concat(
|
||||
link_to(notification,
|
||||
class: [ "card card--notification", { "card--closed": notification.card.closed? }, { "unread": !notification.read? } ],
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
import { Controller } from "@hotwired/stimulus"
|
||||
|
||||
export default class extends Controller {
|
||||
static targets = [ "notification", "hiddenNotifications" ]
|
||||
static classes = [ "grouped" ]
|
||||
|
||||
notificationTargetConnected(notification) {
|
||||
this.#groupNotificationIfNeeded(notification)
|
||||
}
|
||||
|
||||
#groupNotificationIfNeeded(notification) {
|
||||
const groupedNotifications = this.#groupedNotificationsFor(notification)
|
||||
|
||||
if (groupedNotifications.length > 1) {
|
||||
this.#renderGroup(groupedNotifications)
|
||||
}
|
||||
}
|
||||
|
||||
#groupedNotificationsFor(notification) {
|
||||
const cardId = notification.dataset.cardId
|
||||
return this.notificationTargets
|
||||
.filter(notification => notification.dataset.cardId === cardId)
|
||||
.sort((notification_1, notification_2) => parseInt(notification_1.dataset.timestamp) - parseInt(notification_2.dataset.timestamp))
|
||||
}
|
||||
|
||||
#renderGroup(groupedNotifications) {
|
||||
this.#showAsGrouped(groupedNotifications[0], groupedNotifications.length)
|
||||
groupedNotifications.slice(1).forEach(notification => this.#hideInGroup(notification))
|
||||
}
|
||||
|
||||
#showAsGrouped(notification, size) {
|
||||
notification.classList.add(this.groupedClass)
|
||||
this.#showGroupedNotification(notification)
|
||||
this.#setGroupCount(notification, size)
|
||||
}
|
||||
|
||||
#hideInGroup(notification) {
|
||||
this.#hideGroupedNotification(notification)
|
||||
this.#setGroupCount(notification, "")
|
||||
}
|
||||
|
||||
// We use a hidden container instead of hiding the notifications directly so that the CSS that sort the
|
||||
// tray element indexes doesn't get messed up.
|
||||
#showGroupedNotification(notification) {
|
||||
if (notification.parentElement === this.hiddenNotificationsTarget) {
|
||||
this.hiddenNotificationsTarget.parentElement.insertBefore(notification, this.hiddenNotificationsTarget)
|
||||
}
|
||||
}
|
||||
|
||||
#hideGroupedNotification(notification) {
|
||||
this.hiddenNotificationsTarget.appendChild(notification)
|
||||
}
|
||||
|
||||
#setGroupCount(notification, count) {
|
||||
notification.querySelector("[data-group-count]").textContent = count
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
<header class="card__header">
|
||||
<%= render "notifications/notification/#{notification.source_type.underscore}/header", notification: notification %>
|
||||
<span data-group-count></span>
|
||||
</header>
|
||||
|
||||
<div class="card__body">
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
data-navigable-list-actionable-items-value="true"
|
||||
data-navigable-list-reverse-navigation-value="true"
|
||||
data-action="keydown->navigable-list#navigate dialog:show@document->navigable-list#reset turbo-visit->navigable-list#reset keydown.esc->dialog#close:stop click@document->dialog#closeOnClickOutside">
|
||||
<%= turbo_frame_tag "notifications", src: tray_notifications_path, refresh: "morph" %>
|
||||
<%= turbo_frame_tag "notifications", src: tray_notifications_path, refresh: "morph", data: { controller: "notifications-tray", notifications_tray_grouped_class: "notification--grouped" } %>
|
||||
|
||||
<div class="tray__item tray__item--hat txt-x-small gap-half">
|
||||
<div data-navigable-list-target="item" class="full-width">
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
<%= turbo_frame_tag "notifications" do %>
|
||||
<%= turbo_frame_tag "notifications", data: { controller: "notifications-tray", notifications_tray_grouped_class: "notification--grouped" } do %>
|
||||
<%= render partial: "notifications/notification", collection: @notifications, cached: true %>
|
||||
<div hidden data-notifications-tray-target="hiddenNotifications"></div>
|
||||
<% end %>
|
||||
|
||||
Reference in New Issue
Block a user