]> git.giorgioravera.it Git - network-manager.git/commitdiff
Created dedicate modals file
authorGiorgio Ravera <giorgio.ravera@gmail.com>
Tue, 26 May 2026 12:40:56 +0000 (14:40 +0200)
committerGiorgio Ravera <giorgio.ravera@gmail.com>
Tue, 26 May 2026 12:40:56 +0000 (14:40 +0200)
15 files changed:
backend/app.py
frontend/aliases.html
frontend/devices.html
frontend/hosts.html
frontend/index.html
frontend/js/aliases.js
frontend/js/common.js
frontend/js/devices.js
frontend/js/hosts.js
frontend/js/index.js
frontend/js/leases.js
frontend/js/login.js
frontend/js/session.js
frontend/leases.html
frontend/modals.html [new file with mode: 0644]

index c169fce44c02e231d686ba8e9662bbb526f31618..46b00106b3d9e90d74e78d7d364cb794db27abfd 100644 (file)
@@ -172,6 +172,10 @@ def home(request: Request):
 def js_home(request: Request):
     return FileResponse(os.path.join(settings.FRONTEND_DIR, "js/index.js"))
 
+# Modals
+def modals(request: Request):
+    return FileResponse(os.path.join(settings.FRONTEND_DIR, "modals.html"))
+
 # CSS variables
 def css_variables(request: Request):
     return FileResponse(os.path.join(settings.FRONTEND_DIR, "css/variables.css"))
@@ -240,6 +244,7 @@ def create_app() -> FastAPI:
     app.add_api_route("/", home, methods=["GET"])
     app.add_api_route("/home", home, methods=["GET"])
     app.add_api_route("/index.html", home, methods=["GET"])
+    app.add_api_route("/modals.html", modals, methods=["GET"])
     app.add_api_route("/js/index.js", js_home, methods=["GET"])
     app.add_api_route("/css/variables.css", css_variables, methods=["GET"])
     app.add_api_route("/css/layout.css", css_layout, methods=["GET"])
index 07924f60269ff879af706f812ea1bec4c1e8f899..4d587f1a0d3be8516fdf65ad958cd5143db0bacb 100644 (file)
     </div>
     <div id="devices-container"></div>
 
-       <!-- AddAlias -->
-    <div class="modal fade" id="addAliasModal" tabindex="-1" aria-labelledby="addAliasTitle" aria-hidden="true">
-        <div class="modal-dialog modal-dialog-centered"><!-- modal-sm|md|lg se vuoi cambiare -->
-            <div class="modal-content addhost-modal">
-                <!-- Header scuro con logo/brand -->
-                <div class="modal-header addhost-header">
-                    <div class="d-flex align-items-center gap-2">
-                        <!-- Emoji o icona -->
-                        <span class="title-icon" aria-hidden="true">🖧</span>
-                        <h5 class="modal-title mb-0" id="addAliasTitle">Aggiungi Alias</h5>
-                    </div>
-                    <button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Chiudi"></button>
-                </div>
-
-                <div class="modal-body">
-                    <form id="addAliasForm">
-                        <div class="mb-2">
-                            <label for="aliasName" class="form-label">Alias</label>
-                            <input type="text" id="aliasName" class="form-control" required>
-                        </div>
-
-                        <div class="mb-2">
-                            <label for="aliasTarget" class="form-label">Target</label>
-                            <input type="text" id="aliasTarget" class="form-control" required>
-                        </div>
-
-                        <div class="mb-2">
-                            <label for="aliasDescription" class="form-label">Description</label>
-                            <input type="text" id="aliasDescription" class="form-control">
-                        </div>
-
-                        <div class="form-check my-2">
-                            <input class="form-check-input" type="checkbox" id="aliasSSL">
-                            <label class="form-check-label" for="aliasSSL">SSL?</label>
-                        </div>
-
-                        <div class="mb-2">
-                            <label class="form-label d-block">Visibility</label>
-                            <div class="btn-group" role="group">
-                                <!-- Local -->
-                                <input type="radio" class="btn-check" id="aliasVisibilityLocal" name="aliasVisibility" value="0" checked>
-                                <label class="btn btn-outline-primary" for="aliasVisibilityLocal">Local</label>
-                                <!-- Global -->
-                                <input type="radio" class="btn-check" id="aliasVisibilityGlobal" name="aliasVisibility" value="1">
-                                <label class="btn btn-outline-primary" for="aliasVisibilityGlobal">Global</label>
-                                <!-- Alias -->
-                                <input type="radio" class="btn-check" id="aliasVisibilityAlias" name="aliasVisibility" value="2">
-                                <label class="btn btn-outline-primary" for="aliasVisibilityAlias">Alias</label>
-                            </div>
-                        </div>
-                    </form>
-                </div>
-
-                <div class="modal-footer">
-                    <button type="submit" form="addAliasForm" class="btn btn-primary">
-                        <i class="bi bi-check2"></i>
-                    </button>
-                    <button type="button" class="btn btn-primary" data-bs-dismiss="modal">
-                        <i class="bi bi-x"></i>
-                    </button>
-                </div>
-            </div>
-        </div>
-    </div>
+    <!-- Modals -->
+    <div id="modals-container"></div>
 
     <!-- Scripts -->
     <script type="module" src="js/aliases.js"></script>
