position: relative;
margin: 20px;
width: calc(100% - 40px);
- max-height: calc(100vh - 185px);
+ max-height: calc(100vh - 174px);
overflow-x: auto;
overflow-y: auto;
border-radius: 10px;
<span>Network Manager</span>
</a>
- <!-- Spacer -->
- <div class="col d-none d-md-block"></div>
-
- <nav class="navbar navbar-expand-md px-3">
- <!-- Bottone hamburger -->
- <button class="navbar-toggler bg-light" type="button" data-bs-toggle="collapse" data-bs-target="#menuNav">
- <span class="navbar-toggler-icon"></span>
+ <nav class="navbar">
+ <!-- Hamburger -->
+ <button
+ class="btn btn-primary d-md-none"
+ type="button"
+ data-bs-toggle="offcanvas"
+ data-bs-target="#mobileMenu">
+ <i class="bi bi-list fs-4"></i>
</button>
- <!-- Menu -->
- <div class="collapse navbar-collapse" id="menuNav">
- <div class="navbar-nav ms-auto gap-2">
- <a href="/hosts" id="hostsBtn" class="btn btn-primary" aria-current="page">Hostname</a>
- <a href="/aliases" id="aliasesBtn" class="btn btn-primary" aria-current="page">Alias</a>
- <a href="/leases" id="leasesBtn" class="btn btn-primary" aria-current="page">DHCP Leases</a>
- <a href="/devices" id="devicesBtn" class="btn btn-primary active" aria-current="page">Devices</a>
- <a href="/settings" id="settingsBtn" class="btn btn-primary" aria-current="page">Settings</a>
- <button id="logoutBtn" class="btn btn-primary">Logout</button>
- </div>
+
+ <!-- Desktop nav -->
+ <div class="d-none d-md-flex gap-2 ms-auto">
+ <a href="/hosts" class="btn btn-primary"> Hosts</a>
+ <a href="/aliases" class="btn btn-primary"> Alias</a>
+ <a href="/leases" class="btn btn-primary"> DHCP Leases</a>
+ <a href="/devices" class="btn btn-primary active">Devices</a>
+ <a href="/settings" class="btn btn-primary"> Settings</a>
+ <button class="btn btn-primary btn-logout">Logout</button>
</div>
</nav>
+
+ <!-- Mobile offcanvas -->
+ <div class="offcanvas offcanvas-end d-md-none" tabindex="-1" id="mobileMenu">
+
+ <div class="offcanvas-header">
+ <h5 class="offcanvas-title">Network Manager</h5>
+
+ <button
+ type="button"
+ class="btn-close"
+ data-bs-dismiss="offcanvas">
+ </button>
+ </div>
+
+ <div class="offcanvas-body">
+ <div class="d-grid gap-2">
+ <a href="/hosts" class="btn btn-primary"> Hosts</a>
+ <a href="/aliases" class="btn btn-primary"> Alias</a>
+ <a href="/leases" class="btn btn-primary"> DHCP Leases</a>
+ <a href="/devices" class="btn btn-primary active">Devices</a>
+ <a href="/settings" class="btn btn-primary"> Settings</a>
+ <button class="btn btn-primary btn-logout">Logout</button>
+ </div>
+ </div>
+ </div>
</div>
</header>
</div>
<!-- Separator -->
- <div class="vr mx-2"></div>
+ <div class="vr mx-2 d-none d-md-block"></div>
<!-- Add host -->
<button
aria-label="Add Host"
data-bs-toggle="modal" data-bs-target="#addHostModal">
<i class="bi bi-plus-lg"></i>
- <span class="label"> Add Host</span>
+ <span class="label d-none d-md-block"> Add Host</span>
</button>
<!-- Separator -->
- <div class="vr mx-2"></div>
+ <div class="vr mx-2 d-none d-md-block"></div>
<!-- Reload DNS -->
<button
aria-label="Reload DNS"
data-action="reloadDns">
<i class="bi bi-arrow-repeat"></i>
- <span class="label"> Reload DNS</span>
+ <span class="label d-none d-md-block"> Reload DNS</span>
</button>
<!-- Reload DNS -->
aria-label="Reload DHCP"
data-action="reloadDhcp">
<i class="bi bi-arrow-repeat"></i>
- <span class="label"> Reload DHCP</span>
+ <span class="label d-none d-md-block"> Reload DHCP</span>
</button>
</div>
</div>
<span>Network Manager</span>
</a>
- <!-- Spacer -->
- <div class="col d-none d-md-block"></div>
-
- <nav class="navbar navbar-expand-md px-3">
- <!-- Bottone hamburger -->
- <button class="navbar-toggler bg-light" type="button" data-bs-toggle="collapse" data-bs-target="#menuNav">
- <span class="navbar-toggler-icon"></span>
+ <nav class="navbar">
+ <!-- Hamburger -->
+ <button
+ class="btn btn-primary d-md-none"
+ type="button"
+ data-bs-toggle="offcanvas"
+ data-bs-target="#mobileMenu">
+ <i class="bi bi-list fs-4"></i>
</button>
- <!-- Menu -->
- <div class="collapse navbar-collapse" id="menuNav">
- <div class="navbar-nav ms-auto gap-2">
- <a href="/hosts" id="hostsBtn" class="btn btn-primary active" aria-current="page">Hostname</a>
- <a href="/aliases" id="aliasesBtn" class="btn btn-primary" aria-current="page">Alias</a>
- <a href="/leases" id="leasesBtn" class="btn btn-primary" aria-current="page">DHCP Leases</a>
- <a href="/devices" id="devicesBtn" class="btn btn-primary" aria-current="page">Devices</a>
- <a href="/settings" id="settingsBtn" class="btn btn-primary" aria-current="page">Settings</a>
- <button id="logoutBtn" class="btn btn-primary">Logout</button>
- </div>
+
+ <!-- Desktop nav -->
+ <div class="d-none d-md-flex gap-2 ms-auto">
+ <a href="/hosts" class="btn btn-primary active">Hosts</a>
+ <a href="/aliases" class="btn btn-primary"> Alias</a>
+ <a href="/leases" class="btn btn-primary"> DHCP Leases</a>
+ <a href="/devices" class="btn btn-primary"> Devices</a>
+ <a href="/settings" class="btn btn-primary"> Settings</a>
+ <button class="btn btn-primary btn-logout">Logout</button>
</div>
</nav>
+
+ <!-- Mobile offcanvas -->
+ <div class="offcanvas offcanvas-end d-md-none" tabindex="-1" id="mobileMenu">
+
+ <div class="offcanvas-header">
+ <h5 class="offcanvas-title">Network Manager</h5>
+
+ <button
+ type="button"
+ class="btn-close"
+ data-bs-dismiss="offcanvas">
+ </button>
+ </div>
+
+ <div class="offcanvas-body">
+ <div class="d-grid gap-2">
+ <a href="/hosts" class="btn btn-primary active">Hosts</a>
+ <a href="/aliases" class="btn btn-primary"> Alias</a>
+ <a href="/leases" class="btn btn-primary"> DHCP Leases</a>
+ <a href="/devices" class="btn btn-primary"> Devices</a>
+ <a href="/settings" class="btn btn-primary"> Settings</a>
+ <button class="btn btn-primary btn-logout">Logout</button>
+ </div>
+ </div>
+ </div>
</div>
</header>
</div>
<!-- Separator -->
- <div class="vr mx-2"></div>
+ <div class="vr mx-2 d-none d-md-block"></div>
<!-- Add host -->
<button
aria-label="Add Host"
data-bs-toggle="modal" data-bs-target="#addHostModal">
<i class="bi bi-plus-lg"></i>
- <span class="label"> Add Host</span>
+ <span class="label d-none d-md-block"> Add Host</span>
</button>
<!-- Separator -->
- <div class="vr mx-2"></div>
+ <div class="vr mx-2 d-none d-md-block"></div>
<!-- Reload DNS -->
<button
aria-label="Reload DNS"
data-action="reloadDns">
<i class="bi bi-arrow-repeat"></i>
- <span class="label"> Reload DNS</span>
+ <span class="label d-none d-md-block"> Reload DNS</span>
</button>
<!-- Reload DNS -->
aria-label="Reload DHCP"
data-action="reloadDhcp">
<i class="bi bi-arrow-repeat"></i>
- <span class="label"> Reload DHCP</span>
+ <span class="label d-none d-md-block"> Reload DHCP</span>
</button>
</div>
</div>
</th>
<th data-type="string" data-sortable="false" class="text-center text-nowrap">
- Actions <span class="sort-arrow invisible" aria-hidden="true"></span>
+ Actions
</th>
</tr>
</thead>
<span>Network Manager</span>
</a>
- <!-- Spacer -->
- <div class="col d-none d-md-block"></div>
-
- <nav class="navbar navbar-expand-md px-3">
- <!-- Bottone hamburger -->
- <button class="navbar-toggler bg-light" type="button" data-bs-toggle="collapse" data-bs-target="#menuNav">
- <span class="navbar-toggler-icon"></span>
+ <nav class="navbar">
+ <!-- Hamburger -->
+ <button
+ class="btn btn-primary d-md-none"
+ type="button"
+ data-bs-toggle="offcanvas"
+ data-bs-target="#mobileMenu">
+ <i class="bi bi-list fs-4"></i>
</button>
- <!-- Menu -->
- <div class="collapse navbar-collapse" id="menuNav">
- <div class="navbar-nav ms-auto gap-2">
- <button id="api-pill" class="btn btn-outline-primary" title="API Status" aria-label="API Status" data-action="apiCheck">API Status</button>
- <button id="logoutBtn" class="btn btn-primary">Logout</button>
- </div>
+
+ <!-- Desktop nav -->
+ <div class="d-none d-md-flex gap-2 ms-auto">
+ <button class="btn btn-outline-primary btn-api" title="API Status" aria-label="API Status" data-action="apiCheck">API Status</button>
+ <button class="btn btn-primary btn-logout">Logout</button>
</div>
</nav>
+
+ <!-- Mobile offcanvas -->
+ <div class="offcanvas offcanvas-end d-md-none" tabindex="-1" id="mobileMenu">
+
+ <div class="offcanvas-header">
+ <h5 class="offcanvas-title">Network Manager</h5>
+
+ <button
+ type="button"
+ class="btn-close"
+ data-bs-dismiss="offcanvas">
+ </button>
+ </div>
+
+ <div class="offcanvas-body">
+ <div class="d-grid gap-2">
+ <button class="btn btn-outline-primary btn-api" title="API Status" aria-label="API Status" data-action="apiCheck">API Status</button>
+ <button class="btn btn-primary btn-logout">Logout</button>
+ </div>
+ </div>
+ </div>
</div>
</header>
<section class="page-frame">
<div class="container-fluid p-0">
<div class="row g-2 align-items-center">
+
<!-- Title -->
<div class="col-12 col-md-auto">
<h2 class="mb-0 d-flex align-items-center gap-2 lh-1">
allAliases = [];
viewAliases = [];
// hide loader and show table
- loader.style.display = "none";
tableWrapper.classList.remove("d-none");
}
+ finally {
+ loader.style.display = "none";
+ }
}
// -----------------------------
if (!viewAliases.length) {
const trEmpty = document.createElement("tr");
const tdEmpty = document.createElement("td");
- tdEmpty.colSpan = 7;
+ tdEmpty.colSpan = 5;
tdEmpty.textContent = "No alias available.";
tdEmpty.style.textAlign = "center";
trEmpty.appendChild(tdEmpty);
const term =
document.getElementById('searchInput')?.value ||
document.getElementById('searchInputMobile')?.value;
- if (term) {
+ if (term?.trim()) {
handleSearch(term);
}
}
showToast(err?.message || "Error loading alias", false);
// Close modal
modalEl.addEventListener('shown.bs.modal', () => {
- closeAddAliasModal(lastTriggerEl);
+ closeAddAliasModal();
}, { once: true });
}
} else {
allDevices = [];
viewDevices = [];
// hide loader and show table
- loader.style.display = "none";
tableWrapper.classList.remove("d-none");
}
+ finally {
+ loader.style.display = "none";
+ }
}
// -----------------------------
const term =
document.getElementById('searchInput')?.value ||
document.getElementById('searchInputMobile')?.value;
- if (term) {
+ if (term?.trim()) {
handleSearch(term, filterTable);
}
}
showToast(err?.message || "Error loading host", false);
// Close modal
modalEl.addEventListener('shown.bs.modal', () => {
- closeAddHostModal(lastTriggerEl);
+ closeAddHostModal();
}, { once: true });
}
} else {
allHosts = [];
viewHosts = [];
// hide loader and show table
- loader.style.display = "none";
tableWrapper.classList.remove("d-none");
}
+ finally {
+ loader.style.display = "none";
+ }
}
// -----------------------------
if (!viewHosts.length) {
const trEmpty = document.createElement("tr");
const tdEmpty = document.createElement("td");
- tdEmpty.colSpan = 7;
+ tdEmpty.colSpan = 6;
tdEmpty.textContent = "No hosts available.";
tdEmpty.style.textAlign = "center";
trEmpty.appendChild(tdEmpty);
const term =
document.getElementById('searchInput')?.value ||
document.getElementById('searchInputMobile')?.value;
- if (term) {
+ if (term?.trim()) {
handleSearch(term, filterTable);
}
}
showToast(err?.message || "Error loading host", false);
// Close modal
modalEl.addEventListener('shown.bs.modal', () => {
- closeAddHostModal(lastTriggerEl);
+ closeAddHostModal();
}, { once: true });
}
} else {
// Manage Backup List Rendering (usa fetchData() con apiMap.backups)
// -------------------------------------------------------
export async function serviceCheckAbout() {
- const pill = document.getElementById('api-pill');
- if (!pill) return;
+ const pills = document.querySelectorAll('.btn-api');
+
+ if (!pills.length) return;
const ok = await serviceIsAlive();
- if (ok) {
- pill.textContent = 'API OK';
- pill.classList.remove('btn-outline-primary');
- pill.classList.add('btn-primary');
- } else {
- pill.textContent = 'API OFFLINE';
- }
+ pills.forEach(pill => {
+
+ if (ok) {
+ pill.textContent = 'API OK';
+ pill.classList.remove('btn-outline-primary');
+ pill.classList.add('btn-primary');
+
+ } else {
+ pill.textContent = 'API OFFLINE';
+ }
+ });
return ok;
}
allLeases = [];
viewLeases = [];
// hide loader and show table
- loader.style.display = "none";
tableWrapper.classList.remove("d-none");
}
+ finally {
+ loader.style.display = "none";
+ }
}
// -----------------------------
const term =
document.getElementById('searchInput')?.value ||
document.getElementById('searchInputMobile')?.value;
- if (term) {
+ if (term?.trim()) {
handleSearch(term, filterTable);
}
}
showToast(err?.message || "Error loading host", false);
// Close modal
modalEl.addEventListener('shown.bs.modal', () => {
- closeAddHostModal(lastTriggerEl);
+ closeAddHostModal();
}, { once: true });
}
}
// DOMContentLoaded: initialize everything
// -----------------------------
document.addEventListener("DOMContentLoaded", () => {
- const logoutBtn = document.getElementById("logoutBtn");
- if (logoutBtn) {
- logoutBtn.addEventListener("click", handleLogout);
- }
+ document.querySelectorAll(".btn-logout").forEach(btn => {
+ btn.addEventListener("click", handleLogout);
+ });
});
allConfigs = [];
viewConfigs = [];
// hide loader and show table
- loader.style.display = "none";
tableWrapper.classList.remove("d-none");
}
+ finally {
+ loader.style.display = "none";
+ }
}
// -----------------------------
if (!viewConfigs.length) {
const trEmpty = document.createElement("tr");
const tdEmpty = document.createElement("td");
- tdEmpty.colSpan = 7;
+ tdEmpty.colSpan = 4;
tdEmpty.textContent = "No configs available.";
tdEmpty.style.textAlign = "center";
trEmpty.appendChild(tdEmpty);
showToast(err?.message || "Error loading config", false);
// Close modal
modalEl.addEventListener('shown.bs.modal', () => {
- closeEditConfigModal(lastTriggerEl);
+ closeEditConfigModal();
}, { once: true });
}
} else {
<span>Network Manager</span>
</a>
- <!-- Spacer -->
- <div class="col d-none d-md-block"></div>
-
- <nav class="navbar navbar-expand-md px-3">
- <!-- Bottone hamburger -->
- <button class="navbar-toggler bg-light" type="button" data-bs-toggle="collapse" data-bs-target="#menuNav">
- <span class="navbar-toggler-icon"></span>
+ <nav class="navbar">
+ <!-- Hamburger -->
+ <button
+ class="btn btn-primary d-md-none"
+ type="button"
+ data-bs-toggle="offcanvas"
+ data-bs-target="#mobileMenu">
+ <i class="bi bi-list fs-4"></i>
</button>
- <!-- Menu -->
- <div class="collapse navbar-collapse" id="menuNav">
- <div class="navbar-nav ms-auto gap-2">
- <a href="/hosts" id="hostsBtn" class="btn btn-primary" aria-current="page">Hostname</a>
- <a href="/aliases" id="aliasesBtn" class="btn btn-primary" aria-current="page">Alias</a>
- <a href="/leases" id="leasesBtn" class="btn btn-primary active" aria-current="page">DHCP Leases</a>
- <a href="/devices" id="devicesBtn" class="btn btn-primary" aria-current="page">Devices</a>
- <a href="/settings" id="settingsBtn" class="btn btn-primary" aria-current="page">Settings</a>
- <button id="logoutBtn" class="btn btn-primary">Logout</button>
- </div>
+
+ <!-- Desktop nav -->
+ <div class="d-none d-md-flex gap-2 ms-auto">
+ <a href="/hosts" class="btn btn-primary"> Hosts</a>
+ <a href="/aliases" class="btn btn-primary"> Alias</a>
+ <a href="/leases" class="btn btn-primary active">DHCP Leases</a>
+ <a href="/devices" class="btn btn-primary"> Devices</a>
+ <a href="/settings" class="btn btn-primary"> Settings</a>
+ <button class="btn btn-primary btn-logout">Logout</button>
</div>
</nav>
+
+ <!-- Mobile offcanvas -->
+ <div class="offcanvas offcanvas-end d-md-none" tabindex="-1" id="mobileMenu">
+
+ <div class="offcanvas-header">
+ <h5 class="offcanvas-title">Network Manager</h5>
+
+ <button
+ type="button"
+ class="btn-close"
+ data-bs-dismiss="offcanvas">
+ </button>
+ </div>
+
+ <div class="offcanvas-body">
+ <div class="d-grid gap-2">
+ <a href="/hosts" class="btn btn-primary"> Hosts</a>
+ <a href="/aliases" class="btn btn-primary"> Alias</a>
+ <a href="/leases" class="btn btn-primary active">DHCP Leases</a>
+ <a href="/devices" class="btn btn-primary"> Devices</a>
+ <a href="/settings" class="btn btn-primary"> Settings</a>
+ <button class="btn btn-primary btn-logout">Logout</button>
+ </div>
+ </div>
+ </div>
</div>
</header>
</div>
<!-- Separator -->
- <div class="vr mx-2"></div>
+ <div class="vr mx-2 d-none d-md-block"></div>
<!-- Add host -->
<button
aria-label="Add Host"
data-bs-toggle="modal" data-bs-target="#addHostModal">
<i class="bi bi-plus-lg"></i>
- <span class="label"> Add Host</span>
+ <span class="label d-none d-md-block"> Add Host</span>
</button>
<!-- Separator -->
- <div class="vr mx-2"></div>
+ <div class="vr mx-2 d-none d-md-block"></div>
<!-- Reload DNS -->
<button
aria-label="Reload DNS"
data-action="reloadDns">
<i class="bi bi-arrow-repeat"></i>
- <span class="label"> Reload DNS</span>
+ <span class="label d-none d-md-block"> Reload DNS</span>
</button>
<!-- Reload DNS -->
aria-label="Reload DHCP"
data-action="reloadDhcp">
<i class="bi bi-arrow-repeat"></i>
- <span class="label"> Reload DHCP</span>
+ <span class="label d-none d-md-block"> Reload DHCP</span>
</button>
</div>
</div>
<span>Network Manager</span>
</a>
- <!-- Spacer -->
- <div class="col d-none d-md-block"></div>
-
- <nav class="navbar navbar-expand-md px-3">
- <!-- Bottone hamburger -->
- <button class="navbar-toggler bg-light" type="button" data-bs-toggle="collapse" data-bs-target="#menuNav">
- <span class="navbar-toggler-icon"></span>
+ <nav class="navbar">
+ <!-- Hamburger -->
+ <button
+ class="btn btn-primary d-md-none"
+ type="button"
+ data-bs-toggle="offcanvas"
+ data-bs-target="#mobileMenu">
+ <i class="bi bi-list fs-4"></i>
</button>
- <!-- Menu -->
- <div class="collapse navbar-collapse" id="menuNav">
- <div class="navbar-nav ms-auto gap-2">
- <a href="/hosts" id="hostsBtn" class="btn btn-primary" aria-current="page">Hostname</a>
- <a href="/aliases" id="aliasesBtn" class="btn btn-primary" aria-current="page">Alias</a>
- <a href="/leases" id="leasesBtn" class="btn btn-primary" aria-current="page">DHCP Leases</a>
- <a href="/devices" id="devicesBtn" class="btn btn-primary" aria-current="page">Devices</a>
- <a href="/settings" id="settingsBtn" class="btn btn-primary active" aria-current="page">Settings</a>
- <button id="logoutBtn" class="btn btn-primary">Logout</button>
- </div>
+
+ <!-- Desktop nav -->
+ <div class="d-none d-md-flex gap-2 ms-auto">
+ <a href="/hosts" class="btn btn-primary"> Hosts</a>
+ <a href="/aliases" class="btn btn-primary"> Alias</a>
+ <a href="/leases" class="btn btn-primary"> DHCP Leases</a>
+ <a href="/devices" class="btn btn-primary"> Devices</a>
+ <a href="/settings" class="btn btn-primary active">Settings</a>
+ <button class="btn btn-primary btn-logout">Logout</button>
</div>
</nav>
+
+ <!-- Mobile offcanvas -->
+ <div class="offcanvas offcanvas-end d-md-none" tabindex="-1" id="mobileMenu">
+
+ <div class="offcanvas-header">
+ <h5 class="offcanvas-title">Network Manager</h5>
+
+ <button
+ type="button"
+ class="btn-close"
+ data-bs-dismiss="offcanvas">
+ </button>
+ </div>
+
+ <div class="offcanvas-body">
+ <div class="d-grid gap-2">
+ <a href="/hosts" class="btn btn-primary"> Hosts</a>
+ <a href="/aliases" class="btn btn-primary"> Alias</a>
+ <a href="/leases" class="btn btn-primary"> DHCP Leases</a>
+ <a href="/devices" class="btn btn-primary"> Devices</a>
+ <a href="/settings" class="btn btn-primary active">Settings</a>
+ <button class="btn btn-primary btn-logout">Logout</button>
+ </div>
+ </div>
+ </div>
</div>
</header>
</div>
<!-- Separator -->
- <div class="vr mx-2"></div>
+ <div class="vr mx-2 d-none d-md-block"></div>
<!-- Expand -->
<button id="expandAllBtn"
title="Expand all groups"
aria-label="Expand all groups">
<i class="bi bi-arrows-expand"></i>
- <span class="label">Expand</span>
+ <span class="label d-none d-md-block">Expand</span>
</button>
<!-- Collapse -->
title="Collapse all groups"
aria-label="Collapse all groups">
<i class="bi bi-arrows-collapse"></i>
- <span class="label">Collapse</span>
+ <span class="label d-none d-md-block">Collapse</span>
</button>
<!-- Separator -->
- <div class="vr mx-2"></div>
+ <div class="vr mx-2 d-none d-md-block"></div>
<!-- Restart -->
<button class="btn btn-danger d-flex align-items-center gap-2 px-3"
aria-label="Restart system"
data-action="restartApp">
<i class="bi bi-arrow-repeat"></i>
- <span class="label">Restart</span>
+ <span class="label d-none d-md-block">Restart</span>
</button>
</div>
</div>