Browse Source

feat: pdf viewer with docs support

pull/8990/head
DarkPhoenix2704 4 months ago
parent
commit
de45679d86
No known key found for this signature in database
GPG Key ID: 3F76B10622A07849
  1. 89
      packages/nc-gui/assets/nc-icons/google-docs.svg
  2. 3
      packages/nc-gui/components/cell/attachment/Carousel.vue
  3. 35
      packages/nc-gui/components/cell/attachment/Preview/Pdf.vue
  4. 4
      packages/nc-gui/utils/iconUtils.ts

89
packages/nc-gui/assets/nc-icons/google-docs.svg

@ -0,0 +1,89 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="47px" height="65px" viewBox="0 0 47 65" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 54.1 (76490) - https://sketchapp.com -->
<title>Docs-icon</title>
<desc>Created with Sketch.</desc>
<defs>
<path d="M29.375,0 L4.40625,0 C1.9828125,0 0,1.99431818 0,4.43181818 L0,60.5681818 C0,63.0056818 1.9828125,65 4.40625,65 L42.59375,65 C45.0171875,65 47,63.0056818 47,60.5681818 L47,17.7272727 L29.375,0 Z" id="path-1"></path>
<path d="M29.375,0 L4.40625,0 C1.9828125,0 0,1.99431818 0,4.43181818 L0,60.5681818 C0,63.0056818 1.9828125,65 4.40625,65 L42.59375,65 C45.0171875,65 47,63.0056818 47,60.5681818 L47,17.7272727 L29.375,0 Z" id="path-3"></path>
<linearGradient x1="50.0053945%" y1="8.58610612%" x2="50.0053945%" y2="100.013939%" id="linearGradient-5">
<stop stop-color="#1A237E" stop-opacity="0.2" offset="0%"></stop>
<stop stop-color="#1A237E" stop-opacity="0.02" offset="100%"></stop>
</linearGradient>
<path d="M29.375,0 L4.40625,0 C1.9828125,0 0,1.99431818 0,4.43181818 L0,60.5681818 C0,63.0056818 1.9828125,65 4.40625,65 L42.59375,65 C45.0171875,65 47,63.0056818 47,60.5681818 L47,17.7272727 L29.375,0 Z" id="path-6"></path>
<path d="M29.375,0 L4.40625,0 C1.9828125,0 0,1.99431818 0,4.43181818 L0,60.5681818 C0,63.0056818 1.9828125,65 4.40625,65 L42.59375,65 C45.0171875,65 47,63.0056818 47,60.5681818 L47,17.7272727 L29.375,0 Z" id="path-8"></path>
<path d="M29.375,0 L4.40625,0 C1.9828125,0 0,1.99431818 0,4.43181818 L0,60.5681818 C0,63.0056818 1.9828125,65 4.40625,65 L42.59375,65 C45.0171875,65 47,63.0056818 47,60.5681818 L47,17.7272727 L29.375,0 Z" id="path-10"></path>
<path d="M29.375,0 L4.40625,0 C1.9828125,0 0,1.99431818 0,4.43181818 L0,60.5681818 C0,63.0056818 1.9828125,65 4.40625,65 L42.59375,65 C45.0171875,65 47,63.0056818 47,60.5681818 L47,17.7272727 L29.375,0 Z" id="path-12"></path>
<path d="M29.375,0 L4.40625,0 C1.9828125,0 0,1.99431818 0,4.43181818 L0,60.5681818 C0,63.0056818 1.9828125,65 4.40625,65 L42.59375,65 C45.0171875,65 47,63.0056818 47,60.5681818 L47,17.7272727 L29.375,0 Z" id="path-14"></path>
<radialGradient cx="3.16804688%" cy="2.71744318%" fx="3.16804688%" fy="2.71744318%" r="161.248516%" gradientTransform="translate(0.031680,0.027174),scale(1.000000,0.723077),translate(-0.031680,-0.027174)" id="radialGradient-16">
<stop stop-color="#FFFFFF" stop-opacity="0.1" offset="0%"></stop>
<stop stop-color="#FFFFFF" stop-opacity="0" offset="100%"></stop>
</radialGradient>
</defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Consumer-Apps-Docs-Large-VD-R8" transform="translate(-451.000000, -463.000000)">
<g id="Hero" transform="translate(0.000000, 63.000000)">
<g id="Personal" transform="translate(277.000000, 309.000000)">
<g id="Docs-icon" transform="translate(174.000000, 91.000000)">
<g id="Group">
<g id="Clipped">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<g id="SVGID_1_"></g>
<path d="M29.375,0 L4.40625,0 C1.9828125,0 0,1.99431818 0,4.43181818 L0,60.5681818 C0,63.0056818 1.9828125,65 4.40625,65 L42.59375,65 C45.0171875,65 47,63.0056818 47,60.5681818 L47,17.7272727 L36.71875,10.3409091 L29.375,0 Z" id="Path" fill="#4285F4" fill-rule="nonzero" mask="url(#mask-2)"></path>
</g>
<g id="Clipped">
<mask id="mask-4" fill="white">
<use xlink:href="#path-3"></use>
</mask>
<g id="SVGID_1_"></g>
<polygon id="Path" fill="url(#linearGradient-5)" fill-rule="nonzero" mask="url(#mask-4)" points="30.6638281 16.4309659 47 32.8582386 47 17.7272727"></polygon>
</g>
<g id="Clipped">
<mask id="mask-7" fill="white">
<use xlink:href="#path-6"></use>
</mask>
<g id="SVGID_1_"></g>
<path d="M11.75,47.2727273 L35.25,47.2727273 L35.25,44.3181818 L11.75,44.3181818 L11.75,47.2727273 Z M11.75,53.1818182 L29.375,53.1818182 L29.375,50.2272727 L11.75,50.2272727 L11.75,53.1818182 Z M11.75,32.5 L11.75,35.4545455 L35.25,35.4545455 L35.25,32.5 L11.75,32.5 Z M11.75,41.3636364 L35.25,41.3636364 L35.25,38.4090909 L11.75,38.4090909 L11.75,41.3636364 Z" id="Shape" fill="#F1F1F1" fill-rule="nonzero" mask="url(#mask-7)"></path>
</g>
<g id="Clipped">
<mask id="mask-9" fill="white">
<use xlink:href="#path-8"></use>
</mask>
<g id="SVGID_1_"></g>
<g id="Group" mask="url(#mask-9)">
<g transform="translate(26.437500, -2.954545)">
<path d="M2.9375,2.95454545 L2.9375,16.25 C2.9375,18.6985795 4.90929688,20.6818182 7.34375,20.6818182 L20.5625,20.6818182 L2.9375,2.95454545 Z" id="Path" fill="#A1C2FA" fill-rule="nonzero"></path>
</g>
</g>
</g>
<g id="Clipped">
<mask id="mask-11" fill="white">
<use xlink:href="#path-10"></use>
</mask>
<g id="SVGID_1_"></g>
<path d="M4.40625,0 C1.9828125,0 0,1.99431818 0,4.43181818 L0,4.80113636 C0,2.36363636 1.9828125,0.369318182 4.40625,0.369318182 L29.375,0.369318182 L29.375,0 L4.40625,0 Z" id="Path" fill-opacity="0.2" fill="#FFFFFF" fill-rule="nonzero" mask="url(#mask-11)"></path>
</g>
<g id="Clipped">
<mask id="mask-13" fill="white">
<use xlink:href="#path-12"></use>
</mask>
<g id="SVGID_1_"></g>
<path d="M42.59375,64.6306818 L4.40625,64.6306818 C1.9828125,64.6306818 0,62.6363636 0,60.1988636 L0,60.5681818 C0,63.0056818 1.9828125,65 4.40625,65 L42.59375,65 C45.0171875,65 47,63.0056818 47,60.5681818 L47,60.1988636 C47,62.6363636 45.0171875,64.6306818 42.59375,64.6306818 Z" id="Path" fill-opacity="0.2" fill="#1A237E" fill-rule="nonzero" mask="url(#mask-13)"></path>
</g>
<g id="Clipped">
<mask id="mask-15" fill="white">
<use xlink:href="#path-14"></use>
</mask>
<g id="SVGID_1_"></g>
<path d="M33.78125,17.7272727 C31.3467969,17.7272727 29.375,15.7440341 29.375,13.2954545 L29.375,13.6647727 C29.375,16.1133523 31.3467969,18.0965909 33.78125,18.0965909 L47,18.0965909 L47,17.7272727 L33.78125,17.7272727 Z" id="Path" fill-opacity="0.1" fill="#1A237E" fill-rule="nonzero" mask="url(#mask-15)"></path>
</g>
</g>
<path d="M29.375,0 L4.40625,0 C1.9828125,0 0,1.99431818 0,4.43181818 L0,60.5681818 C0,63.0056818 1.9828125,65 4.40625,65 L42.59375,65 C45.0171875,65 47,63.0056818 47,60.5681818 L47,17.7272727 L29.375,0 Z" id="Path" fill="url(#radialGradient-16)" fill-rule="nonzero"></path>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 8.0 KiB

