4.8.6 merge (#1943)

* Dataset collection forbid (#1885)

* perf: tool call support same id

* feat: collection forbid

* feat: collection forbid

* Inheritance Permission for apps (#1897)

* feat: app schema define

chore: references of authapp

* feat: authApp method inheritance

* feat: create and update api

* feat: update

* feat: inheritance Permission controller for app.

* feat: abstract version of inheritPermission

* feat: ancestorId for apps

* chore: update app

* fix: inheritPermission abstract version

* feat: update folder defaultPermission

* feat: app update api

* chore: inheritance frontend

* chore: app list api

* feat: update defaultPermission in app deatil

* feat: backend api finished

* feat: app inheritance permission fe

* fix: app update defaultpermission causes collaborator miss

* fix: ts error

* chore: adjust the codes

* chore: i18n

chore: i18n

* chore: fe adjust and i18n

* chore: adjust the code

* feat: resume api;
chore: rewrite update api and inheritPermission methods

* chore: something

* chore: fe code adjusting

* feat: frontend adjusting

* chore: fe code adjusting

* chore: adjusting the code

* perf: fe loading

* format

* Inheritance fix (#1908)

* fix: SlideCard

* fix: authapp did not return parent app for inheritance app

* fix: fe adjusting

* feat: fe adjusing

* perf: inherit per ux

* doc

* fix: ts errors (#1916)

* perf: inherit permission

* fix: permission inherit

* Workflow type (#1938)

* perf: workflow type

tmp workflow

perf: workflow type

feat: custom field config

* perf: dynamic input

* perf: node classify

* perf: node classify

* perf: node classify

* perf: node classify

* fix: workflow custom input

* feat: text editor and customFeedback move to basic nodes

* feat: community system plugin

* fix: ts

* feat: exprEval plugin

* perf: workflow type

* perf: plugin important

* fix: default templates

* perf: markdown hr css

* lock

* perf: fetch url

* perf: new plugin version

* fix: chat histories update

* fix: collection paths invalid

* perf: app card ui

---------

Co-authored-by: Finley Ge <32237950+FinleyGe@users.noreply.github.com>
This commit is contained in:
Archer
2024-07-04 17:42:09 +08:00
committed by GitHub
parent babf03c218
commit a9cdece341
303 changed files with 18883 additions and 13149 deletions

View File

@@ -9,7 +9,8 @@ import {
Th,
Td,
Tbody,
MenuButton
MenuButton,
Switch
} from '@chakra-ui/react';
import {
delDatasetCollectionById,
@@ -20,8 +21,7 @@ import { useQuery } from '@tanstack/react-query';
import { useConfirm } from '@fastgpt/web/hooks/useConfirm';
import { useTranslation } from 'next-i18next';
import MyIcon from '@fastgpt/web/components/common/Icon';
import dayjs from 'dayjs';
import { useRequest } from '@fastgpt/web/hooks/useRequest';
import { useRequest, useRequest2 } from '@fastgpt/web/hooks/useRequest';
import { useRouter } from 'next/router';
import MyMenu from '@fastgpt/web/components/common/MyMenu';
import { useEditTitle } from '@/web/common/hooks/useEditTitle';
@@ -33,7 +33,6 @@ import {
import { getCollectionIcon } from '@fastgpt/global/core/dataset/utils';
import { TabEnum } from '../../index';
import dynamic from 'next/dynamic';
import { useDrag } from '@/web/common/hooks/useDrag';
import SelectCollections from '@/web/core/dataset/components/SelectCollections';
import { useToast } from '@fastgpt/web/hooks/useToast';
import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
@@ -42,6 +41,14 @@ import MyBox from '@fastgpt/web/components/common/MyBox';
import { useContextSelector } from 'use-context-selector';
import { CollectionPageContext } from './Context';
import { DatasetPageContext } from '@/web/core/dataset/context/datasetPageContext';
import { useI18n } from '@/web/context/I18n';
import { formatTime2YMDHM } from '@fastgpt/global/common/string/time';
import MyTag from '@fastgpt/web/components/common/Tag/index';
import {
checkCollectionIsFolder,
getTrainingTypeLabel
} from '@fastgpt/global/core/dataset/collection/utils';
import { useFolderDrag } from '@/components/common/folder/useFolderDrag';
const Header = dynamic(() => import('./Header'));
const EmptyCollectionTip = dynamic(() => import('./EmptyCollectionTip'));
@@ -51,6 +58,7 @@ const CollectionCard = () => {
const router = useRouter();
const { toast } = useToast();
const { t } = useTranslation();
const { datasetT } = useI18n();
const { datasetDetail, loadDatasetDetail } = useContextSelector(DatasetPageContext, (v) => v);
const { openConfirm: openDeleteConfirm, ConfirmModal: ConfirmDeleteModal } = useConfirm({
@@ -70,8 +78,6 @@ const CollectionCard = () => {
const { collections, Pagination, total, getData, isGetting, pageNum, pageSize } =
useContextSelector(CollectionPageContext, (v) => v);
const { dragStartId, setDragStartId, dragTargetId, setDragTargetId } = useDrag();
// Ad file status icon
const formatCollections = useMemo(
() =>
@@ -83,16 +89,12 @@ const CollectionCard = () => {
statusText: t('dataset.collections.Collection Embedding', {
total: collection.trainingAmount
}),
color: 'myGray.600',
bg: 'myGray.50',
borderColor: 'borderColor.low'
colorSchema: 'gray'
};
}
return {
statusText: t('core.dataset.collection.status.active'),
color: 'green.600',
bg: 'green.50',
borderColor: 'green.300'
colorSchema: 'green'
};
})();
@@ -105,20 +107,15 @@ const CollectionCard = () => {
[collections, t]
);
const { mutate: onUpdateCollectionName } = useRequest({
mutationFn: ({ collectionId, name }: { collectionId: string; name: string }) => {
return putDatasetCollectionById({
id: collectionId,
name
});
},
onSuccess() {
getData(pageNum);
},
successToast: t('common.Rename Success'),
errorToast: t('common.Rename Failed')
});
const { runAsync: onUpdateCollection, loading: isUpdating } = useRequest2(
putDatasetCollectionById,
{
onSuccess() {
getData(pageNum);
},
successToast: t('common.Update Success')
}
);
const { mutate: onDelCollection, isLoading: isDeleting } = useRequest({
mutationFn: (collectionId: string) => {
return delDatasetCollectionById({
@@ -150,10 +147,6 @@ const CollectionCard = () => {
() => !!formatCollections.find((item) => item.trainingAmount > 0),
[formatCollections]
);
const isLoading = useMemo(
() => isDeleting || isSyncing || (isGetting && collections.length === 0),
[collections.length, isDeleting, isGetting, isSyncing]
);
useQuery(
['refreshCollection'],
@@ -170,6 +163,24 @@ const CollectionCard = () => {
}
);
const { getBoxProps, isDropping } = useFolderDrag({
activeStyles: {
bg: 'primary.100'
},
onDrop: async (dragId: string, targetId: string) => {
try {
await putDatasetCollectionById({
id: dragId,
parentId: targetId
});
getData(pageNum);
} catch (error) {}
}
});
const isLoading =
isUpdating || isDeleting || isSyncing || (isGetting && collections.length === 0) || isDropping;
return (
<MyBox isLoading={isLoading} h={'100%'} py={[2, 4]}>
<Flex ref={BoxRef} flexDirection={'column'} py={[1, 3]} h={'100%'}>
@@ -177,75 +188,41 @@ const CollectionCard = () => {
<Header />
{/* collection table */}
<TableContainer
px={[2, 6]}
mt={[0, 3]}
position={'relative'}
flex={'1 0 0'}
overflowY={'auto'}
fontSize={'sm'}
>
<TableContainer px={[2, 6]} mt={[0, 3]} flex={'1 0 0'} overflowY={'auto'} fontSize={'sm'}>
<Table variant={'simple'} draggable={false}>
<Thead draggable={false}>
<Tr>
<Th py={4}>#</Th>
<Th py={4}>{t('common.Name')}</Th>
<Th py={4}>{datasetT('collection.Training type')}</Th>
<Th py={4}>{t('dataset.collections.Data Amount')}</Th>
<Th py={4}>{t('core.dataset.Sync Time')}</Th>
<Th py={4}>{datasetT('collection.Create update time')}</Th>
<Th py={4}>{t('common.Status')}</Th>
<Th py={4}>{datasetT('Enable')}</Th>
<Th py={4} />
</Tr>
</Thead>
<Tbody>
<Tr h={'10px'} />
{formatCollections.map((collection, index) => (
<Tr h={'5px'} />
{formatCollections.map((collection) => (
<Tr
key={collection._id}
_hover={{ bg: 'myGray.50' }}
cursor={'pointer'}
data-drag-id={
collection.type === DatasetCollectionTypeEnum.folder
? collection._id
: undefined
}
bg={dragTargetId === collection._id ? 'primary.100' : ''}
userSelect={'none'}
onDragStart={() => {
setDragStartId(collection._id);
}}
onDragOver={(e) => {
e.preventDefault();
const targetId = e.currentTarget.getAttribute('data-drag-id');
if (!targetId) return;
DatasetCollectionTypeEnum.folder && setDragTargetId(targetId);
}}
onDragLeave={(e) => {
e.preventDefault();
setDragTargetId(undefined);
}}
onDrop={async (e) => {
e.preventDefault();
if (!dragTargetId || !dragStartId || dragTargetId === dragStartId) return;
// update parentId
try {
await putDatasetCollectionById({
id: dragStartId,
parentId: dragTargetId
});
getData(pageNum);
} catch (error) {}
setDragTargetId(undefined);
}}
{...getBoxProps({
dataId: collection._id,
isFolder: collection.type === DatasetCollectionTypeEnum.folder
})}
draggable={false}
onClick={() => {
if (collection.type === DatasetCollectionTypeEnum.folder) {
router.replace({
router.push({
query: {
...router.query,
parentId: collection._id
}
});
} else {
router.replace({
router.push({
query: {
...router.query,
collectionId: collection._id,
@@ -255,8 +232,7 @@ const CollectionCard = () => {
}
}}
>
<Td w={'50px'}>{index + 1}</Td>
<Td minW={'150px'} maxW={['200px', '300px']} draggable>
<Td minW={'150px'} maxW={['200px', '300px']} draggable py={2}>
<Flex alignItems={'center'}>
<MyIcon name={collection.icon as any} w={'16px'} mr={2} />
<MyTooltip label={t('common.folder.Drag Tip')} shouldWrapChildren={false}>
@@ -266,33 +242,36 @@ const CollectionCard = () => {
</MyTooltip>
</Flex>
</Td>
<Td>{collection.dataAmount || '-'}</Td>
<Td>{dayjs(collection.updateTime).format('YYYY/MM/DD HH:mm')}</Td>
<Td>
<Box
display={'inline-flex'}
alignItems={'center'}
w={'auto'}
color={collection.color}
bg={collection.bg}
borderWidth={'1px'}
borderColor={collection.borderColor}
px={3}
py={1}
borderRadius={'md'}
_before={{
content: '""',
w: '6px',
h: '6px',
mr: 2,
borderRadius: 'lg',
bg: collection.color
}}
>
{t(collection.statusText)}
</Box>
<Td py={2}>
{!checkCollectionIsFolder(collection.type) ? (
<>{t(getTrainingTypeLabel(collection.trainingType) || '-')}</>
) : (
'-'
)}
</Td>
<Td onClick={(e) => e.stopPropagation()}>
<Td py={2}>{collection.dataAmount || '-'}</Td>
<Td fontSize={'xs'} py={2} color={'myGray.500'}>
<Box>{formatTime2YMDHM(collection.createTime)}</Box>
<Box>{formatTime2YMDHM(collection.updateTime)}</Box>
</Td>
<Td py={2}>
<MyTag showDot colorSchema={collection.colorSchema as any} type={'borderFill'}>
{t(collection.statusText)}
</MyTag>
</Td>
<Td py={2} onClick={(e) => e.stopPropagation()}>
<Switch
isChecked={!collection.forbid}
size={'sm'}
onChange={(e) =>
onUpdateCollection({
id: collection._id,
forbid: !e.target.checked
})
}
/>
</Td>
<Td py={2} onClick={(e) => e.stopPropagation()}>
{collection.permission.hasWritePer && (
<MyMenu
width={100}
@@ -360,12 +339,11 @@ const CollectionCard = () => {
onClick: () =>
onOpenEditTitleModal({
defaultVal: collection.name,
onSuccess: (newName) => {
onUpdateCollectionName({
collectionId: collection._id,
onSuccess: (newName) =>
onUpdateCollection({
id: collection._id,
name: newName
});
}
})
})
}
]