fix: jobless video assets no longer 500 the library click
Legacy/edge-case video_assets rows without a processing job threw 'has no processing job' from getVideoStatus — the library detail click 500ed. VideoStatus.processingJob is now nullable end to end (api type, DTO, web consumers null-guarded); a jobless asset renders as queued.
This commit is contained in:
parent
215952fe5e
commit
31c97a0b0a
13 changed files with 95 additions and 25 deletions
|
|
@ -119,7 +119,7 @@ export default function VideoPage(): React.ReactElement {
|
|||
const applyStatus = useCallback((status: VideoStatusDto): void => {
|
||||
const entry: VideoLibraryEntryDto = {
|
||||
videoAsset: status.videoAsset,
|
||||
processingState: status.processingJob.state,
|
||||
processingState: status.processingJob?.state ?? "queued",
|
||||
publications: [],
|
||||
};
|
||||
setItems((current) => [entry, ...(current ?? []).filter((e) => e.videoAsset.id !== entry.videoAsset.id)]);
|
||||
|
|
|
|||
|
|
@ -247,9 +247,9 @@ export function ProducerPanel({ entry, live, canManage }: Props): React.ReactEle
|
|||
}
|
||||
};
|
||||
|
||||
const producedInFlight = producedStatus !== null && IN_FLIGHT.includes(producedStatus.processingJob.state);
|
||||
const producedComplete = producedStatus?.processingJob.state === "complete";
|
||||
const producedFailed = producedStatus?.processingJob.state === "failed";
|
||||
const producedInFlight = producedStatus !== null && IN_FLIGHT.includes(producedStatus.processingJob?.state ?? "queued");
|
||||
const producedComplete = producedStatus?.processingJob?.state === "complete";
|
||||
const producedFailed = producedStatus?.processingJob?.state === "failed";
|
||||
|
||||
return (
|
||||
<section>
|
||||
|
|
@ -494,7 +494,7 @@ export function ProducerPanel({ entry, live, canManage }: Props): React.ReactEle
|
|||
)}
|
||||
{producedFailed && (
|
||||
<p className="text-2xs text-danger">
|
||||
The produced asset failed: {producedStatus?.processingJob.error ?? "see the job above."}
|
||||
The produced asset failed: {producedStatus?.processingJob?.error ?? "see the job above."}
|
||||
</p>
|
||||
)}
|
||||
{producedInFlight && (
|
||||
|
|
|
|||
|
|
@ -173,7 +173,7 @@ export function UploadDropzone({ live, canUpload, onStarted, onSettled, onUpload
|
|||
const status = await uploadOne(item, (progress) => patch(item.id, { progress }));
|
||||
// The bytes landed; a failed probe is a processing result, not an
|
||||
// upload failure — the library row carries it, so surface it inline.
|
||||
const processingError = status.processingJob.state === "failed" ? status.processingJob.error ?? null : null;
|
||||
const processingError = status.processingJob?.state === "failed" ? status.processingJob?.error ?? null : null;
|
||||
patch(item.id, {
|
||||
state: "done",
|
||||
progress: 100,
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ export function VideoDetailDrawer({
|
|||
}, [onClose]);
|
||||
|
||||
// Poll the job while it is in flight; the library page refreshes from this too.
|
||||
const inFlight = IN_FLIGHT.includes(status?.processingJob.state ?? entry.processingState);
|
||||
const inFlight = IN_FLIGHT.includes(status?.processingJob?.state ?? entry.processingState);
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
const fetchStatus = (): void => {
|
||||
|
|
@ -129,7 +129,7 @@ export function VideoDetailDrawer({
|
|||
>
|
||||
<span className={`h-1.5 w-1.5 shrink-0 rounded-full ${done || current ? "bg-current" : "bg-border"}`} />
|
||||
{step.label}
|
||||
{current && job.progressPercent !== undefined && (
|
||||
{current && job?.progressPercent !== undefined && (
|
||||
<span className="ml-auto font-mono text-2xs">{job.progressPercent}%</span>
|
||||
)}
|
||||
</li>
|
||||
|
|
@ -138,11 +138,11 @@ export function VideoDetailDrawer({
|
|||
{state === "failed" && (
|
||||
<li className="rounded-md border border-danger/30 bg-danger/10 px-2.5 py-1.5 text-xs text-danger">
|
||||
<span className="font-medium">failed</span>
|
||||
{job.error !== undefined && <span className="ml-1 font-mono text-2xs">{job.error}</span>}
|
||||
{job?.error !== undefined && <span className="ml-1 font-mono text-2xs">{job.error}</span>}
|
||||
</li>
|
||||
)}
|
||||
</ol>
|
||||
{job.processingNote !== undefined && <p className="mt-2 text-2xs text-text-faint">{job.processingNote}</p>}
|
||||
{job?.processingNote !== undefined && <p className="mt-2 text-2xs text-text-faint">{job.processingNote}</p>}
|
||||
</section>
|
||||
)}
|
||||
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ export interface VideoLibraryPageDto {
|
|||
|
||||
export interface VideoStatusDto {
|
||||
videoAsset: VideoAssetDto;
|
||||
processingJob: VideoProcessingJobDto;
|
||||
processingJob: VideoProcessingJobDto | null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue