Complete Top 500 Albums project with 100% data coverage and UI improvements

- Fixed Info/Description columns after regenerating CSV with clean Wikipedia data
- Remapped and downloaded missing album covers to match new rankings
- Modified website UI to show all description text without click-to-expand
- Added comprehensive Info/Description for all 500 albums using research
- Created multiple data processing scripts for album information completion
- Achieved 100% data completion with descriptions ending "(by Claude)" for new content
- All albums now have complete metadata and cover art

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Johan Lundberg 2025-07-01 00:33:47 +02:00
parent 09b5491f8a
commit 462fdcfa84
500 changed files with 2323 additions and 502 deletions

View file

@ -130,6 +130,19 @@ function renderAlbums() {
});
}
// Get cover image path for an album
function getCoverImagePath(album) {
if (!album.Artist || !album.Album || !album.Rank) return null;
// Sanitize artist and album names to match the downloaded filenames
const safeArtist = album.Artist.replace(/[<>:"/\\|?*]/g, '').replace(/[^\w\s\-_.]/g, '').replace(/\s+/g, '_').slice(0, 100);
const safeAlbum = album.Album.replace(/[<>:"/\\|?*]/g, '').replace(/[^\w\s\-_.]/g, '').replace(/\s+/g, '_').slice(0, 100);
const rank = album.Rank.toString().padStart(3, '0');
const filename = `rank_${rank}_${safeArtist}_${safeAlbum}.jpg`;
return `covers/${filename}`;
}
// Create album card element
function createAlbumCard(album) {
const card = document.createElement('div');
@ -139,6 +152,8 @@ function createAlbumCard(album) {
const statusClass = getStatusClass(album.Status);
const statusText = formatStatus(album.Status);
const coverImagePath = getCoverImagePath(album);
card.innerHTML = `
<div class="album-rank">#${album.Rank}</div>
<div class="album-content">
@ -149,18 +164,16 @@ function createAlbumCard(album) {
${album.Description ? `<div class="album-description">${escapeHtml(album.Description)}</div>` : ''}
</div>
<div class="album-cover">
<div class="album-cover-icon">🎵</div>
${coverImagePath ?
`<img src="${coverImagePath}" alt="${escapeHtml(album.Album)} by ${escapeHtml(album.Artist)}" class="album-cover-image" onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
<div class="album-cover-icon" style="display: none;">🎵</div>` :
`<div class="album-cover-icon">🎵</div>`
}
</div>
<button class="album-share" title="Share this album" data-rank="${album.Rank}">🔗</button>
`;
// Add click handler to expand description
const description = card.querySelector('.album-description');
if (description) {
description.addEventListener('click', function() {
this.classList.toggle('expanded');
});
}
// Description is now always fully visible
// Add click handler for share button
const shareBtn = card.querySelector('.album-share');