{% extends "aa_discord_audit/base.html" %} {% load i18n %} {% load static %} {% block page_title %} {% translate "Discord Audit Runs" %} {% endblock %} {% block header_nav_collapse_right %} {% include "aa_discord_audit/_top_actions.html" %} {% endblock %} {% block extra_javascript %} {% include "aa_discord_audit/_datatables_init.html" %} {% endblock %} {% block content %} {% if perms.aa_discord_audit.run_audit %} {% comment %} The launch trigger lives in the top navbar (_top_actions.html); the modal markup it opens stays in the page body so it is present in the DOM with its policy-summary context. {% endcomment %} {% include "aa_discord_audit/_launch_modal.html" %} {% endif %}
{% translate "Last run" %}
{% if summary.last_run %} {# Flex row so the badge and timestamp sit on one line with a controlled gap. Flex blockifies its items, which trims the leading/trailing whitespace the _badge.html include emits inside , and discards the newline between the flex items — neither shows as a stray gap. #} {% else %} {% translate "no runs yet" %} {% endif %}
{% translate "Failed (7 d)" %}
{{ summary.failed_recent }}
{% translate "Pending findings" %}
{{ summary.pending_findings }}
{% translate "Audit runs" %}
{{ total_count }}
{# {% if rows %}: skip DataTables on an empty list so the #} {# {% empty %} placeholder does not trip the #} {# "Incorrect column count" warning (tn/18). The live-poll #} {# attrs stay put — the poller keys off data-active-runs. #} {% for row in rows %} {# Icon-only state badge: the verbose enum label would widen #} {# the column and force a horizontal scrollbar, so it moves to #} {# the hover title; data-order keeps the column sortable. #} {% empty %} {% endfor %}
{% translate "ID" %} {% translate "State" %} {% translate "Started" %} {% translate "Duration" %} {% translate "Trigger" %} {% translate "User" %} {% translate "Members" %} {% translate "Findings" %} {% translate "Applied" %} {% translate "Skipped" %} {% translate "Dry run" %} {% translate "Error" %}
{{ row.obj.pk }} {% include "aa_discord_audit/_badge.html" with badge=row.state_badge icon_only=True only %} {{ row.started_rel }} {{ row.duration }} {% include "aa_discord_audit/_badge.html" with badge=row.trigger_badge only %} {{ row.obj.triggered_by_user|default:"—" }} {{ row.obj.members_scanned }} {{ row.obj.findings_count }} {{ row.obj.actions_applied }} {{ row.obj.actions_skipped }} {% include "aa_discord_audit/_flag_badge.html" with badge=row.dry_run_badge only %} {% if row.error_redacted %} {# Icon trigger opens the shared #payload-modal; the full #} {# (untruncated) run error lives in the hidden source div #} {# and is cloned into the modal by payload_modal.js. #}
{{ row.error_redacted }}
{% else %} — {% endif %}
{# Icon-only link to the run detail page; the visible label #} {# is dropped, so the action name lives in title / aria-label. #}
{% translate "No audit runs to display." %} {% translate "Clear filters" %}
{% if not client_mode and page_obj and page_obj.number == 1 %}

{% translate "Showing the first page — narrow your filters to search across all results." %}

{% include "aa_discord_audit/_pagination.html" with page_obj=page_obj pagination_query=pagination_query only %} {% endif %} {% include "aa_discord_audit/_payload_modal.html" %} {% endblock %}