2
This commit is contained in:
@@ -12,7 +12,10 @@ use crate::models::{Document, Folder, NewFolder};
|
||||
use crate::schema::{document_tags, documents, folders};
|
||||
use crate::state::AppState;
|
||||
|
||||
use super::documents::{load_tags_for_documents, to_document_response, to_iso, DocumentResponse};
|
||||
use super::documents::{
|
||||
load_primary_thumbnails, load_tags_for_documents, to_document_response, to_iso,
|
||||
DocumentResponse,
|
||||
};
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct CreateFolderRequest {
|
||||
@@ -20,6 +23,12 @@ pub struct CreateFolderRequest {
|
||||
pub parent_id: Option<Uuid>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct EnsureFolderPathRequest {
|
||||
pub parent_id: Option<Uuid>,
|
||||
pub segments: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct FolderResponse {
|
||||
pub folder: FolderInfo,
|
||||
@@ -48,6 +57,70 @@ pub struct FolderInfo {
|
||||
pub updated_at: String,
|
||||
}
|
||||
|
||||
pub async fn ensure_folder_path(
|
||||
State(state): State<AppState>,
|
||||
Json(payload): Json<EnsureFolderPathRequest>,
|
||||
) -> AppResult<Json<FolderResponse>> {
|
||||
if payload.segments.is_empty() {
|
||||
return Err(AppError::bad_request("segments must not be empty"));
|
||||
}
|
||||
|
||||
let mut conn = state.db()?;
|
||||
|
||||
let target_folder = conn.transaction::<Folder, AppError, _>(|conn| {
|
||||
let mut current_parent = payload.parent_id;
|
||||
let mut last_folder: Option<Folder> = None;
|
||||
|
||||
for raw_name in &payload.segments {
|
||||
let name = raw_name.trim();
|
||||
if name.is_empty() {
|
||||
return Err(AppError::bad_request("folder names must not be empty"));
|
||||
}
|
||||
|
||||
let existing: Option<Folder> = if let Some(parent_id) = current_parent {
|
||||
folders::table
|
||||
.filter(folders::parent_id.eq(Some(parent_id)))
|
||||
.filter(folders::name.eq(name))
|
||||
.first(conn)
|
||||
.optional()?
|
||||
} else {
|
||||
folders::table
|
||||
.filter(folders::parent_id.is_null())
|
||||
.filter(folders::name.eq(name))
|
||||
.first(conn)
|
||||
.optional()?
|
||||
};
|
||||
|
||||
let folder = if let Some(folder) = existing {
|
||||
folder
|
||||
} else {
|
||||
let path_cache = build_path_cache(conn, current_parent, name)?;
|
||||
let new_folder = NewFolder {
|
||||
id: Uuid::new_v4(),
|
||||
name: name.to_string(),
|
||||
parent_id: current_parent,
|
||||
path_cache,
|
||||
};
|
||||
|
||||
diesel::insert_into(folders::table)
|
||||
.values(&new_folder)
|
||||
.execute(conn)?;
|
||||
|
||||
folders::table.find(new_folder.id).first(conn)?
|
||||
};
|
||||
|
||||
current_parent = Some(folder.id);
|
||||
last_folder = Some(folder);
|
||||
}
|
||||
|
||||
last_folder.ok_or_else(|| AppError::internal("failed to resolve folder path".to_string()))
|
||||
})?;
|
||||
|
||||
Ok(Json(FolderResponse {
|
||||
folder: folder_to_info(target_folder),
|
||||
}))
|
||||
}
|
||||
|
||||
pub async fn create_folder(
|
||||
State(state): State<AppState>,
|
||||
Json(payload): Json<CreateFolderRequest>,
|
||||
@@ -127,12 +200,16 @@ pub async fn list_folder_contents(
|
||||
|
||||
let doc_ids: Vec<Uuid> = docs.iter().map(|doc| doc.id).collect();
|
||||
let tags_map = load_tags_for_documents(&mut conn, &doc_ids)?;
|
||||
drop(conn);
|
||||
|
||||
let thumbnails = load_primary_thumbnails(&state, &docs).await?;
|
||||
|
||||
let documents = docs
|
||||
.into_iter()
|
||||
.map(|doc| {
|
||||
let tags = tags_map.get(&doc.id).cloned();
|
||||
to_document_response(doc, tags)
|
||||
let thumbnail = thumbnails.get(&doc.id).cloned();
|
||||
to_document_response(doc, tags, thumbnail)
|
||||
})
|
||||
.collect();
|
||||
|
||||
@@ -228,11 +305,15 @@ pub async fn search_documents(
|
||||
|
||||
let doc_ids: Vec<Uuid> = docs.iter().map(|doc| doc.id).collect();
|
||||
let tags_map = load_tags_for_documents(&mut conn, &doc_ids)?;
|
||||
drop(conn);
|
||||
|
||||
let thumbnails = load_primary_thumbnails(&state, &docs).await?;
|
||||
let response = docs
|
||||
.into_iter()
|
||||
.map(|doc| {
|
||||
let tags = tags_map.get(&doc.id).cloned();
|
||||
to_document_response(doc, tags)
|
||||
let thumbnail = thumbnails.get(&doc.id).cloned();
|
||||
to_document_response(doc, tags, thumbnail)
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user