add pdf viewer
This commit is contained in:
parent
f1c4e896b6
commit
208c683dac
7 changed files with 1114 additions and 13 deletions
|
|
@ -1,16 +1,26 @@
|
|||
<script setup lang="ts">
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { computed, watch } from 'vue'
|
||||
import { computed, ref, watch } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import ElementParentLink from '@/components/ElementParentLink.vue'
|
||||
import ElementSiblingNavigation from '@/components/ElementSiblingNavigation.vue'
|
||||
import PdfViewerModal from '@/components/PdfViewerModal.vue'
|
||||
import SiteHeader from '@/components/SiteHeader.vue'
|
||||
import { useElementsStore } from '@/stores/elements'
|
||||
|
||||
type TimestampPart = string | undefined
|
||||
type ElementPdfFolder = 'short' | 'long'
|
||||
|
||||
interface ActivePdf {
|
||||
openUrl: string
|
||||
sourceUrl: string
|
||||
title: string
|
||||
}
|
||||
|
||||
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL as string
|
||||
const route = useRoute()
|
||||
const elementsStore = useElementsStore()
|
||||
const activePdf = ref<ActivePdf | null>(null)
|
||||
const {
|
||||
element,
|
||||
childElements,
|
||||
|
|
@ -46,9 +56,23 @@ const youtubeEmbedUrl = computed(() => {
|
|||
return getYoutubeEmbedUrl(youtubeUrl)
|
||||
})
|
||||
|
||||
const activePdfTitle = computed(() => {
|
||||
return activePdf.value?.title ?? ''
|
||||
})
|
||||
|
||||
const activePdfUrl = computed(() => {
|
||||
return activePdf.value?.sourceUrl ?? ''
|
||||
})
|
||||
|
||||
const activePdfOpenUrl = computed(() => {
|
||||
return activePdf.value?.openUrl ?? ''
|
||||
})
|
||||
|
||||
watch(
|
||||
elementId,
|
||||
(currentElementId) => {
|
||||
activePdf.value = null
|
||||
|
||||
if (typeof currentElementId !== 'string' || currentElementId === '') {
|
||||
return
|
||||
}
|
||||
|
|
@ -58,6 +82,61 @@ watch(
|
|||
{ immediate: true },
|
||||
)
|
||||
|
||||
function openPdfViewer(pdfTitle: string, pdfUrl: string | null): void {
|
||||
if (pdfUrl === null) {
|
||||
return
|
||||
}
|
||||
|
||||
activePdf.value = {
|
||||
openUrl: pdfUrl,
|
||||
sourceUrl: getPdfViewerUrl(pdfUrl),
|
||||
title: pdfTitle,
|
||||
}
|
||||
}
|
||||
|
||||
function closePdfViewer(): void {
|
||||
activePdf.value = null
|
||||
}
|
||||
|
||||
function getPdfViewerUrl(pdfUrl: string): string {
|
||||
let parsedPdfUrl: URL
|
||||
try {
|
||||
parsedPdfUrl = new URL(pdfUrl, window.location.origin)
|
||||
} catch {
|
||||
return pdfUrl
|
||||
}
|
||||
|
||||
const pathSegments = parsedPdfUrl.pathname
|
||||
.split('/')
|
||||
.filter((pathSegment) => {
|
||||
return pathSegment !== ''
|
||||
})
|
||||
|
||||
if (pathSegments.length !== 4) {
|
||||
return pdfUrl
|
||||
}
|
||||
|
||||
if (pathSegments[0] !== 'storage' || pathSegments[1] !== 'element-pdfs') {
|
||||
return pdfUrl
|
||||
}
|
||||
|
||||
const pdfFolder = pathSegments[2]
|
||||
const fileName = pathSegments[3]
|
||||
if (!isElementPdfFolder(pdfFolder) || fileName === undefined) {
|
||||
return pdfUrl
|
||||
}
|
||||
|
||||
const encodedFileName = encodeURIComponent(fileName)
|
||||
|
||||
return `${API_BASE_URL}/api/element-pdfs/${pdfFolder}/${encodedFileName}`
|
||||
}
|
||||
|
||||
function isElementPdfFolder(
|
||||
pdfFolder: string | undefined,
|
||||
): pdfFolder is ElementPdfFolder {
|
||||
return pdfFolder === 'short' || pdfFolder === 'long'
|
||||
}
|
||||
|
||||
function getYoutubeEmbedUrl(youtubeUrl: string | null): string | null {
|
||||
if (youtubeUrl === null || youtubeUrl === '') {
|
||||
return null
|
||||
|
|
@ -266,26 +345,24 @@ function isShortYoutubeHost(hostname: string): boolean {
|
|||
v-if="element.shortPdfPath !== null || element.longPdfPath !== null"
|
||||
class="element-page__actions"
|
||||
>
|
||||
<a
|
||||
<button
|
||||
v-if="element.shortPdfPath !== null"
|
||||
:href="element.shortPdfPath"
|
||||
type="button"
|
||||
class="element-page__pdf-link"
|
||||
data-cy="element-short-pdf-link"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
data-cy="element-short-pdf-viewer-button"
|
||||
@click="openPdfViewer('Short PDF', element.shortPdfPath)"
|
||||
>
|
||||
View Short PDF
|
||||
</a>
|
||||
<a
|
||||
</button>
|
||||
<button
|
||||
v-if="element.longPdfPath !== null"
|
||||
:href="element.longPdfPath"
|
||||
type="button"
|
||||
class="element-page__pdf-link"
|
||||
data-cy="element-long-pdf-link"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
data-cy="element-long-pdf-viewer-button"
|
||||
@click="openPdfViewer('Long PDF', element.longPdfPath)"
|
||||
>
|
||||
View Long PDF
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<nav
|
||||
|
|
@ -326,6 +403,13 @@ function isShortYoutubeHost(hostname: string): boolean {
|
|||
/>
|
||||
</section>
|
||||
</main>
|
||||
<PdfViewerModal
|
||||
:is-open="activePdf !== null"
|
||||
:open-url="activePdfOpenUrl"
|
||||
:pdf-title="activePdfTitle"
|
||||
:pdf-url="activePdfUrl"
|
||||
@close="closePdfViewer"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue