diff --git a/internal/admin/admin.go b/internal/admin/admin.go index d22de0a..b8460c3 100644 --- a/internal/admin/admin.go +++ b/internal/admin/admin.go @@ -187,7 +187,7 @@ func Register(mux *http.ServeMux, d Deps) { }) }) - // Actions (HTMX POSTs) + // CREATE mux.HandleFunc("/admin/items/create", func(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { http.Error(w, "method not allowed", http.StatusMethodNotAllowed) @@ -196,12 +196,13 @@ func Register(mux *http.ServeMux, d Deps) { name := strings.TrimSpace(r.FormValue("name")) if name != "" { _, _ = d.Store.Create(r.Context(), name) - _ = d.Mesh.SyncNow(r.Context()) // prompt push (best effort) + _ = d.Mesh.SyncNow(r.Context()) } - // Nach Aktion Items partial zurückgeben (HTMX swap) - http.Redirect(w, r, "/admin", http.StatusSeeOther) + // statt Redirect: + renderItemsPartial(w, r, d) }) + // RENAME mux.HandleFunc("/admin/items/rename", func(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { http.Error(w, "method not allowed", http.StatusMethodNotAllowed) @@ -213,21 +214,22 @@ func Register(mux *http.ServeMux, d Deps) { _, _ = d.Store.Rename(r.Context(), filesvc.ID(id), newName) _ = d.Mesh.SyncNow(r.Context()) } - http.Redirect(w, r, "/admin", http.StatusSeeOther) //hier test nicht mehr /admin/items + renderItemsPartial(w, r, d) }) + // DELETE mux.HandleFunc("/admin/items/delete", func(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { http.Error(w, "method not allowed", http.StatusMethodNotAllowed) return } - - if id64, err := strconv.ParseInt(r.FormValue("id"), 10, 64); err == nil { + id64, err := strconv.ParseInt(r.FormValue("id"), 10, 64) + if err == nil { _, _ = d.Store.Delete(r.Context(), filesvc.ID(id64)) - _ = d.Blob.Delete(r.Context(), id64) // <— Blob löschen + _ = d.Blob.Delete(r.Context(), id64) // Blob wirklich löschen _ = d.Mesh.SyncNow(r.Context()) } - http.Redirect(w, r, "/admin", http.StatusSeeOther) + renderItemsPartial(w, r, d) }) mux.HandleFunc("/admin/mesh/syncnow", func(w http.ResponseWriter, r *http.Request) { @@ -258,3 +260,40 @@ func BasicAuth(user, pass string, next http.Handler) http.Handler { next.ServeHTTP(w, r) }) } + +// rebuild & render items partial for HTMX swaps +func renderItemsPartial(w http.ResponseWriter, r *http.Request, d Deps) { + type row struct { + ID int64 + Name string + UpdatedAt int64 + HasBlob bool + Size int64 + } + + nextQ := strings.TrimSpace(r.URL.Query().Get("next")) + var nextID filesvc.ID + if nextQ != "" { + if n, err := strconv.ParseInt(nextQ, 10, 64); err == nil { + nextID = filesvc.ID(n) + } + } + items, nextOut, _ := d.Store.List(r.Context(), nextID, 100) + + rows := make([]row, 0, len(items)) + for _, it := range items { + meta, ok, _ := d.Blob.Stat(r.Context(), int64(it.ID)) + rows = append(rows, row{ + ID: int64(it.ID), + Name: it.Name, + UpdatedAt: it.UpdatedAt, + HasBlob: ok, + Size: meta.Size, + }) + } + w.Header().Set("Content-Type", "text/html; charset=utf-8") + _ = tplItems.Execute(w, map[string]any{ + "Items": rows, + "Next": nextOut, + }) +} diff --git a/internal/admin/tpl/partials_items.html b/internal/admin/tpl/partials_items.html index 630096a..5a2d8d1 100644 --- a/internal/admin/tpl/partials_items.html +++ b/internal/admin/tpl/partials_items.html @@ -1,6 +1,6 @@