From 87990d12b52c0da17a0781a33224c61aa09af516 Mon Sep 17 00:00:00 2001 From: ChristianVisintin Date: Sun, 29 Nov 2020 13:01:12 +0100 Subject: [PATCH] draw log list --- Cargo.lock | 52 +++++++++++++++- Cargo.toml | 1 + src/ui/activities/filetransfer_activity.rs | 71 +++++++++++----------- src/utils.rs | 20 ++++++ 4 files changed, 109 insertions(+), 35 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7ba7516..a42d5a6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -36,6 +36,19 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chrono" +version = "0.4.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" +dependencies = [ + "libc", + "num-integer", + "num-traits", + "time", + "winapi", +] + [[package]] name = "cloudabi" version = "0.0.3" @@ -112,7 +125,7 @@ checksum = "fc587bc0ec293155d5bfa6b9891ec18a1e330c234f896ea47fbada4cadbe47e6" dependencies = [ "cfg-if 0.1.10", "libc", - "wasi", + "wasi 0.9.0+wasi-snapshot-preview1", ] [[package]] @@ -221,6 +234,25 @@ dependencies = [ "winapi", ] +[[package]] +name = "num-integer" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +dependencies = [ + "autocfg", +] + [[package]] name = "openssl-sys" version = "0.9.58" @@ -436,6 +468,7 @@ dependencies = [ name = "termscp" version = "0.1.0" dependencies = [ + "chrono", "crossterm 0.18.2", "getopts", "rpassword", @@ -447,6 +480,17 @@ dependencies = [ "whoami", ] +[[package]] +name = "time" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" +dependencies = [ + "libc", + "wasi 0.10.0+wasi-snapshot-preview1", + "winapi", +] + [[package]] name = "tui" version = "0.12.0" @@ -494,6 +538,12 @@ version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" +[[package]] +name = "wasi" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + [[package]] name = "whoami" version = "0.9.0" diff --git a/Cargo.toml b/Cargo.toml index a971f9f..25c110b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,6 +23,7 @@ users = "0.11.0" whoami = "0.9.0" rpassword = "5.0.0" unicode-width = "0.1.7" +chrono = "0.4.19" [dev-dependencies] tempfile = "3" diff --git a/src/ui/activities/filetransfer_activity.rs b/src/ui/activities/filetransfer_activity.rs index 4d15e7c..3df4dc6 100644 --- a/src/ui/activities/filetransfer_activity.rs +++ b/src/ui/activities/filetransfer_activity.rs @@ -24,6 +24,7 @@ */ // Dependencies +extern crate chrono; extern crate crossterm; extern crate tui; extern crate unicode_width; @@ -31,6 +32,7 @@ extern crate unicode_width; // locals use super::{Activity, Context}; use crate::filetransfer::FileTransferProtocol; +use crate::utils::time_to_str; // File transfer use crate::filetransfer::sftp_transfer::SftpFileTransfer; @@ -38,16 +40,16 @@ use crate::filetransfer::FileTransfer; use crate::fs::FsEntry; // Includes +use chrono::{DateTime, Local}; use crossterm::event::Event as InputEvent; use crossterm::event::{KeyCode, KeyModifiers}; use crossterm::terminal::{disable_raw_mode, enable_raw_mode}; use std::collections::VecDeque; -use std::io::Stdout; use std::path::{Path, PathBuf}; use std::time::Instant; use tui::{ backend::CrosstermBackend, - layout::{Constraint, Direction, Layout, Rect}, + layout::{Constraint, Corner, Direction, Layout, Rect}, style::{Color, Modifier, Style}, terminal::Frame, text::{Span, Spans, Text}, @@ -173,7 +175,7 @@ enum LogLevel { /// /// Log record entry struct LogRecord { - pub time: Instant, + pub time: DateTime, pub level: LogLevel, pub msg: String, } @@ -184,7 +186,7 @@ impl LogRecord { /// Instantiates a new LogRecord pub fn new(level: LogLevel, msg: &str) -> LogRecord { LogRecord { - time: Instant::now(), + time: Local::now(), level: level, msg: String::from(msg), } @@ -1480,42 +1482,43 @@ impl FileTransferActivity { .style(Style::default().fg(Color::LightYellow).add_modifier(Modifier::BOLD)) } - /* /// ### draw_log_list /// /// Draw log list fn draw_log_list(&self) -> List { - let events: Vec = self.log_records + let events: Vec = self + .log_records .iter() - .map(|&(evt, level)| { - let s = match level { - "CRITICAL" => Style::default().fg(Color::Red), - "ERROR" => Style::default().fg(Color::Magenta), - "WARNING" => Style::default().fg(Color::Yellow), - "INFO" => Style::default().fg(Color::Blue), - _ => Style::default(), - }; - let header = Spans::from(vec![ - Span::styled(format!("{:<9}", level), s), - Span::raw(" "), - Span::styled( - "2020-01-01 10:00:00", - Style::default().add_modifier(Modifier::ITALIC), + .map(|record: &LogRecord| { + let s = match record.level { + LogLevel::Error => Style::default().fg(Color::Red), + LogLevel::Warn => Style::default().fg(Color::Yellow), + LogLevel::Info => Style::default().fg(Color::Green), + }; + let header = Spans::from(vec![ + Span::raw("["), + Span::styled( + format!( + "{:<6}", + match record.level { + LogLevel::Error => "ERROR", + LogLevel::Warn => "WARN", + LogLevel::Info => "INFO", + } ), - ]); - let log = Spans::from(vec![Span::raw(evt)]); - ListItem::new(vec![ - Spans::from("-".repeat(chunks[1].width as usize)), - header, - Spans::from(""), - log, - ]) - }) - .collect(); - let events_list = List::new(events) - .block(Block::default().borders(Borders::ALL).title("List")) - .start_corner(Corner::BottomLeft); - }*/ + s, + ), + Span::raw("] "), + Span::from(format!("{}", record.time.format("%Y-%m-%dT%H:%M:%S%Z"))), + ]); + let log = Spans::from(vec![Span::from(record.msg.clone())]); + ListItem::new(vec![header, log]) + }) + .collect(); + List::new(events) + .block(Block::default().borders(Borders::ALL).title("Log")) + .start_corner(Corner::BottomLeft) + } /// ### draw_footer /// diff --git a/src/utils.rs b/src/utils.rs index 24a8eda..05aae5c 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -24,10 +24,14 @@ */ // Dependencies +extern crate chrono; extern crate whoami; use crate::filetransfer::FileTransferProtocol; +use chrono::prelude::*; +use std::time::SystemTime; + /// ### parse_remote_opt /// /// Parse remote option string. Returns in case of success a tuple made of (address, port, protocol, username) @@ -119,6 +123,16 @@ pub fn parse_remote_opt( Ok((address, port, protocol, username)) } +/// ### instant_to_str +/// +/// Format a `Instant` into a time string +pub fn time_to_str(time: SystemTime, fmt: &str) -> String { + let datetime: DateTime = time.into(); + // Format the datetime how you want + let newdate = datetime.to_rfc3339_opts(SecondsFormat::Secs, true); + format!("{}", datetime.format(fmt)) +} + #[cfg(test)] mod tests { @@ -175,4 +189,10 @@ mod tests { assert!(parse_remote_opt(&String::from("172.26.104.1:abc")).is_err()); // Bad port } + #[test] + fn test_utils_time_to_str() { + let system_time: SystemTime = SystemTime::from(SystemTime::UNIX_EPOCH); + assert_eq!(time_to_str(system_time, "%Y-%m-%d"), String::from("1970-01-01")); + } + }