Loading...
;
- }
+ const refreshJobs = async () => {
+ const data = await getJobs();
+ setJobs(data);
+ };
- if (error) {
- return Loading...
;
+ if (error) return
@@ -116,28 +134,88 @@ function App() {
@@ -147,7 +225,7 @@ function App() {
@@ -166,6 +244,7 @@ function App() {
asset={selectedAsset}
trimStart={trimStart}
trimEnd={trimEnd}
+ onJobCreated={refreshJobs}
/>
) : (
diff --git a/ui/timeline/src/JobPanel.tsx b/ui/timeline/src/JobPanel.tsx
index 690f2cb..58d86f7 100644
--- a/ui/timeline/src/JobPanel.tsx
+++ b/ui/timeline/src/JobPanel.tsx
@@ -1,49 +1,30 @@
import { useState, useEffect } from "react";
-import { getPresets, getJobs, createJob, cancelJob } from "./api";
-import type { MediaAsset, TranscodePreset, TranscodeJob } from "./types";
+import { getPresets, createJob } from "./api";
+import type { MediaAsset, TranscodePreset } from "./types";
interface JobPanelProps {
asset: MediaAsset;
trimStart: number;
trimEnd: number;
+ onJobCreated: () => void;
}
-export default function JobPanel({ asset, trimStart, trimEnd }: JobPanelProps) {
+export default function JobPanel({
+ asset,
+ trimStart,
+ trimEnd,
+ onJobCreated,
+}: JobPanelProps) {
const [presets, setPresets] = useState
([]);
- const [jobs, setJobs] = useState([]);
const [selectedPresetId, setSelectedPresetId] = useState("");
const [submitting, setSubmitting] = useState(false);
- // Load presets on mount
useEffect(() => {
getPresets().then(setPresets).catch(console.error);
}, []);
- // Poll jobs for this asset
- useEffect(() => {
- let active = true;
-
- const fetchJobs = () => {
- getJobs()
- .then((allJobs) => {
- if (active) {
- setJobs(
- allJobs.filter((j) => j.source_asset_id === asset.id),
- );
- }
- })
- .catch(console.error);
- };
-
- fetchJobs();
- const interval = setInterval(fetchJobs, 3000);
- return () => {
- active = false;
- clearInterval(interval);
- };
- }, [asset.id]);
-
- const hasTrim = trimStart > 0 || (asset.duration != null && trimEnd < asset.duration);
+ const hasTrim =
+ trimStart > 0 || (asset.duration != null && trimEnd < asset.duration);
const hasPreset = selectedPresetId !== "";
const canSubmit = hasTrim || hasPreset;
@@ -62,9 +43,7 @@ export default function JobPanel({ asset, trimStart, trimEnd }: JobPanelProps) {
trim_start: hasTrim ? trimStart : null,
trim_end: hasTrim ? trimEnd : null,
});
- // Refresh jobs immediately
- const allJobs = await getJobs();
- setJobs(allJobs.filter((j) => j.source_asset_id === asset.id));
+ onJobCreated();
} catch (e) {
alert(e instanceof Error ? e.message : "Failed to create job");
} finally {
@@ -72,16 +51,6 @@ export default function JobPanel({ asset, trimStart, trimEnd }: JobPanelProps) {
}
}
- async function handleCancel(jobId: string) {
- try {
- await cancelJob(jobId);
- const allJobs = await getJobs();
- setJobs(allJobs.filter((j) => j.source_asset_id === asset.id));
- } catch (e) {
- console.error("Cancel failed:", e);
- }
- }
-
return (
@@ -105,39 +74,6 @@ export default function JobPanel({ asset, trimStart, trimEnd }: JobPanelProps) {
{submitting ? "Submitting..." : buttonLabel}
-
- {jobs.length > 0 && (
-
-
Jobs
- {jobs.map((job) => (
-
-
- {job.output_filename}
- {job.status}
-
- {job.status === "processing" && (
-
- )}
- {(job.status === "pending" || job.status === "processing") && (
-
- )}
- {job.status === "failed" && job.error_message && (
-
{job.error_message}
- )}
-
- ))}
-
- )}
);
}