diff --git a/Cargo.lock b/Cargo.lock index a80d923..faa78c3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -279,7 +279,7 @@ checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" [[package]] name = "cm-dashboard" -version = "0.1.225" +version = "0.1.226" dependencies = [ "anyhow", "chrono", @@ -301,7 +301,7 @@ dependencies = [ [[package]] name = "cm-dashboard-agent" -version = "0.1.225" +version = "0.1.226" dependencies = [ "anyhow", "async-trait", @@ -325,7 +325,7 @@ dependencies = [ [[package]] name = "cm-dashboard-shared" -version = "0.1.225" +version = "0.1.226" dependencies = [ "chrono", "serde", diff --git a/agent/Cargo.toml b/agent/Cargo.toml index 9026c71..2862ba6 100644 --- a/agent/Cargo.toml +++ b/agent/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cm-dashboard-agent" -version = "0.1.226" +version = "0.1.227" edition = "2021" [dependencies] diff --git a/dashboard/Cargo.toml b/dashboard/Cargo.toml index c694a01..a41a5dd 100644 --- a/dashboard/Cargo.toml +++ b/dashboard/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cm-dashboard" -version = "0.1.226" +version = "0.1.227" edition = "2021" [dependencies] diff --git a/dashboard/src/ui/widgets/services.rs b/dashboard/src/ui/widgets/services.rs index 604bd0a..9607137 100644 --- a/dashboard/src/ui/widgets/services.rs +++ b/dashboard/src/ui/widgets/services.rs @@ -11,6 +11,59 @@ use tracing::debug; use crate::ui::theme::{Components, StatusIcons, Theme, Typography}; use ratatui::style::Style; +/// Column visibility configuration based on terminal width +#[derive(Debug, Clone, Copy)] +struct ColumnVisibility { + show_name: bool, + show_status: bool, + show_ram: bool, + show_uptime: bool, + show_restarts: bool, +} + +impl ColumnVisibility { + /// Determine which columns to show based on available width + fn from_width(width: u16) -> Self { + if width >= 80 { + // Full layout: Name (25) + Status (10) + RAM (8) + Uptime (8) + Restarts (5) = 56 chars + Self { + show_name: true, + show_status: true, + show_ram: true, + show_uptime: true, + show_restarts: true, + } + } else if width >= 60 { + // Hide restarts: Name (25) + Status (10) + RAM (8) + Uptime (8) = 51 chars + Self { + show_name: true, + show_status: true, + show_ram: true, + show_uptime: true, + show_restarts: false, + } + } else if width >= 45 { + // Hide uptime and restarts: Name (25) + Status (10) + RAM (8) = 43 chars + Self { + show_name: true, + show_status: true, + show_ram: true, + show_uptime: false, + show_restarts: false, + } + } else { + // Minimal: Name (25) + Status (10) = 35 chars + Self { + show_name: true, + show_status: true, + show_ram: false, + show_uptime: false, + show_restarts: false, + } + } + } +} + /// Services widget displaying hierarchical systemd service statuses #[derive(Clone)] pub struct ServicesWidget { @@ -76,7 +129,7 @@ impl ServicesWidget { } /// Format parent service line - returns text without icon for span formatting - fn format_parent_service_line(&self, name: &str, info: &ServiceInfo) -> String { + fn format_parent_service_line(&self, name: &str, info: &ServiceInfo, columns: ColumnVisibility) -> String { // Truncate long service names to fit layout (account for icon space) let short_name = if name.len() > 22 { format!("{}...", &name[..19]) @@ -129,10 +182,25 @@ impl ServicesWidget { } }); - format!( - "{:<23} {:<10} {:<8} {:<8} {:<5}", - short_name, status_str, memory_str, uptime_str, restart_str - ) + // Build format string based on column visibility + let mut parts = Vec::new(); + if columns.show_name { + parts.push(format!("{:<23}", short_name)); + } + if columns.show_status { + parts.push(format!("{:<10}", status_str)); + } + if columns.show_ram { + parts.push(format!("{:<8}", memory_str)); + } + if columns.show_uptime { + parts.push(format!("{:<8}", uptime_str)); + } + if columns.show_restarts { + parts.push(format!("{:<5}", restart_str)); + } + + parts.join(" ") } @@ -476,11 +544,28 @@ impl ServicesWidget { .constraints([Constraint::Length(1), Constraint::Min(0)]) .split(inner_area); - // Header - let header = format!( - "{:<25} {:<10} {:<8} {:<8} {:<5}", - "Service:", "Status:", "RAM:", "Uptime:", "↻:" - ); + // Determine which columns to show based on available width + let columns = ColumnVisibility::from_width(inner_area.width); + + // Build header based on visible columns + let mut header_parts = Vec::new(); + if columns.show_name { + header_parts.push(format!("{:<25}", "Service:")); + } + if columns.show_status { + header_parts.push(format!("{:<10}", "Status:")); + } + if columns.show_ram { + header_parts.push(format!("{:<8}", "RAM:")); + } + if columns.show_uptime { + header_parts.push(format!("{:<8}", "Uptime:")); + } + if columns.show_restarts { + header_parts.push(format!("{:<5}", "↻:")); + } + let header = header_parts.join(" "); + let header_para = Paragraph::new(header).style(Typography::muted()); frame.render_widget(header_para, content_chunks[0]); @@ -492,11 +577,11 @@ impl ServicesWidget { } // Render the services list - self.render_services(frame, content_chunks[1], is_focused); + self.render_services(frame, content_chunks[1], is_focused, columns); } /// Render services list - fn render_services(&mut self, frame: &mut Frame, area: Rect, is_focused: bool) { + fn render_services(&mut self, frame: &mut Frame, area: Rect, is_focused: bool, columns: ColumnVisibility) { // Build hierarchical service list for display let mut display_lines: Vec<(String, Status, bool, Option<(ServiceInfo, bool)>)> = Vec::new(); @@ -506,7 +591,7 @@ impl ServicesWidget { for (parent_name, parent_info) in parent_services { // Add parent service line - let parent_line = self.format_parent_service_line(parent_name, parent_info); + let parent_line = self.format_parent_service_line(parent_name, parent_info, columns); display_lines.push((parent_line, parent_info.widget_status, false, None)); // Add sub-services for this parent (if any) diff --git a/shared/Cargo.toml b/shared/Cargo.toml index 701737e..af47089 100644 --- a/shared/Cargo.toml +++ b/shared/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cm-dashboard-shared" -version = "0.1.226" +version = "0.1.227" edition = "2021" [dependencies]