diff --git a/ui/src/pages/RoutineDetail.tsx b/ui/src/pages/RoutineDetail.tsx index f25ffba9..59fa33aa 100644 --- a/ui/src/pages/RoutineDetail.tsx +++ b/ui/src/pages/RoutineDetail.tsx @@ -30,7 +30,7 @@ import { AgentIcon } from "../components/AgentIconPicker"; import { InlineEntitySelector, type InlineEntityOption } from "../components/InlineEntitySelector"; import { MarkdownEditor, type MarkdownEditorRef } from "../components/MarkdownEditor"; import { ScheduleEditor, describeSchedule } from "../components/ScheduleEditor"; -import { RunButton, PauseResumeButton } from "../components/AgentActionButtons"; +import { RunButton } from "../components/AgentActionButtons"; import { getRecentAssigneeIds, sortAgentsByRecency, trackRecentAssignee } from "../lib/recent-assignees"; import { Button } from "@/components/ui/button"; import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible"; @@ -280,15 +280,19 @@ export function RoutineDetail() { queryKey: queryKeys.routines.detail(routineId!), queryFn: () => routinesApi.get(routineId!), enabled: !!routineId, - refetchInterval: (query) => query.state.data?.activeIssue ? 5000 : false, }); - const hasLiveRun = !!routine?.activeIssue; const { data: routineRuns } = useQuery({ queryKey: queryKeys.routines.runs(routineId!), queryFn: () => routinesApi.listRuns(routineId!), enabled: !!routineId, - refetchInterval: hasLiveRun ? 3000 : false, + refetchInterval: (query) => { + const runs = query.state.data ?? []; + return runs.some((r) => r.status === "received" || r.status === "issue_created") ? 3000 : false; + }, }); + const hasLiveRun = (routineRuns ?? []).some( + (run) => run.status === "received" || run.status === "issue_created", + ); const relatedActivityIds = useMemo( () => ({ triggerIds: routine?.triggers.map((trigger) => trigger.id) ?? [], @@ -442,7 +446,7 @@ export function RoutineDetail() { mutationFn: (status: string) => routinesApi.update(routineId!, { status }), onSuccess: async (_data, status) => { pushToast({ - title: status === "paused" ? "Routine paused" : "Routine resumed", + title: status === "paused" ? "Automation paused" : "Automation enabled", tone: "success", }); await Promise.all([ @@ -607,29 +611,57 @@ export function RoutineDetail() { ); } + const automationEnabled = routine.status === "active"; + const automationToggleDisabled = updateRoutineStatus.isPending || routine.status === "archived"; + const automationLabel = routine.status === "archived" ? "Archived" : automationEnabled ? "Active" : "Paused"; + const automationLabelClassName = routine.status === "archived" + ? "text-muted-foreground" + : automationEnabled + ? "text-emerald-400" + : "text-muted-foreground"; + return (
{/* Header: status + actions */} -
- - {routine.status.replaceAll("_", " ")} - - {routine.activeIssue && ( - - {routine.activeIssue.identifier ?? routine.activeIssue.id.slice(0, 8)} - - )} -
+
+
+ {routine.activeIssue && ( + + Current issue + {routine.activeIssue.identifier ?? routine.activeIssue.id.slice(0, 8)} + + )} +
+
runRoutine.mutate()} disabled={runRoutine.isPending} /> - updateRoutineStatus.mutate("paused")} - onResume={() => updateRoutineStatus.mutate("active")} - disabled={updateRoutineStatus.isPending || routine.status === "archived"} - /> +
+ Automation +
+ + + {automationLabel} + +
+
@@ -953,9 +985,12 @@ export function RoutineDetail() { - {routine?.activeIssue && ( - - )} + {hasLiveRun && (() => { + const liveRun = (routineRuns ?? []).find((r) => r.status === "received" || r.status === "issue_created"); + const issueId = liveRun?.linkedIssue?.id ?? routine?.activeIssue?.id; + if (!issueId || !routine) return null; + return ; + })()} {(routineRuns ?? []).length === 0 ? (

No runs yet.

) : (