import React, { useCallback, useState, useRef, useMemo } from 'react'; import { Box, Card, IconButton, Flex, Grid, Button, useTheme, Drawer, DrawerBody, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerContent, useDisclosure, HStack, Switch } from '@chakra-ui/react'; import { getDatasetDataList, delOneDatasetDataById, getDatasetCollectionById, putDatasetDataById } from '@/web/core/dataset/api'; import { DeleteIcon } from '@chakra-ui/icons'; import { useQuery } from '@tanstack/react-query'; import { useToast } from '@fastgpt/web/hooks/useToast'; import { debounce } from 'lodash'; import { getErrText } from '@fastgpt/global/common/error/utils'; import { useConfirm } from '@fastgpt/web/hooks/useConfirm'; import { useTranslation } from 'next-i18next'; import { useRouter } from 'next/router'; import MyIcon from '@fastgpt/web/components/common/Icon'; import MyInput from '@/components/MyInput'; import { useLoading } from '@fastgpt/web/hooks/useLoading'; import InputDataModal from '../components/InputDataModal'; import RawSourceBox from '@/components/core/dataset/RawSourceBox'; import type { DatasetDataListItemType } from '@/global/core/dataset/type.d'; import { TabEnum } from '..'; import { useSystemStore } from '@/web/common/system/useSystemStore'; import { DatasetCollectionTypeMap, TrainingTypeMap } from '@fastgpt/global/core/dataset/constants'; import { formatTime2YMDHM } from '@fastgpt/global/common/string/time'; import { formatFileSize } from '@fastgpt/global/common/file/tools'; import { getCollectionSourceAndOpen } from '@/web/core/dataset/hooks/readCollectionSource'; import MyTooltip from '@fastgpt/web/components/common/MyTooltip'; import { usePagination } from '@fastgpt/web/hooks/usePagination'; import { getCollectionSourceData } from '@fastgpt/global/core/dataset/collection/utils'; import { useI18n } from '@/web/context/I18n'; import EmptyTip from '@fastgpt/web/components/common/EmptyTip'; import { DatasetPageContext } from '@/web/core/dataset/context/datasetPageContext'; import { useContextSelector } from 'use-context-selector'; import { useRequest2 } from '@fastgpt/web/hooks/useRequest'; import MyTag from '@fastgpt/web/components/common/Tag/index'; import MyBox from '@fastgpt/web/components/common/MyBox'; import { useSystem } from '@fastgpt/web/hooks/useSystem'; const DataCard = () => { const BoxRef = useRef(null); const theme = useTheme(); const lastSearch = useRef(''); const router = useRouter(); const { isPc } = useSystem(); const { collectionId = '', datasetId } = router.query as { collectionId: string; datasetId: string; }; const datasetDetail = useContextSelector(DatasetPageContext, (v) => v.datasetDetail); const { t } = useTranslation(); const { datasetT } = useI18n(); const [searchText, setSearchText] = useState(''); const { toast } = useToast(); const { openConfirm, ConfirmModal } = useConfirm({ content: t('dataset.Confirm to delete the data'), type: 'delete' }); const { isOpen, onOpen, onClose } = useDisclosure(); const readSource = getCollectionSourceAndOpen(collectionId); const { data: datasetDataList, Pagination, total, getData, pageNum, pageSize, isLoading: isRequesting } = usePagination({ api: getDatasetDataList, pageSize: 24, defaultRequest: false, params: { collectionId, searchText }, onChange() { if (BoxRef.current) { BoxRef.current.scrollTop = 0; } } }); const [editDataId, setEditDataId] = useState(); // get first page data useRequest2( async () => { getData(1); lastSearch.current = searchText; }, { manual: false, debounceWait: 300, refreshDeps: [searchText] } ); // get file info const { data: collection } = useQuery( ['getDatasetCollectionById', collectionId], () => getDatasetCollectionById(collectionId), { onError: () => { router.replace({ query: { datasetId } }); } } ); const canWrite = useMemo(() => datasetDetail.permission.hasWritePer, [datasetDetail]); const metadataList = useMemo(() => { if (!collection) return []; const webSelector = collection?.datasetId?.websiteConfig?.selector || collection?.metadata?.webPageSelector; return [ { label: t('core.dataset.collection.metadata.source'), value: t(DatasetCollectionTypeMap[collection.type]?.name) }, { label: t('core.dataset.collection.metadata.source name'), value: collection.file?.filename || collection?.rawLink || collection?.name }, { label: t('core.dataset.collection.metadata.source size'), value: collection.file ? formatFileSize(collection.file.length) : '-' }, { label: t('core.dataset.collection.metadata.Createtime'), value: formatTime2YMDHM(collection.createTime) }, { label: t('core.dataset.collection.metadata.Updatetime'), value: formatTime2YMDHM(collection.updateTime) }, { label: t('core.dataset.collection.metadata.Raw text length'), value: collection.rawTextLength ?? '-' }, { label: t('core.dataset.collection.metadata.Training Type'), value: t(TrainingTypeMap[collection.trainingType]?.label) }, { label: t('core.dataset.collection.metadata.Chunk Size'), value: collection.chunkSize || '-' }, ...(webSelector ? [ { label: t('core.dataset.collection.metadata.Web page selector'), value: webSelector } ] : []), { ...(collection.tags ? [ { label: datasetT('Collection tags'), value: collection.tags?.join(', ') || '-' } ] : []) } ]; }, [collection, datasetT, t]); const { run: onUpdate, loading } = useRequest2(putDatasetDataById, { onSuccess() { getData(pageNum); } }); const isLoading = isRequesting || loading; return ( {/* Header */} } variant={'whitePrimary'} size={'smSquare'} borderRadius={'50%'} aria-label={''} onClick={() => router.replace({ query: { datasetId: router.query.datasetId, parentId: router.query.parentId, currentTab: TabEnum.collectionCard } }) } /> {collection?._id && ( )} {t('core.dataset.collection.id')}:{' '} {collection?._id} {canWrite && ( )} {isPc && ( } aria-label={''} onClick={onOpen} /> )} {t('core.dataset.data.Total Amount', { total })} } w={['200px', '300px']} placeholder={t('core.dataset.data.Search data placeholder')} value={searchText} onChange={(e) => { setSearchText(e.target.value); }} /> {/* data */} {datasetDataList.map((item) => ( { if (!collection) return; setEditDataId(item._id); }} > # {item.chunkIndex ?? '-'} ID:{item._id} {/* {item.forbid ? ( {datasetT('Disabled')} ) : ( {datasetT('Enabled')} )} { e.stopPropagation(); }} h={'12px'} > { e.stopPropagation(); onUpdate({ dataId: item._id, forbid: !e.target.checked }); }} /> */} {item.q} {item.a} {/* Mask */} {item.q.length + (item.a?.length || 0)} {/* ID:{item._id} */} {canWrite && ( } variant={'whiteDanger'} size={'xsSquare'} aria-label={'delete'} onClick={(e) => { e.stopPropagation(); openConfirm(async () => { try { await delOneDatasetDataById(item._id); getData(pageNum); } catch (error) { toast({ title: getErrText(error), status: 'error' }); } })(); }} /> )} ))} {total > pageSize && ( )} {total === 0 && } {/* metadata drawer */} {t('core.dataset.collection.metadata.metadata')} {metadataList.map((item, i) => ( {item.label} {item.value} ))} {collection?.sourceId && ( )} {editDataId !== undefined && collection && ( setEditDataId(undefined)} onSuccess={() => getData(pageNum)} onDelete={() => getData(pageNum)} /> )} ); }; export default React.memo(DataCard);