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 title %}Maintenance - Admin - DigiServer v2{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% 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="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 style="margin-bottom: 30px; display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 15px;">
|
||||||
<div>
|
<div>
|
||||||
@@ -64,16 +99,17 @@
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<form method="POST" action="{{ url_for('admin.maintenance_set_interval') }}"
|
<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>
|
<div>
|
||||||
<label for="interval_days" style="display: block; font-weight: 600; margin-bottom: 6px;">
|
<label for="interval_days" style="display: block; font-weight: 600; margin-bottom: 6px;">
|
||||||
Automatic reset interval
|
Automatic reset interval
|
||||||
</label>
|
</label>
|
||||||
<input type="number" id="interval_days" name="interval_days" min="0" step="1"
|
<input type="number" id="interval_days" name="interval_days" min="0" step="1"
|
||||||
value="{{ interval_days }}"
|
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>
|
||||||
<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.
|
Days before a token expires automatically. Use <strong>0</strong> to disable.
|
||||||
{% if auth_config %}
|
{% if auth_config %}
|
||||||
<br>Last changed by <strong>{{ auth_config.updated_by or 'unknown' }}</strong>
|
<br>Last changed by <strong>{{ auth_config.updated_by or 'unknown' }}</strong>
|
||||||
@@ -95,49 +131,47 @@
|
|||||||
|
|
||||||
<div style="max-height: 460px; overflow-y: auto;">
|
<div style="max-height: 460px; overflow-y: auto;">
|
||||||
<table class="table" style="width: 100%; border-collapse: collapse;">
|
<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>
|
<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 var(--border-color);">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 var(--border-color);">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 var(--border-color);">Token Age</th>
|
||||||
<th style="padding: 10px; text-align: left; border-bottom: 2px solid #dee2e6;">Re-auth</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 #dee2e6;">Actions</th>
|
<th style="padding: 10px; text-align: right; border-bottom: 2px solid var(--border-color);">Actions</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for player in players %}
|
{% for player in players %}
|
||||||
{% set age = player.auth_token_age_days() %}
|
{% 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;">
|
<td style="padding: 10px;">
|
||||||
<strong>{{ player.name }}</strong>
|
<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>
|
||||||
<td style="padding: 10px;">
|
<td style="padding: 10px;">
|
||||||
{% if player.is_online %}
|
{% if player.is_online %}
|
||||||
<span style="color: #16a34a; font-weight: 600;">● Online</span>
|
<span style="color: #16a34a; font-weight: 600;">● Online</span>
|
||||||
{% else %}
|
{% else %}
|
||||||
<span style="color: #94a3b8;">○ {{ player.status or 'offline' }}</span>
|
<span style="color: var(--text-secondary);">○ {{ player.status or 'offline' }}</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td style="padding: 10px;">
|
<td style="padding: 10px;">
|
||||||
{% if age is not none %}
|
{% if age is not none %}
|
||||||
{{ '%.1f'|format(age) }} day(s)
|
{{ '%.1f'|format(age) }} day(s)
|
||||||
{% if player.auth_token_issued_at %}
|
{% 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') }}
|
issued {{ player.auth_token_issued_at | localtime('%Y-%m-%d %H:%M') }}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% else %}
|
{% else %}
|
||||||
<span style="color: #94a3b8;">—</span>
|
<span style="color: var(--text-secondary);">—</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td style="padding: 10px;">
|
<td style="padding: 10px;">
|
||||||
{% if player.auth_reset_required %}
|
{% if player.auth_reset_required %}
|
||||||
<span style="background: #fef3c7; color: #92400e; padding: 3px 8px; border-radius: 999px; font-size: 12px; font-weight: 600;">
|
<span class="maint-badge-pending">pending</span>
|
||||||
pending
|
|
||||||
</span>
|
|
||||||
{% else %}
|
{% else %}
|
||||||
<span style="color: #94a3b8; font-size: 12px;">—</span>
|
<span style="color: var(--text-secondary); font-size: 12px;">—</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td style="padding: 10px; text-align: right; white-space: nowrap;">
|
<td style="padding: 10px; text-align: right; white-space: nowrap;">
|
||||||
@@ -160,7 +194,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
{% else %}
|
{% else %}
|
||||||
<tr>
|
<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.
|
No players registered yet.
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -200,7 +234,7 @@
|
|||||||
|
|
||||||
function tableRow(cells) {
|
function tableRow(cells) {
|
||||||
return '<tr>' + cells.map(function (c) {
|
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>';
|
}).join('') + '</tr>';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -235,7 +269,7 @@
|
|||||||
html += banner(data.ok,
|
html += banner(data.ok,
|
||||||
data.ok ? 'Database integrity OK — no problems found.'
|
data.ok ? 'Database integrity OK — no problems found.'
|
||||||
: 'Issues detected — review the details below.');
|
: '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>Integrity check: <strong>' + esc(data.integrity.join(', ')) + '</strong></div>' +
|
||||||
'<div>Quick check: <strong>' + esc(data.quick_check.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>' +
|
'<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 += '<table class="table" style="width: 100%; border-collapse: collapse;">';
|
||||||
html += '<thead><tr>' +
|
html += '<thead><tr>' +
|
||||||
['Table', 'Row ID', 'Missing parent', 'Constraint'].map(function (h) {
|
['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>';
|
}).join('') + '</tr></thead><tbody>';
|
||||||
data.foreign_key_violations.slice(0, 100).forEach(function (v) {
|
data.foreign_key_violations.slice(0, 100).forEach(function (v) {
|
||||||
html += tableRow([esc(v.table), esc(v.rowid), esc(v.parent), esc(v.constraint)]);
|
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 += '<table class="table" style="width: 100%; border-collapse: collapse; margin-top: 15px;">';
|
||||||
html += '<thead><tr>' +
|
html += '<thead><tr>' +
|
||||||
['Type', 'Table', 'Action', 'Count'].map(function (h) {
|
['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>';
|
}).join('') + '</tr></thead><tbody>';
|
||||||
data.checks.forEach(function (c) {
|
data.checks.forEach(function (c) {
|
||||||
if (c.error) {
|
if (c.error) {
|
||||||
@@ -337,7 +371,7 @@
|
|||||||
html += '<table class="table" style="width: 100%; border-collapse: collapse; margin-top: 15px;">';
|
html += '<table class="table" style="width: 100%; border-collapse: collapse; margin-top: 15px;">';
|
||||||
html += '<thead><tr>' +
|
html += '<thead><tr>' +
|
||||||
['Record type', 'Action', 'Rows removed'].map(function (h) {
|
['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>';
|
}).join('') + '</tr></thead><tbody>';
|
||||||
data.cleaned.forEach(function (c) {
|
data.cleaned.forEach(function (c) {
|
||||||
html += tableRow([esc(c.label), esc(c.action), c.rows]);
|
html += tableRow([esc(c.label), esc(c.action), c.rows]);
|
||||||
|
|||||||
@@ -290,24 +290,24 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Delete Confirmation Modal -->
|
<!-- Delete Confirmation Modal -->
|
||||||
<div id="deleteModal" style="display: none; position: fixed; z-index: 1000; left: 0; top: 0; width: 100%; height: 100%; overflow: auto; background-color: rgba(0,0,0,0.4);">
|
<div id="deleteModal" class="modal-overlay">
|
||||||
<div style="background-color: #fefefe; margin: 15% auto; padding: 20px; border: 1px solid #888; border-radius: 8px; width: 90%; max-width: 500px; box-shadow: 0 4px 6px rgba(0,0,0,0.1);">
|
<div class="modal-box">
|
||||||
<h2 style="margin-top: 0; color: #dc3545; display: flex; align-items: center; gap: 0.5rem;">
|
<h2 class="modal-title">
|
||||||
<span style="font-size: 1.5rem;">⚠️</span>
|
<span style="font-size: 1.5rem;">⚠️</span>
|
||||||
Confirm Delete
|
Confirm Delete
|
||||||
</h2>
|
</h2>
|
||||||
<p style="font-size: 1.1rem; margin: 1.5rem 0;">
|
<p class="modal-text">
|
||||||
Are you sure you want to delete player <strong>"{{ player.name }}"</strong>?
|
Are you sure you want to delete player <strong class="modal-player">"{{ player.name }}"</strong>?
|
||||||
</p>
|
</p>
|
||||||
<p style="color: #dc3545; margin: 1rem 0;">
|
<p class="modal-warning">
|
||||||
<strong>Warning:</strong> This action cannot be undone. All feedback logs for this player will also be deleted.
|
<strong>Warning:</strong> This action cannot be undone. All feedback logs for this player will also be deleted.
|
||||||
</p>
|
</p>
|
||||||
<div style="display: flex; gap: 0.5rem; justify-content: flex-end; margin-top: 2rem;">
|
<div class="modal-actions">
|
||||||
<button onclick="closeDeleteModal()" class="btn" style="background: #6c757d;">
|
<button onclick="closeDeleteModal()" class="btn modal-cancel">
|
||||||
Cancel
|
Cancel
|
||||||
</button>
|
</button>
|
||||||
<form method="POST" action="{{ url_for('players.delete_player', player_id=player.id) }}" style="margin: 0;">
|
<form method="POST" action="{{ url_for('players.delete_player', player_id=player.id) }}" style="margin: 0;">
|
||||||
<button type="submit" class="btn" style="background: #dc3545;">
|
<button type="submit" class="btn btn-danger">
|
||||||
Yes, Delete Player
|
Yes, Delete Player
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
@@ -316,23 +316,87 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
body.dark-mode #deleteModal > div {
|
/* Delete confirmation modal — themed via the CSS variables defined in
|
||||||
background-color: #1a202c;
|
base.html so it follows the light/dark theme. Inline colours are
|
||||||
border-color: #4a5568;
|
deliberately avoided: they would win over the theme rules and leave
|
||||||
color: #e2e8f0;
|
the modal white (with light text) in dark mode. */
|
||||||
|
.modal-overlay {
|
||||||
|
display: none;
|
||||||
|
position: fixed;
|
||||||
|
z-index: 1000;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
overflow: auto;
|
||||||
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
body.dark-mode #deleteModal h2 {
|
.modal-box {
|
||||||
|
background-color: var(--card-bg);
|
||||||
|
color: var(--text-color);
|
||||||
|
margin: 15% auto;
|
||||||
|
padding: 20px;
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
border-radius: 8px;
|
||||||
|
width: 90%;
|
||||||
|
max-width: 500px;
|
||||||
|
box-shadow: var(--shadow-lg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-title {
|
||||||
|
margin-top: 0;
|
||||||
|
color: #dc3545;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.dark-mode .modal-title {
|
||||||
color: #f87171;
|
color: #f87171;
|
||||||
}
|
}
|
||||||
|
|
||||||
body.dark-mode #deleteModal p {
|
.modal-text {
|
||||||
color: #e2e8f0;
|
font-size: 1.1rem;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
color: var(--text-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
body.dark-mode #deleteModal p strong {
|
.modal-player {
|
||||||
|
color: var(--primary-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
body.dark-mode .modal-player {
|
||||||
|
color: #a78bfa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-warning {
|
||||||
|
margin: 1rem 0;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
border-radius: 6px;
|
||||||
|
background: #fff3cd;
|
||||||
|
color: #856404;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.dark-mode .modal-warning {
|
||||||
|
background: #4a3800;
|
||||||
color: #fbbf24;
|
color: #fbbf24;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.modal-actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 0.5rem;
|
||||||
|
justify-content: flex-end;
|
||||||
|
margin-top: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-cancel {
|
||||||
|
background: #6c757d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-cancel:hover {
|
||||||
|
background: #5a6268;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|||||||
Reference in New Issue
Block a user