Skip to content

Commit 87280c8

Browse files
committed
progress
1 parent 8d4d865 commit 87280c8

File tree

19 files changed

+918
-341
lines changed

19 files changed

+918
-341
lines changed

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/combobox/combobox.tsx

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,23 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
22
import { useReactFlow } from 'reactflow'
33
import { Combobox, type ComboboxOption } from '@/components/emcn/components'
44
import { cn } from '@/lib/core/utils/cn'
5+
import {
6+
buildCanonicalIndex,
7+
hasAdvancedValues,
8+
resolveDependencyValue,
9+
} from '@/lib/workflows/subblocks/visibility'
510
import { formatDisplayText } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/formatted-text'
611
import { SubBlockInputController } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/sub-block-input-controller'
712
import { useSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-value'
813
import { useAccessibleReferencePrefixes } from '@/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-accessible-reference-prefixes'
14+
import { getBlock } from '@/blocks/registry'
915
import type { SubBlockConfig } from '@/blocks/types'
1016
import { getDependsOnFields } from '@/blocks/utils'
1117
import { usePermissionConfig } from '@/hooks/use-permission-config'
1218
import { getProviderFromModel } from '@/providers/utils'
1319
import { useWorkflowRegistry } from '@/stores/workflows/registry/store'
1420
import { useSubBlockStore } from '@/stores/workflows/subblock/store'
21+
import { useWorkflowStore } from '@/stores/workflows/workflow/store'
1522

1623
/**
1724
* Constants for ComboBox component behavior
@@ -91,15 +98,41 @@ export function ComboBox({
9198
// Dependency tracking for fetchOptions
9299
const dependsOnFields = useMemo(() => getDependsOnFields(dependsOn), [dependsOn])
93100
const activeWorkflowId = useWorkflowRegistry((s) => s.activeWorkflowId)
101+
const blockState = useWorkflowStore((state) => state.blocks[blockId])
102+
const blockConfig = blockState?.type ? getBlock(blockState.type) : null
103+
const canonicalIndex = useMemo(
104+
() => buildCanonicalIndex(blockConfig?.subBlocks || []),
105+
[blockConfig?.subBlocks]
106+
)
107+
const canonicalModeOverrides = blockState?.data?.canonicalModes
94108
const dependencyValues = useSubBlockStore(
95109
useCallback(
96110
(state) => {
97111
if (dependsOnFields.length === 0 || !activeWorkflowId) return []
98112
const workflowValues = state.workflowValues[activeWorkflowId] || {}
99113
const blockValues = workflowValues[blockId] || {}
100-
return dependsOnFields.map((depKey) => blockValues[depKey] ?? null)
114+
const displayAdvancedOptions =
115+
(blockState?.advancedMode ?? false) ||
116+
hasAdvancedValues(blockConfig?.subBlocks || [], blockValues, canonicalIndex)
117+
return dependsOnFields.map((depKey) =>
118+
resolveDependencyValue(
119+
depKey,
120+
blockValues,
121+
displayAdvancedOptions,
122+
canonicalIndex,
123+
canonicalModeOverrides
124+
)
125+
)
101126
},
102-
[dependsOnFields, activeWorkflowId, blockId]
127+
[
128+
dependsOnFields,
129+
activeWorkflowId,
130+
blockId,
131+
blockState?.advancedMode,
132+
blockConfig?.subBlocks,
133+
canonicalIndex,
134+
canonicalModeOverrides,
135+
]
103136
)
104137
)
105138

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/dropdown/dropdown.tsx

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,19 @@
11
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
22
import { Badge } from '@/components/emcn'
33
import { Combobox, type ComboboxOption } from '@/components/emcn/components'
4+
import {
5+
buildCanonicalIndex,
6+
hasAdvancedValues,
7+
resolveDependencyValue,
8+
} from '@/lib/workflows/subblocks/visibility'
49
import { useSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-value'
10+
import { getBlock } from '@/blocks/registry'
511
import type { SubBlockConfig } from '@/blocks/types'
612
import { getDependsOnFields } from '@/blocks/utils'
713
import { ResponseBlockHandler } from '@/executor/handlers/response/response-handler'
814
import { useWorkflowRegistry } from '@/stores/workflows/registry/store'
915
import { useSubBlockStore } from '@/stores/workflows/subblock/store'
16+
import { useWorkflowStore } from '@/stores/workflows/workflow/store'
1017

1118
/**
1219
* Dropdown option type - can be a simple string or an object with label, id, and optional icon
@@ -89,15 +96,41 @@ export function Dropdown({
8996
const dependsOnFields = useMemo(() => getDependsOnFields(dependsOn), [dependsOn])
9097

9198
const activeWorkflowId = useWorkflowRegistry((s) => s.activeWorkflowId)
99+
const blockState = useWorkflowStore((state) => state.blocks[blockId])
100+
const blockConfig = blockState?.type ? getBlock(blockState.type) : null
101+
const canonicalIndex = useMemo(
102+
() => buildCanonicalIndex(blockConfig?.subBlocks || []),
103+
[blockConfig?.subBlocks]
104+
)
105+
const canonicalModeOverrides = blockState?.data?.canonicalModes
92106
const dependencyValues = useSubBlockStore(
93107
useCallback(
94108
(state) => {
95109
if (dependsOnFields.length === 0 || !activeWorkflowId) return []
96110
const workflowValues = state.workflowValues[activeWorkflowId] || {}
97111
const blockValues = workflowValues[blockId] || {}
98-
return dependsOnFields.map((depKey) => blockValues[depKey] ?? null)
112+
const displayAdvancedOptions =
113+
(blockState?.advancedMode ?? false) ||
114+
hasAdvancedValues(blockConfig?.subBlocks || [], blockValues, canonicalIndex)
115+
return dependsOnFields.map((depKey) =>
116+
resolveDependencyValue(
117+
depKey,
118+
blockValues,
119+
displayAdvancedOptions,
120+
canonicalIndex,
121+
canonicalModeOverrides
122+
)
123+
)
99124
},
100-
[dependsOnFields, activeWorkflowId, blockId]
125+
[
126+
dependsOnFields,
127+
activeWorkflowId,
128+
blockId,
129+
blockState?.advancedMode,
130+
blockConfig?.subBlocks,
131+
canonicalIndex,
132+
canonicalModeOverrides,
133+
]
101134
)
102135
)
103136

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-depends-on-gate.ts

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,16 @@
11
'use client'
22

33
import { useMemo } from 'react'
4+
import {
5+
buildCanonicalIndex,
6+
hasAdvancedValues,
7+
resolveDependencyValue,
8+
} from '@/lib/workflows/subblocks/visibility'
9+
import { getBlock } from '@/blocks/registry'
410
import type { SubBlockConfig } from '@/blocks/types'
511
import { useWorkflowRegistry } from '@/stores/workflows/registry/store'
612
import { useSubBlockStore } from '@/stores/workflows/subblock/store'
13+
import { useWorkflowStore } from '@/stores/workflows/workflow/store'
714

815
type DependsOnConfig = string[] | { all?: string[]; any?: string[] }
916

@@ -50,6 +57,13 @@ export function useDependsOnGate(
5057
const previewContextValues = opts?.previewContextValues
5158

5259
const activeWorkflowId = useWorkflowRegistry((s) => s.activeWorkflowId)
60+
const blockState = useWorkflowStore((state) => state.blocks[blockId])
61+
const blockConfig = blockState?.type ? getBlock(blockState.type) : null
62+
const canonicalIndex = useMemo(
63+
() => buildCanonicalIndex(blockConfig?.subBlocks || []),
64+
[blockConfig?.subBlocks]
65+
)
66+
const canonicalModeOverrides = blockState?.data?.canonicalModes
5367

5468
// Parse dependsOn config to get all/any field lists
5569
const { allFields, anyFields, allDependsOnFields } = useMemo(
@@ -89,9 +103,21 @@ export function useDependsOnGate(
89103

90104
// If previewContextValues are provided (e.g., tool parameters), use those first
91105
if (previewContextValues) {
106+
const displayAdvancedOptions = hasAdvancedValues(
107+
blockConfig?.subBlocks || [],
108+
previewContextValues,
109+
canonicalIndex
110+
)
92111
const map: Record<string, unknown> = {}
93112
for (const key of allDependsOnFields) {
94-
map[key] = normalizeDependencyValue(previewContextValues[key])
113+
const resolvedValue = resolveDependencyValue(
114+
key,
115+
previewContextValues,
116+
displayAdvancedOptions,
117+
canonicalIndex,
118+
canonicalModeOverrides
119+
)
120+
map[key] = normalizeDependencyValue(resolvedValue)
95121
}
96122
return map
97123
}
@@ -106,9 +132,19 @@ export function useDependsOnGate(
106132

107133
const workflowValues = state.workflowValues[activeWorkflowId] || {}
108134
const blockValues = (workflowValues as any)[blockId] || {}
135+
const displayAdvancedOptions =
136+
(blockState?.advancedMode ?? false) ||
137+
hasAdvancedValues(blockConfig?.subBlocks || [], blockValues, canonicalIndex)
109138
const map: Record<string, unknown> = {}
110139
for (const key of allDependsOnFields) {
111-
map[key] = normalizeDependencyValue((blockValues as any)[key])
140+
const resolvedValue = resolveDependencyValue(
141+
key,
142+
blockValues,
143+
displayAdvancedOptions,
144+
canonicalIndex,
145+
canonicalModeOverrides
146+
)
147+
map[key] = normalizeDependencyValue(resolvedValue)
112148
}
113149
return map
114150
})

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/sub-block.tsx

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { type JSX, type MouseEvent, memo, useRef, useState } from 'react'
2-
import { AlertTriangle, Wand2 } from 'lucide-react'
2+
import { AlertTriangle, ArrowLeftRight, Wand2 } from 'lucide-react'
33
import { Label, Tooltip } from '@/components/emcn/components'
44
import { Button } from '@/components/ui/button'
55
import { cn } from '@/lib/core/utils/cn'
@@ -68,6 +68,11 @@ interface SubBlockProps {
6868
disabled?: boolean
6969
fieldDiffStatus?: FieldDiffStatus
7070
allowExpandInPreview?: boolean
71+
canonicalToggle?: {
72+
mode: 'basic' | 'advanced'
73+
disabled?: boolean
74+
onToggle?: () => void
75+
}
7176
}
7277

7378
/**
@@ -183,7 +188,12 @@ const renderLabel = (
183188
onSearchCancel: () => void
184189
searchInputRef: React.RefObject<HTMLInputElement | null>
185190
},
186-
subBlockValues?: Record<string, any>
191+
subBlockValues?: Record<string, any>,
192+
canonicalToggle?: {
193+
mode: 'basic' | 'advanced'
194+
disabled?: boolean
195+
onToggle?: () => void
196+
}
187197
): JSX.Element | null => {
188198
if (config.type === 'switch') return null
189199
if (!config.title) return null
@@ -204,12 +214,41 @@ const renderLabel = (
204214
} = wandState
205215

206216
const required = isFieldRequired(config, subBlockValues)
217+
const showCanonicalToggle = !!canonicalToggle && !isPreview
218+
const canonicalToggleDisabled = disabled || canonicalToggle?.disabled
207219

208220
return (
209221
<Label className='flex items-center justify-between gap-[6px] pl-[2px]'>
210222
<div className='flex items-center gap-[6px] whitespace-nowrap'>
211223
{config.title}
212224
{required && <span className='ml-0.5'>*</span>}
225+
{showCanonicalToggle && (
226+
<Tooltip.Root>
227+
<Tooltip.Trigger asChild>
228+
<Button
229+
variant='ghost'
230+
className='h-[12px] w-[12px] flex-shrink-0 p-0 hover:bg-transparent'
231+
onClick={canonicalToggle?.onToggle}
232+
disabled={canonicalToggleDisabled}
233+
aria-label={
234+
canonicalToggle?.mode === 'advanced' ? 'Use selector' : 'Enter manual ID'
235+
}
236+
>
237+
<ArrowLeftRight
238+
className={cn(
239+
'!h-[12px] !w-[12px]',
240+
canonicalToggle?.mode === 'advanced'
241+
? 'text-[var(--text-primary)]'
242+
: 'text-[var(--text-secondary)]'
243+
)}
244+
/>
245+
</Button>
246+
</Tooltip.Trigger>
247+
<Tooltip.Content side='top'>
248+
<p>{canonicalToggle?.mode === 'advanced' ? 'Use selector' : 'Enter manual ID'}</p>
249+
</Tooltip.Content>
250+
</Tooltip.Root>
251+
)}
213252
{config.type === 'code' && config.language === 'json' && (
214253
<Tooltip.Root>
215254
<Tooltip.Trigger asChild>
@@ -286,7 +325,9 @@ const arePropsEqual = (prevProps: SubBlockProps, nextProps: SubBlockProps): bool
286325
prevProps.subBlockValues === nextProps.subBlockValues &&
287326
prevProps.disabled === nextProps.disabled &&
288327
prevProps.fieldDiffStatus === nextProps.fieldDiffStatus &&
289-
prevProps.allowExpandInPreview === nextProps.allowExpandInPreview
328+
prevProps.allowExpandInPreview === nextProps.allowExpandInPreview &&
329+
prevProps.canonicalToggle?.mode === nextProps.canonicalToggle?.mode &&
330+
prevProps.canonicalToggle?.disabled === nextProps.canonicalToggle?.disabled
290331
)
291332
}
292333

@@ -315,6 +356,7 @@ function SubBlockComponent({
315356
disabled = false,
316357
fieldDiffStatus,
317358
allowExpandInPreview,
359+
canonicalToggle,
318360
}: SubBlockProps): JSX.Element {
319361
const [isValidJson, setIsValidJson] = useState(true)
320362
const [isSearchActive, setIsSearchActive] = useState(false)
@@ -902,7 +944,8 @@ function SubBlockComponent({
902944
onSearchCancel: handleSearchCancel,
903945
searchInputRef,
904946
},
905-
subBlockValues
947+
subBlockValues,
948+
canonicalToggle
906949
)}
907950
{renderInput()}
908951
</div>

0 commit comments

Comments
 (0)