@@ -60,7 +60,7 @@ import { usePanelEditorStore } from '@/stores/panel/editor/store'
6060import { useGeneralStore } from '@/stores/settings/general/store'
6161import { useWorkflowDiffStore } from '@/stores/workflow-diff/store'
6262import { useWorkflowRegistry } from '@/stores/workflows/registry/store'
63- import { getUniqueBlockName } from '@/stores/workflows/utils'
63+ import { getUniqueBlockName , prepareBlockState } from '@/stores/workflows/utils'
6464import { useWorkflowStore } from '@/stores/workflows/workflow/store'
6565
6666/** Lazy-loaded components for non-critical UI that can load after initial render */
@@ -343,13 +343,12 @@ const WorkflowContent = React.memo(() => {
343343 } , [ userPermissions , currentWorkflow . isSnapshotView ] )
344344
345345 const {
346- collaborativeAddBlock : addBlock ,
347346 collaborativeAddEdge : addEdge ,
348- collaborativeRemoveBlock : removeBlock ,
349347 collaborativeRemoveEdge : removeEdge ,
350348 collaborativeBatchUpdatePositions,
351349 collaborativeUpdateParentId : updateParentId ,
352- collaborativePasteBlocks,
350+ collaborativeBatchAddBlocks,
351+ collaborativeBatchRemoveBlocks,
353352 undo,
354353 redo,
355354 } = useCollaborativeWorkflow ( )
@@ -361,6 +360,39 @@ const WorkflowContent = React.memo(() => {
361360 [ collaborativeBatchUpdatePositions ]
362361 )
363362
363+ const addBlock = useCallback (
364+ (
365+ id : string ,
366+ type : string ,
367+ name : string ,
368+ position : { x : number ; y : number } ,
369+ data ?: Record < string , unknown > ,
370+ parentId ?: string ,
371+ extent ?: 'parent' ,
372+ autoConnectEdge ?: Edge ,
373+ triggerMode ?: boolean
374+ ) => {
375+ const blockData : Record < string , unknown > = { ...( data || { } ) }
376+ if ( parentId ) blockData . parentId = parentId
377+ if ( extent ) blockData . extent = extent
378+
379+ const block = prepareBlockState ( {
380+ id,
381+ type,
382+ name,
383+ position,
384+ data : blockData ,
385+ parentId,
386+ extent,
387+ triggerMode,
388+ } )
389+
390+ collaborativeBatchAddBlocks ( [ block ] , autoConnectEdge ? [ autoConnectEdge ] : [ ] , { } , { } , { } )
391+ usePanelEditorStore . getState ( ) . setCurrentBlockId ( id )
392+ } ,
393+ [ collaborativeBatchAddBlocks ]
394+ )
395+
364396 const { activeBlockIds, pendingBlocks, isDebugging } = useExecutionStore (
365397 useShallow ( ( state ) => ( {
366398 activeBlockIds : state . activeBlockIds ,
@@ -515,13 +547,43 @@ const WorkflowContent = React.memo(() => {
515547 if ( selectedNodes . length > 0 ) {
516548 event . preventDefault ( )
517549 copyBlocks ( selectedNodes . map ( ( node ) => node . id ) )
550+ } else {
551+ const currentBlockId = usePanelEditorStore . getState ( ) . currentBlockId
552+ if ( currentBlockId && blocks [ currentBlockId ] ) {
553+ event . preventDefault ( )
554+ copyBlocks ( [ currentBlockId ] )
555+ }
518556 }
519557 } else if ( ( event . ctrlKey || event . metaKey ) && event . key === 'v' ) {
520558 if ( effectivePermissions . canEdit && hasClipboard ( ) ) {
521559 event . preventDefault ( )
522560 const pasteData = preparePasteData ( )
523561 if ( pasteData ) {
524- collaborativePasteBlocks ( pasteData )
562+ const pastedBlocks = Object . values ( pasteData . blocks )
563+ const hasTriggerInPaste = pastedBlocks . some ( ( block ) =>
564+ TriggerUtils . isAnyTriggerType ( block . type )
565+ )
566+ if ( hasTriggerInPaste ) {
567+ const existingTrigger = Object . values ( blocks ) . find ( ( block ) =>
568+ TriggerUtils . isAnyTriggerType ( block . type )
569+ )
570+ if ( existingTrigger ) {
571+ addNotification ( {
572+ level : 'error' ,
573+ message :
574+ 'A workflow can only have one trigger block. Please remove the existing one before pasting.' ,
575+ workflowId : activeWorkflowId || undefined ,
576+ } )
577+ return
578+ }
579+ }
580+ collaborativeBatchAddBlocks (
581+ pastedBlocks ,
582+ pasteData . edges ,
583+ pasteData . loops ,
584+ pasteData . parallels ,
585+ pasteData . subBlockValues
586+ )
525587 }
526588 }
527589 }
@@ -540,9 +602,12 @@ const WorkflowContent = React.memo(() => {
540602 getNodes ,
541603 copyBlocks ,
542604 preparePasteData ,
543- collaborativePasteBlocks ,
605+ collaborativeBatchAddBlocks ,
544606 hasClipboard ,
545607 effectivePermissions . canEdit ,
608+ blocks ,
609+ addNotification ,
610+ activeWorkflowId ,
546611 ] )
547612
548613 /**
@@ -2399,13 +2464,19 @@ const WorkflowContent = React.memo(() => {
23992464 }
24002465
24012466 event . preventDefault ( )
2402- const primaryNode = selectedNodes [ 0 ]
2403- removeBlock ( primaryNode . id )
2467+ const selectedIds = selectedNodes . map ( ( node ) => node . id )
2468+ collaborativeBatchRemoveBlocks ( selectedIds )
24042469 }
24052470
24062471 window . addEventListener ( 'keydown' , handleKeyDown )
24072472 return ( ) => window . removeEventListener ( 'keydown' , handleKeyDown )
2408- } , [ selectedEdgeInfo , removeEdge , getNodes , removeBlock , effectivePermissions . canEdit ] )
2473+ } , [
2474+ selectedEdgeInfo ,
2475+ removeEdge ,
2476+ getNodes ,
2477+ collaborativeBatchRemoveBlocks ,
2478+ effectivePermissions . canEdit ,
2479+ ] )
24092480
24102481 return (
24112482 < div className = 'flex h-full w-full flex-col overflow-hidden bg-[var(--bg)]' >
0 commit comments