Refactored table filtering and searching so that they are now relative to the table being filtered/searched on. Also created two new widgets for error messages and popups to make life easier moving forward. Going to refactor table sorting into StatefulTable's as well so all tables can be searched, filtered, and sorted moving forwards.
This commit is contained in:
@@ -220,32 +220,6 @@ pub fn draw_drop_down_popup(
|
||||
draw_popup_over(f, app, area, background_fn, drop_down_fn, 20, 30);
|
||||
}
|
||||
|
||||
pub fn draw_error_popup_over(
|
||||
f: &mut Frame<'_>,
|
||||
app: &mut App<'_>,
|
||||
area: Rect,
|
||||
message: &str,
|
||||
background_fn: fn(&mut Frame<'_>, &mut App<'_>, Rect),
|
||||
) {
|
||||
background_fn(f, app, area);
|
||||
draw_error_popup(f, message);
|
||||
}
|
||||
|
||||
pub fn draw_error_popup(f: &mut Frame<'_>, message: &str) {
|
||||
let prompt_area = centered_rect(25, 8, f.size());
|
||||
f.render_widget(Clear, prompt_area);
|
||||
f.render_widget(background_block(), prompt_area);
|
||||
|
||||
let error_message = Paragraph::new(Text::from(message))
|
||||
.block(title_block_centered("Error").failure())
|
||||
.failure()
|
||||
.bold()
|
||||
.wrap(Wrap { trim: false })
|
||||
.alignment(Alignment::Center);
|
||||
|
||||
f.render_widget(error_message, prompt_area);
|
||||
}
|
||||
|
||||
fn draw_tabs(f: &mut Frame<'_>, area: Rect, title: &str, tab_state: &TabState) -> Rect {
|
||||
f.render_widget(title_block(title), area);
|
||||
|
||||
@@ -485,12 +459,3 @@ pub fn draw_input_box_popup(
|
||||
.block(borderless_block());
|
||||
f.render_widget(help, help_area);
|
||||
}
|
||||
|
||||
pub fn draw_error_message_popup(f: &mut Frame<'_>, area: Rect, error_msg: &str) {
|
||||
let input = Paragraph::new(error_msg)
|
||||
.failure()
|
||||
.alignment(Alignment::Center)
|
||||
.block(layout_block());
|
||||
|
||||
f.render_widget(input, area);
|
||||
}
|
||||
|
||||
@@ -72,12 +72,7 @@ pub fn draw_collection_details(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect)
|
||||
Layout::vertical([Constraint::Percentage(25), Constraint::Fill(0)])
|
||||
.margin(1)
|
||||
.areas(area);
|
||||
let collection_selection =
|
||||
if let Some(filtered_collections) = app.data.radarr_data.filtered_collections.as_ref() {
|
||||
filtered_collections.current_selection()
|
||||
} else {
|
||||
app.data.radarr_data.collections.current_selection()
|
||||
};
|
||||
let collection_selection = app.data.radarr_data.collections.current_selection();
|
||||
let quality_profile = app
|
||||
.data
|
||||
.radarr_data
|
||||
|
||||
@@ -89,36 +89,22 @@ impl DrawUi for EditCollectionUi {
|
||||
}
|
||||
|
||||
fn draw_edit_collection_confirmation_prompt(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
||||
let (collection_title, collection_overview) =
|
||||
if let Some(filtered_collections) = app.data.radarr_data.filtered_collections.as_ref() {
|
||||
(
|
||||
filtered_collections.current_selection().title.text.clone(),
|
||||
filtered_collections
|
||||
.current_selection()
|
||||
.overview
|
||||
.clone()
|
||||
.unwrap_or_default(),
|
||||
)
|
||||
} else {
|
||||
(
|
||||
app
|
||||
.data
|
||||
.radarr_data
|
||||
.collections
|
||||
.current_selection()
|
||||
.title
|
||||
.text
|
||||
.clone(),
|
||||
app
|
||||
.data
|
||||
.radarr_data
|
||||
.collections
|
||||
.current_selection()
|
||||
.overview
|
||||
.clone()
|
||||
.unwrap_or_default(),
|
||||
)
|
||||
};
|
||||
let collection_title = app
|
||||
.data
|
||||
.radarr_data
|
||||
.collections
|
||||
.current_selection()
|
||||
.title
|
||||
.text
|
||||
.clone();
|
||||
let collection_overview = app
|
||||
.data
|
||||
.radarr_data
|
||||
.collections
|
||||
.current_selection()
|
||||
.overview
|
||||
.clone()
|
||||
.unwrap_or_default();
|
||||
let title = format!("Edit - {collection_title}");
|
||||
let yes_no_value = app.data.radarr_data.prompt_confirm;
|
||||
let selected_block = app.data.radarr_data.selected_block.get_active_block();
|
||||
|
||||
@@ -12,10 +12,10 @@ use crate::ui::radarr_ui::collections::collection_details_ui::CollectionDetailsU
|
||||
use crate::ui::radarr_ui::collections::edit_collection_ui::EditCollectionUi;
|
||||
use crate::ui::styles::ManagarrStyle;
|
||||
use crate::ui::utils::{get_width_from_percentage, layout_block_top_border};
|
||||
use crate::ui::widgets::error_message::ErrorMessage;
|
||||
use crate::ui::widgets::managarr_table::ManagarrTable;
|
||||
use crate::ui::{
|
||||
draw_error_message_popup, draw_input_box_popup, draw_popup_over, draw_prompt_box,
|
||||
draw_prompt_popup_over, DrawUi,
|
||||
draw_input_box_popup, draw_popup_over, draw_prompt_box, draw_prompt_popup_over, DrawUi,
|
||||
};
|
||||
|
||||
mod collection_details_ui;
|
||||
@@ -101,19 +101,13 @@ impl DrawUi for CollectionsUi {
|
||||
}
|
||||
|
||||
pub(super) fn draw_collections(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
||||
let current_selection =
|
||||
if let Some(filtered_collections) = app.data.radarr_data.filtered_collections.as_ref() {
|
||||
filtered_collections.current_selection().clone()
|
||||
} else if !app.data.radarr_data.collections.items.is_empty() {
|
||||
app.data.radarr_data.collections.current_selection().clone()
|
||||
} else {
|
||||
Collection::default()
|
||||
};
|
||||
let quality_profile_map = &app.data.radarr_data.quality_profile_map;
|
||||
let content = match app.data.radarr_data.filtered_collections.as_mut() {
|
||||
Some(filtered_collections) if !app.data.radarr_data.is_filtering => Some(filtered_collections),
|
||||
_ => Some(&mut app.data.radarr_data.collections),
|
||||
let current_selection = if !app.data.radarr_data.collections.items.is_empty() {
|
||||
app.data.radarr_data.collections.current_selection().clone()
|
||||
} else {
|
||||
Collection::default()
|
||||
};
|
||||
let quality_profile_map = &app.data.radarr_data.quality_profile_map;
|
||||
let content = Some(&mut app.data.radarr_data.collections);
|
||||
let collections_table_footer = app
|
||||
.data
|
||||
.radarr_data
|
||||
@@ -187,7 +181,7 @@ fn draw_collection_search_box(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect)
|
||||
f,
|
||||
area,
|
||||
"Search",
|
||||
app.data.radarr_data.search.as_ref().unwrap(),
|
||||
app.data.radarr_data.collections.search.as_ref().unwrap(),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -196,14 +190,17 @@ fn draw_filter_collections_box(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect)
|
||||
f,
|
||||
area,
|
||||
"Filter",
|
||||
app.data.radarr_data.filter.as_ref().unwrap(),
|
||||
app.data.radarr_data.collections.filter.as_ref().unwrap(),
|
||||
)
|
||||
}
|
||||
|
||||
fn draw_search_collection_error_box(f: &mut Frame<'_>, _: &mut App<'_>, area: Rect) {
|
||||
draw_error_message_popup(f, area, "Collection not found!");
|
||||
f.render_widget(ErrorMessage::new("Collection not found!"), area);
|
||||
}
|
||||
|
||||
fn draw_filter_collections_error_box(f: &mut Frame<'_>, _: &mut App<'_>, area: Rect) {
|
||||
draw_error_message_popup(f, area, "No collections found matching the given filter!");
|
||||
f.render_widget(
|
||||
ErrorMessage::new("No collections found matching the given filter!"),
|
||||
area,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -17,11 +17,12 @@ use crate::ui::utils::{
|
||||
title_block_centered,
|
||||
};
|
||||
use crate::ui::widgets::button::Button;
|
||||
use crate::ui::widgets::error_message::ErrorMessage;
|
||||
use crate::ui::widgets::input_box::InputBox;
|
||||
use crate::ui::widgets::managarr_table::ManagarrTable;
|
||||
use crate::ui::widgets::popup::Popup;
|
||||
use crate::ui::{
|
||||
draw_drop_down_popup, draw_error_popup, draw_error_popup_over, draw_large_popup_over,
|
||||
draw_medium_popup_over, draw_selectable_list, DrawUi,
|
||||
draw_drop_down_popup, draw_large_popup_over, draw_medium_popup_over, draw_selectable_list, DrawUi,
|
||||
};
|
||||
use crate::utils::convert_runtime;
|
||||
use crate::{render_selectable_input_box, App};
|
||||
@@ -68,13 +69,17 @@ impl DrawUi for AddMovieUi {
|
||||
draw_medium_popup_over(f, app, area, draw_add_movie_search, draw_confirmation_popup);
|
||||
}
|
||||
}
|
||||
ActiveRadarrBlock::AddMovieAlreadyInLibrary => draw_error_popup_over(
|
||||
f,
|
||||
app,
|
||||
area,
|
||||
"This film is already in your library",
|
||||
draw_add_movie_search,
|
||||
),
|
||||
ActiveRadarrBlock::AddMovieAlreadyInLibrary => {
|
||||
draw_add_movie_search(f, app, area);
|
||||
f.render_widget(
|
||||
Popup::new(
|
||||
ErrorMessage::new("This film is already in your library"),
|
||||
25,
|
||||
8,
|
||||
),
|
||||
f.size(),
|
||||
);
|
||||
}
|
||||
_ => (),
|
||||
};
|
||||
|
||||
@@ -108,11 +113,11 @@ fn draw_add_movie_search(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
||||
])
|
||||
.margin(1)
|
||||
.areas(area);
|
||||
let block_content = &app.data.radarr_data.search.as_ref().unwrap().text;
|
||||
let block_content = &app.data.radarr_data.add_movie_search.as_ref().unwrap().text;
|
||||
let offset = *app
|
||||
.data
|
||||
.radarr_data
|
||||
.search
|
||||
.add_movie_search
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.offset
|
||||
@@ -197,9 +202,11 @@ fn draw_add_movie_search(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
||||
let help_paragraph = Paragraph::new(help_text)
|
||||
.block(borderless_block())
|
||||
.alignment(Alignment::Center);
|
||||
let error_message = ErrorMessage::new("No movies found matching your query!");
|
||||
let error_message_popup = Popup::new(error_message, 25, 8);
|
||||
|
||||
f.render_widget(layout_block(), results_area);
|
||||
draw_error_popup(f, "No movies found matching your query!");
|
||||
f.render_widget(error_message_popup, f.size());
|
||||
f.render_widget(help_paragraph, help_area);
|
||||
}
|
||||
ActiveRadarrBlock::AddMovieSearchResults
|
||||
|
||||
@@ -19,8 +19,8 @@ use crate::ui::widgets::button::Button;
|
||||
use crate::ui::widgets::checkbox::Checkbox;
|
||||
use crate::ui::widgets::input_box::InputBox;
|
||||
use crate::ui::{
|
||||
draw_drop_down_popup, draw_large_popup_over_background_fn_with_ui,
|
||||
draw_medium_popup_over, draw_popup, draw_selectable_list, DrawUi,
|
||||
draw_drop_down_popup, draw_large_popup_over_background_fn_with_ui, draw_medium_popup_over,
|
||||
draw_popup, draw_selectable_list, DrawUi,
|
||||
};
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -91,31 +91,21 @@ impl DrawUi for EditMovieUi {
|
||||
}
|
||||
|
||||
fn draw_edit_movie_confirmation_prompt(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
||||
let (movie_title, movie_overview) =
|
||||
if let Some(filtered_movies) = app.data.radarr_data.filtered_movies.as_ref() {
|
||||
(
|
||||
filtered_movies.current_selection().title.text.clone(),
|
||||
filtered_movies.current_selection().overview.clone(),
|
||||
)
|
||||
} else {
|
||||
(
|
||||
app
|
||||
.data
|
||||
.radarr_data
|
||||
.movies
|
||||
.current_selection()
|
||||
.title
|
||||
.text
|
||||
.clone(),
|
||||
app
|
||||
.data
|
||||
.radarr_data
|
||||
.movies
|
||||
.current_selection()
|
||||
.overview
|
||||
.clone(),
|
||||
)
|
||||
};
|
||||
let movie_title = app
|
||||
.data
|
||||
.radarr_data
|
||||
.movies
|
||||
.current_selection()
|
||||
.title
|
||||
.text
|
||||
.clone();
|
||||
let movie_overview = app
|
||||
.data
|
||||
.radarr_data
|
||||
.movies
|
||||
.current_selection()
|
||||
.overview
|
||||
.clone();
|
||||
let title = format!("Edit - {movie_title}");
|
||||
let yes_no_value = app.data.radarr_data.prompt_confirm;
|
||||
let selected_block = app.data.radarr_data.selected_block.get_active_block();
|
||||
|
||||
@@ -12,10 +12,10 @@ use crate::ui::radarr_ui::library::delete_movie_ui::DeleteMovieUi;
|
||||
use crate::ui::radarr_ui::library::edit_movie_ui::EditMovieUi;
|
||||
use crate::ui::radarr_ui::library::movie_details_ui::MovieDetailsUi;
|
||||
use crate::ui::utils::{get_width_from_percentage, layout_block_top_border};
|
||||
use crate::ui::widgets::error_message::ErrorMessage;
|
||||
use crate::ui::widgets::managarr_table::ManagarrTable;
|
||||
use crate::ui::{
|
||||
draw_error_message_popup, draw_input_box_popup, draw_popup_over, draw_prompt_box,
|
||||
draw_prompt_popup_over, DrawUi,
|
||||
draw_input_box_popup, draw_popup_over, draw_prompt_box, draw_prompt_popup_over, DrawUi,
|
||||
};
|
||||
use crate::utils::{convert_runtime, convert_to_gb};
|
||||
|
||||
@@ -92,21 +92,15 @@ impl DrawUi for LibraryUi {
|
||||
}
|
||||
|
||||
pub(super) fn draw_library(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
||||
let current_selection =
|
||||
if let Some(filtered_movies) = app.data.radarr_data.filtered_movies.as_ref() {
|
||||
filtered_movies.current_selection().clone()
|
||||
} else if !app.data.radarr_data.movies.items.is_empty() {
|
||||
app.data.radarr_data.movies.current_selection().clone()
|
||||
} else {
|
||||
Movie::default()
|
||||
};
|
||||
let current_selection = if !app.data.radarr_data.movies.items.is_empty() {
|
||||
app.data.radarr_data.movies.current_selection().clone()
|
||||
} else {
|
||||
Movie::default()
|
||||
};
|
||||
let quality_profile_map = &app.data.radarr_data.quality_profile_map;
|
||||
let tags_map = &app.data.radarr_data.tags_map;
|
||||
let downloads_vec = &app.data.radarr_data.downloads.items;
|
||||
let content = match app.data.radarr_data.filtered_movies.as_mut() {
|
||||
Some(filtered_movies) if !app.data.radarr_data.is_filtering => Some(filtered_movies),
|
||||
_ => Some(&mut app.data.radarr_data.movies),
|
||||
};
|
||||
let content = Some(&mut app.data.radarr_data.movies);
|
||||
let help_footer = app
|
||||
.data
|
||||
.radarr_data
|
||||
@@ -203,7 +197,7 @@ fn draw_movie_search_box(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
||||
f,
|
||||
area,
|
||||
"Search",
|
||||
app.data.radarr_data.search.as_ref().unwrap(),
|
||||
app.data.radarr_data.movies.search.as_ref().unwrap(),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -212,14 +206,17 @@ fn draw_filter_movies_box(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
||||
f,
|
||||
area,
|
||||
"Filter",
|
||||
app.data.radarr_data.filter.as_ref().unwrap(),
|
||||
app.data.radarr_data.movies.filter.as_ref().unwrap(),
|
||||
)
|
||||
}
|
||||
|
||||
fn draw_search_movie_error_box(f: &mut Frame<'_>, _: &mut App<'_>, area: Rect) {
|
||||
draw_error_message_popup(f, area, "Movie not found!");
|
||||
f.render_widget(ErrorMessage::new("Movie not found!"), area);
|
||||
}
|
||||
|
||||
fn draw_filter_movies_error_box(f: &mut Frame<'_>, _: &mut App<'_>, area: Rect) {
|
||||
draw_error_message_popup(f, area, "No movies found matching the given filter!");
|
||||
f.render_widget(
|
||||
ErrorMessage::new("No movies found matching the given filter!"),
|
||||
area,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -85,11 +85,6 @@ fn draw_logs_popup(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
||||
fn draw_tasks_popup(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
||||
let tasks_popup_table = |f: &mut Frame<'_>, app: &mut App<'_>, area: Rect| {
|
||||
let help_footer = Some(build_context_clue_string(&SYSTEM_TASKS_CONTEXT_CLUES));
|
||||
// let context_area = draw_help_footer_and_get_content_area(
|
||||
// f,
|
||||
// area,
|
||||
// help_footer,
|
||||
// );
|
||||
let tasks_row_mapping = |task: &Task| {
|
||||
let task_props = extract_task_props(task);
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ impl<'a> Button<'a> {
|
||||
self
|
||||
}
|
||||
|
||||
fn render_button_with_icon(&self, area: Rect, buf: &mut Buffer) {
|
||||
fn render_button_with_icon(self, area: Rect, buf: &mut Buffer) {
|
||||
let [title_area, icon_area] = Layout::horizontal([
|
||||
Constraint::Length(self.title.len() as u16),
|
||||
Constraint::Percentage(25),
|
||||
@@ -63,7 +63,7 @@ impl<'a> Button<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn render_labeled_button(&self, area: Rect, buf: &mut Buffer) {
|
||||
fn render_labeled_button(self, area: Rect, buf: &mut Buffer) {
|
||||
let [label_area, button_area] =
|
||||
Layout::horizontal([Constraint::Percentage(48), Constraint::Percentage(48)]).areas(area);
|
||||
let label_paragraph = Paragraph::new(Text::from(format!("\n{}: ", self.label.unwrap())))
|
||||
@@ -79,7 +79,7 @@ impl<'a> Button<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn render_button(&self, area: Rect, buf: &mut Buffer) {
|
||||
fn render_button(self, area: Rect, buf: &mut Buffer) {
|
||||
Paragraph::new(Text::from(self.title))
|
||||
.block(layout_block())
|
||||
.alignment(Alignment::Center)
|
||||
|
||||
@@ -31,7 +31,7 @@ impl<'a> Checkbox<'a> {
|
||||
self
|
||||
}
|
||||
|
||||
fn render_checkbox(&self, area: Rect, buf: &mut Buffer) {
|
||||
fn render_checkbox(self, area: Rect, buf: &mut Buffer) {
|
||||
let check = if self.is_checked { "✔" } else { "" };
|
||||
let [label_area, checkbox_area] =
|
||||
Layout::horizontal([Constraint::Percentage(48), Constraint::Percentage(48)]).areas(area);
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
use crate::ui::styles::ManagarrStyle;
|
||||
use crate::ui::utils::title_block_centered;
|
||||
use ratatui::buffer::Buffer;
|
||||
use ratatui::layout::{Alignment, Rect};
|
||||
use ratatui::style::Stylize;
|
||||
use ratatui::text::Text;
|
||||
use ratatui::widgets::{Paragraph, Widget};
|
||||
|
||||
pub struct ErrorMessage<'a> {
|
||||
text: Text<'a>,
|
||||
}
|
||||
|
||||
impl<'a> ErrorMessage<'a> {
|
||||
pub fn new<T>(message: T) -> Self
|
||||
where
|
||||
T: Into<Text<'a>>,
|
||||
{
|
||||
ErrorMessage {
|
||||
text: message.into(),
|
||||
}
|
||||
}
|
||||
|
||||
fn render_error_message(self, area: Rect, buf: &mut Buffer) {
|
||||
Paragraph::new(self.text)
|
||||
.failure()
|
||||
.alignment(Alignment::Center)
|
||||
.block(title_block_centered("Error").failure().bold())
|
||||
.render(area, buf);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Widget for ErrorMessage<'a> {
|
||||
fn render(self, area: Rect, buf: &mut Buffer) {
|
||||
self.render_error_message(area, buf);
|
||||
}
|
||||
}
|
||||
@@ -47,12 +47,12 @@ impl<'a> InputBox<'a> {
|
||||
self.label = Some(label);
|
||||
self
|
||||
}
|
||||
|
||||
|
||||
pub fn offset(mut self, offset: usize) -> InputBox<'a> {
|
||||
self.offset = offset;
|
||||
self
|
||||
}
|
||||
|
||||
|
||||
pub fn cursor_after_string(mut self, cursor_after_string: bool) -> InputBox<'a> {
|
||||
self.cursor_after_string = cursor_after_string;
|
||||
self
|
||||
@@ -89,7 +89,7 @@ impl<'a> InputBox<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn render_input_box(&self, area: Rect, buf: &mut Buffer) {
|
||||
fn render_input_box(self, area: Rect, buf: &mut Buffer) {
|
||||
let style =
|
||||
if matches!(self.is_highlighted, Some(true)) && matches!(self.is_selected, Some(false)) {
|
||||
Style::new().system_function().bold()
|
||||
@@ -99,7 +99,7 @@ impl<'a> InputBox<'a> {
|
||||
|
||||
let input_box_paragraph = Paragraph::new(Text::from(self.content))
|
||||
.style(style)
|
||||
.block(self.block.clone());
|
||||
.block(self.block);
|
||||
|
||||
if let Some(label) = self.label {
|
||||
let [label_area, text_box_area] =
|
||||
|
||||
@@ -14,14 +14,14 @@ impl<'a> LoadingBlock<'a> {
|
||||
Self { is_loading, block }
|
||||
}
|
||||
|
||||
fn render_loading_block(&self, area: Rect, buf: &mut Buffer) {
|
||||
fn render_loading_block(self, area: Rect, buf: &mut Buffer) {
|
||||
if self.is_loading {
|
||||
Paragraph::new(Text::from("\n\n Loading ...\n\n"))
|
||||
.system_function()
|
||||
.block(self.block.clone())
|
||||
.block(self.block)
|
||||
.render(area, buf);
|
||||
} else {
|
||||
self.block.clone().render(area, buf);
|
||||
self.block.render(area, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,12 +86,12 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
pub fn highlight_rows(mut self, hightlight_rows: bool) -> Self {
|
||||
self.highlight_rows = hightlight_rows;
|
||||
pub fn highlight_rows(mut self, highlight_rows: bool) -> Self {
|
||||
self.highlight_rows = highlight_rows;
|
||||
self
|
||||
}
|
||||
|
||||
fn render_table(&mut self, area: Rect, buf: &mut Buffer) {
|
||||
fn render_table(self, area: Rect, buf: &mut Buffer) {
|
||||
let table_area = if let Some(ref footer) = self.footer {
|
||||
let [content_area, footer_area] =
|
||||
Layout::vertical([Constraint::Fill(0), Constraint::Length(2)])
|
||||
@@ -109,18 +109,26 @@ where
|
||||
};
|
||||
let loading_block = LoadingBlock::new(self.is_loading, self.block.clone());
|
||||
|
||||
if let Some(ref mut content) = self.content {
|
||||
if !content.items.is_empty() {
|
||||
let rows = content.items.iter().map(&self.row_mapper);
|
||||
if let Some(content) = self.content {
|
||||
let (table_contents, table_state) = if content.filtered_items.is_some() {
|
||||
(
|
||||
content.filtered_items.as_ref().unwrap(),
|
||||
content.filtered_state.as_mut().unwrap(),
|
||||
)
|
||||
} else {
|
||||
(&content.items, &mut content.state)
|
||||
};
|
||||
if !table_contents.is_empty() {
|
||||
let rows = table_contents.iter().map(&self.row_mapper);
|
||||
|
||||
let headers = Row::new(self.table_headers.clone())
|
||||
let headers = Row::new(self.table_headers)
|
||||
.default()
|
||||
.bold()
|
||||
.bottom_margin(0);
|
||||
|
||||
let mut table = Table::new(rows, &self.constraints)
|
||||
.header(headers)
|
||||
.block(self.block.clone());
|
||||
.block(self.block);
|
||||
|
||||
if self.highlight_rows {
|
||||
table = table
|
||||
@@ -128,7 +136,7 @@ where
|
||||
.highlight_symbol(HIGHLIGHT_SYMBOL);
|
||||
}
|
||||
|
||||
StatefulWidget::render(table, table_area, buf, &mut content.state);
|
||||
StatefulWidget::render(table, table_area, buf, table_state);
|
||||
} else {
|
||||
loading_block.render(table_area, buf);
|
||||
}
|
||||
@@ -142,7 +150,7 @@ impl<'a, T, F> Widget for ManagarrTable<'a, T, F>
|
||||
where
|
||||
F: Fn(&T) -> Row<'a>,
|
||||
{
|
||||
fn render(mut self, area: Rect, buf: &mut Buffer) {
|
||||
fn render(self, area: Rect, buf: &mut Buffer) {
|
||||
self.render_table(area, buf);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
pub(super) mod button;
|
||||
pub(super) mod checkbox;
|
||||
pub(super) mod error_message;
|
||||
pub(super) mod input_box;
|
||||
pub(super) mod loading_block;
|
||||
pub(super) mod managarr_table;
|
||||
pub(super) mod popup;
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
use crate::ui::utils::{background_block, centered_rect};
|
||||
use ratatui::buffer::Buffer;
|
||||
use ratatui::layout::Rect;
|
||||
use ratatui::widgets::{Clear, Widget};
|
||||
|
||||
pub struct Popup<T: Widget> {
|
||||
widget: T,
|
||||
percent_x: u16,
|
||||
percent_y: u16,
|
||||
}
|
||||
|
||||
impl<T: Widget> Popup<T> {
|
||||
pub fn new(widget: T, percent_x: u16, percent_y: u16) -> Self {
|
||||
Self {
|
||||
widget,
|
||||
percent_x,
|
||||
percent_y,
|
||||
}
|
||||
}
|
||||
|
||||
fn render_popup(self, area: Rect, buf: &mut Buffer) {
|
||||
let popup_area = centered_rect(self.percent_x, self.percent_y, area);
|
||||
|
||||
Clear.render(popup_area, buf);
|
||||
background_block().render(popup_area, buf);
|
||||
self.widget.render(popup_area, buf);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Widget> Widget for Popup<T> {
|
||||
fn render(self, area: Rect, buf: &mut Buffer) {
|
||||
self.render_popup(area, buf);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user