This commit is contained in:
2025-10-13 14:49:37 +02:00
parent 159577dff9
commit 9060905e7a
3 changed files with 79 additions and 56 deletions
+62 -36
View File
@@ -77,6 +77,20 @@ impl From<Tag> for TagResponse {
}
}
#[derive(Serialize, Clone, Default)]
pub struct DocumentAssetGroupResponse {
#[serde(skip_serializing_if = "Option::is_none")]
pub thumbnail: Option<DocumentAssetResponse>,
#[serde(skip_serializing_if = "Option::is_none")]
pub preview: Option<DocumentAssetResponse>,
}
impl DocumentAssetGroupResponse {
pub fn is_empty(&self) -> bool {
self.thumbnail.is_none() && self.preview.is_none()
}
}
#[derive(Serialize)]
pub struct DocumentResponse {
pub id: Uuid,
@@ -92,8 +106,8 @@ pub struct DocumentResponse {
pub issued_at: Option<String>,
pub metadata: Value,
pub tags: Vec<TagResponse>,
pub thumbnail: Option<DocumentAssetResponse>,
pub preview: Option<DocumentAssetResponse>,
#[serde(default, skip_serializing_if = "DocumentAssetGroupResponse::is_empty")]
pub assets: DocumentAssetGroupResponse,
pub download_path: String,
}
@@ -119,11 +133,7 @@ pub struct DocumentAssetResponse {
pub created_at: String,
}
#[derive(Clone, Default)]
pub struct PrimaryDocumentAssets {
pub thumbnail: Option<DocumentAssetResponse>,
pub preview: Option<DocumentAssetResponse>,
}
type PrimaryDocumentAssets = DocumentAssetGroupResponse;
#[derive(Serialize)]
pub struct DocumentDetailResponse {
@@ -251,18 +261,13 @@ pub async fn list_documents(
let mut response = Vec::with_capacity(doc_ids.len());
for doc in docs {
let tags = tags_map.get(&doc.id).cloned();
let (thumbnail, preview) = if let Some(assets) = primary_assets.get(&doc.id) {
(assets.thumbnail.clone(), assets.preview.clone())
} else {
(None, None)
};
let assets = primary_assets.get(&doc.id).cloned();
response.push(to_document_response(
&state,
user.user_id,
doc,
tags,
thumbnail,
preview,
assets,
)?);
}
@@ -291,14 +296,21 @@ pub async fn get_document(
drop(conn);
let assets = load_asset_responses(&state, version_id).await?;
let thumbnail = assets
let mut grouped_assets = DocumentAssetGroupResponse::default();
if let Some(asset) = assets
.iter()
.find(|asset| asset.asset_type == "thumbnail")
.cloned();
let preview = assets
.cloned()
{
grouped_assets.thumbnail = Some(asset);
}
if let Some(asset) = assets
.iter()
.find(|asset| asset.asset_type == "preview")
.cloned();
.cloned()
{
grouped_assets.preview = Some(asset);
}
Ok(Json(DocumentDetailResponse {
document: to_document_response(
@@ -306,8 +318,7 @@ pub async fn get_document(
user.user_id,
doc,
tags_map.get(&document_id).cloned(),
thumbnail,
preview,
Some(grouped_assets),
)?,
current_version: to_version_response(current_version),
assets,
@@ -695,14 +706,21 @@ pub async fn update_document(
drop(conn);
let assets = load_asset_responses(&state, version_id).await?;
let thumbnail = assets
let mut grouped_assets = DocumentAssetGroupResponse::default();
if let Some(asset) = assets
.iter()
.find(|asset| asset.asset_type == "thumbnail")
.cloned();
let preview = assets
.cloned()
{
grouped_assets.thumbnail = Some(asset);
}
if let Some(asset) = assets
.iter()
.find(|asset| asset.asset_type == "preview")
.cloned();
.cloned()
{
grouped_assets.preview = Some(asset);
}
Ok(Json(DocumentDetailResponse {
document: to_document_response(
@@ -710,8 +728,7 @@ pub async fn update_document(
user.user_id,
document,
tags_map.get(&document_id).cloned(),
thumbnail,
preview,
Some(grouped_assets),
)?,
current_version: to_version_response(current_version),
assets,
@@ -991,14 +1008,21 @@ async fn process_upload(
let tags = tags_map.get(&document.id).cloned();
drop(conn);
let assets = load_asset_responses(state, version.id).await?;
let thumbnail = assets
let mut grouped_assets = DocumentAssetGroupResponse::default();
if let Some(asset) = assets
.iter()
.find(|asset| asset.asset_type == "thumbnail")
.cloned();
let preview = assets
.cloned()
{
grouped_assets.thumbnail = Some(asset);
}
if let Some(asset) = assets
.iter()
.find(|asset| asset.asset_type == "preview")
.cloned();
.cloned()
{
grouped_assets.preview = Some(asset);
}
info!(
document_id = %document.id,
@@ -1009,7 +1033,11 @@ async fn process_upload(
return Ok(UploadOutcome {
detail: DocumentDetailResponse {
document: to_document_response(
state, user_id, document, tags, thumbnail, preview,
state,
user_id,
document,
tags,
Some(grouped_assets),
)?,
current_version: to_version_response(version),
assets,
@@ -1081,7 +1109,7 @@ async fn process_upload(
};
let detail = DocumentDetailResponse {
document: to_document_response(state, user_id, document, None, None, None)?,
document: to_document_response(state, user_id, document, None, None)?,
current_version: to_version_response(version.clone()),
assets: Vec::new(),
};
@@ -1255,8 +1283,7 @@ pub(crate) fn to_document_response(
user_id: Uuid,
doc: Document,
tags: Option<Vec<Tag>>,
thumbnail: Option<DocumentAssetResponse>,
preview: Option<DocumentAssetResponse>,
assets: Option<DocumentAssetGroupResponse>,
) -> AppResult<DocumentResponse> {
let download_path = build_download_path(state, doc.id, user_id)?;
@@ -1278,8 +1305,7 @@ pub(crate) fn to_document_response(
.into_iter()
.map(TagResponse::from)
.collect(),
thumbnail,
preview,
assets: assets.unwrap_or_default(),
download_path,
})
}
+4 -14
View File
@@ -220,18 +220,13 @@ pub async fn list_folder_contents(
let mut documents = Vec::with_capacity(doc_ids.len());
for doc in docs {
let tags = tags_map.get(&doc.id).cloned();
let (thumbnail, preview) = if let Some(assets) = primary_assets.get(&doc.id) {
(assets.thumbnail.clone(), assets.preview.clone())
} else {
(None, None)
};
let assets = primary_assets.get(&doc.id).cloned();
documents.push(to_document_response(
&state,
user.user_id,
doc,
tags,
thumbnail,
preview,
assets,
)?);
}
@@ -408,18 +403,13 @@ pub async fn search_documents(
let mut response = Vec::with_capacity(doc_ids.len());
for doc in docs {
let tags = tags_map.get(&doc.id).cloned();
let (thumbnail, preview) = if let Some(assets) = primary_assets.get(&doc.id) {
(assets.thumbnail.clone(), assets.preview.clone())
} else {
(None, None)
};
let assets = primary_assets.get(&doc.id).cloned();
response.push(to_document_response(
&state,
user.user_id,
doc,
tags,
thumbnail,
preview,
assets,
)?);
}
+13 -6
View File
@@ -731,6 +731,8 @@ const DocumentsTable = ({
rowClasses.push('dragging');
}
const thumbnailAsset = doc?.assets?.thumbnail || null;
return (
<tr
key={doc.id}
@@ -753,9 +755,9 @@ const DocumentsTable = ({
onDragEnd={onDocumentDragEnd}
>
<td className="thumb-cell">
{doc.thumbnail ? (
{thumbnailAsset ? (
<img
src={doc.thumbnail.url}
src={thumbnailAsset.url}
alt={`Thumbnail for ${doc.title || doc.original_name}`}
className="document-thumbnail"
/>
@@ -1029,11 +1031,16 @@ const DetailPanel = ({
const makePreviewItem = useCallback((doc, detailEntry, fallbackUrl = null) => {
if (!doc) return null;
const url = doc.thumbnail?.url || detailEntry?.document?.thumbnail?.url || fallbackUrl;
const detailDocument = detailEntry?.document || null;
const thumbnailAsset =
doc?.assets?.thumbnail ||
detailDocument?.assets?.thumbnail ||
detailEntry?.assets?.find((item) => item.asset_type === 'thumbnail') ||
null;
const url = thumbnailAsset?.url || fallbackUrl;
if (!url) return null;
const asset = detailEntry?.assets?.find((item) => item.asset_type === 'thumbnail');
const width = asset?.width || 0;
const height = asset?.height || 0;
const width = thumbnailAsset?.width || 0;
const height = thumbnailAsset?.height || 0;
const orientation = width > 0 && height > 0 ? (width >= height ? 'landscape' : 'portrait') : 'landscape';
return {
id: doc.id,