fix: close collapsed navigation flyouts
This commit is contained in:
@@ -32,7 +32,7 @@ Release-Tag oder ein bestimmter Commit verwendet werden:
|
||||
|
||||
```bash
|
||||
/opt/netbox/venv/bin/pip install --upgrade --force-reinstall \
|
||||
"git+https://git.mrblake.cc/MrBlake/Netbox-Utilities.git@v0.5.1"
|
||||
"git+https://git.mrblake.cc/MrBlake/Netbox-Utilities.git@v0.5.2"
|
||||
```
|
||||
|
||||
Alternativ kann hinter dem `@` die vollständige Commit-ID stehen.
|
||||
@@ -209,6 +209,8 @@ ein und wieder aus. Dafür gibt es kein zusätzliches Bedienmenü. Beim Ziehen
|
||||
wird die neue Breite nach dem Loslassen im Benutzerprofil gespeichert. Im
|
||||
Icon-Modus öffnen sich die Menüinhalte als seitliches Flyout; auf kleinen
|
||||
beziehungsweise mobilen Ansichten bleibt das normale NetBox-Menü erhalten.
|
||||
Das Flyout schließt sich bei Auswahl eines Eintrags, bei erneutem Klick auf
|
||||
das aktive Icon, bei einem Klick außerhalb und mit der Escape-Taste.
|
||||
|
||||
**Zurücksetzen** stellt neben Reihenfolge und Sichtbarkeit auch die normale
|
||||
ausgeklappte Breite von 288 Pixeln wieder her.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from netbox.plugins import PluginConfig, get_plugin_config
|
||||
|
||||
__version__ = "0.5.1"
|
||||
__version__ = "0.5.2"
|
||||
|
||||
|
||||
class NetBoxUtilitiesConfig(PluginConfig):
|
||||
|
||||
@@ -71,20 +71,40 @@
|
||||
});
|
||||
}
|
||||
|
||||
function closeDropdown(item) {
|
||||
if (!item) return false;
|
||||
const button = item.querySelector(':scope > button.nav-link');
|
||||
const menu = item.querySelector(':scope > .dropdown-menu');
|
||||
if (!button || !menu?.classList.contains('show')) return false;
|
||||
|
||||
// Let NetBox/Bootstrap tear down its Popper instance when available.
|
||||
button.click();
|
||||
if (!menu.classList.contains('show')) {
|
||||
menu.style.removeProperty('--netbox-utilities-dropdown-top');
|
||||
return true;
|
||||
}
|
||||
|
||||
// Fallback for pages on which Bootstrap's data API is unavailable.
|
||||
button.classList.remove('show');
|
||||
button.setAttribute('aria-expanded', 'false');
|
||||
menu.classList.remove('show');
|
||||
menu.style.removeProperty('--netbox-utilities-dropdown-top');
|
||||
return true;
|
||||
}
|
||||
|
||||
function closeDropdowns(sidebar, exceptItem = null) {
|
||||
sidebar.querySelectorAll(':scope > li.nav-item.dropdown').forEach((item) => {
|
||||
if (item !== exceptItem) closeDropdown(item);
|
||||
});
|
||||
}
|
||||
|
||||
function configureCollapsedDropdowns(sidebar) {
|
||||
sidebar.addEventListener('show.bs.dropdown', (event) => {
|
||||
if (!preferences.collapsed) return;
|
||||
const item = event.target.closest('.nav-item.dropdown');
|
||||
if (!item) return;
|
||||
|
||||
sidebar.querySelectorAll(':scope > li.nav-item.dropdown').forEach((otherItem) => {
|
||||
if (otherItem === item) return;
|
||||
const otherButton = otherItem.querySelector(':scope > button.nav-link');
|
||||
const otherMenu = otherItem.querySelector(':scope > .dropdown-menu');
|
||||
otherButton?.classList.remove('show');
|
||||
otherButton?.setAttribute('aria-expanded', 'false');
|
||||
otherMenu?.classList.remove('show');
|
||||
});
|
||||
closeDropdowns(sidebar, item);
|
||||
|
||||
const button = item.querySelector(':scope > button.nav-link');
|
||||
const menu = item.querySelector(':scope > .dropdown-menu');
|
||||
@@ -92,6 +112,32 @@
|
||||
const top = Math.max(8, button.getBoundingClientRect().top);
|
||||
menu.style.setProperty('--netbox-utilities-dropdown-top', `${top}px`);
|
||||
});
|
||||
|
||||
sidebar.addEventListener('click', (event) => {
|
||||
if (!preferences.collapsed || !(event.target instanceof Element)) return;
|
||||
const selectedOption = event.target.closest('.dropdown-menu a[href], .dropdown-menu button');
|
||||
if (selectedOption) closeDropdown(selectedOption.closest('.nav-item.dropdown'));
|
||||
});
|
||||
|
||||
document.addEventListener(
|
||||
'click',
|
||||
(event) => {
|
||||
if (!preferences.collapsed || !(event.target instanceof Element)) return;
|
||||
sidebar.querySelectorAll(':scope > li.nav-item.dropdown').forEach((item) => {
|
||||
if (!item.contains(event.target)) closeDropdown(item);
|
||||
});
|
||||
},
|
||||
true
|
||||
);
|
||||
|
||||
document.addEventListener('keydown', (event) => {
|
||||
if (!preferences.collapsed || event.key !== 'Escape') return;
|
||||
const openItem = sidebar.querySelector(':scope > li.nav-item.dropdown > .dropdown-menu.show')?.closest('.nav-item');
|
||||
if (openItem && closeDropdown(openItem)) {
|
||||
openItem.querySelector(':scope > button.nav-link')?.focus();
|
||||
event.preventDefault();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async function saveLayout(action, width) {
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
||||
|
||||
[project]
|
||||
name = "netbox-utilities"
|
||||
version = "0.5.1"
|
||||
version = "0.5.2"
|
||||
description = "Navigation, tenant filtering, bulk module installation, and atomic rack reordering for NetBox 4.6"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.12"
|
||||
|
||||
Reference in New Issue
Block a user