From a91a6ce3ddc9a3d5de8335bdb91cbc674d84a6fc Mon Sep 17 00:00:00 2001 From: Giorgio Ravera Date: Mon, 26 Jan 2026 16:57:27 +0100 Subject: [PATCH] Added boostrap --- backend/routes/hosts.py | 5 - backend/routes/login.py | 5 - frontend/css/hosts.css | 51 ------ frontend/css/layout.css | 338 ++++++++++++++++++++++++++++++------- frontend/css/login.css | 116 ------------- frontend/css/variables.css | 3 + frontend/hosts.html | 261 ++++++++++++++++++---------- frontend/js/hosts.js | 336 ++++++++++++++++++++++++------------ frontend/js/login.js | 131 +++++++++++--- frontend/login.html | 94 ++++++++--- 10 files changed, 860 insertions(+), 480 deletions(-) delete mode 100644 frontend/css/hosts.css delete mode 100644 frontend/css/login.css diff --git a/backend/routes/hosts.py b/backend/routes/hosts.py index 4337955..3a68e70 100644 --- a/backend/routes/hosts.py +++ b/backend/routes/hosts.py @@ -27,11 +27,6 @@ router = APIRouter() def hosts(request: Request): return FileResponse(os.path.join(settings.FRONTEND_DIR, "hosts.html")) -# Serve hosts.css -@router.get("/css/hosts.css") -def css_hosts(): - return FileResponse(os.path.join(settings.FRONTEND_DIR, "css/hosts.css")) - # Serve hosts.js @router.get("/js/hosts.js") def css_hosts(): diff --git a/backend/routes/login.py b/backend/routes/login.py index 4a8789b..2b7a224 100644 --- a/backend/routes/login.py +++ b/backend/routes/login.py @@ -37,11 +37,6 @@ def check_rate_limit(ip: str): def login_page(request: Request): return FileResponse(os.path.join(settings.FRONTEND_DIR, "login.html")) -# Serve login.css -@router.get("/css/login.css") -def css_login(): - return FileResponse(os.path.join(settings.FRONTEND_DIR, "css/login.css")) - # Serve login.js @router.get("/js/login.js") def css_login(): diff --git a/frontend/css/hosts.css b/frontend/css/hosts.css deleted file mode 100644 index d9fb0a7..0000000 --- a/frontend/css/hosts.css +++ /dev/null @@ -1,51 +0,0 @@ -/* ================================ - Actions column - ================================ */ -td.actions { - white-space: nowrap; - text-align: left; -} - -.actions span { - cursor: pointer; - display: inline-flex; - align-items: center; - padding: 4px; - border-radius: 4px; - transition: background 0.2s ease; - margin-right: 8px; -} - -.actions span:hover { - background-color: #e0f0ff; -} - -/* ================================ - Search bar - ================================ */ -.search-bar { - width: 250px; - padding: 8px 12px; - border: 1px solid var(--border-light); - border-radius: 6px; - font-size: 14px; -} - -/* ================================ - Sort arrows - ================================ */ -.sort-arrow { - display: inline-block; - width: 1em; - text-align: center; - margin-left: .25rem; - color: var(--text-dark); -} - -.sort-arrow.asc::after { - content: "▲"; -} - -.sort-arrow.desc::after { - content: "▼"; -} diff --git a/frontend/css/layout.css b/frontend/css/layout.css index e3d0bd8..381ad66 100644 --- a/frontend/css/layout.css +++ b/frontend/css/layout.css @@ -12,6 +12,13 @@ body { margin: 20px; padding-top: 60px; /* space for fixed topbar */ background-color: var(--bg-light); + color: var(--text-dark); +} + +.body-login { + margin: 0; + padding-top: 0; + background: var(--bg-light); } /* ================================ @@ -20,9 +27,6 @@ body { .topbar { width: 100%; background: var(--bg-dark); - padding: 0; - display: flex; - align-items: center; border-bottom: 3px solid var(--accent); position: fixed; top: 0; @@ -33,7 +37,7 @@ body { .topbar-inner { width: 100%; margin: 0 auto; - padding: 14px 26px; + padding: 10px 26px; display: flex; justify-content: space-between; align-items: center; @@ -79,69 +83,211 @@ body { } /* ================================ - Buttons (pfSense style) + Login page ================================ */ -.btn-primary { - background-color: var(--accent); - color: white; - border: none; - padding: 6px 14px; - font-size: 0.95rem; +.login-wrapper { + min-height: 100vh; + min-height: 100svh; /* mobile moderni */ + display: flex; + align-items: center; + justify-content: center; + padding: 20px 0; + background: var(--bg-light); +} + +.login-box { + background: #fff; + width: 100%; + max-width: 320px; + padding: 24px 28px; + border-radius: 8px; + border-left: 4px solid var(--accent); + box-shadow: 0 4px 14px var(--shadow-soft); +} + +.login-box-header { + background: var(--bg-dark); + padding: 10px 14px; + margin: -24px -28px 16px -28px; /* stacca dal box e abbraccia i bordi */ + border-radius: 8px 8px 0 0; + display: flex; + align-items: center; + gap: 10px; +} + +.login-box-header span { + color: var(--text-light); + font-weight: 600; + font-size: 1rem; +} + +.login-box h2 { + margin: 0 0 16px; + font-size: 1.2rem; + color: var(--text-dark); +} + +.login-box .form-control { + background: var(--bg-light); +} + +/*GRGR*/ +.placeholder-italic::placeholder { + font-style: italic; +} + +/* ================================ + Buttons + ================================ */ +.btn { font-weight: 600; border-radius: 4px; - cursor: pointer; - transition: background 0.2s ease, filter 0.2s ease; box-shadow: 0 2px 4px rgba(0,0,0,0.15); + border: none; + padding: 6px 14px; + font-size: 0.95rem; + line-height: 1; +} + +.btn-primary { + background-color: var(--accent); + border-color: var(--accent); + color: #fff; } -.btn-primary:hover { +.btn-primary:hover, +.btn-primary:focus { background-color: var(--accent-hover); + border-color: var(--accent-hover); filter: brightness(0.96); } -.frame-row { - display: flex; - align-items: center; - gap: 12px; +.btn-outline-primary { + color: var(--accent); + border-color: var(--accent); + background-color: transparent; } -.frame-row h2 { - margin-right: auto; +.btn-outline-primary:hover, +.btn-outline-primary:focus { + color: #fff; + background-color: var(--accent); + border-color: var(--accent); +} + +.btn-primary.btn-login { + width: 100%; + padding: 8px 0; + box-shadow: none; +} + +.btn-primary.btn-login:hover, +.btn-primary.btn-login:focus, +.btn-primary.btn-login:active { + box-shadow: none; +} + +.btn-primary.btn-login:disabled { + opacity: .65; + box-shadow: none; + filter: none; } /* ================================ - Typography + Form controls ================================ */ -h1 { - margin-bottom: 20px; +.form-control, +.form-select { + border: 1px solid var(--border-light); + border-radius: 6px; + padding: 4px 8px; + font-size: 0.85rem; + height: auto; + line-height: 1.1; +} + +.form-label { + font-size: 0.80rem; /* più piccina */ + margin-bottom: 2px; /* Bootstrap usa 8px; lo riduciamo */ } /* ================================ - Table styling + Focus globale per controlli form ================================ */ -table { - border-collapse: collapse; - width: 100%; - background-color: white; +input.form-control:focus, +textarea.form-control:focus, +select.form-select:focus, +.form-control:focus, +.form-select:focus, +.form-check-input:focus { + border-color: var(--accent); + box-shadow: 0 0 0 1px var(--accent); + outline: none; +} + +.form-control.is-invalid:focus, +.form-select.is-invalid:focus { + box-shadow: none; + border-color: #dc3545; /* rosso Bootstrap */ +} + +.form-control.is-valid:focus, +.form-select.is-valid:focus { + box-shadow: none; + border-color: #198754; /* verde Bootstrap */ +} + +.form-check-input:focus { + border-color: var(--accent); + box-shadow: 0 0 0 1px var(--accent); + outline: none; +} + +/* ================================ + Icons + ================================ */ +.icon { + color: var(--icon-color); + display: inline-flex; + align-items: center; +} + +.icon:hover { + color: var(--icon-color-hover); +} + +.icon-static { + --icon-color-hover: var(--icon-color); +} + +.icon-action { + cursor: pointer; +} + +/* ================================ + Table + ================================ */ +.table { + background-color: #fff; box-shadow: 0 3px 6px rgba(0,0,0,0.18); + border-color: var(--border-light); } -th, td { - border: 1px solid var(--border-light); - padding: 10px 12px; - text-align: left; +.table th, +.table td { vertical-align: middle; + border-color: var(--border-light); } -th { +.table thead th { background-color: #eee; - font-weight: bold; + font-weight: 700; cursor: pointer; user-select: none; position: relative; } -th:hover::after { +.table thead th:hover::after { content: ""; position: absolute; left: 0; @@ -151,17 +297,48 @@ th:hover::after { background: var(--accent); } +/* Sort arrows */ .sort-arrow { - margin-left: 6px; - font-size: 12px; - opacity: 0.6; display: inline-block; - width: 12px; + width: 1em; text-align: center; + margin-left: .25rem; + color: var(--text-dark); +} + +.sort-arrow.asc::after { + content: "▲"; +} + +.sort-arrow.desc::after { + content: "▼"; } /* ================================ - Toast notification + Actions column + ================================ */ +td.actions { + white-space: nowrap; + text-align: left; +} + +.actions span { + cursor: pointer; + display: inline-flex; + align-items: center; + padding: 4px; + border-radius: 4px; + transition: background 0.2s ease; + margin-right: 8px; +} + +/* removed due to background with icons +.actions span:hover { + background-color: #e0f0ff; +}*/ + +/* ================================ + Toast ================================ */ .toast { position: fixed; @@ -232,31 +409,74 @@ th:hover::after { margin-top: 18px; } -.cancel-btn { - background: #ccc; - border: none; - padding: 6px 12px; - border-radius: 4px; - cursor: pointer; +/* ================================ + Modal "Add Host" +================================ */ +.addhost-modal { + border-left: 4px solid var(--accent); + border-radius: 8px; + box-shadow: 0 4px 12px var(--shadow-strong); } -.save-btn { - background: var(--accent); - color: white; - border: none; - padding: 6px 14px; - border-radius: 4px; - cursor: pointer; +.addhost-header { + background: var(--bg-dark); + color: var(--text-light); + border-bottom: none; /* più pulita */ + padding: 10px 14px; } -.save-btn:hover { - background: var(--accent-hover); +.addhost-header .modal-title { + font-weight: 600; + font-size: 1rem; /* compatto */ +} + +.addhost-header .btn-close { + filter: invert(1); /* icona chiara su bg scuro */ + opacity: .85; +} + +.addhost-header .btn-close:hover { + opacity: 1; +} + +/* Body & footer compatti come il resto dell'app */ +.addhost-modal .modal-body { + padding: 14px 16px; +} + +.addhost-modal .modal-footer { + border-top: none; + padding: 10px 14px 14px; +} + +/* Label & inputs: usano già i tuoi override globali (form-control compatto) */ +.addhost-modal .form-label { + font-size: 0.80rem; + margin-bottom: 2px; +} + +/* Title icon coerente con l'header */ +.addhost-header .title-icon { + font-size: 1.2em; + line-height: 1; + display: inline-flex; + transform: translateY(-1px); } /* ================================ - SVG icons + Responsive ================================ */ -svg { - display: block; - pointer-events: none; +@media (max-width: 640px) { + body { + padding-top: 48px; /* topbar più compatta su mobile */ + } + + /* Toolbar: su schermi molto stretti mostra solo le icone dei bottoni */ + .btn .label { + display: none; + } + + .btn .icon { + margin-right: 0; + } } diff --git a/frontend/css/login.css b/frontend/css/login.css deleted file mode 100644 index 03e66c2..0000000 --- a/frontend/css/login.css +++ /dev/null @@ -1,116 +0,0 @@ -/* ================================ - Body styles for login page - ================================ */ - -/* Variante per login */ -.body-login { - margin: 0; - padding-top: 0; -} - -/* ================================ - Login page wrapper - ================================ */ -.login-wrapper { - min-height: 100vh; - min-height: 100svh; - display: flex; - align-items: center; - justify-content: center; - background: var(--bg-light); - overflow-y: auto; - padding: 20px 0; -} - -/* ================================ - Login box - ================================ */ -.login-box { - background: white; - padding: 24px 28px; - border-radius: 8px; - width: 320px; - box-shadow: 0 4px 14px var(--shadow-soft); - border-left: 4px solid var(--accent); -} - -/* ================================ - Login box header - ================================ */ -.login-box-header { - background: var(--bg-dark); - padding: 10px 14px; - margin: -24px -28px 16px -28px; - border-radius: 8px 8px 0 0; - display: flex; - align-items: center; - gap: 10px; -} - -.login-box-header span { - color: var(--text-light); - font-weight: 600; - font-size: 1rem; -} - -/* ================================ - Logo / title - ================================ */ -.login-logo { - display: flex; - align-items: center; - gap: 8px; - margin-bottom: 12px; - color: var(--accent); - font-weight: 600; -} - -.login-box h2 { - margin: 0 0 16px; - font-size: 1.2rem; - color: var(--text-dark); -} - -/* ================================ - Labels & inputs - ================================ */ -.login-box label { - display: block; - font-size: 0.85rem; - margin-bottom: 4px; - color: var(--text-dark); -} - -.login-box input[type="text"], -.login-box input[type="password"] { - width: 100%; - padding: 7px 10px; - border-radius: 4px; - border: 1px solid var(--border-light); - font-size: 0.95rem; - margin-bottom: 12px; - background: var(--bg-light); -} - -/* ================================ - Login button - ================================ */ -.btn-primary.login-btn { - width: 100%; - padding: 8px 0; - box-shadow: none; -} - -.btn-primary.login-btn:hover { - box-shadow: none; -} - -/* ================================ - Error message - ================================ */ -.login-error { - margin-top: 10px; - font-size: 0.85rem; - color: #d9534f; - min-height: 16px; -} \ No newline at end of file diff --git a/frontend/css/variables.css b/frontend/css/variables.css index 6852e31..2b1d835 100644 --- a/frontend/css/variables.css +++ b/frontend/css/variables.css @@ -17,4 +17,7 @@ --shadow-soft: rgba(0, 0, 0, 0.12); --shadow-strong: rgba(0, 0, 0, 0.25); + + --icon-color: var(--accent); + --icon-color-hover: var(--accent-hover); } diff --git a/frontend/hosts.html b/frontend/hosts.html index aab6edc..deb7807 100644 --- a/frontend/hosts.html +++ b/frontend/hosts.html @@ -4,105 +4,184 @@ Network Manager + + + + + + + - - -
-
- -
- -
- -
-
-

🖧 Host List

- - - - - - - - -
-
- - - - - - - - - - - - - - -
Name IPv4 IPv6 MAC Note SSL Actions
- - -