feat: live preview toggle, FPS indicator, live counting by object

- Toggle ON/OFF switch to disable preview (faster processing)
- FPS badge showing rolling average processing speed
- Live Loading/Unloading/Net counts updated in real-time
- Pipeline callback pushes stats every 10 frames
- Frontend polls and updates display every 2s
- 62/62 tests pass
This commit is contained in:
jetson committed 2026-09-22 10:36:11 +07:00
1 parent b6379e14c9
commit 09a8829575
7 files changed
+383 -1

No files matched your search

+35
View File
@@ -358,6 +358,31 @@ function initStatusPage(jobId, initialStatus) {
if (!progressFill) return;
var previewToggle = document.getElementById('preview-toggle');
var toggleText = document.getElementById('toggle-text');
var liveFps = document.getElementById('live-fps');
var liveCounts = document.getElementById('live-counts');
var liveLoading = document.getElementById('live-loading');
var liveUnloading = document.getElementById('live-unloading');
var liveNet = document.getElementById('live-net');
if (previewToggle) {
previewToggle.addEventListener('change', function() {
if (this.checked) {
livePreviewImg.src = '/api/preview/' + jobId;
if (previewPlaceholder) previewPlaceholder.style.display = '';
livePreviewSection.style.display = '';
if (toggleText) toggleText.textContent = 'ON';
} else {
livePreviewImg.src = '';
livePreviewImg.style.display = 'none';
if (previewPlaceholder) previewPlaceholder.style.display = '';
livePreviewSection.style.display = '';
if (toggleText) toggleText.textContent = 'OFF';
}
});
}
/* --- Cancel button --- */
if (cancelBtn) {
cancelBtn.addEventListener('click', function() {
@@ -397,6 +422,16 @@ function initStatusPage(jobId, initialStatus) {
updateError(data.error);
announceStatusChange(data.status, data.progress);
if (data.live_fps !== undefined && liveFps) {
liveFps.textContent = data.live_fps > 0 ? data.live_fps.toFixed(1) + ' FPS' : 'Starting...';
}
if (data.live_loading !== undefined) {
if (liveCounts) liveCounts.style.display = '';
if (liveLoading) liveLoading.textContent = data.live_loading;
if (liveUnloading) liveUnloading.textContent = data.live_unloading;
if (liveNet) liveNet.textContent = (data.live_loading - data.live_unloading);
}
if (progressRegion) {
progressRegion.setAttribute('aria-busy', data.status === 'RUNNING' || data.status === 'PENDING' ? 'true' : 'false');
}
+93
View File
@@ -660,6 +660,99 @@ main {
display: block;
}
.live-preview-header {
display: flex;
align-items: center;
gap: var(--space-3);
margin-bottom: var(--space-3);
}
.live-preview-header .section-title {
margin-bottom: 0;
}
.live-fps {
font-size: var(--text-xs);
font-weight: var(--font-semibold);
color: var(--color-primary);
background: var(--color-primary-50, #f0fdfa);
padding: 2px 8px;
border-radius: var(--radius-sm);
white-space: nowrap;
}
.toggle-label {
display: flex;
align-items: center;
gap: var(--space-2);
cursor: pointer;
font-size: var(--text-sm);
user-select: none;
}
.toggle-label input[type="checkbox"] {
display: none;
}
.toggle-switch {
width: 36px;
height: 20px;
background: var(--color-neutral-300);
border-radius: 10px;
position: relative;
transition: background var(--transition-fast);
}
.toggle-switch::after {
content: '';
position: absolute;
width: 16px;
height: 16px;
background: white;
border-radius: 50%;
top: 2px;
left: 2px;
transition: transform var(--transition-fast);
}
.toggle-label input:checked + .toggle-switch {
background: var(--color-primary);
}
.toggle-label input:checked + .toggle-switch::after {
transform: translateX(16px);
}
.toggle-text {
font-weight: var(--font-medium);
color: var(--color-neutral-600);
}
.live-counts {
display: flex;
gap: var(--space-6);
padding: var(--space-3) 0;
border-top: 1px solid var(--color-neutral-100);
margin-top: var(--space-3);
}
.live-count-item {
text-align: center;
flex: 1;
}
.live-count-label {
font-size: var(--text-xs);
color: var(--color-neutral-500);
display: block;
margin-bottom: var(--space-1);
}
.live-count-value {
font-size: var(--text-2xl);
font-weight: var(--font-bold);
}
.preview-placeholder {
position: absolute;
inset: 0;