From 7b7956f3e7ca619d0c9954029afadfbf696923d1 Mon Sep 17 00:00:00 2001 From: KVOJJJin Date: Fri, 3 Jul 2026 15:18:13 +0800 Subject: [PATCH] feat: snippet siderbar update (#38371) --- .../apps/app-list-header-filters.tsx | 3 +- .../snippet-collapsed-preview.spec.tsx | 11 ++++ .../__tests__/snippet-sidebar.spec.tsx | 13 +++++ .../components/snippet-collapsed-preview.tsx | 51 ++++++++++++++++--- .../components/snippet-detail-section.tsx | 2 +- .../components/snippet-placeholder-icon.tsx | 9 +--- .../snippets/components/snippet-sidebar.tsx | 15 ++++++ web/i18n/ar-TN/app.json | 2 +- web/i18n/de-DE/app.json | 2 +- web/i18n/en-US/app.json | 2 +- web/i18n/es-ES/app.json | 2 +- web/i18n/fa-IR/app.json | 2 +- web/i18n/fr-FR/app.json | 2 +- web/i18n/hi-IN/app.json | 2 +- web/i18n/id-ID/app.json | 2 +- web/i18n/it-IT/app.json | 2 +- web/i18n/ja-JP/app.json | 2 +- web/i18n/ko-KR/app.json | 2 +- web/i18n/nl-NL/app.json | 2 +- web/i18n/pl-PL/app.json | 2 +- web/i18n/pt-BR/app.json | 2 +- web/i18n/ro-RO/app.json | 2 +- web/i18n/ru-RU/app.json | 2 +- web/i18n/sl-SI/app.json | 2 +- web/i18n/th-TH/app.json | 2 +- web/i18n/tr-TR/app.json | 2 +- web/i18n/uk-UA/app.json | 2 +- web/i18n/vi-VN/app.json | 2 +- web/i18n/zh-Hans/app.json | 2 +- web/i18n/zh-Hant/app.json | 2 +- 30 files changed, 110 insertions(+), 40 deletions(-) create mode 100644 web/app/components/snippets/components/__tests__/snippet-collapsed-preview.spec.tsx diff --git a/web/app/components/apps/app-list-header-filters.tsx b/web/app/components/apps/app-list-header-filters.tsx index 824e77dd7d2..36b453c77bb 100644 --- a/web/app/components/apps/app-list-header-filters.tsx +++ b/web/app/components/apps/app-list-header-filters.tsx @@ -77,8 +77,9 @@ export function AppListHeaderFilters({
+ {t('studio.viewSnippets', { ns: 'app' })} {showCreateButton && ( diff --git a/web/app/components/snippets/components/__tests__/snippet-collapsed-preview.spec.tsx b/web/app/components/snippets/components/__tests__/snippet-collapsed-preview.spec.tsx new file mode 100644 index 00000000000..ab07e4f9444 --- /dev/null +++ b/web/app/components/snippets/components/__tests__/snippet-collapsed-preview.spec.tsx @@ -0,0 +1,11 @@ +import { render, screen } from '@testing-library/react' +import { SnippetCollapsedPreview } from '../snippet-collapsed-preview' + +describe('SnippetCollapsedPreview', () => { + it('should render collapsed route navigation and input field count', () => { + render() + + expect(screen.getByRole('link', { name: 'snippet.sectionOrchestrate' })).toHaveAttribute('href', '/snippets/snippet-1/orchestrate') + expect(screen.getByLabelText('2 snippet.inputVariables')).toHaveTextContent('2') + }) +}) diff --git a/web/app/components/snippets/components/__tests__/snippet-sidebar.spec.tsx b/web/app/components/snippets/components/__tests__/snippet-sidebar.spec.tsx index 4b2a697278d..9f0328e3024 100644 --- a/web/app/components/snippets/components/__tests__/snippet-sidebar.spec.tsx +++ b/web/app/components/snippets/components/__tests__/snippet-sidebar.spec.tsx @@ -152,6 +152,19 @@ describe('SnippetSidebarContent', () => { expect(capturedVarListProps?.readonly).toBe(true) }) + it('should render the orchestrate route menu item', () => { + render( + , + ) + + expect(screen.getByRole('link', { name: 'snippet.sectionOrchestrate' })).toHaveAttribute('href', '/snippets/snippet-1/orchestrate') + }) + it('should add a new input field from the config variable modal', () => { const onFieldsChange = vi.fn() render( diff --git a/web/app/components/snippets/components/snippet-collapsed-preview.tsx b/web/app/components/snippets/components/snippet-collapsed-preview.tsx index 731af1c744d..81632114df9 100644 --- a/web/app/components/snippets/components/snippet-collapsed-preview.tsx +++ b/web/app/components/snippets/components/snippet-collapsed-preview.tsx @@ -1,27 +1,62 @@ 'use client' +import { cn } from '@langgenius/dify-ui/cn' +import { useTranslation } from 'react-i18next' +import NavLink from '@/app/components/app-sidebar/nav-link' import { SnippetPlaceholderIcon } from './snippet-placeholder-icon' +const NodeTreeIcon = ({ className }: { className?: string }) => ( + +) + export function SnippetCollapsedPreview({ inputFieldCount, + snippetId, }: { inputFieldCount: number + snippetId?: string }) { + const { t } = useTranslation() + const sectionLabel = t('sectionOrchestrate', { ns: 'snippet' }) + return (
- +
+
+
+ ) diff --git a/web/app/components/snippets/components/snippet-detail-section.tsx b/web/app/components/snippets/components/snippet-detail-section.tsx index e9798a903d5..0fa9d81442e 100644 --- a/web/app/components/snippets/components/snippet-detail-section.tsx +++ b/web/app/components/snippets/components/snippet-detail-section.tsx @@ -19,7 +19,7 @@ export function SnippetDetailSection({ expand }: SnippetDetailSectionProps) { const snippetInputFields = useSnippetDraftStore(state => state.inputFields) if (!expand) - return + return if (!snippetNavigation.snippet || !snippetNavigation.onFieldsChange) return null diff --git a/web/app/components/snippets/components/snippet-placeholder-icon.tsx b/web/app/components/snippets/components/snippet-placeholder-icon.tsx index 982ba688e80..92153214719 100644 --- a/web/app/components/snippets/components/snippet-placeholder-icon.tsx +++ b/web/app/components/snippets/components/snippet-placeholder-icon.tsx @@ -14,17 +14,12 @@ export function SnippetPlaceholderIcon({ return ( ) } diff --git a/web/app/components/snippets/components/snippet-sidebar.tsx b/web/app/components/snippets/components/snippet-sidebar.tsx index a2090979d9b..83ae818f53a 100644 --- a/web/app/components/snippets/components/snippet-sidebar.tsx +++ b/web/app/components/snippets/components/snippet-sidebar.tsx @@ -7,6 +7,7 @@ import { toast } from '@langgenius/dify-ui/toast' import { isEqual } from 'es-toolkit/predicate' import { useCallback, useMemo, useState } from 'react' import { useTranslation } from 'react-i18next' +import NavLink from '@/app/components/app-sidebar/nav-link' import SnippetInfoDropdown from '@/app/components/app-sidebar/snippet-info/dropdown' import ConfigVarModal from '@/app/components/app/configuration/config-var/config-modal' import Field from '@/app/components/workflow/nodes/_base/components/field' @@ -36,6 +37,10 @@ const toSnippetInputField = (field: InputVar): SnippetInputField => ({ type: field.type as unknown as SnippetInputField['type'], }) +const NodeTreeIcon = ({ className }: { className?: string }) => ( + +) + export const SnippetSidebarContent = ({ snippet, fields, @@ -109,6 +114,16 @@ export const SnippetSidebarContent = ({ )}
+ +