From e8e50ef9bb583432993b9b515d61a61c07deb87f Mon Sep 17 00:00:00 2001 From: Christoffer Martinsson Date: Sat, 8 Nov 2025 18:28:28 +0100 Subject: [PATCH] Replace empty panels with offline host message for better UX - Hide all system/backup/service panels when host is offline - Show centered wake-up message with host status - Display "Press 'w' to wake up host" if MAC address configured - Provide clear visual indication when hosts are unreachable - Improve user experience by removing confusing empty panels Version 0.1.64 --- Cargo.lock | 6 +-- agent/Cargo.toml | 2 +- dashboard/Cargo.toml | 2 +- dashboard/src/ui/mod.rs | 86 +++++++++++++++++++++++++++++++++++++++++ shared/Cargo.toml | 2 +- 5 files changed, 92 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 903463c..57e69cf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -270,7 +270,7 @@ checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" [[package]] name = "cm-dashboard" -version = "0.1.62" +version = "0.1.63" dependencies = [ "anyhow", "chrono", @@ -292,7 +292,7 @@ dependencies = [ [[package]] name = "cm-dashboard-agent" -version = "0.1.62" +version = "0.1.63" dependencies = [ "anyhow", "async-trait", @@ -315,7 +315,7 @@ dependencies = [ [[package]] name = "cm-dashboard-shared" -version = "0.1.62" +version = "0.1.63" dependencies = [ "chrono", "serde", diff --git a/agent/Cargo.toml b/agent/Cargo.toml index 404368b..dd7538f 100644 --- a/agent/Cargo.toml +++ b/agent/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cm-dashboard-agent" -version = "0.1.63" +version = "0.1.64" edition = "2021" [dependencies] diff --git a/dashboard/Cargo.toml b/dashboard/Cargo.toml index cebb463..de8f8ea 100644 --- a/dashboard/Cargo.toml +++ b/dashboard/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cm-dashboard" -version = "0.1.63" +version = "0.1.64" edition = "2021" [dependencies] diff --git a/dashboard/src/ui/mod.rs b/dashboard/src/ui/mod.rs index 91f809f..5397ef5 100644 --- a/dashboard/src/ui/mod.rs +++ b/dashboard/src/ui/mod.rs @@ -558,6 +558,21 @@ impl TuiApp { ]) .split(main_chunks[1]); // main_chunks[1] is now the content area (between title and statusbar) + // Check if current host is offline + let current_host_offline = if let Some(hostname) = self.current_host.clone() { + self.calculate_host_status(&hostname, metric_store) == Status::Offline + } else { + true // No host selected is considered offline + }; + + // If host is offline, render wake-up message instead of panels + if current_host_offline { + self.render_offline_host_message(frame, main_chunks[1]); + self.render_btop_title(frame, main_chunks[0], metric_store); + self.render_statusbar(frame, main_chunks[2]); + return; + } + // Check if backup panel should be shown let show_backup = if let Some(hostname) = self.current_host.clone() { let host_widgets = self.get_or_create_host_widgets(&hostname); @@ -811,6 +826,77 @@ impl TuiApp { } } + /// Render offline host message with wake-up option + fn render_offline_host_message(&self, frame: &mut Frame, area: Rect) { + use ratatui::layout::Alignment; + use ratatui::style::Modifier; + use ratatui::text::{Line, Span}; + use ratatui::widgets::{Block, Borders, Paragraph}; + + // Get hostname for message + let hostname = self.current_host.as_ref() + .map(|h| h.as_str()) + .unwrap_or("Unknown"); + + // Check if host has MAC address for wake-on-LAN + let has_mac = self.current_host.as_ref() + .and_then(|hostname| self.config.hosts.get(hostname)) + .and_then(|details| details.mac_address.as_ref()) + .is_some(); + + // Create message content + let mut lines = vec![ + Line::from(Span::styled( + format!("Host '{}' is offline", hostname), + Style::default().fg(Theme::muted_text()).add_modifier(Modifier::BOLD), + )), + Line::from(""), + ]; + + if has_mac { + lines.push(Line::from(Span::styled( + "Press 'w' to wake up host", + Style::default().fg(Theme::primary_text()).add_modifier(Modifier::BOLD), + ))); + } else { + lines.push(Line::from(Span::styled( + "No MAC address configured - cannot wake up", + Style::default().fg(Theme::muted_text()), + ))); + } + + // Create centered message + let message = Paragraph::new(lines) + .block(Block::default() + .borders(Borders::ALL) + .border_style(Style::default().fg(Theme::muted_text())) + .title(" Offline Host ") + .title_style(Style::default().fg(Theme::muted_text()).add_modifier(Modifier::BOLD))) + .style(Style::default().bg(Theme::background()).fg(Theme::primary_text())) + .alignment(Alignment::Center); + + // Center the message in the available area + let popup_area = ratatui::layout::Layout::default() + .direction(Direction::Vertical) + .constraints([ + Constraint::Percentage(40), + Constraint::Length(6), + Constraint::Percentage(40), + ]) + .split(area)[1]; + + let popup_area = ratatui::layout::Layout::default() + .direction(Direction::Horizontal) + .constraints([ + Constraint::Percentage(25), + Constraint::Percentage(50), + Constraint::Percentage(25), + ]) + .split(popup_area)[1]; + + frame.render_widget(message, popup_area); + } + /// Parse MAC address string (e.g., "AA:BB:CC:DD:EE:FF") to [u8; 6] fn parse_mac_address(mac_str: &str) -> Result<[u8; 6], &'static str> { let parts: Vec<&str> = mac_str.split(':').collect(); diff --git a/shared/Cargo.toml b/shared/Cargo.toml index bd41f89..d624c0f 100644 --- a/shared/Cargo.toml +++ b/shared/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cm-dashboard-shared" -version = "0.1.63" +version = "0.1.64" edition = "2021" [dependencies]