diff --git a/allstarr/wwwroot/index.html b/allstarr/wwwroot/index.html
index f91f22f..26e33d8 100644
--- a/allstarr/wwwroot/index.html
+++ b/allstarr/wwwroot/index.html
@@ -676,6 +676,51 @@
+
+
+
+
+ Manual Track Mappings
+
+
+
+
+
+ Manual mappings override automatic matching. Local (Jellyfin) mappings will be phased out in favor of the Spotify Import plugin.
+
+
+
+ Total:
+ 0
+
+
+ Jellyfin (Local):
+ 0
+
+
+ External:
+ 0
+
+
+
+
+
+ | Playlist |
+ Spotify ID |
+ Type |
+ Target |
+ Created |
+
+
+
+
+ |
+ Loading mappings...
+ |
+
+
+
+
@@ -1337,6 +1382,52 @@
}
}
+ async function fetchTrackMappings() {
+ try {
+ const res = await fetch('/api/admin/mappings/tracks');
+ const data = await res.json();
+
+ // Update summary
+ document.getElementById('mappings-total').textContent = data.totalCount || 0;
+ document.getElementById('mappings-jellyfin').textContent = data.jellyfinCount || 0;
+ document.getElementById('mappings-external').textContent = data.externalCount || 0;
+
+ const tbody = document.getElementById('mappings-table-body');
+
+ if (data.mappings.length === 0) {
+ tbody.innerHTML = '| No manual mappings found. |
';
+ return;
+ }
+
+ tbody.innerHTML = data.mappings.map(m => {
+ const typeColor = m.type === 'jellyfin' ? 'var(--accent)' : 'var(--success)';
+ const typeBadge = `${m.type}`;
+
+ let targetDisplay = '';
+ if (m.type === 'jellyfin') {
+ targetDisplay = `${m.jellyfinId}`;
+ } else {
+ targetDisplay = `${m.externalProvider}/${m.externalId}`;
+ }
+
+ const createdDate = m.createdAt ? new Date(m.createdAt).toLocaleString() : '-';
+
+ return `
+
+ | ${escapeHtml(m.playlist)} |
+ ${m.spotifyId} |
+ ${typeBadge} |
+ ${targetDisplay} |
+ ${createdDate} |
+
+ `;
+ }).join('');
+ } catch (error) {
+ console.error('Failed to fetch track mappings:', error);
+ showToast('Failed to fetch track mappings', 'error');
+ }
+ }
+
async function fetchConfig() {
try {
const res = await fetch('/api/admin/config');
@@ -2500,6 +2591,7 @@
// Initial load
fetchStatus();
fetchPlaylists();
+ fetchTrackMappings();
fetchJellyfinUsers();
fetchJellyfinPlaylists();
fetchConfig();
@@ -2508,6 +2600,7 @@
setInterval(() => {
fetchStatus();
fetchPlaylists();
+ fetchTrackMappings();
}, 30000);