feat(admin-console): Stage 6 — mail & notifications domain
Add the mail, notifications, and broadcast pages over the mail, notification,
and diplomail services (no new business logic), completing the operator console.
- GET /_gm/mail deliveries (paginated) + dead-letters
- GET /_gm/mail/deliveries/{id} delivery detail + attempts
- POST /_gm/mail/deliveries/{id}/resend re-enqueue a non-sent delivery
- GET /_gm/notifications notifications + dead-letters + malformed
- GET/POST /_gm/broadcast multi-game admin diplomatic broadcast
Console depends on MailAdmin / NotificationAdmin / DiplomailAdmin interfaces
(satisfied by the concrete services); pages render in tests without a database.
Delivery detail and dead-letters live under /_gm/mail/deliveries/* and
/_gm/mail/... static segments to avoid a param/static route conflict. Resend
and broadcast flow through the CSRF guard.
Tests: mail page, delivery detail (+ not-found), resend (+ bad-CSRF),
notifications overview, broadcast form + send (input assertions) + bad game
ids, and unavailable. Plus an integration test that drives /_gm end to end
through the real gateway → backend (401 challenge + authenticated dashboard).
Docs: backend/docs/admin-console.md page inventory completed.
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
{{define "content" -}}
|
||||
<h1>Mail</h1>
|
||||
<nav class="subnav"><a href="/_gm/mail">Deliveries</a> · <a href="/_gm/notifications">Notifications</a> · <a href="/_gm/broadcast">Broadcast</a></nav>
|
||||
{{with .Data}}
|
||||
<section class="panel">
|
||||
<h2>Deliveries</h2>
|
||||
<table class="list">
|
||||
<thead><tr><th>Delivery</th><th>Template</th><th>Status</th><th>Attempts</th><th>Next attempt</th><th>Created</th></tr></thead>
|
||||
<tbody>
|
||||
{{range .Deliveries}}
|
||||
<tr><td><a href="/_gm/mail/deliveries/{{.DeliveryID}}"><code>{{.DeliveryID}}</code></a></td><td>{{.Template}}</td><td>{{.Status}}</td><td>{{.Attempts}}</td><td>{{if .NextAttempt}}{{.NextAttempt}}{{else}}—{{end}}</td><td>{{.Created}}</td></tr>
|
||||
{{else}}<tr><td colspan="6"><span class="note">no deliveries</span></td></tr>{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
<nav class="pager">
|
||||
{{if .HasPrev}}<a href="/_gm/mail?page={{.PrevPage}}&page_size={{.PageSize}}">« prev</a>{{end}}
|
||||
<span>page {{.Page}} · {{.Total}} total</span>
|
||||
{{if .HasNext}}<a href="/_gm/mail?page={{.NextPage}}&page_size={{.PageSize}}">next »</a>{{end}}
|
||||
</nav>
|
||||
</section>
|
||||
<section class="panel">
|
||||
<h2>Dead-letters</h2>
|
||||
<table class="list">
|
||||
<thead><tr><th>Delivery</th><th>Reason</th><th>Archived</th></tr></thead>
|
||||
<tbody>
|
||||
{{range .DeadLetters}}<tr><td><a href="/_gm/mail/deliveries/{{.DeliveryID}}"><code>{{.DeliveryID}}</code></a></td><td>{{.Reason}}</td><td>{{.Archived}}</td></tr>
|
||||
{{else}}<tr><td colspan="3"><span class="note">no dead-letters</span></td></tr>{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
{{end}}
|
||||
{{- end}}
|
||||
Reference in New Issue
Block a user