feat: proper collapsing of root folder paths in the stats layer of the UI
This commit is contained in:
@@ -28,6 +28,7 @@ use crate::ui::lidarr_ui::downloads::DownloadsUi;
|
|||||||
use crate::ui::lidarr_ui::indexers::IndexersUi;
|
use crate::ui::lidarr_ui::indexers::IndexersUi;
|
||||||
use crate::ui::lidarr_ui::root_folders::RootFoldersUi;
|
use crate::ui::lidarr_ui::root_folders::RootFoldersUi;
|
||||||
use crate::ui::lidarr_ui::system::SystemUi;
|
use crate::ui::lidarr_ui::system::SystemUi;
|
||||||
|
use crate::ui::utils::{extract_monitored_disk_space_vec, extract_monitored_root_folders};
|
||||||
use crate::{
|
use crate::{
|
||||||
app::App,
|
app::App,
|
||||||
logos::LIDARR_LOGO,
|
logos::LIDARR_LOGO,
|
||||||
@@ -146,12 +147,13 @@ fn draw_stats_context(f: &mut Frame<'_>, app: &App<'_>, area: Rect) {
|
|||||||
f.render_widget(uptime_paragraph, stat_item_areas[1]);
|
f.render_widget(uptime_paragraph, stat_item_areas[1]);
|
||||||
f.render_widget(storage, stat_item_areas[2]);
|
f.render_widget(storage, stat_item_areas[2]);
|
||||||
|
|
||||||
for i in 0..disk_space_vec.len() {
|
let monitored_disk_space_vec = extract_monitored_disk_space_vec(app, disk_space_vec.clone());
|
||||||
|
for i in 0..monitored_disk_space_vec.len() {
|
||||||
let DiskSpace {
|
let DiskSpace {
|
||||||
path,
|
path,
|
||||||
free_space,
|
free_space,
|
||||||
total_space,
|
total_space,
|
||||||
} = &disk_space_vec[i];
|
} = &monitored_disk_space_vec[i];
|
||||||
let title = if let Some(path) = path {
|
let title = if let Some(path) = path {
|
||||||
path
|
path
|
||||||
} else {
|
} else {
|
||||||
@@ -168,12 +170,13 @@ fn draw_stats_context(f: &mut Frame<'_>, app: &App<'_>, area: Rect) {
|
|||||||
f.render_widget(space_gauge, stat_item_areas[i + 3]);
|
f.render_widget(space_gauge, stat_item_areas[i + 3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
f.render_widget(folders, stat_item_areas[disk_space_vec.len() + 3]);
|
f.render_widget(folders, stat_item_areas[monitored_disk_space_vec.len() + 3]);
|
||||||
|
|
||||||
for i in 0..root_folders.items.len() {
|
let monitored_root_folders = extract_monitored_root_folders(app, root_folders.items.clone());
|
||||||
|
for i in 0..monitored_root_folders.len() {
|
||||||
let RootFolder {
|
let RootFolder {
|
||||||
path, free_space, ..
|
path, free_space, ..
|
||||||
} = &root_folders.items[i];
|
} = &monitored_root_folders[i];
|
||||||
let space: f64 = convert_to_gb(*free_space);
|
let space: f64 = convert_to_gb(*free_space);
|
||||||
let root_folder_space = Paragraph::new(format!("{path}: {space:.2} GB free"))
|
let root_folder_space = Paragraph::new(format!("{path}: {space:.2} GB free"))
|
||||||
.block(borderless_block())
|
.block(borderless_block())
|
||||||
@@ -181,7 +184,7 @@ fn draw_stats_context(f: &mut Frame<'_>, app: &App<'_>, area: Rect) {
|
|||||||
|
|
||||||
f.render_widget(
|
f.render_widget(
|
||||||
root_folder_space,
|
root_folder_space,
|
||||||
stat_item_areas[i + disk_space_vec.len() + 4],
|
stat_item_areas[i + monitored_disk_space_vec.len() + 4],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+21
-19
@@ -1,15 +1,3 @@
|
|||||||
#[cfg(test)]
|
|
||||||
use crate::ui::ui_test_utils::test_utils::Utc;
|
|
||||||
use chrono::Duration;
|
|
||||||
#[cfg(not(test))]
|
|
||||||
use chrono::Utc;
|
|
||||||
use ratatui::Frame;
|
|
||||||
use ratatui::layout::{Constraint, Layout, Rect};
|
|
||||||
use ratatui::prelude::Stylize;
|
|
||||||
use ratatui::text::Text;
|
|
||||||
use ratatui::widgets::{Paragraph, Row};
|
|
||||||
use std::{cmp, iter};
|
|
||||||
|
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::logos::RADARR_LOGO;
|
use crate::logos::RADARR_LOGO;
|
||||||
use crate::models::Route;
|
use crate::models::Route;
|
||||||
@@ -27,11 +15,23 @@ use crate::ui::radarr_ui::library::LibraryUi;
|
|||||||
use crate::ui::radarr_ui::root_folders::RootFoldersUi;
|
use crate::ui::radarr_ui::root_folders::RootFoldersUi;
|
||||||
use crate::ui::radarr_ui::system::SystemUi;
|
use crate::ui::radarr_ui::system::SystemUi;
|
||||||
use crate::ui::styles::ManagarrStyle;
|
use crate::ui::styles::ManagarrStyle;
|
||||||
|
#[cfg(test)]
|
||||||
|
use crate::ui::ui_test_utils::test_utils::Utc;
|
||||||
use crate::ui::utils::{
|
use crate::ui::utils::{
|
||||||
borderless_block, layout_block, line_gauge_with_label, line_gauge_with_title, title_block,
|
borderless_block, extract_monitored_disk_space_vec, extract_monitored_root_folders, layout_block,
|
||||||
|
line_gauge_with_label, line_gauge_with_title, title_block,
|
||||||
};
|
};
|
||||||
use crate::ui::widgets::loading_block::LoadingBlock;
|
use crate::ui::widgets::loading_block::LoadingBlock;
|
||||||
use crate::utils::convert_to_gb;
|
use crate::utils::convert_to_gb;
|
||||||
|
use chrono::Duration;
|
||||||
|
#[cfg(not(test))]
|
||||||
|
use chrono::Utc;
|
||||||
|
use ratatui::Frame;
|
||||||
|
use ratatui::layout::{Constraint, Layout, Rect};
|
||||||
|
use ratatui::prelude::Stylize;
|
||||||
|
use ratatui::text::Text;
|
||||||
|
use ratatui::widgets::{Paragraph, Row};
|
||||||
|
use std::{cmp, iter};
|
||||||
|
|
||||||
mod blocklist;
|
mod blocklist;
|
||||||
mod collections;
|
mod collections;
|
||||||
@@ -139,12 +139,13 @@ fn draw_stats_context(f: &mut Frame<'_>, app: &App<'_>, area: Rect) {
|
|||||||
f.render_widget(uptime_paragraph, stat_item_areas[1]);
|
f.render_widget(uptime_paragraph, stat_item_areas[1]);
|
||||||
f.render_widget(storage, stat_item_areas[2]);
|
f.render_widget(storage, stat_item_areas[2]);
|
||||||
|
|
||||||
for i in 0..disk_space_vec.len() {
|
let monitored_disk_space_vec = extract_monitored_disk_space_vec(app, disk_space_vec.clone());
|
||||||
|
for i in 0..monitored_disk_space_vec.len() {
|
||||||
let DiskSpace {
|
let DiskSpace {
|
||||||
path,
|
path,
|
||||||
free_space,
|
free_space,
|
||||||
total_space,
|
total_space,
|
||||||
} = &disk_space_vec[i];
|
} = &monitored_disk_space_vec[i];
|
||||||
let title = if let Some(path) = path {
|
let title = if let Some(path) = path {
|
||||||
path
|
path
|
||||||
} else {
|
} else {
|
||||||
@@ -161,12 +162,13 @@ fn draw_stats_context(f: &mut Frame<'_>, app: &App<'_>, area: Rect) {
|
|||||||
f.render_widget(space_gauge, stat_item_areas[i + 3]);
|
f.render_widget(space_gauge, stat_item_areas[i + 3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
f.render_widget(folders, stat_item_areas[disk_space_vec.len() + 3]);
|
f.render_widget(folders, stat_item_areas[monitored_disk_space_vec.len() + 3]);
|
||||||
|
|
||||||
for i in 0..root_folders.items.len() {
|
let monitored_root_folders = extract_monitored_root_folders(app, root_folders.items.clone());
|
||||||
|
for i in 0..monitored_root_folders.len() {
|
||||||
let RootFolder {
|
let RootFolder {
|
||||||
path, free_space, ..
|
path, free_space, ..
|
||||||
} = &root_folders.items[i];
|
} = &monitored_root_folders[i];
|
||||||
let space: f64 = convert_to_gb(*free_space);
|
let space: f64 = convert_to_gb(*free_space);
|
||||||
let root_folder_space = Paragraph::new(format!("{path}: {space:.2} GB free"))
|
let root_folder_space = Paragraph::new(format!("{path}: {space:.2} GB free"))
|
||||||
.block(borderless_block())
|
.block(borderless_block())
|
||||||
@@ -174,7 +176,7 @@ fn draw_stats_context(f: &mut Frame<'_>, app: &App<'_>, area: Rect) {
|
|||||||
|
|
||||||
f.render_widget(
|
f.render_widget(
|
||||||
root_folder_space,
|
root_folder_space,
|
||||||
stat_item_areas[i + disk_space_vec.len() + 4],
|
stat_item_areas[i + monitored_disk_space_vec.len() + 4],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+18
-17
@@ -1,5 +1,3 @@
|
|||||||
use std::{cmp, iter};
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
use crate::ui::ui_test_utils::test_utils::Utc;
|
use crate::ui::ui_test_utils::test_utils::Utc;
|
||||||
use blocklist::BlocklistUi;
|
use blocklist::BlocklistUi;
|
||||||
@@ -18,8 +16,18 @@ use ratatui::{
|
|||||||
widgets::Paragraph,
|
widgets::Paragraph,
|
||||||
};
|
};
|
||||||
use root_folders::RootFoldersUi;
|
use root_folders::RootFoldersUi;
|
||||||
|
use std::{cmp, iter};
|
||||||
use system::SystemUi;
|
use system::SystemUi;
|
||||||
|
|
||||||
|
use super::{
|
||||||
|
DrawUi, draw_tabs,
|
||||||
|
styles::ManagarrStyle,
|
||||||
|
utils::{
|
||||||
|
borderless_block, layout_block, line_gauge_with_label, line_gauge_with_title, title_block,
|
||||||
|
},
|
||||||
|
widgets::loading_block::LoadingBlock,
|
||||||
|
};
|
||||||
|
use crate::ui::utils::{extract_monitored_disk_space_vec, extract_monitored_root_folders};
|
||||||
use crate::{
|
use crate::{
|
||||||
app::App,
|
app::App,
|
||||||
logos::SONARR_LOGO,
|
logos::SONARR_LOGO,
|
||||||
@@ -32,15 +40,6 @@ use crate::{
|
|||||||
utils::convert_to_gb,
|
utils::convert_to_gb,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
|
||||||
DrawUi, draw_tabs,
|
|
||||||
styles::ManagarrStyle,
|
|
||||||
utils::{
|
|
||||||
borderless_block, layout_block, line_gauge_with_label, line_gauge_with_title, title_block,
|
|
||||||
},
|
|
||||||
widgets::loading_block::LoadingBlock,
|
|
||||||
};
|
|
||||||
|
|
||||||
mod blocklist;
|
mod blocklist;
|
||||||
mod downloads;
|
mod downloads;
|
||||||
mod history;
|
mod history;
|
||||||
@@ -147,13 +146,14 @@ fn draw_stats_context(f: &mut Frame<'_>, app: &App<'_>, area: Rect) {
|
|||||||
f.render_widget(uptime_paragraph, stat_item_areas[1]);
|
f.render_widget(uptime_paragraph, stat_item_areas[1]);
|
||||||
f.render_widget(storage, stat_item_areas[2]);
|
f.render_widget(storage, stat_item_areas[2]);
|
||||||
|
|
||||||
for i in 0..disk_space_vec.len() {
|
let monitored_disk_space_vec = extract_monitored_disk_space_vec(app, disk_space_vec.clone());
|
||||||
|
for i in 0..monitored_disk_space_vec.len() {
|
||||||
let DiskSpace {
|
let DiskSpace {
|
||||||
path,
|
path,
|
||||||
free_space,
|
free_space,
|
||||||
total_space,
|
total_space,
|
||||||
..
|
..
|
||||||
} = &disk_space_vec[i];
|
} = &monitored_disk_space_vec[i];
|
||||||
let title = if let Some(path) = path {
|
let title = if let Some(path) = path {
|
||||||
path
|
path
|
||||||
} else {
|
} else {
|
||||||
@@ -170,12 +170,13 @@ fn draw_stats_context(f: &mut Frame<'_>, app: &App<'_>, area: Rect) {
|
|||||||
f.render_widget(space_gauge, stat_item_areas[i + 3]);
|
f.render_widget(space_gauge, stat_item_areas[i + 3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
f.render_widget(folders, stat_item_areas[disk_space_vec.len() + 3]);
|
f.render_widget(folders, stat_item_areas[monitored_disk_space_vec.len() + 3]);
|
||||||
|
|
||||||
for i in 0..root_folders.items.len() {
|
let monitored_root_folders = extract_monitored_root_folders(app, root_folders.items.clone());
|
||||||
|
for i in 0..monitored_root_folders.len() {
|
||||||
let RootFolder {
|
let RootFolder {
|
||||||
path, free_space, ..
|
path, free_space, ..
|
||||||
} = &root_folders.items[i];
|
} = &monitored_root_folders[i];
|
||||||
let space: f64 = convert_to_gb(*free_space);
|
let space: f64 = convert_to_gb(*free_space);
|
||||||
let root_folder_space = Paragraph::new(format!("{path}: {space:.2} GB free"))
|
let root_folder_space = Paragraph::new(format!("{path}: {space:.2} GB free"))
|
||||||
.block(borderless_block())
|
.block(borderless_block())
|
||||||
@@ -183,7 +184,7 @@ fn draw_stats_context(f: &mut Frame<'_>, app: &App<'_>, area: Rect) {
|
|||||||
|
|
||||||
f.render_widget(
|
f.render_widget(
|
||||||
root_folder_space,
|
root_folder_space,
|
||||||
stat_item_areas[i + disk_space_vec.len() + 4],
|
stat_item_areas[i + monitored_disk_space_vec.len() + 4],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+116
@@ -1,3 +1,5 @@
|
|||||||
|
use crate::app::App;
|
||||||
|
use crate::models::servarr_models::{DiskSpace, RootFolder};
|
||||||
use crate::ui::THEME;
|
use crate::ui::THEME;
|
||||||
use crate::ui::styles::{
|
use crate::ui::styles::{
|
||||||
ManagarrStyle, default_style, failure_style, primary_style, secondary_style,
|
ManagarrStyle, default_style, failure_style, primary_style, secondary_style,
|
||||||
@@ -7,6 +9,8 @@ use ratatui::layout::{Alignment, Constraint, Layout, Rect};
|
|||||||
use ratatui::style::{Style, Stylize};
|
use ratatui::style::{Style, Stylize};
|
||||||
use ratatui::text::{Line, Span, Text};
|
use ratatui::text::{Line, Span, Text};
|
||||||
use ratatui::widgets::{Block, BorderType, Borders, LineGauge, ListItem, Paragraph, Wrap};
|
use ratatui::widgets::{Block, BorderType, Borders, LineGauge, ListItem, Paragraph, Wrap};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[path = "utils_tests.rs"]
|
#[path = "utils_tests.rs"]
|
||||||
@@ -179,3 +183,115 @@ pub(super) fn decorate_peer_style(seeders: u64, leechers: u64, text: Text<'_>) -
|
|||||||
text.success()
|
text.success()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super) fn extract_monitored_root_folders(
|
||||||
|
app: &App<'_>,
|
||||||
|
root_folders: Vec<RootFolder>,
|
||||||
|
) -> Vec<RootFolder> {
|
||||||
|
let monitored_paths = app
|
||||||
|
.server_tabs
|
||||||
|
.get_active_config()
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.monitored_storage_paths
|
||||||
|
.as_ref();
|
||||||
|
|
||||||
|
if let Some(monitored_paths) = monitored_paths
|
||||||
|
&& !monitored_paths.is_empty()
|
||||||
|
{
|
||||||
|
let monitored_paths: Vec<PathBuf> = monitored_paths.iter().map(PathBuf::from).collect();
|
||||||
|
|
||||||
|
let mut collapsed_folders: HashMap<PathBuf, (RootFolder, Vec<String>)> = HashMap::new();
|
||||||
|
let mut unmatched_folders: Vec<RootFolder> = Vec::new();
|
||||||
|
|
||||||
|
for root_folder in root_folders {
|
||||||
|
let root_path = Path::new(&root_folder.path);
|
||||||
|
|
||||||
|
let matching_monitored_path = monitored_paths
|
||||||
|
.iter()
|
||||||
|
.filter(|mp| root_path.starts_with(mp))
|
||||||
|
.max_by_key(|mp| mp.components().count());
|
||||||
|
|
||||||
|
if let Some(monitored_path) = matching_monitored_path {
|
||||||
|
let subfolder_name = root_path
|
||||||
|
.strip_prefix(monitored_path)
|
||||||
|
.ok()
|
||||||
|
.and_then(|p| p.components().next())
|
||||||
|
.map(|c| c.as_os_str().to_string_lossy().to_string())
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
collapsed_folders
|
||||||
|
.entry(monitored_path.clone())
|
||||||
|
.and_modify(|(_, subfolders)| {
|
||||||
|
if !subfolder_name.is_empty() && !subfolders.contains(&subfolder_name) {
|
||||||
|
subfolders.push(subfolder_name.clone());
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.or_insert_with(|| {
|
||||||
|
let subfolders = if subfolder_name.is_empty() {
|
||||||
|
vec![]
|
||||||
|
} else {
|
||||||
|
vec![subfolder_name]
|
||||||
|
};
|
||||||
|
(root_folder.clone(), subfolders)
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
unmatched_folders.push(root_folder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut result: Vec<RootFolder> = collapsed_folders
|
||||||
|
.into_iter()
|
||||||
|
.map(|(monitored_path, (mut root_folder, mut subfolders))| {
|
||||||
|
subfolders.sort();
|
||||||
|
let path_str = monitored_path.to_string_lossy();
|
||||||
|
root_folder.path = if subfolders.is_empty() {
|
||||||
|
path_str.to_string()
|
||||||
|
} else {
|
||||||
|
format!(
|
||||||
|
"{}/[{}]",
|
||||||
|
path_str.trim_end_matches('/'),
|
||||||
|
subfolders.join(",")
|
||||||
|
)
|
||||||
|
};
|
||||||
|
root_folder
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
result.extend(unmatched_folders);
|
||||||
|
result.sort_by(|a, b| a.path.cmp(&b.path));
|
||||||
|
result
|
||||||
|
} else {
|
||||||
|
root_folders
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn extract_monitored_disk_space_vec(
|
||||||
|
app: &App<'_>,
|
||||||
|
disk_space_vec: Vec<DiskSpace>,
|
||||||
|
) -> Vec<DiskSpace> {
|
||||||
|
let monitored_paths = app
|
||||||
|
.server_tabs
|
||||||
|
.get_active_config()
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.monitored_storage_paths
|
||||||
|
.as_ref();
|
||||||
|
if let Some(monitored_paths) = monitored_paths
|
||||||
|
&& !monitored_paths.is_empty()
|
||||||
|
{
|
||||||
|
let paths: Vec<PathBuf> = monitored_paths.iter().map(PathBuf::from).collect();
|
||||||
|
disk_space_vec
|
||||||
|
.into_iter()
|
||||||
|
.filter(|it| {
|
||||||
|
if let Some(path) = it.path.as_ref() {
|
||||||
|
paths.iter().any(|p| path == p)
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
} else {
|
||||||
|
disk_space_vec
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+279
-1
@@ -1,9 +1,12 @@
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
|
use crate::app::{App, ServarrConfig};
|
||||||
|
use crate::models::servarr_models::{DiskSpace, RootFolder};
|
||||||
use crate::ui::styles::{ManagarrStyle, default_style, failure_style, secondary_style};
|
use crate::ui::styles::{ManagarrStyle, default_style, failure_style, secondary_style};
|
||||||
use crate::ui::utils::{
|
use crate::ui::utils::{
|
||||||
borderless_block, centered_rect, convert_to_minutes_hours_days, decorate_peer_style,
|
borderless_block, centered_rect, convert_to_minutes_hours_days, decorate_peer_style,
|
||||||
get_width_from_percentage, layout_block, layout_block_bottom_border, layout_block_top_border,
|
extract_monitored_disk_space_vec, extract_monitored_root_folders, get_width_from_percentage,
|
||||||
|
layout_block, layout_block_bottom_border, layout_block_top_border,
|
||||||
layout_block_top_border_with_title, layout_block_with_title, logo_block, style_block_highlight,
|
layout_block_top_border_with_title, layout_block_with_title, logo_block, style_block_highlight,
|
||||||
style_log_list_item, title_block, title_block_centered, title_style, unstyled_title_block,
|
style_log_list_item, title_block, title_block_centered, title_style, unstyled_title_block,
|
||||||
};
|
};
|
||||||
@@ -278,6 +281,281 @@ mod test {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_extract_monitored_root_folders_collapses_subfolders() {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.server_tabs.tabs[0].config = Some(ServarrConfig {
|
||||||
|
monitored_storage_paths: Some(vec!["/nfs".to_owned()]),
|
||||||
|
..ServarrConfig::default()
|
||||||
|
});
|
||||||
|
let root_folders = vec![
|
||||||
|
RootFolder {
|
||||||
|
id: 1,
|
||||||
|
path: "/nfs/cartoons".to_string(),
|
||||||
|
accessible: true,
|
||||||
|
free_space: 100,
|
||||||
|
unmapped_folders: None,
|
||||||
|
},
|
||||||
|
RootFolder {
|
||||||
|
id: 2,
|
||||||
|
path: "/nfs/tv".to_string(),
|
||||||
|
accessible: true,
|
||||||
|
free_space: 100,
|
||||||
|
unmapped_folders: None,
|
||||||
|
},
|
||||||
|
RootFolder {
|
||||||
|
id: 3,
|
||||||
|
path: "/nfs/reality".to_string(),
|
||||||
|
accessible: true,
|
||||||
|
free_space: 100,
|
||||||
|
unmapped_folders: None,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
let monitored_root_folders = extract_monitored_root_folders(&app, root_folders);
|
||||||
|
|
||||||
|
assert_eq!(monitored_root_folders.len(), 1);
|
||||||
|
assert_eq!(monitored_root_folders[0].path, "/nfs/[cartoons,reality,tv]");
|
||||||
|
assert_eq!(monitored_root_folders[0].free_space, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_extract_monitored_root_folders_uses_most_specific_monitored_path() {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.server_tabs.tabs[0].config = Some(ServarrConfig {
|
||||||
|
monitored_storage_paths: Some(vec!["/nfs".to_owned(), "/".to_owned()]),
|
||||||
|
..ServarrConfig::default()
|
||||||
|
});
|
||||||
|
let root_folders = vec![
|
||||||
|
RootFolder {
|
||||||
|
id: 1,
|
||||||
|
path: "/nfs/cartoons".to_string(),
|
||||||
|
accessible: true,
|
||||||
|
free_space: 100,
|
||||||
|
unmapped_folders: None,
|
||||||
|
},
|
||||||
|
RootFolder {
|
||||||
|
id: 2,
|
||||||
|
path: "/nfs/tv".to_string(),
|
||||||
|
accessible: true,
|
||||||
|
free_space: 100,
|
||||||
|
unmapped_folders: None,
|
||||||
|
},
|
||||||
|
RootFolder {
|
||||||
|
id: 3,
|
||||||
|
path: "/other/movies".to_string(),
|
||||||
|
accessible: true,
|
||||||
|
free_space: 200,
|
||||||
|
unmapped_folders: None,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
let monitored_root_folders = extract_monitored_root_folders(&app, root_folders);
|
||||||
|
|
||||||
|
assert_eq!(monitored_root_folders.len(), 2);
|
||||||
|
assert_eq!(monitored_root_folders[0].path, "/[other]");
|
||||||
|
assert_eq!(monitored_root_folders[0].free_space, 200);
|
||||||
|
assert_eq!(monitored_root_folders[1].path, "/nfs/[cartoons,tv]");
|
||||||
|
assert_eq!(monitored_root_folders[1].free_space, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_extract_monitored_root_folders_preserves_unmatched_folders() {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.server_tabs.tabs[0].config = Some(ServarrConfig {
|
||||||
|
monitored_storage_paths: Some(vec!["/nfs".to_owned()]),
|
||||||
|
..ServarrConfig::default()
|
||||||
|
});
|
||||||
|
let root_folders = vec![
|
||||||
|
RootFolder {
|
||||||
|
id: 1,
|
||||||
|
path: "/nfs/tv".to_string(),
|
||||||
|
accessible: true,
|
||||||
|
free_space: 100,
|
||||||
|
unmapped_folders: None,
|
||||||
|
},
|
||||||
|
RootFolder {
|
||||||
|
id: 2,
|
||||||
|
path: "/other/movies".to_string(),
|
||||||
|
accessible: true,
|
||||||
|
free_space: 200,
|
||||||
|
unmapped_folders: None,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
let monitored_root_folders = extract_monitored_root_folders(&app, root_folders);
|
||||||
|
|
||||||
|
assert_eq!(monitored_root_folders.len(), 2);
|
||||||
|
assert_eq!(monitored_root_folders[0].path, "/nfs/[tv]");
|
||||||
|
assert_eq!(monitored_root_folders[1].path, "/other/movies");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_extract_monitored_root_folders_returns_all_when_monitored_storage_paths_is_empty() {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.server_tabs.tabs[0].config = Some(ServarrConfig {
|
||||||
|
monitored_storage_paths: Some(vec![]),
|
||||||
|
..ServarrConfig::default()
|
||||||
|
});
|
||||||
|
let root_folders = vec![
|
||||||
|
RootFolder {
|
||||||
|
id: 1,
|
||||||
|
path: "/nfs".to_string(),
|
||||||
|
accessible: true,
|
||||||
|
free_space: 10,
|
||||||
|
unmapped_folders: None,
|
||||||
|
},
|
||||||
|
RootFolder {
|
||||||
|
id: 2,
|
||||||
|
path: "/nfs/some/subpath".to_string(),
|
||||||
|
accessible: true,
|
||||||
|
free_space: 10,
|
||||||
|
unmapped_folders: None,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
let monitored_root_folders = extract_monitored_root_folders(&app, root_folders.clone());
|
||||||
|
|
||||||
|
assert_eq!(monitored_root_folders, root_folders);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_extract_monitored_root_folders_returns_all_when_monitored_storage_paths_is_none() {
|
||||||
|
let app = App::test_default();
|
||||||
|
let root_folders = vec![
|
||||||
|
RootFolder {
|
||||||
|
id: 1,
|
||||||
|
path: "/nfs".to_string(),
|
||||||
|
accessible: true,
|
||||||
|
free_space: 10,
|
||||||
|
unmapped_folders: None,
|
||||||
|
},
|
||||||
|
RootFolder {
|
||||||
|
id: 2,
|
||||||
|
path: "/nfs/some/subpath".to_string(),
|
||||||
|
accessible: true,
|
||||||
|
free_space: 10,
|
||||||
|
unmapped_folders: None,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
let monitored_root_folders = extract_monitored_root_folders(&app, root_folders.clone());
|
||||||
|
|
||||||
|
assert_eq!(monitored_root_folders, root_folders);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_extract_monitored_root_folders_exact_match_shows_no_brackets() {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.server_tabs.tabs[0].config = Some(ServarrConfig {
|
||||||
|
monitored_storage_paths: Some(vec!["/nfs/tv".to_owned()]),
|
||||||
|
..ServarrConfig::default()
|
||||||
|
});
|
||||||
|
let root_folders = vec![RootFolder {
|
||||||
|
id: 1,
|
||||||
|
path: "/nfs/tv".to_string(),
|
||||||
|
accessible: true,
|
||||||
|
free_space: 100,
|
||||||
|
unmapped_folders: None,
|
||||||
|
}];
|
||||||
|
|
||||||
|
let monitored_root_folders = extract_monitored_root_folders(&app, root_folders);
|
||||||
|
|
||||||
|
assert_eq!(monitored_root_folders.len(), 1);
|
||||||
|
assert_eq!(monitored_root_folders[0].path, "/nfs/tv");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_extract_monitored_disk_space_vec() {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.server_tabs.tabs[0].config = Some(ServarrConfig {
|
||||||
|
monitored_storage_paths: Some(vec!["/nfs".to_owned()]),
|
||||||
|
..ServarrConfig::default()
|
||||||
|
});
|
||||||
|
let disk_space = DiskSpace {
|
||||||
|
path: Some("/nfs".to_string()),
|
||||||
|
free_space: 10,
|
||||||
|
total_space: 1000,
|
||||||
|
};
|
||||||
|
let disk_space_with_empty_path = DiskSpace {
|
||||||
|
path: None,
|
||||||
|
free_space: 10,
|
||||||
|
total_space: 1000,
|
||||||
|
};
|
||||||
|
let disk_spaces = vec![
|
||||||
|
disk_space.clone(),
|
||||||
|
disk_space_with_empty_path.clone(),
|
||||||
|
DiskSpace {
|
||||||
|
path: Some("/nfs/some/subpath".to_string()),
|
||||||
|
free_space: 10,
|
||||||
|
total_space: 1000,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
let monitored_disk_space = extract_monitored_disk_space_vec(&app, disk_spaces);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
monitored_disk_space,
|
||||||
|
vec![disk_space, disk_space_with_empty_path]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_extract_monitored_disk_space_vec_returns_all_when_monitored_storage_paths_is_empty() {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.server_tabs.tabs[0].config = Some(ServarrConfig {
|
||||||
|
monitored_storage_paths: Some(Vec::new()),
|
||||||
|
..ServarrConfig::default()
|
||||||
|
});
|
||||||
|
let disk_spaces = vec![
|
||||||
|
DiskSpace {
|
||||||
|
path: Some("/nfs".to_string()),
|
||||||
|
free_space: 10,
|
||||||
|
total_space: 1000,
|
||||||
|
},
|
||||||
|
DiskSpace {
|
||||||
|
path: None,
|
||||||
|
free_space: 10,
|
||||||
|
total_space: 1000,
|
||||||
|
},
|
||||||
|
DiskSpace {
|
||||||
|
path: Some("/nfs/some/subpath".to_string()),
|
||||||
|
free_space: 10,
|
||||||
|
total_space: 1000,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
let monitored_disk_space = extract_monitored_disk_space_vec(&app, disk_spaces.clone());
|
||||||
|
|
||||||
|
assert_eq!(monitored_disk_space, disk_spaces);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_extract_monitored_disk_space_vec_returns_all_when_monitored_storage_paths_is_none() {
|
||||||
|
let app = App::test_default();
|
||||||
|
let disk_spaces = vec![
|
||||||
|
DiskSpace {
|
||||||
|
path: Some("/nfs".to_string()),
|
||||||
|
free_space: 10,
|
||||||
|
total_space: 1000,
|
||||||
|
},
|
||||||
|
DiskSpace {
|
||||||
|
path: None,
|
||||||
|
free_space: 10,
|
||||||
|
total_space: 1000,
|
||||||
|
},
|
||||||
|
DiskSpace {
|
||||||
|
path: Some("/nfs/some/subpath".to_string()),
|
||||||
|
free_space: 10,
|
||||||
|
total_space: 1000,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
let monitored_disk_space = extract_monitored_disk_space_vec(&app, disk_spaces.clone());
|
||||||
|
|
||||||
|
assert_eq!(monitored_disk_space, disk_spaces);
|
||||||
|
}
|
||||||
|
|
||||||
enum PeerStyle {
|
enum PeerStyle {
|
||||||
Failure,
|
Failure,
|
||||||
Warning,
|
Warning,
|
||||||
|
|||||||
Reference in New Issue
Block a user