Fix: Admin-Seite Mobile-kompatibel (Tabellen scrollbar, Filter wrap, Touch-Targets)

This commit is contained in:
rene 2026-04-17 23:25:50 +02:00
parent 92620c2c52
commit bfdf6ebfae
4 changed files with 208 additions and 81 deletions

View file

@ -3,7 +3,7 @@
Router, State-Management, Navigation, Initialisierung.
============================================================ */
const APP_VER = '124'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen
const APP_VER = '126'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen
const App = (() => {

View file

@ -44,7 +44,7 @@ window.Page_admin = (() => {
<div style="max-width:720px;margin:0 auto;padding:var(--space-4)">
<!-- Tabs -->
<div class="by-tabs" style="margin-bottom:var(--space-5)" id="adm-tabs">
<div class="by-tabs adm-tabs" id="adm-tabs">
${TABS.map(t => `
<button class="by-tab${t.id === _tab ? ' active' : ''}" data-tab="${t.id}">
${UI.icon(t.icon)} ${t.label}
@ -144,14 +144,10 @@ window.Page_admin = (() => {
// ------------------------------------------------------------------
async function _renderUsers(el) {
el.innerHTML = `
<div style="display:flex;gap:var(--space-2);margin-bottom:var(--space-4)">
<div class="adm-filter-row">
<input id="adm-user-q" type="search" placeholder="Name oder E-Mail…"
style="flex:1;padding:var(--space-2) var(--space-3);border:1.5px solid var(--c-border);
border-radius:var(--radius-md);font-size:var(--text-sm);font-family:inherit;
background:var(--c-surface);color:var(--c-text)">
<select id="adm-user-rolle" style="padding:var(--space-2) var(--space-3);
border:1.5px solid var(--c-border);border-radius:var(--radius-md);
font-size:var(--text-sm);font-family:inherit;background:var(--c-surface);color:var(--c-text)">
class="adm-filter-input">
<select id="adm-user-rolle" class="adm-filter-select">
<option value="">Alle Rollen</option>
<option value="user">user</option>
<option value="moderator">moderator</option>
@ -339,7 +335,7 @@ window.Page_admin = (() => {
async function _renderForum(el) {
el.innerHTML = `
<!-- Unternavigation -->
<div style="display:flex;gap:var(--space-2);margin-bottom:var(--space-4)">
<div class="adm-subnav">
<button class="btn btn-primary btn-sm adm-forum-nav" data-view="reports" id="adm-fn-reports">
Offene Meldungen
</button>
@ -429,13 +425,10 @@ window.Page_admin = (() => {
} else {
// Threads
el.innerHTML = `
<div style="display:flex;gap:var(--space-2);margin-bottom:var(--space-3)">
<div class="adm-filter-row">
<input id="adm-thread-q" type="search" placeholder="Threads durchsuchen…"
style="flex:1;padding:var(--space-2) var(--space-3);border:1.5px solid var(--c-border);
border-radius:var(--radius-md);font-size:var(--text-sm);font-family:inherit;
background:var(--c-surface);color:var(--c-text)">
<label style="display:flex;align-items:center;gap:var(--space-2);
font-size:var(--text-sm);color:var(--c-text-secondary);white-space:nowrap">
class="adm-filter-input">
<label class="adm-filter-label">
<input type="checkbox" id="adm-show-deleted"> Gelöschte
</label>
</div>
@ -623,39 +616,41 @@ window.Page_admin = (() => {
return;
}
el.innerHTML = `
<div class="card" style="overflow:hidden">
<table style="width:100%;border-collapse:collapse;font-size:var(--text-sm)">
<thead>
<tr style="background:var(--c-surface-2);text-align:left">
<th style="padding:var(--space-3) var(--space-4);font-weight:var(--weight-semibold);color:var(--c-text-secondary)">Job</th>
<th style="padding:var(--space-3) var(--space-4);font-weight:var(--weight-semibold);color:var(--c-text-secondary)">Nächster Lauf</th>
<th style="padding:var(--space-3) var(--space-4);font-weight:var(--weight-semibold);color:var(--c-text-secondary)">Trigger</th>
<th style="padding:var(--space-3) var(--space-4);font-weight:var(--weight-semibold);color:var(--c-text-secondary)"></th>
</tr>
</thead>
<tbody>
${jobs.map((j, i) => `
<tr style="${i % 2 === 1 ? 'background:var(--c-surface-2)' : ''}">
<td style="padding:var(--space-3) var(--space-4);font-weight:var(--weight-semibold);color:var(--c-text)">
${_esc(j.name)}
<div style="font-size:var(--text-xs);color:var(--c-text-muted);font-weight:normal">${_esc(j.id)}</div>
</td>
<td style="padding:var(--space-3) var(--space-4);color:var(--c-text-secondary)">
${j.next_run_time ? _formatDateTime(j.next_run_time) : '<span style="color:var(--c-text-muted)">—</span>'}
</td>
<td style="padding:var(--space-3) var(--space-4);color:var(--c-text-muted);font-size:var(--text-xs);max-width:160px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap">
${_esc(j.trigger)}
</td>
<td style="padding:var(--space-3) var(--space-4);text-align:right">
<button class="btn btn-sm btn-ghost adm-job-trigger" data-id="${_esc(j.id)}" data-name="${_esc(j.name)}"
title="Jetzt ausführen" style="color:var(--c-primary)">
${UI.icon('play')}
</button>
</td>
<div class="card adm-table-card">
<div class="adm-table-scroll">
<table class="adm-table">
<thead>
<tr style="background:var(--c-surface-2);text-align:left">
<th class="adm-th">Job</th>
<th class="adm-th">Nächster Lauf</th>
<th class="adm-th">Trigger</th>
<th class="adm-th"></th>
</tr>
`).join('')}
</tbody>
</table>
</thead>
<tbody>
${jobs.map((j, i) => `
<tr style="${i % 2 === 1 ? 'background:var(--c-surface-2)' : ''}">
<td class="adm-td" style="font-weight:var(--weight-semibold);color:var(--c-text)">
${_esc(j.name)}
<div class="adm-job-id">${_esc(j.id)}</div>
</td>
<td class="adm-td" style="color:var(--c-text-secondary);white-space:nowrap">
${j.next_run_time ? _formatDateTime(j.next_run_time) : '<span style="color:var(--c-text-muted)">—</span>'}
</td>
<td class="adm-td adm-td-trigger">
${_esc(j.trigger)}
</td>
<td class="adm-td" style="text-align:right">
<button class="btn btn-sm btn-ghost adm-job-trigger adm-icon-btn" data-id="${_esc(j.id)}" data-name="${_esc(j.name)}"
title="Jetzt ausführen" style="color:var(--c-primary)">
${UI.icon('play')}
</button>
</td>
</tr>
`).join('')}
</tbody>
</table>
</div>
</div>
`;
el.querySelectorAll('.adm-job-trigger').forEach(btn => {
@ -704,39 +699,38 @@ window.Page_admin = (() => {
return;
}
el.innerHTML = `
<div class="card" style="overflow:hidden">
<table style="width:100%;border-collapse:collapse;font-size:var(--text-sm)">
<thead>
<tr style="background:var(--c-surface-2);text-align:left">
<th style="padding:var(--space-3) var(--space-4);font-weight:var(--weight-semibold);color:var(--c-text-secondary)">Wann</th>
<th style="padding:var(--space-3) var(--space-4);font-weight:var(--weight-semibold);color:var(--c-text-secondary)">Admin</th>
<th style="padding:var(--space-3) var(--space-4);font-weight:var(--weight-semibold);color:var(--c-text-secondary)">Aktion</th>
<th style="padding:var(--space-3) var(--space-4);font-weight:var(--weight-semibold);color:var(--c-text-secondary)">Ziel</th>
</tr>
</thead>
<tbody>
${rows.map((r, i) => `
<tr style="${i % 2 === 1 ? 'background:var(--c-surface-2)' : ''}">
<td style="padding:var(--space-2) var(--space-4);color:var(--c-text-muted);white-space:nowrap;font-size:var(--text-xs)">
${_formatDateTime(r.created_at)}
</td>
<td style="padding:var(--space-2) var(--space-4);color:var(--c-text)">
${_esc(r.admin_name || '—')}
</td>
<td style="padding:var(--space-2) var(--space-4)">
<span style="font-size:var(--text-xs);padding:2px 7px;border-radius:3px;
background:var(--c-surface-2);color:var(--c-text-secondary);font-family:monospace">
${_esc(r.action)}
</span>
${r.detail ? `<div style="font-size:var(--text-xs);color:var(--c-text-muted);margin-top:2px">${_esc(r.detail)}</div>` : ''}
</td>
<td style="padding:var(--space-2) var(--space-4);color:var(--c-text-secondary);font-size:var(--text-xs)">
${_esc(r.target || '—')}
</td>
<div class="card adm-table-card">
<div class="adm-table-scroll">
<table class="adm-table">
<thead>
<tr style="background:var(--c-surface-2);text-align:left">
<th class="adm-th">Wann</th>
<th class="adm-th">Admin</th>
<th class="adm-th">Aktion</th>
<th class="adm-th">Ziel</th>
</tr>
`).join('')}
</tbody>
</table>
</thead>
<tbody>
${rows.map((r, i) => `
<tr style="${i % 2 === 1 ? 'background:var(--c-surface-2)' : ''}">
<td class="adm-td" style="color:var(--c-text-muted);white-space:nowrap;font-size:var(--text-xs)">
${_formatDateTime(r.created_at)}
</td>
<td class="adm-td" style="color:var(--c-text);white-space:nowrap">
${_esc(r.admin_name || '—')}
</td>
<td class="adm-td">
<span class="adm-badge-mono">${_esc(r.action)}</span>
${r.detail ? `<div style="font-size:var(--text-xs);color:var(--c-text-muted);margin-top:2px;max-width:200px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap">${_esc(r.detail)}</div>` : ''}
</td>
<td class="adm-td" style="color:var(--c-text-secondary);font-size:var(--text-xs);white-space:nowrap">
${_esc(r.target || '—')}
</td>
</tr>
`).join('')}
</tbody>
</table>
</div>
</div>
`;
}