Skip to content

Commit 7bdf0e9

Browse files
authored
fix(curl-example): fixed curl example in deploy modal to reflect selected option (#1573)
1 parent 8e43774 commit 7bdf0e9

File tree

4 files changed

+72
-54
lines changed
  • apps/sim/app/workspace/[workspaceId]/w

4 files changed

+72
-54
lines changed

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ export function DeployForm({
413413
setKeyType('personal')
414414
if (createError) setCreateError(null)
415415
}}
416-
className='h-8'
416+
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'
417417
>
418418
Personal
419419
</Button>
@@ -425,7 +425,7 @@ export function DeployForm({
425425
setKeyType('workspace')
426426
if (createError) setCreateError(null)
427427
}}
428-
className='h-8'
428+
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'
429429
>
430430
Workspace
431431
</Button>
@@ -452,7 +452,7 @@ export function DeployForm({
452452

453453
<AlertDialogFooter className='flex'>
454454
<AlertDialogCancel
455-
className='h-9 w-full rounded-[8px]'
455+
className='h-9 w-full rounded-[8px] border-border bg-background text-foreground hover:bg-muted dark:border-border dark:bg-background dark:text-foreground dark:hover:bg-muted/80'
456456
onClick={() => {
457457
setNewKeyName('')
458458
setKeyType('personal')

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/deploy-modal/components/deployment-info/components/example-command/example-command.tsx

Lines changed: 31 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -42,24 +42,19 @@ export function ExampleCommand({
4242
const [exampleType, setExampleType] = useState<ExampleType>('execute')
4343
const isAsyncEnabled = isTruthy(getEnv('NEXT_PUBLIC_TRIGGER_DEV_ENABLED'))
4444

45-
// Format the curl command to use a placeholder for the API key
4645
const formatCurlCommand = (command: string, apiKey: string) => {
4746
if (!command.includes('curl')) return command
4847

49-
// Replace the actual API key with a placeholder in the command
5048
const sanitizedCommand = command.replace(apiKey, '$SIM_API_KEY')
5149

52-
// Format the command with line breaks for better readability
5350
return sanitizedCommand
5451
.replace(' -H ', '\n -H ')
5552
.replace(' -d ', '\n -d ')
5653
.replace(' http', '\n http')
5754
}
5855

59-
// Get the command with placeholder for copying (single line, no line breaks)
6056
const getActualCommand = () => {
6157
const displayCommand = getDisplayCommand()
62-
// Remove line breaks and extra whitespace for copying
6358
return displayCommand
6459
.replace(/\\\n\s*/g, ' ') // Remove backslash + newline + whitespace
6560
.replace(/\n\s*/g, ' ') // Remove any remaining newlines + whitespace
@@ -70,51 +65,56 @@ export function ExampleCommand({
7065
const getDisplayCommand = () => {
7166
const baseEndpoint = endpoint.replace(apiKey, '$SIM_API_KEY')
7267
const inputExample = getInputFormatExample
73-
? getInputFormatExample(false) // No streaming for sync/async modes
68+
? getInputFormatExample(false)
7469
: ' -d \'{"input": "your data here"}\''
7570

71+
const addStreamingParams = (dashD: string) => {
72+
const match = dashD.match(/-d\s*'([\s\S]*)'/)
73+
if (!match) {
74+
const payload: Record<string, any> = { stream: true }
75+
if (selectedStreamingOutputs && selectedStreamingOutputs.length > 0) {
76+
payload.selectedOutputs = selectedStreamingOutputs
77+
}
78+
return ` -d '${JSON.stringify(payload)}'`
79+
}
80+
try {
81+
const payload = JSON.parse(match[1]) as Record<string, any>
82+
payload.stream = true
83+
if (selectedStreamingOutputs && selectedStreamingOutputs.length > 0) {
84+
payload.selectedOutputs = selectedStreamingOutputs
85+
}
86+
return ` -d '${JSON.stringify(payload)}'`
87+
} catch {
88+
return dashD
89+
}
90+
}
91+
7692
switch (mode) {
7793
case 'sync':
78-
// For sync mode, use basic example without streaming
7994
if (getInputFormatExample) {
8095
const syncInputExample = getInputFormatExample(false)
81-
return `curl -X POST \\
82-
-H "X-API-Key: $SIM_API_KEY" \\
83-
-H "Content-Type: application/json"${syncInputExample} \\
84-
${baseEndpoint}`
96+
return `curl -X POST \\\n -H "X-API-Key: $SIM_API_KEY" \\\n -H "Content-Type: application/json"${syncInputExample} \\\n ${baseEndpoint}`
8597
}
8698
return formatCurlCommand(command, apiKey)
8799

88-
case 'stream':
89-
// For stream mode, include streaming params
90-
if (getInputFormatExample) {
91-
const streamInputExample = getInputFormatExample(true)
92-
return `curl -X POST \\
93-
-H "X-API-Key: $SIM_API_KEY" \\
94-
-H "Content-Type: application/json"${streamInputExample} \\
95-
${baseEndpoint}`
96-
}
97-
return formatCurlCommand(command, apiKey)
100+
case 'stream': {
101+
const streamDashD = addStreamingParams(inputExample)
102+
return `curl -X POST \\\n -H "X-API-Key: $SIM_API_KEY" \\\n -H "Content-Type: application/json"${streamDashD} \\\n ${baseEndpoint}`
103+
}
98104

99105
case 'async':
100106
switch (exampleType) {
101107
case 'execute':
102-
return `curl -X POST \\
103-
-H "X-API-Key: $SIM_API_KEY" \\
104-
-H "Content-Type: application/json" \\
105-
-H "X-Execution-Mode: async"${inputExample} \\
106-
${baseEndpoint}`
108+
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}`
107109

108110
case 'status': {
109111
const baseUrl = baseEndpoint.split('/api/workflows/')[0]
110-
return `curl -H "X-API-Key: $SIM_API_KEY" \\
111-
${baseUrl}/api/jobs/JOB_ID_FROM_EXECUTION`
112+
return `curl -H "X-API-Key: $SIM_API_KEY" \\\n ${baseUrl}/api/jobs/JOB_ID_FROM_EXECUTION`
112113
}
113114

114115
case 'rate-limits': {
115116
const baseUrlForRateLimit = baseEndpoint.split('/api/workflows/')[0]
116-
return `curl -H "X-API-Key: $SIM_API_KEY" \\
117-
${baseUrlForRateLimit}/api/users/me/usage-limits`
117+
return `curl -H "X-API-Key: $SIM_API_KEY" \\\n ${baseUrlForRateLimit}/api/users/me/usage-limits`
118118
}
119119

120120
default:
@@ -231,6 +231,7 @@ export function ExampleCommand({
231231
selectedOutputs={selectedStreamingOutputs}
232232
onOutputSelect={onSelectedStreamingOutputsChange}
233233
placeholder='Select outputs for streaming'
234+
valueMode='label'
234235
/>
235236
</div>
236237
)}

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/chat/components/output-select/output-select.tsx

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ interface OutputSelectProps {
1414
onOutputSelect: (outputIds: string[]) => void
1515
disabled?: boolean
1616
placeholder?: string
17+
valueMode?: 'id' | 'label'
1718
}
1819

1920
export function OutputSelect({
@@ -22,6 +23,7 @@ export function OutputSelect({
2223
onOutputSelect,
2324
disabled = false,
2425
placeholder = 'Select output sources',
26+
valueMode = 'id',
2527
}: OutputSelectProps) {
2628
const [isOutputDropdownOpen, setIsOutputDropdownOpen] = useState(false)
2729
const dropdownRef = useRef<HTMLDivElement>(null)
@@ -201,28 +203,31 @@ export function OutputSelect({
201203
return outputs
202204
}, [workflowBlocks, workflowId, isShowingDiff, isDiffReady, diffWorkflow, blocks, subBlockValues])
203205

206+
// Utility to check selected by id or label
207+
const isSelectedValue = (o: { id: string; label: string }) =>
208+
selectedOutputs.includes(o.id) || selectedOutputs.includes(o.label)
209+
204210
// Get selected outputs display text
205211
const selectedOutputsDisplayText = useMemo(() => {
206212
if (!selectedOutputs || selectedOutputs.length === 0) {
207213
return placeholder
208214
}
209215

210-
// Ensure all selected outputs exist in the workflowOutputs array
211-
const validOutputs = selectedOutputs.filter((id) => workflowOutputs.some((o) => o.id === id))
216+
// Ensure all selected outputs exist in the workflowOutputs array by id or label
217+
const validOutputs = selectedOutputs.filter((val) =>
218+
workflowOutputs.some((o) => o.id === val || o.label === val)
219+
)
212220

213221
if (validOutputs.length === 0) {
214222
return placeholder
215223
}
216224

217225
if (validOutputs.length === 1) {
218-
const output = workflowOutputs.find((o) => o.id === validOutputs[0])
226+
const output = workflowOutputs.find(
227+
(o) => o.id === validOutputs[0] || o.label === validOutputs[0]
228+
)
219229
if (output) {
220-
// Add defensive check for output.blockName
221-
const blockNameText =
222-
output.blockName && typeof output.blockName === 'string'
223-
? output.blockName.replace(/\s+/g, '').toLowerCase()
224-
: `block-${output.blockId}`
225-
return `${blockNameText}.${output.path}`
230+
return output.label
226231
}
227232
return placeholder
228233
}
@@ -234,10 +239,14 @@ export function OutputSelect({
234239
const selectedOutputInfo = useMemo(() => {
235240
if (!selectedOutputs || selectedOutputs.length === 0) return null
236241

237-
const validOutputs = selectedOutputs.filter((id) => workflowOutputs.some((o) => o.id === id))
242+
const validOutputs = selectedOutputs.filter((val) =>
243+
workflowOutputs.some((o) => o.id === val || o.label === val)
244+
)
238245
if (validOutputs.length === 0) return null
239246

240-
const output = workflowOutputs.find((o) => o.id === validOutputs[0])
247+
const output = workflowOutputs.find(
248+
(o) => o.id === validOutputs[0] || o.label === validOutputs[0]
249+
)
241250
if (!output) return null
242251

243252
return {
@@ -355,33 +364,41 @@ export function OutputSelect({
355364
}
356365

357366
let attachedScrollTargets: (HTMLElement | Window)[] = []
367+
let rafId: number | null = null
358368
if (isOutputDropdownOpen) {
359369
updatePosition()
360370
window.addEventListener('resize', updatePosition)
361-
// Attach to all scrollable ancestors (including the modal's scroll container)
362371
attachedScrollTargets = getScrollableAncestors(dropdownRef.current)
363372
attachedScrollTargets.forEach((target) =>
364373
target.addEventListener('scroll', updatePosition, { passive: true })
365374
)
375+
const loop = () => {
376+
updatePosition()
377+
rafId = requestAnimationFrame(loop)
378+
}
379+
rafId = requestAnimationFrame(loop)
366380
}
367381

368382
return () => {
369383
window.removeEventListener('resize', updatePosition)
370384
attachedScrollTargets.forEach((target) =>
371385
target.removeEventListener('scroll', updatePosition)
372386
)
387+
if (rafId) cancelAnimationFrame(rafId)
373388
}
374389
}, [isOutputDropdownOpen])
375390

376391
// Handle output selection - toggle selection
377392
const handleOutputSelection = (value: string) => {
393+
const emittedValue =
394+
valueMode === 'label' ? value : workflowOutputs.find((o) => o.label === value)?.id || value
378395
let newSelectedOutputs: string[]
379-
const index = selectedOutputs.indexOf(value)
396+
const index = selectedOutputs.indexOf(emittedValue)
380397

381398
if (index === -1) {
382-
newSelectedOutputs = [...new Set([...selectedOutputs, value])]
399+
newSelectedOutputs = [...new Set([...selectedOutputs, emittedValue])]
383400
} else {
384-
newSelectedOutputs = selectedOutputs.filter((id) => id !== value)
401+
newSelectedOutputs = selectedOutputs.filter((id) => id !== emittedValue)
385402
}
386403

387404
onOutputSelect(newSelectedOutputs)
@@ -434,7 +451,7 @@ export function OutputSelect({
434451
ref={portalRef}
435452
style={{
436453
position: 'fixed',
437-
top: portalStyle.top,
454+
top: portalStyle.top - 1, // overlap border by 1px to avoid visible gap
438455
left: portalStyle.left,
439456
width: portalStyle.width,
440457
zIndex: 2147483647,
@@ -462,7 +479,7 @@ export function OutputSelect({
462479
<button
463480
type='button'
464481
key={output.id}
465-
onClick={() => handleOutputSelection(output.id)}
482+
onClick={() => handleOutputSelection(output.label)}
466483
className={cn(
467484
'flex w-full items-center gap-2 px-3 py-1.5 text-left font-normal text-sm',
468485
'hover:bg-accent hover:text-accent-foreground',
@@ -480,7 +497,7 @@ export function OutputSelect({
480497
</span>
481498
</div>
482499
<span className='flex-1 truncate'>{output.path}</span>
483-
{selectedOutputs.includes(output.id) && (
500+
{isSelectedValue(output) && (
484501
<Check className='h-4 w-4 flex-shrink-0 text-muted-foreground' />
485502
)}
486503
</button>

apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/api-keys/api-keys.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,7 @@ export function ApiKeys({ onOpenChange, registerCloseHandler }: ApiKeysProps) {
510510
setKeyType('personal')
511511
if (createError) setCreateError(null)
512512
}}
513-
className='h-8'
513+
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'
514514
>
515515
Personal
516516
</Button>
@@ -522,7 +522,7 @@ export function ApiKeys({ onOpenChange, registerCloseHandler }: ApiKeysProps) {
522522
setKeyType('workspace')
523523
if (createError) setCreateError(null)
524524
}}
525-
className='h-8'
525+
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'
526526
>
527527
Workspace
528528
</Button>
@@ -549,7 +549,7 @@ export function ApiKeys({ onOpenChange, registerCloseHandler }: ApiKeysProps) {
549549

550550
<AlertDialogFooter className='flex'>
551551
<AlertDialogCancel
552-
className='h-9 w-full rounded-[8px]'
552+
className='h-9 w-full rounded-[8px] border-border bg-background text-foreground hover:bg-muted dark:border-border dark:bg-background dark:text-foreground dark:hover:bg-muted/80'
553553
onClick={() => {
554554
setNewKeyName('')
555555
setKeyType('personal')

0 commit comments

Comments
 (0)