diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/credential-selector/credential-selector.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/credential-selector/credential-selector.tsx index 79087c7c48..378a9baed3 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/credential-selector/credential-selector.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/credential-selector/credential-selector.tsx @@ -35,6 +35,7 @@ interface CredentialSelectorProps { disabled?: boolean isPreview?: boolean previewValue?: any | null + previewContextValues?: Record } export function CredentialSelector({ @@ -43,6 +44,7 @@ export function CredentialSelector({ disabled = false, isPreview = false, previewValue, + previewContextValues, }: CredentialSelectorProps) { const [showOAuthModal, setShowOAuthModal] = useState(false) const [editingValue, setEditingValue] = useState('') @@ -67,7 +69,11 @@ export function CredentialSelector({ canUseCredentialSets ) - const { depsSatisfied, dependsOn } = useDependsOnGate(blockId, subBlock, { disabled, isPreview }) + const { depsSatisfied, dependsOn } = useDependsOnGate(blockId, subBlock, { + disabled, + isPreview, + previewContextValues, + }) const hasDependencies = dependsOn.length > 0 const effectiveDisabled = disabled || (hasDependencies && !depsSatisfied) diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/document-selector/document-selector.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/document-selector/document-selector.tsx index 012c78338f..f1e47ab710 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/document-selector/document-selector.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/document-selector/document-selector.tsx @@ -5,6 +5,7 @@ import { Tooltip } from '@/components/emcn' import { SelectorCombobox } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/selector-combobox/selector-combobox' import { useDependsOnGate } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-depends-on-gate' import { useSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-value' +import { resolvePreviewContextValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/utils' import type { SubBlockConfig } from '@/blocks/types' import type { SelectorContext } from '@/hooks/selectors/types' @@ -33,7 +34,9 @@ export function DocumentSelector({ previewContextValues, }) const [knowledgeBaseIdFromStore] = useSubBlockValue(blockId, 'knowledgeBaseId') - const knowledgeBaseIdValue = previewContextValues?.knowledgeBaseId ?? knowledgeBaseIdFromStore + const knowledgeBaseIdValue = previewContextValues + ? resolvePreviewContextValue(previewContextValues.knowledgeBaseId) + : knowledgeBaseIdFromStore const normalizedKnowledgeBaseId = typeof knowledgeBaseIdValue === 'string' && knowledgeBaseIdValue.trim().length > 0 ? knowledgeBaseIdValue diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/document-tag-entry/document-tag-entry.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/document-tag-entry/document-tag-entry.tsx index ffb5122db9..b21c6f9d42 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/document-tag-entry/document-tag-entry.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/document-tag-entry/document-tag-entry.tsx @@ -17,6 +17,7 @@ import { formatDisplayText } from '@/app/workspace/[workspaceId]/w/[workflowId]/ import { TagDropdown } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/tag-dropdown/tag-dropdown' import { useSubBlockInput } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-input' import { useSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-value' +import { resolvePreviewContextValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/utils' import { useAccessibleReferencePrefixes } from '@/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-accessible-reference-prefixes' import type { SubBlockConfig } from '@/blocks/types' import { useKnowledgeBaseTagDefinitions } from '@/hooks/kb/use-knowledge-base-tag-definitions' @@ -77,7 +78,9 @@ export function DocumentTagEntry({ }) const [knowledgeBaseIdFromStore] = useSubBlockValue(blockId, 'knowledgeBaseId') - const knowledgeBaseIdValue = previewContextValues?.knowledgeBaseId ?? knowledgeBaseIdFromStore + const knowledgeBaseIdValue = previewContextValues + ? resolvePreviewContextValue(previewContextValues.knowledgeBaseId) + : knowledgeBaseIdFromStore const knowledgeBaseId = typeof knowledgeBaseIdValue === 'string' && knowledgeBaseIdValue.trim().length > 0 ? knowledgeBaseIdValue diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/file-selector/file-selector-input.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/file-selector/file-selector-input.tsx index 6805e2ec4a..730f01b248 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/file-selector/file-selector-input.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/file-selector/file-selector-input.tsx @@ -9,6 +9,7 @@ import { SelectorCombobox } from '@/app/workspace/[workspaceId]/w/[workflowId]/c import { useDependsOnGate } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-depends-on-gate' import { useForeignCredential } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-foreign-credential' import { useSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-value' +import { resolvePreviewContextValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/utils' import { getBlock } from '@/blocks/registry' import type { SubBlockConfig } from '@/blocks/types' import { isDependency } from '@/blocks/utils' @@ -62,42 +63,56 @@ export function FileSelectorInput({ const [domainValueFromStore] = useSubBlockValue(blockId, 'domain') - const connectedCredential = previewContextValues?.credential ?? blockValues.credential - const domainValue = previewContextValues?.domain ?? domainValueFromStore + const connectedCredential = previewContextValues + ? resolvePreviewContextValue(previewContextValues.credential) + : blockValues.credential + const domainValue = previewContextValues + ? resolvePreviewContextValue(previewContextValues.domain) + : domainValueFromStore const teamIdValue = useMemo( () => - previewContextValues?.teamId ?? - resolveDependencyValue('teamId', blockValues, canonicalIndex, canonicalModeOverrides), - [previewContextValues?.teamId, blockValues, canonicalIndex, canonicalModeOverrides] + previewContextValues + ? resolvePreviewContextValue(previewContextValues.teamId) + : resolveDependencyValue('teamId', blockValues, canonicalIndex, canonicalModeOverrides), + [previewContextValues, blockValues, canonicalIndex, canonicalModeOverrides] ) const siteIdValue = useMemo( () => - previewContextValues?.siteId ?? - resolveDependencyValue('siteId', blockValues, canonicalIndex, canonicalModeOverrides), - [previewContextValues?.siteId, blockValues, canonicalIndex, canonicalModeOverrides] + previewContextValues + ? resolvePreviewContextValue(previewContextValues.siteId) + : resolveDependencyValue('siteId', blockValues, canonicalIndex, canonicalModeOverrides), + [previewContextValues, blockValues, canonicalIndex, canonicalModeOverrides] ) const collectionIdValue = useMemo( () => - previewContextValues?.collectionId ?? - resolveDependencyValue('collectionId', blockValues, canonicalIndex, canonicalModeOverrides), - [previewContextValues?.collectionId, blockValues, canonicalIndex, canonicalModeOverrides] + previewContextValues + ? resolvePreviewContextValue(previewContextValues.collectionId) + : resolveDependencyValue( + 'collectionId', + blockValues, + canonicalIndex, + canonicalModeOverrides + ), + [previewContextValues, blockValues, canonicalIndex, canonicalModeOverrides] ) const projectIdValue = useMemo( () => - previewContextValues?.projectId ?? - resolveDependencyValue('projectId', blockValues, canonicalIndex, canonicalModeOverrides), - [previewContextValues?.projectId, blockValues, canonicalIndex, canonicalModeOverrides] + previewContextValues + ? resolvePreviewContextValue(previewContextValues.projectId) + : resolveDependencyValue('projectId', blockValues, canonicalIndex, canonicalModeOverrides), + [previewContextValues, blockValues, canonicalIndex, canonicalModeOverrides] ) const planIdValue = useMemo( () => - previewContextValues?.planId ?? - resolveDependencyValue('planId', blockValues, canonicalIndex, canonicalModeOverrides), - [previewContextValues?.planId, blockValues, canonicalIndex, canonicalModeOverrides] + previewContextValues + ? resolvePreviewContextValue(previewContextValues.planId) + : resolveDependencyValue('planId', blockValues, canonicalIndex, canonicalModeOverrides), + [previewContextValues, blockValues, canonicalIndex, canonicalModeOverrides] ) const normalizedCredentialId = diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/folder-selector/components/folder-selector-input.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/folder-selector/components/folder-selector-input.tsx index fa9a48bb4b..4be4a8da3f 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/folder-selector/components/folder-selector-input.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/folder-selector/components/folder-selector-input.tsx @@ -6,6 +6,7 @@ import { SelectorCombobox } from '@/app/workspace/[workspaceId]/w/[workflowId]/c import { useDependsOnGate } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-depends-on-gate' import { useForeignCredential } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-foreign-credential' import { useSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-value' +import { resolvePreviewContextValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/utils' import type { SubBlockConfig } from '@/blocks/types' import { resolveSelectorForSubBlock } from '@/hooks/selectors/resolution' import { useCollaborativeWorkflow } from '@/hooks/use-collaborative-workflow' @@ -17,6 +18,7 @@ interface FolderSelectorInputProps { disabled?: boolean isPreview?: boolean previewValue?: any | null + previewContextValues?: Record } export function FolderSelectorInput({ @@ -25,9 +27,13 @@ export function FolderSelectorInput({ disabled = false, isPreview = false, previewValue, + previewContextValues, }: FolderSelectorInputProps) { const [storeValue] = useSubBlockValue(blockId, subBlock.id) - const [connectedCredential] = useSubBlockValue(blockId, 'credential') + const [credentialFromStore] = useSubBlockValue(blockId, 'credential') + const connectedCredential = previewContextValues + ? resolvePreviewContextValue(previewContextValues.credential) + : credentialFromStore const { collaborativeSetSubblockValue } = useCollaborativeWorkflow() const { activeWorkflowId } = useWorkflowRegistry() const [selectedFolderId, setSelectedFolderId] = useState('') @@ -47,7 +53,11 @@ export function FolderSelectorInput({ ) // Central dependsOn gating - const { finalDisabled } = useDependsOnGate(blockId, subBlock, { disabled, isPreview }) + const { finalDisabled } = useDependsOnGate(blockId, subBlock, { + disabled, + isPreview, + previewContextValues, + }) // Get the current value from the store or prop value if in preview mode useEffect(() => { diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/input-mapping/input-mapping.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/input-mapping/input-mapping.tsx index 55c37277bd..69189c7629 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/input-mapping/input-mapping.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/input-mapping/input-mapping.tsx @@ -7,6 +7,7 @@ import { formatDisplayText } from '@/app/workspace/[workspaceId]/w/[workflowId]/ import { TagDropdown } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/tag-dropdown/tag-dropdown' import { useSubBlockInput } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-input' import { useSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-value' +import { resolvePreviewContextValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/utils' import { useAccessibleReferencePrefixes } from '@/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-accessible-reference-prefixes' import { useWorkflowState } from '@/hooks/queries/workflows' @@ -37,6 +38,8 @@ interface InputMappingProps { isPreview?: boolean previewValue?: Record disabled?: boolean + /** Sub-block values from the preview context for resolving sibling sub-block values */ + previewContextValues?: Record } /** @@ -50,9 +53,13 @@ export function InputMapping({ isPreview = false, previewValue, disabled = false, + previewContextValues, }: InputMappingProps) { const [mapping, setMapping] = useSubBlockValue(blockId, subBlockId) - const [selectedWorkflowId] = useSubBlockValue(blockId, 'workflowId') + const [storeWorkflowId] = useSubBlockValue(blockId, 'workflowId') + const selectedWorkflowId = previewContextValues + ? resolvePreviewContextValue(previewContextValues.workflowId) + : storeWorkflowId const inputController = useSubBlockInput({ blockId, diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/knowledge-tag-filters/knowledge-tag-filters.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/knowledge-tag-filters/knowledge-tag-filters.tsx index 2198555fc9..d297252abc 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/knowledge-tag-filters/knowledge-tag-filters.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/knowledge-tag-filters/knowledge-tag-filters.tsx @@ -17,6 +17,7 @@ import { type FilterFieldType, getOperatorsForFieldType } from '@/lib/knowledge/ import { formatDisplayText } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/formatted-text' import { TagDropdown } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/tag-dropdown/tag-dropdown' import { useSubBlockInput } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-input' +import { resolvePreviewContextValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/utils' import { useAccessibleReferencePrefixes } from '@/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-accessible-reference-prefixes' import type { SubBlockConfig } from '@/blocks/types' import { useKnowledgeBaseTagDefinitions } from '@/hooks/kb/use-knowledge-base-tag-definitions' @@ -69,7 +70,9 @@ export function KnowledgeTagFilters({ const overlayRefs = useRef>({}) const [knowledgeBaseIdFromStore] = useSubBlockValue(blockId, 'knowledgeBaseId') - const knowledgeBaseIdValue = previewContextValues?.knowledgeBaseId ?? knowledgeBaseIdFromStore + const knowledgeBaseIdValue = previewContextValues + ? resolvePreviewContextValue(previewContextValues.knowledgeBaseId) + : knowledgeBaseIdFromStore const knowledgeBaseId = typeof knowledgeBaseIdValue === 'string' && knowledgeBaseIdValue.trim().length > 0 ? knowledgeBaseIdValue diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/mcp-dynamic-args/mcp-dynamic-args.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/mcp-dynamic-args/mcp-dynamic-args.tsx index 41527a5165..5271ecb33f 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/mcp-dynamic-args/mcp-dynamic-args.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/mcp-dynamic-args/mcp-dynamic-args.tsx @@ -6,6 +6,7 @@ import { cn } from '@/lib/core/utils/cn' import { LongInput } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/long-input/long-input' import { ShortInput } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/short-input/short-input' import { useSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-value' +import { resolvePreviewContextValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/utils' import type { SubBlockConfig } from '@/blocks/types' import { useMcpTools } from '@/hooks/mcp/use-mcp-tools' import { formatParameterLabel } from '@/tools/params' @@ -18,6 +19,7 @@ interface McpDynamicArgsProps { disabled?: boolean isPreview?: boolean previewValue?: any + previewContextValues?: Record } /** @@ -47,12 +49,19 @@ export function McpDynamicArgs({ disabled = false, isPreview = false, previewValue, + previewContextValues, }: McpDynamicArgsProps) { const params = useParams() const workspaceId = params.workspaceId as string const { mcpTools, isLoading } = useMcpTools(workspaceId) - const [selectedTool] = useSubBlockValue(blockId, 'tool') - const [cachedSchema] = useSubBlockValue(blockId, '_toolSchema') + const [toolFromStore] = useSubBlockValue(blockId, 'tool') + const selectedTool = previewContextValues + ? resolvePreviewContextValue(previewContextValues.tool) + : toolFromStore + const [schemaFromStore] = useSubBlockValue(blockId, '_toolSchema') + const cachedSchema = previewContextValues + ? resolvePreviewContextValue(previewContextValues._toolSchema) + : schemaFromStore const [toolArgs, setToolArgs] = useSubBlockValue(blockId, subBlockId) const selectedToolConfig = mcpTools.find((tool) => tool.id === selectedTool) diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/mcp-server-modal/mcp-tool-selector.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/mcp-server-modal/mcp-tool-selector.tsx index fa5fcd496c..ca4ff45b18 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/mcp-server-modal/mcp-tool-selector.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/mcp-server-modal/mcp-tool-selector.tsx @@ -4,6 +4,7 @@ import { useEffect, useMemo, useState } from 'react' import { useParams } from 'next/navigation' import { Combobox } from '@/components/emcn/components' import { useSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-value' +import { resolvePreviewContextValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/utils' import type { SubBlockConfig } from '@/blocks/types' import { useMcpTools } from '@/hooks/mcp/use-mcp-tools' @@ -13,6 +14,7 @@ interface McpToolSelectorProps { disabled?: boolean isPreview?: boolean previewValue?: string | null + previewContextValues?: Record } export function McpToolSelector({ @@ -21,6 +23,7 @@ export function McpToolSelector({ disabled = false, isPreview = false, previewValue, + previewContextValues, }: McpToolSelectorProps) { const params = useParams() const workspaceId = params.workspaceId as string @@ -31,7 +34,10 @@ export function McpToolSelector({ const [storeValue, setStoreValue] = useSubBlockValue(blockId, subBlock.id) const [, setSchemaCache] = useSubBlockValue(blockId, '_toolSchema') - const [serverValue] = useSubBlockValue(blockId, 'server') + const [serverFromStore] = useSubBlockValue(blockId, 'server') + const serverValue = previewContextValues + ? resolvePreviewContextValue(previewContextValues.server) + : serverFromStore const label = subBlock.placeholder || 'Select tool' diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/project-selector/project-selector-input.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/project-selector/project-selector-input.tsx index 9d5e353202..e5b7c5d930 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/project-selector/project-selector-input.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/project-selector/project-selector-input.tsx @@ -9,6 +9,7 @@ import { SelectorCombobox } from '@/app/workspace/[workspaceId]/w/[workflowId]/c import { useDependsOnGate } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-depends-on-gate' import { useForeignCredential } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-foreign-credential' import { useSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-value' +import { resolvePreviewContextValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/utils' import { getBlock } from '@/blocks/registry' import type { SubBlockConfig } from '@/blocks/types' import { resolveSelectorForSubBlock } from '@/hooks/selectors/resolution' @@ -55,14 +56,19 @@ export function ProjectSelectorInput({ return (workflowValues as Record>)[blockId] || {} }) - const connectedCredential = previewContextValues?.credential ?? blockValues.credential - const jiraDomain = previewContextValues?.domain ?? jiraDomainFromStore + const connectedCredential = previewContextValues + ? resolvePreviewContextValue(previewContextValues.credential) + : blockValues.credential + const jiraDomain = previewContextValues + ? resolvePreviewContextValue(previewContextValues.domain) + : jiraDomainFromStore const linearTeamId = useMemo( () => - previewContextValues?.teamId ?? - resolveDependencyValue('teamId', blockValues, canonicalIndex, canonicalModeOverrides), - [previewContextValues?.teamId, blockValues, canonicalIndex, canonicalModeOverrides] + previewContextValues + ? resolvePreviewContextValue(previewContextValues.teamId) + : resolveDependencyValue('teamId', blockValues, canonicalIndex, canonicalModeOverrides), + [previewContextValues, blockValues, canonicalIndex, canonicalModeOverrides] ) const serviceId = subBlock.serviceId || '' diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/sheet-selector/sheet-selector-input.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/sheet-selector/sheet-selector-input.tsx index cd2a5adf5b..bfb9dbe4f6 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/sheet-selector/sheet-selector-input.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/sheet-selector/sheet-selector-input.tsx @@ -8,6 +8,7 @@ import { buildCanonicalIndex, resolveDependencyValue } from '@/lib/workflows/sub import { SelectorCombobox } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/selector-combobox/selector-combobox' import { useDependsOnGate } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-depends-on-gate' import { useForeignCredential } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-foreign-credential' +import { resolvePreviewContextValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/utils' import { getBlock } from '@/blocks/registry' import type { SubBlockConfig } from '@/blocks/types' import { resolveSelectorForSubBlock, type SelectorResolution } from '@/hooks/selectors/resolution' @@ -66,9 +67,12 @@ export function SheetSelectorInput({ [blockValues, canonicalIndex, canonicalModeOverrides] ) - const connectedCredential = previewContextValues?.credential ?? connectedCredentialFromStore + const connectedCredential = previewContextValues + ? resolvePreviewContextValue(previewContextValues.credential) + : connectedCredentialFromStore const spreadsheetId = previewContextValues - ? (previewContextValues.spreadsheetId ?? previewContextValues.manualSpreadsheetId) + ? (resolvePreviewContextValue(previewContextValues.spreadsheetId) ?? + resolvePreviewContextValue(previewContextValues.manualSpreadsheetId)) : spreadsheetIdFromStore const normalizedCredentialId = diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/slack-selector/slack-selector-input.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/slack-selector/slack-selector-input.tsx index 9a7e4ebfa2..b99c26bff2 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/slack-selector/slack-selector-input.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/slack-selector/slack-selector-input.tsx @@ -8,6 +8,7 @@ import { SelectorCombobox } from '@/app/workspace/[workspaceId]/w/[workflowId]/c import { useDependsOnGate } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-depends-on-gate' import { useForeignCredential } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-foreign-credential' import { useSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-value' +import { resolvePreviewContextValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/utils' import type { SubBlockConfig } from '@/blocks/types' import type { SelectorContext, SelectorKey } from '@/hooks/selectors/types' @@ -58,9 +59,15 @@ export function SlackSelectorInput({ const [botToken] = useSubBlockValue(blockId, 'botToken') const [connectedCredential] = useSubBlockValue(blockId, 'credential') - const effectiveAuthMethod = previewContextValues?.authMethod ?? authMethod - const effectiveBotToken = previewContextValues?.botToken ?? botToken - const effectiveCredential = previewContextValues?.credential ?? connectedCredential + const effectiveAuthMethod = previewContextValues + ? resolvePreviewContextValue(previewContextValues.authMethod) + : authMethod + const effectiveBotToken = previewContextValues + ? resolvePreviewContextValue(previewContextValues.botToken) + : botToken + const effectiveCredential = previewContextValues + ? resolvePreviewContextValue(previewContextValues.credential) + : connectedCredential const [_selectedValue, setSelectedValue] = useState(null) const serviceId = subBlock.serviceId || '' diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/tool-input/tool-input.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/tool-input/tool-input.tsx index cd2f342a33..8f03f4b2e5 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/tool-input/tool-input.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/tool-input/tool-input.tsx @@ -332,6 +332,7 @@ function FolderSelectorSyncWrapper({ dependsOn: uiComponent.dependsOn, }} disabled={disabled} + previewContextValues={previewContextValues} /> ) diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/sub-block.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/sub-block.tsx index cd1e9168e8..308408c063 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/sub-block.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/sub-block.tsx @@ -785,6 +785,7 @@ function SubBlockComponent({ disabled={isDisabled} isPreview={isPreview} previewValue={previewValue} + previewContextValues={isPreview ? subBlockValues : undefined} /> ) @@ -820,6 +821,7 @@ function SubBlockComponent({ disabled={isDisabled} isPreview={isPreview} previewValue={previewValue} + previewContextValues={isPreview ? subBlockValues : undefined} /> ) @@ -831,6 +833,7 @@ function SubBlockComponent({ disabled={isDisabled} isPreview={isPreview} previewValue={previewValue} + previewContextValues={isPreview ? subBlockValues : undefined} /> ) @@ -853,6 +856,7 @@ function SubBlockComponent({ disabled={isDisabled} isPreview={isPreview} previewValue={previewValue as any} + previewContextValues={isPreview ? subBlockValues : undefined} /> ) @@ -864,6 +868,7 @@ function SubBlockComponent({ disabled={isDisabled} isPreview={isPreview} previewValue={previewValue as any} + previewContextValues={isPreview ? subBlockValues : undefined} /> ) @@ -875,6 +880,7 @@ function SubBlockComponent({ disabled={isDisabled} isPreview={isPreview} previewValue={previewValue as any} + previewContextValues={isPreview ? subBlockValues : undefined} /> ) @@ -899,6 +905,7 @@ function SubBlockComponent({ isPreview={isPreview} previewValue={previewValue as any} disabled={isDisabled} + previewContextValues={isPreview ? subBlockValues : undefined} /> ) @@ -934,6 +941,7 @@ function SubBlockComponent({ disabled={isDisabled} isPreview={isPreview} previewValue={previewValue} + previewContextValues={isPreview ? subBlockValues : undefined} /> ) @@ -967,6 +975,7 @@ function SubBlockComponent({ disabled={isDisabled} isPreview={isPreview} previewValue={previewValue as any} + previewContextValues={isPreview ? subBlockValues : undefined} /> ) @@ -978,6 +987,7 @@ function SubBlockComponent({ disabled={isDisabled} isPreview={isPreview} previewValue={previewValue} + previewContextValues={isPreview ? subBlockValues : undefined} /> ) diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/utils.ts b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/utils.ts new file mode 100644 index 0000000000..1812992214 --- /dev/null +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/utils.ts @@ -0,0 +1,18 @@ +/** + * Extracts the raw value from a preview context entry. + * + * @remarks + * In the sub-block preview context, values are wrapped as `{ value: T }` objects + * (the full sub-block state). In the tool-input preview context, values are already + * raw. This function normalizes both cases to return the underlying value. + * + * @param raw - The preview context entry, which may be a raw value or a `{ value: T }` wrapper + * @returns The unwrapped value, or `null` if the input is nullish + */ +export function resolvePreviewContextValue(raw: unknown): unknown { + if (raw === null || raw === undefined) return null + if (typeof raw === 'object' && !Array.isArray(raw) && 'value' in raw) { + return (raw as Record).value ?? null + } + return raw +} diff --git a/apps/sim/app/workspace/[workspaceId]/w/components/preview/components/preview-editor/preview-editor.tsx b/apps/sim/app/workspace/[workspaceId]/w/components/preview/components/preview-editor/preview-editor.tsx index 90831de455..bfc86ec20d 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/components/preview/components/preview-editor/preview-editor.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/components/preview/components/preview-editor/preview-editor.tsx @@ -784,8 +784,12 @@ function PreviewEditorContent({ ? childWorkflowSnapshotState : childWorkflowState const resolvedIsLoadingChildWorkflow = isExecutionMode ? false : isLoadingChildWorkflow + const isBlockNotExecuted = isExecutionMode && !executionData const isMissingChildWorkflow = - Boolean(childWorkflowId) && !resolvedIsLoadingChildWorkflow && !resolvedChildWorkflowState + Boolean(childWorkflowId) && + !isBlockNotExecuted && + !resolvedIsLoadingChildWorkflow && + !resolvedChildWorkflowState /** Drills down into the child workflow or opens it in a new tab */ const handleExpandChildWorkflow = useCallback(() => { @@ -1192,7 +1196,7 @@ function PreviewEditorContent({
{/* Not Executed Banner - shown when in execution mode but block wasn't executed */} - {isExecutionMode && !executionData && ( + {isBlockNotExecuted && (
@@ -1419,9 +1423,11 @@ function PreviewEditorContent({ ) : (
- {isMissingChildWorkflow - ? DELETED_WORKFLOW_LABEL - : 'Unable to load preview'} + {isBlockNotExecuted + ? 'Not Executed' + : isMissingChildWorkflow + ? DELETED_WORKFLOW_LABEL + : 'Unable to load preview'}
)} diff --git a/apps/sim/lib/logs/execution/snapshot/service.ts b/apps/sim/lib/logs/execution/snapshot/service.ts index cad4c259c6..856c3a1851 100644 --- a/apps/sim/lib/logs/execution/snapshot/service.ts +++ b/apps/sim/lib/logs/execution/snapshot/service.ts @@ -33,11 +33,25 @@ export class SnapshotService implements ISnapshotService { const existingSnapshot = await this.getSnapshotByHash(workflowId, stateHash) if (existingSnapshot) { + let refreshedState: WorkflowState = existingSnapshot.stateData + try { + await db + .update(workflowExecutionSnapshots) + .set({ stateData: state }) + .where(eq(workflowExecutionSnapshots.id, existingSnapshot.id)) + refreshedState = state + } catch (error) { + logger.warn( + `Failed to refresh snapshot stateData for ${existingSnapshot.id}, continuing with existing data`, + error + ) + } + logger.info( `Reusing existing snapshot for workflow ${workflowId} (hash: ${stateHash.slice(0, 12)}...)` ) return { - snapshot: existingSnapshot, + snapshot: { ...existingSnapshot, stateData: refreshedState }, isNew: false, } }