Skip to main content
Glama
SaveToolDialog.tsx4.06 kB
import { useConfig } from "@/src/app/config-context"; import { useTools } from "@/src/app/tools-context"; import { Button } from "@/src/components/ui/button"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/src/components/ui/dialog"; import { Input } from "@/src/components/ui/input"; import { Label } from "@/src/components/ui/label"; import { createSuperglueClient, isValidToolName, validateToolName } from "@/src/lib/client-utils"; import { Workflow as Tool } from "@superglue/client"; import { Loader2 } from "lucide-react"; import { useEffect, useState } from "react"; interface SaveToolDialogProps { tool: Tool | null; isOpen: boolean; onClose: () => void; onSaved?: (savedTool: Tool) => void; } export function SaveToolDialog({ tool, isOpen, onClose, onSaved }: SaveToolDialogProps) { const config = useConfig(); const { tools } = useTools(); const [toolName, setToolName] = useState(""); const [error, setError] = useState(""); const [isSaving, setIsSaving] = useState(false); useEffect(() => { if (isOpen && tool) { setToolName(tool.id); setError(""); } }, [isOpen, tool]); const handleClose = () => { setToolName(""); setError(""); onClose(); }; const handleSave = async () => { if (!tool) return; const trimmedName = toolName.trim(); const validationError = validateToolName(trimmedName); if (validationError) { setError(validationError); return; } const existingTool = tools.find(t => t.id === trimmedName); if (existingTool) { setError("A tool with this name already exists"); return; } try { setIsSaving(true); const client = createSuperglueClient(config.superglueEndpoint); const toolToSave = { ...tool, id: trimmedName }; const saved = await client.upsertWorkflow(trimmedName, toolToSave as any); if (!saved) throw new Error('Failed to save tool'); handleClose(); if (onSaved) { onSaved(saved); } } catch (error: any) { console.error('Error saving tool:', error); setError(error.message || 'Failed to save tool'); } finally { setIsSaving(false); } }; return ( <Dialog open={isOpen} onOpenChange={(open) => !open && handleClose()}> <DialogContent onKeyDown={(e) => { if (e.key === 'Enter' && !isSaving && (e.target as HTMLElement).tagName !== 'BUTTON') { e.preventDefault(); handleSave(); } }}> <DialogHeader> <DialogTitle>Save Tool</DialogTitle> <DialogDescription> Give your tool a name. This will be used to identify and run your tool. </DialogDescription> </DialogHeader> <div className="space-y-4 py-4"> <div className="space-y-2"> <Label htmlFor="tool-name">Tool Name</Label> <Input id="tool-name" value={toolName} onChange={(e) => { const value = e.target.value; if (isValidToolName(value)) { setToolName(value); setError(""); } }} placeholder="Enter tool name" disabled={isSaving} autoFocus /> {error && ( <p className="text-sm text-red-500">{error}</p> )} </div> </div> <DialogFooter> <Button variant="outline" onClick={handleClose} disabled={isSaving} > Cancel </Button> <Button onClick={handleSave} disabled={isSaving} > {isSaving ? ( <> <Loader2 className="mr-2 h-4 w-4 animate-spin" /> Saving... </> ) : ( "Save" )} </Button> </DialogFooter> </DialogContent> </Dialog> ); }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/superglue-ai/superglue'

If you have feedback or need assistance with the MCP directory API, please join our Discord server