feat: Initial Lidarr support for searching for new artists
This commit is contained in:
@@ -0,0 +1,151 @@
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
use ratatui::Frame;
|
||||
use ratatui::layout::{Constraint, Layout, Rect};
|
||||
use ratatui::widgets::{Cell, Row};
|
||||
|
||||
use crate::App;
|
||||
use crate::models::Route;
|
||||
use crate::models::lidarr_models::AddArtistSearchResult;
|
||||
use crate::models::servarr_data::lidarr::lidarr_data::{ADD_ARTIST_BLOCKS, ActiveLidarrBlock};
|
||||
use crate::ui::styles::ManagarrStyle;
|
||||
use crate::ui::utils::{get_width_from_percentage, layout_block, title_block_centered};
|
||||
use crate::ui::widgets::input_box::InputBox;
|
||||
use crate::ui::widgets::managarr_table::ManagarrTable;
|
||||
use crate::ui::widgets::message::Message;
|
||||
use crate::ui::widgets::popup::{Popup, Size};
|
||||
use crate::ui::{DrawUi, draw_popup};
|
||||
|
||||
#[cfg(test)]
|
||||
#[path = "add_artist_ui_tests.rs"]
|
||||
mod add_artist_ui_tests;
|
||||
|
||||
pub(super) struct AddArtistUi;
|
||||
|
||||
impl DrawUi for AddArtistUi {
|
||||
fn accepts(route: Route) -> bool {
|
||||
let Route::Lidarr(active_lidarr_block, _) = route else {
|
||||
return false;
|
||||
};
|
||||
ADD_ARTIST_BLOCKS.contains(&active_lidarr_block)
|
||||
}
|
||||
|
||||
fn draw(f: &mut Frame<'_>, app: &mut App<'_>, _area: Rect) {
|
||||
draw_popup(f, app, draw_add_artist_search, Size::Large);
|
||||
}
|
||||
}
|
||||
|
||||
fn draw_add_artist_search(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
||||
let is_loading = app.is_loading || app.data.lidarr_data.add_searched_artists.is_none();
|
||||
let current_selection = if let Some(add_searched_artists) =
|
||||
app.data.lidarr_data.add_searched_artists.as_ref()
|
||||
&& !add_searched_artists.is_empty()
|
||||
{
|
||||
add_searched_artists.current_selection().clone()
|
||||
} else {
|
||||
AddArtistSearchResult::default()
|
||||
};
|
||||
|
||||
let [search_box_area, results_area] =
|
||||
Layout::vertical([Constraint::Length(3), Constraint::Fill(0)])
|
||||
.margin(1)
|
||||
.areas(area);
|
||||
let block_content = &app
|
||||
.data
|
||||
.lidarr_data
|
||||
.add_artist_search
|
||||
.as_ref()
|
||||
.expect("add_artist_search must be populated")
|
||||
.text;
|
||||
let offset = app
|
||||
.data
|
||||
.lidarr_data
|
||||
.add_artist_search
|
||||
.as_ref()
|
||||
.expect("add_artist_search must be populated")
|
||||
.offset
|
||||
.load(Ordering::SeqCst);
|
||||
|
||||
let search_results_row_mapping = |artist: &AddArtistSearchResult| {
|
||||
let rating = artist
|
||||
.ratings
|
||||
.as_ref()
|
||||
.map_or(String::new(), |r| format!("{:.1}", r.value));
|
||||
let in_library = if app
|
||||
.data
|
||||
.lidarr_data
|
||||
.artists
|
||||
.items
|
||||
.iter()
|
||||
.any(|a| a.foreign_artist_id == artist.foreign_artist_id)
|
||||
{
|
||||
"✔"
|
||||
} else {
|
||||
""
|
||||
};
|
||||
|
||||
artist.artist_name.scroll_left_or_reset(
|
||||
get_width_from_percentage(area, 27),
|
||||
*artist == current_selection,
|
||||
app.ui_scroll_tick_count == 0,
|
||||
);
|
||||
|
||||
Row::new(vec![
|
||||
Cell::from(in_library),
|
||||
Cell::from(artist.artist_name.to_string()),
|
||||
Cell::from(artist.artist_type.clone().unwrap_or_default()),
|
||||
Cell::from(artist.status.to_display_str()),
|
||||
Cell::from(rating),
|
||||
Cell::from(artist.genres.join(", ")),
|
||||
])
|
||||
.primary()
|
||||
};
|
||||
|
||||
if let Route::Lidarr(active_lidarr_block, _) = app.get_current_route() {
|
||||
match active_lidarr_block {
|
||||
ActiveLidarrBlock::AddArtistSearchInput => {
|
||||
let search_box = InputBox::new(block_content)
|
||||
.offset(offset)
|
||||
.block(title_block_centered("Add Artist"));
|
||||
|
||||
search_box.show_cursor(f, search_box_area);
|
||||
f.render_widget(layout_block().default(), results_area);
|
||||
f.render_widget(search_box, search_box_area);
|
||||
}
|
||||
ActiveLidarrBlock::AddArtistEmptySearchResults => {
|
||||
let error_message = Message::new("No artists found matching your query!");
|
||||
let error_message_popup = Popup::new(error_message).size(Size::Message);
|
||||
|
||||
f.render_widget(layout_block().default(), results_area);
|
||||
f.render_widget(error_message_popup, f.area());
|
||||
}
|
||||
ActiveLidarrBlock::AddArtistSearchResults => {
|
||||
let search_results_table = ManagarrTable::new(
|
||||
app.data.lidarr_data.add_searched_artists.as_mut(),
|
||||
search_results_row_mapping,
|
||||
)
|
||||
.loading(is_loading)
|
||||
.block(layout_block().default())
|
||||
.headers(["✔", "Name", "Type", "Status", "Rating", "Genres"])
|
||||
.constraints([
|
||||
Constraint::Percentage(3),
|
||||
Constraint::Percentage(27),
|
||||
Constraint::Percentage(12),
|
||||
Constraint::Percentage(12),
|
||||
Constraint::Percentage(8),
|
||||
Constraint::Percentage(38),
|
||||
]);
|
||||
|
||||
f.render_widget(search_results_table, results_area);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
f.render_widget(
|
||||
InputBox::new(block_content)
|
||||
.offset(offset)
|
||||
.block(title_block_centered("Add Artist")),
|
||||
search_box_area,
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
use crate::models::servarr_data::lidarr::lidarr_data::{ADD_ARTIST_BLOCKS, ActiveLidarrBlock};
|
||||
use crate::ui::DrawUi;
|
||||
use crate::ui::lidarr_ui::library::add_artist_ui::AddArtistUi;
|
||||
|
||||
#[test]
|
||||
fn test_add_artist_ui_accepts() {
|
||||
ActiveLidarrBlock::iter().for_each(|active_lidarr_block| {
|
||||
if ADD_ARTIST_BLOCKS.contains(&active_lidarr_block) {
|
||||
assert!(AddArtistUi::accepts(active_lidarr_block.into()));
|
||||
} else {
|
||||
assert!(!AddArtistUi::accepts(active_lidarr_block.into()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
mod snapshot_tests {
|
||||
use super::*;
|
||||
use crate::app::App;
|
||||
use crate::models::HorizontallyScrollableText;
|
||||
use crate::ui::ui_test_utils::test_utils::{TerminalSize, render_to_string_with_app};
|
||||
use rstest::rstest;
|
||||
|
||||
#[test]
|
||||
fn test_add_artist_ui_renders_loading_for_search() {
|
||||
let mut app = App::test_default_fully_populated();
|
||||
app.data.lidarr_data.add_artist_search = Some(HorizontallyScrollableText::default());
|
||||
app.data.lidarr_data.add_searched_artists = None;
|
||||
app.push_navigation_stack(ActiveLidarrBlock::AddArtistSearchResults.into());
|
||||
|
||||
let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| {
|
||||
AddArtistUi::draw(f, app, f.area());
|
||||
});
|
||||
|
||||
insta::assert_snapshot!(output);
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
fn test_add_artist_ui_renders(
|
||||
#[values(
|
||||
ActiveLidarrBlock::AddArtistSearchInput,
|
||||
ActiveLidarrBlock::AddArtistSearchResults,
|
||||
ActiveLidarrBlock::AddArtistEmptySearchResults
|
||||
)]
|
||||
active_lidarr_block: ActiveLidarrBlock,
|
||||
) {
|
||||
let mut app = App::test_default_fully_populated();
|
||||
app.data.lidarr_data.add_artist_search = Some("Test Artist".into());
|
||||
app.push_navigation_stack(active_lidarr_block.into());
|
||||
|
||||
let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| {
|
||||
AddArtistUi::draw(f, app, f.area());
|
||||
});
|
||||
|
||||
insta::assert_snapshot!(format!("add_artist_ui_{active_lidarr_block}"), output);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@ mod tests {
|
||||
|
||||
use crate::models::lidarr_models::{Artist, ArtistStatistics, ArtistStatus};
|
||||
use crate::models::servarr_data::lidarr::lidarr_data::{
|
||||
ActiveLidarrBlock, DELETE_ARTIST_BLOCKS, EDIT_ARTIST_BLOCKS, LIBRARY_BLOCKS,
|
||||
ADD_ARTIST_BLOCKS, ActiveLidarrBlock, DELETE_ARTIST_BLOCKS, EDIT_ARTIST_BLOCKS, LIBRARY_BLOCKS,
|
||||
};
|
||||
use crate::ui::DrawUi;
|
||||
use crate::ui::lidarr_ui::library::{LibraryUi, decorate_artist_row_with_style};
|
||||
@@ -18,6 +18,7 @@ mod tests {
|
||||
library_ui_blocks.extend(LIBRARY_BLOCKS);
|
||||
library_ui_blocks.extend(DELETE_ARTIST_BLOCKS);
|
||||
library_ui_blocks.extend(EDIT_ARTIST_BLOCKS);
|
||||
library_ui_blocks.extend(ADD_ARTIST_BLOCKS);
|
||||
|
||||
for active_lidarr_block in ActiveLidarrBlock::iter() {
|
||||
if library_ui_blocks.contains(&active_lidarr_block) {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use add_artist_ui::AddArtistUi;
|
||||
use delete_artist_ui::DeleteArtistUi;
|
||||
use edit_artist_ui::EditArtistUi;
|
||||
use ratatui::{
|
||||
@@ -26,6 +27,7 @@ use crate::{
|
||||
},
|
||||
};
|
||||
|
||||
mod add_artist_ui;
|
||||
mod delete_artist_ui;
|
||||
mod edit_artist_ui;
|
||||
|
||||
@@ -38,7 +40,8 @@ pub(super) struct LibraryUi;
|
||||
impl DrawUi for LibraryUi {
|
||||
fn accepts(route: Route) -> bool {
|
||||
if let Route::Lidarr(active_lidarr_block, _) = route {
|
||||
return DeleteArtistUi::accepts(route)
|
||||
return AddArtistUi::accepts(route)
|
||||
|| DeleteArtistUi::accepts(route)
|
||||
|| EditArtistUi::accepts(route)
|
||||
|| LIBRARY_BLOCKS.contains(&active_lidarr_block);
|
||||
}
|
||||
@@ -51,6 +54,7 @@ impl DrawUi for LibraryUi {
|
||||
draw_library(f, app, area);
|
||||
|
||||
match route {
|
||||
_ if AddArtistUi::accepts(route) => AddArtistUi::draw(f, app, area),
|
||||
_ if DeleteArtistUi::accepts(route) => DeleteArtistUi::draw(f, app, area),
|
||||
_ if EditArtistUi::accepts(route) => EditArtistUi::draw(f, app, area),
|
||||
Route::Lidarr(ActiveLidarrBlock::UpdateAllArtistsPrompt, _) => {
|
||||
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
---
|
||||
source: src/ui/lidarr_ui/library/add_artist_ui_tests.rs
|
||||
expression: output
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
╭───────────────────────────────────────────────────── Add Artist ─────────────────────────────────────────────────────╮
|
||||
│Test Artist │
|
||||
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
|
||||
╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ ╭─────────────── Error ───────────────╮ │
|
||||
│ │ No artists found matching your query! │ │
|
||||
│ │ │ │
|
||||
│ ╰───────────────────────────────────────╯ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
---
|
||||
source: src/ui/lidarr_ui/library/add_artist_ui_tests.rs
|
||||
expression: output
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
╭───────────────────────────────────────────────────── Add Artist ─────────────────────────────────────────────────────╮
|
||||
│Test Artist │
|
||||
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
|
||||
╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
---
|
||||
source: src/ui/lidarr_ui/library/add_artist_ui_tests.rs
|
||||
expression: output
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
╭───────────────────────────────────────────────────── Add Artist ─────────────────────────────────────────────────────╮
|
||||
│Test Artist │
|
||||
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
|
||||
╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ ✔ Name Type Status Rating Genres │
|
||||
│=> Test Artist Person Continuing 8.4 soundtrack │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
---
|
||||
source: src/ui/lidarr_ui/library/add_artist_ui_tests.rs
|
||||
expression: output
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
╭───────────────────────────────────────────────────── Add Artist ─────────────────────────────────────────────────────╮
|
||||
│Test Artist │
|
||||
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
|
||||
╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ ╭─────────────── Error ───────────────╮ │
|
||||
│ │ No artists found matching your query! │ │
|
||||
│ │ │ │
|
||||
│ ╰───────────────────────────────────────╯ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
---
|
||||
source: src/ui/lidarr_ui/library/add_artist_ui_tests.rs
|
||||
expression: output
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
╭───────────────────────────────────────────────────── Add Artist ─────────────────────────────────────────────────────╮
|
||||
│Test Artist │
|
||||
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
|
||||
╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
---
|
||||
source: src/ui/lidarr_ui/library/add_artist_ui_tests.rs
|
||||
expression: output
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
╭───────────────────────────────────────────────────── Add Artist ─────────────────────────────────────────────────────╮
|
||||
│Test Artist │
|
||||
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
|
||||
╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ ✔ Name Type Status Rating Genres │
|
||||
│=> Test Artist Person Continuing 8.4 soundtrack │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
---
|
||||
source: src/ui/lidarr_ui/library/add_artist_ui_tests.rs
|
||||
expression: output
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
╭───────────────────────────────────────────────────── Add Artist ─────────────────────────────────────────────────────╮
|
||||
│ │
|
||||
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
|
||||
╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ │
|
||||
│ │
|
||||
│ Loading ... │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
|
||||
@@ -34,12 +34,14 @@ fn draw_test_all_indexers_test_results(f: &mut Frame<'_>, app: &mut App<'_>, are
|
||||
let is_loading = app.is_loading || app.data.radarr_data.indexer_test_all_results.is_none();
|
||||
let block = title_block("Test All Indexers");
|
||||
|
||||
let current_selection =
|
||||
if let Some(test_all_results) = app.data.radarr_data.indexer_test_all_results.as_ref() && !test_all_results.is_empty() {
|
||||
test_all_results.current_selection().clone()
|
||||
} else {
|
||||
IndexerTestResultModalItem::default()
|
||||
};
|
||||
let current_selection = if let Some(test_all_results) =
|
||||
app.data.radarr_data.indexer_test_all_results.as_ref()
|
||||
&& !test_all_results.is_empty()
|
||||
{
|
||||
test_all_results.current_selection().clone()
|
||||
} else {
|
||||
IndexerTestResultModalItem::default()
|
||||
};
|
||||
f.render_widget(block, area);
|
||||
let test_results_row_mapping = |result: &IndexerTestResultModalItem| {
|
||||
result.validation_failures.scroll_left_or_reset(
|
||||
|
||||
@@ -33,12 +33,14 @@ impl DrawUi for TestAllIndexersUi {
|
||||
|
||||
fn draw_test_all_indexers_test_results(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
||||
let is_loading = app.is_loading || app.data.sonarr_data.indexer_test_all_results.is_none();
|
||||
let current_selection =
|
||||
if let Some(test_all_results) = app.data.sonarr_data.indexer_test_all_results.as_ref() && !test_all_results.is_empty() {
|
||||
test_all_results.current_selection().clone()
|
||||
} else {
|
||||
IndexerTestResultModalItem::default()
|
||||
};
|
||||
let current_selection = if let Some(test_all_results) =
|
||||
app.data.sonarr_data.indexer_test_all_results.as_ref()
|
||||
&& !test_all_results.is_empty()
|
||||
{
|
||||
test_all_results.current_selection().clone()
|
||||
} else {
|
||||
IndexerTestResultModalItem::default()
|
||||
};
|
||||
f.render_widget(title_block("Test All Indexers"), area);
|
||||
let test_results_row_mapping = |result: &IndexerTestResultModalItem| {
|
||||
result.validation_failures.scroll_left_or_reset(
|
||||
|
||||
Reference in New Issue
Block a user