index 4a91842bc4b9a2ed9a3d3b0d94a8be67701d439a..f908c9dbc9bcafc686adf540535e8a02321bd73c 100644 (file)
     </div>
     <div id="devices-container"></div>
 
-       <!-- AddHost -->
-    <div class="modal fade" id="addHostModal" tabindex="-1" aria-labelledby="addHostTitle" aria-hidden="true">
-        <div class="modal-dialog modal-dialog-centered"><!-- modal-sm|md|lg se vuoi cambiare -->
-            <div class="modal-content addhost-modal">
-                <!-- Header scuro con logo/brand -->
-                <div class="modal-header addhost-header">
-                    <div class="d-flex align-items-center gap-2">
-                        <!-- Emoji o icona -->
-                        <span class="title-icon" aria-hidden="true">🖧</span>
-                        <h5 class="modal-title mb-0" id="addHostTitle">Aggiungi Host</h5>
-                    </div>
-                    <button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Chiudi"></button>
-                </div>
-
-                <div class="modal-body">
-                    <form id="addHostForm">
-                        <div class="mb-2">
-                            <label for="hostName" class="form-label">Hostname</label>
-                            <input type="text" id="hostName" class="form-control" required>
-                        </div>
-
-                        <div class="mb-2">
-                            <label for="hostIPv4" class="form-label">IPv4</label>
-                            <input type="text" id="hostIPv4" class="form-control" inputmode="decimal" placeholder="es. 192.168.1.10">
-                        </div>
-
-                        <div class="mb-2">
-                            <label for="hostIPv6" class="form-label">IPv6</label>
-                            <input type="text" id="hostIPv6" class="form-control" placeholder="es. fe80::1">
-                        </div>
-
-                        <div class="mb-2">
-                            <label for="hostMAC" class="form-label">MAC Address</label>
-                            <input type="text" id="hostMAC" class="form-control" placeholder="es. AA:BB:CC:DD:EE:FF">
-                        </div>
-
-                        <div class="mb-2">
-                            <label for="hostDescription" class="form-label">Description</label>
-                            <input type="text" id="hostDescription" class="form-control">
-                        </div>
-
-                        <div class="form-check my-2">
-                            <input class="form-check-input" type="checkbox" id="hostSSL">
-                            <label class="form-check-label" for="hostSSL">SSL?</label>
-                        </div>
-
-                        <div class="mb-2">
-                            <label class="form-label d-block">Visibility</label>
-                            <div class="btn-group" role="group">
-                                <!-- Local -->
-                                <input type="radio" class="btn-check" id="hostVisibilityLocal" name="hostVisibility" value="0" checked>
-                                <label class="btn btn-outline-primary" for="hostVisibilityLocal">Local</label>
-                                <!-- Global -->
-                                <input type="radio" class="btn-check" id="hostVisibilityGlobal" name="hostVisibility" value="1">
-                                <label class="btn btn-outline-primary" for="hostVisibilityGlobal">Global</label>
-                                <!-- Alias -->
-                                <input type="radio" class="btn-check" id="hostVisibilityAlias" name="hostVisibility" value="2">
-                                <label class="btn btn-outline-primary" for="hostVisibilityAlias">Alias</label>
-                            </div>
-                        </div>
-                    </form>
-                </div>
-
-                <div class="modal-footer">
-                    <button type="submit" form="addHostForm" class="btn btn-primary">
-                        <i class="bi bi-check2"></i>
-                    </button>
-                    <button type="button" class="btn btn-primary" data-bs-dismiss="modal">
-                        <i class="bi bi-x"></i>
-                    </button>
-                </div>
-            </div>
-        </div>
-    </div>
+    <!-- Modals -->
+    <div id="modals-container"></div>
 
     <!-- Scripts -->
     <script type="module" src="js/devices.js"></script>
index 089a970ebd61f8da305dbc09d8f29a6f1c155e6b..69dd03208c4d1943e9138b8fd3d2eb257ddae02f 100644 (file)
     </div>
     <div id="devices-container"></div>
 
