trust_list.html
187 lignes · 8240 octets
{% extends "base.html" %} {% block title %}{{ page_title }}{% endblock %} {% block navbar %} {% include "components/navbar.html" %} {% endblock %} {% block content %} <div class="container mx-auto px-4 py-8" x-data="fediversePage" data-saved="{% if saved_flash %}true{% else %}false{% endif %}"> {# Breadcrumb #} <nav class="text-sm breadcrumbs mb-6" aria-label="breadcrumb"> <ul> <li><a href="/">{{ breadcrumb_home }}</a></li> <li><a href="/admin">{{ breadcrumb_admin }}</a></li> <li><a href="/admin/fediverse">{{ breadcrumb_federation }}</a></li> <li aria-current="page">{{ breadcrumb_self }}</li> </ul> </nav> {% include "components/admin_tabs.html" %} {# Page header #} <header class="mb-2"> <h1 class="text-3xl font-bold mb-2">{{ heading }}</h1> <p class="text-base-content/70">{{ subtitle }}</p> </header> {# Mode indicator badge #} <div class="mb-6"> <span class="badge {% if is_blocklist %}badge-warning{% else %}badge-success{% endif %} badge-lg"> {{ mode_indicator }} </span> </div> {# Toast on save (Plan UI §3 P3) #} <div x-show="saved" x-transition role="status" aria-live="polite" class="alert alert-success mb-6" > <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" /></svg> <span>{{ saved_toast }}</span> </div> {# Add form #} <section class="card bg-base-100 shadow-xl mb-8" aria-labelledby="add-legend"> <div class="card-body"> <h2 id="add-legend" class="card-title text-xl mb-4">{{ add_form_legend }}</h2> <form method="POST" action="/admin/fediverse/trust_list/add" class="space-y-4"> <input type="hidden" name="csrf_token" value="{{ csrf_token }}"> <div class="form-control"> <label class="label" for="trust-domain"> <span class="label-text font-semibold">{{ domain_label }}</span> </label> <input id="trust-domain" type="text" name="domain" required autocomplete="off" class="input input-bordered w-full max-w-md" placeholder="{{ domain_placeholder }}" > </div> <div class="form-control"> <label class="label" for="trust-note"> <span class="label-text font-semibold"> {% if is_blocklist %}{{ reason_label }}{% else %}{{ note_label }}{% endif %} </span> </label> <input id="trust-note" type="text" name="note_or_reason" autocomplete="off" class="input input-bordered w-full max-w-md" > </div> {% if is_blocklist %} <div class="form-control"> <label class="label" for="trust-severity"> <span class="label-text font-semibold">{{ severity_label }}</span> </label> <select id="trust-severity" name="severity" required class="select select-bordered w-full max-w-md" > <option value="suspend">{{ severity_suspend }}</option> <option value="silence">{{ severity_silence }}</option> <option value="reject_auth">{{ severity_reject_auth }}</option> </select> </div> {% endif %} <div class="flex justify-end"> <button type="submit" class="btn btn-primary">{{ add_button }}</button> </div> </form> </div> </section> {# Table or empty state #} {% if has_entries %} <section class="card bg-base-100 shadow-xl"> <div class="card-body"> <div class="overflow-x-auto"> <table class="table table-zebra"> <thead> <tr> <th>{{ table_domain }}</th> <th>{{ table_note_or_reason }}</th> {% if is_blocklist %}<th>{{ table_severity }}</th>{% endif %} <th>{{ table_created_at }}</th> <th class="text-right">{{ table_actions }}</th> </tr> </thead> <tbody> {% for entry in entries %} <tr> <td class="font-mono">{{ entry.domain }}</td> <td>{% if entry.has_note_or_reason %}{{ entry.note_or_reason }}{% else %}—{% endif %}</td> {% if is_blocklist %}<td>{{ entry.severity }}</td>{% endif %} <td class="text-base-content/70">{{ entry.created_at }}</td> <td class="text-right"> <button type="button" class="btn btn-sm btn-ghost text-error" @click="deleteTarget = '{{ entry.domain }}'" aria-haspopup="dialog" > {{ delete_button }} </button> </td> </tr> {% endfor %} </tbody> </table> </div> </div> </section> {% else %} {# Empty state (Plan UI §3 P4) #} <section class="card bg-base-200 shadow-inner" aria-label="empty-state"> <div class="card-body items-center text-center py-16"> <svg xmlns="http://www.w3.org/2000/svg" class="h-16 w-16 text-base-content/30 mb-4" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" /></svg> <h3 class="text-lg font-semibold">{{ empty_title }}</h3> <p class="text-base-content/70 max-w-md">{{ empty_body }}</p> </div> </section> {% endif %} {# Confirmation modal (Plan UI §3 P2). Triggered by `deleteTarget`. #} <dialog class="modal" :class="{ 'modal-open': deleteTarget !== null }" role="alertdialog" aria-labelledby="confirm-title" aria-describedby="confirm-body" > <div class="modal-box"> <h3 id="confirm-title" class="font-bold text-lg">{{ delete_confirm_title }}</h3> <p id="confirm-body" class="py-4"> {{ delete_confirm_body }} <span class="font-mono block mt-2" x-text="deleteTarget"></span> </p> <form method="POST" action="/admin/fediverse/trust_list/delete" class="modal-action"> <input type="hidden" name="csrf_token" value="{{ csrf_token }}"> <input type="hidden" name="domain" :value="deleteTarget"> <button type="button" class="btn btn-ghost" @click="deleteTarget = null">{{ modal_cancel }}</button> <button type="submit" class="btn btn-error">{{ modal_confirm }}</button> </form> </div> <form method="dialog" class="modal-backdrop"> <button type="button" @click="deleteTarget = null" aria-label="close">close</button> </form> </dialog> </div> {% endblock %}
GitRust