Skip to content

feat: show a film's custom field values on its detail page - #763

Merged
helmerzNL merged 1 commit into
release/v26-betafrom
claude/issue-719-review-features-u9cbuh
Sep 3, 2026
Merged

feat: show a film's custom field values on its detail page#763
helmerzNL merged 1 commit into
release/v26-betafrom
claude/issue-719-review-features-u9cbuh

Conversation

@helmerzNL

Copy link
Copy Markdown
Owner

Closes #762. Asked for by @jeff363b on #719: "is there a plan to show the custom fields on the data card when viewing the data? Right now, I have to go into edit to see what it is."

What

A custom-fields subsection on the film detail page, in the Collectors tab.

Why

Custom fields shipped in 26.9.98 filterable in advanced search, sortable in the wide list, and present in exports — and unreadable on the one screen dedicated to a single film. Reading a value meant opening the edit form, which is a writing surface: you enter it to change something, and leaving it is a decision about whether to save. That is the wrong shape for the field's most common use, which is simply wanting to know what it says.

Collectors is where it belongs rather than a panel of its own: it already holds the owner-managed facts — location, storage location, edition — and a custom field is one of those.

How

No new endpoint and no new request. The definitions already arrive on the dashboard snapshot as customFields; the values already arrive on the detail payload as movie.custom_values. Both halves are in memory when the page draws.

Rendering reuses what exists: movieCustomValueMap, customValueDisplay (the same formatter the export and list columns use), and detailFieldSubsection — a helper written for exactly this and with no caller until now.

Three decisions worth naming:

  • Archived definitions are shown when they carry a value — the opposite of the edit form, on purpose. Archiving means "no new input", not "invisible": the value keeps matching filters and keeps appearing in exports (contract §4e.5), so hiding it here would conceal data the rest of the app still acts on.
  • A film with no values renders no section, not a heading over nothing. detailFieldSubsection returns "" when it produces no rows, which also covers an instance that has defined no fields at all.
  • The heading is translated; the field names are not. The owner typed those. movieDetail.customFields reuses the wording each locale already uses for the admin tab, so one concept does not end up with two names in the same UI.

Order comes from the server (movie_custom_values sorts by sort_order, key), so it matches what the owner set in Admin → Custom fields.

Tests

Seven in tests/test_next_custom_fields_ui.py, bounded to the new renderer so an assertion about what it does not do cannot be satisfied by its neighbour:

  • the block exists and the detail render fills it;
  • it reads values off the movie and definitions off the snapshot, and issues no request;
  • values go through customValueDisplay;
  • an archived field holding a value is still shown;
  • no values means no section;
  • the heading is translated and the names are not;
  • the heading exists in all 29 locales.

Full backend suite green against a local PostgreSQL 16 with all migrations applied (3,465 tests, 2 skipped), as is scripts/check_undefined_names.py.

Deployment-file changes

No deployment-file changes in this PR.

Documentation

To be recorded in App-Guidance (projects/discvault/specs/custom-fields.md): the surfaces a value reaches now include the detail page, and the archived-but-shown rule differs there from the edit form. PR follows.

Translations

One new key, movieDetail.customFields, in all 29 locales, taking each catalogue's own existing wording for the admin tab.


📦 Change Spec — release notes (fill at merge)

version: ""
name: ""
headline: "Your own fields now show on a film's page"
highlights:
  - "A film's custom field values are visible on its page, without opening the edit form"
fixes: []
breaking: []
cta: ""
internal_only:
  - ""
  • Change Spec filled in, or this PR is internal-only (no user-facing release notes).

🤖 Generated with Claude Code

https://claude.ai/code/session_01PUwMZZ585LnTxaWMUuKVgT


Generated by Claude Code

Custom fields shipped in 26.9.98 filterable, sortable and exportable, and
unreadable on the one screen dedicated to a single film. Seeing what a film's
"shelf" or "rip status" held meant opening the edit form -- a writing surface
you enter to change something and then have to decide how to leave.

A subsection now sits in the Collectors tab, beside the other owner-managed
facts: location, storage location, edition. A custom field is one of those, and
it is read for the same reason.

Nothing new is fetched. The definitions already arrive on the dashboard
snapshot as `customFields` and the values on the detail payload as
`movie.custom_values`, so both halves are in memory when the page draws.

Three decisions worth naming:

- Archived definitions are shown when they carry a value, which is the opposite
  of the edit form. Archiving means "no new input", not "invisible": the value
  keeps matching filters and keeps exporting (contract 4e.5), so hiding it here
  would conceal data the rest of the app still acts on.
- A film with no values renders no section, not a heading over nothing --
  `detailFieldSubsection` returns "" when it produces no rows, which also
  covers an instance that has defined no fields at all. It was written for this
  and had no caller until now.
- The heading is translated; the field names are not. The owner typed those.
  `movieDetail.customFields` reuses the wording each locale already uses for
  the admin tab, so one concept does not end up with two names.

Closes #762.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PUwMZZ585LnTxaWMUuKVgT
@helmerzNL
helmerzNL merged commit ca616af into release/v26-beta Sep 3, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants