From 7013b7f7776749a37207e3e62fb3b5795abe11e2 Mon Sep 17 00:00:00 2001 From: waleed Date: Wed, 21 Jan 2026 11:35:45 -0800 Subject: [PATCH 1/2] fix(action-bar): duplicate subflows with children --- .../components/action-bar/action-bar.tsx | 36 ++++++++----------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/action-bar/action-bar.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/action-bar/action-bar.tsx index e2fa63da7c..ad6527df55 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/action-bar/action-bar.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/action-bar/action-bar.tsx @@ -6,8 +6,6 @@ import { isInputDefinitionTrigger } from '@/lib/workflows/triggers/input-definit import { useUserPermissionsContext } from '@/app/workspace/[workspaceId]/providers/workspace-permissions-provider' import { useCollaborativeWorkflow } from '@/hooks/use-collaborative-workflow' import { useWorkflowRegistry } from '@/stores/workflows/registry/store' -import { useSubBlockStore } from '@/stores/workflows/subblock/store' -import { getUniqueBlockName, prepareDuplicateBlockState } from '@/stores/workflows/utils' import { useWorkflowStore } from '@/stores/workflows/workflow/store' const DEFAULT_DUPLICATE_OFFSET = { x: 50, y: 50 } @@ -48,29 +46,25 @@ export const ActionBar = memo( collaborativeBatchToggleBlockEnabled, collaborativeBatchToggleBlockHandles, } = useCollaborativeWorkflow() - const { activeWorkflowId, setPendingSelection } = useWorkflowRegistry() + const { setPendingSelection } = useWorkflowRegistry() const handleDuplicateBlock = useCallback(() => { - const blocks = useWorkflowStore.getState().blocks - const sourceBlock = blocks[blockId] - if (!sourceBlock) return + const { copyBlocks, preparePasteData } = useWorkflowRegistry.getState() + copyBlocks([blockId]) - const newId = crypto.randomUUID() - const newName = getUniqueBlockName(sourceBlock.name, blocks) - const subBlockValues = - useSubBlockStore.getState().workflowValues[activeWorkflowId || '']?.[blockId] || {} + const pasteData = preparePasteData(DEFAULT_DUPLICATE_OFFSET) + if (!pasteData) return - const { block, subBlockValues: filteredValues } = prepareDuplicateBlockState({ - sourceBlock, - newId, - newName, - positionOffset: DEFAULT_DUPLICATE_OFFSET, - subBlockValues, - }) - - setPendingSelection([newId]) - collaborativeBatchAddBlocks([block], [], {}, {}, { [newId]: filteredValues }) - }, [blockId, activeWorkflowId, collaborativeBatchAddBlocks, setPendingSelection]) + const blocks = Object.values(pasteData.blocks) + setPendingSelection(blocks.map((b) => b.id)) + collaborativeBatchAddBlocks( + blocks, + pasteData.edges, + pasteData.loops, + pasteData.parallels, + pasteData.subBlockValues + ) + }, [blockId, collaborativeBatchAddBlocks, setPendingSelection]) const { isEnabled, horizontalHandles, parentId, parentType } = useWorkflowStore( useCallback( From a3e2aeaba91110262330a55159c51695c4a1f77c Mon Sep 17 00:00:00 2001 From: waleed Date: Wed, 21 Jan 2026 14:47:38 -0800 Subject: [PATCH 2/2] fix(action-bar): add validateTriggerPaste for subflow duplicate --- .../components/action-bar/action-bar.tsx | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/action-bar/action-bar.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/action-bar/action-bar.tsx index ad6527df55..9f10058817 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/action-bar/action-bar.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/action-bar/action-bar.tsx @@ -4,7 +4,9 @@ import { Button, Copy, Tooltip, Trash2 } from '@/components/emcn' import { cn } from '@/lib/core/utils/cn' import { isInputDefinitionTrigger } from '@/lib/workflows/triggers/input-definition-triggers' import { useUserPermissionsContext } from '@/app/workspace/[workspaceId]/providers/workspace-permissions-provider' +import { validateTriggerPaste } from '@/app/workspace/[workspaceId]/w/[workflowId]/utils' import { useCollaborativeWorkflow } from '@/hooks/use-collaborative-workflow' +import { useNotificationStore } from '@/stores/notifications' import { useWorkflowRegistry } from '@/stores/workflows/registry/store' import { useWorkflowStore } from '@/stores/workflows/workflow/store' @@ -48,14 +50,27 @@ export const ActionBar = memo( } = useCollaborativeWorkflow() const { setPendingSelection } = useWorkflowRegistry() + const addNotification = useNotificationStore((s) => s.addNotification) + const handleDuplicateBlock = useCallback(() => { - const { copyBlocks, preparePasteData } = useWorkflowRegistry.getState() + const { copyBlocks, preparePasteData, activeWorkflowId } = useWorkflowRegistry.getState() + const existingBlocks = useWorkflowStore.getState().blocks copyBlocks([blockId]) const pasteData = preparePasteData(DEFAULT_DUPLICATE_OFFSET) if (!pasteData) return const blocks = Object.values(pasteData.blocks) + const validation = validateTriggerPaste(blocks, existingBlocks, 'duplicate') + if (!validation.isValid) { + addNotification({ + level: 'error', + message: validation.message!, + workflowId: activeWorkflowId || undefined, + }) + return + } + setPendingSelection(blocks.map((b) => b.id)) collaborativeBatchAddBlocks( blocks, @@ -64,7 +79,7 @@ export const ActionBar = memo( pasteData.parallels, pasteData.subBlockValues ) - }, [blockId, collaborativeBatchAddBlocks, setPendingSelection]) + }, [blockId, addNotification, collaborativeBatchAddBlocks, setPendingSelection]) const { isEnabled, horizontalHandles, parentId, parentType } = useWorkflowStore( useCallback(