diff --git a/web-app/src/api/attachment.ts b/web-app/src/api/attachment.ts index 3fd6927..3946dfa 100644 --- a/web-app/src/api/attachment.ts +++ b/web-app/src/api/attachment.ts @@ -18,10 +18,14 @@ export class AttachmentApiClient extends ApiClient { this.profileName = getSelectedProfile(route) } - downloadAttachment(attachmentId: number, token: string) { - const url = + getAttachmentUrl(attachmentId: number, token: string) { + return ( import.meta.env.VITE_API_BASE_URL + `/profiles/${this.profileName}/attachments/${attachmentId}/download?t=${token}` - window.open(url, '_blank') + ) + } + + downloadAttachment(attachmentId: number, token: string) { + window.open(this.getAttachmentUrl(attachmentId, token), '_blank') } } diff --git a/web-app/src/components/common/AttachmentRow.vue b/web-app/src/components/common/AttachmentRow.vue index 1748a06..1ffe11b 100644 --- a/web-app/src/components/common/AttachmentRow.vue +++ b/web-app/src/components/common/AttachmentRow.vue @@ -3,21 +3,40 @@ import { AttachmentApiClient } from '@/api/attachment' import { useAuthStore } from '@/stores/auth-store' import { useRoute } from 'vue-router' import AppButton from './AppButton.vue' +import { computed, useTemplateRef, type Ref } from 'vue' +import ModalWrapper from './ModalWrapper.vue' interface AttachmentInfo { filename: string contentType: string size: number id?: number + file?: File } const route = useRoute() +const api = new AttachmentApiClient(route) const authStore = useAuthStore() const props = defineProps<{ attachment: AttachmentInfo; disabled?: boolean }>() defineEmits<{ deleted: void }>() +const srcUrl: Ref = computed(() => { + if (props.attachment.file !== undefined) { + return URL.createObjectURL(props.attachment.file) + } + if (props.attachment.id === undefined || authStore.state === null) { + return null + } + return api.getAttachmentUrl(props.attachment.id, authStore.state.token) +}) +const canPreviewAttachment = computed(() => { + if (!srcUrl.value) return false + const c = props.attachment.contentType + return c.startsWith('image') || c === 'application/pdf' +}) + +const attachmentViewerModal = useTemplateRef('attachmentViewer') function downloadFile() { - const api = new AttachmentApiClient(route) if (!authStore.state) return api.downloadAttachment(props.attachment?.id ?? 0, authStore.state.token) } @@ -31,19 +50,39 @@ function downloadFile() {
+
+ + +
+

{{ attachment.filename }}

+ +
+
diff --git a/web-app/src/components/common/ModalWrapper.vue b/web-app/src/components/common/ModalWrapper.vue index 0083cde..1829d1d 100644 --- a/web-app/src/components/common/ModalWrapper.vue +++ b/web-app/src/components/common/ModalWrapper.vue @@ -52,11 +52,16 @@ defineExpose({ show, close }) color: inherit; border-radius: 1rem; border-width: 0; + /* border: 3px solid var(--theme-secondary); */ min-width: 300px; max-width: 500px; padding: 1rem; } +.app-modal-dialog::backdrop { + background-color: rgb(0 0 0 / 60%); +} + .app-modal-dialog-header { margin-top: 0; }