Browse Source

Fix/upgrade btn show logic (#14072)

tags/1.0.0
NFish 8 months ago
parent
commit
bbfe83c86b
No account linked to committer's email address

+ 0
- 10
web/app/components/header/account-dropdown/workplace-selector/index.tsx View File

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()
<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>
)) ))
} }

+ 6
- 34
web/app/components/header/index.tsx View File

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'
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'
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


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()
<WorkspaceProvider> <WorkspaceProvider>
<WorkplaceSelector /> <WorkplaceSelector />
</WorkspaceProvider> </WorkspaceProvider>
{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>
)}
{enableBilling ? <PlanBadge allowHover sandboxAsUpgrade plan={plan.type} onClick={handlePlanClick} /> : <LicenseNav />}
</div> </div>
</div> </div>
} }
<LogoSite /> <LogoSite />
</Link> </Link>
<div className='font-light text-divider-deep'>/</div> <div className='font-light text-divider-deep'>/</div>
{
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>
)
}
{enableBilling ? <PlanBadge allowHover sandboxAsUpgrade plan={plan.type} onClick={handlePlanClick} /> : <LicenseNav />}
</div > </div >
)} )}
{ {
) )
} }
<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 />

+ 10
- 7
web/app/components/header/license-env/index.tsx View File

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()
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'>
{count <= 1 && <span>{t('common.license.expiring', { count })}</span>}
{count > 1 && <span>{t('common.license.expiring_plural', { count })}</span>}
</div>
return <PremiumBadge color='orange' className='select-none'>
<RiHourglass2Fill className='flex items-center pl-0.5 size-3 text-components-premium-badge-indigo-text-stop-0' />
{count <= 1 && <span className='system-xs-medium px-0.5'>{t('common.license.expiring', { count })}</span>}
{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'>
Enterprise
</div>
return <PremiumBadge color="indigo" className='select-none'>
<span className='system-xs-medium px-1'>Enterprise</span>
</PremiumBadge>
} }
return null return null
} }

+ 70
- 0
web/app/components/header/plan-badge/index.tsx View File

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…
Cancel
Save