From 8c84189121f7e8f79458c50644170fca529b2857 Mon Sep 17 00:00:00 2001 From: Broque Thomas <26755000+Nezreka@users.noreply.github.com> Date: Sun, 22 Mar 2026 15:56:12 -0700 Subject: [PATCH] Add per-artist enrichment coverage rings to artist hero section --- web_server.py | 39 +++++++++++++++- webui/index.html | 3 ++ webui/static/script.js | 51 ++++++++++++++++++++ webui/static/style.css | 103 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 195 insertions(+), 1 deletion(-) diff --git a/web_server.py b/web_server.py index 79cb3fe9..68ed5ebe 100644 --- a/web_server.py +++ b/web_server.py @@ -8554,10 +8554,47 @@ def get_artist_detail(artist_id): # Fall back to our database categorization merged_discography = owned_releases + # Compute per-artist track enrichment coverage + enrichment_coverage = {} + try: + with database._get_connection() as conn: + cursor = conn.cursor() + artist_name = artist_info['name'] + server_source = artist_info.get('server_source', '') + cursor.execute(""" + SELECT COUNT(*) FROM tracks t + JOIN albums al ON al.id = t.album_id + JOIN artists ar ON ar.id = al.artist_id + WHERE ar.name = ? AND ar.server_source = ? + """, (artist_name, server_source)) + total = (cursor.fetchone() or [0])[0] + if total > 0: + for svc, col in [('spotify', 'spotify_track_id'), ('musicbrainz', 'musicbrainz_recording_id'), + ('deezer', 'deezer_id'), ('lastfm', 'lastfm_url'), + ('itunes', 'itunes_track_id'), ('audiodb', 'audiodb_id'), + ('genius', 'genius_id'), ('tidal', 'tidal_id'), + ('qobuz', 'qobuz_id')]: + try: + cursor.execute(f""" + SELECT COUNT(*) FROM tracks t + JOIN albums al ON al.id = t.album_id + JOIN artists ar ON ar.id = al.artist_id + WHERE ar.name = ? AND ar.server_source = ? + AND t.{col} IS NOT NULL AND t.{col} != '' + """, (artist_name, server_source)) + matched = (cursor.fetchone() or [0])[0] + enrichment_coverage[svc] = round(matched / total * 100, 1) + except Exception: + enrichment_coverage[svc] = 0 + enrichment_coverage['total_tracks'] = total + except Exception: + pass + response_data = { "success": True, "artist": artist_info, - "discography": merged_discography + "discography": merged_discography, + "enrichment_coverage": enrichment_coverage } # Add Spotify artist data if available diff --git a/webui/index.html b/webui/index.html index 2518dfe7..4e9e11d1 100644 --- a/webui/index.html +++ b/webui/index.html @@ -2581,6 +2581,9 @@ 0/0 + + +
diff --git a/webui/static/script.js b/webui/static/script.js index 94aa8825..c8c034c0 100644 --- a/webui/static/script.js +++ b/webui/static/script.js @@ -38817,6 +38817,9 @@ async function loadArtistDetailData(artistId, artistName) { // Update header with artist name and MusicBrainz link LAST to avoid overwrite updateArtistDetailPageHeaderWithData(data.artist); + // Render per-artist enrichment coverage + renderArtistEnrichmentCoverage(data.enrichment_coverage); + // Start streaming ownership checks if we have Spotify discography with checking state if (data.discography && data.discography.albums) { const hasChecking = [...(data.discography.albums || []), ...(data.discography.eps || []), ...(data.discography.singles || [])] @@ -38894,6 +38897,54 @@ function updateArtistDetailPageHeaderWithData(artist) { } } +function renderArtistEnrichmentCoverage(enrichment) { + const el = document.getElementById('artist-enrichment-coverage'); + if (!el) return; + + if (!enrichment || !enrichment.total_tracks) { + el.style.display = 'none'; + return; + } + + const services = [ + { name: 'Spotify', key: 'spotify', color: '#1db954' }, + { name: 'MusicBrainz', key: 'musicbrainz', color: '#ba55d3' }, + { name: 'Deezer', key: 'deezer', color: '#a238ff' }, + { name: 'Last.fm', key: 'lastfm', color: '#d51007' }, + { name: 'iTunes', key: 'itunes', color: '#fc3c44' }, + { name: 'AudioDB', key: 'audiodb', color: '#1a9fff' }, + { name: 'Genius', key: 'genius', color: '#ffff64' }, + { name: 'Tidal', key: 'tidal', color: '#00ffff' }, + { name: 'Qobuz', key: 'qobuz', color: '#4285f4' }, + ]; + + const r = 20, circ = 2 * Math.PI * r; + + el.style.display = ''; + el.innerHTML = ` +