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');
}