Replace ad hoc TaskCardProps data shape with SDK Task type across the Tasks group components and TasksScreen. - TaskCard: accept `task: Task` instead of flat props (taskId, status, method, target, progress, etc.); derive all display fields from the SDK Task object (taskId, status, ttl, createdAt, lastUpdatedAt, statusMessage); remove fields not present on SDK Task (method, target, progress as number, error, completedAt, elapsed) - TaskControls: type statusFilter as `TaskStatus | undefined`; add runtime validation guard on Select onChange - TaskListPanel: accept `Task[]` instead of `TaskCardProps[]`; pass `onCancel(taskId)` through to each TaskCard; use `task.taskId` as key - TasksScreen: accept `Task[]` + `onCancel(taskId)` callback; type internal statusFilter state as `TaskStatus | undefined` - Delete re-export of `TaskStatus` from TaskCard (import directly from SDK where needed) - Update all stories with real SDK `Task` fixtures - Update ConnectedView TasksActive story Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
61 lines
1.5 KiB
TypeScript
61 lines
1.5 KiB
TypeScript
import { Button, Group, Select, Stack, TextInput, Title } from "@mantine/core";
|
|
import type { TaskStatus } from "@modelcontextprotocol/sdk/types.js";
|
|
|
|
const STATUS_OPTIONS: TaskStatus[] = [
|
|
"working",
|
|
"input_required",
|
|
"completed",
|
|
"failed",
|
|
"cancelled",
|
|
];
|
|
|
|
const ToolbarButton = Button.withProps({
|
|
variant: "subtle",
|
|
size: "sm",
|
|
});
|
|
|
|
export interface TaskControlsProps {
|
|
searchText: string;
|
|
statusFilter?: TaskStatus;
|
|
onSearchChange: (text: string) => void;
|
|
onStatusFilterChange: (status: TaskStatus | undefined) => void;
|
|
onRefresh: () => void;
|
|
}
|
|
|
|
export function TaskControls({
|
|
searchText,
|
|
statusFilter,
|
|
onSearchChange,
|
|
onStatusFilterChange,
|
|
onRefresh,
|
|
}: TaskControlsProps) {
|
|
return (
|
|
<Stack gap="md">
|
|
<Group flex={1} justify={"space-between"}>
|
|
<Title order={4}>Tasks</Title>
|
|
<ToolbarButton onClick={onRefresh}>Refresh</ToolbarButton>
|
|
</Group>
|
|
<Title order={5}>Search</Title>
|
|
<TextInput
|
|
placeholder="Search..."
|
|
value={searchText}
|
|
onChange={(event) => onSearchChange(event.currentTarget.value)}
|
|
/>
|
|
|
|
<Title order={6}>Filter by Status</Title>
|
|
<Select
|
|
placeholder="All statuses"
|
|
data={STATUS_OPTIONS}
|
|
value={statusFilter ?? null}
|
|
onChange={(value) =>
|
|
onStatusFilterChange(
|
|
value && STATUS_OPTIONS.includes(value as TaskStatus)
|
|
? (value as TaskStatus)
|
|
: undefined,
|
|
)
|
|
}
|
|
clearable
|
|
/>
|
|
</Stack>
|
|
);
|
|
}
|