compare view
This commit is contained in:
@@ -10,7 +10,9 @@ import BrandTablePanel from './panels/BrandTablePanel.vue'
|
||||
import TimelinePanel from './panels/TimelinePanel.vue'
|
||||
import CostStatsPanel from './panels/CostStatsPanel.vue'
|
||||
import SourceSelector from './panels/SourceSelector.vue'
|
||||
import CompareView from './panels/CompareView.vue'
|
||||
import StageConfig from './components/StageConfig.vue'
|
||||
import OverlayControls from './components/OverlayControls.vue'
|
||||
import FrameStrip from './components/FrameStrip.vue'
|
||||
import { usePipelineStore } from './stores/pipeline'
|
||||
import { useSSEConnection } from './composables/useSSEConnection'
|
||||
@@ -41,9 +43,14 @@ const {
|
||||
// Editor overlays + CV result accumulation
|
||||
const {
|
||||
editorOverlays, editorBoxes,
|
||||
updateDisplayForFrame, onReplayResult, setActiveStage,
|
||||
updateDisplayForFrame, onReplayResult: _onReplayResult, setActiveStage,
|
||||
saveOverlaysToCache,
|
||||
} = useEditorState(currentFrameRef)
|
||||
|
||||
function onReplayResult(result: any) {
|
||||
_onReplayResult(result)
|
||||
}
|
||||
|
||||
// Set active stage when editor opens
|
||||
watch(() => pipeline.editorStage, (stage) => {
|
||||
if (stage) setActiveStage(stage)
|
||||
@@ -56,6 +63,13 @@ function setCheckpointFrame(index: number) {
|
||||
if (frame) updateDisplayForFrame(frame.seq)
|
||||
}
|
||||
|
||||
// Save overlays to S3 cache then close editor
|
||||
function closeEditorWithSave() {
|
||||
saveOverlaysToCache(pipeline.timelineId, pipeline.jobId)
|
||||
// Small delay to let the save requests fire before navigation
|
||||
setTimeout(() => pipeline.closeEditor(), 100)
|
||||
}
|
||||
|
||||
// Wire job start to clear log panel
|
||||
function onJobStarted(newJobId: string, opts?: { pauseAfterStage?: boolean }) {
|
||||
logPanel.value?.clear()
|
||||
@@ -74,6 +88,11 @@ function onJobStarted(newJobId: string, opts?: { pauseAfterStage?: boolean }) {
|
||||
<path d="M2 4h4l2 2h6v8H2V4z"/><path d="M2 4V2h12v2"/>
|
||||
</svg>
|
||||
</button>
|
||||
<button class="header-btn" title="Compare jobs" @click="pipeline.openCompare()">
|
||||
<svg width="14" height="14" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5">
|
||||
<rect x="1" y="3" width="6" height="10" rx="1"/><rect x="9" y="3" width="6" height="10" rx="1"/><path d="M8 5v6"/>
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<!-- Transport controls — visible when a pipeline is running -->
|
||||
<div v-if="sseConnected && (status === 'live' || status === 'processing' || paused)" class="transport">
|
||||
@@ -210,21 +229,8 @@ function onJobStarted(newJobId: string, opts?: { pauseAfterStage?: boolean }) {
|
||||
/>
|
||||
|
||||
<div class="editor-bottom">
|
||||
<div class="overlay-controls">
|
||||
<label v-for="(overlay, idx) in editorOverlays" :key="idx" class="overlay-toggle">
|
||||
<input type="checkbox" v-model="overlay.visible" />
|
||||
<span class="overlay-label">{{ overlay.label }}</span>
|
||||
<input
|
||||
type="range"
|
||||
min="0" max="1" step="0.05"
|
||||
:value="overlay.opacity ?? 0.5"
|
||||
@input="(e: Event) => overlay.opacity = Number((e.target as HTMLInputElement).value)"
|
||||
class="opacity-slider"
|
||||
/>
|
||||
<span class="opacity-value">{{ Math.round((overlay.opacity ?? 0.5) * 100) }}%</span>
|
||||
</label>
|
||||
</div>
|
||||
<button class="editor-close" @click="pipeline.closeEditor()">✕ Close</button>
|
||||
<OverlayControls :overlays="editorOverlays" />
|
||||
<button class="editor-close" @click="closeEditorWithSave()">✕ Close</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -242,6 +248,9 @@ function onJobStarted(newJobId: string, opts?: { pauseAfterStage?: boolean }) {
|
||||
<!-- === SOURCE SELECTOR MODE === -->
|
||||
<SourceSelector v-else-if="pipeline.layoutMode === 'source_selector'" @job-started="(id: string, opts: any) => onJobStarted(id, opts)" />
|
||||
|
||||
<!-- === COMPARE MODE === -->
|
||||
<CompareView v-else-if="pipeline.layoutMode === 'compare'" />
|
||||
|
||||
</template>
|
||||
</SplitPane>
|
||||
|
||||
@@ -457,41 +466,6 @@ header h1 { font-size: var(--font-size-lg); font-weight: 600; }
|
||||
font-size: var(--font-size-sm);
|
||||
}
|
||||
|
||||
.overlay-controls {
|
||||
display: flex;
|
||||
gap: var(--space-4);
|
||||
padding: var(--space-2) var(--space-3);
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.overlay-toggle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-2);
|
||||
font-size: var(--font-size-sm);
|
||||
color: var(--text-secondary);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.overlay-toggle input[type="checkbox"] {
|
||||
accent-color: #00bcd4;
|
||||
}
|
||||
|
||||
.overlay-label {
|
||||
min-width: 80px;
|
||||
}
|
||||
|
||||
.opacity-slider {
|
||||
width: 80px;
|
||||
height: 3px;
|
||||
}
|
||||
|
||||
.opacity-value {
|
||||
font-size: 10px;
|
||||
color: var(--text-dim);
|
||||
min-width: 30px;
|
||||
}
|
||||
|
||||
/* Source selector */
|
||||
.source-selector {
|
||||
|
||||
Reference in New Issue
Block a user