4.8.4 (#1746)
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
})
|
||||
});
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user