feat(saved): saved-message labels + filter chips (LC-479) #484
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/LC-479-saved-labels"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
LC-479 - Saved-message labels / folders
Lets users tag saved messages (e.g.
follow-up,read-later) and filter the/savedpage by label. Buckets in the spirit of Slack's "Later".Data
0074_bookmark_labels.sql:ALTER TABLE bookmarks ADD COLUMN label TEXT(nullable; NULL = unlabeled). The table is already user-scoped via its composite PK, so a label is private to the owning user.db::bookmarks::set_label(user, message, Option<&str>)updates/clears only the owner's row;bookmarks_for_userselects the label intoBookmarkRow.Editing
/savedrow has an inline label<input>that posts on change toPOST /messages/{id}/bookmark/label. The handler trims, caps at 40 chars (empty = clear), stores, and broadcastsSavedChangedso every/savedtab re-renders its list + chips over the existing WebSocket path (request returns 204; the form ishx-swap="none").Filtering
SavedPage::labels()+has_unlabeled()(shared by the page and the OOB fragment, so a live refresh keeps them in sync).data-lc-saved-label, so the server never needs to know each tab's active filter. The active filter is stored on the stable#lc-saved-wrap(which the live swap does not replace) and re-applied on everyhtmx:afterSettle, so it survives aSavedChangedrefresh. A filter whose label disappears falls back to All.Tests
db_bookmarks:set_labelround-trip (set -> clear) and owner-scoping (one user's label does not touch another's bookmark of the same message).just check,just test,just test-saasall pass (i18n catalog parity covers the four new en/es keys). No test hand-builds these view/db structs, so no contract drift; new migration is picked up automatically by thecommon::chat_pool()migrator.Not operator-visible (no env/config/contract change).
🤖 Generated with Claude Code
POST /messages/{id}/bookmark/label sets/clears the label (trim, 40-char cap, empty = clear) and broadcasts SavedChanged so every /saved tab re-renders over WS (request returns 204; form is hx-swap=none). SavedListRow carries the label; SavedPage/SavedListFragment expose labels()/has_unlabeled() for the shared items partial. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>