-       <!-- AddHost -->
-    <div class="modal fade" id="addHostModal" tabindex="-1" aria-labelledby="addHostTitle" aria-hidden="true">
-        <div class="modal-dialog modal-dialog-centered"><!-- modal-sm|md|lg se vuoi cambiare -->
-            <div class="modal-content addhost-modal">
-                <!-- Header scuro con logo/brand -->
-                <div class="modal-header addhost-header">
-                    <div class="d-flex align-items-center gap-2">
-                        <!-- Emoji o icona -->
-                        <span class="title-icon" aria-hidden="true">🖧</span>
-                        <h5 class="modal-title mb-0" id="addHostTitle">Aggiungi Host</h5>
-                    </div>
-                    <button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Chiudi"></button>
-                </div>
-
-                <div class="modal-body">
-                    <form id="addHostForm">
-                        <div class="mb-2">
-                            <label for="hostName" class="form-label">Hostname</label>
-                            <input type="text" id="hostName" class="form-control" required>
-                        </div>
-
-                        <div class="mb-2">
-                            <label for="hostIPv4" class="form-label">IPv4</label>
-                            <input type="text" id="hostIPv4" class="form-control" inputmode="decimal" placeholder="es. 192.168.1.10">
-                        </div>
-
-                        <div class="mb-2">
-                            <label for="hostIPv6" class="form-label">IPv6</label>
-                            <input type="text" id="hostIPv6" class="form-control" placeholder="es. fe80::1">
-                        </div>
-
-                        <div class="mb-2">
-                            <label for="hostMAC" class="form-label">MAC Address</label>
-                            <input type="text" id="hostMAC" class="form-control" placeholder="es. AA:BB:CC:DD:EE:FF">
-                        </div>
-
-                        <div class="mb-2">
-                            <label for="hostDescription" class="form-label">Description</label>
-                            <input type="text" id="hostDescription" class="form-control">
-                        </div>
-
-                        <div class="form-check my-2">
-                            <input class="form-check-input" type="checkbox" id="hostSSL">
-                            <label class="form-check-label" for="hostSSL">SSL?</label>
-                        </div>
-
-                        <div class="mb-2">
-                            <label class="form-label d-block">Visibility</label>
-                            <div class="btn-group" role="group">
-                                <!-- Local -->
-                                <input type="radio" class="btn-check" id="hostVisibilityLocal" name="hostVisibility" value="0" checked>
-                                <label class="btn btn-outline-primary" for="hostVisibilityLocal">Local</label>
-                                <!-- Global -->
-                                <input type="radio" class="btn-check" id="hostVisibilityGlobal" name="hostVisibility" value="1">
-                                <label class="btn btn-outline-primary" for="hostVisibilityGlobal">Global</label>
-                                <!-- Alias -->
-                                <input type="radio" class="btn-check" id="hostVisibilityAlias" name="hostVisibility" value="2">
-                                <label class="btn btn-outline-primary" for="hostVisibilityAlias">Alias</label>
-                            </div>
-                        </div>
-                    </form>
-                </div>
-
-                <div class="modal-footer">
-                    <button type="submit" form="addHostForm" class="btn btn-primary">
-                        <i class="bi bi-check2"></i>
-                    </button>
-                    <button type="button" class="btn btn-primary" data-bs-dismiss="modal">
-                        <i class="bi bi-x"></i>
-                    </button>
-                </div>
-            </div>
-        </div>
-    </div>
+    <!-- Modals -->
+    <div id="modals-container"></div>
 
     <!-- Scripts -->
     <script type="module" src="js/hosts.js"></script>
index c8a2485640b8eed7901f5f3547a1c2f3461074d4..f317eedbc1baea274060088d8e05361e6822182c 100644 (file)
         </div>
     </main>
 
