Add local/external track columns to Jellyfin playlists, remove libraries filter

This commit is contained in:
2026-02-03 16:08:49 -05:00
parent 75c7acb745
commit df7f11e769
2 changed files with 112 additions and 40 deletions

View File

@@ -575,19 +575,14 @@
<option value="">All Users</option>
</select>
</div>
<div class="form-group" style="margin: 0; flex: 1; min-width: 200px;">
<label style="display: block; margin-bottom: 4px; color: var(--text-secondary); font-size: 0.85rem;">Library</label>
<select id="jellyfin-library-select" onchange="fetchJellyfinPlaylists()" style="width: 100%; padding: 8px; background: var(--bg-secondary); border: 1px solid var(--border); border-radius: 6px; color: var(--text-primary);">
<option value="">All Libraries</option>
</select>
</div>
</div>
<table class="playlist-table">
<thead>
<tr>
<th>Name</th>
<th>Tracks</th>
<th>Local</th>
<th>External</th>
<th>Linked Spotify ID</th>
<th>Status</th>
<th>Actions</th>
@@ -595,7 +590,7 @@
</thead>
<tbody id="jellyfin-playlist-table-body">
<tr>
<td colspan="5" class="loading">
<td colspan="6" class="loading">
<span class="spinner"></span> Loading Jellyfin playlists...
</td>
</tr>
@@ -1076,46 +1071,30 @@
}
}
async function fetchJellyfinLibraries() {
try {
const res = await fetch('/api/admin/jellyfin/libraries');
if (!res.ok) return;
const data = await res.json();
const select = document.getElementById('jellyfin-library-select');
select.innerHTML = '<option value="">All Libraries</option>' +
data.libraries.map(l => `<option value="${l.id}">${escapeHtml(l.name)}${l.collectionType ? ' (' + l.collectionType + ')' : ''}</option>`).join('');
} catch (error) {
console.error('Failed to fetch libraries:', error);
}
}
async function fetchJellyfinPlaylists() {
const tbody = document.getElementById('jellyfin-playlist-table-body');
tbody.innerHTML = '<tr><td colspan="5" class="loading"><span class="spinner"></span> Loading Jellyfin playlists...</td></tr>';
tbody.innerHTML = '<tr><td colspan="6" class="loading"><span class="spinner"></span> Loading Jellyfin playlists...</td></tr>';
try {
// Build URL with optional filters
// Build URL with optional user filter
const userId = document.getElementById('jellyfin-user-select').value;
const parentId = document.getElementById('jellyfin-library-select').value;
let url = '/api/admin/jellyfin/playlists';
const params = new URLSearchParams();
if (userId) params.append('userId', userId);
if (parentId) params.append('parentId', parentId);
if (params.toString()) url += '?' + params.toString();
if (userId) url += '?userId=' + encodeURIComponent(userId);
const res = await fetch(url);
if (!res.ok) {
const errorData = await res.json();
tbody.innerHTML = `<tr><td colspan="5" style="text-align:center;color:var(--error);padding:40px;">${errorData.error || 'Failed to fetch playlists'}</td></tr>`;
tbody.innerHTML = `<tr><td colspan="6" style="text-align:center;color:var(--error);padding:40px;">${errorData.error || 'Failed to fetch playlists'}</td></tr>`;
return;
}
const data = await res.json();
if (data.playlists.length === 0) {
tbody.innerHTML = '<tr><td colspan="5" style="text-align:center;color:var(--text-secondary);padding:40px;">No playlists found in Jellyfin</td></tr>';
tbody.innerHTML = '<tr><td colspan="6" style="text-align:center;color:var(--text-secondary);padding:40px;">No playlists found in Jellyfin</td></tr>';
return;
}
@@ -1128,10 +1107,15 @@
? `<button class="danger" onclick="unlinkPlaylist('${escapeHtml(p.name)}')">Unlink</button>`
: `<button class="primary" onclick="openLinkPlaylist('${escapeHtml(p.id)}', '${escapeHtml(p.name)}')">Link to Spotify</button>`;
const localCount = p.localTracks || 0;
const externalCount = p.externalTracks || 0;
const externalAvail = p.externalAvailable || 0;
return `
<tr>
<td><strong>${escapeHtml(p.name)}</strong></td>
<td class="track-count">${p.trackCount || 0}</td>
<td class="track-count">${localCount}</td>
<td class="track-count">${externalCount > 0 ? `${externalAvail}/${externalCount}` : '-'}</td>
<td style="font-family:monospace;font-size:0.85rem;color:var(--text-secondary);">${p.linkedSpotifyId || '-'}</td>
<td>${statusBadge}</td>
<td>${actionButton}</td>
@@ -1140,7 +1124,7 @@
}).join('');
} catch (error) {
console.error('Failed to fetch Jellyfin playlists:', error);
tbody.innerHTML = '<tr><td colspan="5" style="text-align:center;color:var(--error);padding:40px;">Failed to fetch playlists</td></tr>';
tbody.innerHTML = '<tr><td colspan="6" style="text-align:center;color:var(--error);padding:40px;">Failed to fetch playlists</td></tr>';
}
}
@@ -1468,7 +1452,6 @@
fetchStatus();
fetchPlaylists();
fetchJellyfinUsers();
fetchJellyfinLibraries();
fetchJellyfinPlaylists();
fetchConfig();