refactor: app_data methods re-ordered & renamed

This commit is contained in:
Jack Wills
2023-01-29 01:52:38 +00:00
parent 690bd01ba1
commit c0bb5355d6
5 changed files with 226 additions and 218 deletions
+216 -207
View File
@@ -55,67 +55,6 @@ impl fmt::Display for Header {
} }
impl AppData { impl AppData {
/// Generate a default app_state
pub fn default(args: CliArgs) -> Self {
Self {
args,
containers: StatefulList::new(vec![]),
error: None,
sorted_by: None,
}
}
pub const fn get_sorted(&self) -> Option<(Header, SortedOrder)> {
self.sorted_by
}
pub fn has_containers(&self) -> bool {
self.containers.items.is_empty()
}
pub fn container_title(&self) -> String {
self.containers.get_state_title()
}
/// Select the first container
pub fn containers_start(&mut self) {
self.containers.start();
}
// select the last container
pub fn containers_end(&mut self) {
self.containers.end();
}
/// Select the next container
pub fn containers_next(&mut self) {
self.containers.next();
}
// select the previous container
pub fn containers_previous(&mut self) {
self.containers.previous();
}
/// Remove the sorted header & order, and sort by default - created datetime
pub fn reset_sorted(&mut self) {
self.set_sorted(None);
}
/// Sort containers based on a given header, if headings match, and already ascending, remove sorting
pub fn set_sort_by_header(&mut self, selected_header: Header) {
let mut output = Some((selected_header, SortedOrder::Asc));
if let Some((current_header, order)) = self.get_sorted() {
if current_header == selected_header {
match order {
SortedOrder::Desc => output = None,
SortedOrder::Asc => output = Some((selected_header, SortedOrder::Desc)),
}
}
}
self.set_sorted(output);
}
/// Change the sorted order, also set the selected container state to match new order /// Change the sorted order, also set the selected container state to match new order
fn set_sorted(&mut self, x: Option<(Header, SortedOrder)>) { fn set_sorted(&mut self, x: Option<(Header, SortedOrder)>) {
self.sorted_by = x; self.sorted_by = x;
@@ -137,152 +76,39 @@ impl AppData {
.as_secs() .as_secs()
} }
/// Get the current selected docker command /// Generate a default app_state
/// So know which command to execute pub fn default(args: CliArgs) -> Self {
pub fn selected_docker_command(&self) -> Option<DockerControls> { Self {
self.get_selected_container().and_then(|i| { args,
i.docker_controls.state.selected().and_then(|x| { containers: StatefulList::new(vec![]),
i.docker_controls error: None,
.items sorted_by: None,
.get(x)
.map(std::borrow::ToOwned::to_owned)
})
})
}
/// Get Option of the current selected container
pub fn get_selected_container(&self) -> Option<&ContainerItem> {
self.containers
.state
.selected()
.and_then(|i| self.containers.items.get(i))
}
/// Get Option of the current selected container
pub const fn get_container_items(&self) -> &Vec<ContainerItem> {
&self.containers.items
}
pub fn get_container_state(&mut self) -> &mut ListState {
&mut self.containers.state
}
/// Get mutable Option of the current selected container
fn get_mut_selected_container(&mut self) -> Option<&mut ContainerItem> {
self.containers
.state
.selected()
.and_then(|i| self.containers.items.get_mut(i))
}
/// Get mutable Option of the currently selected container chart data
pub fn get_chart_data(&mut self) -> Option<(CpuTuple, MemTuple)> {
self.containers
.state
.selected()
.and_then(|i| self.containers.items.get_mut(i))
.map(|i| i.get_chart_data())
}
/// Get mutable Vec of current containers logs
pub fn get_logs(&mut self) -> Vec<ListItem<'static>> {
self.containers
.state
.selected()
.and_then(|i| self.containers.items.get_mut(i))
.map_or(vec![], |i| i.logs.to_vec())
}
/// Get mutable Option of the currently selected container Logs state
pub fn get_log_state(&mut self) -> Option<&mut ListState> {
self.containers
.state
.selected()
.and_then(|i| self.containers.items.get_mut(i))
.map(|i| i.logs.state())
}
/// Get mutable Option of the currently selected container DockerControls state
pub fn get_control_state(&mut self) -> Option<&mut ListState> {
self.get_mut_selected_container()
.map(|i| &mut i.docker_controls.state)
}
/// Get mutable Option of the currently selected container DockerControls items
pub fn get_control_items(&mut self) -> Option<&mut Vec<DockerControls>> {
self.get_mut_selected_container()
.map(|i| &mut i.docker_controls.items)
}
/// Get all containers ids
pub fn get_all_ids(&self) -> Vec<ContainerId> {
self.containers
.items
.iter()
.map(|i| i.id.clone())
.collect::<Vec<_>>()
}
/// return a mutable container by given id
fn get_container_by_id(&mut self, id: &ContainerId) -> Option<&mut ContainerItem> {
self.containers.items.iter_mut().find(|i| &i.id == id)
}
/// Change selected choice of docker commands of selected container
pub fn docker_command_next(&mut self) {
if let Some(i) = self.get_mut_selected_container() {
i.docker_controls.next();
} }
} }
/// Change selected choice of docker commands of selected container /// Container sort related methods
pub fn docker_command_previous(&mut self) {
if let Some(i) = self.get_mut_selected_container() { /// Remove the sorted header & order, and sort by default - created datetime
i.docker_controls.previous(); pub fn reset_sorted(&mut self) {
} self.set_sorted(None);
} }
/// Change selected choice of docker commands of selected container /// Sort containers based on a given header, if headings match, and already ascending, remove sorting
pub fn docker_command_start(&mut self) { pub fn set_sort_by_header(&mut self, selected_header: Header) {
if let Some(i) = self.get_mut_selected_container() { let mut output = Some((selected_header, SortedOrder::Asc));
i.docker_controls.start(); if let Some((current_header, order)) = self.get_sorted() {
if current_header == selected_header {
match order {
SortedOrder::Desc => output = None,
SortedOrder::Asc => output = Some((selected_header, SortedOrder::Desc)),
} }
} }
}
self.set_sorted(output);
}
/// Change selected choice of docker commands of selected container pub const fn get_sorted(&self) -> Option<(Header, SortedOrder)> {
pub fn docker_command_end(&mut self) { self.sorted_by
if let Some(i) = self.get_mut_selected_container() {
i.docker_controls.end();
}
}
/// return single app_state error
pub const fn get_error(&self) -> Option<AppError> {
self.error
}
/// remove single app_state error
pub fn remove_error(&mut self) {
self.error = None;
}
/// insert single app_state error
pub fn set_error(&mut self, error: AppError) {
self.error = Some(error);
}
/// Find the id of the currently selected container.
/// If any containers on system, will always return a ContainerId
/// Only returns None when no containers found.
pub fn get_selected_container_id(&self) -> Option<ContainerId> {
self.get_selected_container().map(|i| i.id.clone())
}
/// Check if the selected container is a dockerised version of oxker
/// So that can disallow commands to be send
/// Is a shabby way of implementing this
pub fn selected_container_is_oxker(&self) -> bool {
self.get_selected_container().map_or(false, |i| i.is_oxker)
} }
/// Sort the containers vec, based on a heading, either ascending or descending, /// Sort the containers vec, based on a heading, either ascending or descending,
@@ -360,6 +186,120 @@ impl AppData {
} }
} }
/// Container state methods
/// Just get the total number of containers
pub fn get_container_len(&self) -> usize {
self.containers.items.len()
}
/// Get title for containers section
pub fn container_title(&self) -> String {
self.containers.get_state_title()
}
/// Select the first container
pub fn containers_start(&mut self) {
self.containers.start();
}
// select the last container
pub fn containers_end(&mut self) {
self.containers.end();
}
/// Select the next container
pub fn containers_next(&mut self) {
self.containers.next();
}
// select the previous container
pub fn containers_previous(&mut self) {
self.containers.previous();
}
/// Get Container items
pub const fn get_container_items(&self) -> &Vec<ContainerItem> {
&self.containers.items
}
/// Get Option of the current selected container
pub fn get_selected_container(&self) -> Option<&ContainerItem> {
self.containers
.state
.selected()
.and_then(|i| self.containers.items.get(i))
}
/// Get mutable Option of the current selected container
fn get_mut_selected_container(&mut self) -> Option<&mut ContainerItem> {
self.containers
.state
.selected()
.and_then(|i| self.containers.items.get_mut(i))
}
/// Get ListState of containers
pub fn get_container_state(&mut self) -> &mut ListState {
&mut self.containers.state
}
/// Selected DockerCommand methods
/// Get the current selected docker command
/// So know which command to execute
pub fn selected_docker_command(&self) -> Option<DockerControls> {
self.get_selected_container().and_then(|i| {
i.docker_controls.state.selected().and_then(|x| {
i.docker_controls
.items
.get(x)
.map(std::borrow::ToOwned::to_owned)
})
})
}
/// Get mutable Option of the currently selected container DockerControls state
pub fn get_control_state(&mut self) -> Option<&mut ListState> {
self.get_mut_selected_container()
.map(|i| &mut i.docker_controls.state)
}
/// Get mutable Option of the currently selected container DockerControls items
pub fn get_control_items(&mut self) -> Option<&mut Vec<DockerControls>> {
self.get_mut_selected_container()
.map(|i| &mut i.docker_controls.items)
}
/// Change selected choice of docker commands of selected container
pub fn docker_command_next(&mut self) {
if let Some(i) = self.get_mut_selected_container() {
i.docker_controls.next();
}
}
/// Change selected choice of docker commands of selected container
pub fn docker_command_previous(&mut self) {
if let Some(i) = self.get_mut_selected_container() {
i.docker_controls.previous();
}
}
/// Change selected choice of docker commands of selected container
pub fn docker_command_start(&mut self) {
if let Some(i) = self.get_mut_selected_container() {
i.docker_controls.start();
}
}
/// Change selected choice of docker commands of selected container
pub fn docker_command_end(&mut self) {
if let Some(i) = self.get_mut_selected_container() {
i.docker_controls.end();
}
}
/// Logs related methods
/// Get the title for log panel for selected container, will be either /// Get the title for log panel for selected container, will be either
/// 1) "logs x/x - container_name" where container_name is 32 chars max /// 1) "logs x/x - container_name" where container_name is 32 chars max
/// 2) "logs - container_name" when no logs found, again 32 chars max /// 2) "logs - container_name" when no logs found, again 32 chars max
@@ -405,6 +345,61 @@ impl AppData {
} }
} }
/// Chart data related methods
/// Get mutable Option of the currently selected container chart data
pub fn get_chart_data(&mut self) -> Option<(CpuTuple, MemTuple)> {
self.containers
.state
.selected()
.and_then(|i| self.containers.items.get_mut(i))
.map(|i| i.get_chart_data())
}
/// Logs related methods
/// Get mutable Vec of current containers logs
pub fn get_logs(&mut self) -> Vec<ListItem<'static>> {
self.containers
.state
.selected()
.and_then(|i| self.containers.items.get_mut(i))
.map_or(vec![], |i| i.logs.to_vec())
}
/// Get mutable Option of the currently selected container Logs state
pub fn get_log_state(&mut self) -> Option<&mut ListState> {
self.containers
.state
.selected()
.and_then(|i| self.containers.items.get_mut(i))
.map(|i| i.logs.state())
}
/// Error realted methods
/// return single app_state error
pub const fn get_error(&self) -> Option<AppError> {
self.error
}
/// remove single app_state error
pub fn remove_error(&mut self) {
self.error = None;
}
/// insert single app_state error
pub fn set_error(&mut self, error: AppError) {
self.error = Some(error);
}
/// Check if the selected container is a dockerised version of oxker
/// So that can disallow commands to be send
/// Is a shabby way of implementing this
pub fn is_oxker(&self) -> bool {
self.get_selected_container().map_or(false, |i| i.is_oxker)
}
/// Check if the initial parsing has been completed, by making sure that all ids given (which are running) have a non empty cpu_stats vecdec /// Check if the initial parsing has been completed, by making sure that all ids given (which are running) have a non empty cpu_stats vecdec
pub fn initialised(&mut self, all_ids: &[(bool, ContainerId)]) -> bool { pub fn initialised(&mut self, all_ids: &[(bool, ContainerId)]) -> bool {
let count_is_running = all_ids.iter().filter(|i| i.0).count(); let count_is_running = all_ids.iter().filter(|i| i.0).count();
@@ -417,11 +412,6 @@ impl AppData {
count_is_running == number_with_cpu_status count_is_running == number_with_cpu_status
} }
/// Just get the total number of containers
pub fn get_container_len(&self) -> usize {
self.containers.items.len()
}
/// Find the widths for the strings in the containers panel. /// Find the widths for the strings in the containers panel.
/// So can display nicely and evenly /// So can display nicely and evenly
pub fn get_width(&self) -> Columns { pub fn get_width(&self) -> Columns {
@@ -484,6 +474,20 @@ impl AppData {
columns columns
} }
/// Update related methods
/// return a mutable container by given id
fn get_container_by_id(&mut self, id: &ContainerId) -> Option<&mut ContainerItem> {
self.containers.items.iter_mut().find(|i| &i.id == id)
}
/// Find the id of the currently selected container.
/// If any containers on system, will always return a ContainerId
/// Only returns None when no containers found.
pub fn get_selected_container_id(&self) -> Option<ContainerId> {
self.get_selected_container().map(|i| i.id.clone())
}
/// Update container mem, cpu, & network stats, in single function so only need to call .lock() once /// Update container mem, cpu, & network stats, in single function so only need to call .lock() once
/// Will also, if a sort is set, sort the containers /// Will also, if a sort is set, sort the containers
pub fn update_stats( pub fn update_stats(
@@ -515,14 +519,19 @@ impl AppData {
container.mem_limit.update(mem_limit); container.mem_limit.update(mem_limit);
} }
// need to benchmark this? // need to benchmark this?
if self.get_sorted().is_some() { // if self.get_sorted().is_some() {
self.sort_containers(); self.sort_containers();
} // }
} }
/// Update, or insert, containers /// Update, or insert, containers
pub fn update_containers(&mut self, all_containers: &mut [ContainerSummary]) { pub fn update_containers(&mut self, all_containers: &mut [ContainerSummary]) {
let all_ids = self.get_all_ids(); let all_ids = self
.containers
.items
.iter()
.map(|i| i.id.to_owned())
.collect::<Vec<_>>();
// Only sort it no containers currently set, as afterwards the order is fixed // Only sort it no containers currently set, as afterwards the order is fixed
if self.containers.items.is_empty() { if self.containers.items.is_empty() {
+1 -1
View File
@@ -241,7 +241,7 @@ impl InputHandler {
if let Some(command) = option_command { if let Some(command) = option_command {
let option_id = self.app_data.lock().get_selected_container_id(); let option_id = self.app_data.lock().get_selected_container_id();
// Poor way of disallowing commands to be sent to a containerised okxer // Poor way of disallowing commands to be sent to a containerised okxer
if self.app_data.lock().selected_container_is_oxker() { if self.app_data.lock().is_oxker() {
return; return;
}; };
if let Some(id) = option_id { if let Some(id) = option_id {
+1 -1
View File
@@ -1,7 +1,7 @@
#![forbid(unsafe_code)] #![forbid(unsafe_code)]
#![warn(clippy::unused_async, clippy::unwrap_used, clippy::expect_used)] #![warn(clippy::unused_async, clippy::unwrap_used, clippy::expect_used)]
// Warning - These are indeed pedantic // Warning - These are indeed pedantic
#![warn(clippy::pedantic)] // #![warn(clippy::pedantic)]
#![warn(clippy::nursery)] #![warn(clippy::nursery)]
#![allow( #![allow(
clippy::module_name_repetitions, clippy::module_name_repetitions,
-1
View File
@@ -244,7 +244,6 @@ pub fn logs<B: Backend>(
if let Some(i) = app_data.lock().get_log_state() { if let Some(i) = app_data.lock().get_log_state() {
f.render_stateful_widget(items, area, i); f.render_stateful_widget(items, area, i);
} }
} }
} }
} }
+2 -2
View File
@@ -60,7 +60,7 @@ pub async fn create_ui(
terminal.show_cursor()?; terminal.show_cursor()?;
if let Err(err) = res { if let Err(err) = res {
println!("{err}"); println!("error: {err}");
} }
std::io::stdout().flush().unwrap_or(()); std::io::stdout().flush().unwrap_or(());
Ok(()) Ok(())
@@ -141,7 +141,7 @@ fn ui<B: Backend>(
let height = if height < 12 { height + 4 } else { 12 }; let height = if height < 12 { height + 4 } else { 12 };
let column_widths = app_data.lock().get_width(); let column_widths = app_data.lock().get_width();
let has_containers = !app_data.lock().has_containers(); let has_containers = app_data.lock().get_container_len() > 0;
let has_error = app_data.lock().get_error(); let has_error = app_data.lock().get_error();
let sorted_by = app_data.lock().get_sorted(); let sorted_by = app_data.lock().get_sorted();