-    <!-- Modal Restore -->
-    <div id="restoreModal" class="modal" role="dialog" aria-modal="true" aria-labelledby="restoreTitle">
-        <div class="modal-content addhost-modal">
-            <div class="addhost-header d-flex justify-content-between align-items-center">
-                <div class="d-flex align-items-center gap-2">
-                    <span class="title-icon">💾</span>
-                    <span id="restoreTitle" class="modal-title">Execute Restore</span>
-                </div>
-                <button type="button" class="btn-close" title="Close" aria-label="Close" data-action="closeRestoreModal"></button>
-            </div>
-
-            <div class="modal-body">
-                <label for="restoreBackupId" class="form-label">Backup ID</label>
-                <input type="text" id="restoreBackupId" class="form-control" placeholder="e.g., bk_20260317_200100" />
-                <small class="text-muted">Select the backup ID to restore.</small>
-            </div>
-
-            <div class="modal-footer modal-buttons">
-                <button type="button" class="btn btn-primary" data-action="startRestore"><span class="label">Start Restore</span></button>
-                <button type="button" class="btn btn-outline-primary" data-action="closeRestoreModal"><span class="label">Cancel</span></button>
-            </div>
-        </div>
-    </div>
-
-    <!-- Modal Health -->
-    <div id="healthModal" class="modal" role="dialog" aria-modal="true" aria-labelledby="healthTitle">
-        <div class="modal-dialog modal-dialog-centered">
-            <div class="modal-content addhost-modal">
-                <div class="addhost-header d-flex justify-content-between align-items-center">
-                    <div class="d-flex align-items-center gap-2">
-                        <span class="title-icon">❤️‍🩹</span>
-                        <span id="healthTitle" class="modal-title">Health Status</span>
-                    </div>
-                    <button type="button" class="btn-close" title="Close" aria-label="Close" data-action="closeHealthModal"></button>
-                </div>
-
-                <div class="modal-body">
-                    <!-- Loading -->
-                    <div id="healthLoading" class="d-flex align-items-center gap-2">
-                        <div class="spinner-border text-primary spinner-border-sm" role="status" aria-label="Loading"></div>
-                            <span class="text-muted">Loading status…</span>
-                        </div>
-
-                        <!-- Content -->
-                        <div id="healthContent" class="d-none">
-                            <ul class="list-group mb-3" id="healthSummary">
-                                <!-- Popolato via JS -->
-                            </ul>
-
-                            <div class="mb-3">
-                                <span class="badge rounded-pill" id="healthStatusBadge">—</span>
-                                <small class="text-muted ms-2" id="healthUpdatedAt"></small>
-                            </div>
-
-                            <!--<details>
-                                <summary class="mb-2">JSON completo</summary>
-                                <pre class="bg-light p-2 rounded small mb-0" id="healthRawJson" aria-label="Raw JSON"></pre>
-                            </details>-->
-                        </div>
-
-                    <!-- Error -->
-                    <div id="healthError" class="alert alert-danger d-none" role="alert" aria-live="assertive">
-                        Error fetching health status. Please try again later.
-                    </div>
-                </div>
-
-                <div class="modal-footer modal-buttons">
-                    <button type="button" class="btn btn-outline-primary" data-action="closeHealthModal">
-                        <span class="label">Close</span>
-                    </button>
-                </div>
-            </div>
-        </div>
-    </div>
+    <!-- Modals -->
+    <div id="modals-container"></div>
 
     <!-- Scripts -->
     <script type=module src="js/index.js"></script>
index 7f1f31ef727cfd931aee6de6049c90905467e10d..f34e486a78f563de7473e59b23a51d91e0b203a7 100644 (file)
@@ -1,5 +1,5 @@
 // Import common js
-import { showToast, sortTable, initSortableTable, resetSorting } from './common.js';
+import { loadModals, showToast, sortTable, initSortableTable, resetSorting } from './common.js';
 import { reloadDNS, reloadDHCP } from './services.js';
 
 // -----------------------------
