diff --git a/packages/presentation/lang/en.json b/packages/presentation/lang/en.json index 71bc55b089..4b4296b6f4 100644 --- a/packages/presentation/lang/en.json +++ b/packages/presentation/lang/en.json @@ -30,6 +30,7 @@ "MakePrivateDescription": "Only members can see it", "Created": "Created", "NoResults": "No results to show", - "Next": "Next" + "Next": "Next", + "FailedToPreview": "Failed to preview" } } diff --git a/packages/presentation/lang/es.json b/packages/presentation/lang/es.json index c066edcc82..1f0d61ceb7 100644 --- a/packages/presentation/lang/es.json +++ b/packages/presentation/lang/es.json @@ -30,6 +30,7 @@ "MakePrivateDescription": "Solo los miembros pueden verlo", "Created": "Creado", "NoResults": "No hay resultados para mostrar", - "Next": "Siguiente" + "Next": "Siguiente", + "FailedToPreview": "Error al previsualizar" } } \ No newline at end of file diff --git a/packages/presentation/lang/pt.json b/packages/presentation/lang/pt.json index 0bed2dacee..594ec66c3a 100644 --- a/packages/presentation/lang/pt.json +++ b/packages/presentation/lang/pt.json @@ -30,6 +30,7 @@ "MakePrivateDescription": "Apenas os membros podem ver", "Created": "Criado", "NoResults": "Sem resultados para mostrar", - "Next": "Seguinte" + "Next": "Seguinte", + "FailedToPreview": "Falha ao pré-visualizar" } } \ No newline at end of file diff --git a/packages/presentation/lang/ru.json b/packages/presentation/lang/ru.json index 42aecb5748..7737ffe33e 100644 --- a/packages/presentation/lang/ru.json +++ b/packages/presentation/lang/ru.json @@ -30,6 +30,7 @@ "MakePrivateDescription": "Только пользователи могут видеть это", "Created": "Созданные", "NoResults": "Нет результатов", - "Next": "Далее" + "Next": "Далее", + "FailedToPreview": "Ошибка предпросмотра" } } diff --git a/packages/presentation/src/components/PDFViewer.svelte b/packages/presentation/src/components/PDFViewer.svelte index 1b81ad2ca5..4b5e3da591 100644 --- a/packages/presentation/src/components/PDFViewer.svelte +++ b/packages/presentation/src/components/PDFViewer.svelte @@ -14,20 +14,21 @@ --> <script lang="ts"> // import { Doc } from '@hcengineering/core' - import { Button, Dialog } from '@hcengineering/ui' + import { Button, Dialog, Label, Spinner } from '@hcengineering/ui' import { createEventDispatcher, onMount } from 'svelte' import presentation from '..' import { getFileUrl } from '../utils' import Download from './icons/Download.svelte' import ActionContext from './ActionContext.svelte' - export let file: string + export let file: string | undefined export let name: string export let contentType: string | undefined // export let popupOptions: PopupOptions // export let value: Doc export let showIcon = true export let fullSize = false + export let isLoading = false const dispatch = createEventDispatcher() @@ -42,7 +43,8 @@ } }) let download: HTMLAnchorElement - $: src = getFileUrl(file, 'full', name) + $: src = file === undefined ? '' : getFileUrl(file, 'full', name) + $: isImage = contentType !== undefined && contentType.startsWith('image/') </script> <ActionContext context={{ mode: 'browser' }} /> @@ -67,24 +69,36 @@ </svelte:fragment> <svelte:fragment slot="utils"> - <a class="no-line" href={src} download={name} bind:this={download}> - <Button - icon={Download} - kind={'ghost'} - on:click={() => { - download.click() - }} - showTooltip={{ label: presentation.string.Download }} - /> - </a> + {#if !isLoading && isImage && src !== ''} + <a class="no-line" href={src} download={name} bind:this={download}> + <Button + icon={Download} + kind={'ghost'} + on:click={() => { + download.click() + }} + showTooltip={{ label: presentation.string.Download }} + /> + </a> + {/if} </svelte:fragment> - {#if contentType && contentType.startsWith('image/')} - <div class="pdfviewer-content img"> - <img class="img-fit" {src} alt="" /> - </div> + {#if !isLoading} + {#if src === ''} + <div class="centered"> + <Label label={presentation.string.FailedToPreview} /> + </div> + {:else if isImage} + <div class="pdfviewer-content img"> + <img class="img-fit" {src} alt="" /> + </div> + {:else} + <iframe class="pdfviewer-content" src={src + '#view=FitH&navpanes=0'} title="" /> + {/if} {:else} - <iframe class="pdfviewer-content" src={src + '#view=FitH&navpanes=0'} title="" /> + <div class="centered"> + <Spinner size="medium" /> + </div> {/if} </Dialog> @@ -124,4 +138,12 @@ max-height: 100%; object-fit: contain; } + .centered { + flex-grow: 1; + width: 100; + height: 100; + display: flex; + justify-content: center; + align-items: center; + } </style> diff --git a/packages/presentation/src/plugin.ts b/packages/presentation/src/plugin.ts index 70f8615840..aca8b50ae0 100644 --- a/packages/presentation/src/plugin.ts +++ b/packages/presentation/src/plugin.ts @@ -71,7 +71,8 @@ export default plugin(presentationId, { OpenInANewTab: '' as IntlString, Created: '' as IntlString, NoResults: '' as IntlString, - Next: '' as IntlString + Next: '' as IntlString, + FailedToPreview: '' as IntlString }, metadata: { RequiredVersion: '' as Metadata<string>, diff --git a/plugins/guest-resources/src/components/CreatePublicLink.svelte b/plugins/guest-resources/src/components/CreatePublicLink.svelte index 8663eb7b88..9abaeb0539 100644 --- a/plugins/guest-resources/src/components/CreatePublicLink.svelte +++ b/plugins/guest-resources/src/components/CreatePublicLink.svelte @@ -14,7 +14,7 @@ --> <script lang="ts"> import { Doc, Timestamp } from '@hcengineering/core' - import { PublicLink } from '@hcengineering/guest' + import { PublicLink, createPublicLink } from '@hcengineering/guest' import presentaion, { Card, MessageBox, @@ -22,7 +22,7 @@ createQuery, getClient } from '@hcengineering/presentation' - import { Button, Loading, Location, showPopup, ticker } from '@hcengineering/ui' + import { Button, Loading, showPopup, ticker } from '@hcengineering/ui' import view from '@hcengineering/view' import { getObjectLinkFragment } from '@hcengineering/view-resources' import { createEventDispatcher } from 'svelte' @@ -37,26 +37,11 @@ const dispatch = createEventDispatcher() - async function createLink (location: Location, revokable: boolean = true): Promise<void> { - await client.createDoc(guest.class.PublicLink, guest.space.Links, { - attachedTo: value._id, - location, - revokable, - restrictions: { - readonly: true, - disableNavigation: true, - disableActions: true, - disableComments: true - }, - url: '' - }) - } - async function generate (object: Doc): Promise<void> { const panelComponent = client.getHierarchy().classHierarchyMixin(object._class, view.mixin.ObjectPanel) const comp = panelComponent?.component ?? view.component.EditDoc const loc = await getObjectLinkFragment(client.getHierarchy(), object, {}, comp) - await createLink(loc) + await createPublicLink(client, value, loc) } async function checkNeedGenerate (value: Doc, loading: boolean, link: PublicLink | undefined): Promise<void> { diff --git a/plugins/guest/src/index.ts b/plugins/guest/src/index.ts index 00a125f16f..f35cefc94b 100644 --- a/plugins/guest/src/index.ts +++ b/plugins/guest/src/index.ts @@ -3,6 +3,8 @@ import type { Asset, Plugin } from '@hcengineering/platform' import { plugin } from '@hcengineering/platform' import { AnyComponent, Location } from '@hcengineering/ui' +export * from './utils' + export interface PublicLink extends Doc { attachedTo: Ref<Doc> url: string diff --git a/plugins/guest/src/utils.ts b/plugins/guest/src/utils.ts new file mode 100644 index 0000000000..41f754920f --- /dev/null +++ b/plugins/guest/src/utils.ts @@ -0,0 +1,28 @@ +// +// Copyright © 2024 Hardcore Engineering Inc. +// + +import { Doc, TxOperations } from '@hcengineering/core' +import { type Location } from '@hcengineering/ui' + +import guest from './index' + +export async function createPublicLink ( + client: TxOperations, + object: Doc, + location: Location, + revokable: boolean = true +): Promise<void> { + await client.createDoc(guest.class.PublicLink, guest.space.Links, { + attachedTo: object._id, + location, + revokable, + restrictions: { + readonly: true, + disableNavigation: true, + disableActions: true, + disableComments: true + }, + url: '' + }) +}