mirror of
https://github.com/Freika/dawarich.git
synced 2026-01-11 01:31:39 -05:00
Use notifications badge
This commit is contained in:
parent
14b7397840
commit
bec9db1198
5 changed files with 61 additions and 33 deletions
File diff suppressed because one or more lines are too long
|
|
@ -2,46 +2,73 @@ import { Controller } from "@hotwired/stimulus"
|
||||||
import consumer from "../channels/consumer"
|
import consumer from "../channels/consumer"
|
||||||
|
|
||||||
export default class extends Controller {
|
export default class extends Controller {
|
||||||
static targets = ["container"]
|
static targets = ["badge"]
|
||||||
static values = { userId: Number }
|
static values = { userId: Number }
|
||||||
|
|
||||||
|
initialize() {
|
||||||
|
this.subscription = null
|
||||||
|
}
|
||||||
|
|
||||||
connect() {
|
connect() {
|
||||||
console.log("Controller connecting...")
|
console.log("[Stimulus] Notifications controller connecting...")
|
||||||
// Ensure we clean up any existing subscription
|
|
||||||
|
// Clean up any existing subscription
|
||||||
if (this.subscription) {
|
if (this.subscription) {
|
||||||
console.log("Cleaning up existing subscription")
|
console.log("[Stimulus] Cleaning up existing subscription")
|
||||||
this.subscription.unsubscribe()
|
this.subscription.unsubscribe()
|
||||||
|
this.subscription = null
|
||||||
}
|
}
|
||||||
|
|
||||||
this.subscription = consumer.subscriptions.create("NotificationsChannel", {
|
// Create new subscription
|
||||||
connected: () => {
|
this.createSubscription()
|
||||||
console.log("Connected to NotificationsChannel", this.subscription)
|
|
||||||
},
|
|
||||||
disconnected: () => {
|
|
||||||
console.log("Disconnected from NotificationsChannel")
|
|
||||||
},
|
|
||||||
received: (data) => {
|
|
||||||
console.log("Received notification:", data, "Subscription:", this.subscription)
|
|
||||||
this.displayNotification(data)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
disconnect() {
|
disconnect() {
|
||||||
console.log("Controller disconnecting...")
|
console.log("[Stimulus] Notifications controller disconnecting...")
|
||||||
if (this.subscription) {
|
if (this.subscription) {
|
||||||
this.subscription.unsubscribe()
|
this.subscription.unsubscribe()
|
||||||
this.subscription = null
|
this.subscription = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
displayNotification(data) {
|
createSubscription() {
|
||||||
console.log("Notification received:", data) // For debugging
|
console.log("[Stimulus] Creating new notification subscription")
|
||||||
const notification = document.createElement("div")
|
this.subscription = consumer.subscriptions.create("NotificationsChannel", {
|
||||||
notification.classList.add("notification", `notification-${data.kind}`)
|
connected: () => {
|
||||||
notification.innerHTML = `<strong>${data.title}</strong>: ${data.content}`
|
console.log("[WebSocket] Connected to NotificationsChannel")
|
||||||
|
},
|
||||||
|
disconnected: () => {
|
||||||
|
console.log("[WebSocket] Disconnected from NotificationsChannel")
|
||||||
|
},
|
||||||
|
received: (data) => {
|
||||||
|
console.log("[WebSocket] Received notification:", data)
|
||||||
|
this.animateBadge()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
this.containerTarget.appendChild(notification)
|
animateBadge() {
|
||||||
setTimeout(() => notification.remove(), 5000) // Auto-hide after 5 seconds
|
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)
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,13 +18,14 @@ class Notification < ApplicationRecord
|
||||||
private
|
private
|
||||||
|
|
||||||
def broadcast_notification
|
def broadcast_notification
|
||||||
Rails.logger.debug "Broadcasting notification to #{user.id}"
|
|
||||||
NotificationsChannel.broadcast_to(
|
NotificationsChannel.broadcast_to(
|
||||||
user,
|
user,
|
||||||
{
|
{
|
||||||
|
id: id,
|
||||||
title: title,
|
title: title,
|
||||||
content: content,
|
content: content,
|
||||||
kind: kind
|
kind: kind,
|
||||||
|
timestamp: Time.current.to_i
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -21,9 +21,6 @@
|
||||||
<div class='container mx-auto'>
|
<div class='container mx-auto'>
|
||||||
<%= render 'shared/navbar' %>
|
<%= render 'shared/navbar' %>
|
||||||
<%= render 'shared/flash' %>
|
<%= render 'shared/flash' %>
|
||||||
<div data-controller="notifications" data-notifications-user-id-value="<%= current_user.id %>">
|
|
||||||
<div data-notifications-target="container" class="notifications-container"></div>
|
|
||||||
</div>
|
|
||||||
<div class="flex flex-row gap-5 w-full px-5">
|
<div class="flex flex-row gap-5 w-full px-5">
|
||||||
<%= yield %>
|
<%= yield %>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,9 @@
|
||||||
<div class="navbar-end">
|
<div class="navbar-end">
|
||||||
<ul class="menu menu-horizontal bg-base-100 rounded-box px-1">
|
<ul class="menu menu-horizontal bg-base-100 rounded-box px-1">
|
||||||
<% if user_signed_in? %>
|
<% if user_signed_in? %>
|
||||||
<div class="dropdown dropdown-end dropdown-bottom">
|
<div class="dropdown dropdown-end dropdown-bottom"
|
||||||
|
data-controller="notifications"
|
||||||
|
data-notifications-user-id-value="<%= current_user.id %>">
|
||||||
<div tabindex="0" role="button" class='btn btn-sm btn-ghost hover:btn-ghost'>
|
<div tabindex="0" role="button" class='btn btn-sm btn-ghost hover:btn-ghost'>
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
|
@ -68,7 +70,8 @@
|
||||||
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"></span>
|
<span class="badge badge-xs badge-primary absolute top-0 right-0"
|
||||||
|
data-notifications-target="badge"></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">
|
<ul tabindex="0" class="dropdown-content z-10 menu p-2 shadow-lg bg-base-100 rounded-box min-w-52">
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue