Prefer structured submitted human input data

This commit is contained in:
JzoNg 2026-04-22 08:24:44 +08:00
parent 2ad35e56bc
commit 29cad80e62
3 changed files with 46 additions and 11 deletions

View File

@ -28,4 +28,20 @@ describe('SubmittedHumanInputContent Integration', () => {
// Trans component for triggered action. The mock usually renders the key.
expect(screen.getByText('nodes.humanInput.userActions.triggered')).toBeInTheDocument()
})
it('should prefer structured form data over rendered markdown when available', () => {
render(
<SubmittedHumanInputContent formData={{
...mockFormData,
form_data: {
answer: 'approved',
},
}}
/>,
)
expect(screen.getByTestId('submitted-field-values')).toBeInTheDocument()
expect(screen.getByTestId('submitted-field-answer')).toHaveTextContent('approved')
expect(screen.queryByTestId('submitted-content')).not.toBeInTheDocument()
})
})

View File

@ -9,7 +9,7 @@ import {
} from '@/app/components/workflow/nodes/human-input/types'
type SubmittedFieldValuesProps = {
fields: FormInputItem[]
fields?: FormInputItem[]
values: Record<string, HumanInputFormValue>
}
@ -17,20 +17,36 @@ const SubmittedFieldValues = ({
fields,
values,
}: SubmittedFieldValuesProps) => {
const fieldNames = fields?.map(field => field.output_variable_name) ?? Object.keys(values)
const fieldMap = new Map(fields?.map(field => [field.output_variable_name, field]) ?? [])
return (
<div className="flex flex-col gap-3" data-testid="submitted-field-values">
{fields.map((field) => {
const value = values[field.output_variable_name]
{fieldNames.map((fieldName) => {
const field = fieldMap.get(fieldName)
const value = values[fieldName]
if (value == null)
return null
if (isFileFormInput(field)) {
let valueKind: 'text' | 'file' | 'file-list' = 'text'
if (field && isFileFormInput(field))
valueKind = 'file'
else if (field && isFileListFormInput(field))
valueKind = 'file-list'
else if (typeof value === 'string')
valueKind = 'text'
else if (Array.isArray(value))
valueKind = 'file-list'
else
valueKind = 'file'
if (valueKind === 'file') {
if (typeof value === 'string' || Array.isArray(value))
return null
return (
<div key={field.output_variable_name} data-testid={`submitted-field-${field.output_variable_name}`}>
<div key={fieldName} data-testid={`submitted-field-${fieldName}`}>
<FileList
files={getProcessedFilesFromResponse([value])}
showDeleteAction={false}
@ -40,12 +56,12 @@ const SubmittedFieldValues = ({
)
}
if (isFileListFormInput(field)) {
if (valueKind === 'file-list') {
if (typeof value === 'string' || !Array.isArray(value))
return null
return (
<div key={field.output_variable_name} data-testid={`submitted-field-${field.output_variable_name}`}>
<div key={fieldName} data-testid={`submitted-field-${fieldName}`}>
<FileList
files={getProcessedFilesFromResponse(value)}
showDeleteAction={false}
@ -57,9 +73,9 @@ const SubmittedFieldValues = ({
return (
<div
key={field.output_variable_name}
key={fieldName}
className="body-md-regular break-words text-text-primary"
data-testid={`submitted-field-${field.output_variable_name}`}
data-testid={`submitted-field-${fieldName}`}
>
{String(value)}
</div>

View File

@ -2,11 +2,12 @@ import type { SubmittedHumanInputContentProps } from './type'
import { useMemo } from 'react'
import ExecutedAction from './executed-action'
import SubmittedContent from './submitted-content'
import SubmittedFieldValues from './submitted-field-values'
export const SubmittedHumanInputContent = ({
formData,
}: SubmittedHumanInputContentProps) => {
const { rendered_content, action_id, action_text } = formData
const { rendered_content, action_id, action_text, form_data } = formData
const executedAction = useMemo(() => {
return {
@ -17,7 +18,9 @@ export const SubmittedHumanInputContent = ({
return (
<>
<SubmittedContent content={rendered_content} />
{form_data && Object.keys(form_data).length > 0
? <SubmittedFieldValues values={form_data} />
: <SubmittedContent content={rendered_content} />}
{/* Executed Action */}
<ExecutedAction executedAction={executedAction} />
</>