Skip to content

Commit 64b382e

Browse files
author
aadamgough
committed
ui improvement
1 parent 1dbd161 commit 64b382e

File tree

3 files changed

+331
-94
lines changed
  • apps/sim/app/workspace/[workspaceId]/w

3 files changed

+331
-94
lines changed

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

Lines changed: 104 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ export function McpDeploy({
173173
[]
174174
)
175175

176-
const selectedServerIds = useMemo(() => {
176+
const actualServerIds = useMemo(() => {
177177
const ids: string[] = []
178178
for (const server of servers) {
179179
const toolInfo = serverToolsMap[server.id]
@@ -184,6 +184,20 @@ export function McpDeploy({
184184
return ids
185185
}, [servers, serverToolsMap])
186186

187+
const [pendingSelectedServerIds, setPendingSelectedServerIds] = useState<string[] | null>(null)
188+
189+
const selectedServerIds = pendingSelectedServerIds ?? actualServerIds
190+
191+
useEffect(() => {
192+
if (pendingSelectedServerIds !== null) {
193+
const pendingSet = new Set(pendingSelectedServerIds)
194+
const actualSet = new Set(actualServerIds)
195+
if (pendingSet.size === actualSet.size && [...pendingSet].every((id) => actualSet.has(id))) {
196+
setPendingSelectedServerIds(null)
197+
}
198+
}
199+
}, [actualServerIds, pendingSelectedServerIds])
200+
187201
const hasLoadedInitialData = useRef(false)
188202

189203
useEffect(() => {
@@ -241,7 +255,17 @@ export function McpDeploy({
241255
}, [toolName, toolDescription, parameterDescriptions, savedValues])
242256

243257
const hasDeployedTools = selectedServerIds.length > 0
258+
259+
const hasServerSelectionChanges = useMemo(() => {
260+
if (pendingSelectedServerIds === null) return false
261+
const pendingSet = new Set(pendingSelectedServerIds)
262+
const actualSet = new Set(actualServerIds)
263+
if (pendingSet.size !== actualSet.size) return true
264+
return ![...pendingSet].every((id) => actualSet.has(id))
265+
}, [pendingSelectedServerIds, actualServerIds])
266+
244267
const hasChanges = useMemo(() => {
268+
if (hasServerSelectionChanges && selectedServerIds.length > 0) return true
245269
if (!savedValues || !hasDeployedTools) return false
246270
if (toolName !== savedValues.toolName) return true
247271
if (toolDescription !== savedValues.toolDescription) return true
@@ -251,7 +275,15 @@ export function McpDeploy({
251275
return true
252276
}
253277
return false
254-
}, [toolName, toolDescription, parameterDescriptions, hasDeployedTools, savedValues])
278+
}, [
279+
toolName,
280+
toolDescription,
281+
parameterDescriptions,
282+
hasDeployedTools,
283+
savedValues,
284+
hasServerSelectionChanges,
285+
selectedServerIds.length,
286+
])
255287

256288
useEffect(() => {
257289
onCanSaveChange?.(hasChanges && hasDeployedTools && !!toolName.trim())
@@ -262,74 +294,19 @@ export function McpDeploy({
262294
}, [servers.length, onHasServersChange])
263295

264296
/**
265-
* Save tool configuration to all deployed servers
297+
* Save tool configuration to all selected servers.
298+
* This handles both adding to new servers and updating existing tools.
266299
*/
267300
const handleSave = useCallback(async () => {
268301
if (!toolName.trim()) return
269-
270-
const toolsToUpdate: Array<{ serverId: string; toolId: string }> = []
271-
for (const server of servers) {
272-
const toolInfo = serverToolsMap[server.id]
273-
if (toolInfo?.tool) {
274-
toolsToUpdate.push({ serverId: server.id, toolId: toolInfo.tool.id })
275-
}
276-
}
277-
278-
if (toolsToUpdate.length === 0) return
302+
if (selectedServerIds.length === 0) return
279303

280304
onSubmittingChange?.(true)
281305
try {
282-
for (const { serverId, toolId } of toolsToUpdate) {
283-
await updateToolMutation.mutateAsync({
284-
workspaceId,
285-
serverId,
286-
toolId,
287-
toolName: toolName.trim(),
288-
toolDescription: toolDescription.trim() || undefined,
289-
parameterSchema,
290-
})
291-
}
292-
// Update saved values after successful save (triggers re-render → hasChanges becomes false)
293-
setSavedValues({
294-
toolName,
295-
toolDescription,
296-
parameterDescriptions: { ...parameterDescriptions },
297-
})
298-
onCanSaveChange?.(false)
299-
onSubmittingChange?.(false)
300-
} catch (error) {
301-
logger.error('Failed to save tool configuration:', error)
302-
onSubmittingChange?.(false)
303-
}
304-
}, [
305-
toolName,
306-
toolDescription,
307-
parameterDescriptions,
308-
parameterSchema,
309-
servers,
310-
serverToolsMap,
311-
workspaceId,
312-
updateToolMutation,
313-
onSubmittingChange,
314-
onCanSaveChange,
315-
])
316-
317-
const serverOptions: ComboboxOption[] = useMemo(() => {
318-
return servers.map((server) => ({
319-
label: server.name,
320-
value: server.id,
321-
}))
322-
}, [servers])
323-
324-
const handleServerSelectionChange = useCallback(
325-
async (newSelectedIds: string[]) => {
326-
if (!toolName.trim()) return
327-
328-
const currentIds = new Set(selectedServerIds)
329-
const newIds = new Set(newSelectedIds)
330-
331-
const toAdd = newSelectedIds.filter((id) => !currentIds.has(id))
332-
const toRemove = selectedServerIds.filter((id) => !newIds.has(id))
306+
const actualSet = new Set(actualServerIds)
307+
const toAdd = selectedServerIds.filter((id) => !actualSet.has(id))
308+
const toRemove = actualServerIds.filter((id) => !selectedServerIds.includes(id))
309+
const toUpdate = selectedServerIds.filter((id) => actualSet.has(id))
333310

334311
for (const serverId of toAdd) {
335312
setPendingServerChanges((prev) => new Set(prev).add(serverId))
@@ -342,11 +319,8 @@ export function McpDeploy({
342319
toolDescription: toolDescription.trim() || undefined,
343320
parameterSchema,
344321
})
345-
refetchServers()
346322
onAddedToServer?.()
347323
logger.info(`Added workflow ${workflowId} as tool to server ${serverId}`)
348-
} catch (error) {
349-
logger.error('Failed to add tool:', error)
350324
} finally {
351325
setPendingServerChanges((prev) => {
352326
const next = new Set(prev)
@@ -371,9 +345,6 @@ export function McpDeploy({
371345
delete next[serverId]
372346
return next
373347
})
374-
refetchServers()
375-
} catch (error) {
376-
logger.error('Failed to remove tool:', error)
377348
} finally {
378349
setPendingServerChanges((prev) => {
379350
const next = new Set(prev)
@@ -383,21 +354,69 @@ export function McpDeploy({
383354
}
384355
}
385356
}
386-
},
387-
[
388-
selectedServerIds,
389-
serverToolsMap,
390-
toolName,
391-
toolDescription,
392-
workspaceId,
393-
workflowId,
394-
parameterSchema,
395-
addToolMutation,
396-
deleteToolMutation,
397-
refetchServers,
398-
onAddedToServer,
399-
]
400-
)
357+
358+
for (const serverId of toUpdate) {
359+
const toolInfo = serverToolsMap[serverId]
360+
if (toolInfo?.tool) {
361+
await updateToolMutation.mutateAsync({
362+
workspaceId,
363+
serverId,
364+
toolId: toolInfo.tool.id,
365+
toolName: toolName.trim(),
366+
toolDescription: toolDescription.trim() || undefined,
367+
parameterSchema,
368+
})
369+
}
370+
}
371+
372+
refetchServers()
373+
374+
setPendingSelectedServerIds(null)
375+
setSavedValues({
376+
toolName,
377+
toolDescription,
378+
parameterDescriptions: { ...parameterDescriptions },
379+
})
380+
onCanSaveChange?.(false)
381+
onSubmittingChange?.(false)
382+
} catch (error) {
383+
logger.error('Failed to save tool configuration:', error)
384+
onSubmittingChange?.(false)
385+
}
386+
}, [
387+
toolName,
388+
toolDescription,
389+
parameterDescriptions,
390+
parameterSchema,
391+
servers,
392+
serverToolsMap,
393+
workspaceId,
394+
workflowId,
395+
selectedServerIds,
396+
actualServerIds,
397+
addToolMutation,
398+
deleteToolMutation,
399+
updateToolMutation,
400+
refetchServers,
401+
onSubmittingChange,
402+
onCanSaveChange,
403+
onAddedToServer,
404+
])
405+
406+
const serverOptions: ComboboxOption[] = useMemo(() => {
407+
return servers.map((server) => ({
408+
label: server.name,
409+
value: server.id,
410+
}))
411+
}, [servers])
412+
413+
/**
414+
* Handle server selection change - only updates local state.
415+
* Actual add/remove operations happen when user clicks Save.
416+
*/
417+
const handleServerSelectionChange = useCallback((newSelectedIds: string[]) => {
418+
setPendingSelectedServerIds(newSelectedIds)
419+
}, [])
401420

402421
const selectedServersLabel = useMemo(() => {
403422
const count = selectedServerIds.length

0 commit comments

Comments
 (0)