Remove unused code and eliminate build warnings
Removed unused widget subscription system, cache utilities, error variants, theme functions, and struct fields. Replaced subscription-based widgets with direct metric filtering. Build now completes with zero warnings.
This commit is contained in:
@@ -18,7 +18,6 @@ use crate::metrics::MetricStore;
|
||||
use crate::ui::TuiApp;
|
||||
|
||||
pub struct Dashboard {
|
||||
config: DashboardConfig,
|
||||
zmq_consumer: ZmqConsumer,
|
||||
zmq_command_sender: ZmqCommandSender,
|
||||
metric_store: MetricStore,
|
||||
@@ -111,7 +110,6 @@ impl Dashboard {
|
||||
info!("Dashboard initialization complete");
|
||||
|
||||
Ok(Self {
|
||||
config,
|
||||
zmq_consumer,
|
||||
zmq_command_sender,
|
||||
metric_store,
|
||||
|
||||
@@ -1,136 +1,14 @@
|
||||
use cm_dashboard_shared::{Metric, Status};
|
||||
use std::time::Instant;
|
||||
|
||||
pub mod store;
|
||||
pub mod subscription;
|
||||
|
||||
pub use store::MetricStore;
|
||||
|
||||
/// Widget types that can subscribe to metrics
|
||||
#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
|
||||
pub enum WidgetType {
|
||||
Cpu,
|
||||
Memory,
|
||||
Storage,
|
||||
Services,
|
||||
Backup,
|
||||
Hosts,
|
||||
Alerts,
|
||||
}
|
||||
|
||||
/// Historical metric data point
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct MetricDataPoint {
|
||||
pub metric: Metric,
|
||||
pub received_at: Instant,
|
||||
}
|
||||
|
||||
/// Metric filtering and selection utilities
|
||||
pub mod filter {
|
||||
use super::*;
|
||||
|
||||
/// Filter metrics by widget type subscription
|
||||
pub fn filter_metrics_for_widget<'a>(
|
||||
metrics: &'a [Metric],
|
||||
subscriptions: &[String],
|
||||
) -> Vec<&'a Metric> {
|
||||
metrics
|
||||
.iter()
|
||||
.filter(|metric| subscriptions.contains(&metric.name))
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Get metrics by pattern matching
|
||||
pub fn filter_metrics_by_pattern<'a>(
|
||||
metrics: &'a [Metric],
|
||||
pattern: &str,
|
||||
) -> Vec<&'a Metric> {
|
||||
if pattern.is_empty() {
|
||||
return metrics.iter().collect();
|
||||
}
|
||||
|
||||
metrics
|
||||
.iter()
|
||||
.filter(|metric| metric.name.contains(pattern))
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Aggregate status from multiple metrics
|
||||
pub fn aggregate_widget_status(metrics: &[&Metric]) -> Status {
|
||||
if metrics.is_empty() {
|
||||
return Status::Unknown;
|
||||
}
|
||||
|
||||
let statuses: Vec<Status> = metrics.iter().map(|m| m.status).collect();
|
||||
Status::aggregate(&statuses)
|
||||
}
|
||||
}
|
||||
|
||||
/// Widget metric subscription definitions
|
||||
pub mod subscriptions {
|
||||
/// CPU widget metric subscriptions
|
||||
pub const CPU_WIDGET_METRICS: &[&str] = &[
|
||||
"cpu_load_1min",
|
||||
"cpu_load_5min",
|
||||
"cpu_load_15min",
|
||||
"cpu_temperature_celsius",
|
||||
"cpu_frequency_mhz",
|
||||
];
|
||||
|
||||
/// Memory widget metric subscriptions
|
||||
pub const MEMORY_WIDGET_METRICS: &[&str] = &[
|
||||
"memory_usage_percent",
|
||||
"memory_total_gb",
|
||||
"memory_used_gb",
|
||||
"memory_available_gb",
|
||||
"memory_swap_total_gb",
|
||||
"memory_swap_used_gb",
|
||||
"disk_tmp_size_mb",
|
||||
"disk_tmp_total_mb",
|
||||
"disk_tmp_usage_percent",
|
||||
];
|
||||
|
||||
/// Storage widget metric subscriptions
|
||||
pub const STORAGE_WIDGET_METRICS: &[&str] = &[
|
||||
"disk_nvme0_temperature_celsius",
|
||||
"disk_nvme0_wear_percent",
|
||||
"disk_nvme0_spare_percent",
|
||||
"disk_nvme0_hours",
|
||||
"disk_nvme0_capacity_gb",
|
||||
"disk_nvme0_usage_gb",
|
||||
"disk_nvme0_usage_percent",
|
||||
];
|
||||
|
||||
/// Services widget metric subscriptions
|
||||
/// Note: Individual service metrics are dynamically discovered
|
||||
/// Pattern: "service_{name}_status" and "service_{name}_memory_mb"
|
||||
pub const SERVICES_WIDGET_METRICS: &[&str] = &[
|
||||
// Individual service metrics will be matched by pattern in the widget
|
||||
// e.g., "service_sshd_status", "service_nginx_status", etc.
|
||||
];
|
||||
|
||||
/// Backup widget metric subscriptions
|
||||
pub const BACKUP_WIDGET_METRICS: &[&str] = &[
|
||||
"backup_overall_status",
|
||||
"backup_duration_seconds",
|
||||
"backup_last_run_timestamp",
|
||||
"backup_total_services",
|
||||
"backup_total_repo_size_gb",
|
||||
"backup_services_completed_count",
|
||||
"backup_services_failed_count",
|
||||
"backup_services_disabled_count",
|
||||
];
|
||||
|
||||
/// Get all metric subscriptions for a widget type
|
||||
pub fn get_widget_subscriptions(widget_type: super::WidgetType) -> &'static [&'static str] {
|
||||
match widget_type {
|
||||
super::WidgetType::Cpu => CPU_WIDGET_METRICS,
|
||||
super::WidgetType::Memory => MEMORY_WIDGET_METRICS,
|
||||
super::WidgetType::Storage => STORAGE_WIDGET_METRICS,
|
||||
super::WidgetType::Services => SERVICES_WIDGET_METRICS,
|
||||
super::WidgetType::Backup => BACKUP_WIDGET_METRICS,
|
||||
super::WidgetType::Hosts => &[], // Hosts widget doesn't subscribe to specific metrics
|
||||
super::WidgetType::Alerts => &[], // Alerts widget aggregates from all metrics
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
use cm_dashboard_shared::{Metric, Status};
|
||||
use cm_dashboard_shared::Metric;
|
||||
use std::collections::HashMap;
|
||||
use std::time::{Duration, Instant};
|
||||
use tracing::{debug, info, warn};
|
||||
|
||||
use super::{MetricDataPoint, WidgetType, subscriptions};
|
||||
use super::MetricDataPoint;
|
||||
|
||||
/// Central metric storage for the dashboard
|
||||
pub struct MetricStore {
|
||||
@@ -54,7 +54,6 @@ impl MetricStore {
|
||||
|
||||
// Add to history
|
||||
host_history.push(MetricDataPoint {
|
||||
metric,
|
||||
received_at: now,
|
||||
});
|
||||
}
|
||||
@@ -80,6 +79,7 @@ impl MetricStore {
|
||||
}
|
||||
|
||||
/// Get all current metrics for a host
|
||||
#[allow(dead_code)]
|
||||
pub fn get_host_metrics(&self, hostname: &str) -> Option<&HashMap<String, Metric>> {
|
||||
self.current_metrics.get(hostname)
|
||||
}
|
||||
@@ -93,36 +93,7 @@ impl MetricStore {
|
||||
}
|
||||
}
|
||||
|
||||
/// Get metrics for a specific widget type
|
||||
pub fn get_metrics_for_widget(&self, hostname: &str, widget_type: WidgetType) -> Vec<&Metric> {
|
||||
let subscriptions = subscriptions::get_widget_subscriptions(widget_type);
|
||||
|
||||
if let Some(host_metrics) = self.get_host_metrics(hostname) {
|
||||
subscriptions
|
||||
.iter()
|
||||
.filter_map(|&metric_name| host_metrics.get(metric_name))
|
||||
.collect()
|
||||
} else {
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
|
||||
/// Get aggregated status for a widget
|
||||
pub fn get_widget_status(&self, hostname: &str, widget_type: WidgetType) -> Status {
|
||||
let metrics = self.get_metrics_for_widget(hostname, widget_type);
|
||||
|
||||
if metrics.is_empty() {
|
||||
Status::Unknown
|
||||
} else {
|
||||
let statuses: Vec<Status> = metrics.iter().map(|m| m.status).collect();
|
||||
Status::aggregate(&statuses)
|
||||
}
|
||||
}
|
||||
|
||||
/// Get list of all hosts with metrics
|
||||
pub fn get_hosts(&self) -> Vec<String> {
|
||||
self.current_metrics.keys().cloned().collect()
|
||||
}
|
||||
|
||||
/// Get connected hosts (hosts with recent updates)
|
||||
pub fn get_connected_hosts(&self, timeout: Duration) -> Vec<String> {
|
||||
@@ -140,45 +111,7 @@ impl MetricStore {
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Get last update timestamp for a host
|
||||
pub fn get_last_update(&self, hostname: &str) -> Option<Instant> {
|
||||
self.last_update.get(hostname).copied()
|
||||
}
|
||||
|
||||
/// Check if host is considered connected
|
||||
pub fn is_host_connected(&self, hostname: &str, timeout: Duration) -> bool {
|
||||
if let Some(&last_update) = self.last_update.get(hostname) {
|
||||
Instant::now().duration_since(last_update) <= timeout
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// Get metric value as specific type (helper function)
|
||||
pub fn get_metric_value_f32(&self, hostname: &str, metric_name: &str) -> Option<f32> {
|
||||
self.get_metric(hostname, metric_name)?
|
||||
.value
|
||||
.as_f32()
|
||||
}
|
||||
|
||||
/// Get metric value as string (helper function)
|
||||
pub fn get_metric_value_string(&self, hostname: &str, metric_name: &str) -> Option<String> {
|
||||
Some(self.get_metric(hostname, metric_name)?
|
||||
.value
|
||||
.as_string())
|
||||
}
|
||||
|
||||
/// Get historical data for a metric
|
||||
pub fn get_metric_history(&self, hostname: &str, metric_name: &str) -> Vec<&MetricDataPoint> {
|
||||
if let Some(history) = self.historical_metrics.get(hostname) {
|
||||
history
|
||||
.iter()
|
||||
.filter(|dp| dp.metric.name == metric_name)
|
||||
.collect()
|
||||
} else {
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
|
||||
/// Cleanup old data and enforce limits
|
||||
fn cleanup_host_data(&mut self, hostname: &str) {
|
||||
@@ -199,32 +132,4 @@ impl MetricStore {
|
||||
}
|
||||
}
|
||||
|
||||
/// Get storage statistics
|
||||
pub fn get_stats(&self) -> MetricStoreStats {
|
||||
let total_current_metrics: usize = self.current_metrics
|
||||
.values()
|
||||
.map(|host_metrics| host_metrics.len())
|
||||
.sum();
|
||||
|
||||
let total_historical_metrics: usize = self.historical_metrics
|
||||
.values()
|
||||
.map(|history| history.len())
|
||||
.sum();
|
||||
|
||||
MetricStoreStats {
|
||||
total_hosts: self.current_metrics.len(),
|
||||
total_current_metrics,
|
||||
total_historical_metrics,
|
||||
connected_hosts: self.get_connected_hosts(Duration::from_secs(30)).len(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Metric store statistics
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct MetricStoreStats {
|
||||
pub total_hosts: usize,
|
||||
pub total_current_metrics: usize,
|
||||
pub total_historical_metrics: usize,
|
||||
pub connected_hosts: usize,
|
||||
}
|
||||
@@ -1,160 +0,0 @@
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use tracing::{debug, info};
|
||||
|
||||
use super::{WidgetType, subscriptions};
|
||||
|
||||
/// Manages metric subscriptions for widgets
|
||||
pub struct SubscriptionManager {
|
||||
/// Widget subscriptions: widget_type -> metric_names
|
||||
widget_subscriptions: HashMap<WidgetType, Vec<String>>,
|
||||
/// All subscribed metric names (for efficient filtering)
|
||||
all_subscribed_metrics: HashSet<String>,
|
||||
/// Active hosts
|
||||
active_hosts: HashSet<String>,
|
||||
}
|
||||
|
||||
impl SubscriptionManager {
|
||||
pub fn new() -> Self {
|
||||
let mut manager = Self {
|
||||
widget_subscriptions: HashMap::new(),
|
||||
all_subscribed_metrics: HashSet::new(),
|
||||
active_hosts: HashSet::new(),
|
||||
};
|
||||
|
||||
// Initialize default subscriptions
|
||||
manager.initialize_default_subscriptions();
|
||||
|
||||
manager
|
||||
}
|
||||
|
||||
/// Initialize default widget subscriptions
|
||||
fn initialize_default_subscriptions(&mut self) {
|
||||
// Subscribe CPU widget to CPU metrics
|
||||
self.subscribe_widget(
|
||||
WidgetType::Cpu,
|
||||
subscriptions::CPU_WIDGET_METRICS.iter().map(|&s| s.to_string()).collect()
|
||||
);
|
||||
|
||||
// Subscribe Memory widget to memory metrics
|
||||
self.subscribe_widget(
|
||||
WidgetType::Memory,
|
||||
subscriptions::MEMORY_WIDGET_METRICS.iter().map(|&s| s.to_string()).collect()
|
||||
);
|
||||
|
||||
|
||||
info!("Initialized default widget subscriptions for {} widgets",
|
||||
self.widget_subscriptions.len());
|
||||
}
|
||||
|
||||
/// Subscribe a widget to specific metrics
|
||||
pub fn subscribe_widget(&mut self, widget_type: WidgetType, metric_names: Vec<String>) {
|
||||
debug!("Subscribing {:?} widget to {} metrics", widget_type, metric_names.len());
|
||||
|
||||
// Update widget subscriptions
|
||||
self.widget_subscriptions.insert(widget_type, metric_names.clone());
|
||||
|
||||
// Update global subscription set
|
||||
for metric_name in metric_names {
|
||||
self.all_subscribed_metrics.insert(metric_name);
|
||||
}
|
||||
|
||||
debug!("Total subscribed metrics: {}", self.all_subscribed_metrics.len());
|
||||
}
|
||||
|
||||
/// Get metrics subscribed by a specific widget
|
||||
pub fn get_widget_subscriptions(&self, widget_type: WidgetType) -> Vec<String> {
|
||||
self.widget_subscriptions
|
||||
.get(&widget_type)
|
||||
.cloned()
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
/// Get all subscribed metric names
|
||||
pub fn get_all_subscribed_metrics(&self) -> Vec<String> {
|
||||
self.all_subscribed_metrics.iter().cloned().collect()
|
||||
}
|
||||
|
||||
/// Check if a metric is subscribed by any widget
|
||||
pub fn is_metric_subscribed(&self, metric_name: &str) -> bool {
|
||||
self.all_subscribed_metrics.contains(metric_name)
|
||||
}
|
||||
|
||||
/// Add a host to active hosts list
|
||||
pub fn add_host(&mut self, hostname: String) {
|
||||
if self.active_hosts.insert(hostname.clone()) {
|
||||
info!("Added host to subscription manager: {}", hostname);
|
||||
}
|
||||
}
|
||||
|
||||
/// Remove a host from active hosts list
|
||||
pub fn remove_host(&mut self, hostname: &str) {
|
||||
if self.active_hosts.remove(hostname) {
|
||||
info!("Removed host from subscription manager: {}", hostname);
|
||||
}
|
||||
}
|
||||
|
||||
/// Get list of active hosts
|
||||
pub fn get_active_hosts(&self) -> Vec<String> {
|
||||
self.active_hosts.iter().cloned().collect()
|
||||
}
|
||||
|
||||
/// Get subscription statistics
|
||||
pub fn get_stats(&self) -> SubscriptionStats {
|
||||
SubscriptionStats {
|
||||
total_widgets_subscribed: self.widget_subscriptions.len(),
|
||||
total_metric_subscriptions: self.all_subscribed_metrics.len(),
|
||||
active_hosts: self.active_hosts.len(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Update widget subscription dynamically
|
||||
pub fn update_widget_subscription(&mut self, widget_type: WidgetType, metric_names: Vec<String>) {
|
||||
// Remove old subscriptions from global set
|
||||
if let Some(old_subscriptions) = self.widget_subscriptions.get(&widget_type) {
|
||||
for old_metric in old_subscriptions {
|
||||
// Only remove if no other widget subscribes to it
|
||||
let still_subscribed = self.widget_subscriptions
|
||||
.iter()
|
||||
.filter(|(&wt, _)| wt != widget_type)
|
||||
.any(|(_, metrics)| metrics.contains(old_metric));
|
||||
|
||||
if !still_subscribed {
|
||||
self.all_subscribed_metrics.remove(old_metric);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add new subscriptions
|
||||
self.subscribe_widget(widget_type, metric_names);
|
||||
|
||||
debug!("Updated subscription for {:?} widget", widget_type);
|
||||
}
|
||||
|
||||
/// Get widgets that subscribe to a specific metric
|
||||
pub fn get_widgets_for_metric(&self, metric_name: &str) -> Vec<WidgetType> {
|
||||
self.widget_subscriptions
|
||||
.iter()
|
||||
.filter_map(|(&widget_type, metrics)| {
|
||||
if metrics.contains(&metric_name.to_string()) {
|
||||
Some(widget_type)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for SubscriptionManager {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
/// Subscription manager statistics
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct SubscriptionStats {
|
||||
pub total_widgets_subscribed: usize,
|
||||
pub total_metric_subscriptions: usize,
|
||||
pub active_hosts: usize,
|
||||
}
|
||||
@@ -14,7 +14,7 @@ pub mod widgets;
|
||||
pub mod theme;
|
||||
|
||||
use widgets::{CpuWidget, MemoryWidget, ServicesWidget, BackupWidget, Widget};
|
||||
use crate::metrics::{MetricStore, WidgetType};
|
||||
use crate::metrics::MetricStore;
|
||||
use cm_dashboard_shared::{Metric, Status};
|
||||
use theme::{Theme, Layout as ThemeLayout, Typography, Components, StatusIcons};
|
||||
|
||||
@@ -82,8 +82,14 @@ impl TuiApp {
|
||||
let all_metrics = metric_store.get_metrics_for_host(&hostname);
|
||||
if !all_metrics.is_empty() {
|
||||
// Get metrics first while hostname is borrowed
|
||||
let cpu_metrics = metric_store.get_metrics_for_widget(&hostname, WidgetType::Cpu);
|
||||
let memory_metrics = metric_store.get_metrics_for_widget(&hostname, WidgetType::Memory);
|
||||
let cpu_metrics: Vec<&Metric> = all_metrics.iter()
|
||||
.filter(|m| m.name.starts_with("cpu_") || m.name.contains("c_state_") || m.name.starts_with("process_top_"))
|
||||
.copied()
|
||||
.collect();
|
||||
let memory_metrics: Vec<&Metric> = all_metrics.iter()
|
||||
.filter(|m| m.name.starts_with("memory_") || m.name.starts_with("disk_tmp_"))
|
||||
.copied()
|
||||
.collect();
|
||||
let service_metrics: Vec<&Metric> = all_metrics.iter()
|
||||
.filter(|m| m.name.starts_with("service_"))
|
||||
.copied()
|
||||
|
||||
@@ -3,6 +3,7 @@ use ratatui::widgets::{Block, Borders};
|
||||
use cm_dashboard_shared::Status;
|
||||
|
||||
/// Complete terminal color palette matching your configuration
|
||||
#[allow(dead_code)]
|
||||
pub struct TerminalColors {
|
||||
// Primary colors
|
||||
pub foreground: Color,
|
||||
@@ -86,6 +87,7 @@ impl Default for TerminalColors {
|
||||
/// Comprehensive theming engine for dashboard consistency
|
||||
pub struct Theme;
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl Theme {
|
||||
fn colors() -> &'static TerminalColors {
|
||||
static COLORS: std::sync::OnceLock<TerminalColors> = std::sync::OnceLock::new();
|
||||
@@ -243,22 +245,6 @@ impl StatusIcons {
|
||||
}
|
||||
}
|
||||
|
||||
/// Get style for status-colored text (icon + text in status color)
|
||||
pub fn get_status_style(status: Status) -> Style {
|
||||
let color = match status {
|
||||
Status::Ok => Theme::success(), // Green
|
||||
Status::Warning => Theme::warning(), // Yellow
|
||||
Status::Critical => Theme::error(), // Red
|
||||
Status::Unknown => Theme::muted_text(), // Gray
|
||||
};
|
||||
Style::default().fg(color).bg(Theme::background())
|
||||
}
|
||||
|
||||
/// Format text with status icon (entire line uses status color)
|
||||
pub fn format_with_status(status: Status, text: &str) -> String {
|
||||
let icon = Self::get_icon(status);
|
||||
format!("{} {}", icon, text)
|
||||
}
|
||||
|
||||
/// Create spans with status icon colored and text in foreground color
|
||||
pub fn create_status_spans(status: Status, text: &str) -> Vec<ratatui::text::Span<'static>> {
|
||||
@@ -282,17 +268,11 @@ impl StatusIcons {
|
||||
]
|
||||
}
|
||||
|
||||
/// Get style for secondary text with status icon (icon in status color, text in secondary)
|
||||
pub fn get_secondary_with_status_style(_status: Status) -> Style {
|
||||
// For now, use secondary color but we could enhance this later
|
||||
// The icon color will come from the status color in the formatted text
|
||||
Style::default().fg(Theme::secondary_text()).bg(Theme::background())
|
||||
}
|
||||
}
|
||||
|
||||
impl Components {
|
||||
/// Standard widget block with title using bright foreground for title
|
||||
pub fn widget_block(title: &str) -> Block {
|
||||
pub fn widget_block(title: &str) -> Block<'_> {
|
||||
Block::default()
|
||||
.title(title)
|
||||
.borders(Borders::ALL)
|
||||
@@ -300,40 +280,6 @@ impl Components {
|
||||
.title_style(Style::default().fg(Theme::border_title()).bg(Theme::background()))
|
||||
}
|
||||
|
||||
/// Status bar style
|
||||
pub fn status_bar() -> Style {
|
||||
Style::default()
|
||||
.fg(Theme::muted_text())
|
||||
.bg(Theme::background())
|
||||
}
|
||||
|
||||
/// CPU usage styling based on percentage
|
||||
pub fn cpu_usage_style(percentage: u16) -> Style {
|
||||
Style::default()
|
||||
.fg(Theme::cpu_color(percentage))
|
||||
.bg(Theme::background())
|
||||
}
|
||||
|
||||
/// Memory usage styling based on percentage
|
||||
pub fn memory_usage_style(percentage: u16) -> Style {
|
||||
Style::default()
|
||||
.fg(Theme::memory_color(percentage))
|
||||
.bg(Theme::background())
|
||||
}
|
||||
|
||||
/// Service status styling
|
||||
pub fn service_status_style(status: Status) -> Style {
|
||||
Style::default()
|
||||
.fg(Theme::status_color(status))
|
||||
.bg(Theme::background())
|
||||
}
|
||||
|
||||
/// Backup item styling
|
||||
pub fn backup_item_style(status: Status) -> Style {
|
||||
Style::default()
|
||||
.fg(Theme::status_color(status))
|
||||
.bg(Theme::background())
|
||||
}
|
||||
}
|
||||
|
||||
impl Typography {
|
||||
@@ -367,10 +313,4 @@ impl Typography {
|
||||
.add_modifier(Modifier::BOLD)
|
||||
}
|
||||
|
||||
/// Status text with dynamic colors
|
||||
pub fn status(status: Status) -> Style {
|
||||
Style::default()
|
||||
.fg(Theme::status_color(status))
|
||||
.bg(Theme::background())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,19 +107,6 @@ impl BackupWidget {
|
||||
}
|
||||
}
|
||||
|
||||
/// Format service status counts
|
||||
fn format_service_counts(&self) -> String {
|
||||
let completed = self.services_completed_count.unwrap_or(0);
|
||||
let failed = self.services_failed_count.unwrap_or(0);
|
||||
let disabled = self.services_disabled_count.unwrap_or(0);
|
||||
let total = self.total_services.unwrap_or(0);
|
||||
|
||||
if failed > 0 {
|
||||
format!("{}✓ {}✗ {}◯ ({})", completed, failed, disabled, total)
|
||||
} else {
|
||||
format!("{}✓ {}◯ ({})", completed, disabled, total)
|
||||
}
|
||||
}
|
||||
|
||||
/// Format disk usage in format "usedGB/totalGB"
|
||||
fn format_repo_size(&self) -> String {
|
||||
@@ -160,30 +147,7 @@ impl BackupWidget {
|
||||
}
|
||||
}
|
||||
|
||||
/// Get status indicator symbol
|
||||
fn get_status_symbol(&self) -> &str {
|
||||
match self.overall_status {
|
||||
Status::Ok => "●",
|
||||
Status::Warning => "◐",
|
||||
Status::Critical => "◯",
|
||||
Status::Unknown => "?",
|
||||
}
|
||||
}
|
||||
|
||||
/// Format size in GB to appropriate unit (kB/MB/GB)
|
||||
fn format_size_gb(size_gb: f32) -> String {
|
||||
if size_gb >= 1.0 {
|
||||
format!("{:.1}GB", size_gb)
|
||||
} else if size_gb >= 0.001 {
|
||||
let size_mb = size_gb * 1024.0;
|
||||
format!("{:.1}MB", size_mb)
|
||||
} else if size_gb >= 0.000001 {
|
||||
let size_kb = size_gb * 1024.0 * 1024.0;
|
||||
format!("{:.0}kB", size_kb)
|
||||
} else {
|
||||
format!("{:.0}B", size_gb * 1024.0 * 1024.0 * 1024.0)
|
||||
}
|
||||
}
|
||||
|
||||
/// Format product name display
|
||||
fn format_product_name(&self) -> String {
|
||||
|
||||
@@ -118,36 +118,6 @@ impl ServicesWidget {
|
||||
disk_str)
|
||||
}
|
||||
|
||||
/// Format sub-service line (indented, no memory/disk columns) - returns text without icon for span formatting
|
||||
fn format_sub_service_line(&self, name: &str, info: &ServiceInfo) -> String {
|
||||
// Truncate long sub-service names to fit layout (accounting for indentation)
|
||||
let short_name = if name.len() > 18 {
|
||||
format!("{}...", &name[..15])
|
||||
} else {
|
||||
name.to_string()
|
||||
};
|
||||
|
||||
// Sub-services show latency if available, otherwise status
|
||||
let status_str = if let Some(latency) = info.latency_ms {
|
||||
if latency < 0.0 {
|
||||
"timeout".to_string()
|
||||
} else {
|
||||
format!("{:.0}ms", latency)
|
||||
}
|
||||
} else {
|
||||
match info.widget_status {
|
||||
Status::Ok => "active".to_string(),
|
||||
Status::Warning => "inactive".to_string(),
|
||||
Status::Critical => "failed".to_string(),
|
||||
Status::Unknown => "unknown".to_string(),
|
||||
}
|
||||
};
|
||||
|
||||
// Indent sub-services with " ├─ " prefix (no memory/disk columns)
|
||||
format!(" ├─ {:<20} {:<10}",
|
||||
short_name,
|
||||
status_str)
|
||||
}
|
||||
|
||||
/// Create spans for sub-service with icon next to name
|
||||
fn create_sub_service_spans(&self, name: &str, info: &ServiceInfo) -> Vec<ratatui::text::Span<'static>> {
|
||||
|
||||
Reference in New Issue
Block a user