Fix: eagerload series.sets i admin og API (MissingGreenlet i async mode)

This commit is contained in:
2026-07-01 22:15:14 +02:00
parent c0952a3bd3
commit 8361066f2f
20 changed files with 1075 additions and 554 deletions
+20 -85
View File
@@ -1,95 +1,30 @@
{% extends "base.html" %}
{% block title %}Admin panel{% endblock %}
{% block title %}Admin{% endblock %}
{% block content %}
<h1>⚙️ Admin panel</h1>
<p style="color:var(--text-muted);margin-bottom:24px;">Velkommen, {{ user.username }}!</p>
<h1>🔧 Adminpanel</h1>
<p style="color:var(--text-muted);margin-bottom:24px;">Velkommen, {{ request.state.user.username }}!</p>
<div class="card-grid">
<a href="/admin/sets" style="text-decoration:none;color:var(--text);">
<div class="card" style="text-align:center;padding:32px;">
<div style="font-size:2rem;margin-bottom:8px;">📦</div>
<h3>Administrér serier</h3>
<p style="font-size:0.85rem;color:var(--text-muted);">Opret, redigér og slet serier/sets</p>
<a href="/admin/series" class="card-set">
<div class="card" style="text-align:center;">
<p style="font-size:2rem;margin-bottom:8px;">📦</p>
<h3>Serier</h3>
<p style="font-size:0.85rem;color:var(--text-muted);">Administrér serier</p>
</div>
</a>
<a href="/search" style="text-decoration:none;color:var(--text);">
<div class="card" style="text-align:center;padding:32px;">
<div style="font-size:2rem;margin-bottom:8px;">🔍</div>
<h3>Se kort</h3>
<p style="font-size:0.85rem;color:var(--text-muted);">Søg og gennemse alle kort</p>
<a href="/admin/sets" class="card-set">
<div class="card" style="text-align:center;">
<p style="font-size:2rem;margin-bottom:8px;">📁</p>
<h3>Sæt</h3>
<p style="font-size:0.85rem;color:var(--text-muted);">Administrér sæt</p>
</div>
</a>
<a href="/search" class="card-set">
<div class="card" style="text-align:center;">
<p style="font-size:2rem;margin-bottom:8px;">🔍</p>
<h3>Søg</h3>
<p style="font-size:0.85rem;color:var(--text-muted);">Søg efter kort</p>
</div>
</a>
</div>
<div class="card" style="margin-top:24px;">
<h2>👥 Brugere</h2>
<table>
<thead>
<tr><th>Brugernavn</th><th>Rolle</th><th>Oprettet</th></tr>
</thead>
<tbody id="user-list">
<tr><td colspan="3">Indlæser...</td></tr>
</tbody>
</table>
<div style="margin-top:16px;">
<h3>Opret ny bruger</h3>
<form id="create-user-form" style="display:flex;gap:8px;flex-wrap:wrap;margin-top:8px;">
<input type="text" name="username" placeholder="Brugernavn" required style="max-width:200px;">
<input type="password" name="password" placeholder="Adgangskode" required style="max-width:200px;">
<select name="role" style="max-width:120px;">
<option value="user">Bruger</option>
<option value="admin">Admin</option>
</select>
<button type="submit" class="btn btn-primary">Opret</button>
</form>
<p id="user-msg" style="font-size:0.85rem;margin-top:8px;"></p>
</div>
</div>
<script>
async function loadUsers() {
try {
const res = await fetch('/api/admin/users');
const users = await res.json();
const tbody = document.getElementById('user-list');
tbody.innerHTML = users.map(u =>
'<tr><td>' + u.username + '</td><td><span class="tag">' + u.role + '</span></td><td>' + (u.created_at || '') + '</td></tr>'
).join('');
} catch(e) {
document.getElementById('user-list').innerHTML = '<tr><td colspan="3">Kunne ikke indlæse brugere</td></tr>';
}
}
document.getElementById('create-user-form').addEventListener('submit', async (e) => {
e.preventDefault();
const form = e.target;
const msg = document.getElementById('user-msg');
try {
const res = await fetch('/api/admin/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
username: form.username.value,
password: form.password.value,
role: form.role.value,
}),
});
if (res.ok) {
form.reset();
msg.style.color = 'var(--text)';
msg.textContent = '✅ Bruger oprettet';
loadUsers();
} else {
const err = await res.json();
msg.style.color = 'var(--accent)';
msg.textContent = '❌ ' + (err.detail || 'Fejl');
}
} catch(e) {
msg.style.color = 'var(--accent)';
msg.textContent = '❌ Kunne ikke forbinde';
}
});
loadUsers();
</script>
{% endblock %}