Skip to main content
Glama
DhcpServerCard.tsx9.3 kB
import React, { useState } from 'react'; import { Copy, CheckCircle, Plus, Trash2 } from 'lucide-react'; interface DhcpServerConfig { name: string; interface: string; poolName: string; poolRange: string; network: string; gateway: string; dnsServers?: string[]; leaseTime?: string; } interface DhcpServerParams { servers: DhcpServerConfig[]; } interface DhcpServerCardProps { onCompile?: (params: DhcpServerParams) => Promise<string[]>; } export const DhcpServerCard: React.FC<DhcpServerCardProps> = ({ onCompile }) => { const [servers, setServers] = useState<DhcpServerConfig[]>([ { name: 'dhcp-lan', interface: 'bridge-lan', poolName: 'pool-lan', poolRange: '192.168.1.100-192.168.1.200', network: '192.168.1.0/24', gateway: '192.168.1.1', dnsServers: ['8.8.8.8', '8.8.4.4'], leaseTime: '1d', }, ]); const [commands, setCommands] = useState<string[]>([]); const [copied, setCopied] = useState(false); const addServer = () => { setServers([ ...servers, { name: `dhcp-vlan${servers.length + 1}`, interface: '', poolName: `pool-vlan${servers.length + 1}`, poolRange: '', network: '', gateway: '', dnsServers: ['8.8.8.8'], leaseTime: '1d', }, ]); }; const removeServer = (index: number) => { setServers(servers.filter((_, i) => i !== index)); }; const updateServer = (index: number, field: keyof DhcpServerConfig, value: any) => { const updated = [...servers]; updated[index] = { ...updated[index], [field]: value }; setServers(updated); }; const handleGenerate = async () => { const params: DhcpServerParams = { servers }; if (onCompile) { const result = await onCompile(params); setCommands(result); } else { // Fallback: generate commands locally const cmds: string[] = []; servers.forEach(srv => { // Create pool cmds.push(`/ip pool add name=${srv.poolName} ranges=${srv.poolRange}`); // Create DHCP network const dnsStr = srv.dnsServers && srv.dnsServers.length > 0 ? ` dns-server=${srv.dnsServers.join(',')}` : ''; cmds.push(`/ip dhcp-server network add address=${srv.network} gateway=${srv.gateway}${dnsStr}`); // Create DHCP server cmds.push(`/ip dhcp-server add name=${srv.name} interface=${srv.interface} address-pool=${srv.poolName} lease-time=${srv.leaseTime || '1d'} disabled=no`); }); setCommands(cmds); } }; const handleCopy = () => { navigator.clipboard.writeText(commands.join('\n')); setCopied(true); setTimeout(() => setCopied(false), 2000); }; return ( <div className="bg-white rounded-lg shadow-md p-6 border border-gray-200"> <div className="flex items-center justify-between mb-4"> <h3 className="text-lg font-semibold text-gray-800">DHCP Server</h3> <span className="px-2 py-1 bg-green-100 text-green-700 text-xs font-medium rounded"> Low Risk </span> </div> <div className="space-y-4 mb-4"> {servers.map((server, index) => ( <div key={index} className="border border-gray-200 rounded p-4 relative"> {servers.length > 1 && ( <button onClick={() => removeServer(index)} className="absolute top-2 right-2 text-red-500 hover:text-red-700" > <Trash2 className="w-4 h-4" /> </button> )} <div className="grid grid-cols-2 gap-3"> <div> <label className="block text-xs font-medium text-gray-700 mb-1">Name</label> <input type="text" value={server.name} onChange={(e) => updateServer(index, 'name', e.target.value)} className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded focus:ring-2 focus:ring-blue-500" /> </div> <div> <label className="block text-xs font-medium text-gray-700 mb-1">Interface</label> <input type="text" value={server.interface} onChange={(e) => updateServer(index, 'interface', e.target.value)} placeholder="bridge-lan" className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded focus:ring-2 focus:ring-blue-500" /> </div> <div> <label className="block text-xs font-medium text-gray-700 mb-1">Pool Name</label> <input type="text" value={server.poolName} onChange={(e) => updateServer(index, 'poolName', e.target.value)} className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded focus:ring-2 focus:ring-blue-500" /> </div> <div> <label className="block text-xs font-medium text-gray-700 mb-1">Pool Range</label> <input type="text" value={server.poolRange} onChange={(e) => updateServer(index, 'poolRange', e.target.value)} placeholder="192.168.1.100-192.168.1.200" className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded focus:ring-2 focus:ring-blue-500" /> </div> <div> <label className="block text-xs font-medium text-gray-700 mb-1">Network (CIDR)</label> <input type="text" value={server.network} onChange={(e) => updateServer(index, 'network', e.target.value)} placeholder="192.168.1.0/24" className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded focus:ring-2 focus:ring-blue-500" /> </div> <div> <label className="block text-xs font-medium text-gray-700 mb-1">Gateway</label> <input type="text" value={server.gateway} onChange={(e) => updateServer(index, 'gateway', e.target.value)} placeholder="192.168.1.1" className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded focus:ring-2 focus:ring-blue-500" /> </div> <div> <label className="block text-xs font-medium text-gray-700 mb-1">DNS Servers (comma-sep)</label> <input type="text" value={server.dnsServers?.join(',') || ''} onChange={(e) => updateServer(index, 'dnsServers', e.target.value.split(',').map(s => s.trim()))} placeholder="8.8.8.8, 8.8.4.4" className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded focus:ring-2 focus:ring-blue-500" /> </div> <div> <label className="block text-xs font-medium text-gray-700 mb-1">Lease Time</label> <input type="text" value={server.leaseTime || '1d'} onChange={(e) => updateServer(index, 'leaseTime', e.target.value)} placeholder="1d" className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded focus:ring-2 focus:ring-blue-500" /> </div> </div> </div> ))} <button onClick={addServer} className="w-full py-2 border-2 border-dashed border-gray-300 rounded text-sm text-gray-600 hover:border-blue-400 hover:text-blue-600 transition-colors flex items-center justify-center gap-2" > <Plus className="w-4 h-4" /> Add DHCP Server </button> </div> <button onClick={handleGenerate} className="w-full bg-blue-600 text-white py-2 px-4 rounded-md hover:bg-blue-700 transition-colors mb-4" > Generate Commands </button> {commands.length > 0 && ( <div className="mt-4 border-t pt-4"> <div className="flex items-center justify-between mb-2"> <span className="text-sm font-medium text-gray-700"> Generated Commands ({commands.length}) </span> <button onClick={handleCopy} className="flex items-center gap-1 px-3 py-1 text-sm text-blue-600 hover:bg-blue-50 rounded transition-colors" > {copied ? ( <> <CheckCircle className="w-4 h-4" /> <span>Copied!</span> </> ) : ( <> <Copy className="w-4 h-4" /> <span>Copy</span> </> )} </button> </div> <pre className="bg-gray-50 p-3 rounded text-xs font-mono overflow-x-auto border border-gray-200"> {commands.join('\n')} </pre> </div> )} </div> ); };

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/babasida246/ai-mcp-gateway'

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