Files
rdmsandClaude Opus 5.5 4458300f43 feat: Tabellen per Spaltenkopf sortierbar (A11-T4)
Neues static/sort.js sortiert Tabellen clientseitig per Klick auf den
Spaltenkopf (⇅/▲/▼): Datum TT.MM.JJJJ, deutsche Zahlen/Beträge, sonst
Text (Intl.Collator 'de'). Sortierwert optional per td[data-sort]
(Punkt-Dezimal/ISO) überschreibbar, th[data-nosort] bekommt keinen
Button, table[data-sort-mode="server"] wird übersprungen (Buchungen
sortiert serverseitig, folgt in Task 5). Bearbeiten-/Tilgungsplan-
Zeilen (tr[data-sort-follow]) wandern mit ihrer Vorzeile mit.
Initialisierung über htmx.onLoad, greift auch bei nachgeladenen
Fragmenten.

Templates entsprechend annotiert (Planung, Szenarien, Admin, Index,
Salden, Import-Liste, Buchungen); Salden-Gesamtzeile dafür in ein
tfoot verschoben. test_gui.py::test_gui_zeigt_deutsche_betragsformate
angepasst, da das neue machinenlesbare data-sort-Attribut bewusst
Punkt-Dezimal führt (Interface-Konvention) - die Prüfung auf deutsches
Format im sichtbaren Text bleibt bestehen.

JS-Unit-/DOM-Tests unter tests/js (node --test, DOM-Teil optional via
jsdom), pytest-Wrapper skip ohne node (Fable-Gate führt sie per
Podman aus). Suite: 248 passed, 3 skipped (vorher 242/2).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 19:22:34 +02:00

68 lines
3.4 KiB
HTML
Raw Permalink 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.
<table>
<thead>
<tr><th>Datei</th><th>Bank</th><th>Zeitraum</th><th>Status</th><th></th></tr>
</thead>
<tbody>
{% for s in statements %}
<tr>
<td>{{ s.filename }}</td>
<td>{{ s.bank }}</td>
<td data-sort="{{ s.period_start.isoformat() if s.period_start else '' }}">
{% if s.period_start and s.period_end %}
{{ s.period_start.strftime('%d.%m.%Y') }} – {{ s.period_end.strftime('%d.%m.%Y') }}
{% endif %}
</td>
<td>
{% if s.status == "draft" %}
<span class="badge badge-warning">wartet auf Bestätigung</span>
{% elif s.status == "error" %}
<span class="badge badge-error">Fehler: {{ s.error_message }}</span>
{% elif s.status == "confirmed" %}
<span class="badge badge-ok">übernommen</span>
{% else %}
<span class="badge">{{ s.status }}</span>
{% endif %}
</td>
<td>
{% if s.status == "draft" %}
<details hx-get="/import/{{ s.id }}/preview-fragment"
hx-trigger="toggle once" hx-target="find .preview-slot" hx-swap="innerHTML">
<summary>Vorschau</summary>
<div class="preview-slot">Lädt…</div>
</details>
<form class="inline-form" hx-post="/api/imports/{{ s.id }}/confirm" hx-swap="none"
hx-on::after-request="if(event.detail.successful){htmx.trigger(document.getElementById('imports'), 'refresh')}">
<button type="submit">Übernehmen</button>
</form>
<form class="inline-form" hx-delete="/api/imports/{{ s.id }}" hx-swap="none"
hx-confirm="Import „{{ s.filename }}“ wirklich verwerfen?"
hx-on::after-request="if(event.detail.successful){htmx.trigger(document.getElementById('imports'), 'refresh')}">
<button type="submit">Verwerfen</button>
</form>
<button type="button" class="inline-form" disabled title="Nur für bestätigte Importe">Import zurückrollen</button>
{% elif s.status == "confirmed" %}
<span class="muted">Bestätigt — Buchungen übernommen</span>
<button type="button" class="inline-form" disabled title="Nur für Entwürfe">Übernehmen</button>
<button type="button" class="inline-form" disabled title="Nur für Entwürfe">Verwerfen</button>
<form class="inline-form" hx-post="/api/imports/{{ s.id }}/rollback" hx-swap="none"
hx-confirm="Diesen Import und ALLE zugehörigen Buchungen unwiderruflich löschen? Salden und Projektionen ändern sich."
hx-on::after-request="if(event.detail.successful){htmx.trigger(document.getElementById('imports'), 'refresh')}">
<button type="submit">Import zurückrollen</button>
</form>
{% else %}
<button type="button" class="inline-form" disabled title="Nur für Entwürfe">Übernehmen</button>
<form class="inline-form" hx-delete="/api/imports/{{ s.id }}" hx-swap="none"
hx-confirm="Import „{{ s.filename }}“ wirklich verwerfen?"
hx-on::after-request="if(event.detail.successful){htmx.trigger(document.getElementById('imports'), 'refresh')}">
<button type="submit">Verwerfen</button>
</form>
<button type="button" class="inline-form" disabled title="Nur für bestätigte Importe">Import zurückrollen</button>
{% endif %}
</td>
</tr>
{% else %}
<tr><td colspan="5">Noch keine Imports vorhanden.</td></tr>
{% endfor %}
</tbody>
</table>