diff --git a/allianceauth/framework/static/allianceauth/framework/css/auth-framework.css b/allianceauth/framework/static/allianceauth/framework/css/auth-framework.css index a7cf70b6..b866d344 100644 --- a/allianceauth/framework/static/allianceauth/framework/css/auth-framework.css +++ b/allianceauth/framework/static/allianceauth/framework/css/auth-framework.css @@ -47,6 +47,12 @@ /* Side Navigation ------------------------------------------------------------------------------------- */ @media all { + .sidemenu-total-notifications-badge { + position: absolute; + left: 28px; + font-size: 42.5% !important; + } + #sidebar > div { width: 325px; } diff --git a/allianceauth/static/allianceauth/js/sidebar-collapse.js b/allianceauth/static/allianceauth/js/sidebar-collapse.js deleted file mode 100644 index 1dc76f80..00000000 --- a/allianceauth/static/allianceauth/js/sidebar-collapse.js +++ /dev/null @@ -1,13 +0,0 @@ -$(document).ready(() => { - 'use strict'; - - const activeChildMenuItem = document.querySelector('ul#sidebar-menu ul.collapse a.active'); - - if (activeChildMenuItem) { - const activeChildMenuUl = activeChildMenuItem.closest('ul'); - activeChildMenuUl.classList.add('show'); - - document.querySelectorAll(`[data-bs-target^="#${activeChildMenuUl.id}"]`) - .forEach(element => element.setAttribute('aria-expanded', true)); - } -}); diff --git a/allianceauth/static/allianceauth/js/sidebar.js b/allianceauth/static/allianceauth/js/sidebar.js new file mode 100644 index 00000000..6d9303a3 --- /dev/null +++ b/allianceauth/static/allianceauth/js/sidebar.js @@ -0,0 +1,57 @@ +$(document).ready(() => { + 'use strict'; + + /** + * Collect all badges in the sidebar menu that are not part of a collapsible submenu, and calculate the total notification count. + * Show a total notification badge in the navbar if there are any notifications. + */ + const totalNotificationsBadge = () => { + const badges = []; + let notificationCount = 0; + + document.querySelectorAll('#sidebar-menu .badge').forEach(b => { + const li = b.closest('li'); + + if (!li || !li.querySelector('ul.collapse')) { + badges.push(b); + notificationCount += parseInt(b.textContent); + } + }); + + if (badges.length > 0 && notificationCount > 0) { + const notificationBadge = document.createElement('span'); + + notificationBadge.classList.add( + 'badge', + 'text-bg-danger', + 'align-self-center', + 'sidemenu-notification-badge', + 'sidemenu-total-notifications-badge' + ); + notificationBadge.textContent = String(notificationCount); + + document.querySelector('a.navbar-brand i.fa-solid').prepend(notificationBadge); + } + }; + + /** + * Find the active child menu item in the sidebar menu, if any, and ensure its parent submenu is expanded. + */ + const expandChildMenu = () => { + const activeChildMenuItem = document.querySelector('ul#sidebar-menu ul.collapse a.active'); + + if (activeChildMenuItem) { + const activeChildMenuUl = activeChildMenuItem.closest('ul'); + activeChildMenuUl.classList.add('show'); + + document.querySelectorAll(`[data-bs-target^="#${activeChildMenuUl.id}"]`) + .forEach(element => element.setAttribute('aria-expanded', 'true')); + } + }; + + // Execute functions on document ready + [ + totalNotificationsBadge, + expandChildMenu + ].forEach(fn => fn()); +}); diff --git a/allianceauth/templates/bundles/auth-sidebar-collapse-js.html b/allianceauth/templates/bundles/auth-sidebar-collapse-js.html index 0840249a..1a2c7665 100644 --- a/allianceauth/templates/bundles/auth-sidebar-collapse-js.html +++ b/allianceauth/templates/bundles/auth-sidebar-collapse-js.html @@ -1,3 +1,3 @@ {% load sri %} -{% sri_static 'allianceauth/js/sidebar-collapse.js' %} +{% sri_static 'allianceauth/js/sidebar.js' %}