diff --git a/frontend/src/components/panels/DetailPanel.tsx b/frontend/src/components/panels/DetailPanel.tsx index 71cbe7d..8dc8843 100644 --- a/frontend/src/components/panels/DetailPanel.tsx +++ b/frontend/src/components/panels/DetailPanel.tsx @@ -1,20 +1,31 @@ -import { X, Edit, Trash2, ExternalLink } from 'lucide-react' +import { useState } from 'react' +import { X, Edit, Trash2, ExternalLink, Plus } from 'lucide-react' import { Button } from '@/components/ui/button' +import { Input } from '@/components/ui/input' import { useCanvasStore } from '@/stores/canvasStore' import { NODE_TYPE_LABELS, STATUS_COLORS, type ServiceInfo } from '@/types' +import { getServiceUrl } from '@/utils/serviceUrl' interface DetailPanelProps { onEdit: (id: string) => void } export function DetailPanel({ onEdit }: DetailPanelProps) { - const { nodes, selectedNodeId, setSelectedNode, deleteNode } = useCanvasStore() + const { nodes, selectedNodeId, setSelectedNode, deleteNode, updateNode } = useCanvasStore() const node = nodes.find((n) => n.id === selectedNodeId) - if (!node) return null + const [addingService, setAddingService] = useState(false) + const [newSvc, setNewSvc] = useState<{ port: string; protocol: 'tcp' | 'udp'; service_name: string }>({ + port: '', + protocol: 'tcp', + service_name: '', + }) + + if (!node || node.data.type === 'groupRect') return null const { data } = node const statusColor = STATUS_COLORS[data.status] + const host = data.ip ?? data.hostname const handleDelete = () => { if (confirm(`Delete "${data.label}"?`)) { @@ -22,6 +33,24 @@ export function DetailPanel({ onEdit }: DetailPanelProps) { } } + const handleAddService = () => { + const port = parseInt(newSvc.port, 10) + if (!newSvc.service_name.trim() || isNaN(port) || port < 1 || port > 65535) return + const svc: ServiceInfo = { + port, + protocol: newSvc.protocol, + service_name: newSvc.service_name.trim(), + } + updateNode(node.id, { services: [...(data.services ?? []), svc] }) + setNewSvc({ port: '', protocol: 'tcp', service_name: '' }) + setAddingService(false) + } + + const handleRemoveService = (index: number) => { + const updated = data.services.filter((_, i) => i !== index) + updateNode(node.id, { services: updated }) + } + return (