feat: invitation link (#3979)
* feat: invitation link schema and apis * feat: add invitation link * feat: member status: active, leave, forbidden * fix: expires show hours and minutes * feat: invalid invitation link hint * fix: typo * chore: fix typo & i18n * fix * pref: fe * feat: add ttl index for 30-day-clean-up
This commit is contained in:
@@ -18,7 +18,6 @@ import WorkorderButton from './WorkorderButton';
|
||||
|
||||
const Navbar = dynamic(() => import('./navbar'));
|
||||
const NavbarPhone = dynamic(() => import('./navbarPhone'));
|
||||
const UpdateInviteModal = dynamic(() => import('@/components/support/user/team/UpdateInviteModal'));
|
||||
const NotSufficientModal = dynamic(() => import('@/components/support/wallet/NotSufficientModal'));
|
||||
const SystemMsgModal = dynamic(() => import('@/components/support/user/inform/SystemMsgModal'));
|
||||
const ImportantInform = dynamic(() => import('@/components/support/user/inform/ImportantInform'));
|
||||
@@ -151,7 +150,6 @@ const Layout = ({ children }: { children: JSX.Element }) => {
|
||||
</Box>
|
||||
{feConfigs?.isPlus && (
|
||||
<>
|
||||
{!!userInfo && <UpdateInviteModal />}
|
||||
{notSufficientModalType && <NotSufficientModal type={notSufficientModalType} />}
|
||||
{!!userInfo && <SystemMsgModal />}
|
||||
{showUpdateNotification && (
|
||||
|
||||
@@ -1,132 +0,0 @@
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import MyModal from '@fastgpt/web/components/common/MyModal';
|
||||
import { Button, ModalFooter, ModalBody, Flex, Box, useTheme } from '@chakra-ui/react';
|
||||
import { getTeamList, updateInviteResult } from '@/web/support/user/team/api';
|
||||
import { TeamMemberStatusEnum } from '@fastgpt/global/support/user/team/constant';
|
||||
import Avatar from '@fastgpt/web/components/common/Avatar';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import { useConfirm } from '@fastgpt/web/hooks/useConfirm';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
import { useRequest2 } from '@fastgpt/web/hooks/useRequest';
|
||||
import { useUserStore } from '@/web/support/user/useUserStore';
|
||||
|
||||
const UpdateInviteModal = () => {
|
||||
const { t } = useTranslation();
|
||||
const theme = useTheme();
|
||||
const { toast } = useToast();
|
||||
const { feConfigs } = useSystemStore();
|
||||
const { initUserInfo } = useUserStore();
|
||||
|
||||
const { ConfirmModal, openConfirm } = useConfirm({});
|
||||
|
||||
const { data: inviteList = [], run: fetchInviteList } = useRequest2(
|
||||
async () => (feConfigs.isPlus ? getTeamList(TeamMemberStatusEnum.waiting) : []),
|
||||
{
|
||||
manual: false
|
||||
}
|
||||
);
|
||||
|
||||
const { runAsync: onAccept, loading: isLoadingAccept } = useRequest2(updateInviteResult, {
|
||||
onSuccess() {
|
||||
toast({
|
||||
status: 'success',
|
||||
title: t('common:user.team.invite.Accepted')
|
||||
});
|
||||
fetchInviteList();
|
||||
initUserInfo();
|
||||
}
|
||||
});
|
||||
const { runAsync: onReject, loading: isLoadingReject } = useRequest2(updateInviteResult, {
|
||||
onSuccess() {
|
||||
toast({
|
||||
status: 'success',
|
||||
title: t('common:user.team.invite.Reject')
|
||||
});
|
||||
fetchInviteList();
|
||||
initUserInfo();
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<MyModal
|
||||
isOpen={inviteList && inviteList.length > 0}
|
||||
iconSrc="/imgs/modal/team.svg"
|
||||
title={
|
||||
<Box>
|
||||
<Box>{t('common:user.team.Processing invitations')}</Box>
|
||||
<Box fontWeight={'normal'} fontSize={'sm'} color={'myGray.500'}>
|
||||
{t('common:user.team.Processing invitations Tips', { amount: inviteList?.length })}
|
||||
</Box>
|
||||
</Box>
|
||||
}
|
||||
maxW={['90vw', '500px']}
|
||||
>
|
||||
<ModalBody>
|
||||
{inviteList?.map((item) => (
|
||||
<Flex
|
||||
key={item.teamId}
|
||||
alignItems={'center'}
|
||||
border={theme.borders.base}
|
||||
borderRadius={'md'}
|
||||
px={3}
|
||||
py={2}
|
||||
_notFirst={{
|
||||
mt: 3
|
||||
}}
|
||||
>
|
||||
<Avatar src={item.avatar} w={['16px', '23px']} />
|
||||
<Box mx={2}>{item.teamName}</Box>
|
||||
<Box flex={1} />
|
||||
<Button
|
||||
size="sm"
|
||||
variant={'solid'}
|
||||
colorScheme="green"
|
||||
isLoading={isLoadingAccept}
|
||||
onClick={() => {
|
||||
openConfirm(
|
||||
() =>
|
||||
onAccept({
|
||||
tmbId: item.tmbId,
|
||||
status: TeamMemberStatusEnum.active
|
||||
}),
|
||||
undefined,
|
||||
t('common:user.team.invite.Accept Confirm')
|
||||
)();
|
||||
}}
|
||||
>
|
||||
{t('common:user.team.invite.accept')}
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
ml={2}
|
||||
variant={'solid'}
|
||||
colorScheme="red"
|
||||
isLoading={isLoadingReject}
|
||||
onClick={() => {
|
||||
openConfirm(
|
||||
() =>
|
||||
onReject({
|
||||
tmbId: item.tmbId,
|
||||
status: TeamMemberStatusEnum.reject
|
||||
}),
|
||||
undefined,
|
||||
t('common:user.team.invite.Reject Confirm')
|
||||
)();
|
||||
}}
|
||||
>
|
||||
{t('common:user.team.invite.reject')}
|
||||
</Button>
|
||||
</Flex>
|
||||
))}
|
||||
</ModalBody>
|
||||
<ModalFooter justifyContent={'center'}>
|
||||
<Box>{t('common:user.team.invite.Deal Width Footer Tip')}</Box>
|
||||
</ModalFooter>
|
||||
|
||||
<ConfirmModal />
|
||||
</MyModal>
|
||||
);
|
||||
};
|
||||
|
||||
export default React.memo(UpdateInviteModal);
|
||||
Reference in New Issue
Block a user