feat(client): show new file metadata fields on the client
This commit is contained in:
parent
db41b15609
commit
42bdda9476
|
|
@ -30,6 +30,7 @@ interface FileIntegrityDisplayProps {
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
userId?: string;
|
userId?: string;
|
||||||
|
username?: string;
|
||||||
compact?: boolean;
|
compact?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -41,6 +42,7 @@ const FileIntegrityDisplay: React.FC<FileIntegrityDisplayProps> = ({
|
||||||
createdAt,
|
createdAt,
|
||||||
updatedAt,
|
updatedAt,
|
||||||
userId,
|
userId,
|
||||||
|
username,
|
||||||
compact = false,
|
compact = false,
|
||||||
}) => {
|
}) => {
|
||||||
const [copied, setCopied] = useState(false);
|
const [copied, setCopied] = useState(false);
|
||||||
|
|
@ -328,7 +330,7 @@ const FileIntegrityDisplay: React.FC<FileIntegrityDisplayProps> = ({
|
||||||
Uploaded By
|
Uploaded By
|
||||||
</Typography>
|
</Typography>
|
||||||
<Chip
|
<Chip
|
||||||
label={`User: ${userId ? userId.substring(0, 8) + '...' : 'Unknown'}`}
|
label={username || (userId ? `User: ${userId.substring(0, 8)}...` : 'Unknown')}
|
||||||
size="small"
|
size="small"
|
||||||
sx={{
|
sx={{
|
||||||
fontSize: '0.75rem',
|
fontSize: '0.75rem',
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ interface ProcessingTimelineProps {
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
userId: string;
|
userId: string;
|
||||||
|
username?: string;
|
||||||
ocrStatus?: string;
|
ocrStatus?: string;
|
||||||
ocrCompletedAt?: string;
|
ocrCompletedAt?: string;
|
||||||
ocrRetryCount?: number;
|
ocrRetryCount?: number;
|
||||||
|
|
@ -62,6 +63,7 @@ const ProcessingTimeline: React.FC<ProcessingTimelineProps> = ({
|
||||||
createdAt,
|
createdAt,
|
||||||
updatedAt,
|
updatedAt,
|
||||||
userId,
|
userId,
|
||||||
|
username,
|
||||||
ocrStatus,
|
ocrStatus,
|
||||||
ocrCompletedAt,
|
ocrCompletedAt,
|
||||||
ocrRetryCount = 0,
|
ocrRetryCount = 0,
|
||||||
|
|
@ -114,7 +116,7 @@ const ProcessingTimeline: React.FC<ProcessingTimelineProps> = ({
|
||||||
title: 'Document Uploaded',
|
title: 'Document Uploaded',
|
||||||
description: `File "${fileName}" was uploaded successfully`,
|
description: `File "${fileName}" was uploaded successfully`,
|
||||||
status: 'success',
|
status: 'success',
|
||||||
metadata: { userId },
|
metadata: { userId, username },
|
||||||
});
|
});
|
||||||
|
|
||||||
// OCR processing events
|
// OCR processing events
|
||||||
|
|
@ -352,7 +354,7 @@ const ProcessingTimeline: React.FC<ProcessingTimelineProps> = ({
|
||||||
<Box sx={{ display: 'flex', alignItems: 'center', mt: 1 }}>
|
<Box sx={{ display: 'flex', alignItems: 'center', mt: 1 }}>
|
||||||
<PersonIcon sx={{ fontSize: 14, mr: 0.5, color: theme.palette.text.secondary }} />
|
<PersonIcon sx={{ fontSize: 14, mr: 0.5, color: theme.palette.text.secondary }} />
|
||||||
<Typography variant="caption" color="text.secondary">
|
<Typography variant="caption" color="text.secondary">
|
||||||
User: {event.metadata.userId.substring(0, 8)}...
|
{event.metadata.username || `User: ${event.metadata.userId.substring(0, 8)}...`}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -699,6 +699,7 @@ const DocumentDetailsPage: React.FC = () => {
|
||||||
createdAt={document.created_at}
|
createdAt={document.created_at}
|
||||||
updatedAt={document.updated_at}
|
updatedAt={document.updated_at}
|
||||||
userId={document.user_id}
|
userId={document.user_id}
|
||||||
|
username={document.username}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
@ -884,6 +885,7 @@ const DocumentDetailsPage: React.FC = () => {
|
||||||
createdAt={document.created_at}
|
createdAt={document.created_at}
|
||||||
updatedAt={document.updated_at}
|
updatedAt={document.updated_at}
|
||||||
userId={document.user_id}
|
userId={document.user_id}
|
||||||
|
username={document.username}
|
||||||
ocrStatus={document.has_ocr_text ? 'completed' : 'pending'}
|
ocrStatus={document.has_ocr_text ? 'completed' : 'pending'}
|
||||||
ocrCompletedAt={ocrData?.ocr_completed_at}
|
ocrCompletedAt={ocrData?.ocr_completed_at}
|
||||||
ocrError={ocrData?.ocr_error}
|
ocrError={ocrData?.ocr_error}
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ export interface Document {
|
||||||
created_at: string
|
created_at: string
|
||||||
updated_at: string
|
updated_at: string
|
||||||
user_id: string
|
user_id: string
|
||||||
|
username?: string
|
||||||
file_hash?: string
|
file_hash?: string
|
||||||
original_created_at?: string
|
original_created_at?: string
|
||||||
original_modified_at?: string
|
original_modified_at?: string
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,9 @@ pub struct DocumentResponse {
|
||||||
pub updated_at: DateTime<Utc>,
|
pub updated_at: DateTime<Utc>,
|
||||||
/// User who uploaded/owns the document
|
/// User who uploaded/owns the document
|
||||||
pub user_id: Uuid,
|
pub user_id: Uuid,
|
||||||
|
/// Username of the user who uploaded/owns the document
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none", default)]
|
||||||
|
pub username: Option<String>,
|
||||||
/// SHA256 hash of the file content
|
/// SHA256 hash of the file content
|
||||||
#[serde(skip_serializing_if = "Option::is_none", default)]
|
#[serde(skip_serializing_if = "Option::is_none", default)]
|
||||||
pub file_hash: Option<String>,
|
pub file_hash: Option<String>,
|
||||||
|
|
@ -271,6 +274,7 @@ impl From<Document> for DocumentResponse {
|
||||||
created_at: doc.created_at,
|
created_at: doc.created_at,
|
||||||
updated_at: doc.updated_at,
|
updated_at: doc.updated_at,
|
||||||
user_id: doc.user_id,
|
user_id: doc.user_id,
|
||||||
|
username: None, // Username will be populated separately where needed
|
||||||
file_hash: doc.file_hash,
|
file_hash: doc.file_hash,
|
||||||
has_ocr_text: doc.ocr_text.is_some(),
|
has_ocr_text: doc.ocr_text.is_some(),
|
||||||
ocr_confidence: doc.ocr_confidence,
|
ocr_confidence: doc.ocr_confidence,
|
||||||
|
|
|
||||||
|
|
@ -189,8 +189,20 @@ pub async fn get_document_by_id(
|
||||||
StatusCode::INTERNAL_SERVER_ERROR
|
StatusCode::INTERNAL_SERVER_ERROR
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
// Get username for the document owner
|
||||||
|
let username = state
|
||||||
|
.db
|
||||||
|
.get_user_by_id(document.user_id)
|
||||||
|
.await
|
||||||
|
.map_err(|e| {
|
||||||
|
error!("Failed to get user for document {}: {}", document_id, e);
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR
|
||||||
|
})?
|
||||||
|
.map(|user| user.username);
|
||||||
|
|
||||||
let mut response = DocumentResponse::from(document);
|
let mut response = DocumentResponse::from(document);
|
||||||
response.labels = labels;
|
response.labels = labels;
|
||||||
|
response.username = username;
|
||||||
|
|
||||||
Ok(Json(response))
|
Ok(Json(response))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue