Skip to content

Commit 5988d0e

Browse files
fix(ring): duplicate should clear original block (#2916)
* fix(ring): duplicate should clear original block * rename correctly
1 parent 145db9d commit 5988d0e

File tree

14 files changed

+76
-53
lines changed

14 files changed

+76
-53
lines changed

apps/sim/app/api/form/[identifier]/route.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { preprocessExecution } from '@/lib/execution/preprocessing'
1111
import { LoggingSession } from '@/lib/logs/execution/logging-session'
1212
import { normalizeInputFormatValue } from '@/lib/workflows/input-format'
1313
import { createStreamingResponse } from '@/lib/workflows/streaming/streaming'
14-
import { isValidStartBlockType } from '@/lib/workflows/triggers/start-block-types'
14+
import { isInputDefinitionTrigger } from '@/lib/workflows/triggers/input-definition-triggers'
1515
import { setFormAuthCookie, validateFormAuth } from '@/app/api/form/utils'
1616
import { createErrorResponse, createSuccessResponse } from '@/app/api/workflows/utils'
1717

@@ -36,7 +36,7 @@ async function getWorkflowInputSchema(workflowId: string): Promise<any[]> {
3636
.from(workflowBlocks)
3737
.where(eq(workflowBlocks.workflowId, workflowId))
3838

39-
const startBlock = blocks.find((block) => isValidStartBlockType(block.type))
39+
const startBlock = blocks.find((block) => isInputDefinitionTrigger(block.type))
4040

4141
if (!startBlock) {
4242
return []

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/action-bar/action-bar.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { memo, useCallback } from 'react'
22
import { ArrowLeftRight, ArrowUpDown, Circle, CircleOff, LogOut } from 'lucide-react'
33
import { Button, Copy, Tooltip, Trash2 } from '@/components/emcn'
44
import { cn } from '@/lib/core/utils/cn'
5-
import { isValidStartBlockType } from '@/lib/workflows/triggers/start-block-types'
5+
import { isInputDefinitionTrigger } from '@/lib/workflows/triggers/input-definition-triggers'
66
import { useUserPermissionsContext } from '@/app/workspace/[workspaceId]/providers/workspace-permissions-provider'
77
import { useCollaborativeWorkflow } from '@/hooks/use-collaborative-workflow'
88
import { useWorkflowRegistry } from '@/stores/workflows/registry/store'
@@ -90,7 +90,7 @@ export const ActionBar = memo(
9090

9191
const userPermissions = useUserPermissionsContext()
9292

93-
const isStartBlock = isValidStartBlockType(blockType)
93+
const isStartBlock = isInputDefinitionTrigger(blockType)
9494
const isResponseBlock = blockType === 'response'
9595
const isNoteBlock = blockType === 'note'
9696
const isSubflowBlock = blockType === 'loop' || blockType === 'parallel'

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/block-menu/block-menu.tsx

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
PopoverDivider,
99
PopoverItem,
1010
} from '@/components/emcn'
11-
import { isValidStartBlockType } from '@/lib/workflows/triggers/start-block-types'
11+
import { TriggerUtils } from '@/lib/workflows/triggers/triggers'
1212

1313
/**
1414
* Block information for context menu actions
@@ -74,12 +74,16 @@ export function BlockMenu({
7474
const allEnabled = selectedBlocks.every((b) => b.enabled)
7575
const allDisabled = selectedBlocks.every((b) => !b.enabled)
7676

77-
const hasStarterBlock = selectedBlocks.some((b) => isValidStartBlockType(b.type))
77+
const hasSingletonBlock = selectedBlocks.some(
78+
(b) =>
79+
TriggerUtils.requiresSingleInstance(b.type) || TriggerUtils.isSingleInstanceBlockType(b.type)
80+
)
81+
const hasTriggerBlock = selectedBlocks.some((b) => TriggerUtils.isTriggerBlock(b))
7882
const allNoteBlocks = selectedBlocks.every((b) => b.type === 'note')
7983
const isSubflow =
8084
isSingleBlock && (selectedBlocks[0]?.type === 'loop' || selectedBlocks[0]?.type === 'parallel')
8185

82-
const canRemoveFromSubflow = showRemoveFromSubflow && !hasStarterBlock
86+
const canRemoveFromSubflow = showRemoveFromSubflow && !hasTriggerBlock
8387

8488
const getToggleEnabledLabel = () => {
8589
if (allEnabled) return 'Disable'
@@ -127,7 +131,7 @@ export function BlockMenu({
127131
<span>Paste</span>
128132
<span className='ml-auto opacity-70 group-hover:opacity-100'>⌘V</span>
129133
</PopoverItem>
130-
{!hasStarterBlock && (
134+
{!hasSingletonBlock && (
131135
<PopoverItem
132136
disabled={disableEdit}
133137
onClick={() => {

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/deploy/components/deploy-modal/components/form/form.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import { Skeleton } from '@/components/ui'
1717
import { isDev } from '@/lib/core/config/feature-flags'
1818
import { cn } from '@/lib/core/utils/cn'
1919
import { getBaseUrl, getEmailDomain } from '@/lib/core/utils/urls'
20-
import { isValidStartBlockType } from '@/lib/workflows/triggers/start-block-types'
20+
import { isInputDefinitionTrigger } from '@/lib/workflows/triggers/input-definition-triggers'
2121
import {
2222
type FieldConfig,
2323
useCreateForm,
@@ -147,7 +147,7 @@ export function FormDeploy({
147147

148148
useEffect(() => {
149149
const blocks = Object.values(useWorkflowStore.getState().blocks)
150-
const startBlock = blocks.find((b) => isValidStartBlockType(b.type))
150+
const startBlock = blocks.find((b) => isInputDefinitionTrigger(b.type))
151151

152152
if (startBlock) {
153153
const inputFormat = useSubBlockStore.getState().getValue(startBlock.id, 'inputFormat')

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/deploy/components/deploy-modal/components/general/components/api-info-modal.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {
1414
Textarea,
1515
} from '@/components/emcn'
1616
import { normalizeInputFormatValue } from '@/lib/workflows/input-format'
17-
import { isValidStartBlockType } from '@/lib/workflows/triggers/start-block-types'
17+
import { isInputDefinitionTrigger } from '@/lib/workflows/triggers/input-definition-triggers'
1818
import type { InputFormatField } from '@/lib/workflows/types'
1919
import { useWorkflowRegistry } from '@/stores/workflows/registry/store'
2020
import { useSubBlockStore } from '@/stores/workflows/subblock/store'
@@ -52,7 +52,7 @@ export function ApiInfoModal({ open, onOpenChange, workflowId }: ApiInfoModalPro
5252
for (const [blockId, block] of Object.entries(blocks)) {
5353
if (!block || typeof block !== 'object') continue
5454
const blockType = (block as { type?: string }).type
55-
if (blockType && isValidStartBlockType(blockType)) {
55+
if (blockType && isInputDefinitionTrigger(blockType)) {
5656
return blockId
5757
}
5858
}

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/deploy/components/deploy-modal/components/mcp/mcp.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import {
1515
import { Skeleton } from '@/components/ui'
1616
import { generateToolInputSchema, sanitizeToolName } from '@/lib/mcp/workflow-tool-schema'
1717
import { normalizeInputFormatValue } from '@/lib/workflows/input-format'
18-
import { isValidStartBlockType } from '@/lib/workflows/triggers/start-block-types'
18+
import { isInputDefinitionTrigger } from '@/lib/workflows/triggers/input-definition-triggers'
1919
import type { InputFormatField } from '@/lib/workflows/types'
2020
import {
2121
useAddWorkflowMcpTool,
@@ -107,7 +107,7 @@ export function McpDeploy({
107107
for (const [blockId, block] of Object.entries(blocks)) {
108108
if (!block || typeof block !== 'object') continue
109109
const blockType = (block as { type?: string }).type
110-
if (blockType && isValidStartBlockType(blockType)) {
110+
if (blockType && isInputDefinitionTrigger(blockType)) {
111111
return blockId
112112
}
113113
}

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-accessible-reference-prefixes.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { useMemo } from 'react'
22
import { useShallow } from 'zustand/react/shallow'
33
import { BlockPathCalculator } from '@/lib/workflows/blocks/block-path-calculator'
44
import { SYSTEM_REFERENCE_PREFIXES } from '@/lib/workflows/sanitization/references'
5-
import { isValidStartBlockType } from '@/lib/workflows/triggers/start-block-types'
5+
import { isInputDefinitionTrigger } from '@/lib/workflows/triggers/input-definition-triggers'
66
import { normalizeName } from '@/executor/constants'
77
import { useWorkflowStore } from '@/stores/workflows/workflow/store'
88
import type { Loop, Parallel } from '@/stores/workflows/workflow/types'
@@ -27,7 +27,7 @@ export function useAccessibleReferencePrefixes(blockId?: string | null): Set<str
2727
const accessibleIds = new Set<string>(ancestorIds)
2828
accessibleIds.add(blockId)
2929

30-
const starterBlock = Object.values(blocks).find((block) => isValidStartBlockType(block.type))
30+
const starterBlock = Object.values(blocks).find((block) => isInputDefinitionTrigger(block.type))
3131
if (starterBlock && ancestorIds.includes(starterBlock.id)) {
3232
accessibleIds.add(starterBlock.id)
3333
}

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/workflow.tsx

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,21 @@ function mapEdgesByNode(edges: Edge[], nodeIds: Set<string>): Map<string, Edge[]
180180
return result
181181
}
182182

183+
/**
184+
* Syncs the panel editor with the current selection state.
185+
* Shows block details when exactly one block is selected, clears otherwise.
186+
*/
187+
function syncPanelWithSelection(selectedIds: string[]) {
188+
const { currentBlockId, clearCurrentBlock, setCurrentBlockId } = usePanelEditorStore.getState()
189+
if (selectedIds.length === 1 && selectedIds[0] !== currentBlockId) {
190+
setCurrentBlockId(selectedIds[0])
191+
} else if (selectedIds.length === 0 && currentBlockId) {
192+
clearCurrentBlock()
193+
} else if (selectedIds.length > 1 && currentBlockId) {
194+
clearCurrentBlock()
195+
}
196+
}
197+
183198
/** Custom node types for ReactFlow. */
184199
const nodeTypes: NodeTypes = {
185200
workflowBlock: WorkflowBlock,
@@ -2075,7 +2090,10 @@ const WorkflowContent = React.memo(() => {
20752090
...node,
20762091
selected: pendingSet.has(node.id),
20772092
}))
2078-
setDisplayNodes(resolveParentChildSelectionConflicts(withSelection, blocks))
2093+
const resolved = resolveParentChildSelectionConflicts(withSelection, blocks)
2094+
setDisplayNodes(resolved)
2095+
const selectedIds = resolved.filter((node) => node.selected).map((node) => node.id)
2096+
syncPanelWithSelection(selectedIds)
20792097
return
20802098
}
20812099

@@ -2175,13 +2193,7 @@ const WorkflowContent = React.memo(() => {
21752193
})
21762194
const selectedIds = selectedIdsRef.current as string[] | null
21772195
if (selectedIds !== null) {
2178-
const { currentBlockId, clearCurrentBlock, setCurrentBlockId } =
2179-
usePanelEditorStore.getState()
2180-
if (selectedIds.length === 1 && selectedIds[0] !== currentBlockId) {
2181-
setCurrentBlockId(selectedIds[0])
2182-
} else if (selectedIds.length === 0 && currentBlockId) {
2183-
clearCurrentBlock()
2184-
}
2196+
syncPanelWithSelection(selectedIds)
21852197
}
21862198
},
21872199
[blocks]

apps/sim/lib/copilot/tools/client/workflow/get-block-upstream-references.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import {
1717
type GetBlockUpstreamReferencesResultType,
1818
} from '@/lib/copilot/tools/shared/schemas'
1919
import { BlockPathCalculator } from '@/lib/workflows/blocks/block-path-calculator'
20-
import { isValidStartBlockType } from '@/lib/workflows/triggers/start-block-types'
20+
import { isInputDefinitionTrigger } from '@/lib/workflows/triggers/input-definition-triggers'
2121
import { useWorkflowRegistry } from '@/stores/workflows/registry/store'
2222
import { useWorkflowStore } from '@/stores/workflows/workflow/store'
2323
import type { Loop, Parallel } from '@/stores/workflows/workflow/types'
@@ -141,7 +141,7 @@ export class GetBlockUpstreamReferencesClientTool extends BaseClientTool {
141141
const accessibleIds = new Set<string>(ancestorIds)
142142
accessibleIds.add(blockId)
143143

144-
const starterBlock = Object.values(blocks).find((b) => isValidStartBlockType(b.type))
144+
const starterBlock = Object.values(blocks).find((b) => isInputDefinitionTrigger(b.type))
145145
if (starterBlock && ancestorIds.includes(starterBlock.id)) {
146146
accessibleIds.add(starterBlock.id)
147147
}

apps/sim/lib/mcp/workflow-tool-schema.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { z } from 'zod'
22
import { normalizeInputFormatValue } from '@/lib/workflows/input-format'
3-
import { isValidStartBlockType } from '@/lib/workflows/triggers/start-block-types'
3+
import { isInputDefinitionTrigger } from '@/lib/workflows/triggers/input-definition-triggers'
44
import type { InputFormatField } from '@/lib/workflows/types'
55
import type { McpToolSchema } from './types'
66

@@ -217,7 +217,7 @@ export function extractInputFormatFromBlocks(
217217
const blockObj = block as Record<string, unknown>
218218
const blockType = blockObj.type as string
219219

220-
if (isValidStartBlockType(blockType)) {
220+
if (isInputDefinitionTrigger(blockType)) {
221221
// Try to get inputFormat from subBlocks.inputFormat.value
222222
const subBlocks = blockObj.subBlocks as Record<string, { value?: unknown }> | undefined
223223
const subBlockValue = subBlocks?.inputFormat?.value

0 commit comments

Comments
 (0)