This commit is contained in:
Lars Behrends
2025-10-19 22:05:21 +02:00
parent 0f95458466
commit 552bb72370
8 changed files with 560 additions and 70 deletions

View File

@@ -34,37 +34,49 @@
<!-- Jellyfin-specific sync options -->
<div class="d-flex gap-1 mb-2 flex-wrap">
<button onclick="startSync({{ source.id }}, 'all')"
class="btn btn-primary btn-sm flex-fill">
class="btn btn-primary btn-sm flex-fill"
data-source-id="{{ source.id }}">
All Content
</button>
<button onclick="startSync({{ source.id }}, 'movies')"
class="btn btn-outline-primary btn-sm flex-fill">
class="btn btn-outline-primary btn-sm flex-fill"
data-source-id="{{ source.id }}">
Movies Only
</button>
<button onclick="startSync({{ source.id }}, 'tvshows')"
class="btn btn-outline-primary btn-sm flex-fill">
class="btn btn-outline-primary btn-sm flex-fill"
data-source-id="{{ source.id }}">
TV Shows Only
</button>
</div>
<div class="d-flex gap-1 mb-2">
<button onclick="startSync({{ source.id }}, 'full')"
class="btn btn-secondary btn-sm flex-fill">
class="btn btn-secondary btn-sm flex-fill"
data-source-id="{{ source.id }}">
Full Sync
</button>
<button onclick="startSync({{ source.id }}, 'incremental')"
class="btn btn-outline-secondary btn-sm flex-fill">
class="btn btn-outline-secondary btn-sm flex-fill"
data-source-id="{{ source.id }}">
Incremental
</button>
<button onclick="startSync({{ source.id }}, 'cleanup')"
class="btn btn-outline-warning btn-sm flex-fill"
data-source-id="{{ source.id }}">
Cleanup
</button>
</div>
{% else %}
<!-- Standard sync options for other sources -->
<div class="d-flex gap-2 mb-2">
<button onclick="startSync({{ source.id }}, 'full')"
class="btn btn-primary btn-sm flex-fill">
class="btn btn-primary btn-sm flex-fill"
data-source-id="{{ source.id }}">
Full Sync
</button>
<button onclick="startSync({{ source.id }}, 'incremental')"
class="btn btn-secondary btn-sm flex-fill">
class="btn btn-secondary btn-sm flex-fill"
data-source-id="{{ source.id }}">
Incremental
</button>
</div>
@@ -223,11 +235,12 @@
progressBar.style.width = '0%';
statusDiv.textContent = 'Starting sync...';
// Disable all sync buttons for this source
const buttons = document.querySelectorAll(`[onclick*="startSync(${sourceId},"]`);
// Disable all sync buttons for this source - use a more reliable selector
const buttons = document.querySelectorAll(`[data-source-id="${sourceId}"]`);
buttons.forEach(button => {
button.disabled = true;
button.textContent = 'Syncing...';
button.dataset.originalText = button.textContent;
});
// Start sync via API
@@ -249,7 +262,7 @@
// Re-enable buttons on error
buttons.forEach(button => {
button.disabled = false;
button.textContent = button.textContent.replace('Syncing...', '').trim();
button.textContent = button.dataset.originalText || button.textContent.replace('Syncing...', '').trim();
});
}
})
@@ -259,7 +272,7 @@
// Re-enable buttons on error
buttons.forEach(button => {
button.disabled = false;
button.textContent = button.textContent.replace('Syncing...', '').trim();
button.textContent = button.dataset.originalText || button.textContent.replace('Syncing...', '').trim();
});
});
}
@@ -269,31 +282,47 @@
fetch(`/admin/sync/status/${syncLogId}`)
.then(response => response.json())
.then(data => {
// Update progress
if (data.total_items > 0) {
const progress = (data.processed_items / data.total_items) * 100;
progressBar.style.width = progress + '%';
// Update progress bar using percentage from backend
if (data.progress_percentage !== undefined && data.progress_percentage > 0) {
progressBar.style.width = data.progress_percentage + '%';
}
// Update status
statusDiv.textContent = getStatusMessage(data);
// Debug logging for troubleshooting
console.log('Sync status check:', {
syncLogId: syncLogId,
status: data.status,
message: data.message,
progress_percentage: data.progress_percentage,
processed_items: data.processed_items,
total_items: data.total_items,
completed_at: data.completed_at
});
// Stop monitoring if sync is complete or failed
if (['completed', 'failed'].includes(data.status)) {
clearInterval(interval);
delete syncIntervals[sourceId];
if (data.status === 'completed') {
// Show completion message briefly before hiding
statusDiv.textContent = 'Sync completed successfully!';
setTimeout(() => {
document.getElementById(`sync-progress-${sourceId}`).classList.add('d-none');
// Refresh page to show updated sync log
location.reload();
}, 2000);
// Re-enable buttons immediately on completion
buttons.forEach(button => {
button.disabled = false;
button.textContent = button.dataset.originalText || button.textContent.replace('Syncing...', '').trim();
});
}, 1500);
} else {
// Re-enable buttons on failure
buttons.forEach(button => {
button.disabled = false;
button.textContent = button.textContent.replace('Syncing...', '').trim();
button.textContent = button.dataset.originalText || button.textContent.replace('Syncing...', '').trim();
});
}
}
@@ -305,7 +334,7 @@
// Re-enable buttons on error
buttons.forEach(button => {
button.disabled = false;
button.textContent = button.textContent.replace('Syncing...', '').trim();
button.textContent = button.dataset.originalText || button.textContent.replace('Syncing...', '').trim();
});
});
}, 1000);
@@ -318,6 +347,12 @@
let message = `Completed: ${data.new_items || 0} new`;
if (data.updated_items > 0) message += `, ${data.updated_items} updated`;
if (data.deleted_items > 0) message += `, ${data.deleted_items} deleted`;
// If we have a cleaner message from the completion handler, use it
if (data.message && !data.message.includes('===')) {
return data.message;
}
return message;
} else if (data.status === 'failed') {
return 'Failed: ' + (data.message || 'Unknown error');
@@ -326,7 +361,13 @@
if (data.total_items > 0) {
progress += `: ${data.processed_items}/${data.total_items} items`;
}
if (data.message) {
if (data.progress_percentage !== undefined && data.progress_percentage > 0) {
progress += ` (${Math.round(data.progress_percentage)}%)`;
}
if (data.sync_type === 'cleanup') {
progress = 'Cleanup: ' + progress;
}
if (data.message && !data.message.includes('===')) {
progress += ` - ${data.message}`;
}
return progress;