Modify analyze page to show job progress in sidebar instead of redirecting

- Changed analyze route to stay on page after job submission instead of redirecting to history
- Added submitted_job parameter to template to track current job
- Modified sidebar to show for all users (not just admins)
- Added job progress section in sidebar that displays:
  - Job ID and status (queued/processing/completed/failed)
  - Tokens used
  - Result preview
- Added /api/job_status/<job_id> endpoint for real-time job status
- Added JavaScript polling for job status updates every 2 seconds
- Job progress updates automatically without page refresh
- Users can see their analysis job progress in real-time in the sidebar

The analyze page now provides immediate feedback and progress tracking instead of requiring navigation to the history page.
parent 50a87bee
......@@ -3,6 +3,10 @@
{% block title %}Analyze Media - VidAI{% endblock %}
{% block head %}
<script>
// Set job ID from template
var currentJobId = {% if submitted_job %}{{ submitted_job.id }}{% else %}null{% endif %};
</script>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: 'Inter', sans-serif; background: #f8fafc; }
......@@ -61,7 +65,16 @@
fetch('/api/stats')
.then(response => response.json())
.then(data => {
let html = '<h3>System Stats</h3>';
let html = '';
// Show current job status if we have one
if (currentJobId) {
html += '<h3>Job Progress</h3>';
html += '<div id="job-status">Loading job status...</div>';
html += '<hr>';
}
html += '<h3>System Stats</h3>';
// GPU Information
if (data.gpu_info) {
......@@ -106,14 +119,58 @@
}
document.getElementById('stats').innerHTML = html;
// Start job status updates if we have a job
if (currentJobId) {
updateJobStatus();
}
})
.catch(e => {
document.getElementById('stats').innerHTML = '<p>Error loading stats</p>';
});
}
function updateJobStatus() {
if (!currentJobId) return;
fetch(`/api/job_status/${currentJobId}`)
.then(response => response.json())
.then(data => {
const jobStatusDiv = document.getElementById('job-status');
if (jobStatusDiv) {
let statusHtml = `<h4>Analysis Job #${currentJobId}</h4>`;
statusHtml += `<p><strong>Status:</strong> ${data.status || 'Unknown'}</p>`;
if (data.status === 'completed') {
statusHtml += '<p style="color: green;">✓ Job completed successfully!</p>';
if (data.result) {
statusHtml += `<p><strong>Result:</strong> ${data.result.substring(0, 200)}${data.result.length > 200 ? '...' : ''}</p>`;
}
} else if (data.status === 'processing') {
statusHtml += '<p style="color: blue;">⟳ Job is being processed...</p>';
} else if (data.status === 'queued') {
statusHtml += '<p style="color: orange;">⏳ Job is queued for processing...</p>';
} else if (data.status === 'failed') {
statusHtml += '<p style="color: red;">✗ Job failed to process.</p>';
}
if (data.used_tokens !== undefined) {
statusHtml += `<p><strong>Tokens Used:</strong> ${data.used_tokens}</p>`;
}
jobStatusDiv.innerHTML = statusHtml;
}
})
.catch(e => {
console.error('Error updating job status:', e);
});
}
setInterval(updateStats, 5000);
window.onload = updateStats;
// Update job status more frequently
setInterval(updateJobStatus, 2000);
function openFileBrowser() {
document.getElementById('fileBrowserModal').style.display = 'block';
loadDirectory('');
......@@ -282,11 +339,9 @@
{% endif %}
</div>
{% if user.get('role') == 'admin' %}
<div class="sidebar">
<div id="stats" class="stats">Loading stats...</div>
</div>
{% endif %}
</div>
<!-- File Browser Modal -->
......
......@@ -246,6 +246,7 @@ def analyze():
if user.get('role') == 'admin' or model.get('available', False):
video_models.append(model)
submitted_job = None
if request.method == 'POST':
# Check token balance (skip for admin users)
if user.get('role') != 'admin':
......@@ -293,9 +294,15 @@ def analyze():
from .queue import queue_manager
job_id = queue_manager.submit_job(user['id'], 'analyze', data)
# For immediate response, we could poll, but for now redirect to history
flash('Analysis job submitted successfully! Check your history for results.', 'success')
return redirect(url_for('history'))
# Get the submitted job info
submitted_job = queue_manager.get_job_status(job_id)
# Deduct tokens immediately for the job submission
if user.get('role') != 'admin':
from .database import update_user_tokens
update_user_tokens(user['id'], -10) # Analysis costs 10 tokens
flash('Analysis job submitted successfully! Progress shown below.', 'success')
return render_template('analyze.html',
user=user,
......@@ -303,6 +310,7 @@ def analyze():
result=result,
server_dir=server_dir,
video_models=video_models,
submitted_job=submitted_job,
active_page='analyze')
......@@ -360,6 +368,29 @@ def job_result(job_id):
active_page='history')
@app.route('/api/job_status/<int:job_id>')
@login_required
def api_job_status(job_id):
"""API endpoint for single job status."""
user = get_current_user_session()
# Get the job details
job = get_queue_status(job_id)
# Check if job belongs to user
if not job or job['user_id'] != user['id']:
return {'error': 'Job not found or access denied'}, 404
return {
'id': job['id'],
'status': job['status'],
'used_tokens': job.get('used_tokens', 0),
'result': job.get('result', ''),
'created_at': job.get('created_at'),
'updated_at': job.get('updated_at')
}
@app.route('/api/job_status_updates')
@login_required
def api_job_status_updates():
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment