Skip to content

Roadmap 29-33 Discogs review UI#49

Merged
Fredoq merged 3 commits into
mainfrom
roadmap-29-discogs-release-ui
Jun 4, 2026
Merged

Roadmap 29-33 Discogs review UI#49
Fredoq merged 3 commits into
mainfrom
roadmap-29-discogs-release-ui

Conversation

@Fredoq
Copy link
Copy Markdown
Owner

@Fredoq Fredoq commented Jun 4, 2026

Summary

  • Adds Discogs review UI for release, artist, and track metadata workflows.
  • Adds external metadata API client support for Discogs artist, release, and track lookup/detail responses.
  • Extends artist/release/track models and submit mapping with external source provenance.
  • Adds multi-role credit editing, compact Discogs review panels, scrollable role picker menus, and safer draft apply feedback.
  • Keeps Discogs data as review-only form state until the user saves the record.

Validation

  • npm run format:check
  • npm run lint
  • npm run typecheck
  • npm test -- src/features/catalog/externalMetadataClient.test.ts src/App.discogs-release-autocomplete.test.tsx
  • npm run build
  • git diff --check

Also visually checked the role picker popover in the local browser: the custom menu uses max-height and overflow-y auto, so long role lists scroll.

Summary by CodeRabbit

Release Notes

  • New Features

    • Added Discogs integration for artist, release, and track lookup with review and apply workflows
    • Introduced support for multiple artist credit roles per credit
    • Added release date field to release forms
    • Added "Update via Discogs" action buttons in detail panels
    • Enhanced responsive design for mobile and small-screen layouts
  • Documentation

    • Updated design system with Discogs release review requirements and UI flow specifications

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 4, 2026

Review Change Stack

Warning

Review limit reached

@Fredoq, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 60 minutes. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ae4bc511-cca8-460b-925a-5732b56b89e7

📥 Commits

Reviewing files that changed from the base of the PR and between 7a7fa50 and 12d932f.

📒 Files selected for processing (24)
  • .superdesign/design-system.md
  • src/App.catalog-actions.cases.ts
  • src/App.catalog-actions.test.tsx
  • src/App.release-entry-basics.test.tsx
  • src/App.release-entry-tracklist.test.tsx
  • src/app/AuthenticatedApp.tsx
  • src/features/artists/DiscogsArtistLookupPanel.tsx
  • src/features/catalog/api/catalogEntityMappers.ts
  • src/features/catalog/api/catalogTypes.ts
  • src/features/catalog/api/catalogValueMappers.ts
  • src/features/releases/DiscogsCandidateReview.tsx
  • src/features/releases/DiscogsReleaseLookupPanel.tsx
  • src/features/releases/ReleaseArtistCreditsSection.tsx
  • src/features/releases/ReleaseDetail.tsx
  • src/features/releases/ReleaseEntryForm.tsx
  • src/features/releases/discogs-release-lookup.css
  • src/features/releases/discogsReleaseApply.ts
  • src/features/releases/discogsRoleUtils.ts
  • src/features/releases/release-form.css
  • src/features/releases/releases.css
  • src/features/tracks/TrackEntryForm.tsx
  • src/features/tracks/discogsTrackApply.ts
  • src/features/tracks/tracks.css
  • src/test/appTestHarness.ts
📝 Walkthrough

Walkthrough

This PR adds comprehensive Discogs external metadata integration across artist, release, and track entities. It introduces search → review → apply workflows with compile-aware tracklist handling, multi-role credit support, and full-catalog hydration for workspace navigation.

Changes

Discogs external metadata integration for artists, releases, and tracks

