import React, { useMemo, useRef, useState } from 'react'; import { postChangeOwner, resumeInheritPer } from '@/web/core/dataset/api'; import { Box, Flex, Grid, HStack } from '@chakra-ui/react'; import { DatasetTypeEnum, DatasetTypeMap } from '@fastgpt/global/core/dataset/constants'; import MyMenu from '@fastgpt/web/components/common/MyMenu'; import MyIcon from '@fastgpt/web/components/common/Icon'; import { useRouter } from 'next/router'; import PermissionIconText from '@/components/support/permission/IconText'; import Avatar from '@fastgpt/web/components/common/Avatar'; import { useConfirm } from '@fastgpt/web/hooks/useConfirm'; import { useRequest, useRequest2 } from '@fastgpt/web/hooks/useRequest'; import { type DatasetItemType } from '@fastgpt/global/core/dataset/type'; import { useSystemStore } from '@/web/common/system/useSystemStore'; import { checkTeamExportDatasetLimit } from '@/web/support/user/team/api'; import { downloadFetch } from '@/web/common/system/utils'; import MyTooltip from '@fastgpt/web/components/common/MyTooltip'; import dynamic from 'next/dynamic'; import { useContextSelector } from 'use-context-selector'; import { DatasetsContext } from '../../../pages/dataset/list/context'; import { DatasetPermissionList } from '@fastgpt/global/support/permission/dataset/constant'; import ConfigPerModal from '@/components/support/permission/ConfigPerModal'; import { deleteDatasetCollaborators, getCollaboratorList, postUpdateDatasetCollaborators } from '@/web/core/dataset/api/collaborator'; import EmptyTip from '@fastgpt/web/components/common/EmptyTip'; import { useFolderDrag } from '@/components/common/folder/useFolderDrag'; import MyBox from '@fastgpt/web/components/common/MyBox'; import { useTranslation } from 'next-i18next'; import { useSystem } from '@fastgpt/web/hooks/useSystem'; import SideTag from './SideTag'; import { getModelProvider } from '@fastgpt/global/core/ai/provider'; import UserBox from '@fastgpt/web/components/common/UserBox'; const EditResourceModal = dynamic(() => import('@/components/common/Modal/EditResourceModal')); function List() { const { setLoading } = useSystemStore(); const { isPc } = useSystem(); const { t } = useTranslation(); const { loadMyDatasets, setMoveDatasetId, refetchPaths, editedDataset, setEditedDataset, onDelDataset, onUpdateDataset, myDatasets, folderDetail, setSearchKey } = useContextSelector(DatasetsContext, (v) => v); const [editPerDatasetId, setEditPerDatasetId] = useState(); const router = useRouter(); const { parentId = null } = router.query as { parentId?: string | null }; const parentDataset = useMemo( () => myDatasets.find((item) => String(item._id) === parentId), [parentId, myDatasets] ); const { openConfirm: openMoveConfirm, ConfirmModal: MoveConfirmModal } = useConfirm({ type: 'common', title: t('common:move.confirm'), content: t('dataset:move.hint') }); const { runAsync: updateDataset } = useRequest2(onUpdateDataset); const { getBoxProps } = useFolderDrag({ activeStyles: { borderColor: 'primary.600' }, onDrop: (dragId: string, targetId: string) => { openMoveConfirm(() => updateDataset({ id: dragId, parentId: targetId }) )(); } }); const editPerDataset = useMemo( () => myDatasets.find((item) => String(item._id) === String(editPerDatasetId)), [editPerDatasetId, myDatasets] ); const { mutate: exportDataset } = useRequest({ mutationFn: async (dataset: DatasetItemType) => { setLoading(true); await checkTeamExportDatasetLimit(dataset._id); await downloadFetch({ url: `/api/core/dataset/exportAll?datasetId=${dataset._id}`, filename: `${dataset.name}.csv` }); }, onSettled() { setLoading(false); }, successToast: t('common:core.dataset.Start export'), errorToast: t('common:dataset.Export Dataset Limit Error') }); const DeleteTipsMap = useRef({ [DatasetTypeEnum.folder]: t('common:dataset.deleteFolderTips'), [DatasetTypeEnum.dataset]: t('common:core.dataset.Delete Confirm'), [DatasetTypeEnum.websiteDataset]: t('common:core.dataset.Delete Confirm'), [DatasetTypeEnum.externalFile]: t('common:core.dataset.Delete Confirm') }); const formatDatasets = useMemo( () => myDatasets.map((item) => { return { ...item, label: DatasetTypeMap[item.type]?.label, icon: DatasetTypeMap[item.type]?.icon }; }), [myDatasets] ); const { openConfirm, ConfirmModal } = useConfirm({ type: 'delete' }); const onClickDeleteDataset = (id: string) => { openConfirm( () => onDelDataset(id).then(() => { refetchPaths(); loadMyDatasets(); }), undefined, DeleteTipsMap.current[DatasetTypeEnum.dataset] )(); }; return ( <> {formatDatasets.length > 0 && ( {formatDatasets.map((dataset, index) => { const vectorModelAvatar = getModelProvider(dataset.vectorModel.provider)?.avatar; return ( {dataset.type === DatasetTypeEnum.folder ? t('common:open_folder') : t('common:folder.open_dataset')} } > { if (dataset.type === DatasetTypeEnum.folder) { setSearchKey(''); router.push({ pathname: '/dataset/list', query: { parentId: dataset._id } }); } else { router.push({ pathname: '/dataset/detail', query: { datasetId: dataset._id } }); } }} > {dataset.name} {dataset.type !== DatasetTypeEnum.folder && ( )} {dataset.intro || (dataset.type === DatasetTypeEnum.folder ? t('common:core.dataset.Folder placeholder') : t('common:core.dataset.Intro Placeholder'))} {isPc && dataset.type !== DatasetTypeEnum.folder && ( {dataset.vectorModel.name} )} {(dataset.type === DatasetTypeEnum.folder ? dataset.permission.hasManagePer : dataset.permission.hasWritePer) && ( { e.stopPropagation(); }} > } menuList={[ { children: [ { icon: 'edit', label: t('common:dataset.Edit Info'), onClick: () => setEditedDataset({ id: dataset._id, name: dataset.name, intro: dataset.intro, avatar: dataset.avatar }) }, ...((parentDataset ? parentDataset : dataset)?.permission .hasManagePer ? [ { icon: 'common/file/move', label: t('common:Move'), onClick: () => { setMoveDatasetId(dataset._id); } } ] : []), ...(dataset.permission.hasManagePer ? [ { icon: 'key', label: t('common:permission.Permission'), onClick: () => setEditPerDatasetId(dataset._id) } ] : []) ] }, ...(dataset.type != DatasetTypeEnum.folder ? [ { children: [ { icon: 'export', label: t('common:Export'), onClick: () => { exportDataset(dataset); } } ] } ] : []), ...(dataset.permission.hasManagePer ? [ { children: [ { icon: 'delete', label: t('common:Delete'), type: 'danger' as 'danger', onClick: () => onClickDeleteDataset(dataset._id) } ] } ] : []) ]} /> )} ); })} )} {myDatasets.length === 0 && ( )} {editedDataset && ( setEditedDataset(undefined)} onEdit={async (data) => { await onUpdateDataset({ id: editedDataset.id, name: data.name, intro: data.intro, avatar: data.avatar }); }} /> )} {!!editPerDataset && ( postChangeOwner({ datasetId: editPerDataset._id, ownerId: tmbId }).then(() => loadMyDatasets()) } hasParent={!!parentId} refetchResource={loadMyDatasets} isInheritPermission={editPerDataset.inheritPermission} resumeInheritPermission={() => resumeInheritPer(editPerDataset._id).then(() => Promise.all([loadMyDatasets()])) } avatar={editPerDataset.avatar} name={editPerDataset.name} managePer={{ permission: editPerDataset.permission, onGetCollaboratorList: () => getCollaboratorList(editPerDataset._id), permissionList: DatasetPermissionList, onUpdateCollaborators: (props) => postUpdateDatasetCollaborators({ ...props, datasetId: editPerDataset._id }), onDelOneCollaborator: async (props) => deleteDatasetCollaborators({ ...props, datasetId: editPerDataset._id }), refreshDeps: [editPerDataset._id, editPerDataset.inheritPermission] }} onClose={() => setEditPerDatasetId(undefined)} /> )} ); } export default List;