diff --git a/frontend/src/pages/AdminPipeline.tsx b/frontend/src/pages/AdminPipeline.tsx index 6f10b80..c503b30 100644 --- a/frontend/src/pages/AdminPipeline.tsx +++ b/frontend/src/pages/AdminPipeline.tsx @@ -3,7 +3,8 @@ * expandable event log with token usage and collapsible JSON viewer. */ -import { useCallback, useEffect, useState } from "react"; +import { useCallback, useEffect, useRef, useState } from "react"; +import { useSearchParams } from "react-router-dom"; import { fetchPipelineVideos, fetchPipelineEvents, @@ -448,6 +449,7 @@ function StatusFilter({ // ── Main Page ──────────────────────────────────────────────────────────────── export default function AdminPipeline() { + const [searchParams] = useSearchParams(); const [videos, setVideos] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); @@ -456,6 +458,8 @@ export default function AdminPipeline() { const [actionMessage, setActionMessage] = useState<{ id: string; text: string; ok: boolean } | null>(null); const [activeFilter, setActiveFilter] = useState(null); const [debugMode, setDebugModeState] = useState(null); + const videoRefs = useRef>(new Map()); + const deepLinked = useRef(false); const load = useCallback(async () => { setLoading(true); @@ -474,6 +478,22 @@ export default function AdminPipeline() { void load(); }, [load]); + // Deep-link: auto-expand and scroll to ?video= on first load + useEffect(() => { + if (deepLinked.current || loading || videos.length === 0) return; + const targetVideoId = searchParams.get("video"); + if (!targetVideoId) return; + const match = videos.find((v) => v.id === targetVideoId); + if (!match) return; + deepLinked.current = true; + setExpandedId(targetVideoId); + // Scroll after the expanded detail renders + requestAnimationFrame(() => { + const el = videoRefs.current.get(targetVideoId); + if (el) el.scrollIntoView({ behavior: "smooth", block: "start" }); + }); + }, [loading, videos, searchParams]); + useEffect(() => { let cancelled = false; fetchDebugMode() @@ -568,7 +588,7 @@ export default function AdminPipeline() { {videos .filter((v) => activeFilter === null || v.processing_status === activeFilter) .map((video) => ( -
+
{ if (el) videoRefs.current.set(video.id, el); }}>
toggleExpand(video.id)}