refactor: split CSS and JS into modular files (SRP)
This commit is contained in:
313
src/server/web/static/js/queue/queue-init.js
Normal file
313
src/server/web/static/js/queue/queue-init.js
Normal file
@@ -0,0 +1,313 @@
|
||||
/**
|
||||
* AniWorld - Queue Page Application Initializer
|
||||
*
|
||||
* Main entry point for the queue page. Initializes all modules.
|
||||
*
|
||||
* Dependencies: All shared and queue modules
|
||||
*/
|
||||
|
||||
var AniWorld = window.AniWorld || {};
|
||||
|
||||
AniWorld.QueueApp = (function() {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Initialize the queue page application
|
||||
*/
|
||||
async function init() {
|
||||
console.log('AniWorld Queue App initializing...');
|
||||
|
||||
// Check authentication first
|
||||
const isAuthenticated = await AniWorld.Auth.checkAuth();
|
||||
if (!isAuthenticated) {
|
||||
return; // Auth module handles redirect
|
||||
}
|
||||
|
||||
// Initialize theme
|
||||
AniWorld.Theme.init();
|
||||
|
||||
// Initialize WebSocket connection
|
||||
AniWorld.WebSocketClient.init();
|
||||
|
||||
// Initialize socket event handlers for this page
|
||||
AniWorld.QueueSocketHandler.init(AniWorld.QueueApp);
|
||||
|
||||
// Bind UI events
|
||||
bindEvents();
|
||||
|
||||
// Load initial data
|
||||
await loadQueueData();
|
||||
|
||||
console.log('AniWorld Queue App initialized successfully');
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind UI event handlers
|
||||
*/
|
||||
function bindEvents() {
|
||||
// Theme toggle
|
||||
const themeToggle = document.getElementById('theme-toggle');
|
||||
if (themeToggle) {
|
||||
themeToggle.addEventListener('click', function() {
|
||||
AniWorld.Theme.toggle();
|
||||
});
|
||||
}
|
||||
|
||||
// Queue management actions
|
||||
const clearCompletedBtn = document.getElementById('clear-completed-btn');
|
||||
if (clearCompletedBtn) {
|
||||
clearCompletedBtn.addEventListener('click', function() {
|
||||
clearQueue('completed');
|
||||
});
|
||||
}
|
||||
|
||||
const clearFailedBtn = document.getElementById('clear-failed-btn');
|
||||
if (clearFailedBtn) {
|
||||
clearFailedBtn.addEventListener('click', function() {
|
||||
clearQueue('failed');
|
||||
});
|
||||
}
|
||||
|
||||
const clearPendingBtn = document.getElementById('clear-pending-btn');
|
||||
if (clearPendingBtn) {
|
||||
clearPendingBtn.addEventListener('click', function() {
|
||||
clearQueue('pending');
|
||||
});
|
||||
}
|
||||
|
||||
const retryAllBtn = document.getElementById('retry-all-btn');
|
||||
if (retryAllBtn) {
|
||||
retryAllBtn.addEventListener('click', retryAllFailed);
|
||||
}
|
||||
|
||||
// Download controls
|
||||
const startQueueBtn = document.getElementById('start-queue-btn');
|
||||
if (startQueueBtn) {
|
||||
startQueueBtn.addEventListener('click', startDownload);
|
||||
}
|
||||
|
||||
const stopQueueBtn = document.getElementById('stop-queue-btn');
|
||||
if (stopQueueBtn) {
|
||||
stopQueueBtn.addEventListener('click', stopDownloads);
|
||||
}
|
||||
|
||||
// Modal events
|
||||
const closeConfirm = document.getElementById('close-confirm');
|
||||
if (closeConfirm) {
|
||||
closeConfirm.addEventListener('click', AniWorld.UI.hideConfirmModal);
|
||||
}
|
||||
|
||||
const confirmCancel = document.getElementById('confirm-cancel');
|
||||
if (confirmCancel) {
|
||||
confirmCancel.addEventListener('click', AniWorld.UI.hideConfirmModal);
|
||||
}
|
||||
|
||||
const modalOverlay = document.querySelector('#confirm-modal .modal-overlay');
|
||||
if (modalOverlay) {
|
||||
modalOverlay.addEventListener('click', AniWorld.UI.hideConfirmModal);
|
||||
}
|
||||
|
||||
// Logout functionality
|
||||
const logoutBtn = document.getElementById('logout-btn');
|
||||
if (logoutBtn) {
|
||||
logoutBtn.addEventListener('click', function() {
|
||||
AniWorld.Auth.logout(AniWorld.UI.showToast);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load queue data and update display
|
||||
*/
|
||||
async function loadQueueData() {
|
||||
const data = await AniWorld.QueueAPI.loadQueueData();
|
||||
if (data) {
|
||||
AniWorld.QueueRenderer.updateQueueDisplay(data);
|
||||
AniWorld.ProgressHandler.processPendingProgressUpdates();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear queue by type
|
||||
* @param {string} type - 'completed', 'failed', or 'pending'
|
||||
*/
|
||||
async function clearQueue(type) {
|
||||
const titles = {
|
||||
completed: 'Clear Completed Downloads',
|
||||
failed: 'Clear Failed Downloads',
|
||||
pending: 'Remove All Pending Downloads'
|
||||
};
|
||||
|
||||
const messages = {
|
||||
completed: 'Are you sure you want to clear all completed downloads?',
|
||||
failed: 'Are you sure you want to clear all failed downloads?',
|
||||
pending: 'Are you sure you want to remove all pending downloads from the queue?'
|
||||
};
|
||||
|
||||
const confirmed = await AniWorld.UI.showConfirmModal(titles[type], messages[type]);
|
||||
if (!confirmed) return;
|
||||
|
||||
try {
|
||||
let data;
|
||||
if (type === 'completed') {
|
||||
data = await AniWorld.QueueAPI.clearCompleted();
|
||||
AniWorld.UI.showToast('Cleared ' + (data?.count || 0) + ' completed downloads', 'success');
|
||||
} else if (type === 'failed') {
|
||||
data = await AniWorld.QueueAPI.clearFailed();
|
||||
AniWorld.UI.showToast('Cleared ' + (data?.count || 0) + ' failed downloads', 'success');
|
||||
} else if (type === 'pending') {
|
||||
data = await AniWorld.QueueAPI.clearPending();
|
||||
AniWorld.UI.showToast('Removed ' + (data?.count || 0) + ' pending downloads', 'success');
|
||||
}
|
||||
await loadQueueData();
|
||||
} catch (error) {
|
||||
console.error('Error clearing queue:', error);
|
||||
AniWorld.UI.showToast('Failed to clear queue', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retry a failed download
|
||||
* @param {string} downloadId - Download item ID
|
||||
*/
|
||||
async function retryDownload(downloadId) {
|
||||
try {
|
||||
const data = await AniWorld.QueueAPI.retryDownloads([downloadId]);
|
||||
AniWorld.UI.showToast('Retried ' + (data?.retried_count || 1) + ' download(s)', 'success');
|
||||
await loadQueueData();
|
||||
} catch (error) {
|
||||
console.error('Error retrying download:', error);
|
||||
AniWorld.UI.showToast('Failed to retry download', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retry all failed downloads
|
||||
*/
|
||||
async function retryAllFailed() {
|
||||
const confirmed = await AniWorld.UI.showConfirmModal(
|
||||
'Retry All Failed Downloads',
|
||||
'Are you sure you want to retry all failed downloads?'
|
||||
);
|
||||
if (!confirmed) return;
|
||||
|
||||
try {
|
||||
// Get all failed download IDs
|
||||
const failedCards = document.querySelectorAll('#failed-downloads .download-card.failed');
|
||||
const itemIds = Array.from(failedCards).map(function(card) {
|
||||
return card.dataset.id;
|
||||
}).filter(function(id) {
|
||||
return id;
|
||||
});
|
||||
|
||||
if (itemIds.length === 0) {
|
||||
AniWorld.UI.showToast('No failed downloads to retry', 'info');
|
||||
return;
|
||||
}
|
||||
|
||||
const data = await AniWorld.QueueAPI.retryDownloads(itemIds);
|
||||
AniWorld.UI.showToast('Retried ' + (data?.retried_count || itemIds.length) + ' download(s)', 'success');
|
||||
await loadQueueData();
|
||||
} catch (error) {
|
||||
console.error('Error retrying failed downloads:', error);
|
||||
AniWorld.UI.showToast('Failed to retry downloads', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove item from queue
|
||||
* @param {string} downloadId - Download item ID
|
||||
*/
|
||||
async function removeFromQueue(downloadId) {
|
||||
try {
|
||||
const success = await AniWorld.QueueAPI.removeFromQueue(downloadId);
|
||||
if (success) {
|
||||
AniWorld.UI.showToast('Download removed from queue', 'success');
|
||||
await loadQueueData();
|
||||
} else {
|
||||
AniWorld.UI.showToast('Failed to remove from queue', 'error');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error removing from queue:', error);
|
||||
AniWorld.UI.showToast('Failed to remove from queue', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start queue processing
|
||||
*/
|
||||
async function startDownload() {
|
||||
try {
|
||||
const data = await AniWorld.QueueAPI.startQueue();
|
||||
|
||||
if (data && data.status === 'success') {
|
||||
AniWorld.UI.showToast('Queue processing started - all items will download automatically', 'success');
|
||||
|
||||
// Update UI
|
||||
document.getElementById('start-queue-btn').style.display = 'none';
|
||||
document.getElementById('stop-queue-btn').style.display = 'inline-flex';
|
||||
document.getElementById('stop-queue-btn').disabled = false;
|
||||
|
||||
await loadQueueData();
|
||||
} else {
|
||||
AniWorld.UI.showToast('Failed to start queue: ' + (data?.message || 'Unknown error'), 'error');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error starting queue:', error);
|
||||
AniWorld.UI.showToast('Failed to start queue processing', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop queue processing
|
||||
*/
|
||||
async function stopDownloads() {
|
||||
try {
|
||||
const data = await AniWorld.QueueAPI.stopQueue();
|
||||
|
||||
if (data && data.status === 'success') {
|
||||
AniWorld.UI.showToast('Queue processing stopped', 'success');
|
||||
|
||||
// Update UI
|
||||
document.getElementById('stop-queue-btn').style.display = 'none';
|
||||
document.getElementById('start-queue-btn').style.display = 'inline-flex';
|
||||
document.getElementById('start-queue-btn').disabled = false;
|
||||
|
||||
await loadQueueData();
|
||||
} else {
|
||||
AniWorld.UI.showToast('Failed to stop queue: ' + (data?.message || 'Unknown error'), 'error');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error stopping queue:', error);
|
||||
AniWorld.UI.showToast('Failed to stop queue', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
// Public API
|
||||
return {
|
||||
init: init,
|
||||
loadQueueData: loadQueueData,
|
||||
retryDownload: retryDownload,
|
||||
removeFromQueue: removeFromQueue,
|
||||
startDownload: startDownload,
|
||||
stopDownloads: stopDownloads
|
||||
};
|
||||
})();
|
||||
|
||||
// Initialize the application when DOM is loaded
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
AniWorld.QueueApp.init();
|
||||
});
|
||||
|
||||
// Expose for inline event handlers (backwards compatibility)
|
||||
window.queueManager = {
|
||||
retryDownload: function(id) {
|
||||
return AniWorld.QueueApp.retryDownload(id);
|
||||
},
|
||||
removeFromQueue: function(id) {
|
||||
return AniWorld.QueueApp.removeFromQueue(id);
|
||||
},
|
||||
removeFailedDownload: function(id) {
|
||||
return AniWorld.QueueApp.removeFromQueue(id);
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user