Files
wrapped/app/templates/admin_audit.html
T
inecs a881570938 Добавить статистику и очистку аудита; доработать UI расшифровки.
- Страница /admin/stats: MinIO, pending/consumed, загрузки, audit-метрики
- Кнопка «Очистить» в аудите с подтверждением
- Красивые callout’ы и ошибки пароля; пустой пароль не тратит попытку
- Убрать автоопределение языка; «Расшифруй» в RU UI
2026-07-18 23:50:44 +03:00

145 lines
5.8 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{% extends "admin_base.html" %}
{% block admin_content %}
{% if request.query_params.get('cleared') is not none %}
<p class="ok">
<span data-i18n="admin.audit.clearedPrefix">Cleared</span>
<span class="audit-count">{{ request.query_params.get('cleared') }}</span>
<span data-i18n="admin.audit.clearedSuffix">audit event(s).</span>
</p>
{% endif %}
<section class="audit-page">
<form class="audit-filters" id="audit-filter-form" method="get" action="/admin/audit">
<input type="hidden" name="page" value="1" />
<label class="audit-field">
<span data-i18n="admin.audit.eventType">Event type</span>
<select name="event_type" id="audit-event-type">
<option value="" {% if not event_type %}selected{% endif %} data-i18n="admin.audit.allEvents">All events</option>
{% for t in event_types %}
<option value="{{ t }}" {% if event_type == t %}selected{% endif %}>{{ t }}</option>
{% endfor %}
</select>
</label>
<label class="audit-field audit-field-grow">
<span data-i18n="admin.audit.wrapId">Wrap ID</span>
<input name="wrap_id" value="{{ wrap_id }}" class="mono" placeholder="…" autocomplete="off" />
</label>
<label class="audit-field">
<span data-i18n="admin.audit.perPage">Per page</span>
<select name="per_page" id="audit-per-page">
{% for n in per_page_options %}
<option value="{{ n }}" {% if per_page == n %}selected{% endif %}>{{ n }}</option>
{% endfor %}
</select>
</label>
<button class="btn primary audit-filter-btn" type="submit" data-i18n="admin.audit.filter">Filter</button>
</form>
<div class="audit-meta-row">
<div class="audit-meta">
{% if total %}
<span class="audit-count">{{ from_idx }}{{ to_idx }}</span>
<span data-i18n="admin.audit.of">of</span>
<span class="audit-count">{{ total }}</span>
{% else %}
<span class="audit-count">0</span>
{% endif %}
<span data-i18n="admin.audit.events">events</span>
</div>
<form method="post" action="/admin/audit/clear" id="audit-clear-form" class="audit-clear-form">
<button
type="submit"
class="btn danger tiny"
id="audit-clear-btn"
{% if not total %}disabled{% endif %}
data-i18n="admin.audit.clear"
>
Clear
</button>
</form>
</div>
<div class="audit-table-wrap">
<table class="audit-table">
<thead>
<tr>
<th data-i18n="admin.audit.col.time">Time</th>
<th data-i18n="admin.audit.col.event">Event</th>
<th data-i18n="admin.audit.col.ok">OK</th>
<th data-i18n="admin.audit.col.wrap">Wrap</th>
<th>IP</th>
<th>UA</th>
<th data-i18n="admin.audit.col.details">Details</th>
</tr>
</thead>
<tbody>
{% for e in events %}
<tr class="{% if not e.success %}audit-row-fail{% endif %}">
<td class="mono audit-time" data-ts="{{ e.created_at.isoformat() if e.created_at else '' }}">{{ e.created_at }}</td>
<td><span class="audit-event-pill">{{ e.event_type }}</span></td>
<td>
{% if e.success %}
<span class="audit-status ok"><i class="fa-solid fa-check" aria-hidden="true"></i> <span data-i18n="admin.audit.yes">yes</span></span>
{% else %}
<span class="audit-status fail"><i class="fa-solid fa-xmark" aria-hidden="true"></i> <span data-i18n="admin.audit.no">no</span></span>
{% endif %}
</td>
<td class="mono">{{ e.wrap_id or "—" }}</td>
<td class="mono">{{ e.ip or "—" }}</td>
<td class="ua" title="{{ e.user_agent or '' }}">{{ e.user_agent or "—" }}</td>
<td class="audit-details"><code>{{ e.details }}</code></td>
</tr>
{% else %}
<tr>
<td colspan="7" class="audit-empty" data-i18n="admin.audit.empty">No events</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% if show_pagination %}
<nav class="pagination" aria-label="Pagination">
{% if has_prev %}
<a class="btn pagination-nav" href="/admin/audit?page={{ page - 1 }}&amp;per_page={{ per_page }}&amp;event_type={{ event_type|urlencode }}&amp;wrap_id={{ wrap_id|urlencode }}">
<i class="fa-solid fa-chevron-left" aria-hidden="true"></i>
<span data-i18n="admin.audit.prev">Prev</span>
</a>
{% else %}
<span class="btn pagination-nav" aria-disabled="true">
<i class="fa-solid fa-chevron-left" aria-hidden="true"></i>
<span data-i18n="admin.audit.prev">Prev</span>
</span>
{% endif %}
<div class="pagination-pages">
{% for p in page_window %}
{% if p is none %}
<span class="pagination-ellipsis" aria-hidden="true"></span>
{% elif p == page %}
<span class="pagination-page is-current" aria-current="page">{{ p }}</span>
{% else %}
<a class="pagination-page" href="/admin/audit?page={{ p }}&amp;per_page={{ per_page }}&amp;event_type={{ event_type|urlencode }}&amp;wrap_id={{ wrap_id|urlencode }}">{{ p }}</a>
{% endif %}
{% endfor %}
</div>
{% if has_next %}
<a class="btn pagination-nav" href="/admin/audit?page={{ page + 1 }}&amp;per_page={{ per_page }}&amp;event_type={{ event_type|urlencode }}&amp;wrap_id={{ wrap_id|urlencode }}">
<span data-i18n="admin.audit.next">Next</span>
<i class="fa-solid fa-chevron-right" aria-hidden="true"></i>
</a>
{% else %}
<span class="btn pagination-nav" aria-disabled="true">
<span data-i18n="admin.audit.next">Next</span>
<i class="fa-solid fa-chevron-right" aria-hidden="true"></i>
</span>
{% endif %}
</nav>
{% endif %}
</section>
{% endblock %}
{% block admin_scripts %}
<script src="/static/js/admin-audit.js"></script>
{% endblock %}