mirror of
https://github.com/langgenius/dify.git
synced 2026-03-25 01:36:52 +00:00
Compare commits
4 Commits
deploy/age
...
chore/work
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2ad7f53c5b | ||
|
|
e4fc606e44 | ||
|
|
43d22289d1 | ||
|
|
2603ef8eca |
@@ -49,9 +49,12 @@ vi.mock('@/service/use-tools', () => ({
|
||||
|
||||
// Mock Toast - need to verify notification calls
|
||||
const mockToastNotify = vi.fn()
|
||||
vi.mock('@/app/components/base/toast', () => ({
|
||||
default: {
|
||||
notify: (options: { type: string, message: string }) => mockToastNotify(options),
|
||||
vi.mock('@/app/components/base/ui/toast', () => ({
|
||||
toast: {
|
||||
success: (message: string) => mockToastNotify({ type: 'success', message }),
|
||||
error: (message: string) => mockToastNotify({ type: 'error', message }),
|
||||
warning: (message: string) => mockToastNotify({ type: 'warning', message }),
|
||||
info: (message: string) => mockToastNotify({ type: 'info', message }),
|
||||
},
|
||||
}))
|
||||
|
||||
|
||||
@@ -33,9 +33,12 @@ vi.mock('@/service/use-tools', () => ({
|
||||
}))
|
||||
|
||||
const mockToastNotify = vi.fn()
|
||||
vi.mock('@/app/components/base/toast', () => ({
|
||||
default: {
|
||||
notify: (options: { type: string, message: string }) => mockToastNotify(options),
|
||||
vi.mock('@/app/components/base/ui/toast', () => ({
|
||||
toast: {
|
||||
success: (message: string) => mockToastNotify({ type: 'success', message }),
|
||||
error: (message: string) => mockToastNotify({ type: 'error', message }),
|
||||
warning: (message: string) => mockToastNotify({ type: 'warning', message }),
|
||||
info: (message: string) => mockToastNotify({ type: 'info', message }),
|
||||
},
|
||||
}))
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { InputVar, Variable } from '@/app/components/workflow/types'
|
||||
import type { PublishWorkflowParams } from '@/types/workflow'
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import { useAppContext } from '@/context/app-context'
|
||||
import { useRouter } from '@/next/navigation'
|
||||
import { createWorkflowToolProvider, saveWorkflowToolProvider } from '@/service/tools'
|
||||
@@ -188,14 +188,11 @@ export function useConfigureButton(options: UseConfigureButtonOptions) {
|
||||
invalidateAllWorkflowTools()
|
||||
onRefreshData?.()
|
||||
invalidateDetail(workflowAppId)
|
||||
Toast.notify({
|
||||
type: 'success',
|
||||
message: t('api.actionSuccess', { ns: 'common' }),
|
||||
})
|
||||
toast.success(t('api.actionSuccess', { ns: 'common' }))
|
||||
setShowModal(false)
|
||||
}
|
||||
catch (e) {
|
||||
Toast.notify({ type: 'error', message: (e as Error).message })
|
||||
toast.error((e as Error).message)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,14 +206,11 @@ export function useConfigureButton(options: UseConfigureButtonOptions) {
|
||||
onRefreshData?.()
|
||||
invalidateAllWorkflowTools()
|
||||
invalidateDetail(workflowAppId)
|
||||
Toast.notify({
|
||||
type: 'success',
|
||||
message: t('api.actionSuccess', { ns: 'common' }),
|
||||
})
|
||||
toast.success(t('api.actionSuccess', { ns: 'common' }))
|
||||
setShowModal(false)
|
||||
}
|
||||
catch (e) {
|
||||
Toast.notify({ type: 'error', message: (e as Error).message })
|
||||
toast.error((e as Error).message)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,8 +12,8 @@ import Drawer from '@/app/components/base/drawer-plus'
|
||||
import EmojiPicker from '@/app/components/base/emoji-picker'
|
||||
import Input from '@/app/components/base/input'
|
||||
import Textarea from '@/app/components/base/textarea'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import LabelSelector from '@/app/components/tools/labels/selector'
|
||||
import ConfirmModal from '@/app/components/tools/workflow-tool/confirm-modal'
|
||||
import MethodSelector from '@/app/components/tools/workflow-tool/method-selector'
|
||||
@@ -129,10 +129,7 @@ const WorkflowToolAsModal: FC<Props> = ({
|
||||
errorMessage = t('createTool.nameForToolCall', { ns: 'tools' }) + t('createTool.nameForToolCallTip', { ns: 'tools' })
|
||||
|
||||
if (errorMessage) {
|
||||
Toast.notify({
|
||||
type: 'error',
|
||||
message: errorMessage,
|
||||
})
|
||||
toast.error(errorMessage)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -114,9 +114,12 @@ vi.mock('@/service/use-tools', () => ({
|
||||
useInvalidateAllMCPTools: vi.fn(),
|
||||
}))
|
||||
|
||||
vi.mock('@/app/components/base/toast', () => ({
|
||||
default: {
|
||||
notify: (payload: unknown) => mockNotify(payload),
|
||||
vi.mock('@/app/components/base/ui/toast', () => ({
|
||||
toast: {
|
||||
success: (message: string) => mockNotify({ type: 'success', message }),
|
||||
error: (message: string) => mockNotify({ type: 'error', message }),
|
||||
warning: (message: string) => mockNotify({ type: 'warning', message }),
|
||||
info: (message: string) => mockNotify({ type: 'info', message }),
|
||||
},
|
||||
}))
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ import {
|
||||
PortalToFollowElemContent,
|
||||
PortalToFollowElemTrigger,
|
||||
} from '@/app/components/base/portal-to-follow-elem'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import SearchBox from '@/app/components/plugins/marketplace/search-box'
|
||||
import EditCustomToolModal from '@/app/components/tools/edit-custom-collection-modal'
|
||||
import AllTools from '@/app/components/workflow/block-selector/all-tools'
|
||||
@@ -137,10 +137,7 @@ const ToolPicker: FC<Props> = ({
|
||||
|
||||
const doCreateCustomToolCollection = async (data: CustomCollectionBackend) => {
|
||||
await createCustomCollection(data)
|
||||
Toast.notify({
|
||||
type: 'success',
|
||||
message: t('api.actionSuccess', { ns: 'common' }),
|
||||
})
|
||||
toast.success(t('api.actionSuccess', { ns: 'common' }))
|
||||
hideEditCustomCollectionModal()
|
||||
handleAddedCustomTool()
|
||||
}
|
||||
|
||||
@@ -60,9 +60,12 @@ vi.mock('@/service/use-workflow', () => ({
|
||||
}),
|
||||
}))
|
||||
|
||||
vi.mock('../../../base/toast', () => ({
|
||||
default: {
|
||||
notify: (payload: unknown) => mockNotify(payload),
|
||||
vi.mock('@/app/components/base/ui/toast', () => ({
|
||||
toast: {
|
||||
success: (message: string) => mockNotify({ type: 'success', message }),
|
||||
error: (message: string) => mockNotify({ type: 'error', message }),
|
||||
warning: (message: string) => mockNotify({ type: 'warning', message }),
|
||||
info: (message: string) => mockNotify({ type: 'info', message }),
|
||||
},
|
||||
}))
|
||||
|
||||
|
||||
@@ -46,10 +46,13 @@ vi.mock('../../hooks/use-dynamic-test-run-options', () => ({
|
||||
useDynamicTestRunOptions: () => mockDynamicOptions,
|
||||
}))
|
||||
|
||||
vi.mock('@/app/components/base/toast/context', () => ({
|
||||
useToastContext: () => ({
|
||||
notify: mockNotify,
|
||||
}),
|
||||
vi.mock('@/app/components/base/ui/toast', () => ({
|
||||
toast: {
|
||||
success: (message: string) => mockNotify({ type: 'success', message }),
|
||||
error: (message: string) => mockNotify({ type: 'error', message }),
|
||||
warning: (message: string) => mockNotify({ type: 'warning', message }),
|
||||
info: (message: string) => mockNotify({ type: 'info', message }),
|
||||
},
|
||||
}))
|
||||
|
||||
vi.mock('@/app/components/base/amplitude', () => ({
|
||||
|
||||
@@ -4,11 +4,11 @@ import {
|
||||
} from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Button from '@/app/components/base/button'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import useTheme from '@/hooks/use-theme'
|
||||
import { useInvalidAllLastRun, useRestoreWorkflow } from '@/service/use-workflow'
|
||||
import { getFlowPrefix } from '@/service/utils'
|
||||
import { cn } from '@/utils/classnames'
|
||||
import Toast from '../../base/toast'
|
||||
import {
|
||||
useWorkflowRefreshDraft,
|
||||
useWorkflowRun,
|
||||
@@ -65,18 +65,12 @@ const HeaderInRestoring = ({
|
||||
workflowStore.setState({ isRestoring: false })
|
||||
workflowStore.setState({ backupDraft: undefined })
|
||||
handleRefreshWorkflowDraft()
|
||||
Toast.notify({
|
||||
type: 'success',
|
||||
message: t('versionHistory.action.restoreSuccess', { ns: 'workflow' }),
|
||||
})
|
||||
toast.success(t('versionHistory.action.restoreSuccess', { ns: 'workflow' }))
|
||||
deleteAllInspectVars()
|
||||
invalidAllLastRun()
|
||||
}
|
||||
catch {
|
||||
Toast.notify({
|
||||
type: 'error',
|
||||
message: t('versionHistory.action.restoreFailure', { ns: 'workflow' }),
|
||||
})
|
||||
toast.error(t('versionHistory.action.restoreFailure', { ns: 'workflow' }))
|
||||
}
|
||||
finally {
|
||||
onRestoreSettled?.()
|
||||
|
||||
@@ -5,7 +5,7 @@ import { useCallback, useEffect, useRef } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { trackEvent } from '@/app/components/base/amplitude'
|
||||
import { StopCircle } from '@/app/components/base/icons/src/vender/line/mediaAndDevices'
|
||||
import { useToastContext } from '@/app/components/base/toast/context'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import { useWorkflowRun, useWorkflowRunValidation, useWorkflowStartRun } from '@/app/components/workflow/hooks'
|
||||
import ShortcutsName from '@/app/components/workflow/shortcuts-name'
|
||||
import { useStore } from '@/app/components/workflow/store'
|
||||
@@ -41,7 +41,6 @@ const RunMode = ({
|
||||
|
||||
const dynamicOptions = useDynamicTestRunOptions()
|
||||
const testRunMenuRef = useRef<TestRunMenuRef>(null)
|
||||
const { notify } = useToastContext()
|
||||
|
||||
useEffect(() => {
|
||||
// @ts-expect-error - Dynamic property for backward compatibility with keyboard shortcuts
|
||||
@@ -66,7 +65,7 @@ const RunMode = ({
|
||||
isValid = false
|
||||
})
|
||||
if (!isValid) {
|
||||
notify({ type: 'error', message: t('panel.checklistTip', { ns: 'workflow' }) })
|
||||
toast.error(t('panel.checklistTip', { ns: 'workflow' }))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -98,7 +97,7 @@ const RunMode = ({
|
||||
// Placeholder for trigger-specific execution logic for schedule, webhook, plugin types
|
||||
console.log('TODO: Handle trigger execution for type:', option.type, 'nodeId:', option.nodeId)
|
||||
}
|
||||
}, [warningNodes, notify, t, handleWorkflowStartRunInWorkflow, handleWorkflowTriggerScheduleRunInWorkflow, handleWorkflowTriggerWebhookRunInWorkflow, handleWorkflowTriggerPluginRunInWorkflow, handleWorkflowRunAllTriggersInWorkflow])
|
||||
}, [warningNodes, t, handleWorkflowStartRunInWorkflow, handleWorkflowTriggerScheduleRunInWorkflow, handleWorkflowTriggerWebhookRunInWorkflow, handleWorkflowTriggerPluginRunInWorkflow, handleWorkflowRunAllTriggersInWorkflow])
|
||||
|
||||
const { eventEmitter } = useEventEmitterContextContext()
|
||||
eventEmitter?.useSubscription((v: any) => {
|
||||
|
||||
@@ -89,8 +89,13 @@ vi.mock('../index', () => ({
|
||||
useNodesMetaData: () => ({ nodes: [], nodesMap: mockNodesMap }),
|
||||
}))
|
||||
|
||||
vi.mock('@/app/components/base/toast/context', () => ({
|
||||
useToastContext: () => ({ notify: vi.fn() }),
|
||||
vi.mock('@/app/components/base/ui/toast', () => ({
|
||||
toast: {
|
||||
success: vi.fn(),
|
||||
error: vi.fn(),
|
||||
warning: vi.fn(),
|
||||
info: vi.fn(),
|
||||
},
|
||||
}))
|
||||
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
|
||||
@@ -27,7 +27,7 @@ import {
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useEdges, useStoreApi } from 'reactflow'
|
||||
import { useStore as useAppStore } from '@/app/components/app/store'
|
||||
import { useToastContext } from '@/app/components/base/toast/context'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import { ModelTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
|
||||
import { useModelList } from '@/app/components/header/account-setting/model-provider-page/hooks'
|
||||
import useNodes from '@/app/components/workflow/store/workflow/use-nodes'
|
||||
@@ -325,7 +325,6 @@ export const useChecklist = (nodes: Node[], edges: Edge[]) => {
|
||||
export const useChecklistBeforePublish = () => {
|
||||
const { t } = useTranslation()
|
||||
const language = useGetLanguage()
|
||||
const { notify } = useToastContext()
|
||||
const queryClient = useQueryClient()
|
||||
const store = useStoreApi()
|
||||
const { nodesMap: nodesExtraData } = useNodesMetaData()
|
||||
@@ -390,7 +389,7 @@ export const useChecklistBeforePublish = () => {
|
||||
const { validNodes, maxDepth } = getValidTreeNodes(filteredNodes, edges)
|
||||
|
||||
if (maxDepth > MAX_TREE_DEPTH) {
|
||||
notify({ type: 'error', message: t('common.maxTreeDepth', { ns: 'workflow', depth: MAX_TREE_DEPTH }) })
|
||||
toast.error(t('common.maxTreeDepth', { ns: 'workflow', depth: MAX_TREE_DEPTH }))
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -488,7 +487,7 @@ export const useChecklistBeforePublish = () => {
|
||||
isModelProviderInstalled: isLLMModelProviderInstalled(modelProvider, installedPluginIds),
|
||||
})
|
||||
if (modelIssue === LLMModelIssueCode.providerPluginUnavailable) {
|
||||
notify({ type: 'error', message: `[${node.data.title}] ${t('errorMsg.configureModel', { ns: 'workflow' })}` })
|
||||
toast.error(`[${node.data.title}] ${t('errorMsg.configureModel', { ns: 'workflow' })}`)
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -497,7 +496,7 @@ export const useChecklistBeforePublish = () => {
|
||||
const { errorMessage } = nodesExtraData![node.data.type as BlockEnum].checkValid(checkData, t, moreDataForCheckValid)
|
||||
|
||||
if (errorMessage) {
|
||||
notify({ type: 'error', message: `[${node.data.title}] ${errorMessage}` })
|
||||
toast.error(`[${node.data.title}] ${errorMessage}`)
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -510,12 +509,12 @@ export const useChecklistBeforePublish = () => {
|
||||
if (usedNode) {
|
||||
const usedVar = usedNode.vars.find(v => v.variable === variable?.[1])
|
||||
if (!usedVar) {
|
||||
notify({ type: 'error', message: `[${node.data.title}] ${t('errorMsg.invalidVariable', { ns: 'workflow' })}` })
|
||||
toast.error(`[${node.data.title}] ${t('errorMsg.invalidVariable', { ns: 'workflow' })}`)
|
||||
return false
|
||||
}
|
||||
}
|
||||
else {
|
||||
notify({ type: 'error', message: `[${node.data.title}] ${t('errorMsg.invalidVariable', { ns: 'workflow' })}` })
|
||||
toast.error(`[${node.data.title}] ${t('errorMsg.invalidVariable', { ns: 'workflow' })}`)
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -526,7 +525,7 @@ export const useChecklistBeforePublish = () => {
|
||||
const isUnconnected = !validNodes.some(n => n.id === node.id)
|
||||
|
||||
if (isUnconnected && !canSkipConnectionCheck) {
|
||||
notify({ type: 'error', message: `[${node.data.title}] ${t('common.needConnectTip', { ns: 'workflow' })}` })
|
||||
toast.error(`[${node.data.title}] ${t('common.needConnectTip', { ns: 'workflow' })}`)
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -534,7 +533,7 @@ export const useChecklistBeforePublish = () => {
|
||||
if (shouldCheckStartNode) {
|
||||
const startNodesFiltered = nodes.filter(node => START_NODE_TYPES.includes(node.data.type as BlockEnum))
|
||||
if (startNodesFiltered.length === 0) {
|
||||
notify({ type: 'error', message: t('common.needStartNode', { ns: 'workflow' }) })
|
||||
toast.error(t('common.needStartNode', { ns: 'workflow' }))
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -545,13 +544,13 @@ export const useChecklistBeforePublish = () => {
|
||||
const type = isRequiredNodesType[i]
|
||||
|
||||
if (!filteredNodes.some(node => node.data.type === type)) {
|
||||
notify({ type: 'error', message: t('common.needAdd', { ns: 'workflow', node: t(`blocks.${type}` as I18nKeysWithPrefix<'workflow', 'blocks.'>, { ns: 'workflow' }) }) })
|
||||
toast.error(t('common.needAdd', { ns: 'workflow', node: t(`blocks.${type}` as I18nKeysWithPrefix<'workflow', 'blocks.'>, { ns: 'workflow' }) }))
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}, [store, workflowStore, getNodesAvailableVarList, shouldCheckStartNode, nodesExtraData, notify, t, updateDatasetsDetail, buildInTools, customTools, workflowTools, language, getCheckData, queryClient, strategyProviders, modelProviders])
|
||||
}, [store, workflowStore, getNodesAvailableVarList, shouldCheckStartNode, nodesExtraData, t, updateDatasetsDetail, buildInTools, customTools, workflowTools, language, getCheckData, queryClient, strategyProviders, modelProviders])
|
||||
|
||||
return {
|
||||
handleCheckBeforePublish,
|
||||
@@ -563,15 +562,14 @@ export const useWorkflowRunValidation = () => {
|
||||
const nodes = useNodes()
|
||||
const edges = useEdges<CommonEdgeType>()
|
||||
const needWarningNodes = useChecklist(nodes, edges)
|
||||
const { notify } = useToastContext()
|
||||
|
||||
const validateBeforeRun = useCallback(() => {
|
||||
if (needWarningNodes.length > 0) {
|
||||
notify({ type: 'error', message: t('panel.checklistTip', { ns: 'workflow' }) })
|
||||
toast.error(t('panel.checklistTip', { ns: 'workflow' }))
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}, [needWarningNodes, notify, t])
|
||||
}, [needWarningNodes, t])
|
||||
|
||||
return {
|
||||
validateBeforeRun,
|
||||
|
||||
@@ -19,11 +19,13 @@ vi.mock('@/app/components/base/file-uploader/hooks', () => ({
|
||||
useFileSizeLimit: vi.fn(),
|
||||
}))
|
||||
|
||||
vi.mock('@/app/components/base/toast/context', () => ({
|
||||
useToastContext: () => ({
|
||||
notify: vi.fn(),
|
||||
close: vi.fn(),
|
||||
}),
|
||||
vi.mock('@/app/components/base/ui/toast', () => ({
|
||||
toast: {
|
||||
success: vi.fn(),
|
||||
error: vi.fn(),
|
||||
warning: vi.fn(),
|
||||
info: vi.fn(),
|
||||
},
|
||||
}))
|
||||
|
||||
const createPayload = (overrides: Partial<UploadFileSetting> = {}): UploadFileSetting => ({
|
||||
|
||||
@@ -10,7 +10,7 @@ import { useEffect, useRef } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Button from '@/app/components/base/button'
|
||||
import { getProcessedFiles } from '@/app/components/base/file-uploader/utils'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import Split from '@/app/components/workflow/nodes/_base/components/split'
|
||||
import SingleRunForm from '@/app/components/workflow/nodes/human-input/components/single-run-form'
|
||||
import { BlockEnum, InputVarType } from '@/app/components/workflow/types'
|
||||
@@ -126,10 +126,7 @@ const BeforeRunForm: FC<BeforeRunFormProps> = ({
|
||||
})
|
||||
})
|
||||
if (errMsg) {
|
||||
Toast.notify({
|
||||
message: errMsg,
|
||||
type: 'error',
|
||||
})
|
||||
toast.error(errMsg)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -147,10 +144,7 @@ const BeforeRunForm: FC<BeforeRunFormProps> = ({
|
||||
})
|
||||
})
|
||||
if (parseErrorJsonField) {
|
||||
Toast.notify({
|
||||
message: t('errorMsg.invalidJson', { ns: 'workflow', field: parseErrorJsonField }),
|
||||
type: 'error',
|
||||
})
|
||||
toast.error(t('errorMsg.invalidJson', { ns: 'workflow', field: parseErrorJsonField }))
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { Params as OneStepRunParams } from '@/app/components/workflow/nodes
|
||||
// import
|
||||
import type { CommonNodeType, ValueSelector } from '@/app/components/workflow/types'
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import {
|
||||
useNodesSyncDraft,
|
||||
} from '@/app/components/workflow/hooks'
|
||||
@@ -163,7 +163,7 @@ const useLastRun = <T>({
|
||||
return false
|
||||
|
||||
const message = warningForNode.errorMessages[0] || 'This node has unresolved checklist issues'
|
||||
Toast.notify({ type: 'error', message })
|
||||
toast.error(message)
|
||||
return true
|
||||
}, [warningNodes, id])
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
} from 'reactflow'
|
||||
import { trackEvent } from '@/app/components/base/amplitude'
|
||||
import { getInputVars as doGetInputVars } from '@/app/components/base/prompt-editor/constants'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import {
|
||||
useIsChatMode,
|
||||
useNodeDataUpdate,
|
||||
@@ -410,14 +410,14 @@ const useOneStepRun = <T>({
|
||||
})
|
||||
|
||||
if (!response) {
|
||||
const message = 'Schedule trigger run failed'
|
||||
Toast.notify({ type: 'error', message })
|
||||
const message = t('common.scheduleTriggerRunFailed', { ns: 'workflow' })
|
||||
toast.error(message)
|
||||
throw new Error(message)
|
||||
}
|
||||
|
||||
if (response?.status === 'error') {
|
||||
const message = response?.message || 'Schedule trigger run failed'
|
||||
Toast.notify({ type: 'error', message })
|
||||
const message = response?.message || t('common.scheduleTriggerRunFailed', { ns: 'workflow' })
|
||||
toast.error(message)
|
||||
throw new Error(message)
|
||||
}
|
||||
|
||||
@@ -442,10 +442,10 @@ const useOneStepRun = <T>({
|
||||
_singleRunningStatus: NodeRunningStatus.Failed,
|
||||
},
|
||||
})
|
||||
Toast.notify({ type: 'error', message: 'Schedule trigger run failed' })
|
||||
toast.error(t('common.scheduleTriggerRunFailed', { ns: 'workflow' }))
|
||||
throw error
|
||||
}
|
||||
}, [flowId, id, handleNodeDataUpdate, data])
|
||||
}, [flowId, id, handleNodeDataUpdate, data, t])
|
||||
|
||||
const runWebhookSingleRun = useCallback(async (): Promise<any | null> => {
|
||||
const urlPath = `/apps/${flowId}/workflows/draft/nodes/${id}/trigger/run`
|
||||
@@ -467,8 +467,8 @@ const useOneStepRun = <T>({
|
||||
return null
|
||||
|
||||
if (!response) {
|
||||
const message = response?.message || 'Webhook debug failed'
|
||||
Toast.notify({ type: 'error', message })
|
||||
const message = response?.message || t('common.webhookDebugFailed', { ns: 'workflow' })
|
||||
toast.error(message)
|
||||
cancelWebhookSingleRun()
|
||||
throw new Error(message)
|
||||
}
|
||||
@@ -495,8 +495,8 @@ const useOneStepRun = <T>({
|
||||
}
|
||||
|
||||
if (response?.status === 'error') {
|
||||
const message = response.message || 'Webhook debug failed'
|
||||
Toast.notify({ type: 'error', message })
|
||||
const message = response.message || t('common.webhookDebugFailed', { ns: 'workflow' })
|
||||
toast.error(message)
|
||||
cancelWebhookSingleRun()
|
||||
throw new Error(message)
|
||||
}
|
||||
@@ -519,7 +519,7 @@ const useOneStepRun = <T>({
|
||||
if (controller.signal.aborted)
|
||||
return null
|
||||
|
||||
Toast.notify({ type: 'error', message: 'Webhook debug request failed' })
|
||||
toast.error(t('common.webhookDebugRequestFailed', { ns: 'workflow' }))
|
||||
cancelWebhookSingleRun()
|
||||
if (error instanceof Error)
|
||||
throw error
|
||||
@@ -531,7 +531,7 @@ const useOneStepRun = <T>({
|
||||
}
|
||||
|
||||
return null
|
||||
}, [flowId, id, data, handleNodeDataUpdate, cancelWebhookSingleRun])
|
||||
}, [flowId, id, data, handleNodeDataUpdate, cancelWebhookSingleRun, t])
|
||||
|
||||
const runPluginSingleRun = useCallback(async (): Promise<any | null> => {
|
||||
const urlPath = `/apps/${flowId}/workflows/draft/nodes/${id}/trigger/run`
|
||||
@@ -566,14 +566,14 @@ const useOneStepRun = <T>({
|
||||
if (controller.signal.aborted)
|
||||
return null
|
||||
|
||||
Toast.notify({ type: 'error', message: requestError.message })
|
||||
toast.error(requestError.message)
|
||||
cancelPluginSingleRun()
|
||||
throw requestError
|
||||
}
|
||||
|
||||
if (!response) {
|
||||
const message = 'Plugin debug failed'
|
||||
Toast.notify({ type: 'error', message })
|
||||
toast.error(message)
|
||||
cancelPluginSingleRun()
|
||||
throw new Error(message)
|
||||
}
|
||||
@@ -600,7 +600,7 @@ const useOneStepRun = <T>({
|
||||
|
||||
if (response?.status === 'error') {
|
||||
const message = response.message || 'Plugin debug failed'
|
||||
Toast.notify({ type: 'error', message })
|
||||
toast.error(message)
|
||||
cancelPluginSingleRun()
|
||||
throw new Error(message)
|
||||
}
|
||||
@@ -633,10 +633,8 @@ const useOneStepRun = <T>({
|
||||
_isSingleRun: false,
|
||||
},
|
||||
})
|
||||
Toast.notify({
|
||||
type: 'error',
|
||||
message: res.errorMessage || '',
|
||||
})
|
||||
if (res.errorMessage)
|
||||
toast.error(res.errorMessage)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import { useTranslation } from 'react-i18next'
|
||||
import Button from '@/app/components/base/button'
|
||||
import Modal from '@/app/components/base/modal'
|
||||
import Textarea from '@/app/components/base/textarea'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import { useNodesInteractions } from '@/app/components/workflow/hooks'
|
||||
import { BodyPayloadValueType, BodyType, Method } from '../types'
|
||||
|
||||
@@ -124,10 +124,7 @@ const CurlPanel: FC<Props> = ({ nodeId, isShow, onHide, handleCurlImport }) => {
|
||||
const handleSave = useCallback(() => {
|
||||
const { node, error } = parseCurl(inputString)
|
||||
if (error) {
|
||||
Toast.notify({
|
||||
type: 'error',
|
||||
message: error,
|
||||
})
|
||||
toast.error(error)
|
||||
return
|
||||
}
|
||||
if (!node)
|
||||
|
||||
@@ -12,7 +12,7 @@ import Divider from '@/app/components/base/divider'
|
||||
import Input from '@/app/components/base/input'
|
||||
import Modal from '@/app/components/base/modal'
|
||||
import Switch from '@/app/components/base/switch'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import { useSelector as useAppContextWithSelector } from '@/context/app-context'
|
||||
import MailBodyInput from './mail-body-input'
|
||||
import Recipient from './recipient'
|
||||
@@ -45,31 +45,22 @@ const EmailConfigureModal = ({
|
||||
|
||||
const checkValidConfig = useCallback(() => {
|
||||
if (!subject.trim()) {
|
||||
Toast.notify({
|
||||
type: 'error',
|
||||
message: 'subject is required',
|
||||
})
|
||||
toast.error(t(`${i18nPrefix}.deliveryMethod.emailConfigure.subjectRequired`, { ns: 'workflow' }))
|
||||
return false
|
||||
}
|
||||
if (!body.trim()) {
|
||||
Toast.notify({
|
||||
type: 'error',
|
||||
message: 'body is required',
|
||||
})
|
||||
toast.error(t(`${i18nPrefix}.deliveryMethod.emailConfigure.bodyRequired`, { ns: 'workflow' }))
|
||||
return false
|
||||
}
|
||||
if (!/\{\{#url#\}\}/.test(body.trim())) {
|
||||
Toast.notify({
|
||||
type: 'error',
|
||||
message: `body must contain one ${t('promptEditor.requestURL.item.title', { ns: 'common' })}`,
|
||||
})
|
||||
toast.error(t(`${i18nPrefix}.deliveryMethod.emailConfigure.bodyMustContainRequestURL`, {
|
||||
ns: 'workflow',
|
||||
field: t('promptEditor.requestURL.item.title', { ns: 'common' }),
|
||||
}))
|
||||
return false
|
||||
}
|
||||
if (!recipients || (recipients.items.length === 0 && !recipients.whole_workspace)) {
|
||||
Toast.notify({
|
||||
type: 'error',
|
||||
message: 'recipients is required',
|
||||
})
|
||||
toast.error(t(`${i18nPrefix}.deliveryMethod.emailConfigure.recipientsRequired`, { ns: 'workflow' }))
|
||||
return false
|
||||
}
|
||||
return true
|
||||
|
||||
@@ -7,7 +7,7 @@ import * as React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Button from '@/app/components/base/button'
|
||||
import Input from '@/app/components/base/input'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import ButtonStyleDropdown from './button-style-dropdown'
|
||||
|
||||
const i18nPrefix = 'nodes.humanInput'
|
||||
@@ -47,14 +47,14 @@ const UserActionItem: FC<UserActionItemProps> = ({
|
||||
.join('')
|
||||
|
||||
if (sanitized !== withUnderscores) {
|
||||
Toast.notify({ type: 'error', message: t(`${i18nPrefix}.userActions.actionIdFormatTip`, { ns: 'workflow' }) })
|
||||
toast.error(t(`${i18nPrefix}.userActions.actionIdFormatTip`, { ns: 'workflow' }))
|
||||
return
|
||||
}
|
||||
|
||||
// Limit to 20 characters
|
||||
if (sanitized.length > ACTION_ID_MAX_LENGTH) {
|
||||
sanitized = sanitized.slice(0, ACTION_ID_MAX_LENGTH)
|
||||
Toast.notify({ type: 'error', message: t(`${i18nPrefix}.userActions.actionIdTooLong`, { ns: 'workflow', maxLength: ACTION_ID_MAX_LENGTH }) })
|
||||
toast.error(t(`${i18nPrefix}.userActions.actionIdTooLong`, { ns: 'workflow', maxLength: ACTION_ID_MAX_LENGTH }))
|
||||
}
|
||||
|
||||
if (sanitized)
|
||||
@@ -65,7 +65,7 @@ const UserActionItem: FC<UserActionItemProps> = ({
|
||||
let value = e.target.value
|
||||
if (value.length > BUTTON_TEXT_MAX_LENGTH) {
|
||||
value = value.slice(0, BUTTON_TEXT_MAX_LENGTH)
|
||||
Toast.notify({ type: 'error', message: t(`${i18nPrefix}.userActions.buttonTextTooLong`, { ns: 'workflow', maxLength: BUTTON_TEXT_MAX_LENGTH }) })
|
||||
toast.error(t(`${i18nPrefix}.userActions.buttonTextTooLong`, { ns: 'workflow', maxLength: BUTTON_TEXT_MAX_LENGTH }))
|
||||
}
|
||||
onChange({ ...data, title: value })
|
||||
}
|
||||
|
||||
@@ -16,8 +16,8 @@ import { useTranslation } from 'react-i18next'
|
||||
import ActionButton from '@/app/components/base/action-button'
|
||||
import Button from '@/app/components/base/button'
|
||||
import Divider from '@/app/components/base/divider'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import OutputVars, { VarItem } from '@/app/components/workflow/nodes/_base/components/output-vars'
|
||||
import Split from '@/app/components/workflow/nodes/_base/components/split'
|
||||
import useAvailableVarList from '@/app/components/workflow/nodes/_base/hooks/use-available-var-list'
|
||||
@@ -132,7 +132,7 @@ const Panel: FC<NodePanelProps<HumanInputNodeType>> = ({
|
||||
className="flex size-6 cursor-pointer items-center justify-center rounded-md hover:bg-components-button-ghost-bg-hover"
|
||||
onClick={() => {
|
||||
copy(inputs.form_content)
|
||||
Toast.notify({ type: 'success', message: t('actionMsg.copySuccessfully', { ns: 'common' }) })
|
||||
toast.success(t('actionMsg.copySuccessfully', { ns: 'common' }))
|
||||
}}
|
||||
>
|
||||
<RiClipboardLine className="h-4 w-4 text-text-secondary" />
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { IterationNodeType } from '../types'
|
||||
import type { PanelProps } from '@/types/workflow'
|
||||
import { fireEvent, render, screen } from '@testing-library/react'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import { ErrorHandleMode } from '@/app/components/workflow/types'
|
||||
import { BlockEnum, VarType } from '../../../types'
|
||||
import AddBlock from '../add-block'
|
||||
@@ -15,6 +15,15 @@ const mockHandleNodeAdd = vi.fn()
|
||||
const mockHandleNodeIterationRerender = vi.fn()
|
||||
let mockNodesReadOnly = false
|
||||
|
||||
vi.mock('@/app/components/base/ui/toast', () => ({
|
||||
toast: {
|
||||
success: vi.fn(),
|
||||
error: vi.fn(),
|
||||
warning: vi.fn(),
|
||||
info: vi.fn(),
|
||||
},
|
||||
}))
|
||||
|
||||
vi.mock('reactflow', async () => {
|
||||
const actual = await vi.importActual<typeof import('reactflow')>('reactflow')
|
||||
return {
|
||||
@@ -102,7 +111,7 @@ vi.mock('../use-config', () => ({
|
||||
}))
|
||||
|
||||
const mockUseConfig = vi.mocked(useConfig)
|
||||
const mockToastNotify = vi.spyOn(Toast, 'notify').mockImplementation(() => ({}))
|
||||
const mockToastWarning = vi.mocked(toast.warning)
|
||||
|
||||
const createData = (overrides: Partial<IterationNodeType> = {}): IterationNodeType => ({
|
||||
title: 'Iteration',
|
||||
@@ -191,11 +200,7 @@ describe('iteration path', () => {
|
||||
expect(screen.getByRole('button', { name: 'select-block' })).toBeInTheDocument()
|
||||
expect(screen.getByTestId('iteration-background-iteration-node')).toBeInTheDocument()
|
||||
expect(mockHandleNodeIterationRerender).toHaveBeenCalledWith('iteration-node')
|
||||
expect(mockToastNotify).toHaveBeenCalledWith({
|
||||
type: 'warning',
|
||||
message: 'workflow.nodes.iteration.answerNodeWarningDesc',
|
||||
duration: 5000,
|
||||
})
|
||||
expect(mockToastWarning).toHaveBeenCalledWith('workflow.nodes.iteration.answerNodeWarningDesc')
|
||||
})
|
||||
|
||||
it('should wire panel input, output, parallel, numeric, error mode, and flatten actions', async () => {
|
||||
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
useNodesInitialized,
|
||||
useViewport,
|
||||
} from 'reactflow'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import { cn } from '@/utils/classnames'
|
||||
import { IterationStartNodeDumb } from '../iteration-start'
|
||||
import AddBlock from './add-block'
|
||||
@@ -34,11 +34,7 @@ const Node: FC<NodeProps<IterationNodeType>> = ({
|
||||
if (nodesInitialized)
|
||||
handleNodeIterationRerender(id)
|
||||
if (data.is_parallel && showTips) {
|
||||
Toast.notify({
|
||||
type: 'warning',
|
||||
message: t(`${i18nPrefix}.answerNodeWarningDesc`, { ns: 'workflow' }),
|
||||
duration: 5000,
|
||||
})
|
||||
toast.warning(t(`${i18nPrefix}.answerNodeWarningDesc`, { ns: 'workflow' }))
|
||||
setShowTips(false)
|
||||
}
|
||||
}, [nodesInitialized, id, handleNodeIterationRerender, data.is_parallel, showTips, t])
|
||||
|
||||
@@ -4,7 +4,7 @@ import { useCallback, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Button from '@/app/components/base/button'
|
||||
import Divider from '@/app/components/base/divider'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import { JSON_SCHEMA_MAX_DEPTH } from '@/config'
|
||||
import { cn } from '@/utils/classnames'
|
||||
import { SegmentedControl } from '../../../../../base/segmented-control'
|
||||
@@ -196,10 +196,7 @@ const JsonSchemaConfig: FC<JsonSchemaConfigProps> = ({
|
||||
}
|
||||
else if (currentTab === SchemaView.VisualEditor) {
|
||||
if (advancedEditing || isAddingNewField) {
|
||||
Toast.notify({
|
||||
type: 'warning',
|
||||
message: t('nodes.llm.jsonSchema.warningTips.saveSchema', { ns: 'workflow' }),
|
||||
})
|
||||
toast.warning(t('nodes.llm.jsonSchema.warningTips.saveSchema', { ns: 'workflow' }))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
PortalToFollowElemContent,
|
||||
PortalToFollowElemTrigger,
|
||||
} from '@/app/components/base/portal-to-follow-elem'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import { ModelTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
|
||||
import { useModelListAndDefaultModelAndCurrentProviderAndModel } from '@/app/components/header/account-setting/model-provider-page/hooks'
|
||||
import useTheme from '@/hooks/use-theme'
|
||||
@@ -112,10 +112,7 @@ const JsonSchemaGenerator: FC<JsonSchemaGeneratorProps> = ({
|
||||
const generateSchema = useCallback(async () => {
|
||||
const { output, error } = await generateStructuredOutputRules({ instruction, model_config: model! })
|
||||
if (error) {
|
||||
Toast.notify({
|
||||
type: 'error',
|
||||
message: error,
|
||||
})
|
||||
toast.error(error)
|
||||
setSchema(null)
|
||||
setView(GeneratorView.promptEditor)
|
||||
return
|
||||
|
||||
@@ -3,7 +3,8 @@ import type { Field } from '../../../types'
|
||||
import type { EditData } from './edit-card'
|
||||
import { noop } from 'es-toolkit/function'
|
||||
import { produce } from 'immer'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import { ArrayType, Type } from '../../../types'
|
||||
import { findPropertyWithPath } from '../../../utils'
|
||||
import { useMittContext } from './context'
|
||||
@@ -22,6 +23,7 @@ type AddEventParams = {
|
||||
|
||||
export const useSchemaNodeOperations = (props: VisualEditorProps) => {
|
||||
const { schema: jsonSchema, onChange: doOnChange } = props
|
||||
const { t } = useTranslation()
|
||||
const onChange = doOnChange || noop
|
||||
const backupSchema = useVisualEditorStore(state => state.backupSchema)
|
||||
const setBackupSchema = useVisualEditorStore(state => state.setBackupSchema)
|
||||
@@ -65,10 +67,7 @@ export const useSchemaNodeOperations = (props: VisualEditorProps) => {
|
||||
if (schema.type === Type.object) {
|
||||
const properties = schema.properties || {}
|
||||
if (properties[newName]) {
|
||||
Toast.notify({
|
||||
type: 'error',
|
||||
message: 'Property name already exists',
|
||||
})
|
||||
toast.error(t('nodes.llm.jsonSchema.fieldNameAlreadyExists', { ns: 'workflow' }))
|
||||
emit('restorePropertyName')
|
||||
return
|
||||
}
|
||||
@@ -92,10 +91,7 @@ export const useSchemaNodeOperations = (props: VisualEditorProps) => {
|
||||
if (schema.type === Type.array && schema.items && schema.items.type === Type.object) {
|
||||
const properties = schema.items.properties || {}
|
||||
if (properties[newName]) {
|
||||
Toast.notify({
|
||||
type: 'error',
|
||||
message: 'Property name already exists',
|
||||
})
|
||||
toast.error(t('nodes.llm.jsonSchema.fieldNameAlreadyExists', { ns: 'workflow' }))
|
||||
emit('restorePropertyName')
|
||||
return
|
||||
}
|
||||
@@ -267,10 +263,7 @@ export const useSchemaNodeOperations = (props: VisualEditorProps) => {
|
||||
if (oldName !== newName) {
|
||||
const properties = parentSchema.properties
|
||||
if (properties[newName]) {
|
||||
Toast.notify({
|
||||
type: 'error',
|
||||
message: 'Property name already exists',
|
||||
})
|
||||
toast.error(t('nodes.llm.jsonSchema.fieldNameAlreadyExists', { ns: 'workflow' }))
|
||||
samePropertyNameError = true
|
||||
}
|
||||
|
||||
@@ -358,10 +351,7 @@ export const useSchemaNodeOperations = (props: VisualEditorProps) => {
|
||||
if (oldName !== newName) {
|
||||
const properties = parentSchema.items.properties || {}
|
||||
if (properties[newName]) {
|
||||
Toast.notify({
|
||||
type: 'error',
|
||||
message: 'Property name already exists',
|
||||
})
|
||||
toast.error(t('nodes.llm.jsonSchema.fieldNameAlreadyExists', { ns: 'workflow' }))
|
||||
samePropertyNameError = true
|
||||
}
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@ import { useCallback } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import AddButton2 from '@/app/components/base/button/add-button'
|
||||
import Switch from '@/app/components/base/switch'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import ModelParameterModal from '@/app/components/header/account-setting/model-provider-page/model-parameter-modal'
|
||||
import Field from '@/app/components/workflow/nodes/_base/components/field'
|
||||
import OutputVars, { VarItem } from '@/app/components/workflow/nodes/_base/components/output-vars'
|
||||
@@ -98,11 +98,11 @@ const Panel: FC<NodePanelProps<LLMNodeType>> = ({
|
||||
)
|
||||
const keys = Object.keys(removedDetails)
|
||||
if (keys.length)
|
||||
Toast.notify({ type: 'warning', message: `${t('modelProvider.parametersInvalidRemoved', { ns: 'common' })}: ${keys.map(k => `${k} (${removedDetails[k]})`).join(', ')}` })
|
||||
toast.warning(`${t('modelProvider.parametersInvalidRemoved', { ns: 'common' })}: ${keys.map(k => `${k} (${removedDetails[k]})`).join(', ')}`)
|
||||
handleCompletionParamsChange(filtered)
|
||||
}
|
||||
catch {
|
||||
Toast.notify({ type: 'error', message: t('error', { ns: 'common' }) })
|
||||
toast.error(t('error', { ns: 'common' }))
|
||||
handleCompletionParamsChange({})
|
||||
}
|
||||
finally {
|
||||
|
||||
@@ -181,10 +181,12 @@ vi.mock('@/app/components/workflow/nodes/_base/components/editor/code-editor', (
|
||||
),
|
||||
}))
|
||||
|
||||
vi.mock('@/app/components/base/toast', () => ({
|
||||
__esModule: true,
|
||||
default: {
|
||||
notify: (payload: unknown) => mockToastNotify(payload),
|
||||
vi.mock('@/app/components/base/ui/toast', () => ({
|
||||
toast: {
|
||||
success: (message: string) => mockToastNotify({ type: 'success', message }),
|
||||
error: (message: string) => mockToastNotify({ type: 'error', message }),
|
||||
warning: (message: string) => mockToastNotify({ type: 'warning', message }),
|
||||
info: (message: string) => mockToastNotify({ type: 'info', message }),
|
||||
},
|
||||
}))
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import { useCallback } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import ActionButton from '@/app/components/base/action-button'
|
||||
import Input from '@/app/components/base/input'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import { ValueType, VarType } from '@/app/components/workflow/types'
|
||||
import { checkKeys, replaceSpaceWithUnderscoreInVarNameInput } from '@/utils/var'
|
||||
import FormItem from './form-item'
|
||||
@@ -28,10 +28,7 @@ const Item = ({
|
||||
const checkVariableName = (value: string) => {
|
||||
const { isValid, errorMessageKey } = checkKeys([value], false)
|
||||
if (!isValid) {
|
||||
Toast.notify({
|
||||
type: 'error',
|
||||
message: t(`varKeyError.${errorMessageKey}`, { ns: 'appDebug', key: t('env.modal.name', { ns: 'workflow' }) }),
|
||||
})
|
||||
toast.error(t(`varKeyError.${errorMessageKey}`, { ns: 'appDebug', key: t('env.modal.name', { ns: 'workflow' }) }))
|
||||
return false
|
||||
}
|
||||
return true
|
||||
|
||||
@@ -6,7 +6,7 @@ import type { ToolDefaultValue } from '@/app/components/workflow/block-selector/
|
||||
import type { PanelProps } from '@/types/workflow'
|
||||
import { fireEvent, render, screen } from '@testing-library/react'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import {
|
||||
useTextGenerationCurrentProviderAndModelAndModelList,
|
||||
} from '@/app/components/header/account-setting/model-provider-page/hooks'
|
||||
@@ -36,6 +36,15 @@ let mockWorkflowTools: MockToolCollection[] = []
|
||||
let mockSelectedToolInfo: ToolDefaultValue | undefined
|
||||
let mockBlockSelectorOpen = false
|
||||
|
||||
vi.mock('@/app/components/base/ui/toast', () => ({
|
||||
toast: {
|
||||
success: vi.fn(),
|
||||
error: vi.fn(),
|
||||
warning: vi.fn(),
|
||||
info: vi.fn(),
|
||||
},
|
||||
}))
|
||||
|
||||
vi.mock('@/app/components/workflow/block-selector', () => ({
|
||||
__esModule: true,
|
||||
default: ({
|
||||
@@ -254,7 +263,7 @@ vi.mock('../use-config', () => ({
|
||||
|
||||
const mockUseTextGeneration = vi.mocked(useTextGenerationCurrentProviderAndModelAndModelList)
|
||||
const mockUseConfig = vi.mocked(useConfig)
|
||||
const mockToastNotify = vi.spyOn(Toast, 'notify').mockImplementation(() => ({}))
|
||||
const mockToastError = vi.mocked(toast.error)
|
||||
|
||||
const createToolParameter = (overrides: Partial<ToolParameter> = {}): ToolParameter => ({
|
||||
name: 'city',
|
||||
@@ -356,7 +365,7 @@ const panelProps: PanelProps = {
|
||||
describe('parameter-extractor path', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
mockToastNotify.mockClear()
|
||||
mockToastError.mockClear()
|
||||
mockBuiltInTools = []
|
||||
mockCustomTools = []
|
||||
mockWorkflowTools = []
|
||||
@@ -582,7 +591,7 @@ describe('parameter-extractor path', () => {
|
||||
await user.click(screen.getByRole('button', { name: 'common.operation.save' }))
|
||||
|
||||
expect(onSave).not.toHaveBeenCalled()
|
||||
expect(mockToastNotify).toHaveBeenCalled()
|
||||
expect(mockToastError).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should render the add trigger for new parameters', () => {
|
||||
@@ -614,7 +623,7 @@ describe('parameter-extractor path', () => {
|
||||
const descriptionInput = screen.getByPlaceholderText('workflow.nodes.parameterExtractor.addExtractParameterContent.descriptionPlaceholder')
|
||||
|
||||
fireEvent.change(nameInput, { target: { value: '1bad' } })
|
||||
expect(mockToastNotify).toHaveBeenCalled()
|
||||
expect(mockToastError).toHaveBeenCalled()
|
||||
expect(nameInput).toHaveValue('')
|
||||
|
||||
fireEvent.change(nameInput, { target: { value: 'temporary_name' } })
|
||||
@@ -649,7 +658,7 @@ describe('parameter-extractor path', () => {
|
||||
await user.click(screen.getByRole('button', { name: 'common.operation.save' }))
|
||||
|
||||
expect(onSave).not.toHaveBeenCalled()
|
||||
expect(mockToastNotify).toHaveBeenCalled()
|
||||
expect(mockToastError).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should keep rename metadata and updated options when editing a select parameter', async () => {
|
||||
|
||||
@@ -15,7 +15,7 @@ import Modal from '@/app/components/base/modal'
|
||||
import Select from '@/app/components/base/select'
|
||||
import Switch from '@/app/components/base/switch'
|
||||
import Textarea from '@/app/components/base/textarea'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import { ChangeType } from '@/app/components/workflow/types'
|
||||
import { checkKeys } from '@/utils/var'
|
||||
import { ParamType } from '../../types'
|
||||
@@ -54,10 +54,7 @@ const AddExtractParameter: FC<Props> = ({
|
||||
if (key === 'name') {
|
||||
const { isValid, errorKey, errorMessageKey } = checkKeys([value], true)
|
||||
if (!isValid) {
|
||||
Toast.notify({
|
||||
type: 'error',
|
||||
message: t(`varKeyError.${errorMessageKey}`, { ns: 'appDebug', key: errorKey }),
|
||||
})
|
||||
toast.error(t(`varKeyError.${errorMessageKey}`, { ns: 'appDebug', key: errorKey }))
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -106,10 +103,7 @@ const AddExtractParameter: FC<Props> = ({
|
||||
errMessage = t(`${errorI18nPrefix}.fieldRequired`, { ns: 'workflow', field: t(`${i18nPrefix}.addExtractParameterContent.description`, { ns: 'workflow' }) })
|
||||
|
||||
if (errMessage) {
|
||||
Toast.notify({
|
||||
type: 'error',
|
||||
message: errMessage,
|
||||
})
|
||||
toast.error(errMessage)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
|
||||
@@ -7,7 +7,7 @@ import * as React from 'react'
|
||||
import { useCallback, useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { ReactSortable } from 'react-sortablejs'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import { ChangeType } from '@/app/components/workflow/types'
|
||||
import { cn } from '@/utils/classnames'
|
||||
import { hasDuplicateStr } from '@/utils/var'
|
||||
@@ -43,10 +43,7 @@ const VarList: FC<Props> = ({
|
||||
}
|
||||
|
||||
if (errorMsgKey && typeName) {
|
||||
Toast.notify({
|
||||
type: 'error',
|
||||
message: t(errorMsgKey, { ns: 'appDebug', key: t(typeName, { ns: 'appDebug' }) }),
|
||||
})
|
||||
toast.error(t(errorMsgKey, { ns: 'appDebug', key: t(typeName, { ns: 'appDebug' }) }))
|
||||
return false
|
||||
}
|
||||
onChange(newList, moreInfo ? { index, payload: moreInfo } : undefined)
|
||||
|
||||
@@ -4,7 +4,7 @@ import { useBoolean } from 'ahooks'
|
||||
import { produce } from 'immer'
|
||||
import { useCallback, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import {
|
||||
useIsChatMode,
|
||||
useNodesReadOnly,
|
||||
@@ -97,10 +97,7 @@ const useConfig = (id: string, payload: StartNodeType) => {
|
||||
}
|
||||
|
||||
if (errorMsgKey && typeName) {
|
||||
Toast.notify({
|
||||
type: 'error',
|
||||
message: t(errorMsgKey, { ns: 'appDebug', key: t(typeName, { ns: 'appDebug' }) }),
|
||||
})
|
||||
toast.error(t(errorMsgKey, { ns: 'appDebug', key: t(typeName, { ns: 'appDebug' }) }))
|
||||
return false
|
||||
}
|
||||
setInputs(newInputs)
|
||||
|
||||
@@ -5,7 +5,7 @@ import { capitalize } from 'es-toolkit/string'
|
||||
import { produce } from 'immer'
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import { useLanguage } from '@/app/components/header/account-setting/model-provider-page/hooks'
|
||||
import { CollectionType } from '@/app/components/tools/types'
|
||||
import {
|
||||
@@ -66,10 +66,7 @@ const useConfig = (id: string, payload: ToolNodeType) => {
|
||||
async (value: any) => {
|
||||
await updateBuiltInToolCredential(currCollection?.name as string, value)
|
||||
|
||||
Toast.notify({
|
||||
type: 'success',
|
||||
message: t('api.actionSuccess', { ns: 'common' }),
|
||||
})
|
||||
toast.success(t('api.actionSuccess', { ns: 'common' }))
|
||||
invalidToolsByType()
|
||||
hideSetAuthModal()
|
||||
},
|
||||
|
||||
@@ -8,7 +8,6 @@ import { useEffect, useRef, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import InputWithCopy from '@/app/components/base/input-with-copy'
|
||||
import { SimpleSelect } from '@/app/components/base/select'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import {
|
||||
NumberField,
|
||||
@@ -18,6 +17,7 @@ import {
|
||||
NumberFieldIncrement,
|
||||
NumberFieldInput,
|
||||
} from '@/app/components/base/ui/number-field'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import Field from '@/app/components/workflow/nodes/_base/components/field'
|
||||
import OutputVars from '@/app/components/workflow/nodes/_base/components/output-vars'
|
||||
import Split from '@/app/components/workflow/nodes/_base/components/split'
|
||||
@@ -102,10 +102,7 @@ const Panel: FC<NodePanelProps<WebhookTriggerNodeType>> = ({
|
||||
placeholder={t(`${i18nPrefix}.webhookUrlPlaceholder`, { ns: 'workflow' })}
|
||||
readOnly
|
||||
onCopy={() => {
|
||||
Toast.notify({
|
||||
type: 'success',
|
||||
message: t(`${i18nPrefix}.urlCopied`, { ns: 'workflow' }),
|
||||
})
|
||||
toast.success(t(`${i18nPrefix}.urlCopied`, { ns: 'workflow' }))
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -5,7 +5,7 @@ import { useCallback } from 'react'
|
||||
|
||||
import { useTranslation } from 'react-i18next'
|
||||
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 { useNodesReadOnly, useWorkflow } from '@/app/components/workflow/hooks'
|
||||
import useNodeCrud from '@/app/components/workflow/nodes/_base/hooks/use-node-crud'
|
||||
import { VarType } from '@/app/components/workflow/types'
|
||||
@@ -67,13 +67,10 @@ export const useConfig = (id: string, payload: WebhookTriggerNodeType) => {
|
||||
|
||||
const hasReservedConflict = sanitizedEntries.some(entry => entry.sanitizedName === WEBHOOK_RAW_VARIABLE_NAME)
|
||||
if (hasReservedConflict) {
|
||||
Toast.notify({
|
||||
type: 'error',
|
||||
message: t('varKeyError.keyAlreadyExists', {
|
||||
ns: 'appDebug',
|
||||
key: t('variableConfig.varName', { ns: 'appDebug' }),
|
||||
}),
|
||||
})
|
||||
toast.error(t('varKeyError.keyAlreadyExists', {
|
||||
ns: 'appDebug',
|
||||
key: t('variableConfig.varName', { ns: 'appDebug' }),
|
||||
}))
|
||||
return false
|
||||
}
|
||||
const existingOtherVarNames = new Set(
|
||||
@@ -84,37 +81,28 @@ export const useConfig = (id: string, payload: WebhookTriggerNodeType) => {
|
||||
|
||||
const crossScopeConflict = sanitizedEntries.find(entry => existingOtherVarNames.has(entry.sanitizedName))
|
||||
if (crossScopeConflict) {
|
||||
Toast.notify({
|
||||
type: 'error',
|
||||
message: t('varKeyError.keyAlreadyExists', {
|
||||
ns: 'appDebug',
|
||||
key: crossScopeConflict.sanitizedName,
|
||||
}),
|
||||
})
|
||||
toast.error(t('varKeyError.keyAlreadyExists', {
|
||||
ns: 'appDebug',
|
||||
key: crossScopeConflict.sanitizedName,
|
||||
}))
|
||||
return false
|
||||
}
|
||||
|
||||
if (hasDuplicateStr(sanitizedEntries.map(entry => entry.sanitizedName))) {
|
||||
Toast.notify({
|
||||
type: 'error',
|
||||
message: t('varKeyError.keyAlreadyExists', {
|
||||
ns: 'appDebug',
|
||||
key: t('variableConfig.varName', { ns: 'appDebug' }),
|
||||
}),
|
||||
})
|
||||
toast.error(t('varKeyError.keyAlreadyExists', {
|
||||
ns: 'appDebug',
|
||||
key: t('variableConfig.varName', { ns: 'appDebug' }),
|
||||
}))
|
||||
return false
|
||||
}
|
||||
|
||||
for (const { sanitizedName } of sanitizedEntries) {
|
||||
const { isValid, errorMessageKey } = checkKeys([sanitizedName], false)
|
||||
if (!isValid) {
|
||||
Toast.notify({
|
||||
type: 'error',
|
||||
message: t(`varKeyError.${errorMessageKey}`, {
|
||||
ns: 'appDebug',
|
||||
key: t('variableConfig.varName', { ns: 'appDebug' }),
|
||||
}),
|
||||
})
|
||||
toast.error(t(`varKeyError.${errorMessageKey}`, {
|
||||
ns: 'appDebug',
|
||||
key: t('variableConfig.varName', { ns: 'appDebug' }),
|
||||
}))
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { VariableAssignerNodeType } from '../types'
|
||||
import type { PanelProps } from '@/types/workflow'
|
||||
import { fireEvent, render, screen } from '@testing-library/react'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import { renderWorkflowFlowComponent } from '@/app/components/workflow/__tests__/workflow-test-env'
|
||||
import { BlockEnum, VarType } from '@/app/components/workflow/types'
|
||||
import AddVariable from '../components/add-variable'
|
||||
@@ -19,6 +19,15 @@ const mockHandleGroupItemMouseEnter = vi.fn()
|
||||
const mockHandleGroupItemMouseLeave = vi.fn()
|
||||
const mockGetAvailableVars = vi.fn()
|
||||
|
||||
vi.mock('@/app/components/base/ui/toast', () => ({
|
||||
toast: {
|
||||
success: vi.fn(),
|
||||
error: vi.fn(),
|
||||
warning: vi.fn(),
|
||||
info: vi.fn(),
|
||||
},
|
||||
}))
|
||||
|
||||
vi.mock('@/app/components/workflow/nodes/_base/components/add-variable-popup', () => ({
|
||||
default: ({ onSelect }: any) => (
|
||||
<button
|
||||
@@ -102,6 +111,7 @@ vi.mock('../use-config', () => ({
|
||||
}))
|
||||
|
||||
const mockUseConfig = vi.mocked(useConfig)
|
||||
const mockToastError = vi.mocked(toast.error)
|
||||
|
||||
const createData = (overrides: Partial<VariableAssignerNodeType> = {}): VariableAssignerNodeType => ({
|
||||
title: 'Variable Assigner',
|
||||
@@ -168,7 +178,6 @@ describe('variable-assigner path', () => {
|
||||
},
|
||||
])
|
||||
mockUseConfig.mockReturnValue(createConfigResult())
|
||||
vi.spyOn(Toast, 'notify').mockImplementation(() => ({}))
|
||||
})
|
||||
|
||||
describe('Path Integration', () => {
|
||||
@@ -296,7 +305,7 @@ describe('variable-assigner path', () => {
|
||||
|
||||
await user.click(screen.getByText('Group1'))
|
||||
fireEvent.change(screen.getByDisplayValue('Group1'), { target: { value: '1bad' } })
|
||||
expect(Toast.notify).toHaveBeenCalled()
|
||||
expect(mockToastError).toHaveBeenCalled()
|
||||
|
||||
fireEvent.change(screen.getByDisplayValue('Group1'), { target: { value: 'Renamed Group' } })
|
||||
expect(onGroupNameChange).toHaveBeenCalledWith('Renamed_Group')
|
||||
|
||||
@@ -11,7 +11,7 @@ import * as React from 'react'
|
||||
import { useCallback } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Folder } from '@/app/components/base/icons/src/vender/line/files'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import Field from '@/app/components/workflow/nodes/_base/components/field'
|
||||
import { VarType as VarKindType } from '@/app/components/workflow/nodes/tool/types'
|
||||
import { VarType } from '@/app/components/workflow/types'
|
||||
@@ -94,10 +94,7 @@ const VarGroupItem: FC<Props> = ({
|
||||
const value = e.target.value
|
||||
const { isValid, errorKey, errorMessageKey } = checkKeys([value], false)
|
||||
if (!isValid) {
|
||||
Toast.notify({
|
||||
type: 'error',
|
||||
message: t(`varKeyError.${errorMessageKey}`, { ns: 'appDebug', key: errorKey }),
|
||||
})
|
||||
toast.error(t(`varKeyError.${errorMessageKey}`, { ns: 'appDebug', key: errorKey }))
|
||||
return
|
||||
}
|
||||
onGroupNameChange?.(value)
|
||||
|
||||
@@ -17,11 +17,13 @@ vi.mock('next/navigation', () => ({
|
||||
useParams: () => ({}),
|
||||
}))
|
||||
|
||||
vi.mock('@/app/components/base/toast/context', () => ({
|
||||
useToastContext: () => ({
|
||||
notify: mockNotify,
|
||||
close: vi.fn(),
|
||||
}),
|
||||
vi.mock('@/app/components/base/ui/toast', () => ({
|
||||
toast: {
|
||||
success: (message: string) => mockNotify({ type: 'success', message }),
|
||||
error: (message: string) => mockNotify({ type: 'error', message }),
|
||||
warning: (message: string) => mockNotify({ type: 'warning', message }),
|
||||
info: (message: string) => mockNotify({ type: 'info', message }),
|
||||
},
|
||||
}))
|
||||
|
||||
vi.mock('@/app/components/base/chat/chat/check-input-forms-hooks', () => ({
|
||||
|
||||
@@ -4,8 +4,7 @@ import { produce } from 'immer'
|
||||
import * as React from 'react'
|
||||
import { useCallback, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useContext } from 'use-context-selector'
|
||||
import { ToastContext } from '@/app/components/base/toast/context'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import RemoveButton from '@/app/components/workflow/nodes/_base/components/remove-button'
|
||||
import VariableTypeSelector from '@/app/components/workflow/panel/chat-variable-panel/components/variable-type-select'
|
||||
import { ChatVarType } from '@/app/components/workflow/panel/chat-variable-panel/type'
|
||||
@@ -33,19 +32,21 @@ const ObjectValueItem: FC<Props> = ({
|
||||
onChange,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const { notify } = useContext(ToastContext)
|
||||
const [isFocus, setIsFocus] = useState(false)
|
||||
|
||||
const handleKeyChange = useCallback((index: number) => {
|
||||
return (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
if (!/^\w+$/.test(e.target.value)) {
|
||||
toast.error(t('chatVariable.modal.objectKeyPatternError', { ns: 'workflow' }))
|
||||
return
|
||||
}
|
||||
|
||||
const newList = produce(list, (draft: any[]) => {
|
||||
if (!/^\w+$/.test(e.target.value))
|
||||
return notify({ type: 'error', message: 'key is can only contain letters, numbers and underscores' })
|
||||
draft[index].key = e.target.value
|
||||
})
|
||||
onChange(newList)
|
||||
}
|
||||
}, [list, notify, onChange])
|
||||
}, [list, onChange, t])
|
||||
|
||||
const handleTypeChange = useCallback((index: number) => {
|
||||
return (type: ChatVarType) => {
|
||||
|
||||
@@ -3,11 +3,10 @@ import { RiCloseLine, RiDraftLine, RiInputField } from '@remixicon/react'
|
||||
import * as React from 'react'
|
||||
import { useCallback, useEffect, useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useContext } from 'use-context-selector'
|
||||
import { v4 as uuid4 } from 'uuid'
|
||||
import Button from '@/app/components/base/button'
|
||||
import Input from '@/app/components/base/input'
|
||||
import { ToastContext } from '@/app/components/base/toast/context'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import CodeEditor from '@/app/components/workflow/nodes/_base/components/editor/code-editor'
|
||||
import { CodeLanguage } from '@/app/components/workflow/nodes/code/types'
|
||||
import ArrayValueList from '@/app/components/workflow/panel/chat-variable-panel/components/array-value-list'
|
||||
@@ -57,7 +56,6 @@ const ChatVariableModal = ({
|
||||
onSave,
|
||||
}: ModalPropsType) => {
|
||||
const { t } = useTranslation()
|
||||
const { notify } = useContext(ToastContext)
|
||||
const workflowStore = useWorkflowStore()
|
||||
const [name, setName] = React.useState('')
|
||||
const [type, setType] = React.useState<ChatVarType>(ChatVarType.String)
|
||||
@@ -125,10 +123,7 @@ const ChatVariableModal = ({
|
||||
const checkVariableName = (value: string) => {
|
||||
const { isValid, errorMessageKey } = checkKeys([value], false)
|
||||
if (!isValid) {
|
||||
notify({
|
||||
type: 'error',
|
||||
message: t(`varKeyError.${errorMessageKey}`, { ns: 'appDebug', key: t('env.modal.name', { ns: 'workflow' }) }),
|
||||
})
|
||||
toast.error(t(`varKeyError.${errorMessageKey}`, { ns: 'appDebug', key: t('env.modal.name', { ns: 'workflow' }) }))
|
||||
return false
|
||||
}
|
||||
return true
|
||||
@@ -236,11 +231,9 @@ const ChatVariableModal = ({
|
||||
return
|
||||
const varList = workflowStore.getState().conversationVariables
|
||||
if (!chatVar && varList.some(chatVar => chatVar.name === name))
|
||||
return notify({ type: 'error', message: 'name is existed' })
|
||||
// if (type !== ChatVarType.Object && !value)
|
||||
// return notify({ type: 'error', message: 'value can not be empty' })
|
||||
return toast.error(t('varKeyError.keyAlreadyExists', { ns: 'appDebug', key: t('chatVariable.modal.name', { ns: 'workflow' }) }))
|
||||
if (type === ChatVarType.Object && objectValue.some(item => !item.key && !!item.value))
|
||||
return notify({ type: 'error', message: 'object key can not be empty' })
|
||||
return toast.error(t('chatVariable.modal.objectKeyRequired', { ns: 'workflow' }))
|
||||
|
||||
onSave({
|
||||
id: chatVar ? chatVar.id : uuid4(),
|
||||
|
||||
@@ -27,8 +27,13 @@ vi.mock('@/service/workflow', () => ({
|
||||
submitHumanInputForm: (...args: any[]) => mockSubmitHumanInputForm(...args),
|
||||
}))
|
||||
|
||||
vi.mock('@/app/components/base/toast/context', () => ({
|
||||
useToastContext: () => ({ notify: mockNotify }),
|
||||
vi.mock('@/app/components/base/ui/toast', () => ({
|
||||
toast: {
|
||||
success: vi.fn(),
|
||||
error: vi.fn(),
|
||||
warning: vi.fn(),
|
||||
info: (...args: any[]) => mockNotify(...args),
|
||||
},
|
||||
}))
|
||||
|
||||
vi.mock('reactflow', () => ({
|
||||
|
||||
@@ -26,8 +26,13 @@ vi.mock('@/service/workflow', () => ({
|
||||
submitHumanInputForm: (...args: any[]) => mockSubmitHumanInputForm(...args),
|
||||
}))
|
||||
|
||||
vi.mock('@/app/components/base/toast/context', () => ({
|
||||
useToastContext: () => ({ notify: mockNotify }),
|
||||
vi.mock('@/app/components/base/ui/toast', () => ({
|
||||
toast: {
|
||||
success: vi.fn(),
|
||||
error: vi.fn(),
|
||||
warning: vi.fn(),
|
||||
info: (...args: any[]) => mockNotify(...args),
|
||||
},
|
||||
}))
|
||||
|
||||
vi.mock('reactflow', () => ({
|
||||
@@ -96,7 +101,7 @@ describe('useChat – handleSend', () => {
|
||||
expect(returned).toBe(false)
|
||||
})
|
||||
|
||||
expect(mockNotify).toHaveBeenCalledWith(expect.objectContaining({ type: 'info' }))
|
||||
expect(mockNotify).toHaveBeenCalledWith('appDebug.errorMessage.waitForResponse')
|
||||
})
|
||||
|
||||
it('should set isResponding to true after sending', () => {
|
||||
|
||||
@@ -27,8 +27,13 @@ vi.mock('@/service/workflow', () => ({
|
||||
submitHumanInputForm: (...args: any[]) => mockSubmitHumanInputForm(...args),
|
||||
}))
|
||||
|
||||
vi.mock('@/app/components/base/toast/context', () => ({
|
||||
useToastContext: () => ({ notify: mockNotify }),
|
||||
vi.mock('@/app/components/base/ui/toast', () => ({
|
||||
toast: {
|
||||
success: vi.fn(),
|
||||
error: vi.fn(),
|
||||
warning: vi.fn(),
|
||||
info: (...args: any[]) => mockNotify(...args),
|
||||
},
|
||||
}))
|
||||
|
||||
vi.mock('reactflow', () => ({
|
||||
|
||||
@@ -27,8 +27,13 @@ vi.mock('@/service/workflow', () => ({
|
||||
submitHumanInputForm: (...args: any[]) => mockSubmitHumanInputForm(...args),
|
||||
}))
|
||||
|
||||
vi.mock('@/app/components/base/toast/context', () => ({
|
||||
useToastContext: () => ({ notify: mockNotify }),
|
||||
vi.mock('@/app/components/base/ui/toast', () => ({
|
||||
toast: {
|
||||
success: vi.fn(),
|
||||
error: vi.fn(),
|
||||
warning: vi.fn(),
|
||||
info: (...args: any[]) => mockNotify(...args),
|
||||
},
|
||||
}))
|
||||
|
||||
vi.mock('reactflow', () => ({
|
||||
|
||||
@@ -27,8 +27,13 @@ vi.mock('@/service/workflow', () => ({
|
||||
submitHumanInputForm: (...args: any[]) => mockSubmitHumanInputForm(...args),
|
||||
}))
|
||||
|
||||
vi.mock('@/app/components/base/toast/context', () => ({
|
||||
useToastContext: () => ({ notify: mockNotify }),
|
||||
vi.mock('@/app/components/base/ui/toast', () => ({
|
||||
toast: {
|
||||
success: vi.fn(),
|
||||
error: vi.fn(),
|
||||
warning: vi.fn(),
|
||||
info: (...args: any[]) => mockNotify(...args),
|
||||
},
|
||||
}))
|
||||
|
||||
vi.mock('reactflow', () => ({
|
||||
|
||||
@@ -26,8 +26,13 @@ vi.mock('@/service/workflow', () => ({
|
||||
submitHumanInputForm: (...args: any[]) => mockSubmitHumanInputForm(...args),
|
||||
}))
|
||||
|
||||
vi.mock('@/app/components/base/toast/context', () => ({
|
||||
useToastContext: () => ({ notify: mockNotify }),
|
||||
vi.mock('@/app/components/base/ui/toast', () => ({
|
||||
toast: {
|
||||
success: vi.fn(),
|
||||
error: vi.fn(),
|
||||
warning: vi.fn(),
|
||||
info: (...args: any[]) => mockNotify(...args),
|
||||
},
|
||||
}))
|
||||
|
||||
vi.mock('reactflow', () => ({
|
||||
|
||||
@@ -26,7 +26,7 @@ import {
|
||||
getProcessedFiles,
|
||||
getProcessedFilesFromResponse,
|
||||
} from '@/app/components/base/file-uploader/utils'
|
||||
import { useToastContext } from '@/app/components/base/toast/context'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import {
|
||||
CUSTOM_NODE,
|
||||
} from '@/app/components/workflow/constants'
|
||||
@@ -57,7 +57,6 @@ export const useChat = (
|
||||
stopChat?: (taskId: string) => void,
|
||||
) => {
|
||||
const { t } = useTranslation()
|
||||
const { notify } = useToastContext()
|
||||
const { handleRun } = useWorkflowRun()
|
||||
const hasStopResponded = useRef(false)
|
||||
const workflowStore = useWorkflowStore()
|
||||
@@ -259,7 +258,7 @@ export const useChat = (
|
||||
}: SendCallback,
|
||||
) => {
|
||||
if (isRespondingRef.current) {
|
||||
notify({ type: 'info', message: t('errorMessage.waitForResponse', { ns: 'appDebug' }) })
|
||||
toast.info(t('errorMessage.waitForResponse', { ns: 'appDebug' }))
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -659,7 +658,7 @@ export const useChat = (
|
||||
},
|
||||
},
|
||||
)
|
||||
}, [threadMessages, chatTree.length, updateCurrentQAOnTree, handleResponding, formSettings?.inputsForm, handleRun, notify, t, workflowStore, fetchInspectVars, invalidAllLastRun, config?.suggested_questions_after_answer?.enabled])
|
||||
}, [threadMessages, chatTree.length, updateCurrentQAOnTree, handleResponding, formSettings?.inputsForm, handleRun, t, workflowStore, fetchInspectVars, invalidAllLastRun, config?.suggested_questions_after_answer?.enabled])
|
||||
|
||||
const handleSubmitHumanInputForm = async (formToken: string, formData: any) => {
|
||||
await submitHumanInputForm(formToken, formData)
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import type { ReactElement } from 'react'
|
||||
import type { IToastProps } from '@/app/components/base/toast/context'
|
||||
import type { Shape } from '@/app/components/workflow/store/workflow'
|
||||
import type { EnvironmentVariable } from '@/app/components/workflow/types'
|
||||
import { fireEvent, render, screen } from '@testing-library/react'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
import * as React from 'react'
|
||||
import { ToastContext } from '@/app/components/base/toast/context'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import { WorkflowContext } from '@/app/components/workflow/context'
|
||||
import { createWorkflowStore } from '@/app/components/workflow/store/workflow'
|
||||
import EnvItem from '../env-item'
|
||||
@@ -16,6 +15,17 @@ vi.mock('uuid', () => ({
|
||||
v4: () => 'env-created',
|
||||
}))
|
||||
|
||||
vi.mock('@/app/components/base/ui/toast', () => ({
|
||||
toast: {
|
||||
success: vi.fn(),
|
||||
error: vi.fn(),
|
||||
warning: vi.fn(),
|
||||
info: vi.fn(),
|
||||
},
|
||||
}))
|
||||
|
||||
const mockToastError = vi.mocked(toast.error)
|
||||
|
||||
const createEnv = (overrides: Partial<EnvironmentVariable> = {}): EnvironmentVariable => ({
|
||||
id: 'env-1',
|
||||
name: 'api_key',
|
||||
@@ -29,27 +39,22 @@ const renderWithProviders = (
|
||||
ui: ReactElement,
|
||||
options: {
|
||||
storeState?: Partial<Shape>
|
||||
notify?: (props: IToastProps) => void
|
||||
} = {},
|
||||
) => {
|
||||
const store = createWorkflowStore({})
|
||||
const notify = options.notify ?? vi.fn<(props: IToastProps) => void>()
|
||||
|
||||
if (options.storeState)
|
||||
store.setState(options.storeState)
|
||||
|
||||
const result = render(
|
||||
<ToastContext.Provider value={{ notify, close: vi.fn() }}>
|
||||
<WorkflowContext.Provider value={store}>
|
||||
{ui}
|
||||
</WorkflowContext.Provider>
|
||||
</ToastContext.Provider>,
|
||||
<WorkflowContext.Provider value={store}>
|
||||
{ui}
|
||||
</WorkflowContext.Provider>,
|
||||
)
|
||||
|
||||
return {
|
||||
...result,
|
||||
store,
|
||||
notify,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,33 +158,27 @@ describe('EnvPanel integration', () => {
|
||||
|
||||
it('should reject invalid and duplicate variable names', async () => {
|
||||
const user = userEvent.setup()
|
||||
const notify = vi.fn()
|
||||
|
||||
renderWithProviders(
|
||||
<VariableModal onClose={vi.fn()} onSave={vi.fn()} />,
|
||||
{
|
||||
storeState: {
|
||||
environmentVariables: [createEnv({ id: 'env-existing', name: 'duplicated', value_type: 'string', value: '1' })],
|
||||
},
|
||||
notify,
|
||||
},
|
||||
)
|
||||
|
||||
fireEvent.change(screen.getByPlaceholderText('workflow.env.modal.namePlaceholder'), {
|
||||
target: { value: '1bad' },
|
||||
})
|
||||
expect(notify).toHaveBeenCalled()
|
||||
expect(mockToastError).toHaveBeenCalled()
|
||||
|
||||
notify.mockClear()
|
||||
mockToastError.mockClear()
|
||||
await user.clear(screen.getByPlaceholderText('workflow.env.modal.namePlaceholder'))
|
||||
await user.type(screen.getByPlaceholderText('workflow.env.modal.namePlaceholder'), 'duplicated')
|
||||
await user.type(screen.getByPlaceholderText('workflow.env.modal.valuePlaceholder'), '42')
|
||||
await user.click(screen.getByRole('button', { name: 'common.operation.save' }))
|
||||
|
||||
expect(notify).toHaveBeenCalledWith({
|
||||
type: 'error',
|
||||
message: 'name is existed',
|
||||
})
|
||||
expect(mockToastError).toHaveBeenCalledWith('appDebug.varKeyError.keyAlreadyExists:{"key":"workflow.env.modal.name"}')
|
||||
})
|
||||
|
||||
it('should load existing secret values and convert them to numbers when editing', async () => {
|
||||
|
||||
@@ -3,12 +3,11 @@ import { RiCloseLine } from '@remixicon/react'
|
||||
import * as React from 'react'
|
||||
import { useEffect } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useContext } from 'use-context-selector'
|
||||
import { v4 as uuid4 } from 'uuid'
|
||||
import Button from '@/app/components/base/button'
|
||||
import Input from '@/app/components/base/input'
|
||||
import { ToastContext } from '@/app/components/base/toast/context'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import { useWorkflowStore } from '@/app/components/workflow/store'
|
||||
import { cn } from '@/utils/classnames'
|
||||
import { checkKeys, replaceSpaceWithUnderscoreInVarNameInput } from '@/utils/var'
|
||||
@@ -24,7 +23,6 @@ const VariableModal = ({
|
||||
onSave,
|
||||
}: ModalPropsType) => {
|
||||
const { t } = useTranslation()
|
||||
const { notify } = useContext(ToastContext)
|
||||
const workflowStore = useWorkflowStore()
|
||||
const [type, setType] = React.useState<'string' | 'number' | 'secret'>('string')
|
||||
const [name, setName] = React.useState('')
|
||||
@@ -34,10 +32,7 @@ const VariableModal = ({
|
||||
const checkVariableName = (value: string) => {
|
||||
const { isValid, errorMessageKey } = checkKeys([value], false)
|
||||
if (!isValid) {
|
||||
notify({
|
||||
type: 'error',
|
||||
message: t(`varKeyError.${errorMessageKey}`, { ns: 'appDebug', key: t('env.modal.name', { ns: 'workflow' }) }),
|
||||
})
|
||||
toast.error(t(`varKeyError.${errorMessageKey}`, { ns: 'appDebug', key: t('env.modal.name', { ns: 'workflow' }) }))
|
||||
return false
|
||||
}
|
||||
return true
|
||||
@@ -54,15 +49,15 @@ const VariableModal = ({
|
||||
if (!checkVariableName(name))
|
||||
return
|
||||
if (!value)
|
||||
return notify({ type: 'error', message: 'value can not be empty' })
|
||||
return toast.error(t('env.modal.valueRequired', { ns: 'workflow' }))
|
||||
|
||||
// Add check for duplicate name when editing
|
||||
const envList = workflowStore.getState().environmentVariables
|
||||
if (env && env.name !== name && envList.some(e => e.name === name))
|
||||
return notify({ type: 'error', message: 'name is existed' })
|
||||
return toast.error(t('varKeyError.keyAlreadyExists', { ns: 'appDebug', key: t('env.modal.name', { ns: 'workflow' }) }))
|
||||
// Original check for create new variable
|
||||
if (!env && envList.some(e => e.name === name))
|
||||
return notify({ type: 'error', message: 'name is existed' })
|
||||
return toast.error(t('varKeyError.keyAlreadyExists', { ns: 'appDebug', key: t('env.modal.name', { ns: 'workflow' }) }))
|
||||
|
||||
onSave({
|
||||
id: env ? env.id : uuid4(),
|
||||
|
||||
@@ -4,9 +4,8 @@ import type { WorkflowRunDetailResponse } from '@/models/log'
|
||||
import type { NodeTracing } from '@/types/workflow'
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useContext } from 'use-context-selector'
|
||||
import Loading from '@/app/components/base/loading'
|
||||
import { ToastContext } from '@/app/components/base/toast/context'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import { WorkflowRunningStatus } from '@/app/components/workflow/types'
|
||||
import { fetchRunDetail, fetchTracingList } from '@/service/log'
|
||||
import { cn } from '@/utils/classnames'
|
||||
@@ -32,7 +31,6 @@ const RunPanel: FC<RunProps> = ({
|
||||
tracingListUrl,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const { notify } = useContext(ToastContext)
|
||||
const [currentTab, setCurrentTab] = useState<string>(activeTab)
|
||||
const [loading, setLoading] = useState<boolean>(true)
|
||||
const [runDetail, setRunDetail] = useState<WorkflowRunDetailResponse>()
|
||||
@@ -55,12 +53,9 @@ const RunPanel: FC<RunProps> = ({
|
||||
getResultCallback(res)
|
||||
}
|
||||
catch (err) {
|
||||
notify({
|
||||
type: 'error',
|
||||
message: `${err}`,
|
||||
})
|
||||
toast.error(`${err}`)
|
||||
}
|
||||
}, [notify, getResultCallback, runDetailUrl])
|
||||
}, [getResultCallback, runDetailUrl])
|
||||
|
||||
const getTracingList = useCallback(async () => {
|
||||
try {
|
||||
@@ -70,12 +65,9 @@ const RunPanel: FC<RunProps> = ({
|
||||
setList(nodeList)
|
||||
}
|
||||
catch (err) {
|
||||
notify({
|
||||
type: 'error',
|
||||
message: `${err}`,
|
||||
})
|
||||
toast.error(`${err}`)
|
||||
}
|
||||
}, [notify, tracingListUrl])
|
||||
}, [tracingListUrl])
|
||||
|
||||
const getData = useCallback(async () => {
|
||||
setLoading(true)
|
||||
|
||||
@@ -18,13 +18,12 @@ import {
|
||||
useState,
|
||||
} from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useContext } from 'use-context-selector'
|
||||
import Uploader from '@/app/components/app/create-from-dsl-modal/uploader'
|
||||
import { useStore as useAppStore } from '@/app/components/app/store'
|
||||
import Button from '@/app/components/base/button'
|
||||
import Modal from '@/app/components/base/modal'
|
||||
import { FILE_EXTS } from '@/app/components/base/prompt-editor/constants'
|
||||
import { ToastContext } from '@/app/components/base/toast/context'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import { usePluginDependencies } from '@/app/components/workflow/plugin-dependency/hooks'
|
||||
import { useEventEmitterContextContext } from '@/context/event-emitter'
|
||||
import {
|
||||
@@ -59,7 +58,6 @@ const UpdateDSLModal = ({
|
||||
onImport,
|
||||
}: UpdateDSLModalProps) => {
|
||||
const { t } = useTranslation()
|
||||
const { notify } = useContext(ToastContext)
|
||||
const appDetail = useAppStore(s => s.appDetail)
|
||||
const [currentFile, setDSLFile] = useState<File>()
|
||||
const [fileContent, setFileContent] = useState<string>()
|
||||
@@ -153,13 +151,13 @@ const UpdateDSLModal = ({
|
||||
return invalidNodes.includes(node?.data?.type)
|
||||
})
|
||||
if (hasInvalidNode) {
|
||||
notify({ type: 'error', message: t('common.importFailure', { ns: 'workflow' }) })
|
||||
toast.error(t('common.importFailure', { ns: 'workflow' }))
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
catch {
|
||||
notify({ type: 'error', message: t('common.importFailure', { ns: 'workflow' }) })
|
||||
toast.error(t('common.importFailure', { ns: 'workflow' }))
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -179,17 +177,13 @@ const UpdateDSLModal = ({
|
||||
|
||||
if (status === DSLImportStatus.COMPLETED || status === DSLImportStatus.COMPLETED_WITH_WARNINGS) {
|
||||
if (!app_id) {
|
||||
notify({ type: 'error', message: t('common.importFailure', { ns: 'workflow' }) })
|
||||
toast.error(t('common.importFailure', { ns: 'workflow' }))
|
||||
return
|
||||
}
|
||||
handleWorkflowUpdate(app_id)
|
||||
if (onImport)
|
||||
onImport()
|
||||
notify({
|
||||
type: status === DSLImportStatus.COMPLETED ? 'success' : 'warning',
|
||||
message: t(status === DSLImportStatus.COMPLETED ? 'common.importSuccess' : 'common.importWarning', { ns: 'workflow' }),
|
||||
children: status === DSLImportStatus.COMPLETED_WITH_WARNINGS && t('common.importWarningDetails', { ns: 'workflow' }),
|
||||
})
|
||||
toast(t(status === DSLImportStatus.COMPLETED ? 'common.importSuccess' : 'common.importWarning', { ns: 'workflow' }), { type: status === DSLImportStatus.COMPLETED ? 'success' : 'warning', description: status === DSLImportStatus.COMPLETED_WITH_WARNINGS && t('common.importWarningDetails', { ns: 'workflow' }) })
|
||||
await handleCheckPluginDependencies(app_id)
|
||||
setLoading(false)
|
||||
onCancel()
|
||||
@@ -207,17 +201,17 @@ const UpdateDSLModal = ({
|
||||
}
|
||||
else {
|
||||
setLoading(false)
|
||||
notify({ type: 'error', message: t('common.importFailure', { ns: 'workflow' }) })
|
||||
toast.error(t('common.importFailure', { ns: 'workflow' }))
|
||||
}
|
||||
}
|
||||
}
|
||||
// eslint-disable-next-line unused-imports/no-unused-vars
|
||||
catch (e) {
|
||||
setLoading(false)
|
||||
notify({ type: 'error', message: t('common.importFailure', { ns: 'workflow' }) })
|
||||
toast.error(t('common.importFailure', { ns: 'workflow' }))
|
||||
}
|
||||
isCreatingRef.current = false
|
||||
}, [currentFile, fileContent, onCancel, notify, t, appDetail, onImport, handleWorkflowUpdate, handleCheckPluginDependencies])
|
||||
}, [currentFile, fileContent, onCancel, t, appDetail, onImport, handleWorkflowUpdate, handleCheckPluginDependencies])
|
||||
|
||||
const onUpdateDSLConfirm: MouseEventHandler = async () => {
|
||||
try {
|
||||
@@ -231,26 +225,26 @@ const UpdateDSLModal = ({
|
||||
|
||||
if (status === DSLImportStatus.COMPLETED) {
|
||||
if (!app_id) {
|
||||
notify({ type: 'error', message: t('common.importFailure', { ns: 'workflow' }) })
|
||||
toast.error(t('common.importFailure', { ns: 'workflow' }))
|
||||
return
|
||||
}
|
||||
handleWorkflowUpdate(app_id)
|
||||
await handleCheckPluginDependencies(app_id)
|
||||
if (onImport)
|
||||
onImport()
|
||||
notify({ type: 'success', message: t('common.importSuccess', { ns: 'workflow' }) })
|
||||
toast.success(t('common.importSuccess', { ns: 'workflow' }))
|
||||
setLoading(false)
|
||||
onCancel()
|
||||
}
|
||||
else if (status === DSLImportStatus.FAILED) {
|
||||
setLoading(false)
|
||||
notify({ type: 'error', message: t('common.importFailure', { ns: 'workflow' }) })
|
||||
toast.error(t('common.importFailure', { ns: 'workflow' }))
|
||||
}
|
||||
}
|
||||
// eslint-disable-next-line unused-imports/no-unused-vars
|
||||
catch (e) {
|
||||
setLoading(false)
|
||||
notify({ type: 'error', message: t('common.importFailure', { ns: 'workflow' }) })
|
||||
toast.error(t('common.importFailure', { ns: 'workflow' }))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6386,14 +6386,9 @@
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"app/components/tools/workflow-tool/hooks/use-configure-button.ts": {
|
||||
"no-restricted-imports": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"app/components/tools/workflow-tool/index.tsx": {
|
||||
"no-restricted-imports": {
|
||||
"count": 2
|
||||
"count": 1
|
||||
},
|
||||
"tailwindcss/enforce-consistent-class-order": {
|
||||
"count": 7
|
||||
@@ -6599,7 +6594,7 @@
|
||||
},
|
||||
"app/components/workflow/block-selector/tool-picker.tsx": {
|
||||
"no-restricted-imports": {
|
||||
"count": 2
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"app/components/workflow/block-selector/tool/action-item.tsx": {
|
||||
@@ -6694,9 +6689,6 @@
|
||||
}
|
||||
},
|
||||
"app/components/workflow/header/header-in-restoring.tsx": {
|
||||
"no-restricted-imports": {
|
||||
"count": 1
|
||||
},
|
||||
"tailwindcss/no-unnecessary-whitespace": {
|
||||
"count": 1
|
||||
}
|
||||
@@ -6710,9 +6702,6 @@
|
||||
"no-console": {
|
||||
"count": 1
|
||||
},
|
||||
"no-restricted-imports": {
|
||||
"count": 1
|
||||
},
|
||||
"ts/no-explicit-any": {
|
||||
"count": 1
|
||||
}
|
||||
@@ -6773,9 +6762,6 @@
|
||||
}
|
||||
},
|
||||
"app/components/workflow/hooks/use-checklist.ts": {
|
||||
"no-restricted-imports": {
|
||||
"count": 1
|
||||
},
|
||||
"ts/no-empty-object-type": {
|
||||
"count": 1
|
||||
},
|
||||
@@ -6891,9 +6877,6 @@
|
||||
}
|
||||
},
|
||||
"app/components/workflow/nodes/_base/components/before-run-form/index.tsx": {
|
||||
"no-restricted-imports": {
|
||||
"count": 1
|
||||
},
|
||||
"ts/no-explicit-any": {
|
||||
"count": 11
|
||||
}
|
||||
@@ -7331,9 +7314,6 @@
|
||||
}
|
||||
},
|
||||
"app/components/workflow/nodes/_base/components/workflow-panel/last-run/use-last-run.ts": {
|
||||
"no-restricted-imports": {
|
||||
"count": 1
|
||||
},
|
||||
"react/set-state-in-effect": {
|
||||
"count": 1
|
||||
},
|
||||
@@ -7353,9 +7333,6 @@
|
||||
}
|
||||
},
|
||||
"app/components/workflow/nodes/_base/hooks/use-one-step-run.ts": {
|
||||
"no-restricted-imports": {
|
||||
"count": 1
|
||||
},
|
||||
"react/set-state-in-effect": {
|
||||
"count": 2
|
||||
},
|
||||
@@ -7623,7 +7600,7 @@
|
||||
},
|
||||
"app/components/workflow/nodes/http/components/curl-panel.tsx": {
|
||||
"no-restricted-imports": {
|
||||
"count": 2
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"app/components/workflow/nodes/http/components/key-value/key-value-edit/index.tsx": {
|
||||
@@ -7680,7 +7657,7 @@
|
||||
},
|
||||
"app/components/workflow/nodes/human-input/components/delivery-method/email-configure-modal.tsx": {
|
||||
"no-restricted-imports": {
|
||||
"count": 2
|
||||
"count": 1
|
||||
},
|
||||
"tailwindcss/enforce-consistent-class-order": {
|
||||
"count": 8
|
||||
@@ -7792,11 +7769,6 @@
|
||||
"count": 2
|
||||
}
|
||||
},
|
||||
"app/components/workflow/nodes/human-input/components/user-action.tsx": {
|
||||
"no-restricted-imports": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"app/components/workflow/nodes/human-input/components/variable-in-markdown.tsx": {
|
||||
"react-refresh/only-export-components": {
|
||||
"count": 2
|
||||
@@ -7812,7 +7784,7 @@
|
||||
},
|
||||
"app/components/workflow/nodes/human-input/panel.tsx": {
|
||||
"no-restricted-imports": {
|
||||
"count": 2
|
||||
"count": 1
|
||||
},
|
||||
"tailwindcss/enforce-consistent-class-order": {
|
||||
"count": 4
|
||||
@@ -7912,9 +7884,6 @@
|
||||
}
|
||||
},
|
||||
"app/components/workflow/nodes/iteration/node.tsx": {
|
||||
"no-restricted-imports": {
|
||||
"count": 1
|
||||
},
|
||||
"react/set-state-in-effect": {
|
||||
"count": 1
|
||||
}
|
||||
@@ -8222,9 +8191,6 @@
|
||||
"app/components/workflow/nodes/llm/components/json-schema-config-modal/json-schema-config.tsx": {
|
||||
"erasable-syntax-only/enums": {
|
||||
"count": 1
|
||||
},
|
||||
"no-restricted-imports": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"app/components/workflow/nodes/llm/components/json-schema-config-modal/json-schema-generator/generated-result.tsx": {
|
||||
@@ -8240,7 +8206,7 @@
|
||||
"count": 1
|
||||
},
|
||||
"no-restricted-imports": {
|
||||
"count": 2
|
||||
"count": 1
|
||||
},
|
||||
"react/set-state-in-effect": {
|
||||
"count": 2
|
||||
@@ -8301,9 +8267,6 @@
|
||||
}
|
||||
},
|
||||
"app/components/workflow/nodes/llm/components/json-schema-config-modal/visual-editor/hooks.ts": {
|
||||
"no-restricted-imports": {
|
||||
"count": 1
|
||||
},
|
||||
"ts/no-explicit-any": {
|
||||
"count": 1
|
||||
}
|
||||
@@ -8323,7 +8286,7 @@
|
||||
},
|
||||
"app/components/workflow/nodes/llm/panel.tsx": {
|
||||
"no-restricted-imports": {
|
||||
"count": 2
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"app/components/workflow/nodes/llm/types.ts": {
|
||||
@@ -8433,9 +8396,6 @@
|
||||
}
|
||||
},
|
||||
"app/components/workflow/nodes/loop/components/loop-variables/item.tsx": {
|
||||
"no-restricted-imports": {
|
||||
"count": 1
|
||||
},
|
||||
"ts/no-explicit-any": {
|
||||
"count": 4
|
||||
}
|
||||
@@ -8470,7 +8430,7 @@
|
||||
},
|
||||
"app/components/workflow/nodes/parameter-extractor/components/extract-parameter/update.tsx": {
|
||||
"no-restricted-imports": {
|
||||
"count": 3
|
||||
"count": 2
|
||||
},
|
||||
"ts/no-explicit-any": {
|
||||
"count": 1
|
||||
@@ -8548,11 +8508,6 @@
|
||||
"count": 8
|
||||
}
|
||||
},
|
||||
"app/components/workflow/nodes/start/components/var-list.tsx": {
|
||||
"no-restricted-imports": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"app/components/workflow/nodes/start/node.tsx": {
|
||||
"tailwindcss/enforce-consistent-class-order": {
|
||||
"count": 2
|
||||
@@ -8567,9 +8522,6 @@
|
||||
}
|
||||
},
|
||||
"app/components/workflow/nodes/start/use-config.ts": {
|
||||
"no-restricted-imports": {
|
||||
"count": 1
|
||||
},
|
||||
"ts/no-explicit-any": {
|
||||
"count": 1
|
||||
}
|
||||
@@ -8648,9 +8600,6 @@
|
||||
}
|
||||
},
|
||||
"app/components/workflow/nodes/tool/hooks/use-config.ts": {
|
||||
"no-restricted-imports": {
|
||||
"count": 1
|
||||
},
|
||||
"ts/no-explicit-any": {
|
||||
"count": 6
|
||||
}
|
||||
@@ -8754,12 +8703,7 @@
|
||||
},
|
||||
"app/components/workflow/nodes/trigger-webhook/panel.tsx": {
|
||||
"no-restricted-imports": {
|
||||
"count": 3
|
||||
}
|
||||
},
|
||||
"app/components/workflow/nodes/trigger-webhook/use-config.ts": {
|
||||
"no-restricted-imports": {
|
||||
"count": 1
|
||||
"count": 2
|
||||
}
|
||||
},
|
||||
"app/components/workflow/nodes/trigger-webhook/utils/render-output-vars.tsx": {
|
||||
@@ -8783,9 +8727,6 @@
|
||||
}
|
||||
},
|
||||
"app/components/workflow/nodes/variable-assigner/components/var-group-item.tsx": {
|
||||
"no-restricted-imports": {
|
||||
"count": 1
|
||||
},
|
||||
"tailwindcss/enforce-consistent-class-order": {
|
||||
"count": 2
|
||||
},
|
||||
@@ -8910,9 +8851,6 @@
|
||||
}
|
||||
},
|
||||
"app/components/workflow/panel/chat-variable-panel/components/object-value-item.tsx": {
|
||||
"no-restricted-imports": {
|
||||
"count": 1
|
||||
},
|
||||
"react-refresh/only-export-components": {
|
||||
"count": 1
|
||||
},
|
||||
@@ -8942,9 +8880,6 @@
|
||||
}
|
||||
},
|
||||
"app/components/workflow/panel/chat-variable-panel/components/variable-modal.tsx": {
|
||||
"no-restricted-imports": {
|
||||
"count": 1
|
||||
},
|
||||
"react/set-state-in-effect": {
|
||||
"count": 8
|
||||
},
|
||||
@@ -8990,9 +8925,6 @@
|
||||
}
|
||||
},
|
||||
"app/components/workflow/panel/debug-and-preview/hooks.ts": {
|
||||
"no-restricted-imports": {
|
||||
"count": 1
|
||||
},
|
||||
"ts/no-explicit-any": {
|
||||
"count": 12
|
||||
}
|
||||
@@ -9017,7 +8949,7 @@
|
||||
},
|
||||
"app/components/workflow/panel/env-panel/variable-modal.tsx": {
|
||||
"no-restricted-imports": {
|
||||
"count": 2
|
||||
"count": 1
|
||||
},
|
||||
"react/set-state-in-effect": {
|
||||
"count": 4
|
||||
@@ -9171,9 +9103,6 @@
|
||||
}
|
||||
},
|
||||
"app/components/workflow/run/index.tsx": {
|
||||
"no-restricted-imports": {
|
||||
"count": 1
|
||||
},
|
||||
"react/set-state-in-effect": {
|
||||
"count": 2
|
||||
}
|
||||
@@ -9349,7 +9278,7 @@
|
||||
},
|
||||
"app/components/workflow/update-dsl-modal.tsx": {
|
||||
"no-restricted-imports": {
|
||||
"count": 2
|
||||
"count": 1
|
||||
},
|
||||
"ts/no-explicit-any": {
|
||||
"count": 2
|
||||
|
||||
@@ -96,6 +96,8 @@
|
||||
"chatVariable.modal.name": "Name",
|
||||
"chatVariable.modal.namePlaceholder": "Variable name",
|
||||
"chatVariable.modal.objectKey": "Key",
|
||||
"chatVariable.modal.objectKeyPatternError": "Key can only contain letters, numbers, and underscores",
|
||||
"chatVariable.modal.objectKeyRequired": "Object key cannot be empty",
|
||||
"chatVariable.modal.objectType": "Type",
|
||||
"chatVariable.modal.objectValue": "Default Value",
|
||||
"chatVariable.modal.oneByOne": "Add one by one",
|
||||
@@ -207,6 +209,7 @@
|
||||
"common.runApp": "Run App",
|
||||
"common.runHistory": "Run History",
|
||||
"common.running": "Running",
|
||||
"common.scheduleTriggerRunFailed": "Schedule trigger run failed",
|
||||
"common.searchVar": "Search variable",
|
||||
"common.setVarValuePlaceholder": "Set variable",
|
||||
"common.showRunHistory": "Show Run History",
|
||||
@@ -220,6 +223,8 @@
|
||||
"common.viewDetailInTracingPanel": "View details",
|
||||
"common.viewOnly": "View Only",
|
||||
"common.viewRunHistory": "View run history",
|
||||
"common.webhookDebugFailed": "Webhook debug failed",
|
||||
"common.webhookDebugRequestFailed": "Webhook debug request failed",
|
||||
"common.workflowAsTool": "Workflow as Tool",
|
||||
"common.workflowAsToolDisabledHint": "Publish the latest workflow and ensure a connected User Input node before configuring it as a tool.",
|
||||
"common.workflowAsToolTip": "Tool reconfiguration is required after the workflow update.",
|
||||
@@ -293,6 +298,7 @@
|
||||
"env.modal.type": "Type",
|
||||
"env.modal.value": "Value",
|
||||
"env.modal.valuePlaceholder": "env value",
|
||||
"env.modal.valueRequired": "Value cannot be empty",
|
||||
"error.operations.addingNodes": "adding nodes",
|
||||
"error.operations.connectingNodes": "connecting nodes",
|
||||
"error.operations.modifyingWorkflow": "modifying workflow",
|
||||
@@ -513,7 +519,9 @@
|
||||
"nodes.humanInput.deliveryMethod.contactTip2": "Tell us at <email>support@dify.ai</email>.",
|
||||
"nodes.humanInput.deliveryMethod.emailConfigure.allMembers": "All members ({{workspaceName}})",
|
||||
"nodes.humanInput.deliveryMethod.emailConfigure.body": "Body",
|
||||
"nodes.humanInput.deliveryMethod.emailConfigure.bodyMustContainRequestURL": "Body must contain {{field}}",
|
||||
"nodes.humanInput.deliveryMethod.emailConfigure.bodyPlaceholder": "Enter email body",
|
||||
"nodes.humanInput.deliveryMethod.emailConfigure.bodyRequired": "Body is required",
|
||||
"nodes.humanInput.deliveryMethod.emailConfigure.debugMode": "Debug Mode",
|
||||
"nodes.humanInput.deliveryMethod.emailConfigure.debugModeTip1": "In debug mode, the email will only be sent to your account email <email>{{email}}</email>.",
|
||||
"nodes.humanInput.deliveryMethod.emailConfigure.debugModeTip2": "The production environment is not affected.",
|
||||
@@ -524,9 +532,11 @@
|
||||
"nodes.humanInput.deliveryMethod.emailConfigure.memberSelector.title": "Add workspace members or external recipients",
|
||||
"nodes.humanInput.deliveryMethod.emailConfigure.memberSelector.trigger": "Select",
|
||||
"nodes.humanInput.deliveryMethod.emailConfigure.recipient": "Recipient",
|
||||
"nodes.humanInput.deliveryMethod.emailConfigure.recipientsRequired": "At least one recipient is required",
|
||||
"nodes.humanInput.deliveryMethod.emailConfigure.requestURLTip": "The request URL variable is the trigger entry for human input.",
|
||||
"nodes.humanInput.deliveryMethod.emailConfigure.subject": "Subject",
|
||||
"nodes.humanInput.deliveryMethod.emailConfigure.subjectPlaceholder": "Enter email subject",
|
||||
"nodes.humanInput.deliveryMethod.emailConfigure.subjectRequired": "Subject is required",
|
||||
"nodes.humanInput.deliveryMethod.emailConfigure.title": "Email Configuration",
|
||||
"nodes.humanInput.deliveryMethod.emailSender.debugDone": "A test email has been sent to <email>{{email}}</email>. Please check your inbox.",
|
||||
"nodes.humanInput.deliveryMethod.emailSender.debugModeTip": "Debug mode is enabled.",
|
||||
@@ -741,6 +751,7 @@
|
||||
"nodes.llm.jsonSchema.back": "Back",
|
||||
"nodes.llm.jsonSchema.descriptionPlaceholder": "Add description",
|
||||
"nodes.llm.jsonSchema.doc": "Learn more about structured output",
|
||||
"nodes.llm.jsonSchema.fieldNameAlreadyExists": "Property name already exists",
|
||||
"nodes.llm.jsonSchema.fieldNamePlaceholder": "Field Name",
|
||||
"nodes.llm.jsonSchema.generate": "Generate",
|
||||
"nodes.llm.jsonSchema.generateJsonSchema": "Generate JSON Schema",
|
||||
|
||||
Reference in New Issue
Block a user