feat: support bool type variable frontend (#24437)
Co-authored-by: QuantumGhost <obelisk.reg+git@gmail.com>
This commit is contained in:
@@ -38,6 +38,7 @@ import { VarType } from '@/app/components/workflow/types'
|
||||
import cn from '@/utils/classnames'
|
||||
import { SimpleSelect as Select } from '@/app/components/base/select'
|
||||
import { Variable02 } from '@/app/components/base/icons/src/vender/solid/development'
|
||||
import BoolValue from '@/app/components/workflow/panel/chat-variable-panel/components/bool-value'
|
||||
import { getVarType } from '@/app/components/workflow/nodes/_base/components/variable/utils'
|
||||
import { useIsChatMode } from '@/app/components/workflow/hooks/use-workflow'
|
||||
const optionNameI18NPrefix = 'workflow.nodes.ifElse.optionName'
|
||||
@@ -142,12 +143,12 @@ const ConditionItem = ({
|
||||
|
||||
const isArrayValue = fileAttr?.key === 'transfer_method' || fileAttr?.key === 'type'
|
||||
|
||||
const handleUpdateConditionValue = useCallback((value: string) => {
|
||||
if (value === condition.value || (isArrayValue && value === condition.value?.[0]))
|
||||
const handleUpdateConditionValue = useCallback((value: string | boolean) => {
|
||||
if (value === condition.value || (isArrayValue && value === (condition.value as string[])?.[0]))
|
||||
return
|
||||
const newCondition = {
|
||||
...condition,
|
||||
value: isArrayValue ? [value] : value,
|
||||
value: isArrayValue ? [value as string] : value,
|
||||
}
|
||||
doUpdateCondition(newCondition)
|
||||
}, [condition, doUpdateCondition, isArrayValue])
|
||||
@@ -203,8 +204,12 @@ const ConditionItem = ({
|
||||
}, [caseId, condition, conditionId, isSubVariableKey, onRemoveCondition, onRemoveSubVariableCondition])
|
||||
|
||||
const handleVarChange = useCallback((valueSelector: ValueSelector, _varItem: Var) => {
|
||||
const {
|
||||
conversationVariables,
|
||||
} = workflowStore.getState()
|
||||
const resolvedVarType = getVarType({
|
||||
valueSelector,
|
||||
conversationVariables,
|
||||
availableNodes,
|
||||
isChatMode,
|
||||
})
|
||||
@@ -212,7 +217,7 @@ const ConditionItem = ({
|
||||
const newCondition = produce(condition, (draft) => {
|
||||
draft.variable_selector = valueSelector
|
||||
draft.varType = resolvedVarType
|
||||
draft.value = ''
|
||||
draft.value = resolvedVarType === VarType.boolean ? false : ''
|
||||
draft.comparison_operator = getOperators(resolvedVarType)[0]
|
||||
setTimeout(() => setControlPromptEditorRerenderKey(Date.now()))
|
||||
})
|
||||
@@ -220,6 +225,14 @@ const ConditionItem = ({
|
||||
setOpen(false)
|
||||
}, [condition, doUpdateCondition, availableNodes, isChatMode, setControlPromptEditorRerenderKey])
|
||||
|
||||
const showBooleanInput = useMemo(() => {
|
||||
if(condition.varType === VarType.boolean)
|
||||
return true
|
||||
// eslint-disable-next-line sonarjs/prefer-single-boolean-return
|
||||
if(condition.varType === VarType.arrayBoolean && [ComparisonOperator.contains, ComparisonOperator.notContains].includes(condition.comparison_operator!))
|
||||
return true
|
||||
return false
|
||||
}, [condition])
|
||||
return (
|
||||
<div className={cn('mb-1 flex last-of-type:mb-0', className)}>
|
||||
<div className={cn(
|
||||
@@ -273,7 +286,7 @@ const ConditionItem = ({
|
||||
/>
|
||||
</div>
|
||||
{
|
||||
!comparisonOperatorNotRequireValue(condition.comparison_operator) && !isNotInput && condition.varType !== VarType.number && (
|
||||
!comparisonOperatorNotRequireValue(condition.comparison_operator) && !isNotInput && condition.varType !== VarType.number && !showBooleanInput && (
|
||||
<div className='max-h-[100px] overflow-y-auto border-t border-t-divider-subtle px-2 py-1'>
|
||||
<ConditionInput
|
||||
disabled={disabled}
|
||||
@@ -285,6 +298,16 @@ const ConditionItem = ({
|
||||
</div>
|
||||
)
|
||||
}
|
||||
{
|
||||
!comparisonOperatorNotRequireValue(condition.comparison_operator) && !isNotInput && showBooleanInput && (
|
||||
<div className='p-1'>
|
||||
<BoolValue
|
||||
value={condition.value as boolean}
|
||||
onChange={handleUpdateConditionValue}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
{
|
||||
!comparisonOperatorNotRequireValue(condition.comparison_operator) && !isNotInput && condition.varType === VarType.number && (
|
||||
<div className='border-t border-t-divider-subtle px-2 py-1 pt-[3px]'>
|
||||
|
||||
@@ -24,7 +24,7 @@ type ConditionValueProps = {
|
||||
variableSelector: string[]
|
||||
labelName?: string
|
||||
operator: ComparisonOperator
|
||||
value: string | string[]
|
||||
value: string | string[] | boolean
|
||||
}
|
||||
const ConditionValue = ({
|
||||
variableSelector,
|
||||
@@ -46,6 +46,9 @@ const ConditionValue = ({
|
||||
if (Array.isArray(value)) // transfer method
|
||||
return value[0]
|
||||
|
||||
if(value === true || value === false)
|
||||
return value ? 'True' : 'False'
|
||||
|
||||
return value.replace(/{{#([^#]*)#}}/g, (a, b) => {
|
||||
const arr: string[] = b.split('.')
|
||||
if (isSystemVar(arr))
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { BlockEnum, type NodeDefault } from '../../types'
|
||||
import { BlockEnum, type NodeDefault, VarType } from '../../types'
|
||||
import { type IfElseNodeType, LogicalOperator } from './types'
|
||||
import { isEmptyRelatedOperator } from './utils'
|
||||
import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks'
|
||||
@@ -58,13 +58,13 @@ const nodeDefault: NodeDefault<IfElseNodeType> = {
|
||||
if (isEmptyRelatedOperator(c.comparison_operator!))
|
||||
return true
|
||||
|
||||
return !!c.value
|
||||
return (c.varType === VarType.boolean || c.varType === VarType.arrayBoolean) ? c.value === undefined : !!c.value
|
||||
})
|
||||
if (!isSet)
|
||||
errorMessages = t(`${i18nPrefix}.fieldRequired`, { field: t(`${i18nPrefix}.fields.variableValue`) })
|
||||
}
|
||||
else {
|
||||
if (!isEmptyRelatedOperator(condition.comparison_operator!) && !condition.value)
|
||||
if (!isEmptyRelatedOperator(condition.comparison_operator!) && ((condition.varType === VarType.boolean || condition.varType === VarType.arrayBoolean) ? condition.value === undefined : !condition.value))
|
||||
errorMessages = t(`${i18nPrefix}.fieldRequired`, { field: t(`${i18nPrefix}.fields.variableValue`) })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import { isEmptyRelatedOperator } from './utils'
|
||||
import type { Condition, IfElseNodeType } from './types'
|
||||
import ConditionValue from './components/condition-value'
|
||||
import ConditionFilesListValue from './components/condition-files-list-value'
|
||||
import { VarType } from '../../types'
|
||||
const i18nPrefix = 'workflow.nodes.ifElse'
|
||||
|
||||
const IfElseNode: FC<NodeProps<IfElseNodeType>> = (props) => {
|
||||
@@ -23,18 +24,14 @@ const IfElseNode: FC<NodeProps<IfElseNodeType>> = (props) => {
|
||||
if (!c.comparison_operator)
|
||||
return false
|
||||
|
||||
if (isEmptyRelatedOperator(c.comparison_operator!))
|
||||
return true
|
||||
|
||||
return !!c.value
|
||||
return (c.varType === VarType.boolean || c.varType === VarType.arrayBoolean) ? true : !!c.value
|
||||
})
|
||||
return isSet
|
||||
}
|
||||
else {
|
||||
if (isEmptyRelatedOperator(condition.comparison_operator!))
|
||||
return true
|
||||
|
||||
return !!condition.value
|
||||
return (condition.varType === VarType.boolean || condition.varType === VarType.arrayBoolean) ? true : !!condition.value
|
||||
}
|
||||
}, [])
|
||||
const conditionNotSet = (<div className='flex h-6 items-center space-x-1 rounded-md bg-workflow-block-parma-bg px-1 text-xs font-normal text-text-secondary'>
|
||||
@@ -73,7 +70,7 @@ const IfElseNode: FC<NodeProps<IfElseNodeType>> = (props) => {
|
||||
<ConditionValue
|
||||
variableSelector={condition.variable_selector!}
|
||||
operator={condition.comparison_operator!}
|
||||
value={condition.value}
|
||||
value={condition.varType === VarType.boolean ? (!condition.value ? 'False' : condition.value) : condition.value}
|
||||
/>
|
||||
)
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ export type Condition = {
|
||||
variable_selector?: ValueSelector
|
||||
key?: string // sub variable key
|
||||
comparison_operator?: ComparisonOperator
|
||||
value: string | string[]
|
||||
value: string | string[] | boolean
|
||||
numberVarType?: NumberVarType
|
||||
sub_variable_condition?: CaseItem
|
||||
}
|
||||
|
||||
@@ -144,7 +144,7 @@ const useConfig = (id: string, payload: IfElseNodeType) => {
|
||||
varType: varItem.type,
|
||||
variable_selector: valueSelector,
|
||||
comparison_operator: getOperators(varItem.type, getIsVarFileAttribute(valueSelector) ? { key: valueSelector.slice(-1)[0] } : undefined)[0],
|
||||
value: '',
|
||||
value: (varItem.type === VarType.boolean || varItem.type === VarType.arrayBoolean) ? false : '',
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
@@ -107,6 +107,11 @@ export const getOperators = (type?: VarType, file?: { key: string }) => {
|
||||
ComparisonOperator.empty,
|
||||
ComparisonOperator.notEmpty,
|
||||
]
|
||||
case VarType.boolean:
|
||||
return [
|
||||
ComparisonOperator.is,
|
||||
ComparisonOperator.isNot,
|
||||
]
|
||||
case VarType.file:
|
||||
return [
|
||||
ComparisonOperator.exists,
|
||||
@@ -114,6 +119,7 @@ export const getOperators = (type?: VarType, file?: { key: string }) => {
|
||||
]
|
||||
case VarType.arrayString:
|
||||
case VarType.arrayNumber:
|
||||
case VarType.arrayBoolean:
|
||||
return [
|
||||
ComparisonOperator.contains,
|
||||
ComparisonOperator.notContains,
|
||||
|
||||
Reference in New Issue
Block a user