diff --git a/allstarr/Controllers/AdminController.cs b/allstarr/Controllers/AdminController.cs index f681827..c23cb2b 100644 --- a/allstarr/Controllers/AdminController.cs +++ b/allstarr/Controllers/AdminController.cs @@ -656,6 +656,37 @@ public class AdminController : ControllerBase _logger.LogInformation("Cleared playlist caches for {Playlist} to force rebuild", decodedName); + // Fetch the mapped Jellyfin track details to return to the UI + try + { + var trackUrl = $"{_jellyfinSettings.Url}/Items/{request.JellyfinId}?api_key={_jellyfinSettings.ApiKey}"; + var response = await _jellyfinHttpClient.GetAsync(trackUrl); + + if (response.IsSuccessStatusCode) + { + var trackData = await response.Content.ReadAsStringAsync(); + using var doc = JsonDocument.Parse(trackData); + var track = doc.RootElement; + + var mappedTrack = new + { + id = request.JellyfinId, + title = track.TryGetProperty("Name", out var nameEl) ? nameEl.GetString() : "", + artist = track.TryGetProperty("AlbumArtist", out var artistEl) ? artistEl.GetString() : + (track.TryGetProperty("Artists", out var artistsEl) && artistsEl.GetArrayLength() > 0 + ? artistsEl[0].GetString() : ""), + album = track.TryGetProperty("Album", out var albumEl) ? albumEl.GetString() : "", + isLocal = true + }; + + return Ok(new { message = "Mapping saved successfully", track = mappedTrack }); + } + } + catch (Exception ex) + { + _logger.LogWarning(ex, "Failed to fetch mapped track details, but mapping was saved"); + } + return Ok(new { message = "Mapping saved successfully" }); } catch (Exception ex) diff --git a/allstarr/wwwroot/index.html b/allstarr/wwwroot/index.html index 295a21b..39d2bac 100644 --- a/allstarr/wwwroot/index.html +++ b/allstarr/wwwroot/index.html @@ -1760,7 +1760,7 @@ } return ` -
+
${t.position + 1}

${escapeHtml(t.title)}${statusBadge}${mapButton}

@@ -2021,6 +2021,7 @@ const playlistName = document.getElementById('map-playlist-name').value; const spotifyId = document.getElementById('map-spotify-id').value; const jellyfinId = document.getElementById('map-selected-jellyfin-id').value; + const position = parseInt(document.getElementById('map-position').textContent) - 1; // Convert back to 0-indexed if (!jellyfinId) { showToast('Please select a track', 'error'); @@ -2037,10 +2038,43 @@ const data = await res.json(); if (res.ok) { - showToast('Track mapped successfully! Refresh the playlist to see changes.', 'success'); + showToast('✓ Track mapped successfully', 'success'); closeModal('manual-map-modal'); - // Refresh the tracks view - viewTracks(playlistName); + + // Update the track in the UI without refreshing + if (data.track) { + const trackItem = document.querySelector(`.track-item[data-position="${position}"]`); + if (trackItem) { + // Update the track info + const titleEl = trackItem.querySelector('.track-info h4'); + const artistEl = trackItem.querySelector('.track-info .artists'); + const statusBadge = trackItem.querySelector('.status-badge'); + const mapButton = trackItem.querySelector('.map-track-btn'); + const searchLink = trackItem.querySelector('.track-meta a'); + + if (titleEl) { + // Remove the old status badge and map button, add new content + const titleText = data.track.title; + const newStatusBadge = 'Local'; + titleEl.innerHTML = escapeHtml(titleText) + newStatusBadge; + } + + if (artistEl) artistEl.textContent = data.track.artist; + + // Remove the search link since it's now local + if (searchLink) { + const metaEl = trackItem.querySelector('.track-meta'); + if (metaEl) { + // Keep album and ISRC, remove search link + const albumText = data.track.album ? escapeHtml(data.track.album) : ''; + metaEl.innerHTML = albumText; + } + } + } + } + + // Also refresh the playlist counts in the background + fetchPlaylists(); } else { showToast(data.error || 'Failed to save mapping', 'error'); }