Add menu highlighting logic via HX-Trigger, update templates for dynamic menu state management, and extend mixins to support menu highlighting.

This commit is contained in:
2026-01-16 23:57:06 +01:00
parent 5898a3ac6d
commit 17e91cd7f8
4 changed files with 28 additions and 2 deletions

View File

@@ -19,6 +19,7 @@ class MemberListView(HTMXViewMixin, PermissionRequiredMixin, FilterView):
permission_denied_message = _("You do not have permission to view this page.") permission_denied_message = _("You do not have permission to view this page.")
permission_required = "members.view_member" permission_required = "members.view_member"
partial_name = "members/member_filter.html#content" partial_name = "members/member_filter.html#content"
menu_highlight = "members"
def handle_no_permission(self) -> HttpResponseRedirect: def handle_no_permission(self) -> HttpResponseRedirect:
messages.error(self.request, self.get_permission_denied_message()) messages.error(self.request, self.get_permission_denied_message())
@@ -48,6 +49,7 @@ class MemberDeleteView(HTMXViewMixin, PermissionRequiredMixin, SuccessMessageMix
permission_required = "members.delete_member" permission_required = "members.delete_member"
permission_denied_message = _("You do not have permission to view this page.") permission_denied_message = _("You do not have permission to view this page.")
success_url = reverse_lazy("backend:members:list") success_url = reverse_lazy("backend:members:list")
menu_highlight = "members"
def handle_no_permission(self) -> HttpResponseRedirect: def handle_no_permission(self) -> HttpResponseRedirect:
messages.error(self.request, self.get_permission_denied_message()) messages.error(self.request, self.get_permission_denied_message())

View File

@@ -1,3 +1,5 @@
import json
from django.http import HttpResponse from django.http import HttpResponse
from django.template.loader import render_to_string from django.template.loader import render_to_string
from django_htmx.http import HttpResponseClientRedirect, HttpResponseClientRefresh from django_htmx.http import HttpResponseClientRedirect, HttpResponseClientRefresh
@@ -33,6 +35,9 @@ class HTMXViewMixin:
# Optional: automatically push URL on GET # Optional: automatically push URL on GET
htmx_push_url = None htmx_push_url = None
# Optional: name of the menu item to highlight
menu_highlight = None
# Optional: trigger events after rendering # Optional: trigger events after rendering
htmx_trigger = None htmx_trigger = None
htmx_trigger_after_settle = None htmx_trigger_after_settle = None
@@ -62,9 +67,21 @@ class HTMXViewMixin:
response.headers["HX-Push-Url"] = self.htmx_push_url or request.get_full_path() response.headers["HX-Push-Url"] = self.htmx_push_url or request.get_full_path()
print(response.headers) print(response.headers)
# Build HX-Trigger payload
trigger_payload = {}
# 1. User-defined triggers
if self.htmx_trigger: if self.htmx_trigger:
response.headers["HX-Trigger"] = self.htmx_trigger trigger_payload.update(json.loads(self.htmx_trigger))
# 2. Auto menu highlight trigger
if self.menu_highlight:
trigger_payload["menuHighlight"] = self.menu_highlight
# Emit HX-Trigger if anything is present
if trigger_payload:
response.headers["HX-Trigger"] = json.dumps(trigger_payload)
if self.htmx_trigger_after_settle: if self.htmx_trigger_after_settle:
response.headers["HX-Trigger-After-Settle"] = self.htmx_trigger_after_settle response.headers["HX-Trigger-After-Settle"] = self.htmx_trigger_after_settle

View File

@@ -9,7 +9,7 @@
{% if is_member_manager %} {% if is_member_manager %}
<li class="menu-title">Members</li> <li class="menu-title">Members</li>
<li><a href="{{ members_list }}" {% if members_list in request.path %}class="menu-active"{% endif %}><i class="fa-solid fa-users"></i> Members</a></li> <li><a href="{{ members_list }}" class="menu-item {% if members_list in request.path %}menu-active{% endif %}" data-menu="members" hx-get="{% url "backend:members:list" %}" hx-target="#content"><i class="fa-solid fa-users"></i> Members</a></li>
{% endif %} {% endif %}
<li class="menu-title mt-4">Navigation</li> <li class="menu-title mt-4">Navigation</li>

View File

@@ -116,6 +116,13 @@
</footer> </footer>
<script> <script>
document.body.addEventListener("menuHighlight", (event) => {
const active = event.detail.value;
document.querySelectorAll(".menu-item").forEach(el => {
el.classList.toggle("menu-active", el.dataset.menu === active);
});
});
{% comment %}// Shrinking navbar on scroll {% comment %}// Shrinking navbar on scroll
const navbar = document.getElementById("mainNavbar"); const navbar = document.getElementById("mainNavbar");
let lastScroll = 0; window.addEventListener("scroll", () => { let lastScroll = 0; window.addEventListener("scroll", () => {