mirror of
https://git.mirrors.martin98.com/https://github.com/langgenius/dify.git
synced 2025-07-29 22:12:03 +08:00
Fix/upgrade btn show logic (#14072)
This commit is contained in:
parent
55aa4e424a
commit
bbfe83c86b
@ -8,7 +8,6 @@ import { switchWorkspace } from '@/service/common'
|
|||||||
import { useWorkspacesContext } from '@/context/workspace-context'
|
import { useWorkspacesContext } from '@/context/workspace-context'
|
||||||
import { useProviderContext } from '@/context/provider-context'
|
import { useProviderContext } from '@/context/provider-context'
|
||||||
import { ToastContext } from '@/app/components/base/toast'
|
import { ToastContext } from '@/app/components/base/toast'
|
||||||
import PremiumBadge from '@/app/components/base/premium-badge'
|
|
||||||
|
|
||||||
const WorkplaceSelector = () => {
|
const WorkplaceSelector = () => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
@ -72,15 +71,6 @@ const WorkplaceSelector = () => {
|
|||||||
<div className='flex py-1 pl-3 pr-2 items-center gap-2 self-stretch hover:bg-state-base-hover rounded-lg' key={workspace.id} onClick={() => handleSwitchWorkspace(workspace.id)}>
|
<div className='flex py-1 pl-3 pr-2 items-center gap-2 self-stretch hover:bg-state-base-hover rounded-lg' key={workspace.id} onClick={() => handleSwitchWorkspace(workspace.id)}>
|
||||||
<div className='flex items-center justify-center w-6 h-6 bg-[#EFF4FF] rounded-md text-xs font-medium text-primary-600'>{workspace.name[0].toLocaleUpperCase()}</div>
|
<div className='flex items-center justify-center w-6 h-6 bg-[#EFF4FF] rounded-md text-xs font-medium text-primary-600'>{workspace.name[0].toLocaleUpperCase()}</div>
|
||||||
<div className='line-clamp-1 grow overflow-hidden text-text-secondary text-ellipsis system-md-regular cursor-pointer'>{workspace.name}</div>
|
<div className='line-clamp-1 grow overflow-hidden text-text-secondary text-ellipsis system-md-regular cursor-pointer'>{workspace.name}</div>
|
||||||
{
|
|
||||||
<PremiumBadge size='s' color='gray' allowHover={false}>
|
|
||||||
<div className='system-2xs-medium'>
|
|
||||||
<span className='p-[2px]'>
|
|
||||||
{plan.type === 'professional' ? 'PRO' : plan.type.toUpperCase()}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</PremiumBadge>
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,6 @@ import Link from 'next/link'
|
|||||||
import { useBoolean } from 'ahooks'
|
import { useBoolean } from 'ahooks'
|
||||||
import { useSelectedLayoutSegment } from 'next/navigation'
|
import { useSelectedLayoutSegment } from 'next/navigation'
|
||||||
import { Bars3Icon } from '@heroicons/react/20/solid'
|
import { Bars3Icon } from '@heroicons/react/20/solid'
|
||||||
import { SparklesSoft } from '@/app/components/base/icons/src/public/common'
|
|
||||||
import PremiumBadge from '../base/premium-badge'
|
|
||||||
import AccountDropdown from './account-dropdown'
|
import AccountDropdown from './account-dropdown'
|
||||||
import AppNav from './app-nav'
|
import AppNav from './app-nav'
|
||||||
import DatasetNav from './dataset-nav'
|
import DatasetNav from './dataset-nav'
|
||||||
@ -13,7 +11,6 @@ import EnvNav from './env-nav'
|
|||||||
import PluginsNav from './plugins-nav'
|
import PluginsNav from './plugins-nav'
|
||||||
import ExploreNav from './explore-nav'
|
import ExploreNav from './explore-nav'
|
||||||
import ToolsNav from './tools-nav'
|
import ToolsNav from './tools-nav'
|
||||||
import LicenseNav from './license-env'
|
|
||||||
import { WorkspaceProvider } from '@/context/workspace-context'
|
import { WorkspaceProvider } from '@/context/workspace-context'
|
||||||
import { useAppContext } from '@/context/app-context'
|
import { useAppContext } from '@/context/app-context'
|
||||||
import LogoSite from '@/app/components/base/logo/logo-site'
|
import LogoSite from '@/app/components/base/logo/logo-site'
|
||||||
@ -21,7 +18,9 @@ import WorkplaceSelector from '@/app/components/header/account-dropdown/workplac
|
|||||||
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
|
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
|
||||||
import { useProviderContext } from '@/context/provider-context'
|
import { useProviderContext } from '@/context/provider-context'
|
||||||
import { useModalContext } from '@/context/modal-context'
|
import { useModalContext } from '@/context/modal-context'
|
||||||
import { useTranslation } from 'react-i18next'
|
import LicenseNav from './license-env'
|
||||||
|
import PlanBadge from './plan-badge'
|
||||||
|
import { Plan } from '../billing/type'
|
||||||
|
|
||||||
const navClassName = `
|
const navClassName = `
|
||||||
flex items-center relative mr-0 sm:mr-3 px-3 h-8 rounded-xl
|
flex items-center relative mr-0 sm:mr-3 px-3 h-8 rounded-xl
|
||||||
@ -31,15 +30,13 @@ const navClassName = `
|
|||||||
|
|
||||||
const Header = () => {
|
const Header = () => {
|
||||||
const { isCurrentWorkspaceEditor, isCurrentWorkspaceDatasetOperator } = useAppContext()
|
const { isCurrentWorkspaceEditor, isCurrentWorkspaceDatasetOperator } = useAppContext()
|
||||||
const { t } = useTranslation()
|
|
||||||
|
|
||||||
const selectedSegment = useSelectedLayoutSegment()
|
const selectedSegment = useSelectedLayoutSegment()
|
||||||
const media = useBreakpoints()
|
const media = useBreakpoints()
|
||||||
const isMobile = media === MediaType.mobile
|
const isMobile = media === MediaType.mobile
|
||||||
const [isShowNavMenu, { toggle, setFalse: hideNavMenu }] = useBoolean(false)
|
const [isShowNavMenu, { toggle, setFalse: hideNavMenu }] = useBoolean(false)
|
||||||
const { enableBilling, plan } = useProviderContext()
|
const { enableBilling, plan } = useProviderContext()
|
||||||
const { setShowPricingModal, setShowAccountSettingModal } = useModalContext()
|
const { setShowPricingModal, setShowAccountSettingModal } = useModalContext()
|
||||||
const isFreePlan = plan.type === 'sandbox'
|
const isFreePlan = plan.type === Plan.sandbox
|
||||||
const handlePlanClick = useCallback(() => {
|
const handlePlanClick = useCallback(() => {
|
||||||
if (isFreePlan)
|
if (isFreePlan)
|
||||||
setShowPricingModal()
|
setShowPricingModal()
|
||||||
@ -71,18 +68,7 @@ const Header = () => {
|
|||||||
<WorkspaceProvider>
|
<WorkspaceProvider>
|
||||||
<WorkplaceSelector />
|
<WorkplaceSelector />
|
||||||
</WorkspaceProvider>
|
</WorkspaceProvider>
|
||||||
{enableBilling && (
|
{enableBilling ? <PlanBadge allowHover sandboxAsUpgrade plan={plan.type} onClick={handlePlanClick} /> : <LicenseNav />}
|
||||||
<div className='select-none'>
|
|
||||||
<PremiumBadge color='blue' allowHover={true} onClick={handlePlanClick}>
|
|
||||||
<SparklesSoft className='flex items-center py-[1px] pl-[3px] w-3.5 h-3.5 text-components-premium-badge-indigo-text-stop-0' />
|
|
||||||
<div className='system-xs-medium'>
|
|
||||||
<span className='p-1'>
|
|
||||||
{t('billing.upgradeBtn.encourageShort')}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</PremiumBadge>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
@ -93,20 +79,7 @@ const Header = () => {
|
|||||||
<LogoSite />
|
<LogoSite />
|
||||||
</Link>
|
</Link>
|
||||||
<div className='font-light text-divider-deep'>/</div>
|
<div className='font-light text-divider-deep'>/</div>
|
||||||
{
|
{enableBilling ? <PlanBadge allowHover sandboxAsUpgrade plan={plan.type} onClick={handlePlanClick} /> : <LicenseNav />}
|
||||||
enableBilling && (
|
|
||||||
<div className='select-none'>
|
|
||||||
<PremiumBadge color='blue' allowHover={true} onClick={handlePlanClick}>
|
|
||||||
<SparklesSoft className='flex items-center py-[1px] pl-[3px] w-3.5 h-3.5 text-components-premium-badge-indigo-text-stop-0' />
|
|
||||||
<div className='system-xs-medium'>
|
|
||||||
<span className='p-1'>
|
|
||||||
{t('billing.upgradeBtn.encourageShort')}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</PremiumBadge>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
</div >
|
</div >
|
||||||
)}
|
)}
|
||||||
{
|
{
|
||||||
@ -120,7 +93,6 @@ const Header = () => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
<div className='flex items-center shrink-0'>
|
<div className='flex items-center shrink-0'>
|
||||||
<LicenseNav />
|
|
||||||
<EnvNav />
|
<EnvNav />
|
||||||
<div className='mr-3'>
|
<div className='mr-3'>
|
||||||
<PluginsNav />
|
<PluginsNav />
|
||||||
|
@ -5,6 +5,8 @@ import { LicenseStatus } from '@/types/feature'
|
|||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { useContextSelector } from 'use-context-selector'
|
import { useContextSelector } from 'use-context-selector'
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
|
import PremiumBadge from '../../base/premium-badge'
|
||||||
|
import { RiHourglass2Fill } from '@remixicon/react'
|
||||||
|
|
||||||
const LicenseNav = () => {
|
const LicenseNav = () => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
@ -13,15 +15,16 @@ const LicenseNav = () => {
|
|||||||
if (systemFeatures.license?.status === LicenseStatus.EXPIRING) {
|
if (systemFeatures.license?.status === LicenseStatus.EXPIRING) {
|
||||||
const expiredAt = systemFeatures.license?.expired_at
|
const expiredAt = systemFeatures.license?.expired_at
|
||||||
const count = dayjs(expiredAt).diff(dayjs(), 'days')
|
const count = dayjs(expiredAt).diff(dayjs(), 'days')
|
||||||
return <div className='px-2 py-1 mr-4 rounded-full bg-util-colors-orange-orange-50 border-util-colors-orange-orange-100 system-xs-medium text-util-colors-orange-orange-600'>
|
return <PremiumBadge color='orange' className='select-none'>
|
||||||
{count <= 1 && <span>{t('common.license.expiring', { count })}</span>}
|
<RiHourglass2Fill className='flex items-center pl-0.5 size-3 text-components-premium-badge-indigo-text-stop-0' />
|
||||||
{count > 1 && <span>{t('common.license.expiring_plural', { count })}</span>}
|
{count <= 1 && <span className='system-xs-medium px-0.5'>{t('common.license.expiring', { count })}</span>}
|
||||||
</div>
|
{count > 1 && <span className='system-xs-medium px-0.5'>{t('common.license.expiring_plural', { count })}</span>}
|
||||||
|
</PremiumBadge>
|
||||||
}
|
}
|
||||||
if (systemFeatures.license.status === LicenseStatus.ACTIVE) {
|
if (systemFeatures.license.status === LicenseStatus.ACTIVE) {
|
||||||
return <div className='px-2 py-1 mr-4 rounded-md bg-util-colors-indigo-indigo-50 border-util-colors-indigo-indigo-100 system-xs-medium text-util-colors-indigo-indigo-600'>
|
return <PremiumBadge color="indigo" className='select-none'>
|
||||||
Enterprise
|
<span className='system-xs-medium px-1'>Enterprise</span>
|
||||||
</div>
|
</PremiumBadge>
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
70
web/app/components/header/plan-badge/index.tsx
Normal file
70
web/app/components/header/plan-badge/index.tsx
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
import { useProviderContext } from '@/context/provider-context'
|
||||||
|
import classNames from '@/utils/classnames'
|
||||||
|
import type { FC } from 'react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import { SparklesSoft } from '../../base/icons/src/public/common'
|
||||||
|
import PremiumBadge from '../../base/premium-badge'
|
||||||
|
import { Plan } from '../../billing/type'
|
||||||
|
|
||||||
|
type PlanBadgeProps = {
|
||||||
|
plan: Plan
|
||||||
|
size?: 's' | 'm'
|
||||||
|
allowHover?: boolean
|
||||||
|
sandboxAsUpgrade?: boolean
|
||||||
|
onClick?: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
const PlanBadge: FC<PlanBadgeProps> = ({ plan, allowHover, size = 'm', sandboxAsUpgrade = false, onClick }) => {
|
||||||
|
const { isFetchedPlan } = useProviderContext()
|
||||||
|
const { t } = useTranslation()
|
||||||
|
|
||||||
|
if (!isFetchedPlan) return null
|
||||||
|
if (plan === Plan.sandbox && sandboxAsUpgrade) {
|
||||||
|
return <div className='select-none'>
|
||||||
|
<PremiumBadge color='blue' allowHover={allowHover} onClick={onClick}>
|
||||||
|
<SparklesSoft className='flex items-center py-[1px] pl-[3px] w-3.5 h-3.5 text-components-premium-badge-indigo-text-stop-0' />
|
||||||
|
<div className='system-xs-medium'>
|
||||||
|
<span className='p-1'>
|
||||||
|
{t('billing.upgradeBtn.encourageShort')}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</PremiumBadge>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
if (plan === Plan.sandbox) {
|
||||||
|
return <div className='select-none'>
|
||||||
|
<PremiumBadge size={size} color='gray' allowHover={allowHover} onClick={onClick}>
|
||||||
|
<div className={classNames(size === 's' ? 'system-2xs-medium-uppercase' : 'system-xs-medium-uppercase')}>
|
||||||
|
<span className='p-1'>
|
||||||
|
{plan}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</PremiumBadge>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
if (plan === Plan.professional) {
|
||||||
|
return <div className='select-none'>
|
||||||
|
<PremiumBadge size={size} color='blue' allowHover={allowHover} onClick={onClick}>
|
||||||
|
<div className={classNames(size === 's' ? 'system-2xs-medium-uppercase' : 'system-xs-medium-uppercase')}>
|
||||||
|
<span className='p-1'>
|
||||||
|
pro
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</PremiumBadge>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
if (plan === Plan.team) {
|
||||||
|
return <div className='select-none'>
|
||||||
|
<PremiumBadge size={size} color='indigo' allowHover={allowHover} onClick={onClick}>
|
||||||
|
<div className={classNames(size === 's' ? 'system-2xs-medium-uppercase' : 'system-xs-medium-uppercase')}>
|
||||||
|
<span className='p-1'>
|
||||||
|
{plan}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</PremiumBadge>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PlanBadge
|
Loading…
x
Reference in New Issue
Block a user