From 9fceae63fc2f78645a275ddfd481c8daf9707e62 Mon Sep 17 00:00:00 2001 From: Quick <31828688+Quick104@users.noreply.github.com> Date: Thu, 28 May 2026 20:26:15 -0400 Subject: [PATCH] fix(metadata): persist a cleared air_timezone instead of skipping it Clearing a previously-set air timezone sent JSON null, which decodes to a nil *string that UpdateMetadata treats as "skip this column", so the old value remained. The dialog now sends "" (accepted by ValidateAirTimezone), and UpdateMetadata maps air_timezone through NULLIF so an empty value persists as SQL NULL (matching the nullable column) rather than "". Addresses PR #21 review (P2). Co-Authored-By: Claude Opus 4.8 (1M context) --- internal/catalog/item_repo.go | 11 ++++++++++- web/src/components/EditMetadataDialog.tsx | 5 ++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/internal/catalog/item_repo.go b/internal/catalog/item_repo.go index 2b917837..e6b31719 100644 --- a/internal/catalog/item_repo.go +++ b/internal/catalog/item_repo.go @@ -1240,6 +1240,15 @@ func (r *ItemRepository) UpdateMetadata(ctx context.Context, contentID string, u argIdx++ } } + // addNullableString behaves like addString but stores an empty string as SQL + // NULL (via NULLIF), so clearing a nullable column persists as NULL. + addNullableString := func(col string, val *string) { + if val != nil { + setClauses = append(setClauses, fmt.Sprintf("%s = NULLIF($%d, '')", col, argIdx)) + args = append(args, *val) + argIdx++ + } + } addInt := func(col string, val *int) { if val != nil { setClauses = append(setClauses, fmt.Sprintf("%s = $%d", col, argIdx)) @@ -1289,7 +1298,7 @@ func (r *ItemRepository) UpdateMetadata(ctx context.Context, contentID string, u addString("first_air_date", upd.FirstAirDate) addString("last_air_date", upd.LastAirDate) addString("air_time", upd.AirTime) - addString("air_timezone", upd.AirTimezone) + addNullableString("air_timezone", upd.AirTimezone) addString("status", upd.Status) addString("show_status", upd.ShowStatus) addString("imdb_id", upd.ImdbID) diff --git a/web/src/components/EditMetadataDialog.tsx b/web/src/components/EditMetadataDialog.tsx index 9d54429d..053da6e0 100644 --- a/web/src/components/EditMetadataDialog.tsx +++ b/web/src/components/EditMetadataDialog.tsx @@ -185,7 +185,10 @@ export default function EditMetadataDialog({ item, open, onOpenChange }: EditMet data.last_air_date = form.last_air_date || null; if (form.air_time !== originalForm.air_time) data.air_time = form.air_time || null; if (form.air_timezone !== originalForm.air_timezone) - data.air_timezone = form.air_timezone || null; + // Send "" (not null) when cleared: the server treats null as "skip", so + // clearing a previously-set timezone would not persist. "" is accepted by + // validation and normalized to NULL server-side. + data.air_timezone = form.air_timezone; if (form.air_date !== originalForm.air_date) data.air_date = form.air_date || null; if (form.status !== originalForm.status) data.status = form.status; if (form.rating_imdb !== originalForm.rating_imdb) data.rating_imdb = form.rating_imdb;