05fc1a14f6
Header nav order was Dashboard, Players, Playlists, Ajutor, Admin, Logout, toggle. Ajutor now sits after Logout and before the theme toggle, so the navigation links stay grouped and the two "settings"-style controls (logout, help, theme) are together at the end.
634 lines
25 KiB
HTML
634 lines
25 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 %}DigiServer v2{% endblock %}</title>
|
|
<style>
|
|
/* Ensure emoji font support */
|
|
@supports (font-family: "Apple Color Emoji") {
|
|
body {
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji";
|
|
}
|
|
}
|
|
|
|
:root {
|
|
/* Light Mode Colors */
|
|
--primary-gradient: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
--primary-color: #667eea;
|
|
--primary-dark: #5568d3;
|
|
--secondary-color: #764ba2;
|
|
/* Colour for text links. Kept separate from --primary-color so the
|
|
primary colour can stay dark enough for button backgrounds while
|
|
links remain legible on the matching background. */
|
|
--link-color: #667eea;
|
|
--bg-color: #f5f7fa;
|
|
--card-bg: #ffffff;
|
|
--text-color: #2d3748;
|
|
--text-secondary: #718096;
|
|
--border-color: #e2e8f0;
|
|
--header-bg: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
--shadow: 0 4px 6px rgba(0, 0, 0, 0.07);
|
|
--shadow-lg: 0 10px 25px rgba(0, 0, 0, 0.1);
|
|
}
|
|
|
|
body.dark-mode {
|
|
/* Dark Mode Colors */
|
|
--primary-gradient: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
--primary-color: #7c3aed;
|
|
--primary-dark: #6d28d9;
|
|
--secondary-color: #8b5cf6;
|
|
/* Dark background needs a lighter link colour (#7c3aed is too dim
|
|
on a dark surface). */
|
|
--link-color: #a78bfa;
|
|
--bg-color: #1a202c;
|
|
--card-bg: #2d3748;
|
|
--text-color: #e2e8f0;
|
|
--text-secondary: #a0aec0;
|
|
--border-color: #4a5568;
|
|
--header-bg: linear-gradient(135deg, #7c3aed 0%, #8b5cf6 100%);
|
|
--shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
|
|
--shadow-lg: 0 10px 25px rgba(0, 0, 0, 0.4);
|
|
}
|
|
|
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
|
|
body {
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
|
line-height: 1.6;
|
|
color: var(--text-color);
|
|
background: var(--bg-color);
|
|
transition: background 0.3s, color 0.3s;
|
|
}
|
|
.container {
|
|
max-width: 1200px;
|
|
margin: 0 auto;
|
|
padding: 20px;
|
|
}
|
|
header {
|
|
background: var(--header-bg);
|
|
color: white;
|
|
padding: 1rem 0;
|
|
margin-bottom: 2rem;
|
|
box-shadow: var(--shadow);
|
|
}
|
|
header .container {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
flex-wrap: wrap;
|
|
gap: 1rem;
|
|
}
|
|
header h1 {
|
|
font-size: 1.5rem;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
}
|
|
nav {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
flex-wrap: wrap;
|
|
}
|
|
nav a {
|
|
color: white;
|
|
text-decoration: none;
|
|
padding: 0.5rem 1rem;
|
|
border-radius: 6px;
|
|
transition: all 0.3s;
|
|
font-weight: 500;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
}
|
|
nav a:hover {
|
|
background: rgba(255,255,255,0.2);
|
|
transform: translateY(-2px);
|
|
}
|
|
nav a img {
|
|
width: 18px;
|
|
height: 18px;
|
|
filter: brightness(0) invert(1);
|
|
}
|
|
|
|
/* Mobile Responsive */
|
|
@media (max-width: 768px) {
|
|
header .container {
|
|
flex-direction: column;
|
|
align-items: stretch;
|
|
padding: 1rem;
|
|
}
|
|
|
|
header h1 {
|
|
font-size: 1.25rem;
|
|
justify-content: center;
|
|
text-align: center;
|
|
}
|
|
|
|
nav {
|
|
flex-direction: column;
|
|
gap: 0.5rem;
|
|
width: 100%;
|
|
}
|
|
|
|
nav a {
|
|
justify-content: center;
|
|
width: 100%;
|
|
padding: 0.75rem 1rem;
|
|
}
|
|
|
|
.dark-mode-toggle {
|
|
margin-left: 0;
|
|
width: 100%;
|
|
padding: 0.75rem;
|
|
}
|
|
|
|
.container {
|
|
padding: 15px;
|
|
}
|
|
|
|
.card {
|
|
padding: 1rem;
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
.card-header {
|
|
padding: 15px;
|
|
margin: -1rem -1rem 1rem -1rem;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 480px) {
|
|
header h1 {
|
|
font-size: 1.1rem;
|
|
}
|
|
|
|
nav a {
|
|
font-size: 0.9rem;
|
|
padding: 0.6rem 0.8rem;
|
|
}
|
|
|
|
nav a img {
|
|
width: 16px;
|
|
height: 16px;
|
|
}
|
|
}
|
|
|
|
.dark-mode-toggle {
|
|
background: rgba(255,255,255,0.2);
|
|
border: 2px solid rgba(255,255,255,0.3);
|
|
color: white;
|
|
cursor: pointer;
|
|
padding: 0.5rem;
|
|
border-radius: 6px;
|
|
transition: all 0.3s;
|
|
margin-left: 0.5rem;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
.dark-mode-toggle:hover {
|
|
background: rgba(255,255,255,0.3);
|
|
transform: scale(1.1);
|
|
}
|
|
.dark-mode-toggle img {
|
|
width: 20px;
|
|
height: 20px;
|
|
filter: brightness(0) invert(1);
|
|
}
|
|
|
|
/* Emoji fallback for systems without emoji fonts */
|
|
.emoji-fallback::before {
|
|
content: attr(data-emoji);
|
|
font-family: 'Apple Color Emoji', 'Segoe UI Emoji', 'Noto Color Emoji', sans-serif;
|
|
}
|
|
.alert {
|
|
padding: 1rem;
|
|
margin-bottom: 1rem;
|
|
border-radius: 8px;
|
|
border-left: 4px solid;
|
|
transition: all 0.3s;
|
|
}
|
|
.alert-success {
|
|
background: #d4edda;
|
|
border-color: #28a745;
|
|
color: #155724;
|
|
}
|
|
body.dark-mode .alert-success {
|
|
background: rgba(40, 167, 69, 0.2);
|
|
border-color: #28a745;
|
|
color: #7ce3a3;
|
|
}
|
|
.alert-danger {
|
|
background: #f8d7da;
|
|
border-color: #dc3545;
|
|
color: #721c24;
|
|
}
|
|
body.dark-mode .alert-danger {
|
|
background: rgba(220, 53, 69, 0.2);
|
|
border-color: #dc3545;
|
|
color: #f88f9a;
|
|
}
|
|
.alert-warning {
|
|
background: #fff3cd;
|
|
border-color: #ffc107;
|
|
color: #856404;
|
|
}
|
|
body.dark-mode .alert-warning {
|
|
background: rgba(255, 193, 7, 0.2);
|
|
border-color: #ffc107;
|
|
color: #ffd454;
|
|
}
|
|
.alert-info {
|
|
background: #d1ecf1;
|
|
border-color: #17a2b8;
|
|
color: #0c5460;
|
|
}
|
|
body.dark-mode .alert-info {
|
|
background: rgba(23, 162, 184, 0.2);
|
|
border-color: #17a2b8;
|
|
color: #7dd3e0;
|
|
}
|
|
.card {
|
|
background: var(--card-bg);
|
|
border-radius: 12px;
|
|
padding: 1.5rem;
|
|
margin-bottom: 1.5rem;
|
|
box-shadow: var(--shadow);
|
|
transition: all 0.3s;
|
|
border: 1px solid var(--border-color);
|
|
}
|
|
.card:hover {
|
|
box-shadow: var(--shadow-lg);
|
|
transform: translateY(-2px);
|
|
}
|
|
.card h2 {
|
|
margin-bottom: 1rem;
|
|
color: var(--text-color);
|
|
font-weight: 600;
|
|
}
|
|
.card h3 {
|
|
color: var(--text-color);
|
|
}
|
|
|
|
/* Card with gradient header */
|
|
.card-header {
|
|
background: var(--primary-gradient);
|
|
color: white;
|
|
padding: 20px;
|
|
border-radius: 12px 12px 0 0;
|
|
margin: -1.5rem -1.5rem 1.5rem -1.5rem;
|
|
}
|
|
.card-header h2 {
|
|
margin: 0;
|
|
color: white;
|
|
}
|
|
|
|
.btn {
|
|
display: inline-block;
|
|
padding: 0.5rem 1rem;
|
|
background: var(--primary-color);
|
|
color: white;
|
|
text-decoration: none;
|
|
border-radius: 6px;
|
|
border: none;
|
|
cursor: pointer;
|
|
transition: all 0.3s;
|
|
font-weight: 500;
|
|
}
|
|
.btn:hover {
|
|
background: var(--primary-dark);
|
|
transform: translateY(-2px);
|
|
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
|
|
}
|
|
.btn-primary {
|
|
background: var(--primary-gradient);
|
|
}
|
|
.btn-primary:hover {
|
|
transform: translateY(-2px);
|
|
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.4);
|
|
}
|
|
.btn-danger { background: #e74c3c; }
|
|
.btn-danger:hover {
|
|
background: #c0392b;
|
|
box-shadow: 0 4px 12px rgba(231, 76, 60, 0.4);
|
|
}
|
|
.btn-success { background: #27ae60; }
|
|
.btn-success:hover {
|
|
background: #229954;
|
|
box-shadow: 0 4px 12px rgba(39, 174, 96, 0.4);
|
|
}
|
|
.btn-info {
|
|
background: #3498db;
|
|
}
|
|
.btn-info:hover {
|
|
background: #2980b9;
|
|
box-shadow: 0 4px 12px rgba(52, 152, 219, 0.4);
|
|
}
|
|
.btn-sm {
|
|
padding: 0.375rem 0.75rem;
|
|
font-size: 0.875rem;
|
|
}
|
|
|
|
/* Form Inputs */
|
|
input, textarea, select {
|
|
background: var(--card-bg);
|
|
color: var(--text-color);
|
|
border: 1px solid var(--border-color);
|
|
transition: all 0.3s;
|
|
}
|
|
input:focus, textarea:focus, select:focus {
|
|
border-color: var(--primary-color);
|
|
outline: none;
|
|
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
|
|
}
|
|
body.dark-mode input:focus,
|
|
body.dark-mode textarea:focus,
|
|
body.dark-mode select:focus {
|
|
box-shadow: 0 0 0 3px rgba(124, 58, 237, 0.3);
|
|
}
|
|
|
|
/* Tables */
|
|
table {
|
|
background: var(--card-bg);
|
|
color: var(--text-color);
|
|
}
|
|
th {
|
|
background: var(--bg-color);
|
|
color: var(--text-color);
|
|
}
|
|
tr {
|
|
border-bottom: 1px solid var(--border-color);
|
|
}
|
|
|
|
/* Code blocks */
|
|
code, pre {
|
|
background: var(--bg-color);
|
|
color: var(--text-color);
|
|
border: 1px solid var(--border-color);
|
|
}
|
|
|
|
footer {
|
|
margin-top: 2rem;
|
|
padding: 1rem 0;
|
|
text-align: center;
|
|
color: var(--text-secondary);
|
|
font-size: 0.9rem;
|
|
}
|
|
|
|
/* ================================================================
|
|
Dark-mode fixes for INLINE colours
|
|
----------------------------------------------------------------
|
|
A recurring pattern across the templates is to set colours with
|
|
inline style="..." attributes (a few JS blocks build nodes the
|
|
same way). An inline declaration outranks every normal rule --
|
|
including the body.dark-mode rules above -- so those literals keep
|
|
their LIGHT value in dark mode. The text, which inherits the (now
|
|
light) --text-color, then ends up light-on-light: unreadable.
|
|
|
|
Inline styles can only be beaten with !important, so the light
|
|
literals are mapped to the theme variables here, centrally, with
|
|
the property scoped so a colour used for two things (e.g. #1a202c
|
|
is both a dark surface and dark text) is only changed where it is
|
|
wrong. This fixes every template at once -- including any future
|
|
page that repeats the pattern -- instead of patching each file.
|
|
|
|
Everything is scoped to body.dark-mode, so the LIGHT theme is
|
|
completely untouched.
|
|
|
|
Ordering matters: selectors have equal specificity, so later rules
|
|
win. The bare "#fff" rule is therefore placed BEFORE the "#fff3cd"
|
|
/"#fff8e1" ones, because "#fff" is a string prefix of them.
|
|
================================================================ */
|
|
|
|
/* --- White / near-white surfaces -> dark card --------------------- */
|
|
body.dark-mode [style*="background: white"], body.dark-mode [style*="background-color: white"],
|
|
body.dark-mode [style*="background: #fff"], body.dark-mode [style*="background-color: #fff"],
|
|
body.dark-mode [style*="background: #ffffff"], body.dark-mode [style*="background-color: #ffffff"],
|
|
body.dark-mode [style*="background: #fefefe"], body.dark-mode [style*="background-color: #fefefe"],
|
|
body.dark-mode [style*="background: #f5f7fa"], body.dark-mode [style*="background-color: #f5f7fa"],
|
|
body.dark-mode [style*="background: #e9ecef"], body.dark-mode [style*="background-color: #e9ecef"],
|
|
body.dark-mode [style*="background: #e0e0e0"], body.dark-mode [style*="background-color: #e0e0e0"],
|
|
body.dark-mode [style*="background: #f0f2ff"], body.dark-mode [style*="background-color: #f0f2ff"],
|
|
body.dark-mode [style*="background: #e8ebff"], body.dark-mode [style*="background-color: #e8ebff"],
|
|
body.dark-mode [style*="background: #e7e9ff"], body.dark-mode [style*="background-color: #e7e9ff"],
|
|
body.dark-mode [style*="background: #ede9fe"], body.dark-mode [style*="background-color: #ede9fe"] {
|
|
background: var(--card-bg) !important;
|
|
}
|
|
|
|
/* --- Light grey panels -> dark page background -------------------- */
|
|
body.dark-mode [style*="background: #f8f9fa"], body.dark-mode [style*="background-color: #f8f9fa"],
|
|
body.dark-mode [style*="background: #f0f0f0"], body.dark-mode [style*="background-color: #f0f0f0"],
|
|
body.dark-mode [style*="background: #f5f5f5"], body.dark-mode [style*="background-color: #f5f5f5"],
|
|
body.dark-mode [style*="background: #f4f4f4"], body.dark-mode [style*="background-color: #f4f4f4"],
|
|
body.dark-mode [style*="background: #f8fafc"], body.dark-mode [style*="background-color: #f8fafc"] {
|
|
background: var(--bg-color) !important;
|
|
}
|
|
|
|
/* --- Semantic pastel backgrounds -> dark equivalents -------------- */
|
|
/* info / blue */
|
|
body.dark-mode [style*="background: #d1ecf1"], body.dark-mode [style*="background-color: #d1ecf1"],
|
|
body.dark-mode [style*="background: #cce5ff"], body.dark-mode [style*="background-color: #cce5ff"],
|
|
body.dark-mode [style*="background: #e7f3ff"], body.dark-mode [style*="background-color: #e7f3ff"],
|
|
body.dark-mode [style*="background: #f0f7ff"], body.dark-mode [style*="background-color: #f0f7ff"] {
|
|
background: #1e3a5f !important;
|
|
}
|
|
/* success / green */
|
|
body.dark-mode [style*="background: #d4edda"], body.dark-mode [style*="background-color: #d4edda"],
|
|
body.dark-mode [style*="background: #d1f0e0"], body.dark-mode [style*="background-color: #d1f0e0"],
|
|
body.dark-mode [style*="background: #c6f6d5"], body.dark-mode [style*="background-color: #c6f6d5"] {
|
|
background: #1a4d2e !important;
|
|
}
|
|
/* warning / amber (must stay AFTER the "#fff" rule above) */
|
|
body.dark-mode [style*="background: #fff3cd"], body.dark-mode [style*="background-color: #fff3cd"],
|
|
body.dark-mode [style*="background: #fff8e1"], body.dark-mode [style*="background-color: #fff8e1"],
|
|
body.dark-mode [style*="background: #ffeaa7"], body.dark-mode [style*="background-color: #ffeaa7"],
|
|
body.dark-mode [style*="background: #fef3c7"], body.dark-mode [style*="background-color: #fef3c7"],
|
|
body.dark-mode [style*="background: #feebc8"], body.dark-mode [style*="background-color: #feebc8"] {
|
|
background: #4a3800 !important;
|
|
}
|
|
/* danger / red */
|
|
body.dark-mode [style*="background: #f8d7da"], body.dark-mode [style*="background-color: #f8d7da"],
|
|
body.dark-mode [style*="background: #fed7d7"], body.dark-mode [style*="background-color: #fed7d7"] {
|
|
background: #4a1a1a !important;
|
|
}
|
|
/* mid-grey chips / knobs */
|
|
body.dark-mode [style*="background: #ccc"], body.dark-mode [style*="background-color: #ccc"],
|
|
body.dark-mode [style*="background: #6c757d"], body.dark-mode [style*="background-color: #6c757d"] {
|
|
background: #4a5568 !important;
|
|
}
|
|
|
|
/* --- Dark text -> light text -------------------------------------- */
|
|
body.dark-mode [style*="color: black"] {
|
|
color: var(--text-color) !important;
|
|
}
|
|
body.dark-mode [style*="color: #6c757d"], body.dark-mode [style*="color:#6c757d"],
|
|
body.dark-mode [style*="color: #666"], body.dark-mode [style*="color: #888"],
|
|
body.dark-mode [style*="color: #999"], body.dark-mode [style*="color: #aaa"],
|
|
body.dark-mode [style*="color: #495057"], body.dark-mode [style*="color: #718096"],
|
|
body.dark-mode [style*="color: #7f8c8d"], body.dark-mode [style*="color: #5a6a78"],
|
|
body.dark-mode [style*="color: #4a5568"] {
|
|
color: var(--text-secondary) !important;
|
|
}
|
|
body.dark-mode [style*="color: #555"], body.dark-mode [style*="color: #475569"],
|
|
body.dark-mode [style*="color: #64748b"] {
|
|
color: #cbd5e1 !important;
|
|
}
|
|
body.dark-mode [style*="color: #333"], body.dark-mode [style*="color: #2c3e50"],
|
|
body.dark-mode [style*="color: #000"], body.dark-mode [style*="color: #1a202c"],
|
|
body.dark-mode [style*="color: #2d3748"] {
|
|
color: var(--text-color) !important;
|
|
}
|
|
/* links / info blue */
|
|
body.dark-mode [style*="color: #0066cc"], body.dark-mode [style*="color: #007bff"],
|
|
body.dark-mode [style*="color: #0056b3"], body.dark-mode [style*="color: #0c5460"],
|
|
body.dark-mode [style*="color: #004085"], body.dark-mode [style*="color: #3498db"] {
|
|
color: #90cdf4 !important;
|
|
}
|
|
/* success text */
|
|
body.dark-mode [style*="color: #155724"], body.dark-mode [style*="color: #156b2e"],
|
|
body.dark-mode [style*="color: #28a745"], body.dark-mode [style*="color: #27ae60"],
|
|
body.dark-mode [style*="color: #2f855a"] {
|
|
color: #86efac !important;
|
|
}
|
|
/* warning text */
|
|
body.dark-mode [style*="color: #856404"], body.dark-mode [style*="color: #92400e"],
|
|
body.dark-mode [style*="color: #c05621"], body.dark-mode [style*="color: #e67e22"] {
|
|
color: #fbbf24 !important;
|
|
}
|
|
/* danger text */
|
|
body.dark-mode [style*="color: #721c24"], body.dark-mode [style*="color: #dc3545"],
|
|
body.dark-mode [style*="color: #e74c3c"], body.dark-mode [style*="color: #e53e3e"],
|
|
body.dark-mode [style*="color:#e53e3e"], body.dark-mode [style*="color: #c53030"],
|
|
body.dark-mode [style*="color: #b91c1c"] {
|
|
color: #fca5a5 !important;
|
|
}
|
|
/* purple accents */
|
|
body.dark-mode [style*="color: #5b21b6"] {
|
|
color: #a78bfa !important;
|
|
}
|
|
|
|
/* --- Light borders -> dark borders ------------------------------- */
|
|
body.dark-mode [style*="border-top-color: white"] {
|
|
border-top-color: var(--border-color) !important;
|
|
}
|
|
body.dark-mode [style*="#e2e8f0"], body.dark-mode [style*="#dee2e6"],
|
|
body.dark-mode [style*="#ddd"], body.dark-mode [style*="#ccc"],
|
|
body.dark-mode [style*="#ced4da"], body.dark-mode [style*="#e0e0e0"],
|
|
body.dark-mode [style*="#eee"], body.dark-mode [style*="#e9ecef"],
|
|
body.dark-mode [style*="#f0f0f0"], body.dark-mode [style*="#f0f2ff"],
|
|
body.dark-mode [style*="#888"], body.dark-mode [style*="#999"] {
|
|
border-color: #4a5568 !important;
|
|
}
|
|
body.dark-mode [style*="#c3e6cb"], body.dark-mode [style*="#d1f0e0"] {
|
|
border-color: #2f855a !important;
|
|
}
|
|
body.dark-mode [style*="#f5c6cb"] {
|
|
border-color: #c53030 !important;
|
|
}
|
|
body.dark-mode [style*="#bee5eb"], body.dark-mode [style*="#cce5ff"] {
|
|
border-color: #2c5282 !important;
|
|
}
|
|
|
|
/* --- "Back" links (class used across the admin pages) ------------- */
|
|
body.dark-mode .back-link {
|
|
color: #90cdf4 !important;
|
|
}
|
|
</style>
|
|
{% block extra_css %}{% endblock %}
|
|
</head>
|
|
<body>
|
|
<header>
|
|
<div class="container">
|
|
<h1>
|
|
<img src="{{ url_for('static', filename='uploads/header_logo.png') }}?v={{ logo_version }}" alt="DigiServer" style="height: 32px; width: auto; margin-right: 8px;" onerror="this.style.display='none';" onload="this.style.display='inline';">
|
|
DigiServer
|
|
</h1>
|
|
<nav>
|
|
{% if current_user.is_authenticated %}
|
|
<a href="{{ url_for('main.dashboard') }}">
|
|
<img src="{{ url_for('static', filename='icons/home.svg') }}" alt="">
|
|
Dashboard
|
|
</a>
|
|
<a href="{{ url_for('players.list') }}">
|
|
<img src="{{ url_for('static', filename='icons/monitor.svg') }}" alt="">
|
|
Players
|
|
</a>
|
|
<a href="{{ url_for('content.content_list') }}">
|
|
<img src="{{ url_for('static', filename='icons/playlist.svg') }}" alt="">
|
|
Playlists
|
|
</a>
|
|
<a href="{{ url_for('admin.admin_panel') }}">Admin</a>
|
|
<a href="{{ url_for('auth.logout') }}">Logout ({{ current_user.username }})</a>
|
|
<a href="{{ url_for('main.help_page') }}">
|
|
<img src="{{ url_for('static', filename='icons/help.svg') }}" alt="" onerror="this.style.display='none';">
|
|
Ajutor
|
|
</a>
|
|
<button class="dark-mode-toggle" onclick="toggleDarkMode()" title="Toggle Dark Mode">
|
|
<img id="theme-icon" src="{{ url_for('static', filename='icons/moon.svg') }}" alt="Toggle theme">
|
|
</button>
|
|
{% else %}
|
|
<a href="{{ url_for('auth.login') }}">Login</a>
|
|
<a href="{{ url_for('auth.register') }}">Register</a>
|
|
{% endif %}
|
|
</nav>
|
|
</div>
|
|
</header>
|
|
|
|
<div class="container">
|
|
{% with messages = get_flashed_messages(with_categories=true) %}
|
|
{% if messages %}
|
|
{% for category, message in messages %}
|
|
<div class="alert alert-{{ category }}">
|
|
{{ message }}
|
|
</div>
|
|
{% endfor %}
|
|
{% endif %}
|
|
{% endwith %}
|
|
|
|
{% block content %}{% endblock %}
|
|
</div>
|
|
|
|
<footer>
|
|
<div class="container">
|
|
DigiServer v2.0.0-alpha | Blueprint Architecture | {{ server_version if server_version else 'Development' }}
|
|
</div>
|
|
</footer>
|
|
|
|
<script>
|
|
// Dark Mode Toggle
|
|
function toggleDarkMode() {
|
|
const body = document.body;
|
|
const themeIcon = document.getElementById('theme-icon');
|
|
|
|
body.classList.toggle('dark-mode');
|
|
|
|
// Update icon
|
|
if (body.classList.contains('dark-mode')) {
|
|
themeIcon.src = "{{ url_for('static', filename='icons/sun.svg') }}";
|
|
localStorage.setItem('darkMode', 'enabled');
|
|
} else {
|
|
themeIcon.src = "{{ url_for('static', filename='icons/moon.svg') }}";
|
|
localStorage.setItem('darkMode', 'disabled');
|
|
}
|
|
}
|
|
|
|
// Load saved theme preference
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
const darkMode = localStorage.getItem('darkMode');
|
|
const themeIcon = document.getElementById('theme-icon');
|
|
|
|
if (darkMode === 'enabled') {
|
|
document.body.classList.add('dark-mode');
|
|
if (themeIcon) {
|
|
themeIcon.src = "{{ url_for('static', filename='icons/sun.svg') }}";
|
|
}
|
|
}
|
|
});
|
|
</script>
|
|
|
|
{% block extra_js %}{% endblock %}
|
|
</body>
|
|
</html>
|