The Trail Log — SquatchMail's default landing page (squatch_mail_dashboard
mounted at /), showing the live activity feed: stat strip, filters, and
the sent-email activity table.
One LiveView, four pages
This module also serves the sidebar's three archive pages, distinguished by
live_action (see @pages):
:index— the Trail Log itself (/): recent activity, 7-day default range, stat strip.:sightings— the Sightings archive (/sightings): every email on record, all-time default range.:bounces/:complaints— the same table locked to status"bounced"/"complained"(/bounces,/complaints). The status filter is forced and its select hidden; a hand-typed?status=param can't unlock it.
They share everything that matters — the URL-driven filters, the telemetry-driven refresh, pagination, and the activity table — so they're per-action page configs rather than three near-identical modules.
Filters live in the URL
Every filter (status, search, date range) is a query param, patched via
push_patch/2 from handle_event/3 and re-read in handle_params/3 — the
same pattern SquatchMail.Web.Live.Suppressions uses. This is what lets
SquatchMail.Web.ActivityExportController's CSV export and the "back to
Trail Log" link from the Sighting inspector both reconstruct the exact
filter set a user was looking at, just from the URL.
Live updates
Rather than push every new email/event straight into the assigns from a
telemetry handler (telemetry handlers run in the emitting process, not
this LiveView's — attaching a handler here would execute in the wrong
process and race with everything else), mount/3 attaches a handler that
simply forwards [:squatch_mail, :email, :recorded] telemetry events to
this LiveView's own process via send/2, debounced so a burst of events
collapses into a single reload. A 30s poll (:timer.send_interval/2) is
the fallback for whatever telemetry might miss (host restarts the handler
attachment, a handler exception detaches it, etc.) The handler is detached
in terminate/2 — leaving it attached would leak a reference to a dead
LiveView process on every mount.
Summary
Functions
Builds Tracker.list_emails/1-shaped filters from Trail Log's query
params. Public and shared with SquatchMail.Web.ActivityExportController
so the CSV export always matches whatever's on screen — the archive pages'
"Export CSV" links spell their locked status and effective range out as
explicit query params (see export_query/2), so this 1-arity form (Trail
Log defaults) is all the controller ever needs.
Functions
Builds Tracker.list_emails/1-shaped filters from Trail Log's query
params. Public and shared with SquatchMail.Web.ActivityExportController
so the CSV export always matches whatever's on screen — the archive pages'
"Export CSV" links spell their locked status and effective range out as
explicit query params (see export_query/2), so this 1-arity form (Trail
Log defaults) is all the controller ever needs.