From 5ac8d92d2eb1b6756d8235164323df0a4f930d7a Mon Sep 17 00:00:00 2001 From: balibabu Date: Thu, 30 Jul 2026 18:40:29 +0800 Subject: [PATCH] Feat: Add an update button to the graph page of the dataset. (#17571) ### Summary Feat: Add an update button to the graph page of the dataset. --- .../generate-log-button.tsx | 6 +- .../graph-rag-form-fields.tsx | 11 ++- .../raptor-form-fields.tsx | 11 ++- web/src/constants/knowledge.ts | 63 +++++++++++++ .../hook.ts => hooks/use-dataset-generate.ts} | 40 ++++++++- web/src/hooks/use-knowledge-request.ts | 21 +++-- web/src/locales/en.ts | 3 + web/src/locales/zh.ts | 3 + .../pages/dataset/compilation/constants.ts | 2 +- .../compilation/dataset-structure-view.tsx | 80 +++++++++++++---- .../pages/dataset/compilation/empty-state.tsx | 4 +- .../dataset/compilation/llm-wiki-view.tsx | 13 ++- .../pages/dataset/compilation/skills-view.tsx | 13 ++- .../dataset/compilation/update-button.tsx | 88 +++++++++++++++++++ ...-update-sheet.tsx => update-log-sheet.tsx} | 25 +++--- ...e-progress.tsx => update-run-progress.tsx} | 22 ++--- .../wiki-left-panel/hooks/use-wiki-update.ts | 4 +- .../compilation/wiki-left-panel/index.tsx | 87 ++++++------------ .../dataset-overview/dataset-common.ts | 23 ----- .../dataset-overview/overview-table.tsx | 8 +- .../dataset/generate-button/constants.ts | 41 --------- .../generate-button/use-generate-status.ts | 33 ------- web/src/services/knowledge-service.ts | 6 +- 23 files changed, 355 insertions(+), 252 deletions(-) rename web/src/{pages/dataset/dataset/generate-button => components}/generate-log-button.tsx (95%) rename web/src/{pages/dataset/dataset/generate-button/hook.ts => hooks/use-dataset-generate.ts} (83%) create mode 100644 web/src/pages/dataset/compilation/update-button.tsx rename web/src/pages/dataset/compilation/{wiki-left-panel/wiki-update-sheet.tsx => update-log-sheet.tsx} (52%) rename web/src/pages/dataset/compilation/{wiki-left-panel/wiki-update-progress.tsx => update-run-progress.tsx} (73%) delete mode 100644 web/src/pages/dataset/dataset/generate-button/constants.ts delete mode 100644 web/src/pages/dataset/dataset/generate-button/use-generate-status.ts diff --git a/web/src/pages/dataset/dataset/generate-button/generate-log-button.tsx b/web/src/components/generate-log-button.tsx similarity index 95% rename from web/src/pages/dataset/dataset/generate-button/generate-log-button.tsx rename to web/src/components/generate-log-button.tsx index f7bd610a26..57f7e5dacb 100644 --- a/web/src/pages/dataset/dataset/generate-button/generate-log-button.tsx +++ b/web/src/components/generate-log-button.tsx @@ -1,12 +1,12 @@ import { Button } from '@/components/ui/button'; import { Modal } from '@/components/ui/modal/modal'; +import { GenerateType, GenerateTypeMap } from '@/constants/knowledge'; +import { useUnBindTask } from '@/hooks/use-dataset-generate'; import { cn } from '@/lib/utils'; import { formatDate } from '@/utils/date'; import { lowerFirst } from 'lodash'; import { Trash2 } from 'lucide-react'; import { useTranslation } from 'react-i18next'; -import { GenerateType, GenerateTypeMap } from './constants'; -import { useUnBindTask } from './hook'; export type IGenerateLogButtonProps = { finish_at: string; @@ -112,5 +112,3 @@ export function GenerateLogButton(props: IGenerateLogProps) { ); } - -export default GenerateLogButton; diff --git a/web/src/components/parse-configuration/graph-rag-form-fields.tsx b/web/src/components/parse-configuration/graph-rag-form-fields.tsx index c19409b245..5a01a2deb3 100644 --- a/web/src/components/parse-configuration/graph-rag-form-fields.tsx +++ b/web/src/components/parse-configuration/graph-rag-form-fields.tsx @@ -1,19 +1,18 @@ import { FormLayout } from '@/constants/form'; -import { DocumentParserType } from '@/constants/knowledge'; +import { DocumentParserType, GenerateType } from '@/constants/knowledge'; import { useTranslate } from '@/hooks/common-hooks'; import { cn } from '@/lib/utils'; import { useKnowledgeBaseContext } from '@/pages/dataset/contexts/knowledge-base-context'; import { LLMModelItem } from '@/pages/dataset/dataset-setting/configuration/common-item'; -import { GenerateType } from '@/pages/dataset/dataset/generate-button/constants'; -import { - GenerateLogButton, - IGenerateLogButtonProps, -} from '@/pages/dataset/dataset/generate-button/generate-log-button'; import { upperFirst } from 'lodash'; import { useCallback, useMemo } from 'react'; import { useFormContext, useWatch } from 'react-hook-form'; import { EntityTypesFormField } from '../entity-types-form-field'; import { FormContainer } from '../form-container'; +import { + GenerateLogButton, + IGenerateLogButtonProps, +} from '../generate-log-button'; import { SliderInputFormField } from '../slider-input-form-field'; import { FormControl, diff --git a/web/src/components/parse-configuration/raptor-form-fields.tsx b/web/src/components/parse-configuration/raptor-form-fields.tsx index c0eb41d225..1cc2de5c72 100644 --- a/web/src/components/parse-configuration/raptor-form-fields.tsx +++ b/web/src/components/parse-configuration/raptor-form-fields.tsx @@ -1,15 +1,14 @@ import { FormLayout } from '@/constants/form'; -import { DocumentParserType } from '@/constants/knowledge'; +import { DocumentParserType, GenerateType } from '@/constants/knowledge'; import { useTranslate } from '@/hooks/common-hooks'; -import { GenerateType } from '@/pages/dataset/dataset/generate-button/constants'; -import { - GenerateLogButton, - IGenerateLogButtonProps, -} from '@/pages/dataset/dataset/generate-button/generate-log-button'; import random from 'lodash/random'; import { Shuffle } from 'lucide-react'; import { useCallback, useEffect, useMemo } from 'react'; import { useFormContext, useWatch } from 'react-hook-form'; +import { + GenerateLogButton, + IGenerateLogButtonProps, +} from '../generate-log-button'; import { SliderInputFormField } from '../slider-input-form-field'; import { FormControl, diff --git a/web/src/constants/knowledge.ts b/web/src/constants/knowledge.ts index d7ef00793f..d723f4f093 100644 --- a/web/src/constants/knowledge.ts +++ b/web/src/constants/knowledge.ts @@ -116,3 +116,66 @@ export enum ParseType { BuiltIn = 1, Pipeline = 2, } + +export enum ProcessingType { + knowledgeGraph = 'Graph', + raptor = 'RAPTOR', + artifact = 'Artifact', + skill = 'Skill', + mindmap = 'Mindmap', + timeline = 'Timeline', + sessionEssence = 'Session_Essence', + sessionGraph = 'Session_Graph', +} + +export const ProcessingTypeMap = { + [ProcessingType.knowledgeGraph]: 'Knowledge Graph', + [ProcessingType.raptor]: 'RAPTOR', + [ProcessingType.artifact]: 'Artifact', + [ProcessingType.skill]: 'Skill', + [ProcessingType.mindmap]: 'Mind Map', + [ProcessingType.timeline]: 'Timeline', + [ProcessingType.sessionEssence]: 'Session Essence', + [ProcessingType.sessionGraph]: 'Session Graph', + GraphRAG: 'Knowledge Graph', +}; + +export enum GenerateStatus { + Running = 'running', + Completed = 'completed', + Start = 'start', + Failed = 'failed', +} + +export enum GenerateType { + KnowledgeGraph = 'KnowledgeGraph', + Raptor = 'Raptor', + Artifact = 'Artifact', + ToSkills = 'ToSkills', + MindMap = 'MindMap', + Timeline = 'Timeline', + SessionEssence = 'SessionEssence', + SessionGraph = 'SessionGraph', +} + +export enum TraceType { + Graph = 'graph', + Raptor = 'raptor', + Artifact = 'artifact', + Skill = 'skill', + MindMap = 'mindmap', + Timeline = 'timeline', + SessionEssence = 'session_essence', + SessionGraph = 'session_graph', +} + +export const GenerateTypeMap = { + [GenerateType.KnowledgeGraph]: ProcessingType.knowledgeGraph, + [GenerateType.Raptor]: ProcessingType.raptor, + [GenerateType.Artifact]: ProcessingType.artifact, + [GenerateType.ToSkills]: ProcessingType.skill, + [GenerateType.MindMap]: ProcessingType.mindmap, + [GenerateType.Timeline]: ProcessingType.timeline, + [GenerateType.SessionEssence]: ProcessingType.sessionEssence, + [GenerateType.SessionGraph]: ProcessingType.sessionGraph, +}; diff --git a/web/src/pages/dataset/dataset/generate-button/hook.ts b/web/src/hooks/use-dataset-generate.ts similarity index 83% rename from web/src/pages/dataset/dataset/generate-button/hook.ts rename to web/src/hooks/use-dataset-generate.ts index 04cbd583e1..a0092f9ae4 100644 --- a/web/src/pages/dataset/dataset/generate-button/hook.ts +++ b/web/src/hooks/use-dataset-generate.ts @@ -1,4 +1,11 @@ import message from '@/components/ui/message'; +import { + GenerateStatus, + GenerateType, + GenerateTypeMap, + ProcessingType, + TraceType, +} from '@/constants/knowledge'; import agentService from '@/services/agent-service'; import { deletePipelineTask, @@ -6,10 +13,9 @@ import { traceIndex, } from '@/services/knowledge-service'; import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; +import { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import { useParams } from 'react-router'; -import { ProcessingType } from '../../dataset-overview/dataset-common'; -import { GenerateType, GenerateTypeMap, TraceType } from './constants'; enum DatasetKey { generate = 'generate', @@ -111,6 +117,7 @@ export const useUnBindTask = () => { }); return { handleUnbindTask }; }; + export const useDatasetGenerate = () => { const queryClient = useQueryClient(); const { id } = useParams(); @@ -164,3 +171,32 @@ export const useDatasetGenerate = () => { }); return { runGenerate: mutateAsync, pauseGenerate, data, loading }; }; + +export function useGenerateStatus(data?: ITraceInfo) { + const status = useMemo(() => { + if (!data) { + return GenerateStatus.Start; + } + if (data.progress >= 1) { + return GenerateStatus.Completed; + } else if (!data.progress && data.progress !== 0) { + return GenerateStatus.Start; + } else if (data.progress < 0) { + return GenerateStatus.Failed; + } else if (data.progress < 1) { + return GenerateStatus.Running; + } + return GenerateStatus.Start; + }, [data]); + + const percent = useMemo(() => { + if (status === GenerateStatus.Failed) { + return 100; + } else if (status === GenerateStatus.Running) { + return data!.progress * 100; + } + return 0; + }, [status, data]); + + return { status, percent }; +} diff --git a/web/src/hooks/use-knowledge-request.ts b/web/src/hooks/use-knowledge-request.ts index 9007a3aae1..140565c55d 100644 --- a/web/src/hooks/use-knowledge-request.ts +++ b/web/src/hooks/use-knowledge-request.ts @@ -1,9 +1,7 @@ import { useHandleFilterSubmit } from '@/components/list-filter-bar/use-handle-filter-submit'; import message from '@/components/ui/message'; -import { ParseType } from '@/constants/knowledge'; +import { GenerateType, ParseType } from '@/constants/knowledge'; import { ResponsePostType, ResponseType } from '@/interfaces/database/base'; -import { GenerateType } from '@/pages/dataset/dataset/generate-button/constants'; -import { DatasetGenerateKeys } from '@/pages/dataset/dataset/generate-button/hook'; import { IArtifact, IArtifactAlteration, @@ -73,6 +71,7 @@ import { isPipelineParserConfig, } from './parser-config-utils'; import { useSetPaginationParams } from './route-hook'; +import { DatasetGenerateKeys } from './use-dataset-generate'; export const enum KnowledgeApiAction { FetchKnowledgeListByPage = 'fetchKnowledgeListByPage', @@ -450,20 +449,20 @@ export const ArtifactTopicKeys = { }; export const ArtifactAlterationKeys = { - detail: (datasetId: string) => - [KnowledgeApiAction.FetchArtifactAlteration, datasetId] as const, + detail: (datasetId: string, kind: string) => + [KnowledgeApiAction.FetchArtifactAlteration, datasetId, kind] as const, }; -export function useFetchArtifactAlteration() { +export function useFetchArtifactAlteration(kind: string) { const knowledgeBaseId = useKnowledgeBaseId(); const { data, isFetching: loading } = useQuery({ - queryKey: ArtifactAlterationKeys.detail(knowledgeBaseId), + queryKey: ArtifactAlterationKeys.detail(knowledgeBaseId, kind), initialData: null, - enabled: !!knowledgeBaseId, + enabled: !!knowledgeBaseId && !!kind, gcTime: 0, queryFn: async () => { - const { data } = await getArtifactsAlteration(knowledgeBaseId); + const { data } = await getArtifactsAlteration(knowledgeBaseId, kind); return data?.data ?? null; }, }); @@ -953,7 +952,7 @@ export const useClearWiki = () => { return { data, loading, clearWiki: mutateAsync }; }; -export const useRunArtifactIndex = () => { +export const useRunArtifactIndex = (kind: string) => { const knowledgeBaseId = useKnowledgeBaseId(); const queryClient = useQueryClient(); @@ -968,7 +967,7 @@ export const useRunArtifactIndex = () => { if (data?.code === 0) { message.success(i18n.t('message.operated')); queryClient.invalidateQueries({ - queryKey: ArtifactAlterationKeys.detail(knowledgeBaseId), + queryKey: ArtifactAlterationKeys.detail(knowledgeBaseId, kind), }); queryClient.invalidateQueries({ queryKey: ArtifactKeys.listByDataset(knowledgeBaseId), diff --git a/web/src/locales/en.ts b/web/src/locales/en.ts index 7d2b78f36a..a8e9d20fc3 100644 --- a/web/src/locales/en.ts +++ b/web/src/locales/en.ts @@ -469,6 +469,9 @@ Example: A 1 KB message with 1024-dim embedding uses ~9 KB. The 5 MB default lim updateTooltip: '{{newlyUploaded}} new, {{removed}} removed documents found. Click to compile and merge into current Wiki.', updateSheetTitle: 'Update Wiki', + updateStructureSheetTitle: 'Update {{name}}', + updateStructureTooltip: + '{{newlyUploaded}} new, {{removed}} removed documents found. Click to update the {{name}}.', viewUpdateLogs: 'View update logs', log: 'Log', noSkills: 'No skills yet', diff --git a/web/src/locales/zh.ts b/web/src/locales/zh.ts index 32368be78d..1ea30be696 100644 --- a/web/src/locales/zh.ts +++ b/web/src/locales/zh.ts @@ -419,6 +419,9 @@ export default { updateTooltip: '发现 {{newlyUploaded}} 个新文档,{{removed}} 个已移除文档。点击编译并合并到当前 Wiki。', updateSheetTitle: '更新 Wiki', + updateStructureSheetTitle: '更新{{name}}', + updateStructureTooltip: + '发现 {{newlyUploaded}} 个新文档,{{removed}} 个已移除文档。点击更新{{name}}。', viewUpdateLogs: '查看更新日志', log: '日志', noSkills: '暂无技能', diff --git a/web/src/pages/dataset/compilation/constants.ts b/web/src/pages/dataset/compilation/constants.ts index c40a3f5ff9..378f5a990b 100644 --- a/web/src/pages/dataset/compilation/constants.ts +++ b/web/src/pages/dataset/compilation/constants.ts @@ -1,4 +1,4 @@ -import { GenerateType } from '@/pages/dataset/dataset/generate-button/constants'; +import { GenerateType } from '@/constants/knowledge'; export enum ViewMode { LlmWiki = 'llm-wiki', diff --git a/web/src/pages/dataset/compilation/dataset-structure-view.tsx b/web/src/pages/dataset/compilation/dataset-structure-view.tsx index bf8bc5e703..1449cccfc4 100644 --- a/web/src/pages/dataset/compilation/dataset-structure-view.tsx +++ b/web/src/pages/dataset/compilation/dataset-structure-view.tsx @@ -7,16 +7,20 @@ 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 { GenerateStatus } from '@/constants/knowledge'; +import { + useDatasetGenerate, + useGenerateStatus, + useTraceRunData, +} from '@/hooks/use-dataset-generate'; import { DatasetStructureKeys, useDeleteDatasetStructure, + useFetchArtifactAlteration, useFetchDatasetStructureGraph, useFetchKnowledgeBaseConfiguration, useKnowledgeBaseId, } from '@/hooks/use-knowledge-request'; -import { GenerateStatus } from '@/pages/dataset/dataset/generate-button/constants'; -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'; @@ -30,6 +34,8 @@ import { } from './constants'; import CompilationEmptyState from './empty-state'; import { CompilationLoadingCard } from './loading-card'; +import { CompilationUpdateButton } from './update-button'; +import { UpdateLogSheet } from './update-log-sheet'; interface DatasetStructureViewProps { kind: StructureKind; @@ -47,13 +53,21 @@ export function DatasetStructureView({ kind }: DatasetStructureViewProps) { const { deleteDatasetStructure, loading: deleting } = useDeleteDatasetStructure(); - const { data: structureRunData } = useTraceRunData( - ViewModeGenerateTypeMap[kind], - ); + const generateType = ViewModeGenerateTypeMap[kind]; + const { data: structureRunData } = useTraceRunData(generateType); const { status: structureStatus } = useGenerateStatus(structureRunData); + const { data: alteration, loading: alterationLoading } = + useFetchArtifactAlteration(kind); + const { runGenerate, loading: runLoading } = useDatasetGenerate(); + const [updateSheetOpen, setUpdateSheetOpen] = useState(false); + + const newlyUploaded = alteration?.newly_uploaded ?? 0; + const removed = alteration?.removed ?? 0; + const hasChanges = newlyUploaded > 0 || removed > 0; + useEffect(() => { - if (structureStatus === GenerateStatus.completed) { + if (structureStatus === GenerateStatus.Completed) { queryClient.invalidateQueries({ queryKey: DatasetStructureKeys.kind(knowledgeBaseId, kind), }); @@ -105,6 +119,14 @@ export function DatasetStructureView({ kind }: DatasetStructureViewProps) { } }, [deleteDatasetStructure, kind]); + const handleUpdateClick = useCallback(async () => { + setUpdateSheetOpen(true); + if (structureStatus === GenerateStatus.Running) { + return; + } + await runGenerate({ type: generateType }).catch(() => {}); + }, [structureStatus, runGenerate, generateType]); + const canGenerate = (knowledgeBase?.chunk_count ?? 0) > 0; if (loading && !data) { @@ -124,16 +146,32 @@ export function DatasetStructureView({ kind }: DatasetStructureViewProps) { return (
- - - +
+ + + + +
{kind === ViewMode.Graph && ( + ); } diff --git a/web/src/pages/dataset/compilation/empty-state.tsx b/web/src/pages/dataset/compilation/empty-state.tsx index 46a96a6be5..1c6556cf68 100644 --- a/web/src/pages/dataset/compilation/empty-state.tsx +++ b/web/src/pages/dataset/compilation/empty-state.tsx @@ -7,8 +7,8 @@ import { Button } from '@/components/ui/button'; import { ITraceInfo, useDatasetGenerate, -} from '@/pages/dataset/dataset/generate-button/hook'; -import { useGenerateStatus } from '@/pages/dataset/dataset/generate-button/use-generate-status'; + useGenerateStatus, +} from '@/hooks/use-dataset-generate'; import { GenerableViewMode, diff --git a/web/src/pages/dataset/compilation/llm-wiki-view.tsx b/web/src/pages/dataset/compilation/llm-wiki-view.tsx index 190cfba43d..ffc2562121 100644 --- a/web/src/pages/dataset/compilation/llm-wiki-view.tsx +++ b/web/src/pages/dataset/compilation/llm-wiki-view.tsx @@ -4,18 +4,17 @@ import { ResizablePanel, ResizablePanelGroup, } from '@/components/ui/resizable'; +import { GenerateStatus, GenerateType } from '@/constants/knowledge'; +import { + useGenerateStatus, + useTraceRunData, +} from '@/hooks/use-dataset-generate'; import { ArtifactKeys, ArtifactTopicKeys, useFetchArtifactTopicList, useFetchKnowledgeBaseConfiguration, } from '@/hooks/use-knowledge-request'; -import { - GenerateStatus, - GenerateType, -} from '@/pages/dataset/dataset/generate-button/constants'; -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 { useCallback, useEffect, useState } from 'react'; import { useParams } from 'react-router'; @@ -46,7 +45,7 @@ export function LlmWikiView() { const [updateSheetOpen, setUpdateSheetOpen] = useState(false); useEffect(() => { - if (artifactStatus === GenerateStatus.completed) { + if (artifactStatus === GenerateStatus.Completed) { setUpdateSheetOpen(false); queryClient.invalidateQueries({ queryKey: ArtifactKeys.listByDataset(id!), diff --git a/web/src/pages/dataset/compilation/skills-view.tsx b/web/src/pages/dataset/compilation/skills-view.tsx index 02262e106a..3bccf478aa 100644 --- a/web/src/pages/dataset/compilation/skills-view.tsx +++ b/web/src/pages/dataset/compilation/skills-view.tsx @@ -5,14 +5,13 @@ import { ResizablePanel, ResizablePanelGroup, } from '@/components/ui/resizable'; +import { GenerateStatus, GenerateType } from '@/constants/knowledge'; +import { + useGenerateStatus, + useTraceRunData, +} from '@/hooks/use-dataset-generate'; import { DatasetSkillKeys } from '@/hooks/use-dataset-skill-request'; import { useFetchKnowledgeBaseConfiguration } from '@/hooks/use-knowledge-request'; -import { - GenerateStatus, - GenerateType, -} from '@/pages/dataset/dataset/generate-button/constants'; -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 { useEffect } from 'react'; import { useParams } from 'react-router'; @@ -39,7 +38,7 @@ export function SkillsView() { const { status: skillStatus } = useGenerateStatus(skillRunData); useEffect(() => { - if (skillStatus === GenerateStatus.completed) { + if (skillStatus === GenerateStatus.Completed) { queryClient.invalidateQueries({ queryKey: DatasetSkillKeys.tree(id!), }); diff --git a/web/src/pages/dataset/compilation/update-button.tsx b/web/src/pages/dataset/compilation/update-button.tsx new file mode 100644 index 0000000000..3a189f8c89 --- /dev/null +++ b/web/src/pages/dataset/compilation/update-button.tsx @@ -0,0 +1,88 @@ +import { WandSparkles } from 'lucide-react'; +import { useTranslation } from 'react-i18next'; + +import { Badge } from '@/components/ui/badge'; +import { Button } from '@/components/ui/button'; +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from '@/components/ui/tooltip'; +import { GenerateStatus, GenerateType } from '@/constants/knowledge'; +import { + ITraceInfo, + useGenerateStatus, +} from '@/hooks/use-dataset-generate'; + +import { UpdateRunProgress } from './update-run-progress'; + +type CompilationUpdateButtonProps = { + traceData?: ITraceInfo; + generateType: GenerateType; + hasChanges: boolean; + newlyUploaded: number; + removed: number; + loading: boolean; + tooltip: string; + onClick: () => void; +}; + +export function CompilationUpdateButton({ + traceData, + generateType, + hasChanges, + newlyUploaded, + removed, + loading, + tooltip, + onClick, +}: CompilationUpdateButtonProps) { + const { t } = useTranslation(); + const { status } = useGenerateStatus(traceData); + const isRunning = status === GenerateStatus.Running; + const isGenerating = isRunning || status === GenerateStatus.Failed; + + // A failed trace persists (progress stays < 0) until the next run, so it + // must not keep the button visible on its own — only real changes or a + // live run should. + if (!hasChanges && !isRunning) { + return null; + } + + return ( + + + + + + + {isGenerating + ? t('knowledgeDetails.viewUpdateLogs', { + defaultValue: 'View update logs', + }) + : tooltip} + + + + ); +} diff --git a/web/src/pages/dataset/compilation/wiki-left-panel/wiki-update-sheet.tsx b/web/src/pages/dataset/compilation/update-log-sheet.tsx similarity index 52% rename from web/src/pages/dataset/compilation/wiki-left-panel/wiki-update-sheet.tsx rename to web/src/pages/dataset/compilation/update-log-sheet.tsx index 17ed343450..86da2193bf 100644 --- a/web/src/pages/dataset/compilation/wiki-left-panel/wiki-update-sheet.tsx +++ b/web/src/pages/dataset/compilation/update-log-sheet.tsx @@ -1,5 +1,4 @@ import { useEffect } from 'react'; -import { useTranslation } from 'react-i18next'; import { Sheet, @@ -7,28 +6,28 @@ import { SheetHeader, SheetTitle, } from '@/components/ui/sheet'; -import { GenerateStatus } from '@/pages/dataset/dataset/generate-button/constants'; -import { ITraceInfo } from '@/pages/dataset/dataset/generate-button/hook'; -import { useGenerateStatus } from '@/pages/dataset/dataset/generate-button/use-generate-status'; +import { GenerateStatus } from '@/constants/knowledge'; +import { ITraceInfo, useGenerateStatus } from '@/hooks/use-dataset-generate'; -import { ProgressLogPanel } from '../progress-log-panel'; +import { ProgressLogPanel } from './progress-log-panel'; -type WikiUpdateSheetProps = { +type UpdateLogSheetProps = { open: boolean; onOpenChange: (open: boolean) => void; data?: ITraceInfo; + title: string; }; -export function WikiUpdateSheet({ +export function UpdateLogSheet({ open, onOpenChange, data, -}: WikiUpdateSheetProps) { - const { t } = useTranslation(); + title, +}: UpdateLogSheetProps) { const { status } = useGenerateStatus(data); useEffect(() => { - if (status === GenerateStatus.completed) { + if (status === GenerateStatus.Completed) { onOpenChange(false); } }, [status, onOpenChange]); @@ -37,11 +36,7 @@ export function WikiUpdateSheet({ - - {t('knowledgeDetails.updateSheetTitle', { - defaultValue: 'Update Wiki', - })} - + {title}
{ e.stopPropagation(); if (data?.id) { - pauseGenerate({ task_id: data.id, type: GenerateType.Artifact }).catch( - () => {}, - ); + pauseGenerate({ task_id: data.id, type: generateType }).catch(() => {}); } }, - [pauseGenerate, data?.id], + [pauseGenerate, data?.id, generateType], ); return ( diff --git a/web/src/pages/dataset/compilation/wiki-left-panel/hooks/use-wiki-update.ts b/web/src/pages/dataset/compilation/wiki-left-panel/hooks/use-wiki-update.ts index 62ff99c095..bb3dc6fe99 100644 --- a/web/src/pages/dataset/compilation/wiki-left-panel/hooks/use-wiki-update.ts +++ b/web/src/pages/dataset/compilation/wiki-left-panel/hooks/use-wiki-update.ts @@ -9,8 +9,8 @@ type UseWikiUpdateOptions = { }; export function useWikiUpdate({ onUpdate }: UseWikiUpdateOptions = {}) { - const { data, loading: queryLoading } = useFetchArtifactAlteration(); - const { runArtifactIndex, loading: mutationLoading } = useRunArtifactIndex(); + const { data, loading: queryLoading } = useFetchArtifactAlteration('wiki'); + const { runArtifactIndex, loading: mutationLoading } = useRunArtifactIndex('wiki'); const newlyUploaded = data?.newly_uploaded ?? 0; const removed = data?.removed ?? 0; diff --git a/web/src/pages/dataset/compilation/wiki-left-panel/index.tsx b/web/src/pages/dataset/compilation/wiki-left-panel/index.tsx index 55bc8ec468..38572e6d4d 100644 --- a/web/src/pages/dataset/compilation/wiki-left-panel/index.tsx +++ b/web/src/pages/dataset/compilation/wiki-left-panel/index.tsx @@ -1,28 +1,23 @@ import { ConfirmDeleteDialog } from '@/components/confirm-delete-dialog'; -import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { Tabs, TabsList, TabsTrigger } from '@/components/ui/tabs'; +import { GenerateStatus, GenerateType } from '@/constants/knowledge'; import { - Tooltip, - TooltipContent, - TooltipProvider, - TooltipTrigger, -} from '@/components/ui/tooltip'; + ITraceInfo, + useGenerateStatus, +} from '@/hooks/use-dataset-generate'; import { IArtifact } from '@/interfaces/database/dataset'; -import { GenerateStatus } from '@/pages/dataset/dataset/generate-button/constants'; -import { ITraceInfo } from '@/pages/dataset/dataset/generate-button/hook'; -import { useGenerateStatus } from '@/pages/dataset/dataset/generate-button/use-generate-status'; -import { Trash2, WandSparkles } from 'lucide-react'; +import { Trash2 } from 'lucide-react'; import { useCallback } from 'react'; import { useTranslation } from 'react-i18next'; import { LeftPanelTab } from '../constants'; +import { CompilationUpdateButton } from '../update-button'; +import { UpdateLogSheet } from '../update-log-sheet'; import { useWikiClear } from './hooks/use-wiki-clear'; import { useWikiUpdate } from './hooks/use-wiki-update'; import { WikiGraphPanel } from './wiki-graph-panel'; import { WikiNavBar } from './wiki-nav-bar'; -import { WikiUpdateProgress } from './wiki-update-progress'; -import { WikiUpdateSheet } from './wiki-update-sheet'; type WikiLeftPanelProps = { tab: LeftPanelTab; @@ -62,12 +57,10 @@ export function WikiLeftPanel({ } = useWikiUpdate(); const { status } = useGenerateStatus(traceData); - const isGenerating = - status === GenerateStatus.running || status === GenerateStatus.failed; const handleUpdateClick = useCallback(async () => { onUpdateSheetOpenChange(true); - if (status === GenerateStatus.running) { + if (status === GenerateStatus.Running) { return; } await handleUpdate(); @@ -76,50 +69,21 @@ export function WikiLeftPanel({ return ( ); diff --git a/web/src/pages/dataset/dataset-overview/dataset-common.ts b/web/src/pages/dataset/dataset-overview/dataset-common.ts index afce1b1ec6..18b25a14b1 100644 --- a/web/src/pages/dataset/dataset-overview/dataset-common.ts +++ b/web/src/pages/dataset/dataset-overview/dataset-common.ts @@ -2,26 +2,3 @@ export enum LogTabs { FILE_LOGS = 'fileLogs', DATASET_LOGS = 'datasetLogs', } - -export enum ProcessingType { - knowledgeGraph = 'Graph', - raptor = 'RAPTOR', - artifact = 'Artifact', - skill = 'Skill', - mindmap = 'Mindmap', - timeline = 'Timeline', - sessionEssence = 'Session_Essence', - sessionGraph = 'Session_Graph', -} - -export const ProcessingTypeMap = { - [ProcessingType.knowledgeGraph]: 'Knowledge Graph', - [ProcessingType.raptor]: 'RAPTOR', - [ProcessingType.artifact]: 'Artifact', - [ProcessingType.skill]: 'Skill', - [ProcessingType.mindmap]: 'Mind Map', - [ProcessingType.timeline]: 'Timeline', - [ProcessingType.sessionEssence]: 'Session Essence', - [ProcessingType.sessionGraph]: 'Session Graph', - GraphRAG: 'Knowledge Graph', -}; diff --git a/web/src/pages/dataset/dataset-overview/overview-table.tsx b/web/src/pages/dataset/dataset-overview/overview-table.tsx index b1617baa8a..5e7f832d9e 100644 --- a/web/src/pages/dataset/dataset-overview/overview-table.tsx +++ b/web/src/pages/dataset/dataset-overview/overview-table.tsx @@ -18,7 +18,11 @@ import { TooltipContent, TooltipTrigger, } from '@/components/ui/tooltip'; -import { RunningStatusMap } from '@/constants/knowledge'; +import { + ProcessingType, + ProcessingTypeMap, + RunningStatusMap, +} from '@/constants/knowledge'; import { useTranslate } from '@/hooks/common-hooks'; import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks'; import { cn } from '@/lib/utils'; @@ -45,7 +49,7 @@ import { FC, useMemo, useState } from 'react'; import { useParams } from 'react-router'; import { RunningStatus } from '../dataset/constant'; import ProcessLogModal, { ILogInfo } from '../process-log-modal'; -import { LogTabs, ProcessingType, ProcessingTypeMap } from './dataset-common'; +import { LogTabs } from './dataset-common'; import { DocumentLog, FileLogsTableProps, IFileLogItem } from './interface'; export const getFileLogsTableColumns = ( diff --git a/web/src/pages/dataset/dataset/generate-button/constants.ts b/web/src/pages/dataset/dataset/generate-button/constants.ts deleted file mode 100644 index d1369fbe4f..0000000000 --- a/web/src/pages/dataset/dataset/generate-button/constants.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { ProcessingType } from '../../dataset-overview/dataset-common'; - -export const GenerateStatus = { - running: 'running', - completed: 'completed', - start: 'start', - failed: 'failed', -}; - -export enum GenerateType { - KnowledgeGraph = 'KnowledgeGraph', - Raptor = 'Raptor', - Artifact = 'Artifact', - ToSkills = 'ToSkills', - MindMap = 'MindMap', - Timeline = 'Timeline', - SessionEssence = 'SessionEssence', - SessionGraph = 'SessionGraph', -} - -export enum TraceType { - Graph = 'graph', - Raptor = 'raptor', - Artifact = 'artifact', - Skill = 'skill', - MindMap = 'mindmap', - Timeline = 'timeline', - SessionEssence = 'session_essence', - SessionGraph = 'session_graph', -} - -export const GenerateTypeMap = { - [GenerateType.KnowledgeGraph]: ProcessingType.knowledgeGraph, - [GenerateType.Raptor]: ProcessingType.raptor, - [GenerateType.Artifact]: ProcessingType.artifact, - [GenerateType.ToSkills]: ProcessingType.skill, - [GenerateType.MindMap]: ProcessingType.mindmap, - [GenerateType.Timeline]: ProcessingType.timeline, - [GenerateType.SessionEssence]: ProcessingType.sessionEssence, - [GenerateType.SessionGraph]: ProcessingType.sessionGraph, -}; diff --git a/web/src/pages/dataset/dataset/generate-button/use-generate-status.ts b/web/src/pages/dataset/dataset/generate-button/use-generate-status.ts deleted file mode 100644 index e58833cee9..0000000000 --- a/web/src/pages/dataset/dataset/generate-button/use-generate-status.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { useMemo } from 'react'; - -import { GenerateStatus } from './constants'; -import { ITraceInfo } from './hook'; - -export function useGenerateStatus(data?: ITraceInfo) { - const status = useMemo(() => { - if (!data) { - return GenerateStatus.start; - } - if (data.progress >= 1) { - return GenerateStatus.completed; - } else if (!data.progress && data.progress !== 0) { - return GenerateStatus.start; - } else if (data.progress < 0) { - return GenerateStatus.failed; - } else if (data.progress < 1) { - return GenerateStatus.running; - } - return GenerateStatus.start; - }, [data]); - - const percent = useMemo(() => { - if (status === GenerateStatus.failed) { - return 100; - } else if (status === GenerateStatus.running) { - return data!.progress * 100; - } - return 0; - }, [status, data]); - - return { status, percent }; -} diff --git a/web/src/services/knowledge-service.ts b/web/src/services/knowledge-service.ts index 194af141b2..c23f64c040 100644 --- a/web/src/services/knowledge-service.ts +++ b/web/src/services/knowledge-service.ts @@ -1,3 +1,4 @@ +import { ProcessingType } from '@/constants/knowledge'; import { IRenameTag } from '@/interfaces/database/dataset'; import { IFetchArtifactGraphRequestParams, @@ -7,7 +8,6 @@ import { IFetchKnowledgeListRequestParams, IUpdateArtifactPageRequestBody, } from '@/interfaces/request/knowledge'; -import { ProcessingType } from '@/pages/dataset/dataset-overview/dataset-common'; import api from '@/utils/api'; import nextRequest from '@/utils/next-request'; import registerServer from '@/utils/register-server'; @@ -419,8 +419,8 @@ export const getArtifactGraph = ( params?: IFetchArtifactGraphRequestParams, ) => request.get(api.getArtifactGraph(datasetId), { params }); -export const getArtifactsAlteration = (datasetId: string) => - request.get(api.artifactsAlteration(datasetId)); +export const getArtifactsAlteration = (datasetId: string, kind: string) => + request.get(api.artifactsAlteration(datasetId), { params: { kind } }); export const getArtifactsStructure = ( datasetId: string,