3
packages/nc-gui/components/cell/attachment/Carousel.vue

@ -13,7 +13,7 @@ const { getPossibleAttachmentSrc } = useAttachment()
useEventListener(container, 'click', (e) => {
const target = e.target as HTMLElement
if (!target.closest('.keep-open') && (!target.closest('img') || !target.closest('video'))) {
if (!target.closest('.keep-open') || !target.closest('.nc-button')) {
selectedFile.value = false
}
})
@ -105,6 +105,7 @@ watchOnce(emblaMainApi, async (emblaMainApi) => {
/>
<LazyCellAttachmentPreviewPdf
v-else-if="isPdf(item.title, item.mimeType)"
class="keep-open"
:src="getPossibleAttachmentSrc(item)[0]"
/>
<div v-else class="bg-white h-full flex flex-col justify-center rounded-md gap-1 items-center w-full">

35
packages/nc-gui/components/cell/attachment/Preview/Pdf.vue

@ -1,13 +1,46 @@
<script setup lang="ts">
interface Props {
src: string
class?: string
}
const props = defineProps<Props>()
const openMethod = ref<'browser' | 'google' | undefined>()
</script>
<template>
<iframe :src="props.src" width="100%" height="100%"></iframe>
<div v-if="!openMethod" :class="props.class" class="flex flex-col text-white gap-2 items-center justify-center">
<GeneralIcon class="w-28 h-28" icon="pdfFile" />
<h1 class="font-bold text-white text-center text-lg">Opening your file in external service exposes your data</h1>
<div class="flex items-center justify-center gap-2">
<NcButton @click="openMethod = 'browser'">
<div class="flex items-center gap-1">
<GeneralIcon icon="lock" />
Open in browser
</div>
</NcButton>
<NcButton type="secondary" @click="openMethod = 'google'">
<div class="flex items-center gap-1">
<GeneralIcon class="w-4 h-4" icon="googleDocs" />
Open with Google Docs
</div>
</NcButton>
</div>
</div>
<iframe v-if="openMethod === 'browser'" :class="props.class" :src="props.src" width="100%" height="100%"></iframe>
<iframe
v-else-if="openMethod === 'google'"
:class="props.class"
:src="`https://docs.google.com/viewer?url=${src}&embedded=true`"
width="100%"
height="100%"
frameborder="0"
></iframe>
</template>
<style scoped lang="scss"></style>

4
packages/nc-gui/utils/iconUtils.ts

@ -40,6 +40,7 @@ import Phishing from '~icons/material-symbols/phishing-outline-rounded'
import MdiAccountGroup from '~icons/mdi/account-group'
import MdiDotsVertical from '~icons/mdi/dots-vertical'
import MdiDotsHorizontal from '~icons/mdi/dots-horizontal'
import MdiPdf from '~icons/mdi/file-pdf'
import PhExcelThin from '~icons/ph/microsoft-excel-logo-light'
import VscodeIconsExcelColored from '~icons/vscode-icons/file-type-excel'
import PhCsvThin from '~icons/ph/file-csv'
@ -205,6 +206,7 @@ import NcMaximizeAll from '~icons/nc-icons/maximize-all'
import NcDrag from '~icons/nc-icons/drag'
import NcRefresh from '~icons/nc-icons/refresh'
import NcPlay from '~icons/nc-icons/play'
import GoogleDocs from '~icons/nc-icons/google-docs'
// keep it for reference
// todo: remove it after all icons are migrated
@ -640,6 +642,8 @@ export const iconMap = {
refresh: NcRefresh,
chevronUpDown: NcChevronUpDown,
play: NcPlay,
googleDocs: GoogleDocs,
pdfFile: MdiPdf,
}
export const getMdiIcon = (type: string): any => {

Loading…
Cancel
Save