'use client' import { Button } from '@langgenius/dify-ui/button' import { toast } from '@langgenius/dify-ui/toast' import { useInfiniteQuery } from '@tanstack/react-query' import { useAtomValue } from 'jotai' import { useState } from 'react' import { useTranslation } from 'react-i18next' import { SearchInput } from '@/app/components/base/search-input' import ExternalAPIPanel from '@/app/components/datasets/external-api/external-api-panel' import ServiceApi from '@/app/components/datasets/extra-info/service-api' import { useExternalApiPanel } from '@/context/external-api-panel-context' import { workspacePermissionKeysAtom } from '@/context/permission-state' import Link from '@/next/link' import { consoleQuery } from '@/service/client' import { useDatasetApiBaseUrl } from '@/service/knowledge/use-dataset' import { hasPermission } from '@/utils/permission' import { KnowledgeSpaceCard } from './components/knowledge-space-card' import { KnowledgeViewSwitcher } from './components/knowledge-view-switcher' import { KNOWLEDGE_SPACE_GRID_CLASS_NAME, NewKnowledgeEmptyState, NewKnowledgeLoadingState, NewKnowledgePageState, } from './components/new-knowledge-list-states' const PAGE_SIZE = 30 function isUnavailableError(error: unknown) { if (!error || typeof error !== 'object') return false const status = 'status' in error ? error.status : undefined if (status === 404 || status === 503) return true const data = 'data' in error ? error.data : undefined if (!data || typeof data !== 'object') return false const dataStatus = 'status' in data ? data.status : undefined return dataStatus === 404 || dataStatus === 503 } function MetadataFilter({ label, onClick }: { label: string; onClick: () => void }) { return ( {label} ) } export function NewKnowledgeList({ view, onViewChange, }: { view: 'legacy' | 'new' onViewChange: (value: 'legacy' | 'new') => void }) { const { t } = useTranslation('dataset') const { t: tCommon } = useTranslation('common') const { data: apiBaseInfo } = useDatasetApiBaseUrl() const { showExternalApiPanel, setShowExternalApiPanel } = useExternalApiPanel() const workspacePermissionKeys = useAtomValue(workspacePermissionKeysAtom) const canCreate = hasPermission(workspacePermissionKeys, 'dataset.create_and_management') const canConnect = hasPermission(workspacePermissionKeys, 'dataset.external.connect') const filtersUnavailable = t(($) => $['newKnowledge.filtersUnavailable']) const showFilterBoundary = () => toast.info(filtersUnavailable) const createLabel = tCommon(($) => $['operation.create']) const [searchValue, setSearchValue] = useState('') const knowledgeSpacesQuery = useInfiniteQuery( consoleQuery.knowledgeFs.listKnowledgeSpaces.infiniteOptions({ input: (pageParam) => ({ query: { limit: PAGE_SIZE, ...(typeof pageParam === 'string' ? { cursor: pageParam } : {}), }, }), getNextPageParam: (lastPage) => lastPage.nextCursor, initialPageParam: null as string | null, }), ) const knowledgeSpaces = knowledgeSpacesQuery.data?.pages.flatMap((page) => page.items) ?? [] const normalizedSearchValue = searchValue.trim().toLocaleLowerCase() const visibleKnowledgeSpaces = normalizedSearchValue ? knowledgeSpaces.filter( (knowledgeSpace) => knowledgeSpace.name.toLocaleLowerCase().includes(normalizedSearchValue) || knowledgeSpace.description?.toLocaleLowerCase().includes(normalizedSearchValue), ) : knowledgeSpaces return ( $['newKnowledge.new'])} className="relative flex grow flex-col overflow-y-auto bg-background-body" > {t(($) => $.knowledge)} {canConnect && ( setShowExternalApiPanel(true)} > {t(($) => $.externalAPIPanelTitle)} )} $['newKnowledge.tags'])} onClick={showFilterBoundary} /> $['newKnowledge.creators'])} onClick={showFilterBoundary} /> {canCreate && ( } variant="primary" size="medium" className="gap-0.5 px-2 shadow-xs" > {createLabel} )} {knowledgeSpacesQuery.isPending ? ( ) : knowledgeSpacesQuery.error && !knowledgeSpacesQuery.data ? ( isUnavailableError(knowledgeSpacesQuery.error) ? ( $['newKnowledge.unavailableTitle'])} description={t(($) => $['newKnowledge.unavailableDescription'])} /> ) : ( $['newKnowledge.errorTitle'])} description={t(($) => $['newKnowledge.errorDescription'])} action={ void knowledgeSpacesQuery.refetch()}> {tCommon(($) => $['operation.retry'])} } /> ) ) : knowledgeSpaces.length === 0 ? ( ) : ( <> $.knowledge)}> {visibleKnowledgeSpaces.map((knowledgeSpace) => ( ))} {knowledgeSpacesQuery.isFetchNextPageError ? ( {t(($) => $['newKnowledge.errorDescription'])} void knowledgeSpacesQuery.fetchNextPage()}> {tCommon(($) => $['operation.retry'])} ) : knowledgeSpacesQuery.hasNextPage ? ( void knowledgeSpacesQuery.fetchNextPage()} > {t(($) => $['newKnowledge.loadMore'])} ) : null} > )} {showExternalApiPanel && canConnect && ( setShowExternalApiPanel(false)} /> )} ) }