fix: batch tag queries, inline edit, delete response, SPA catch-all, link glyph

- Fix N+1 tag query in List() with batched IN clause
- Add inline body editing in web detail pane (dblclick or e key)
- Delete API returns {result: "soft"|"hard"} with 200 instead of 204
- SPA handler serves index.html for all extensionless paths
- Link glyph changed from emoji 🔗 to unicode ↗ for terminal alignment
- Capture bar contrast and hover glow increased
- Comment on load-bearing "--" in root.go
This commit is contained in:
2026-05-14 12:37:13 -04:00
parent 5b0d0a8f33
commit 03094706c3
9 changed files with 152 additions and 23 deletions
+13 -4
View File
@@ -235,16 +235,25 @@ func TestDeleteEntity_SoftThenHard(t *testing.T) {
// Soft delete
req, _ := http.NewRequest("DELETE", srv.URL+"/api/entities/"+created.ID, nil)
resp, _ := http.DefaultClient.Do(req)
var delResp DeleteResponse
json.NewDecoder(resp.Body).Decode(&delResp)
resp.Body.Close()
if resp.StatusCode != http.StatusNoContent {
t.Fatalf("soft delete: expected 204, got %d", resp.StatusCode)
if resp.StatusCode != http.StatusOK {
t.Fatalf("soft delete: expected 200, got %d", resp.StatusCode)
}
if delResp.Result != "soft" {
t.Fatalf("soft delete: expected result 'soft', got %q", delResp.Result)
}
// Hard delete
resp, _ = http.DefaultClient.Do(req)
json.NewDecoder(resp.Body).Decode(&delResp)
resp.Body.Close()
if resp.StatusCode != http.StatusNoContent {
t.Fatalf("hard delete: expected 204, got %d", resp.StatusCode)
if resp.StatusCode != http.StatusOK {
t.Fatalf("hard delete: expected 200, got %d", resp.StatusCode)
}
if delResp.Result != "hard" {
t.Fatalf("hard delete: expected result 'hard', got %q", delResp.Result)
}
// Gone
+10 -2
View File
@@ -214,10 +214,14 @@ func updateEntity(store *db.Store) http.HandlerFunc {
}
}
type DeleteResponse struct {
Result string `json:"result"`
}
func deleteEntity(store *db.Store) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
id := chi.URLParam(r, "id")
_, err := store.SoftDelete(id)
result, err := store.SoftDelete(id)
if err != nil {
if err == db.ErrNotFound {
writeError(w, http.StatusNotFound, "not_found", "no entity with id "+id)
@@ -226,7 +230,11 @@ func deleteEntity(store *db.Store) http.HandlerFunc {
writeError(w, http.StatusInternalServerError, "internal", err.Error())
return
}
w.WriteHeader(http.StatusNoContent)
label := "soft"
if result == db.DeletedHard {
label = "hard"
}
writeJSON(w, http.StatusOK, DeleteResponse{Result: label})
}
}
+3 -2
View File
@@ -3,6 +3,7 @@ package api
import (
"io/fs"
"net/http"
"path"
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
@@ -45,8 +46,8 @@ func spaHandler(fsys fs.FS) http.HandlerFunc {
indexHTML, _ := fs.ReadFile(fsys, "index.html")
return func(w http.ResponseWriter, r *http.Request) {
path := r.URL.Path
if path == "/" || path == "/cards" {
p := r.URL.Path
if p == "/" || path.Ext(p) == "" {
w.Header().Set("Content-Type", "text/html; charset=utf-8")
w.Write(indexHTML)
return