wip: sort by

This commit is contained in:
Jack Wills
2022-07-22 16:33:40 +00:00
parent dc4a62910c
commit d14744b378
6 changed files with 258 additions and 166 deletions
+34 -31
View File
@@ -5,9 +5,12 @@ use tui::{
widgets::{ListItem, ListState},
};
use super::Header;
#[derive(Debug, Clone)]
pub struct StatefulList<T> {
pub state: ListState,
// HASH MAP!
pub items: Vec<T>,
}
@@ -114,18 +117,18 @@ impl State {
_ => Color::Red,
}
}
pub fn as_text(&self) -> &'static str {
match self {
Self::Dead => "dead",
Self::Exited => "exited",
Self::Paused => "paused",
Self::Removing => "removing",
Self::Restarting => "restarting",
Self::Running => "running",
Self::Unknown => "unknown",
}
}
}
pub fn as_text(&self) -> &'static str {
match self {
Self::Dead => "dead",
Self::Exited => "exited",
Self::Paused => "paused",
Self::Removing => "removing",
Self::Restarting => "restarting",
Self::Running => "running",
Self::Unknown => "unknown",
}
}
}
impl From<&str> for State {
fn from(input: &str) -> Self {
@@ -420,31 +423,31 @@ impl ContainerItem {
/// Container information panel headings + widths, for nice pretty formatting
#[derive(Debug)]
pub struct Columns {
pub state: (String, usize),
pub status: (String, usize),
pub cpu: (String, usize),
pub mem: (String, usize),
pub id: (String, usize),
pub name: (String, usize),
pub image: (String, usize),
pub net_rx: (String, usize),
pub net_tx: (String, usize),
pub state: (Header, usize),
pub status: (Header, usize),
pub cpu: (Header, usize),
pub mem: (Header, usize),
pub id: (Header, usize),
pub name: (Header, usize),
pub image: (Header, usize),
pub net_rx: (Header, usize),
pub net_tx: (Header, usize),
}
impl Columns {
//. (Column titles, minimum header string length)
// (Column titles, minimum header string length)
pub fn new() -> Self {
Self {
state: (String::from("state"), 11),
status: (String::from("status"), 16),
state: (Header::State, 11),
status: (Header::Status, 16),
// 7 to allow for "100.00%"
cpu: (String::from("cpu"), 7),
mem: (String::from("memory/limit"), 12),
id: (String::from("id"), 8),
name: (String::from("name"), 4),
image: (String::from("image"), 5),
net_rx: (String::from("↓ rx"), 5),
net_tx: (String::from("↑ tx"), 5),
cpu: (Header::Cpu, 7),
mem: (Header::Memory, 12),
id: (Header::Id, 8),
name: (Header::Name, 4),
image: (Header::Image, 5),
net_rx: (Header::Rx, 5),
net_tx: (Header::Tx, 5),
}
}
}
+136 -96
View File
@@ -1,4 +1,5 @@
use bollard::models::ContainerSummary;
use core::fmt;
use std::time::{SystemTime, UNIX_EPOCH};
use tui::widgets::ListItem;
@@ -16,31 +17,58 @@ pub struct AppData {
pub containers: StatefulList<ContainerItem>,
pub init: bool,
pub show_error: bool,
// todo
sort_by: Header
sorted_by: Option<(Header, SortedOrder)>,
}
#[derive(Debug, Clone)]
pub enum SortedOrder{
Asc,
Desc
pub enum SortedOrder {
Asc,
Desc,
}
#[derive(Debug, Clone)]
pub enum Header{
State,
Status,
Cpu,
Memory,
Id,
Name,
Image,
Rx,
Tx
#[derive(Debug, Clone, PartialEq)]
pub enum Header {
State,
Status,
Cpu,
Memory,
Id,
Name,
Image,
Rx,
Tx,
}
/// Convert errors into strings to display
impl fmt::Display for Header {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let disp = match self {
Self::State => "state",
Self::Status => "status",
Self::Cpu => "cpu",
Self::Memory => "memory/limit",
Self::Id => "id",
Self::Name => "name",
Self::Image => "image",
Self::Rx => "↓ rx",
Self::Tx => "↑ tx",
};
write!(f, "{:>x$}", disp, x = f.width().unwrap_or(1))
}
}
impl AppData {
pub fn get_sorted(&self) -> Option<(Header, SortedOrder)> {
self.sorted_by.clone()
}
/// Change the sorted order, also set the selected pointer!
pub fn set_sorted(&mut self, x: Option<(Header, SortedOrder)>) {
self.sorted_by = x;
let id = self.get_selected_container_id();
self.sort_containers();
self.containers.state.select(self.containers.items.iter().position(|i| Some(i.id.to_owned()) == id));
}
/// Generate a default app_state
pub fn default(args: CliArgs) -> Self {
Self {
@@ -50,7 +78,7 @@ impl AppData {
init: false,
logs_parsed: false,
show_error: false,
sort_by: Header::Memory,
sorted_by: Some((Header::Memory, SortedOrder::Asc)),
}
}
@@ -141,85 +169,97 @@ impl AppData {
output
}
pub fn sort_containers(&mut self, so: SortedOrder) {
// State,
// Status,
// Cpu,
// Memory,
// Id,
// Name,
// Image,
// Rx,
// Tx
match self.sort_by {
Header::State => {
match so {
SortedOrder::Asc => self.containers.items.sort_by(|a,b|a.state.as_text().cmp(b.state.as_text())),
SortedOrder::Desc => self.containers.items.sort_by(|a,b|b.state.as_text().cmp(a.state.as_text())),
}
},
Header::Status => {
match so {
SortedOrder::Asc => self.containers.items.sort_by(|a,b|a.status.cmp(&b.status)),
SortedOrder::Desc => self.containers.items.sort_by(|a,b|b.status.cmp(&a.status)),
}
},
Header::Status => {
match so {
SortedOrder::Asc => self.containers.items.sort_by(|a,b|a.status.cmp(&b.status)),
SortedOrder::Desc => self.containers.items.sort_by(|a,b|b.status.cmp(&a.status)),
}
},
Header::Cpu => {
match so {
SortedOrder::Desc =>
self.containers.items.sort_by(|a,b|a.cpu_stats.back().cmp(&b.cpu_stats.back())),
SortedOrder::Asc => self.containers.items.sort_by(|a,b|b.cpu_stats.back().cmp(&a.cpu_stats.back()))
}
},
Header::Memory => {
match so {
SortedOrder::Desc =>
self.containers.items.sort_by(|a,b|a.mem_stats.back().cmp(&b.mem_stats.back())),
SortedOrder::Asc => self.containers.items.sort_by(|a,b|b.mem_stats.back().cmp(&a.mem_stats.back()))
}
},
Header::Image => {
match so {
SortedOrder::Asc => self.containers.items.sort_by(|a,b|a.image.cmp(&b.image)),
SortedOrder::Desc => self.containers.items.sort_by(|a,b|b.image.cmp(&a.image)),
}
},
Header::Name => {
match so {
SortedOrder::Asc => self.containers.items.sort_by(|a,b|a.name.cmp(&b.name)),
SortedOrder::Desc => self.containers.items.sort_by(|a,b|b.name.cmp(&a.name)),
}
},
_ => ()
}
}
// match so {
// SortedOrder::Asc => self.containers.items.sort_by(|a,b|b.name.cmp(&a.name)),
// SortedOrder::Desc => self.containers.items.sort_by(|a,b|a.name.cmp(&b.name))
// }
// }
pub fn sort_by_id(&mut self, so: SortedOrder) {
match so {
SortedOrder::Asc => self.containers.items.sort_by(|a,b|b.id.cmp(&a.id)),
SortedOrder::Desc => self.containers.items.sort_by(|a,b|a.id.cmp(&b.id))
}
}
/// Sort the containers vec, based on a heading, either ascending or descending
pub fn sort_containers(&mut self) {
if let Some((head, so)) = self.sorted_by.as_ref() {
match head {
Header::State => match so {
SortedOrder::Asc => self
.containers
.items
.sort_by(|a, b| a.state.as_text().cmp(b.state.as_text())),
SortedOrder::Desc => self
.containers
.items
.sort_by(|a, b| b.state.as_text().cmp(a.state.as_text())),
},
Header::Status => match so {
SortedOrder::Asc => self
.containers
.items
.sort_by(|a, b| a.status.cmp(&b.status)),
SortedOrder::Desc => self
.containers
.items
.sort_by(|a, b| b.status.cmp(&a.status)),
},
Header::Status => match so {
SortedOrder::Asc => self
.containers
.items
.sort_by(|a, b| a.status.cmp(&b.status)),
SortedOrder::Desc => self
.containers
.items
.sort_by(|a, b| b.status.cmp(&a.status)),
},
Header::Cpu => match so {
SortedOrder::Desc => self
.containers
.items
.sort_by(|a, b| a.cpu_stats.back().cmp(&b.cpu_stats.back())),
SortedOrder::Asc => self
.containers
.items
.sort_by(|a, b| b.cpu_stats.back().cmp(&a.cpu_stats.back())),
},
Header::Memory => match so {
SortedOrder::Desc => self
.containers
.items
.sort_by(|a, b| a.mem_stats.back().cmp(&b.mem_stats.back())),
SortedOrder::Asc => self
.containers
.items
.sort_by(|a, b| b.mem_stats.back().cmp(&a.mem_stats.back())),
},
Header::Id => match so {
SortedOrder::Asc => self.containers.items.sort_by(|a, b| a.id.cmp(&b.id)),
SortedOrder::Desc => self.containers.items.sort_by(|a, b| b.id.cmp(&a.id)),
},
Header::Image => match so {
SortedOrder::Asc => self.containers.items.sort_by(|a, b| a.image.cmp(&b.image)),
SortedOrder::Desc => {
self.containers.items.sort_by(|a, b| b.image.cmp(&a.image))
}
},
Header::Name => match so {
SortedOrder::Asc => self.containers.items.sort_by(|a, b| a.name.cmp(&b.name)),
SortedOrder::Desc => self.containers.items.sort_by(|a, b| b.name.cmp(&a.name)),
},
Header::Rx => match so {
SortedOrder::Asc => self
.containers
.items
.sort_by(|a, b| a.net_rx.cmp(&b.net_rx)),
SortedOrder::Desc => self
.containers
.items
.sort_by(|a, b| b.net_rx.cmp(&a.net_rx)),
},
Header::Tx => match so {
SortedOrder::Asc => self
.containers
.items
.sort_by(|a, b| a.net_tx.cmp(&b.net_tx)),
SortedOrder::Desc => self
.containers
.items
.sort_by(|a, b| b.net_tx.cmp(&a.net_tx)),
},
}
}
}
/// Find the index of the currently selected single log line
pub fn get_selected_log_index(&self) -> Option<usize> {