mirror of
https://github.com/langgenius/dify.git
synced 2026-04-29 04:26:30 +08:00
add timeout of human input node
This commit is contained in:
parent
1ab02c6e9a
commit
95b88a0621
@ -0,0 +1,53 @@
|
|||||||
|
import type { FC } from 'react'
|
||||||
|
import React from 'react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import type { Timeout } from '../types'
|
||||||
|
import Input from '@/app/components/base/input'
|
||||||
|
import cn from '@/utils/classnames'
|
||||||
|
|
||||||
|
const i18nPrefix = 'workflow.nodes.humanInput'
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
timeout: Timeout
|
||||||
|
onChange: (state: Timeout) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
const TimeoutInput: FC<Props> = ({
|
||||||
|
timeout,
|
||||||
|
onChange,
|
||||||
|
}) => {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
return (
|
||||||
|
<div className='flex items-center gap-1'>
|
||||||
|
<Input
|
||||||
|
wrapperClassName='w-16'
|
||||||
|
type='number'
|
||||||
|
value={timeout.value}
|
||||||
|
min={1}
|
||||||
|
onChange={e => onChange({ ...timeout, value: Number(e.target.value) })}
|
||||||
|
/>
|
||||||
|
<div className='flex items-center gap-0.5 rounded-[10px] bg-components-segmented-control-bg-normal p-0.5'>
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
'cursor-pointer rounded-lg px-2 py-1 text-text-tertiary hover:bg-state-base-hover hover:text-text-secondary',
|
||||||
|
timeout.unit === 'days' && 'bg-components-segmented-control-item-active-bg text-text-accent-light-mode-only shadow-sm hover:bg-components-segmented-control-item-active-bg hover:text-text-accent-light-mode-only',
|
||||||
|
)}
|
||||||
|
onClick={() => onChange({ ...timeout, unit: 'days' })}
|
||||||
|
>
|
||||||
|
<div className='system-sm-medium p-0.5'>{t(`${i18nPrefix}.timeout.days`)}</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
'cursor-pointer rounded-lg px-2 py-1 text-text-tertiary hover:bg-state-base-hover hover:text-text-secondary',
|
||||||
|
timeout.unit === 'hours' && 'bg-components-segmented-control-item-active-bg text-text-accent-light-mode-only shadow-sm hover:bg-components-segmented-control-item-active-bg hover:text-text-accent-light-mode-only',
|
||||||
|
)}
|
||||||
|
onClick={() => onChange({ ...timeout, unit: 'hours' })}
|
||||||
|
>
|
||||||
|
<div className='system-sm-medium p-0.5'>{t(`${i18nPrefix}.timeout.hours`)}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default TimeoutInput
|
||||||
@ -37,6 +37,10 @@ const nodeDefault: NodeDefault<HumanInputNodeType> = {
|
|||||||
type: UserActionButtonType.Ghost,
|
type: UserActionButtonType.Ghost,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
timeout: {
|
||||||
|
value: 3,
|
||||||
|
unit: 'days',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
getAvailablePrevNodes(isChatMode: boolean) {
|
getAvailablePrevNodes(isChatMode: boolean) {
|
||||||
const nodes = isChatMode
|
const nodes = isChatMode
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import type { FC } from 'react'
|
import type { FC } from 'react'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
import {
|
import {
|
||||||
RiMailSendFill,
|
RiMailSendFill,
|
||||||
RiRobot2Fill,
|
RiRobot2Fill,
|
||||||
@ -9,7 +10,11 @@ import type { HumanInputNodeType } from './types'
|
|||||||
import type { NodeProps } from '@/app/components/workflow/types'
|
import type { NodeProps } from '@/app/components/workflow/types'
|
||||||
import { DeliveryMethodType } from './types'
|
import { DeliveryMethodType } from './types'
|
||||||
|
|
||||||
|
const i18nPrefix = 'workflow.nodes.humanInput'
|
||||||
|
|
||||||
const Node: FC<NodeProps<HumanInputNodeType>> = (props) => {
|
const Node: FC<NodeProps<HumanInputNodeType>> = (props) => {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
|
||||||
const { data } = props
|
const { data } = props
|
||||||
const deliveryMethods = data.deliveryMethod
|
const deliveryMethods = data.deliveryMethod
|
||||||
const userActions = data.userActions
|
const userActions = data.userActions
|
||||||
@ -18,7 +23,7 @@ const Node: FC<NodeProps<HumanInputNodeType>> = (props) => {
|
|||||||
<>
|
<>
|
||||||
{deliveryMethods.length > 0 && (
|
{deliveryMethods.length > 0 && (
|
||||||
<div className='space-y-0.5 py-1'>
|
<div className='space-y-0.5 py-1'>
|
||||||
<div className='system-2xs-medium-uppercase px-2.5 py-0.5 text-text-tertiary'>delivery method</div>
|
<div className='system-2xs-medium-uppercase px-2.5 py-0.5 text-text-tertiary'>{t(`${i18nPrefix}.deliveryMethod.title`)}</div>
|
||||||
<div className='space-y-0.5 px-2.5'>
|
<div className='space-y-0.5 px-2.5'>
|
||||||
{deliveryMethods.map(method => (
|
{deliveryMethods.map(method => (
|
||||||
<div key={method.type} className='flex items-center gap-1 rounded-[6px] bg-workflow-block-parma-bg p-1'>
|
<div key={method.type} className='flex items-center gap-1 rounded-[6px] bg-workflow-block-parma-bg p-1'>
|
||||||
|
|||||||
@ -1,8 +1,11 @@
|
|||||||
import type { FC } from 'react'
|
import type { FC } from 'react'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import useConfig from './use-config'
|
||||||
import type { HumanInputNodeType } from './types'
|
import type { HumanInputNodeType } from './types'
|
||||||
import type { NodePanelProps } from '@/app/components/workflow/types'
|
import type { NodePanelProps } from '@/app/components/workflow/types'
|
||||||
|
import Divider from '@/app/components/base/divider'
|
||||||
|
import TimeoutInput from './components/timeout'
|
||||||
|
|
||||||
const i18nPrefix = 'workflow.nodes.humanInput'
|
const i18nPrefix = 'workflow.nodes.humanInput'
|
||||||
|
|
||||||
@ -11,11 +14,21 @@ const Panel: FC<NodePanelProps<HumanInputNodeType>> = ({
|
|||||||
data,
|
data,
|
||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
const {
|
||||||
|
inputs,
|
||||||
|
handleTimeoutChange,
|
||||||
|
} = useConfig(id, data)
|
||||||
return (
|
return (
|
||||||
<div className='mt-2'>
|
<div className='py-2'>
|
||||||
<div className='space-y-4 px-4 pb-4'>
|
<div className='px-4 py-2'>
|
||||||
TODO
|
<Divider className='!my-0 !h-px !bg-divider-subtle' />
|
||||||
|
</div>
|
||||||
|
<div className='flex items-center justify-between px-4 py-2'>
|
||||||
|
<div className='system-sm-semibold-uppercase text-text-secondary'>{t(`${i18nPrefix}.timeout.title`)}</div>
|
||||||
|
<TimeoutInput
|
||||||
|
timeout={inputs.timeout}
|
||||||
|
onChange={handleTimeoutChange}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -4,7 +4,7 @@ export type HumanInputNodeType = CommonNodeType & {
|
|||||||
deliveryMethod: DeliveryMethod[]
|
deliveryMethod: DeliveryMethod[]
|
||||||
formContent: any
|
formContent: any
|
||||||
userActions: UserAction[]
|
userActions: UserAction[]
|
||||||
timeout: any
|
timeout: Timeout
|
||||||
outputs: Variable[]
|
outputs: Variable[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
import useVarList from '../_base/hooks/use-var-list'
|
import type { HumanInputNodeType, Timeout } from './types'
|
||||||
import type { HumanInputNodeType } from './types'
|
|
||||||
import useNodeCrud from '@/app/components/workflow/nodes/_base/hooks/use-node-crud'
|
import useNodeCrud from '@/app/components/workflow/nodes/_base/hooks/use-node-crud'
|
||||||
import {
|
import {
|
||||||
useNodesReadOnly,
|
useNodesReadOnly,
|
||||||
@ -8,19 +7,17 @@ const useConfig = (id: string, payload: HumanInputNodeType) => {
|
|||||||
const { nodesReadOnly: readOnly } = useNodesReadOnly()
|
const { nodesReadOnly: readOnly } = useNodesReadOnly()
|
||||||
const { inputs, setInputs } = useNodeCrud<HumanInputNodeType>(id, payload)
|
const { inputs, setInputs } = useNodeCrud<HumanInputNodeType>(id, payload)
|
||||||
|
|
||||||
const { handleVarListChange, handleAddVariable } = useVarList<HumanInputNodeType>({
|
const handleTimeoutChange = (timeout: Timeout) => {
|
||||||
inputs,
|
setInputs({
|
||||||
setInputs: (newInputs) => {
|
...inputs,
|
||||||
setInputs(newInputs)
|
timeout,
|
||||||
},
|
})
|
||||||
varKey: 'outputs',
|
}
|
||||||
})
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
readOnly,
|
readOnly,
|
||||||
inputs,
|
inputs,
|
||||||
handleVarListChange,
|
handleTimeoutChange,
|
||||||
handleAddVariable,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -905,9 +905,16 @@ const translation = {
|
|||||||
parameterSchema: 'Parameter Schema',
|
parameterSchema: 'Parameter Schema',
|
||||||
},
|
},
|
||||||
humanInput: {
|
humanInput: {
|
||||||
deliveryMethod: 'delivery method',
|
deliveryMethod: {
|
||||||
|
title: 'Delivery Method',
|
||||||
|
},
|
||||||
formContent: 'form content',
|
formContent: 'form content',
|
||||||
userActions: 'user actions',
|
userActions: 'user actions',
|
||||||
|
timeout: {
|
||||||
|
title: 'Timeout',
|
||||||
|
hours: 'Hours',
|
||||||
|
days: 'Days',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
tracing: {
|
tracing: {
|
||||||
|
|||||||
@ -906,9 +906,16 @@ const translation = {
|
|||||||
parameterSchema: '参数 Schema',
|
parameterSchema: '参数 Schema',
|
||||||
},
|
},
|
||||||
humanInput: {
|
humanInput: {
|
||||||
deliveryMethod: '提交方式',
|
deliveryMethod: {
|
||||||
|
title: '提交方式',
|
||||||
|
},
|
||||||
formContent: '表单内容',
|
formContent: '表单内容',
|
||||||
userActions: '用户操作',
|
userActions: '用户操作',
|
||||||
|
timeout: {
|
||||||
|
title: '超时设置',
|
||||||
|
hours: '小时',
|
||||||
|
days: '日',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
tracing: {
|
tracing: {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user