feat: inline label editing for topology links
This commit is contained in:
@ -8,7 +8,7 @@ import { LabTemplate, Device, TopologyLink } from '../types';
|
||||
import TopologyPanel from './TopologyPanel';
|
||||
import {
|
||||
Server, Plus, Edit3, Trash, User, MapPin,
|
||||
Layers, ChevronRight, Save, X, Check
|
||||
Layers, ChevronRight, Save, X, Check, Pencil
|
||||
} from 'lucide-react';
|
||||
|
||||
interface LabTemplatesProps {
|
||||
@ -37,6 +37,8 @@ export default function LabTemplates({
|
||||
const [linkFrom, setLinkFrom] = useState('');
|
||||
const [linkTo, setLinkTo] = useState('');
|
||||
const [linkType, setLinkType] = useState('Trunk Uplink');
|
||||
const [editingLinkIdx, setEditingLinkIdx] = useState<number | null>(null);
|
||||
const [editingLinkLabel, setEditingLinkLabel] = useState('');
|
||||
|
||||
const [formData, setFormData] = useState<{
|
||||
id?: string;
|
||||
@ -467,19 +469,54 @@ export default function LabTemplates({
|
||||
{tempLinks.map((link, idx) => {
|
||||
const fromDev = devices.find(d => d.id === link.fromDevice)?.hostname || link.fromDevice;
|
||||
const toDev = devices.find(d => d.id === link.toDevice)?.hostname || link.toDevice;
|
||||
const isEditingThis = editingLinkIdx === idx;
|
||||
return (
|
||||
<div key={idx} className="flex justify-between items-center bg-slate-950 px-3 py-1.5 rounded border border-slate-855 font-mono text-[10px] hover:border-slate-700">
|
||||
<span className="text-slate-300">
|
||||
<strong>{fromDev}</strong> ──── {link.type} ──── <strong>{toDev}</strong>
|
||||
</span>
|
||||
<div key={idx} className="flex items-center gap-2 bg-slate-950 px-3 py-1.5 rounded border border-slate-855 font-mono text-[10px] hover:border-slate-700">
|
||||
<span className="text-slate-300 shrink-0"><strong>{fromDev}</strong> ────</span>
|
||||
{isEditingThis ? (
|
||||
<input
|
||||
autoFocus
|
||||
value={editingLinkLabel}
|
||||
onChange={(e) => setEditingLinkLabel(e.target.value)}
|
||||
onBlur={() => {
|
||||
if (editingLinkLabel.trim()) {
|
||||
setTempLinks(tempLinks.map((l, i) => i === idx ? { ...l, type: editingLinkLabel.trim() } : l));
|
||||
}
|
||||
setEditingLinkIdx(null);
|
||||
}}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter') {
|
||||
if (editingLinkLabel.trim()) {
|
||||
setTempLinks(tempLinks.map((l, i) => i === idx ? { ...l, type: editingLinkLabel.trim() } : l));
|
||||
}
|
||||
setEditingLinkIdx(null);
|
||||
}
|
||||
if (e.key === 'Escape') setEditingLinkIdx(null);
|
||||
}}
|
||||
className="flex-1 min-w-0 bg-slate-800 text-slate-100 border border-indigo-500 rounded px-1.5 py-0.5 focus:outline-none"
|
||||
/>
|
||||
) : (
|
||||
<span className="flex-1 min-w-0 text-indigo-300 truncate">{link.type}</span>
|
||||
)}
|
||||
<span className="text-slate-300 shrink-0">──── <strong>{toDev}</strong></span>
|
||||
<div className="flex gap-1.5 shrink-0 ml-auto font-sans">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => { setEditingLinkIdx(idx); setEditingLinkLabel(link.type); }}
|
||||
className="text-slate-400 hover:text-indigo-400 transition-colors"
|
||||
title="Edit label"
|
||||
>
|
||||
<Pencil className="w-3 h-3" />
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => handleRemoveLink(idx)}
|
||||
className="text-rose-500 hover:text-rose-450 font-sans font-bold"
|
||||
className="text-rose-500 hover:text-rose-400 font-bold"
|
||||
>
|
||||
Remove
|
||||
<X className="w-3 h-3" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user