Skip to content

Commit 51b5d32

Browse files
committed
improvement(modal): fixed popover issue in custom tools modal, removed the ability to update if no changes made
1 parent ac991d4 commit 51b5d32

3 files changed

Lines changed: 91 additions & 30 deletions

File tree

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -591,12 +591,11 @@ export function DeployModal({
591591
)}
592592
{activeTab === 'api' && (
593593
<ModalFooter className='items-center justify-between'>
594-
<div>
594+
<div />
595+
<div className='flex items-center gap-2'>
595596
<Button variant='default' onClick={() => setIsApiInfoModalOpen(true)}>
596597
Edit API Info
597598
</Button>
598-
</div>
599-
<div className='flex items-center gap-2'>
600599
<Button
601600
variant='tertiary'
602601
onClick={() => setIsCreateKeyModalOpen(true)}

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/tool-input/components/code-editor/code-editor.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ export function CodeEditor({
4242
placeholder = '',
4343
className = '',
4444
gutterClassName = '',
45-
minHeight = '360px',
45+
minHeight,
4646
highlightVariables = true,
4747
onKeyDown,
4848
disabled = false,
@@ -186,7 +186,7 @@ export function CodeEditor({
186186
}
187187

188188
return (
189-
<Code.Container className={className} style={{ minHeight }}>
189+
<Code.Container className={className} style={minHeight ? { minHeight } : undefined}>
190190
{showWandButton && onWandClick && (
191191
<Button
192192
variant='ghost'
@@ -220,7 +220,7 @@ export function CodeEditor({
220220
disabled={disabled}
221221
{...getCodeEditorProps({ disabled })}
222222
className={cn(getCodeEditorProps({ disabled }).className, 'h-full')}
223-
style={{ minHeight }}
223+
style={minHeight ? { minHeight } : undefined}
224224
textareaClassName={cn(
225225
getCodeEditorProps({ disabled }).textareaClassName,
226226
'!block !h-full !min-h-full'

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/tool-input/components/custom-tool-modal/custom-tool-modal.tsx

Lines changed: 86 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -87,15 +87,15 @@ export function CustomToolModal({
8787
const [codeError, setCodeError] = useState<string | null>(null)
8888
const [isEditing, setIsEditing] = useState(false)
8989
const [toolId, setToolId] = useState<string | undefined>(undefined)
90+
const [initialJsonSchema, setInitialJsonSchema] = useState('')
91+
const [initialFunctionCode, setInitialFunctionCode] = useState('')
9092
const [showDeleteConfirm, setShowDeleteConfirm] = useState(false)
9193
const [isSchemaPromptActive, setIsSchemaPromptActive] = useState(false)
9294
const [schemaPromptInput, setSchemaPromptInput] = useState('')
93-
const [schemaPromptSummary, setSchemaPromptSummary] = useState<string | null>(null)
9495
const schemaPromptInputRef = useRef<HTMLInputElement | null>(null)
9596

9697
const [isCodePromptActive, setIsCodePromptActive] = useState(false)
9798
const [codePromptInput, setCodePromptInput] = useState('')
98-
const [codePromptSummary, setCodePromptSummary] = useState<string | null>(null)
9999
const codePromptInputRef = useRef<HTMLInputElement | null>(null)
100100

101101
const schemaGeneration = useWand({
@@ -272,12 +272,15 @@ try {
272272

273273
if (initialValues) {
274274
try {
275-
setJsonSchema(
275+
const schemaValue =
276276
typeof initialValues.schema === 'string'
277277
? initialValues.schema
278278
: JSON.stringify(initialValues.schema, null, 2)
279-
)
280-
setFunctionCode(initialValues.code || '')
279+
const codeValue = initialValues.code || ''
280+
setJsonSchema(schemaValue)
281+
setFunctionCode(codeValue)
282+
setInitialJsonSchema(schemaValue)
283+
setInitialFunctionCode(codeValue)
281284
setIsEditing(true)
282285
setToolId(initialValues.id)
283286
} catch (error) {
@@ -304,13 +307,13 @@ try {
304307
const resetForm = () => {
305308
setJsonSchema('')
306309
setFunctionCode('')
310+
setInitialJsonSchema('')
311+
setInitialFunctionCode('')
307312
setSchemaError(null)
308313
setCodeError(null)
309314
setActiveSection('schema')
310315
setIsEditing(false)
311316
setToolId(undefined)
312-
setSchemaPromptSummary(null)
313-
setCodePromptSummary(null)
314317
setIsSchemaPromptActive(false)
315318
setIsCodePromptActive(false)
316319
setSchemaPromptInput('')
@@ -376,6 +379,11 @@ try {
376379

377380
const isSchemaValid = useMemo(() => validateJsonSchema(jsonSchema), [jsonSchema])
378381

382+
const hasChanges = useMemo(() => {
383+
if (!isEditing) return true
384+
return jsonSchema !== initialJsonSchema || functionCode !== initialFunctionCode
385+
}, [isEditing, jsonSchema, initialJsonSchema, functionCode, initialFunctionCode])
386+
379387
const handleSave = async () => {
380388
try {
381389
if (!jsonSchema) {
@@ -483,17 +491,9 @@ try {
483491
}
484492

485493
onSave(customTool)
486-
487-
setSchemaPromptSummary(null)
488-
setCodePromptSummary(null)
489-
490494
handleClose()
491495
} catch (error) {
492496
logger.error('Error saving custom tool:', { error })
493-
494-
setSchemaPromptSummary(null)
495-
setCodePromptSummary(null)
496-
497497
const errorMessage = error instanceof Error ? error.message : 'Failed to save custom tool'
498498

499499
if (errorMessage.includes('Cannot change function name')) {
@@ -667,6 +667,41 @@ try {
667667
}
668668
}
669669

670+
// Global keyboard handler for schema params dropdown (like EnvVarDropdown)
671+
useEffect(() => {
672+
if (!showSchemaParams || schemaParameters.length === 0) return
673+
674+
const handleKeyboardEvent = (e: KeyboardEvent) => {
675+
switch (e.key) {
676+
case 'ArrowDown':
677+
e.preventDefault()
678+
e.stopPropagation()
679+
setSchemaParamSelectedIndex((prev) => Math.min(prev + 1, schemaParameters.length - 1))
680+
break
681+
case 'ArrowUp':
682+
e.preventDefault()
683+
e.stopPropagation()
684+
setSchemaParamSelectedIndex((prev) => Math.max(prev - 1, 0))
685+
break
686+
case 'Enter':
687+
e.preventDefault()
688+
e.stopPropagation()
689+
if (schemaParamSelectedIndex >= 0 && schemaParamSelectedIndex < schemaParameters.length) {
690+
handleSchemaParamSelect(schemaParameters[schemaParamSelectedIndex].name)
691+
}
692+
break
693+
case 'Escape':
694+
e.preventDefault()
695+
e.stopPropagation()
696+
setShowSchemaParams(false)
697+
break
698+
}
699+
}
700+
701+
window.addEventListener('keydown', handleKeyboardEvent, true)
702+
return () => window.removeEventListener('keydown', handleKeyboardEvent, true)
703+
}, [showSchemaParams, schemaParamSelectedIndex, schemaParameters])
704+
670705
const handleKeyDown = (e: React.KeyboardEvent) => {
671706
const isSchemaPromptVisible = activeSection === 'schema' && schemaGeneration.isPromptVisible
672707
const isCodePromptVisible = activeSection === 'code' && codeGeneration.isPromptVisible
@@ -709,27 +744,32 @@ try {
709744
e.preventDefault()
710745
e.stopPropagation()
711746
setSchemaParamSelectedIndex((prev) => Math.min(prev + 1, schemaParameters.length - 1))
712-
break
747+
return
713748
case 'ArrowUp':
714749
e.preventDefault()
715750
e.stopPropagation()
716751
setSchemaParamSelectedIndex((prev) => Math.max(prev - 1, 0))
717-
break
752+
return
718753
case 'Enter':
719754
e.preventDefault()
720755
e.stopPropagation()
721756
if (schemaParamSelectedIndex >= 0 && schemaParamSelectedIndex < schemaParameters.length) {
722757
const selectedParam = schemaParameters[schemaParamSelectedIndex]
723758
handleSchemaParamSelect(selectedParam.name)
724759
}
725-
break
760+
return
726761
case 'Escape':
727762
e.preventDefault()
728763
e.stopPropagation()
729764
setShowSchemaParams(false)
765+
return
766+
case ' ':
767+
case 'Tab':
768+
// Close dropdown but let the key event continue (don't prevent default)
769+
// This allows the space/tab character to be typed normally
770+
setShowSchemaParams(false)
730771
break
731772
}
732-
return
733773
}
734774

735775
if (showEnvVars || showTags) {
@@ -743,7 +783,7 @@ try {
743783
const handleSchemaWandClick = () => {
744784
if (schemaGeneration.isLoading || schemaGeneration.isStreaming) return
745785
setIsSchemaPromptActive(true)
746-
setSchemaPromptInput(schemaPromptSummary ?? '')
786+
setSchemaPromptInput('')
747787
setTimeout(() => {
748788
schemaPromptInputRef.current?.focus()
749789
}, 0)
@@ -762,7 +802,6 @@ try {
762802
const handleSchemaPromptSubmit = () => {
763803
const trimmedPrompt = schemaPromptInput.trim()
764804
if (!trimmedPrompt || schemaGeneration.isLoading || schemaGeneration.isStreaming) return
765-
setSchemaPromptSummary(trimmedPrompt)
766805
schemaGeneration.generateStream({ prompt: trimmedPrompt })
767806
setSchemaPromptInput('')
768807
setIsSchemaPromptActive(false)
@@ -782,7 +821,7 @@ try {
782821
const handleCodeWandClick = () => {
783822
if (codeGeneration.isLoading || codeGeneration.isStreaming) return
784823
setIsCodePromptActive(true)
785-
setCodePromptInput(codePromptSummary ?? '')
824+
setCodePromptInput('')
786825
setTimeout(() => {
787826
codePromptInputRef.current?.focus()
788827
}, 0)
@@ -801,7 +840,6 @@ try {
801840
const handleCodePromptSubmit = () => {
802841
const trimmedPrompt = codePromptInput.trim()
803842
if (!trimmedPrompt || codeGeneration.isLoading || codeGeneration.isStreaming) return
804-
setCodePromptSummary(trimmedPrompt)
805843
codeGeneration.generateStream({ prompt: trimmedPrompt })
806844
setCodePromptInput('')
807845
setIsCodePromptActive(false)
@@ -1130,6 +1168,30 @@ try {
11301168
collisionPadding={6}
11311169
onOpenAutoFocus={(e) => e.preventDefault()}
11321170
onCloseAutoFocus={(e) => e.preventDefault()}
1171+
onKeyDown={(e) => {
1172+
if (e.key === 'ArrowDown') {
1173+
e.preventDefault()
1174+
setSchemaParamSelectedIndex((prev) =>
1175+
Math.min(prev + 1, schemaParameters.length - 1)
1176+
)
1177+
} else if (e.key === 'ArrowUp') {
1178+
e.preventDefault()
1179+
setSchemaParamSelectedIndex((prev) => Math.max(prev - 1, 0))
1180+
} else if (e.key === 'Enter') {
1181+
e.preventDefault()
1182+
if (
1183+
schemaParamSelectedIndex >= 0 &&
1184+
schemaParamSelectedIndex < schemaParameters.length
1185+
) {
1186+
handleSchemaParamSelect(
1187+
schemaParameters[schemaParamSelectedIndex].name
1188+
)
1189+
}
1190+
} else if (e.key === 'Escape') {
1191+
e.preventDefault()
1192+
setShowSchemaParams(false)
1193+
}
1194+
}}
11331195
>
11341196
<PopoverScrollArea>
11351197
<PopoverSection>Available Parameters</PopoverSection>
@@ -1211,7 +1273,7 @@ try {
12111273
<Button
12121274
variant='tertiary'
12131275
onClick={handleSave}
1214-
disabled={!isSchemaValid || !!schemaError}
1276+
disabled={!isSchemaValid || !!schemaError || !hasChanges}
12151277
>
12161278
{isEditing ? 'Update Tool' : 'Save Tool'}
12171279
</Button>

0 commit comments

Comments
 (0)