From b6d2dabc67be62aee85f736096935beb0d303aae Mon Sep 17 00:00:00 2001 From: waleed Date: Tue, 7 Oct 2025 18:43:57 -0700 Subject: [PATCH] fix(curl-example): fixed curl example in deploy modal to reflect selected option --- .../components/deploy-form/deploy-form.tsx | 6 +- .../example-command/example-command.tsx | 61 ++++++++++--------- .../output-select/output-select.tsx | 53 ++++++++++------ .../components/api-keys/api-keys.tsx | 6 +- 4 files changed, 72 insertions(+), 54 deletions(-) diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/deploy-modal/components/deploy-form/deploy-form.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/deploy-modal/components/deploy-form/deploy-form.tsx index 34c2c70ce33..99718815454 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/deploy-modal/components/deploy-form/deploy-form.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/deploy-modal/components/deploy-form/deploy-form.tsx @@ -413,7 +413,7 @@ export function DeployForm({ setKeyType('personal') if (createError) setCreateError(null) }} - className='h-8' + className='h-8 data-[variant=outline]:border-border data-[variant=outline]:bg-background data-[variant=outline]:text-foreground data-[variant=outline]:hover:bg-muted dark:data-[variant=outline]:border-border dark:data-[variant=outline]:bg-background dark:data-[variant=outline]:text-foreground dark:data-[variant=outline]:hover:bg-muted/80' > Personal @@ -425,7 +425,7 @@ export function DeployForm({ setKeyType('workspace') if (createError) setCreateError(null) }} - className='h-8' + className='h-8 data-[variant=outline]:border-border data-[variant=outline]:bg-background data-[variant=outline]:text-foreground data-[variant=outline]:hover:bg-muted dark:data-[variant=outline]:border-border dark:data-[variant=outline]:bg-background dark:data-[variant=outline]:text-foreground dark:data-[variant=outline]:hover:bg-muted/80' > Workspace @@ -452,7 +452,7 @@ export function DeployForm({ { setNewKeyName('') setKeyType('personal') diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/deploy-modal/components/deployment-info/components/example-command/example-command.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/deploy-modal/components/deployment-info/components/example-command/example-command.tsx index 496fd0b9e95..ce3ee3d8fce 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/deploy-modal/components/deployment-info/components/example-command/example-command.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/deploy-modal/components/deployment-info/components/example-command/example-command.tsx @@ -42,24 +42,19 @@ export function ExampleCommand({ const [exampleType, setExampleType] = useState('execute') const isAsyncEnabled = isTruthy(getEnv('NEXT_PUBLIC_TRIGGER_DEV_ENABLED')) - // Format the curl command to use a placeholder for the API key const formatCurlCommand = (command: string, apiKey: string) => { if (!command.includes('curl')) return command - // Replace the actual API key with a placeholder in the command const sanitizedCommand = command.replace(apiKey, '$SIM_API_KEY') - // Format the command with line breaks for better readability return sanitizedCommand .replace(' -H ', '\n -H ') .replace(' -d ', '\n -d ') .replace(' http', '\n http') } - // Get the command with placeholder for copying (single line, no line breaks) const getActualCommand = () => { const displayCommand = getDisplayCommand() - // Remove line breaks and extra whitespace for copying return displayCommand .replace(/\\\n\s*/g, ' ') // Remove backslash + newline + whitespace .replace(/\n\s*/g, ' ') // Remove any remaining newlines + whitespace @@ -70,51 +65,56 @@ export function ExampleCommand({ const getDisplayCommand = () => { const baseEndpoint = endpoint.replace(apiKey, '$SIM_API_KEY') const inputExample = getInputFormatExample - ? getInputFormatExample(false) // No streaming for sync/async modes + ? getInputFormatExample(false) : ' -d \'{"input": "your data here"}\'' + const addStreamingParams = (dashD: string) => { + const match = dashD.match(/-d\s*'([\s\S]*)'/) + if (!match) { + const payload: Record = { stream: true } + if (selectedStreamingOutputs && selectedStreamingOutputs.length > 0) { + payload.selectedOutputs = selectedStreamingOutputs + } + return ` -d '${JSON.stringify(payload)}'` + } + try { + const payload = JSON.parse(match[1]) as Record + payload.stream = true + if (selectedStreamingOutputs && selectedStreamingOutputs.length > 0) { + payload.selectedOutputs = selectedStreamingOutputs + } + return ` -d '${JSON.stringify(payload)}'` + } catch { + return dashD + } + } + switch (mode) { case 'sync': - // For sync mode, use basic example without streaming if (getInputFormatExample) { const syncInputExample = getInputFormatExample(false) - return `curl -X POST \\ - -H "X-API-Key: $SIM_API_KEY" \\ - -H "Content-Type: application/json"${syncInputExample} \\ - ${baseEndpoint}` + return `curl -X POST \\\n -H "X-API-Key: $SIM_API_KEY" \\\n -H "Content-Type: application/json"${syncInputExample} \\\n ${baseEndpoint}` } return formatCurlCommand(command, apiKey) - case 'stream': - // For stream mode, include streaming params - if (getInputFormatExample) { - const streamInputExample = getInputFormatExample(true) - return `curl -X POST \\ - -H "X-API-Key: $SIM_API_KEY" \\ - -H "Content-Type: application/json"${streamInputExample} \\ - ${baseEndpoint}` - } - return formatCurlCommand(command, apiKey) + case 'stream': { + const streamDashD = addStreamingParams(inputExample) + return `curl -X POST \\\n -H "X-API-Key: $SIM_API_KEY" \\\n -H "Content-Type: application/json"${streamDashD} \\\n ${baseEndpoint}` + } case 'async': switch (exampleType) { case 'execute': - return `curl -X POST \\ - -H "X-API-Key: $SIM_API_KEY" \\ - -H "Content-Type: application/json" \\ - -H "X-Execution-Mode: async"${inputExample} \\ - ${baseEndpoint}` + return `curl -X POST \\\n -H "X-API-Key: $SIM_API_KEY" \\\n -H "Content-Type: application/json" \\\n -H "X-Execution-Mode: async"${inputExample} \\\n ${baseEndpoint}` case 'status': { const baseUrl = baseEndpoint.split('/api/workflows/')[0] - return `curl -H "X-API-Key: $SIM_API_KEY" \\ - ${baseUrl}/api/jobs/JOB_ID_FROM_EXECUTION` + return `curl -H "X-API-Key: $SIM_API_KEY" \\\n ${baseUrl}/api/jobs/JOB_ID_FROM_EXECUTION` } case 'rate-limits': { const baseUrlForRateLimit = baseEndpoint.split('/api/workflows/')[0] - return `curl -H "X-API-Key: $SIM_API_KEY" \\ - ${baseUrlForRateLimit}/api/users/me/usage-limits` + return `curl -H "X-API-Key: $SIM_API_KEY" \\\n ${baseUrlForRateLimit}/api/users/me/usage-limits` } default: @@ -231,6 +231,7 @@ export function ExampleCommand({ selectedOutputs={selectedStreamingOutputs} onOutputSelect={onSelectedStreamingOutputsChange} placeholder='Select outputs for streaming' + valueMode='label' /> )} diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/chat/components/output-select/output-select.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/chat/components/output-select/output-select.tsx index 159bf561f38..2247e482eb8 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/chat/components/output-select/output-select.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/chat/components/output-select/output-select.tsx @@ -14,6 +14,7 @@ interface OutputSelectProps { onOutputSelect: (outputIds: string[]) => void disabled?: boolean placeholder?: string + valueMode?: 'id' | 'label' } export function OutputSelect({ @@ -22,6 +23,7 @@ export function OutputSelect({ onOutputSelect, disabled = false, placeholder = 'Select output sources', + valueMode = 'id', }: OutputSelectProps) { const [isOutputDropdownOpen, setIsOutputDropdownOpen] = useState(false) const dropdownRef = useRef(null) @@ -201,28 +203,31 @@ export function OutputSelect({ return outputs }, [workflowBlocks, workflowId, isShowingDiff, isDiffReady, diffWorkflow, blocks, subBlockValues]) + // Utility to check selected by id or label + const isSelectedValue = (o: { id: string; label: string }) => + selectedOutputs.includes(o.id) || selectedOutputs.includes(o.label) + // Get selected outputs display text const selectedOutputsDisplayText = useMemo(() => { if (!selectedOutputs || selectedOutputs.length === 0) { return placeholder } - // Ensure all selected outputs exist in the workflowOutputs array - const validOutputs = selectedOutputs.filter((id) => workflowOutputs.some((o) => o.id === id)) + // Ensure all selected outputs exist in the workflowOutputs array by id or label + const validOutputs = selectedOutputs.filter((val) => + workflowOutputs.some((o) => o.id === val || o.label === val) + ) if (validOutputs.length === 0) { return placeholder } if (validOutputs.length === 1) { - const output = workflowOutputs.find((o) => o.id === validOutputs[0]) + const output = workflowOutputs.find( + (o) => o.id === validOutputs[0] || o.label === validOutputs[0] + ) if (output) { - // Add defensive check for output.blockName - const blockNameText = - output.blockName && typeof output.blockName === 'string' - ? output.blockName.replace(/\s+/g, '').toLowerCase() - : `block-${output.blockId}` - return `${blockNameText}.${output.path}` + return output.label } return placeholder } @@ -234,10 +239,14 @@ export function OutputSelect({ const selectedOutputInfo = useMemo(() => { if (!selectedOutputs || selectedOutputs.length === 0) return null - const validOutputs = selectedOutputs.filter((id) => workflowOutputs.some((o) => o.id === id)) + const validOutputs = selectedOutputs.filter((val) => + workflowOutputs.some((o) => o.id === val || o.label === val) + ) if (validOutputs.length === 0) return null - const output = workflowOutputs.find((o) => o.id === validOutputs[0]) + const output = workflowOutputs.find( + (o) => o.id === validOutputs[0] || o.label === validOutputs[0] + ) if (!output) return null return { @@ -355,14 +364,19 @@ export function OutputSelect({ } let attachedScrollTargets: (HTMLElement | Window)[] = [] + let rafId: number | null = null if (isOutputDropdownOpen) { updatePosition() window.addEventListener('resize', updatePosition) - // Attach to all scrollable ancestors (including the modal's scroll container) attachedScrollTargets = getScrollableAncestors(dropdownRef.current) attachedScrollTargets.forEach((target) => target.addEventListener('scroll', updatePosition, { passive: true }) ) + const loop = () => { + updatePosition() + rafId = requestAnimationFrame(loop) + } + rafId = requestAnimationFrame(loop) } return () => { @@ -370,18 +384,21 @@ export function OutputSelect({ attachedScrollTargets.forEach((target) => target.removeEventListener('scroll', updatePosition) ) + if (rafId) cancelAnimationFrame(rafId) } }, [isOutputDropdownOpen]) // Handle output selection - toggle selection const handleOutputSelection = (value: string) => { + const emittedValue = + valueMode === 'label' ? value : workflowOutputs.find((o) => o.label === value)?.id || value let newSelectedOutputs: string[] - const index = selectedOutputs.indexOf(value) + const index = selectedOutputs.indexOf(emittedValue) if (index === -1) { - newSelectedOutputs = [...new Set([...selectedOutputs, value])] + newSelectedOutputs = [...new Set([...selectedOutputs, emittedValue])] } else { - newSelectedOutputs = selectedOutputs.filter((id) => id !== value) + newSelectedOutputs = selectedOutputs.filter((id) => id !== emittedValue) } onOutputSelect(newSelectedOutputs) @@ -434,7 +451,7 @@ export function OutputSelect({ ref={portalRef} style={{ position: 'fixed', - top: portalStyle.top, + top: portalStyle.top - 1, // overlap border by 1px to avoid visible gap left: portalStyle.left, width: portalStyle.width, zIndex: 2147483647, @@ -462,7 +479,7 @@ export function OutputSelect({ diff --git a/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/api-keys/api-keys.tsx b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/api-keys/api-keys.tsx index 60b34418059..38e076d9850 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/api-keys/api-keys.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/api-keys/api-keys.tsx @@ -510,7 +510,7 @@ export function ApiKeys({ onOpenChange, registerCloseHandler }: ApiKeysProps) { setKeyType('personal') if (createError) setCreateError(null) }} - className='h-8' + className='h-8 data-[variant=outline]:border-border data-[variant=outline]:bg-background data-[variant=outline]:text-foreground data-[variant=outline]:hover:bg-muted dark:data-[variant=outline]:border-border dark:data-[variant=outline]:bg-background dark:data-[variant=outline]:text-foreground dark:data-[variant=outline]:hover:bg-muted/80' > Personal @@ -522,7 +522,7 @@ export function ApiKeys({ onOpenChange, registerCloseHandler }: ApiKeysProps) { setKeyType('workspace') if (createError) setCreateError(null) }} - className='h-8' + className='h-8 data-[variant=outline]:border-border data-[variant=outline]:bg-background data-[variant=outline]:text-foreground data-[variant=outline]:hover:bg-muted dark:data-[variant=outline]:border-border dark:data-[variant=outline]:bg-background dark:data-[variant=outline]:text-foreground dark:data-[variant=outline]:hover:bg-muted/80' > Workspace @@ -549,7 +549,7 @@ export function ApiKeys({ onOpenChange, registerCloseHandler }: ApiKeysProps) { { setNewKeyName('') setKeyType('personal')