diff --git a/packages/global/core/dataset/type.d.ts b/packages/global/core/dataset/type.d.ts index 104c67b09..8c9d5b872 100644 --- a/packages/global/core/dataset/type.d.ts +++ b/packages/global/core/dataset/type.d.ts @@ -137,7 +137,9 @@ export type DatasetSimpleItemType = { }; export type DatasetListItemType = { _id: string; + tmbId: string; avatar: string; + updateTime: Date; name: string; intro: string; type: `${DatasetTypeEnum}`; diff --git a/packages/web/components/common/Icon/constants.ts b/packages/web/components/common/Icon/constants.ts index f89af800c..1528b7d83 100644 --- a/packages/web/components/common/Icon/constants.ts +++ b/packages/web/components/common/Icon/constants.ts @@ -32,6 +32,7 @@ export const iconPaths = { 'common/googleFill': () => import('./icons/common/googleFill.svg'), 'common/importLight': () => import('./icons/common/importLight.svg'), 'common/info': () => import('./icons/common/info.svg'), + 'common/help': () => import('./icons/common/help.svg'), 'common/inviteLight': () => import('./icons/common/inviteLight.svg'), 'common/language/en': () => import('./icons/common/language/en.svg'), 'common/language/zh': () => import('./icons/common/language/zh.svg'), @@ -129,11 +130,15 @@ export const iconPaths = { 'core/chat/stopSpeech': () => import('./icons/core/chat/stopSpeech.svg'), 'core/dataset/commonDataset': () => import('./icons/core/dataset/commonDataset.svg'), 'core/dataset/commonDatasetColor': () => import('./icons/core/dataset/commonDatasetColor.svg'), + 'core/dataset/commonDatasetOutline': () => + import('./icons/core/dataset/commonDatasetOutline.svg'), 'core/dataset/datasetFill': () => import('./icons/core/dataset/datasetFill.svg'), 'core/dataset/datasetLight': () => import('./icons/core/dataset/datasetLight.svg'), 'core/dataset/externalDataset': () => import('./icons/core/dataset/externalDataset.svg'), 'core/dataset/externalDatasetColor': () => import('./icons/core/dataset/externalDatasetColor.svg'), + 'core/dataset/externalDatasetOutline': () => + import('./icons/core/dataset/externalDatasetOutline.svg'), 'core/dataset/fileCollection': () => import('./icons/core/dataset/fileCollection.svg'), 'core/dataset/fullTextRecall': () => import('./icons/core/dataset/fullTextRecall.svg'), 'core/dataset/manualCollection': () => import('./icons/core/dataset/manualCollection.svg'), @@ -145,6 +150,8 @@ export const iconPaths = { 'core/dataset/tag': () => import('./icons/core/dataset/tag.svg'), 'core/dataset/websiteDataset': () => import('./icons/core/dataset/websiteDataset.svg'), 'core/dataset/websiteDatasetColor': () => import('./icons/core/dataset/websiteDatasetColor.svg'), + 'core/dataset/websiteDatasetOutline': () => + import('./icons/core/dataset/websiteDatasetOutline.svg'), 'core/modules/basicNode': () => import('./icons/core/modules/basicNode.svg'), 'core/modules/fixview': () => import('./icons/core/modules/fixview.svg'), 'core/modules/flowLight': () => import('./icons/core/modules/flowLight.svg'), diff --git a/packages/web/components/common/Icon/icons/common/help.svg b/packages/web/components/common/Icon/icons/common/help.svg new file mode 100644 index 000000000..97e79689c --- /dev/null +++ b/packages/web/components/common/Icon/icons/common/help.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/web/components/common/Icon/icons/core/dataset/commonDatasetColor.svg b/packages/web/components/common/Icon/icons/core/dataset/commonDatasetColor.svg index ffcca3a46..1e737e869 100644 --- a/packages/web/components/common/Icon/icons/core/dataset/commonDatasetColor.svg +++ b/packages/web/components/common/Icon/icons/core/dataset/commonDatasetColor.svg @@ -1,8 +1,8 @@ - + - + diff --git a/packages/web/components/common/Icon/icons/core/dataset/commonDatasetOutline.svg b/packages/web/components/common/Icon/icons/core/dataset/commonDatasetOutline.svg new file mode 100644 index 000000000..7be7be394 --- /dev/null +++ b/packages/web/components/common/Icon/icons/core/dataset/commonDatasetOutline.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/packages/web/components/common/Icon/icons/core/dataset/externalDatasetColor.svg b/packages/web/components/common/Icon/icons/core/dataset/externalDatasetColor.svg index b1276dc27..b99fd29d5 100644 --- a/packages/web/components/common/Icon/icons/core/dataset/externalDatasetColor.svg +++ b/packages/web/components/common/Icon/icons/core/dataset/externalDatasetColor.svg @@ -1,5 +1,5 @@ - + @@ -8,3 +8,4 @@ + \ No newline at end of file diff --git a/packages/web/components/common/Icon/icons/core/dataset/externalDatasetOutline.svg b/packages/web/components/common/Icon/icons/core/dataset/externalDatasetOutline.svg new file mode 100644 index 000000000..90463dda7 --- /dev/null +++ b/packages/web/components/common/Icon/icons/core/dataset/externalDatasetOutline.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/packages/web/components/common/Icon/icons/core/dataset/websiteDatasetColor.svg b/packages/web/components/common/Icon/icons/core/dataset/websiteDatasetColor.svg index c3943a6aa..c215cd802 100644 --- a/packages/web/components/common/Icon/icons/core/dataset/websiteDatasetColor.svg +++ b/packages/web/components/common/Icon/icons/core/dataset/websiteDatasetColor.svg @@ -1,5 +1,5 @@ - + diff --git a/packages/web/components/common/Icon/icons/core/dataset/websiteDatasetOutline.svg b/packages/web/components/common/Icon/icons/core/dataset/websiteDatasetOutline.svg new file mode 100644 index 000000000..ea0e079c0 --- /dev/null +++ b/packages/web/components/common/Icon/icons/core/dataset/websiteDatasetOutline.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/packages/web/components/common/MyMenu/index.tsx b/packages/web/components/common/MyMenu/index.tsx index 924612b7d..267e44608 100644 --- a/packages/web/components/common/MyMenu/index.tsx +++ b/packages/web/components/common/MyMenu/index.tsx @@ -6,7 +6,8 @@ import { Box, useOutsideClick, MenuButton, - MenuItemProps + MenuItemProps, + PlacementWithLogical } from '@chakra-ui/react'; import MyDivider from '../MyDivider'; import type { IconNameType } from '../Icon/type'; @@ -21,6 +22,8 @@ export type Props = { Button: React.ReactNode; trigger?: 'hover' | 'click'; iconSize?: string; + iconRadius?: string; + placement?: PlacementWithLogical; menuList: { label?: string; children: { @@ -40,7 +43,9 @@ const MyMenu = ({ offset, iconSize = '1rem', Button, - menuList + menuList, + iconRadius = 'sm', + placement = 'bottom-start' }: Props) => { const typeMapStyle: Record = { primary: { @@ -107,7 +112,7 @@ const MyMenu = ({ direction={'ltr'} isLazy lazyBehavior={'keepMounted'} - placement="bottom-start" + placement={placement} computePositionOnMount > - {!!child.icon && } + {!!child.icon && ( + + )} {child.label} diff --git a/projects/app/src/pages/api/core/dataset/list.ts b/projects/app/src/pages/api/core/dataset/list.ts index c691b3d0c..d513063e4 100644 --- a/projects/app/src/pages/api/core/dataset/list.ts +++ b/projects/app/src/pages/api/core/dataset/list.ts @@ -128,7 +128,9 @@ async function handler(req: ApiRequestProps) { permission: item.permission, vectorModel: getVectorModel(item.vectorModel), defaultPermission: item.defaultPermission ?? DatasetDefaultPermissionVal, - inheritPermission: item.inheritPermission + inheritPermission: item.inheritPermission, + tmbId: item.tmbId, + updateTime: item.updateTime })) ); diff --git a/projects/app/src/pages/app/list/index.tsx b/projects/app/src/pages/app/list/index.tsx index 0cae6e541..ceb1011c0 100644 --- a/projects/app/src/pages/app/list/index.tsx +++ b/projects/app/src/pages/app/list/index.tsx @@ -186,7 +186,7 @@ const MyApps = () => { {userInfo?.team.permission.hasWritePer && folderDetail?.type !== AppTypeEnum.httpPlugin && ( }> {t('common:common.Create New')} diff --git a/projects/app/src/pages/dataset/list/component/CreateModal.tsx b/projects/app/src/pages/dataset/list/component/CreateModal.tsx index 9a38921f4..f4cfc7f41 100644 --- a/projects/app/src/pages/dataset/list/component/CreateModal.tsx +++ b/projects/app/src/pages/dataset/list/component/CreateModal.tsx @@ -17,8 +17,7 @@ import { useTranslation } from 'next-i18next'; import { DatasetTypeEnum } from '@fastgpt/global/core/dataset/constants'; import { MongoImageTypeEnum } from '@fastgpt/global/common/file/image/constants'; import AIModelSelector from '@/components/Select/AIModelSelector'; - -import QuestionTip from '@fastgpt/web/components/common/MyTooltip/QuestionTip'; +import MyIcon from '@fastgpt/web/components/common/Icon'; import { useSystem } from '@fastgpt/web/hooks/useSystem'; export type CreateDatasetType = @@ -116,17 +115,23 @@ const CreateModal = ({ return ( + + {t('common:core.dataset.Create dataset', { name: databaseNameMap[type] })} + + } isOpen onClose={onClose} isCentered={!isPc} - w={'450px'} + w={'490px'} > - - - {t('common:common.Set Name')} - + + + + {t('common:common.Set Name')} + + {filterNotHiddenVectorModelList.length > 1 && ( - - + + {t('common:core.ai.model.Vector Model')} - + + + - + ({ label: item.name, @@ -173,13 +192,24 @@ const CreateModal = ({ )} {datasetModelList.length > 1 && ( - - + + {t('common:core.ai.model.Dataset Agent Model')} - + ({ label: item.name, @@ -194,7 +224,7 @@ const CreateModal = ({ )} - + diff --git a/projects/app/src/pages/dataset/list/component/List.tsx b/projects/app/src/pages/dataset/list/component/List.tsx index ce348fbb3..89dc1f642 100644 --- a/projects/app/src/pages/dataset/list/component/List.tsx +++ b/projects/app/src/pages/dataset/list/component/List.tsx @@ -1,16 +1,15 @@ import React, { useMemo, useRef, useState } from 'react'; import { resumeInheritPer } from '@/web/core/dataset/api'; import { useDatasetStore } from '@/web/core/dataset/store/dataset'; -import { Box, Flex, Grid } from '@chakra-ui/react'; +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 DatasetTypeTag from '@/components/core/dataset/DatasetTypeTag'; import Avatar from '@fastgpt/web/components/common/Avatar'; import { useConfirm } from '@fastgpt/web/hooks/useConfirm'; -import { useRequest } from '@fastgpt/web/hooks/useRequest'; +import { useRequest, useRequest2 } from '@fastgpt/web/hooks/useRequest'; import { DatasetItemType } from '@fastgpt/global/core/dataset/type'; import { useSystemStore } from '@/web/common/system/useSystemStore'; import { useToast } from '@fastgpt/web/hooks/useToast'; @@ -35,12 +34,18 @@ import { useFolderDrag } from '@/components/common/folder/useFolderDrag'; import MyBox from '@fastgpt/web/components/common/MyBox'; import { useI18n } from '@/web/context/I18n'; import { useTranslation } from 'next-i18next'; +import { useUserStore } from '@/web/support/user/useUserStore'; +import { formatTimeToChatTime } from '@fastgpt/global/common/string/time'; +import { useSystem } from '@fastgpt/web/hooks/useSystem'; +import SideTag from './SideTag'; function List() { const { setLoading } = useSystemStore(); const { toast } = useToast(); + const { isPc } = useSystem(); const { t } = useTranslation(); const { commonT } = useI18n(); + const { loadAndGetTeamMembers } = useUserStore(); const { loadMyDatasets, setMoveDatasetId, @@ -71,6 +76,10 @@ function List() { } }); + const { data: members = [], loading: isLoadMembers } = useRequest2(loadAndGetTeamMembers, { + manual: false + }); + const editPerDataset = useMemo( () => (editPerDatasetIndex !== undefined ? myDatasets[editPerDatasetIndex] : undefined), [editPerDatasetIndex, myDatasets] @@ -152,197 +161,238 @@ function List() { gridGap={5} alignItems={'stretch'} > - {formatDatasets.map((dataset, index) => ( - - - {dataset.type === DatasetTypeEnum.folder - ? t('common.folder.Open folder') - : t('common.folder.open_dataset')} - - - } - > - { + const owner = members.find((v) => v.tmbId === dataset.tmbId); + return ( + + + {dataset.type === DatasetTypeEnum.folder + ? t('common.folder.Open folder') + : t('common.folder.open_dataset')} + + } - }} - onClick={() => { - if (dataset.type === DatasetTypeEnum.folder) { - router.push({ - pathname: '/dataset/list', - query: { - parentId: dataset._id - } - }); - } else { - router.push({ - pathname: '/dataset/detail', - query: { - datasetId: dataset._id - } - }); - } - }} - > - {dataset.permission.hasWritePer && ( - + { - e.stopPropagation(); + onClick={() => { + if (dataset.type === DatasetTypeEnum.folder) { + router.push({ + pathname: '/dataset/list', + query: { + parentId: dataset._id + } + }); + } else { + router.push({ + pathname: '/dataset/detail', + query: { + datasetId: dataset._id + } + }); + } }} > - - - - } - menuList={[ - { - children: [ - { - icon: 'edit', - label: commonT('dataset.Edit Info'), - onClick: () => - setEditedDataset({ - id: dataset._id, - name: dataset.name, - intro: dataset.intro, - avatar: dataset.avatar - }) - }, - { - icon: 'common/file/move', - label: t('common:Move'), - onClick: () => setMoveDatasetId(dataset._id) - }, - ...(dataset.permission.hasManagePer - ? [ - { - icon: 'support/team/key', - label: t('common:permission.Permission'), - onClick: () => setEditPerDatasetIndex(index) - } - ] - : []) - ] - }, - ...(dataset.type != DatasetTypeEnum.folder - ? [ - { - children: [ - { - icon: 'export', - label: t('common:Export'), - onClick: () => { - exportDataset(dataset); - } - } - ] - } - ] - : []), - ...(dataset.permission.hasManagePer - ? [ - { - children: [ - { - icon: 'delete', - label: t('common:common.Delete'), - type: 'danger' as 'danger', - onClick: () => onClickDeleteDataset(dataset._id) - } - ] - } - ] - : []) - ]} - /> - - )} + + + + {dataset.name} + - - - - {dataset.name} - - - - {dataset.intro || - (dataset.type === DatasetTypeEnum.folder - ? t('common:core.dataset.Folder placeholder') - : t('common:core.dataset.Intro Placeholder'))} - - - - - - {dataset.type !== DatasetTypeEnum.folder && ( - - )} - - - - ))} + + {dataset.type !== DatasetTypeEnum.folder && ( + + )} + + + + + {dataset.intro || + (dataset.type === DatasetTypeEnum.folder + ? t('common:core.dataset.Folder placeholder') + : t('common:core.dataset.Intro Placeholder'))} + + + + + {owner && ( + + + + {owner.memberName} + + + )} + + + + + {isPc && ( + + + + {formatTimeToChatTime(dataset.updateTime)} + + + )} + {dataset.permission.hasWritePer && ( + { + e.stopPropagation(); + }} + > + + + + } + menuList={[ + { + children: [ + { + icon: 'edit', + label: commonT('dataset.Edit Info'), + onClick: () => + setEditedDataset({ + id: dataset._id, + name: dataset.name, + intro: dataset.intro, + avatar: dataset.avatar + }) + }, + { + icon: 'common/file/move', + label: t('common:Move'), + onClick: () => setMoveDatasetId(dataset._id) + }, + ...(dataset.permission.hasManagePer + ? [ + { + icon: 'support/team/key', + label: t('common:permission.Permission'), + onClick: () => setEditPerDatasetIndex(index) + } + ] + : []) + ] + }, + ...(dataset.type != DatasetTypeEnum.folder + ? [ + { + children: [ + { + icon: 'export', + label: t('common:Export'), + onClick: () => { + exportDataset(dataset); + } + } + ] + } + ] + : []), + ...(dataset.permission.hasManagePer + ? [ + { + children: [ + { + icon: 'delete', + label: t('common:common.Delete'), + type: 'danger' as 'danger', + onClick: () => onClickDeleteDataset(dataset._id) + } + ] + } + ] + : []) + ]} + /> + + )} + + + + + ); + })} )} {myDatasets.length === 0 && ( diff --git a/projects/app/src/pages/dataset/list/component/SideTag.tsx b/projects/app/src/pages/dataset/list/component/SideTag.tsx new file mode 100644 index 000000000..df6eae04f --- /dev/null +++ b/projects/app/src/pages/dataset/list/component/SideTag.tsx @@ -0,0 +1,53 @@ +import { Box, Flex, FlexProps } from '@chakra-ui/react'; +import { DatasetTypeEnum } from '@fastgpt/global/core/dataset/constants'; +import MyIcon from '@fastgpt/web/components/common/Icon'; +import React, { useMemo } from 'react'; +import { useTranslation } from 'next-i18next'; + +const SideTag = ({ type, ...props }: { type: `${DatasetTypeEnum}` } & FlexProps) => { + if (type === DatasetTypeEnum.folder) return null; + const { t } = useTranslation(); + const DatasetListTypeMap = useMemo(() => { + return { + [DatasetTypeEnum.dataset]: { + icon: 'core/dataset/commonDatasetOutline', + label: t('dataset:common_dataset'), + collectionLabel: 'common.File' + }, + [DatasetTypeEnum.websiteDataset]: { + icon: 'core/dataset/websiteDatasetOutline', + label: t('dataset:website_dataset'), + collectionLabel: 'common.Website' + }, + [DatasetTypeEnum.externalFile]: { + icon: 'core/dataset/externalDatasetOutline', + label: t('dataset:external_file'), + collectionLabel: 'common.File' + } + }; + }, [t]); + const item = DatasetListTypeMap[type] || DatasetListTypeMap['dataset']; + + return ( + + + + {/* @ts-ignore */} + {item.label} + + + ); +}; + +export default SideTag; diff --git a/projects/app/src/pages/dataset/list/index.tsx b/projects/app/src/pages/dataset/list/index.tsx index 69b17e481..cf302c60c 100644 --- a/projects/app/src/pages/dataset/list/index.tsx +++ b/projects/app/src/pages/dataset/list/index.tsx @@ -10,7 +10,6 @@ import { Input } from '@chakra-ui/react'; import { useRouter } from 'next/router'; -import PageContainer from '@/components/PageContainer'; import { useTranslation } from 'next-i18next'; import { serviceSideProps } from '@/web/common/utils/i18n'; import ParentPaths from '@/components/common/folder/Path'; @@ -92,14 +91,17 @@ const Dataset = () => { const RenderSearchInput = useMemo( () => ( - + - +