mirror of
https://github.com/labring/FastGPT.git
synced 2025-08-02 20:58:12 +00:00
v4.6 -1 (#459)
This commit is contained in:
@@ -50,6 +50,8 @@ import { useDrag } from '@/web/common/hooks/useDrag';
|
||||
import SelectCollections from '@/web/core/dataset/components/SelectCollections';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import MyTooltip from '@/components/MyTooltip';
|
||||
import { useUserStore } from '@/web/support/user/useUserStore';
|
||||
import { TeamMemberRoleEnum } from '@fastgpt/global/support/user/team/constant';
|
||||
|
||||
const FileImportModal = dynamic(() => import('./Import/ImportModal'), {});
|
||||
|
||||
@@ -62,6 +64,7 @@ const CollectionCard = () => {
|
||||
const { t } = useTranslation();
|
||||
const { Loading } = useLoading();
|
||||
const { isPc } = useSystemStore();
|
||||
const { userInfo } = useUserStore();
|
||||
const [searchText, setSearchText] = useState('');
|
||||
const { setLoading } = useSystemStore();
|
||||
|
||||
@@ -271,67 +274,69 @@ const CollectionCard = () => {
|
||||
/>
|
||||
</Flex>
|
||||
)}
|
||||
<MyMenu
|
||||
offset={[-40, 10]}
|
||||
width={120}
|
||||
Button={
|
||||
<MenuButton
|
||||
_hover={{
|
||||
color: 'myBlue.600'
|
||||
}}
|
||||
fontSize={['sm', 'md']}
|
||||
>
|
||||
<Flex
|
||||
alignItems={'center'}
|
||||
px={5}
|
||||
py={2}
|
||||
borderRadius={'md'}
|
||||
cursor={'pointer'}
|
||||
bg={'myBlue.600'}
|
||||
overflow={'hidden'}
|
||||
color={'white'}
|
||||
h={['28px', '35px']}
|
||||
{userInfo?.team?.role !== TeamMemberRoleEnum.visitor && (
|
||||
<MyMenu
|
||||
offset={[-40, 10]}
|
||||
width={120}
|
||||
Button={
|
||||
<MenuButton
|
||||
_hover={{
|
||||
color: 'myBlue.600'
|
||||
}}
|
||||
fontSize={['sm', 'md']}
|
||||
>
|
||||
<MyIcon name={'importLight'} mr={2} w={'14px'} />
|
||||
<Box>{t('dataset.collections.Create And Import')}</Box>
|
||||
</Flex>
|
||||
</MenuButton>
|
||||
}
|
||||
menuList={[
|
||||
{
|
||||
child: (
|
||||
<Flex>
|
||||
<Image src={FolderAvatarSrc} alt={''} w={'20px'} mr={2} />
|
||||
{t('Folder')}
|
||||
<Flex
|
||||
alignItems={'center'}
|
||||
px={5}
|
||||
py={2}
|
||||
borderRadius={'md'}
|
||||
cursor={'pointer'}
|
||||
bg={'myBlue.600'}
|
||||
overflow={'hidden'}
|
||||
color={'white'}
|
||||
h={['28px', '35px']}
|
||||
>
|
||||
<MyIcon name={'importLight'} mr={2} w={'14px'} />
|
||||
<Box>{t('dataset.collections.Create And Import')}</Box>
|
||||
</Flex>
|
||||
),
|
||||
onClick: () => setEditFolderData({})
|
||||
},
|
||||
{
|
||||
child: (
|
||||
<Flex>
|
||||
<Image src={'/imgs/files/collection.svg'} alt={''} w={'20px'} mr={2} />
|
||||
{t('dataset.Create Virtual File')}
|
||||
</Flex>
|
||||
),
|
||||
onClick: () => {
|
||||
onOpenCreateVirtualFileModal({
|
||||
defaultVal: '',
|
||||
onSuccess: (name) => onCreateVirtualFile({ name })
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
child: (
|
||||
<Flex>
|
||||
<Image src={'/imgs/files/file.svg'} alt={''} w={'20px'} mr={2} />
|
||||
{t('dataset.File Input')}
|
||||
</Flex>
|
||||
),
|
||||
onClick: onOpenFileImportModal
|
||||
</MenuButton>
|
||||
}
|
||||
]}
|
||||
/>
|
||||
menuList={[
|
||||
{
|
||||
child: (
|
||||
<Flex>
|
||||
<Image src={FolderAvatarSrc} alt={''} w={'20px'} mr={2} />
|
||||
{t('Folder')}
|
||||
</Flex>
|
||||
),
|
||||
onClick: () => setEditFolderData({})
|
||||
},
|
||||
{
|
||||
child: (
|
||||
<Flex>
|
||||
<Image src={'/imgs/files/collection.svg'} alt={''} w={'20px'} mr={2} />
|
||||
{t('dataset.Create Virtual File')}
|
||||
</Flex>
|
||||
),
|
||||
onClick: () => {
|
||||
onOpenCreateVirtualFileModal({
|
||||
defaultVal: '',
|
||||
onSuccess: (name) => onCreateVirtualFile({ name })
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
child: (
|
||||
<Flex>
|
||||
<Image src={'/imgs/files/file.svg'} alt={''} w={'20px'} mr={2} />
|
||||
{t('dataset.File Input')}
|
||||
</Flex>
|
||||
),
|
||||
onClick: onOpenFileImportModal
|
||||
}
|
||||
]}
|
||||
/>
|
||||
)}
|
||||
</Flex>
|
||||
|
||||
<TableContainer mt={[0, 3]} position={'relative'} flex={'1 0 0'} overflowY={'auto'}>
|
||||
@@ -436,85 +441,87 @@ const CollectionCard = () => {
|
||||
</Flex>
|
||||
</Td>
|
||||
<Td onClick={(e) => e.stopPropagation()}>
|
||||
<MyMenu
|
||||
width={100}
|
||||
Button={
|
||||
<MenuButton
|
||||
w={'22px'}
|
||||
h={'22px'}
|
||||
borderRadius={'md'}
|
||||
_hover={{
|
||||
color: 'myBlue.600',
|
||||
'& .icon': {
|
||||
bg: 'myGray.100'
|
||||
}
|
||||
}}
|
||||
>
|
||||
<MyIcon
|
||||
className="icon"
|
||||
name={'more'}
|
||||
h={'16px'}
|
||||
w={'16px'}
|
||||
px={1}
|
||||
py={1}
|
||||
{collection.canWrite && userInfo?.team?.role !== TeamMemberRoleEnum.visitor && (
|
||||
<MyMenu
|
||||
width={100}
|
||||
Button={
|
||||
<MenuButton
|
||||
w={'22px'}
|
||||
h={'22px'}
|
||||
borderRadius={'md'}
|
||||
cursor={'pointer'}
|
||||
/>
|
||||
</MenuButton>
|
||||
}
|
||||
menuList={[
|
||||
{
|
||||
child: (
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'moveLight'} w={'14px'} mr={2} />
|
||||
{t('Move')}
|
||||
</Flex>
|
||||
),
|
||||
onClick: () => setMoveCollectionData({ collectionId: collection._id })
|
||||
},
|
||||
{
|
||||
child: (
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'edit'} w={'14px'} mr={2} />
|
||||
{t('Rename')}
|
||||
</Flex>
|
||||
),
|
||||
onClick: () =>
|
||||
onOpenEditTitleModal({
|
||||
defaultVal: collection.name,
|
||||
onSuccess: (newName) => {
|
||||
onUpdateCollectionName({
|
||||
collectionId: collection._id,
|
||||
name: newName
|
||||
});
|
||||
_hover={{
|
||||
color: 'myBlue.600',
|
||||
'& .icon': {
|
||||
bg: 'myGray.100'
|
||||
}
|
||||
})
|
||||
},
|
||||
{
|
||||
child: (
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon
|
||||
mr={1}
|
||||
name={'delete'}
|
||||
w={'14px'}
|
||||
_hover={{ color: 'red.600' }}
|
||||
/>
|
||||
<Box>{t('common.Delete')}</Box>
|
||||
</Flex>
|
||||
),
|
||||
onClick: () =>
|
||||
openConfirm(
|
||||
() => {
|
||||
onDelCollection(collection._id);
|
||||
},
|
||||
undefined,
|
||||
collection.type === DatasetCollectionTypeEnum.folder
|
||||
? t('dataset.collections.Confirm to delete the folder')
|
||||
: t('dataset.Confirm to delete the file')
|
||||
)()
|
||||
}}
|
||||
>
|
||||
<MyIcon
|
||||
className="icon"
|
||||
name={'more'}
|
||||
h={'16px'}
|
||||
w={'16px'}
|
||||
px={1}
|
||||
py={1}
|
||||
borderRadius={'md'}
|
||||
cursor={'pointer'}
|
||||
/>
|
||||
</MenuButton>
|
||||
}
|
||||
]}
|
||||
/>
|
||||
menuList={[
|
||||
{
|
||||
child: (
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'moveLight'} w={'14px'} mr={2} />
|
||||
{t('Move')}
|
||||
</Flex>
|
||||
),
|
||||
onClick: () => setMoveCollectionData({ collectionId: collection._id })
|
||||
},
|
||||
{
|
||||
child: (
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'edit'} w={'14px'} mr={2} />
|
||||
{t('Rename')}
|
||||
</Flex>
|
||||
),
|
||||
onClick: () =>
|
||||
onOpenEditTitleModal({
|
||||
defaultVal: collection.name,
|
||||
onSuccess: (newName) => {
|
||||
onUpdateCollectionName({
|
||||
collectionId: collection._id,
|
||||
name: newName
|
||||
});
|
||||
}
|
||||
})
|
||||
},
|
||||
{
|
||||
child: (
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon
|
||||
mr={1}
|
||||
name={'delete'}
|
||||
w={'14px'}
|
||||
_hover={{ color: 'red.600' }}
|
||||
/>
|
||||
<Box>{t('common.Delete')}</Box>
|
||||
</Flex>
|
||||
),
|
||||
onClick: () =>
|
||||
openConfirm(
|
||||
() => {
|
||||
onDelCollection(collection._id);
|
||||
},
|
||||
undefined,
|
||||
collection.type === DatasetCollectionTypeEnum.folder
|
||||
? t('dataset.collections.Confirm to delete the folder')
|
||||
: t('dataset.Confirm to delete the file')
|
||||
)()
|
||||
}
|
||||
]}
|
||||
/>
|
||||
)}
|
||||
</Td>
|
||||
</Tr>
|
||||
))}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import React, { useCallback, useState, useRef, useMemo } from 'react';
|
||||
import { Box, Card, IconButton, Flex, Grid, Image, Button } from '@chakra-ui/react';
|
||||
import { Box, Card, IconButton, Flex, Grid, Button } from '@chakra-ui/react';
|
||||
import { usePagination } from '@/web/common/hooks/usePagination';
|
||||
import {
|
||||
getDatasetDataList,
|
||||
@@ -17,21 +17,22 @@ import { useRouter } from 'next/router';
|
||||
import MyIcon from '@/components/Icon';
|
||||
import MyInput from '@/components/MyInput';
|
||||
import { useLoading } from '@/web/common/hooks/useLoading';
|
||||
import { getCollectionIcon } from '@fastgpt/global/core/dataset/utils';
|
||||
import InputDataModal, { RawSourceText, type InputDataType } from '../components/InputDataModal';
|
||||
import type { DatasetDataListItemType } from '@/global/core/dataset/response.d';
|
||||
import { TabEnum } from '..';
|
||||
import { useUserStore } from '@/web/support/user/useUserStore';
|
||||
import { TeamMemberRoleEnum } from '@fastgpt/global/support/user/team/constant';
|
||||
|
||||
const DataCard = () => {
|
||||
const BoxRef = useRef<HTMLDivElement>(null);
|
||||
const lastSearch = useRef('');
|
||||
const router = useRouter();
|
||||
const { userInfo } = useUserStore();
|
||||
const { collectionId = '' } = router.query as { collectionId: string };
|
||||
const { Loading, setIsLoading } = useLoading({ defaultLoading: true });
|
||||
const { t } = useTranslation();
|
||||
const [searchText, setSearchText] = useState('');
|
||||
const { toast } = useToast();
|
||||
const [isDeleting, setIsDeleting] = useState(false);
|
||||
const { openConfirm, ConfirmModal } = useConfirm({
|
||||
content: t('dataset.Confirm to delete the data')
|
||||
});
|
||||
@@ -74,6 +75,11 @@ const DataCard = () => {
|
||||
getDatasetCollectionById(collectionId)
|
||||
);
|
||||
|
||||
const canWrite = useMemo(
|
||||
() => userInfo?.team?.role !== TeamMemberRoleEnum.visitor && !!collection?.canWrite,
|
||||
[collection?.canWrite, userInfo?.team?.role]
|
||||
);
|
||||
|
||||
return (
|
||||
<Box ref={BoxRef} position={'relative'} px={5} py={[1, 5]} h={'100%'} overflow={'overlay'}>
|
||||
<Flex alignItems={'center'}>
|
||||
@@ -112,24 +118,25 @@ const DataCard = () => {
|
||||
</Box>
|
||||
</Box>
|
||||
</Flex>
|
||||
<Box>
|
||||
<Button
|
||||
ml={2}
|
||||
variant={'base'}
|
||||
size={['sm', 'md']}
|
||||
onClick={() => {
|
||||
if (!collection) return;
|
||||
setEditInputData({
|
||||
datasetId: collection.datasetId,
|
||||
collectionId: collection._id,
|
||||
sourceId: collection.metadata?.fileId || collection.metadata?.rawLink,
|
||||
sourceName: collection.name
|
||||
});
|
||||
}}
|
||||
>
|
||||
{t('dataset.Insert Data')}
|
||||
</Button>
|
||||
</Box>
|
||||
{canWrite && (
|
||||
<Box>
|
||||
<Button
|
||||
ml={2}
|
||||
variant={'base'}
|
||||
size={['sm', 'md']}
|
||||
onClick={() => {
|
||||
if (!collection) return;
|
||||
setEditInputData({
|
||||
collectionId: collection._id,
|
||||
sourceId: collection.metadata?.fileId || collection.metadata?.rawLink,
|
||||
sourceName: collection.name
|
||||
});
|
||||
}}
|
||||
>
|
||||
{t('dataset.Insert Data')}
|
||||
</Button>
|
||||
</Box>
|
||||
)}
|
||||
</Flex>
|
||||
<Flex my={3} alignItems={'center'}>
|
||||
<Box>
|
||||
@@ -180,7 +187,6 @@ const DataCard = () => {
|
||||
if (!collection) return;
|
||||
setEditInputData({
|
||||
id: item.id,
|
||||
datasetId: collection.datasetId,
|
||||
collectionId: collection._id,
|
||||
q: item.q,
|
||||
a: item.a,
|
||||
@@ -206,34 +212,35 @@ const DataCard = () => {
|
||||
<Box className={'textEllipsis'} flex={1} color={'myGray.500'}>
|
||||
ID:{item.id}
|
||||
</Box>
|
||||
<IconButton
|
||||
className="delete"
|
||||
display={['flex', 'none']}
|
||||
icon={<DeleteIcon />}
|
||||
variant={'base'}
|
||||
colorScheme={'gray'}
|
||||
aria-label={'delete'}
|
||||
size={'xs'}
|
||||
borderRadius={'md'}
|
||||
_hover={{ color: 'red.600' }}
|
||||
isLoading={isDeleting}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
openConfirm(async () => {
|
||||
try {
|
||||
setIsDeleting(true);
|
||||
await delOneDatasetDataById(item.id);
|
||||
getData(pageNum);
|
||||
} catch (error) {
|
||||
toast({
|
||||
title: getErrText(error),
|
||||
status: 'error'
|
||||
});
|
||||
}
|
||||
setIsDeleting(false);
|
||||
})();
|
||||
}}
|
||||
/>
|
||||
{canWrite && (
|
||||
<IconButton
|
||||
className="delete"
|
||||
display={['flex', 'none']}
|
||||
icon={<DeleteIcon />}
|
||||
variant={'base'}
|
||||
colorScheme={'gray'}
|
||||
aria-label={'delete'}
|
||||
size={'xs'}
|
||||
borderRadius={'md'}
|
||||
_hover={{ color: 'red.600' }}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
openConfirm(async () => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
await delOneDatasetDataById(item.id);
|
||||
getData(pageNum);
|
||||
} catch (error) {
|
||||
toast({
|
||||
title: getErrText(error),
|
||||
status: 'error'
|
||||
});
|
||||
}
|
||||
setIsLoading(false);
|
||||
})();
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Flex>
|
||||
</Card>
|
||||
))}
|
||||
@@ -248,17 +255,18 @@ const DataCard = () => {
|
||||
<Flex flexDirection={'column'} alignItems={'center'} pt={'10vh'}>
|
||||
<MyIcon name="empty" w={'48px'} h={'48px'} color={'transparent'} />
|
||||
<Box mt={2} color={'myGray.500'}>
|
||||
知识库空空如也
|
||||
内容空空的,快创建一个吧!
|
||||
</Box>
|
||||
</Flex>
|
||||
)}
|
||||
|
||||
{editInputData !== undefined && collection && (
|
||||
<InputDataModal
|
||||
datasetId={collection.datasetId}
|
||||
datasetId={collection?.datasetId}
|
||||
defaultValues={editInputData}
|
||||
onClose={() => setEditInputData(undefined)}
|
||||
onSuccess={() => getData(pageNum)}
|
||||
canWrite={canWrite}
|
||||
/>
|
||||
)}
|
||||
<ConfirmModal />
|
||||
|
@@ -10,7 +10,7 @@ import {
|
||||
NumberDecrementStepper
|
||||
} from '@chakra-ui/react';
|
||||
import { useConfirm } from '@/web/common/hooks/useConfirm';
|
||||
import { formatPrice } from '@fastgpt/global/common/bill/tools';
|
||||
import { formatPrice } from '@fastgpt/global/support/wallet/bill/tools';
|
||||
import MyTooltip from '@/components/MyTooltip';
|
||||
import { QuestionOutlineIcon } from '@chakra-ui/icons';
|
||||
import { useDatasetStore } from '@/web/core/dataset/store/dataset';
|
||||
|
@@ -5,13 +5,13 @@ import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { splitText2Chunks } from '@/global/common/string/tools';
|
||||
import { simpleText } from '@fastgpt/global/common/string/tools';
|
||||
import {
|
||||
uploadFiles,
|
||||
fileDownload,
|
||||
readCsvContent,
|
||||
readTxtContent,
|
||||
readPdfContent,
|
||||
readDocContent
|
||||
} from '@/web/common/file/utils';
|
||||
import { uploadFiles } from '@/web/common/file/controller';
|
||||
import { Box, Flex, useDisclosure, type BoxProps } from '@chakra-ui/react';
|
||||
import React, { DragEvent, useCallback, useState } from 'react';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
@@ -108,13 +108,18 @@ const FileSelect = ({
|
||||
if (!icon) continue;
|
||||
|
||||
// upload file
|
||||
const filesId = await uploadFiles([file], { datasetId: datasetDetail._id }, (percent) => {
|
||||
if (percent < 100) {
|
||||
setSelectingText(
|
||||
t('file.Uploading', { name: file.name.slice(0, 30), percent }) || ''
|
||||
);
|
||||
} else {
|
||||
setSelectingText(t('file.Parse', { name: file.name.slice(0, 30) }) || '');
|
||||
const filesId = await uploadFiles({
|
||||
files: [file],
|
||||
bucketName: 'dataset',
|
||||
metadata: { datasetId: datasetDetail._id },
|
||||
percentListen: (percent) => {
|
||||
if (percent < 100) {
|
||||
setSelectingText(
|
||||
t('file.Uploading', { name: file.name.slice(0, 30), percent }) || ''
|
||||
);
|
||||
} else {
|
||||
setSelectingText(t('file.Parse', { name: file.name.slice(0, 30) }) || '');
|
||||
}
|
||||
}
|
||||
});
|
||||
const fileId = filesId[0];
|
||||
@@ -243,7 +248,11 @@ const FileSelect = ({
|
||||
type: txtBlob.type,
|
||||
lastModified: new Date().getTime()
|
||||
});
|
||||
const fileIds = await uploadFiles([txtFile], { datasetId: datasetDetail._id });
|
||||
const fileIds = await uploadFiles({
|
||||
files: [txtFile],
|
||||
bucketName: 'dataset',
|
||||
metadata: { datasetId: datasetDetail._id }
|
||||
});
|
||||
|
||||
const splitRes = splitText2Chunks({
|
||||
text: content,
|
||||
|
@@ -45,7 +45,7 @@ const ImportData = ({
|
||||
mode: TrainingModeEnum.index
|
||||
},
|
||||
[ImportTypeEnum.qa]: {
|
||||
defaultChunkLen: qaModel?.maxToken * 0.5 || 8000,
|
||||
defaultChunkLen: qaModel?.maxContext * 0.5 || 8000,
|
||||
unitPrice: qaModel?.price || 3,
|
||||
mode: TrainingModeEnum.qa
|
||||
},
|
||||
|
@@ -11,7 +11,7 @@ import React, {
|
||||
import FileSelect, { FileItemType, Props as FileSelectProps } from './FileSelect';
|
||||
import { useRequest } from '@/web/common/hooks/useRequest';
|
||||
import { postDatasetCollection } from '@/web/core/dataset/api';
|
||||
import { formatPrice } from '@fastgpt/global/common/bill/tools';
|
||||
import { formatPrice } from '@fastgpt/global/support/wallet/bill/tools';
|
||||
import { splitText2Chunks } from '@/global/common/string/tools';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { getErrText } from '@fastgpt/global/common/error/utils';
|
||||
@@ -21,7 +21,7 @@ import { CloseIcon } from '@chakra-ui/icons';
|
||||
import DeleteIcon, { hoverDeleteStyles } from '@/components/Icon/delete';
|
||||
import MyIcon from '@/components/Icon';
|
||||
import { chunksUpload } from '@/web/core/dataset/utils';
|
||||
import { postCreateTrainingBill } from '@/web/common/bill/api';
|
||||
import { postCreateTrainingBill } from '@/web/support/wallet/bill/api';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ImportTypeEnum } from './ImportModal';
|
||||
|
||||
@@ -129,19 +129,19 @@ const Provider = ({
|
||||
let totalInsertion = 0;
|
||||
for await (const file of files) {
|
||||
const chunks = file.chunks;
|
||||
// create training bill
|
||||
const billId = await postCreateTrainingBill({
|
||||
name: t('dataset.collections.Create Training Data', { filename: file.filename })
|
||||
});
|
||||
// create a file collection and training bill
|
||||
const [collectionId, billId] = await Promise.all([
|
||||
postDatasetCollection({
|
||||
datasetId,
|
||||
parentId,
|
||||
name: file.filename,
|
||||
type: file.type,
|
||||
metadata: file.metadata
|
||||
}),
|
||||
postCreateTrainingBill({
|
||||
name: t('dataset.collections.Create Training Data', { filename: file.filename })
|
||||
})
|
||||
]);
|
||||
const collectionId = await postDatasetCollection({
|
||||
datasetId,
|
||||
parentId,
|
||||
name: file.filename,
|
||||
type: file.type,
|
||||
metadata: file.metadata
|
||||
});
|
||||
|
||||
// upload data
|
||||
const { insertLen } = await chunksUpload({
|
||||
collectionId,
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import React, { useState, useMemo } from 'react';
|
||||
import { Box, Flex, Button, Input } from '@chakra-ui/react';
|
||||
import { useConfirm } from '@/web/common/hooks/useConfirm';
|
||||
import { formatPrice } from '@fastgpt/global/common/bill/tools';
|
||||
import { formatPrice } from '@fastgpt/global/support/wallet/bill/tools';
|
||||
import MyTooltip from '@/components/MyTooltip';
|
||||
import { QuestionOutlineIcon, InfoOutlineIcon } from '@chakra-ui/icons';
|
||||
import { Prompt_AgentQA } from '@/global/core/prompt/agent';
|
||||
|
@@ -15,11 +15,13 @@ import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { useDatasetStore } from '@/web/core/dataset/store/dataset';
|
||||
import { useConfirm } from '@/web/common/hooks/useConfirm';
|
||||
import { UseFormReturn } from 'react-hook-form';
|
||||
import { compressImg } from '@/web/common/file/utils';
|
||||
import { compressImgAndUpload } from '@/web/common/file/controller';
|
||||
import type { DatasetItemType } from '@/types/core/dataset';
|
||||
import Avatar from '@/components/Avatar';
|
||||
import Tag from '@/components/Tag';
|
||||
import MyTooltip from '@/components/MyTooltip';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import PermissionRadio from '@/components/support/permission/Radio';
|
||||
|
||||
export interface ComponentRef {
|
||||
initInput: (tags: string) => void;
|
||||
@@ -29,6 +31,7 @@ const Info = (
|
||||
{ datasetId, form }: { datasetId: string; form: UseFormReturn<DatasetItemType, any> },
|
||||
ref: ForwardedRef<ComponentRef>
|
||||
) => {
|
||||
const { t } = useTranslation();
|
||||
const { getValues, formState, setValue, register, handleSubmit } = form;
|
||||
const InputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
@@ -115,7 +118,7 @@ const Info = (
|
||||
const file = e[0];
|
||||
if (!file) return;
|
||||
try {
|
||||
const src = await compressImg({
|
||||
const src = await compressImgAndUpload({
|
||||
file,
|
||||
maxW: 100,
|
||||
maxH: 100
|
||||
@@ -220,6 +223,23 @@ const Info = (
|
||||
))}
|
||||
</Flex>
|
||||
</Flex>
|
||||
{datasetDetail.isOwner && (
|
||||
<Flex mt={5} alignItems={'center'} w={'100%'} flexWrap={'wrap'}>
|
||||
<Box flex={['0 0 90px', '0 0 160px']} w={0}>
|
||||
{t('user.Permission')}
|
||||
</Box>
|
||||
<Box>
|
||||
<PermissionRadio
|
||||
value={getValues('permission')}
|
||||
onChange={(e) => {
|
||||
setValue('permission', e);
|
||||
setRefresh(!refresh);
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
</Flex>
|
||||
)}
|
||||
|
||||
<Flex mt={5} w={'100%'} alignItems={'flex-end'}>
|
||||
<Box flex={['0 0 90px', '0 0 160px']} w={0}></Box>
|
||||
<Button
|
||||
@@ -230,18 +250,20 @@ const Info = (
|
||||
>
|
||||
保存
|
||||
</Button>
|
||||
<IconButton
|
||||
isLoading={btnLoading}
|
||||
icon={<DeleteIcon />}
|
||||
aria-label={''}
|
||||
variant={'outline'}
|
||||
size={'sm'}
|
||||
_hover={{
|
||||
color: 'red.600',
|
||||
borderColor: 'red.600'
|
||||
}}
|
||||
onClick={openConfirm(onclickDelKb)}
|
||||
/>
|
||||
{datasetDetail.isOwner && (
|
||||
<IconButton
|
||||
isLoading={btnLoading}
|
||||
icon={<DeleteIcon />}
|
||||
aria-label={''}
|
||||
variant={'outline'}
|
||||
size={'sm'}
|
||||
_hover={{
|
||||
color: 'red.600',
|
||||
borderColor: 'red.600'
|
||||
}}
|
||||
onClick={openConfirm(onclickDelKb)}
|
||||
/>
|
||||
)}
|
||||
</Flex>
|
||||
<File onSelect={onSelectFile} />
|
||||
<ConfirmModal />
|
||||
|
@@ -15,7 +15,7 @@ import { QuestionOutlineIcon } from '@chakra-ui/icons';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useDatasetStore } from '@/web/core/dataset/store/dataset';
|
||||
import { getFileAndOpen } from '@/web/common/file/utils';
|
||||
import { getFileAndOpen } from '@/web/core/dataset/utils';
|
||||
import { strIsLink } from '@fastgpt/global/common/string/tools';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
import type { SetOneDatasetDataProps } from '@/global/core/api/datasetReq';
|
||||
@@ -39,17 +39,18 @@ const InputDataModal = ({
|
||||
onDelete,
|
||||
datasetId,
|
||||
defaultValues = {
|
||||
datasetId: '',
|
||||
collectionId: '',
|
||||
sourceId: '',
|
||||
sourceName: ''
|
||||
}
|
||||
},
|
||||
canWrite
|
||||
}: {
|
||||
onClose: () => void;
|
||||
onSuccess: (data: SetOneDatasetDataProps) => void;
|
||||
onDelete?: () => void;
|
||||
datasetId: string;
|
||||
defaultValues: InputDataType;
|
||||
canWrite: boolean;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const { toast } = useToast();
|
||||
@@ -223,7 +224,7 @@ const InputDataModal = ({
|
||||
/>
|
||||
|
||||
<Box flex={1}>
|
||||
{defaultValues.id && onDelete && (
|
||||
{defaultValues.id && onDelete && canWrite && (
|
||||
<IconButton
|
||||
variant={'outline'}
|
||||
icon={<MyIcon name={'delete'} w={'16px'} h={'16px'} />}
|
||||
@@ -259,13 +260,16 @@ const InputDataModal = ({
|
||||
<Button variant={'base'} mr={3} isLoading={loading} onClick={onClose}>
|
||||
{t('common.Close')}
|
||||
</Button>
|
||||
<Button
|
||||
isLoading={loading}
|
||||
// @ts-ignore
|
||||
onClick={handleSubmit(defaultValues.id ? onUpdateData : sureImportData)}
|
||||
>
|
||||
{defaultValues.id ? '确认变更' : '确认导入'}
|
||||
</Button>
|
||||
<MyTooltip label={canWrite ? '' : t('dataset.data.Can not edit')}>
|
||||
<Button
|
||||
isDisabled={!canWrite}
|
||||
isLoading={loading}
|
||||
// @ts-ignore
|
||||
onClick={handleSubmit(defaultValues.id ? onUpdateData : sureImportData)}
|
||||
>
|
||||
{defaultValues.id ? '确认变更' : '确认导入'}
|
||||
</Button>
|
||||
</MyTooltip>
|
||||
</Box>
|
||||
</Flex>
|
||||
</Flex>
|
||||
@@ -325,7 +329,7 @@ export function RawSourceText({
|
||||
>
|
||||
<Image src={icon} alt="" w={'14px'} mr={2} />
|
||||
<Box maxW={['200px', '300px']} className={'textEllipsis'}>
|
||||
{sourceName || t('common.Unknow Source')}
|
||||
{sourceName || t('common.UnKnow Source')}
|
||||
</Box>
|
||||
</Box>
|
||||
</MyTooltip>
|
||||
|
@@ -206,7 +206,6 @@ const Test = ({ datasetId }: { datasetId: string }) => {
|
||||
|
||||
setEditInputData({
|
||||
id: data.id,
|
||||
datasetId: data.datasetId,
|
||||
collectionId: data.collectionId,
|
||||
q: data.q,
|
||||
a: data.a,
|
||||
@@ -256,7 +255,8 @@ const Test = ({ datasetId }: { datasetId: string }) => {
|
||||
|
||||
{!!editInputData && (
|
||||
<InputDataModal
|
||||
datasetId={editInputData.datasetId}
|
||||
datasetId={datasetDetail._id}
|
||||
canWrite={datasetDetail.canWrite}
|
||||
defaultValues={editInputData}
|
||||
onClose={() => setEditInputData(undefined)}
|
||||
onSuccess={(data) => {
|
||||
|
@@ -17,13 +17,14 @@ import Avatar from '@/components/Avatar';
|
||||
import Info from './components/Info';
|
||||
import { serviceSideProps } from '@/web/common/utils/i18n';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { getTrainingQueueLen, delDatasetEmptyFiles } from '@/web/core/dataset/api';
|
||||
import { getTrainingQueueLen } from '@/web/core/dataset/api';
|
||||
import MyTooltip from '@/components/MyTooltip';
|
||||
import { QuestionOutlineIcon } from '@chakra-ui/icons';
|
||||
import { feConfigs } from '@/web/common/system/staticData';
|
||||
import Script from 'next/script';
|
||||
import CollectionCard from './components/CollectionCard';
|
||||
import { useDatasetStore } from '@/web/core/dataset/store/dataset';
|
||||
import { useUserStore } from '@/web/support/user/useUserStore';
|
||||
|
||||
const DataCard = dynamic(() => import('./components/DataCard'), {
|
||||
ssr: false
|
||||
@@ -47,12 +48,15 @@ const Detail = ({ datasetId, currentTab }: { datasetId: string; currentTab: `${T
|
||||
const router = useRouter();
|
||||
const { isPc } = useSystemStore();
|
||||
const { datasetDetail, loadDatasetDetail } = useDatasetStore();
|
||||
const { userInfo } = useUserStore();
|
||||
|
||||
const tabList = useRef([
|
||||
const tabList = [
|
||||
{ label: '数据集', id: TabEnum.collectionCard, icon: 'overviewLight' },
|
||||
{ label: '搜索测试', id: TabEnum.test, icon: 'kbTest' },
|
||||
{ label: '配置', id: TabEnum.info, icon: 'settingLight' }
|
||||
]);
|
||||
...(userInfo?.team.canWrite && datasetDetail.isOwner
|
||||
? [{ label: '配置', id: TabEnum.info, icon: 'settingLight' }]
|
||||
: [])
|
||||
];
|
||||
|
||||
const setCurrentTab = useCallback(
|
||||
(tab: `${TabEnum}`) => {
|
||||
@@ -88,14 +92,6 @@ const Detail = ({ datasetId, currentTab }: { datasetId: string; currentTab: `${T
|
||||
refetchInterval: 10000
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
try {
|
||||
delDatasetEmptyFiles(datasetId);
|
||||
} catch (error) {}
|
||||
};
|
||||
}, [datasetId]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Script src="/js/pdf.js" strategy="lazyOnload"></Script>
|
||||
@@ -120,7 +116,7 @@ const Detail = ({ datasetId, currentTab }: { datasetId: string; currentTab: `${T
|
||||
mx={'auto'}
|
||||
mt={2}
|
||||
w={'100%'}
|
||||
list={tabList.current}
|
||||
list={tabList}
|
||||
activeId={currentTab}
|
||||
onChange={(e: any) => {
|
||||
setCurrentTab(e);
|
||||
@@ -169,7 +165,7 @@ const Detail = ({ datasetId, currentTab }: { datasetId: string; currentTab: `${T
|
||||
m={'auto'}
|
||||
w={'260px'}
|
||||
size={isPc ? 'md' : 'sm'}
|
||||
list={tabList.current.map((item) => ({
|
||||
list={tabList.map((item) => ({
|
||||
id: item.id,
|
||||
label: item.label
|
||||
}))}
|
||||
|
@@ -2,7 +2,7 @@ import React, { useCallback, useState, useRef } from 'react';
|
||||
import { Box, Flex, Button, ModalHeader, ModalFooter, ModalBody, Input } from '@chakra-ui/react';
|
||||
import { useSelectFile } from '@/web/common/file/hooks/useSelectFile';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { compressImg } from '@/web/common/file/utils';
|
||||
import { compressImgAndUpload } from '@/web/common/file/controller';
|
||||
import { getErrText } from '@fastgpt/global/common/error/utils';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { useRouter } from 'next/router';
|
||||
@@ -27,7 +27,7 @@ const CreateModal = ({ onClose, parentId }: { onClose: () => void; parentId?: st
|
||||
defaultValues: {
|
||||
avatar: '/icon/logo.svg',
|
||||
name: '',
|
||||
tags: [],
|
||||
tags: '',
|
||||
vectorModel: vectorModelList[0].model,
|
||||
type: 'dataset',
|
||||
parentId
|
||||
@@ -45,7 +45,7 @@ const CreateModal = ({ onClose, parentId }: { onClose: () => void; parentId?: st
|
||||
const file = e[0];
|
||||
if (!file) return;
|
||||
try {
|
||||
const src = await compressImg({
|
||||
const src = await compressImgAndUpload({
|
||||
file,
|
||||
maxW: 100,
|
||||
maxH: 100
|
||||
@@ -135,13 +135,14 @@ const CreateModal = ({ onClose, parentId }: { onClose: () => void; parentId?: st
|
||||
placeholder={'标签,使用空格分割。'}
|
||||
maxLength={30}
|
||||
onChange={(e) => {
|
||||
setValue('tags', e.target.value.split(' '));
|
||||
setValue('tags', e.target.value);
|
||||
setRefresh(!refresh);
|
||||
}}
|
||||
/>
|
||||
</Flex>
|
||||
<Flex mt={2} flexWrap={'wrap'}>
|
||||
{getValues('tags')
|
||||
.split(' ')
|
||||
.filter((item) => item)
|
||||
.map((item, i) => (
|
||||
<Tag mr={2} mb={2} key={i} whiteSpace={'nowrap'}>
|
||||
|
@@ -36,6 +36,10 @@ import { useEditTitle } from '@/web/common/hooks/useEditTitle';
|
||||
import { feConfigs } from '@/web/common/system/staticData';
|
||||
import EditFolderModal, { useEditFolder } from '../component/EditFolderModal';
|
||||
import { useDrag } from '@/web/common/hooks/useDrag';
|
||||
import { useUserStore } from '@/web/support/user/useUserStore';
|
||||
import { TeamMemberRoleEnum } from '@fastgpt/global/support/user/team/constant';
|
||||
import PermissionIconText from '@/components/support/permission/IconText';
|
||||
import { PermissionTypeEnum } from '@fastgpt/global/support/permission/constant';
|
||||
|
||||
const CreateModal = dynamic(() => import('./component/CreateModal'), { ssr: false });
|
||||
const MoveModal = dynamic(() => import('./component/MoveModal'), { ssr: false });
|
||||
@@ -46,6 +50,7 @@ const Kb = () => {
|
||||
const router = useRouter();
|
||||
const { parentId } = router.query as { parentId: string };
|
||||
const { setLoading } = useSystemStore();
|
||||
const { userInfo } = useUserStore();
|
||||
|
||||
const DeleteTipsMap = useRef({
|
||||
[DatasetTypeEnum.folder]: t('dataset.deleteFolderTips'),
|
||||
@@ -162,50 +167,51 @@ const Kb = () => {
|
||||
</Box>
|
||||
</Flex>
|
||||
)}
|
||||
|
||||
<MyMenu
|
||||
offset={[-30, 10]}
|
||||
width={120}
|
||||
Button={
|
||||
<MenuButton
|
||||
_hover={{
|
||||
color: 'myBlue.600'
|
||||
}}
|
||||
>
|
||||
<Flex
|
||||
alignItems={'center'}
|
||||
border={theme.borders.base}
|
||||
px={5}
|
||||
py={2}
|
||||
borderRadius={'md'}
|
||||
cursor={'pointer'}
|
||||
{userInfo?.team?.canWrite && (
|
||||
<MyMenu
|
||||
offset={[-30, 10]}
|
||||
width={120}
|
||||
Button={
|
||||
<MenuButton
|
||||
_hover={{
|
||||
color: 'myBlue.600'
|
||||
}}
|
||||
>
|
||||
<AddIcon mr={2} />
|
||||
<Box>{t('Create New')}</Box>
|
||||
</Flex>
|
||||
</MenuButton>
|
||||
}
|
||||
menuList={[
|
||||
{
|
||||
child: (
|
||||
<Flex>
|
||||
<Image src={FolderAvatarSrc} alt={''} w={'20px'} mr={1} />
|
||||
{t('Folder')}
|
||||
<Flex
|
||||
alignItems={'center'}
|
||||
border={theme.borders.base}
|
||||
px={5}
|
||||
py={2}
|
||||
borderRadius={'md'}
|
||||
cursor={'pointer'}
|
||||
>
|
||||
<AddIcon mr={2} />
|
||||
<Box>{t('Create New')}</Box>
|
||||
</Flex>
|
||||
),
|
||||
onClick: () => setEditFolderData({})
|
||||
},
|
||||
{
|
||||
child: (
|
||||
<Flex>
|
||||
<Image src={'/imgs/module/db.png'} alt={''} w={'20px'} mr={1} />
|
||||
{t('Dataset')}
|
||||
</Flex>
|
||||
),
|
||||
onClick: onOpenCreateModal
|
||||
</MenuButton>
|
||||
}
|
||||
]}
|
||||
/>
|
||||
menuList={[
|
||||
{
|
||||
child: (
|
||||
<Flex>
|
||||
<Image src={FolderAvatarSrc} alt={''} w={'20px'} mr={1} />
|
||||
{t('Folder')}
|
||||
</Flex>
|
||||
),
|
||||
onClick: () => setEditFolderData({})
|
||||
},
|
||||
{
|
||||
child: (
|
||||
<Flex>
|
||||
<Image src={'/imgs/module/db.png'} alt={''} w={'20px'} mr={1} />
|
||||
{t('Dataset')}
|
||||
</Flex>
|
||||
),
|
||||
onClick: onOpenCreateModal
|
||||
}
|
||||
]}
|
||||
/>
|
||||
)}
|
||||
</Flex>
|
||||
<Grid
|
||||
p={5}
|
||||
@@ -279,91 +285,126 @@ const Kb = () => {
|
||||
}
|
||||
}}
|
||||
>
|
||||
<MyMenu
|
||||
offset={[-30, 10]}
|
||||
width={120}
|
||||
Button={
|
||||
<MenuButton
|
||||
position={'absolute'}
|
||||
top={3}
|
||||
right={3}
|
||||
w={'22px'}
|
||||
h={'22px'}
|
||||
borderRadius={'md'}
|
||||
_hover={{
|
||||
color: 'myBlue.600',
|
||||
'& .icon': {
|
||||
bg: 'myGray.100'
|
||||
}
|
||||
}}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
}}
|
||||
>
|
||||
<MyIcon
|
||||
className="icon"
|
||||
name={'more'}
|
||||
h={'16px'}
|
||||
w={'16px'}
|
||||
px={1}
|
||||
py={1}
|
||||
{userInfo?.team.canWrite && dataset.isOwner && (
|
||||
<MyMenu
|
||||
offset={[-30, 10]}
|
||||
width={120}
|
||||
Button={
|
||||
<MenuButton
|
||||
position={'absolute'}
|
||||
top={3}
|
||||
right={3}
|
||||
w={'22px'}
|
||||
h={'22px'}
|
||||
borderRadius={'md'}
|
||||
cursor={'pointer'}
|
||||
/>
|
||||
</MenuButton>
|
||||
}
|
||||
menuList={[
|
||||
{
|
||||
child: (
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'edit'} w={'14px'} mr={2} />
|
||||
{t('Rename')}
|
||||
</Flex>
|
||||
),
|
||||
onClick: () =>
|
||||
onOpenTitleModal({
|
||||
defaultVal: dataset.name,
|
||||
onSuccess: (val) => {
|
||||
if (val === dataset.name || !val) return;
|
||||
updateDataset({ id: dataset._id, name: val });
|
||||
_hover={{
|
||||
color: 'myBlue.600',
|
||||
'& .icon': {
|
||||
bg: 'myGray.100'
|
||||
}
|
||||
})
|
||||
},
|
||||
{
|
||||
child: (
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'moveLight'} w={'14px'} mr={2} />
|
||||
{t('Move')}
|
||||
</Flex>
|
||||
),
|
||||
onClick: () => setMoveDataId(dataset._id)
|
||||
},
|
||||
{
|
||||
child: (
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'export'} w={'14px'} mr={2} />
|
||||
{t('Export')}
|
||||
</Flex>
|
||||
),
|
||||
onClick: () => onclickExport(dataset._id)
|
||||
},
|
||||
{
|
||||
child: (
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'delete'} w={'14px'} mr={2} />
|
||||
{t('common.Delete')}
|
||||
</Flex>
|
||||
),
|
||||
onClick: () => {
|
||||
openConfirm(
|
||||
() => onclickDelDataset(dataset._id),
|
||||
undefined,
|
||||
DeleteTipsMap.current[dataset.type]
|
||||
)();
|
||||
}
|
||||
}}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
}}
|
||||
>
|
||||
<MyIcon
|
||||
className="icon"
|
||||
name={'more'}
|
||||
h={'16px'}
|
||||
w={'16px'}
|
||||
px={1}
|
||||
py={1}
|
||||
borderRadius={'md'}
|
||||
cursor={'pointer'}
|
||||
/>
|
||||
</MenuButton>
|
||||
}
|
||||
]}
|
||||
/>
|
||||
menuList={[
|
||||
...(dataset.permission === PermissionTypeEnum.private
|
||||
? [
|
||||
{
|
||||
child: (
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'support/permission/publicLight'} w={'14px'} mr={2} />
|
||||
{t('permission.Set Public')}
|
||||
</Flex>
|
||||
),
|
||||
onClick: () => {
|
||||
updateDataset({
|
||||
id: dataset._id,
|
||||
permission: PermissionTypeEnum.public
|
||||
});
|
||||
}
|
||||
}
|
||||
]
|
||||
: [
|
||||
{
|
||||
child: (
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'support/permission/privateLight'} w={'14px'} mr={2} />
|
||||
{t('permission.Set Private')}
|
||||
</Flex>
|
||||
),
|
||||
onClick: () => {
|
||||
updateDataset({
|
||||
id: dataset._id,
|
||||
permission: PermissionTypeEnum.private
|
||||
});
|
||||
}
|
||||
}
|
||||
]),
|
||||
{
|
||||
child: (
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'edit'} w={'14px'} mr={2} />
|
||||
{t('Rename')}
|
||||
</Flex>
|
||||
),
|
||||
onClick: () =>
|
||||
onOpenTitleModal({
|
||||
defaultVal: dataset.name,
|
||||
onSuccess: (val) => {
|
||||
if (val === dataset.name || !val) return;
|
||||
updateDataset({ id: dataset._id, name: val });
|
||||
}
|
||||
})
|
||||
},
|
||||
{
|
||||
child: (
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'moveLight'} w={'14px'} mr={2} />
|
||||
{t('Move')}
|
||||
</Flex>
|
||||
),
|
||||
onClick: () => setMoveDataId(dataset._id)
|
||||
},
|
||||
{
|
||||
child: (
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'export'} w={'14px'} mr={2} />
|
||||
{t('Export')}
|
||||
</Flex>
|
||||
),
|
||||
onClick: () => onclickExport(dataset._id)
|
||||
},
|
||||
{
|
||||
child: (
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'delete'} w={'14px'} mr={2} />
|
||||
{t('common.Delete')}
|
||||
</Flex>
|
||||
),
|
||||
onClick: () => {
|
||||
openConfirm(
|
||||
() => onclickDelDataset(dataset._id),
|
||||
undefined,
|
||||
DeleteTipsMap.current[dataset.type]
|
||||
)();
|
||||
}
|
||||
}
|
||||
]}
|
||||
/>
|
||||
)}
|
||||
<Flex alignItems={'center'} h={'38px'}>
|
||||
<Avatar src={dataset.avatar} borderRadius={'lg'} w={'28px'} />
|
||||
<Box mx={3} className="textEllipsis3">
|
||||
@@ -372,14 +413,20 @@ const Kb = () => {
|
||||
</Flex>
|
||||
<Box flex={'1 0 0'} overflow={'hidden'} pt={2}>
|
||||
<Flex>
|
||||
{dataset.tags.map((tag, i) => (
|
||||
<Tag key={i} mr={2} mb={2}>
|
||||
{tag}
|
||||
</Tag>
|
||||
))}
|
||||
{dataset.tags
|
||||
.split(' ')
|
||||
.filter((item) => item)
|
||||
.map((tag, i) => (
|
||||
<Tag key={i} mr={2} mb={2}>
|
||||
{tag}
|
||||
</Tag>
|
||||
))}
|
||||
</Flex>
|
||||
</Box>
|
||||
<Flex justifyContent={'flex-end'} alignItems={'center'} fontSize={'sm'}>
|
||||
<Flex alignItems={'center'} fontSize={'sm'}>
|
||||
<Box flex={1}>
|
||||
<PermissionIconText permission={dataset.permission} color={'myGray.600'} />
|
||||
</Box>
|
||||
{dataset.type === DatasetTypeEnum.folder ? (
|
||||
<Box color={'myGray.500'}>{t('Folder')}</Box>
|
||||
) : (
|
||||
@@ -419,7 +466,7 @@ const Kb = () => {
|
||||
name,
|
||||
type: DatasetTypeEnum.folder,
|
||||
avatar: FolderAvatarSrc,
|
||||
tags: []
|
||||
tags: ''
|
||||
});
|
||||
}
|
||||
refetch();
|
||||
|
Reference in New Issue
Block a user