plug task enqueing properly

This commit is contained in:
2026-02-06 10:49:05 -03:00
parent 2cf6c89fbb
commit 013587d108
20 changed files with 413 additions and 356 deletions

View File

@@ -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<TranscodePreset[]>([]);
const [jobs, setJobs] = useState<TranscodeJob[]>([]);
const [selectedPresetId, setSelectedPresetId] = useState<string>("");
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 (
<div className="job-panel">
<div className="job-controls">
@@ -105,39 +74,6 @@ export default function JobPanel({ asset, trimStart, trimEnd }: JobPanelProps) {
{submitting ? "Submitting..." : buttonLabel}
</button>
</div>
{jobs.length > 0 && (
<div className="job-list">
<h3>Jobs</h3>
{jobs.map((job) => (
<div key={job.id} className="job-item">
<div className="job-item-header">
<span className="job-filename">{job.output_filename}</span>
<span className={`job-status ${job.status}`}>{job.status}</span>
</div>
{job.status === "processing" && (
<div className="job-progress-bar">
<div
className="job-progress-fill"
style={{ width: `${job.progress}%` }}
/>
</div>
)}
{(job.status === "pending" || job.status === "processing") && (
<button
className="job-cancel"
onClick={() => handleCancel(job.id)}
>
Cancel
</button>
)}
{job.status === "failed" && job.error_message && (
<div className="job-error">{job.error_message}</div>
)}
</div>
))}
</div>
)}
</div>
);
}