This commit is contained in:
Archer
2024-06-12 15:17:21 +08:00
committed by GitHub
parent bc6864c3dc
commit d0085a23e6
61 changed files with 558 additions and 348 deletions

View File

@@ -8,13 +8,13 @@ import { useTranslation } from 'next-i18next';
import { useConfirm } from '@fastgpt/web/hooks/useConfirm';
import { PermissionValueType } from '@fastgpt/global/support/permission/type';
import DefaultPermissionList from '@/components/support/permission/DefaultPerList';
import {
CollaboratorContextProvider,
import CollaboratorContextProvider, {
MemberManagerInputPropsType
} from '../../support/permission/MemberManager/context';
import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
const FolderSlideCard = ({
refreshDeps,
name,
intro,
onEdit,
@@ -25,6 +25,7 @@ const FolderSlideCard = ({
defaultPer,
managePer
}: {
refreshDeps?: any[];
name: string;
intro?: string;
onEdit: () => void;
@@ -86,22 +87,24 @@ const FolderSlideCard = ({
>
{t('common.Move')}
</Button>
<Button
variant={'transparentDanger'}
pl={1}
leftIcon={<MyIcon name={'delete'} w={'1rem'} />}
transform={'none !important'}
w={'100%'}
justifyContent={'flex-start'}
size={'sm'}
fontSize={'mini'}
mt={3}
onClick={() => {
openConfirm(onDelete)();
}}
>
{t('common.Delete folder')}
</Button>
{managePer.permission.isOwner && (
<Button
variant={'transparentDanger'}
pl={1}
leftIcon={<MyIcon name={'delete'} w={'1rem'} />}
transform={'none !important'}
w={'100%'}
justifyContent={'flex-start'}
size={'sm'}
fontSize={'mini'}
mt={3}
onClick={() => {
openConfirm(onDelete)();
}}
>
{t('common.Delete folder')}
</Button>
)}
</Box>
</>
)}
@@ -125,7 +128,7 @@ const FolderSlideCard = ({
</Box>
)}
<Box mt={6}>
<CollaboratorContextProvider {...managePer}>
<CollaboratorContextProvider {...managePer} refreshDeps={refreshDeps}>
{({ MemberListCard, onOpenManageModal, onOpenAddMember }) => {
return (
<>

View File

@@ -2,7 +2,7 @@ import React from 'react';
import MyModal from '@fastgpt/web/components/common/MyModal';
import { useTranslation } from 'next-i18next';
import { PermissionValueType } from '@fastgpt/global/support/permission/type';
import { MemberManagerInputPropsType, CollaboratorContextProvider } from '../MemberManager/context';
import CollaboratorContextProvider, { MemberManagerInputPropsType } from '../MemberManager/context';
import { Box, Button, Flex, HStack, ModalBody } from '@chakra-ui/react';
import Avatar from '@/components/Avatar';
import DefaultPermissionList from '../DefaultPerList';

View File

@@ -20,8 +20,11 @@ const PermissionIconText = ({
const per = useMemo(() => {
if (permission) return permission;
if (defaultPermission) {
return new Permission({ per: defaultPermission }).hasReadPer ? 'public' : 'private';
if (defaultPermission !== undefined) {
const Per = new Permission({ per: defaultPermission });
if (Per.hasWritePer) return PermissionTypeEnum.publicWrite;
if (Per.hasReadPer) return PermissionTypeEnum.publicRead;
return PermissionTypeEnum.clbPrivate;
}
return 'private';
}, [defaultPermission, permission]);

View File

@@ -26,12 +26,14 @@ import MyBox from '@fastgpt/web/components/common/MyBox';
import { ChevronDownIcon } from '@chakra-ui/icons';
import Avatar from '@/components/Avatar';
import { useRequest } from '@fastgpt/web/hooks/useRequest';
import { useTranslation } from 'next-i18next';
export type AddModalPropsType = {
onClose: () => void;
};
function AddMemberModal({ onClose }: AddModalPropsType) {
const { t } = useTranslation();
const { userInfo } = useUserStore();
const { permissionList, collaboratorList, onUpdateCollaborators, getPerLabelList } =
@@ -63,9 +65,12 @@ function AddMemberModal({ onClose }: AddModalPropsType) {
const { mutate: onConfirm, isLoading: isUpdating } = useRequest({
mutationFn: () => {
return onUpdateCollaborators(selectedMemberIdList, selectedPermission);
return onUpdateCollaborators({
tmbIds: selectedMemberIdList,
permission: selectedPermission
});
},
successToast: '添加成功',
successToast: t('common.Add Success'),
errorToast: 'Error',
onSuccess() {
onClose();

View File

@@ -39,7 +39,10 @@ function ManageModal({ onClose }: ManageModalProps) {
const { mutate: onUpdate, isLoading: isUpdating } = useRequest({
mutationFn: ({ tmbId, per }: { tmbId: string; per: PermissionValueType }) => {
return onUpdateCollaborators([tmbId], per);
return onUpdateCollaborators({
tmbIds: [tmbId],
permission: per
});
},
successToast: '更新成功',
errorToast: 'Error'

View File

@@ -6,7 +6,8 @@ import {
MenuList,
Box,
Radio,
useOutsideClick
useOutsideClick,
HStack
} from '@chakra-ui/react';
import React, { useMemo, useRef, useState } from 'react';
import MyIcon from '@fastgpt/web/components/common/Icon';
@@ -142,9 +143,15 @@ function PermissionSelect({
bottom={0}
left={0}
/>
<Box position={'relative'} cursor={'pointer'} userSelect={'none'}>
<Flex
alignItems={'center'}
justifyContent={'center'}
position={'relative'}
cursor={'pointer'}
userSelect={'none'}
>
{Button}
</Box>
</Flex>
</Box>
<MenuList
minW={isOpen ? `${width}px !important` : 0}
@@ -182,7 +189,7 @@ function PermissionSelect({
<Box ml={4}>
<Box>{item.name}</Box>
<Box color={'myGray.500'} fontSize={'mini'}>
{item.description}
{t(item.description)}
</Box>
</Box>
</Flex>
@@ -236,7 +243,7 @@ function PermissionSelect({
{onDelete && (
<>
<MyDivider my={2} h={'2px'} borderColor={'myGray.200'} />
<Flex
<HStack
{...MenuStyle}
onClick={() => {
onDelete();
@@ -244,8 +251,8 @@ function PermissionSelect({
}}
>
<MyIcon name="delete" w="20px" color="red.600" />
<Box color="red.600">{t('common.Delete')}</Box>
</Flex>
<Box color="red.600">{t('common.Remove')}</Box>
</HStack>
</>
)}
</MenuList>

View File

@@ -1,5 +1,8 @@
import { BoxProps, useDisclosure } from '@chakra-ui/react';
import { CollaboratorItemType } from '@fastgpt/global/support/permission/collaborator';
import {
CollaboratorItemType,
UpdateClbPermissionProps
} from '@fastgpt/global/support/permission/collaborator';
import { PermissionList } from '@fastgpt/global/support/permission/constant';
import { Permission } from '@fastgpt/global/support/permission/controller';
import { PermissionListType, PermissionValueType } from '@fastgpt/global/support/permission/type';
@@ -9,6 +12,7 @@ import { createContext } from 'use-context-selector';
import dynamic from 'next/dynamic';
import MemberListCard, { MemberListCardProps } from './MemberListCard';
import { useRequest2 } from '@fastgpt/web/hooks/useRequest';
const AddMemberModal = dynamic(() => import('./AddMemberModal'));
const ManageModal = dynamic(() => import('./ManageModal'));
@@ -16,8 +20,9 @@ export type MemberManagerInputPropsType = {
permission: Permission;
onGetCollaboratorList: () => Promise<CollaboratorItemType[]>;
permissionList: PermissionListType;
onUpdateCollaborators: (tmbIds: string[], permission: PermissionValueType) => any;
onUpdateCollaborators: (props: UpdateClbPermissionProps) => any;
onDelOneCollaborator: (tmbId: string) => any;
refreshDeps?: any[];
};
export type MemberManagerPropsType = MemberManagerInputPropsType & {
collaboratorList: CollaboratorItemType[];
@@ -55,24 +60,28 @@ export const CollaboratorContext = createContext<CollaboratorContextType>({
permission: new Permission()
});
export const CollaboratorContextProvider = ({
const CollaboratorContextProvider = ({
permission,
onGetCollaboratorList,
permissionList,
onUpdateCollaborators,
onDelOneCollaborator,
refreshDeps = [],
children
}: MemberManagerInputPropsType & {
children: (props: ChildrenProps) => ReactNode;
}) => {
const {
data: collaboratorList = [],
refetch: refetchCollaboratorList,
isLoading: isFetchingCollaborator
} = useQuery(['collaboratorList'], onGetCollaboratorList);
runAsync: refetchCollaboratorList,
loading: isFetchingCollaborator
} = useRequest2(onGetCollaboratorList, {
manual: false,
refreshDeps
});
const onUpdateCollaboratorsThen = async (tmbIds: string[], permission: PermissionValueType) => {
await onUpdateCollaborators(tmbIds, permission);
const onUpdateCollaboratorsThen = async (props: UpdateClbPermissionProps) => {
await onUpdateCollaborators(props);
refetchCollaboratorList();
};
const onDelOneCollaboratorThen = async (tmbId: string) => {
@@ -136,3 +145,5 @@ export const CollaboratorContextProvider = ({
</CollaboratorContext.Provider>
);
};
export default CollaboratorContextProvider;

View File

@@ -0,0 +1,66 @@
import React, { useMemo } from 'react';
import { Permission } from '@fastgpt/global/support/permission/controller';
import { PermissionListType } from '@fastgpt/global/support/permission/type';
import { PermissionList } from '@fastgpt/global/support/permission/constant';
import MyTag from '@fastgpt/web/components/common/Tag/index';
import { HStack } from '@chakra-ui/react';
import { useTranslation } from 'next-i18next';
const PermissionTag = ({
permission,
permissionList
}: {
permission: Permission;
permissionList: PermissionListType;
}) => {
const { t } = useTranslation();
const { commonLabel, otherLabels } = useMemo(() => {
const Per = new Permission({ per: permission.value });
const commonLabel = (() => {
if (permission.isOwner) return t('permission.Owner');
if (permission.hasManagePer) return PermissionList['manage'].name;
if (permission.hasWritePer) return PermissionList['write'].name;
if (permission.hasReadPer) return PermissionList['read'].name;
return;
})();
const otherLabels: string[] = [];
Object.values(permissionList).forEach((item) => {
if (item.checkBoxType === 'multiple') {
if (Per.checkPer(item.value)) {
otherLabels.push(item.name);
}
}
});
return {
commonLabel,
otherLabels
};
}, [
permission.hasManagePer,
permission.hasReadPer,
permission.hasWritePer,
permission.value,
permissionList
]);
return (
<HStack>
{commonLabel && (
<MyTag type="fill" colorSchema="blue">
{commonLabel}
</MyTag>
)}
{otherLabels.map((tag, i) => (
<MyTag key={i} type="fill" colorSchema="purple">
{tag}
</MyTag>
))}
</HStack>
);
};
export default PermissionTag;

View File

@@ -3,12 +3,18 @@ import MyModal from '@fastgpt/web/components/common/MyModal';
import { useTranslation } from 'next-i18next';
import { ModalCloseButton, ModalBody, Box, ModalFooter, Button } from '@chakra-ui/react';
import TagTextarea from '@/components/common/Textarea/TagTextarea';
import { TeamMemberRoleEnum } from '@fastgpt/global/support/user/team/constant';
import { useRequest } from '@fastgpt/web/hooks/useRequest';
import { postInviteTeamMember } from '@/web/support/user/team/api';
import { useConfirm } from '@fastgpt/web/hooks/useConfirm';
import type { InviteMemberResponse } from '@fastgpt/global/support/user/team/controller.d';
import MySelect from '@fastgpt/web/components/common/MySelect';
import {
ManagePermissionVal,
ReadPermissionVal,
WritePermissionVal
} from '@fastgpt/global/support/permission/constant';
import { useI18n } from '@/web/context/I18n';
import { useUserStore } from '@/web/support/user/useUserStore';
const InviteModal = ({
teamId,
@@ -20,25 +26,37 @@ const InviteModal = ({
onSuccess: () => void;
}) => {
const { t } = useTranslation();
const { userT } = useI18n();
const { ConfirmModal, openConfirm } = useConfirm({
title: t('user.team.Invite Member Result Tip'),
showCancel: false
});
const { userInfo } = useUserStore();
const [inviteUsernames, setInviteUsernames] = useState<string[]>([]);
const inviteTypes = useMemo(
() => [
{
alias: t('user.team.Invite Role Visitor Alias'),
label: t('user.team.Invite Role Visitor Tip'),
value: TeamMemberRoleEnum.visitor
label: userT('permission.Read'),
description: userT('permission.Read desc'),
value: ReadPermissionVal
},
{
alias: t('user.team.Invite Role Admin Alias'),
label: t('user.team.Invite Role Admin Tip'),
value: TeamMemberRoleEnum.admin
}
label: userT('permission.Write'),
description: userT('permission.Write tip'),
value: WritePermissionVal
},
...(userInfo?.team?.permission.isOwner
? [
{
label: userT('permission.Manage'),
description: userT('permission.Manage tip'),
value: ManagePermissionVal
}
]
: [])
],
[t]
[userInfo?.team?.permission.isOwner, userT]
);
const [selectedInviteType, setSelectInviteType] = useState(inviteTypes[0].value);
@@ -47,7 +65,7 @@ const InviteModal = ({
return postInviteTeamMember({
teamId,
usernames: inviteUsernames,
role: selectedInviteType
permission: selectedInviteType
});
},
onSuccess(res: InviteMemberResponse) {

View File

@@ -1,47 +1,51 @@
import Avatar from '@/components/Avatar';
import MyIcon from '@fastgpt/web/components/common/Icon';
import { Box, MenuButton, Table, TableContainer, Tbody, Td, Th, Thead, Tr } from '@chakra-ui/react';
import {
Box,
HStack,
MenuButton,
Table,
TableContainer,
Tbody,
Td,
Th,
Thead,
Tr
} from '@chakra-ui/react';
import {
TeamMemberRoleEnum,
TeamMemberRoleMap,
TeamMemberStatusMap
} from '@fastgpt/global/support/user/team/constant';
import MyMenu from '@fastgpt/web/components/common/MyMenu';
import { useTranslation } from 'next-i18next';
import { useContextSelector } from 'use-context-selector';
import { useUserStore } from '@/web/support/user/useUserStore';
import { TeamModalContext } from '../context';
import { useRequest } from '@fastgpt/web/hooks/useRequest';
import { delRemoveMember } from '@/web/support/user/team/api';
import { useConfirm } from '@fastgpt/web/hooks/useConfirm';
import MyBox from '@fastgpt/web/components/common/MyBox';
import PermissionTags from '@/components/support/permission/PermissionTags';
import { TeamPermissionList } from '@fastgpt/global/support/permission/user/constant';
import PermissionSelect from '@/components/support/permission/MemberManager/PermissionSelect';
import { CollaboratorContext } from '@/components/support/permission/MemberManager/context';
import { delRemoveMember } from '@/web/support/user/team/api';
function MemberTable() {
const { userInfo } = useUserStore();
const { t } = useTranslation();
const { members, refetchMembers } = useContextSelector(TeamModalContext, (v) => v);
const { onUpdateCollaborators } = useContextSelector(CollaboratorContext, (v) => v);
const { ConfirmModal: ConfirmRemoveMemberModal, openConfirm: openRemoveMember } = useConfirm({
type: 'delete'
});
const { mutate: onRemoveMember, isLoading: isRemovingMember } = useRequest({
mutationFn: delRemoveMember,
onSuccess() {
refetchMembers();
},
successToast: t('user.team.Remove Member Success'),
errorToast: t('user.team.Remove Member Failed')
});
return (
<MyBox isLoading={isRemovingMember}>
<MyBox>
<TableContainer overflow={'unset'} fontSize={'sm'}>
<Table overflow={'unset'}>
<Thead bg={'myWhite.400'}>
<Tr>
<Th borderRadius={'none !important'}>{t('common.Username')}</Th>
<Th>{t('user.team.Role')}</Th>
<Th>{t('common.Permission')}</Th>
<Th>{t('common.Status')}</Th>
<Th borderRadius={'none !important'}>{t('common.Action')}</Th>
</Tr>
@@ -49,13 +53,20 @@ function MemberTable() {
<Tbody>
{members.map((item) => (
<Tr key={item.userId} overflow={'unset'}>
<Td display={'flex'} alignItems={'center'}>
<Avatar src={item.avatar} w={['18px', '22px']} />
<Box flex={'1 0 0'} w={0} ml={1} className={'textEllipsis'}>
{item.memberName}
</Box>
<Td>
<HStack>
<Avatar src={item.avatar} w={['18px', '22px']} />
<Box maxW={'150px'} className={'textEllipsis'}>
{item.memberName}
</Box>
</HStack>
</Td>
<Td>
<PermissionTags
permission={item.permission}
permissionList={TeamPermissionList}
/>
</Td>
<Td>{t(TeamMemberRoleMap[item.role]?.label || '')}</Td>
<Td color={TeamMemberStatusMap[item.status].color}>
{t(TeamMemberStatusMap[item.status]?.label || '')}
</Td>
@@ -63,9 +74,8 @@ function MemberTable() {
{userInfo?.team.permission.hasManagePer &&
item.role !== TeamMemberRoleEnum.owner &&
item.tmbId !== userInfo?.team.tmbId && (
<MyMenu
width={20}
trigger="hover"
<PermissionSelect
value={item.permission.value}
Button={
<MenuButton
_hover={{
@@ -79,27 +89,21 @@ function MemberTable() {
<MyIcon name={'edit'} cursor={'pointer'} w="1rem" />
</MenuButton>
}
menuList={[
{
children: [
{
label: t('user.team.Remove Member Tip'),
onClick: () =>
openRemoveMember(
() =>
onRemoveMember({
teamId: item.teamId,
memberId: item.tmbId
}),
undefined,
t('user.team.Remove Member Confirm Tip', {
username: item.memberName
})
)()
}
]
}
]}
onChange={(permission) => {
onUpdateCollaborators({
tmbIds: [item.tmbId],
permission
});
}}
onDelete={() => {
openRemoveMember(
() => delRemoveMember(item.tmbId).then(refetchMembers),
undefined,
t('user.team.Remove Member Confirm Tip', {
username: item.memberName
})
)();
}}
/>
)}
</Td>

View File

@@ -38,7 +38,7 @@ function AddManagerModal({ onClose, onSuccess }: { onClose: () => void; onSucces
mutationFn: async () => {
return updateMemberPermission({
permission: ManagePermissionVal,
memberIds: selected.map((item) => {
tmbIds: selected.map((item) => {
return item.tmbId;
})
});

View File

@@ -1,14 +1,26 @@
import React, { ReactNode, useState } from 'react';
import React, { ReactNode, useCallback, useState } from 'react';
import { createContext } from 'use-context-selector';
import type { EditTeamFormDataType } from './components/EditInfoModal';
import dynamic from 'next/dynamic';
import { useQuery } from '@tanstack/react-query';
import { getTeamList, getTeamMembers, putSwitchTeam } from '@/web/support/user/team/api';
import {
delMemberPermission,
getTeamList,
getTeamMembers,
putSwitchTeam,
updateMemberPermission
} from '@/web/support/user/team/api';
import { TeamMemberStatusEnum } from '@fastgpt/global/support/user/team/constant';
import { useUserStore } from '@/web/support/user/useUserStore';
import type { TeamTmbItemType, TeamMemberItemType } from '@fastgpt/global/support/user/team/type';
import { useRequest } from '@fastgpt/web/hooks/useRequest';
import { useRequest, useRequest2 } from '@fastgpt/web/hooks/useRequest';
import { useTranslation } from 'next-i18next';
import CollaboratorContextProvider from '@/components/support/permission/MemberManager/context';
import { TeamPermissionList } from '@fastgpt/global/support/permission/user/constant';
import {
CollaboratorItemType,
UpdateClbPermissionProps
} from '@fastgpt/global/support/permission/collaborator';
const EditInfoModal = dynamic(() => import('./components/EditInfoModal'));
@@ -55,12 +67,35 @@ export const TeamModalContextProvider = ({ children }: { children: ReactNode })
// member action
const {
data: members = [],
refetch: refetchMembers,
isLoading: loadingMembers
} = useQuery(['getMembers', userInfo?.team?.teamId], () => {
if (!userInfo?.team?.teamId) return [];
return getTeamMembers();
});
runAsync: refetchMembers,
loading: loadingMembers
} = useRequest2(
() => {
if (!userInfo?.team?.teamId) return Promise.resolve([]);
return getTeamMembers();
},
{
manual: false,
refreshDeps: [userInfo?.team?.teamId]
}
);
const onGetClbList = useCallback(() => {
return refetchMembers().then((res) =>
res.map<CollaboratorItemType>((member) => ({
teamId: member.teamId,
tmbId: member.tmbId,
permission: member.permission,
name: member.memberName,
avatar: member.avatar
}))
);
}, [refetchMembers]);
const { runAsync: onUpdatePer, loading: isUpdatingPer } = useRequest2(
(props: UpdateClbPermissionProps) => {
return updateMemberPermission(props);
}
);
const { mutate: onSwitchTeam, isLoading: isSwitchingTeam } = useRequest({
mutationFn: async (teamId: string) => {
@@ -70,7 +105,7 @@ export const TeamModalContextProvider = ({ children }: { children: ReactNode })
errorToast: t('user.team.Switch Team Failed')
});
const isLoading = isLoadingTeams || isSwitchingTeam || loadingMembers;
const isLoading = isLoadingTeams || isSwitchingTeam || loadingMembers || isUpdatingPer;
const contextValue = {
myTeams,
@@ -86,16 +121,30 @@ export const TeamModalContextProvider = ({ children }: { children: ReactNode })
return (
<TeamModalContext.Provider value={contextValue}>
{children}
{!!editTeamData && (
<EditInfoModal
defaultData={editTeamData}
onClose={() => setEditTeamData(undefined)}
onSuccess={() => {
refetchTeams();
initUserInfo();
}}
/>
{userInfo?.team?.permission && (
<CollaboratorContextProvider
permission={userInfo?.team?.permission}
permissionList={TeamPermissionList}
onGetCollaboratorList={onGetClbList}
onUpdateCollaborators={onUpdatePer}
onDelOneCollaborator={delMemberPermission}
>
{() => (
<>
{children}
{!!editTeamData && (
<EditInfoModal
defaultData={editTeamData}
onClose={() => setEditTeamData(undefined)}
onSuccess={() => {
refetchTeams();
initUserInfo();
}}
/>
)}
</>
)}
</CollaboratorContextProvider>
)}
</TeamModalContext.Provider>
);

View File

@@ -12,6 +12,7 @@ import { readConfigData } from '@/service/common/system';
import { exit } from 'process';
import { FastGPTProUrl } from '@fastgpt/service/common/system/constants';
import { initFastGPTConfig } from '@fastgpt/service/common/system/tools';
import json5 from 'json5';
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
await getInitConfig();
@@ -88,7 +89,7 @@ export async function initSystemConfig() {
getFastGPTConfigFromDB(),
readConfigData('config.json')
]);
const fileRes = JSON.parse(fileConfig) as FastGPTConfigFileType;
const fileRes = json5.parse(fileConfig) as FastGPTConfigFileType;
// get config from database
const config: FastGPTConfigFileType = {
@@ -131,7 +132,7 @@ export function getSystemVersion() {
if (process.env.NODE_ENV === 'development') {
global.systemVersion = process.env.npm_package_version || '0.0.0';
} else {
const packageJson = JSON.parse(readFileSync('/app/package.json', 'utf-8'));
const packageJson = json5.parse(readFileSync('/app/package.json', 'utf-8'));
global.systemVersion = packageJson?.version;
}
@@ -157,7 +158,7 @@ function getSystemPlugin() {
const fileTemplates: (PluginTemplateType & { weight: number })[] = filterFiles.map((filename) => {
const content = readFileSync(`${basePath}/${filename}`, 'utf-8');
return {
...JSON.parse(content),
...json5.parse(content),
id: `${PluginSourceEnum.community}-${filename.replace('.json', '')}`,
source: PluginSourceEnum.community
};

View File

@@ -8,8 +8,12 @@ import { mongoSessionRun } from '@fastgpt/service/common/mongo/sessionRun';
import { MongoAppVersion } from '@fastgpt/service/core/app/version/schema';
import { NextAPI } from '@/service/middleware/entry';
import { MongoChatInputGuide } from '@fastgpt/service/core/chat/inputGuide/schema';
import { OwnerPermissionVal } from '@fastgpt/global/support/permission/constant';
import {
OwnerPermissionVal,
PerResourceTypeEnum
} from '@fastgpt/global/support/permission/constant';
import { findAppAndAllChildren } from '@fastgpt/service/core/app/controller';
import { MongoResourcePermission } from '@fastgpt/service/support/permission/schema';
async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
const { appId } = req.query as { appId: string };
@@ -27,8 +31,6 @@ async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
fields: '_id'
});
console.log(apps);
await mongoSessionRun(async (session) => {
for await (const app of apps) {
const appId = app._id;
@@ -65,6 +67,14 @@ async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
},
{ session }
);
await MongoResourcePermission.deleteMany(
{
resourceType: PerResourceTypeEnum.app,
teamId,
resourceId: appId
},
{ session }
);
// delete app
await MongoApp.deleteOne(
{

View File

@@ -14,7 +14,6 @@ import { authApp } from '@fastgpt/service/support/permission/app/auth';
import { dispatchWorkFlow } from '@fastgpt/service/core/workflow/dispatch';
import { authCert } from '@fastgpt/service/support/permission/auth/common';
import { getUserChatInfoAndAuthTeamPoints } from '@/service/support/permission/auth/team';
import { chatValue2RuntimePrompt } from '@fastgpt/global/core/chat/adapt';
import { RuntimeEdgeItemType } from '@fastgpt/global/core/workflow/type/edge';
import { RuntimeNodeItemType } from '@fastgpt/global/core/workflow/runtime/type';
import { removeEmptyUserInput } from '@fastgpt/global/core/chat/utils';
@@ -61,7 +60,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
}
/* user auth */
const [_, { teamId, tmbId }] = await Promise.all([
const [{ app }, { teamId, tmbId }] = await Promise.all([
authApp({ req, authToken: true, appId, per: ReadPermissionVal }),
authCert({
req,
@@ -79,7 +78,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
teamId,
tmbId,
user,
appId,
app,
runtimeNodes: nodes,
runtimeEdges: edges,
variables,

View File

@@ -9,6 +9,7 @@ import { PostWorkflowDebugProps, PostWorkflowDebugResponse } from '@/global/core
import { authPluginCrud } from '@fastgpt/service/support/permission/auth/plugin';
import { NextAPI } from '@/service/middleware/entry';
import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant';
import { defaultApp } from '@/web/core/app/constants';
async function handler(
req: NextApiRequest,
@@ -45,6 +46,12 @@ async function handler(
// auth balance
const { user } = await getUserChatInfoAndAuthTeamPoints(tmbId);
const app = {
...defaultApp,
teamId,
tmbId
};
/* start process */
const { flowUsages, flowResponses, debugResponse } = await dispatchWorkFlow({
res,
@@ -52,7 +59,7 @@ async function handler(
teamId,
tmbId,
user,
appId,
app,
runtimeNodes: nodes,
runtimeEdges: edges,
variables,

View File

@@ -13,6 +13,9 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
if (!requestPath) {
throw new Error('url is empty');
}
if (!FastGPTProUrl) {
throw new Error('未配置商业版链接');
}
const parsedUrl = new URL(FastGPTProUrl);
delete req.headers?.rootkey;

View File

@@ -191,7 +191,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
user,
teamId: String(teamId),
tmbId: String(tmbId),
appId: String(app._id),
app,
chatId,
responseChatItemId,
runtimeNodes: storeNodes2RuntimeNodes(nodes, getDefaultEntryNodeIds(nodes)),

View File

@@ -20,7 +20,7 @@ import Avatar from '@/components/Avatar';
import MyModal from '@fastgpt/web/components/common/MyModal';
import { useTranslation } from 'next-i18next';
import { MongoImageTypeEnum } from '@fastgpt/global/common/file/image/constants';
import { CollaboratorContextProvider } from '@/components/support/permission/MemberManager/context';
import CollaboratorContextProvider from '@/components/support/permission/MemberManager/context';
import {
postUpdateAppCollaborators,
deleteAppCollaborators,
@@ -35,6 +35,7 @@ import {
import { PermissionValueType } from '@fastgpt/global/support/permission/type';
import DefaultPermissionList from '@/components/support/permission/DefaultPerList';
import MyIcon from '@fastgpt/web/components/common/Icon';
import { UpdateClbPermissionProps } from '@fastgpt/global/support/permission/collaborator';
const InfoModal = ({ onClose }: { onClose: () => void }) => {
const { t } = useTranslation();
@@ -123,7 +124,7 @@ const InfoModal = ({ onClose }: { onClose: () => void }) => {
[setValue, t, toast]
);
const onUpdateCollaborators = async (tmbIds: string[], permission: PermissionValueType) => {
const onUpdateCollaborators = async ({ tmbIds, permission }: UpdateClbPermissionProps) => {
await postUpdateAppCollaborators({
tmbIds,
permission,

View File

@@ -108,7 +108,7 @@ const Logs = ({ appId }: { appId: string }) => {
<Th>{appT('Mark Count')}</Th>
</Tr>
</Thead>
<Tbody>
<Tbody fontSize={'xs'}>
{logs.map((item) => (
<Tr
key={item._id}

View File

@@ -89,10 +89,23 @@ const EditForm = ({
const { setValue, getValues, handleSubmit, control, watch } = editForm;
const { fields: datasets, replace: replaceKbList } = useFieldArray({
const { fields: datasets, replace: replaceDatasetList } = useFieldArray({
control,
name: 'dataset.datasets'
});
const selectDatasets = useMemo(
() => allDatasets.filter((item) => datasets.find((dataset) => dataset.datasetId === item._id)),
[allDatasets, datasets]
);
useEffect(() => {
if (selectDatasets.length !== datasets.length) {
replaceDatasetList(
selectDatasets.map((item) => ({
datasetId: item._id
}))
);
}
}, [datasets, replaceDatasetList, selectDatasets]);
const {
isOpen: isOpenDatasetSelect,
@@ -131,11 +144,6 @@ const EditForm = ({
const scheduledTriggerConfig = watch('chatConfig.scheduledTriggerConfig');
const searchMode = watch('dataset.searchMode');
const selectDatasets = useMemo(
() => allDatasets.filter((item) => datasets.find((dataset) => dataset.datasetId === item._id)),
[allDatasets, datasets]
);
const tokenLimit = useMemo(() => {
return llmModelList.find((item) => item.model === selectLLMModel)?.quoteMaxToken || 3000;
}, [selectLLMModel, llmModelList]);
@@ -475,7 +483,7 @@ const EditForm = ({
vectorModel: item.vectorModel
}))}
onClose={onCloseKbSelect}
onChange={replaceKbList}
onChange={replaceDatasetList}
/>
)}
{isOpenDatasetParams && (

View File

@@ -271,7 +271,13 @@ const ListItem = () => {
permission: editPerApp.permission,
onGetCollaboratorList: () => getCollaboratorList(editPerApp._id),
permissionList: AppPermissionList,
onUpdateCollaborators: (tmbIds: string[], permission: number) => {
onUpdateCollaborators: ({
tmbIds,
permission
}: {
tmbIds: string[];
permission: number;
}) => {
return postUpdateAppCollaborators({
tmbIds,
permission,

View File

@@ -140,6 +140,7 @@ const MyApps = () => {
{!!folderDetail && isPc && (
<Box pt={[4, 6]}>
<FolderSlideCard
refreshDeps={[folderDetail._id]}
name={folderDetail.name}
intro={folderDetail.intro}
onEdit={() => {
@@ -163,7 +164,13 @@ const MyApps = () => {
permission: folderDetail.permission,
onGetCollaboratorList: () => getCollaboratorList(folderDetail._id),
permissionList: AppPermissionList,
onUpdateCollaborators: (tmbIds: string[], permission: number) => {
onUpdateCollaborators: ({
tmbIds,
permission
}: {
tmbIds: string[];
permission: number;
}) => {
return postUpdateAppCollaborators({
tmbIds,
permission,

View File

@@ -374,7 +374,6 @@ const DataCard = () => {
e.stopPropagation();
openConfirm(async () => {
try {
setIsLoading(true);
await delOneDatasetDataById(item._id);
getData(pageNum);
} catch (error) {
@@ -383,7 +382,6 @@ const DataCard = () => {
status: 'error'
});
}
setIsLoading(false);
})();
}}
/>
@@ -411,14 +409,8 @@ const DataCard = () => {
</DrawerHeader>
<DrawerBody>
{metadataList.map((item) => (
<Flex
key={item.label}
alignItems={'center'}
mb={5}
wordBreak={'break-all'}
fontSize={'sm'}
>
{metadataList.map((item, i) => (
<Flex key={i} alignItems={'center'} mb={5} wordBreak={'break-all'} fontSize={'sm'}>
<Box color={'myGray.500'} flex={'0 0 100px'}>
{item.label}
</Box>

View File

@@ -41,7 +41,7 @@ const Slider = ({ currentTab }: { currentTab: TabEnum }) => {
icon: 'common/overviewLight'
},
{ label: t('core.dataset.test.Search Test'), id: TabEnum.test, icon: 'kbTest' },
...(userInfo?.team.permission.hasWritePer && datasetDetail.isOwner
...(userInfo?.team.permission.hasManagePer || datasetDetail.isOwner
? [{ label: t('common.Config'), id: TabEnum.info, icon: 'common/settingLight' }]
: [])
];

View File

@@ -34,7 +34,7 @@ export const getScheduleTriggerApp = async () => {
mode: 'chat',
teamId: String(app.teamId),
tmbId: String(app.tmbId),
appId: String(app._id),
app,
runtimeNodes: storeNodes2RuntimeNodes(app.modules, getDefaultEntryNodeIds(app.modules)),
runtimeEdges: initWorkflowEdgeStatus(app.edges),
variables: {},

View File

@@ -1,12 +1,10 @@
import { GET, POST, PUT, DELETE } from '@/web/common/api/request';
import { UpdateClbPermissionProps } from '@fastgpt/global/support/permission/collaborator';
import {
CreateTeamProps,
DelMemberProps,
InviteMemberProps,
InviteMemberResponse,
UpdateInviteProps,
UpdateTeamMemberPermissionProps,
UpdateTeamMemberProps,
UpdateTeamProps
} from '@fastgpt/global/support/user/team/controller.d';
import type { TeamTagItemType, TeamTagSchema } from '@fastgpt/global/support/user/team/type';
@@ -33,15 +31,15 @@ export const postInviteTeamMember = (data: InviteMemberProps) =>
POST<InviteMemberResponse>(`/proApi/support/user/team/member/invite`, data);
export const putUpdateMemberName = (name: string) =>
PUT(`/proApi/support/user/team/member/updateName`, { name });
export const delRemoveMember = (props: DelMemberProps) =>
DELETE(`/proApi/support/user/team/member/delete`, props);
export const delRemoveMember = (tmbId: string) =>
DELETE(`/proApi/support/user/team/member/delete`, { tmbId });
export const updateInviteResult = (data: UpdateInviteProps) =>
PUT('/proApi/support/user/team/member/updateInvite', data);
export const delLeaveTeam = (teamId: string) =>
DELETE('/proApi/support/user/team/member/leave', { teamId });
/* -------------- team collaborator -------------------- */
export const updateMemberPermission = (data: UpdateTeamMemberPermissionProps) =>
export const updateMemberPermission = (data: UpdateClbPermissionProps) =>
PUT('/proApi/support/user/team/collaborator/update', data);
export const delMemberPermission = (tmbId: string) =>
DELETE('/proApi/support/user/team/collaborator/delete', { tmbId });