import { useState } from "react"; import { canCancelJob, currentJobs, useJobs } from "./jobs"; import type { Job } from "@chopin/protocol"; import type { JobStore } from "./jobs"; export type TasksProps = { store: JobStore; connected: boolean; canEdit: boolean; headingId?: string; }; function result(detail: Job.Detail | undefined): { title: string; summary: string } | undefined { let value = detail?.artifact?.value; if (!value || typeof value !== "object" || Array.isArray(value)) return undefined; let artifact = value as Record; if (typeof artifact.summary === "string") { return { title: "Document summary", summary: artifact.summary }; } let report = artifact.report; if (!report || typeof report !== "object" || Array.isArray(report)) return undefined; let body = report as Record; return typeof body.title === "string" && typeof body.summary === "string" ? { title: body.title, summary: body.summary } : undefined; } function Task( { canEdit, connected, job, store }: { canEdit: boolean; connected: boolean; job: Job.View; store: JobStore; }, ) { let snapshot = useJobs(store); let [open, setOpen] = useState(false); let [error, setError] = useState(); let detail = snapshot.details[job.id]; let artifact = result(detail); let subject = job.type === "research-question" ? `Research question: ${job.subject ?? job.targetKey.split(":").at(-1)}` : "Document summary"; let toggle = () => { setOpen(value => !value); if (!detail) void store.detail(job.id).catch(() => {}); }; return (
{subject} {job.state}{job.reason ? ` · ${job.reason}` : ""}
{job.state === "completed" && ( )} {canEdit && canCancelJob(job) && ( )}
{open && artifact && (

{artifact.title}

{artifact.summary}

)} {open && detail && !artifact &&

Result is unavailable.

} {error &&

{error}

}
); } export function Tasks({ store, connected, canEdit, headingId }: TasksProps) { let snapshot = useJobs(store); let jobs = currentJobs(snapshot.jobs); return (

Tasks & Progress

{!snapshot.ready &&

Loading background work…

} {snapshot.error &&

{snapshot.error}

} {snapshot.ready && jobs.length === 0 &&

No background work yet.

} {jobs.map(job => ( ))} {snapshot.truncated &&

Only the most recent background work is shown.

}
); }