Files
RadMac/app/templates/base.html
2025-04-01 10:12:38 -04:00

240 lines
5.4 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>{% block title %}FreeRADIUS Manager{% endblock %}</title>
<style>
:root {
--bg: #ffffff;
--fg: #000000;
--cell-bg: #f5f5f5;
--th-bg: #e0e0e0;
}
[data-theme="dark"] {
--bg: #121212;
--fg: #e0e0e0;
--cell-bg: #1e1e1e;
--th-bg: #2c2c2c;
}
body {
background-color: var(--bg);
color: var(--fg);
font-family: sans-serif;
margin: 0;
padding: 0;
}
nav {
background-color: var(--th-bg);
padding: 10px;
display: flex;
align-items: center;
}
nav a {
margin-right: 10px;
text-decoration: none;
padding: 5px 10px;
border: 1px solid #ccc;
border-radius: 5px;
color: var(--fg);
}
nav a.active {
background-color: var(--cell-bg);
}
.content {
padding: 20px;
}
#theme-toggle {
margin-left: auto;
cursor: pointer;
padding: 5px 10px;
border-radius: 5px;
border: 1px solid #ccc;
background-color: var(--cell-bg);
color: var(--fg);
}
.styled-table {
border-collapse: collapse;
width: 100%;
margin-bottom: 2rem;
background-color: var(--bg);
color: var(--fg);
transition: all 0.3s ease;
}
.styled-table th,
.styled-table td {
border: 1px solid #444;
padding: 8px;
text-align: left;
}
.styled-table input,
.styled-table select {
background-color: var(--cell-bg);
color: var(--fg);
border: 1px solid #666;
padding: 4px;
border-radius: 4px;
transition: background-color 0.3s;
}
.styled-table input:focus,
.styled-table select:focus {
background-color: #555;
outline: none;
}
.styled-table thead {
background-color: var(--th-bg);
position: sticky;
top: 0;
z-index: 1;
}
.styled-table tbody tr:hover {
background-color: rgba(255, 255, 255, 0.05);
}
.icon-button {
background-color: var(--cell-bg);
color: var(--fg);
border: 1px solid #666;
border-radius: 4px;
padding: 4px 8px;
margin: 2px;
cursor: pointer;
font-size: 1rem;
transition: background-color 0.2s, transform 0.2s;
}
.icon-button:hover {
background-color: #555;
transform: scale(1.05);
}
.icon-button.pulse {
animation: pulse 2s infinite;
}
@keyframes pulse {
0% { box-shadow: 0 0 0 0 rgba(50, 205, 50, 0.4); }
70% { box-shadow: 0 0 0 10px rgba(50, 205, 50, 0); }
100% { box-shadow: 0 0 0 0 rgba(50, 205, 50, 0); }
}
.page-title {
margin-bottom: 1rem;
color: var(--fg);
}
.merged-cell {
border: none;
}
.fade-in {
animation: fadeIn 0.5s ease-in;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(-10px); }
to { opacity: 1; transform: translateY(0); }
}
#toast-container {
position: fixed;
bottom: 20px;
right: 20px;
z-index: 1000;
}
.toast {
background-color: #444;
color: #fff;
padding: 10px 16px;
margin-top: 10px;
border-radius: 4px;
box-shadow: 0 0 10px rgba(0,0,0,0.2);
opacity: 0.95;
animation: fadein 0.5s, fadeout 0.5s 2.5s;
}
@keyframes fadein {
from { opacity: 0; right: 0; }
to { opacity: 0.95; }
}
@keyframes fadeout {
from { opacity: 0.95; }
to { opacity: 0; }
}
</style>
</head>
<body>
<nav>
<a href="/" {% if request.path == '/' %}class="active"{% endif %}>Home</a>
<a href="/user/user_list" {% if request.path.startswith('/user') %}class="active"{% endif %}>User List</a>
<a href="/group/groups" {% if request.path.startswith('/group') %}class="active"{% endif %}>Group List</a>
<a href="/stats" {% if request.path.startswith('/stats') %}class="active"{% endif %}>Stats</a>
<button id="theme-toggle" onclick="toggleTheme()">🌓</button>
</nav>
<div class="content">
{% block content %}{% endblock %}
</div>
<div id="toast-container"></div>
<script>
function showToast(message) {
const toast = document.createElement('div');
toast.textContent = message;
toast.style.cssText = `
position: fixed;
bottom: 1rem;
left: 50%;
transform: translateX(-50%);
background: var(--cell-bg, #333);
color: var(--fg, #fff);
padding: 10px 20px;
border-radius: 6px;
box-shadow: 0 2px 10px rgba(0,0,0,0.2);
z-index: 9999;
font-weight: bold;
`;
document.body.appendChild(toast);
setTimeout(() => toast.remove(), 3000);
}
function toggleTheme() {
const current = document.body.dataset.theme || 'light';
const next = current === 'light' ? 'dark' : 'light';
document.body.dataset.theme = next;
localStorage.setItem('theme', next);
}
window.onload = () => {
document.body.dataset.theme = localStorage.getItem('theme') || 'light';
};
</script>
<script>
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
showToast("{{ message }}");
{% endfor %}
{% endif %}
{% endwith %}
</script>
</body>
</html>