From 141d0ee89976434a533a3b81a6419377d35ee48c Mon Sep 17 00:00:00 2001 From: Trevor Merritt Date: Thu, 1 May 2025 09:54:09 -0400 Subject: [PATCH] BUGFIX: Delete works for lists of hosts using popups --- src/tui/mode_monitoring.rs | 117 ++++++++++++++++--------------------- src/tui/ratatui_app.rs | 12 ++++ 2 files changed, 62 insertions(+), 67 deletions(-) diff --git a/src/tui/mode_monitoring.rs b/src/tui/mode_monitoring.rs index 1142410..4bc14f9 100644 --- a/src/tui/mode_monitoring.rs +++ b/src/tui/mode_monitoring.rs @@ -1,16 +1,13 @@ -use std::collections::BTreeMap; -use crate::duration_to_string; +use crate::{duration_to_string}; use color_eyre::Result; use crossterm::event; use crossterm::event::{Event, KeyCode, KeyEventKind}; use ratatui::prelude::*; -use ratatui::widgets::{Block, Borders, Cell, Clear, List, ListItem, ListState, Paragraph, Row, Table, TableState, Wrap}; +use ratatui::widgets::{Block, Borders, Cell, Clear, List, ListItem, Paragraph, Row, Table, TableState}; use ratatui::Frame; use std::time::{Duration, SystemTime}; use ratatui::layout::Flex; -use crate::target_state::TargetState; use crate::tui::ratatui_app::RatatuiApp; -use crate::tui::ratatui_screens::RatatuiScreens::{Adding, Deleting, Editing}; pub struct RatatuiMonitoringMode {} @@ -21,26 +18,18 @@ impl RatatuiMonitoringMode { .iter() .map(|h| Cell::from(*h)); let header = Row::new(headers) - .style(Style::default().fg(Color::Yellow)) + .style(Style::default().fg(Color::Yellow).bold()) .bottom_margin(1); /// Rows let mut rows = vec![]; for (_, current) in state.state.iter() { - let mut name_field = format!("{} ({})", current.name.clone(), current.target.clone()); + let name_field = format!("{:<40}", format!("{} ({})", current.name.clone(), current.target.clone())); - while name_field.len() < 40 { - name_field.push(' '); - } + let name_style = if current.alive { Style::default().fg(Color::Green) } else { Style::default().fg(Color::Red) }; - let name_style = if current.alive { - Style::default().fg(Color::Green) - } else { - Style::default().fg(Color::Red) - }; - - let to_push = vec![ + rows.push(Row::new(vec![ Cell::from(name_field).style(name_style), Cell::from(current.last_rtt.to_string()), Cell::from( @@ -52,9 +41,7 @@ impl RatatuiMonitoringMode { ) ) ) - ]; - - rows.push(Row::new(to_push)); + ])); } /// Table Builder @@ -64,9 +51,9 @@ impl RatatuiMonitoringMode { .title(Line::from(format!("PP v{}", env!("CARGO_PKG_VERSION")))) .borders(Borders::ALL)) .widths(&[ - Constraint::Fill(3), - Constraint::Min(4), - Constraint::Min(30) + Constraint::Fill(2), // Host + Constraint::Min(4), // RTT + Constraint::Min(30) // TIme Since ]) .row_highlight_style( Style::default() @@ -81,77 +68,72 @@ impl RatatuiMonitoringMode { } fn render_logs(frame: &mut Frame, state: &mut RatatuiApp, logs_layout: Rect) { - let mut list_items = vec![]; - for entry in state.get_log_entries(10) { - list_items.push(ListItem::new(entry)); - } + let list_items: Vec = state + .get_log_entries(10) + .iter() + .map(|entry| ListItem::new(entry.clone())) + .collect(); - let list = List::new(list_items) - .block(Block::default().title("Logs").borders(Borders::ALL)) - .highlight_style( - Style::default() - .fg(Color::Yellow) - .add_modifier(Modifier::BOLD), - ); // Log - frame.render_widget(list, logs_layout); - + frame.render_widget(List::new(list_items) + .block(Block::default() + .title("Logs") + .borders(Borders::ALL)) + .highlight_style( + Style::default() + .fg(Color::Yellow) + .add_modifier(Modifier::BOLD), + ), logs_layout); } fn render_footer_block(frame: &mut Frame, footer_layout: Rect) { - // let footer_text = "Press or q to exit"; - let footer_text = "Press or q to exit | Press d to delete host | Press a to add host"; - frame.render_widget( - Paragraph::new(footer_text) + Paragraph::new("Press or q to exit | Press d to delete host | Press a to add host") .block(Block::bordered()) .centered(), footer_layout, ); - } pub fn render(frame: &mut Frame, state: &mut RatatuiApp) { let layouts = Layout::default() .direction(Direction::Vertical) .constraints([ - Constraint::Fill(1), - Constraint::Length(10), - Constraint::Length(3), + Constraint::Fill(1), // Top Bar + Constraint::Length(10), // Hosts + Constraint::Length(3), // Logs ]) .split(frame.area()); - Self::render_hosts_list(frame, state, layouts[0]); + Self::render_hosts_list(frame, state, layouts[0]); Self::render_logs(frame, state, layouts[1]); Self::render_footer_block(frame, layouts[2]); - Self::add_popup(state, frame); - Self::exit_popup(state, frame); - Self::delete_popup(state, frame); + Self::add_popup(frame, state); + Self::exit_popup(frame, state); + Self::delete_popup(frame, state); } - fn add_popup(state: &RatatuiApp, frame: &mut Frame) { + fn add_popup(frame: &mut Frame, state: &RatatuiApp) { if state.showing_add_popup { - let block = Block::bordered().title("Add Host"); let area = RatatuiMonitoringMode::popup_area(frame.area(), 60, 20); frame.render_widget(Clear, area); - frame.render_widget(block, area); + frame.render_widget(Block::bordered().title("Add Host"), area); } } - fn exit_popup(state: &RatatuiApp, frame: &mut Frame) { + fn exit_popup(frame: &mut Frame, state: &RatatuiApp) { if state.trying_to_exit { - let block = Paragraph::new("Are you sure? (Y/N)") - .block(Block::bordered().title("Exit")); let area = RatatuiMonitoringMode::popup_area(frame.area(), 60, 20); frame.render_widget(Clear, area); - frame.render_widget(block, area); + frame.render_widget(Paragraph::new("Are you sure? (Y/N)") + .block(Block::bordered().title("Exit")), area); } } - fn delete_popup(state: &RatatuiApp, frame: &mut Frame) { - if state.trying_to_delete { + fn delete_popup(frame: &mut Frame, state: &RatatuiApp) { + if state.trying_to_delete { let as_list = state.state.clone(); let mut host_name = String::new(); for (index, (label, _)) in as_list.iter().enumerate() { @@ -179,13 +161,13 @@ impl RatatuiMonitoringMode { match key { KeyCode::Esc => { app.showing_add_popup = false; - }, + } KeyCode::Backspace => { app.add_host_name.remove(app.add_host_name.len()); - }, + } KeyCode::Enter => { dbg!("SAVE THE VALUE TO A NEW TARGETSTATE"); - }, + } _ => { app.add_host_name = format!("{}{}", app.add_host_name, key); } @@ -224,11 +206,11 @@ impl RatatuiMonitoringMode { KeyCode::Esc | KeyCode::Char('q') | KeyCode::Char('Q') => { app.trying_to_exit = true; } - KeyCode::Char('a') | KeyCode::Char('A') => { + KeyCode::Char('a') | KeyCode::Char('A') => { app.showing_add_popup = true; } - KeyCode::Char('d') | KeyCode::Char('D') => { - app.trying_to_delete = true; + KeyCode::Char('d') | KeyCode::Char('D') => { + app.trying_to_delete = true; } _ => {} } @@ -237,12 +219,13 @@ impl RatatuiMonitoringMode { fn handle_delete_popup_inputs(app: &mut RatatuiApp, key: KeyCode) { match key { KeyCode::Char('y') | KeyCode::Char('Y') => { - // app.remove_selected_host(); - dbg!("Delete this item."); - }, + app.remove_selected_host(); + app.trying_to_delete = false; + } KeyCode::Char('n') | KeyCode::Char('N') => { dbg!("Do not delete this item."); - }, + app.trying_to_delete = false; + } _ => {} } } diff --git a/src/tui/ratatui_app.rs b/src/tui/ratatui_app.rs index a5075a6..df96281 100644 --- a/src/tui/ratatui_app.rs +++ b/src/tui/ratatui_app.rs @@ -21,6 +21,8 @@ use std::sync::mpsc::Receiver; use std::thread; use std::time::{Duration, SystemTime}; +const LOG_ENTRIES_DEFAULT_COUNT: u32 = 10; + #[derive(Default)] pub struct RatatuiApp { running: bool, @@ -34,10 +36,19 @@ pub struct RatatuiApp { pub trying_to_delete: bool, pub add_host_cursor_position: usize, pub add_host_name: String, + pub num_log_entries: u32 } /// Private Methods impl RatatuiApp { + pub fn remove_selected_host(self: &mut RatatuiApp) { + for (index, (name, data)) in self.state.clone().iter().enumerate() { + if index == self.selected_host { + self.state.remove(name).unwrap(); + } + } + } + pub fn set_filename(mut self, new_filename: String) { self.filename = Some(new_filename) } @@ -218,6 +229,7 @@ impl RatatuiApp { } }; working.state = targets.clone(); + working.num_log_entries = LOG_ENTRIES_DEFAULT_COUNT; working }