diff --git a/eslint-suppressions.json b/eslint-suppressions.json
index 9cb80eb758..87230e947e 100644
--- a/eslint-suppressions.json
+++ b/eslint-suppressions.json
@@ -192,11 +192,6 @@
"count": 1
}
},
- "web/app/(commonLayout)/snippets/[snippetId]/page.tsx": {
- "no-restricted-imports": {
- "count": 1
- }
- },
"web/app/(shareLayout)/components/authenticated-layout.tsx": {
"jsx-a11y/click-events-have-key-events": {
"count": 1
diff --git a/web/app/(commonLayout)/snippets/[snippetId]/page.tsx b/web/app/(commonLayout)/snippets/[snippetId]/page.tsx
index 3b35e29360..2aea2751f0 100644
--- a/web/app/(commonLayout)/snippets/[snippetId]/page.tsx
+++ b/web/app/(commonLayout)/snippets/[snippetId]/page.tsx
@@ -1,4 +1,4 @@
-import { redirect } from 'next/navigation'
+import { redirect } from '@/next/navigation'
const Page = async (props: {
params: Promise<{ snippetId: string }>
diff --git a/web/app/components/apps/__tests__/list.spec.tsx b/web/app/components/apps/__tests__/list.spec.tsx
index 52af9b17f4..22c86a1fbe 100644
--- a/web/app/components/apps/__tests__/list.spec.tsx
+++ b/web/app/components/apps/__tests__/list.spec.tsx
@@ -417,15 +417,17 @@ describe('List', () => {
expect(screen.getByRole('button', { name: 'common.operation.create' }))!.toBeInTheDocument()
})
- it('should render link to snippets before the create button', () => {
+ it('should render sort filter before search and the snippets link', () => {
renderList()
const sortButton = screen.getByRole('button', { name: 'Sort by Last modified' })
+ const searchInput = screen.getByRole('searchbox', { name: 'app.gotoAnything.actions.searchApplications' })
const snippetsLink = screen.getByRole('link', { name: 'app.studio.viewSnippets' })
const createButton = screen.getByRole('button', { name: 'common.operation.create' })
expect(snippetsLink).toHaveAttribute('href', '/snippets')
- expect(sortButton.compareDocumentPosition(snippetsLink) & Node.DOCUMENT_POSITION_FOLLOWING).toBeTruthy()
+ expect(sortButton.compareDocumentPosition(searchInput) & Node.DOCUMENT_POSITION_FOLLOWING).toBeTruthy()
+ expect(searchInput.compareDocumentPosition(snippetsLink) & Node.DOCUMENT_POSITION_FOLLOWING).toBeTruthy()
expect(snippetsLink.compareDocumentPosition(createButton) & Node.DOCUMENT_POSITION_FOLLOWING).toBeTruthy()
})
diff --git a/web/app/components/apps/app-list-header-filters.tsx b/web/app/components/apps/app-list-header-filters.tsx
index b0a2319dad..df32f57d7b 100644
--- a/web/app/components/apps/app-list-header-filters.tsx
+++ b/web/app/components/apps/app-list-header-filters.tsx
@@ -62,6 +62,7 @@ export function AppListHeaderFilters({
showLeadingIcon={false}
/>
+
-
{
expect(screen.getByRole('link', { name: /common.mainNav.home/ })).not.toHaveAttribute('aria-current')
})
+ it('hides the main menu on snippet detail routes while keeping account settings available', () => {
+ mockPathname = '/snippets/snippet-1/orchestrate'
+
+ renderMainNav()
+
+ expect(screen.getByRole('complementary')).toHaveClass('w-16')
+ expect(screen.queryByLabelText('Dify')).not.toBeInTheDocument()
+ expect(screen.queryByRole('button', { name: 'common.mainNav.workspace.openMenu' })).not.toBeInTheDocument()
+ expect(screen.queryByRole('link', { name: /common.mainNav.home/ })).not.toBeInTheDocument()
+ expect(screen.queryByRole('link', { name: /common.menus.apps/ })).not.toBeInTheDocument()
+ expect(screen.queryByRole('button', { name: 'explore.sidebar.webApps' })).not.toBeInTheDocument()
+ expect(screen.getByRole('button', { name: 'common.account.account' })).toBeInTheDocument()
+ expect(screen.getByRole('button', { name: 'common.mainNav.help.openMenu' })).toBeInTheDocument()
+ })
+
it('replaces global navigation with app detail navigation on app routes', () => {
mockPathname = '/app/app-1/overview'
diff --git a/web/app/components/main-nav/index.tsx b/web/app/components/main-nav/index.tsx
index c8f6950c9c..ccb149978d 100644
--- a/web/app/components/main-nav/index.tsx
+++ b/web/app/components/main-nav/index.tsx
@@ -60,6 +60,12 @@ const isDatasetDetailPathname = (pathname: string) => {
return true
}
+const isSnippetDetailPathname = (pathname: string) => {
+ const [section, snippetId] = pathname.split('/').filter(Boolean)
+
+ return section === 'snippets' && !!snippetId
+}
+
const MainNav = ({
className,
}: MainNavProps) => {
@@ -70,6 +76,7 @@ const MainNav = ({
const showEnvTag = langGeniusVersionInfo.current_env === 'TESTING' || langGeniusVersionInfo.current_env === 'DEVELOPMENT'
const showAppDetailNavigation = !isCurrentWorkspaceDatasetOperator && pathname.startsWith('/app/')
const showDatasetDetailNavigation = isDatasetDetailPathname(pathname)
+ const showSnippetDetailBottomNavigation = isSnippetDetailPathname(pathname)
const showDetailNavigation = showAppDetailNavigation || showDatasetDetailNavigation
const { hasAppDetail, appSidebarExpand, setAppDetail, setAppSidebarExpand } = useAppStore(useShallow(state => ({
hasAppDetail: !!state.appDetail,
@@ -87,7 +94,9 @@ const MainNav = ({
const detailNavigationTransitionTimerRef = useRef
| null>(null)
const isDetailNavigationHoverPreviewOpen = isCollapsedDetailNavigation && detailNavigationHoverPreviewOpen
const detailNavigationVisibleExpanded = detailNavigationExpanded || isDetailNavigationHoverPreviewOpen
- const bottomNavigationExpanded = !showDetailNavigation || detailNavigationVisibleExpanded
+ const bottomNavigationExpanded = showSnippetDetailBottomNavigation
+ ? false
+ : !showDetailNavigation || detailNavigationVisibleExpanded
const handleToggleDetailNavigation = useCallback(() => {
if (isDetailNavigationHoverPreviewOpen) {
if (detailNavigationTransitionTimerRef.current)
@@ -234,7 +243,9 @@ const MainNav = ({
? detailNavigationExpanded
? 'w-[248px] bg-background-body p-1'
: 'w-16 bg-background-body p-1'
- : 'w-60 flex-col',
+ : showSnippetDetailBottomNavigation
+ ? 'w-16 bg-background-body p-1'
+ : 'w-60 flex-col',
'bg-background-body',
className,
)}
@@ -267,32 +278,36 @@ const MainNav = ({
onToggle={handleToggleDetailNavigation}
/>
)
- : (
- <>
-
- {renderLogo()}
-
-
-
-
-
- >
- )}
+ : showSnippetDetailBottomNavigation
+ ? null
+ : (
+ <>
+
+ {renderLogo()}
+
+
+
+
+
+ >
+ )}
{showDetailNavigation
? showAppDetailNavigation
?
:
- : (
- <>
-
- {!isCurrentWorkspaceDatasetOperator && }
- >
- )}
- {showEnvTag && detailNavigationVisibleExpanded && (
+ : showSnippetDetailBottomNavigation
+ ? null
+ : (
+ <>
+
+ {!isCurrentWorkspaceDatasetOperator && }
+ >
+ )}
+ {showEnvTag && !showSnippetDetailBottomNavigation && detailNavigationVisibleExpanded && (