### What problem does this PR solve? Feat: Add agent page. #3221 ### Type of change - [x] New Feature (non-breaking change which adds functionality)tags/v0.17.0
| navigate(Routes.Chat); | navigate(Routes.Chat); | ||||
| }, [navigate]); | }, [navigate]); | ||||
| const navigateToAgentList = useCallback(() => { | |||||
| navigate(Routes.Agents); | |||||
| }, [navigate]); | |||||
| const navigateToAgent = useCallback(() => { | |||||
| navigate(Routes.Agent); | |||||
| }, [navigate]); | |||||
| const navigateToChunkParsedResult = useCallback( | const navigateToChunkParsedResult = useCallback( | ||||
| (id: string, knowledgeId?: string) => () => { | (id: string, knowledgeId?: string) => () => { | ||||
| navigate( | navigate( | ||||
| navigateToChunkParsedResult, | navigateToChunkParsedResult, | ||||
| getQueryString, | getQueryString, | ||||
| navigateToChunk, | navigateToChunk, | ||||
| navigateToAgentList, | |||||
| navigateToAgent, | |||||
| }; | }; | ||||
| }; | }; |
| { path: Routes.Datasets, name: t('knowledgeBase'), icon: Library }, | { path: Routes.Datasets, name: t('knowledgeBase'), icon: Library }, | ||||
| { path: Routes.Chats, name: t('chat'), icon: MessageSquareText }, | { path: Routes.Chats, name: t('chat'), icon: MessageSquareText }, | ||||
| { path: Routes.Search, name: t('search'), icon: Search }, | { path: Routes.Search, name: t('search'), icon: Search }, | ||||
| { path: Routes.Agent, name: t('flow'), icon: Cpu }, | |||||
| { path: Routes.Agents, name: t('flow'), icon: Cpu }, | |||||
| { path: Routes.Files, name: t('fileManager'), icon: File }, | { path: Routes.Files, name: t('fileManager'), icon: File }, | ||||
| ], | ], | ||||
| [t], | [t], |
| import { PageHeader } from '@/components/page-header'; | |||||
| import { Button } from '@/components/ui/button'; | |||||
| import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks'; | |||||
| import { Trash2 } from 'lucide-react'; | |||||
| export default function Agent() { | export default function Agent() { | ||||
| return <div>Agent</div>; | |||||
| const { navigateToAgentList } = useNavigatePage(); | |||||
| return ( | |||||
| <section> | |||||
| <PageHeader back={navigateToAgentList} title="Agent 01"> | |||||
| <div className="flex items-center gap-2"> | |||||
| <Button variant={'icon'} size={'icon'}> | |||||
| <Trash2 /> | |||||
| </Button> | |||||
| <Button variant={'outline'} size={'sm'}> | |||||
| Save | |||||
| </Button> | |||||
| <Button variant={'outline'} size={'sm'}> | |||||
| API | |||||
| </Button> | |||||
| <Button variant={'outline'} size={'sm'}> | |||||
| Run app | |||||
| </Button> | |||||
| <Button variant={'tertiary'} size={'sm'}> | |||||
| Publish | |||||
| </Button> | |||||
| </div> | |||||
| </PageHeader> | |||||
| </section> | |||||
| ); | |||||
| } | } |
| import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'; | |||||
| import { Button } from '@/components/ui/button'; | |||||
| import { Card, CardContent } from '@/components/ui/card'; | |||||
| import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks'; | |||||
| import { IFlow } from '@/interfaces/database/flow'; | |||||
| import { formatPureDate } from '@/utils/date'; | |||||
| import { ChevronRight, Trash2 } from 'lucide-react'; | |||||
| interface IProps { | |||||
| data: IFlow; | |||||
| } | |||||
| export function AgentCard({ data }: IProps) { | |||||
| const { navigateToAgent } = useNavigatePage(); | |||||
| return ( | |||||
| <Card className="bg-colors-background-inverse-weak border-colors-outline-neutral-standard"> | |||||
| <CardContent className="p-4"> | |||||
| <div className="flex justify-between mb-4"> | |||||
| {data.avatar ? ( | |||||
| <div | |||||
| className="w-[70px] h-[70px] rounded-xl bg-cover" | |||||
| style={{ backgroundImage: `url(${data.avatar})` }} | |||||
| /> | |||||
| ) : ( | |||||
| <Avatar className="w-[70px] h-[70px]"> | |||||
| <AvatarImage src="https://github.com/shadcn.png" /> | |||||
| <AvatarFallback>CN</AvatarFallback> | |||||
| </Avatar> | |||||
| )} | |||||
| </div> | |||||
| <h3 className="text-xl font-bold mb-2">{data.title}</h3> | |||||
| <p>An app that does things An app that does things</p> | |||||
| <section className="flex justify-between pt-3"> | |||||
| <div> | |||||
| Search app | |||||
| <p className="text-sm opacity-80"> | |||||
| {formatPureDate(data.update_time)} | |||||
| </p> | |||||
| </div> | |||||
| <div className="space-x-2"> | |||||
| <Button variant="icon" size="icon" onClick={navigateToAgent}> | |||||
| <ChevronRight className="h-6 w-6" /> | |||||
| </Button> | |||||
| <Button variant="icon" size="icon"> | |||||
| <Trash2 /> | |||||
| </Button> | |||||
| </div> | |||||
| </section> | |||||
| </CardContent> | |||||
| </Card> | |||||
| ); | |||||
| } |
| import ListFilterBar from '@/components/list-filter-bar'; | |||||
| import { useFetchFlowList } from '@/hooks/flow-hooks'; | |||||
| import { Plus } from 'lucide-react'; | |||||
| import { AgentCard } from './agent-card'; | |||||
| export default function Agent() { | |||||
| const { data } = useFetchFlowList(); | |||||
| return ( | |||||
| <section> | |||||
| <div className="px-8 pt-8"> | |||||
| <ListFilterBar title="Agents"> | |||||
| <Plus className="mr-2 h-4 w-4" /> | |||||
| Create app | |||||
| </ListFilterBar> | |||||
| </div> | |||||
| <div className="grid gap-6 sm:grid-cols-1 md:grid-cols-2 lg:grid-cols-4 xl:grid-cols-6 2xl:grid-cols-8 max-h-[84vh] overflow-auto px-8"> | |||||
| {data.map((x) => { | |||||
| return <AgentCard key={x.id} data={x}></AgentCard>; | |||||
| })} | |||||
| </div> | |||||
| </section> | |||||
| ); | |||||
| } |
| DatasetBase = '/dataset', | DatasetBase = '/dataset', | ||||
| Dataset = `${Routes.DatasetBase}${Routes.DatasetBase}`, | Dataset = `${Routes.DatasetBase}${Routes.DatasetBase}`, | ||||
| Agent = '/agent', | Agent = '/agent', | ||||
| Agents = '/agents', | |||||
| Search = '/next-search', | Search = '/next-search', | ||||
| Chats = '/next-chats', | Chats = '/next-chats', | ||||
| Chat = '/next-chat', | Chat = '/next-chat', | ||||
| ], | ], | ||||
| }, | }, | ||||
| { | { | ||||
| path: Routes.Agent, | |||||
| path: Routes.Agents, | |||||
| layout: false, | layout: false, | ||||
| component: '@/layouts/next', | component: '@/layouts/next', | ||||
| routes: [ | routes: [ | ||||
| { | { | ||||
| path: Routes.Agent, | |||||
| component: `@/pages${Routes.Agent}`, | |||||
| path: Routes.Agents, | |||||
| component: `@/pages${Routes.Agents}`, | |||||
| }, | }, | ||||
| ], | ], | ||||
| }, | }, | ||||
| { | |||||
| path: Routes.Agent, | |||||
| layout: false, | |||||
| component: `@/pages${Routes.Agent}`, | |||||
| }, | |||||
| { | { | ||||
| path: Routes.Files, | path: Routes.Files, | ||||
| layout: false, | layout: false, |