diff --git a/web/src/hooks/logic-hooks/navigate-hooks.ts b/web/src/hooks/logic-hooks/navigate-hooks.ts index 3951ca5e6..c09a01ab1 100644 --- a/web/src/hooks/logic-hooks/navigate-hooks.ts +++ b/web/src/hooks/logic-hooks/navigate-hooks.ts @@ -46,6 +46,10 @@ export const useNavigatePage = () => { navigate(Routes.Agent); }, [navigate]); + const navigateToAgentTemplates = useCallback(() => { + navigate(Routes.AgentTemplates); + }, [navigate]); + const navigateToSearchList = useCallback(() => { navigate(Routes.Searches); }, [navigate]); @@ -99,6 +103,7 @@ export const useNavigatePage = () => { navigateToChunk, navigateToAgentList, navigateToAgent, + navigateToAgentTemplates, navigateToSearchList, navigateToSearch, }; diff --git a/web/src/pages/agents/agent-templates.tsx b/web/src/pages/agents/agent-templates.tsx new file mode 100644 index 000000000..16eb87c64 --- /dev/null +++ b/web/src/pages/agents/agent-templates.tsx @@ -0,0 +1,51 @@ +import { PageHeader } from '@/components/page-header'; +import { useSetModalState } from '@/hooks/common-hooks'; +import { useFetchFlowTemplates } from '@/hooks/flow-hooks'; +import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks'; +import { useCallback } from 'react'; +import { useTranslation } from 'react-i18next'; +import { CreateAgentDialog } from './create-agent-dialog'; +import { TemplateCard } from './template-card'; + +export default function AgentTemplates() { + const { navigateToAgentList } = useNavigatePage(); + const { t } = useTranslation(); + const { data: list } = useFetchFlowTemplates(); + const { + visible: creatingVisible, + hideModal: hideCreatingModal, + showModal: showCreatingModal, + } = useSetModalState(); + + const handleOk = useCallback(async () => { + // return onOk(name, checkedId); + }, []); + + return ( +
+ +
+ {list?.map((x) => { + return ( + + ); + })} +
+ {creatingVisible && ( + + )} +
+ ); +} diff --git a/web/src/pages/agents/create-agent-dialog.tsx b/web/src/pages/agents/create-agent-dialog.tsx new file mode 100644 index 000000000..dd866085d --- /dev/null +++ b/web/src/pages/agents/create-agent-dialog.tsx @@ -0,0 +1,36 @@ +import { + Dialog, + DialogContent, + DialogFooter, + DialogHeader, + DialogTitle, +} from '@/components/ui/dialog'; +import { LoadingButton } from '@/components/ui/loading-button'; +import { IModalProps } from '@/interfaces/common'; +import { TagRenameId } from '@/pages/add-knowledge/constant'; +import { useTranslation } from 'react-i18next'; +import { CreateAgentForm } from './create-agent-form'; + +export function CreateAgentDialog({ + hideModal, + onOk, + loading, +}: IModalProps) { + const { t } = useTranslation(); + + return ( + + + + {t('flow.createGraph')} + + + + + {t('common.save')} + + + + + ); +} diff --git a/web/src/pages/agents/create-agent-form.tsx b/web/src/pages/agents/create-agent-form.tsx new file mode 100644 index 000000000..69285c979 --- /dev/null +++ b/web/src/pages/agents/create-agent-form.tsx @@ -0,0 +1,106 @@ +'use client'; + +import { zodResolver } from '@hookform/resolvers/zod'; +import { useForm } from 'react-hook-form'; +import { z } from 'zod'; + +import { + Form, + FormControl, + FormField, + FormItem, + FormLabel, + FormMessage, +} from '@/components/ui/form'; +import { Input } from '@/components/ui/input'; +import { IModalProps } from '@/interfaces/common'; +import { TagRenameId } from '@/pages/add-knowledge/constant'; +import { useTranslation } from 'react-i18next'; + +export function CreateAgentForm({ hideModal, onOk }: IModalProps) { + const { t } = useTranslation(); + const FormSchema = z.object({ + name: z + .string() + .min(1, { + message: t('common.namePlaceholder'), + }) + .trim(), + tag: z.string().trim().optional(), + description: z.string().trim().optional(), + }); + + const form = useForm>({ + resolver: zodResolver(FormSchema), + defaultValues: { name: '' }, + }); + + async function onSubmit(data: z.infer) { + const ret = await onOk?.(data); + if (ret) { + hideModal?.(); + } + } + + return ( +
+ + ( + + {t('common.name')} + + + + + + )} + /> + ( + + {t('flow.tag')} + + + + + + )} + /> + ( + + {t('flow.description')} + + + + + + )} + /> + + + ); +} diff --git a/web/src/pages/agents/index.tsx b/web/src/pages/agents/index.tsx index 7a037758c..f568dc629 100644 --- a/web/src/pages/agents/index.tsx +++ b/web/src/pages/agents/index.tsx @@ -1,15 +1,17 @@ import ListFilterBar from '@/components/list-filter-bar'; import { useFetchFlowList } from '@/hooks/flow-hooks'; +import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks'; import { Plus } from 'lucide-react'; import { AgentCard } from './agent-card'; export default function Agent() { const { data } = useFetchFlowList(); + const { navigateToAgentTemplates } = useNavigatePage(); return (
- + Create app diff --git a/web/src/pages/agents/template-card.tsx b/web/src/pages/agents/template-card.tsx new file mode 100644 index 000000000..38c7fa44e --- /dev/null +++ b/web/src/pages/agents/template-card.tsx @@ -0,0 +1,45 @@ +import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'; +import { Button } from '@/components/ui/button'; +import { Card, CardContent } from '@/components/ui/card'; +import { useSetModalState } from '@/hooks/common-hooks'; +import { IFlowTemplate } from '@/interfaces/database/flow'; +import { useTranslation } from 'react-i18next'; + +interface IProps { + data: IFlowTemplate; +} + +export function TemplateCard({ + data, + showModal, +}: IProps & Pick, 'showModal'>) { + const { t } = useTranslation(); + return ( + + +
+ {data.avatar ? ( +
+ ) : ( + + + CN + + )} +
+

{data.title}

+

{data.description}

+ + + + ); +} diff --git a/web/src/routes.ts b/web/src/routes.ts index 754e82ed4..c7376e7bd 100644 --- a/web/src/routes.ts +++ b/web/src/routes.ts @@ -5,6 +5,7 @@ export enum Routes { DatasetBase = '/dataset', Dataset = `${Routes.DatasetBase}${Routes.DatasetBase}`, Agent = '/agent', + AgentTemplates = '/agent-templates', Agents = '/agents', Searches = '/next-searches', Search = '/next-search', @@ -218,6 +219,11 @@ const routes = [ layout: false, component: `@/pages${Routes.Agent}`, }, + { + path: Routes.AgentTemplates, + layout: false, + component: `@/pages${Routes.Agents}${Routes.AgentTemplates}`, + }, { path: Routes.Files, layout: false,