Fix adding new notifications to the list and updating the badge count

This commit is contained in:
Eugene Burmakin 2024-11-07 19:07:59 +01:00
parent 23237b6c7c
commit ea9ce874be
3 changed files with 12 additions and 37 deletions

View file

@ -11,7 +11,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
### Added ### Added
- New notifications are now being indicated with a blue-ish dot in the top right corner of the screen. Clicking on the bell icon will show you all your notifications. - New notifications are now being indicated with a blue-ish dot in the top right corner of the screen. Hovering over the bell icon will show you last 10 notifications.
- New points on the map will now be shown in real-time. No need to reload the map to see new points. - New points on the map will now be shown in real-time. No need to reload the map to see new points.
- User can now enable or disable Live Mode in the map controls. When Live Mode is enabled, the map will automatically scroll to the new points as they are being added to the map. - User can now enable or disable Live Mode in the map controls. When Live Mode is enabled, the map will automatically scroll to the new points as they are being added to the map.

View file

@ -10,21 +10,16 @@ export default class extends Controller {
} }
connect() { connect() {
// console.log("[Stimulus] Notifications controller connecting...")
// Clean up any existing subscription // Clean up any existing subscription
if (this.subscription) { if (this.subscription) {
// console.log("[Stimulus] Cleaning up existing subscription")
this.subscription.unsubscribe() this.subscription.unsubscribe()
this.subscription = null this.subscription = null
} }
// Create new subscription
this.createSubscription() this.createSubscription()
} }
disconnect() { disconnect() {
// console.log("[Stimulus] Notifications controller disconnecting...")
if (this.subscription) { if (this.subscription) {
this.subscription.unsubscribe() this.subscription.unsubscribe()
this.subscription = null this.subscription = null
@ -32,7 +27,6 @@ export default class extends Controller {
} }
createSubscription() { createSubscription() {
// console.log("[Stimulus] Creating new notification subscription")
this.subscription = consumer.subscriptions.create("NotificationsChannel", { this.subscription = consumer.subscriptions.create("NotificationsChannel", {
connected: () => { connected: () => {
// console.log("[WebSocket] Connected to NotificationsChannel") // console.log("[WebSocket] Connected to NotificationsChannel")
@ -42,38 +36,17 @@ export default class extends Controller {
}, },
received: (data) => { received: (data) => {
// console.log("[WebSocket] Received notification:", data) // console.log("[WebSocket] Received notification:", data)
this.animateBadge()
this.prependNotification(data) this.prependNotification(data)
} }
}) })
} }
animateBadge() {
let badge = this.hasBadgeTarget ? this.badgeTarget : null
if (!badge) {
badge = document.createElement("span")
badge.className = "badge badge-xs badge-primary absolute top-0 right-0"
badge.setAttribute("data-notifications-target", "badge")
this.element.querySelector('.btn').appendChild(badge)
}
// Create ping effect div if it doesn't exist
let pingEffect = badge.querySelector('.ping-effect')
if (!pingEffect) {
pingEffect = document.createElement("span")
pingEffect.className = "ping-effect absolute inline-flex h-full w-full rounded-full animate-ping bg-primary opacity-75"
badge.appendChild(pingEffect)
} else {
// Reset animation
pingEffect.remove()
requestAnimationFrame(() => {
badge.appendChild(pingEffect)
})
}
}
prependNotification(notification) { prependNotification(notification) {
const existingNotification = this.listTarget.querySelector(`a[href="/notifications/${notification.id}"]`)
if (existingNotification) {
return
}
const li = this.createNotificationListItem(notification) const li = this.createNotificationListItem(notification)
const divider = this.listTarget.querySelector(".divider") const divider = this.listTarget.querySelector(".divider")
if (divider) { if (divider) {
@ -82,12 +55,12 @@ export default class extends Controller {
this.listTarget.prepend(li) this.listTarget.prepend(li)
} }
// Update the badge count
this.updateBadge() this.updateBadge()
} }
createNotificationListItem(notification) { createNotificationListItem(notification) {
const li = document.createElement("li") const li = document.createElement("li")
li.className = "notification-item"
li.innerHTML = ` li.innerHTML = `
<a href="/notifications/${notification.id}"> <a href="/notifications/${notification.id}">
${notification.title} ${notification.title}
@ -98,7 +71,7 @@ export default class extends Controller {
} }
updateBadge() { updateBadge() {
const badgeCount = this.listTarget.children.length const badgeCount = this.listTarget.querySelectorAll(".notification-item").length
this.badgeTarget.textContent = badgeCount this.badgeTarget.textContent = badgeCount
this.badgeTarget.classList.toggle("hidden", badgeCount === 0) this.badgeTarget.classList.toggle("hidden", badgeCount === 0)
} }

View file

@ -70,14 +70,16 @@
d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9" /> d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9" />
</svg> </svg>
<% if @unread_notifications.present? %> <% if @unread_notifications.present? %>
<span class="badge badge-xs badge-primary absolute top-0 right-0" data-notifications-target="badge"></span> <span class="badge badge-xs badge-primary absolute top-0 right-0" data-notifications-target="badge">
<%= @unread_notifications.size %>
</span>
<% end %> <% end %>
</div> </div>
<ul tabindex="0" class="dropdown-content z-10 menu p-2 shadow-lg bg-base-100 rounded-box min-w-52" data-notifications-target="list"> <ul tabindex="0" class="dropdown-content z-10 menu p-2 shadow-lg bg-base-100 rounded-box min-w-52" data-notifications-target="list">
<li><%= link_to 'See all', notifications_path %></li> <li><%= link_to 'See all', notifications_path %></li>
<div class="divider p-0 m-0"></div> <div class="divider p-0 m-0"></div>
<% @unread_notifications.first(10).each do |notification| %> <% @unread_notifications.first(10).each do |notification| %>
<li> <li class='notification-item'>
<%= link_to notification do %> <%= link_to notification do %>
<%= notification.title %> <%= notification.title %>
<div class="badge badge-xs justify-self-end badge-<%= notification.kind %>"></div> <div class="badge badge-xs justify-self-end badge-<%= notification.kind %>"></div>