mirror of
https://github.com/simstudioai/sim.git
synced 2026-09-24 15:45:35 +08:00
Created functional protocol for output type dependencies
This commit is contained in:
@@ -23,7 +23,7 @@ export function ConnectionBlock({ blockId }: ConnectionBlockProps) {
|
||||
{connection.name.replace(' ', '').toLowerCase()}
|
||||
</span>
|
||||
<span className="text-muted-foreground">
|
||||
.{connection.outputType}
|
||||
.{connection.outputType === 'any' ? 'res' : connection.outputType}
|
||||
</span>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
import { BlockState, SubBlockState } from '@/stores/workflow/types'
|
||||
import { OutputTypeConfig, OutputType } from '@/blocks/types'
|
||||
|
||||
interface CodeLine {
|
||||
id: string
|
||||
content: string
|
||||
}
|
||||
|
||||
function isEmptyValue(value: SubBlockState['value']): boolean {
|
||||
if (value === null || value === undefined) return true
|
||||
if (typeof value === 'string') return value.trim() === ''
|
||||
if (typeof value === 'number') return false
|
||||
if (Array.isArray(value)) {
|
||||
// Handle code editor's array of lines format
|
||||
if (value.length === 0) return true
|
||||
if (isCodeEditorValue(value)) {
|
||||
return value.every((line: any) => !line.content.trim())
|
||||
}
|
||||
return value.length === 0
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
function isCodeEditorValue(value: any[]): value is CodeLine[] {
|
||||
return value.length > 0 && 'id' in value[0] && 'content' in value[0]
|
||||
}
|
||||
|
||||
export function resolveOutputType(
|
||||
outputTypeConfig: OutputTypeConfig,
|
||||
subBlocks: Record<string, SubBlockState>
|
||||
): OutputType {
|
||||
// If outputType is a string, return it directly
|
||||
if (typeof outputTypeConfig === 'string') {
|
||||
return outputTypeConfig
|
||||
}
|
||||
|
||||
// Handle dependent output types
|
||||
const { dependsOn } = outputTypeConfig
|
||||
const subBlock = subBlocks[dependsOn.subBlockId]
|
||||
|
||||
return isEmptyValue(subBlock?.value)
|
||||
? dependsOn.condition.whenEmpty
|
||||
: dependsOn.condition.whenFilled
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import { Edge } from 'reactflow'
|
||||
import { Position, SubBlockState, WorkflowStore } from './types'
|
||||
import { getBlock } from '@/blocks'
|
||||
import { withHistory, WorkflowStoreWithHistory, pushHistory } from './history-middleware'
|
||||
import { resolveOutputType } from '@/blocks/utils'
|
||||
|
||||
const initialState = {
|
||||
blocks: {},
|
||||
@@ -29,21 +30,38 @@ export const useWorkflowStore = create<WorkflowStoreWithHistory>()(
|
||||
canRedo: () => false,
|
||||
|
||||
updateSubBlock: (blockId: string, subBlockId: string, value: any) => {
|
||||
set((state) => ({
|
||||
blocks: {
|
||||
...state.blocks,
|
||||
[blockId]: {
|
||||
...state.blocks[blockId],
|
||||
subBlocks: {
|
||||
...state.blocks[blockId].subBlocks,
|
||||
[subBlockId]: {
|
||||
...state.blocks[blockId].subBlocks[subBlockId],
|
||||
value,
|
||||
},
|
||||
set((state) => {
|
||||
const block = state.blocks[blockId]
|
||||
const blockConfig = getBlock(block.type)
|
||||
|
||||
if (!blockConfig) return state
|
||||
|
||||
// Create new subBlocks state
|
||||
const newSubBlocks = {
|
||||
...block.subBlocks,
|
||||
[subBlockId]: {
|
||||
...block.subBlocks[subBlockId],
|
||||
value,
|
||||
},
|
||||
}
|
||||
|
||||
// Resolve new output type
|
||||
const newOutputType = resolveOutputType(
|
||||
blockConfig.workflow.outputType,
|
||||
newSubBlocks
|
||||
)
|
||||
|
||||
return {
|
||||
blocks: {
|
||||
...state.blocks,
|
||||
[blockId]: {
|
||||
...block,
|
||||
subBlocks: newSubBlocks,
|
||||
outputType: newOutputType,
|
||||
},
|
||||
},
|
||||
},
|
||||
}))
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
addBlock: (id: string, type: string, name: string, position: Position) => {
|
||||
|
||||
Reference in New Issue
Block a user