Layer / File(s) Summary
Design system Discogs requirements
.superdesign/design-system.md
Specifies end-to-end Discogs lookup UI flow, review-before-apply mandate, barcode/identifier prohibition, and compilation/Various Artists handling rules.
External metadata API infrastructure
src/features/catalog/api/externalMetadataClient.ts, src/features/catalog/api/catalogTypes.ts, src/features/catalog/catalogApi.ts, src/features/catalog/externalMetadataClient.test.ts
New externalMetadataClient module defines search/detail DTOs and exports async functions for Discogs release/artist/track search and detail retrieval with URL trimming and collection-id validation.
Error handling for rate limits
src/features/catalog/api/httpClient.ts
CatalogApiError captures HTTP Retry-After header for display of rate-limit messaging in Discogs UI.
Catalog data models extended
src/features/catalog/api/catalogTypes.ts
ArtistDto, ReleaseDto, TrackDto gain externalSources field; credit DTOs gain roles array to support multi-role per-artist.
Catalog mappers for new fields
src/features/catalog/api/catalogEntityMappers.ts, src/features/catalog/api/catalogValueMappers.ts
toArtistRecord/toReleaseRecord/toTrackRecord include externalSources; toTrackCredit/toReleaseArtistCredit compute deduplicated roles and derive primary role; releaseArtistDisplay/releaseArtistCreditsFromDisplay use roles-aware main-artist detection.
Request mappers for roles
src/features/catalog/api/catalogRequestMappers.ts
toReleaseArtistCreditRequest and toTrackCreditRequest normalize roles array, set primary role from first, and populate roles in outgoing requests.
API client updates
src/features/catalog/api/artistLabelClient.ts, src/features/catalog/api/releaseClient.ts, src/features/catalog/api/trackClient.ts
createArtist/updateArtist, createRelease/updateRelease, createTrackRecord/updateTrack conditionally include externalSources when provided.
Artist Discogs flow
src/features/artists/DiscogsArtistLookupPanel.tsx, src/features/artists/ArtistsWorkspace.tsx, src/features/artists/ArtistDetail.tsx, src/features/artists/artistsData.ts, src/App.discogs-artist-autocomplete.test.tsx
New DiscogsArtistLookupPanel component searches, reviews, and applies Discogs artist data; workspace tracks Discogs mode and wires initial-show preference; ArtistRecord extends with externalSources; end-to-end tests verify create/update flows with external source metadata and appliedAt timestamps.
Release Discogs flow
src/features/releases/DiscogsReleaseLookupPanel.tsx, src/features/releases/ReleaseEntryForm.tsx, src/features/releases/ReleasesWorkspace.tsx, src/features/releases/ReleaseCoreSection.tsx, src/features/releases/ReleaseDetail.tsx, src/features/releases/releaseFormHelpers.ts, src/features/releases/releaseSubmit.ts, src/features/releases/releasesData.ts, src/features/releases/useReleaseTrackDrafts.ts, src/features/releases/discogsReleaseTrackRows.ts, src/App.discogs-release-autocomplete.test.tsx
DiscogsReleaseLookupPanel searches releases and renders impact preview for core/artists/labels/classification/tracklist; detects compilation-like track-artist mismatches; ReleaseEntryForm manages releaseDate, editable credits with roles, and Discogs draft application via helpers that group credits and apply tracklist; workspace tracks Discogs mode; ReleaseRecord extends with externalSources and releaseDate; tests verify multi-group apply, compilation detection, and saved state.
Track Discogs flow
src/features/tracks/DiscogsTrackLookupPanel.tsx, src/features/tracks/TrackEntryForm.tsx, src/features/tracks/TracksWorkspace.tsx, src/features/tracks/TrackDetail.tsx, src/features/tracks/tracksData.ts, src/features/tracks/trackDisplayHelpers.ts, src/App.discogs-track-autocomplete.test.tsx
DiscogsTrackLookupPanel searches tracks with release context and applies core/credits groups; TrackEntryForm uses multi-role credit array and handleApplyDiscogsDraft to group Discogs credits by artist; workspace tracks Discogs mode; TrackRecord extends with externalSources; tests verify barcode absence, review-before-apply, and saved state with credits mapping.
Multi-role credit UI components
src/features/releases/CreditRolePicker.tsx, src/features/releases/ReleaseArtistCreditsSection.tsx, src/features/releases/ReleaseTrackArtistCreditChip.tsx, src/features/releases/ReleaseTrackDetail.tsx, src/features/releases/ReleaseTracklistSection.tsx
CreditRolePicker dropdown for selecting available roles; ReleaseArtistCreditsSection/ReleaseTrackArtistCreditChip render role pills with removal buttons and picker for adding roles; callback types broadened to accept string|string[].
Workspace routing consolidation
src/app/AuthenticatedApp.tsx, src/app/renderWorkspace.tsx
AuthenticatedApp.fullCatalogRoutes populated with /artists, /labels, /owned-items, /playlists, /relations, /releases, /tracks; renderWorkspace removes server-backed entity workspace logic and updates routes to use client-based catalog workspace.
App integration tests
src/App.auth.test.tsx, src/App.catalog-actions.test.tsx, src/App.owned-items-inventory.test.tsx, src/App.relation-credit-navigation.test.tsx, src/App.search-v1.test.tsx, src/App.server-navigation.test.tsx
Auth/navigation tests updated: artist login uses emptyCatalogLoadResponses; /tracks workspace error test uses custom fetch returning 500; mutation tests use stateful fetch stubs; owned-items/relation-credit/search-v1 tests expanded to stub catalog endpoints; server-navigation tests added for Releases workspace and catalog hydration.
Catalog mutation tests
src/features/catalog/catalogApi.mutations.test.ts
New tests verify that create/update adapter calls for releases, artists, and tracks include provided externalSources in request payload.
CSS styling
src/features/releases/release-form.css, src/features/releases/release-tracklist.css, src/features/manualEntry/manual-entry.css, src/features/tracks/tracks.css, src/styles/responsive.css
release-form.css adds Discogs lookup styling and multi-role chip system with removal/add controls; responsive breakpoints added for narrow screens; track/manual-entry CSS adds single-column layouts; responsive.css adds table-scroll min-width.
Discogs utilities
src/features/releases/discogsReleaseTrackRows.ts, src/features/releases/discogsReleaseTrackRows.test.ts
discogsDraftTrackRows filters out non-track heading rows and renumbers positions 1-based.
Vitest configuration
vitest.config.ts
Disabled file-level parallelism and set per-test timeout to 10000ms for async external metadata tests.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related issues

