add variable type to webhook request parameters panel

This commit is contained in:
hjlarry 2025-09-30 16:31:21 +08:00
parent 5ecc006805
commit 43574c852d
4 changed files with 22 additions and 32 deletions

View File

@ -280,7 +280,7 @@ const GenericTable: FC<GenericTableProps> = ({
return ( return (
<div className={className}> <div className={className}>
<div className="mb-3 flex items-center justify-between"> <div className="mb-3 flex items-center justify-between">
<h4 className="text-sm font-medium text-text-secondary">{title}</h4> <h4 className="system-sm-semibold-uppercase text-text-secondary">{title}</h4>
</div> </div>
{showPlaceholder ? ( {showPlaceholder ? (

View File

@ -14,8 +14,6 @@ type ParameterTableProps = {
onChange: (params: WebhookParameter[]) => void onChange: (params: WebhookParameter[]) => void
readonly?: boolean readonly?: boolean
placeholder?: string placeholder?: string
showType?: boolean
isRequestBody?: boolean // Special handling for request body parameters
contentType?: string contentType?: string
} }
@ -25,37 +23,33 @@ const ParameterTable: FC<ParameterTableProps> = ({
onChange, onChange,
readonly, readonly,
placeholder, placeholder,
showType = true,
isRequestBody = false,
contentType, contentType,
}) => { }) => {
const { t } = useTranslation() const { t } = useTranslation()
// Memoize typeOptions to prevent unnecessary re-renders that cause SimpleSelect state resets // Memoize typeOptions to prevent unnecessary re-renders that cause SimpleSelect state resets
const typeOptions = useMemo(() => const typeOptions = useMemo(() =>
createParameterTypeOptions(contentType, isRequestBody), createParameterTypeOptions(contentType),
[contentType, isRequestBody], [contentType],
) )
// Define columns based on component type - matching prototype design // Define columns based on component type - matching prototype design
const columns: ColumnConfig[] = [ const columns: ColumnConfig[] = [
{ {
key: 'key', key: 'key',
title: isRequestBody ? 'Name' : 'Variable Name', title: 'Variable Name',
type: 'input', type: 'input',
width: 'flex-1', width: 'flex-1',
placeholder: isRequestBody ? 'Name' : 'Variable Name', placeholder: 'Variable Name',
},
{
key: 'type',
title: 'Type',
type: 'select',
width: 'w-[120px]',
placeholder: 'Type',
options: typeOptions,
}, },
...(showType
? [{
key: 'type',
title: 'Type',
type: (isRequestBody ? 'select' : 'input') as ColumnConfig['type'],
width: 'w-[120px]',
placeholder: 'Type',
options: isRequestBody ? typeOptions : undefined,
}]
: []),
{ {
key: 'required', key: 'required',
title: 'Required', title: 'Required',
@ -70,7 +64,7 @@ const ParameterTable: FC<ParameterTableProps> = ({
// Empty row template for new rows // Empty row template for new rows
const emptyRowData: GenericTableRow = { const emptyRowData: GenericTableRow = {
key: '', key: '',
type: isRequestBody ? defaultTypeValue : '', type: defaultTypeValue,
required: false, required: false,
} }
@ -83,8 +77,8 @@ const ParameterTable: FC<ParameterTableProps> = ({
const handleDataChange = (data: GenericTableRow[]) => { const handleDataChange = (data: GenericTableRow[]) => {
// For text/plain, enforce single text body semantics: keep only first non-empty row and force string type // For text/plain, enforce single text body semantics: keep only first non-empty row and force string type
// For application/octet-stream, enforce single file body semantics: keep only first non-empty row and force file type // For application/octet-stream, enforce single file body semantics: keep only first non-empty row and force file type
const isTextPlain = isRequestBody && (contentType || '').toLowerCase() === 'text/plain' const isTextPlain = (contentType || '').toLowerCase() === 'text/plain'
const isOctetStream = isRequestBody && (contentType || '').toLowerCase() === 'application/octet-stream' const isOctetStream = (contentType || '').toLowerCase() === 'application/octet-stream'
const normalized = data const normalized = data
.filter(row => typeof row.key === 'string' && (row.key as string).trim() !== '') .filter(row => typeof row.key === 'string' && (row.key as string).trim() !== '')

View File

@ -158,7 +158,6 @@ const Panel: FC<NodePanelProps<WebhookTriggerNodeType>> = ({
parameters={inputs.params} parameters={inputs.params}
onChange={handleParamsChange} onChange={handleParamsChange}
placeholder={t(`${i18nPrefix}.noQueryParameters`)} placeholder={t(`${i18nPrefix}.noQueryParameters`)}
showType={false}
/> />
{/* Header Parameters */} {/* Header Parameters */}
@ -175,8 +174,6 @@ const Panel: FC<NodePanelProps<WebhookTriggerNodeType>> = ({
parameters={inputs.body} parameters={inputs.body}
onChange={handleBodyChange} onChange={handleBodyChange}
placeholder={t(`${i18nPrefix}.noBodyParameters`)} placeholder={t(`${i18nPrefix}.noBodyParameters`)}
showType={true}
isRequestBody={true}
contentType={inputs.content_type} contentType={inputs.content_type}
/> />

View File

@ -26,6 +26,7 @@ const TYPE_DISPLAY_NAMES: Record<VarType, string> = {
'array[file]': 'Array[File]', 'array[file]': 'Array[File]',
[VarType.any]: 'Any', [VarType.any]: 'Any',
'array[any]': 'Array[Any]', 'array[any]': 'Array[Any]',
[VarType.integer]: 'Integer',
} as const } as const
// Content type configurations // Content type configurations
@ -98,11 +99,9 @@ export const getParameterTypeDisplayName = (type: VarType): string => {
* Gets available parameter types based on content type * Gets available parameter types based on content type
* Provides context-aware type filtering for different webhook content types * Provides context-aware type filtering for different webhook content types
*/ */
export const getAvailableParameterTypes = (contentType?: string, isRequestBody = false): VarType[] => { export const getAvailableParameterTypes = (contentType?: string): VarType[] => {
if (!isRequestBody) { if (!contentType)
// Query parameters and headers are always strings return [VarType.string, VarType.number, VarType.boolean]
return [VarType.string]
}
const normalizedContentType = (contentType || '').toLowerCase() const normalizedContentType = (contentType || '').toLowerCase()
const configKey = normalizedContentType in CONTENT_TYPE_CONFIGS const configKey = normalizedContentType in CONTENT_TYPE_CONFIGS
@ -116,8 +115,8 @@ export const getAvailableParameterTypes = (contentType?: string, isRequestBody =
/** /**
* Creates type options for UI select components * Creates type options for UI select components
*/ */
export const createParameterTypeOptions = (contentType?: string, isRequestBody = false) => { export const createParameterTypeOptions = (contentType?: string) => {
const availableTypes = getAvailableParameterTypes(contentType, isRequestBody) const availableTypes = getAvailableParameterTypes(contentType)
return availableTypes.map(type => ({ return availableTypes.map(type => ({
name: getParameterTypeDisplayName(type), name: getParameterTypeDisplayName(type),