mirror of
https://github.com/Freika/dawarich.git
synced 2026-01-10 01:01:39 -05:00
Add new notification to the list right away
This commit is contained in:
parent
4de6688827
commit
23237b6c7c
7 changed files with 78 additions and 20 deletions
|
|
@ -14,6 +14,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||
- 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 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.
|
||||
|
||||
### Changed
|
||||
|
||||
- Scale on the map now shows the distance both in kilometers and miles.
|
||||
|
||||
# 0.15.13 - 2024-11-01
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -1,7 +1,7 @@
|
|||
import { Controller } from "@hotwired/stimulus";
|
||||
import L from "leaflet";
|
||||
import "leaflet.heat";
|
||||
import consumer from "../channels/consumer"; // Add this import
|
||||
import consumer from "../channels/consumer";
|
||||
|
||||
import { createMarkersArray } from "../maps/markers";
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { Controller } from "@hotwired/stimulus"
|
|||
import consumer from "../channels/consumer"
|
||||
|
||||
export default class extends Controller {
|
||||
static targets = ["badge"]
|
||||
static targets = ["badge", "list"]
|
||||
static values = { userId: Number }
|
||||
|
||||
initialize() {
|
||||
|
|
@ -43,6 +43,7 @@ export default class extends Controller {
|
|||
received: (data) => {
|
||||
// console.log("[WebSocket] Received notification:", data)
|
||||
this.animateBadge()
|
||||
this.prependNotification(data)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
@ -71,4 +72,34 @@ export default class extends Controller {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
prependNotification(notification) {
|
||||
const li = this.createNotificationListItem(notification)
|
||||
const divider = this.listTarget.querySelector(".divider")
|
||||
if (divider) {
|
||||
divider.parentNode.insertBefore(li, divider.nextSibling)
|
||||
} else {
|
||||
this.listTarget.prepend(li)
|
||||
}
|
||||
|
||||
// Update the badge count
|
||||
this.updateBadge()
|
||||
}
|
||||
|
||||
createNotificationListItem(notification) {
|
||||
const li = document.createElement("li")
|
||||
li.innerHTML = `
|
||||
<a href="/notifications/${notification.id}">
|
||||
${notification.title}
|
||||
<div class="badge badge-xs justify-self-end badge-${notification.kind}"></div>
|
||||
</a>
|
||||
`
|
||||
return li
|
||||
}
|
||||
|
||||
updateBadge() {
|
||||
const badgeCount = this.listTarget.children.length
|
||||
this.badgeTarget.textContent = badgeCount
|
||||
this.badgeTarget.classList.toggle("hidden", badgeCount === 0)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ class Notification < ApplicationRecord
|
|||
|
||||
enum :kind, { info: 0, warning: 1, error: 2 }
|
||||
|
||||
scope :unread, -> { where(read_at: nil) }
|
||||
scope :unread, -> { where(read_at: nil).order(created_at: :desc) }
|
||||
|
||||
def read?
|
||||
read_at.present?
|
||||
|
|
@ -19,13 +19,10 @@ class Notification < ApplicationRecord
|
|||
|
||||
def broadcast_notification
|
||||
NotificationsChannel.broadcast_to(
|
||||
user,
|
||||
{
|
||||
# id: id,
|
||||
# title: title,
|
||||
# content: content,
|
||||
# kind: kind,
|
||||
# timestamp: Time.current.to_i
|
||||
user, {
|
||||
title: title,
|
||||
id: id,
|
||||
kind: kind
|
||||
}
|
||||
)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@
|
|||
<div class="navbar-end">
|
||||
<ul class="menu menu-horizontal bg-base-100 rounded-box px-1">
|
||||
<% if user_signed_in? %>
|
||||
<div class="dropdown dropdown-end dropdown-bottom"
|
||||
<div class="dropdown dropdown-end dropdown-bottom dropdown-hover z-[10000]"
|
||||
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'>
|
||||
|
|
@ -70,15 +70,12 @@
|
|||
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>
|
||||
<% 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"></span>
|
||||
<% end %>
|
||||
</div>
|
||||
<ul tabindex="0" class="dropdown-content z-10 menu p-2 shadow-lg bg-base-100 rounded-box min-w-52">
|
||||
<% if @unread_notifications.any? %>
|
||||
<li><%= link_to 'See all', notifications_path %></li>
|
||||
<div class="divider p-0 m-0"></div>
|
||||
<% end %>
|
||||
<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>
|
||||
<div class="divider p-0 m-0"></div>
|
||||
<% @unread_notifications.first(10).each do |notification| %>
|
||||
<li>
|
||||
<%= link_to notification do %>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,35 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe ImportsChannel, type: :channel do
|
||||
pending "add some examples to (or delete) #{__FILE__}"
|
||||
let(:user) { create(:user) }
|
||||
let(:import) { create(:import) }
|
||||
|
||||
before { stub_connection current_user: user }
|
||||
|
||||
describe '#subscribe' do
|
||||
it 'confirms the subscription and subscribes to a stream' do
|
||||
subscribe(import_id: import.id)
|
||||
|
||||
expect(subscription).to be_confirmed
|
||||
expect(subscription).to have_stream_for(import)
|
||||
end
|
||||
|
||||
it 'rejects the subscription without import_id' do
|
||||
subscribe
|
||||
|
||||
expect(subscription).to be_rejected
|
||||
end
|
||||
end
|
||||
|
||||
describe '#broadcast' do
|
||||
it 'broadcasts a message to the stream' do
|
||||
subscribe(import_id: import.id)
|
||||
|
||||
expect do
|
||||
ImportsChannel.broadcast_to(import, message: 'Test message')
|
||||
end.to have_broadcasted_to(import).with(message: 'Test message')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in a new issue