feat: Copy VLANs wizard + CPU display fix for hardware switches (v0.11.0 Beta)

Add 'Copy VLANs from Another Switch' — a 3-step modal available on the
VLANs tab of any switch device. Step 1 selects a source switch and which
VLAN IDs to copy (VLAN 1 deselected by default with a management risk
warning). Step 2 lets the user assign interfaces on the target device
per VLAN: clicking a port chip cycles it through None → Tagged → Untagged
→ None, with a live summary and bridge picker per VLAN. Conflict detection
identifies VLANs already present on the target and offers per-VLAN
Skip/Overwrite with the port grid disabling itself when Skip is active.
Step 3 shows the full plan before a single apply call executes all
operations over one device connection and reports per-VLAN results.

Also fix CPU load display on the Devices page for hardware switches that
report 0% CPU via ASIC offloading — the previous filter (v > 0) silently
dropped all valid zero readings; now filters on field presence instead.
This commit is contained in:
2GT-Rich
2026-05-15 14:43:53 -07:00
parent 17e989da99
commit d3aa72c488
10 changed files with 1003 additions and 7 deletions
+2
View File
@@ -197,6 +197,8 @@ export const devicesApi = {
updateVlan: (id: number, vlanDbId: number, data: { tagged_ports: string[]; untagged_ports: string[] }) =>
api.put(`/devices/${id}/vlans/${vlanDbId}`, data),
deleteVlan: (id: number, vlanDbId: number) => api.delete(`/devices/${id}/vlans/${vlanDbId}`),
copyVlans: (id: number, operations: Array<{ action: 'add' | 'update'; vlan_id: number; bridge: string; tagged_ports: string[]; untagged_ports: string[] }>) =>
api.post<{ results: Array<{ vlan_id: number; action: string; success: boolean; error?: string }>; vlans: Vlan[] }>(`/devices/${id}/vlans/copy`, { operations }),
reboot: (id: number) => api.post<{ message: string }>(`/devices/${id}/reboot`),
getPortMonitor: (id: number, name: string) =>
api.get<PortMonitorData>(`/devices/${id}/ports/${encodeURIComponent(name)}/monitor`),