diff --git a/CLAUDE.md b/CLAUDE.md index 0d56f12..b8c8406 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -660,10 +660,24 @@ Behoben durch explizites `flex-direction: row` in `.filter-bar` selbst — jetzt unabhängig davon robust, ob die Klasse auf einem `
` oder einem `
` sitzt. -Noch nicht übertragen: Betreiber-Accounts, Betreiber-Audit-Log, -Wiedervorlage, "Meine Anträge" — nächste Kandidaten, falls das Muster -fortgesetzt werden soll (Audit-Log wird langfristig am ehesten groß -genug für Paginierung). +**Ebenfalls ausgerollt (2026-08-31, zweite Runde):** Betreiber-Accounts +(`.page-header` + Filter über Firmenname + Paginierung), Betreiber- +Audit-Log (`.page-header` + Filter über Aktion/Zieltyp/Details + +Paginierung), "Meine Anträge" (`.page-header` + Filter über Titel/ +Status/Häufigkeit + Paginierung), Wiedervorlage (nur `.page-header`, +bewusst ohne Paginierung — natürlich begrenzt auf "braucht gerade +Aufmerksamkeit"). + +**Bekannte Einschränkung beim Audit-Log:** `ListAuditLog` holt weiterhin +nur die neuesten `auditLogFetchLimit` (1000) Einträge aus der DB, dann +wird in Go gefiltert/paginiert (`auditLogFetchLimit`-Konstante in +`betreiber_handlers.go`) — keine echte DB-seitige Offset-Paginierung. +Für ein potenziell sehr groß werdendes, append-only Audit-Log ist das +mittelfristig nicht die saubere Lösung (Einträge jenseits der 1000 +neuesten sind über die Such-/Paginierungs-UI nicht erreichbar), aber +proportional zum aktuellen Datenvolumen und konsistent mit dem +In-Memory-Paginierungsmuster der übrigen Listen. Bei echtem Bedarf: +`store.ListAuditLog` um `offset`/echtes SQL-`LIMIT`/`OFFSET` erweitern. **Verifikationsmethode für CSS-Änderungen:** Live-Cookie-Auth per Chromium-Headless/CDP ist im Sandbox-Environment nicht möglich (kein diff --git a/internal/web/antrag_handlers.go b/internal/web/antrag_handlers.go index e1d85c1..e201b61 100644 --- a/internal/web/antrag_handlers.go +++ b/internal/web/antrag_handlers.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "net/http" + "strings" "github.com/netcell-it/deklarix/internal/rules" "github.com/netcell-it/deklarix/internal/store" @@ -334,9 +335,11 @@ type antragListItem struct { } type antragListData struct { - Title string - Nav navData - Antraege []antragListItem + Title string + Nav navData + Antraege []antragListItem + Suche string + Pagination pagination } // handleAntragList zeigt die eigenen Anträge (Ebene 2 — "Eigene @@ -351,8 +354,16 @@ func (s *Server) handleAntragList(w http.ResponseWriter, r *http.Request) { http.Error(w, "Anträge konnten nicht geladen werden: "+err.Error(), http.StatusInternalServerError) return } - data := antragListData{Title: "Meine Anträge", Nav: navFor(r)} + q := strings.TrimSpace(r.URL.Query().Get("q")) + var gefiltert []store.Antrag for _, a := range list { + if matchesQuery(q, a.Titel, a.Status, a.Haeufigkeit) { + gefiltert = append(gefiltert, a) + } + } + pag := paginationFromRequest(r, len(gefiltert)) + data := antragListData{Title: "Meine Anträge", Nav: navFor(r), Suche: q, Pagination: pag} + for _, a := range paginate(gefiltert, pag) { data.Antraege = append(data.Antraege, antragListItem{ ID: a.ID, Titel: a.Titel, Status: a.Status, Haeufigkeit: a.Haeufigkeit, CreatedAt: a.CreatedAt.Format("02.01.2006 15:04"), diff --git a/internal/web/betreiber_handlers.go b/internal/web/betreiber_handlers.go index bad1881..08490c7 100644 --- a/internal/web/betreiber_handlers.go +++ b/internal/web/betreiber_handlers.go @@ -2,9 +2,11 @@ package web import ( "net/http" + "strings" "time" "github.com/netcell-it/deklarix/internal/auth" + "github.com/netcell-it/deklarix/internal/store" ) type betreiberDashboardData struct { @@ -52,9 +54,11 @@ type betreiberAccountListItem struct { } type betreiberAccountListData struct { - Title string - Nav navData - Accounts []betreiberAccountListItem + Title string + Nav navData + Accounts []betreiberAccountListItem + Suche string + Pagination pagination } // handleBetreiberAccountList listet alle Mandanten der Plattform. @@ -64,8 +68,16 @@ func (s *Server) handleBetreiberAccountList(w http.ResponseWriter, r *http.Reque http.Error(w, "Accounts konnten nicht geladen werden: "+err.Error(), http.StatusInternalServerError) return } - data := betreiberAccountListData{Title: "Accounts", Nav: navFor(r)} + q := strings.TrimSpace(r.URL.Query().Get("q")) + var gefiltert []store.Account for _, a := range accounts { + if matchesQuery(q, a.Name) { + gefiltert = append(gefiltert, a) + } + } + pag := paginationFromRequest(r, len(gefiltert)) + data := betreiberAccountListData{Title: "Accounts", Nav: navFor(r), Suche: q, Pagination: pag} + for _, a := range paginate(gefiltert, pag) { data.Accounts = append(data.Accounts, betreiberAccountListItem{ ID: a.ID, Name: a.Name, CreatedAt: a.CreatedAt.Format("02.01.2006 15:04"), }) @@ -218,20 +230,37 @@ type betreiberAuditEntryView struct { } type betreiberAuditLogData struct { - Title string - Nav navData - Entries []betreiberAuditEntryView + Title string + Nav navData + Entries []betreiberAuditEntryView + Suche string + Pagination pagination } +// auditLogFetchLimit begrenzt, wie viele der neuesten Einträge aus der +// DB geholt werden, bevor im Go-Code gefiltert/paginiert wird — echte +// DB-seitige Offset-Paginierung wäre für ein potenziell sehr groß +// werdendes Audit-Log der sauberere Ansatz, ist hier aber (noch) nicht +// umgesetzt (siehe CLAUDE.md, Offene Punkte). +const auditLogFetchLimit = 1000 + // handleBetreiberAuditLog zeigt das plattformweite Audit-Log. func (s *Server) handleBetreiberAuditLog(w http.ResponseWriter, r *http.Request) { - entries, err := s.store.ListAuditLog(r.Context(), 200) + entries, err := s.store.ListAuditLog(r.Context(), auditLogFetchLimit) if err != nil { http.Error(w, "Audit-Log konnte nicht geladen werden: "+err.Error(), http.StatusInternalServerError) return } - data := betreiberAuditLogData{Title: "Audit-Log", Nav: navFor(r)} + q := strings.TrimSpace(r.URL.Query().Get("q")) + var gefiltert []store.AuditEntry for _, e := range entries { + if matchesQuery(q, e.Action, e.TargetType, e.Details) { + gefiltert = append(gefiltert, e) + } + } + pag := paginationFromRequest(r, len(gefiltert)) + data := betreiberAuditLogData{Title: "Audit-Log", Nav: navFor(r), Suche: q, Pagination: pag} + for _, e := range paginate(gefiltert, pag) { data.Entries = append(data.Entries, betreiberAuditEntryView{ CreatedAt: e.CreatedAt.Format("02.01.2006 15:04:05"), Action: e.Action, TargetType: e.TargetType, TargetID: e.TargetID, Details: e.Details, diff --git a/internal/web/templates/antraege_liste.html b/internal/web/templates/antraege_liste.html index 3d067c3..3e99afd 100644 --- a/internal/web/templates/antraege_liste.html +++ b/internal/web/templates/antraege_liste.html @@ -4,22 +4,42 @@ {{template "nav" .Nav}}
-

Meine Anträge

-{{if not .Antraege}} -

Noch keine Anträge gestellt.

-{{else}} - -{{end}} -

Neuen Antrag stellen

+
diff --git a/internal/web/templates/betreiber_accounts.html b/internal/web/templates/betreiber_accounts.html index 57ca13b..463aa92 100644 --- a/internal/web/templates/betreiber_accounts.html +++ b/internal/web/templates/betreiber_accounts.html @@ -5,9 +5,20 @@ {{template "nav" .Nav}}

← Plattform

-

Accounts

+ +
+ + + {{if .Suche}}Zurücksetzen{{end}} +
{{if not .Accounts}} -

Noch keine Accounts.

+

{{if .Suche}}Keine Treffer für diese Suche.{{else}}Noch keine Accounts.{{end}}

{{else}}
    {{range .Accounts}} @@ -18,8 +29,26 @@ {{end}}
+ {{end}} -

Firma anlegen

diff --git a/internal/web/templates/betreiber_audit_log.html b/internal/web/templates/betreiber_audit_log.html index aba6a62..f547355 100644 --- a/internal/web/templates/betreiber_audit_log.html +++ b/internal/web/templates/betreiber_audit_log.html @@ -5,9 +5,19 @@ {{template "nav" .Nav}}

← Plattform

-

Audit-Log

+ +
+ + + {{if .Suche}}Zurücksetzen{{end}} +
{{if not .Entries}} -

Noch keine Einträge.

+

{{if .Suche}}Keine Treffer für diese Suche.{{else}}Noch keine Einträge.{{end}}

{{else}}
    {{range .Entries}} @@ -17,6 +27,25 @@ {{end}}
+ {{end}}
diff --git a/internal/web/templates/wiedervorlage_liste.html b/internal/web/templates/wiedervorlage_liste.html index 6fc2c30..91b853c 100644 --- a/internal/web/templates/wiedervorlage_liste.html +++ b/internal/web/templates/wiedervorlage_liste.html @@ -4,11 +4,15 @@ {{template "nav" .Nav}}
-

Wiedervorlage

-

- Genehmigungen, die abgelaufen sind, bald ablaufen, oder deren - Werkzeug sich seit der Entscheidung im Katalog geändert hat. -

+ {{if not .Eintraege}}

Nichts zur Wiedervorlage.

{{else}}