mirror of
https://github.com/thegeneralist01/archivr
synced 2026-07-22 03:05:32 +02:00
feat: tag delete, rename, and per-user humanize-tags display setting (#16)
* feat: add tag delete and rename (backend + frontend)
- DELETE /api/archives/:id/tags/:tag_uid — deletes tag subtree via
recursive CTE; entry_tag_assignments cascade automatically
- PATCH /api/archives/:id/tags/:tag_uid { name } — renames a tag
segment (case-preserving slug), cascades full_path to all descendants
in one transaction using hierarchy CTE (not LIKE), returns updated Tag
- database: rename_tag + delete_tag with 7 unit tests covering subtree
cascade, collision detection, descendant path rewrite, slug stripping
- TagsView: inline rename (pencil icon / double-click → input), × delete
with confirmation dialog (warns about child tags)
- App.jsx: handleTagRenamed rewrites tagFilter for exact + descendant
paths; handleTagDeleted clears filter for deleted subtree
- api.js: renameTag (PATCH, returns Tag) + deleteTag (DELETE)
- ContextRail: tag pills show displayPath(full_path) (humanized) with
raw full_path in title tooltip; humanize-tags setting coming next
* feat: per-user humanize-tags display setting
- auth DB: idempotent migration adds users.humanize_slugs INTEGER DEFAULT 0
- GET /api/auth/me: returns humanize_slugs bool
- PATCH /api/auth/me: accepts { humanize_slugs: bool }, persisted via
database::update_user_humanize_slugs
- displayPath() helper moved to utils.js (was local to ContextRail)
- TagsView: node label shows tag.name vs tag.slug based on humanizeTags
- ContextRail: pill label applies displayPath conditionally
- App.jsx: derives humanizeTags from currentUser.humanize_slugs, passes
to TagsView + ContextRail; filter badge label humanized when on
- Settings > Profile: Display Preferences section with checkbox toggle,
updates backend and currentUser immediately via setCurrentUser
- api.js: patchMe(patch) for generic PATCH /api/auth/me
- Tests: auth_me default=false, PATCH persists=true (2 route tests)
This commit is contained in:
parent
d6b52ba06c
commit
55f85134df
13 changed files with 699 additions and 69 deletions
|
|
@ -673,6 +673,56 @@ select {
|
|||
.tag-node-btn:hover { text-decoration: underline; }
|
||||
.tag-node-btn.is-active { font-weight: 600; color: var(--ink); }
|
||||
|
||||
/* tag-node-row: flex row containing the name button + delete × */
|
||||
.tag-node-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
.tag-node-row .tag-node-btn {
|
||||
flex: 1 1 0;
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
width: auto;
|
||||
}
|
||||
/* constrain the edit pencil so it doesn't inherit unconstrained SVG dimensions */
|
||||
.tag-node-btn .edit-icon {
|
||||
width: 0.75em;
|
||||
height: 0.75em;
|
||||
flex-shrink: 0;
|
||||
vertical-align: -0.1em;
|
||||
opacity: 0.35;
|
||||
}
|
||||
.tag-node-btn:hover .edit-icon { opacity: 0.65; }
|
||||
/* delete × button next to tag name — small, unobtrusive */
|
||||
.tag-node-delete {
|
||||
flex-shrink: 0;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
color: var(--muted-2);
|
||||
cursor: pointer;
|
||||
padding: 0 3px;
|
||||
font-size: 14px;
|
||||
line-height: 1;
|
||||
opacity: 0;
|
||||
}
|
||||
.tag-node-row:hover .tag-node-delete { opacity: 1; }
|
||||
.tag-node-delete:hover { color: var(--accent); }
|
||||
/* rename input inside the tag list */
|
||||
.tag-rename-input {
|
||||
font-size: 13px;
|
||||
flex: 1 1 0;
|
||||
min-width: 0;
|
||||
padding: 2px 5px;
|
||||
border: 1px solid var(--accent);
|
||||
border-radius: var(--r);
|
||||
background: var(--field);
|
||||
color: var(--ink);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/* ── Collections page (sidebar layout) ──────────────────────────────────── */
|
||||
.collections-view {
|
||||
padding: 24px;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue