mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-05-20 10:34:30 +00:00
ui: Dismiss notifications without page reload
- Delete only the <li> of the notification using HTMX. - Notifications list stays open. User can dismiss another notification. - Decrement notification counter using JavaScript after removing notification from the list. - Added HTMX to every kind of notification. - Tested dismissing notifications from the top, middle and bottom of the list. Signed-off-by: Joseph Nuthalapati <njoseph@riseup.net> [sunil: Update comment format in .js file] Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org> Reviewed-by: Sunil Mohan Adapa <sunil@medhas.org>
This commit is contained in:
parent
4e668c8a98
commit
13a575017c
@ -42,6 +42,9 @@
|
|||||||
{% trans "Go to Distribution Update" %}
|
{% trans "Go to Distribution Update" %}
|
||||||
</a>
|
</a>
|
||||||
<a href="{% url 'notification_dismiss' id=id %}?next={{ request.path|iriencode }}"
|
<a href="{% url 'notification_dismiss' id=id %}?next={{ request.path|iriencode }}"
|
||||||
|
hx-get="{% url 'notification_dismiss' id=id %}"
|
||||||
|
hx-target="#notification-{{ id }}"
|
||||||
|
hx-swap="delete swap:300ms"
|
||||||
role="button" class="btn btn-default">
|
role="button" class="btn btn-default">
|
||||||
{% trans "Dismiss" %}
|
{% trans "Dismiss" %}
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@ -18,6 +18,9 @@
|
|||||||
|
|
||||||
<p>
|
<p>
|
||||||
<a href="{% url 'notification_dismiss' id=id %}?next={{ request.path|iriencode }}"
|
<a href="{% url 'notification_dismiss' id=id %}?next={{ request.path|iriencode }}"
|
||||||
|
hx-get="{% url 'notification_dismiss' id=id %}"
|
||||||
|
hx-target="#notification-{{ id }}"
|
||||||
|
hx-swap="delete swap:300ms"
|
||||||
role="button" class="btn btn-default">
|
role="button" class="btn btn-default">
|
||||||
{% trans "Dismiss" %}
|
{% trans "Dismiss" %}
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@ -11,7 +11,8 @@
|
|||||||
<div id="notifications" class="notifications collapse no-no-js" hx-swap-oob="true">
|
<div id="notifications" class="notifications collapse no-no-js" hx-swap-oob="true">
|
||||||
<ul>
|
<ul>
|
||||||
{% for note in notifications %}
|
{% for note in notifications %}
|
||||||
<li class="notification notification-{{ note.severity }}">
|
<li id="notification-{{ note.id }}"
|
||||||
|
class="notification notification-{{ note.severity }}">
|
||||||
<div class="notification-header">
|
<div class="notification-header">
|
||||||
<span class="notification-time"
|
<span class="notification-time"
|
||||||
title="{{ note.last_update_time|date:'DATETIME_FORMAT' }}">
|
title="{{ note.last_update_time|date:'DATETIME_FORMAT' }}">
|
||||||
@ -54,6 +55,9 @@
|
|||||||
{% for action in note.actions %}
|
{% for action in note.actions %}
|
||||||
{% if action.type == "dismiss" %}
|
{% if action.type == "dismiss" %}
|
||||||
<a href="{% url 'notification_dismiss' id=note.id %}?next={{ request.path|iriencode }}"
|
<a href="{% url 'notification_dismiss' id=note.id %}?next={{ request.path|iriencode }}"
|
||||||
|
hx-get="{% url 'notification_dismiss' id=note.id %}"
|
||||||
|
hx-target="#notification-{{ note.id }}"
|
||||||
|
hx-swap="delete swap:300ms"
|
||||||
role="button" class="btn btn-default">
|
role="button" class="btn btn-default">
|
||||||
{% trans "Dismiss" %}
|
{% trans "Dismiss" %}
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@ -19,6 +19,9 @@
|
|||||||
{% if data.state == "completed" %}
|
{% if data.state == "completed" %}
|
||||||
<div class="btn-toolbar">
|
<div class="btn-toolbar">
|
||||||
<a href="{% url 'notification_dismiss' id=id %}?next={{ request.path|iriencode }}"
|
<a href="{% url 'notification_dismiss' id=id %}?next={{ request.path|iriencode }}"
|
||||||
|
hx-get="{% url 'notification_dismiss' id=id %}"
|
||||||
|
hx-target="#notification-{{ id }}"
|
||||||
|
hx-swap="delete swap:300ms"
|
||||||
role="button" class="btn btn-default">
|
role="button" class="btn btn-default">
|
||||||
{% trans "Dismiss" %}
|
{% trans "Dismiss" %}
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@ -682,10 +682,18 @@ class AppLogsView(TemplateView):
|
|||||||
|
|
||||||
def notification_dismiss(request, id):
|
def notification_dismiss(request, id):
|
||||||
"""Dismiss a notification."""
|
"""Dismiss a notification."""
|
||||||
|
from django.http import HttpResponse
|
||||||
from .notification import Notification
|
from .notification import Notification
|
||||||
notes = Notification.list(key=id, user=request.user)
|
notes = Notification.list(key=id, user=request.user)
|
||||||
if notes:
|
if notes:
|
||||||
# If a notification is not found, no need to dismiss it.
|
# If a notification is not found, no need to dismiss it.
|
||||||
notes[0].dismiss()
|
notes[0].dismiss()
|
||||||
|
|
||||||
|
# Don't redirect if the request is from HTMX.
|
||||||
|
if request.headers.get('HX-Request'):
|
||||||
|
response = HttpResponse(status=200)
|
||||||
|
# Trigger the notification-dismissed event to update the UI.
|
||||||
|
response['HX-Trigger'] = 'notification-dismissed'
|
||||||
|
return response
|
||||||
|
|
||||||
return HttpResponseRedirect(_get_redirect_url_from_param(request))
|
return HttpResponseRedirect(_get_redirect_url_from_param(request))
|
||||||
|
|||||||
@ -298,3 +298,24 @@ document.addEventListener('htmx:afterSwap', function (event) {
|
|||||||
window.location.reload();
|
window.location.reload();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Decrement notification counter badge when a notification is dismissed via
|
||||||
|
* HTMX.
|
||||||
|
*/
|
||||||
|
document.addEventListener('notification-dismissed', function (evt) {
|
||||||
|
// There are 2 badges on the page. One for mobile navbar and one for desktop
|
||||||
|
// navbar.
|
||||||
|
const badges = document.querySelectorAll('.notifications-dropdown .badge');
|
||||||
|
|
||||||
|
badges.forEach(badge => {
|
||||||
|
const count = parseInt(badge.textContent.trim());
|
||||||
|
|
||||||
|
if (count > 1) {
|
||||||
|
badge.textContent = count - 1;
|
||||||
|
} else {
|
||||||
|
const dropdowns = document.querySelectorAll('.notifications-dropdown');
|
||||||
|
dropdowns.forEach(dropdown => dropdown.remove());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user