* feat: add third party account config (#3443) * temp * editor workflow variable style * add team to dispatch * i18n * delete console * change openai account position * fix * fix * fix * fix * fix * 4.8.17 test (#3461) * perf: external provider config * perf: ui * feat: add template config (#3434) * change template position * template config * delete console * delete * fix * fix * perf: Mongo visutal field (#3464) * remve invalid code * perf: team member visutal code * perf: virtual search; perf: search test data * fix: ts * fix: image response headers * perf: template code * perf: auth layout;perf: auto save (#3472) * perf: auth layout * perf: auto save * perf: auto save * fix: template guide display & http input support external variables (#3475) * fix: template guide display * http editor support external workflow variables * perf: auto save;fix: ifelse checker line break; (#3478) * perf: auto save * perf: auto save * fix: ifelse checker line break * perf: doc * perf: doc * fix: update var type error * 4.8.17 test (#3479) * perf: auto save * perf: auto save * perf: template code * 4.8.17 test (#3480) * perf: auto save * perf: auto save * perf: model price model * feat: add react memo * perf: model provider filter * fix: ts (#3481) * perf: auto save * perf: auto save * fix: ts * simple app tool select (#3473) * workflow plugin userguide & simple tool ui * simple tool filter * reuse component * change component to hook * fix * perf: too selector modal (#3484) * perf: auto save * perf: auto save * perf: markdown render * perf: too selector * fix: app version require tmbId * perf: templates refresh * perf: templates refresh * hide auto save error tip * perf: toolkit guide --------- Co-authored-by: heheer <heheer@sealos.io>
264 lines
8.6 KiB
TypeScript
264 lines
8.6 KiB
TypeScript
import AccountContainer from '../components/AccountContainer';
|
|
import { Box, Flex, Grid, Progress, useDisclosure } from '@chakra-ui/react';
|
|
import MyIcon from '@fastgpt/web/components/common/Icon';
|
|
import { useTranslation } from 'next-i18next';
|
|
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
|
import { useUserStore } from '@/web/support/user/useUserStore';
|
|
import { TeamMemberRoleEnum } from '@fastgpt/global/support/user/team/constant';
|
|
import dynamic from 'next/dynamic';
|
|
import { useState, useMemo } from 'react';
|
|
import WorkflowVariableModal from './components/WorkflowVariableModal';
|
|
import { useToast } from '@fastgpt/web/hooks/useToast';
|
|
import { serviceSideProps } from '@fastgpt/web/common/system/nextjs';
|
|
import { useRequest2 } from '@fastgpt/web/hooks/useRequest';
|
|
import { GET } from '@/web/common/api/request';
|
|
import type { checkUsageResponse } from '@/pages/api/support/user/team/thirtdParty/checkUsage';
|
|
import MyBox from '@fastgpt/web/components/common/MyBox';
|
|
|
|
const LafAccountModal = dynamic(() => import('@/components/support/laf/LafAccountModal'));
|
|
const OpenAIAccountModal = dynamic(() => import('./components/OpenAIAccountModal'));
|
|
|
|
export type ThirdPartyAccountType = {
|
|
name: string;
|
|
icon: string;
|
|
iconColor?: string;
|
|
key?: string;
|
|
intro: string;
|
|
onClick?: () => void;
|
|
isOpen?: boolean;
|
|
active: boolean;
|
|
usage?: {
|
|
used: number;
|
|
total: number;
|
|
};
|
|
};
|
|
|
|
const ThirdParty = () => {
|
|
const { t } = useTranslation();
|
|
const { feConfigs } = useSystemStore();
|
|
const { toast } = useToast();
|
|
const { isOpen: isOpenLaf, onClose: onCloseLaf, onOpen: onOpenLaf } = useDisclosure();
|
|
const { isOpen: isOpenOpenai, onClose: onCloseOpenai, onOpen: onOpenOpenai } = useDisclosure();
|
|
|
|
const [workflowVariable, setWorkflowVariable] = useState<ThirdPartyAccountType>();
|
|
|
|
const { userInfo } = useUserStore();
|
|
|
|
const isOwner = userInfo?.team?.role === TeamMemberRoleEnum.owner;
|
|
|
|
const defaultAccountList: ThirdPartyAccountType[] = useMemo(
|
|
() => [
|
|
{
|
|
name: t('account_thirdParty:laf_account'),
|
|
icon: 'support/account/laf',
|
|
intro: t('common:support.user.Laf account intro'),
|
|
onClick: onOpenLaf,
|
|
isOpen: !!feConfigs?.lafEnv,
|
|
active: !!userInfo?.team?.lafAccount?.appid
|
|
},
|
|
{
|
|
name: t('account_thirdParty:openai_account_configuration'),
|
|
iconColor: 'black',
|
|
icon: 'common/openai',
|
|
intro: t('account_thirdParty:open_api_notice'),
|
|
onClick: onOpenOpenai,
|
|
isOpen: feConfigs?.show_openai_account,
|
|
active: userInfo?.team?.openaiAccount?.key !== undefined
|
|
}
|
|
],
|
|
[
|
|
feConfigs?.lafEnv,
|
|
feConfigs?.show_openai_account,
|
|
onOpenLaf,
|
|
onOpenOpenai,
|
|
t,
|
|
userInfo?.team?.lafAccount?.appid,
|
|
userInfo?.team?.openaiAccount?.key
|
|
]
|
|
);
|
|
|
|
const { data: workflowVariables = [], loading } = useRequest2(
|
|
async (): Promise<ThirdPartyAccountType[]> => {
|
|
return Promise.all(
|
|
(feConfigs?.externalProviderWorkflowVariables || []).map(async (item) => {
|
|
const usage = await (async () => {
|
|
try {
|
|
return await GET<checkUsageResponse>('/support/user/team/thirtdParty/checkUsage', {
|
|
key: item.key
|
|
});
|
|
} catch (err) {
|
|
return;
|
|
}
|
|
})();
|
|
|
|
const account = {
|
|
key: item.key,
|
|
name: item.name,
|
|
active: userInfo?.team?.externalWorkflowVariables?.[item.key] !== undefined,
|
|
icon: 'common/variable',
|
|
iconColor: 'primary.600',
|
|
intro: item.intro || t('account_thirdParty:no_intro')
|
|
};
|
|
|
|
return {
|
|
...account,
|
|
usage,
|
|
onClick: () => setWorkflowVariable(account),
|
|
isOpen: item.isOpen
|
|
};
|
|
})
|
|
);
|
|
},
|
|
{
|
|
manual: false,
|
|
refreshDeps: [
|
|
feConfigs?.externalProviderWorkflowVariables,
|
|
userInfo?.team?.externalWorkflowVariables
|
|
]
|
|
}
|
|
);
|
|
|
|
const accountList = useMemo(
|
|
() => [...defaultAccountList, ...workflowVariables],
|
|
[defaultAccountList, workflowVariables]
|
|
);
|
|
|
|
return (
|
|
<AccountContainer>
|
|
<MyBox isLoading={loading} px={[4, 8]} py={[4, 6]} bg={'white'} h={'full'}>
|
|
<Flex>
|
|
<MyIcon name={'common/thirdParty'} w={'24px'} color={'myGray.900'} />
|
|
<Box ml={3}>
|
|
<Box fontSize={'md'} color={'myGray.900'}>
|
|
{t('account_thirdParty:third_party_account')}
|
|
</Box>
|
|
<Box fontSize={'mini'} color={'myGray.500'}>
|
|
{t('account_thirdParty:third_party_account_desc')}
|
|
</Box>
|
|
</Box>
|
|
</Flex>
|
|
<Grid
|
|
gridTemplateColumns={[
|
|
'1fr',
|
|
'repeat(2,1fr)',
|
|
'repeat(3,1fr)',
|
|
'repeat(3,1fr)',
|
|
'repeat(4,1fr)'
|
|
]}
|
|
gridGap={4}
|
|
alignItems={'stretch'}
|
|
mt={5}
|
|
pb={5}
|
|
>
|
|
{accountList
|
|
.filter((item) => item.isOpen)
|
|
.map((item) => (
|
|
<Flex
|
|
key={item.name}
|
|
flexDirection={'column'}
|
|
border={'1px solid'}
|
|
borderColor={'myGray.200'}
|
|
pt={4}
|
|
px={5}
|
|
borderRadius={'10px'}
|
|
h={'146px'}
|
|
cursor={'pointer'}
|
|
_hover={{
|
|
borderColor: 'primary.600'
|
|
}}
|
|
onClick={
|
|
isOwner
|
|
? item.onClick
|
|
: () =>
|
|
toast({
|
|
title: t('account_thirdParty:error.no_permission'),
|
|
status: 'warning'
|
|
})
|
|
}
|
|
position={'relative'}
|
|
>
|
|
<Flex>
|
|
<MyIcon name={item.icon as any} w={'24px'} color={item.iconColor} />
|
|
<Box ml={2} flex={1} fontWeight={'medium'} fontSize={'16px'} color={'myGray.900'}>
|
|
{item.name}
|
|
</Box>
|
|
<Box
|
|
color={item.active ? 'green.600' : 'myGray.700'}
|
|
bg={item.active ? 'green.50' : 'myGray.100'}
|
|
px={2}
|
|
py={1}
|
|
borderRadius={'sm'}
|
|
fontSize={'10px'}
|
|
>
|
|
{item.active
|
|
? t('account_thirdParty:configured')
|
|
: t('account_thirdParty:not_configured')}
|
|
</Box>
|
|
</Flex>
|
|
<Box
|
|
className="textEllipsis2"
|
|
mt={3}
|
|
fontSize={'mini'}
|
|
color={'myGray.500'}
|
|
lineHeight={'18px'}
|
|
>
|
|
{item.intro}
|
|
</Box>
|
|
<Box flex={1} />
|
|
{item.active && item.usage && (
|
|
<Box w={'full'} mb={4}>
|
|
<Flex fontSize={'mini'} color={'myGray.500'}>
|
|
<Box>{t('account_thirdParty:usage')}</Box>
|
|
{item.usage?.total ? (
|
|
<Box ml={1}>
|
|
{item.usage.used}/{item.usage.total}
|
|
</Box>
|
|
) : (
|
|
<Box ml={1}>{t('account_thirdParty:unavailable')}</Box>
|
|
)}
|
|
</Flex>
|
|
<Box mt={1} w={'full'}>
|
|
<Progress
|
|
size={'sm'}
|
|
value={(item.usage.used / item.usage.total) * 100}
|
|
colorScheme={'blue'}
|
|
borderRadius={'md'}
|
|
borderWidth={'1px'}
|
|
borderColor={'low'}
|
|
isAnimated
|
|
hasStripe
|
|
/>
|
|
</Box>
|
|
</Box>
|
|
)}
|
|
</Flex>
|
|
))}
|
|
</Grid>
|
|
</MyBox>
|
|
|
|
{isOpenLaf && userInfo && (
|
|
<LafAccountModal defaultData={userInfo?.team?.lafAccount} onClose={onCloseLaf} />
|
|
)}
|
|
{isOpenOpenai && userInfo && (
|
|
<OpenAIAccountModal defaultData={userInfo?.team?.openaiAccount} onClose={onCloseOpenai} />
|
|
)}
|
|
{workflowVariable && (
|
|
<WorkflowVariableModal
|
|
defaultData={workflowVariable}
|
|
onClose={() => setWorkflowVariable(undefined)}
|
|
/>
|
|
)}
|
|
</AccountContainer>
|
|
);
|
|
};
|
|
|
|
export async function getServerSideProps(content: any) {
|
|
return {
|
|
props: {
|
|
...(await serviceSideProps(content, ['account', 'account_thirdParty']))
|
|
}
|
|
};
|
|
}
|
|
|
|
export default ThirdParty;
|