mirror of https://github.com/langgenius/dify.git
refactor: streamline input variable handling and enhance type definitions in human input components
This commit is contained in:
parent
528e3400da
commit
645793c48c
|
|
@ -1,5 +1,4 @@
|
|||
import type { ValueSelector } from '../../workflow/types'
|
||||
import { uniqBy } from 'es-toolkit/compat'
|
||||
import { SupportUploadFileTypes } from '../../workflow/types'
|
||||
|
||||
export const CONTEXT_PLACEHOLDER_TEXT = '{{#context#}}'
|
||||
|
|
@ -58,8 +57,7 @@ export const getInputVars = (text: string): ValueSelector[] => {
|
|||
|
||||
return valueSelector
|
||||
})
|
||||
const uniqueInputVars = uniqBy(inputVars, item => item.join('.'))
|
||||
return uniqueInputVars
|
||||
return inputVars
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import type { Props as FormProps } from './form'
|
|||
import type { Emoji } from '@/app/components/tools/types'
|
||||
import type { SpecialResultPanelProps } from '@/app/components/workflow/run/special-result-panel'
|
||||
import type { NodeRunningStatus } from '@/app/components/workflow/types'
|
||||
import type { HumanInputFormData } from '@/types/workflow'
|
||||
import * as React from 'react'
|
||||
import { useEffect, useRef } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
|
@ -35,7 +36,7 @@ export type BeforeRunFormProps = {
|
|||
showGeneratedForm?: boolean
|
||||
handleShowGeneratedForm?: (data: Record<string, any>) => void
|
||||
handleHideGeneratedForm?: () => void
|
||||
formData?: any
|
||||
formData?: HumanInputFormData
|
||||
handleSubmitHumanInputForm?: (data: any) => Promise<void>
|
||||
handleAfterHumanInputStepRun?: () => void
|
||||
} & Partial<SpecialResultPanelProps>
|
||||
|
|
|
|||
|
|
@ -324,7 +324,7 @@ const BasePanel: FC<BasePanelProps> = ({
|
|||
const currentDataSource = useMemo(() => {
|
||||
if (data.type === BlockEnum.DataSource && data.provider_type !== DataSourceClassification.localFile)
|
||||
return dataSourceList?.find(item => item.plugin_id === data.plugin_id)
|
||||
}, [dataSourceList, data.provider_id, data.type, data.provider_type])
|
||||
}, [data.type, data.provider_type, data.plugin_id, dataSourceList])
|
||||
|
||||
const handleAuthorizationItemClick = useCallback((credential_id: string) => {
|
||||
handleNodeDataUpdateWithSyncDraft({
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import type { DeliveryMethod, DeliveryMethodType } from '../../types'
|
||||
import type { DeliveryMethod, DeliveryMethodType, FormInputItem } from '../../types'
|
||||
import type {
|
||||
Node,
|
||||
NodeOutPutVar,
|
||||
|
|
@ -19,6 +19,7 @@ type Props = {
|
|||
nodesOutputVars?: NodeOutPutVar[]
|
||||
availableNodes?: Node[]
|
||||
formContent?: string
|
||||
formInputs?: FormInputItem[]
|
||||
onChange: (value: DeliveryMethod[]) => void
|
||||
readonly?: boolean
|
||||
}
|
||||
|
|
@ -29,6 +30,7 @@ const DeliveryMethodForm: React.FC<Props> = ({
|
|||
nodesOutputVars,
|
||||
availableNodes,
|
||||
formContent,
|
||||
formInputs,
|
||||
onChange,
|
||||
readonly,
|
||||
}) => {
|
||||
|
|
@ -95,6 +97,7 @@ const DeliveryMethodForm: React.FC<Props> = ({
|
|||
nodesOutputVars={nodesOutputVars}
|
||||
availableNodes={availableNodes}
|
||||
formContent={formContent}
|
||||
formInputs={formInputs}
|
||||
readonly={readonly}
|
||||
/>
|
||||
))}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import type { FC } from 'react'
|
||||
import type { DeliveryMethod, EmailConfig } from '../../types'
|
||||
import type { DeliveryMethod, EmailConfig, FormInputItem } from '../../types'
|
||||
import type {
|
||||
Node,
|
||||
NodeOutPutVar,
|
||||
|
|
@ -33,6 +33,7 @@ type DeliveryMethodItemProps = {
|
|||
nodesOutputVars?: NodeOutPutVar[]
|
||||
availableNodes?: Node[]
|
||||
formContent?: string
|
||||
formInputs?: FormInputItem[]
|
||||
onChange: (method: DeliveryMethod) => void
|
||||
onDelete: (type: DeliveryMethodType) => void
|
||||
readonly?: boolean
|
||||
|
|
@ -44,6 +45,7 @@ const DeliveryMethodItem: FC<DeliveryMethodItemProps> = ({
|
|||
nodesOutputVars,
|
||||
availableNodes,
|
||||
formContent,
|
||||
formInputs,
|
||||
onChange,
|
||||
onDelete,
|
||||
readonly,
|
||||
|
|
@ -187,6 +189,7 @@ const DeliveryMethodItem: FC<DeliveryMethodItemProps> = ({
|
|||
isShow={showTestEmailModal}
|
||||
config={method.config as EmailConfig}
|
||||
formContent={formContent}
|
||||
formInputs={formInputs}
|
||||
nodesOutputVars={nodesOutputVars}
|
||||
availableNodes={availableNodes}
|
||||
onClose={() => setShowTestEmailModal(false)}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
import type { EmailConfig } from '../../types'
|
||||
import type { EmailConfig, FormInputItem } from '../../types'
|
||||
import type {
|
||||
Node,
|
||||
NodeOutPutVar,
|
||||
ValueSelector,
|
||||
} from '@/app/components/workflow/types'
|
||||
import { RiArrowRightSFill, RiCloseLine } from '@remixicon/react'
|
||||
import { noop, unionBy } from 'es-toolkit/compat'
|
||||
|
|
@ -36,6 +37,7 @@ type EmailConfigureModalProps = {
|
|||
onClose: () => void
|
||||
config?: EmailConfig
|
||||
formContent?: string
|
||||
formInputs?: FormInputItem[]
|
||||
nodesOutputVars?: NodeOutPutVar[]
|
||||
availableNodes?: Node[]
|
||||
}
|
||||
|
|
@ -69,6 +71,7 @@ const EmailSenderModal = ({
|
|||
onClose,
|
||||
config,
|
||||
formContent,
|
||||
formInputs,
|
||||
nodesOutputVars = [],
|
||||
availableNodes = [],
|
||||
}: EmailConfigureModalProps) => {
|
||||
|
|
@ -86,8 +89,14 @@ const EmailSenderModal = ({
|
|||
const accounts = members?.accounts || []
|
||||
|
||||
const generatedInputs = useMemo(() => {
|
||||
const placeholderValueSelectors = (formInputs || []).reduce((acc, input) => {
|
||||
if (input.placeholder.type === 'variable') {
|
||||
acc.push(input.placeholder.selector)
|
||||
}
|
||||
return acc
|
||||
}, [] as ValueSelector[])
|
||||
const valueSelectors = doGetInputVars((formContent || '') + (config?.body || ''))
|
||||
const variables = unionBy(valueSelectors, item => item.join('.')).map((item) => {
|
||||
const variables = unionBy([...valueSelectors, ...placeholderValueSelectors], item => item.join('.')).map((item) => {
|
||||
const varInfo = getNodeInfoById(availableNodes, item[0])?.data
|
||||
|
||||
return {
|
||||
|
|
@ -120,7 +129,7 @@ const EmailSenderModal = ({
|
|||
}
|
||||
})
|
||||
return varInputs
|
||||
}, [availableNodes, config?.body, formContent, nodesOutputVars])
|
||||
}, [availableNodes, config?.body, formContent, formInputs, nodesOutputVars])
|
||||
|
||||
const [inputs, setInputs] = useState<Record<string, unknown>>({})
|
||||
const [collapsed, setCollapsed] = useState(true)
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
'use client'
|
||||
import type { FormInputItem, UserAction } from '@/app/components/workflow/nodes/human-input/types'
|
||||
import type { HumanInputFormData } from '@/types/workflow'
|
||||
import { RiArrowLeftLine } from '@remixicon/react'
|
||||
import * as React from 'react'
|
||||
import { useState } from 'react'
|
||||
|
||||
import { useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Button from '@/app/components/base/button'
|
||||
import ContentItem from '@/app/components/base/chat/chat/answer/human-input-content/content-item'
|
||||
|
|
@ -11,11 +11,7 @@ import { getButtonStyle, initializeInputs, splitByOutputVar } from '@/app/compon
|
|||
|
||||
type Props = {
|
||||
nodeName: string
|
||||
data: {
|
||||
form_content: string
|
||||
inputs: FormInputItem[]
|
||||
actions: UserAction[]
|
||||
}
|
||||
data: HumanInputFormData
|
||||
showBackButton?: boolean
|
||||
handleBack?: () => void
|
||||
onSubmit?: (data: any) => Promise<void>
|
||||
|
|
@ -67,6 +63,7 @@ const FormContent = ({
|
|||
formInputFields={data.inputs}
|
||||
inputs={inputs}
|
||||
onInputChange={handleInputsChange}
|
||||
resolvedPlaceholderValues={data.resolved_placeholder_values}
|
||||
/>
|
||||
))}
|
||||
<div className="flex flex-wrap gap-1 py-1">
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import type { HumanInputNodeType } from '../types'
|
||||
import type { Props as FormProps } from '@/app/components/workflow/nodes/_base/components/before-run-form/form'
|
||||
import type { InputVar } from '@/app/components/workflow/types'
|
||||
import type { HumanInputFormData } from '@/types/workflow'
|
||||
import { useCallback, useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useStore as useAppStore } from '@/app/components/app/store'
|
||||
|
|
@ -28,13 +29,19 @@ const useSingleRunFormParams = ({
|
|||
const { t } = useTranslation()
|
||||
const { inputs } = useNodeCrud<HumanInputNodeType>(id, payload)
|
||||
const [showGeneratedForm, setShowGeneratedForm] = useState(false)
|
||||
const [formData, setFormData] = useState<any>(null)
|
||||
const [formData, setFormData] = useState<HumanInputFormData | null>(null)
|
||||
const [requiredInputs, setRequiredInputs] = useState<Record<string, any>>()
|
||||
const generatedInputs = useMemo(() => {
|
||||
const placeholderInputs = inputs.inputs.reduce((acc, input) => {
|
||||
if (input.placeholder.type === 'variable') {
|
||||
acc.push(...getInputVars([`{{#${input.placeholder.selector.join('.')}#}}`]))
|
||||
}
|
||||
return acc
|
||||
}, [] as InputVar[])
|
||||
if (!inputs.form_content)
|
||||
return []
|
||||
return getInputVars([inputs.form_content]).filter(item => !isOutput(item.value_selector || []))
|
||||
}, [getInputVars, inputs.form_content])
|
||||
return placeholderInputs
|
||||
return [...placeholderInputs, ...getInputVars([inputs.form_content]).filter(item => !isOutput(item.value_selector || []))]
|
||||
}, [getInputVars, inputs.form_content, inputs.inputs])
|
||||
|
||||
const forms = useMemo(() => {
|
||||
const forms: FormProps[] = [{
|
||||
|
|
|
|||
|
|
@ -89,6 +89,7 @@ const Panel: FC<NodePanelProps<HumanInputNodeType>> = ({
|
|||
nodeId={id}
|
||||
value={inputs.delivery_methods || []}
|
||||
formContent={inputs.form_content}
|
||||
formInputs={inputs.inputs}
|
||||
nodesOutputVars={availableVars}
|
||||
availableNodes={availableNodesWithParent}
|
||||
onChange={handleDeliveryMethodChange}
|
||||
|
|
|
|||
|
|
@ -3057,7 +3057,7 @@
|
|||
},
|
||||
"app/components/workflow/nodes/_base/components/before-run-form/index.tsx": {
|
||||
"ts/no-explicit-any": {
|
||||
"count": 12
|
||||
"count": 11
|
||||
}
|
||||
},
|
||||
"app/components/workflow/nodes/_base/components/editor/code-editor/editor-support-vars.tsx": {
|
||||
|
|
@ -3440,7 +3440,7 @@
|
|||
},
|
||||
"app/components/workflow/nodes/human-input/hooks/use-single-run-form-params.ts": {
|
||||
"ts/no-explicit-any": {
|
||||
"count": 7
|
||||
"count": 6
|
||||
}
|
||||
},
|
||||
"app/components/workflow/nodes/if-else/components/condition-list/condition-input.tsx": {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import type { FormInputItem, UserAction } from '@/app/components/workflow/nodes/human-input/types'
|
||||
import type { BlockEnum } from '@/app/components/workflow/types'
|
||||
import type { CommonResponse } from '@/models/common'
|
||||
import type { FlowType } from '@/types/common'
|
||||
import type {
|
||||
ConversationVariableResponse,
|
||||
FetchWorkflowDraftResponse,
|
||||
HumanInputFormData,
|
||||
NodesDefaultConfigsResponse,
|
||||
VarInInspect,
|
||||
} from '@/types/workflow'
|
||||
|
|
@ -111,11 +111,7 @@ export const fetchHumanInputNodeStepRunForm = (
|
|||
inputs: Record<string, any>
|
||||
},
|
||||
) => {
|
||||
return post<{
|
||||
form_content: string
|
||||
inputs: FormInputItem[]
|
||||
user_actions: UserAction[]
|
||||
}>(`${url}/preview`, { body: data })
|
||||
return post<HumanInputFormData>(`${url}/preview`, { body: data })
|
||||
}
|
||||
|
||||
export const submitHumanInputNodeStepRunForm = (
|
||||
|
|
|
|||
Loading…
Reference in New Issue