diff --git a/src/webui/internal/handlers/configure_interfaces.go b/src/webui/internal/handlers/configure_interfaces.go index 0389988c..f8fa4ca6 100644 --- a/src/webui/internal/handlers/configure_interfaces.go +++ b/src/webui/internal/handlers/configure_interfaces.go @@ -94,6 +94,7 @@ type cfgIfaceRow struct { AdminEnabled bool // true when enabled leaf absent (YANG default) or explicitly true MemberOf string // bridge or lag name this interface belongs to AddrSummary string + ConfigTags []string // type-aware overview pills (DHCP, SLAAC, vid N, …) BridgeMembers []string // interface names that are ports of this bridge/lag BridgeMemberSet map[string]bool // for checkbox pre-selection PortCandidates []string // free ports + current members of this bridge/lag @@ -2042,6 +2043,7 @@ func (h *ConfigureInterfacesHandler) buildRows(ifaces []ifaceJSON, oper []ifaceJ } } row.AddrSummary = addrSummary(iface) + row.ConfigTags = configSummary(&row) if row.IsBridge { members := bridgeMembers[iface.Name] @@ -2647,3 +2649,40 @@ func addrSummary(iface ifaceJSON) string { return fmt.Sprintf("%d addresses", len(addrs)) } } + +// configSummary builds the type-aware overview pills for an interface in the +// Configure list. It mirrors the Status > Interfaces "Data" column but is +// slanted to configured intent rather than operational result: each role +// contributes the properties worth seeing without unfolding the row — IP +// acquisition (DHCP, SLAAC, zeroconf) for L3 interfaces, the tag id for VLANs, +// the radio mode for WiFi, and 802.1Q for VLAN-filtering bridges. Static +// addresses are rendered separately via AddrSummary. +func configSummary(row *cfgIfaceRow) []string { + var tags []string + + if row.IsVlan && row.Vlan != nil { + tags = append(tags, fmt.Sprintf("vid %d", row.Vlan.ID)) + } + if row.IsWifi && row.WifiMode != "" { + tags = append(tags, row.WifiMode) + } + if row.IsBridge && row.BridgeIs8021Q { + tags = append(tags, "802.1Q") + } + if row.HasIP { + if row.DHCPv4Enabled { + tags = append(tags, "DHCPv4") + } + if row.IPv4 != nil && row.IPv4.Autoconf != nil { + tags = append(tags, "Zeroconf") + } + if row.DHCPv6Enabled { + tags = append(tags, "DHCPv6") + } + if row.IPv6 != nil && row.IPv6.SLAACv6 != nil { + tags = append(tags, "SLAAC") + } + } + + return tags +} diff --git a/src/webui/static/css/style.css b/src/webui/static/css/style.css index d8cec957..0ef816c2 100644 --- a/src/webui/static/css/style.css +++ b/src/webui/static/css/style.css @@ -1099,6 +1099,25 @@ details[open].nav-group-top > summary.nav-group-summary-top::before { .badge-drop { background: var(--slate-100); color: var(--slate-600); } .badge-continue { background: #dbeafe; color: #1e40af; } +/* Type-aware Config column pills in the Configure > Interfaces overview. */ +.iface-cfg-cell { white-space: normal; } +.iface-tag { + display: inline-block; + margin: 0.1rem 0.25rem 0.1rem 0; + padding: 0.05rem 0.4rem; + border-radius: var(--radius-sm); + background: var(--slate-100); + color: var(--slate-600); + font-size: 0.7rem; + font-weight: 600; + white-space: nowrap; +} +.iface-cfg-addr { color: var(--slate-600); } +.dark .iface-tag { background: var(--slate-800); color: var(--slate-300); } +@media (prefers-color-scheme: dark) { + .iface-tag { background: var(--slate-800); color: var(--slate-300); } +} + @media (prefers-color-scheme: dark) { .badge-accept { background: rgba(22, 163, 74, 0.2); color: #86efac; } .badge-reject { background: rgba(220, 38, 38, 0.2); color: #fca5a5; } diff --git a/src/webui/templates/pages/configure-interfaces.html b/src/webui/templates/pages/configure-interfaces.html index 841cb0dc..366caa92 100644 --- a/src/webui/templates/pages/configure-interfaces.html +++ b/src/webui/templates/pages/configure-interfaces.html @@ -30,7 +30,7 @@