571 lines
18 KiB
Rust
571 lines
18 KiB
Rust
use std::sync::Arc;
|
|
|
|
use parking_lot::Mutex;
|
|
use ratatui::{
|
|
Frame,
|
|
layout::{Alignment, Rect},
|
|
style::{Modifier, Style, Stylize},
|
|
widgets::{List, Paragraph},
|
|
};
|
|
|
|
use crate::{
|
|
app_data::AppData,
|
|
config::AppColors,
|
|
ui::{FrameData, GuiState, SelectablePanel, Status},
|
|
};
|
|
|
|
use super::{RIGHT_ARROW, generate_block};
|
|
|
|
/// Draw the logs panel
|
|
pub fn draw(
|
|
app_data: &Arc<Mutex<AppData>>,
|
|
area: Rect,
|
|
colors: AppColors,
|
|
f: &mut Frame,
|
|
fd: &FrameData,
|
|
gui_state: &Arc<Mutex<GuiState>>,
|
|
) {
|
|
let mut block = generate_block(area, colors, fd, gui_state, SelectablePanel::Logs);
|
|
if !fd.color_logs {
|
|
block = block.bg(colors.logs.background);
|
|
}
|
|
|
|
if fd.status.contains(&Status::Init) {
|
|
let mut paragraph = Paragraph::new(format!("parsing logs {}", fd.loading_icon))
|
|
.block(block)
|
|
.alignment(Alignment::Center);
|
|
if !fd.color_logs {
|
|
paragraph = paragraph.fg(colors.logs.text);
|
|
}
|
|
f.render_widget(paragraph, area);
|
|
} else {
|
|
let logs = app_data.lock().get_logs();
|
|
if logs.is_empty() {
|
|
let mut paragraph = Paragraph::new("no logs found")
|
|
.block(block)
|
|
.alignment(Alignment::Center);
|
|
if !fd.color_logs {
|
|
paragraph = paragraph.fg(colors.logs.text);
|
|
}
|
|
f.render_widget(paragraph, area);
|
|
} else if fd.color_logs {
|
|
let items = List::new(logs)
|
|
.block(block)
|
|
.highlight_symbol(RIGHT_ARROW)
|
|
.highlight_style(Style::default().add_modifier(Modifier::BOLD));
|
|
// This should always return Some, as logs is not empty
|
|
if let Some(log_state) = app_data.lock().get_log_state() {
|
|
f.render_stateful_widget(items, area, log_state);
|
|
}
|
|
} else {
|
|
let items = List::new(logs)
|
|
.fg(colors.logs.text)
|
|
.block(block)
|
|
.highlight_symbol(RIGHT_ARROW)
|
|
.highlight_style(Style::default().add_modifier(Modifier::BOLD));
|
|
// This should always return Some, as logs is not empty
|
|
if let Some(log_state) = app_data.lock().get_log_state() {
|
|
f.render_stateful_widget(items, area, log_state);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
#[allow(clippy::unwrap_used)]
|
|
mod tests {
|
|
use insta::assert_snapshot;
|
|
use ratatui::style::{Color, Modifier};
|
|
use uuid::Uuid;
|
|
|
|
use crate::{
|
|
app_data::{ContainerImage, ContainerName},
|
|
config::AppColors,
|
|
ui::{
|
|
FrameData, Status,
|
|
draw_blocks::tests::{BORDER_CHARS, get_result, insert_logs, test_setup},
|
|
},
|
|
};
|
|
|
|
#[test]
|
|
/// No logs, panel unselected, then selected, border color changes correctly
|
|
fn test_draw_blocks_logs_none() {
|
|
let mut setup = test_setup(35, 6, true, true);
|
|
|
|
let colors = setup.app_data.lock().config.app_colors;
|
|
|
|
setup
|
|
.terminal
|
|
.draw(|f| {
|
|
super::draw(
|
|
&setup.app_data,
|
|
setup.area,
|
|
colors,
|
|
f,
|
|
&setup.fd,
|
|
&setup.gui_state,
|
|
);
|
|
})
|
|
.unwrap();
|
|
assert_snapshot!(setup.terminal.backend());
|
|
|
|
for (row_index, result_row) in get_result(&setup) {
|
|
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
|
|
match (row_index, result_cell_index) {
|
|
(0 | 5, 0..=34) | (1..=4, 0) | (1..=5, 34) => {
|
|
assert_eq!(result_cell.bg, Color::Reset);
|
|
assert_eq!(result_cell.fg, Color::Gray);
|
|
}
|
|
_ => {
|
|
assert_eq!(result_cell.fg, Color::Reset);
|
|
assert_eq!(result_cell.bg, Color::Reset);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
setup
|
|
.gui_state
|
|
.lock()
|
|
.selectable_panel_next(&setup.app_data);
|
|
setup
|
|
.gui_state
|
|
.lock()
|
|
.selectable_panel_next(&setup.app_data);
|
|
let fd = FrameData::from((&setup.app_data, &setup.gui_state));
|
|
|
|
// When selected, has a blue border
|
|
setup
|
|
.terminal
|
|
.draw(|f| {
|
|
super::draw(
|
|
&setup.app_data,
|
|
setup.area,
|
|
colors,
|
|
f,
|
|
&fd,
|
|
&setup.gui_state,
|
|
);
|
|
})
|
|
.unwrap();
|
|
|
|
for (_, result_row) in get_result(&setup) {
|
|
for result_cell in result_row {
|
|
if BORDER_CHARS.contains(&result_cell.symbol()) {
|
|
assert_eq!(result_cell.fg, Color::LightCyan);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
/// Parsing logs, first frame spinner visible
|
|
fn test_draw_blocks_logs_parsing_frame_one() {
|
|
let mut setup = test_setup(32, 6, true, true);
|
|
let uuid = Uuid::new_v4();
|
|
setup.gui_state.lock().next_loading(uuid);
|
|
|
|
let mut fd = FrameData::from((&setup.app_data, &setup.gui_state));
|
|
fd.status.insert(Status::Init);
|
|
|
|
setup
|
|
.terminal
|
|
.draw(|f| {
|
|
super::draw(
|
|
&setup.app_data,
|
|
setup.area,
|
|
AppColors::new(),
|
|
f,
|
|
&fd,
|
|
&setup.gui_state,
|
|
);
|
|
})
|
|
.unwrap();
|
|
|
|
assert_snapshot!(setup.terminal.backend());
|
|
for (row_index, result_row) in get_result(&setup) {
|
|
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
|
|
match (row_index, result_cell_index) {
|
|
(0, 0..=31) | (1..=4, 0) | (1..=5, 31) | (5, 0..=30) => {
|
|
assert_eq!(result_cell.bg, Color::Reset);
|
|
assert_eq!(result_cell.fg, Color::Gray);
|
|
}
|
|
_ => {
|
|
assert_eq!(result_cell.fg, Color::Reset);
|
|
assert_eq!(result_cell.bg, Color::Reset);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#[test]
|
|
/// Parsing logs, second frame spinner visible
|
|
fn test_draw_blocks_logs_parsing_frame_two() {
|
|
let mut setup = test_setup(32, 6, true, true);
|
|
let uuid = Uuid::new_v4();
|
|
setup.gui_state.lock().next_loading(uuid);
|
|
|
|
let mut fd = FrameData::from((&setup.app_data, &setup.gui_state));
|
|
fd.status.insert(Status::Init);
|
|
|
|
// animation moved by one frame
|
|
setup.gui_state.lock().next_loading(uuid);
|
|
|
|
let mut fd = FrameData::from((&setup.app_data, &setup.gui_state));
|
|
fd.status.insert(Status::Init);
|
|
setup
|
|
.terminal
|
|
.draw(|f| {
|
|
super::draw(
|
|
&setup.app_data,
|
|
setup.area,
|
|
AppColors::new(),
|
|
f,
|
|
&fd,
|
|
&setup.gui_state,
|
|
);
|
|
})
|
|
.unwrap();
|
|
|
|
assert_snapshot!(setup.terminal.backend());
|
|
|
|
for (row_index, result_row) in get_result(&setup) {
|
|
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
|
|
match (row_index, result_cell_index) {
|
|
(0, 0..=31) | (1..=4, 0) | (1..=5, 31) | (5, 0..=30) => {
|
|
assert_eq!(result_cell.bg, Color::Reset);
|
|
assert_eq!(result_cell.fg, Color::Gray);
|
|
}
|
|
_ => {
|
|
assert_eq!(result_cell.fg, Color::Reset);
|
|
assert_eq!(result_cell.bg, Color::Reset);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
/// Logs correct displayed, changing log state also draws correctly
|
|
fn test_draw_blocks_logs_some_line_three() {
|
|
let mut setup = test_setup(36, 6, true, true);
|
|
|
|
insert_logs(&setup);
|
|
|
|
let fd = FrameData::from((&setup.app_data, &setup.gui_state));
|
|
setup
|
|
.terminal
|
|
.draw(|f| {
|
|
super::draw(
|
|
&setup.app_data,
|
|
setup.area,
|
|
AppColors::new(),
|
|
f,
|
|
&fd,
|
|
&setup.gui_state,
|
|
);
|
|
})
|
|
.unwrap();
|
|
|
|
assert_snapshot!(setup.terminal.backend());
|
|
for (row_index, result_row) in get_result(&setup) {
|
|
// let expected_row = expected_to_vec(&expected, row_index);
|
|
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
|
|
// assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
|
|
assert_eq!(result_cell.bg, Color::Reset);
|
|
if let (1..=4, 1..=34) = (row_index, result_cell_index) {
|
|
assert_eq!(result_cell.fg, Color::Reset);
|
|
} else {
|
|
assert_eq!(result_cell.fg, Color::Gray);
|
|
}
|
|
if row_index == 3 && (1..=34).contains(&result_cell_index) {
|
|
assert_eq!(result_cell.modifier, Modifier::BOLD);
|
|
} else {
|
|
assert!(result_cell.modifier.is_empty());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#[test]
|
|
/// Logs correct displayed, changing log state also draws correctly
|
|
fn test_draw_blocks_logs_some_line_two() {
|
|
let mut setup = test_setup(36, 6, true, true);
|
|
|
|
insert_logs(&setup);
|
|
|
|
let fd = FrameData::from((&setup.app_data, &setup.gui_state));
|
|
setup
|
|
.terminal
|
|
.draw(|f| {
|
|
super::draw(
|
|
&setup.app_data,
|
|
setup.area,
|
|
AppColors::new(),
|
|
f,
|
|
&fd,
|
|
&setup.gui_state,
|
|
);
|
|
})
|
|
.unwrap();
|
|
setup.app_data.lock().log_previous();
|
|
let fd = FrameData::from((&setup.app_data, &setup.gui_state));
|
|
|
|
setup
|
|
.terminal
|
|
.draw(|f| {
|
|
super::draw(
|
|
&setup.app_data,
|
|
setup.area,
|
|
AppColors::new(),
|
|
f,
|
|
&fd,
|
|
&setup.gui_state,
|
|
);
|
|
})
|
|
.unwrap();
|
|
|
|
assert_snapshot!(setup.terminal.backend());
|
|
|
|
for (row_index, result_row) in get_result(&setup) {
|
|
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
|
|
assert_eq!(result_cell.bg, Color::Reset);
|
|
if let (1..=4, 1..=34) = (row_index, result_cell_index) {
|
|
assert_eq!(result_cell.fg, Color::Reset);
|
|
} else {
|
|
assert_eq!(result_cell.fg, Color::Gray);
|
|
}
|
|
if row_index == 2 && (1..=34).contains(&result_cell_index) {
|
|
assert_eq!(result_cell.modifier, Modifier::BOLD);
|
|
} else {
|
|
assert!(result_cell.modifier.is_empty());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
/// Full (long) name displayed in logs border
|
|
fn test_draw_blocks_logs_long_name() {
|
|
let mut setup = test_setup(80, 6, true, true);
|
|
setup.app_data.lock().containers.items[0].name =
|
|
ContainerName::from("a_long_container_name_for_the_purposes_of_this_test");
|
|
setup.app_data.lock().containers.items[0].image =
|
|
ContainerImage::from("a_long_image_name_for_the_purposes_of_this_test");
|
|
insert_logs(&setup);
|
|
|
|
let fd = FrameData::from((&setup.app_data, &setup.gui_state));
|
|
|
|
setup
|
|
.terminal
|
|
.draw(|f| {
|
|
super::draw(
|
|
&setup.app_data,
|
|
setup.area,
|
|
AppColors::new(),
|
|
f,
|
|
&fd,
|
|
&setup.gui_state,
|
|
);
|
|
})
|
|
.unwrap();
|
|
|
|
assert_snapshot!(setup.terminal.backend());
|
|
}
|
|
|
|
#[test]
|
|
fn test_draw_blocks_logs_custom_colors_parsing() {
|
|
let mut setup = test_setup(32, 6, true, true);
|
|
let uuid = Uuid::new_v4();
|
|
setup.gui_state.lock().next_loading(uuid);
|
|
|
|
let mut fd = FrameData::from((&setup.app_data, &setup.gui_state));
|
|
fd.status.insert(Status::Init);
|
|
|
|
let mut colors = AppColors::new();
|
|
colors.logs.background = Color::Green;
|
|
colors.logs.text = Color::Black;
|
|
|
|
setup
|
|
.terminal
|
|
.draw(|f| {
|
|
super::draw(
|
|
&setup.app_data,
|
|
setup.area,
|
|
colors,
|
|
f,
|
|
&fd,
|
|
&setup.gui_state,
|
|
);
|
|
})
|
|
.unwrap();
|
|
|
|
assert_snapshot!(setup.terminal.backend());
|
|
|
|
for (row_index, result_row) in get_result(&setup) {
|
|
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
|
|
assert_eq!(result_cell.bg, Color::Green);
|
|
if let (1..=4, 1..=29) = (row_index, result_cell_index) {
|
|
assert_eq!(result_cell.fg, Color::Black);
|
|
}
|
|
}
|
|
}
|
|
|
|
fd.color_logs = true;
|
|
|
|
setup
|
|
.terminal
|
|
.draw(|f| {
|
|
super::draw(
|
|
&setup.app_data,
|
|
setup.area,
|
|
colors,
|
|
f,
|
|
&fd,
|
|
&setup.gui_state,
|
|
);
|
|
})
|
|
.unwrap();
|
|
|
|
for (row_index, result_row) in get_result(&setup) {
|
|
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
|
|
assert_eq!(result_cell.bg, Color::Reset);
|
|
if let (1..=4, 1..=29) = (row_index, result_cell_index) {
|
|
assert_eq!(result_cell.fg, Color::Reset);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
|
|
fn test_draw_blocks_logs_custom_colors_no_logs() {
|
|
let mut setup = test_setup(35, 6, true, true);
|
|
|
|
let mut colors = AppColors::new();
|
|
colors.logs.background = Color::Green;
|
|
colors.logs.text = Color::Black;
|
|
|
|
setup
|
|
.terminal
|
|
.draw(|f| {
|
|
super::draw(
|
|
&setup.app_data,
|
|
setup.area,
|
|
colors,
|
|
f,
|
|
&setup.fd,
|
|
&setup.gui_state,
|
|
);
|
|
})
|
|
.unwrap();
|
|
|
|
assert_snapshot!(setup.terminal.backend());
|
|
|
|
for (row_index, result_row) in get_result(&setup) {
|
|
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
|
|
assert_eq!(result_cell.bg, Color::Green);
|
|
if let (1..=4, 1..=29) = (row_index, result_cell_index) {
|
|
assert_eq!(result_cell.fg, Color::Black);
|
|
}
|
|
}
|
|
}
|
|
|
|
setup.fd.color_logs = true;
|
|
setup
|
|
.terminal
|
|
.draw(|f| {
|
|
super::draw(
|
|
&setup.app_data,
|
|
setup.area,
|
|
colors,
|
|
f,
|
|
&setup.fd,
|
|
&setup.gui_state,
|
|
);
|
|
})
|
|
.unwrap();
|
|
|
|
for (row_index, result_row) in get_result(&setup) {
|
|
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
|
|
assert_eq!(result_cell.bg, Color::Reset);
|
|
if let (1..=4, 1..=29) = (row_index, result_cell_index) {
|
|
assert_eq!(result_cell.fg, Color::Reset);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
/// Logs correct displayed with custom colors
|
|
fn test_draw_blocks_logs_custom_colors_logs() {
|
|
let mut setup = test_setup(36, 6, true, true);
|
|
insert_logs(&setup);
|
|
|
|
let mut colors = setup.app_data.lock().config.app_colors;
|
|
colors.logs.background = Color::Green;
|
|
colors.logs.text = Color::Black;
|
|
let mut fd = FrameData::from((&setup.app_data, &setup.gui_state));
|
|
fd.color_logs = true;
|
|
|
|
// Standard colors when color_logs is true
|
|
setup
|
|
.terminal
|
|
.draw(|f| {
|
|
super::draw(
|
|
&setup.app_data,
|
|
setup.area,
|
|
colors,
|
|
f,
|
|
&fd,
|
|
&setup.gui_state,
|
|
);
|
|
})
|
|
.unwrap();
|
|
|
|
assert_snapshot!(setup.terminal.backend());
|
|
for (row_index, result_row) in get_result(&setup) {
|
|
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
|
|
assert_eq!(result_cell.bg, Color::Reset);
|
|
if let (1..=4, 1..=34) = (row_index, result_cell_index) {
|
|
assert_eq!(result_cell.fg, Color::Reset);
|
|
if row_index == 3 && (1..=34).contains(&result_cell_index) {
|
|
assert_eq!(result_cell.modifier, Modifier::BOLD);
|
|
} else {
|
|
assert!(result_cell.modifier.is_empty());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fd.color_logs = false;
|
|
|
|
setup
|
|
.terminal
|
|
.draw(|f| {
|
|
super::draw(
|
|
&setup.app_data,
|
|
setup.area,
|
|
colors,
|
|
f,
|
|
&fd,
|
|
&setup.gui_state,
|
|
);
|
|
})
|
|
.unwrap();
|
|
|
|
for (row_index, result_row) in get_result(&setup) {
|
|
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
|
|
assert_eq!(result_cell.bg, Color::Green);
|
|
if let (1..=4, 1..=34) = (row_index, result_cell_index) {
|
|
assert_eq!(result_cell.fg, Color::Black);
|
|
if row_index == 3 && (1..=34).contains(&result_cell_index) {
|
|
assert_eq!(result_cell.modifier, Modifier::BOLD);
|
|
} else {
|
|
assert!(result_cell.modifier.is_empty());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|