feat(mentor-workspace): inline document preview matching applicant docs pattern

- Eye toggle expands the row below to embed FilePreview from
  @/components/shared/file-viewer (PDF iframe, image, video, Office docs)
- Download button uses explicit Content-Disposition: attachment via a
  new `disposition` input on workspaceGetFileDownloadUrl
- getPresignedUrl learns `inline: true` and optional `response-content-type`
  override so PDFs/images don't get force-downloaded by MinIO's default
- Eye button only renders for previewable mime types

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Matt
2026-05-22 18:26:20 +02:00
parent ec92b03006
commit 48e48f058d
3 changed files with 92 additions and 14 deletions

View File

@@ -78,13 +78,17 @@ export async function getPresignedUrl(
objectKey: string,
method: 'GET' | 'PUT' = 'GET',
expirySeconds: number = 900, // 15 minutes default
options?: { downloadFileName?: string }
options?: { downloadFileName?: string; inline?: boolean; contentType?: string }
): Promise<string> {
const publicClient = getPublicMinioClient()
if (method === 'GET') {
const respHeaders = options?.downloadFileName
? { 'response-content-disposition': `attachment; filename="${options.downloadFileName}"` }
: undefined
let respHeaders: Record<string, string> | undefined
if (options?.inline) {
respHeaders = { 'response-content-disposition': 'inline' }
if (options.contentType) respHeaders['response-content-type'] = options.contentType
} else if (options?.downloadFileName) {
respHeaders = { 'response-content-disposition': `attachment; filename="${options.downloadFileName}"` }
}
return publicClient.presignedGetObject(bucket, objectKey, expirySeconds, respHeaders)
} else {
return publicClient.presignedPutObject(bucket, objectKey, expirySeconds)