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"))
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"])
</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>
</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>
</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>
</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>
// 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';
// -----------------------------
// -----------------------------
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();
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
// -----------------------------
// 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';
// -----------------------------
// -----------------------------
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();
// 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';
// -----------------------------
// -----------------------------
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();
// -------------------------------------------------------
// IMPORT
// -------------------------------------------------------
-import { showToast } from './common.js';
+import { loadModals, showToast } from './common.js';
import { apiCheck, reloadDNS, reloadDHCP, doBackup, doRestore, checkHealth } from './services.js';
// -------------------------------------------------------
}
};
+// -----------------------------
+// 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
// -------------------------------------------------------
}
});
-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();
});
// 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';
// -----------------------------
// -----------------------------
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();
-document.addEventListener('DOMContentLoaded', () => {
+// -----------------------------
+// DOMContentLoaded: initialize everything
+// -----------------------------
+document.addEventListener("DOMContentLoaded", () => {
const form = document.getElementById('loginForm');
if (!form) return;
}
// -----------------------------
-// DOM Ready
+// DOMContentLoaded: initialize everything
// -----------------------------
document.addEventListener("DOMContentLoaded", () => {
const logoutBtn = document.getElementById("logoutBtn");
</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>
--- /dev/null
+<!-- 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