import { Ellipsis, Files, FlaskConical, Pencil, Plus, Trash2 } from 'lucide-react';
import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useNavigate, useParams } from 'react-router-dom';
import type { KnowledgeBaseView } from '@/api';
import { CreateCredentialDialog } from '@/components/dialog/CreateCredentialDialog.tsx';
import { CreateKnowledgeBaseDialog } from '@/components/dialog/CreateKnowledgeBaseDialog.tsx';
import { DeleteDialog } from '@/components/dialog/DeleteDialog.tsx';
import { EditKnowledgeBaseDialog } from '@/components/dialog/EditKnowledgeBaseDialog.tsx';
import { KnowledgeSearchDrawer } from '@/components/drawer/KnowledgeSearchDrawer.tsx';
import { KnowledgeDocumentsPanel } from '@/components/knowledge/KnowledgeDocumentsPanel.tsx';
import { Button } from '@/components/ui/button.tsx';
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu.tsx';
import {
Empty,
EmptyContent,
EmptyDescription,
EmptyHeader,
EmptyMedia,
EmptyTitle,
} from '@/components/ui/empty.tsx';
import { Separator } from '@/components/ui/separator.tsx';
import {
Sidebar,
SidebarContent,
SidebarFooter,
SidebarGroup,
SidebarGroupAction,
SidebarGroupContent,
SidebarGroupLabel,
SidebarHeader,
SidebarMenu,
SidebarMenuAction,
SidebarMenuButton,
SidebarMenuItem,
} from '@/components/ui/sidebar.tsx';
import { useKnowledgeBases } from '@/hooks/useKnowledgeBases.ts';
interface DetailPanelProps {
knowledgeBase?: KnowledgeBaseView;
onTest?: () => void;
}
function DetailPanel({ knowledgeBase, onTest }: DetailPanelProps) {
const { t } = useTranslation();
if (!knowledgeBase) {
return (
{t('knowledge.selectHint')}
{t('knowledge.selectHintDescription')}
);
}
return (
{/* Header */}
{knowledgeBase.name}
{knowledgeBase.description ? (
{knowledgeBase.description}
) : null}
{/* Documents */}
);
}
export const KnowledgePage = () => {
const navigate = useNavigate();
const { kbId: urlKbId } = useParams<{ kbId?: string }>();
const { t } = useTranslation();
const { knowledgeBases, remove, refetch } = useKnowledgeBases();
const [selectedKbId, setSelectedKbId] = useState(urlKbId);
const [createDialogOpen, setCreateDialogOpen] = useState(false);
const [credentialOpen, setCredentialOpen] = useState(false);
const [credentialRefetchTrigger, setCredentialRefetchTrigger] = useState(0);
const [editTarget, setEditTarget] = useState(null);
const [deleteTarget, setDeleteTarget] = useState(null);
const [testOpen, setTestOpen] = useState(false);
const selectedKb = knowledgeBases.find((kb) => kb.id === selectedKbId);
const handleCreated = async (knowledgeBaseId: string) => {
await refetch();
setSelectedKbId(knowledgeBaseId);
navigate(`/knowledge/${knowledgeBaseId}`);
};
const handleConfirmDelete = async () => {
if (!deleteTarget) return;
const id = deleteTarget.id;
await remove(id);
await refetch();
if (selectedKbId === id) {
setSelectedKbId(undefined);
navigate('/knowledge');
}
};
return (
{t('common.knowledge')}
{t('knowledge.subtitle')}
{t('knowledge.list.label')}
{knowledgeBases.length === 0 ? (
{t('knowledge.list.emptyTitle')}
{t('knowledge.list.emptyDescription')}
) : (
{knowledgeBases.map((kb) => {
return (
{
setSelectedKbId(kb.id);
navigate(`/knowledge/${kb.id}`);
}}
>
{kb.name}
setEditTarget(kb)}
>
{t('common.edit')}
setDeleteTarget(kb)}
>
{t('common.delete')}
);
})}
)}
setTestOpen(true)} />
setCredentialOpen(true)}
credentialRefetchTrigger={credentialRefetchTrigger}
/>
setCredentialRefetchTrigger((n) => n + 1)}
/>
{
if (!open) setEditTarget(null);
}}
knowledgeBase={editTarget}
onUpdated={() => refetch()}
/>
{
if (!open) setDeleteTarget(null);
}}
title={t('dialog-knowledge-base-delete.title')}
description={t('dialog-knowledge-base-delete.description', {
name: deleteTarget?.name ?? '',
})}
onConfirm={handleConfirmDelete}
/>
{selectedKb && (
)}
);
};