diff --git a/backend/temp_downloads/job_31743b3b-021a-4d64-aff8-e8c10f34c770/generated_video_1.mp4 b/backend/temp_downloads/job_31743b3b-021a-4d64-aff8-e8c10f34c770/generated_video_1.mp4 new file mode 100644 index 0000000..f8dac89 Binary files /dev/null and b/backend/temp_downloads/job_31743b3b-021a-4d64-aff8-e8c10f34c770/generated_video_1.mp4 differ diff --git a/backend/temp_downloads/job_4e64eb9c-039b-4a58-a4ce-ec8ba4d120b7/generated_video_1.mp4 b/backend/temp_downloads/job_4e64eb9c-039b-4a58-a4ce-ec8ba4d120b7/generated_video_1.mp4 new file mode 100644 index 0000000..7d9d3ff Binary files /dev/null and b/backend/temp_downloads/job_4e64eb9c-039b-4a58-a4ce-ec8ba4d120b7/generated_video_1.mp4 differ diff --git a/backend/temp_downloads/job_95739b90-d0e7-4345-a019-0a770ef21a87/generated_video_1.mp4 b/backend/temp_downloads/job_95739b90-d0e7-4345-a019-0a770ef21a87/generated_video_1.mp4 new file mode 100644 index 0000000..02f5290 Binary files /dev/null and b/backend/temp_downloads/job_95739b90-d0e7-4345-a019-0a770ef21a87/generated_video_1.mp4 differ diff --git a/backend/temp_downloads/job_a8d9e337-79b2-4525-b019-4bb11ba7f213/generated_video_1.mp4 b/backend/temp_downloads/job_a8d9e337-79b2-4525-b019-4bb11ba7f213/generated_video_1.mp4 new file mode 100644 index 0000000..e8cff13 Binary files /dev/null and b/backend/temp_downloads/job_a8d9e337-79b2-4525-b019-4bb11ba7f213/generated_video_1.mp4 differ diff --git a/backend/temp_downloads/job_d4ffd8b1-bc4a-4344-949e-6ea66777b668/generated_video_1.mp4 b/backend/temp_downloads/job_d4ffd8b1-bc4a-4344-949e-6ea66777b668/generated_video_1.mp4 new file mode 100644 index 0000000..559b25b Binary files /dev/null and b/backend/temp_downloads/job_d4ffd8b1-bc4a-4344-949e-6ea66777b668/generated_video_1.mp4 differ diff --git a/frontend/src/components/QueueManager.jsx b/frontend/src/components/QueueManager.jsx index a1e411b..5d5ee13 100644 --- a/frontend/src/components/QueueManager.jsx +++ b/frontend/src/components/QueueManager.jsx @@ -108,8 +108,8 @@ const QueueManager = ({ userEmail }) => { return job.progress || 0; }; - const isActiveJob = (job) => { - const activeStatuses = [ + const isProcessingJob = (job) => { + const processingStatuses = [ JOB_STATUS.STARTING, JOB_STATUS.UPLOADING_IMAGE, JOB_STATUS.GENERATING, @@ -119,15 +119,32 @@ const QueueManager = ({ userEmail }) => { 'retry_2_of_3', 'retry_3_of_3' ]; - return activeStatuses.includes(job.status) || job.status.startsWith('retry_'); + return processingStatuses.includes(job.status) || job.status.startsWith('retry_'); }; - const getMostRecentActiveJob = () => { - return jobs.find(job => isActiveJob(job)); + const isQueuedJob = (job) => { + return job.status === JOB_STATUS.QUEUED; + }; + + const isHistoricalJob = (job) => { + return job.status === JOB_STATUS.COMPLETED || + job.status === JOB_STATUS.FAILED || + job.status === JOB_STATUS.CANCELLED; + }; + + const getProcessingJobs = () => { + return jobs.filter(job => isProcessingJob(job)) + .sort((a, b) => new Date(a.created_at) - new Date(b.created_at)); // FIFO order + }; + + const getQueuedJobs = () => { + return jobs.filter(job => isQueuedJob(job)) + .sort((a, b) => new Date(a.created_at) - new Date(b.created_at)); // FIFO order }; const getHistoricalJobs = () => { - return jobs.filter(job => !isActiveJob(job)); + return jobs.filter(job => isHistoricalJob(job)) + .sort((a, b) => new Date(b.created_at) - new Date(a.created_at)); // Most recent first }; const renderDownloadButtons = (job) => { @@ -170,19 +187,28 @@ const QueueManager = ({ userEmail }) => { return {buttons}; }; - const renderJobItem = (job, isActive = false) => { + const renderJobItem = (job, jobType = 'history', queuePosition = null) => { + const isProcessing = jobType === 'processing'; + const isQueued = jobType === 'queued'; return ( @@ -197,9 +223,10 @@ const QueueManager = ({ userEmail }) => { color={getStatusColor(job.status)} size="small" /> - {job.status === JOB_STATUS.QUEUED && job.queue_position > 0 && ( + {isQueued && queuePosition && ( @@ -229,26 +256,40 @@ const QueueManager = ({ userEmail }) => { {job.message || 'Processing...'} - {/* Enhanced Progress Bar for Active Jobs */} + {/* Progress Bar */} - {isActive && ( + {isProcessing && ( {getProgressValue(job)}% complete )} + {isQueued && ( + + Waiting in queue... + + )} + {/* Download Buttons */} {renderDownloadButtons(job)} @@ -359,47 +400,72 @@ const QueueManager = ({ userEmail }) => { ) : ( <> - {/* Active Job Section */} - {getMostRecentActiveJob() && ( + {/* Processing Jobs Section */} + {getProcessingJobs().length > 0 && ( <> - - Current Video Generation + + + Currently Processing ({getProcessingJobs().length}) - {renderJobItem(getMostRecentActiveJob(), true)} + {getProcessingJobs().map((job, index) => ( + + {renderJobItem(job, 'processing')} + {index < getProcessingJobs().length - 1 && } + + ))} + + + )} + + {/* Queued Jobs Section */} + {getQueuedJobs().length > 0 && ( + <> + {getProcessingJobs().length > 0 && } + + + In Queue ({getQueuedJobs().length}) + + + {getQueuedJobs().map((job, index) => ( + + {renderJobItem(job, 'queued', index + 1)} + {index < getQueuedJobs().length - 1 && } + + ))} - - {getHistoricalJobs().length > 0 && ( - <> - - - Job History - - - )} )} {/* Historical Jobs Section */} {getHistoricalJobs().length > 0 && ( - - {getHistoricalJobs().map((job, index) => ( - - {renderJobItem(job, false)} - {index < getHistoricalJobs().length - 1 && } - - ))} - + <> + {(getProcessingJobs().length > 0 || getQueuedJobs().length > 0) && ( + + )} + + + History ({getHistoricalJobs().length}) + + + {getHistoricalJobs().map((job, index) => ( + + {renderJobItem(job, 'history')} + {index < getHistoricalJobs().length - 1 && } + + ))} + + )} )} diff --git a/frontend/src/components/VideoForm.jsx b/frontend/src/components/VideoForm.jsx index 3755bf8..713b204 100644 --- a/frontend/src/components/VideoForm.jsx +++ b/frontend/src/components/VideoForm.jsx @@ -432,7 +432,7 @@ const VideoForm = ({ onSubmit, isGenerating, userJobs = [], queueLimit = 4 }) => > {userJobs.length >= queueLimit ? 'Queue Full' - : userJobs.some(job => ['starting', 'uploading_image', 'generating', 'processing', 'downloading'].includes(job.status)) + : userJobs.some(job => ['starting', 'uploading_image', 'generating', 'processing', 'downloading', 'queued'].includes(job.status)) ? 'Add to Queue' : 'Generate Video' }