From b1bb6ef977fb0e5cbc49c76582904712d2adf6a5 Mon Sep 17 00:00:00 2001 From: Stephen Zhou Date: Tue, 30 Jun 2026 18:36:38 +0800 Subject: [PATCH] perf(web): improve vinext home startup time (#38219) --- web/app/(commonLayout)/global-mounts.tsx | 21 +++++ web/app/(commonLayout)/layout.tsx | 12 +-- .../main-nav/__tests__/index.spec.tsx | 86 ++++++++++--------- .../components/snippet-detail-section.tsx | 35 ++++++++ web/app/components/main-nav/index.tsx | 41 +++------ web/i18n-config/client.ts | 7 +- web/i18n-config/load-resource.ts | 35 ++++++++ web/i18n-config/locale-resources/ar-TN.ts | 1 + web/i18n-config/locale-resources/de-DE.ts | 1 + web/i18n-config/locale-resources/en-US.ts | 1 + web/i18n-config/locale-resources/es-ES.ts | 1 + web/i18n-config/locale-resources/fa-IR.ts | 1 + web/i18n-config/locale-resources/fr-FR.ts | 1 + web/i18n-config/locale-resources/hi-IN.ts | 1 + web/i18n-config/locale-resources/id-ID.ts | 1 + web/i18n-config/locale-resources/it-IT.ts | 1 + web/i18n-config/locale-resources/ja-JP.ts | 1 + web/i18n-config/locale-resources/ko-KR.ts | 1 + web/i18n-config/locale-resources/nl-NL.ts | 1 + web/i18n-config/locale-resources/pl-PL.ts | 1 + web/i18n-config/locale-resources/pt-BR.ts | 1 + web/i18n-config/locale-resources/ro-RO.ts | 1 + web/i18n-config/locale-resources/ru-RU.ts | 1 + web/i18n-config/locale-resources/sl-SI.ts | 1 + web/i18n-config/locale-resources/th-TH.ts | 1 + web/i18n-config/locale-resources/tr-TR.ts | 1 + web/i18n-config/locale-resources/uk-UA.ts | 1 + web/i18n-config/locale-resources/vi-VN.ts | 1 + web/i18n-config/locale-resources/zh-Hans.ts | 1 + web/i18n-config/locale-resources/zh-Hant.ts | 1 + web/i18n-config/server.ts | 9 +- web/knip.config.ts | 1 + 32 files changed, 178 insertions(+), 92 deletions(-) create mode 100644 web/app/(commonLayout)/global-mounts.tsx create mode 100644 web/app/components/main-nav/components/snippet-detail-section.tsx create mode 100644 web/i18n-config/load-resource.ts create mode 100644 web/i18n-config/locale-resources/ar-TN.ts create mode 100644 web/i18n-config/locale-resources/de-DE.ts create mode 100644 web/i18n-config/locale-resources/en-US.ts create mode 100644 web/i18n-config/locale-resources/es-ES.ts create mode 100644 web/i18n-config/locale-resources/fa-IR.ts create mode 100644 web/i18n-config/locale-resources/fr-FR.ts create mode 100644 web/i18n-config/locale-resources/hi-IN.ts create mode 100644 web/i18n-config/locale-resources/id-ID.ts create mode 100644 web/i18n-config/locale-resources/it-IT.ts create mode 100644 web/i18n-config/locale-resources/ja-JP.ts create mode 100644 web/i18n-config/locale-resources/ko-KR.ts create mode 100644 web/i18n-config/locale-resources/nl-NL.ts create mode 100644 web/i18n-config/locale-resources/pl-PL.ts create mode 100644 web/i18n-config/locale-resources/pt-BR.ts create mode 100644 web/i18n-config/locale-resources/ro-RO.ts create mode 100644 web/i18n-config/locale-resources/ru-RU.ts create mode 100644 web/i18n-config/locale-resources/sl-SI.ts create mode 100644 web/i18n-config/locale-resources/th-TH.ts create mode 100644 web/i18n-config/locale-resources/tr-TR.ts create mode 100644 web/i18n-config/locale-resources/uk-UA.ts create mode 100644 web/i18n-config/locale-resources/vi-VN.ts create mode 100644 web/i18n-config/locale-resources/zh-Hans.ts create mode 100644 web/i18n-config/locale-resources/zh-Hant.ts diff --git a/web/app/(commonLayout)/global-mounts.tsx b/web/app/(commonLayout)/global-mounts.tsx new file mode 100644 index 00000000000..9da151d84f8 --- /dev/null +++ b/web/app/(commonLayout)/global-mounts.tsx @@ -0,0 +1,21 @@ +'use client' + +import dynamic from '@/next/dynamic' + +const InSiteMessageNotification = dynamic(() => import('@/app/components/app/in-site-message/notification'), { ssr: false }) +const PartnerStack = dynamic(() => import('@/app/components/billing/partner-stack'), { ssr: false }) +const ReadmePanel = dynamic(() => import('@/app/components/plugins/readme-panel'), { ssr: false }) +const WorkflowGeneratorMount = dynamic(() => import('@/app/components/workflow/workflow-generator/mount'), { ssr: false }) +const GotoAnything = dynamic(() => import('@/app/components/goto-anything').then(mod => mod.GotoAnything), { ssr: false }) + +export function CommonLayoutGlobalMounts() { + return ( + <> + + + + + + + ) +} diff --git a/web/app/(commonLayout)/layout.tsx b/web/app/(commonLayout)/layout.tsx index 69a72bdb3ee..e2d29f85d30 100644 --- a/web/app/(commonLayout)/layout.tsx +++ b/web/app/(commonLayout)/layout.tsx @@ -1,20 +1,16 @@ import type { ReactNode } from 'react' -import InSiteMessageNotification from '@/app/components/app/in-site-message/notification' import AmplitudeProvider from '@/app/components/base/amplitude' import { GoogleAnalyticsScripts } from '@/app/components/base/ga' import Zendesk from '@/app/components/base/zendesk' import { EducationVerifyActionRecorder } from '@/app/components/education-verify-action-recorder' -import { GotoAnything } from '@/app/components/goto-anything' import MainNavLayout from '@/app/components/main-nav/layout' import { NextRouteStateBridge } from '@/app/components/next-route-state' import { OAuthRegistrationAnalytics } from '@/app/components/oauth-registration-analytics' -import ReadmePanel from '@/app/components/plugins/readme-panel' -import WorkflowGeneratorMount from '@/app/components/workflow/workflow-generator/mount' import { AppContextProvider } from '@/context/app-context-provider' import { EventEmitterContextProvider } from '@/context/event-emitter-provider' import { ModalContextProvider } from '@/context/modal-context-provider' import { ProviderContextProvider } from '@/context/provider-context-provider' -import PartnerStack from '../components/billing/partner-stack' +import { CommonLayoutGlobalMounts } from './global-mounts' import { CommonLayoutHydrationBoundary } from './hydration-boundary' export default async function Layout({ children }: { children: ReactNode }) { @@ -33,11 +29,7 @@ export default async function Layout({ children }: { children: ReactNode }) { {children} - - - - - + diff --git a/web/app/components/main-nav/__tests__/index.spec.tsx b/web/app/components/main-nav/__tests__/index.spec.tsx index 8846220c21c..d1722533b9a 100644 --- a/web/app/components/main-nav/__tests__/index.spec.tsx +++ b/web/app/components/main-nav/__tests__/index.spec.tsx @@ -495,7 +495,7 @@ describe('MainNav', () => { expect(screen.queryByRole('link', { name: /common.menus.deployments/ })).not.toBeInTheDocument() }) - it('aligns the global navigation spacing with the main sidebar design', () => { + it('aligns the global navigation spacing with the main sidebar design', async () => { mockInstalledApps = [createInstalledApp()] renderMainNav() @@ -508,7 +508,7 @@ describe('MainNav', () => { expect(homeLink.closest('nav')).toHaveClass('isolate', 'flex', 'flex-col', 'gap-px', 'p-2') expect(homeLink).toHaveClass('h-8', 'w-full', 'rounded-[10px]', 'px-2', 'py-1.5') - const webAppsButton = screen.getByRole('button', { name: 'explore.sidebar.webApps' }) + const webAppsButton = await screen.findByRole('button', { name: 'explore.sidebar.webApps' }) expect(webAppsButton.parentElement).toHaveClass('py-1', 'pr-2', 'pl-2') const helpButton = screen.getByRole('button', { name: 'common.mainNav.help.openMenu' }) @@ -551,7 +551,7 @@ describe('MainNav', () => { expect(container.querySelector('.relative.z-30')).not.toBeInTheDocument() }) - it('hides the environment tag when app detail navigation is collapsed', () => { + it('hides the environment tag when app detail navigation is collapsed', async () => { mockPathname = '/app/app-1/overview' ;(useAppContext as Mock).mockReturnValue({ ...appContextValue, @@ -562,7 +562,7 @@ describe('MainNav', () => { }) const { container } = renderMainNav() - fireEvent.click(screen.getByTestId('app-detail-toggle')) + fireEvent.click(await screen.findByTestId('app-detail-toggle')) expect(screen.queryByText('common.environment.testing')).not.toBeInTheDocument() expect(container.querySelector('.relative.z-30')).not.toBeInTheDocument() @@ -659,7 +659,7 @@ describe('MainNav', () => { expect(screen.getByRole('link', { name: /common.mainNav.home/ })).not.toHaveAttribute('aria-current') }) - it('replaces global navigation with snippet detail navigation on snippet routes', () => { + it('replaces global navigation with snippet detail navigation on snippet routes', async () => { mockPathname = '/snippets/snippet-1/orchestrate' snippetDraftState.inputFields = snippetFields snippetNavigationState.onFieldsChange = mockSnippetFieldsChange @@ -671,8 +671,8 @@ describe('MainNav', () => { expect(screen.getByRole('complementary')).toHaveClass('w-62') expect(screen.getByRole('complementary')).toHaveClass('p-1') expect(screen.getByRole('complementary')).toHaveClass('bg-background-body') - expect(screen.getByTestId('snippet-detail-top')).toHaveAttribute('data-expand', 'true') - expect(screen.getByTestId('snippet-sidebar-content')).toHaveAttribute('data-readonly', 'false') + expect(await screen.findByTestId('snippet-detail-top')).toHaveAttribute('data-expand', 'true') + expect(await screen.findByTestId('snippet-sidebar-content')).toHaveAttribute('data-readonly', 'false') expect(screen.getByText(snippet.name)).toBeInTheDocument() expect(screen.getByText('query')).toBeInTheDocument() fireEvent.click(screen.getByRole('button', { name: 'change snippet fields' })) @@ -686,14 +686,14 @@ describe('MainNav', () => { expect(screen.getByRole('button', { name: 'common.mainNav.help.openMenu' })).toBeInTheDocument() }) - it('collapses snippet detail navigation from the top-right toggle', () => { + it('collapses snippet detail navigation from the top-right toggle', async () => { mockPathname = '/snippets/snippet-1/orchestrate' snippetDraftState.inputFields = snippetFields snippetNavigationState.onFieldsChange = mockSnippetFieldsChange snippetNavigationState.snippet = snippet renderMainNav() - fireEvent.click(screen.getByTestId('snippet-detail-toggle')) + fireEvent.click(await screen.findByTestId('snippet-detail-toggle')) expect(screen.getByRole('complementary')).toHaveClass('w-16') expect(screen.getByRole('complementary')).toHaveClass('p-1') @@ -704,13 +704,13 @@ describe('MainNav', () => { expect(localStorage.getItem(DETAIL_SIDEBAR_STORAGE_KEY)).toBe('collapse') }) - it('replaces global navigation with app detail navigation on app routes', () => { + it('replaces global navigation with app detail navigation on app routes', async () => { mockPathname = '/app/app-1/overview' renderMainNav() - expect(screen.getByTestId('app-detail-top')).toBeInTheDocument() - expect(screen.getByTestId('app-detail-section')).toBeInTheDocument() + expect(await screen.findByTestId('app-detail-top')).toBeInTheDocument() + expect(await screen.findByTestId('app-detail-section')).toBeInTheDocument() expect(screen.getByTestId('app-detail-top')).toHaveAttribute('data-expand', 'true') expect(screen.getByTestId('app-detail-section')).toHaveAttribute('data-expand', 'true') expect(screen.getByRole('complementary')).toHaveClass('w-62') @@ -742,56 +742,56 @@ describe('MainNav', () => { }) }) - it('collapses app detail navigation from the top-right toggle', () => { + it('collapses app detail navigation from the top-right toggle', async () => { mockPathname = '/app/app-1/overview' renderMainNav() - fireEvent.click(screen.getByTestId('app-detail-toggle')) + fireEvent.click(await screen.findByTestId('app-detail-toggle')) expect(screen.getByRole('complementary')).toHaveClass('w-16') expect(screen.getByRole('complementary')).not.toHaveClass('transition-none') expect(screen.getByRole('complementary')).toHaveClass('p-1') expect(screen.getByTestId('app-detail-top')).toHaveAttribute('data-expand', 'false') - expect(screen.getByTestId('app-detail-section')).toHaveAttribute('data-expand', 'false') + expect(await screen.findByTestId('app-detail-section')).toHaveAttribute('data-expand', 'false') expect(localStorage.getItem(DETAIL_SIDEBAR_STORAGE_KEY)).toBe('collapse') }) - it('shows app detail navigation as a floating preview when hovering the collapsed top toggle', () => { + it('shows app detail navigation as a floating preview when hovering the collapsed top toggle', async () => { mockPathname = '/app/app-1/overview' renderMainNav() - fireEvent.click(screen.getByTestId('app-detail-toggle')) + fireEvent.click(await screen.findByTestId('app-detail-toggle')) fireEvent.mouseEnter(screen.getByTestId('app-detail-top').parentElement!) expect(screen.getByRole('complementary')).toHaveClass('w-16', 'overflow-visible') expect(localStorage.getItem(DETAIL_SIDEBAR_STORAGE_KEY)).toBe('collapse') expect(screen.getAllByTestId('app-detail-top')).toHaveLength(1) expect(screen.getByTestId('app-detail-top')).toHaveAttribute('data-expand', 'true') - expect(screen.getByTestId('app-detail-section')).toHaveAttribute('data-expand', 'true') + expect(await screen.findByTestId('app-detail-section')).toHaveAttribute('data-expand', 'true') }) - it('persists expanded app detail navigation without width animation when clicking the hovered toggle', () => { + it('persists expanded app detail navigation without width animation when clicking the hovered toggle', async () => { mockPathname = '/app/app-1/overview' renderMainNav() - fireEvent.click(screen.getByTestId('app-detail-toggle')) + fireEvent.click(await screen.findByTestId('app-detail-toggle')) fireEvent.mouseEnter(screen.getByTestId('app-detail-top').parentElement!) fireEvent.click(screen.getByTestId('app-detail-toggle')) expect(screen.getByRole('complementary')).toHaveClass('w-62', 'transition-none') expect(screen.getByRole('complementary')).not.toHaveClass('overflow-visible') expect(screen.getByTestId('app-detail-top')).toHaveAttribute('data-expand', 'true') - expect(screen.getByTestId('app-detail-section')).toHaveAttribute('data-expand', 'true') + expect(await screen.findByTestId('app-detail-section')).toHaveAttribute('data-expand', 'true') expect(localStorage.getItem(DETAIL_SIDEBAR_STORAGE_KEY)).toBe('expand') }) - it('replaces global navigation with dataset detail navigation on dataset routes', () => { + it('replaces global navigation with dataset detail navigation on dataset routes', async () => { mockPathname = '/datasets/dataset-1/documents' renderMainNav() - expect(screen.getByTestId('dataset-detail-top')).toBeInTheDocument() - expect(screen.getByTestId('dataset-detail-section')).toBeInTheDocument() + expect(await screen.findByTestId('dataset-detail-top')).toBeInTheDocument() + expect(await screen.findByTestId('dataset-detail-section')).toBeInTheDocument() expect(screen.getByTestId('dataset-detail-top')).toHaveAttribute('data-expand', 'true') expect(screen.getByTestId('dataset-detail-section')).toHaveAttribute('data-expand', 'true') expect(screen.getByRole('complementary')).toHaveClass('w-62') @@ -802,42 +802,44 @@ describe('MainNav', () => { expect(screen.queryByRole('link', { name: /common.menus.datasets/ })).not.toBeInTheDocument() }) - it('collapses dataset detail navigation from the top-right toggle', () => { + it('collapses dataset detail navigation from the top-right toggle', async () => { mockPathname = '/datasets/dataset-1/documents' renderMainNav() - fireEvent.click(screen.getByTestId('dataset-detail-toggle')) + fireEvent.click(await screen.findByTestId('dataset-detail-toggle')) expect(screen.getByRole('complementary')).toHaveClass('w-16') expect(screen.getByRole('complementary')).toHaveClass('p-1') expect(screen.getByTestId('dataset-detail-top')).toHaveAttribute('data-expand', 'false') - expect(screen.getByTestId('dataset-detail-section')).toHaveAttribute('data-expand', 'false') + expect(await screen.findByTestId('dataset-detail-section')).toHaveAttribute('data-expand', 'false') expect(localStorage.getItem(DETAIL_SIDEBAR_STORAGE_KEY)).toBe('collapse') }) - it('shows dataset detail navigation as a floating preview when hovering the collapsed top toggle', () => { + it('shows dataset detail navigation as a floating preview when hovering the collapsed top toggle', async () => { mockPathname = '/datasets/dataset-1/documents' renderMainNav() - fireEvent.click(screen.getByTestId('dataset-detail-toggle')) + fireEvent.click(await screen.findByTestId('dataset-detail-toggle')) fireEvent.mouseEnter(screen.getByTestId('dataset-detail-top').parentElement!) expect(screen.getByRole('complementary')).toHaveClass('w-16', 'overflow-visible') expect(localStorage.getItem(DETAIL_SIDEBAR_STORAGE_KEY)).toBe('collapse') expect(screen.getAllByTestId('dataset-detail-top')).toHaveLength(1) expect(screen.getByTestId('dataset-detail-top')).toHaveAttribute('data-expand', 'true') - expect(screen.getByTestId('dataset-detail-section')).toHaveAttribute('data-expand', 'true') + expect(await screen.findByTestId('dataset-detail-section')).toHaveAttribute('data-expand', 'true') }) - it('replaces global navigation with agent detail navigation on roster detail routes', () => { + it('replaces global navigation with agent detail navigation on roster detail routes', async () => { mockPathname = '/roster/agent/agent-1/configure' renderMainNav() - expect(screen.getByTestId('agent-detail-top')).toBeInTheDocument() - expect(screen.getByTestId('agent-detail-section')).toBeInTheDocument() + expect(await screen.findByTestId('agent-detail-top')).toBeInTheDocument() + const agentDetailNavigation = await screen.findByRole('navigation', { name: 'agentV2.agentDetail.navigationLabel' }) + expect(agentDetailNavigation).toBeInTheDocument() + expect(screen.getByRole('link', { name: /agentV2.agentDetail.sections.configure/ })).toHaveAttribute('href', '/roster/agent/agent-1/configure') expect(screen.getByTestId('agent-detail-top')).toHaveAttribute('data-expand', 'true') - expect(screen.getByTestId('agent-detail-section')).toHaveAttribute('data-expand', 'true') + expect(agentDetailNavigation).toHaveClass('px-1') expect(screen.getByRole('complementary')).toHaveClass('w-62') expect(screen.getByRole('complementary')).toHaveClass('p-1') expect(screen.getByRole('complementary')).toHaveClass('bg-background-body') @@ -873,16 +875,16 @@ describe('MainNav', () => { expect(screen.queryByRole('link', { name: /common.menus.deployments/ })).not.toBeInTheDocument() }) - it('collapses agent detail navigation from the top-right toggle', () => { + it('collapses agent detail navigation from the top-right toggle', async () => { mockPathname = '/roster/agent/agent-1/configure' renderMainNav() - fireEvent.click(screen.getByTestId('agent-detail-toggle')) + fireEvent.click(await screen.findByTestId('agent-detail-toggle')) expect(screen.getByRole('complementary')).toHaveClass('w-16') expect(screen.getByRole('complementary')).toHaveClass('p-1') expect(screen.getByTestId('agent-detail-top')).toHaveAttribute('data-expand', 'false') - expect(screen.getByTestId('agent-detail-section')).toHaveAttribute('data-expand', 'false') + expect(await screen.findByRole('navigation', { name: 'agentV2.agentDetail.navigationLabel' })).toHaveClass('px-3') expect(localStorage.getItem(DETAIL_SIDEBAR_STORAGE_KEY)).toBe('collapse') }) @@ -923,18 +925,18 @@ describe('MainNav', () => { ) }) - it('shows agent detail navigation as a floating preview when hovering the collapsed top toggle', () => { + it('shows agent detail navigation as a floating preview when hovering the collapsed top toggle', async () => { mockPathname = '/roster/agent/agent-1/configure' renderMainNav() - fireEvent.click(screen.getByTestId('agent-detail-toggle')) + fireEvent.click(await screen.findByTestId('agent-detail-toggle')) fireEvent.mouseEnter(screen.getByTestId('agent-detail-top').parentElement!) expect(screen.getByRole('complementary')).toHaveClass('w-16', 'overflow-visible') expect(localStorage.getItem(DETAIL_SIDEBAR_STORAGE_KEY)).toBe('collapse') expect(screen.getAllByTestId('agent-detail-top')).toHaveLength(1) expect(screen.getByTestId('agent-detail-top')).toHaveAttribute('data-expand', 'true') - expect(screen.getByTestId('agent-detail-section')).toHaveAttribute('data-expand', 'true') + expect(await screen.findByRole('navigation', { name: 'agentV2.agentDetail.navigationLabel' })).toHaveClass('px-1') }) it.each([ @@ -1258,12 +1260,12 @@ describe('MainNav', () => { } }) - it('collapses and expands installed web apps from the section arrow', () => { + it('collapses and expands installed web apps from the section arrow', async () => { mockInstalledApps = [createInstalledApp()] renderMainNav() - const webAppsButton = screen.getByRole('button', { name: 'explore.sidebar.webApps' }) + const webAppsButton = await screen.findByRole('button', { name: 'explore.sidebar.webApps' }) expect(webAppsButton).toHaveAttribute('aria-expanded', 'true') expect(screen.getByText('Alpha App')).toBeInTheDocument() diff --git a/web/app/components/main-nav/components/snippet-detail-section.tsx b/web/app/components/main-nav/components/snippet-detail-section.tsx new file mode 100644 index 00000000000..e9798a903d5 --- /dev/null +++ b/web/app/components/main-nav/components/snippet-detail-section.tsx @@ -0,0 +1,35 @@ +'use client' + +import { useShallow } from 'zustand/react/shallow' +import { SnippetCollapsedPreview } from '@/app/components/snippets/components/snippet-collapsed-preview' +import { SnippetSidebarContent } from '@/app/components/snippets/components/snippet-sidebar' +import { useSnippetDraftStore } from '@/app/components/snippets/draft-store' +import { useSnippetDetailStore } from '@/app/components/snippets/store' + +type SnippetDetailSectionProps = { + expand: boolean +} + +export function SnippetDetailSection({ expand }: SnippetDetailSectionProps) { + const snippetNavigation = useSnippetDetailStore(useShallow(state => ({ + onFieldsChange: state.onFieldsChange, + readonly: state.readonly, + snippet: state.snippet, + }))) + const snippetInputFields = useSnippetDraftStore(state => state.inputFields) + + if (!expand) + return + + if (!snippetNavigation.snippet || !snippetNavigation.onFieldsChange) + return null + + return ( + + ) +} diff --git a/web/app/components/main-nav/index.tsx b/web/app/components/main-nav/index.tsx index 9caa2900bb2..19e0872b7b1 100644 --- a/web/app/components/main-nav/index.tsx +++ b/web/app/components/main-nav/index.tsx @@ -7,31 +7,21 @@ import { useSuspenseQuery } from '@tanstack/react-query' import { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' import { useShallow } from 'zustand/react/shallow' -import AppDetailSection from '@/app/components/app-sidebar/app-detail-section' -import AppDetailTop from '@/app/components/app-sidebar/app-detail-top' -import DatasetDetailSection from '@/app/components/app-sidebar/dataset-detail-section' -import DatasetDetailTop from '@/app/components/app-sidebar/dataset-detail-top' import { useStore as useAppStore } from '@/app/components/app/store' import Badge from '@/app/components/base/badge' import DifyLogo from '@/app/components/base/logo/dify-logo' import EnvNav from '@/app/components/header/env-nav' -import { SnippetCollapsedPreview } from '@/app/components/snippets/components/snippet-collapsed-preview' -import { SnippetSidebarContent } from '@/app/components/snippets/components/snippet-sidebar' -import { useSnippetDraftStore } from '@/app/components/snippets/draft-store' -import { useSnippetDetailStore } from '@/app/components/snippets/store' import { useAppContext } from '@/context/app-context' -import { AgentDetailSection, AgentDetailTop } from '@/features/agent-v2/agent-detail/navigation' import { isAgentV2Enabled } from '@/features/agent-v2/feature-flag' import { DeploymentDetailSection, DeploymentDetailTop } from '@/features/deployments/detail/deployment-sidebar' import { systemFeaturesQueryOptions } from '@/features/system-features/client' +import dynamic from '@/next/dynamic' import Link from '@/next/link' import { usePathname } from '@/next/navigation' import AccountSection from './components/account-section' import HelpMenu from './components/help-menu' import MainNavLink from './components/nav-link' import { MainNavSearchButton } from './components/search-button' -import SnippetDetailTop from './components/snippet-detail-top' -import WebAppsSection from './components/web-apps-section' import { WorkspaceCard } from './components/workspace-card' import { isMainNavRouteVisible, MAIN_NAV_ROUTES } from './routes' import { useDetailSidebarMode } from './storage' @@ -41,6 +31,16 @@ const DATASET_DOCUMENT_CREATION_ROUTES = new Set(['create', 'create-from-pipelin const DEPLOYMENT_COLLECTION_ROUTES = new Set(['create']) const secondarySidebarHelpTriggerIcon = +const AppDetailSection = dynamic(() => import('@/app/components/app-sidebar/app-detail-section'), { ssr: false }) +const AppDetailTop = dynamic(() => import('@/app/components/app-sidebar/app-detail-top'), { ssr: false }) +const DatasetDetailSection = dynamic(() => import('@/app/components/app-sidebar/dataset-detail-section'), { ssr: false }) +const DatasetDetailTop = dynamic(() => import('@/app/components/app-sidebar/dataset-detail-top'), { ssr: false }) +const AgentDetailSection = dynamic(() => import('@/features/agent-v2/agent-detail/navigation').then(mod => mod.AgentDetailSection), { ssr: false }) +const AgentDetailTop = dynamic(() => import('@/features/agent-v2/agent-detail/navigation').then(mod => mod.AgentDetailTop), { ssr: false }) +const SnippetDetailTop = dynamic(() => import('./components/snippet-detail-top'), { ssr: false }) +const SnippetDetailSection = dynamic(() => import('./components/snippet-detail-section').then(mod => mod.SnippetDetailSection), { ssr: false }) +const WebAppsSection = dynamic(() => import('./components/web-apps-section'), { ssr: false }) + function SecondarySidebarHelpMenu({ triggerClassName, }: { @@ -103,12 +103,6 @@ export function MainNav({ const showDeploymentDetailNavigation = canUseAppDeploy && !isCurrentWorkspaceDatasetOperator && isDeploymentDetailPathname(pathname) const showSnippetDetailNavigation = isSnippetDetailPathname(pathname) const showDetailNavigation = showAppDetailNavigation || showDatasetDetailNavigation || showAgentDetailNavigation || showDeploymentDetailNavigation || showSnippetDetailNavigation - const snippetNavigation = useSnippetDetailStore(useShallow(state => ({ - onFieldsChange: state.onFieldsChange, - readonly: state.readonly, - snippet: state.snippet, - }))) - const snippetInputFields = useSnippetDraftStore(state => state.inputFields) const { hasAppDetail, setAppDetail } = useAppStore(useShallow(state => ({ hasAppDetail: !!state.appDetail, setAppDetail: state.setAppDetail, @@ -307,18 +301,7 @@ export function MainNav({ ? : showDeploymentDetailNavigation ? - : detailNavigationVisibleExpanded - ? snippetNavigation.snippet && snippetNavigation.onFieldsChange - ? ( - - ) - : null - : + : : ( <>