Fix dark-theme colours on player delete modal and maintenance page
Both bugs had the same cause: light colours were set with inline style attributes, which outrank the theme rules in base.html and so survived the dark theme. Text that inherits --text-color then became light-on-light. * manage_player.html: the delete confirmation modal used an inline background-color of #fefefe with the body's dark-mode text colour, making the message unreadable in dark mode. Rebuilt it with .modal-* classes driven by the base.html CSS variables (and dark-mode variants for the title, warning and player name). * admin/maintenance.html: the "Automatic reset interval" panel, table headers and JS-rendered rows/tables hardcoded #f8f9fa/#e2e8f0/#dee2e6. Switched them to --bg-color / --card-bg / --border-color / --text-secondary and added a themed .maint-badge-pending. Verified with computed styles in both themes; light mode is unchanged.
This commit is contained in:
@@ -3,6 +3,41 @@
|
||||
{% block title %}Maintenance - Admin - DigiServer v2{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<style>
|
||||
/* Theme-aware building blocks for the maintenance console. Using the
|
||||
variables defined in base.html keeps every panel readable in both the
|
||||
light and dark themes (inline colours would override the theme). */
|
||||
.maint-panel {
|
||||
background: var(--bg-color);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.maint-thead {
|
||||
background: var(--card-bg);
|
||||
}
|
||||
|
||||
.maint-badge-pending {
|
||||
display: inline-block;
|
||||
padding: 3px 8px;
|
||||
border-radius: 999px;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
background: #fef3c7;
|
||||
color: #92400e;
|
||||
}
|
||||
|
||||
body.dark-mode .maint-badge-pending {
|
||||
background: #4a3800;
|
||||
color: #fbbf24;
|
||||
}
|
||||
|
||||
/* Muted description text should stay readable on the dark card. */
|
||||
body.dark-mode .card > p[style*="color: #6c757d"] {
|
||||
color: var(--text-secondary) !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div style="max-width: 1200px; margin: 0 auto;">
|
||||
<div style="margin-bottom: 30px; display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 15px;">
|
||||
<div>
|
||||
@@ -64,16 +99,17 @@
|
||||
</p>
|
||||
|
||||
<form method="POST" action="{{ url_for('admin.maintenance_set_interval') }}"
|
||||
style="display: flex; align-items: flex-end; gap: 12px; flex-wrap: wrap; margin-bottom: 25px; padding: 15px; background: #f8f9fa; border-radius: 8px; border: 1px solid #e2e8f0;">
|
||||
class="maint-panel"
|
||||
style="display: flex; align-items: flex-end; gap: 12px; flex-wrap: wrap; margin-bottom: 25px; padding: 15px;">
|
||||
<div>
|
||||
<label for="interval_days" style="display: block; font-weight: 600; margin-bottom: 6px;">
|
||||
Automatic reset interval
|
||||
</label>
|
||||
<input type="number" id="interval_days" name="interval_days" min="0" step="1"
|
||||
value="{{ interval_days }}"
|
||||
style="padding: 10px; border: 1px solid #ccc; border-radius: 6px; width: 140px;">
|
||||
style="padding: 10px; border: 1px solid var(--border-color); border-radius: 6px; width: 140px;">
|
||||
</div>
|
||||
<div style="flex: 1; min-width: 220px; color: #6c757d; font-size: 0.9rem;">
|
||||
<div style="flex: 1; min-width: 220px; color: var(--text-secondary); font-size: 0.9rem;">
|
||||
Days before a token expires automatically. Use <strong>0</strong> to disable.
|
||||
{% if auth_config %}
|
||||
<br>Last changed by <strong>{{ auth_config.updated_by or 'unknown' }}</strong>
|
||||
@@ -95,49 +131,47 @@
|
||||
|
||||
<div style="max-height: 460px; overflow-y: auto;">
|
||||
<table class="table" style="width: 100%; border-collapse: collapse;">
|
||||
<thead style="position: sticky; top: 0; background: #f8f9fa; z-index: 1;">
|
||||
<thead class="maint-thead" style="position: sticky; top: 0; z-index: 1;">
|
||||
<tr>
|
||||
<th style="padding: 10px; text-align: left; border-bottom: 2px solid #dee2e6;">Player</th>
|
||||
<th style="padding: 10px; text-align: left; border-bottom: 2px solid #dee2e6;">Status</th>
|
||||
<th style="padding: 10px; text-align: left; border-bottom: 2px solid #dee2e6;">Token Age</th>
|
||||
<th style="padding: 10px; text-align: left; border-bottom: 2px solid #dee2e6;">Re-auth</th>
|
||||
<th style="padding: 10px; text-align: right; border-bottom: 2px solid #dee2e6;">Actions</th>
|
||||
<th style="padding: 10px; text-align: left; border-bottom: 2px solid var(--border-color);">Player</th>
|
||||
<th style="padding: 10px; text-align: left; border-bottom: 2px solid var(--border-color);">Status</th>
|
||||
<th style="padding: 10px; text-align: left; border-bottom: 2px solid var(--border-color);">Token Age</th>
|
||||
<th style="padding: 10px; text-align: left; border-bottom: 2px solid var(--border-color);">Re-auth</th>
|
||||
<th style="padding: 10px; text-align: right; border-bottom: 2px solid var(--border-color);">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for player in players %}
|
||||
{% set age = player.auth_token_age_days() %}
|
||||
<tr style="border-bottom: 1px solid #dee2e6;">
|
||||
<tr style="border-bottom: 1px solid var(--border-color);">
|
||||
<td style="padding: 10px;">
|
||||
<strong>{{ player.name }}</strong>
|
||||
<div style="font-size: 12px; color: #6c757d;">{{ player.hostname }}</div>
|
||||
<div style="font-size: 12px; color: var(--text-secondary);">{{ player.hostname }}</div>
|
||||
</td>
|
||||
<td style="padding: 10px;">
|
||||
{% if player.is_online %}
|
||||
<span style="color: #16a34a; font-weight: 600;">● Online</span>
|
||||
{% else %}
|
||||
<span style="color: #94a3b8;">○ {{ player.status or 'offline' }}</span>
|
||||
<span style="color: var(--text-secondary);">○ {{ player.status or 'offline' }}</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td style="padding: 10px;">
|
||||
{% if age is not none %}
|
||||
{{ '%.1f'|format(age) }} day(s)
|
||||
{% if player.auth_token_issued_at %}
|
||||
<div style="font-size: 12px; color: #6c757d;">
|
||||
<div style="font-size: 12px; color: var(--text-secondary);">
|
||||
issued {{ player.auth_token_issued_at | localtime('%Y-%m-%d %H:%M') }}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<span style="color: #94a3b8;">—</span>
|
||||
<span style="color: var(--text-secondary);">—</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td style="padding: 10px;">
|
||||
{% if player.auth_reset_required %}
|
||||
<span style="background: #fef3c7; color: #92400e; padding: 3px 8px; border-radius: 999px; font-size: 12px; font-weight: 600;">
|
||||
pending
|
||||
</span>
|
||||
<span class="maint-badge-pending">pending</span>
|
||||
{% else %}
|
||||
<span style="color: #94a3b8; font-size: 12px;">—</span>
|
||||
<span style="color: var(--text-secondary); font-size: 12px;">—</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td style="padding: 10px; text-align: right; white-space: nowrap;">
|
||||
@@ -160,7 +194,7 @@
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="5" style="padding: 30px; text-align: center; color: #999;">
|
||||
<td colspan="5" style="padding: 30px; text-align: center; color: var(--text-secondary);">
|
||||
No players registered yet.
|
||||
</td>
|
||||
</tr>
|
||||
@@ -200,7 +234,7 @@
|
||||
|
||||
function tableRow(cells) {
|
||||
return '<tr>' + cells.map(function (c) {
|
||||
return '<td style="padding: 8px 10px; border-bottom: 1px solid #e2e8f0;">' + c + '</td>';
|
||||
return '<td style="padding: 8px 10px; border-bottom: 1px solid var(--border-color);">' + c + '</td>';
|
||||
}).join('') + '</tr>';
|
||||
}
|
||||
|
||||
@@ -235,7 +269,7 @@
|
||||
html += banner(data.ok,
|
||||
data.ok ? 'Database integrity OK — no problems found.'
|
||||
: 'Issues detected — review the details below.');
|
||||
html += '<div style="margin-top: 12px; font-size: 0.9rem; color: #475569;">' +
|
||||
html += '<div style="margin-top: 12px; font-size: 0.9rem; color: var(--text-secondary);">' +
|
||||
'<div>Integrity check: <strong>' + esc(data.integrity.join(', ')) + '</strong></div>' +
|
||||
'<div>Quick check: <strong>' + esc(data.quick_check.join(', ')) + '</strong></div>' +
|
||||
'<div>Database size: <strong>' + esc(data.db_size_mb) + ' MB</strong>' +
|
||||
@@ -247,7 +281,7 @@
|
||||
html += '<table class="table" style="width: 100%; border-collapse: collapse;">';
|
||||
html += '<thead><tr>' +
|
||||
['Table', 'Row ID', 'Missing parent', 'Constraint'].map(function (h) {
|
||||
return '<th style="padding: 8px; text-align: left; border-bottom: 2px solid #dee2e6;">' + h + '</th>';
|
||||
return '<th style="padding: 8px; text-align: left; border-bottom: 2px solid var(--border-color);">' + h + '</th>';
|
||||
}).join('') + '</tr></thead><tbody>';
|
||||
data.foreign_key_violations.slice(0, 100).forEach(function (v) {
|
||||
html += tableRow([esc(v.table), esc(v.rowid), esc(v.parent), esc(v.constraint)]);
|
||||
@@ -299,7 +333,7 @@
|
||||
html += '<table class="table" style="width: 100%; border-collapse: collapse; margin-top: 15px;">';
|
||||
html += '<thead><tr>' +
|
||||
['Type', 'Table', 'Action', 'Count'].map(function (h) {
|
||||
return '<th style="padding: 8px; text-align: left; border-bottom: 2px solid #dee2e6;">' + h + '</th>';
|
||||
return '<th style="padding: 8px; text-align: left; border-bottom: 2px solid var(--border-color);">' + h + '</th>';
|
||||
}).join('') + '</tr></thead><tbody>';
|
||||
data.checks.forEach(function (c) {
|
||||
if (c.error) {
|
||||
@@ -337,7 +371,7 @@
|
||||
html += '<table class="table" style="width: 100%; border-collapse: collapse; margin-top: 15px;">';
|
||||
html += '<thead><tr>' +
|
||||
['Record type', 'Action', 'Rows removed'].map(function (h) {
|
||||
return '<th style="padding: 8px; text-align: left; border-bottom: 2px solid #dee2e6;">' + h + '</th>';
|
||||
return '<th style="padding: 8px; text-align: left; border-bottom: 2px solid var(--border-color);">' + h + '</th>';
|
||||
}).join('') + '</tr></thead><tbody>';
|
||||
data.cleaned.forEach(function (c) {
|
||||
html += tableRow([esc(c.label), esc(c.action), c.rows]);
|
||||
|
||||
Reference in New Issue
Block a user