This commit is contained in:
@@ -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,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<div class="row">
|
||||
<div style="flex: 1 1 360px">
|
||||
<form hx-post="/admin/items/create" hx-target="#items" hx-get="/admin/items" hx-swap="outerHTML">
|
||||
<form hx-post="/admin/items/create" hx-target="#items" hx-swap="outerHTML">
|
||||
<label>Neue leere Datei (nur Metadaten)</label>
|
||||
<div style="display:flex; gap:8px; margin-top:6px">
|
||||
<input type="text" name="name" placeholder="z.B. notes.txt" required>
|
||||
@@ -42,17 +42,17 @@
|
||||
{{ end }}
|
||||
</td>
|
||||
<td>
|
||||
<form style="display:inline-flex; gap:6px"
|
||||
hx-post="/admin/items/rename"
|
||||
hx-target="#items" hx-get="/admin/items" hx-swap="outerHTML">
|
||||
<form style="display:inline-flex; gap:6px"
|
||||
hx-post="/admin/items/rename"
|
||||
hx-target="#items" hx-swap="outerHTML">
|
||||
<input type="hidden" name="id" value="{{ .ID }}">
|
||||
<input type="text" name="name" placeholder="Neuer Name">
|
||||
<button class="btn" type="submit">Rename</button>
|
||||
</form>
|
||||
<form style="display:inline"
|
||||
hx-post="/admin/items/delete"
|
||||
hx-target="#items" hx-get="/admin/items" hx-swap="outerHTML"
|
||||
onsubmit="return confirm('Wirklich löschen (inkl. Blob)?');">
|
||||
<form style="display:inline"
|
||||
hx-post="/admin/items/delete"
|
||||
hx-target="#items" hx-swap="outerHTML"
|
||||
onsubmit="return confirm('Wirklich löschen (inkl. Blob)?');">
|
||||
<input type="hidden" name="id" value="{{ .ID }}">
|
||||
<button class="btn" type="submit">Delete</button>
|
||||
</form>
|
||||
|
||||
Reference in New Issue
Block a user