diff --git a/packages/iconify-collections/assets/vender/main-nav/home-active.svg b/packages/iconify-collections/assets/vender/main-nav/home-active.svg index ce1204492c..13dc13e094 100644 --- a/packages/iconify-collections/assets/vender/main-nav/home-active.svg +++ b/packages/iconify-collections/assets/vender/main-nav/home-active.svg @@ -1,5 +1,5 @@ - + diff --git a/packages/iconify-collections/assets/vender/main-nav/integrations-active.svg b/packages/iconify-collections/assets/vender/main-nav/integrations-active.svg index a7367871d1..351802502f 100644 --- a/packages/iconify-collections/assets/vender/main-nav/integrations-active.svg +++ b/packages/iconify-collections/assets/vender/main-nav/integrations-active.svg @@ -1,5 +1,5 @@ - + diff --git a/packages/iconify-collections/assets/vender/main-nav/studio-active.svg b/packages/iconify-collections/assets/vender/main-nav/studio-active.svg index 59826145ab..2441d4760c 100644 --- a/packages/iconify-collections/assets/vender/main-nav/studio-active.svg +++ b/packages/iconify-collections/assets/vender/main-nav/studio-active.svg @@ -1,5 +1,5 @@ - + diff --git a/packages/iconify-collections/custom-vender/icons.json b/packages/iconify-collections/custom-vender/icons.json index 5293600cfc..55d525a7d8 100644 --- a/packages/iconify-collections/custom-vender/icons.json +++ b/packages/iconify-collections/custom-vender/icons.json @@ -1,6 +1,6 @@ { "prefix": "custom-vender", - "lastModified": 1778201271, + "lastModified": 1778535177, "icons": { "features-citations": { "body": "", @@ -697,7 +697,7 @@ "height": 20 }, "main-nav-home-active": { - "body": "", + "body": "", "width": 20, "height": 20 }, @@ -707,7 +707,7 @@ "height": 20 }, "main-nav-integrations-active": { - "body": "", + "body": "", "width": 20, "height": 20 }, @@ -742,7 +742,7 @@ "height": 20 }, "main-nav-studio-active": { - "body": "", + "body": "", "width": 20, "height": 20 }, diff --git a/web/app/components/main-nav/__tests__/index.spec.tsx b/web/app/components/main-nav/__tests__/index.spec.tsx index c1f16fe396..71c1a00a2c 100644 --- a/web/app/components/main-nav/__tests__/index.spec.tsx +++ b/web/app/components/main-nav/__tests__/index.spec.tsx @@ -154,9 +154,9 @@ const appContextValue: AppContextValue = { isValidatingCurrentWorkspace: false, } -const renderMainNav = () => renderWithSystemFeatures(, { - systemFeatures: { branding: { enabled: false } }, -}) +const renderMainNav = ( + systemFeatures = { branding: { enabled: false } }, +) => renderWithSystemFeatures(, { systemFeatures }) describe('MainNav', () => { beforeEach(() => { @@ -321,7 +321,6 @@ describe('MainNav', () => { const homeLink = screen.getByRole('link', { name: /common.mainNav.home/ }) expect(homeLink).toHaveClass( - 'border-transparent', 'backdrop-blur-[5px]', 'text-saas-dify-blue-inverted', activeEdgeClassName, @@ -357,13 +356,19 @@ describe('MainNav', () => { expect(mockPush).not.toHaveBeenCalled() }) - it('opens workspace settings, members, provider credits, upgrade, and workspace switching actions', async () => { + it('hides the help menu when branding is enabled', () => { + renderMainNav({ branding: { enabled: true } }) + + expect(screen.queryByRole('button', { name: 'common.mainNav.help.openMenu' })).not.toBeInTheDocument() + }) + + it('opens workspace settings, members, provider credits, plan, and workspace switching actions', async () => { renderMainNav() fireEvent.click(screen.getByRole('button', { name: /common\.mainNav\.workspace\.credits|7,500 credits/ })) expect(mockSetShowAccountSettingModal).toHaveBeenCalledWith({ payload: ACCOUNT_SETTING_TAB.PROVIDER }) - fireEvent.click(screen.getByText('billing.upgradeBtn.encourageShort')) + fireEvent.click(screen.getByText('billing.upgradeBtn.plain')) expect(mockSetShowPricingModal).toHaveBeenCalled() fireEvent.click(screen.getByRole('button', { name: 'common.mainNav.workspace.openMenu' })) @@ -381,7 +386,20 @@ describe('MainNav', () => { }) }) - it('hides the upgrade shortcut for paid plans', () => { + it('shows the upgrade shortcut for sandbox workspaces', () => { + ;(useWorkspacesContext as Mock).mockReturnValue({ + workspaces: [ + { id: 'workspace-1', name: 'Solar Studio', plan: Plan.sandbox, status: 'normal', created_at: 0, current: true }, + ], + }) + + renderMainNav() + + expect(screen.getByText('billing.upgradeBtn.encourageShort')).toBeInTheDocument() + expect(screen.queryByText('billing.upgradeBtn.plain')).not.toBeInTheDocument() + }) + + it('shows the view plan shortcut for paid workspaces', () => { ;(useProviderContext as Mock).mockReturnValue({ enableBilling: true, isEducationAccount: false, @@ -393,6 +411,9 @@ describe('MainNav', () => { renderMainNav() expect(screen.queryByText('billing.upgradeBtn.encourageShort')).not.toBeInTheDocument() + fireEvent.click(screen.getByText('billing.upgradeBtn.plain')) + expect(mockSetShowPricingModal).toHaveBeenCalled() + expect(mockSetShowAccountSettingModal).not.toHaveBeenCalledWith({ payload: ACCOUNT_SETTING_TAB.BILLING }) }) it('limits workspace settings and invite actions by role', async () => { diff --git a/web/app/components/main-nav/__tests__/layout.spec.tsx b/web/app/components/main-nav/__tests__/layout.spec.tsx index f74d016da9..41b4a7a928 100644 --- a/web/app/components/main-nav/__tests__/layout.spec.tsx +++ b/web/app/components/main-nav/__tests__/layout.spec.tsx @@ -58,14 +58,14 @@ describe('MainNavLayout', () => { expect(screen.getByText('content')).toBeInTheDocument() }) - it('keeps the current header on mobile', () => { + it('uses the main nav on mobile too', () => { mockMediaType = MediaType.mobile render(
content
) - expect(screen.getByTestId('header-wrapper')).toBeInTheDocument() - expect(screen.getByTestId('desktop-header')).toBeInTheDocument() - expect(screen.queryByTestId('main-nav')).not.toBeInTheDocument() + expect(screen.getByTestId('main-nav')).toBeInTheDocument() + expect(screen.queryByTestId('header-wrapper')).not.toBeInTheDocument() + expect(screen.queryByTestId('desktop-header')).not.toBeInTheDocument() }) it('hides the desktop main nav on fullscreen workflow canvases', () => { diff --git a/web/app/components/main-nav/components/help-menu.tsx b/web/app/components/main-nav/components/help-menu.tsx index 644eb8bc17..a508bc22a7 100644 --- a/web/app/components/main-nav/components/help-menu.tsx +++ b/web/app/components/main-nav/components/help-menu.tsx @@ -36,6 +36,9 @@ const HelpMenu = () => { const [aboutVisible, setAboutVisible] = useState(false) const [open, setOpen] = useState(false) + if (systemFeatures.branding.enabled) + return null + return ( <> @@ -54,76 +57,74 @@ const HelpMenu = () => { sideOffset={8} popupClassName="w-60 overflow-hidden bg-components-panel-bg-blur! p-0! backdrop-blur-[5px]" > - {!systemFeatures.branding.enabled && ( - <> - - + <> + + + } + /> + +
+ + + {t('mainNav.help.learnDify', { ns: 'common' })} + + event.stopPropagation()} + onCheckedChange={checked => setLearnDifyHidden(!checked)} + /> +
+ setOpen(false)} /> + {IS_CLOUD_EDITION && isCurrentWorkspaceOwner && } +
+ + + + } + /> + + + + + + + )} + /> + + {env.NEXT_PUBLIC_SITE_ABOUT !== 'hide' && ( + { + setAboutVisible(true) + setOpen(false) + }} + > } - /> -
-
- - - {t('mainNav.help.learnDify', { ns: 'common' })} - - event.stopPropagation()} - onCheckedChange={checked => setLearnDifyHidden(!checked)} - /> -
- setOpen(false)} /> - {IS_CLOUD_EDITION && isCurrentWorkspaceOwner && } -
- - - - } - /> - - - - - +
+
{t('about.version', { ns: 'common', version: langGeniusVersionInfo.current_version })}
+
)} /> -
- {env.NEXT_PUBLIC_SITE_ABOUT !== 'hide' && ( - { - setAboutVisible(true) - setOpen(false) - }} - > - -
{t('about.version', { ns: 'common', version: langGeniusVersionInfo.current_version })}
- - - )} - /> -
- )} -
- - )} + + )} + +
{aboutVisible && setAboutVisible(false)} langGeniusVersionInfo={langGeniusVersionInfo} />} diff --git a/web/app/components/main-nav/components/nav-link.tsx b/web/app/components/main-nav/components/nav-link.tsx index 0e4098e8c6..39a3b16b92 100644 --- a/web/app/components/main-nav/components/nav-link.tsx +++ b/web/app/components/main-nav/components/nav-link.tsx @@ -7,7 +7,7 @@ import Link from '@/next/link' const navItemClassName = 'group relative flex h-9 items-center gap-2 rounded-xl p-2 transition-colors' const activeNavItemClassName = cn( - 'overflow-hidden border border-transparent', + 'overflow-hidden', 'bg-[linear-gradient(98.077deg,rgba(0,51,255,0.08)_0%,rgba(0,51,255,0.12)_17.98%,rgba(0,51,255,0.1)_58.75%,rgba(0,51,255,0.08)_101.09%)]', 'system-md-semibold text-saas-dify-blue-inverted backdrop-blur-[5px]', 'shadow-[0px_4px_8px_0px_rgba(255,255,255,0),0px_12px_16px_-4px_rgba(9,9,11,0.08),0px_4px_6px_-2px_rgba(9,9,11,0.03),0px_10px_16px_-4px_rgba(0,51,255,0.06)]', diff --git a/web/app/components/main-nav/components/workspace-card.tsx b/web/app/components/main-nav/components/workspace-card.tsx index d627670a0a..a81d663280 100644 --- a/web/app/components/main-nav/components/workspace-card.tsx +++ b/web/app/components/main-nav/components/workspace-card.tsx @@ -60,18 +60,16 @@ const WorkspaceCard = () => { const credits = getRemainingCredits(currentWorkspace.trial_credits, currentWorkspace.trial_credits_used) const formattedCredits = formatCredits(credits) const workspacePlan = (workspaces.find(workspace => workspace.current)?.plan || currentWorkspace.plan || plan.type) as Plan - const isFreePlan = plan.type === Plan.sandbox + const isFreePlan = workspacePlan === Plan.sandbox const showCloudBilling = IS_CLOUD_EDITION && enableBilling - const showUpgradeAction = showCloudBilling && isFreePlan + const showPlanAction = showCloudBilling + const planActionLabel = t(isFreePlan ? 'upgradeBtn.encourageShort' : 'upgradeBtn.plain', { ns: 'billing' }) const showWorkspaceSettings = !isCurrentWorkspaceDatasetOperator const showInviteMembers = showWorkspaceSettings && isCurrentWorkspaceManager const renderWorkspaceStatus = () => enableBilling ? : const handlePlanClick = () => { - if (isFreePlan) - setShowPricingModal() - else - setShowAccountSettingModal({ payload: ACCOUNT_SETTING_TAB.BILLING }) + setShowPricingModal() } const handleSwitchWorkspace = async (tenant_id: string) => { @@ -135,17 +133,17 @@ const WorkspaceCard = () => { {formattedCredits} {t('mainNav.workspace.creditsUnit', { ns: 'common' })} - {showUpgradeAction && ( + {showPlanAction && ( )} diff --git a/web/app/components/main-nav/layout.tsx b/web/app/components/main-nav/layout.tsx index df8e046c97..c6f081aa7a 100644 --- a/web/app/components/main-nav/layout.tsx +++ b/web/app/components/main-nav/layout.tsx @@ -4,11 +4,8 @@ import type { ReactNode } from 'react' import type { EventEmitterValue } from '@/context/event-emitter' import { cn } from '@langgenius/dify-ui/cn' import { useState } from 'react' -import Header from '@/app/components/header' -import HeaderWrapper from '@/app/components/header/header-wrapper' import { useEventEmitterContextContext } from '@/context/event-emitter' import { WorkspaceProvider } from '@/context/workspace-context-provider' -import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints' import { usePathname } from '@/next/navigation' import MainNav from './index' @@ -19,8 +16,6 @@ type MainNavLayoutProps = { const MainNavLayout = ({ children, }: MainNavLayoutProps) => { - const media = useBreakpoints() - const isMobile = media === MediaType.mobile const pathname = usePathname() const inWorkflowCanvas = pathname.endsWith('/workflow') const isPipelineCanvas = pathname.endsWith('/pipeline') @@ -34,17 +29,6 @@ const MainNavLayout = ({ setHideMainNav(v.payload) }) - if (isMobile) { - return ( - <> - -
- - {children} - - ) - } - return (