From 5fa2a785c50132071d56ae60e8722a6f49f43cab Mon Sep 17 00:00:00 2001 From: angrynode Date: Mon, 23 Feb 2026 15:23:34 +0100 Subject: [PATCH 1/2] feat: Add CategoryRequest extractor --- src/extractors/category_request.rs | 53 ++++++++++++++++++++++++++++++ src/extractors/mod.rs | 1 + src/routes/category.rs | 51 +++++++++++++--------------- 3 files changed, 77 insertions(+), 28 deletions(-) create mode 100644 src/extractors/category_request.rs diff --git a/src/extractors/category_request.rs b/src/extractors/category_request.rs new file mode 100644 index 0000000..154417c --- /dev/null +++ b/src/extractors/category_request.rs @@ -0,0 +1,53 @@ +use axum::extract::{FromRequestParts, Path}; +use axum::http::request::Parts; +use snafu::prelude::*; + +use crate::database::category::{self, CategoryOperator}; +use crate::database::content_folder::PathBreadcrumb; +use crate::filesystem::FileSystemEntry; +use crate::state::{AppState, error::*}; + +#[derive(Clone, Debug)] +pub struct CategoryRequest { + pub category: category::Model, + pub breadcrumbs: Vec, + pub children: Vec, +} + +impl FromRequestParts for CategoryRequest { + type Rejection = AppStateError; + + async fn from_request_parts( + parts: &mut Parts, + app_state: &AppState, + ) -> Result { + let Path(category_name) = + as FromRequestParts>::from_request_parts(parts, app_state) + .await + .unwrap(); + + // Read-only operators: no need to extract the current user + let categories = CategoryOperator::new(app_state.clone(), None); + + let category = categories + .find_by_name(category_name.to_string()) + .await + .context(CategorySnafu)?; + + // get all content folders in this category + let content_folders = categories + .list_folders(category.id) + .await + .context(CategorySnafu)?; + + let children = FileSystemEntry::from_content_folders(&category, &content_folders); + + let breadcrumbs = PathBreadcrumb::for_filesystem_path(category.name.as_str()); + + Ok(Self { + category, + children, + breadcrumbs, + }) + } +} diff --git a/src/extractors/mod.rs b/src/extractors/mod.rs index 6537af5..a95eb77 100644 --- a/src/extractors/mod.rs +++ b/src/extractors/mod.rs @@ -1,3 +1,4 @@ +pub mod category_request; pub mod folder_request; pub mod normalized_path; pub mod torrent_list; diff --git a/src/routes/category.rs b/src/routes/category.rs index b36ff76..d9e8103 100644 --- a/src/routes/category.rs +++ b/src/routes/category.rs @@ -4,16 +4,16 @@ use axum::Form; use axum::extract::Path; use axum_extra::extract::CookieJar; use serde::{Deserialize, Serialize}; -use snafu::prelude::*; use crate::database::category; use crate::database::content_folder::PathBreadcrumb; +use crate::extractors::category_request::CategoryRequest; use crate::extractors::normalized_path::*; use crate::filesystem::FileSystemEntry; +use crate::state::AppStateContext; use crate::state::flash_message::{ FallibleTemplate, FlashRedirect, FlashTemplate, OperationStatus, StatusCookie, }; -use crate::state::{AppStateContext, error::*}; #[derive(Clone, Debug, Deserialize, Serialize)] pub struct CategoryForm { @@ -87,6 +87,24 @@ pub struct CategoryShowTemplate { pub breadcrumbs: Vec, } +impl CategoryShowTemplate { + fn new(context: AppStateContext, category: CategoryRequest) -> Self { + let CategoryRequest { + breadcrumbs, + category, + children, + } = category; + + Self { + breadcrumbs, + category, + children, + flash: None, + state: context, + } + } +} + impl FallibleTemplate for CategoryShowTemplate { fn with_optional_flash(&mut self, flash: Option) { self.flash = flash; @@ -95,31 +113,8 @@ impl FallibleTemplate for CategoryShowTemplate { pub async fn show( context: AppStateContext, - Path(category_name): Path, + category: CategoryRequest, status: StatusCookie, -) -> Result, AppStateError> { - let categories = context.db.category(); - - let category = categories - .find_by_name(category_name.to_string()) - .await - .context(CategorySnafu)?; - - // get all content folders in this category - let content_folders = categories - .list_folders(category.id) - .await - .context(CategorySnafu)?; - - let children = FileSystemEntry::from_content_folders(&category, &content_folders); - - let breadcrumbs = PathBreadcrumb::for_filesystem_path(category.name.as_str()); - - Ok(status.with_template(CategoryShowTemplate { - category, - children, - state: context, - flash: None, - breadcrumbs, - })) +) -> FlashTemplate { + status.with_template(CategoryShowTemplate::new(context, category)) } From dd2e78ee0facf4f4081b8feeffed676e8dab05bb Mon Sep 17 00:00:00 2001 From: angrynode Date: Mon, 23 Feb 2026 15:30:18 +0100 Subject: [PATCH 2/2] minor: ContentFolderShowTemplate constructor --- src/routes/content_folder.rs | 31 ++++++++++++++++++++--------- templates/content_folders/show.html | 4 ++-- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/routes/content_folder.rs b/src/routes/content_folder.rs index e52479d..7016a78 100644 --- a/src/routes/content_folder.rs +++ b/src/routes/content_folder.rs @@ -30,7 +30,7 @@ pub struct ContentFolderShowTemplate { /// Global application state pub state: AppStateContext, /// current folder - pub current_content_folder: content_folder::Model, + pub folder: content_folder::Model, /// Folders with parent_id set to current folder pub children: Vec, /// Category @@ -41,6 +41,26 @@ pub struct ContentFolderShowTemplate { pub flash: Option, } +impl ContentFolderShowTemplate { + fn new(context: AppStateContext, folder: FolderRequest) -> Self { + let FolderRequest { + breadcrumbs, + category, + children, + folder, + } = folder; + + Self { + breadcrumbs, + category, + children, + flash: None, + folder, + state: context, + } + } +} + impl FallibleTemplate for ContentFolderShowTemplate { fn with_optional_flash(&mut self, flash: Option) { self.flash = flash; @@ -52,14 +72,7 @@ pub async fn show( folder: FolderRequest, status: StatusCookie, ) -> FlashTemplate { - status.with_template(ContentFolderShowTemplate { - breadcrumbs: folder.breadcrumbs, - children: folder.children, - current_content_folder: folder.folder, - category: folder.category, - state: context, - flash: None, - }) + status.with_template(ContentFolderShowTemplate::new(context, folder)) } pub async fn create( diff --git a/templates/content_folders/show.html b/templates/content_folders/show.html index 280cfaa..56c9a17 100644 --- a/templates/content_folders/show.html +++ b/templates/content_folders/show.html @@ -1,7 +1,7 @@ {% extends "layouts/file_system_base.html" %} {% block folder_title %} - {{ current_content_folder.name }} + {{ folder.name }} {% endblock%} {% block actions_buttons %} @@ -22,7 +22,7 @@ - +