Update network display format to match CLAUDE.md specification
All checks were successful
Build and Release / build-and-release (push) Successful in 1m38s
All checks were successful
Build and Release / build-and-release (push) Successful in 1m38s
Nest IP addresses under physical interface names. Show physical interfaces with status icon on header line. Virtual interfaces show inline with compressed IPs. Format: ● eno1: ├─ ip: 192.168.30.105 └─ tailscale0: 100.125.108.16 Version bump to 0.1.166
This commit is contained in:
parent
fc247bd0ad
commit
9f0aa5f806
@ -304,6 +304,12 @@ exclude_fs_types = ["tmpfs", "devtmpfs", "sysfs", "proc"]
|
|||||||
### Display Format
|
### Display Format
|
||||||
|
|
||||||
```
|
```
|
||||||
|
Network:
|
||||||
|
● eno1:
|
||||||
|
├─ ip: 192.168.30.105
|
||||||
|
└─ tailscale0: 100.125.108.16
|
||||||
|
● eno2:
|
||||||
|
└─ ip: 192.168.32.105
|
||||||
CPU:
|
CPU:
|
||||||
● Load: 0.23 0.21 0.13
|
● Load: 0.23 0.21 0.13
|
||||||
└─ Freq: 1048 MHz
|
└─ Freq: 1048 MHz
|
||||||
|
|||||||
6
Cargo.lock
generated
6
Cargo.lock
generated
@ -279,7 +279,7 @@ checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cm-dashboard"
|
name = "cm-dashboard"
|
||||||
version = "0.1.165"
|
version = "0.1.166"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"chrono",
|
"chrono",
|
||||||
@ -301,7 +301,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cm-dashboard-agent"
|
name = "cm-dashboard-agent"
|
||||||
version = "0.1.165"
|
version = "0.1.166"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
@ -324,7 +324,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cm-dashboard-shared"
|
name = "cm-dashboard-shared"
|
||||||
version = "0.1.165"
|
version = "0.1.166"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"serde",
|
"serde",
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "cm-dashboard-agent"
|
name = "cm-dashboard-agent"
|
||||||
version = "0.1.165"
|
version = "0.1.166"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "cm-dashboard"
|
name = "cm-dashboard"
|
||||||
version = "0.1.165"
|
version = "0.1.166"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|||||||
@ -628,60 +628,65 @@ impl SystemWidget {
|
|||||||
let physical: Vec<_> = self.network_interfaces.iter().filter(|i| i.is_physical).collect();
|
let physical: Vec<_> = self.network_interfaces.iter().filter(|i| i.is_physical).collect();
|
||||||
let virtual_interfaces: Vec<_> = self.network_interfaces.iter().filter(|i| !i.is_physical).collect();
|
let virtual_interfaces: Vec<_> = self.network_interfaces.iter().filter(|i| !i.is_physical).collect();
|
||||||
|
|
||||||
// Render physical interfaces first
|
// Render physical interfaces
|
||||||
for (i, interface) in physical.iter().enumerate() {
|
for (phy_idx, interface) in physical.iter().enumerate() {
|
||||||
let is_last = i == physical.len() - 1 && virtual_interfaces.is_empty();
|
let is_last_physical = phy_idx == physical.len() - 1 && virtual_interfaces.is_empty();
|
||||||
let tree_symbol = if is_last { " └─ " } else { " ├─ " };
|
|
||||||
|
|
||||||
// Show interface name with IPs
|
// Physical interface header with status icon
|
||||||
let mut interface_text = format!("{}: ", interface.name);
|
let mut header_spans = vec![];
|
||||||
|
header_spans.extend(StatusIcons::create_status_spans(
|
||||||
// Add compressed IPv4 addresses
|
|
||||||
if !interface.ipv4_addresses.is_empty() {
|
|
||||||
interface_text.push_str(&Self::compress_ipv4_addresses(&interface.ipv4_addresses));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add IPv6 addresses (no compression for now)
|
|
||||||
if !interface.ipv6_addresses.is_empty() {
|
|
||||||
if !interface.ipv4_addresses.is_empty() {
|
|
||||||
interface_text.push_str(", ");
|
|
||||||
}
|
|
||||||
interface_text.push_str(&interface.ipv6_addresses.join(", "));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Physical interfaces show status icon
|
|
||||||
let mut spans = vec![
|
|
||||||
Span::styled(tree_symbol, Typography::tree()),
|
|
||||||
];
|
|
||||||
spans.extend(StatusIcons::create_status_spans(
|
|
||||||
interface.link_status.clone(),
|
interface.link_status.clone(),
|
||||||
&interface_text
|
&format!("{}:", interface.name)
|
||||||
));
|
));
|
||||||
lines.push(Line::from(spans));
|
lines.push(Line::from(header_spans));
|
||||||
|
|
||||||
|
// Show IPs nested under the interface
|
||||||
|
let ip_count = interface.ipv4_addresses.len() + interface.ipv6_addresses.len();
|
||||||
|
let mut ip_index = 0;
|
||||||
|
|
||||||
|
// IPv4 addresses
|
||||||
|
for ipv4 in &interface.ipv4_addresses {
|
||||||
|
ip_index += 1;
|
||||||
|
let is_last_ip = ip_index == ip_count && is_last_physical;
|
||||||
|
let tree_symbol = if is_last_ip { " └─ " } else { " ├─ " };
|
||||||
|
lines.push(Line::from(vec![
|
||||||
|
Span::styled(tree_symbol, Typography::tree()),
|
||||||
|
Span::styled(format!("ip: {}", ipv4), Typography::secondary()),
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPv6 addresses
|
||||||
|
for ipv6 in &interface.ipv6_addresses {
|
||||||
|
ip_index += 1;
|
||||||
|
let is_last_ip = ip_index == ip_count && is_last_physical;
|
||||||
|
let tree_symbol = if is_last_ip { " └─ " } else { " ├─ " };
|
||||||
|
lines.push(Line::from(vec![
|
||||||
|
Span::styled(tree_symbol, Typography::tree()),
|
||||||
|
Span::styled(format!("ip: {}", ipv6), Typography::secondary()),
|
||||||
|
]));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render virtual interfaces
|
// Render standalone virtual interfaces (those without a parent)
|
||||||
for (i, interface) in virtual_interfaces.iter().enumerate() {
|
for (virt_idx, interface) in virtual_interfaces.iter().enumerate() {
|
||||||
let is_last = i == virtual_interfaces.len() - 1;
|
let is_last = virt_idx == virtual_interfaces.len() - 1;
|
||||||
let tree_symbol = if is_last { " └─ " } else { " ├─ " };
|
let tree_symbol = if is_last { " └─ " } else { " ├─ " };
|
||||||
|
|
||||||
// Show interface name with IPs
|
// Virtual interface with IPs
|
||||||
let mut interface_text = format!("{}: ", interface.name);
|
let ip_text = if !interface.ipv4_addresses.is_empty() {
|
||||||
|
Self::compress_ipv4_addresses(&interface.ipv4_addresses)
|
||||||
|
} else if !interface.ipv6_addresses.is_empty() {
|
||||||
|
interface.ipv6_addresses.join(", ")
|
||||||
|
} else {
|
||||||
|
String::new()
|
||||||
|
};
|
||||||
|
|
||||||
// Add compressed IPv4 addresses
|
let interface_text = if !ip_text.is_empty() {
|
||||||
if !interface.ipv4_addresses.is_empty() {
|
format!("{}: {}", interface.name, ip_text)
|
||||||
interface_text.push_str(&Self::compress_ipv4_addresses(&interface.ipv4_addresses));
|
} else {
|
||||||
}
|
format!("{}:", interface.name)
|
||||||
|
};
|
||||||
|
|
||||||
// Add IPv6 addresses (no compression for now)
|
|
||||||
if !interface.ipv6_addresses.is_empty() {
|
|
||||||
if !interface.ipv4_addresses.is_empty() {
|
|
||||||
interface_text.push_str(", ");
|
|
||||||
}
|
|
||||||
interface_text.push_str(&interface.ipv6_addresses.join(", "));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Virtual interfaces don't show status icon
|
|
||||||
lines.push(Line::from(vec![
|
lines.push(Line::from(vec![
|
||||||
Span::styled(tree_symbol, Typography::tree()),
|
Span::styled(tree_symbol, Typography::tree()),
|
||||||
Span::styled(interface_text, Typography::secondary()),
|
Span::styled(interface_text, Typography::secondary()),
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "cm-dashboard-shared"
|
name = "cm-dashboard-shared"
|
||||||
version = "0.1.165"
|
version = "0.1.166"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user