This commit is contained in:
2026-03-28 10:05:59 -03:00
parent e46bbc419c
commit d0707333fd
12 changed files with 381 additions and 120 deletions

View File

@@ -1,10 +1,17 @@
<script setup lang="ts">
import { ref, watch, computed } from 'vue'
import { ref, watch, computed, onMounted } from 'vue'
import { Panel, GraphRenderer } from 'mpr-ui-framework'
import type { GraphNode, GraphMode, DataSource } from 'mpr-ui-framework'
import { usePipelineStore } from '../stores/pipeline'
import { useStageRegistry } from '../composables/useStageRegistry'
interface PipelineConfigResponse {
name: string
profile_name: string
stages: { name: string; branch: string; execution_target: string }[]
edges: { source: string; target: string; condition: string }[]
}
const props = defineProps<{
source: DataSource
status?: 'idle' | 'live' | 'processing' | 'error'
@@ -14,6 +21,19 @@ const pipeline = usePipelineStore()
const { stageNames, editableStages } = useStageRegistry()
const nodes = ref<GraphNode[]>([])
const pipelineConfig = ref<PipelineConfigResponse | null>(null)
// Fetch pipeline config for a profile
async function fetchPipelineConfig(profileName: string) {
try {
const resp = await fetch(`/api/detect/config/profiles/${profileName}/pipeline`)
if (!resp.ok) return
pipelineConfig.value = await resp.json()
} catch { /* ignore */ }
}
// Load default profile config on mount
onMounted(() => fetchPipelineConfig('soccer_broadcast'))
// Derive graph mode from pipeline layout mode
const graphMode = computed<GraphMode>(() => {
@@ -23,27 +43,20 @@ const graphMode = computed<GraphMode>(() => {
return 'observe'
})
// Initialize nodes from registry when it loads
// Initialize nodes from pipeline config when it loads
watch(pipelineConfig, (config) => {
if (config && config.stages.length > 0 && nodes.value.length === 0) {
nodes.value = config.stages.map((s) => ({ id: s.name, status: 'pending' }))
}
}, { immediate: true })
// Fallback: init from registry if no config loaded
watch(stageNames, (names) => {
if (names.length > 0 && nodes.value.length === 0) {
nodes.value = names.map((id) => ({ id, status: 'pending' }))
}
}, { immediate: true })
// Source selector: placeholders until a chunk is selected, then real stage names
const displayNodes = computed<GraphNode[]>(() => {
if (pipeline.layoutMode === 'source_selector') {
if (pipeline.sourceHasSelection) {
return stageNames.value.map((id) => ({ id, status: 'pending' as const }))
}
return Array.from({ length: 10 }, (_, i) => ({
id: `_placeholder_${i}`,
status: 'placeholder' as const,
}))
}
return nodes.value
})
props.source.on<{ nodes: GraphNode[] }>('graph_update', (e) => {
nodes.value = e.nodes
})
@@ -63,6 +76,25 @@ props.source.on<{ report?: { status?: string } }>('job_complete', (e) => {
}
})
// Source selector: placeholders until a chunk is selected, then real stage names
const configStageNames = computed(() =>
pipelineConfig.value?.stages.map(s => s.name) ?? stageNames.value
)
const displayNodes = computed<GraphNode[]>(() => {
if (pipeline.layoutMode === 'source_selector') {
if (pipeline.sourceHasSelection) {
return configStageNames.value.map((id) => ({ id, status: 'pending' as const }))
}
const count = configStageNames.value.length || 10
return Array.from({ length: count }, (_, i) => ({
id: `_placeholder_${i}`,
status: 'placeholder' as const,
}))
}
return nodes.value
})
function onOpenRegionEditor(stage: string) {
pipeline.openBBoxEditor(stage)
}