Poem

🐰 Hops through Discogs with delight so bright,
Artists, releases, tracks—all in sight!
Review before apply, the rabbit's command,
External metadata, perfectly planned!

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch roadmap-29-discogs-release-ui

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7a7fa5010c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/features/tracks/TrackEntryForm.tsx Outdated
.split(',')
.map((part) => part.trim())
.filter(Boolean)
.map((part) => toCreditRole(part)),
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Translate Discogs track role codes before storing

When the Discogs track detail draft returns dictionary codes such as mainArtist (the client fixture for /api/external-metadata/discogs/tracks/... uses that shape), applying Credits stores the literal code because this path only trims with toCreditRole instead of resolving against dictionaries.creditRole like the release form does. The resulting track shows a mainArtist pill and hasMainArtistRole no longer recognizes it as the main artist in the UI, so Discogs track updates can leave credits/display state inconsistent until reloaded from the server.

Useful? React with 👍 / 👎.

Comment on lines +515 to +516
.split(',')
.map((part) => part.trim())
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve bracketed Discogs role text when applying

For Discogs roles that contain commas inside qualifiers, such as Written-By [Music, Lyrics], applying a release or tracklist draft splits the single role into Written-By [Music and Lyrics]. The review panel already avoids this with bracket-aware splitting, so users can review one role but persist broken role labels when they apply Artists or Tracklist from Discogs.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/features/catalog/api/catalogEntityMappers.ts (1)

145-155: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Roles array should deduplicate like the primary credit path.

The fallback credit mapping (lines 145-155) builds a roles array but doesn't deduplicate, while the primary path (via toReleaseArtistCreditcreditRolesFromDto) wraps the mapped roles in new Set(...) to deduplicate. If a credit has duplicate role codes or codes that map to the same label, the two paths will produce inconsistent results.

