- Remove unused fields from CommandStatus variants - Clean up unused methods and unused collector fields - Fix lifetime syntax warning in SystemWidget - Delete unused cache module completely - Remove redundant render methods from widgets All agent and dashboard warnings eliminated while preserving panel switching and scrolling functionality.
344 lines
11 KiB
Rust
344 lines
11 KiB
Rust
use cm_dashboard_shared::Status;
|
|
use ratatui::style::{Color, Modifier, Style};
|
|
use ratatui::widgets::{Block, Borders};
|
|
|
|
/// Complete terminal color palette matching your configuration
|
|
#[allow(dead_code)]
|
|
pub struct TerminalColors {
|
|
// Primary colors
|
|
pub foreground: Color,
|
|
pub dim_foreground: Color,
|
|
pub bright_foreground: Color,
|
|
pub background: Color,
|
|
|
|
// Normal colors
|
|
pub normal_black: Color,
|
|
pub normal_red: Color,
|
|
pub normal_green: Color,
|
|
pub normal_yellow: Color,
|
|
pub normal_blue: Color,
|
|
pub normal_magenta: Color,
|
|
pub normal_cyan: Color,
|
|
pub normal_white: Color,
|
|
|
|
// Bright colors
|
|
pub bright_black: Color,
|
|
pub bright_red: Color,
|
|
pub bright_green: Color,
|
|
pub bright_yellow: Color,
|
|
pub bright_blue: Color,
|
|
pub bright_magenta: Color,
|
|
pub bright_cyan: Color,
|
|
pub bright_white: Color,
|
|
|
|
// Dim colors
|
|
pub dim_black: Color,
|
|
pub dim_red: Color,
|
|
pub dim_green: Color,
|
|
pub dim_yellow: Color,
|
|
pub dim_blue: Color,
|
|
pub dim_magenta: Color,
|
|
pub dim_cyan: Color,
|
|
pub dim_white: Color,
|
|
}
|
|
|
|
impl Default for TerminalColors {
|
|
fn default() -> Self {
|
|
Self {
|
|
// Primary colors
|
|
foreground: Color::Rgb(198, 198, 198), // #c6c6c6
|
|
dim_foreground: Color::Rgb(112, 112, 112), // #707070
|
|
bright_foreground: Color::Rgb(255, 255, 255), // #ffffff
|
|
background: Color::Rgb(38, 38, 38), // #262626
|
|
|
|
// Normal colors
|
|
normal_black: Color::Rgb(0, 0, 0), // #000000
|
|
normal_red: Color::Rgb(215, 84, 0), // #d75400
|
|
normal_green: Color::Rgb(175, 215, 135), // #afd787
|
|
normal_yellow: Color::Rgb(215, 175, 95), // #d7af5f
|
|
normal_blue: Color::Rgb(135, 175, 215), // #87afd7
|
|
normal_magenta: Color::Rgb(215, 215, 175), // #d7d7af
|
|
normal_cyan: Color::Rgb(160, 160, 160), // #a0a0a0
|
|
normal_white: Color::Rgb(238, 238, 238), // #eeeeee
|
|
|
|
// Bright colors
|
|
bright_black: Color::Rgb(48, 48, 48), // #303030
|
|
bright_red: Color::Rgb(215, 84, 0), // #d75400
|
|
bright_green: Color::Rgb(175, 215, 135), // #afd787
|
|
bright_yellow: Color::Rgb(215, 175, 95), // #d7af5f
|
|
bright_blue: Color::Rgb(135, 175, 215), // #87afd7
|
|
bright_magenta: Color::Rgb(215, 215, 175), // #d7d7af
|
|
bright_cyan: Color::Rgb(160, 160, 160), // #a0a0a0
|
|
bright_white: Color::Rgb(255, 255, 255), // #ffffff
|
|
|
|
// Dim colors
|
|
dim_black: Color::Rgb(0, 0, 0), // #000000
|
|
dim_red: Color::Rgb(215, 84, 0), // #d75400
|
|
dim_green: Color::Rgb(175, 215, 135), // #afd787
|
|
dim_yellow: Color::Rgb(215, 175, 95), // #d7af5f
|
|
dim_blue: Color::Rgb(135, 175, 215), // #87afd7
|
|
dim_magenta: Color::Rgb(215, 215, 175), // #d7d7af
|
|
dim_cyan: Color::Rgb(160, 160, 160), // #a0a0a0
|
|
dim_white: Color::Rgb(221, 221, 221), // #dddddd
|
|
}
|
|
}
|
|
}
|
|
|
|
/// 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();
|
|
COLORS.get_or_init(TerminalColors::default)
|
|
}
|
|
|
|
// Semantic color mapping using the terminal color struct
|
|
pub fn primary_text() -> Color {
|
|
Self::colors().normal_white
|
|
}
|
|
|
|
pub fn secondary_text() -> Color {
|
|
Self::colors().foreground
|
|
}
|
|
|
|
pub fn muted_text() -> Color {
|
|
Self::colors().dim_foreground
|
|
}
|
|
|
|
pub fn border() -> Color {
|
|
Self::colors().dim_foreground
|
|
}
|
|
|
|
pub fn border_title() -> Color {
|
|
Self::colors().bright_white
|
|
}
|
|
|
|
pub fn background() -> Color {
|
|
Self::colors().background
|
|
}
|
|
|
|
pub fn success() -> Color {
|
|
Self::colors().normal_green
|
|
}
|
|
|
|
pub fn warning() -> Color {
|
|
Self::colors().normal_yellow
|
|
}
|
|
|
|
pub fn error() -> Color {
|
|
Self::colors().normal_red
|
|
}
|
|
|
|
pub fn info() -> Color {
|
|
Self::colors().normal_cyan
|
|
}
|
|
|
|
pub fn highlight() -> Color {
|
|
Self::colors().normal_blue
|
|
}
|
|
|
|
/// Get color for status level
|
|
pub fn status_color(status: Status) -> Color {
|
|
match status {
|
|
Status::Ok => Self::success(),
|
|
Status::Pending => Self::highlight(), // Blue for pending
|
|
Status::Warning => Self::warning(),
|
|
Status::Critical => Self::error(),
|
|
Status::Unknown => Self::muted_text(),
|
|
}
|
|
}
|
|
|
|
/// Get style for status level
|
|
pub fn status_style(status: Status) -> Style {
|
|
Style::default().fg(Self::status_color(status))
|
|
}
|
|
|
|
/// CPU usage colors using terminal color struct
|
|
pub fn cpu_color(percentage: u16) -> Color {
|
|
match percentage {
|
|
0..=25 => Self::colors().normal_green, // Low usage
|
|
26..=50 => Self::colors().normal_yellow, // Medium usage
|
|
51..=75 => Self::colors().normal_magenta, // High usage
|
|
76..=100 => Self::colors().normal_red, // Critical usage
|
|
_ => Self::colors().normal_red, // Over 100%
|
|
}
|
|
}
|
|
|
|
/// Memory usage colors using terminal color struct
|
|
pub fn memory_color(percentage: u16) -> Color {
|
|
match percentage {
|
|
0..=60 => Self::colors().normal_green, // Low usage
|
|
61..=80 => Self::colors().normal_yellow, // Medium usage
|
|
81..=95 => Self::colors().normal_magenta, // High usage
|
|
96..=100 => Self::colors().normal_red, // Critical usage
|
|
_ => Self::colors().normal_red, // Over 100%
|
|
}
|
|
}
|
|
|
|
/// Get gauge color based on percentage
|
|
pub fn gauge_color(percentage: u16, warning_threshold: u16, critical_threshold: u16) -> Color {
|
|
if percentage >= critical_threshold {
|
|
Self::error()
|
|
} else if percentage >= warning_threshold {
|
|
Self::warning()
|
|
} else {
|
|
Self::success()
|
|
}
|
|
}
|
|
|
|
/// Widget border style
|
|
pub fn widget_border_style() -> Style {
|
|
Style::default().fg(Self::border()).bg(Self::background())
|
|
}
|
|
|
|
/// Inactive widget border style
|
|
pub fn widget_border_inactive_style() -> Style {
|
|
Style::default()
|
|
.fg(Self::muted_text())
|
|
.bg(Self::background())
|
|
}
|
|
|
|
/// Title style
|
|
pub fn title_style() -> Style {
|
|
Style::default()
|
|
.fg(Self::border_title())
|
|
.bg(Self::background())
|
|
}
|
|
|
|
/// Status bar style
|
|
pub fn status_bar_style() -> Style {
|
|
Style::default()
|
|
.fg(Self::muted_text())
|
|
.bg(Self::background())
|
|
}
|
|
}
|
|
|
|
/// Layout and spacing constants
|
|
pub struct Layout;
|
|
|
|
impl Layout {
|
|
/// Left panel percentage (system + backup)
|
|
pub const LEFT_PANEL_WIDTH: u16 = 45;
|
|
/// Right panel percentage (services)
|
|
pub const RIGHT_PANEL_WIDTH: u16 = 55;
|
|
/// System vs backup split (equal)
|
|
pub const SYSTEM_PANEL_HEIGHT: u16 = 50;
|
|
pub const BACKUP_PANEL_HEIGHT: u16 = 50;
|
|
}
|
|
|
|
/// Typography system
|
|
pub struct Typography;
|
|
|
|
/// Component styling system
|
|
pub struct Components;
|
|
|
|
/// Status icons and styling
|
|
pub struct StatusIcons;
|
|
|
|
impl StatusIcons {
|
|
/// Get status icon symbol
|
|
pub fn get_icon(status: Status) -> &'static str {
|
|
match status {
|
|
Status::Ok => "●",
|
|
Status::Pending => "◉", // Hollow circle for pending
|
|
Status::Warning => "◐",
|
|
Status::Critical => "◯",
|
|
Status::Unknown => "?",
|
|
}
|
|
}
|
|
|
|
/// 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>> {
|
|
let icon = Self::get_icon(status);
|
|
let status_color = match status {
|
|
Status::Ok => Theme::success(), // Green
|
|
Status::Pending => Theme::highlight(), // Blue
|
|
Status::Warning => Theme::warning(), // Yellow
|
|
Status::Critical => Theme::error(), // Red
|
|
Status::Unknown => Theme::muted_text(), // Gray
|
|
};
|
|
|
|
vec![
|
|
ratatui::text::Span::styled(
|
|
format!("{} ", icon),
|
|
Style::default().fg(status_color).bg(Theme::background()),
|
|
),
|
|
ratatui::text::Span::styled(
|
|
text.to_string(),
|
|
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<'_> {
|
|
Block::default()
|
|
.title(title)
|
|
.borders(Borders::ALL)
|
|
.style(Style::default().fg(Theme::border()).bg(Theme::background()))
|
|
.title_style(
|
|
Style::default()
|
|
.fg(Theme::border_title())
|
|
.bg(Theme::background()),
|
|
)
|
|
}
|
|
|
|
/// Widget block with focus indicator (blue border)
|
|
pub fn focused_widget_block(title: &str) -> Block<'_> {
|
|
Block::default()
|
|
.title(title)
|
|
.borders(Borders::ALL)
|
|
.style(Style::default().fg(Theme::highlight()).bg(Theme::background())) // Blue border for focus
|
|
.title_style(
|
|
Style::default()
|
|
.fg(Theme::highlight()) // Blue title for focus
|
|
.bg(Theme::background()),
|
|
)
|
|
}
|
|
}
|
|
|
|
impl Typography {
|
|
/// Main title style (dashboard header)
|
|
pub fn title() -> Style {
|
|
Style::default()
|
|
.fg(Theme::primary_text())
|
|
.bg(Theme::background())
|
|
}
|
|
|
|
/// Widget title style (panel headers) - bold bright white
|
|
pub fn widget_title() -> Style {
|
|
Style::default()
|
|
.fg(Color::White)
|
|
.bg(Theme::background())
|
|
.add_modifier(Modifier::BOLD)
|
|
}
|
|
|
|
/// Secondary content text
|
|
pub fn secondary() -> Style {
|
|
Style::default()
|
|
.fg(Theme::secondary_text())
|
|
.bg(Theme::background())
|
|
}
|
|
|
|
/// Muted text (inactive items, placeholders) - now bold bright white for headers
|
|
pub fn muted() -> Style {
|
|
Style::default()
|
|
.fg(Color::White)
|
|
.bg(Theme::background())
|
|
.add_modifier(Modifier::BOLD)
|
|
}
|
|
|
|
/// Tree symbols style (blue color)
|
|
pub fn tree() -> Style {
|
|
Style::default()
|
|
.fg(Theme::highlight())
|
|
.bg(Theme::background())
|
|
}
|
|
}
|