mirror of
https://github.com/SoPat712/allstarr.git
synced 2026-02-09 23:55:10 -05:00
Add loading state to save mapping button and timeout handling
This commit is contained in:
@@ -841,16 +841,24 @@ public class AdminController : ControllerBase
|
|||||||
{
|
{
|
||||||
_logger.LogInformation("Triggering immediate playlist rebuild for {Playlist} with new manual mapping", decodedName);
|
_logger.LogInformation("Triggering immediate playlist rebuild for {Playlist} with new manual mapping", decodedName);
|
||||||
|
|
||||||
// Wait for the rebuild to complete before responding to ensure UI gets updated cache
|
// Run rebuild in background with timeout to avoid blocking the response
|
||||||
|
_ = Task.Run(async () =>
|
||||||
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
using var cts = new CancellationTokenSource(TimeSpan.FromMinutes(2)); // 2 minute timeout
|
||||||
await _matchingService.TriggerMatchingForPlaylistAsync(decodedName);
|
await _matchingService.TriggerMatchingForPlaylistAsync(decodedName);
|
||||||
_logger.LogInformation("✓ Playlist {Playlist} rebuilt successfully with manual mapping", decodedName);
|
_logger.LogInformation("✓ Playlist {Playlist} rebuilt successfully with manual mapping", decodedName);
|
||||||
}
|
}
|
||||||
|
catch (OperationCanceledException)
|
||||||
|
{
|
||||||
|
_logger.LogWarning("Playlist rebuild for {Playlist} timed out after 2 minutes", decodedName);
|
||||||
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError(ex, "Failed to rebuild playlist {Playlist} after manual mapping", decodedName);
|
_logger.LogError(ex, "Failed to rebuild playlist {Playlist} after manual mapping", decodedName);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2042,13 +2042,24 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Show loading state
|
||||||
|
const saveBtn = document.getElementById('map-save-btn');
|
||||||
|
const originalText = saveBtn.textContent;
|
||||||
|
saveBtn.textContent = 'Saving...';
|
||||||
|
saveBtn.disabled = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
const controller = new AbortController();
|
||||||
|
const timeoutId = setTimeout(() => controller.abort(), 30000); // 30 second timeout
|
||||||
|
|
||||||
const res = await fetch('/api/admin/playlists/' + encodeURIComponent(playlistName) + '/map', {
|
const res = await fetch('/api/admin/playlists/' + encodeURIComponent(playlistName) + '/map', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
body: JSON.stringify({ spotifyId, jellyfinId })
|
body: JSON.stringify({ spotifyId, jellyfinId }),
|
||||||
|
signal: controller.signal
|
||||||
});
|
});
|
||||||
|
|
||||||
|
clearTimeout(timeoutId);
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
|
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
@@ -2093,8 +2104,16 @@
|
|||||||
showToast(data.error || 'Failed to save mapping', 'error');
|
showToast(data.error || 'Failed to save mapping', 'error');
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
if (error.name === 'AbortError') {
|
||||||
|
showToast('Request timed out - mapping may still be processing', 'warning');
|
||||||
|
} else {
|
||||||
showToast('Failed to save mapping', 'error');
|
showToast('Failed to save mapping', 'error');
|
||||||
}
|
}
|
||||||
|
} finally {
|
||||||
|
// Reset button state
|
||||||
|
saveBtn.textContent = originalText;
|
||||||
|
saveBtn.disabled = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function escapeJs(text) {
|
function escapeJs(text) {
|
||||||
|
|||||||
Reference in New Issue
Block a user