mirror of
https://git.mirrors.martin98.com/https://github.com/langgenius/dify.git
synced 2025-07-21 12:34:25 +08:00
fix: show build app limit in app creation modal (#16940)
This commit is contained in:
parent
c7fcfc863d
commit
9feafb6dbd
@ -214,6 +214,7 @@ function CreateApp({ onClose, onSuccess, onCreateFromTemplate }: CreateAppProps)
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{isAppsFull && <AppsFull className='mt-4' loc='app-create' />}
|
||||
<div className='flex items-center justify-between pb-10 pt-5'>
|
||||
<div className='system-xs-regular flex cursor-pointer items-center gap-1 text-text-tertiary' onClick={onCreateFromTemplate}>
|
||||
<span>{t('app.newApp.noIdeaTip')}</span>
|
||||
@ -251,13 +252,6 @@ function CreateApp({ onClose, onSuccess, onCreateFromTemplate }: CreateAppProps)
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{
|
||||
isAppsFull && (
|
||||
<div className='px-8 py-2'>
|
||||
<AppsFull loc='app-create' />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</>
|
||||
}
|
||||
type CreateAppDialogProps = CreateAppProps & {
|
||||
|
@ -96,7 +96,7 @@ const DuplicateAppModal = ({
|
||||
className='h-10'
|
||||
/>
|
||||
</div>
|
||||
{isAppsFull && <AppsFull loc='app-duplicate-create' />}
|
||||
{isAppsFull && <AppsFull className='mt-4' loc='app-duplicate-create' />}
|
||||
</div>
|
||||
<div className='flex flex-row-reverse'>
|
||||
<Button disabled={isAppsFull} className='ml-2 w-24' variant='primary' onClick={submit}>{t('app.duplicate')}</Button>
|
||||
|
@ -3,35 +3,82 @@ import type { FC } from 'react'
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import UpgradeBtn from '../upgrade-btn'
|
||||
import AppsInfo from '../usage-info/apps-info'
|
||||
import ProgressBar from '@/app/components/billing/progress-bar'
|
||||
import Button from '@/app/components/base/button'
|
||||
import { mailToSupport } from '@/app/components/header/utils/util'
|
||||
import { useProviderContext } from '@/context/provider-context'
|
||||
import { useAppContext } from '@/context/app-context'
|
||||
import { Plan } from '@/app/components/billing/type'
|
||||
import s from './style.module.css'
|
||||
import cn from '@/utils/classnames'
|
||||
import GridMask from '@/app/components/base/grid-mask'
|
||||
|
||||
const AppsFull: FC<{ loc: string; className?: string }> = ({
|
||||
const LOW = 50
|
||||
const MIDDLE = 80
|
||||
|
||||
const AppsFull: FC<{ loc: string; className?: string; }> = ({
|
||||
loc,
|
||||
className,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const { plan } = useProviderContext()
|
||||
const { userProfile, langeniusVersionInfo } = useAppContext()
|
||||
const isTeam = plan.type === Plan.team
|
||||
const usage = plan.usage.buildApps
|
||||
const total = plan.total.buildApps
|
||||
const percent = usage / total * 100
|
||||
const color = (() => {
|
||||
if (percent < LOW)
|
||||
return 'bg-components-progress-bar-progress-solid'
|
||||
|
||||
if (percent < MIDDLE)
|
||||
return 'bg-components-progress-warning-progress'
|
||||
|
||||
return 'bg-components-progress-error-progress'
|
||||
})()
|
||||
return (
|
||||
<GridMask wrapperClassName='rounded-lg' canvasClassName='rounded-lg' gradientClassName='rounded-lg'>
|
||||
<div className={cn(
|
||||
'mt-6 flex cursor-pointer flex-col rounded-lg border-2 border-solid border-transparent px-3.5 py-4 shadow-md transition-all duration-200 ease-in-out',
|
||||
'flex flex-col gap-3 rounded-xl border-[0.5px] border-components-panel-border-subtle bg-components-panel-on-panel-item-bg p-4 shadow-xs backdrop-blur-sm',
|
||||
className,
|
||||
)}>
|
||||
<div className='flex items-center justify-between'>
|
||||
<div className={cn(s.textGradient, 'text-base font-semibold leading-[24px]')}>
|
||||
<div>{t('billing.apps.fullTipLine1')}</div>
|
||||
<div>{t('billing.apps.fullTipLine2')}</div>
|
||||
<div className='flex justify-between'>
|
||||
{!isTeam && (
|
||||
<div>
|
||||
<div className={cn('title-xl-semi-bold mb-1', s.textGradient)}>
|
||||
{t('billing.apps.fullTip1')}
|
||||
</div>
|
||||
<div className='flex'>
|
||||
<UpgradeBtn loc={loc} />
|
||||
<div className='system-xs-regular text-text-tertiary'>{t('billing.apps.fullTip1des')}</div>
|
||||
</div>
|
||||
)}
|
||||
{isTeam && (
|
||||
<div>
|
||||
<div className={cn('title-xl-semi-bold mb-1', s.textGradient)}>
|
||||
{t('billing.apps.fullTip2')}
|
||||
</div>
|
||||
<div className='system-xs-regular text-text-tertiary'>{t('billing.apps.fullTip2des')}</div>
|
||||
</div>
|
||||
)}
|
||||
{(plan.type === Plan.sandbox || plan.type === Plan.professional) && (
|
||||
<UpgradeBtn isShort loc={loc} />
|
||||
)}
|
||||
{plan.type !== Plan.sandbox && plan.type !== Plan.professional && (
|
||||
<Button variant='secondary-accent'>
|
||||
<a target='_blank' rel='noopener noreferrer' href={mailToSupport(userProfile.email, plan.type, langeniusVersionInfo.current_version)}>
|
||||
{t('billing.apps.contactUs')}
|
||||
</a>
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
<div className='flex flex-col gap-2'>
|
||||
<div className='system-xs-medium flex items-center justify-between text-text-secondary'>
|
||||
<div>{t('billing.usagePage.buildApps')}</div>
|
||||
<div>{usage}/{total}</div>
|
||||
</div>
|
||||
<ProgressBar
|
||||
percent={percent}
|
||||
color={color}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<AppsInfo className='mt-4' />
|
||||
</div>
|
||||
</GridMask>
|
||||
)
|
||||
}
|
||||
export default React.memo(AppsFull)
|
||||
|
@ -1,5 +1,5 @@
|
||||
.textGradient {
|
||||
background: linear-gradient(92deg, #2250F2 -29.55%, #0EBCF3 75.22%);
|
||||
background: linear-gradient(92deg, #0EBCF3 -29.55%, #2250F2 75.22%);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
|
@ -1,27 +0,0 @@
|
||||
'use client'
|
||||
import type { FC } from 'react'
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import UpgradeBtn from '../upgrade-btn'
|
||||
import s from './style.module.css'
|
||||
import cn from '@/utils/classnames'
|
||||
import GridMask from '@/app/components/base/grid-mask'
|
||||
|
||||
const AppsFull: FC = () => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<GridMask wrapperClassName='rounded-lg' canvasClassName='rounded-lg' gradientClassName='rounded-lg'>
|
||||
<div className='col-span-1 flex min-h-[160px] cursor-pointer flex-col rounded-lg border-2 border-solid border-transparent px-3.5 pt-3.5 shadow-xs transition-all duration-200 ease-in-out hover:shadow-lg'>
|
||||
<div className={cn(s.textGradient, 'text-base font-semibold leading-[24px]')}>
|
||||
<div>{t('billing.apps.fullTipLine1')}</div>
|
||||
<div>{t('billing.apps.fullTipLine2')}</div>
|
||||
</div>
|
||||
<div className='mt-8 flex'>
|
||||
<UpgradeBtn loc='app-create' />
|
||||
</div>
|
||||
</div>
|
||||
</GridMask>
|
||||
)
|
||||
}
|
||||
export default React.memo(AppsFull)
|
@ -1,7 +0,0 @@
|
||||
.textGradient {
|
||||
background: linear-gradient(92deg, #2250F2 -29.55%, #0EBCF3 75.22%);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
text-fill-color: transparent;
|
||||
}
|
@ -142,7 +142,7 @@ const CreateAppModal = ({
|
||||
<p className='body-xs-regular text-text-tertiary'>{t('app.answerIcon.descriptionInExplore')}</p>
|
||||
</div>
|
||||
)}
|
||||
{!isEditModal && isAppsFull && <AppsFull loc='app-explore-create' />}
|
||||
{!isEditModal && isAppsFull && <AppsFull className='mt-4' loc='app-explore-create' />}
|
||||
</div>
|
||||
<div className='flex flex-row-reverse'>
|
||||
<Button disabled={!isEditModal && isAppsFull} className='ml-2 w-24' variant='primary' onClick={submit}>{!isEditModal ? t('common.operation.create') : t('common.operation.save')}</Button>
|
||||
|
@ -170,8 +170,11 @@ const translation = {
|
||||
fullSolution: 'Upgrade your plan to get more space.',
|
||||
},
|
||||
apps: {
|
||||
fullTipLine1: 'Upgrade your plan to',
|
||||
fullTipLine2: 'build more apps.',
|
||||
fullTip1: 'Upgrade to create more apps',
|
||||
fullTip1des: 'You\'ve reached the limit of build apps on this plan',
|
||||
fullTip2: 'Plan limit reached',
|
||||
fullTip2des: 'It is recommended to clean up inactive applications to free up usage, or contact us.',
|
||||
contactUs: 'Contact us',
|
||||
},
|
||||
annotatedResponse: {
|
||||
fullTipLine1: 'Upgrade your plan to',
|
||||
|
@ -169,8 +169,11 @@ const translation = {
|
||||
fullSolution: '升级您的套餐以获得更多空间。',
|
||||
},
|
||||
apps: {
|
||||
fullTipLine1: '升级您的套餐以',
|
||||
fullTipLine2: '构建更多的程序。',
|
||||
fullTip1: '升级以创建更多应用',
|
||||
fullTip1des: '您已达到此计划上构建应用的限制',
|
||||
fullTip2: '计划限制已达到',
|
||||
fullTip2des: '推荐您清理不活跃的应用或者联系我们',
|
||||
contactUs: '联系我们',
|
||||
},
|
||||
annotatedResponse: {
|
||||
fullTipLine1: '升级您的套餐以',
|
||||
|
Loading…
x
Reference in New Issue
Block a user