mirror of
https://github.com/langgenius/dify.git
synced 2026-04-20 10:47:21 +08:00
refactore: Replace hardcoded null strategy strings with constant
This commit is contained in:
@ -15,6 +15,7 @@ import CodeEditor from '@/app/components/workflow/nodes/_base/components/editor/
|
||||
import Field from '@/app/components/workflow/nodes/_base/components/field'
|
||||
import VarReferencePicker from '@/app/components/workflow/nodes/_base/components/variable/var-reference-picker'
|
||||
import Tab, { TabType } from '@/app/components/workflow/nodes/_base/components/workflow-panel/tab'
|
||||
import { NULL_STRATEGY } from '@/app/components/workflow/nodes/_base/constants'
|
||||
import { CodeLanguage } from '@/app/components/workflow/nodes/code/types'
|
||||
import { cn } from '@/utils/classnames'
|
||||
|
||||
@ -62,12 +63,12 @@ const ConfigPanel: FC<ConfigPanelProps> = ({
|
||||
const [nullStrategyOpen, setNullStrategyOpen] = useState(false)
|
||||
const whenOutputNoneOptions = useMemo(() => ([
|
||||
{
|
||||
value: 'raise_error' as const,
|
||||
value: NULL_STRATEGY.RAISE_ERROR,
|
||||
label: t('subGraphModal.whenOutputNone.error', { ns: 'workflow' }),
|
||||
description: t('subGraphModal.whenOutputNone.errorDesc', { ns: 'workflow' }),
|
||||
},
|
||||
{
|
||||
value: 'use_default' as const,
|
||||
value: NULL_STRATEGY.USE_DEFAULT,
|
||||
label: t('subGraphModal.whenOutputNone.default', { ns: 'workflow' }),
|
||||
description: t('subGraphModal.whenOutputNone.defaultDesc', { ns: 'workflow' }),
|
||||
},
|
||||
@ -194,7 +195,7 @@ const ConfigPanel: FC<ConfigPanelProps> = ({
|
||||
{selectedWhenOutputNoneOption.description}
|
||||
</div>
|
||||
)}
|
||||
{nestedNodeConfig.null_strategy === 'use_default' && (
|
||||
{nestedNodeConfig.null_strategy === NULL_STRATEGY.USE_DEFAULT && (
|
||||
<div className={cn('overflow-hidden rounded-lg border border-components-input-border-active bg-components-input-bg-normal p-1')}>
|
||||
<CodeEditor
|
||||
noWrapper
|
||||
|
||||
@ -22,6 +22,7 @@ import { WorkflowContext } from '@/app/components/workflow/context'
|
||||
import { HooksStoreContext } from '@/app/components/workflow/hooks-store/provider'
|
||||
import CodeEditor from '@/app/components/workflow/nodes/_base/components/editor/code-editor'
|
||||
import VarReferencePicker from '@/app/components/workflow/nodes/_base/components/variable/var-reference-picker'
|
||||
import { NULL_STRATEGY } from '@/app/components/workflow/nodes/_base/constants'
|
||||
import useAvailableVarList from '@/app/components/workflow/nodes/_base/hooks/use-available-var-list'
|
||||
import { CodeLanguage } from '@/app/components/workflow/nodes/code/types'
|
||||
import MixedVariableTextInput from '@/app/components/workflow/nodes/tool/components/mixed-variable-text-input'
|
||||
@ -334,7 +335,7 @@ const FormInputItem: FC<Props> = ({
|
||||
? (nestedNodeConfig ?? varInput?.nested_node_config ?? {
|
||||
extractor_node_id: nodeId && variable ? `${nodeId}_ext_${variable}` : '',
|
||||
output_selector: ['result'],
|
||||
null_strategy: 'use_default',
|
||||
null_strategy: NULL_STRATEGY.RAISE_ERROR,
|
||||
default_value: '',
|
||||
})
|
||||
: undefined
|
||||
|
||||
6
web/app/components/workflow/nodes/_base/constants.ts
Normal file
6
web/app/components/workflow/nodes/_base/constants.ts
Normal file
@ -0,0 +1,6 @@
|
||||
export const NULL_STRATEGY = {
|
||||
RAISE_ERROR: 'raise_error',
|
||||
USE_DEFAULT: 'use_default',
|
||||
} as const
|
||||
|
||||
export type NullStrategy = typeof NULL_STRATEGY[keyof typeof NULL_STRATEGY]
|
||||
@ -1,3 +1,4 @@
|
||||
import type { NullStrategy } from '@/app/components/workflow/nodes/_base/constants'
|
||||
import type { ValueSelector } from '@/app/components/workflow/types'
|
||||
|
||||
// Generic variable types for all resource forms
|
||||
@ -11,7 +12,7 @@ export enum VarKindType {
|
||||
export type NestedNodeConfig = {
|
||||
extractor_node_id: string
|
||||
output_selector: ValueSelector
|
||||
null_strategy: 'raise_error' | 'use_default'
|
||||
null_strategy: NullStrategy
|
||||
default_value: unknown
|
||||
}
|
||||
|
||||
|
||||
@ -23,6 +23,7 @@ type Props = {
|
||||
codeNodeId: string
|
||||
availableVars?: NodeOutPutVar[]
|
||||
availableNodes?: Node[]
|
||||
onOpenInternalViewAndRun?: () => void
|
||||
}
|
||||
|
||||
export type ContextGenerateModalHandle = {
|
||||
@ -59,6 +60,7 @@ const ContextGenerateModal = forwardRef<ContextGenerateModalHandle, Props>(({
|
||||
codeNodeId,
|
||||
availableVars,
|
||||
availableNodes,
|
||||
onOpenInternalViewAndRun,
|
||||
}, ref) => {
|
||||
const configsMap = useHooksStore(s => s.configsMap)
|
||||
const nodes = useStore(s => s.nodes)
|
||||
@ -179,13 +181,22 @@ const ContextGenerateModal = forwardRef<ContextGenerateModalHandle, Props>(({
|
||||
return
|
||||
if (current)
|
||||
applyToNode(false)
|
||||
const store = workflowStore.getState()
|
||||
store.setInitShowLastRunTab(true)
|
||||
store.setPendingSingleRun({
|
||||
nodeId: codeNodeId,
|
||||
action: 'run',
|
||||
})
|
||||
}, [applyToNode, codeNodeId, current, workflowStore])
|
||||
|
||||
if (onOpenInternalViewAndRun) {
|
||||
// Close this modal and open internal view, then run
|
||||
handleCloseModal()
|
||||
onOpenInternalViewAndRun()
|
||||
}
|
||||
else {
|
||||
// Fallback: direct run (for cases without internal view)
|
||||
const store = workflowStore.getState()
|
||||
store.setInitShowLastRunTab(true)
|
||||
store.setPendingSingleRun({
|
||||
nodeId: codeNodeId,
|
||||
action: 'run',
|
||||
})
|
||||
}
|
||||
}, [applyToNode, codeNodeId, current, handleCloseModal, onOpenInternalViewAndRun, workflowStore])
|
||||
|
||||
const isRunning = useMemo(() => {
|
||||
const target = nodes.find(node => node.id === codeNodeId)
|
||||
|
||||
@ -10,6 +10,7 @@ import type {
|
||||
Node as WorkflowNode,
|
||||
} from '@/app/components/workflow/types'
|
||||
import { useCallback, useMemo } from 'react'
|
||||
import { NULL_STRATEGY } from '@/app/components/workflow/nodes/_base/constants'
|
||||
import { Type } from '@/app/components/workflow/nodes/llm/types'
|
||||
import { BlockEnum, EditionType, isPromptMessageContext, PromptRole, VarType } from '@/app/components/workflow/types'
|
||||
import { generateNewNode, getNodeCustomTypeByNodeDataType, mergeNodeDefaultData } from '@/app/components/workflow/utils'
|
||||
@ -46,7 +47,7 @@ export const buildAssembleNestedNodeConfig = (
|
||||
return {
|
||||
extractor_node_id: extractorNodeId,
|
||||
output_selector: defaultOutputKey ? [defaultOutputKey] : [],
|
||||
null_strategy: 'use_default',
|
||||
null_strategy: NULL_STRATEGY.RAISE_ERROR,
|
||||
default_value: '',
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,6 +13,7 @@ import type {
|
||||
import {
|
||||
memo,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
@ -22,9 +23,10 @@ import { useNodes, useStoreApi } from 'reactflow'
|
||||
import PromptEditor from '@/app/components/base/prompt-editor'
|
||||
import { useNodesMetaData, useNodesSyncDraft } from '@/app/components/workflow/hooks'
|
||||
import { useHooksStore } from '@/app/components/workflow/hooks-store'
|
||||
import { NULL_STRATEGY } from '@/app/components/workflow/nodes/_base/constants'
|
||||
import { VarKindType as VarKindTypeEnum } from '@/app/components/workflow/nodes/_base/types'
|
||||
import { Type } from '@/app/components/workflow/nodes/llm/types'
|
||||
import { useStore } from '@/app/components/workflow/store'
|
||||
import { useStore, useWorkflowStore } from '@/app/components/workflow/store'
|
||||
import { BlockEnum } from '@/app/components/workflow/types'
|
||||
import { useGetLanguage } from '@/context/i18n'
|
||||
import { useStrategyProviders } from '@/service/use-strategy'
|
||||
@ -46,7 +48,7 @@ type WorkflowNodesMap = NonNullable<WorkflowVariableBlockType['workflowNodesMap'
|
||||
const DEFAULT_NESTED_NODE_CONFIG: NestedNodeConfig = {
|
||||
extractor_node_id: '',
|
||||
output_selector: [],
|
||||
null_strategy: 'use_default',
|
||||
null_strategy: NULL_STRATEGY.RAISE_ERROR,
|
||||
default_value: '',
|
||||
}
|
||||
|
||||
@ -96,6 +98,8 @@ const MixedVariableTextInput = ({
|
||||
const [isSubGraphModalOpen, setIsSubGraphModalOpen] = useState(false)
|
||||
const [isContextGenerateModalOpen, setIsContextGenerateModalOpen] = useState(false)
|
||||
const contextGenerateModalRef = useRef<ContextGenerateModalHandle>(null)
|
||||
const [pendingRunAfterSubGraphOpen, setPendingRunAfterSubGraphOpen] = useState(false)
|
||||
const workflowStore = useWorkflowStore()
|
||||
|
||||
const nodesByIdMap = useMemo(() => {
|
||||
return availableNodes.reduce((acc, node) => {
|
||||
@ -352,12 +356,39 @@ const MixedVariableTextInput = ({
|
||||
|
||||
const handleCloseSubGraphModal = useCallback(() => {
|
||||
setIsSubGraphModalOpen(false)
|
||||
setPendingRunAfterSubGraphOpen(false)
|
||||
}, [])
|
||||
|
||||
const handleCloseContextGenerateModal = useCallback(() => {
|
||||
setIsContextGenerateModalOpen(false)
|
||||
}, [])
|
||||
|
||||
const handleOpenInternalViewAndRun = useCallback(() => {
|
||||
setIsSubGraphModalOpen(true)
|
||||
setPendingRunAfterSubGraphOpen(true)
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
if (!isSubGraphModalOpen || !pendingRunAfterSubGraphOpen)
|
||||
return
|
||||
|
||||
const extractorNodeId = assembleExtractorNodeId || (toolNodeId && paramKey ? `${toolNodeId}_ext_${paramKey}` : '')
|
||||
if (!extractorNodeId)
|
||||
return
|
||||
|
||||
const timer = setTimeout(() => {
|
||||
const store = workflowStore()
|
||||
store.setInitShowLastRunTab(true)
|
||||
store.setPendingSingleRun({
|
||||
nodeId: extractorNodeId,
|
||||
action: 'run',
|
||||
})
|
||||
setPendingRunAfterSubGraphOpen(false)
|
||||
}, 300)
|
||||
|
||||
return () => clearTimeout(timer)
|
||||
}, [isSubGraphModalOpen, pendingRunAfterSubGraphOpen, assembleExtractorNodeId, toolNodeId, paramKey, workflowStore])
|
||||
|
||||
const sourceVariable: ValueSelector | undefined = detectedAgentFromValue
|
||||
? [detectedAgentFromValue.nodeId, 'context']
|
||||
: undefined
|
||||
@ -462,6 +493,7 @@ const MixedVariableTextInput = ({
|
||||
codeNodeId={assembleExtractorNodeId || `${toolNodeId}_ext_${paramKey}`}
|
||||
availableVars={nodesOutputVars}
|
||||
availableNodes={availableNodes}
|
||||
onOpenInternalViewAndRun={handleOpenInternalViewAndRun}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@ -16,6 +16,7 @@ import { AssembleVariablesAlt } from '@/app/components/base/icons/src/vender/lin
|
||||
import { Agent } from '@/app/components/base/icons/src/vender/workflow'
|
||||
import { useIsChatMode, useNodesSyncDraft, useWorkflow, useWorkflowVariables } from '@/app/components/workflow/hooks'
|
||||
import { useHooksStore } from '@/app/components/workflow/hooks-store'
|
||||
import { NULL_STRATEGY } from '@/app/components/workflow/nodes/_base/constants'
|
||||
import { VarKindType } from '@/app/components/workflow/nodes/_base/types'
|
||||
import { useStore as useWorkflowStore } from '@/app/components/workflow/store'
|
||||
import { EditionType, isPromptMessageContext, PromptRole, VarType } from '@/app/components/workflow/types'
|
||||
@ -23,7 +24,15 @@ import SubGraphCanvas from './sub-graph-canvas'
|
||||
|
||||
const SubGraphModal: FC<SubGraphModalProps> = (props) => {
|
||||
const { t } = useTranslation()
|
||||
const { isOpen, onClose, variant, toolNodeId, paramKey } = props
|
||||
const {
|
||||
isOpen,
|
||||
onClose,
|
||||
variant,
|
||||
toolNodeId,
|
||||
paramKey,
|
||||
pendingSingleRun,
|
||||
onPendingSingleRunHandled,
|
||||
} = props
|
||||
const isAgentVariant = variant === 'agent'
|
||||
const resolvedAgentNodeId = isAgentVariant ? props.agentNodeId : ''
|
||||
const agentName = isAgentVariant ? props.agentName : ''
|
||||
@ -93,7 +102,7 @@ const SubGraphModal: FC<SubGraphModalProps> = (props) => {
|
||||
return {
|
||||
extractor_node_id: current?.extractor_node_id || extractorNodeId,
|
||||
output_selector: outputSelector.length > 0 ? outputSelector : defaultOutputSelector,
|
||||
null_strategy: current?.null_strategy || 'use_default',
|
||||
null_strategy: current?.null_strategy || NULL_STRATEGY.RAISE_ERROR,
|
||||
default_value: current?.default_value ?? '',
|
||||
}
|
||||
}, [extractorNodeId, isAgentVariant, paramKey, toolParam?.nested_node_config])
|
||||
@ -273,6 +282,9 @@ const SubGraphModal: FC<SubGraphModalProps> = (props) => {
|
||||
variant="agent"
|
||||
toolNodeId={toolNodeId}
|
||||
paramKey={paramKey}
|
||||
isOpen={isOpen}
|
||||
pendingSingleRun={pendingSingleRun}
|
||||
onPendingSingleRunHandled={onPendingSingleRunHandled}
|
||||
sourceVariable={props.sourceVariable}
|
||||
agentNodeId={props.agentNodeId}
|
||||
agentName={props.agentName}
|
||||
@ -292,6 +304,9 @@ const SubGraphModal: FC<SubGraphModalProps> = (props) => {
|
||||
variant="assemble"
|
||||
toolNodeId={toolNodeId}
|
||||
paramKey={paramKey}
|
||||
isOpen={isOpen}
|
||||
pendingSingleRun={pendingSingleRun}
|
||||
onPendingSingleRunHandled={onPendingSingleRunHandled}
|
||||
title={props.title}
|
||||
configsMap={configsMap}
|
||||
nestedNodeConfig={nestedNodeConfig}
|
||||
|
||||
@ -6,6 +6,8 @@ type BaseSubGraphModalProps = {
|
||||
onClose: () => void
|
||||
toolNodeId: string
|
||||
paramKey: string
|
||||
pendingSingleRun?: boolean
|
||||
onPendingSingleRunHandled?: () => void
|
||||
}
|
||||
|
||||
type AgentSubGraphModalProps = BaseSubGraphModalProps & {
|
||||
|
||||
Reference in New Issue
Block a user