Files
next-tjwater-frontend/src/features/agent/components/agent-topic-controls.tsx
T
jiang 2d8506fea0
Generic Container CI/CD / test-build-publish (push) Successful in 2m9s
Frontend CI/CD / build-test-publish-and-deploy (push) Successful in 2m39s
feat: add project-aware agent workspace
2026-10-22 18:52:18 +08:00

56 lines
3.6 KiB
TypeScript

import { ChevronsUpDown, Folder, FolderPlus, Settings2 } from "lucide-react";
import { useRef, useState } from "react";
import type { AgentTopic } from "../api/client";
import { Button } from "@/shared/ui/button";
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuTrigger } from "@/shared/ui/dropdown-menu";
import { AgentTopicDialog } from "./agent-topic-dialog";
export type AgentTopicControlsProps = {
topics: AgentTopic[];
topicId?: string | null;
loading?: boolean;
error?: string;
onOpen: () => Promise<unknown>;
onSelect: (id: string | null) => void;
onCreate: (name: string) => Promise<unknown>;
onRename: (id: string, name: string) => Promise<unknown>;
onDelete: (id: string) => Promise<unknown>;
};
export function AgentTopicControls({ topics, topicId, loading, error, onOpen, onSelect, onCreate, onRename, onDelete }: AgentTopicControlsProps) {
const triggerRef = useRef<HTMLButtonElement>(null);
const [open, setOpen] = useState(false);
const [mode, setMode] = useState<"create" | "manage">("create");
const [dialogKey, setDialogKey] = useState(0);
const current = topics.find((topic) => topic.id === topicId);
const begin = (next: "create" | "manage") => {
setMode(next);
setDialogKey((key) => key + 1);
setOpen(true);
};
return <>
<DropdownMenu onOpenChange={(next) => { if (next) void onOpen().catch(() => {}); }}>
<DropdownMenuTrigger asChild><Button ref={triggerRef} variant="outline" size="sm" aria-label="选择主题" aria-description={current?.name ?? "未分类"} title={`主题:${current?.name ?? "未分类"}`} className="min-w-0 max-w-full justify-start gap-1.5 px-1.5 text-xs font-medium text-foreground">
<Folder aria-hidden="true" className="text-muted-foreground" /><span className="truncate">{current?.name ?? "未分类"}</span><ChevronsUpDown aria-hidden="true" className="ml-auto text-muted-foreground" />
</Button></DropdownMenuTrigger>
<DropdownMenuContent data-agent-theme="chat" align="start" side="bottom" className="w-[var(--radix-dropdown-menu-trigger-width)] min-w-56 max-w-[min(20rem,calc(100vw-1rem))]">
<DropdownMenuLabel className="text-xs font-normal text-muted-foreground">切换主题</DropdownMenuLabel>
<DropdownMenuRadioGroup value={current?.id ?? "unclassified"} onValueChange={(id) => onSelect(id === "unclassified" ? null : id)} className="max-h-[min(45dvh,15rem)] overflow-y-auto">
<DropdownMenuRadioItem value="unclassified">未分类</DropdownMenuRadioItem>
{topics.map((topic) => <DropdownMenuRadioItem key={topic.id} value={topic.id}>
<span className="min-w-0 line-clamp-2 break-words" title={topic.name}>{topic.name}</span>
</DropdownMenuRadioItem>)}
</DropdownMenuRadioGroup>
{loading ? <p role="status" className="px-2 py-2 text-xs text-muted-foreground">正在加载主题…</p> : null}
{error ? <p role="alert" className="px-2 py-2 text-xs text-destructive">{error}</p> : null}
<DropdownMenuSeparator className="bg-border/50" />
<DropdownMenuItem onSelect={() => begin("create")}><FolderPlus size={15} />新建主题</DropdownMenuItem>
<DropdownMenuItem onSelect={() => begin("manage")}><Settings2 size={15} />管理主题</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
<AgentTopicDialog key={dialogKey} open={open} initialMode={mode} onOpenChange={setOpen} triggerRef={triggerRef}
topics={topics} onCreate={onCreate} onRename={onRename} onDelete={onDelete} />
</>;
}