feat(web): unified task stream with plan tab, task detail drawer and audit links (FE-1)
Tasks page merges engine runs (with W9-I business fields) into one stream: all / active / failed / plan tabs, filters for source, business kind, status and time; detail drawer with business summary, timeline, collapsed engine steps, cancel/retry and related audit links. The schedule board moves into the plan tab; card history jumps to the stream filtered by schedule key. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
f8362a3f4c
commit
d8b9bd9662
10 files changed
+1189
-30
No files matched your search
@@ -1,5 +1,6 @@
|
||||
import type { AgentCheckConfig, ScheduledJob, ScheduleSpecInput } from "@umt/contracts";
|
||||
import { History, LoaderCircle, Pencil, Play, RotateCcw, SkipForward, Trash2 } from "lucide-react";
|
||||
import { useEffect, useRef } from "react";
|
||||
import { toast } from "sonner";
|
||||
import { useDeleteSchedule, useRunScheduleNow, useSkipSchedule, useUpdateSchedule } from "~/api/schedules.ts";
|
||||
import { ConfirmDialog } from "~/components/console/confirm-dialog.tsx";
|
||||
@@ -8,6 +9,7 @@ import { Button } from "~/components/ui/button.tsx";
|
||||
import { Switch } from "~/components/ui/switch.tsx";
|
||||
import { errorMessage } from "~/lib/api.ts";
|
||||
import { formatRelative } from "~/lib/labels.ts";
|
||||
import { cn } from "~/lib/utils.ts";
|
||||
import { IntervalEditor } from "./interval-editor.tsx";
|
||||
import { CHECK_TRIGGER_LABEL, countdown, formatMs, RUN_STATUS } from "./labels.ts";
|
||||
|
||||
@@ -54,16 +56,23 @@ export function ScheduleCard({
|
||||
now,
|
||||
onHistory,
|
||||
onEdit,
|
||||
highlight = false,
|
||||
}: {
|
||||
job: ScheduledJob;
|
||||
now: number;
|
||||
onHistory: (job: ScheduledJob) => void;
|
||||
onEdit: (job: ScheduledJob) => void;
|
||||
/** 从任务流跳来时高亮并滚到可见 */
|
||||
highlight?: boolean;
|
||||
}) {
|
||||
const update = useUpdateSchedule();
|
||||
const runNow = useRunScheduleNow();
|
||||
const skip = useSkipSchedule();
|
||||
const del = useDeleteSchedule();
|
||||
const ref = useRef<HTMLElement>(null);
|
||||
useEffect(() => {
|
||||
if (highlight) ref.current?.scrollIntoView({ block: "center" });
|
||||
}, [highlight]);
|
||||
const busy = !!job.runningSince || !!job.runRequestedAt;
|
||||
const last = job.lastStatus ? RUN_STATUS[job.lastStatus] : null;
|
||||
|
||||
@@ -74,7 +83,15 @@ export function ScheduleCard({
|
||||
);
|
||||
|
||||
return (
|
||||
<article className="pg-slab grid min-w-0 gap-3 rounded-xl px-4 py-3.5" aria-label={job.name}>
|
||||
<article
|
||||
id={`job-${job.id}`}
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"pg-slab grid min-w-0 scroll-mt-20 gap-3 rounded-xl px-4 py-3.5",
|
||||
highlight && "ring-2 ring-ring/50",
|
||||
)}
|
||||
aria-label={job.name}
|
||||
>
|
||||
<header className="flex items-start justify-between gap-3">
|
||||
<div className="min-w-0">
|
||||
<h3 className="truncate text-lead font-medium text-foreground" title={job.name}>
|
||||
|
||||
Reference in new issue
Block a user