🔧 Recommended fix to deduplicate roles

Replace the inline mapping with a call to the shared helper:

       : credits.map((credit) => ({
           artistId: credit.contributorArtistId,
           artist:
             artistsById.get(credit.contributorArtistId)?.name ??
             credit.contributorName,
-          role: creditRoleLabel(credit.role, dictionaries),
-          roles: (credit.roles && credit.roles.length > 0
-            ? credit.roles
-            : [credit.role]
-          ).map((role) => creditRoleLabel(role, dictionaries)),
+          ...(() => {
+            const roles = creditRolesFromDto(credit, dictionaries)
+            return {
+              role: roles[0] ?? creditRoleLabel(credit.role, dictionaries),
+              roles,
+            }
+          })(),
         }))

Or import and call creditRolesFromDto directly to ensure consistency.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/catalog/api/catalogEntityMappers.ts` around lines 145 - 155, The
fallback mapping builds roles without deduplication causing inconsistency with
the primary path; replace the inline roles mapping with the shared helper
creditRolesFromDto (or call toReleaseArtistCredit) so role labels are deduped
the same way—i.e., pass the DTO role list into creditRolesFromDto (or reuse
toReleaseArtistCredit logic) and assign its result to roles instead of mapping
manually.
🧹 Nitpick comments (3)
src/app/AuthenticatedApp.tsx (1)

594-602: ⚡ Quick win

Deduplicate full-catalog route membership to avoid contract drift.

Line 594 redefines the same route set already exported as manualEntryRoutes in src/app/renderWorkspace.tsx (Lines 35-43). Keeping two independent sets can desynchronize hydration gating from workspace behavior. Reusing one source of truth avoids that class of routing bugs.

♻️ Proposed refactor
-const fullCatalogRoutes = new Set<AppRoutePath>([
-  '/artists',
-  '/labels',
-  '/owned-items',
-  '/playlists',
-  '/relations',
-  '/releases',
-  '/tracks',
-])
+const fullCatalogRoutes: ReadonlySet<AppRoutePath> = manualEntryRoutes
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/AuthenticatedApp.tsx` around lines 594 - 602, The duplicated
Set<AppRoutePath> declared as fullCatalogRoutes should be replaced with the
single exported manualEntryRoutes to avoid diverging route definitions; locate
the fullCatalogRoutes declaration in AuthenticatedApp.tsx and import/use
manualEntryRoutes (the exported symbol from renderWorkspace.tsx) instead of
redefining the route Set so hydration gating and workspace behavior share the
same source of truth.
src/features/tracks/TrackEntryForm.tsx (1)

503-531: ⚡ Quick win

Potential key collision in role pill rendering.

At line 504, the key uses only role, which could lead to React key collisions if a credit somehow has duplicate roles in its roles array (despite deduplication in the apply logic). Consider using key={${role}-${index}} or ensuring roles are always unique.

However, the grouping logic (lines 289-290) uses a Set to deduplicate roles, so duplicate roles within a single credit should not occur in practice. This is likely safe.

