From f9e798f3b30234886ec77196c0e6e9bc0b5a89fc Mon Sep 17 00:00:00 2001 From: Nils Schneider Date: Fri, 17 Oct 2025 18:01:07 +0200 Subject: [PATCH] include_documents for /contents --- backend/src/routes/folders.rs | 83 +++++++++++++++++++++-------------- backend/tests/folders_flow.rs | 14 ++++++ 2 files changed, 64 insertions(+), 33 deletions(-) diff --git a/backend/src/routes/folders.rs b/backend/src/routes/folders.rs index 3386f1f..d907d0b 100644 --- a/backend/src/routes/folders.rs +++ b/backend/src/routes/folders.rs @@ -1,5 +1,5 @@ use axum::{ - extract::{Json, Path, State}, + extract::{Json, Path, Query, State}, http::StatusCode, }; use diesel::{dsl::exists, prelude::*, PgConnection}; @@ -50,6 +50,16 @@ pub struct FolderContentsResponse { pub documents: Vec, } +#[derive(Deserialize)] +pub struct FolderContentsQuery { + #[serde(default = "default_include_documents")] + pub include_documents: bool, +} + +const fn default_include_documents() -> bool { + true +} + #[derive(Serialize)] pub struct FolderInfo { pub id: Uuid, @@ -150,6 +160,7 @@ pub async fn create_folder( pub async fn list_folder_contents( State(state): State, Path(folder_identifier): Path, + Query(query): Query, user: AuthenticatedUser, ) -> AppResult> { let mut conn = state.db()?; @@ -183,42 +194,48 @@ pub async fn list_folder_contents( }; let subfolders = child_folders.into_iter().map(folder_to_info).collect(); - let docs_query = documents::table - .filter(documents::deleted_at.is_null()) - .order(documents::uploaded_at.desc()); + let documents = if query.include_documents { + let docs_query = documents::table + .filter(documents::deleted_at.is_null()) + .order(documents::uploaded_at.desc()); - let docs: Vec = if let Some(current_folder) = folder_id { - docs_query - .filter(documents::folder_id.eq(current_folder)) - .load(&mut conn)? + let docs: Vec = if let Some(current_folder) = folder_id { + docs_query + .filter(documents::folder_id.eq(current_folder)) + .load(&mut conn)? + } else { + docs_query + .filter(documents::folder_id.is_null()) + .load(&mut conn)? + }; + + let doc_ids: Vec = docs.iter().map(|doc| doc.id).collect(); + let tags_map = load_tags_for_documents(&mut conn, &doc_ids)?; + let mut correspondents_map = load_correspondents_for_documents(&mut conn, &doc_ids)?; + drop(conn); + + let primary_versions = load_primary_assets(&state, &docs).await?; + + let mut documents = Vec::with_capacity(doc_ids.len()); + for doc in docs { + let tags = tags_map.get(&doc.id).cloned(); + let correspondents = correspondents_map.remove(&doc.id).unwrap_or_default(); + let current_version = primary_versions.get(&doc.id).cloned(); + documents.push(to_document_response( + &state, + user.user_id, + doc, + tags, + correspondents, + current_version, + )?); + } + + documents } else { - docs_query - .filter(documents::folder_id.is_null()) - .load(&mut conn)? + Vec::new() }; - let doc_ids: Vec = docs.iter().map(|doc| doc.id).collect(); - let tags_map = load_tags_for_documents(&mut conn, &doc_ids)?; - let mut correspondents_map = load_correspondents_for_documents(&mut conn, &doc_ids)?; - drop(conn); - - let primary_versions = load_primary_assets(&state, &docs).await?; - - let mut documents = Vec::with_capacity(doc_ids.len()); - for doc in docs { - let tags = tags_map.get(&doc.id).cloned(); - let correspondents = correspondents_map.remove(&doc.id).unwrap_or_default(); - let current_version = primary_versions.get(&doc.id).cloned(); - documents.push(to_document_response( - &state, - user.user_id, - doc, - tags, - correspondents, - current_version, - )?); - } - Ok(Json(FolderContentsResponse { folder, subfolders, diff --git a/backend/tests/folders_flow.rs b/backend/tests/folders_flow.rs index c9447cc..7a399a5 100644 --- a/backend/tests/folders_flow.rs +++ b/backend/tests/folders_flow.rs @@ -287,6 +287,20 @@ async fn folder_rename_updates_name_and_child_paths() -> Result<()> { .expect("renamed folder present"); assert_eq!(renamed.name, "Archive"); + let folders_only = app + .get( + &format!( + "/api/folders/{}/contents?include_documents=false", + parent.folder.id + ), + Some(&token), + ) + .await?; + assert_eq!(folders_only.status(), StatusCode::OK); + let folders_only_body = body_to_vec(folders_only.into_body()).await?; + let folders_only_contents: FolderContents = serde_json::from_slice(&folders_only_body)?; + assert!(folders_only_contents.documents.is_empty()); + let child_contents = app .get( &format!("/api/folders/{}/contents", child.folder.id),