[#1548] added PDF preview
This commit is contained in:
@@ -4,6 +4,8 @@
|
||||
let panel;
|
||||
let url = "";
|
||||
|
||||
export let type;
|
||||
|
||||
export function show(newUrl) {
|
||||
if (newUrl === "") {
|
||||
return;
|
||||
@@ -17,16 +19,22 @@
|
||||
export function hide() {
|
||||
return panel?.hide();
|
||||
}
|
||||
|
||||
$: filename = url.substring(url.lastIndexOf("/") + 1);
|
||||
</script>
|
||||
|
||||
<OverlayPanel bind:this={panel} class="image-preview" btnClose={false} popup on:show on:hide>
|
||||
<OverlayPanel bind:this={panel} class="preview {type}-preview" btnClose={false} popup on:show on:hide>
|
||||
<svelte:fragment slot="header">
|
||||
<button type="button" class="overlay-close" on:click|preventDefault={hide}>
|
||||
<i class="ri-close-line" />
|
||||
</button>
|
||||
</svelte:fragment>
|
||||
|
||||
<img src={url} alt="Preview {url}" />
|
||||
{#if type === "image"}
|
||||
<img src={url} alt="Preview {url}" />
|
||||
{:else if type === "pdf"}
|
||||
<object title={filename} data={url} type="application/pdf"> PDF embed not loaded. </object>
|
||||
{/if}
|
||||
|
||||
<svelte:fragment slot="footer">
|
||||
<a
|
||||
@@ -36,7 +44,8 @@
|
||||
rel="noreferrer noopener"
|
||||
class="link-hint txt-ellipsis"
|
||||
>
|
||||
{url.substring(url.lastIndexOf("/") + 1)}
|
||||
<i class="ri-file-download-line" />
|
||||
{filename}
|
||||
</a>
|
||||
<div class="flex-fill" />
|
||||
<button type="button" class="btn btn-secondary" on:click={hide}>Close</button>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import tooltip from "@/actions/tooltip";
|
||||
import IdLabel from "@/components/base/IdLabel.svelte";
|
||||
import FormattedDate from "@/components/base/FormattedDate.svelte";
|
||||
import RecordFilePreview from "@/components/records/RecordFilePreview.svelte";
|
||||
import RecordFileThumb from "@/components/records/RecordFileThumb.svelte";
|
||||
|
||||
export let record;
|
||||
export let field;
|
||||
@@ -57,9 +57,7 @@
|
||||
{:else if field.type === "file"}
|
||||
<div class="inline-flex">
|
||||
{#each CommonHelper.toArray(record[field.name]) as filename, i (i + filename)}
|
||||
<figure class="thumb thumb-sm">
|
||||
<RecordFilePreview {record} {filename} />
|
||||
</figure>
|
||||
<RecordFileThumb {record} {filename} size="sm" />
|
||||
{/each}
|
||||
</div>
|
||||
{:else}
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
<script>
|
||||
import ApiClient from "@/utils/ApiClient";
|
||||
import CommonHelper from "@/utils/CommonHelper";
|
||||
import PreviewPopup from "@/components/base/PreviewPopup.svelte";
|
||||
|
||||
export let record;
|
||||
export let filename;
|
||||
|
||||
let previewPopup;
|
||||
let thumbUrl = "";
|
||||
let originalUrl = "";
|
||||
|
||||
$: hasPreview = CommonHelper.hasImageExtension(filename);
|
||||
|
||||
$: if (hasPreview) {
|
||||
originalUrl = ApiClient.getFileUrl(record, `${filename}`);
|
||||
}
|
||||
|
||||
$: thumbUrl = originalUrl ? originalUrl + "?thumb=100x100" : "";
|
||||
|
||||
function onError() {
|
||||
thumbUrl = "";
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if hasPreview}
|
||||
<img
|
||||
src={thumbUrl}
|
||||
alt={filename}
|
||||
title="Preview {filename}"
|
||||
class:link-fade={hasPreview}
|
||||
on:click={(e) => {
|
||||
e.stopPropagation();
|
||||
previewPopup?.show(originalUrl);
|
||||
}}
|
||||
on:error={onError}
|
||||
/>
|
||||
{:else}
|
||||
<i class="ri-file-line" />
|
||||
{/if}
|
||||
|
||||
<PreviewPopup bind:this={previewPopup} />
|
||||
@@ -0,0 +1,43 @@
|
||||
<script>
|
||||
import ApiClient from "@/utils/ApiClient";
|
||||
import CommonHelper from "@/utils/CommonHelper";
|
||||
import PreviewPopup from "@/components/base/PreviewPopup.svelte";
|
||||
|
||||
export let record;
|
||||
export let filename;
|
||||
export let size;
|
||||
|
||||
let previewPopup;
|
||||
let thumbUrl = "";
|
||||
let originalUrl = ApiClient.getFileUrl(record, `${filename}`);
|
||||
|
||||
$: type = CommonHelper.getFileType(filename);
|
||||
$: hasPreview = ["image", "pdf"].includes(type);
|
||||
$: thumbUrl = originalUrl ? originalUrl + "?thumb=100x100" : "";
|
||||
|
||||
function onError() {
|
||||
thumbUrl = "";
|
||||
}
|
||||
</script>
|
||||
|
||||
<a
|
||||
class="thumb thumb-{size} link-fade"
|
||||
href={originalUrl}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
on:click|stopPropagation={(e) => {
|
||||
if (!hasPreview) return;
|
||||
e.preventDefault();
|
||||
previewPopup?.show(originalUrl);
|
||||
}}
|
||||
>
|
||||
{#if type === "image"}
|
||||
<img src={thumbUrl} alt={filename} title="Preview {filename}" on:error={onError} />
|
||||
{:else if type === "pdf"}
|
||||
<i class="ri-file-pdf-line" />
|
||||
{:else}
|
||||
<i class="ri-file-3-line" />
|
||||
{/if}
|
||||
</a>
|
||||
|
||||
<PreviewPopup bind:this={previewPopup} {type} />
|
||||
@@ -5,7 +5,7 @@
|
||||
import tooltip from "@/actions/tooltip";
|
||||
import Field from "@/components/base/Field.svelte";
|
||||
import UploadedFilePreview from "@/components/base/UploadedFilePreview.svelte";
|
||||
import RecordFilePreview from "@/components/records/RecordFilePreview.svelte";
|
||||
import RecordFileThumb from "@/components/records/RecordFileThumb.svelte";
|
||||
|
||||
export let record;
|
||||
export let value = "";
|
||||
@@ -79,9 +79,9 @@
|
||||
<div bind:this={filesListElem} class="files-list">
|
||||
{#each valueAsArray as filename, i (filename)}
|
||||
<div class="list-item">
|
||||
<figure class="thumb" class:fade={deletedFileIndexes.includes(i)}>
|
||||
<RecordFilePreview {record} {filename} />
|
||||
</figure>
|
||||
<div class:fade={deletedFileIndexes.includes(i)}>
|
||||
<RecordFileThumb {record} {filename} />
|
||||
</div>
|
||||
<a
|
||||
href={ApiClient.getFileUrl(record, filename)}
|
||||
class="filename link-hint"
|
||||
|
||||
@@ -210,12 +210,7 @@
|
||||
&.full-width-popup {
|
||||
width: 100%;
|
||||
}
|
||||
&.image-preview {
|
||||
width: auto;
|
||||
min-width: 300px;
|
||||
min-height: 250px;
|
||||
max-width: 70%;
|
||||
max-height: 90%;
|
||||
&.preview {
|
||||
.panel-header {
|
||||
position: absolute;
|
||||
z-index: 99;
|
||||
@@ -243,12 +238,30 @@
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
&.image-preview {
|
||||
width: auto;
|
||||
min-width: 300px;
|
||||
min-height: 250px;
|
||||
max-width: 70%;
|
||||
max-height: 90%;
|
||||
img {
|
||||
max-width: 100%;
|
||||
border-top-left-radius: var(--baseRadius);
|
||||
border-top-right-radius: var(--baseRadius);
|
||||
}
|
||||
}
|
||||
&.pdf-preview {
|
||||
width: 70%;
|
||||
height: 90%;
|
||||
object {
|
||||
position:absolute;
|
||||
left:0;
|
||||
top:0;
|
||||
width:100%;
|
||||
height:100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 900px) {
|
||||
.overlay-panel-section {
|
||||
|
||||
@@ -663,6 +663,28 @@ export default class CommonHelper {
|
||||
return /\.jpg|\.jpeg|\.png|\.svg|\.gif|\.jfif|\.webp|\.avif$/.test(filename)
|
||||
}
|
||||
|
||||
/**
|
||||
* Loosely check if a file is a pdf based on its filename extension.
|
||||
*
|
||||
* @param {String} filename
|
||||
* @return {Boolean}
|
||||
*/
|
||||
static hasPdfExtension(filename) {
|
||||
return /\.pdf$/.test(filename);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns file type
|
||||
*
|
||||
* @param {String} filename
|
||||
* @return {String}
|
||||
*/
|
||||
static getFileType(filename) {
|
||||
if (this.hasImageExtension(filename)) return "image";
|
||||
if (this.hasPdfExtension(filename)) return "pdf";
|
||||
return "file";
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a thumbnail from `File` with the specified `width` and `height` params.
|
||||
* Returns a `Promise` with the generated base64 url.
|
||||
|
||||
Reference in New Issue
Block a user