Skip to content

feat(v3 library): persistent "no match" badge + Unmatched quick filter#781

Merged
byrongamatos merged 2 commits into
mainfrom
feat/v3-unmatched-visibility
Jul 5, 2026
Merged

feat(v3 library): persistent "no match" badge + Unmatched quick filter#781
byrongamatos merged 2 commits into
mainfrom
feat/v3-unmatched-visibility

Conversation

@ChrisBeWithYou

@ChrisBeWithYou ChrisBeWithYou commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Makes the metadata misses visible and reachable — the two follow-ups to the Refresh-Metadata batch (#764). Independent of the Fix-metadata popup stack; branches off main.

The gap: the batch paints a per-tile "no match" only while a pass runs, then clears it — so at rest you can't see which songs (the ~640 city-pop imports) never matched.

Persistent per-card "No match" badge

  • query_page now marks each row unmatched — a cheap match_state='failed' set-membership over the page (like favs/estd), so no N+1.
  • enrichBadge paints a subtle resting marker on those cards (right-click → fix by hand). It's tracked in a _unmatched set so a batch tile clearing falls back to the resting badge instead of wiping it; a live batch tile still wins while a pass runs (they never coexist).

"Unmatched" quick filter

  • A local-only Unmatched toolbar toggle: one click applies the same filter as the drawer's Match → Unmatched (match_state='failed'), re-queries, and reflects active state — so the no-match pile is one click from the batch, without digging into the filter drawer.

Testing

  • query_page flags a failed row (unmatched: true) and not a matched one; the match=unmatched filter returns only the failed song. test_library_filters + keyset + enrichment suites green (67). node --check clean; reuses existing utility classes (no CSS regen).

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added persistent No match (unmatched) badges on song cards for items that failed metadata matching.
    • Added an Unmatched quick filter to show only songs with no metadata match.
  • Bug Fixes

    • Song cards retain the no-match indicator across metadata refreshes, instead of clearing when temporary batch tile state is gone.
  • Tests

    • Added coverage for the unmatched flag behavior and the match=unmatched quick filter results.

The Refresh-Metadata batch (#764) shows a transient per-tile "no match" only
while a pass runs, so the unmatched pile goes quiet at rest. Two additions make
it visible + reachable:

- Persistent per-card "No match" badge: query_page now marks each row
  `unmatched` (a cheap failed-set membership like favs/estd), and enrichBadge
  paints a subtle resting marker for those cards — tracked in a `_unmatched` set
  so a batch tile clearing falls back to it instead of wiping it. A live batch
  tile still wins while a pass runs.
- "Unmatched" toolbar toggle (local-only): one click applies the same filter as
  the drawer's Match → Unmatched (match_state='failed'), so the no-match pile is
  a click away right after a batch. Re-queries + reflects active state.

Test: query_page flags a failed row + the match=unmatched filter returns it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 83307a25-df28-4475-ba80-9028c0136b00

📥 Commits

Reviewing files that changed from the base of the PR and between 502de02 and 9b3431d.

📒 Files selected for processing (1)
  • static/v3/songs.js
🚧 Files skipped from review as they are similar to previous changes (1)
  • static/v3/songs.js

📝 Walkthrough

Walkthrough

Adds a backend unmatched flag for failed enrichment matches, surfaces it in library query results, and updates the Songs UI to show a persistent no-match badge plus an Unmatched filter toggle. A test covers the flag and filter behavior.

Changes

Persistent Unmatched Badge and Filter

Layer / File(s) Summary
Backend unmatched flag computation
server.py
Adds MetadataDB._unmatched_set(filenames) using chunked SQL IN queries to find songs in 'failed' enrichment state, and wires it into query_page to set unmatched on each returned song card.
Persistent badge rendering and toolbar filter
static/v3/songs.js
Extends enrichBadge with an unmatched flag and _unmatched tracking set to render a resting nomatch badge with tooltip, passes song.unmatched into card rendering, and adds an Unmatched toolbar button with visibility logic and a toggleUnmatchedFilter() handler that toggles the match filter and reloads the grid.
Test for unmatched flag and quick filter
tests/test_library_filters.py
Adds a test seeding matched and failed rows, asserting the unmatched flag, and verifying /api/library?match=unmatched returns only the unmatched song.

Estimated code review effort: 2 (Simple) | ~12 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Browser
  participant songsjs as songs.js
  participant Server
  participant MetadataDB

  Browser->>songsjs: click `#v3-songs-unmatched`
  songsjs->>songsjs: toggleUnmatchedFilter()
  songsjs->>Server: reload() -> GET /api/library?match=unmatched
  Server->>MetadataDB: _unmatched_set(filenames)
  MetadataDB-->>Server: failed filenames set
  Server-->>songsjs: songs with unmatched flag
  songsjs->>songsjs: enrichBadge(key, song.unmatched)
  songsjs-->>Browser: render nomatch badge
Loading

Possibly related PRs

  • got-feedBack/feedBack#764: Shares the same enrichment match-state and per-card metadata refresh badge machinery that the unmatched badge feature builds on.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main v3 library changes: persistent no-match badges and the new Unmatched quick filter.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/v3-unmatched-visibility

Comment @coderabbitai help to get the list of available commands.

@ChrisBeWithYou

Copy link
Copy Markdown
Contributor Author

📋 Merge order — metadata-curation epic (7 PRs)

  1. feat(v3 library): "Fix metadata" popup — per-song override + lock, cover picker, MusicBrainz + AcoustID #777 — Fix-metadata popup
  2. feat(v3 library): "Write to file" in the Fix-metadata popup #778 — Write to file
  3. feat(v3 library): Match→Details "use these values" bridge #779 — Match→Details bridge
  4. feat(v3 library): genre field in the Fix-metadata popup #780 — Genre in Details
  5. feat(v3 library): persistent "no match" badge + Unmatched quick filter #781 — No-match badge + Unmatched filter (independent of 1–4 — fine to merge any time)
  6. feat(v3 library): batch→popup handoff + English-base romaji (metadata-curation capstone) #782 — Batch→popup handoff + romaji (capstone)
  7. feat(v3 library): searchable Cover Art Archive picker in Change-cover #783 — Searchable cover picker

#778#780 are stacked (each based on the branch above), so GitHub re-points each to main automatically as the previous one merges — just merge #777#778#779#780 top-down. #781 is independent (base: main).

⚠️ Hold #782 and #783 until #777#781 are all in main. #782's branch is a combined branch that already contains #777#781, so merging it early would double-merge the stack. Once #777#781 land, the author will rebase #782 (then #783) onto main — they shrink to just their own commits — and they're then ready to merge.

@ChrisBeWithYou

Copy link
Copy Markdown
Contributor Author

Integration note — from a full-queue dry-run that merged every open org PR into a next-version test build.

Your persistent "No match" badge now overlaps #783 (the Fix-metadata capstone), which turns the same badge into a clickable hand-off into the Fix-metadata popup (data-meta-fix/fixable in songs.js). When both are merged, #783's clickable badge is the superset and #781's non-interactive badge is redundant.

Recommend: rebase on #783 and trim this PR down to just its unique surface — the Unmatched quick-filter button + toggleUnmatchedFilter + the Match filter section. Those merge cleanly and are the real contribution; the badge itself is already covered by #783. (In the dry-run I kept #783's clickable badge, and #781's filter + toggle slotted in intact.)

…e-clear

_clearMetaTiles removed every .v3-meta-tile node — including the new
persistent 'No match' resting badge, which derives from _unmatched rather
than _metaTile. A metadata rescan's tile-clear therefore dropped the badge
until the next scroll re-rendered the card. Repaint it from _unmatched.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@byrongamatos
byrongamatos merged commit 3e036e3 into main Jul 5, 2026
3 of 4 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