fix(connection-tags): drag and drop didn't render tag dropdown with input format fields (#1647)

This commit is contained in:
Vikhyath Mondreti
2025-10-15 16:31:30 -07:00
committed by GitHub
parent 56d04a9558
commit ba8acbba07
2 changed files with 77 additions and 14 deletions

View File

@@ -1,6 +1,8 @@
import { shallow } from 'zustand/shallow'
import { BlockPathCalculator } from '@/lib/block-path-calculator'
import { createLogger } from '@/lib/logs/console/logger'
import { getBlockOutputs } from '@/lib/workflows/block-outputs'
import { useWorkflowRegistry } from '@/stores/workflows/registry/store'
import { useSubBlockStore } from '@/stores/workflows/subblock/store'
import { useWorkflowStore } from '@/stores/workflows/workflow/store'
@@ -92,6 +94,22 @@ export function useBlockConnections(blockId: string) {
shallow
)
const workflowId = useWorkflowRegistry((state) => state.activeWorkflowId)
const workflowSubBlockValues = useSubBlockStore((state) =>
workflowId ? (state.workflowValues[workflowId] ?? {}) : {}
)
// Helper function to merge block subBlocks with live values from subblock store
const getMergedSubBlocks = (sourceBlockId: string): Record<string, any> => {
const base = blocks[sourceBlockId]?.subBlocks || {}
const live = workflowSubBlockValues?.[sourceBlockId] || {}
const merged: Record<string, any> = { ...base }
for (const [subId, liveVal] of Object.entries(live)) {
merged[subId] = { ...(base[subId] || {}), value: liveVal }
}
return merged
}
// Find all blocks along paths leading to this block
const allPathNodeIds = BlockPathCalculator.findAllPathNodes(edges, blockId)
@@ -101,20 +119,37 @@ export function useBlockConnections(blockId: string) {
const sourceBlock = blocks[sourceId]
if (!sourceBlock) return null
// Get merged subblocks for this source block
const mergedSubBlocks = getMergedSubBlocks(sourceId)
// Get the response format from the subblock store
const responseFormatValue = useSubBlockStore.getState().getValue(sourceId, 'responseFormat')
// Safely parse response format with proper error handling
const responseFormat = parseResponseFormatSafely(responseFormatValue, sourceId)
// Get the default output type from the block's outputs
const defaultOutputs: Field[] = Object.entries(sourceBlock.outputs || {}).map(([key]) => ({
name: key,
type: 'string',
}))
// Use getBlockOutputs to properly handle dynamic outputs from inputFormat
const blockOutputs = getBlockOutputs(
sourceBlock.type,
mergedSubBlocks,
sourceBlock.triggerMode
)
// Extract fields from the response format using our helper function
const outputFields = responseFormat ? extractFieldsFromSchema(responseFormat) : defaultOutputs
// Extract fields from the response format if available, otherwise use block outputs
let outputFields: Field[]
if (responseFormat) {
outputFields = extractFieldsFromSchema(responseFormat)
} else {
// Convert block outputs to field format
outputFields = Object.entries(blockOutputs).map(([key, value]: [string, any]) => ({
name: key,
type: value && typeof value === 'object' && 'type' in value ? value.type : 'string',
description:
value && typeof value === 'object' && 'description' in value
? value.description
: undefined,
}))
}
return {
id: sourceBlock.id,
@@ -133,6 +168,9 @@ export function useBlockConnections(blockId: string) {
const sourceBlock = blocks[edge.source]
if (!sourceBlock) return null
// Get merged subblocks for this source block
const mergedSubBlocks = getMergedSubBlocks(edge.source)
// Get the response format from the subblock store instead
const responseFormatValue = useSubBlockStore
.getState()
@@ -141,14 +179,28 @@ export function useBlockConnections(blockId: string) {
// Safely parse response format with proper error handling
const responseFormat = parseResponseFormatSafely(responseFormatValue, edge.source)
// Get the default output type from the block's outputs
const defaultOutputs: Field[] = Object.entries(sourceBlock.outputs || {}).map(([key]) => ({
name: key,
type: 'string',
}))
// Use getBlockOutputs to properly handle dynamic outputs from inputFormat
const blockOutputs = getBlockOutputs(
sourceBlock.type,
mergedSubBlocks,
sourceBlock.triggerMode
)
// Extract fields from the response format using our helper function
const outputFields = responseFormat ? extractFieldsFromSchema(responseFormat) : defaultOutputs
// Extract fields from the response format if available, otherwise use block outputs
let outputFields: Field[]
if (responseFormat) {
outputFields = extractFieldsFromSchema(responseFormat)
} else {
// Convert block outputs to field format
outputFields = Object.entries(blockOutputs).map(([key, value]: [string, any]) => ({
name: key,
type: value && typeof value === 'object' && 'type' in value ? value.type : 'string',
description:
value && typeof value === 'object' && 'description' in value
? value.description
: undefined,
}))
}
return {
id: sourceBlock.id,

View File

@@ -453,6 +453,17 @@ export const TagDropdown: React.FC<TagDropdownProps> = ({
blockTags = [normalizedBlockName]
}
}
} else if (sourceBlock.type === 'api_trigger' || sourceBlock.type === 'input_trigger') {
// Handle API trigger and Input Form trigger with inputFormat
const inputFormatValue = mergedSubBlocks?.inputFormat?.value
if (inputFormatValue && Array.isArray(inputFormatValue) && inputFormatValue.length > 0) {
blockTags = inputFormatValue
.filter((field: { name?: string }) => field.name && field.name.trim() !== '')
.map((field: { name: string }) => `${normalizedBlockName}.${field.name}`)
} else {
blockTags = []
}
} else {
blockTags = [normalizedBlockName]
}