feat(documents): migrate storage to filesystem, add server-side pagination
- Replace Base64 data URIs with file-based storage served via dedicated endpoints - Add DocumentPreviewModal navigation, DocumentThumbnail fileUrl support - Refactor documents page with server-side pagination, search, sort and filters - Update all components to use fileUrl/downloadUrl instead of raw path - Add pagination composable support (total, page, itemsPerPage, attachmentFilter) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -19,26 +19,32 @@ export const formatSize = (size: number | null | undefined): string => {
|
||||
return `${formatted.toFixed(1)} ${units[index]}`
|
||||
}
|
||||
|
||||
const resolveUrl = (doc: any): string => doc?.fileUrl || doc?.path || ''
|
||||
|
||||
export const shouldInlinePdf = (doc: any): boolean => {
|
||||
if (!doc || !isPdfDocument(doc) || !doc.path) return false
|
||||
if (!doc || !isPdfDocument(doc)) return false
|
||||
const url = resolveUrl(doc)
|
||||
if (!url) return false
|
||||
if (typeof doc.size === 'number' && doc.size > PDF_PREVIEW_MAX_BYTES) return false
|
||||
return true
|
||||
}
|
||||
|
||||
export const appendPdfViewerParams = (src: string): string => {
|
||||
if (!src || src.startsWith('data:')) return src || ''
|
||||
if (!src) return ''
|
||||
if (src.startsWith('data:')) return src
|
||||
if (src.includes('#')) return `${src}&toolbar=0&navpanes=0`
|
||||
return `${src}#toolbar=0&navpanes=0`
|
||||
}
|
||||
|
||||
export const documentPreviewSrc = (doc: any): string => {
|
||||
if (!doc?.path) return ''
|
||||
if (isPdfDocument(doc)) return appendPdfViewerParams(doc.path)
|
||||
return doc.path
|
||||
const url = resolveUrl(doc)
|
||||
if (!url) return ''
|
||||
if (isPdfDocument(doc)) return appendPdfViewerParams(url)
|
||||
return url
|
||||
}
|
||||
|
||||
export const documentThumbnailClass = (doc: any): string => {
|
||||
if (shouldInlinePdf(doc) || (isImageDocument(doc) && doc?.path)) return 'h-24 w-20'
|
||||
if (shouldInlinePdf(doc) || (isImageDocument(doc) && resolveUrl(doc))) return 'h-24 w-20'
|
||||
return 'h-16 w-16'
|
||||
}
|
||||
|
||||
@@ -52,8 +58,14 @@ export const documentIcon = (doc: any): FileIconResult =>
|
||||
getFileIcon({ name: doc?.filename || doc?.name, mime: doc?.mimeType })
|
||||
|
||||
export const downloadDocument = (doc: any): void => {
|
||||
if (!doc?.path) return
|
||||
const target = String(doc.path)
|
||||
// Prefer dedicated download endpoint
|
||||
if (doc?.downloadUrl) {
|
||||
window.open(doc.downloadUrl, '_blank')
|
||||
return
|
||||
}
|
||||
// Fallback for legacy data: URIs during migration
|
||||
const target = resolveUrl(doc)
|
||||
if (!target) return
|
||||
if (target.startsWith('data:')) {
|
||||
const link = document.createElement('a')
|
||||
link.href = target
|
||||
|
||||
Reference in New Issue
Block a user