Commit 4519c6ab authored by Joel's avatar Joel

feat: conditions struct

parent 32c6431d
......@@ -5,8 +5,8 @@ import { memo } from 'react'
import Workflow from '@/app/components/workflow'
import { BlockEnum } from '@/app/components/workflow/types'
const nodes = [
BlockEnum.VariableAssigner/* 11 */, BlockEnum.Start/* 1 */, BlockEnum.DirectAnswer/* 2 */, BlockEnum.LLM/* 3 */, BlockEnum.KnowledgeRetrieval/* 4 */, BlockEnum.QuestionClassifier/* 5 */,
BlockEnum.IfElse/* 6 */, BlockEnum.Code/* 7 */, BlockEnum.TemplateTransform/* 8 */, BlockEnum.HttpRequest/* 9 */, BlockEnum.Tool/* 10 */,
BlockEnum.IfElse/* 6 */, BlockEnum.VariableAssigner/* 11 */, BlockEnum.Start/* 1 */, BlockEnum.DirectAnswer/* 2 */, BlockEnum.LLM/* 3 */, BlockEnum.KnowledgeRetrieval/* 4 */, BlockEnum.QuestionClassifier/* 5 */,
BlockEnum.Code/* 7 */, BlockEnum.TemplateTransform/* 8 */, BlockEnum.HttpRequest/* 9 */, BlockEnum.Tool/* 10 */,
BlockEnum.End/* 12 */,
].map((item, i) => ({
id: `${i + 1}`,
......
'use client'
import type { FC } from 'react'
import React, { useCallback } from 'react'
import produce from 'immer'
import { useTranslation } from 'react-i18next'
import cn from 'classnames'
import VarReferencePicker from '../../_base/components/variable/var-reference-picker'
import type { Condition } from '@/app/components/workflow/nodes/if-else/types'
import type { ValueSelector } from '@/app/components/workflow/types'
import { Trash03 } from '@/app/components/base/icons/src/vender/line/general'
const i18nPrefix = 'workflow.nodes.ifElse'
type Props = {
readonly: boolean
list: Condition[]
onChange: (newList: Condition[]) => void
}
type ItemProps = {
readonly: boolean
payload: Condition
onChange: (newItem: Condition) => void
canRemove: boolean
onRemove?: () => void
}
const Item: FC<ItemProps> = ({
readonly,
payload,
onChange,
canRemove,
onRemove = () => { },
}) => {
const { t } = useTranslation()
const handleVarReferenceChange = useCallback((value: ValueSelector) => {
onChange({
...payload,
variable_selector: value,
})
}, [onChange, payload])
const handleValueChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
onChange({
...payload,
value: e.target.value,
})
}, [onChange, payload])
return (
<div className='flex items-center space-x-1'>
<VarReferencePicker
readonly={readonly}
isShowNodeName
className='grow'
value={payload.variable_selector}
onChange={handleVarReferenceChange}
/>
<input
readOnly={readonly}
value={payload.value}
onChange={handleValueChange}
placeholder={t(`${i18nPrefix}.enterValue`)!}
className='w-[144px] h-8 leading-8 px-2.5 rounded-lg border-0 bg-gray-100 text-gray-900 text-[13px] placeholder:text-gray-400 focus:outline-none focus:ring-1 focus:ring-inset focus:ring-gray-200'
type='text'
/>
<div
className={cn(canRemove ? 'text-gray-500 bg-gray-100 hover:bg-gray-200 cursor-pointer' : 'bg-gray-25 text-gray-300', 'p-2 rounded-lg ')}
onClick={onRemove}
>
<Trash03 className='w-4 h-4 ' />
</div>
</div>
)
}
const ConditionList: FC<Props> = ({
readonly,
list,
onChange,
}) => {
const handleItemChange = useCallback((index: number) => {
return (newItem: Condition) => {
const newList = produce(list, (draft) => {
draft[index] = newItem
})
onChange(newList)
}
}, [list, onChange])
const handleItemRemove = useCallback((index: number) => {
return () => {
const newList = produce(list, (draft) => {
draft.splice(index, 1)
})
onChange(newList)
}
}, [list, onChange])
if (list.length === 0)
return null
return (
<div>
<Item
readonly={readonly}
payload={list[0]}
onChange={handleItemChange(0)}
canRemove={false}
/>
{
list.length > 1 && (
<>
<div className='flex items-center justify-center h-6 text-gray-500'>
AND
</div>
{
list.slice(1).map((item, i) => (
<Item
key={item.id}
readonly={readonly}
payload={item}
onChange={handleItemChange(i + 1)}
canRemove
onRemove={handleItemRemove(i + 1)}
/>
))
}
</>)
}
</div>
)
}
export default React.memo(ConditionList)
import { BlockEnum } from '../../types'
import type { IfElseNodeType } from './types'
import { ComparisonOperator, LogicalOperator } from './types'
export const mockData: IfElseNodeType = {
title: 'Test',
desc: 'Test',
type: 'Test',
type: BlockEnum.IfElse,
logical_operator: LogicalOperator.and,
conditions: [
{
......
import type { FC } from 'react'
import { useTranslation } from 'react-i18next'
import useConfig from './use-config'
import { mockData } from './mock'
import ConditionList from './components/condition-list'
import Field from '@/app/components/workflow/nodes/_base/components/field'
const i18nPrefix = 'workflow.nodes.ifElse'
const Panel: FC = () => {
const { t } = useTranslation()
const readOnly = false
const {
inputs,
handleConditionsChange,
handleAddCondition,
} = useConfig(mockData)
return (
<div>start panel inputs</div>
<div className='mt-2'>
<div className='px-4 pb-4 space-y-4'>
<Field
title={t(`${i18nPrefix}.conditions`)}
>
<ConditionList
readonly={readOnly}
list={inputs.conditions}
onChange={handleConditionsChange}
/>
</Field>
</div>
</div>
)
}
......
import { useCallback, useState } from 'react'
import produce from 'immer'
import type { Condition, IfElseNodeType, LogicalOperator } from './types'
const useConfig = (initInputs: IfElseNodeType) => {
const [inputs, setInputs] = useState<IfElseNodeType>(initInputs)
const handleConditionsChange = useCallback((newConditions: Condition[]) => {
setInputs((prev) => {
return {
...prev,
conditions: newConditions,
}
})
}, [])
const handleAddCondition = useCallback((condition: Condition) => {
const newInputs = produce(inputs, (draft) => {
draft.conditions.push(condition)
})
setInputs(newInputs)
}, [inputs])
const handleLogicalOperatorChange = useCallback((newOperator: LogicalOperator) => {
const newInputs = produce(inputs, (draft) => {
draft.logical_operator = newOperator
})
setInputs(newInputs)
}, [inputs])
return {
inputs,
handleConditionsChange,
handleAddCondition,
handleLogicalOperatorChange,
}
}
export default useConfig
......@@ -86,6 +86,7 @@ const translation = {
'null': 'is null',
'not null': 'is not null',
},
enterValue: 'Enter value',
},
variableAssigner: {
title: 'Assign variables',
......
......@@ -85,6 +85,7 @@ const translation = {
'null': '空',
'not null': '不为空',
},
enterValue: '输入值',
},
variableAssigner: {
title: '变量赋值',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment