Files
the-daily-epub/src/web/templates/dashboard/users.html
T
thalladaandClaude Fable 5.1 8d0516bedc Show table-centric dashboard pages at full height
Only the profile page's version history keeps the 70vh scrolling island;
it has three sections below it. Everything else is paginated or last on
its page, so the page itself scrolls.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-20 22:16:07 +00:00

30 lines
3.0 KiB
HTML

{% extends "layout.html" %}{% block content %}<section class="dashboard">
<header class="page-head"><div>
<h1>Users</h1>
<p class="page-desc">{{ requests.len() }} open access request{% if requests.len() != 1 %}s{% endif %}; every account on this server, with its role and open sessions.</p>
</div></header>
<p class="muted text-sm">Approve creates a user account with a temporary password and emails it; the user must choose a new password on first sign-in. Or create accounts with <code>daily-epub users add</code> and mark the request done. Change, disable, enable, or sign out users with the <code>daily-epub users</code> CLI.</p>
<section class="card"><h2>Access requests</h2>
{% if requests.is_empty() %}<p class="muted">No open requests.</p>{% else %}<div class="scroll-x"><table>
<thead><tr><th>Email</th><th>Username</th><th>Reason or comment</th><th>Requested</th><th><span class="sr-only">Action</span></th></tr></thead>
<tbody>{% for request in requests %}<tr>
<td class="font-medium text-ink"><a href="mailto:{{ request.email }}">{{ request.email }}</a></td>
<td class="font-medium text-ink">{{ request.suggested_username }}</td>
<td class="cell-wrap">{% if request.reason.is_empty() %}<span class="text-muted">—</span>{% else %}{{ request.reason }}{% endif %}</td>
<td class="cell-tight text-muted">{{ request.requested }}</td>
<td><div class="flex flex-wrap gap-2"><form class="form-inline" method="post" action="/dashboard/users/requests/{{ request.id }}/approve"><input type="text" name="username" value="{{ request.suggested_username }}" autocomplete="username" maxlength="32" required pattern="[A-Za-z0-9._-]+" aria-label="Username for {{ request.email }}"><button class="btn-primary" type="submit"{% if !mail_configured %} disabled title="Email is not configured"{% endif %}>Approve</button></form><form method="post" action="/dashboard/users/requests/{{ request.id }}/done"><button class="btn" type="submit">Mark done</button></form></div></td>
</tr>{% endfor %}</tbody></table></div>{% endif %}
</section>
{% if users.len() > 1 %}<input type="search" class="table-filter" placeholder="Filter rows on this page" aria-label="Filter rows on this page" data-table-filter>{% endif %}<div class="scroll-x"><table data-filter>
<thead><tr><th>Username</th><th>Role</th><th>Status</th><th>Created</th><th>Last login</th><th class="num">Open sessions</th></tr></thead>
<tbody>{% for user in users %}<tr>
<td class="font-medium text-ink">{{ user.username }}</td>
<td><span class="badge">{{ user.role }}</span></td>
<td>{% if user.disabled %}<span class="badge down">disabled</span>{% else %}<span class="badge loved">enabled</span>{% endif %}</td>
<td class="cell-tight text-muted">{{ user.created }}</td>
<td class="cell-tight text-muted">{{ user.last_login }}</td>
<td class="num">{{ user.open_sessions }}</td>
</tr>{% endfor %}{% if users.is_empty() %}<tr><td colspan="6" class="text-muted">No users. Bootstrap an admin with <code>daily-epub users add &lt;username&gt;</code> <code>--admin</code>.</td></tr>{% endif %}</tbody>
</table></div>
</section>{% endblock %}