Skip to main content
Glama
tool-manager.tsx6.04 kB
import { useState } from "react"; import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Card, CardContent } from "@/components/ui/card"; import { Eye, EyeOff, Key, Save, Info } from "lucide-react"; import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { apiRequest } from "@/lib/queryClient"; import { useToast } from "@/hooks/use-toast"; import LoadingSpinner from "@/components/ui/loading-spinner"; interface TokenManagerProps { onClose: () => void; } export default function TokenManager({ onClose }: TokenManagerProps) { const [newToken, setNewToken] = useState(""); const [showToken, setShowToken] = useState(false); const { toast } = useToast(); const queryClient = useQueryClient(); // Get current token status const { data: tokenStatus } = useQuery({ queryKey: ["/api/token/status"], }); const updateTokenMutation = useMutation({ mutationFn: async (token: string) => { const response = await apiRequest("PUT", "/api/token/update", { token }); return response.json(); }, onSuccess: () => { toast({ title: "Success!", description: "GitHub token updated successfully.", }); // Invalidate relevant queries queryClient.invalidateQueries({ queryKey: ["/api/token/status"] }); queryClient.invalidateQueries({ queryKey: ["/api/tools"] }); onClose(); }, onError: (error: any) => { toast({ title: "Update Failed", description: error.message || "Failed to update token. Please try again.", variant: "destructive", }); }, }); const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); if (!newToken.trim()) { toast({ title: "Token Required", description: "Please enter a new token.", variant: "destructive", }); return; } if (!newToken.startsWith('ghp_') && !newToken.startsWith('github_pat_')) { toast({ title: "Invalid Format", description: "Please enter a valid GitHub personal access token.", variant: "destructive", }); return; } updateTokenMutation.mutate(newToken); }; const formatDate = (dateString: string | undefined) => { if (!dateString) return "Unknown"; return new Date(dateString).toLocaleString(); }; return ( <Dialog open={true} onOpenChange={onClose}> <DialogContent className="max-w-md"> <DialogHeader> <DialogTitle className="flex items-center gap-3"> <div className="w-10 h-10 bg-gradient-to-r from-purple-600 to-blue-600 rounded-lg flex items-center justify-center"> <Key className="h-5 w-5 text-white" /> </div> <div> <h3 className="text-xl font-semibold">Manage GitHub Token</h3> <p className="text-sm text-muted-foreground">Update your authentication credentials</p> </div> </DialogTitle> </DialogHeader> <div className="space-y-4"> <form onSubmit={handleSubmit} className="space-y-4"> <div className="space-y-2"> <Label htmlFor="new-github-token">New GitHub Token</Label> <div className="relative"> <Input id="new-github-token" type={showToken ? "text" : "password"} placeholder="Enter new token..." value={newToken} onChange={(e) => setNewToken(e.target.value)} className="pr-10" disabled={updateTokenMutation.isPending} /> <Button type="button" variant="ghost" size="sm" className="absolute right-0 top-0 h-full px-3 py-2 hover:bg-transparent" onClick={() => setShowToken(!showToken)} disabled={updateTokenMutation.isPending} > {showToken ? ( <EyeOff className="h-4 w-4 text-muted-foreground" /> ) : ( <Eye className="h-4 w-4 text-muted-foreground" /> )} </Button> </div> </div> <Card className="bg-muted/50"> <CardContent className="pt-4"> <div className="flex items-center mb-2"> <Info className="h-4 w-4 text-primary mr-2" /> <span className="text-sm font-medium">Current Status</span> </div> <div className="space-y-1 text-sm text-muted-foreground"> <div className="flex items-center"> <div className="w-2 h-2 bg-green-500 rounded-full mr-2"></div> <span>Token active</span> </div> </div> </CardContent> </Card> <div className="flex items-center justify-between pt-4"> <Button type="button" variant="outline" onClick={onClose}> Cancel </Button> <Button type="submit" disabled={updateTokenMutation.isPending} className="bg-gradient-to-r from-purple-600 to-blue-600 hover:from-purple-700 hover:to-blue-700" > {updateTokenMutation.isPending ? ( <> <LoadingSpinner className="mr-2 h-4 w-4" /> Updating... </> ) : ( <> <Save className="mr-2 h-4 w-4" /> Update Token </> )} </Button> </div> </form> </div> </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/Rohitkumar0056/GitHub-MCP'

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