jobs: after creating a job, show a View/Close confirmation instead of navigating away

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-23 15:57:42 +00:00
co-authored by Claude Opus 4.8
parent 39a235197c
commit 99293b0b49
@@ -740,9 +740,10 @@ type ScriptRunnerProps = {
entryType?: 'file' | 'directory';
filePath?: string;
selectedNames?: string[];
onClose: () => void;
};
const ScriptRunner = ({ taskDirName, autoInputs, context, cwd, entryType, filePath, selectedNames }: ScriptRunnerProps) => {
const ScriptRunner = ({ taskDirName, autoInputs, context, cwd, entryType, filePath, selectedNames, onClose }: ScriptRunnerProps) => {
const runner = useTaskRunner();
const client = useClient();
const navigate = useNavigate();
@@ -751,6 +752,8 @@ const ScriptRunner = ({ taskDirName, autoInputs, context, cwd, entryType, filePa
const [inline, setInline] = useState(false);
// Is a job already running? (drives the Run vs Queue affordance).
const [jobRunning, setJobRunning] = useState(false);
// After a job is created, show a confirmation (View / Close) rather than navigating away.
const [created, setCreated] = useState<{ jobId: string; action: 'start' | 'queue' } | null>(null);
const bottomRef = useRef<HTMLDivElement | null>(null);
const [inputDefs, setInputDefs] = useState<Record<string, TaskInputDef> | null>(null);
const [formValues, setFormValues] = useState<Record<string, string>>({});
@@ -938,12 +941,42 @@ const ScriptRunner = ({ taskDirName, autoInputs, context, cwd, entryType, filePa
const submitJob = async (action: 'start' | 'queue') => {
try {
const { jobId } = await client.post<{ jobId: string }>('/jobs', { taskDirName, inputs: buildAllInputs(), cwd, action });
navigate(action === 'queue' ? '/jobs' : `/jobs/${jobId}`);
setCreated({ jobId, action });
} catch {
/* stays on the modal so the user can retry */
}
};
if (created) {
return (
<div className="flex-1 flex flex-col items-center justify-center gap-4 p-8 text-center">
<CircleCheck className="h-10 w-10 text-duck-teal" />
<div>
<div className="text-base font-medium text-duck-dark dark:text-foreground">
{created.action === 'queue' ? 'Job queued' : 'Job started'}
</div>
<div className="text-sm text-duck-dark/50 dark:text-foreground/50 mt-1">
{created.action === 'queue' ? 'It will run when the current job finishes.' : "Its running in the background."}
</div>
</div>
<div className="flex items-center gap-3">
<button
onClick={() => { onClose(); navigate(created.action === 'queue' ? '/jobs' : `/jobs/${created.jobId}`); }}
className="flex items-center gap-2 px-5 py-2 rounded-lg bg-duck-teal text-white text-sm font-medium hover:bg-duck-teal/90 cursor-pointer"
>
<ExternalLink className="h-4 w-4" /> {created.action === 'queue' ? 'View queue' : 'View job'}
</button>
<button
onClick={onClose}
className="px-5 py-2 rounded-lg text-sm font-medium text-duck-dark/70 dark:text-foreground/70 hover:bg-duck-dark/5 dark:hover:bg-foreground/5 cursor-pointer"
>
Close
</button>
</div>
</div>
);
}
if (runner.phase === 'ready') {
return (
<div className="flex-1 flex flex-col">
@@ -1475,6 +1508,7 @@ export const TaskRunnerModal = ({ open, onOpenChange, task, entryName, entryFull
entryType={effectiveEntryType}
filePath={multi ? cwd.path || undefined : entryName ? (cwd.path ? `${cwd.path}/${entryName}` : entryName) : undefined}
selectedNames={multi ? selectedNames : undefined}
onClose={() => onOpenChange(false)}
/>
) : (
<PiMonoInner