feat(ui): Edit series support
This commit is contained in:
@@ -15,7 +15,7 @@ pub(super) struct EditSeriesHandler<'a, 'b> {
|
|||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
active_sonarr_block: ActiveSonarrBlock,
|
active_sonarr_block: ActiveSonarrBlock,
|
||||||
_context: Option<ActiveSonarrBlock>,
|
context: Option<ActiveSonarrBlock>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for EditSeriesHandler<'a, 'b> {
|
impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for EditSeriesHandler<'a, 'b> {
|
||||||
@@ -27,13 +27,13 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for EditSeriesHandler<'a
|
|||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
active_block: ActiveSonarrBlock,
|
active_block: ActiveSonarrBlock,
|
||||||
_context: Option<ActiveSonarrBlock>,
|
context: Option<ActiveSonarrBlock>,
|
||||||
) -> EditSeriesHandler<'a, 'b> {
|
) -> EditSeriesHandler<'a, 'b> {
|
||||||
EditSeriesHandler {
|
EditSeriesHandler {
|
||||||
key,
|
key,
|
||||||
app,
|
app,
|
||||||
active_sonarr_block: active_block,
|
active_sonarr_block: active_block,
|
||||||
_context,
|
context,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -267,22 +267,18 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for EditSeriesHandler<'a
|
|||||||
ActiveSonarrBlock::EditSeriesSelectSeriesType
|
ActiveSonarrBlock::EditSeriesSelectSeriesType
|
||||||
| ActiveSonarrBlock::EditSeriesSelectQualityProfile
|
| ActiveSonarrBlock::EditSeriesSelectQualityProfile
|
||||||
| ActiveSonarrBlock::EditSeriesSelectLanguageProfile => self.app.push_navigation_stack(
|
| ActiveSonarrBlock::EditSeriesSelectLanguageProfile => self.app.push_navigation_stack(
|
||||||
self
|
(
|
||||||
.app
|
self.app.data.sonarr_data.selected_block.get_active_block(),
|
||||||
.data
|
self.context,
|
||||||
.sonarr_data
|
)
|
||||||
.selected_block
|
|
||||||
.get_active_block()
|
|
||||||
.into(),
|
.into(),
|
||||||
),
|
),
|
||||||
ActiveSonarrBlock::EditSeriesPathInput | ActiveSonarrBlock::EditSeriesTagsInput => {
|
ActiveSonarrBlock::EditSeriesPathInput | ActiveSonarrBlock::EditSeriesTagsInput => {
|
||||||
self.app.push_navigation_stack(
|
self.app.push_navigation_stack(
|
||||||
self
|
(
|
||||||
.app
|
self.app.data.sonarr_data.selected_block.get_active_block(),
|
||||||
.data
|
self.context,
|
||||||
.sonarr_data
|
)
|
||||||
.selected_block
|
|
||||||
.get_active_block()
|
|
||||||
.into(),
|
.into(),
|
||||||
);
|
);
|
||||||
self.app.should_ignore_quit_key = true;
|
self.app.should_ignore_quit_key = true;
|
||||||
|
|||||||
@@ -663,7 +663,7 @@ mod tests {
|
|||||||
|
|
||||||
use crate::models::servarr_data::sonarr::modals::EditSeriesModal;
|
use crate::models::servarr_data::sonarr::modals::EditSeriesModal;
|
||||||
use crate::models::servarr_data::sonarr::sonarr_data::EDIT_SERIES_SELECTION_BLOCKS;
|
use crate::models::servarr_data::sonarr::sonarr_data::EDIT_SERIES_SELECTION_BLOCKS;
|
||||||
use crate::models::BlockSelectionState;
|
use crate::models::{BlockSelectionState, Route};
|
||||||
use crate::network::sonarr_network::SonarrEvent;
|
use crate::network::sonarr_network::SonarrEvent;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
@@ -825,24 +825,25 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_series_toggle_monitored_submit() {
|
fn test_edit_series_toggle_monitored_submit() {
|
||||||
|
let current_route = Route::from((
|
||||||
|
ActiveSonarrBlock::EditSeriesPrompt,
|
||||||
|
Some(ActiveSonarrBlock::Series),
|
||||||
|
));
|
||||||
let mut app = App::default();
|
let mut app = App::default();
|
||||||
app.data.sonarr_data.edit_series_modal = Some(EditSeriesModal::default());
|
app.data.sonarr_data.edit_series_modal = Some(EditSeriesModal::default());
|
||||||
app.data.sonarr_data.selected_block = BlockSelectionState::new(EDIT_SERIES_SELECTION_BLOCKS);
|
app.data.sonarr_data.selected_block = BlockSelectionState::new(EDIT_SERIES_SELECTION_BLOCKS);
|
||||||
app.push_navigation_stack(ActiveSonarrBlock::Series.into());
|
app.push_navigation_stack(ActiveSonarrBlock::Series.into());
|
||||||
app.push_navigation_stack(ActiveSonarrBlock::EditSeriesPrompt.into());
|
app.push_navigation_stack(current_route);
|
||||||
|
|
||||||
EditSeriesHandler::with(
|
EditSeriesHandler::with(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveSonarrBlock::EditSeriesPrompt,
|
ActiveSonarrBlock::EditSeriesPrompt,
|
||||||
None,
|
Some(ActiveSonarrBlock::Series),
|
||||||
)
|
)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(app.get_current_route(), current_route);
|
||||||
app.get_current_route(),
|
|
||||||
ActiveSonarrBlock::EditSeriesPrompt.into()
|
|
||||||
);
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
@@ -858,14 +859,11 @@ mod tests {
|
|||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveSonarrBlock::EditSeriesPrompt,
|
ActiveSonarrBlock::EditSeriesPrompt,
|
||||||
None,
|
Some(ActiveSonarrBlock::Series),
|
||||||
)
|
)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(app.get_current_route(), current_route);
|
||||||
app.get_current_route(),
|
|
||||||
ActiveSonarrBlock::EditSeriesPrompt.into()
|
|
||||||
);
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
@@ -880,25 +878,26 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_series_toggle_use_season_folders_submit() {
|
fn test_edit_series_toggle_use_season_folders_submit() {
|
||||||
|
let current_route = Route::from((
|
||||||
|
ActiveSonarrBlock::EditSeriesPrompt,
|
||||||
|
Some(ActiveSonarrBlock::Series),
|
||||||
|
));
|
||||||
let mut app = App::default();
|
let mut app = App::default();
|
||||||
app.data.sonarr_data.edit_series_modal = Some(EditSeriesModal::default());
|
app.data.sonarr_data.edit_series_modal = Some(EditSeriesModal::default());
|
||||||
app.data.sonarr_data.selected_block = BlockSelectionState::new(EDIT_SERIES_SELECTION_BLOCKS);
|
app.data.sonarr_data.selected_block = BlockSelectionState::new(EDIT_SERIES_SELECTION_BLOCKS);
|
||||||
app.data.sonarr_data.selected_block.set_index(0, 1);
|
app.data.sonarr_data.selected_block.set_index(0, 1);
|
||||||
app.push_navigation_stack(ActiveSonarrBlock::Series.into());
|
app.push_navigation_stack(ActiveSonarrBlock::Series.into());
|
||||||
app.push_navigation_stack(ActiveSonarrBlock::EditSeriesPrompt.into());
|
app.push_navigation_stack(current_route);
|
||||||
|
|
||||||
EditSeriesHandler::with(
|
EditSeriesHandler::with(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveSonarrBlock::EditSeriesPrompt,
|
ActiveSonarrBlock::EditSeriesPrompt,
|
||||||
None,
|
Some(ActiveSonarrBlock::Series),
|
||||||
)
|
)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(app.get_current_route(), current_route);
|
||||||
app.get_current_route(),
|
|
||||||
ActiveSonarrBlock::EditSeriesPrompt.into()
|
|
||||||
);
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
@@ -914,14 +913,11 @@ mod tests {
|
|||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveSonarrBlock::EditSeriesPrompt,
|
ActiveSonarrBlock::EditSeriesPrompt,
|
||||||
None,
|
Some(ActiveSonarrBlock::Series),
|
||||||
)
|
)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(app.get_current_route(), current_route);
|
||||||
app.get_current_route(),
|
|
||||||
ActiveSonarrBlock::EditSeriesPrompt.into()
|
|
||||||
);
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
@@ -947,7 +943,13 @@ mod tests {
|
|||||||
let mut app = App::default();
|
let mut app = App::default();
|
||||||
app.data.sonarr_data.edit_series_modal = Some(EditSeriesModal::default());
|
app.data.sonarr_data.edit_series_modal = Some(EditSeriesModal::default());
|
||||||
app.push_navigation_stack(ActiveSonarrBlock::Series.into());
|
app.push_navigation_stack(ActiveSonarrBlock::Series.into());
|
||||||
app.push_navigation_stack(ActiveSonarrBlock::EditSeriesPrompt.into());
|
app.push_navigation_stack(
|
||||||
|
(
|
||||||
|
ActiveSonarrBlock::EditSeriesPrompt,
|
||||||
|
Some(ActiveSonarrBlock::Series),
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
|
);
|
||||||
app.data.sonarr_data.selected_block = BlockSelectionState::new(EDIT_SERIES_SELECTION_BLOCKS);
|
app.data.sonarr_data.selected_block = BlockSelectionState::new(EDIT_SERIES_SELECTION_BLOCKS);
|
||||||
app.data.sonarr_data.selected_block.set_index(0, y_index);
|
app.data.sonarr_data.selected_block.set_index(0, y_index);
|
||||||
|
|
||||||
@@ -959,7 +961,10 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert_eq!(app.get_current_route(), selected_block.into());
|
assert_eq!(
|
||||||
|
app.get_current_route(),
|
||||||
|
(selected_block, Some(ActiveSonarrBlock::Series)).into()
|
||||||
|
);
|
||||||
assert_eq!(app.data.sonarr_data.prompt_confirm_action, None);
|
assert_eq!(app.data.sonarr_data.prompt_confirm_action, None);
|
||||||
|
|
||||||
if selected_block == ActiveSonarrBlock::EditSeriesPathInput
|
if selected_block == ActiveSonarrBlock::EditSeriesPathInput
|
||||||
@@ -977,7 +982,13 @@ mod tests {
|
|||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
app.data.sonarr_data.edit_series_modal = Some(EditSeriesModal::default());
|
app.data.sonarr_data.edit_series_modal = Some(EditSeriesModal::default());
|
||||||
app.push_navigation_stack(ActiveSonarrBlock::Series.into());
|
app.push_navigation_stack(ActiveSonarrBlock::Series.into());
|
||||||
app.push_navigation_stack(ActiveSonarrBlock::EditSeriesPrompt.into());
|
app.push_navigation_stack(
|
||||||
|
(
|
||||||
|
ActiveSonarrBlock::EditSeriesPrompt,
|
||||||
|
Some(ActiveSonarrBlock::Series),
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
|
);
|
||||||
app.data.sonarr_data.selected_block = BlockSelectionState::new(EDIT_SERIES_SELECTION_BLOCKS);
|
app.data.sonarr_data.selected_block = BlockSelectionState::new(EDIT_SERIES_SELECTION_BLOCKS);
|
||||||
app.data.sonarr_data.selected_block.set_index(0, y_index);
|
app.data.sonarr_data.selected_block.set_index(0, y_index);
|
||||||
|
|
||||||
@@ -985,13 +996,17 @@ mod tests {
|
|||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveSonarrBlock::EditSeriesPrompt,
|
ActiveSonarrBlock::EditSeriesPrompt,
|
||||||
None,
|
Some(ActiveSonarrBlock::Series),
|
||||||
)
|
)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app.get_current_route(),
|
app.get_current_route(),
|
||||||
ActiveSonarrBlock::EditSeriesPrompt.into()
|
(
|
||||||
|
ActiveSonarrBlock::EditSeriesPrompt,
|
||||||
|
Some(ActiveSonarrBlock::Series),
|
||||||
|
)
|
||||||
|
.into()
|
||||||
);
|
);
|
||||||
assert_eq!(app.data.sonarr_data.prompt_confirm_action, None);
|
assert_eq!(app.data.sonarr_data.prompt_confirm_action, None);
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.should_ignore_quit_key);
|
||||||
@@ -1014,7 +1029,13 @@ mod tests {
|
|||||||
app.push_navigation_stack(ActiveSonarrBlock::EditSeriesPrompt.into());
|
app.push_navigation_stack(ActiveSonarrBlock::EditSeriesPrompt.into());
|
||||||
app.push_navigation_stack(active_sonarr_block.into());
|
app.push_navigation_stack(active_sonarr_block.into());
|
||||||
|
|
||||||
EditSeriesHandler::with(SUBMIT_KEY, &mut app, active_sonarr_block, None).handle();
|
EditSeriesHandler::with(
|
||||||
|
SUBMIT_KEY,
|
||||||
|
&mut app,
|
||||||
|
active_sonarr_block,
|
||||||
|
Some(ActiveSonarrBlock::Series),
|
||||||
|
)
|
||||||
|
.handle();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app.get_current_route(),
|
app.get_current_route(),
|
||||||
|
|||||||
@@ -324,7 +324,7 @@ fn draw_confirmation_prompt(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
|||||||
|
|
||||||
let [paragraph_area, root_folder_area, monitor_area, quality_profile_area, language_profile_area, series_type_area, season_folder_area, tags_area, _, buttons_area, help_area] =
|
let [paragraph_area, root_folder_area, monitor_area, quality_profile_area, language_profile_area, series_type_area, season_folder_area, tags_area, _, buttons_area, help_area] =
|
||||||
Layout::vertical([
|
Layout::vertical([
|
||||||
Constraint::Length(7),
|
Constraint::Length(6),
|
||||||
Constraint::Length(3),
|
Constraint::Length(3),
|
||||||
Constraint::Length(3),
|
Constraint::Length(3),
|
||||||
Constraint::Length(3),
|
Constraint::Length(3),
|
||||||
|
|||||||
@@ -0,0 +1,256 @@
|
|||||||
|
use std::sync::atomic::Ordering;
|
||||||
|
|
||||||
|
use ratatui::layout::{Constraint, Rect};
|
||||||
|
use ratatui::prelude::Layout;
|
||||||
|
use ratatui::text::Text;
|
||||||
|
use ratatui::widgets::{ListItem, Paragraph};
|
||||||
|
use ratatui::Frame;
|
||||||
|
|
||||||
|
use crate::app::context_clues::{build_context_clue_string, CONFIRMATION_PROMPT_CONTEXT_CLUES};
|
||||||
|
use crate::app::App;
|
||||||
|
use crate::models::servarr_data::sonarr::modals::EditSeriesModal;
|
||||||
|
use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, EDIT_SERIES_BLOCKS};
|
||||||
|
use crate::models::{EnumDisplayStyle, Route};
|
||||||
|
use crate::render_selectable_input_box;
|
||||||
|
use crate::ui::sonarr_ui::library::draw_library;
|
||||||
|
|
||||||
|
use crate::ui::styles::ManagarrStyle;
|
||||||
|
use crate::ui::utils::{layout_paragraph_borderless, title_block_centered};
|
||||||
|
use crate::ui::widgets::button::Button;
|
||||||
|
use crate::ui::widgets::checkbox::Checkbox;
|
||||||
|
use crate::ui::widgets::input_box::InputBox;
|
||||||
|
use crate::ui::widgets::popup::{Popup, Size};
|
||||||
|
use crate::ui::widgets::selectable_list::SelectableList;
|
||||||
|
use crate::ui::{draw_popup_over, DrawUi};
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[path = "edit_series_ui_tests.rs"]
|
||||||
|
mod edit_series_ui_tests;
|
||||||
|
|
||||||
|
pub(super) struct EditSeriesUi;
|
||||||
|
|
||||||
|
impl DrawUi for EditSeriesUi {
|
||||||
|
fn accepts(route: Route) -> bool {
|
||||||
|
if let Route::Sonarr(active_sonarr_block, _) = route {
|
||||||
|
return EDIT_SERIES_BLOCKS.contains(&active_sonarr_block);
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
||||||
|
if let Route::Sonarr(active_sonarr_block, context_option) = app.get_current_route() {
|
||||||
|
let draw_edit_series_prompt =
|
||||||
|
|f: &mut Frame<'_>, app: &mut App<'_>, prompt_area: Rect| match active_sonarr_block {
|
||||||
|
ActiveSonarrBlock::EditSeriesSelectSeriesType => {
|
||||||
|
draw_edit_series_confirmation_prompt(f, app, prompt_area);
|
||||||
|
draw_edit_series_select_series_type_popup(f, app);
|
||||||
|
}
|
||||||
|
ActiveSonarrBlock::EditSeriesSelectQualityProfile => {
|
||||||
|
draw_edit_series_confirmation_prompt(f, app, prompt_area);
|
||||||
|
draw_edit_series_select_quality_profile_popup(f, app);
|
||||||
|
}
|
||||||
|
ActiveSonarrBlock::EditSeriesSelectLanguageProfile => {
|
||||||
|
draw_edit_series_confirmation_prompt(f, app, prompt_area);
|
||||||
|
draw_edit_series_select_language_profile_popup(f, app);
|
||||||
|
}
|
||||||
|
ActiveSonarrBlock::EditSeriesPrompt
|
||||||
|
| ActiveSonarrBlock::EditSeriesToggleMonitored
|
||||||
|
| ActiveSonarrBlock::EditSeriesToggleSeasonFolder
|
||||||
|
| ActiveSonarrBlock::EditSeriesPathInput
|
||||||
|
| ActiveSonarrBlock::EditSeriesTagsInput => {
|
||||||
|
draw_edit_series_confirmation_prompt(f, app, prompt_area)
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(context) = context_option {
|
||||||
|
match context {
|
||||||
|
ActiveSonarrBlock::Series => {
|
||||||
|
draw_popup_over(
|
||||||
|
f,
|
||||||
|
app,
|
||||||
|
area,
|
||||||
|
draw_library,
|
||||||
|
draw_edit_series_prompt,
|
||||||
|
Size::Long,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// _ if SERIES_DETAILS_BLOCKS.contains(&context) => {
|
||||||
|
// draw_popup_over_ui::<SeriesDetailsUi>(f, app, area, draw_library, Size::Large);
|
||||||
|
// draw_popup(f, app, draw_edit_series_prompt, Size::Medium);
|
||||||
|
// }
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_edit_series_confirmation_prompt(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
||||||
|
let series_title = app
|
||||||
|
.data
|
||||||
|
.sonarr_data
|
||||||
|
.series
|
||||||
|
.current_selection()
|
||||||
|
.title
|
||||||
|
.text
|
||||||
|
.clone();
|
||||||
|
let series_overview = app
|
||||||
|
.data
|
||||||
|
.sonarr_data
|
||||||
|
.series
|
||||||
|
.current_selection()
|
||||||
|
.overview
|
||||||
|
.clone()
|
||||||
|
.unwrap_or_default();
|
||||||
|
let title = format!("Edit - {series_title}");
|
||||||
|
let yes_no_value = app.data.sonarr_data.prompt_confirm;
|
||||||
|
let selected_block = app.data.sonarr_data.selected_block.get_active_block();
|
||||||
|
let highlight_yes_no = selected_block == ActiveSonarrBlock::EditSeriesConfirmPrompt;
|
||||||
|
let EditSeriesModal {
|
||||||
|
series_type_list,
|
||||||
|
quality_profile_list,
|
||||||
|
language_profile_list,
|
||||||
|
monitored,
|
||||||
|
use_season_folders,
|
||||||
|
path,
|
||||||
|
tags,
|
||||||
|
} = app.data.sonarr_data.edit_series_modal.as_ref().unwrap();
|
||||||
|
let selected_series_type = series_type_list.current_selection();
|
||||||
|
let selected_quality_profile = quality_profile_list.current_selection();
|
||||||
|
let selected_language_profile = language_profile_list.current_selection();
|
||||||
|
|
||||||
|
let [paragraph_area, monitored_area, season_folder_area, quality_profile_area, language_profile_area, series_type_area, path_area, tags_area, _, buttons_area, help_area] =
|
||||||
|
Layout::vertical([
|
||||||
|
Constraint::Length(6),
|
||||||
|
Constraint::Length(3),
|
||||||
|
Constraint::Length(3),
|
||||||
|
Constraint::Length(3),
|
||||||
|
Constraint::Length(3),
|
||||||
|
Constraint::Length(3),
|
||||||
|
Constraint::Length(3),
|
||||||
|
Constraint::Length(3),
|
||||||
|
Constraint::Fill(1),
|
||||||
|
Constraint::Length(3),
|
||||||
|
Constraint::Length(1),
|
||||||
|
])
|
||||||
|
.margin(1)
|
||||||
|
.areas(area);
|
||||||
|
let [save_area, cancel_area] =
|
||||||
|
Layout::horizontal([Constraint::Percentage(50), Constraint::Percentage(50)])
|
||||||
|
.areas(buttons_area);
|
||||||
|
|
||||||
|
let help_text = Text::from(build_context_clue_string(&CONFIRMATION_PROMPT_CONTEXT_CLUES).help());
|
||||||
|
let help_paragraph = Paragraph::new(help_text).centered();
|
||||||
|
let prompt_paragraph = layout_paragraph_borderless(&series_overview);
|
||||||
|
let monitored_checkbox = Checkbox::new("Monitored")
|
||||||
|
.checked(monitored.unwrap_or_default())
|
||||||
|
.highlighted(selected_block == ActiveSonarrBlock::EditSeriesToggleMonitored);
|
||||||
|
let season_folder_checkbox = Checkbox::new("Season Folder")
|
||||||
|
.checked(use_season_folders.unwrap_or_default())
|
||||||
|
.highlighted(selected_block == ActiveSonarrBlock::EditSeriesToggleSeasonFolder);
|
||||||
|
let series_type_drop_down_button = Button::new()
|
||||||
|
.title(selected_series_type.to_display_str())
|
||||||
|
.label("Series Type")
|
||||||
|
.icon("▼")
|
||||||
|
.selected(selected_block == ActiveSonarrBlock::EditSeriesSelectSeriesType);
|
||||||
|
let quality_profile_drop_down_button = Button::new()
|
||||||
|
.title(selected_quality_profile)
|
||||||
|
.label("Quality Profile")
|
||||||
|
.icon("▼")
|
||||||
|
.selected(selected_block == ActiveSonarrBlock::EditSeriesSelectQualityProfile);
|
||||||
|
let language_profile_drop_down_button = Button::new()
|
||||||
|
.title(selected_language_profile)
|
||||||
|
.label("Language Profile")
|
||||||
|
.icon("▼")
|
||||||
|
.selected(selected_block == ActiveSonarrBlock::EditSeriesSelectLanguageProfile);
|
||||||
|
|
||||||
|
if let Route::Sonarr(active_sonarr_block, _) = app.get_current_route() {
|
||||||
|
let path_input_box = InputBox::new(&path.text)
|
||||||
|
.offset(path.offset.load(Ordering::SeqCst))
|
||||||
|
.label("Path")
|
||||||
|
.highlighted(selected_block == ActiveSonarrBlock::EditSeriesPathInput)
|
||||||
|
.selected(active_sonarr_block == ActiveSonarrBlock::EditSeriesPathInput);
|
||||||
|
let tags_input_box = InputBox::new(&tags.text)
|
||||||
|
.offset(tags.offset.load(Ordering::SeqCst))
|
||||||
|
.label("Tags")
|
||||||
|
.highlighted(selected_block == ActiveSonarrBlock::EditSeriesTagsInput)
|
||||||
|
.selected(active_sonarr_block == ActiveSonarrBlock::EditSeriesTagsInput);
|
||||||
|
|
||||||
|
match active_sonarr_block {
|
||||||
|
ActiveSonarrBlock::EditSeriesPathInput => path_input_box.show_cursor(f, path_area),
|
||||||
|
ActiveSonarrBlock::EditSeriesTagsInput => tags_input_box.show_cursor(f, tags_area),
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
|
||||||
|
render_selectable_input_box!(path_input_box, f, path_area);
|
||||||
|
render_selectable_input_box!(tags_input_box, f, tags_area);
|
||||||
|
}
|
||||||
|
|
||||||
|
let save_button = Button::new()
|
||||||
|
.title("Save")
|
||||||
|
.selected(yes_no_value && highlight_yes_no);
|
||||||
|
let cancel_button = Button::new()
|
||||||
|
.title("Cancel")
|
||||||
|
.selected(!yes_no_value && highlight_yes_no);
|
||||||
|
|
||||||
|
f.render_widget(title_block_centered(&title), area);
|
||||||
|
f.render_widget(prompt_paragraph, paragraph_area);
|
||||||
|
f.render_widget(monitored_checkbox, monitored_area);
|
||||||
|
f.render_widget(season_folder_checkbox, season_folder_area);
|
||||||
|
f.render_widget(quality_profile_drop_down_button, quality_profile_area);
|
||||||
|
f.render_widget(language_profile_drop_down_button, language_profile_area);
|
||||||
|
f.render_widget(series_type_drop_down_button, series_type_area);
|
||||||
|
f.render_widget(save_button, save_area);
|
||||||
|
f.render_widget(cancel_button, cancel_area);
|
||||||
|
f.render_widget(help_paragraph, help_area);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_edit_series_select_series_type_popup(f: &mut Frame<'_>, app: &mut App<'_>) {
|
||||||
|
let series_type_list = SelectableList::new(
|
||||||
|
&mut app
|
||||||
|
.data
|
||||||
|
.sonarr_data
|
||||||
|
.edit_series_modal
|
||||||
|
.as_mut()
|
||||||
|
.unwrap()
|
||||||
|
.series_type_list,
|
||||||
|
|series_type| ListItem::new(series_type.to_display_str().to_owned()),
|
||||||
|
);
|
||||||
|
let popup = Popup::new(series_type_list).size(Size::Dropdown);
|
||||||
|
|
||||||
|
f.render_widget(popup, f.area());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_edit_series_select_quality_profile_popup(f: &mut Frame<'_>, app: &mut App<'_>) {
|
||||||
|
let quality_profile_list = SelectableList::new(
|
||||||
|
&mut app
|
||||||
|
.data
|
||||||
|
.sonarr_data
|
||||||
|
.edit_series_modal
|
||||||
|
.as_mut()
|
||||||
|
.unwrap()
|
||||||
|
.quality_profile_list,
|
||||||
|
|quality_profile| ListItem::new(quality_profile.clone()),
|
||||||
|
);
|
||||||
|
let popup = Popup::new(quality_profile_list).size(Size::Dropdown);
|
||||||
|
|
||||||
|
f.render_widget(popup, f.area());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_edit_series_select_language_profile_popup(f: &mut Frame<'_>, app: &mut App<'_>) {
|
||||||
|
let language_profile_list = SelectableList::new(
|
||||||
|
&mut app
|
||||||
|
.data
|
||||||
|
.sonarr_data
|
||||||
|
.edit_series_modal
|
||||||
|
.as_mut()
|
||||||
|
.unwrap()
|
||||||
|
.language_profile_list,
|
||||||
|
|language_profile| ListItem::new(language_profile.clone()),
|
||||||
|
);
|
||||||
|
let popup = Popup::new(language_profile_list).size(Size::Dropdown);
|
||||||
|
|
||||||
|
f.render_widget(popup, f.area());
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
|
use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, EDIT_SERIES_BLOCKS};
|
||||||
|
use crate::ui::sonarr_ui::library::edit_series_ui::EditSeriesUi;
|
||||||
|
use crate::ui::DrawUi;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_edit_movie_ui_accepts() {
|
||||||
|
ActiveSonarrBlock::iter().for_each(|active_sonarr_block| {
|
||||||
|
if EDIT_SERIES_BLOCKS.contains(&active_sonarr_block) {
|
||||||
|
assert!(EditSeriesUi::accepts(active_sonarr_block.into()));
|
||||||
|
} else {
|
||||||
|
assert!(!EditSeriesUi::accepts(active_sonarr_block.into()));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::models::servarr_data::sonarr::sonarr_data::{
|
use crate::models::servarr_data::sonarr::sonarr_data::{
|
||||||
ActiveSonarrBlock, ADD_SERIES_BLOCKS, DELETE_SERIES_BLOCKS,
|
ActiveSonarrBlock, ADD_SERIES_BLOCKS, DELETE_SERIES_BLOCKS, EDIT_SERIES_BLOCKS,
|
||||||
};
|
};
|
||||||
use crate::models::{
|
use crate::models::{
|
||||||
servarr_data::sonarr::sonarr_data::LIBRARY_BLOCKS, sonarr_models::SeriesStatus,
|
servarr_data::sonarr::sonarr_data::LIBRARY_BLOCKS, sonarr_models::SeriesStatus,
|
||||||
@@ -25,6 +25,7 @@ mod tests {
|
|||||||
library_ui_blocks.extend(LIBRARY_BLOCKS);
|
library_ui_blocks.extend(LIBRARY_BLOCKS);
|
||||||
library_ui_blocks.extend(ADD_SERIES_BLOCKS);
|
library_ui_blocks.extend(ADD_SERIES_BLOCKS);
|
||||||
library_ui_blocks.extend(DELETE_SERIES_BLOCKS);
|
library_ui_blocks.extend(DELETE_SERIES_BLOCKS);
|
||||||
|
library_ui_blocks.extend(EDIT_SERIES_BLOCKS);
|
||||||
|
|
||||||
ActiveSonarrBlock::iter().for_each(|active_radarr_block| {
|
ActiveSonarrBlock::iter().for_each(|active_radarr_block| {
|
||||||
if library_ui_blocks.contains(&active_radarr_block) {
|
if library_ui_blocks.contains(&active_radarr_block) {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
use add_series_ui::AddSeriesUi;
|
use add_series_ui::AddSeriesUi;
|
||||||
use delete_series_ui::DeleteSeriesUi;
|
use delete_series_ui::DeleteSeriesUi;
|
||||||
|
use edit_series_ui::EditSeriesUi;
|
||||||
use ratatui::{
|
use ratatui::{
|
||||||
layout::{Constraint, Rect},
|
layout::{Constraint, Rect},
|
||||||
widgets::{Cell, Row},
|
widgets::{Cell, Row},
|
||||||
@@ -29,6 +30,7 @@ use crate::{
|
|||||||
|
|
||||||
mod add_series_ui;
|
mod add_series_ui;
|
||||||
mod delete_series_ui;
|
mod delete_series_ui;
|
||||||
|
mod edit_series_ui;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[path = "library_ui_tests.rs"]
|
#[path = "library_ui_tests.rs"]
|
||||||
@@ -41,6 +43,7 @@ impl DrawUi for LibraryUi {
|
|||||||
if let Route::Sonarr(active_sonarr_block, _) = route {
|
if let Route::Sonarr(active_sonarr_block, _) = route {
|
||||||
return AddSeriesUi::accepts(route)
|
return AddSeriesUi::accepts(route)
|
||||||
|| DeleteSeriesUi::accepts(route)
|
|| DeleteSeriesUi::accepts(route)
|
||||||
|
|| EditSeriesUi::accepts(route)
|
||||||
|| LIBRARY_BLOCKS.contains(&active_sonarr_block);
|
|| LIBRARY_BLOCKS.contains(&active_sonarr_block);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,6 +99,7 @@ impl DrawUi for LibraryUi {
|
|||||||
match route {
|
match route {
|
||||||
_ if AddSeriesUi::accepts(route) => AddSeriesUi::draw(f, app, area),
|
_ if AddSeriesUi::accepts(route) => AddSeriesUi::draw(f, app, area),
|
||||||
_ if DeleteSeriesUi::accepts(route) => DeleteSeriesUi::draw(f, app, area),
|
_ if DeleteSeriesUi::accepts(route) => DeleteSeriesUi::draw(f, app, area),
|
||||||
|
_ if EditSeriesUi::accepts(route) => EditSeriesUi::draw(f, app, area),
|
||||||
Route::Sonarr(active_sonarr_block, _) if LIBRARY_BLOCKS.contains(&active_sonarr_block) => {
|
Route::Sonarr(active_sonarr_block, _) if LIBRARY_BLOCKS.contains(&active_sonarr_block) => {
|
||||||
series_ui_matchers(active_sonarr_block)
|
series_ui_matchers(active_sonarr_block)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ impl Size {
|
|||||||
Size::Small => (40, 40),
|
Size::Small => (40, 40),
|
||||||
Size::Medium => (60, 60),
|
Size::Medium => (60, 60),
|
||||||
Size::Large => (75, 75),
|
Size::Large => (75, 75),
|
||||||
Size::Long => (65, 80),
|
Size::Long => (65, 75),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ mod tests {
|
|||||||
assert_eq!(Size::Small.to_percent(), (40, 40));
|
assert_eq!(Size::Small.to_percent(), (40, 40));
|
||||||
assert_eq!(Size::Medium.to_percent(), (60, 60));
|
assert_eq!(Size::Medium.to_percent(), (60, 60));
|
||||||
assert_eq!(Size::Large.to_percent(), (75, 75));
|
assert_eq!(Size::Large.to_percent(), (75, 75));
|
||||||
assert_eq!(Size::Long.to_percent(), (65, 80));
|
assert_eq!(Size::Long.to_percent(), (65, 75));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
Reference in New Issue
Block a user