feat: Logs - einzelne Eintraege per Button aus DB und Uebersicht loeschbar

This commit is contained in:
2026-07-18 16:04:22 +02:00
parent 418c4bb112
commit b508d449b6
2 changed files with 46 additions and 4 deletions

View File

@@ -570,4 +570,23 @@ router.get('/logs', authenticate, requireAdmin, (req, res) => {
res.json(combined); res.json(combined);
}); });
// DELETE /logs/:id einzelnen Log-Eintrag löschen (Admin). Die ID trägt ein
// Präfix ("push-123" / "access-45"), damit klar ist, aus welcher Tabelle
// gelöscht werden muss.
router.delete('/logs/:id', authenticate, requireAdmin, (req, res) => {
const raw = req.params.id;
const [prefix, numStr] = raw.split('-');
const numId = parseInt(numStr, 10);
if (!numId) return res.status(400).json({ error: 'Ungültige ID' });
if (prefix === 'push') {
db.prepare('DELETE FROM push_log WHERE id=?').run(numId);
} else if (prefix === 'access') {
db.prepare('DELETE FROM public_access_log WHERE id=?').run(numId);
} else {
return res.status(400).json({ error: 'Ungültige ID' });
}
res.json({ ok: true });
});
module.exports = router; module.exports = router;

View File

@@ -3227,6 +3227,17 @@ function PushLogs({ toast }) {
}; };
useEffect(() => { load(); }, []); useEffect(() => { load(); }, []);
const deleteLog = async (id) => {
const prev = logs;
setLogs(l => l.filter(x => x.id !== id)); // optimistisch sofort entfernen
try {
await api(`/admin/logs/${id}`, { method:'DELETE' });
} catch(e) {
setLogs(prev); // bei Fehler zurückrollen
toast?.(e.message||'Löschen fehlgeschlagen','error');
}
};
const fmtDate = iso => { const fmtDate = iso => {
if (!iso) return '—'; if (!iso) return '—';
const d = new Date(iso.replace(' ', 'T')); const d = new Date(iso.replace(' ', 'T'));
@@ -3280,9 +3291,15 @@ function PushLogs({ toast }) {
<span style={{ color:'#4ecdc4', fontFamily:"'Space Mono',monospace", fontSize:11, fontWeight:700 }}> <span style={{ color:'#4ecdc4', fontFamily:"'Space Mono',monospace", fontSize:11, fontWeight:700 }}>
{PUBLIC_LINK_LABELS[l.linkType] || '🔗 Öffentlicher Link besucht'} {PUBLIC_LINK_LABELS[l.linkType] || '🔗 Öffentlicher Link besucht'}
</span> </span>
<span style={{ display:'flex', alignItems:'center', gap:8 }}>
<span style={{ color:'rgba(255,255,255,0.35)', fontFamily:'monospace', fontSize:10 }}> <span style={{ color:'rgba(255,255,255,0.35)', fontFamily:'monospace', fontSize:10 }}>
{fmtDate(l.created_at)} {fmtDate(l.created_at)}
</span> </span>
<button onClick={()=>deleteLog(l.id)} title="Eintrag löschen"
style={{ background:'none', border:'none', color:'rgba(248,113,113,0.6)', cursor:'pointer', fontSize:12, padding:0, lineHeight:1 }}>
🗑
</button>
</span>
</div> </div>
<div onClick={()=>copyPath(window.location.origin + l.path)} title={`${window.location.origin}${l.path} — antippen zum Kopieren`} <div onClick={()=>copyPath(window.location.origin + l.path)} title={`${window.location.origin}${l.path} — antippen zum Kopieren`}
style={{ color:'rgba(255,255,255,0.85)', fontFamily:'monospace', fontSize:12, marginBottom:4, style={{ color:'rgba(255,255,255,0.85)', fontFamily:'monospace', fontSize:12, marginBottom:4,
@@ -3307,9 +3324,15 @@ function PushLogs({ toast }) {
<span style={{ color:'#4ecdc4', fontFamily:"'Space Mono',monospace", fontSize:11, fontWeight:700 }}> <span style={{ color:'#4ecdc4', fontFamily:"'Space Mono',monospace", fontSize:11, fontWeight:700 }}>
{l.username || `User #${l.user_id ?? '?'}`} {l.username || `User #${l.user_id ?? '?'}`}
</span> </span>
<span style={{ display:'flex', alignItems:'center', gap:8 }}>
<span style={{ color:'rgba(255,255,255,0.35)', fontFamily:'monospace', fontSize:10 }}> <span style={{ color:'rgba(255,255,255,0.35)', fontFamily:'monospace', fontSize:10 }}>
{fmtDate(l.created_at)} {fmtDate(l.created_at)}
</span> </span>
<button onClick={()=>deleteLog(l.id)} title="Eintrag löschen"
style={{ background:'none', border:'none', color:'rgba(248,113,113,0.6)', cursor:'pointer', fontSize:12, padding:0, lineHeight:1 }}>
🗑
</button>
</span>
</div> </div>
<div style={{ color:'rgba(255,255,255,0.85)', fontFamily:'monospace', fontSize:12, marginBottom:2 }}> <div style={{ color:'rgba(255,255,255,0.85)', fontFamily:'monospace', fontSize:12, marginBottom:2 }}>
{l.title} {l.title}