Fix: subblock rendering based on condition of other subblock

This commit is contained in:
Emir Karabeg
2025-02-12 18:38:04 -08:00
parent 322b2bec80
commit 0cba346c51
3 changed files with 42 additions and 38 deletions

View File

@@ -19,18 +19,10 @@ interface SubBlockProps {
}
export function SubBlock({ blockId, config, isConnecting }: SubBlockProps) {
const [fieldValue] = useSubBlockValue(blockId, config.condition?.field || '')
const handleMouseDown = (e: React.MouseEvent) => {
e.stopPropagation()
}
// Check if the sub-block should be rendered based on its condition
const shouldRender = () => {
if (!config.condition) return true
return fieldValue === config.condition.value
}
const renderInput = () => {
switch (config.type) {
case 'short-input':
@@ -108,10 +100,6 @@ export function SubBlock({ blockId, config, isConnecting }: SubBlockProps) {
}
}
if (!shouldRender()) {
return null
}
return (
<div className="space-y-1" onMouseDown={handleMouseDown}>
{config.type !== 'switch' && <Label>{config.title}</Label>}

View File

@@ -99,16 +99,30 @@ export function WorkflowBlock({ id, data, selected }: NodeProps<WorkflowBlockPro
}, [id, blockHeight, updateBlockHeight, updateNodeInternals])
// SubBlock layout management
function groupSubBlocks(subBlocks: SubBlockConfig[]) {
const visibleSubBlocks = subBlocks.filter((block) => !block.hidden)
function groupSubBlocks(subBlocks: SubBlockConfig[], blockId: string) {
const rows: SubBlockConfig[][] = []
let currentRow: SubBlockConfig[] = []
let currentRowWidth = 0
// Filter visible blocks and those that meet their conditions
const visibleSubBlocks = subBlocks.filter((block) => {
if (block.hidden) return false
// If there's no condition, the block should be shown
if (!block.condition) return true
// Get the value of the field this block depends on
const fieldValue =
useWorkflowStore.getState().blocks[blockId]?.subBlocks[block.condition.field]?.value
return fieldValue === block.condition.value
})
visibleSubBlocks.forEach((block) => {
const blockWidth = block.layout === 'half' ? 0.5 : 1
if (currentRowWidth + blockWidth > 1) {
rows.push([...currentRow])
if (currentRow.length > 0) {
rows.push([...currentRow])
}
currentRow = [block]
currentRowWidth = blockWidth
} else {
@@ -124,7 +138,7 @@ export function WorkflowBlock({ id, data, selected }: NodeProps<WorkflowBlockPro
return rows
}
const subBlockRows = groupSubBlocks(workflow.subBlocks)
const subBlockRows = groupSubBlocks(workflow.subBlocks, id)
// Name editing handlers
const handleNameClick = () => {
@@ -236,18 +250,20 @@ export function WorkflowBlock({ id, data, selected }: NodeProps<WorkflowBlockPro
{/* Block Content */}
<div ref={contentRef} className="px-4 pt-3 pb-4 space-y-4 cursor-pointer">
{subBlockRows.map((row, rowIndex) => (
<div key={`row-${rowIndex}`} className="flex gap-4">
{row.map((subBlock, blockIndex) => (
<div
key={`${id}-${rowIndex}-${blockIndex}`}
className={`space-y-1 ${subBlock.layout === 'half' ? 'flex-1' : 'w-full'}`}
>
<SubBlock blockId={id} config={subBlock} isConnecting={isConnecting} />
{subBlockRows.length > 0
? subBlockRows.map((row, rowIndex) => (
<div key={`row-${rowIndex}`} className="flex gap-4">
{row.map((subBlock, blockIndex) => (
<div
key={`${id}-${rowIndex}-${blockIndex}`}
className={cn('space-y-1', subBlock.layout === 'half' ? 'flex-1' : 'w-full')}
>
<SubBlock blockId={id} config={subBlock} isConnecting={isConnecting} />
</div>
))}
</div>
))}
</div>
))}
))
: null}
</div>
{/* Output Handle */}

View File

@@ -7,7 +7,7 @@ type XResponse = XWriteResponse | XReadResponse | XSearchResponse | XUserRespons
export const XBlock: BlockConfig<XResponse> = {
type: 'x_block',
toolbar: {
title: 'X (Twitter)',
title: 'X',
description: 'Interact with X',
bgColor: '#000000', // X's black color
icon: xIcon,
@@ -105,7 +105,7 @@ export const XBlock: BlockConfig<XResponse> = {
id: 'replyTo',
title: 'Reply To (Tweet ID)',
type: 'short-input',
layout: 'half',
layout: 'full',
placeholder: 'Enter tweet ID to reply to',
condition: { field: 'operation', value: 'x_write' },
},
@@ -113,7 +113,7 @@ export const XBlock: BlockConfig<XResponse> = {
id: 'mediaIds',
title: 'Media IDs',
type: 'short-input',
layout: 'half',
layout: 'full',
placeholder: 'Enter comma-separated media IDs',
condition: { field: 'operation', value: 'x_write' },
},
@@ -122,7 +122,7 @@ export const XBlock: BlockConfig<XResponse> = {
id: 'tweetId',
title: 'Tweet ID',
type: 'short-input',
layout: 'half',
layout: 'full',
placeholder: 'Enter tweet ID to read',
condition: { field: 'operation', value: 'x_read' },
},
@@ -130,7 +130,7 @@ export const XBlock: BlockConfig<XResponse> = {
id: 'includeReplies',
title: 'Include Replies',
type: 'dropdown',
layout: 'half',
layout: 'full',
options: ['true', 'false'],
value: () => 'false',
condition: { field: 'operation', value: 'x_read' },
@@ -148,7 +148,7 @@ export const XBlock: BlockConfig<XResponse> = {
id: 'maxResults',
title: 'Max Results',
type: 'short-input',
layout: 'half',
layout: 'full',
placeholder: '10',
condition: { field: 'operation', value: 'x_search' },
},
@@ -156,7 +156,7 @@ export const XBlock: BlockConfig<XResponse> = {
id: 'sortOrder',
title: 'Sort Order',
type: 'dropdown',
layout: 'half',
layout: 'full',
options: ['recency', 'relevancy'],
value: () => 'recency',
condition: { field: 'operation', value: 'x_search' },
@@ -165,7 +165,7 @@ export const XBlock: BlockConfig<XResponse> = {
id: 'startTime',
title: 'Start Time',
type: 'short-input',
layout: 'half',
layout: 'full',
placeholder: 'YYYY-MM-DDTHH:mm:ssZ',
condition: { field: 'operation', value: 'x_search' },
},
@@ -173,7 +173,7 @@ export const XBlock: BlockConfig<XResponse> = {
id: 'endTime',
title: 'End Time',
type: 'short-input',
layout: 'half',
layout: 'full',
placeholder: 'YYYY-MM-DDTHH:mm:ssZ',
condition: { field: 'operation', value: 'x_search' },
},
@@ -182,7 +182,7 @@ export const XBlock: BlockConfig<XResponse> = {
id: 'username',
title: 'Username',
type: 'short-input',
layout: 'half',
layout: 'full',
placeholder: 'Enter username (without @)',
condition: { field: 'operation', value: 'x_user' },
},
@@ -190,7 +190,7 @@ export const XBlock: BlockConfig<XResponse> = {
id: 'includeRecentTweets',
title: 'Include Recent Tweets',
type: 'dropdown',
layout: 'half',
layout: 'full',
options: ['true', 'false'],
value: () => 'false',
condition: { field: 'operation', value: 'x_user' },