{% load common_extras humanize %} {% comment %} The broadcast table. One renderer for the toolbar's fetch and for every mutation's refresh event. The status chip is `status-pill status-pill-{{ broadcast.status }}`: the five classes exist in styles.css, named for the stored values, so this template never branches on which one a row is in. The counters come off the row's stored `stats` (SPEC §5), not from a per-row aggregate — a list of fifty broadcasts must not be fifty GROUP BYs. The detail page is where the live figures are computed, and it writes them back here. {% endcomment %}
{% if broadcasts %} {% comment %} The delivery bar is the stored counters drawn as one stacked track (HANDOFF §3, Broadcasts): green for sent, blue for still going out, red for failed, each as a share of everyone queued. Skipped recipients — the compliance filter's exclusions — are not in the bar; the detail page itemises them. {% endcomment %}| Broadcast | Status | Delivery | Audience | When |
|---|---|---|---|---|
| {{ broadcast.name }} | {{ broadcast.get_status_display }} |
{% if stats.queued %}
{% widthratio stats.sent stats.queued 100 as sent_pct %}
{% widthratio stats.pending stats.queued 100 as pending_pct %}
{% widthratio stats.failed stats.queued 100 as failed_pct %}
{{ stats.sent|default:0|intcomma }} of {{ stats.queued|intcomma }}{% if stats.skipped %} · {{ stats.skipped|intcomma }} skipped{% endif %} {% else %}— {% endif %} |
{% if stats.queued %}{{ stats.queued|intcomma }}{% else %}—{% endif %} | {% if broadcast.status == "sending" %}Now {% elif broadcast.finished_at %}{{ broadcast.finished_at|naturalday:"j M" }} {% elif broadcast.scheduled_at %}{{ broadcast.scheduled_at|naturalday:"j M"|capfirst }} {{ broadcast.scheduled_at|time:"H:i" }} {% else %}Not sent{% endif %} |
Showing the {{ page_size }} most recent. Search or filter by status to find an older one.
{% endif %}