@@ -587,6 +587,14 @@ const actionHandlers = {
 // -----------------------------
 document.addEventListener("DOMContentLoaded", async () => {
 
+    // Load modals (Bootstrap 5 requires JS initialization for dynamic content)
+    try {
+        await loadModals();
+    } catch (err) {
+        console.error(err?.message || "Error loading modals");
+        showToast(err?.message || "Error loading modals", false);
+    }
+
     // Init UI sort (aria-sort, arrows)
     initSortableTable();
 
index 7c608f48acc52456bc29719f9a0ccd3876c673ea..fad618b86d2560aabb6ca90641da93cba74e5b38 100644 (file)
@@ -4,6 +4,29 @@
 let timeoutToast = 3000; // milliseconds
 const stringCollator = new Intl.Collator(undefined, { numeric: true, sensitivity: "base" });
 
+// -----------------------------
+// Load modals HTML and initialize them
+// -----------------------------
+export async function loadModals() {
+    try {
+        const r = await fetch("/modals.html");
+        if (!r.ok) throw new Error("Error loading modals");
+
+        const html = await r.text();
+
+        const container = document.getElementById("modals-container");
+        if (!container) {
+            console.warn("modals-container not found");
+            return;
+        }
+
+        container.innerHTML = html;
+
+    } catch (err) {
+        console.error("Modals load error:", err);
+    }
+}
+
 // -----------------------------
 // Validate the IPv4 address format
 // -----------------------------
index 4b2966bdfe66d954898c08c35d391a35aa2e3bdc..e2da545917f01ad6d7142346a901c46745cc71c0 100644 (file)
@@ -1,5 +1,5 @@
 // Import common js
-import { isValidIPv4, isValidIPv6, isValidMAC, showToast, sortTable, initSortableTable, resetSorting } from './common.js';
+import { loadModals, isValidIPv4, isValidIPv6, isValidMAC, showToast, sortTable, initSortableTable, resetSorting } from './common.js';
 import { reloadDNS, reloadDHCP } from './services.js';
 
 // -----------------------------
@@ -704,6 +704,14 @@ const actionHandlers = {
 // -----------------------------
 document.addEventListener("DOMContentLoaded", async () => {
 
+    // Load modals (Bootstrap 5 requires JS initialization for dynamic content)
+    try {
+        await loadModals();
+    } catch (err) {
+        console.error(err?.message || "Error loading modals");
+        showToast(err?.message || "Error loading modals", false);
+    }
+
     // Init UI sort (aria-sort, arrows)
     initSortableTable();
 
index f142b43a4883ab09e8ea2f3d6b5645164afece70..c69c42b8aa0bb7acc46f1f755405c8b47b22bb8b 100644 (file)
@@ -1,5 +1,5 @@
 // Import common js
-import { isValidIPv4, isValidIPv6, isValidMAC, showToast, sortTable, initSortableTable, resetSorting } from './common.js';
+import { loadModals, isValidIPv4, isValidIPv6, isValidMAC, showToast, sortTable, initSortableTable, resetSorting } from './common.js';
 import { reloadDNS, reloadDHCP } from './services.js';
 
 // -----------------------------
@@ -611,6 +611,14 @@ const actionHandlers = {
 // -----------------------------
 document.addEventListener("DOMContentLoaded", async () => {
 
+    // Load modals (Bootstrap 5 requires JS initialization for dynamic content)
+    try {
+        await loadModals();
+    } catch (err) {
+        console.error(err?.message || "Error loading modals");
+        showToast(err?.message || "Error loading modals", false);
+    }
+
     // Init UI sort (aria-sort, arrows)
     initSortableTable();
 
index 2c5faf3c1225caa8a9598fd23ac11d0ad261f4b1..6704c026e6896852d1a9780ba4552425f520e28b 100644 (file)
@@ -1,7 +1,7 @@
 // -------------------------------------------------------
 // IMPORT
 // -------------------------------------------------------
-import { showToast } from './common.js';
+import { loadModals, showToast } from './common.js';
 import { apiCheck, reloadDNS, reloadDHCP, doBackup, doRestore, checkHealth } from './services.js';
 
 // -------------------------------------------------------
@@ -252,6 +252,23 @@ const actionHandlers = {
     }
 };
 
+// -----------------------------
+// DOMContentLoaded: initialize everything
+// -----------------------------
+document.addEventListener("DOMContentLoaded", async () => {
+
+    // Load modals (Bootstrap 5 requires JS initialization for dynamic content)
+    try {
+        await loadModals();
+    } catch (err) {
+        console.error(err?.message || "Error loading modals");
+        showToast(err?.message || "Error loading modals", false);
+    }
+
+    // Init Restore Backup Modal (backdrop click to close)
+    initRestoreBackupModal();
+});
+
 // -------------------------------------------------------
 // Global Click Delegation
 // -------------------------------------------------------
@@ -281,8 +298,13 @@ document.addEventListener('keydown', (e) => {
     }
 });
 
-const restoreModal = document.getElementById('restoreModal');
-if (restoreModal) {
+// -------------------------------------------------------
+// Init Restore Backup Modal (backdrop click to close)
+// -------------------------------------------------------
+function initRestoreBackupModal() {
+    const restoreModal = document.getElementById('restoreModal');
+    if (!restoreModal) return;
+
     restoreModal.addEventListener('click', (e) => {
         if (e.target === restoreModal) closeRestoreModal();
     });
index 81ae6ad5391423bd457944b9d9273125f82edd80..f8e496b0db378947b6dbea44c3a3a208162265dd 100644 (file)
@@ -1,5 +1,5 @@
 // Import common js
-import { isValidIPv4, isValidIPv6, isValidMAC, showToast, sortTable, initSortableTable, resetSorting } from './common.js';
+import { loadModals, isValidIPv4, isValidIPv6, isValidMAC, showToast, sortTable, initSortableTable, resetSorting } from './common.js';
 import { reloadDNS, reloadDHCP } from './services.js';
 
 // -----------------------------
@@ -575,6 +575,14 @@ const actionHandlers = {
 // -----------------------------
 document.addEventListener("DOMContentLoaded", async () => {
 
+    // Load modals (Bootstrap 5 requires JS initialization for dynamic content)
+    try {
+        await loadModals();
+    } catch (err) {
+        console.error(err?.message || "Error loading modals");
+        showToast(err?.message || "Error loading modals", false);
+    }
+
     // Init UI sort (aria-sort, arrows)
     initSortableTable();
 
index b29bc04c4761729f71a449b882cfdfd6acd8fe1f..31d0422a35a3ec4c657808712cc28b32c631fd9c 100644 (file)
@@ -1,4 +1,7 @@
-document.addEventListener('DOMContentLoaded', () => {
+// -----------------------------
+// DOMContentLoaded: initialize everything
+// -----------------------------
+document.addEventListener("DOMContentLoaded", () => {
     const form = document.getElementById('loginForm');
     if (!form) return;
 
index a140a4ab79afa982d3906ec9fd4d7564e5de73f7..e85e7767256a543cb604b850537288b7e097d2cc 100644 (file)
@@ -11,7 +11,7 @@ async function handleLogout() {
 }
 
 // -----------------------------
-// DOM Ready
+// DOMContentLoaded: initialize everything
 // -----------------------------
 document.addEventListener("DOMContentLoaded", () => {
     const logoutBtn = document.getElementById("logoutBtn");
index 8b228b76d6dde3efc0bbfffdd66037d45f7a594e..54e648d9a36a4f7f160f4dca139e1719ed8b4bf5 100644 (file)
     </div>
     <div id="devices-container"></div>
 
-       <!-- AddHost -->
-    <div class="modal fade" id="addHostModal" tabindex="-1" aria-labelledby="addHostTitle" aria-hidden="true">
-        <div class="modal-dialog modal-dialog-centered"><!-- modal-sm|md|lg se vuoi cambiare -->
-            <div class="modal-content addhost-modal">
-                <!-- Header scuro con logo/brand -->
-                <div class="modal-header addhost-header">
-                    <div class="d-flex align-items-center gap-2">
-                        <!-- Emoji o icona -->
-                        <span class="title-icon" aria-hidden="true">🖧</span>
-                        <h5 class="modal-title mb-0" id="addHostTitle">Aggiungi Host</h5>
-                    </div>
-                    <button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Chiudi"></button>
-                </div>
-
-                <div class="modal-body">
-                    <form id="addHostForm">
-                        <div class="mb-2">
-                            <label for="hostName" class="form-label">Hostname</label>
-                            <input type="text" id="hostName" class="form-control" required>
-                        </div>
-
-                        <div class="mb-2">
-                            <label for="hostIPv4" class="form-label">IPv4</label>
-                            <input type="text" id="hostIPv4" class="form-control" inputmode="decimal" placeholder="es. 192.168.1.10">
-                        </div>
-
-                        <div class="mb-2">
-                            <label for="hostIPv6" class="form-label">IPv6</label>
-                            <input type="text" id="hostIPv6" class="form-control" placeholder="es. fe80::1">
-                        </div>
-
-                        <div class="mb-2">
-                            <label for="hostMAC" class="form-label">MAC Address</label>
-                            <input type="text" id="hostMAC" class="form-control" placeholder="es. AA:BB:CC:DD:EE:FF">
-                        </div>
-
-                        <div class="mb-2">
-                            <label for="hostDescription" class="form-label">Description</label>
-                            <input type="text" id="hostDescription" class="form-control">
-                        </div>
-
-                        <div class="form-check my-2">
-                            <input class="form-check-input" type="checkbox" id="hostSSL">
-                            <label class="form-check-label" for="hostSSL">SSL?</label>
-                        </div>
-
-                        <div class="mb-2">
-                            <label class="form-label d-block">Visibility</label>
-                            <div class="btn-group" role="group">
-                                <!-- Local -->
-                                <input type="radio" class="btn-check" id="hostVisibilityLocal" name="hostVisibility" value="0" checked>
-                                <label class="btn btn-outline-primary" for="hostVisibilityLocal">Local</label>
-                                <!-- Global -->
-                                <input type="radio" class="btn-check" id="hostVisibilityGlobal" name="hostVisibility" value="1">
-                                <label class="btn btn-outline-primary" for="hostVisibilityGlobal">Global</label>
-                                <!-- Alias -->
-                                <input type="radio" class="btn-check" id="hostVisibilityAlias" name="hostVisibility" value="2">
-                                <label class="btn btn-outline-primary" for="hostVisibilityAlias">Alias</label>
-                            </div>
-                        </div>
-                    </form>
-                </div>
-
-                <div class="modal-footer">
-                    <button type="submit" form="addHostForm" class="btn btn-primary">
-                        <i class="bi bi-check2"></i>
-                    </button>
-                    <button type="button" class="btn btn-primary" data-bs-dismiss="modal">
-                        <i class="bi bi-x"></i>
-                    </button>
-                </div>
-            </div>
-        </div>
-    </div>
+    <!-- Modals -->
+    <div id="modals-container"></div>
 
     <!-- Scripts -->
     <script type="module" src="js/leases.js"></script>
diff --git a/frontend/modals.html b/frontend/modals.html
new file mode 100644 (file)
index 0000000..3d4cf70
--- /dev/null
@@ -0,0 +1,214 @@
+<!-- AddHost -->
+<div class="modal fade" id="addHostModal" tabindex="-1" aria-labelledby="addHostTitle" aria-hidden="true">
+    <div class="modal-dialog modal-dialog-centered"><!-- modal-sm|md|lg se vuoi cambiare -->
+        <div class="modal-content addhost-modal">
+            <!-- Header scuro con logo/brand -->
+            <div class="modal-header addhost-header">
+                <div class="d-flex align-items-center gap-2">
+                    <!-- Emoji o icona -->
+                    <span class="title-icon" aria-hidden="true">🖧</span>
+                    <h5 class="modal-title mb-0" id="addHostTitle">Aggiungi Host</h5>
+                </div>
+                <button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Chiudi"></button>
+            </div>
+
+            <div class="modal-body">
+                <form id="addHostForm">
+                    <div class="mb-2">
+                        <label for="hostName" class="form-label">Hostname</label>
+                        <input type="text" id="hostName" class="form-control" required>
+                    </div>
+
+                    <div class="mb-2">
+                        <label for="hostIPv4" class="form-label">IPv4</label>
+                        <input type="text" id="hostIPv4" class="form-control" inputmode="decimal" placeholder="es. 192.168.1.10">
+                    </div>
+
+                    <div class="mb-2">
+                        <label for="hostIPv6" class="form-label">IPv6</label>
+                        <input type="text" id="hostIPv6" class="form-control" placeholder="es. fe80::1">
+                    </div>
+
+                    <div class="mb-2">
+                        <label for="hostMAC" class="form-label">MAC Address</label>
+                        <input type="text" id="hostMAC" class="form-control" placeholder="es. AA:BB:CC:DD:EE:FF">
+                    </div>
+
+                    <div class="mb-2">
+                        <label for="hostDescription" class="form-label">Description</label>
+                        <input type="text" id="hostDescription" class="form-control">
+                    </div>
+
+                    <div class="form-check my-2">
+                        <input class="form-check-input" type="checkbox" id="hostSSL">
+                        <label class="form-check-label" for="hostSSL">SSL?</label>
+                    </div>
+
+                    <div class="mb-2">
+                        <label class="form-label d-block">Visibility</label>
+                        <div class="btn-group" role="group">
+                            <!-- Local -->
+                            <input type="radio" class="btn-check" id="hostVisibilityLocal" name="hostVisibility" value="0" checked>
+                            <label class="btn btn-outline-primary" for="hostVisibilityLocal">Local</label>
+                            <!-- Global -->
+                            <input type="radio" class="btn-check" id="hostVisibilityGlobal" name="hostVisibility" value="1">
+                            <label class="btn btn-outline-primary" for="hostVisibilityGlobal">Global</label>
+                            <!-- Alias -->
+                            <input type="radio" class="btn-check" id="hostVisibilityAlias" name="hostVisibility" value="2">
+                            <label class="btn btn-outline-primary" for="hostVisibilityAlias">Alias</label>
+                        </div>
+                    </div>
+                </form>
+            </div>
+
+            <div class="modal-footer">
+                <button type="submit" form="addHostForm" class="btn btn-primary">
+                    <i class="bi bi-check2"></i>
+                </button>
+                <button type="button" class="btn btn-primary" data-bs-dismiss="modal">
+                    <i class="bi bi-x"></i>
+                </button>
+            </div>
+        </div>
+    </div>
+</div>
+
+<!-- AddAlias -->
+<div class="modal fade" id="addAliasModal" tabindex="-1" aria-labelledby="addAliasTitle" aria-hidden="true">
+    <div class="modal-dialog modal-dialog-centered"><!-- modal-sm|md|lg se vuoi cambiare -->
+        <div class="modal-content addhost-modal">
+            <!-- Header scuro con logo/brand -->
+            <div class="modal-header addhost-header">
+                <div class="d-flex align-items-center gap-2">
+                    <!-- Emoji o icona -->
+                    <span class="title-icon" aria-hidden="true">🖧</span>
+                    <h5 class="modal-title mb-0" id="addAliasTitle">Aggiungi Alias</h5>
+                </div>
+                <button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Chiudi"></button>
+            </div>
+
+            <div class="modal-body">
+                <form id="addAliasForm">
+                    <div class="mb-2">
+                        <label for="aliasName" class="form-label">Alias</label>
+                        <input type="text" id="aliasName" class="form-control" required>
+                    </div>
+
+                    <div class="mb-2">
+                        <label for="aliasTarget" class="form-label">Target</label>
+                        <input type="text" id="aliasTarget" class="form-control" required>
+                    </div>
+
+                    <div class="mb-2">
+                        <label for="aliasDescription" class="form-label">Description</label>
+                        <input type="text" id="aliasDescription" class="form-control">
+                    </div>
+
+                    <div class="form-check my-2">
+                        <input class="form-check-input" type="checkbox" id="aliasSSL">
+                        <label class="form-check-label" for="aliasSSL">SSL?</label>
+                    </div>
+
+                    <div class="mb-2">
+                        <label class="form-label d-block">Visibility</label>
+                        <div class="btn-group" role="group">
+                            <!-- Local -->
+                            <input type="radio" class="btn-check" id="aliasVisibilityLocal" name="aliasVisibility" value="0" checked>
+                            <label class="btn btn-outline-primary" for="aliasVisibilityLocal">Local</label>
+                            <!-- Global -->
+                            <input type="radio" class="btn-check" id="aliasVisibilityGlobal" name="aliasVisibility" value="1">
+                            <label class="btn btn-outline-primary" for="aliasVisibilityGlobal">Global</label>
+                            <!-- Alias -->
+                            <input type="radio" class="btn-check" id="aliasVisibilityAlias" name="aliasVisibility" value="2">
+                            <label class="btn btn-outline-primary" for="aliasVisibilityAlias">Alias</label>
+                        </div>
+                    </div>
+                </form>
+            </div>
+
+            <div class="modal-footer">
+                <button type="submit" form="addAliasForm" class="btn btn-primary">
+                    <i class="bi bi-check2"></i>
+                </button>
+                <button type="button" class="btn btn-primary" data-bs-dismiss="modal">
+                    <i class="bi bi-x"></i>
+                </button>
+            </div>
+        </div>
+    </div>
+</div>
+
+<!-- Modal Restorebackup -->
+<div id="restoreModal" class="modal" role="dialog" aria-modal="true" aria-labelledby="restoreTitle">
+    <div class="modal-content addhost-modal">
+        <div class="addhost-header d-flex justify-content-between align-items-center">
+            <div class="d-flex align-items-center gap-2">
+                <span class="title-icon">💾</span>
+                <span id="restoreTitle" class="modal-title">Execute Restore</span>
+            </div>
+            <button type="button" class="btn-close" title="Close" aria-label="Close" data-action="closeRestoreModal"></button>
+        </div>
+
+        <div class="modal-body">
+            <label for="restoreBackupId" class="form-label">Backup ID</label>
+            <input type="text" id="restoreBackupId" class="form-control" placeholder="e.g., bk_20260317_200100" />
+            <small class="text-muted">Select the backup ID to restore.</small>
+        </div>
+
+        <div class="modal-footer modal-buttons">
+            <button type="button" class="btn btn-primary" data-action="startRestore"><span class="label">Start Restore</span></button>
+            <button type="button" class="btn btn-outline-primary" data-action="closeRestoreModal"><span class="label">Cancel</span></button>
+        </div>
+    </div>
+</div>
+
+<!-- Modal Health -->
+<div id="healthModal" class="modal" role="dialog" aria-modal="true" aria-labelledby="healthTitle">
+    <div class="modal-dialog modal-dialog-centered">
+        <div class="modal-content addhost-modal">
+            <div class="addhost-header d-flex justify-content-between align-items-center">
+                <div class="d-flex align-items-center gap-2">
+                    <span class="title-icon">❤️‍🩹</span>
+                    <span id="healthTitle" class="modal-title">Health Status</span>
+                </div>
+                <button type="button" class="btn-close" title="Close" aria-label="Close" data-action="closeHealthModal"></button>
+            </div>
+
+            <div class="modal-body">
+                <!-- Loading -->
+                <div id="healthLoading" class="d-flex align-items-center gap-2">
+                    <div class="spinner-border text-primary spinner-border-sm" role="status" aria-label="Loading"></div>
+                        <span class="text-muted">Loading status…</span>
+                    </div>
+
+                    <!-- Content -->
+                    <div id="healthContent" class="d-none">
+                        <ul class="list-group mb-3" id="healthSummary">
+                            <!-- Popolato via JS -->
+                        </ul>
+
+                        <div class="mb-3">
+                            <span class="badge rounded-pill" id="healthStatusBadge">—</span>
+                            <small class="text-muted ms-2" id="healthUpdatedAt"></small>
+                        </div>
+
+                        <!--<details>
+                            <summary class="mb-2">JSON completo</summary>
+                            <pre class="bg-light p-2 rounded small mb-0" id="healthRawJson" aria-label="Raw JSON"></pre>
+                        </details>-->
+                    </div>
+
+                <!-- Error -->
+                <div id="healthError" class="alert alert-danger d-none" role="alert" aria-live="assertive">
+                    Error fetching health status. Please try again later.
+                </div>
+            </div>
+
+            <div class="modal-footer modal-buttons">
+                <button type="button" class="btn btn-outline-primary" data-action="closeHealthModal">
+                    <span class="label">Close</span>
+                </button>
+            </div>
+        </div>
+    </div>
+</div>
\ No newline at end of file