feat: add edit/delete buttons to list views and inline privacy toggle
Fave cards in the list and profile views now show edit, delete, and
privacy toggle buttons directly — no need to open the detail page first.
- New POST /faves/{id}/privacy route with HTMX privacy toggle partial
- New UpdatePrivacy store method for single-column update
- fave_list.html: edit link, HTMX delete, privacy toggle on every card
- profile.html: edit/delete for owner's own cards
- privacy_toggle.html: new HTMX partial that swaps inline on toggle
- CSS: compact .fave-card-actions styles
The existing handleFaveDelete already returns empty 200 for HTMX
requests, so hx-target="closest article" hx-swap="outerHTML" removes
the card from DOM seamlessly.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
1260cfd18f
commit
b186fb4bc5
9 changed files with 360 additions and 3 deletions
|
|
@ -335,6 +335,51 @@ func (h *Handler) handleFaveDelete(w http.ResponseWriter, r *http.Request) {
|
|||
http.Redirect(w, r, h.deps.Config.BasePath+"/faves", http.StatusSeeOther)
|
||||
}
|
||||
|
||||
// handleFaveTogglePrivacy toggles a fave's privacy and returns the updated toggle partial.
|
||||
func (h *Handler) handleFaveTogglePrivacy(w http.ResponseWriter, r *http.Request) {
|
||||
user := middleware.UserFromContext(r.Context())
|
||||
|
||||
id, err := strconv.ParseInt(r.PathValue("id"), 10, 64)
|
||||
if err != nil {
|
||||
h.notFound(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
fave, err := h.deps.Faves.GetByID(id)
|
||||
if err != nil {
|
||||
if errors.Is(err, store.ErrFaveNotFound) {
|
||||
h.notFound(w, r)
|
||||
return
|
||||
}
|
||||
slog.Error("get fave error", "error", err)
|
||||
http.Error(w, "Internal error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
if user.ID != fave.UserID {
|
||||
h.forbidden(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
newPrivacy := "private"
|
||||
if fave.Privacy == "private" {
|
||||
newPrivacy = "public"
|
||||
}
|
||||
|
||||
if err := h.deps.Faves.UpdatePrivacy(id, newPrivacy); err != nil {
|
||||
slog.Error("toggle privacy error", "error", err)
|
||||
http.Error(w, "Internal error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
fave.Privacy = newPrivacy
|
||||
|
||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
if err := h.deps.Renderer.Partial(w, "privacy_toggle", fave); err != nil {
|
||||
slog.Error("render privacy toggle error", "error", err)
|
||||
}
|
||||
}
|
||||
|
||||
// handleTagSearch handles tag autocomplete HTMX requests.
|
||||
func (h *Handler) handleTagSearch(w http.ResponseWriter, r *http.Request) {
|
||||
q := r.URL.Query().Get("q")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue