add musicbrainz icon for items where matched
This commit is contained in:
parent
8cdf548561
commit
22eb62bb77
3 changed files with 238 additions and 6 deletions
|
|
@ -4033,13 +4033,14 @@ class MusicDatabase:
|
|||
a.name,
|
||||
a.thumb_url,
|
||||
a.genres,
|
||||
a.musicbrainz_id,
|
||||
COUNT(DISTINCT al.id) as album_count,
|
||||
COUNT(DISTINCT t.id) as track_count
|
||||
FROM artists a
|
||||
LEFT JOIN albums al ON a.id = al.artist_id
|
||||
LEFT JOIN tracks t ON al.id = t.album_id
|
||||
WHERE {where_clause}
|
||||
GROUP BY a.id, a.name, a.thumb_url, a.genres
|
||||
GROUP BY a.id, a.name, a.thumb_url, a.genres, a.musicbrainz_id
|
||||
ORDER BY a.name COLLATE NOCASE
|
||||
LIMIT ? OFFSET ?
|
||||
"""
|
||||
|
|
@ -4076,6 +4077,7 @@ class MusicDatabase:
|
|||
'name': artist.name,
|
||||
'image_url': artist.thumb_url,
|
||||
'genres': artist.genres,
|
||||
'musicbrainz_id': row['musicbrainz_id'],
|
||||
'album_count': row['album_count'] or 0,
|
||||
'track_count': row['track_count'] or 0
|
||||
}
|
||||
|
|
@ -4130,7 +4132,7 @@ class MusicDatabase:
|
|||
# Get artist information
|
||||
cursor.execute("""
|
||||
SELECT
|
||||
id, name, thumb_url, genres, server_source
|
||||
id, name, thumb_url, genres, server_source, musicbrainz_id
|
||||
FROM artists
|
||||
WHERE id = ?
|
||||
""", (artist_id,))
|
||||
|
|
@ -4173,6 +4175,7 @@ class MusicDatabase:
|
|||
a.year,
|
||||
SUM(a.track_count) as track_count,
|
||||
MAX(a.thumb_url) as thumb_url,
|
||||
MAX(a.musicbrainz_release_id) as musicbrainz_release_id,
|
||||
COUNT(t.id) as owned_tracks
|
||||
FROM albums a
|
||||
LEFT JOIN tracks t ON a.id = t.album_id
|
||||
|
|
@ -4225,6 +4228,7 @@ class MusicDatabase:
|
|||
'owned': True, # All albums in our DB are owned
|
||||
'track_count': album_row['track_count'],
|
||||
'owned_tracks': owned_tracks,
|
||||
'musicbrainz_release_id': album_row['musicbrainz_release_id'],
|
||||
'track_completion': completion_percentage
|
||||
}
|
||||
|
||||
|
|
@ -4265,6 +4269,7 @@ class MusicDatabase:
|
|||
'image_url': artist_image_url,
|
||||
'genres': genres,
|
||||
'server_source': artist_row['server_source'],
|
||||
'musicbrainz_id': artist_row['musicbrainz_id'],
|
||||
'album_count': album_count,
|
||||
'track_count': track_count
|
||||
},
|
||||
|
|
|
|||
|
|
@ -20011,8 +20011,20 @@ function createArtistCardHTML(artist) {
|
|||
// Track if image needs to be lazy loaded
|
||||
const needsImage = imageUrl ? 'false' : 'true';
|
||||
|
||||
// Check for MusicBrainz ID
|
||||
let mbIconHTML = '';
|
||||
if (artist.musicbrainz_id) {
|
||||
const mbLogoUrl = 'https://upload.wikimedia.org/wikipedia/commons/thumb/9/9e/MusicBrainz_Logo_%282016%29.svg/500px-MusicBrainz_Logo_%282016%29.svg.png'; // Use official SVG logo
|
||||
mbIconHTML = `
|
||||
<div class="mb-card-icon" title="View on MusicBrainz" onclick="event.stopPropagation(); window.open('https://musicbrainz.org/artist/${artist.musicbrainz_id}', '_blank')">
|
||||
<img src="${mbLogoUrl}" style="width: 20px; height: auto; display: block;">
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
return `
|
||||
<div class="artist-card" data-artist-id="${artist.id}" data-needs-image="${needsImage}">
|
||||
${mbIconHTML}
|
||||
<div class="artist-card-background" style="${backgroundStyle}"></div>
|
||||
<div class="artist-card-overlay"></div>
|
||||
<div class="artist-card-content">
|
||||
|
|
@ -20122,6 +20134,17 @@ async function loadArtistDiscography(artistId, artistName = null) {
|
|||
singles: data.singles || []
|
||||
};
|
||||
|
||||
// Update selected artist with full details from backend (includes MusicBrainz ID)
|
||||
if (data.artist) {
|
||||
console.log('✨ Updating artist details with fresh data from backend');
|
||||
artistsPageState.selectedArtist = {
|
||||
...artistsPageState.selectedArtist,
|
||||
...data.artist
|
||||
};
|
||||
// Refresh header to show MusicBrainz link
|
||||
updateArtistDetailHeader(artistsPageState.selectedArtist);
|
||||
}
|
||||
|
||||
console.log(`✅ Loaded ${discography.albums.length} albums and ${discography.singles.length} singles`);
|
||||
|
||||
// Cache the results
|
||||
|
|
@ -21120,6 +21143,35 @@ function updateArtistDetailHeader(artist) {
|
|||
|
||||
if (nameElement) {
|
||||
nameElement.textContent = artist.name;
|
||||
|
||||
// DEBUG: Log the artist object to check for MBID
|
||||
console.log(`🔍 [DEBUG] Updating header for ${artist.name}`, artist);
|
||||
console.log(`🔍 [DEBUG] MBID present?`, artist.musicbrainz_id);
|
||||
|
||||
// Add MusicBrainz link if available
|
||||
if (artist.musicbrainz_id) {
|
||||
console.log('✅ [DEBUG] Adding MusicBrainz link to header');
|
||||
// Remove existing MB link if any
|
||||
const existingMb = nameElement.parentNode.querySelector('.mb-link-btn');
|
||||
if (existingMb) existingMb.remove();
|
||||
|
||||
const mbLink = document.createElement('a');
|
||||
mbLink.className = 'mb-link-btn';
|
||||
mbLink.href = `https://musicbrainz.org/artist/${artist.musicbrainz_id}`;
|
||||
mbLink.target = '_blank';
|
||||
mbLink.title = 'View on MusicBrainz';
|
||||
mbLink.innerHTML = `
|
||||
<img src="https://custom-icon-badges.demolab.com/badge/-MusicBrainz-353535?style=flat&logo=musicbrainz&logoColor=white" style="width: auto; height: 16px; margin: 0;">
|
||||
`;
|
||||
// Simplified button style to just be the badge/icon for cleaner look header
|
||||
mbLink.style.padding = '0';
|
||||
mbLink.style.border = 'none';
|
||||
mbLink.style.background = 'transparent';
|
||||
mbLink.style.marginLeft = '12px';
|
||||
mbLink.style.verticalAlign = 'middle';
|
||||
|
||||
nameElement.appendChild(mbLink);
|
||||
}
|
||||
}
|
||||
|
||||
if (genresElement) {
|
||||
|
|
@ -25117,6 +25169,26 @@ function createLibraryArtistCard(artist) {
|
|||
const card = document.createElement("div");
|
||||
card.className = "library-artist-card";
|
||||
card.setAttribute("data-artist-id", artist.id);
|
||||
// Add relative positioning for icon and smooth transition
|
||||
card.style.position = 'relative';
|
||||
card.style.transition = 'transform 0.2s, box-shadow 0.2s';
|
||||
|
||||
// Add MusicBrainz icon if ID exists
|
||||
if (artist.musicbrainz_id) {
|
||||
const mbIcon = document.createElement('div');
|
||||
mbIcon.className = 'mb-card-icon';
|
||||
mbIcon.title = 'View on MusicBrainz';
|
||||
|
||||
// Use official SVG logo
|
||||
const mbLogoUrl = 'https://upload.wikimedia.org/wikipedia/commons/thumb/9/9e/MusicBrainz_Logo_%282016%29.svg/500px-MusicBrainz_Logo_%282016%29.svg.png';
|
||||
mbIcon.innerHTML = `<img src="${mbLogoUrl}" style="width: 20px; height: auto; display: block;">`;
|
||||
|
||||
mbIcon.onclick = (e) => {
|
||||
e.stopPropagation();
|
||||
window.open(`https://musicbrainz.org/artist/${artist.musicbrainz_id}`, '_blank');
|
||||
};
|
||||
card.appendChild(mbIcon);
|
||||
}
|
||||
|
||||
// Create image element
|
||||
const imageContainer = document.createElement("div");
|
||||
|
|
@ -25329,12 +25401,12 @@ async function loadArtistDetailData(artistId, artistName) {
|
|||
console.log(`🎨 Main content visibility:`, document.getElementById('artist-detail-main'));
|
||||
console.log(`🎨 Albums section:`, document.getElementById('albums-section'));
|
||||
|
||||
// Update header with artist name now that data is loaded
|
||||
updateArtistDetailPageHeader(data.artist.name);
|
||||
|
||||
// Populate the page with data
|
||||
// Populate the page with data (which updates the hero section and sets textContent)
|
||||
populateArtistDetailPage(data);
|
||||
|
||||
// Update header with artist name and MusicBrainz link LAST to avoid overwrite
|
||||
updateArtistDetailPageHeaderWithData(data.artist);
|
||||
|
||||
} catch (error) {
|
||||
console.error(`❌ Error loading artist detail data:`, error);
|
||||
|
||||
|
|
@ -25358,6 +25430,63 @@ function updateArtistDetailPageHeader(artistName) {
|
|||
const mainTitle = document.getElementById("artist-info-name");
|
||||
if (mainTitle) {
|
||||
mainTitle.textContent = artistName;
|
||||
|
||||
// Try to find the artist object in memory to get the MBID
|
||||
// We can look at the data passed to populateArtistDetailPage if this function accepted the full object
|
||||
// Or access the state if it was saved
|
||||
|
||||
// Actually, let's look at how this is invoked. It's called from loadArtistDetailData which has the full 'data' object.
|
||||
// But this function only accepts 'artistName'.
|
||||
// We should query the state or modify the function signature.
|
||||
// For now, let's try to find the MB link element and update it if we can find the artist in data.
|
||||
}
|
||||
}
|
||||
|
||||
function updateArtistDetailPageHeaderWithData(artist) {
|
||||
// Target the visible header element
|
||||
const mainTitle = document.getElementById("artist-detail-name");
|
||||
|
||||
if (mainTitle) {
|
||||
console.log('✅ [DEBUG] Updating header for:', artist.name);
|
||||
// We assume textContent is set by updateArtistHeroSection, so we just APPEND the link
|
||||
// But to be safe, we can ensure name is there.
|
||||
// If we run AFTER populateArtistDetailPage, textContent is already set.
|
||||
|
||||
// If we reset textContent here, we might lose other formatting?
|
||||
// artist-detail-name usually just contains text.
|
||||
mainTitle.textContent = artist.name;
|
||||
|
||||
if (artist.musicbrainz_id) {
|
||||
console.log('✅ [DEBUG] Adding MusicBrainz link to DETAIL page header for', artist.name);
|
||||
|
||||
// Remove existing link if any (to prevent duplicates)
|
||||
const existingMb = mainTitle.querySelector('.mb-link-btn');
|
||||
if (existingMb) existingMb.remove();
|
||||
|
||||
const mbLink = document.createElement('a');
|
||||
mbLink.className = 'mb-link-btn';
|
||||
mbLink.href = `https://musicbrainz.org/artist/${artist.musicbrainz_id}`;
|
||||
mbLink.target = '_blank';
|
||||
mbLink.title = 'View on MusicBrainz';
|
||||
// Use the specific logo requested by user
|
||||
const mbLogoUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/9/9e/MusicBrainz_Logo_%282016%29.svg/500px-MusicBrainz_Logo_%282016%29.svg.png";
|
||||
|
||||
mbLink.innerHTML = `
|
||||
<img src="${mbLogoUrl}" style="height: 24px; width: auto; vertical-align: middle; display: inline-block;">
|
||||
<span style="color:rgba(255,255,255,0.9); margin-left:10px; font-size: 13px; font-weight: 600; vertical-align: middle;">View on MusicBrainz</span>
|
||||
`;
|
||||
mbLink.style.padding = '5px 14px';
|
||||
mbLink.style.border = '1px solid rgba(255,255,255,0.1)';
|
||||
mbLink.style.background = 'rgba(0,0,0,0.4)';
|
||||
mbLink.style.borderRadius = '20px';
|
||||
mbLink.style.marginLeft = '16px';
|
||||
mbLink.style.display = 'inline-flex';
|
||||
mbLink.style.alignItems = 'center';
|
||||
mbLink.style.textDecoration = 'none';
|
||||
mbLink.style.verticalAlign = 'middle';
|
||||
|
||||
mainTitle.appendChild(mbLink);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -25602,6 +25731,28 @@ function createReleaseCard(release) {
|
|||
card.setAttribute("data-release-id", release.id || "");
|
||||
card.setAttribute("data-spotify-id", release.spotify_id || "");
|
||||
|
||||
// DEBUG: Log release to check for MBID
|
||||
// console.log(`🔍 [DEBUG] Release: ${release.title}`, release);
|
||||
|
||||
// Add MusicBrainz icon if available
|
||||
let mbIcon = null;
|
||||
if (release.musicbrainz_release_id) {
|
||||
console.log(`✅ [DEBUG] Adding MB icon for release: ${release.title}`);
|
||||
const mbLogoUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/9/9e/MusicBrainz_Logo_%282016%29.svg/500px-MusicBrainz_Logo_%282016%29.svg.png";
|
||||
mbIcon = document.createElement("div");
|
||||
mbIcon.className = "mb-card-icon";
|
||||
mbIcon.title = "View on MusicBrainz";
|
||||
// Use image instead of text
|
||||
mbIcon.innerHTML = `<img src="${mbLogoUrl}" style="width: 20px; height: auto; display: block;">`;
|
||||
mbIcon.onclick = (e) => {
|
||||
e.stopPropagation();
|
||||
window.open(`https://musicbrainz.org/release/${release.musicbrainz_release_id}`, '_blank');
|
||||
};
|
||||
// Will append last
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Create image
|
||||
const imageContainer = document.createElement("div");
|
||||
if (release.image_url && release.image_url.trim() !== "") {
|
||||
|
|
@ -25733,6 +25884,11 @@ function createReleaseCard(release) {
|
|||
card.appendChild(year);
|
||||
card.appendChild(completion);
|
||||
|
||||
// Add MusicBrainz icon LAST to ensure it's on top
|
||||
if (release.musicbrainz_release_id && mbIcon) { // Check if mbIcon was created
|
||||
card.appendChild(mbIcon);
|
||||
}
|
||||
|
||||
// Add click handler for release card
|
||||
card.addEventListener("click", async () => {
|
||||
console.log(`Clicked on release: ${release.title} (Owned: ${release.owned})`);
|
||||
|
|
|
|||
|
|
@ -21714,4 +21714,75 @@ body {
|
|||
border-left: 6px solid transparent;
|
||||
border-right: 6px solid transparent;
|
||||
border-bottom: 8px solid rgba(30, 30, 30, 0.98);
|
||||
}
|
||||
|
||||
/* MusicBrainz Integration */
|
||||
.release-card {
|
||||
position: relative !important;
|
||||
/* Ensure positioning context */
|
||||
}
|
||||
|
||||
.mb-link-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 6px 12px;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||
border-radius: 6px;
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
transition: all 0.2s ease;
|
||||
margin-left: 10px;
|
||||
cursor: pointer;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.mb-link-btn:hover {
|
||||
background: rgba(186, 71, 143, 0.4);
|
||||
/* MusicBrainz Purple-ish */
|
||||
border-color: rgba(186, 71, 143, 0.6);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.mb-link-btn img,
|
||||
.mb-link-btn svg {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-right: 6px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.mb-card-icon {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 8px;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
backdrop-filter: blur(4px);
|
||||
/* MusicBrainz Purple - Force visible color */
|
||||
border: 1px solid rgba(255, 255, 255, 0.3);
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
opacity: 0.9 !important;
|
||||
/* Force visible */
|
||||
transition: transform 0.2s;
|
||||
cursor: pointer;
|
||||
z-index: 100 !important;
|
||||
/* Force on top */
|
||||
color: white;
|
||||
font-size: 11px;
|
||||
font-weight: 800;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
.mb-card-icon:hover {
|
||||
transform: scale(1.1);
|
||||
background: #d466a9;
|
||||
opacity: 1 !important;
|
||||
}
|
||||
Loading…
Reference in a new issue