fix: toggle preview display bug, add job deletion, optimize pipeline

- Fix: toggle ON now resets img display to block (was stuck on 'waiting')
- Toggle OFF sends API call to stop preview file writes
- Delete button on status page + jobs page cards
- DELETE /api/jobs/<id> endpoint removes job + output files
- PUT /api/jobs/<id>/preview endpoint toggles preview_enabled
- Pipeline skips resize/encode/write when preview_enabled=False
- Reduced preview defaults: 480px max, JPEG quality 60
- 62/62 tests pass
This commit is contained in:
jetson committed 2026-09-22 10:49:06 +07:00
1 parent 09a8829575
commit 163280078f
6 files changed
+140 -7

No files matched your search

+54 -3
View File
@@ -199,8 +199,32 @@
display: flex;
align-items: center;
justify-content: space-between;
padding: var(--space-3) var(--space-5);
border-top: 1px solid var(--color-neutral-100);
padding: var(--space-3) var(--space-4);
border-top: 1px solid var(--color-neutral-200);
font-size: var(--text-xs);
color: var(--color-neutral-500);
}
.job-card-actions {
display: flex;
align-items: center;
gap: var(--space-2);
}
.job-delete-btn {
padding: 2px 6px;
font-size: var(--text-xs);
color: var(--color-neutral-400);
border: none;
background: none;
cursor: pointer;
opacity: 0;
transition: opacity var(--transition-fast);
}
.job-card:hover .job-delete-btn {
opacity: 1;
}
.job-delete-btn:hover {
color: var(--color-error, #DC2626);
}
.job-card-time {
@@ -265,7 +289,12 @@
</div>
<div class="job-card-footer">
<span class="job-card-time" data-timestamp="{{ job.created_at }}"></span>
<a href="/status/{{ job.job_id }}" class="job-card-link">View Details</a>
<div class="job-card-actions">
{% if job.status.name in ('COMPLETED', 'FAILED', 'CANCELLED') %}
<button class="btn btn-ghost btn-sm job-delete-btn" data-job-id="{{ job.job_id }}" title="Delete job" aria-label="Delete job {{ job.job_id[:8] }}">&#128465;</button>
{% endif %}
<a href="/status/{{ job.job_id }}" class="job-card-link">View Details</a>
</div>
</div>
</article>
{% endfor %}
@@ -338,5 +367,27 @@ document.querySelectorAll('.copy-btn').forEach(function(btn) {
});
});
});
document.querySelectorAll('.job-delete-btn').forEach(function(btn) {
btn.addEventListener('click', function(e) {
e.preventDefault();
e.stopPropagation();
var id = this.getAttribute('data-job-id');
if (!confirm('Delete this job and all its output files?')) return;
fetch('/api/jobs/' + id, { method: 'DELETE' })
.then(function(res) { return res.json(); })
.then(function(data) {
if (data.status === 'deleted') {
btn.closest('.job-card').remove();
var grid = document.querySelector('.jobs-grid');
if (grid && !grid.querySelector('.job-card')) {
grid.innerHTML = '<div class="empty-state"><h3>No jobs yet</h3><p>Upload a video to start processing.</p><a href="/" class="btn btn-primary">Upload a video</a></div>';
}
} else if (data.error) {
alert(data.error);
}
});
});
});
</script>
{% endblock %}
+1
View File
@@ -9,6 +9,7 @@
{{ job.status.name }}
</span>
<button class="btn btn-danger btn-sm" id="cancel-btn" style="display:{{ 'inline-flex' if job.status.name in ('PENDING', 'RUNNING') else 'none' }}" aria-label="Abort this job">Abort</button>
<button class="btn btn-ghost btn-sm" id="delete-btn" style="display:{{ 'inline-flex' if job.status.name in ('COMPLETED', 'FAILED', 'CANCELLED') else 'none' }}" aria-label="Delete this job">Delete</button>
<time class="status-time" id="created-time" datetime="{{ job.created_at }}">{{ job.created_at | int }}</time>
</div>
<h2 class="job-id" id="job-title">Job {{ job.job_id[:8] }}...</h2>