Added the ability to edit existing indexers with basic options, added a tags column to the indexers table, and fixed a bug in the counter fields that displayed the cursor next to the integer instead of on it to make understanding the counter easier. Also upgraded to confy v0.60.0 and rust version to 1.75

This commit is contained in:
2024-01-19 15:45:41 -07:00
parent 3d249cc51c
commit 2ec4472efc
29 changed files with 3513 additions and 362 deletions
+92 -2
View File
@@ -1,6 +1,6 @@
use crate::models::radarr_models::{
Collection, Credit, MinimumAvailability, Monitor, Movie, MovieHistoryItem, Release, ReleaseField,
RootFolder,
Collection, Credit, Indexer, MinimumAvailability, Monitor, Movie, MovieHistoryItem, Release,
ReleaseField, RootFolder,
};
use crate::models::servarr_data::radarr::radarr_data::RadarrData;
use crate::models::{HorizontallyScrollableText, ScrollableText, StatefulList, StatefulTable};
@@ -24,6 +24,96 @@ pub struct MovieDetailsModal {
pub sort_ascending: Option<bool>,
}
#[derive(Default, Debug, PartialEq, Eq)]
pub struct EditIndexerModal {
pub name: HorizontallyScrollableText,
pub enable_rss: Option<bool>,
pub enable_automatic_search: Option<bool>,
pub enable_interactive_search: Option<bool>,
pub url: HorizontallyScrollableText,
pub api_key: HorizontallyScrollableText,
pub seed_ratio: HorizontallyScrollableText,
pub tags: HorizontallyScrollableText,
}
impl From<&RadarrData<'_>> for EditIndexerModal {
fn from(radarr_data: &RadarrData<'_>) -> EditIndexerModal {
let mut edit_indexer_modal = EditIndexerModal::default();
let Indexer {
name,
enable_rss,
enable_automatic_search,
enable_interactive_search,
tags,
fields,
..
} = radarr_data.indexers.current_selection();
let seed_ratio_field_option = fields
.as_ref()
.unwrap()
.iter()
.find(|field| field.name.as_ref().unwrap() == "seedCriteria.seedRatio");
let seed_ratio_value_option = if let Some(seed_ratio_field) = seed_ratio_field_option {
seed_ratio_field.value.clone()
} else {
None
};
edit_indexer_modal.name = name.clone().unwrap().into();
edit_indexer_modal.enable_rss = Some(*enable_rss);
edit_indexer_modal.enable_automatic_search = Some(*enable_automatic_search);
edit_indexer_modal.enable_interactive_search = Some(*enable_interactive_search);
edit_indexer_modal.url = fields
.as_ref()
.unwrap()
.iter()
.find(|field| field.name.as_ref().unwrap() == "baseUrl")
.unwrap()
.value
.clone()
.unwrap()
.as_str()
.unwrap()
.into();
edit_indexer_modal.api_key = fields
.as_ref()
.unwrap()
.iter()
.find(|field| field.name.as_ref().unwrap() == "apiKey")
.unwrap()
.value
.clone()
.unwrap()
.as_str()
.unwrap()
.into();
if seed_ratio_value_option.is_some() {
edit_indexer_modal.seed_ratio = seed_ratio_value_option
.unwrap()
.as_f64()
.unwrap()
.to_string()
.into();
}
edit_indexer_modal.tags = tags
.iter()
.map(|tag_id| {
radarr_data
.tags_map
.get_by_left(&tag_id.as_i64().unwrap())
.unwrap()
.clone()
})
.collect::<Vec<String>>()
.join(", ")
.into();
edit_indexer_modal
}
}
#[derive(Default)]
pub struct EditMovieModal {
pub minimum_availability_list: StatefulList<MinimumAvailability>,
+99 -3
View File
@@ -1,8 +1,10 @@
#[cfg(test)]
mod test {
use crate::models::radarr_models::{Collection, MinimumAvailability, Monitor, Movie, RootFolder};
use crate::models::radarr_models::{
Collection, Indexer, IndexerField, MinimumAvailability, Monitor, Movie, RootFolder,
};
use crate::models::servarr_data::radarr::modals::{
AddMovieModal, EditCollectionModal, EditMovieModal,
AddMovieModal, EditCollectionModal, EditIndexerModal, EditMovieModal,
};
use crate::models::servarr_data::radarr::radarr_data::radarr_test_utils::utils::create_test_radarr_data;
use crate::models::servarr_data::radarr::radarr_data::RadarrData;
@@ -10,9 +12,103 @@ mod test {
use bimap::BiMap;
use pretty_assertions::{assert_eq, assert_str_eq};
use rstest::rstest;
use serde_json::Number;
use serde_json::{Number, Value};
use strum::IntoEnumIterator;
#[rstest]
fn test_edit_indexer_modal_from_radarr_data(#[values(true, false)] seed_ratio_present: bool) {
let mut radarr_data = RadarrData {
tags_map: BiMap::from_iter([(1, "usenet".to_owned()), (2, "test".to_owned())]),
..RadarrData::default()
};
let mut fields = vec![
IndexerField {
name: Some("baseUrl".to_owned()),
value: Some(Value::String("https://test.com".to_owned())),
},
IndexerField {
name: Some("apiKey".to_owned()),
value: Some(Value::String("1234".to_owned())),
},
];
if seed_ratio_present {
fields.push(IndexerField {
name: Some("seedCriteria.seedRatio".to_owned()),
value: Some(Value::from(1.2f64)),
});
}
let indexer = Indexer {
name: Some("Test".to_owned()),
enable_rss: true,
enable_automatic_search: true,
enable_interactive_search: true,
tags: vec![Number::from(1), Number::from(2)],
fields: Some(fields),
..Indexer::default()
};
radarr_data.indexers.set_items(vec![indexer]);
let edit_indexer_modal = EditIndexerModal::from(&radarr_data);
assert_str_eq!(edit_indexer_modal.name.text, "Test");
assert_eq!(edit_indexer_modal.enable_rss, Some(true));
assert_eq!(edit_indexer_modal.enable_automatic_search, Some(true));
assert_eq!(edit_indexer_modal.enable_interactive_search, Some(true));
assert_str_eq!(edit_indexer_modal.url.text, "https://test.com");
assert_str_eq!(edit_indexer_modal.api_key.text, "1234");
if seed_ratio_present {
assert_str_eq!(edit_indexer_modal.seed_ratio.text, "1.2");
} else {
assert!(edit_indexer_modal.seed_ratio.text.is_empty());
}
}
#[test]
fn test_edit_indexer_modal_from_radarr_data_seed_ratio_value_is_none() {
let mut radarr_data = RadarrData {
tags_map: BiMap::from_iter([(1, "usenet".to_owned()), (2, "test".to_owned())]),
..RadarrData::default()
};
let fields = vec![
IndexerField {
name: Some("baseUrl".to_owned()),
value: Some(Value::String("https://test.com".to_owned())),
},
IndexerField {
name: Some("apiKey".to_owned()),
value: Some(Value::String("1234".to_owned())),
},
IndexerField {
name: Some("seedCriteria.seedRatio".to_owned()),
value: None,
},
];
let indexer = Indexer {
name: Some("Test".to_owned()),
enable_rss: true,
enable_automatic_search: true,
enable_interactive_search: true,
tags: vec![Number::from(1), Number::from(2)],
fields: Some(fields),
..Indexer::default()
};
radarr_data.indexers.set_items(vec![indexer]);
let edit_indexer_modal = EditIndexerModal::from(&radarr_data);
assert_str_eq!(edit_indexer_modal.name.text, "Test");
assert_eq!(edit_indexer_modal.enable_rss, Some(true));
assert_eq!(edit_indexer_modal.enable_automatic_search, Some(true));
assert_eq!(edit_indexer_modal.enable_interactive_search, Some(true));
assert_str_eq!(edit_indexer_modal.url.text, "https://test.com");
assert_str_eq!(edit_indexer_modal.api_key.text, "1234");
assert!(edit_indexer_modal.seed_ratio.text.is_empty());
}
#[rstest]
fn test_edit_movie_modal_from_radarr_data(#[values(true, false)] test_filtered_movies: bool) {
let mut radarr_data = RadarrData {
+51 -5
View File
@@ -10,7 +10,8 @@ use crate::models::radarr_models::{
IndexerSettings, Movie, QueueEvent, RootFolder, Task,
};
use crate::models::servarr_data::radarr::modals::{
AddMovieModal, EditCollectionModal, EditMovieModal, IndexerTestResultModalItem, MovieDetailsModal,
AddMovieModal, EditCollectionModal, EditIndexerModal, EditMovieModal, IndexerTestResultModalItem,
MovieDetailsModal,
};
use crate::models::{
BlockSelectionState, HorizontallyScrollableText, Route, ScrollableText, StatefulList,
@@ -55,6 +56,7 @@ pub struct RadarrData<'a> {
pub add_searched_movies: Option<StatefulTable<AddMovieSearchResult>>,
pub edit_movie_modal: Option<EditMovieModal>,
pub edit_collection_modal: Option<EditCollectionModal>,
pub edit_indexer_modal: Option<EditIndexerModal>,
pub edit_root_folder: Option<HorizontallyScrollableText>,
pub filtered_collections: Option<StatefulTable<Collection>>,
pub filtered_movies: Option<StatefulTable<Movie>>,
@@ -123,6 +125,7 @@ impl<'a> Default for RadarrData<'a> {
add_searched_movies: None,
edit_movie_modal: None,
edit_collection_modal: None,
edit_indexer_modal: None,
edit_root_folder: None,
filtered_collections: None,
filtered_movies: None,
@@ -252,7 +255,16 @@ pub enum ActiveRadarrBlock {
EditCollectionSelectQualityProfile,
EditCollectionToggleSearchOnAdd,
EditCollectionToggleMonitored,
EditIndexer,
EditIndexerPrompt,
EditIndexerConfirmPrompt,
EditIndexerApiKeyInput,
EditIndexerNameInput,
EditIndexerSeedRatioInput,
EditIndexerToggleEnableRss,
EditIndexerToggleEnableAutomaticSearch,
EditIndexerToggleEnableInteractiveSearch,
EditIndexerUrlInput,
EditIndexerTagsInput,
EditMoviePrompt,
EditMovieConfirmPrompt,
EditMoviePathInput,
@@ -318,12 +330,10 @@ pub static COLLECTIONS_BLOCKS: [ActiveRadarrBlock; 6] = [
ActiveRadarrBlock::FilterCollectionsError,
ActiveRadarrBlock::UpdateAllCollectionsPrompt,
];
pub static INDEXERS_BLOCKS: [ActiveRadarrBlock; 5] = [
pub static INDEXERS_BLOCKS: [ActiveRadarrBlock; 3] = [
ActiveRadarrBlock::AddIndexer,
ActiveRadarrBlock::EditIndexer,
ActiveRadarrBlock::DeleteIndexerPrompt,
ActiveRadarrBlock::Indexers,
ActiveRadarrBlock::TestAllIndexers,
];
pub static ROOT_FOLDERS_BLOCKS: [ActiveRadarrBlock; 3] = [
ActiveRadarrBlock::RootFolders,
@@ -416,6 +426,42 @@ pub static DELETE_MOVIE_SELECTION_BLOCKS: [ActiveRadarrBlock; 3] = [
ActiveRadarrBlock::DeleteMovieToggleAddListExclusion,
ActiveRadarrBlock::DeleteMovieConfirmPrompt,
];
pub static EDIT_INDEXER_BLOCKS: [ActiveRadarrBlock; 10] = [
ActiveRadarrBlock::EditIndexerPrompt,
ActiveRadarrBlock::EditIndexerConfirmPrompt,
ActiveRadarrBlock::EditIndexerApiKeyInput,
ActiveRadarrBlock::EditIndexerNameInput,
ActiveRadarrBlock::EditIndexerSeedRatioInput,
ActiveRadarrBlock::EditIndexerToggleEnableRss,
ActiveRadarrBlock::EditIndexerToggleEnableAutomaticSearch,
ActiveRadarrBlock::EditIndexerToggleEnableInteractiveSearch,
ActiveRadarrBlock::EditIndexerUrlInput,
ActiveRadarrBlock::EditIndexerTagsInput,
];
pub static EDIT_INDEXER_TORRENT_SELECTION_BLOCKS: [ActiveRadarrBlock; 10] = [
ActiveRadarrBlock::EditIndexerNameInput,
ActiveRadarrBlock::EditIndexerToggleEnableRss,
ActiveRadarrBlock::EditIndexerToggleEnableAutomaticSearch,
ActiveRadarrBlock::EditIndexerToggleEnableInteractiveSearch,
ActiveRadarrBlock::EditIndexerConfirmPrompt,
ActiveRadarrBlock::EditIndexerUrlInput,
ActiveRadarrBlock::EditIndexerApiKeyInput,
ActiveRadarrBlock::EditIndexerSeedRatioInput,
ActiveRadarrBlock::EditIndexerTagsInput,
ActiveRadarrBlock::EditIndexerConfirmPrompt,
];
pub static EDIT_INDEXER_NZB_SELECTION_BLOCKS: [ActiveRadarrBlock; 10] = [
ActiveRadarrBlock::EditIndexerNameInput,
ActiveRadarrBlock::EditIndexerToggleEnableRss,
ActiveRadarrBlock::EditIndexerToggleEnableAutomaticSearch,
ActiveRadarrBlock::EditIndexerToggleEnableInteractiveSearch,
ActiveRadarrBlock::EditIndexerConfirmPrompt,
ActiveRadarrBlock::EditIndexerUrlInput,
ActiveRadarrBlock::EditIndexerApiKeyInput,
ActiveRadarrBlock::EditIndexerTagsInput,
ActiveRadarrBlock::EditIndexerConfirmPrompt,
ActiveRadarrBlock::EditIndexerConfirmPrompt,
];
pub static INDEXER_SETTINGS_BLOCKS: [ActiveRadarrBlock; 10] = [
ActiveRadarrBlock::IndexerSettingsPrompt,
ActiveRadarrBlock::IndexerSettingsAvailabilityDelayInput,
@@ -98,6 +98,7 @@ mod tests {
assert!(radarr_data.edit_movie_modal.is_none());
assert!(radarr_data.edit_collection_modal.is_none());
assert!(radarr_data.edit_root_folder.is_none());
assert!(radarr_data.edit_indexer_modal.is_none());
assert!(radarr_data.filtered_collections.is_none());
assert!(radarr_data.filtered_movies.is_none());
assert!(radarr_data.indexer_settings.is_none());
@@ -270,9 +271,10 @@ mod tests {
ActiveRadarrBlock, ADD_MOVIE_BLOCKS, ADD_MOVIE_SELECTION_BLOCKS, COLLECTIONS_BLOCKS,
COLLECTION_DETAILS_BLOCKS, DELETE_MOVIE_BLOCKS, DELETE_MOVIE_SELECTION_BLOCKS,
DOWNLOADS_BLOCKS, EDIT_COLLECTION_BLOCKS, EDIT_COLLECTION_SELECTION_BLOCKS,
EDIT_MOVIE_BLOCKS, EDIT_MOVIE_SELECTION_BLOCKS, INDEXERS_BLOCKS, INDEXER_SETTINGS_BLOCKS,
INDEXER_SETTINGS_SELECTION_BLOCKS, LIBRARY_BLOCKS, MOVIE_DETAILS_BLOCKS, ROOT_FOLDERS_BLOCKS,
SYSTEM_DETAILS_BLOCKS,
EDIT_INDEXER_BLOCKS, EDIT_INDEXER_NZB_SELECTION_BLOCKS,
EDIT_INDEXER_TORRENT_SELECTION_BLOCKS, EDIT_MOVIE_BLOCKS, EDIT_MOVIE_SELECTION_BLOCKS,
INDEXERS_BLOCKS, INDEXER_SETTINGS_BLOCKS, INDEXER_SETTINGS_SELECTION_BLOCKS, LIBRARY_BLOCKS,
MOVIE_DETAILS_BLOCKS, ROOT_FOLDERS_BLOCKS, SYSTEM_DETAILS_BLOCKS,
};
#[test]
@@ -299,12 +301,10 @@ mod tests {
#[test]
fn test_indexers_blocks_contents() {
assert_eq!(INDEXERS_BLOCKS.len(), 5);
assert_eq!(INDEXERS_BLOCKS.len(), 3);
assert!(INDEXERS_BLOCKS.contains(&ActiveRadarrBlock::AddIndexer));
assert!(INDEXERS_BLOCKS.contains(&ActiveRadarrBlock::EditIndexer));
assert!(INDEXERS_BLOCKS.contains(&ActiveRadarrBlock::DeleteIndexerPrompt));
assert!(INDEXERS_BLOCKS.contains(&ActiveRadarrBlock::Indexers));
assert!(INDEXERS_BLOCKS.contains(&ActiveRadarrBlock::TestAllIndexers));
}
#[test]
@@ -398,6 +398,25 @@ mod tests {
assert!(DELETE_MOVIE_BLOCKS.contains(&ActiveRadarrBlock::DeleteMovieToggleAddListExclusion));
}
#[test]
fn test_edit_indexer_blocks_contents() {
assert_eq!(EDIT_INDEXER_BLOCKS.len(), 10);
assert!(EDIT_INDEXER_BLOCKS.contains(&ActiveRadarrBlock::EditIndexerPrompt));
assert!(EDIT_INDEXER_BLOCKS.contains(&ActiveRadarrBlock::EditIndexerConfirmPrompt));
assert!(EDIT_INDEXER_BLOCKS.contains(&ActiveRadarrBlock::EditIndexerApiKeyInput));
assert!(EDIT_INDEXER_BLOCKS.contains(&ActiveRadarrBlock::EditIndexerNameInput));
assert!(EDIT_INDEXER_BLOCKS.contains(&ActiveRadarrBlock::EditIndexerSeedRatioInput));
assert!(EDIT_INDEXER_BLOCKS.contains(&ActiveRadarrBlock::EditIndexerToggleEnableRss));
assert!(
EDIT_INDEXER_BLOCKS.contains(&ActiveRadarrBlock::EditIndexerToggleEnableAutomaticSearch)
);
assert!(
EDIT_INDEXER_BLOCKS.contains(&ActiveRadarrBlock::EditIndexerToggleEnableInteractiveSearch)
);
assert!(EDIT_INDEXER_BLOCKS.contains(&ActiveRadarrBlock::EditIndexerUrlInput));
assert!(EDIT_INDEXER_BLOCKS.contains(&ActiveRadarrBlock::EditIndexerTagsInput));
}
#[test]
fn test_indexer_settings_blocks_contents() {
assert_eq!(INDEXER_SETTINGS_BLOCKS.len(), 10);
@@ -542,6 +561,101 @@ mod tests {
assert_eq!(delete_movie_block_iter.next(), None);
}
#[test]
fn test_edit_indexer_torrent_selection_blocks_ordering() {
let mut edit_indexer_torrent_selection_block_iter =
EDIT_INDEXER_TORRENT_SELECTION_BLOCKS.iter();
assert_eq!(
edit_indexer_torrent_selection_block_iter.next().unwrap(),
&ActiveRadarrBlock::EditIndexerNameInput
);
assert_eq!(
edit_indexer_torrent_selection_block_iter.next().unwrap(),
&ActiveRadarrBlock::EditIndexerToggleEnableRss
);
assert_eq!(
edit_indexer_torrent_selection_block_iter.next().unwrap(),
&ActiveRadarrBlock::EditIndexerToggleEnableAutomaticSearch
);
assert_eq!(
edit_indexer_torrent_selection_block_iter.next().unwrap(),
&ActiveRadarrBlock::EditIndexerToggleEnableInteractiveSearch
);
assert_eq!(
edit_indexer_torrent_selection_block_iter.next().unwrap(),
&ActiveRadarrBlock::EditIndexerConfirmPrompt
);
assert_eq!(
edit_indexer_torrent_selection_block_iter.next().unwrap(),
&ActiveRadarrBlock::EditIndexerUrlInput
);
assert_eq!(
edit_indexer_torrent_selection_block_iter.next().unwrap(),
&ActiveRadarrBlock::EditIndexerApiKeyInput
);
assert_eq!(
edit_indexer_torrent_selection_block_iter.next().unwrap(),
&ActiveRadarrBlock::EditIndexerSeedRatioInput
);
assert_eq!(
edit_indexer_torrent_selection_block_iter.next().unwrap(),
&ActiveRadarrBlock::EditIndexerTagsInput
);
assert_eq!(
edit_indexer_torrent_selection_block_iter.next().unwrap(),
&ActiveRadarrBlock::EditIndexerConfirmPrompt
);
assert_eq!(edit_indexer_torrent_selection_block_iter.next(), None);
}
#[test]
fn test_edit_indexer_nzb_selection_blocks_ordering() {
let mut edit_indexer_nzb_selection_block_iter = EDIT_INDEXER_NZB_SELECTION_BLOCKS.iter();
assert_eq!(
edit_indexer_nzb_selection_block_iter.next().unwrap(),
&ActiveRadarrBlock::EditIndexerNameInput
);
assert_eq!(
edit_indexer_nzb_selection_block_iter.next().unwrap(),
&ActiveRadarrBlock::EditIndexerToggleEnableRss
);
assert_eq!(
edit_indexer_nzb_selection_block_iter.next().unwrap(),
&ActiveRadarrBlock::EditIndexerToggleEnableAutomaticSearch
);
assert_eq!(
edit_indexer_nzb_selection_block_iter.next().unwrap(),
&ActiveRadarrBlock::EditIndexerToggleEnableInteractiveSearch
);
assert_eq!(
edit_indexer_nzb_selection_block_iter.next().unwrap(),
&ActiveRadarrBlock::EditIndexerConfirmPrompt
);
assert_eq!(
edit_indexer_nzb_selection_block_iter.next().unwrap(),
&ActiveRadarrBlock::EditIndexerUrlInput
);
assert_eq!(
edit_indexer_nzb_selection_block_iter.next().unwrap(),
&ActiveRadarrBlock::EditIndexerApiKeyInput
);
assert_eq!(
edit_indexer_nzb_selection_block_iter.next().unwrap(),
&ActiveRadarrBlock::EditIndexerTagsInput
);
assert_eq!(
edit_indexer_nzb_selection_block_iter.next().unwrap(),
&ActiveRadarrBlock::EditIndexerConfirmPrompt
);
assert_eq!(
edit_indexer_nzb_selection_block_iter.next().unwrap(),
&ActiveRadarrBlock::EditIndexerConfirmPrompt
);
assert_eq!(edit_indexer_nzb_selection_block_iter.next(), None);
}
#[test]
fn test_indexer_settings_selection_blocks_ordering() {
let mut indexer_settings_block_iter = INDEXER_SETTINGS_SELECTION_BLOCKS.iter();