+
+
+
+
- {expand && (
-
-
- {snippet.name}
-
- {snippet.status && (
-
- {snippet.status}
-
- )}
-
- )}
+ {expand &&
}
+ {expand && (
+
+
+ {snippet.name}
+
+
+ {t('typeLabel')}
+
+
+ )}
{expand && snippet.description && (
-
+
{snippet.description}
)}
diff --git a/web/app/components/snippets/components/snippet-main.tsx b/web/app/components/snippets/components/snippet-main.tsx
index d1f936a0c5..b2ffdf71ea 100644
--- a/web/app/components/snippets/components/snippet-main.tsx
+++ b/web/app/components/snippets/components/snippet-main.tsx
@@ -6,8 +6,8 @@ import type { SnippetDetailPayload, SnippetInputField, SnippetSection } from '@/
import {
RiFlaskFill,
RiFlaskLine,
- RiGitBranchFill,
- RiGitBranchLine,
+ RiTerminalWindowFill,
+ RiTerminalWindowLine,
} from '@remixicon/react'
import { useEffect, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
@@ -16,7 +16,7 @@ import AppSideBar from '@/app/components/app-sidebar'
import NavLink from '@/app/components/app-sidebar/nav-link'
import SnippetInfo from '@/app/components/app-sidebar/snippet-info'
import { useStore as useAppStore } from '@/app/components/app/store'
-import Toast from '@/app/components/base/toast'
+import { toast } from '@/app/components/base/ui/toast'
import Evaluation from '@/app/components/evaluation'
import { WorkflowWithInnerContext } from '@/app/components/workflow'
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
@@ -30,8 +30,8 @@ type SnippetMainProps = {
} & Pick
const ORCHESTRATE_ICONS: { normal: NavIcon, selected: NavIcon } = {
- normal: RiGitBranchLine,
- selected: RiGitBranchFill,
+ normal: RiTerminalWindowLine,
+ selected: RiTerminalWindowFill,
}
const EVALUATION_ICONS: { normal: NavIcon, selected: NavIcon } = {
@@ -107,10 +107,7 @@ const SnippetMain = ({
const duplicated = fields.some(item => item.variable === field.variable && item.variable !== originalVariable)
if (duplicated) {
- Toast.notify({
- type: 'error',
- message: t('inputFieldPanel.error.variableDuplicate', { ns: 'datasetPipeline' }),
- })
+ toast.error(t('inputFieldPanel.error.variableDuplicate', { ns: 'datasetPipeline' }))
return
}
diff --git a/web/app/components/snippets/hooks/use-snippet-init.ts b/web/app/components/snippets/hooks/use-snippet-init.ts
index a5978603cd..1468c65beb 100644
--- a/web/app/components/snippets/hooks/use-snippet-init.ts
+++ b/web/app/components/snippets/hooks/use-snippet-init.ts
@@ -1,4 +1,5 @@
-import { useSnippetDetail } from '@/service/use-snippets'
+// import { useSnippetDetail } from '@/service/use-snippets'
+import { useSnippetDetail } from '@/service/use-snippets.mock'
export const useSnippetInit = (snippetId: string) => {
return useSnippetDetail(snippetId)
diff --git a/web/app/components/workflow/create-snippet-dialog.tsx b/web/app/components/workflow/create-snippet-dialog.tsx
index 8c72602668..2da326bc27 100644
--- a/web/app/components/workflow/create-snippet-dialog.tsx
+++ b/web/app/components/workflow/create-snippet-dialog.tsx
@@ -20,12 +20,21 @@ export type CreateSnippetDialogPayload = {
selectedNodeIds: string[]
}
+export type CreateSnippetDialogInitialValue = {
+ name?: string
+ description?: string
+ icon?: AppIconSelection
+}
+
type CreateSnippetDialogProps = {
isOpen: boolean
selectedNodeIds: string[]
onClose: () => void
onConfirm: (payload: CreateSnippetDialogPayload) => void
isSubmitting?: boolean
+ title?: string
+ confirmText?: string
+ initialValue?: CreateSnippetDialogInitialValue
}
const defaultIcon: AppIconSelection = {
@@ -40,11 +49,14 @@ const CreateSnippetDialog: FC = ({
onClose,
onConfirm,
isSubmitting = false,
+ title,
+ confirmText,
+ initialValue,
}) => {
const { t } = useTranslation()
- const [name, setName] = useState('')
- const [description, setDescription] = useState('')
- const [icon, setIcon] = useState(defaultIcon)
+ const [name, setName] = useState(initialValue?.name ?? '')
+ const [description, setDescription] = useState(initialValue?.description ?? '')
+ const [icon, setIcon] = useState(initialValue?.icon ?? defaultIcon)
const [showAppIconPicker, setShowAppIconPicker] = useState(false)
const resetForm = useCallback(() => {
@@ -94,7 +106,7 @@ const CreateSnippetDialog: FC = ({
- {t('snippet.createDialogTitle', { ns: 'workflow' })}
+ {title || t('snippet.createDialogTitle', { ns: 'workflow' })}
@@ -148,7 +160,7 @@ const CreateSnippetDialog: FC = ({
loading={isSubmitting}
onClick={handleConfirm}
>
- {t('snippet.confirm', { ns: 'workflow' })}
+ {confirmText || t('snippet.confirm', { ns: 'workflow' })}
diff --git a/web/app/components/workflow/selection-contextmenu.tsx b/web/app/components/workflow/selection-contextmenu.tsx
index 4b8935c526..434f4bc4a5 100644
--- a/web/app/components/workflow/selection-contextmenu.tsx
+++ b/web/app/components/workflow/selection-contextmenu.tsx
@@ -439,14 +439,16 @@ const SelectionContextmenu = () => {
))}
-
{
- void payload
- }}
- />
+ {isCreateSnippetDialogOpen && (
+ {
+ void payload
+ }}
+ />
+ )}
)
}
diff --git a/web/i18n/en-US/snippet.json b/web/i18n/en-US/snippet.json
index 8ce20472eb..3bc86cfe43 100644
--- a/web/i18n/en-US/snippet.json
+++ b/web/i18n/en-US/snippet.json
@@ -3,9 +3,20 @@
"createFailed": "Failed to create snippet",
"createFromBlank": "Create from blank",
"defaultName": "Untitled Snippet",
+ "deleteConfirmContent": "Deleting this snippet is irreversible. Its draft workflow and published content will no longer be available.",
+ "deleteConfirmTitle": "Delete Snippet?",
+ "deleteFailed": "Failed to delete snippet",
+ "deleted": "Snippet deleted",
+ "editDialogTitle": "Edit Snippet Info",
+ "editDone": "Snippet info updated",
+ "editFailed": "Failed to update snippet info",
+ "exportFailed": "Export snippet failed.",
"importFailed": "Failed to import snippet DSL",
"importSuccess": "Snippet imported",
"inputFieldButton": "Input Field",
+ "menu.deleteSnippet": "Delete",
+ "menu.editInfo": "Edit Info",
+ "menu.exportSnippet": "Export Snippet",
"notFoundDescription": "The requested snippet mock was not found.",
"notFoundTitle": "Snippet not found",
"panelDescription": "Defines the input fields that allow the snippet to receive data from other nodes.",
@@ -14,9 +25,11 @@
"panelTitle": "Input Field",
"publishButton": "Publish",
"publishMenuCurrentDraft": "Current draft unpublished",
+ "save": "Save",
"sectionEvaluation": "Evaluation",
"sectionOrchestrate": "Orchestrate",
"testRunButton": "Test run",
+ "typeLabel": "Snippet",
"usageCount": "Used {{count}} times",
"variableInspect": "Variable Inspect"
}
diff --git a/web/i18n/zh-Hans/snippet.json b/web/i18n/zh-Hans/snippet.json
index eeb38faf44..bb4514d622 100644
--- a/web/i18n/zh-Hans/snippet.json
+++ b/web/i18n/zh-Hans/snippet.json
@@ -3,9 +3,20 @@
"createFailed": "创建 Snippet 失败",
"createFromBlank": "创建空白 Snippet",
"defaultName": "未命名 Snippet",
+ "deleteConfirmContent": "删除后不可恢复,草稿工作流和已发布内容都将无法继续使用。",
+ "deleteConfirmTitle": "删除 Snippet?",
+ "deleteFailed": "删除 Snippet 失败",
+ "deleted": "Snippet 已删除",
+ "editDialogTitle": "编辑 Snippet 信息",
+ "editDone": "Snippet 信息已更新",
+ "editFailed": "更新 Snippet 信息失败",
+ "exportFailed": "导出 Snippet 失败。",
"importFailed": "导入 Snippet DSL 失败",
"importSuccess": "Snippet 导入成功",
"inputFieldButton": "输入字段",
+ "menu.deleteSnippet": "删除",
+ "menu.editInfo": "编辑信息",
+ "menu.exportSnippet": "导出 Snippet",
"notFoundDescription": "未找到对应的 snippet 静态数据。",
"notFoundTitle": "未找到 Snippet",
"panelDescription": "定义允许 snippet 从其他节点接收数据的输入字段。",
@@ -14,9 +25,11 @@
"panelTitle": "输入字段",
"publishButton": "发布",
"publishMenuCurrentDraft": "当前草稿未发布",
+ "save": "保存",
"sectionEvaluation": "评测",
"sectionOrchestrate": "编排",
"testRunButton": "测试运行",
+ "typeLabel": "Snippet",
"usageCount": "已使用 {{count}} 次",
"variableInspect": "变量查看"
}
diff --git a/web/service/use-snippets.ts b/web/service/use-snippets.ts
index f8fc8537ef..076510a5c9 100644
--- a/web/service/use-snippets.ts
+++ b/web/service/use-snippets.ts
@@ -263,6 +263,17 @@ export const useDeleteSnippetMutation = () => {
})
}
+export const useExportSnippetMutation = () => {
+ return useMutation
({
+ mutationFn: ({ snippetId, include = false }) => {
+ return consoleClient.snippets.export({
+ params: { snippetId },
+ query: { include_secret: include ? 'true' : 'false' },
+ })
+ },
+ })
+}
+
export const usePublishSnippetMutation = () => {
const queryClient = useQueryClient()