feat: Created a History tab in the Radarr UI and created a list history command and mark-history-item-as-failed command for Radarr
This commit is contained in:
@@ -62,6 +62,11 @@ impl App<'_> {
|
|||||||
.dispatch_network_event(RadarrEvent::GetDownloads(500).into())
|
.dispatch_network_event(RadarrEvent::GetDownloads(500).into())
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
|
ActiveRadarrBlock::History => {
|
||||||
|
self
|
||||||
|
.dispatch_network_event(RadarrEvent::GetHistory(500).into())
|
||||||
|
.await;
|
||||||
|
}
|
||||||
ActiveRadarrBlock::Indexers => {
|
ActiveRadarrBlock::Indexers => {
|
||||||
self
|
self
|
||||||
.dispatch_network_event(RadarrEvent::GetTags.into())
|
.dispatch_network_event(RadarrEvent::GetTags.into())
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ mod tests {
|
|||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::app::context_clues::{
|
use crate::app::context_clues::{
|
||||||
BARE_POPUP_CONTEXT_CLUES, BLOCKLIST_CONTEXT_CLUES, CONFIRMATION_PROMPT_CONTEXT_CLUES,
|
BARE_POPUP_CONTEXT_CLUES, BLOCKLIST_CONTEXT_CLUES, CONFIRMATION_PROMPT_CONTEXT_CLUES,
|
||||||
ContextClue, ContextClueProvider, DOWNLOADS_CONTEXT_CLUES, INDEXERS_CONTEXT_CLUES,
|
ContextClue, ContextClueProvider, DOWNLOADS_CONTEXT_CLUES, HISTORY_CONTEXT_CLUES,
|
||||||
ROOT_FOLDERS_CONTEXT_CLUES, SYSTEM_CONTEXT_CLUES,
|
INDEXERS_CONTEXT_CLUES, ROOT_FOLDERS_CONTEXT_CLUES, SYSTEM_CONTEXT_CLUES,
|
||||||
};
|
};
|
||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||||
use crate::app::radarr::radarr_context_clues::{
|
use crate::app::radarr::radarr_context_clues::{
|
||||||
@@ -459,9 +459,10 @@ mod tests {
|
|||||||
#[case(1, ActiveRadarrBlock::Collections, &COLLECTIONS_CONTEXT_CLUES)]
|
#[case(1, ActiveRadarrBlock::Collections, &COLLECTIONS_CONTEXT_CLUES)]
|
||||||
#[case(2, ActiveRadarrBlock::Downloads, &DOWNLOADS_CONTEXT_CLUES)]
|
#[case(2, ActiveRadarrBlock::Downloads, &DOWNLOADS_CONTEXT_CLUES)]
|
||||||
#[case(3, ActiveRadarrBlock::Blocklist, &BLOCKLIST_CONTEXT_CLUES)]
|
#[case(3, ActiveRadarrBlock::Blocklist, &BLOCKLIST_CONTEXT_CLUES)]
|
||||||
#[case(4, ActiveRadarrBlock::RootFolders, &ROOT_FOLDERS_CONTEXT_CLUES)]
|
#[case(4, ActiveRadarrBlock::History, &HISTORY_CONTEXT_CLUES)]
|
||||||
#[case(5, ActiveRadarrBlock::Indexers, &INDEXERS_CONTEXT_CLUES)]
|
#[case(5, ActiveRadarrBlock::RootFolders, &ROOT_FOLDERS_CONTEXT_CLUES)]
|
||||||
#[case(6, ActiveRadarrBlock::System, &SYSTEM_CONTEXT_CLUES)]
|
#[case(6, ActiveRadarrBlock::Indexers, &INDEXERS_CONTEXT_CLUES)]
|
||||||
|
#[case(7, ActiveRadarrBlock::System, &SYSTEM_CONTEXT_CLUES)]
|
||||||
fn test_radarr_context_clue_provider_radarr_blocks_context_clues(
|
fn test_radarr_context_clue_provider_radarr_blocks_context_clues(
|
||||||
#[case] index: usize,
|
#[case] index: usize,
|
||||||
#[case] active_radarr_block: ActiveRadarrBlock,
|
#[case] active_radarr_block: ActiveRadarrBlock,
|
||||||
|
|||||||
@@ -147,6 +147,23 @@ mod tests {
|
|||||||
assert_eq!(app.tick_count, 0);
|
assert_eq!(app.tick_count, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_dispatch_by_history_block() {
|
||||||
|
let (mut app, mut sync_network_rx) = construct_app_unit();
|
||||||
|
|
||||||
|
app
|
||||||
|
.dispatch_by_radarr_block(&ActiveRadarrBlock::History)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
assert!(app.is_loading);
|
||||||
|
assert_eq!(
|
||||||
|
sync_network_rx.recv().await.unwrap(),
|
||||||
|
RadarrEvent::GetHistory(500).into()
|
||||||
|
);
|
||||||
|
assert!(!app.data.radarr_data.prompt_confirm);
|
||||||
|
assert_eq!(app.tick_count, 0);
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_dispatch_by_root_folders_block() {
|
async fn test_dispatch_by_root_folders_block() {
|
||||||
let (mut app, mut sync_network_rx) = construct_app_unit();
|
let (mut app, mut sync_network_rx) = construct_app_unit();
|
||||||
|
|||||||
@@ -29,6 +29,11 @@ pub enum RadarrListCommand {
|
|||||||
},
|
},
|
||||||
#[command(about = "List disk space details for all provisioned root folders in Radarr")]
|
#[command(about = "List disk space details for all provisioned root folders in Radarr")]
|
||||||
DiskSpace,
|
DiskSpace,
|
||||||
|
#[command(about = "Fetch all Radarr history events")]
|
||||||
|
History {
|
||||||
|
#[arg(long, help = "How many history events to fetch", default_value_t = 500)]
|
||||||
|
events: u64,
|
||||||
|
},
|
||||||
#[command(about = "List all Radarr indexers")]
|
#[command(about = "List all Radarr indexers")]
|
||||||
Indexers,
|
Indexers,
|
||||||
#[command(about = "Fetch Radarr logs")]
|
#[command(about = "Fetch Radarr logs")]
|
||||||
@@ -121,6 +126,13 @@ impl<'a, 'b> CliCommandHandler<'a, 'b, RadarrListCommand> for RadarrListCommandH
|
|||||||
.await?;
|
.await?;
|
||||||
serde_json::to_string_pretty(&resp)?
|
serde_json::to_string_pretty(&resp)?
|
||||||
}
|
}
|
||||||
|
RadarrListCommand::History { events: items } => {
|
||||||
|
let resp = self
|
||||||
|
.network
|
||||||
|
.handle_network_event(RadarrEvent::GetHistory(items).into())
|
||||||
|
.await?;
|
||||||
|
serde_json::to_string_pretty(&resp)?
|
||||||
|
}
|
||||||
RadarrListCommand::Indexers => {
|
RadarrListCommand::Indexers => {
|
||||||
let resp = self
|
let resp = self
|
||||||
.network
|
.network
|
||||||
|
|||||||
@@ -111,6 +111,29 @@ mod tests {
|
|||||||
assert_eq!(refresh_command, expected_args);
|
assert_eq!(refresh_command, expected_args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_list_history_events_flag_requires_arguments() {
|
||||||
|
let result =
|
||||||
|
Cli::command().try_get_matches_from(["managarr", "radarr", "list", "history", "--events"]);
|
||||||
|
|
||||||
|
assert_err!(&result);
|
||||||
|
assert_eq!(result.unwrap_err().kind(), ErrorKind::InvalidValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_list_history_default_values() {
|
||||||
|
let expected_args = RadarrListCommand::History { events: 500 };
|
||||||
|
let result = Cli::try_parse_from(["managarr", "radarr", "list", "history"]);
|
||||||
|
|
||||||
|
assert_ok!(&result);
|
||||||
|
|
||||||
|
let Some(Command::Radarr(RadarrCommand::List(history_command))) = result.unwrap().command
|
||||||
|
else {
|
||||||
|
panic!("Unexpected command type");
|
||||||
|
};
|
||||||
|
assert_eq!(history_command, expected_args);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_list_logs_default_values() {
|
fn test_list_logs_default_values() {
|
||||||
let expected_args = RadarrListCommand::Logs {
|
let expected_args = RadarrListCommand::Logs {
|
||||||
@@ -233,6 +256,32 @@ mod tests {
|
|||||||
assert_ok!(&result);
|
assert_ok!(&result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_handle_list_history_command() {
|
||||||
|
let expected_events = 1000;
|
||||||
|
let mut mock_network = MockNetworkTrait::new();
|
||||||
|
mock_network
|
||||||
|
.expect_handle_network_event()
|
||||||
|
.with(eq::<NetworkEvent>(
|
||||||
|
RadarrEvent::GetHistory(expected_events).into(),
|
||||||
|
))
|
||||||
|
.times(1)
|
||||||
|
.returning(|_| {
|
||||||
|
Ok(Serdeable::Radarr(RadarrSerdeable::Value(
|
||||||
|
json!({"testResponse": "response"}),
|
||||||
|
)))
|
||||||
|
});
|
||||||
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
|
let list_history_command = RadarrListCommand::History { events: 1000 };
|
||||||
|
|
||||||
|
let result =
|
||||||
|
RadarrListCommandHandler::with(&app_arc, list_history_command, &mut mock_network)
|
||||||
|
.handle()
|
||||||
|
.await;
|
||||||
|
|
||||||
|
assert_ok!(&result);
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_handle_list_logs_command() {
|
async fn test_handle_list_logs_command() {
|
||||||
let expected_events = 1000;
|
let expected_events = 1000;
|
||||||
|
|||||||
@@ -64,6 +64,15 @@ pub enum RadarrCommand {
|
|||||||
Refresh(RadarrRefreshCommand),
|
Refresh(RadarrRefreshCommand),
|
||||||
#[command(about = "Clear the blocklist")]
|
#[command(about = "Clear the blocklist")]
|
||||||
ClearBlocklist,
|
ClearBlocklist,
|
||||||
|
#[command(about = "Mark the Radarr history item with the given ID as 'failed'")]
|
||||||
|
MarkHistoryItemAsFailed {
|
||||||
|
#[arg(
|
||||||
|
long,
|
||||||
|
help = "The Radarr ID of the history item you wish to mark as 'failed'",
|
||||||
|
required = true
|
||||||
|
)]
|
||||||
|
history_item_id: i64,
|
||||||
|
},
|
||||||
#[command(about = "Manually download the given release for the specified movie ID")]
|
#[command(about = "Manually download the given release for the specified movie ID")]
|
||||||
DownloadRelease {
|
DownloadRelease {
|
||||||
#[arg(long, help = "The GUID of the release to download", required = true)]
|
#[arg(long, help = "The GUID of the release to download", required = true)]
|
||||||
@@ -208,6 +217,15 @@ impl<'a, 'b> CliCommandHandler<'a, 'b, RadarrCommand> for RadarrCliHandler<'a, '
|
|||||||
.await?;
|
.await?;
|
||||||
serde_json::to_string_pretty(&resp)?
|
serde_json::to_string_pretty(&resp)?
|
||||||
}
|
}
|
||||||
|
RadarrCommand::MarkHistoryItemAsFailed { history_item_id } => {
|
||||||
|
let _ = self
|
||||||
|
.network
|
||||||
|
.handle_network_event(RadarrEvent::MarkHistoryItemAsFailed(history_item_id).into())
|
||||||
|
.await?;
|
||||||
|
serde_json::to_string_pretty(
|
||||||
|
&serde_json::json!({"message": "Radarr history item marked as 'failed'"}),
|
||||||
|
)?
|
||||||
|
}
|
||||||
RadarrCommand::DownloadRelease {
|
RadarrCommand::DownloadRelease {
|
||||||
guid,
|
guid,
|
||||||
indexer_id,
|
indexer_id,
|
||||||
|
|||||||
@@ -31,6 +31,31 @@ mod tests {
|
|||||||
assert_ok!(&result);
|
assert_ok!(&result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_mark_history_item_as_failed_requires_history_item_id() {
|
||||||
|
let result =
|
||||||
|
Cli::command().try_get_matches_from(["managarr", "radarr", "mark-history-item-as-failed"]);
|
||||||
|
|
||||||
|
assert_err!(&result);
|
||||||
|
assert_eq!(
|
||||||
|
result.unwrap_err().kind(),
|
||||||
|
ErrorKind::MissingRequiredArgument
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_mark_history_item_as_failed_requirements_satisfied() {
|
||||||
|
let result = Cli::command().try_get_matches_from([
|
||||||
|
"managarr",
|
||||||
|
"radarr",
|
||||||
|
"mark-history-item-as-failed",
|
||||||
|
"--history-item-id",
|
||||||
|
"1",
|
||||||
|
]);
|
||||||
|
|
||||||
|
assert_ok!(&result);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_download_release_requires_movie_id() {
|
fn test_download_release_requires_movie_id() {
|
||||||
let result = Cli::command().try_get_matches_from([
|
let result = Cli::command().try_get_matches_from([
|
||||||
@@ -327,6 +352,36 @@ mod tests {
|
|||||||
assert_ok!(&result);
|
assert_ok!(&result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_mark_history_item_as_failed_command() {
|
||||||
|
let expected_history_item_id = 1;
|
||||||
|
let mut mock_network = MockNetworkTrait::new();
|
||||||
|
mock_network
|
||||||
|
.expect_handle_network_event()
|
||||||
|
.with(eq::<NetworkEvent>(
|
||||||
|
RadarrEvent::MarkHistoryItemAsFailed(expected_history_item_id).into(),
|
||||||
|
))
|
||||||
|
.times(1)
|
||||||
|
.returning(|_| {
|
||||||
|
Ok(Serdeable::Radarr(RadarrSerdeable::Value(
|
||||||
|
json!({"testResponse": "response"}),
|
||||||
|
)))
|
||||||
|
});
|
||||||
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
|
let mark_history_item_as_failed_command =
|
||||||
|
RadarrCommand::MarkHistoryItemAsFailed { history_item_id: 1 };
|
||||||
|
|
||||||
|
let result = RadarrCliHandler::with(
|
||||||
|
&app_arc,
|
||||||
|
mark_history_item_as_failed_command,
|
||||||
|
&mut mock_network,
|
||||||
|
)
|
||||||
|
.handle()
|
||||||
|
.await;
|
||||||
|
|
||||||
|
assert_ok!(&result);
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_download_release_command() {
|
async fn test_download_release_command() {
|
||||||
let expected_release_download_body = RadarrReleaseDownloadBody {
|
let expected_release_download_body = RadarrReleaseDownloadBody {
|
||||||
|
|||||||
@@ -356,6 +356,9 @@ mod test_utils {
|
|||||||
.radarr_data
|
.radarr_data
|
||||||
.movies
|
.movies
|
||||||
.set_items(vec![$crate::models::radarr_models::Movie::default()]);
|
.set_items(vec![$crate::models::radarr_models::Movie::default()]);
|
||||||
|
app.data.radarr_data.history.set_items(vec![
|
||||||
|
$crate::models::radarr_models::RadarrHistoryItem::default(),
|
||||||
|
]);
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
.radarr_data
|
.radarr_data
|
||||||
|
|||||||
@@ -91,9 +91,9 @@ mod tests {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app.data.radarr_data.main_tabs.get_active_route(),
|
app.data.radarr_data.main_tabs.get_active_route(),
|
||||||
ActiveRadarrBlock::RootFolders.into()
|
ActiveRadarrBlock::History.into()
|
||||||
);
|
);
|
||||||
assert_navigation_pushed!(app, ActiveRadarrBlock::RootFolders.into());
|
assert_navigation_pushed!(app, ActiveRadarrBlock::History.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
|
|||||||
@@ -0,0 +1,438 @@
|
|||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use std::cmp::Ordering;
|
||||||
|
|
||||||
|
use chrono::DateTime;
|
||||||
|
use pretty_assertions::{assert_eq, assert_str_eq};
|
||||||
|
use rstest::rstest;
|
||||||
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
|
use crate::app::App;
|
||||||
|
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||||
|
use crate::assert_navigation_pushed;
|
||||||
|
use crate::event::Key;
|
||||||
|
use crate::handlers::KeyEventHandler;
|
||||||
|
use crate::handlers::radarr_handlers::history::{HistoryHandler, history_sorting_options};
|
||||||
|
use crate::models::radarr_models::{RadarrHistoryEventType, RadarrHistoryItem};
|
||||||
|
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, HISTORY_BLOCKS};
|
||||||
|
use crate::models::servarr_models::{Language, Quality, QualityWrapper};
|
||||||
|
|
||||||
|
mod test_handle_left_right_action {
|
||||||
|
use pretty_assertions::assert_eq;
|
||||||
|
use rstest::rstest;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
use crate::assert_navigation_pushed;
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_history_tab_left(#[values(true, false)] is_ready: bool) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.push_navigation_stack(ActiveRadarrBlock::History.into());
|
||||||
|
app.is_loading = is_ready;
|
||||||
|
app.data.radarr_data.main_tabs.set_index(4);
|
||||||
|
|
||||||
|
HistoryHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.left.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveRadarrBlock::History,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.handle();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
app.data.radarr_data.main_tabs.get_active_route(),
|
||||||
|
ActiveRadarrBlock::Blocklist.into()
|
||||||
|
);
|
||||||
|
assert_navigation_pushed!(app, ActiveRadarrBlock::Blocklist.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_history_tab_right(#[values(true, false)] is_ready: bool) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.push_navigation_stack(ActiveRadarrBlock::History.into());
|
||||||
|
app.is_loading = is_ready;
|
||||||
|
app.data.radarr_data.main_tabs.set_index(4);
|
||||||
|
|
||||||
|
HistoryHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.right.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveRadarrBlock::History,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.handle();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
app.data.radarr_data.main_tabs.get_active_route(),
|
||||||
|
ActiveRadarrBlock::RootFolders.into()
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
app.get_current_route(),
|
||||||
|
ActiveRadarrBlock::RootFolders.into()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod test_handle_submit {
|
||||||
|
use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
const SUBMIT_KEY: Key = DEFAULT_KEYBINDINGS.submit.key;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_history_submit() {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.data.radarr_data.history.set_items(history_vec());
|
||||||
|
app.push_navigation_stack(ActiveRadarrBlock::History.into());
|
||||||
|
|
||||||
|
HistoryHandler::new(SUBMIT_KEY, &mut app, ActiveRadarrBlock::History, None).handle();
|
||||||
|
|
||||||
|
assert_navigation_pushed!(app, ActiveRadarrBlock::HistoryItemDetails.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_history_submit_no_op_when_not_ready() {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.is_loading = true;
|
||||||
|
app.data.radarr_data.history.set_items(history_vec());
|
||||||
|
app.push_navigation_stack(ActiveRadarrBlock::History.into());
|
||||||
|
|
||||||
|
HistoryHandler::new(SUBMIT_KEY, &mut app, ActiveRadarrBlock::History, None).handle();
|
||||||
|
|
||||||
|
assert_eq!(app.get_current_route(), ActiveRadarrBlock::History.into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod test_handle_esc {
|
||||||
|
use pretty_assertions::assert_eq;
|
||||||
|
use rstest::rstest;
|
||||||
|
|
||||||
|
use crate::models::servarr_data::radarr::radarr_data::radarr_test_utils::utils::create_test_radarr_data;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
use crate::assert_navigation_popped;
|
||||||
|
|
||||||
|
const ESC_KEY: Key = DEFAULT_KEYBINDINGS.esc.key;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_esc_history_item_details() {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app
|
||||||
|
.data
|
||||||
|
.radarr_data
|
||||||
|
.history
|
||||||
|
.set_items(vec![RadarrHistoryItem::default()]);
|
||||||
|
app.push_navigation_stack(ActiveRadarrBlock::History.into());
|
||||||
|
app.push_navigation_stack(ActiveRadarrBlock::HistoryItemDetails.into());
|
||||||
|
|
||||||
|
HistoryHandler::new(
|
||||||
|
ESC_KEY,
|
||||||
|
&mut app,
|
||||||
|
ActiveRadarrBlock::HistoryItemDetails,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.handle();
|
||||||
|
|
||||||
|
assert_navigation_popped!(app, ActiveRadarrBlock::History.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_default_esc(#[values(true, false)] is_ready: bool) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.is_loading = is_ready;
|
||||||
|
app.error = "test error".to_owned().into();
|
||||||
|
app.push_navigation_stack(ActiveRadarrBlock::History.into());
|
||||||
|
app.push_navigation_stack(ActiveRadarrBlock::History.into());
|
||||||
|
app.data.radarr_data = create_test_radarr_data();
|
||||||
|
app
|
||||||
|
.data
|
||||||
|
.radarr_data
|
||||||
|
.history
|
||||||
|
.set_items(vec![RadarrHistoryItem::default()]);
|
||||||
|
|
||||||
|
HistoryHandler::new(ESC_KEY, &mut app, ActiveRadarrBlock::History, None).handle();
|
||||||
|
|
||||||
|
assert_eq!(app.get_current_route(), ActiveRadarrBlock::History.into());
|
||||||
|
assert_is_empty!(app.error.text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod test_handle_key_char {
|
||||||
|
use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
use crate::assert_navigation_pushed;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_refresh_history_key() {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.data.radarr_data.history.set_items(history_vec());
|
||||||
|
app.push_navigation_stack(ActiveRadarrBlock::History.into());
|
||||||
|
|
||||||
|
HistoryHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.refresh.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveRadarrBlock::History,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.handle();
|
||||||
|
|
||||||
|
assert_navigation_pushed!(app, ActiveRadarrBlock::History.into());
|
||||||
|
assert!(app.should_refresh);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_refresh_history_key_no_op_when_not_ready() {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.is_loading = true;
|
||||||
|
app.data.radarr_data.history.set_items(history_vec());
|
||||||
|
app.push_navigation_stack(ActiveRadarrBlock::History.into());
|
||||||
|
|
||||||
|
HistoryHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.refresh.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveRadarrBlock::History,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.handle();
|
||||||
|
|
||||||
|
assert_eq!(app.get_current_route(), ActiveRadarrBlock::History.into());
|
||||||
|
assert!(!app.should_refresh);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_history_sorting_options_source_title() {
|
||||||
|
let expected_cmp_fn: fn(&RadarrHistoryItem, &RadarrHistoryItem) -> Ordering = |a, b| {
|
||||||
|
a.source_title
|
||||||
|
.text
|
||||||
|
.to_lowercase()
|
||||||
|
.cmp(&b.source_title.text.to_lowercase())
|
||||||
|
};
|
||||||
|
let mut expected_history_vec = history_vec();
|
||||||
|
expected_history_vec.sort_by(expected_cmp_fn);
|
||||||
|
|
||||||
|
let sort_option = history_sorting_options()[0].clone();
|
||||||
|
let mut sorted_history_vec = history_vec();
|
||||||
|
sorted_history_vec.sort_by(sort_option.cmp_fn.unwrap());
|
||||||
|
|
||||||
|
assert_eq!(sorted_history_vec, expected_history_vec);
|
||||||
|
assert_str_eq!(sort_option.name, "Source Title");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_history_sorting_options_event_type() {
|
||||||
|
let expected_cmp_fn: fn(&RadarrHistoryItem, &RadarrHistoryItem) -> Ordering = |a, b| {
|
||||||
|
a.event_type
|
||||||
|
.to_string()
|
||||||
|
.to_lowercase()
|
||||||
|
.cmp(&b.event_type.to_string().to_lowercase())
|
||||||
|
};
|
||||||
|
let mut expected_history_vec = history_vec();
|
||||||
|
expected_history_vec.sort_by(expected_cmp_fn);
|
||||||
|
|
||||||
|
let sort_option = history_sorting_options()[1].clone();
|
||||||
|
let mut sorted_history_vec = history_vec();
|
||||||
|
sorted_history_vec.sort_by(sort_option.cmp_fn.unwrap());
|
||||||
|
|
||||||
|
assert_eq!(sorted_history_vec, expected_history_vec);
|
||||||
|
assert_str_eq!(sort_option.name, "Event Type");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_history_sorting_options_language() {
|
||||||
|
let expected_cmp_fn: fn(&RadarrHistoryItem, &RadarrHistoryItem) -> Ordering = |a, b| {
|
||||||
|
let default_language = Language {
|
||||||
|
id: 1,
|
||||||
|
name: "_".to_owned(),
|
||||||
|
};
|
||||||
|
let language_a = a.languages.first().unwrap_or(&default_language);
|
||||||
|
let language_b = b.languages.first().unwrap_or(&default_language);
|
||||||
|
|
||||||
|
language_a.cmp(language_b)
|
||||||
|
};
|
||||||
|
let mut expected_history_vec = history_vec();
|
||||||
|
expected_history_vec.sort_by(expected_cmp_fn);
|
||||||
|
|
||||||
|
let sort_option = history_sorting_options()[2].clone();
|
||||||
|
let mut sorted_history_vec = history_vec();
|
||||||
|
sorted_history_vec.sort_by(sort_option.cmp_fn.unwrap());
|
||||||
|
|
||||||
|
assert_eq!(sorted_history_vec, expected_history_vec);
|
||||||
|
assert_str_eq!(sort_option.name, "Language");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_history_sorting_options_quality() {
|
||||||
|
let expected_cmp_fn: fn(&RadarrHistoryItem, &RadarrHistoryItem) -> Ordering = |a, b| {
|
||||||
|
a.quality
|
||||||
|
.quality
|
||||||
|
.name
|
||||||
|
.to_lowercase()
|
||||||
|
.cmp(&b.quality.quality.name.to_lowercase())
|
||||||
|
};
|
||||||
|
let mut expected_history_vec = history_vec();
|
||||||
|
expected_history_vec.sort_by(expected_cmp_fn);
|
||||||
|
|
||||||
|
let sort_option = history_sorting_options()[3].clone();
|
||||||
|
let mut sorted_history_vec = history_vec();
|
||||||
|
sorted_history_vec.sort_by(sort_option.cmp_fn.unwrap());
|
||||||
|
|
||||||
|
assert_eq!(sorted_history_vec, expected_history_vec);
|
||||||
|
assert_str_eq!(sort_option.name, "Quality");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_history_sorting_options_date() {
|
||||||
|
let expected_cmp_fn: fn(&RadarrHistoryItem, &RadarrHistoryItem) -> Ordering =
|
||||||
|
|a, b| a.date.cmp(&b.date);
|
||||||
|
let mut expected_history_vec = history_vec();
|
||||||
|
expected_history_vec.sort_by(expected_cmp_fn);
|
||||||
|
|
||||||
|
let sort_option = history_sorting_options()[4].clone();
|
||||||
|
let mut sorted_history_vec = history_vec();
|
||||||
|
sorted_history_vec.sort_by(sort_option.cmp_fn.unwrap());
|
||||||
|
|
||||||
|
assert_eq!(sorted_history_vec, expected_history_vec);
|
||||||
|
assert_str_eq!(sort_option.name, "Date");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_history_handler_accepts() {
|
||||||
|
ActiveRadarrBlock::iter().for_each(|active_radarr_block| {
|
||||||
|
if HISTORY_BLOCKS.contains(&active_radarr_block) {
|
||||||
|
assert!(HistoryHandler::accepts(active_radarr_block));
|
||||||
|
} else {
|
||||||
|
assert!(!HistoryHandler::accepts(active_radarr_block));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_history_handler_ignore_special_keys(
|
||||||
|
#[values(true, false)] ignore_special_keys_for_textbox_input: bool,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = ignore_special_keys_for_textbox_input;
|
||||||
|
let handler = HistoryHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveRadarrBlock::default(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
handler.ignore_special_keys(),
|
||||||
|
ignore_special_keys_for_textbox_input
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_history_handler_not_ready_when_loading() {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.push_navigation_stack(ActiveRadarrBlock::History.into());
|
||||||
|
app.is_loading = true;
|
||||||
|
|
||||||
|
let handler = HistoryHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveRadarrBlock::History,
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert!(!handler.is_ready());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_history_handler_not_ready_when_history_is_empty() {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.push_navigation_stack(ActiveRadarrBlock::History.into());
|
||||||
|
app.is_loading = false;
|
||||||
|
|
||||||
|
let handler = HistoryHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveRadarrBlock::History,
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert!(!handler.is_ready());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_history_handler_ready_when_not_loading_and_history_is_not_empty() {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.push_navigation_stack(ActiveRadarrBlock::History.into());
|
||||||
|
app.is_loading = false;
|
||||||
|
app
|
||||||
|
.data
|
||||||
|
.radarr_data
|
||||||
|
.history
|
||||||
|
.set_items(vec![RadarrHistoryItem::default()]);
|
||||||
|
|
||||||
|
let handler = HistoryHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveRadarrBlock::History,
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert!(handler.is_ready());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn history_vec() -> Vec<RadarrHistoryItem> {
|
||||||
|
vec![
|
||||||
|
RadarrHistoryItem {
|
||||||
|
id: 3,
|
||||||
|
source_title: "test 1".into(),
|
||||||
|
movie_id: 1,
|
||||||
|
event_type: RadarrHistoryEventType::Grabbed,
|
||||||
|
languages: vec![Language {
|
||||||
|
id: 1,
|
||||||
|
name: "telgu".to_owned(),
|
||||||
|
}],
|
||||||
|
quality: QualityWrapper {
|
||||||
|
quality: Quality {
|
||||||
|
name: "HD - 1080p".to_owned(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
date: DateTime::from(DateTime::parse_from_rfc3339("2024-01-10T07:28:45Z").unwrap()),
|
||||||
|
..RadarrHistoryItem::default()
|
||||||
|
},
|
||||||
|
RadarrHistoryItem {
|
||||||
|
id: 2,
|
||||||
|
source_title: "test 2".into(),
|
||||||
|
movie_id: 2,
|
||||||
|
event_type: RadarrHistoryEventType::DownloadFolderImported,
|
||||||
|
languages: vec![Language {
|
||||||
|
id: 3,
|
||||||
|
name: "chinese".to_owned(),
|
||||||
|
}],
|
||||||
|
quality: QualityWrapper {
|
||||||
|
quality: Quality {
|
||||||
|
name: "SD - 720p".to_owned(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
date: DateTime::from(DateTime::parse_from_rfc3339("2024-02-10T07:28:45Z").unwrap()),
|
||||||
|
..RadarrHistoryItem::default()
|
||||||
|
},
|
||||||
|
RadarrHistoryItem {
|
||||||
|
id: 1,
|
||||||
|
source_title: "test 3".into(),
|
||||||
|
movie_id: 3,
|
||||||
|
event_type: RadarrHistoryEventType::MovieFileDeleted,
|
||||||
|
languages: vec![Language {
|
||||||
|
id: 1,
|
||||||
|
name: "english".to_owned(),
|
||||||
|
}],
|
||||||
|
quality: QualityWrapper {
|
||||||
|
quality: Quality {
|
||||||
|
name: "HD - 1080p".to_owned(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
date: DateTime::from(DateTime::parse_from_rfc3339("2024-03-10T07:28:45Z").unwrap()),
|
||||||
|
..RadarrHistoryItem::default()
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,179 @@
|
|||||||
|
use crate::app::App;
|
||||||
|
use crate::event::Key;
|
||||||
|
use crate::handlers::radarr_handlers::handle_change_tab_left_right_keys;
|
||||||
|
use crate::handlers::table_handler::{TableHandlingConfig, handle_table};
|
||||||
|
use crate::handlers::{KeyEventHandler, handle_clear_errors};
|
||||||
|
use crate::matches_key;
|
||||||
|
use crate::models::Route;
|
||||||
|
use crate::models::radarr_models::RadarrHistoryItem;
|
||||||
|
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, HISTORY_BLOCKS};
|
||||||
|
use crate::models::servarr_models::Language;
|
||||||
|
use crate::models::stateful_table::SortOption;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[path = "history_handler_tests.rs"]
|
||||||
|
mod history_handler_tests;
|
||||||
|
|
||||||
|
pub(super) struct HistoryHandler<'a, 'b> {
|
||||||
|
key: Key,
|
||||||
|
app: &'a mut App<'b>,
|
||||||
|
active_radarr_block: ActiveRadarrBlock,
|
||||||
|
_context: Option<ActiveRadarrBlock>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl HistoryHandler<'_, '_> {}
|
||||||
|
|
||||||
|
impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for HistoryHandler<'a, 'b> {
|
||||||
|
fn handle(&mut self) {
|
||||||
|
let history_table_handling_config = TableHandlingConfig::new(ActiveRadarrBlock::History.into())
|
||||||
|
.sorting_block(ActiveRadarrBlock::HistorySortPrompt.into())
|
||||||
|
.sort_options(history_sorting_options())
|
||||||
|
.searching_block(ActiveRadarrBlock::SearchHistory.into())
|
||||||
|
.search_error_block(ActiveRadarrBlock::SearchHistoryError.into())
|
||||||
|
.search_field_fn(|history| &history.source_title.text)
|
||||||
|
.filtering_block(ActiveRadarrBlock::FilterHistory.into())
|
||||||
|
.filter_error_block(ActiveRadarrBlock::FilterHistoryError.into())
|
||||||
|
.filter_field_fn(|history| &history.source_title.text);
|
||||||
|
|
||||||
|
if !handle_table(
|
||||||
|
self,
|
||||||
|
|app| &mut app.data.radarr_data.history,
|
||||||
|
history_table_handling_config,
|
||||||
|
) {
|
||||||
|
self.handle_key_event();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn accepts(active_block: ActiveRadarrBlock) -> bool {
|
||||||
|
HISTORY_BLOCKS.contains(&active_block)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new(
|
||||||
|
key: Key,
|
||||||
|
app: &'a mut App<'b>,
|
||||||
|
active_block: ActiveRadarrBlock,
|
||||||
|
context: Option<ActiveRadarrBlock>,
|
||||||
|
) -> Self {
|
||||||
|
HistoryHandler {
|
||||||
|
key,
|
||||||
|
app,
|
||||||
|
active_radarr_block: active_block,
|
||||||
|
_context: context,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_key(&self) -> Key {
|
||||||
|
self.key
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_ready(&self) -> bool {
|
||||||
|
!self.app.is_loading && !self.app.data.radarr_data.history.is_empty()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_scroll_up(&mut self) {}
|
||||||
|
|
||||||
|
fn handle_scroll_down(&mut self) {}
|
||||||
|
|
||||||
|
fn handle_home(&mut self) {}
|
||||||
|
|
||||||
|
fn handle_end(&mut self) {}
|
||||||
|
|
||||||
|
fn handle_delete(&mut self) {}
|
||||||
|
|
||||||
|
fn handle_left_right_action(&mut self) {
|
||||||
|
if self.active_radarr_block == ActiveRadarrBlock::History {
|
||||||
|
handle_change_tab_left_right_keys(self.app, self.key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_submit(&mut self) {
|
||||||
|
if self.active_radarr_block == ActiveRadarrBlock::History {
|
||||||
|
self
|
||||||
|
.app
|
||||||
|
.push_navigation_stack(ActiveRadarrBlock::HistoryItemDetails.into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_esc(&mut self) {
|
||||||
|
if self.active_radarr_block == ActiveRadarrBlock::HistoryItemDetails {
|
||||||
|
self.app.pop_navigation_stack();
|
||||||
|
} else {
|
||||||
|
handle_clear_errors(self.app);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_char_key_event(&mut self) {
|
||||||
|
let key = self.key;
|
||||||
|
if self.active_radarr_block == ActiveRadarrBlock::History {
|
||||||
|
match self.key {
|
||||||
|
_ if matches_key!(refresh, key) => {
|
||||||
|
self.app.should_refresh = true;
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn app_mut(&mut self) -> &mut App<'b> {
|
||||||
|
self.app
|
||||||
|
}
|
||||||
|
|
||||||
|
fn current_route(&self) -> Route {
|
||||||
|
self.app.get_current_route()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(in crate::handlers::radarr_handlers) fn history_sorting_options()
|
||||||
|
-> Vec<SortOption<RadarrHistoryItem>> {
|
||||||
|
vec![
|
||||||
|
SortOption {
|
||||||
|
name: "Source Title",
|
||||||
|
cmp_fn: Some(|a, b| {
|
||||||
|
a.source_title
|
||||||
|
.text
|
||||||
|
.to_lowercase()
|
||||||
|
.cmp(&b.source_title.text.to_lowercase())
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
SortOption {
|
||||||
|
name: "Event Type",
|
||||||
|
cmp_fn: Some(|a, b| {
|
||||||
|
a.event_type
|
||||||
|
.to_string()
|
||||||
|
.to_lowercase()
|
||||||
|
.cmp(&b.event_type.to_string().to_lowercase())
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
SortOption {
|
||||||
|
name: "Language",
|
||||||
|
cmp_fn: Some(|a, b| {
|
||||||
|
let default_language = Language {
|
||||||
|
id: 1,
|
||||||
|
name: "_".to_owned(),
|
||||||
|
};
|
||||||
|
let language_a = a.languages.first().unwrap_or(&default_language);
|
||||||
|
let language_b = b.languages.first().unwrap_or(&default_language);
|
||||||
|
|
||||||
|
language_a.cmp(language_b)
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
SortOption {
|
||||||
|
name: "Quality",
|
||||||
|
cmp_fn: Some(|a, b| {
|
||||||
|
a.quality
|
||||||
|
.quality
|
||||||
|
.name
|
||||||
|
.to_lowercase()
|
||||||
|
.cmp(&b.quality.quality.name.to_lowercase())
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
SortOption {
|
||||||
|
name: "Date",
|
||||||
|
cmp_fn: Some(|a, b| a.date.cmp(&b.date)),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -65,7 +65,7 @@ mod tests {
|
|||||||
fn test_indexers_tab_left(#[values(true, false)] is_ready: bool) {
|
fn test_indexers_tab_left(#[values(true, false)] is_ready: bool) {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = is_ready;
|
app.is_loading = is_ready;
|
||||||
app.data.radarr_data.main_tabs.set_index(5);
|
app.data.radarr_data.main_tabs.set_index(6);
|
||||||
|
|
||||||
IndexersHandler::new(
|
IndexersHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.left.key,
|
DEFAULT_KEYBINDINGS.left.key,
|
||||||
@@ -86,7 +86,7 @@ mod tests {
|
|||||||
fn test_indexers_tab_right(#[values(true, false)] is_ready: bool) {
|
fn test_indexers_tab_right(#[values(true, false)] is_ready: bool) {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = is_ready;
|
app.is_loading = is_ready;
|
||||||
app.data.radarr_data.main_tabs.set_index(5);
|
app.data.radarr_data.main_tabs.set_index(6);
|
||||||
|
|
||||||
IndexersHandler::new(
|
IndexersHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.right.key,
|
DEFAULT_KEYBINDINGS.right.key,
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ use crate::handlers::KeyEventHandler;
|
|||||||
use crate::handlers::radarr_handlers::blocklist::BlocklistHandler;
|
use crate::handlers::radarr_handlers::blocklist::BlocklistHandler;
|
||||||
use crate::handlers::radarr_handlers::collections::CollectionsHandler;
|
use crate::handlers::radarr_handlers::collections::CollectionsHandler;
|
||||||
use crate::handlers::radarr_handlers::downloads::DownloadsHandler;
|
use crate::handlers::radarr_handlers::downloads::DownloadsHandler;
|
||||||
|
use crate::handlers::radarr_handlers::history::HistoryHandler;
|
||||||
use crate::handlers::radarr_handlers::indexers::IndexersHandler;
|
use crate::handlers::radarr_handlers::indexers::IndexersHandler;
|
||||||
use crate::handlers::radarr_handlers::library::LibraryHandler;
|
use crate::handlers::radarr_handlers::library::LibraryHandler;
|
||||||
use crate::handlers::radarr_handlers::root_folders::RootFoldersHandler;
|
use crate::handlers::radarr_handlers::root_folders::RootFoldersHandler;
|
||||||
@@ -13,6 +14,7 @@ use crate::{App, Key, matches_key};
|
|||||||
mod blocklist;
|
mod blocklist;
|
||||||
mod collections;
|
mod collections;
|
||||||
mod downloads;
|
mod downloads;
|
||||||
|
mod history;
|
||||||
mod indexers;
|
mod indexers;
|
||||||
mod library;
|
mod library;
|
||||||
mod root_folders;
|
mod root_folders;
|
||||||
@@ -51,6 +53,9 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for RadarrHandler<'a, 'b
|
|||||||
_ if DownloadsHandler::accepts(self.active_radarr_block) => {
|
_ if DownloadsHandler::accepts(self.active_radarr_block) => {
|
||||||
DownloadsHandler::new(self.key, self.app, self.active_radarr_block, self.context).handle()
|
DownloadsHandler::new(self.key, self.app, self.active_radarr_block, self.context).handle()
|
||||||
}
|
}
|
||||||
|
_ if HistoryHandler::accepts(self.active_radarr_block) => {
|
||||||
|
HistoryHandler::new(self.key, self.app, self.active_radarr_block, self.context).handle()
|
||||||
|
}
|
||||||
_ if RootFoldersHandler::accepts(self.active_radarr_block) => {
|
_ if RootFoldersHandler::accepts(self.active_radarr_block) => {
|
||||||
RootFoldersHandler::new(self.key, self.app, self.active_radarr_block, self.context).handle()
|
RootFoldersHandler::new(self.key, self.app, self.active_radarr_block, self.context).handle()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,10 +16,11 @@ mod tests {
|
|||||||
#[case(0, ActiveRadarrBlock::System, ActiveRadarrBlock::Collections)]
|
#[case(0, ActiveRadarrBlock::System, ActiveRadarrBlock::Collections)]
|
||||||
#[case(1, ActiveRadarrBlock::Movies, ActiveRadarrBlock::Downloads)]
|
#[case(1, ActiveRadarrBlock::Movies, ActiveRadarrBlock::Downloads)]
|
||||||
#[case(2, ActiveRadarrBlock::Collections, ActiveRadarrBlock::Blocklist)]
|
#[case(2, ActiveRadarrBlock::Collections, ActiveRadarrBlock::Blocklist)]
|
||||||
#[case(3, ActiveRadarrBlock::Downloads, ActiveRadarrBlock::RootFolders)]
|
#[case(3, ActiveRadarrBlock::Downloads, ActiveRadarrBlock::History)]
|
||||||
#[case(4, ActiveRadarrBlock::Blocklist, ActiveRadarrBlock::Indexers)]
|
#[case(4, ActiveRadarrBlock::Blocklist, ActiveRadarrBlock::RootFolders)]
|
||||||
#[case(5, ActiveRadarrBlock::RootFolders, ActiveRadarrBlock::System)]
|
#[case(5, ActiveRadarrBlock::History, ActiveRadarrBlock::Indexers)]
|
||||||
#[case(6, ActiveRadarrBlock::Indexers, ActiveRadarrBlock::Movies)]
|
#[case(6, ActiveRadarrBlock::RootFolders, ActiveRadarrBlock::System)]
|
||||||
|
#[case(7, ActiveRadarrBlock::Indexers, ActiveRadarrBlock::Movies)]
|
||||||
fn test_radarr_handler_change_tab_left_right_keys(
|
fn test_radarr_handler_change_tab_left_right_keys(
|
||||||
#[case] index: usize,
|
#[case] index: usize,
|
||||||
#[case] left_block: ActiveRadarrBlock,
|
#[case] left_block: ActiveRadarrBlock,
|
||||||
@@ -51,10 +52,11 @@ mod tests {
|
|||||||
#[case(0, ActiveRadarrBlock::System, ActiveRadarrBlock::Collections)]
|
#[case(0, ActiveRadarrBlock::System, ActiveRadarrBlock::Collections)]
|
||||||
#[case(1, ActiveRadarrBlock::Movies, ActiveRadarrBlock::Downloads)]
|
#[case(1, ActiveRadarrBlock::Movies, ActiveRadarrBlock::Downloads)]
|
||||||
#[case(2, ActiveRadarrBlock::Collections, ActiveRadarrBlock::Blocklist)]
|
#[case(2, ActiveRadarrBlock::Collections, ActiveRadarrBlock::Blocklist)]
|
||||||
#[case(3, ActiveRadarrBlock::Downloads, ActiveRadarrBlock::RootFolders)]
|
#[case(3, ActiveRadarrBlock::Downloads, ActiveRadarrBlock::History)]
|
||||||
#[case(4, ActiveRadarrBlock::Blocklist, ActiveRadarrBlock::Indexers)]
|
#[case(4, ActiveRadarrBlock::Blocklist, ActiveRadarrBlock::RootFolders)]
|
||||||
#[case(5, ActiveRadarrBlock::RootFolders, ActiveRadarrBlock::System)]
|
#[case(5, ActiveRadarrBlock::History, ActiveRadarrBlock::Indexers)]
|
||||||
#[case(6, ActiveRadarrBlock::Indexers, ActiveRadarrBlock::Movies)]
|
#[case(6, ActiveRadarrBlock::RootFolders, ActiveRadarrBlock::System)]
|
||||||
|
#[case(7, ActiveRadarrBlock::Indexers, ActiveRadarrBlock::Movies)]
|
||||||
fn test_radarr_handler_change_tab_left_right_keys_alt_navigation(
|
fn test_radarr_handler_change_tab_left_right_keys_alt_navigation(
|
||||||
#[case] index: usize,
|
#[case] index: usize,
|
||||||
#[case] left_block: ActiveRadarrBlock,
|
#[case] left_block: ActiveRadarrBlock,
|
||||||
@@ -88,9 +90,10 @@ mod tests {
|
|||||||
#[case(1, ActiveRadarrBlock::Collections)]
|
#[case(1, ActiveRadarrBlock::Collections)]
|
||||||
#[case(2, ActiveRadarrBlock::Downloads)]
|
#[case(2, ActiveRadarrBlock::Downloads)]
|
||||||
#[case(3, ActiveRadarrBlock::Blocklist)]
|
#[case(3, ActiveRadarrBlock::Blocklist)]
|
||||||
#[case(4, ActiveRadarrBlock::RootFolders)]
|
#[case(4, ActiveRadarrBlock::History)]
|
||||||
#[case(5, ActiveRadarrBlock::Indexers)]
|
#[case(5, ActiveRadarrBlock::RootFolders)]
|
||||||
#[case(6, ActiveRadarrBlock::System)]
|
#[case(6, ActiveRadarrBlock::Indexers)]
|
||||||
|
#[case(7, ActiveRadarrBlock::System)]
|
||||||
fn test_radarr_handler_change_tab_left_right_keys_alt_navigation_no_op_when_ignoring_quit_key(
|
fn test_radarr_handler_change_tab_left_right_keys_alt_navigation_no_op_when_ignoring_quit_key(
|
||||||
#[case] index: usize,
|
#[case] index: usize,
|
||||||
#[case] block: ActiveRadarrBlock,
|
#[case] block: ActiveRadarrBlock,
|
||||||
@@ -281,6 +284,26 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_delegates_history_blocks_to_history_handler(
|
||||||
|
#[values(
|
||||||
|
ActiveRadarrBlock::History,
|
||||||
|
ActiveRadarrBlock::HistoryItemDetails,
|
||||||
|
ActiveRadarrBlock::HistorySortPrompt,
|
||||||
|
ActiveRadarrBlock::FilterHistory,
|
||||||
|
ActiveRadarrBlock::FilterHistoryError,
|
||||||
|
ActiveRadarrBlock::SearchHistory,
|
||||||
|
ActiveRadarrBlock::SearchHistoryError
|
||||||
|
)]
|
||||||
|
active_radarr_block: ActiveRadarrBlock,
|
||||||
|
) {
|
||||||
|
test_handler_delegation!(
|
||||||
|
RadarrHandler,
|
||||||
|
ActiveRadarrBlock::History,
|
||||||
|
active_radarr_block
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_radarr_handler_accepts() {
|
fn test_radarr_handler_accepts() {
|
||||||
ActiveRadarrBlock::iter().for_each(|active_radarr_block| {
|
ActiveRadarrBlock::iter().for_each(|active_radarr_block| {
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ mod tests {
|
|||||||
fn test_root_folders_tab_left(#[values(true, false)] is_ready: bool) {
|
fn test_root_folders_tab_left(#[values(true, false)] is_ready: bool) {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = is_ready;
|
app.is_loading = is_ready;
|
||||||
app.data.radarr_data.main_tabs.set_index(4);
|
app.data.radarr_data.main_tabs.set_index(5);
|
||||||
|
|
||||||
RootFoldersHandler::new(
|
RootFoldersHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.left.key,
|
DEFAULT_KEYBINDINGS.left.key,
|
||||||
@@ -142,16 +142,16 @@ mod tests {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app.data.radarr_data.main_tabs.get_active_route(),
|
app.data.radarr_data.main_tabs.get_active_route(),
|
||||||
ActiveRadarrBlock::Blocklist.into()
|
ActiveRadarrBlock::History.into()
|
||||||
);
|
);
|
||||||
assert_navigation_pushed!(app, ActiveRadarrBlock::Blocklist.into());
|
assert_navigation_pushed!(app, ActiveRadarrBlock::History.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_root_folders_tab_right(#[values(true, false)] is_ready: bool) {
|
fn test_root_folders_tab_right(#[values(true, false)] is_ready: bool) {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = is_ready;
|
app.is_loading = is_ready;
|
||||||
app.data.radarr_data.main_tabs.set_index(4);
|
app.data.radarr_data.main_tabs.set_index(5);
|
||||||
|
|
||||||
RootFoldersHandler::new(
|
RootFoldersHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.right.key,
|
DEFAULT_KEYBINDINGS.right.key,
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ mod tests {
|
|||||||
fn test_system_tab_left(#[values(true, false)] is_ready: bool) {
|
fn test_system_tab_left(#[values(true, false)] is_ready: bool) {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = is_ready;
|
app.is_loading = is_ready;
|
||||||
app.data.radarr_data.main_tabs.set_index(6);
|
app.data.radarr_data.main_tabs.set_index(7);
|
||||||
|
|
||||||
SystemHandler::new(
|
SystemHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.left.key,
|
DEFAULT_KEYBINDINGS.left.key,
|
||||||
@@ -47,7 +47,7 @@ mod tests {
|
|||||||
fn test_system_tab_right(#[values(true, false)] is_ready: bool) {
|
fn test_system_tab_right(#[values(true, false)] is_ready: bool) {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = is_ready;
|
app.is_loading = is_ready;
|
||||||
app.data.radarr_data.main_tabs.set_index(6);
|
app.data.radarr_data.main_tabs.set_index(7);
|
||||||
|
|
||||||
SystemHandler::new(
|
SystemHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.right.key,
|
DEFAULT_KEYBINDINGS.right.key,
|
||||||
|
|||||||
@@ -408,6 +408,69 @@ pub struct SystemStatus {
|
|||||||
pub start_time: DateTime<Utc>,
|
pub start_time: DateTime<Utc>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Default, Debug, Clone, PartialEq, Eq)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct RadarrHistoryWrapper {
|
||||||
|
pub records: Vec<RadarrHistoryItem>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Default, Debug, Clone, PartialEq, Eq)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct RadarrHistoryData {
|
||||||
|
pub indexer: Option<String>,
|
||||||
|
pub release_group: Option<String>,
|
||||||
|
pub nzb_info_url: Option<String>,
|
||||||
|
pub download_client: Option<String>,
|
||||||
|
pub download_client_name: Option<String>,
|
||||||
|
pub age: Option<String>,
|
||||||
|
pub published_date: Option<DateTime<Utc>>,
|
||||||
|
pub message: Option<String>,
|
||||||
|
pub reason: Option<String>,
|
||||||
|
pub dropped_path: Option<String>,
|
||||||
|
pub imported_path: Option<String>,
|
||||||
|
pub source_path: Option<String>,
|
||||||
|
pub path: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(
|
||||||
|
Serialize, Deserialize, Default, Debug, Clone, PartialEq, Eq, Display, EnumDisplayStyle,
|
||||||
|
)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
#[strum(serialize_all = "camelCase")]
|
||||||
|
pub enum RadarrHistoryEventType {
|
||||||
|
#[default]
|
||||||
|
Unknown,
|
||||||
|
Grabbed,
|
||||||
|
#[display_style(name = "Download Folder Imported")]
|
||||||
|
DownloadFolderImported,
|
||||||
|
#[display_style(name = "Download Failed")]
|
||||||
|
DownloadFailed,
|
||||||
|
#[display_style(name = "Movie File Deleted")]
|
||||||
|
MovieFileDeleted,
|
||||||
|
#[display_style(name = "Movie Folder Imported")]
|
||||||
|
MovieFolderImported,
|
||||||
|
#[display_style(name = "Movie File Renamed")]
|
||||||
|
MovieFileRenamed,
|
||||||
|
#[display_style(name = "Download Ignored")]
|
||||||
|
DownloadIgnored,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Default, Debug, Clone, PartialEq, Eq)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct RadarrHistoryItem {
|
||||||
|
#[serde(deserialize_with = "super::from_i64")]
|
||||||
|
pub id: i64,
|
||||||
|
pub source_title: HorizontallyScrollableText,
|
||||||
|
#[serde(deserialize_with = "super::from_i64")]
|
||||||
|
pub movie_id: i64,
|
||||||
|
pub quality: QualityWrapper,
|
||||||
|
pub languages: Vec<Language>,
|
||||||
|
pub date: DateTime<Utc>,
|
||||||
|
pub event_type: RadarrHistoryEventType,
|
||||||
|
#[serde(default)]
|
||||||
|
pub data: RadarrHistoryData,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default, Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
|
#[derive(Default, Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct RadarrTask {
|
pub struct RadarrTask {
|
||||||
@@ -461,6 +524,7 @@ serde_enum_from!(
|
|||||||
Credits(Vec<Credit>),
|
Credits(Vec<Credit>),
|
||||||
DiskSpaces(Vec<DiskSpace>),
|
DiskSpaces(Vec<DiskSpace>),
|
||||||
DownloadsResponse(DownloadsResponse),
|
DownloadsResponse(DownloadsResponse),
|
||||||
|
HistoryWrapper(RadarrHistoryWrapper),
|
||||||
HostConfig(HostConfig),
|
HostConfig(HostConfig),
|
||||||
Indexers(Vec<Indexer>),
|
Indexers(Vec<Indexer>),
|
||||||
IndexerSettings(IndexerSettings),
|
IndexerSettings(IndexerSettings),
|
||||||
|
|||||||
@@ -3,6 +3,9 @@ mod tests {
|
|||||||
use pretty_assertions::{assert_eq, assert_str_eq};
|
use pretty_assertions::{assert_eq, assert_str_eq};
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
|
|
||||||
|
use crate::models::radarr_models::{
|
||||||
|
RadarrHistoryEventType, RadarrHistoryItem, RadarrHistoryWrapper,
|
||||||
|
};
|
||||||
use crate::models::{
|
use crate::models::{
|
||||||
Serdeable,
|
Serdeable,
|
||||||
radarr_models::{
|
radarr_models::{
|
||||||
@@ -61,6 +64,66 @@ mod tests {
|
|||||||
assert_str_eq!(MovieMonitor::None.to_display_str(), "None");
|
assert_str_eq!(MovieMonitor::None.to_display_str(), "None");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_radarr_history_event_type_display() {
|
||||||
|
assert_str_eq!(RadarrHistoryEventType::Unknown.to_string(), "unknown");
|
||||||
|
assert_str_eq!(RadarrHistoryEventType::Grabbed.to_string(), "grabbed");
|
||||||
|
assert_str_eq!(
|
||||||
|
RadarrHistoryEventType::DownloadFolderImported.to_string(),
|
||||||
|
"downloadFolderImported"
|
||||||
|
);
|
||||||
|
assert_str_eq!(
|
||||||
|
RadarrHistoryEventType::DownloadFailed.to_string(),
|
||||||
|
"downloadFailed"
|
||||||
|
);
|
||||||
|
assert_str_eq!(
|
||||||
|
RadarrHistoryEventType::MovieFileDeleted.to_string(),
|
||||||
|
"movieFileDeleted"
|
||||||
|
);
|
||||||
|
assert_str_eq!(
|
||||||
|
RadarrHistoryEventType::MovieFolderImported.to_string(),
|
||||||
|
"movieFolderImported"
|
||||||
|
);
|
||||||
|
assert_str_eq!(
|
||||||
|
RadarrHistoryEventType::MovieFileRenamed.to_string(),
|
||||||
|
"movieFileRenamed"
|
||||||
|
);
|
||||||
|
assert_str_eq!(
|
||||||
|
RadarrHistoryEventType::DownloadIgnored.to_string(),
|
||||||
|
"downloadIgnored"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_radarr_history_event_type_to_display_str() {
|
||||||
|
assert_str_eq!(RadarrHistoryEventType::Unknown.to_display_str(), "Unknown");
|
||||||
|
assert_str_eq!(RadarrHistoryEventType::Grabbed.to_display_str(), "Grabbed");
|
||||||
|
assert_str_eq!(
|
||||||
|
RadarrHistoryEventType::DownloadFolderImported.to_display_str(),
|
||||||
|
"Download Folder Imported"
|
||||||
|
);
|
||||||
|
assert_str_eq!(
|
||||||
|
RadarrHistoryEventType::DownloadFailed.to_display_str(),
|
||||||
|
"Download Failed"
|
||||||
|
);
|
||||||
|
assert_str_eq!(
|
||||||
|
RadarrHistoryEventType::MovieFileDeleted.to_display_str(),
|
||||||
|
"Movie File Deleted"
|
||||||
|
);
|
||||||
|
assert_str_eq!(
|
||||||
|
RadarrHistoryEventType::MovieFolderImported.to_display_str(),
|
||||||
|
"Movie Folder Imported"
|
||||||
|
);
|
||||||
|
assert_str_eq!(
|
||||||
|
RadarrHistoryEventType::MovieFileRenamed.to_display_str(),
|
||||||
|
"Movie File Renamed"
|
||||||
|
);
|
||||||
|
assert_str_eq!(
|
||||||
|
RadarrHistoryEventType::DownloadIgnored.to_display_str(),
|
||||||
|
"Download Ignored"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_download_record_default_indexer_value() {
|
fn test_download_record_default_indexer_value() {
|
||||||
let json = r#"{
|
let json = r#"{
|
||||||
@@ -235,6 +298,23 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_radarr_serdeable_from_history_wrapper() {
|
||||||
|
let history_wrapper = RadarrHistoryWrapper {
|
||||||
|
records: vec![RadarrHistoryItem {
|
||||||
|
id: 1,
|
||||||
|
..RadarrHistoryItem::default()
|
||||||
|
}],
|
||||||
|
};
|
||||||
|
|
||||||
|
let radarr_serdeable: RadarrSerdeable = history_wrapper.clone().into();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
radarr_serdeable,
|
||||||
|
RadarrSerdeable::HistoryWrapper(history_wrapper)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_radarr_serdeable_from_log_response() {
|
fn test_radarr_serdeable_from_log_response() {
|
||||||
let log_response = LogResponse {
|
let log_response = LogResponse {
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ use crate::models::{HorizontallyScrollableText, ScrollableText};
|
|||||||
mod modals_tests;
|
mod modals_tests;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
#[cfg_attr(test, derive(Debug))]
|
||||||
pub struct MovieDetailsModal {
|
pub struct MovieDetailsModal {
|
||||||
pub movie_details: ScrollableText,
|
pub movie_details: ScrollableText,
|
||||||
pub file_details: String,
|
pub file_details: String,
|
||||||
@@ -97,6 +98,7 @@ impl From<&RadarrData<'_>> for EditIndexerModal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
#[cfg_attr(test, derive(Debug))]
|
||||||
pub struct EditMovieModal {
|
pub struct EditMovieModal {
|
||||||
pub minimum_availability_list: StatefulList<MinimumAvailability>,
|
pub minimum_availability_list: StatefulList<MinimumAvailability>,
|
||||||
pub quality_profile_list: StatefulList<String>,
|
pub quality_profile_list: StatefulList<String>,
|
||||||
@@ -157,6 +159,7 @@ impl From<&RadarrData<'_>> for EditMovieModal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
#[cfg_attr(test, derive(Debug))]
|
||||||
pub struct AddMovieModal {
|
pub struct AddMovieModal {
|
||||||
pub root_folder_list: StatefulList<RootFolder>,
|
pub root_folder_list: StatefulList<RootFolder>,
|
||||||
pub monitor_list: StatefulList<MovieMonitor>,
|
pub monitor_list: StatefulList<MovieMonitor>,
|
||||||
@@ -186,6 +189,7 @@ impl From<&RadarrData<'_>> for AddMovieModal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
#[cfg_attr(test, derive(Debug))]
|
||||||
pub struct EditCollectionModal {
|
pub struct EditCollectionModal {
|
||||||
pub monitored: Option<bool>,
|
pub monitored: Option<bool>,
|
||||||
pub minimum_availability_list: StatefulList<MinimumAvailability>,
|
pub minimum_availability_list: StatefulList<MinimumAvailability>,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use crate::app::context_clues::{
|
use crate::app::context_clues::{
|
||||||
BLOCKLIST_CONTEXT_CLUES, DOWNLOADS_CONTEXT_CLUES, INDEXERS_CONTEXT_CLUES,
|
BLOCKLIST_CONTEXT_CLUES, DOWNLOADS_CONTEXT_CLUES, HISTORY_CONTEXT_CLUES, INDEXERS_CONTEXT_CLUES,
|
||||||
ROOT_FOLDERS_CONTEXT_CLUES, SYSTEM_CONTEXT_CLUES,
|
ROOT_FOLDERS_CONTEXT_CLUES, SYSTEM_CONTEXT_CLUES,
|
||||||
};
|
};
|
||||||
use crate::app::radarr::radarr_context_clues::{
|
use crate::app::radarr::radarr_context_clues::{
|
||||||
@@ -8,7 +8,7 @@ use crate::app::radarr::radarr_context_clues::{
|
|||||||
};
|
};
|
||||||
use crate::models::radarr_models::{
|
use crate::models::radarr_models::{
|
||||||
AddMovieSearchResult, BlocklistItem, Collection, CollectionMovie, DownloadRecord,
|
AddMovieSearchResult, BlocklistItem, Collection, CollectionMovie, DownloadRecord,
|
||||||
IndexerSettings, Movie, RadarrTask,
|
IndexerSettings, Movie, RadarrHistoryItem, RadarrTask,
|
||||||
};
|
};
|
||||||
use crate::models::servarr_data::modals::{EditIndexerModal, IndexerTestResultModalItem};
|
use crate::models::servarr_data::modals::{EditIndexerModal, IndexerTestResultModalItem};
|
||||||
use crate::models::servarr_data::radarr::modals::{
|
use crate::models::servarr_data::radarr::modals::{
|
||||||
@@ -34,7 +34,8 @@ use {
|
|||||||
crate::network::radarr_network::radarr_network_test_utils::test_utils::{
|
crate::network::radarr_network::radarr_network_test_utils::test_utils::{
|
||||||
add_movie_search_result, blocklist_item, cast_credit, collection, collection_movie,
|
add_movie_search_result, blocklist_item, cast_credit, collection, collection_movie,
|
||||||
crew_credit, download_record, indexer, log_line, movie, movie_history_item,
|
crew_credit, download_record, indexer, log_line, movie, movie_history_item,
|
||||||
quality_profile_map, tags_map, task, torrent_release, updates, usenet_release,
|
quality_profile_map, radarr_history_item, tags_map, task, torrent_release, updates,
|
||||||
|
usenet_release,
|
||||||
},
|
},
|
||||||
crate::network::servarr_test_utils::diskspace,
|
crate::network::servarr_test_utils::diskspace,
|
||||||
crate::network::servarr_test_utils::indexer_test_result,
|
crate::network::servarr_test_utils::indexer_test_result,
|
||||||
@@ -62,6 +63,7 @@ pub struct RadarrData<'a> {
|
|||||||
pub downloads: StatefulTable<DownloadRecord>,
|
pub downloads: StatefulTable<DownloadRecord>,
|
||||||
pub indexers: StatefulTable<Indexer>,
|
pub indexers: StatefulTable<Indexer>,
|
||||||
pub blocklist: StatefulTable<BlocklistItem>,
|
pub blocklist: StatefulTable<BlocklistItem>,
|
||||||
|
pub history: StatefulTable<RadarrHistoryItem>,
|
||||||
pub quality_profile_map: BiMap<i64, String>,
|
pub quality_profile_map: BiMap<i64, String>,
|
||||||
pub tags_map: BiMap<i64, String>,
|
pub tags_map: BiMap<i64, String>,
|
||||||
pub collections: StatefulTable<Collection>,
|
pub collections: StatefulTable<Collection>,
|
||||||
@@ -135,6 +137,7 @@ impl<'a> Default for RadarrData<'a> {
|
|||||||
downloads: StatefulTable::default(),
|
downloads: StatefulTable::default(),
|
||||||
indexers: StatefulTable::default(),
|
indexers: StatefulTable::default(),
|
||||||
blocklist: StatefulTable::default(),
|
blocklist: StatefulTable::default(),
|
||||||
|
history: StatefulTable::default(),
|
||||||
quality_profile_map: BiMap::default(),
|
quality_profile_map: BiMap::default(),
|
||||||
tags_map: BiMap::default(),
|
tags_map: BiMap::default(),
|
||||||
collections: StatefulTable::default(),
|
collections: StatefulTable::default(),
|
||||||
@@ -184,6 +187,12 @@ impl<'a> Default for RadarrData<'a> {
|
|||||||
contextual_help: Some(&BLOCKLIST_CONTEXT_CLUES),
|
contextual_help: Some(&BLOCKLIST_CONTEXT_CLUES),
|
||||||
config: None,
|
config: None,
|
||||||
},
|
},
|
||||||
|
TabRoute {
|
||||||
|
title: "History".to_string(),
|
||||||
|
route: ActiveRadarrBlock::History.into(),
|
||||||
|
contextual_help: Some(&HISTORY_CONTEXT_CLUES),
|
||||||
|
config: None,
|
||||||
|
},
|
||||||
TabRoute {
|
TabRoute {
|
||||||
title: "Root Folders".to_string(),
|
title: "Root Folders".to_string(),
|
||||||
route: ActiveRadarrBlock::RootFolders.into(),
|
route: ActiveRadarrBlock::RootFolders.into(),
|
||||||
@@ -387,6 +396,10 @@ impl RadarrData<'_> {
|
|||||||
radarr_data.downloads.set_items(vec![download_record()]);
|
radarr_data.downloads.set_items(vec![download_record()]);
|
||||||
radarr_data.blocklist.set_items(vec![blocklist_item()]);
|
radarr_data.blocklist.set_items(vec![blocklist_item()]);
|
||||||
radarr_data.blocklist.sorting(vec![sort_option!(id)]);
|
radarr_data.blocklist.sorting(vec![sort_option!(id)]);
|
||||||
|
radarr_data.history.set_items(vec![radarr_history_item()]);
|
||||||
|
radarr_data.history.sorting(vec![sort_option!(id)]);
|
||||||
|
radarr_data.history.search = Some("Something".into());
|
||||||
|
radarr_data.history.filter = Some("Something".into());
|
||||||
radarr_data.indexers.set_items(vec![indexer()]);
|
radarr_data.indexers.set_items(vec![indexer()]);
|
||||||
radarr_data.indexers.sorting(vec![sort_option!(id)]);
|
radarr_data.indexers.sorting(vec![sort_option!(id)]);
|
||||||
radarr_data.indexers.search = Some("Something".into());
|
radarr_data.indexers.search = Some("Something".into());
|
||||||
@@ -420,6 +433,13 @@ pub enum ActiveRadarrBlock {
|
|||||||
BlocklistClearAllItemsPrompt,
|
BlocklistClearAllItemsPrompt,
|
||||||
BlocklistItemDetails,
|
BlocklistItemDetails,
|
||||||
BlocklistSortPrompt,
|
BlocklistSortPrompt,
|
||||||
|
History,
|
||||||
|
HistoryItemDetails,
|
||||||
|
HistorySortPrompt,
|
||||||
|
FilterHistory,
|
||||||
|
FilterHistoryError,
|
||||||
|
SearchHistory,
|
||||||
|
SearchHistoryError,
|
||||||
Collections,
|
Collections,
|
||||||
CollectionsSortPrompt,
|
CollectionsSortPrompt,
|
||||||
CollectionDetails,
|
CollectionDetails,
|
||||||
@@ -538,6 +558,15 @@ pub static BLOCKLIST_BLOCKS: [ActiveRadarrBlock; 5] = [
|
|||||||
ActiveRadarrBlock::BlocklistClearAllItemsPrompt,
|
ActiveRadarrBlock::BlocklistClearAllItemsPrompt,
|
||||||
ActiveRadarrBlock::BlocklistSortPrompt,
|
ActiveRadarrBlock::BlocklistSortPrompt,
|
||||||
];
|
];
|
||||||
|
pub static HISTORY_BLOCKS: [ActiveRadarrBlock; 7] = [
|
||||||
|
ActiveRadarrBlock::History,
|
||||||
|
ActiveRadarrBlock::HistoryItemDetails,
|
||||||
|
ActiveRadarrBlock::HistorySortPrompt,
|
||||||
|
ActiveRadarrBlock::FilterHistory,
|
||||||
|
ActiveRadarrBlock::FilterHistoryError,
|
||||||
|
ActiveRadarrBlock::SearchHistory,
|
||||||
|
ActiveRadarrBlock::SearchHistoryError,
|
||||||
|
];
|
||||||
pub static ADD_MOVIE_BLOCKS: [ActiveRadarrBlock; 10] = [
|
pub static ADD_MOVIE_BLOCKS: [ActiveRadarrBlock; 10] = [
|
||||||
ActiveRadarrBlock::AddMovieSearchInput,
|
ActiveRadarrBlock::AddMovieSearchInput,
|
||||||
ActiveRadarrBlock::AddMovieSearchResults,
|
ActiveRadarrBlock::AddMovieSearchResults,
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
mod tests {
|
mod tests {
|
||||||
mod radarr_data_tests {
|
mod radarr_data_tests {
|
||||||
use crate::app::context_clues::{
|
use crate::app::context_clues::{
|
||||||
BLOCKLIST_CONTEXT_CLUES, DOWNLOADS_CONTEXT_CLUES, INDEXERS_CONTEXT_CLUES,
|
BLOCKLIST_CONTEXT_CLUES, DOWNLOADS_CONTEXT_CLUES, HISTORY_CONTEXT_CLUES,
|
||||||
ROOT_FOLDERS_CONTEXT_CLUES, SYSTEM_CONTEXT_CLUES,
|
INDEXERS_CONTEXT_CLUES, ROOT_FOLDERS_CONTEXT_CLUES, SYSTEM_CONTEXT_CLUES,
|
||||||
};
|
};
|
||||||
use crate::app::radarr::radarr_context_clues::{
|
use crate::app::radarr::radarr_context_clues::{
|
||||||
COLLECTIONS_CONTEXT_CLUES, LIBRARY_CONTEXT_CLUES, MANUAL_MOVIE_SEARCH_CONTEXT_CLUES,
|
COLLECTIONS_CONTEXT_CLUES, LIBRARY_CONTEXT_CLUES, MANUAL_MOVIE_SEARCH_CONTEXT_CLUES,
|
||||||
@@ -105,41 +105,42 @@ mod tests {
|
|||||||
fn test_radarr_data_defaults() {
|
fn test_radarr_data_defaults() {
|
||||||
let radarr_data = RadarrData::default();
|
let radarr_data = RadarrData::default();
|
||||||
|
|
||||||
assert!(radarr_data.root_folders.items.is_empty());
|
assert_is_empty!(radarr_data.root_folders.items);
|
||||||
assert_eq!(radarr_data.disk_space_vec, Vec::new());
|
assert_eq!(radarr_data.disk_space_vec, Vec::new());
|
||||||
assert!(radarr_data.version.is_empty());
|
assert_is_empty!(radarr_data.version);
|
||||||
assert_eq!(radarr_data.start_time, <DateTime<Utc>>::default());
|
assert_eq!(radarr_data.start_time, <DateTime<Utc>>::default());
|
||||||
assert!(radarr_data.movies.is_empty());
|
assert_is_empty!(radarr_data.movies);
|
||||||
assert_eq!(radarr_data.selected_block, BlockSelectionState::default());
|
assert_eq!(radarr_data.selected_block, BlockSelectionState::default());
|
||||||
assert!(radarr_data.downloads.items.is_empty());
|
assert_is_empty!(radarr_data.downloads.items);
|
||||||
assert!(radarr_data.indexers.items.is_empty());
|
assert_is_empty!(radarr_data.indexers.items);
|
||||||
assert!(radarr_data.blocklist.items.is_empty());
|
assert_is_empty!(radarr_data.blocklist.items);
|
||||||
assert!(radarr_data.quality_profile_map.is_empty());
|
assert_is_empty!(radarr_data.history.items);
|
||||||
assert!(radarr_data.tags_map.is_empty());
|
assert_is_empty!(radarr_data.quality_profile_map);
|
||||||
assert!(radarr_data.collections.items.is_empty());
|
assert_is_empty!(radarr_data.tags_map);
|
||||||
assert!(radarr_data.collection_movies.items.is_empty());
|
assert_is_empty!(radarr_data.collections.items);
|
||||||
assert!(radarr_data.logs.items.is_empty());
|
assert_is_empty!(radarr_data.collection_movies.items);
|
||||||
assert!(radarr_data.log_details.items.is_empty());
|
assert_is_empty!(radarr_data.logs.items);
|
||||||
assert!(radarr_data.tasks.items.is_empty());
|
assert_is_empty!(radarr_data.log_details.items);
|
||||||
assert!(radarr_data.queued_events.items.is_empty());
|
assert_is_empty!(radarr_data.tasks.items);
|
||||||
assert!(radarr_data.updates.get_text().is_empty());
|
assert_is_empty!(radarr_data.queued_events.items);
|
||||||
assert!(radarr_data.add_movie_search.is_none());
|
assert_is_empty!(radarr_data.updates.get_text());
|
||||||
assert!(radarr_data.add_movie_modal.is_none());
|
assert_none!(&radarr_data.add_movie_search);
|
||||||
assert!(radarr_data.add_searched_movies.is_none());
|
assert_none!(&radarr_data.add_movie_modal);
|
||||||
assert!(radarr_data.edit_movie_modal.is_none());
|
assert_none!(&radarr_data.add_searched_movies);
|
||||||
assert!(radarr_data.edit_collection_modal.is_none());
|
assert_none!(&radarr_data.edit_movie_modal);
|
||||||
assert!(radarr_data.edit_root_folder.is_none());
|
assert_none!(&radarr_data.edit_collection_modal);
|
||||||
assert!(radarr_data.edit_indexer_modal.is_none());
|
assert_none!(&radarr_data.edit_root_folder);
|
||||||
assert!(radarr_data.indexer_settings.is_none());
|
assert_none!(&radarr_data.edit_indexer_modal);
|
||||||
assert!(radarr_data.indexer_test_errors.is_none());
|
assert_none!(&radarr_data.indexer_settings);
|
||||||
assert!(radarr_data.indexer_test_all_results.is_none());
|
assert_none!(&radarr_data.indexer_test_errors);
|
||||||
assert!(radarr_data.movie_details_modal.is_none());
|
assert_none!(&radarr_data.indexer_test_all_results);
|
||||||
assert!(radarr_data.prompt_confirm_action.is_none());
|
assert_none!(&radarr_data.movie_details_modal);
|
||||||
|
assert_none!(&radarr_data.prompt_confirm_action);
|
||||||
assert!(!radarr_data.prompt_confirm);
|
assert!(!radarr_data.prompt_confirm);
|
||||||
assert!(!radarr_data.delete_movie_files);
|
assert!(!radarr_data.delete_movie_files);
|
||||||
assert!(!radarr_data.add_list_exclusion);
|
assert!(!radarr_data.add_list_exclusion);
|
||||||
|
|
||||||
assert_eq!(radarr_data.main_tabs.tabs.len(), 7);
|
assert_eq!(radarr_data.main_tabs.tabs.len(), 8);
|
||||||
|
|
||||||
assert_str_eq!(radarr_data.main_tabs.tabs[0].title, "Library");
|
assert_str_eq!(radarr_data.main_tabs.tabs[0].title, "Library");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@@ -189,42 +190,54 @@ mod tests {
|
|||||||
);
|
);
|
||||||
assert_eq!(radarr_data.main_tabs.tabs[3].config, None);
|
assert_eq!(radarr_data.main_tabs.tabs[3].config, None);
|
||||||
|
|
||||||
assert_str_eq!(radarr_data.main_tabs.tabs[4].title, "Root Folders");
|
assert_str_eq!(radarr_data.main_tabs.tabs[4].title, "History");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
radarr_data.main_tabs.tabs[4].route,
|
radarr_data.main_tabs.tabs[4].route,
|
||||||
ActiveRadarrBlock::RootFolders.into()
|
ActiveRadarrBlock::History.into()
|
||||||
);
|
);
|
||||||
assert!(radarr_data.main_tabs.tabs[4].contextual_help.is_some());
|
assert!(radarr_data.main_tabs.tabs[4].contextual_help.is_some());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
radarr_data.main_tabs.tabs[4].contextual_help.unwrap(),
|
radarr_data.main_tabs.tabs[4].contextual_help.unwrap(),
|
||||||
&ROOT_FOLDERS_CONTEXT_CLUES
|
&HISTORY_CONTEXT_CLUES
|
||||||
);
|
);
|
||||||
assert_eq!(radarr_data.main_tabs.tabs[4].config, None);
|
assert_eq!(radarr_data.main_tabs.tabs[4].config, None);
|
||||||
|
|
||||||
assert_str_eq!(radarr_data.main_tabs.tabs[5].title, "Indexers");
|
assert_str_eq!(radarr_data.main_tabs.tabs[5].title, "Root Folders");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
radarr_data.main_tabs.tabs[5].route,
|
radarr_data.main_tabs.tabs[5].route,
|
||||||
ActiveRadarrBlock::Indexers.into()
|
ActiveRadarrBlock::RootFolders.into()
|
||||||
);
|
);
|
||||||
assert!(radarr_data.main_tabs.tabs[5].contextual_help.is_some());
|
assert!(radarr_data.main_tabs.tabs[5].contextual_help.is_some());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
radarr_data.main_tabs.tabs[5].contextual_help.unwrap(),
|
radarr_data.main_tabs.tabs[5].contextual_help.unwrap(),
|
||||||
&INDEXERS_CONTEXT_CLUES
|
&ROOT_FOLDERS_CONTEXT_CLUES
|
||||||
);
|
);
|
||||||
assert_eq!(radarr_data.main_tabs.tabs[5].config, None);
|
assert_eq!(radarr_data.main_tabs.tabs[5].config, None);
|
||||||
|
|
||||||
assert_str_eq!(radarr_data.main_tabs.tabs[6].title, "System");
|
assert_str_eq!(radarr_data.main_tabs.tabs[6].title, "Indexers");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
radarr_data.main_tabs.tabs[6].route,
|
radarr_data.main_tabs.tabs[6].route,
|
||||||
ActiveRadarrBlock::System.into()
|
ActiveRadarrBlock::Indexers.into()
|
||||||
);
|
);
|
||||||
assert!(radarr_data.main_tabs.tabs[6].contextual_help.is_some());
|
assert!(radarr_data.main_tabs.tabs[6].contextual_help.is_some());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
radarr_data.main_tabs.tabs[6].contextual_help.unwrap(),
|
radarr_data.main_tabs.tabs[6].contextual_help.unwrap(),
|
||||||
&SYSTEM_CONTEXT_CLUES
|
&INDEXERS_CONTEXT_CLUES
|
||||||
);
|
);
|
||||||
assert_eq!(radarr_data.main_tabs.tabs[6].config, None);
|
assert_eq!(radarr_data.main_tabs.tabs[6].config, None);
|
||||||
|
|
||||||
|
assert_str_eq!(radarr_data.main_tabs.tabs[7].title, "System");
|
||||||
|
assert_eq!(
|
||||||
|
radarr_data.main_tabs.tabs[7].route,
|
||||||
|
ActiveRadarrBlock::System.into()
|
||||||
|
);
|
||||||
|
assert!(radarr_data.main_tabs.tabs[7].contextual_help.is_some());
|
||||||
|
assert_eq!(
|
||||||
|
radarr_data.main_tabs.tabs[7].contextual_help.unwrap(),
|
||||||
|
&SYSTEM_CONTEXT_CLUES
|
||||||
|
);
|
||||||
|
assert_eq!(radarr_data.main_tabs.tabs[7].config, None);
|
||||||
|
|
||||||
assert_eq!(radarr_data.movie_info_tabs.tabs.len(), 6);
|
assert_eq!(radarr_data.movie_info_tabs.tabs.len(), 6);
|
||||||
|
|
||||||
assert_str_eq!(radarr_data.movie_info_tabs.tabs[0].title, "Details");
|
assert_str_eq!(radarr_data.movie_info_tabs.tabs[0].title, "Details");
|
||||||
@@ -334,8 +347,8 @@ mod tests {
|
|||||||
DELETE_MOVIE_SELECTION_BLOCKS, DOWNLOADS_BLOCKS, EDIT_COLLECTION_BLOCKS,
|
DELETE_MOVIE_SELECTION_BLOCKS, DOWNLOADS_BLOCKS, EDIT_COLLECTION_BLOCKS,
|
||||||
EDIT_COLLECTION_SELECTION_BLOCKS, EDIT_INDEXER_BLOCKS, EDIT_INDEXER_NZB_SELECTION_BLOCKS,
|
EDIT_COLLECTION_SELECTION_BLOCKS, EDIT_INDEXER_BLOCKS, EDIT_INDEXER_NZB_SELECTION_BLOCKS,
|
||||||
EDIT_INDEXER_TORRENT_SELECTION_BLOCKS, EDIT_MOVIE_BLOCKS, EDIT_MOVIE_SELECTION_BLOCKS,
|
EDIT_INDEXER_TORRENT_SELECTION_BLOCKS, EDIT_MOVIE_BLOCKS, EDIT_MOVIE_SELECTION_BLOCKS,
|
||||||
INDEXER_SETTINGS_BLOCKS, INDEXER_SETTINGS_SELECTION_BLOCKS, INDEXERS_BLOCKS, LIBRARY_BLOCKS,
|
HISTORY_BLOCKS, INDEXER_SETTINGS_BLOCKS, INDEXER_SETTINGS_SELECTION_BLOCKS, INDEXERS_BLOCKS,
|
||||||
MOVIE_DETAILS_BLOCKS, ROOT_FOLDERS_BLOCKS, SYSTEM_DETAILS_BLOCKS,
|
LIBRARY_BLOCKS, MOVIE_DETAILS_BLOCKS, ROOT_FOLDERS_BLOCKS, SYSTEM_DETAILS_BLOCKS,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -388,6 +401,18 @@ mod tests {
|
|||||||
assert!(BLOCKLIST_BLOCKS.contains(&ActiveRadarrBlock::BlocklistSortPrompt));
|
assert!(BLOCKLIST_BLOCKS.contains(&ActiveRadarrBlock::BlocklistSortPrompt));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_history_blocks_contents() {
|
||||||
|
assert_eq!(HISTORY_BLOCKS.len(), 7);
|
||||||
|
assert!(HISTORY_BLOCKS.contains(&ActiveRadarrBlock::History));
|
||||||
|
assert!(HISTORY_BLOCKS.contains(&ActiveRadarrBlock::HistoryItemDetails));
|
||||||
|
assert!(HISTORY_BLOCKS.contains(&ActiveRadarrBlock::HistorySortPrompt));
|
||||||
|
assert!(HISTORY_BLOCKS.contains(&ActiveRadarrBlock::FilterHistory));
|
||||||
|
assert!(HISTORY_BLOCKS.contains(&ActiveRadarrBlock::FilterHistoryError));
|
||||||
|
assert!(HISTORY_BLOCKS.contains(&ActiveRadarrBlock::SearchHistory));
|
||||||
|
assert!(HISTORY_BLOCKS.contains(&ActiveRadarrBlock::SearchHistoryError));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_add_movie_blocks_contents() {
|
fn test_add_movie_blocks_contents() {
|
||||||
assert_eq!(ADD_MOVIE_BLOCKS.len(), 10);
|
assert_eq!(ADD_MOVIE_BLOCKS.len(), 10);
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
use crate::models::Route;
|
||||||
|
use crate::models::radarr_models::RadarrHistoryWrapper;
|
||||||
|
use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock;
|
||||||
|
use crate::network::radarr_network::RadarrEvent;
|
||||||
|
use crate::network::{Network, RequestMethod};
|
||||||
|
use anyhow::Result;
|
||||||
|
use log::info;
|
||||||
|
use serde_json::Value;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[path = "radarr_history_network_tests.rs"]
|
||||||
|
mod radarr_history_network_tests;
|
||||||
|
|
||||||
|
impl Network<'_, '_> {
|
||||||
|
pub(in crate::network::radarr_network) async fn get_radarr_history(
|
||||||
|
&mut self,
|
||||||
|
events: u64,
|
||||||
|
) -> Result<RadarrHistoryWrapper> {
|
||||||
|
info!("Fetching all Radarr history events");
|
||||||
|
let event = RadarrEvent::GetHistory(events);
|
||||||
|
|
||||||
|
let params = format!("pageSize={events}&sortDirection=descending&sortKey=date");
|
||||||
|
let request_props = self
|
||||||
|
.request_props_from(event, RequestMethod::Get, None::<()>, None, Some(params))
|
||||||
|
.await;
|
||||||
|
|
||||||
|
self
|
||||||
|
.handle_request::<(), RadarrHistoryWrapper>(request_props, |history_response, mut app| {
|
||||||
|
if !matches!(
|
||||||
|
app.get_current_route(),
|
||||||
|
Route::Radarr(ActiveRadarrBlock::HistorySortPrompt, _)
|
||||||
|
) {
|
||||||
|
let mut history_vec = history_response.records;
|
||||||
|
history_vec.sort_by(|a, b| a.id.cmp(&b.id));
|
||||||
|
app.data.radarr_data.history.set_items(history_vec);
|
||||||
|
app.data.radarr_data.history.apply_sorting_toggle(false);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(in crate::network::radarr_network) async fn mark_radarr_history_item_as_failed(
|
||||||
|
&mut self,
|
||||||
|
history_item_id: i64,
|
||||||
|
) -> Result<Value> {
|
||||||
|
info!("Marking the Radarr history item with ID: {history_item_id} as 'failed'");
|
||||||
|
let event = RadarrEvent::MarkHistoryItemAsFailed(history_item_id);
|
||||||
|
|
||||||
|
let request_props = self
|
||||||
|
.request_props_from(
|
||||||
|
event,
|
||||||
|
RequestMethod::Post,
|
||||||
|
None,
|
||||||
|
Some(format!("/{history_item_id}")),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
self
|
||||||
|
.handle_request::<(), Value>(request_props, |_, _| ())
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,196 @@
|
|||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::models::radarr_models::{RadarrHistoryItem, RadarrHistoryWrapper, RadarrSerdeable};
|
||||||
|
use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock;
|
||||||
|
use crate::models::stateful_table::SortOption;
|
||||||
|
use crate::network::network_tests::test_utils::{MockServarrApi, test_network};
|
||||||
|
use crate::network::radarr_network::RadarrEvent;
|
||||||
|
use crate::network::radarr_network::radarr_network_test_utils::test_utils::radarr_history_item;
|
||||||
|
use pretty_assertions::assert_eq;
|
||||||
|
use rstest::rstest;
|
||||||
|
use serde_json::json;
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_handle_get_radarr_history_event(#[values(true, false)] use_custom_sorting: bool) {
|
||||||
|
let history_json = json!({"records": [{
|
||||||
|
"id": 123,
|
||||||
|
"sourceTitle": "z movie",
|
||||||
|
"movieId": 1007,
|
||||||
|
"quality": { "quality": { "name": "HD - 1080p" } },
|
||||||
|
"languages": [{ "id": 1, "name": "English" }],
|
||||||
|
"date": "2022-12-30T07:37:56Z",
|
||||||
|
"eventType": "grabbed",
|
||||||
|
"data": {
|
||||||
|
"indexer": "DrunkenSlug (Prowlarr)",
|
||||||
|
"releaseGroup": "SPARKS",
|
||||||
|
"downloadClient": "transmission",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 456,
|
||||||
|
"sourceTitle": "A Movie",
|
||||||
|
"movieId": 2001,
|
||||||
|
"quality": { "quality": { "name": "HD - 1080p" } },
|
||||||
|
"languages": [{ "id": 1, "name": "English" }],
|
||||||
|
"date": "2022-12-30T07:37:56Z",
|
||||||
|
"eventType": "grabbed",
|
||||||
|
"data": {
|
||||||
|
"indexer": "DrunkenSlug (Prowlarr)",
|
||||||
|
"releaseGroup": "SPARKS",
|
||||||
|
"downloadClient": "transmission",
|
||||||
|
}
|
||||||
|
}]});
|
||||||
|
let response: RadarrHistoryWrapper = serde_json::from_value(history_json.clone()).unwrap();
|
||||||
|
let mut expected_history_items = vec![
|
||||||
|
RadarrHistoryItem {
|
||||||
|
id: 123,
|
||||||
|
movie_id: 1007,
|
||||||
|
source_title: "z movie".into(),
|
||||||
|
..radarr_history_item()
|
||||||
|
},
|
||||||
|
RadarrHistoryItem {
|
||||||
|
id: 456,
|
||||||
|
movie_id: 2001,
|
||||||
|
source_title: "A Movie".into(),
|
||||||
|
..radarr_history_item()
|
||||||
|
},
|
||||||
|
];
|
||||||
|
let (mock, app, _server) = MockServarrApi::get()
|
||||||
|
.returns(history_json)
|
||||||
|
.query("pageSize=500&sortDirection=descending&sortKey=date")
|
||||||
|
.build_for(RadarrEvent::GetHistory(500))
|
||||||
|
.await;
|
||||||
|
app.lock().await.data.radarr_data.history.sort_asc = true;
|
||||||
|
if use_custom_sorting {
|
||||||
|
let cmp_fn = |a: &RadarrHistoryItem, b: &RadarrHistoryItem| {
|
||||||
|
a.source_title
|
||||||
|
.text
|
||||||
|
.to_lowercase()
|
||||||
|
.cmp(&b.source_title.text.to_lowercase())
|
||||||
|
};
|
||||||
|
expected_history_items.sort_by(cmp_fn);
|
||||||
|
|
||||||
|
let history_sort_option = SortOption {
|
||||||
|
name: "Source Title",
|
||||||
|
cmp_fn: Some(cmp_fn),
|
||||||
|
};
|
||||||
|
app
|
||||||
|
.lock()
|
||||||
|
.await
|
||||||
|
.data
|
||||||
|
.radarr_data
|
||||||
|
.history
|
||||||
|
.sorting(vec![history_sort_option]);
|
||||||
|
}
|
||||||
|
let mut network = test_network(&app);
|
||||||
|
|
||||||
|
let RadarrSerdeable::HistoryWrapper(history) = network
|
||||||
|
.handle_radarr_event(RadarrEvent::GetHistory(500))
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
else {
|
||||||
|
panic!("Expected HistoryWrapper")
|
||||||
|
};
|
||||||
|
mock.assert_async().await;
|
||||||
|
assert_eq!(
|
||||||
|
app.lock().await.data.radarr_data.history.items,
|
||||||
|
expected_history_items
|
||||||
|
);
|
||||||
|
assert!(app.lock().await.data.radarr_data.history.sort_asc);
|
||||||
|
assert_eq!(history, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_handle_get_radarr_history_event_no_op_when_user_is_selecting_sort_options() {
|
||||||
|
let history_json = json!({"records": [{
|
||||||
|
"id": 123,
|
||||||
|
"sourceTitle": "z movie",
|
||||||
|
"movieId": 1007,
|
||||||
|
"quality": { "quality": { "name": "Bluray-1080p" } },
|
||||||
|
"languages": [{ "id": 1, "name": "English" }],
|
||||||
|
"date": "2024-02-10T07:28:45Z",
|
||||||
|
"eventType": "grabbed",
|
||||||
|
"data": {
|
||||||
|
"indexer": "DrunkenSlug (Prowlarr)",
|
||||||
|
"releaseGroup": "SPARKS"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 456,
|
||||||
|
"sourceTitle": "A Movie",
|
||||||
|
"movieId": 2001,
|
||||||
|
"quality": { "quality": { "name": "Bluray-1080p" } },
|
||||||
|
"languages": [{ "id": 1, "name": "English" }],
|
||||||
|
"date": "2024-02-10T07:28:45Z",
|
||||||
|
"eventType": "grabbed",
|
||||||
|
"data": {
|
||||||
|
"indexer": "DrunkenSlug (Prowlarr)",
|
||||||
|
"releaseGroup": "SPARKS"
|
||||||
|
}
|
||||||
|
}]});
|
||||||
|
let response: RadarrHistoryWrapper = serde_json::from_value(history_json.clone()).unwrap();
|
||||||
|
let (mock, app, _server) = MockServarrApi::get()
|
||||||
|
.returns(history_json)
|
||||||
|
.query("pageSize=500&sortDirection=descending&sortKey=date")
|
||||||
|
.build_for(RadarrEvent::GetHistory(500))
|
||||||
|
.await;
|
||||||
|
app.lock().await.data.radarr_data.history.sort_asc = true;
|
||||||
|
app
|
||||||
|
.lock()
|
||||||
|
.await
|
||||||
|
.push_navigation_stack(ActiveRadarrBlock::HistorySortPrompt.into());
|
||||||
|
let cmp_fn = |a: &RadarrHistoryItem, b: &RadarrHistoryItem| {
|
||||||
|
a.source_title
|
||||||
|
.text
|
||||||
|
.to_lowercase()
|
||||||
|
.cmp(&b.source_title.text.to_lowercase())
|
||||||
|
};
|
||||||
|
let history_sort_option = SortOption {
|
||||||
|
name: "Source Title",
|
||||||
|
cmp_fn: Some(cmp_fn),
|
||||||
|
};
|
||||||
|
app
|
||||||
|
.lock()
|
||||||
|
.await
|
||||||
|
.data
|
||||||
|
.radarr_data
|
||||||
|
.history
|
||||||
|
.sorting(vec![history_sort_option]);
|
||||||
|
let mut network = test_network(&app);
|
||||||
|
|
||||||
|
let RadarrSerdeable::HistoryWrapper(history) = network
|
||||||
|
.handle_radarr_event(RadarrEvent::GetHistory(500))
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
else {
|
||||||
|
panic!("Expected HistoryWrapper")
|
||||||
|
};
|
||||||
|
mock.assert_async().await;
|
||||||
|
assert_is_empty!(app.lock().await.data.radarr_data.history);
|
||||||
|
assert!(app.lock().await.data.radarr_data.history.sort_asc);
|
||||||
|
assert_eq!(history, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_handle_mark_radarr_history_item_as_failed_event() {
|
||||||
|
let expected_history_item_id = 1;
|
||||||
|
let (mock, app, _server) = MockServarrApi::post()
|
||||||
|
.returns(json!({}))
|
||||||
|
.path("/1")
|
||||||
|
.build_for(RadarrEvent::MarkHistoryItemAsFailed(
|
||||||
|
expected_history_item_id,
|
||||||
|
))
|
||||||
|
.await;
|
||||||
|
let mut network = test_network(&app);
|
||||||
|
|
||||||
|
let result = network
|
||||||
|
.handle_radarr_event(RadarrEvent::MarkHistoryItemAsFailed(
|
||||||
|
expected_history_item_id,
|
||||||
|
))
|
||||||
|
.await;
|
||||||
|
|
||||||
|
mock.assert_async().await;
|
||||||
|
assert_ok!(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,6 +16,7 @@ use super::NetworkResource;
|
|||||||
mod blocklist;
|
mod blocklist;
|
||||||
mod collections;
|
mod collections;
|
||||||
mod downloads;
|
mod downloads;
|
||||||
|
mod history;
|
||||||
mod indexers;
|
mod indexers;
|
||||||
mod library;
|
mod library;
|
||||||
mod root_folders;
|
mod root_folders;
|
||||||
@@ -47,10 +48,12 @@ pub enum RadarrEvent {
|
|||||||
GetBlocklist,
|
GetBlocklist,
|
||||||
GetCollections,
|
GetCollections,
|
||||||
GetDownloads(u64),
|
GetDownloads(u64),
|
||||||
|
GetHistory(u64),
|
||||||
GetHostConfig,
|
GetHostConfig,
|
||||||
GetIndexers,
|
GetIndexers,
|
||||||
GetAllIndexerSettings,
|
GetAllIndexerSettings,
|
||||||
GetLogs(u64),
|
GetLogs(u64),
|
||||||
|
MarkHistoryItemAsFailed(i64),
|
||||||
GetMovieCredits(i64),
|
GetMovieCredits(i64),
|
||||||
GetMovieDetails(i64),
|
GetMovieDetails(i64),
|
||||||
GetMovieHistory(i64),
|
GetMovieHistory(i64),
|
||||||
@@ -86,7 +89,9 @@ impl NetworkResource for RadarrEvent {
|
|||||||
RadarrEvent::GetBlocklist => "/blocklist?page=1&pageSize=10000",
|
RadarrEvent::GetBlocklist => "/blocklist?page=1&pageSize=10000",
|
||||||
RadarrEvent::GetCollections | RadarrEvent::EditCollection(_) => "/collection",
|
RadarrEvent::GetCollections | RadarrEvent::EditCollection(_) => "/collection",
|
||||||
RadarrEvent::GetDownloads(_) | RadarrEvent::DeleteDownload(_) => "/queue",
|
RadarrEvent::GetDownloads(_) | RadarrEvent::DeleteDownload(_) => "/queue",
|
||||||
|
RadarrEvent::GetHistory(_) => "/history",
|
||||||
RadarrEvent::GetHostConfig | RadarrEvent::GetSecurityConfig => "/config/host",
|
RadarrEvent::GetHostConfig | RadarrEvent::GetSecurityConfig => "/config/host",
|
||||||
|
RadarrEvent::MarkHistoryItemAsFailed(_) => "/history/failed",
|
||||||
RadarrEvent::GetIndexers | RadarrEvent::EditIndexer(_) | RadarrEvent::DeleteIndexer(_) => {
|
RadarrEvent::GetIndexers | RadarrEvent::EditIndexer(_) | RadarrEvent::DeleteIndexer(_) => {
|
||||||
"/indexer"
|
"/indexer"
|
||||||
}
|
}
|
||||||
@@ -199,6 +204,10 @@ impl Network<'_, '_> {
|
|||||||
.get_radarr_downloads(count)
|
.get_radarr_downloads(count)
|
||||||
.await
|
.await
|
||||||
.map(RadarrSerdeable::from),
|
.map(RadarrSerdeable::from),
|
||||||
|
RadarrEvent::GetHistory(events) => self
|
||||||
|
.get_radarr_history(events)
|
||||||
|
.await
|
||||||
|
.map(RadarrSerdeable::from),
|
||||||
RadarrEvent::GetHostConfig => self
|
RadarrEvent::GetHostConfig => self
|
||||||
.get_radarr_host_config()
|
.get_radarr_host_config()
|
||||||
.await
|
.await
|
||||||
@@ -208,6 +217,10 @@ impl Network<'_, '_> {
|
|||||||
.get_radarr_logs(events)
|
.get_radarr_logs(events)
|
||||||
.await
|
.await
|
||||||
.map(RadarrSerdeable::from),
|
.map(RadarrSerdeable::from),
|
||||||
|
RadarrEvent::MarkHistoryItemAsFailed(history_item_id) => self
|
||||||
|
.mark_radarr_history_item_as_failed(history_item_id)
|
||||||
|
.await
|
||||||
|
.map(RadarrSerdeable::from),
|
||||||
RadarrEvent::GetMovieCredits(movie_id) => {
|
RadarrEvent::GetMovieCredits(movie_id) => {
|
||||||
self.get_credits(movie_id).await.map(RadarrSerdeable::from)
|
self.get_credits(movie_id).await.map(RadarrSerdeable::from)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ pub mod test_utils {
|
|||||||
use crate::models::radarr_models::{
|
use crate::models::radarr_models::{
|
||||||
AddMovieSearchResult, BlocklistItem, BlocklistItemMovie, Collection, CollectionMovie, Credit,
|
AddMovieSearchResult, BlocklistItem, BlocklistItemMovie, Collection, CollectionMovie, Credit,
|
||||||
CreditType, DownloadRecord, DownloadsResponse, IndexerSettings, MediaInfo, MinimumAvailability,
|
CreditType, DownloadRecord, DownloadsResponse, IndexerSettings, MediaInfo, MinimumAvailability,
|
||||||
Movie, MovieCollection, MovieFile, MovieHistoryItem, RadarrRelease, RadarrTask, RadarrTaskName,
|
Movie, MovieCollection, MovieFile, MovieHistoryItem, RadarrHistoryData, RadarrHistoryEventType,
|
||||||
Rating, RatingsList,
|
RadarrHistoryItem, RadarrRelease, RadarrTask, RadarrTaskName, Rating, RatingsList,
|
||||||
};
|
};
|
||||||
use crate::models::servarr_models::{
|
use crate::models::servarr_models::{
|
||||||
Indexer, IndexerField, Language, Quality, QualityWrapper, RootFolder,
|
Indexer, IndexerField, Language, Quality, QualityWrapper, RootFolder,
|
||||||
@@ -313,6 +313,24 @@ pub mod test_utils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn radarr_history_item() -> RadarrHistoryItem {
|
||||||
|
RadarrHistoryItem {
|
||||||
|
id: 1,
|
||||||
|
source_title: HorizontallyScrollableText::from("Test"),
|
||||||
|
movie_id: 1,
|
||||||
|
quality: quality_wrapper(),
|
||||||
|
languages: vec![language()],
|
||||||
|
date: DateTime::from(DateTime::parse_from_rfc3339("2022-12-30T07:37:56Z").unwrap()),
|
||||||
|
event_type: RadarrHistoryEventType::Grabbed,
|
||||||
|
data: RadarrHistoryData {
|
||||||
|
indexer: Some("DrunkenSlug (Prowlarr)".to_owned()),
|
||||||
|
release_group: Some("SPARKS".to_owned()),
|
||||||
|
download_client: Some("transmission".to_owned()),
|
||||||
|
..RadarrHistoryData::default()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn download_record() -> DownloadRecord {
|
pub fn download_record() -> DownloadRecord {
|
||||||
DownloadRecord {
|
DownloadRecord {
|
||||||
title: "Test Download Title".to_owned(),
|
title: "Test Download Title".to_owned(),
|
||||||
|
|||||||
@@ -136,7 +136,9 @@ mod test {
|
|||||||
#[case(RadarrEvent::ClearBlocklist, "/blocklist/bulk")]
|
#[case(RadarrEvent::ClearBlocklist, "/blocklist/bulk")]
|
||||||
#[case(RadarrEvent::DeleteBlocklistItem(1), "/blocklist")]
|
#[case(RadarrEvent::DeleteBlocklistItem(1), "/blocklist")]
|
||||||
#[case(RadarrEvent::GetBlocklist, "/blocklist?page=1&pageSize=10000")]
|
#[case(RadarrEvent::GetBlocklist, "/blocklist?page=1&pageSize=10000")]
|
||||||
|
#[case(RadarrEvent::GetHistory(500), "/history")]
|
||||||
#[case(RadarrEvent::GetLogs(500), "/log")]
|
#[case(RadarrEvent::GetLogs(500), "/log")]
|
||||||
|
#[case(RadarrEvent::MarkHistoryItemAsFailed(1), "/history/failed")]
|
||||||
#[case(RadarrEvent::SearchNewMovie(String::new()), "/movie/lookup")]
|
#[case(RadarrEvent::SearchNewMovie(String::new()), "/movie/lookup")]
|
||||||
#[case(RadarrEvent::GetMovieCredits(0), "/credit")]
|
#[case(RadarrEvent::GetMovieCredits(0), "/credit")]
|
||||||
#[case(RadarrEvent::GetMovieHistory(0), "/history/movie")]
|
#[case(RadarrEvent::GetMovieHistory(0), "/history/movie")]
|
||||||
|
|||||||
@@ -0,0 +1,79 @@
|
|||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
|
use crate::app::App;
|
||||||
|
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, HISTORY_BLOCKS};
|
||||||
|
use crate::ui::DrawUi;
|
||||||
|
use crate::ui::radarr_ui::history::HistoryUi;
|
||||||
|
use crate::ui::ui_test_utils::test_utils::render_to_string_with_app;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_history_ui_accepts() {
|
||||||
|
ActiveRadarrBlock::iter().for_each(|active_radarr_block| {
|
||||||
|
if HISTORY_BLOCKS.contains(&active_radarr_block) {
|
||||||
|
assert!(HistoryUi::accepts(active_radarr_block.into()));
|
||||||
|
} else {
|
||||||
|
assert!(!HistoryUi::accepts(active_radarr_block.into()));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
mod snapshot_tests {
|
||||||
|
use crate::ui::ui_test_utils::test_utils::TerminalSize;
|
||||||
|
use rstest::rstest;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_history_ui_renders_loading() {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.is_loading = true;
|
||||||
|
app.push_navigation_stack(ActiveRadarrBlock::History.into());
|
||||||
|
|
||||||
|
let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| {
|
||||||
|
HistoryUi::draw(f, app, f.area());
|
||||||
|
});
|
||||||
|
|
||||||
|
insta::assert_snapshot!(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_history_ui_renders_empty(
|
||||||
|
#[values(ActiveRadarrBlock::History, ActiveRadarrBlock::HistoryItemDetails)]
|
||||||
|
active_radarr_block: ActiveRadarrBlock,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.push_navigation_stack(active_radarr_block.into());
|
||||||
|
|
||||||
|
let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| {
|
||||||
|
HistoryUi::draw(f, app, f.area());
|
||||||
|
});
|
||||||
|
|
||||||
|
insta::assert_snapshot!(format!("loading_history_tab_{active_radarr_block}"), output);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_history_ui_renders(
|
||||||
|
#[values(
|
||||||
|
ActiveRadarrBlock::History,
|
||||||
|
ActiveRadarrBlock::HistoryItemDetails,
|
||||||
|
ActiveRadarrBlock::HistorySortPrompt,
|
||||||
|
ActiveRadarrBlock::FilterHistory,
|
||||||
|
ActiveRadarrBlock::FilterHistoryError,
|
||||||
|
ActiveRadarrBlock::SearchHistory,
|
||||||
|
ActiveRadarrBlock::SearchHistoryError
|
||||||
|
)]
|
||||||
|
active_radarr_block: ActiveRadarrBlock,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default_fully_populated();
|
||||||
|
app.push_navigation_stack(active_radarr_block.into());
|
||||||
|
|
||||||
|
let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| {
|
||||||
|
HistoryUi::draw(f, app, f.area());
|
||||||
|
});
|
||||||
|
|
||||||
|
insta::assert_snapshot!(format!("history_tab_{active_radarr_block}"), output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,129 @@
|
|||||||
|
use crate::app::App;
|
||||||
|
use crate::models::Route;
|
||||||
|
use crate::models::radarr_models::RadarrHistoryItem;
|
||||||
|
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, HISTORY_BLOCKS};
|
||||||
|
use crate::ui::DrawUi;
|
||||||
|
use crate::ui::styles::{ManagarrStyle, secondary_style};
|
||||||
|
use crate::ui::utils::{get_width_from_percentage, layout_block_top_border};
|
||||||
|
use crate::ui::widgets::managarr_table::ManagarrTable;
|
||||||
|
use crate::ui::widgets::message::Message;
|
||||||
|
use crate::ui::widgets::popup::{Popup, Size};
|
||||||
|
use ratatui::Frame;
|
||||||
|
use ratatui::layout::{Alignment, Constraint, Rect};
|
||||||
|
use ratatui::text::Text;
|
||||||
|
use ratatui::widgets::{Cell, Row};
|
||||||
|
|
||||||
|
use super::radarr_ui_utils::create_history_event_details;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[path = "history_ui_tests.rs"]
|
||||||
|
mod history_ui_tests;
|
||||||
|
|
||||||
|
pub(super) struct HistoryUi;
|
||||||
|
|
||||||
|
impl DrawUi for HistoryUi {
|
||||||
|
fn accepts(route: Route) -> bool {
|
||||||
|
if let Route::Radarr(active_radarr_block, _) = route {
|
||||||
|
return HISTORY_BLOCKS.contains(&active_radarr_block);
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
||||||
|
if let Route::Radarr(active_radarr_block, _) = app.get_current_route() {
|
||||||
|
draw_history_table(f, app, area);
|
||||||
|
|
||||||
|
if active_radarr_block == ActiveRadarrBlock::HistoryItemDetails {
|
||||||
|
draw_history_item_details_popup(f, app);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_history_table(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
||||||
|
let current_selection = if app.data.radarr_data.history.items.is_empty() {
|
||||||
|
RadarrHistoryItem::default()
|
||||||
|
} else {
|
||||||
|
app.data.radarr_data.history.current_selection().clone()
|
||||||
|
};
|
||||||
|
if let Route::Radarr(active_radarr_block, _) = app.get_current_route() {
|
||||||
|
let history_row_mapping = |history_item: &RadarrHistoryItem| {
|
||||||
|
let RadarrHistoryItem {
|
||||||
|
source_title,
|
||||||
|
languages,
|
||||||
|
quality,
|
||||||
|
event_type,
|
||||||
|
date,
|
||||||
|
..
|
||||||
|
} = history_item;
|
||||||
|
|
||||||
|
source_title.scroll_left_or_reset(
|
||||||
|
get_width_from_percentage(area, 40),
|
||||||
|
current_selection == *history_item,
|
||||||
|
app.ui_scroll_tick_count == 0,
|
||||||
|
);
|
||||||
|
|
||||||
|
Row::new(vec![
|
||||||
|
Cell::from(source_title.to_string()),
|
||||||
|
Cell::from(event_type.to_string()),
|
||||||
|
Cell::from(
|
||||||
|
languages
|
||||||
|
.iter()
|
||||||
|
.map(|language| language.name.to_owned())
|
||||||
|
.collect::<Vec<String>>()
|
||||||
|
.join(","),
|
||||||
|
),
|
||||||
|
Cell::from(quality.quality.name.to_owned()),
|
||||||
|
Cell::from(date.to_string()),
|
||||||
|
])
|
||||||
|
.primary()
|
||||||
|
};
|
||||||
|
let history_table =
|
||||||
|
ManagarrTable::new(Some(&mut app.data.radarr_data.history), history_row_mapping)
|
||||||
|
.block(layout_block_top_border())
|
||||||
|
.loading(app.is_loading)
|
||||||
|
.sorting(active_radarr_block == ActiveRadarrBlock::HistorySortPrompt)
|
||||||
|
.searching(active_radarr_block == ActiveRadarrBlock::SearchHistory)
|
||||||
|
.search_produced_empty_results(active_radarr_block == ActiveRadarrBlock::SearchHistoryError)
|
||||||
|
.filtering(active_radarr_block == ActiveRadarrBlock::FilterHistory)
|
||||||
|
.filter_produced_empty_results(active_radarr_block == ActiveRadarrBlock::FilterHistoryError)
|
||||||
|
.headers(["Source Title", "Event Type", "Language", "Quality", "Date"])
|
||||||
|
.constraints([
|
||||||
|
Constraint::Percentage(40),
|
||||||
|
Constraint::Percentage(15),
|
||||||
|
Constraint::Percentage(12),
|
||||||
|
Constraint::Percentage(13),
|
||||||
|
Constraint::Percentage(20),
|
||||||
|
]);
|
||||||
|
|
||||||
|
if [
|
||||||
|
ActiveRadarrBlock::SearchHistory,
|
||||||
|
ActiveRadarrBlock::FilterHistory,
|
||||||
|
]
|
||||||
|
.contains(&active_radarr_block)
|
||||||
|
{
|
||||||
|
history_table.show_cursor(f, area);
|
||||||
|
}
|
||||||
|
|
||||||
|
f.render_widget(history_table, area);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_history_item_details_popup(f: &mut Frame<'_>, app: &mut App<'_>) {
|
||||||
|
let current_selection = if app.data.radarr_data.history.items.is_empty() {
|
||||||
|
RadarrHistoryItem::default()
|
||||||
|
} else {
|
||||||
|
app.data.radarr_data.history.current_selection().clone()
|
||||||
|
};
|
||||||
|
|
||||||
|
let line_vec = create_history_event_details(current_selection);
|
||||||
|
let text = Text::from(line_vec);
|
||||||
|
|
||||||
|
let message = Message::new(text)
|
||||||
|
.title("Details")
|
||||||
|
.style(secondary_style())
|
||||||
|
.alignment(Alignment::Left);
|
||||||
|
|
||||||
|
f.render_widget(Popup::new(message).size(Size::NarrowLongMessage), f.area());
|
||||||
|
}
|
||||||
+28
@@ -0,0 +1,28 @@
|
|||||||
|
---
|
||||||
|
source: src/ui/radarr_ui/history/history_ui_tests.rs
|
||||||
|
expression: output
|
||||||
|
---
|
||||||
|
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
|
||||||
|
Source Title ▼ Event Type Language Quality Date
|
||||||
|
=> Test grabbed English HD - 1080p 2022-12-30 07:37:56 UTC
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
╭───────────────── Filter ──────────────────╮
|
||||||
|
│Something │
|
||||||
|
╰─────────────────────────────────────────────╯
|
||||||
+31
@@ -0,0 +1,31 @@
|
|||||||
|
---
|
||||||
|
source: src/ui/radarr_ui/history/history_ui_tests.rs
|
||||||
|
expression: output
|
||||||
|
---
|
||||||
|
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
|
||||||
|
Source Title ▼ Event Type Language Quality Date
|
||||||
|
=> Test grabbed English HD - 1080p 2022-12-30 07:37:56 UTC
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
╭─────────────── Error ───────────────╮
|
||||||
|
│The given filter produced empty results│
|
||||||
|
│ │
|
||||||
|
╰───────────────────────────────────────╯
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
source: src/ui/radarr_ui/history/history_ui_tests.rs
|
||||||
|
expression: output
|
||||||
|
---
|
||||||
|
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
|
||||||
|
Source Title ▼ Event Type Language Quality Date
|
||||||
|
=> Test grabbed English HD - 1080p 2022-12-30 07:37:56 UTC
|
||||||
+39
@@ -0,0 +1,39 @@
|
|||||||
|
---
|
||||||
|
source: src/ui/radarr_ui/history/history_ui_tests.rs
|
||||||
|
expression: output
|
||||||
|
---
|
||||||
|
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
|
||||||
|
Source Title ▼ Event Type Language Quality Date
|
||||||
|
=> Test grabbed English HD - 1080p 2022-12-30 07:37:56 UTC
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
╭─────────────────────────────────── Details ───────────────────────────────────╮
|
||||||
|
│Source Title: Test │
|
||||||
|
│Event Type: grabbed │
|
||||||
|
│Indexer: DrunkenSlug (Prowlarr) │
|
||||||
|
│Release Group: SPARKS │
|
||||||
|
│NZB Info URL: │
|
||||||
|
│Download Client: transmission │
|
||||||
|
│Age: 0 days │
|
||||||
|
│Published Date: 1970-01-01 00:00:00 UTC │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
╰─────────────────────────────────────────────────────────────────────────────────╯
|
||||||
+42
@@ -0,0 +1,42 @@
|
|||||||
|
---
|
||||||
|
source: src/ui/radarr_ui/history/history_ui_tests.rs
|
||||||
|
expression: output
|
||||||
|
---
|
||||||
|
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
|
||||||
|
Source Title Event Type Language Quality Date
|
||||||
|
=> Test grabbed English HD - 1080p 2022-12-30 07:37:56 UTC
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
╭───────────────────────────────╮
|
||||||
|
│Something │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
╰───────────────────────────────╯
|
||||||
+28
@@ -0,0 +1,28 @@
|
|||||||
|
---
|
||||||
|
source: src/ui/radarr_ui/history/history_ui_tests.rs
|
||||||
|
expression: output
|
||||||
|
---
|
||||||
|
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
|
||||||
|
Source Title ▼ Event Type Language Quality Date
|
||||||
|
=> Test grabbed English HD - 1080p 2022-12-30 07:37:56 UTC
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
╭───────────────── Search ──────────────────╮
|
||||||
|
│Something │
|
||||||
|
╰─────────────────────────────────────────────╯
|
||||||
+31
@@ -0,0 +1,31 @@
|
|||||||
|
---
|
||||||
|
source: src/ui/radarr_ui/history/history_ui_tests.rs
|
||||||
|
expression: output
|
||||||
|
---
|
||||||
|
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
|
||||||
|
Source Title ▼ Event Type Language Quality Date
|
||||||
|
=> Test grabbed English HD - 1080p 2022-12-30 07:37:56 UTC
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
╭─────────────── Error ───────────────╮
|
||||||
|
│ No items found matching search │
|
||||||
|
│ │
|
||||||
|
╰───────────────────────────────────────╯
|
||||||
+8
@@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
source: src/ui/radarr_ui/history/history_ui_tests.rs
|
||||||
|
expression: output
|
||||||
|
---
|
||||||
|
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
|
||||||
|
Loading ...
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
source: src/ui/radarr_ui/history/history_ui_tests.rs
|
||||||
|
expression: output
|
||||||
|
---
|
||||||
|
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
|
||||||
+39
@@ -0,0 +1,39 @@
|
|||||||
|
---
|
||||||
|
source: src/ui/radarr_ui/history/history_ui_tests.rs
|
||||||
|
expression: output
|
||||||
|
---
|
||||||
|
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
╭─────────────────────────────────── Details ───────────────────────────────────╮
|
||||||
|
│Source Title: │
|
||||||
|
│Event Type: unknown │
|
||||||
|
│ │
|
||||||
|
│No additional data available │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
╰─────────────────────────────────────────────────────────────────────────────────╯
|
||||||
@@ -21,6 +21,7 @@ use crate::ui::draw_tabs;
|
|||||||
use crate::ui::radarr_ui::blocklist::BlocklistUi;
|
use crate::ui::radarr_ui::blocklist::BlocklistUi;
|
||||||
use crate::ui::radarr_ui::collections::CollectionsUi;
|
use crate::ui::radarr_ui::collections::CollectionsUi;
|
||||||
use crate::ui::radarr_ui::downloads::DownloadsUi;
|
use crate::ui::radarr_ui::downloads::DownloadsUi;
|
||||||
|
use crate::ui::radarr_ui::history::HistoryUi;
|
||||||
use crate::ui::radarr_ui::indexers::IndexersUi;
|
use crate::ui::radarr_ui::indexers::IndexersUi;
|
||||||
use crate::ui::radarr_ui::library::LibraryUi;
|
use crate::ui::radarr_ui::library::LibraryUi;
|
||||||
use crate::ui::radarr_ui::root_folders::RootFoldersUi;
|
use crate::ui::radarr_ui::root_folders::RootFoldersUi;
|
||||||
@@ -35,10 +36,12 @@ use crate::utils::convert_to_gb;
|
|||||||
mod blocklist;
|
mod blocklist;
|
||||||
mod collections;
|
mod collections;
|
||||||
mod downloads;
|
mod downloads;
|
||||||
|
mod history;
|
||||||
mod indexers;
|
mod indexers;
|
||||||
mod library;
|
mod library;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod radarr_ui_tests;
|
mod radarr_ui_tests;
|
||||||
|
mod radarr_ui_utils;
|
||||||
mod root_folders;
|
mod root_folders;
|
||||||
mod system;
|
mod system;
|
||||||
|
|
||||||
@@ -61,6 +64,7 @@ impl DrawUi for RadarrUi {
|
|||||||
_ if RootFoldersUi::accepts(route) => RootFoldersUi::draw(f, app, content_area),
|
_ if RootFoldersUi::accepts(route) => RootFoldersUi::draw(f, app, content_area),
|
||||||
_ if SystemUi::accepts(route) => SystemUi::draw(f, app, content_area),
|
_ if SystemUi::accepts(route) => SystemUi::draw(f, app, content_area),
|
||||||
_ if BlocklistUi::accepts(route) => BlocklistUi::draw(f, app, content_area),
|
_ if BlocklistUi::accepts(route) => BlocklistUi::draw(f, app, content_area),
|
||||||
|
_ if HistoryUi::accepts(route) => HistoryUi::draw(f, app, content_area),
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,9 +29,10 @@ mod tests {
|
|||||||
#[case(ActiveRadarrBlock::Collections, 1)]
|
#[case(ActiveRadarrBlock::Collections, 1)]
|
||||||
#[case(ActiveRadarrBlock::Downloads, 2)]
|
#[case(ActiveRadarrBlock::Downloads, 2)]
|
||||||
#[case(ActiveRadarrBlock::Blocklist, 3)]
|
#[case(ActiveRadarrBlock::Blocklist, 3)]
|
||||||
#[case(ActiveRadarrBlock::RootFolders, 4)]
|
#[case(ActiveRadarrBlock::History, 4)]
|
||||||
#[case(ActiveRadarrBlock::Indexers, 5)]
|
#[case(ActiveRadarrBlock::RootFolders, 5)]
|
||||||
#[case(ActiveRadarrBlock::System, 6)]
|
#[case(ActiveRadarrBlock::Indexers, 6)]
|
||||||
|
#[case(ActiveRadarrBlock::System, 7)]
|
||||||
fn test_radarr_ui_renders_radarr_tabs(
|
fn test_radarr_ui_renders_radarr_tabs(
|
||||||
#[case] active_radarr_block: ActiveRadarrBlock,
|
#[case] active_radarr_block: ActiveRadarrBlock,
|
||||||
#[case] index: usize,
|
#[case] index: usize,
|
||||||
|
|||||||
@@ -0,0 +1,121 @@
|
|||||||
|
use ratatui::text::Line;
|
||||||
|
|
||||||
|
use crate::models::radarr_models::{RadarrHistoryData, RadarrHistoryEventType, RadarrHistoryItem};
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[path = "radarr_ui_utils_tests.rs"]
|
||||||
|
mod radarr_ui_utils_tests;
|
||||||
|
|
||||||
|
pub(super) fn create_history_event_details(history_item: RadarrHistoryItem) -> Vec<Line<'static>> {
|
||||||
|
let RadarrHistoryItem {
|
||||||
|
source_title,
|
||||||
|
event_type,
|
||||||
|
data,
|
||||||
|
..
|
||||||
|
} = history_item;
|
||||||
|
let RadarrHistoryData {
|
||||||
|
indexer,
|
||||||
|
release_group,
|
||||||
|
nzb_info_url,
|
||||||
|
download_client,
|
||||||
|
download_client_name,
|
||||||
|
age,
|
||||||
|
published_date,
|
||||||
|
dropped_path,
|
||||||
|
imported_path,
|
||||||
|
message,
|
||||||
|
reason,
|
||||||
|
source_path,
|
||||||
|
path,
|
||||||
|
..
|
||||||
|
} = data;
|
||||||
|
|
||||||
|
let mut lines = vec![
|
||||||
|
Line::from(format!("Source Title: {}", source_title.text.trim_start())),
|
||||||
|
Line::from(format!("Event Type: {}", event_type)),
|
||||||
|
];
|
||||||
|
|
||||||
|
match event_type {
|
||||||
|
RadarrHistoryEventType::Grabbed => {
|
||||||
|
lines.push(Line::from(format!(
|
||||||
|
"Indexer: {}",
|
||||||
|
indexer.unwrap_or_default().trim_start(),
|
||||||
|
)));
|
||||||
|
lines.push(Line::from(format!(
|
||||||
|
"Release Group: {}",
|
||||||
|
release_group.unwrap_or_default().trim_start(),
|
||||||
|
)));
|
||||||
|
lines.push(Line::from(format!(
|
||||||
|
"NZB Info URL: {}",
|
||||||
|
nzb_info_url.unwrap_or_default().trim_start(),
|
||||||
|
)));
|
||||||
|
lines.push(Line::from(format!(
|
||||||
|
"Download Client: {}",
|
||||||
|
download_client
|
||||||
|
.or(download_client_name)
|
||||||
|
.unwrap_or_default()
|
||||||
|
.trim_start()
|
||||||
|
)));
|
||||||
|
lines.push(Line::from(format!(
|
||||||
|
"Age: {} days",
|
||||||
|
age.unwrap_or("0".to_owned()).trim_start(),
|
||||||
|
)));
|
||||||
|
lines.push(Line::from(format!(
|
||||||
|
"Published Date: {}",
|
||||||
|
published_date.unwrap_or_default().to_string().trim_start(),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
RadarrHistoryEventType::DownloadFolderImported => {
|
||||||
|
lines.push(Line::from(format!(
|
||||||
|
"Dropped Path: {}",
|
||||||
|
dropped_path.unwrap_or_default().trim_start(),
|
||||||
|
)));
|
||||||
|
lines.push(Line::from(format!(
|
||||||
|
"Imported Path: {}",
|
||||||
|
imported_path.unwrap_or_default().trim_start(),
|
||||||
|
)));
|
||||||
|
lines.push(Line::from(format!(
|
||||||
|
"Download Client: {}",
|
||||||
|
download_client
|
||||||
|
.or(download_client_name)
|
||||||
|
.unwrap_or_default()
|
||||||
|
.trim_start()
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
RadarrHistoryEventType::DownloadFailed => {
|
||||||
|
lines.push(Line::from(format!(
|
||||||
|
"Download Client: {}",
|
||||||
|
download_client
|
||||||
|
.or(download_client_name)
|
||||||
|
.unwrap_or_default()
|
||||||
|
.trim_start(),
|
||||||
|
)));
|
||||||
|
lines.push(Line::from(format!(
|
||||||
|
"Message: {}",
|
||||||
|
message.unwrap_or_default().trim_start(),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
RadarrHistoryEventType::MovieFileDeleted => {
|
||||||
|
lines.push(Line::from(format!(
|
||||||
|
"Reason: {}",
|
||||||
|
reason.unwrap_or_default().trim_start(),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
RadarrHistoryEventType::MovieFileRenamed => {
|
||||||
|
lines.push(Line::from(format!(
|
||||||
|
"Source Path: {}",
|
||||||
|
source_path.unwrap_or_default().trim_start(),
|
||||||
|
)));
|
||||||
|
lines.push(Line::from(format!(
|
||||||
|
"Destination Path: {}",
|
||||||
|
path.unwrap_or_default().trim_start(),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
lines.push(Line::from(String::new()));
|
||||||
|
lines.push(Line::from("No additional data available"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lines
|
||||||
|
}
|
||||||
@@ -0,0 +1,236 @@
|
|||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use chrono::Utc;
|
||||||
|
use ratatui::text::Line;
|
||||||
|
|
||||||
|
use crate::models::radarr_models::RadarrHistoryEventType;
|
||||||
|
use crate::models::radarr_models::{RadarrHistoryData, RadarrHistoryItem};
|
||||||
|
use crate::ui::radarr_ui::radarr_ui_utils::create_history_event_details;
|
||||||
|
use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_create_grabbed_history_event_details() {
|
||||||
|
let history_item = radarr_history_item(RadarrHistoryEventType::Grabbed);
|
||||||
|
let RadarrHistoryItem {
|
||||||
|
source_title,
|
||||||
|
data,
|
||||||
|
event_type,
|
||||||
|
..
|
||||||
|
} = history_item.clone();
|
||||||
|
let RadarrHistoryData {
|
||||||
|
indexer,
|
||||||
|
release_group,
|
||||||
|
nzb_info_url,
|
||||||
|
download_client,
|
||||||
|
download_client_name,
|
||||||
|
age,
|
||||||
|
published_date,
|
||||||
|
..
|
||||||
|
} = data;
|
||||||
|
let expected_vec = vec![
|
||||||
|
Line::from(format!("Source Title: {}", source_title.text.trim_start(),)),
|
||||||
|
Line::from(format!("Event Type: {event_type}")),
|
||||||
|
Line::from(format!(
|
||||||
|
"Indexer: {}",
|
||||||
|
indexer.unwrap_or_default().trim_start(),
|
||||||
|
)),
|
||||||
|
Line::from(format!(
|
||||||
|
"Release Group: {}",
|
||||||
|
release_group.unwrap_or_default().trim_start()
|
||||||
|
)),
|
||||||
|
Line::from(format!(
|
||||||
|
"NZB Info URL: {}",
|
||||||
|
nzb_info_url.unwrap_or_default().trim_start()
|
||||||
|
)),
|
||||||
|
Line::from(format!(
|
||||||
|
"Download Client: {}",
|
||||||
|
download_client
|
||||||
|
.or(download_client_name)
|
||||||
|
.unwrap_or_default()
|
||||||
|
.trim_start()
|
||||||
|
)),
|
||||||
|
Line::from(format!(
|
||||||
|
"Age: {} days",
|
||||||
|
age.unwrap_or("0".to_owned()).trim_start(),
|
||||||
|
)),
|
||||||
|
Line::from(format!(
|
||||||
|
"Published Date: {}",
|
||||||
|
published_date.unwrap_or_default().to_string().trim_start()
|
||||||
|
)),
|
||||||
|
];
|
||||||
|
|
||||||
|
let history_details_vec = create_history_event_details(history_item);
|
||||||
|
|
||||||
|
assert_eq!(expected_vec, history_details_vec);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_create_download_folder_imported_history_event_details() {
|
||||||
|
let history_item = radarr_history_item(RadarrHistoryEventType::DownloadFolderImported);
|
||||||
|
let RadarrHistoryItem {
|
||||||
|
source_title,
|
||||||
|
data,
|
||||||
|
event_type,
|
||||||
|
..
|
||||||
|
} = history_item.clone();
|
||||||
|
let RadarrHistoryData {
|
||||||
|
dropped_path,
|
||||||
|
imported_path,
|
||||||
|
download_client,
|
||||||
|
..
|
||||||
|
} = data;
|
||||||
|
let expected_vec = vec![
|
||||||
|
Line::from(format!("Source Title: {}", source_title.text.trim_start(),)),
|
||||||
|
Line::from(format!("Event Type: {event_type}")),
|
||||||
|
Line::from(format!(
|
||||||
|
"Dropped Path: {}",
|
||||||
|
dropped_path.unwrap_or_default().trim_start()
|
||||||
|
)),
|
||||||
|
Line::from(format!(
|
||||||
|
"Imported Path: {}",
|
||||||
|
imported_path.unwrap_or_default().trim_start()
|
||||||
|
)),
|
||||||
|
Line::from(format!(
|
||||||
|
"Download Client: {}",
|
||||||
|
download_client.unwrap_or_default().trim_start(),
|
||||||
|
)),
|
||||||
|
];
|
||||||
|
|
||||||
|
let history_details_vec = create_history_event_details(history_item);
|
||||||
|
|
||||||
|
assert_eq!(expected_vec, history_details_vec);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_create_download_failed_history_event_details() {
|
||||||
|
let history_item = radarr_history_item(RadarrHistoryEventType::DownloadFailed);
|
||||||
|
let RadarrHistoryItem {
|
||||||
|
source_title,
|
||||||
|
data,
|
||||||
|
event_type,
|
||||||
|
..
|
||||||
|
} = history_item.clone();
|
||||||
|
let RadarrHistoryData {
|
||||||
|
message,
|
||||||
|
download_client,
|
||||||
|
..
|
||||||
|
} = data;
|
||||||
|
let expected_vec = vec![
|
||||||
|
Line::from(format!("Source Title: {}", source_title.text.trim_start())),
|
||||||
|
Line::from(format!("Event Type: {event_type}")),
|
||||||
|
Line::from(format!(
|
||||||
|
"Download Client: {}",
|
||||||
|
download_client.unwrap_or_default().trim_start()
|
||||||
|
)),
|
||||||
|
Line::from(format!(
|
||||||
|
"Message: {}",
|
||||||
|
message.unwrap_or_default().trim_start()
|
||||||
|
)),
|
||||||
|
];
|
||||||
|
|
||||||
|
let history_details_vec = create_history_event_details(history_item);
|
||||||
|
|
||||||
|
assert_eq!(expected_vec, history_details_vec);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_create_movie_file_deleted_history_event_details() {
|
||||||
|
let history_item = radarr_history_item(RadarrHistoryEventType::MovieFileDeleted);
|
||||||
|
let RadarrHistoryItem {
|
||||||
|
source_title,
|
||||||
|
data,
|
||||||
|
event_type,
|
||||||
|
..
|
||||||
|
} = history_item.clone();
|
||||||
|
let RadarrHistoryData { reason, .. } = data;
|
||||||
|
let expected_vec = vec![
|
||||||
|
Line::from(format!("Source Title: {}", source_title.text.trim_start(),)),
|
||||||
|
Line::from(format!("Event Type: {event_type}")),
|
||||||
|
Line::from(format!(
|
||||||
|
"Reason: {}",
|
||||||
|
reason.unwrap_or_default().trim_start(),
|
||||||
|
)),
|
||||||
|
];
|
||||||
|
|
||||||
|
let history_details_vec = create_history_event_details(history_item);
|
||||||
|
|
||||||
|
assert_eq!(expected_vec, history_details_vec);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_create_movie_file_renamed_history_event_details() {
|
||||||
|
let history_item = radarr_history_item(RadarrHistoryEventType::MovieFileRenamed);
|
||||||
|
let RadarrHistoryItem {
|
||||||
|
source_title,
|
||||||
|
data,
|
||||||
|
event_type,
|
||||||
|
..
|
||||||
|
} = history_item.clone();
|
||||||
|
let RadarrHistoryData {
|
||||||
|
source_path, path, ..
|
||||||
|
} = data;
|
||||||
|
let expected_vec = vec![
|
||||||
|
Line::from(format!("Source Title: {}", source_title.text.trim_start(),)),
|
||||||
|
Line::from(format!("Event Type: {event_type}")),
|
||||||
|
Line::from(format!(
|
||||||
|
"Source Path: {}",
|
||||||
|
source_path.unwrap_or_default().trim_start(),
|
||||||
|
)),
|
||||||
|
Line::from(format!(
|
||||||
|
"Destination Path: {}",
|
||||||
|
path.unwrap_or_default().trim_start(),
|
||||||
|
)),
|
||||||
|
];
|
||||||
|
|
||||||
|
let history_details_vec = create_history_event_details(history_item);
|
||||||
|
|
||||||
|
assert_eq!(expected_vec, history_details_vec);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_create_no_data_history_event_details() {
|
||||||
|
let history_item = radarr_history_item(RadarrHistoryEventType::Unknown);
|
||||||
|
let RadarrHistoryItem {
|
||||||
|
source_title,
|
||||||
|
event_type,
|
||||||
|
..
|
||||||
|
} = history_item.clone();
|
||||||
|
let expected_vec = vec![
|
||||||
|
Line::from(format!("Source Title: {}", source_title.text.trim_start(),)),
|
||||||
|
Line::from(format!("Event Type: {event_type}")),
|
||||||
|
Line::from(String::new()),
|
||||||
|
Line::from("No additional data available"),
|
||||||
|
];
|
||||||
|
|
||||||
|
let history_details_vec = create_history_event_details(history_item);
|
||||||
|
|
||||||
|
assert_eq!(expected_vec, history_details_vec);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn radarr_history_item(event_type: RadarrHistoryEventType) -> RadarrHistoryItem {
|
||||||
|
RadarrHistoryItem {
|
||||||
|
source_title: "test.source.title".into(),
|
||||||
|
event_type,
|
||||||
|
data: radarr_history_data(),
|
||||||
|
..RadarrHistoryItem::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn radarr_history_data() -> RadarrHistoryData {
|
||||||
|
RadarrHistoryData {
|
||||||
|
dropped_path: Some("/dropped/test".into()),
|
||||||
|
imported_path: Some("/imported/test".into()),
|
||||||
|
indexer: Some("Test Indexer".into()),
|
||||||
|
release_group: Some("test release group".into()),
|
||||||
|
nzb_info_url: Some("test url".into()),
|
||||||
|
download_client: Some("test download client".into()),
|
||||||
|
download_client_name: None,
|
||||||
|
age: Some("1".into()),
|
||||||
|
published_date: Some(Utc::now()),
|
||||||
|
message: Some("test message".into()),
|
||||||
|
reason: Some("test reason".into()),
|
||||||
|
source_path: Some("/source/path".into()),
|
||||||
|
path: Some("/path".into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -3,7 +3,7 @@ source: src/ui/radarr_ui/radarr_ui_tests.rs
|
|||||||
expression: output
|
expression: output
|
||||||
---
|
---
|
||||||
╭ Movies ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
╭ Movies ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
||||||
│ Library │ Collections │ Downloads │ Blocklist │ Root Folders │ Indexers │ System │
|
│ Library │ Collections │ Downloads │ Blocklist │ History │ Root Folders │ Indexers │ System │
|
||||||
│───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│
|
│───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│
|
||||||
│ Movie Title ▼ Source Title Languages Quality Formats Date │
|
│ Movie Title ▼ Source Title Languages Quality Formats Date │
|
||||||
│=> Test z movie English HD - 1080p English 2024-02-10 07:28:45 UTC │
|
│=> Test z movie English HD - 1080p English 2024-02-10 07:28:45 UTC │
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@ source: src/ui/radarr_ui/radarr_ui_tests.rs
|
|||||||
expression: output
|
expression: output
|
||||||
---
|
---
|
||||||
╭ Movies ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
╭ Movies ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
||||||
│ Library │ Collections │ Downloads │ Blocklist │ Root Folders │ Indexers │ System │
|
│ Library │ Collections │ Downloads │ Blocklist │ History │ Root Folders │ Indexers │ System │
|
||||||
│───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│
|
│───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│
|
||||||
│ Collection ▼ Number of Movies Root Folder Path Quality Profile Search on Add Monitored │
|
│ Collection ▼ Number of Movies Root Folder Path Quality Profile Search on Add Monitored │
|
||||||
│=> Test Collection 1 /nfs/movies HD - 1080p Yes 🏷 │
|
│=> Test Collection 1 /nfs/movies HD - 1080p Yes 🏷 │
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@ source: src/ui/radarr_ui/radarr_ui_tests.rs
|
|||||||
expression: output
|
expression: output
|
||||||
---
|
---
|
||||||
╭ Movies ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
╭ Movies ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
||||||
│ Library │ Collections │ Downloads │ Blocklist │ Root Folders │ Indexers │ System │
|
│ Library │ Collections │ Downloads │ Blocklist │ History │ Root Folders │ Indexers │ System │
|
||||||
│───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│
|
│───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│
|
||||||
│ Title Percent Complete Size Output Path Indexer Download Client │
|
│ Title Percent Complete Size Output Path Indexer Download Client │
|
||||||
│=> Test Download Title 50% 3.30 GB /nfs/movies/Test kickass torrents transmission │
|
│=> Test Download Title 50% 3.30 GB /nfs/movies/Test kickass torrents transmission │
|
||||||
|
|||||||
+54
@@ -0,0 +1,54 @@
|
|||||||
|
---
|
||||||
|
source: src/ui/radarr_ui/radarr_ui_tests.rs
|
||||||
|
expression: output
|
||||||
|
---
|
||||||
|
╭ Movies ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
||||||
|
│ Library │ Collections │ Downloads │ Blocklist │ History │ Root Folders │ Indexers │ System │
|
||||||
|
│───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│
|
||||||
|
│ Source Title ▼ Event Type Language Quality Date │
|
||||||
|
│=> Test grabbed English HD - 1080p 2022-12-30 07:37:56 UTC │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
|
||||||
+1
-1
@@ -3,7 +3,7 @@ source: src/ui/radarr_ui/radarr_ui_tests.rs
|
|||||||
expression: output
|
expression: output
|
||||||
---
|
---
|
||||||
╭ Movies ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
╭ Movies ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
||||||
│ Library │ Collections │ Downloads │ Blocklist │ Root Folders │ Indexers │ System │
|
│ Library │ Collections │ Downloads │ Blocklist │ History │ Root Folders │ Indexers │ System │
|
||||||
│───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│
|
│───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│
|
||||||
│ Indexer ▼ RSS Automatic Search Interactive Search Priority Tags │
|
│ Indexer ▼ RSS Automatic Search Interactive Search Priority Tags │
|
||||||
│=> Test Indexer Enabled Enabled Enabled 25 alex │
|
│=> Test Indexer Enabled Enabled Enabled 25 alex │
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@ source: src/ui/radarr_ui/radarr_ui_tests.rs
|
|||||||
expression: output
|
expression: output
|
||||||
---
|
---
|
||||||
╭ Movies ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
╭ Movies ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
||||||
│ Library │ Collections │ Downloads │ Blocklist │ Root Folders │ Indexers │ System │
|
│ Library │ Collections │ Downloads │ Blocklist │ History │ Root Folders │ Indexers │ System │
|
||||||
│───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│
|
│───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│
|
||||||
│ Title ▼ Year Studio Runtime Rating Language Size Quality Profile Monitored Tags │
|
│ Title ▼ Year Studio Runtime Rating Language Size Quality Profile Monitored Tags │
|
||||||
│=> Test 2023 21st Century Alex 2h 0m R English 3.30 GB HD - 1080p 🏷 alex │
|
│=> Test 2023 21st Century Alex 2h 0m R English 3.30 GB HD - 1080p 🏷 alex │
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@ source: src/ui/radarr_ui/radarr_ui_tests.rs
|
|||||||
expression: output
|
expression: output
|
||||||
---
|
---
|
||||||
╭ Movies ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
╭ Movies ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
||||||
│ Library │ Collections │ Downloads │ Blocklist │ Root Folders │ Indexers │ System │
|
│ Library │ Collections │ Downloads │ Blocklist │ History │ Root Folders │ Indexers │ System │
|
||||||
│───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│
|
│───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│
|
||||||
│ Path Free Space Unmapped Folders │
|
│ Path Free Space Unmapped Folders │
|
||||||
│=> /nfs 204800.00 GB 0 │
|
│=> /nfs 204800.00 GB 0 │
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@ source: src/ui/radarr_ui/radarr_ui_tests.rs
|
|||||||
expression: output
|
expression: output
|
||||||
---
|
---
|
||||||
╭ Movies ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
╭ Movies ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
||||||
│ Library │ Collections │ Downloads │ Blocklist │ Root Folders │ Indexers │ System │
|
│ Library │ Collections │ Downloads │ Blocklist │ History │ Root Folders │ Indexers │ System │
|
||||||
│╭ Tasks ───────────────────────────────────────────────────────────────────────╮╭ Queued Events ──────────────────────────────────────────────────────────────╮│
|
│╭ Tasks ───────────────────────────────────────────────────────────────────────╮╭ Queued Events ──────────────────────────────────────────────────────────────╮│
|
||||||
││Name Interval Last Execution Last Duration Next Execution ││Trigger Status Name Queued Started Duration ││
|
││Name Interval Last Execution Last Duration Next Execution ││Trigger Status Name Queued Started Duration ││
|
||||||
││Backup 1 hour now 00:00:17 59 minutes ││manual completed Refresh Monitored 4 minutes ago 4 minutes a 00:03:03 ││
|
││Backup 1 hour now 00:00:17 59 minutes ││manual completed Refresh Monitored 4 minutes ago 4 minutes a 00:03:03 ││
|
||||||
|
|||||||
+1
-1
@@ -16,7 +16,7 @@ expression: output
|
|||||||
│ ││ ││ │
|
│ ││ ││ │
|
||||||
╰───────────────────────────────────────────────────────────────────────╯╰──────────────────────────────────────────────────────────────────────╯╰──────────────────╯
|
╰───────────────────────────────────────────────────────────────────────╯╰──────────────────────────────────────────────────────────────────────╯╰──────────────────╯
|
||||||
╭ Movies ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
╭ Movies ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
||||||
│ Library │ Collections │ Downloads │ Blocklist │ Root Folders │ Indexers │ System │
|
│ Library │ Collections │ Downloads │ Blocklist │ History │ Root Folders │ Indexers │ System │
|
||||||
│───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│
|
│───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│
|
||||||
│ Title ▼ Year Studio Runtime Rating Language Size Quality Profile Monitored Tags │
|
│ Title ▼ Year Studio Runtime Rating Language Size Quality Profile Monitored Tags │
|
||||||
│=> Test 2023 21st Century Alex 2h 0m R English 3.30 GB HD - 1080p 🏷 alex │
|
│=> Test 2023 21st Century Alex 2h 0m R English 3.30 GB HD - 1080p 🏷 alex │
|
||||||
|
|||||||
+1
-1
@@ -19,7 +19,7 @@ expression: output
|
|||||||
│ ││ ││ │
|
│ ││ ││ │
|
||||||
╰───────────────────────────────────────────────────────────────────────╯╰──────────────────────────────────────────────────────────────────────╯╰──────────────────╯
|
╰───────────────────────────────────────────────────────────────────────╯╰──────────────────────────────────────────────────────────────────────╯╰──────────────────╯
|
||||||
╭ Movies ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
╭ Movies ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
||||||
│ Library │ Collections │ Downloads │ Blocklist │ Root Folders │ Indexers │ System │
|
│ Library │ Collections │ Downloads │ Blocklist │ History │ Root Folders │ Indexers │ System │
|
||||||
│───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│
|
│───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│
|
||||||
│ Title ▼ Year Studio Runtime Rating Language Size Quality Profile Monitored Tags │
|
│ Title ▼ Year Studio Runtime Rating Language Size Quality Profile Monitored Tags │
|
||||||
│=> Test 2023 21st Century Alex 2h 0m R English 3.30 GB HD - 1080p 🏷 alex │
|
│=> Test 2023 21st Century Alex 2h 0m R English 3.30 GB HD - 1080p 🏷 alex │
|
||||||
|
|||||||
Reference in New Issue
Block a user