mirror of
https://github.com/SoPat712/allstarr.git
synced 2026-02-09 23:55:10 -05:00
Add manual mapping indicators and search button for missing tracks
- Manual mappings now show a blue 'Manual' badge next to the track status
- Added search button (🔍) for missing tracks to help find them
- Backend now returns isManualMapping, manualMappingType, and manualMappingId
- Frontend displays manual mapping indicators for both local and external tracks
- Missing tracks now show a search link to help locate them on SquidWTF
This commit is contained in:
@@ -519,11 +519,17 @@ public class AdminController : ControllerBase
|
|||||||
// FIRST: Check for manual mapping (same as SpotifyTrackMatchingService)
|
// FIRST: Check for manual mapping (same as SpotifyTrackMatchingService)
|
||||||
var manualMappingKey = $"spotify:manual-map:{decodedName}:{track.SpotifyId}";
|
var manualMappingKey = $"spotify:manual-map:{decodedName}:{track.SpotifyId}";
|
||||||
var manualJellyfinId = await _cache.GetAsync<string>(manualMappingKey);
|
var manualJellyfinId = await _cache.GetAsync<string>(manualMappingKey);
|
||||||
|
bool isManualMapping = false;
|
||||||
|
string? manualMappingType = null;
|
||||||
|
string? manualMappingId = null;
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(manualJellyfinId))
|
if (!string.IsNullOrEmpty(manualJellyfinId))
|
||||||
{
|
{
|
||||||
// Manual Jellyfin mapping exists - this track is definitely local
|
// Manual Jellyfin mapping exists - this track is definitely local
|
||||||
isLocal = true;
|
isLocal = true;
|
||||||
|
isManualMapping = true;
|
||||||
|
manualMappingType = "jellyfin";
|
||||||
|
manualMappingId = manualJellyfinId;
|
||||||
_logger.LogDebug("✓ Manual Jellyfin mapping found for {Title}: Jellyfin ID {Id}",
|
_logger.LogDebug("✓ Manual Jellyfin mapping found for {Title}: Jellyfin ID {Id}",
|
||||||
track.Title, manualJellyfinId);
|
track.Title, manualJellyfinId);
|
||||||
}
|
}
|
||||||
@@ -558,6 +564,9 @@ public class AdminController : ControllerBase
|
|||||||
// External manual mapping exists
|
// External manual mapping exists
|
||||||
isLocal = false;
|
isLocal = false;
|
||||||
externalProvider = provider;
|
externalProvider = provider;
|
||||||
|
isManualMapping = true;
|
||||||
|
manualMappingType = "external";
|
||||||
|
manualMappingId = externalId;
|
||||||
_logger.LogDebug("✓ Manual external mapping found for {Title}: {Provider} {ExternalId}",
|
_logger.LogDebug("✓ Manual external mapping found for {Title}: {Provider} {ExternalId}",
|
||||||
track.Title, provider, externalId);
|
track.Title, provider, externalId);
|
||||||
}
|
}
|
||||||
@@ -624,7 +633,10 @@ public class AdminController : ControllerBase
|
|||||||
albumArtUrl = track.AlbumArtUrl,
|
albumArtUrl = track.AlbumArtUrl,
|
||||||
isLocal = isLocal,
|
isLocal = isLocal,
|
||||||
externalProvider = externalProvider,
|
externalProvider = externalProvider,
|
||||||
searchQuery = isLocal == false ? $"{track.Title} {track.PrimaryArtist}" : null
|
searchQuery = isLocal == false ? $"{track.Title} {track.PrimaryArtist}" : null,
|
||||||
|
isManualMapping = isManualMapping,
|
||||||
|
manualMappingType = manualMappingType,
|
||||||
|
manualMappingId = manualMappingId
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1788,9 +1788,17 @@
|
|||||||
|
|
||||||
if (t.isLocal === true) {
|
if (t.isLocal === true) {
|
||||||
statusBadge = '<span class="status-badge success" style="font-size:0.75rem;padding:2px 8px;margin-left:8px;"><span class="status-dot"></span>Local</span>';
|
statusBadge = '<span class="status-badge success" style="font-size:0.75rem;padding:2px 8px;margin-left:8px;"><span class="status-dot"></span>Local</span>';
|
||||||
|
// Add manual mapping indicator for local tracks
|
||||||
|
if (t.isManualMapping && t.manualMappingType === 'jellyfin') {
|
||||||
|
statusBadge += '<span class="status-badge" style="font-size:0.75rem;padding:2px 8px;margin-left:4px;background:var(--info);color:white;"><span class="status-dot" style="background:white;"></span>Manual</span>';
|
||||||
|
}
|
||||||
} else if (t.isLocal === false) {
|
} else if (t.isLocal === false) {
|
||||||
const provider = t.externalProvider || 'External';
|
const provider = t.externalProvider || 'External';
|
||||||
statusBadge = `<span class="status-badge warning" style="font-size:0.75rem;padding:2px 8px;margin-left:8px;"><span class="status-dot"></span>${escapeHtml(provider)}</span>`;
|
statusBadge = `<span class="status-badge warning" style="font-size:0.75rem;padding:2px 8px;margin-left:8px;"><span class="status-dot"></span>${escapeHtml(provider)}</span>`;
|
||||||
|
// Add manual mapping indicator for external tracks
|
||||||
|
if (t.isManualMapping && t.manualMappingType === 'external') {
|
||||||
|
statusBadge += '<span class="status-badge" style="font-size:0.75rem;padding:2px 8px;margin-left:4px;background:var(--info);color:white;"><span class="status-dot" style="background:white;"></span>Manual</span>';
|
||||||
|
}
|
||||||
// Add manual map button for external tracks using data attributes
|
// Add manual map button for external tracks using data attributes
|
||||||
const firstArtist = (t.artists && t.artists.length > 0) ? t.artists[0] : '';
|
const firstArtist = (t.artists && t.artists.length > 0) ? t.artists[0] : '';
|
||||||
mapButton = `<button class="small map-track-btn"
|
mapButton = `<button class="small map-track-btn"
|
||||||
@@ -1832,6 +1840,7 @@
|
|||||||
${t.album ? escapeHtml(t.album) : ''}
|
${t.album ? escapeHtml(t.album) : ''}
|
||||||
${t.isrc ? '<br><small>ISRC: ' + t.isrc + '</small>' : ''}
|
${t.isrc ? '<br><small>ISRC: ' + t.isrc + '</small>' : ''}
|
||||||
${t.isLocal === false && t.searchQuery && t.externalProvider ? '<br><small style="color:var(--accent)"><a href="#" onclick="searchProvider(\'' + escapeJs(t.searchQuery) + '\', \'' + escapeJs(t.externalProvider) + '\'); return false;" style="color:var(--accent);text-decoration:underline;">🔍 Search: ' + escapeHtml(t.searchQuery) + '</a></small>' : ''}
|
${t.isLocal === false && t.searchQuery && t.externalProvider ? '<br><small style="color:var(--accent)"><a href="#" onclick="searchProvider(\'' + escapeJs(t.searchQuery) + '\', \'' + escapeJs(t.externalProvider) + '\'); return false;" style="color:var(--accent);text-decoration:underline;">🔍 Search: ' + escapeHtml(t.searchQuery) + '</a></small>' : ''}
|
||||||
|
${t.isLocal === null && t.searchQuery ? '<br><small style="color:var(--text-secondary)"><a href="#" onclick="searchProvider(\'' + escapeJs(t.title + ' ' + (t.artists && t.artists.length > 0 ? t.artists[0] : '')) + '\', \'SquidWTF\'); return false;" style="color:var(--text-secondary);text-decoration:underline;">🔍 Search: ' + escapeHtml(t.title + ' ' + (t.artists && t.artists.length > 0 ? t.artists[0] : '')) + '</a></small>' : ''}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|||||||
Reference in New Issue
Block a user