ui(sidebar): drop Title field, add bulk notes editor

The Title (user_title) field hadn't earned its place in the sidebar
form — the underlying column stays on the model but the editable
row + its draft state + commit handler are gone.

Bulk Notes: a textarea in the multi-photo bulk panel that replaces
user_notes across the whole selection with one string. Apply commits;
Clear empties the draft without committing. New backend bulk action
'set_notes' validates the value is a string (or null/empty to clear)
and writes to every photo in the selection in one go. Wired through
the standard useBulkPhotoMutations optimistic-patch path, so the
photo cache flips immediately and rolls back on error.

user_notes added to the shared Photo type so patchPhotos accepts the
field; previously it was only on PhotoInfoPanel's local PhotoDetails.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Claudio
2026-05-11 00:07:02 +02:00
parent c69322a89d
commit f743733edd
6 changed files with 91 additions and 31 deletions

View File

@@ -1252,6 +1252,18 @@ async def bulk_action(
elif action.action == 'set_color':
for photo in photos:
photo.color_label = action.value
elif action.action == 'set_notes':
# value is the replacement notes string (empty string clears).
# Sent verbatim — no whitespace trimming, callers can pre-trim
# client-side if they want.
if action.value is not None and not isinstance(action.value, str):
raise HTTPException(
status_code=400,
detail="set_notes requires a string value (or null to clear)",
)
new_notes = action.value or None # empty string -> null
for photo in photos:
photo.user_notes = new_notes
elif action.action in ('set_taken_at', 'set_taken_at_map'):
# Two shapes share one code path:
# set_taken_at → value is one ISO datetime, applied to every id