diff --git a/web/src/hooks/use-knowledge-request.ts b/web/src/hooks/use-knowledge-request.ts index 8ecba3f6a0..99503df057 100644 --- a/web/src/hooks/use-knowledge-request.ts +++ b/web/src/hooks/use-knowledge-request.ts @@ -30,6 +30,7 @@ import { import i18n from '@/locales/config'; import kbService, { clearWiki, + deleteArtifactsStructure, deleteKnowledgeGraph, getArtifactsAlteration, getArtifactGraph, @@ -95,6 +96,7 @@ export const enum KnowledgeApiAction { RemoveKnowledgeGraph = 'removeKnowledgeGraph', ClearWiki = 'clearWiki', FetchDatasetStructure = 'fetchDatasetStructure', + DeleteDatasetStructure = 'deleteDatasetStructure', FetchArtifactAlteration = 'fetchArtifactAlteration', RunArtifactIndex = 'runArtifactIndex', } @@ -833,6 +835,31 @@ export function useFetchDatasetStructureGraph(kind: string, keywords?: string) { return { data, loading }; } +export const useDeleteDatasetStructure = () => { + const knowledgeBaseId = useKnowledgeBaseId(); + const queryClient = useQueryClient(); + + const { + data, + isPending: loading, + mutateAsync, + } = useMutation({ + mutationKey: [KnowledgeApiAction.DeleteDatasetStructure], + mutationFn: async (kind: string) => { + const { data } = await deleteArtifactsStructure(knowledgeBaseId, kind); + if (data?.code === 0) { + message.success(i18n.t('message.deleted')); + queryClient.invalidateQueries({ + queryKey: DatasetStructureKeys.all(knowledgeBaseId), + }); + } + return data?.code; + }, + }); + + return { data, loading, deleteDatasetStructure: mutateAsync }; +}; + export function useFetchKnowledgeMetadata(kbIds: string[] = []) { const { data, isFetching: loading } = useQuery< Record> diff --git a/web/src/locales/en.ts b/web/src/locales/en.ts index 1a9a40a054..e2030651d7 100644 --- a/web/src/locales/en.ts +++ b/web/src/locales/en.ts @@ -537,6 +537,7 @@ Example: A 1 KB message with 1024-dim embedding uses ~9 KB. The 5 MB default lim noStructureTimeline: 'No timeline yet', noStructureSessionEssence: 'No session essence yet', noStructureSessionGraph: 'No session graph yet', + deleteStructureConfirm: 'Are you sure you want to delete the {{name}}?', contents: 'Navigation', topics: 'Topics', concept: 'Concept', diff --git a/web/src/locales/zh.ts b/web/src/locales/zh.ts index 893ae64187..c047177394 100644 --- a/web/src/locales/zh.ts +++ b/web/src/locales/zh.ts @@ -482,6 +482,7 @@ export default { noStructureTimeline: '暂无时间线', noStructureSessionEssence: '暂无会话摘要', noStructureSessionGraph: '暂无会话图谱', + deleteStructureConfirm: '确定要删除{{name}}吗?', contents: '导航', topics: '主题', concept: '概念', diff --git a/web/src/pages/dataset/compilation/constants.ts b/web/src/pages/dataset/compilation/constants.ts index f059292c0e..7e8dba9d51 100644 --- a/web/src/pages/dataset/compilation/constants.ts +++ b/web/src/pages/dataset/compilation/constants.ts @@ -26,6 +26,12 @@ export const StructureKinds = [ export type StructureKind = (typeof StructureKinds)[number]; +export const StructureKindLabelKeyMap: Record = { + [ViewMode.Graph]: 'knowledgeDetails.structureGraph', + [ViewMode.MindMap]: 'knowledgeDetails.structureMindmap', + [ViewMode.Timeline]: 'knowledgeDetails.structureTimeline', +}; + export type GenerableViewMode = Exclude; export const ViewModeGenerateTypeMap: Record = diff --git a/web/src/pages/dataset/compilation/dataset-structure-view.tsx b/web/src/pages/dataset/compilation/dataset-structure-view.tsx index 870249ee31..0a1300b440 100644 --- a/web/src/pages/dataset/compilation/dataset-structure-view.tsx +++ b/web/src/pages/dataset/compilation/dataset-structure-view.tsx @@ -2,11 +2,14 @@ import { SelectWithSearch, SelectWithSearchFlagOptionType, } from '@/components/originui/select-with-search'; +import { ConfirmDeleteDialog } from '@/components/confirm-delete-dialog'; import { getEntityDisplayName } from '@/components/structure-graph/adapters'; import { RepresentationRenderer } from '@/components/structure-graph/representation-renderer'; +import { Button } from '@/components/ui/button'; import { Card } from '@/components/ui/card'; import { DatasetStructureKeys, + useDeleteDatasetStructure, useFetchDatasetStructureGraph, useFetchKnowledgeBaseConfiguration, useKnowledgeBaseId, @@ -15,10 +18,16 @@ import { GenerateStatus } from '@/pages/dataset/dataset/generate-button/constant import { useTraceRunData } from '@/pages/dataset/dataset/generate-button/hook'; import { useGenerateStatus } from '@/pages/dataset/dataset/generate-button/use-generate-status'; import { useQueryClient } from '@tanstack/react-query'; +import { Trash2 } from 'lucide-react'; import { useCallback, useEffect, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { StructureKind, ViewMode, ViewModeGenerateTypeMap } from './constants'; +import { + StructureKind, + StructureKindLabelKeyMap, + ViewMode, + ViewModeGenerateTypeMap, +} from './constants'; import CompilationEmptyState from './empty-state'; import { CompilationLoadingCard } from './loading-card'; @@ -35,6 +44,8 @@ export function DatasetStructureView({ kind }: DatasetStructureViewProps) { const [selectedNodeId, setSelectedNodeId] = useState(''); const { data, loading } = useFetchDatasetStructureGraph(kind, graphKeywords); const template = data?.templates?.[0]; + const { deleteDatasetStructure, loading: deleting } = + useDeleteDatasetStructure(); const { data: structureRunData } = useTraceRunData( ViewModeGenerateTypeMap[kind], @@ -86,6 +97,14 @@ export function DatasetStructureView({ kind }: DatasetStructureViewProps) { setSelectedNodeId(''); }, []); + const handleDeleteStructure = useCallback(async () => { + const code = await deleteDatasetStructure(kind); + if (code === 0) { + setGraphKeywords(''); + setSelectedNodeId(''); + } + }, [deleteDatasetStructure, kind]); + const canGenerate = (knowledgeBase?.chunk_count ?? 0) > 0; if (loading && !data) { @@ -104,8 +123,18 @@ export function DatasetStructureView({ kind }: DatasetStructureViewProps) { return ( - {kind === ViewMode.Graph && ( -
+
+ + + + {kind === ViewMode.Graph && ( -
- )} + )} +
+ request.delete(api.artifactsStructure(datasetId), { params: { kind } }); + export const updateArtifactPage = ( datasetId: string, pageType: string,