refactor(web): derive workspace billing from current workspace (#39674)

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
yyh 2026-07-28 17:32:03 +08:00 committed by GitHub
parent eef709e475
commit 798e5ed7a7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 18 additions and 41 deletions

View File

@ -1,6 +1,7 @@
import type { PostWorkspacesCurrentResponse } from '@dify/contracts/api/console/workspaces/types.gen'
import type { ModalContextState } from '@/context/modal-context'
import type { ProviderContextState } from '@/context/provider-context'
import type { ICurrentWorkspace, IWorkspace } from '@/models/common'
import type { IWorkspace } from '@/models/common'
import { fireEvent, screen, waitFor, within } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { Plan } from '@/app/components/billing/type'
@ -95,14 +96,13 @@ vi.mock('@/service/client', async (importOriginal) => {
}
})
const currentWorkspaceValue: ICurrentWorkspace = {
const currentWorkspaceValue: PostWorkspacesCurrentResponse = {
id: 'workspace-1',
name: 'Solar Studio',
plan: Plan.sandbox,
status: 'normal',
created_at: 0,
role: 'owner',
providers: [],
trial_credits: 10000,
trial_credits_used: 2500,
trial_credits_exhausted_at: 0,
@ -111,11 +111,11 @@ const currentWorkspaceValue: ICurrentWorkspace = {
const mockSetShowPricingModal = vi.fn()
const mockSetShowAccountSettingModal = vi.fn()
let mockCurrentWorkspace: ICurrentWorkspace | undefined = currentWorkspaceValue
let mockCurrentWorkspace: PostWorkspacesCurrentResponse | undefined = currentWorkspaceValue
let mockWorkspaces: IWorkspace[] = []
const mockCurrentWorkspaceQuery = (
data: ICurrentWorkspace | undefined = currentWorkspaceValue,
data: PostWorkspacesCurrentResponse | undefined = currentWorkspaceValue,
isPending = false,
) => {
mockCurrentWorkspace = isPending ? undefined : data
@ -284,13 +284,12 @@ describe('WorkspaceCard', () => {
plan: Plan.team,
})
vi.mocked(useProviderContext).mockReturnValue({
enableBilling: true,
enableBilling: false,
isEducationAccount: false,
isEducationWorkspace: false,
isFetchedPlan: true,
plan: { type: Plan.team },
plan: { type: Plan.sandbox },
} as ProviderContextState)
renderWorkspaceCard({ systemFeatures: { deployment_edition: 'CLOUD' } })
expect(screen.getByText(Plan.team)).toBeInTheDocument()
@ -304,14 +303,6 @@ describe('WorkspaceCard', () => {
...currentWorkspaceValue,
plan: Plan.team,
})
vi.mocked(useProviderContext).mockReturnValue({
enableBilling: true,
isEducationAccount: false,
isEducationWorkspace: false,
isFetchedPlan: true,
plan: { type: Plan.team },
} as ProviderContextState)
renderWorkspaceCard({ systemFeatures: { deployment_edition: 'CLOUD' } })
expect(screen.getByText(Plan.team)).toBeInTheDocument()
@ -322,14 +313,6 @@ describe('WorkspaceCard', () => {
...currentWorkspaceValue,
plan: '',
})
vi.mocked(useProviderContext).mockReturnValue({
enableBilling: true,
isEducationAccount: false,
isEducationWorkspace: false,
isFetchedPlan: false,
plan: { type: Plan.sandbox },
} as ProviderContextState)
renderWorkspaceCard({
systemFeatures: {
deployment_edition: 'ENTERPRISE',
@ -471,13 +454,10 @@ describe('WorkspaceCard', () => {
})
it('opens members settings from workspace menu when billing is disabled', async () => {
vi.mocked(useProviderContext).mockReturnValue({
enableBilling: false,
isEducationAccount: false,
isEducationWorkspace: false,
isFetchedPlan: false,
plan: { type: Plan.sandbox },
} as ProviderContextState)
mockCurrentWorkspaceQuery({
...currentWorkspaceValue,
plan: null,
})
renderWorkspaceCard()

View File

@ -16,7 +16,6 @@ import LicenseNav from '@/app/components/header/license-env'
import { buildIntegrationPath } from '@/app/components/integrations/routes'
import { useModalContext } from '@/context/modal-context'
import { workspacePermissionKeysAtom } from '@/context/permission-state'
import { useProviderContext } from '@/context/provider-context'
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
import Link from '@/next/link'
import { consoleQuery } from '@/service/client'
@ -259,26 +258,24 @@ export function WorkspaceCard() {
const switchWorkspaceMutation = useMutation(consoleQuery.workspaces.switch.post.mutationOptions())
const currentWorkspace = currentWorkspaceQuery.data
const workspaces = workspacesQuery.data?.workspaces
const { enableBilling } = useProviderContext()
const workspacePermissionKeys = useAtomValue(workspacePermissionKeysAtom)
const { setShowPricingModal, setShowAccountSettingModal } = useModalContext()
const showCloudBilling = deploymentEdition === 'CLOUD' && enableBilling
const isCloudEdition = deploymentEdition === 'CLOUD'
const prefetchWorkspaces = () => {
void queryClient.prefetchQuery(workspacesQueryOptions)
}
if (currentWorkspaceQuery.isPending || !currentWorkspace?.name) {
return (
<WorkspaceCardSkeleton
showCloudBilling={showCloudBilling}
showPlanAction={showCloudBilling}
/>
<WorkspaceCardSkeleton showCloudBilling={isCloudEdition} showPlanAction={isCloudEdition} />
)
}
const workspacePlan = isWorkspacePlan(currentWorkspace.plan) ? currentWorkspace.plan : null
const isFreePlan = workspacePlan === Plan.sandbox
const hasBillingPlan = typeof currentWorkspace.plan === 'string'
const showCloudBilling = isCloudEdition && hasBillingPlan
const showPlanAction = showCloudBilling && workspacePlan !== null
const isFreePlan = workspacePlan === Plan.sandbox
const planActionLabel = t(
($) => $[isFreePlan ? 'upgradeBtn.encourageShort' : 'upgradeBtn.plain'],
{ ns: 'billing' },
@ -286,7 +283,7 @@ export function WorkspaceCard() {
const showInviteMembers = hasPermission(workspacePermissionKeys, 'workspace.member.manage')
const renderWorkspaceStatus = () => {
if (deploymentEdition === 'CLOUD')
return enableBilling && workspacePlan ? <WorkspacePlanBadge plan={workspacePlan} /> : null
return workspacePlan ? <WorkspacePlanBadge plan={workspacePlan} /> : null
if (deploymentEdition === 'ENTERPRISE') return <LicenseNav />
return null
}
@ -333,7 +330,7 @@ export function WorkspaceCard() {
onOpenSettings={() => {
setOpen(false)
setShowAccountSettingModal({
payload: enableBilling ? ACCOUNT_SETTING_TAB.BILLING : ACCOUNT_SETTING_TAB.MEMBERS,
payload: hasBillingPlan ? ACCOUNT_SETTING_TAB.BILLING : ACCOUNT_SETTING_TAB.MEMBERS,
})
}}
onInviteMembers={() => {