🔐 Defensive key generation
-                      {credit.roles.map((role) => (
+                      {credit.roles.map((role, roleIndex) => (
-                        <span className="release-artist-role-pill" key={role}>
+                        <span className="release-artist-role-pill" key={`${role}-${roleIndex}`}>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/tracks/TrackEntryForm.tsx` around lines 503 - 531, The role pill
list uses role as the React key (in credit.roles.map) which risks collisions if
duplicates appear; update the key to a stable composite (e.g., include the
parent credit id or the map index) such as combining credit.id and role (or role
and index) so each <span> rendered in credit.roles.map has a unique key; keep
the existing remove handler (setCredits/currentCredits/currentCredit.id)
unchanged.
src/features/releases/DiscogsReleaseLookupPanel.tsx (1)

742-788: ⚡ Quick win

Extract duplicated compilation detection logic to a shared utility.

This compilation detection logic (lines 742-788) is duplicated in ReleaseEntryForm.tsx (lines 650-699) with the same implementation. The functions normalizedSet, normalizeText, setsEqual, and the main detection logic are identical across both files.

Extract these utilities to a shared module (e.g., src/features/releases/compilationDetectionUtils.ts) to prevent divergence and reduce maintenance burden. Compilation detection is core business logic for Discogs integration—having it in two places increases the risk that future bug fixes or enhancements will only be applied to one copy.

♻️ Suggested extraction

Create a new shared utility file:

// src/features/releases/compilationDetectionUtils.ts
import type { ExternalMetadataReleaseDetailDto } from '../catalog/catalogApi'

export function hasCompilationTrackArtists(
  detail: ExternalMetadataReleaseDetailDto
): boolean {
  const releaseMainArtists = normalizedSet(
    detail.draft.artistCredits
      .filter((credit) => normalizeText(credit.role) === 'mainartist')
      .map((credit) => credit.name)
  )
  const releaseArtists =
    releaseMainArtists.size > 0
      ? releaseMainArtists
      : normalizedSet(detail.draft.artistCredits.map((credit) => credit.name))

  return detail.draft.tracklist.some((track) => {
    const trackMainArtists = normalizedSet(
      track.artistCredits
        .filter((credit) => normalizeText(credit.role) === 'mainartist')
        .map((credit) => credit.name)
    )

    if (trackMainArtists.size === 0) {
      return false
    }

    return !setsEqual(releaseArtists, trackMainArtists)
  })
}

function normalizedSet(values: string[]) {
  return new Set(values.map(normalizeText).filter(Boolean))
}

function normalizeText(value: string) {
  return value.trim().toLowerCase()
}

function setsEqual(left: Set<string>, right: Set<string>) {
  if (left.size !== right.size) {
    return false
  }

  for (const value of left) {
    if (!right.has(value)) {
      return false
    }
  }

  return true
}

Then import and use in both DiscogsReleaseLookupPanel.tsx and ReleaseEntryForm.tsx.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/releases/DiscogsReleaseLookupPanel.tsx` around lines 742 - 788,
Duplicate compilation-detection logic exists in DiscogsReleaseLookupPanel.tsx
and ReleaseEntryForm.tsx; extract it into a shared utility module and import it
from both places. Move the implementation of hasCompilationTrackArtists plus its
helpers (normalizedSet, normalizeText, setsEqual) into a new shared module,
export hasCompilationTrackArtists (helpers can be module-private or exported if
needed), then replace the local implementations in DiscogsReleaseLookupPanel.tsx
and ReleaseEntryForm.tsx with an import of hasCompilationTrackArtists and remove
the duplicated helper functions from both files so both components call the
single shared function.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.superdesign/design-system.md:
- Line 32: The design doc requires an explicit review impact for "External
Source", but the shipped UI/tests do not surface an External Source review
group; either (A) implement the missing impact group in the UI and tests by
adding the External Source review UI and corresponding assertions where release
lookup behavior is handled (see DiscogsReleaseLookupPanel and the
discogs-release-autocomplete test suite) so the doc matches implementation, or
(B) update the design-system.md text to remove or relax the External Source
requirement to align with current product behavior and tests (adjusting the
release review-impact list that currently includes Core, Artists, Labels,
Tracklist, and External Source). Ensure whichever path you choose is reflected
both in the UI/test code (DiscogsReleaseLookupPanel and the related tests) and
the design doc so the contract is consistent.

In `@src/features/artists/DiscogsArtistLookupPanel.tsx`:
- Around line 67-73: In handleSearch, prevent blank/whitespace queries by
trimming the input and short-circuiting before calling searchDiscogsArtists:
call const q = query.trim(), if q is empty then setStatus to a message like
'Enter an artist name to search.' (and optionally clear candidates with
setCandidates([]) and setSelectedDetail(null)), and return early; otherwise call
searchDiscogsArtists with q (and limit) as before. Ensure you reference
handleSearch, query, searchDiscogsArtists, setStatus, setCandidates, and
setSelectedDetail in the change.

In `@src/features/releases/ReleaseArtistCreditsSection.tsx`:
- Around line 166-200: The bug is that addCreditRole/removeCreditRole use the
render-captured credit.roles snapshot, causing lost updates; update them to
compute mutations from the live state inside the setArtistCredits updater using
currentCredit (the mapped value). Specifically, in
addCreditRole/removeCreditRole, remove reliance on the outer credit.roles and
instead in the credits.map branch for currentCredit.id === credit.id compute
const existing = currentCredit.roles; if adding, if existing.includes(role)
return currentCredit else return { ...currentCredit, role: currentCredit.role ||
role, roles: [...existing, role] }; if removing, compute const nextRoles =
existing.filter(r => r !== role) and return { ...currentCredit, role:
nextRoles[0] ?? '', roles: nextRoles } so rapid consecutive edits operate on the
latest state.

In `@src/features/releases/ReleaseDetail.tsx`:
- Around line 110-112: The actions container rendering guard currently checks
onEdit, onUpdateViaDiscogs, and onEditLocalFiles && localTracks.length > 0 but
omits onDelete, so the delete control can be hidden; update the conditional that
renders the "detail-actions" block to include onDelete (e.g., add || onDelete to
the existing expression) so the actions container is shown when onDelete is
provided; ensure you reference the same variables used in the file (onEdit,
onUpdateViaDiscogs, onEditLocalFiles, localTracks, onDelete) and preserve the
existing localTracks length check.

In `@src/features/tracks/tracks.css`:
- Around line 45-51: The .discogs-track-lookup .discogs-search-form currently
forces three columns and compresses controls on small screens; inside the
existing small-screen media query add a fallback that sets .discogs-track-lookup
.discogs-search-form { grid-template-columns: repeat(1, minmax(0, 1fr)); } and
adjust the button alignment (e.g., .discogs-track-lookup .discogs-search-form >
.button { justify-self: stretch; } or justify-self: start as preferred) so the
form collapses to a single column and text/controls fit on mobile.

---

Outside diff comments:
In `@src/features/catalog/api/catalogEntityMappers.ts`:
- Around line 145-155: The fallback mapping builds roles without deduplication
causing inconsistency with the primary path; replace the inline roles mapping
with the shared helper creditRolesFromDto (or call toReleaseArtistCredit) so
role labels are deduped the same way—i.e., pass the DTO role list into
creditRolesFromDto (or reuse toReleaseArtistCredit logic) and assign its result
to roles instead of mapping manually.

---

Nitpick comments:
In `@src/app/AuthenticatedApp.tsx`:
- Around line 594-602: The duplicated Set<AppRoutePath> declared as
fullCatalogRoutes should be replaced with the single exported manualEntryRoutes
to avoid diverging route definitions; locate the fullCatalogRoutes declaration
in AuthenticatedApp.tsx and import/use manualEntryRoutes (the exported symbol
from renderWorkspace.tsx) instead of redefining the route Set so hydration
gating and workspace behavior share the same source of truth.

In `@src/features/releases/DiscogsReleaseLookupPanel.tsx`:
- Around line 742-788: Duplicate compilation-detection logic exists in
DiscogsReleaseLookupPanel.tsx and ReleaseEntryForm.tsx; extract it into a shared
utility module and import it from both places. Move the implementation of
hasCompilationTrackArtists plus its helpers (normalizedSet, normalizeText,
setsEqual) into a new shared module, export hasCompilationTrackArtists (helpers
can be module-private or exported if needed), then replace the local
implementations in DiscogsReleaseLookupPanel.tsx and ReleaseEntryForm.tsx with
an import of hasCompilationTrackArtists and remove the duplicated helper
functions from both files so both components call the single shared function.

In `@src/features/tracks/TrackEntryForm.tsx`:
- Around line 503-531: The role pill list uses role as the React key (in
credit.roles.map) which risks collisions if duplicates appear; update the key to
a stable composite (e.g., include the parent credit id or the map index) such as
combining credit.id and role (or role and index) so each <span> rendered in
credit.roles.map has a unique key; keep the existing remove handler
(setCredits/currentCredits/currentCredit.id) unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1145d435-9c49-4f28-8605-25a1d7cb0a71

📥 Commits

Reviewing files that changed from the base of the PR and between 5df72ca and 7a7fa50.

📒 Files selected for processing (57)
  • .superdesign/design-system.md
  • src/App.auth.test.tsx
  • src/App.catalog-actions.test.tsx
  • src/App.discogs-artist-autocomplete.test.tsx
  • src/App.discogs-release-autocomplete.test.tsx
  • src/App.discogs-track-autocomplete.test.tsx
  • src/App.owned-items-inventory.test.tsx
  • src/App.relation-credit-navigation.test.tsx
  • src/App.search-v1.test.tsx
  • src/App.server-navigation.test.tsx
  • src/app/AuthenticatedApp.tsx
  • src/app/renderWorkspace.tsx
  • src/features/artists/ArtistDetail.tsx
  • src/features/artists/ArtistsWorkspace.tsx
  • src/features/artists/DiscogsArtistLookupPanel.tsx
  • src/features/artists/artistsData.ts
  • src/features/catalog/api/artistLabelClient.ts
  • src/features/catalog/api/catalogEntityMappers.ts
  • src/features/catalog/api/catalogRequestMappers.ts
  • src/features/catalog/api/catalogTypes.ts
  • src/features/catalog/api/catalogValueMappers.ts
  • src/features/catalog/api/externalMetadataClient.ts
  • src/features/catalog/api/httpClient.ts
  • src/features/catalog/api/releaseClient.ts
  • src/features/catalog/api/trackClient.ts
  • src/features/catalog/catalogApi.mutations.test.ts
  • src/features/catalog/catalogApi.ts
  • src/features/catalog/externalMetadataClient.test.ts
  • src/features/manualEntry/manual-entry.css
  • src/features/releases/CreditRolePicker.tsx
  • src/features/releases/DiscogsReleaseLookupPanel.tsx
  • src/features/releases/ReleaseArtistCreditsSection.tsx
  • src/features/releases/ReleaseCoreSection.tsx
  • src/features/releases/ReleaseDetail.tsx
  • src/features/releases/ReleaseEntryForm.tsx
  • src/features/releases/ReleaseEntryFormTypes.ts
  • src/features/releases/ReleaseTrackArtistCreditChip.tsx
  • src/features/releases/ReleaseTrackDetail.tsx
  • src/features/releases/ReleaseTracklistSection.tsx
  • src/features/releases/ReleasesWorkspace.tsx
  • src/features/releases/discogsReleaseTrackRows.test.ts
  • src/features/releases/discogsReleaseTrackRows.ts
  • src/features/releases/release-form.css
  • src/features/releases/release-tracklist.css
  • src/features/releases/releaseFormHelpers.ts
  • src/features/releases/releaseSubmit.ts
  • src/features/releases/releasesData.ts
  • src/features/releases/useReleaseTrackDrafts.ts
  • src/features/tracks/DiscogsTrackLookupPanel.tsx
  • src/features/tracks/TrackDetail.tsx
  • src/features/tracks/TrackEntryForm.tsx
  • src/features/tracks/TracksWorkspace.tsx
  • src/features/tracks/trackDisplayHelpers.ts
  • src/features/tracks/tracks.css
  • src/features/tracks/tracksData.ts
  • src/styles/responsive.css
  • vitest.config.ts

Comment thread .superdesign/design-system.md Outdated
Comment thread src/features/artists/DiscogsArtistLookupPanel.tsx
Comment thread src/features/releases/ReleaseArtistCreditsSection.tsx Outdated
Comment thread src/features/releases/ReleaseDetail.tsx
Comment thread src/features/tracks/tracks.css
@Fredoq Fredoq merged commit 63b930e into main Jun 4, 2026
2 checks passed
@Fredoq Fredoq deleted the roadmap-29-discogs-release-ui branch June 4, 2026 09:26
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.

1 participant