From 241dcb6f0c1dcaaf20d71bbfbc18c92449d43ba6 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Wed, 3 Nov 2021 14:47:14 +0100 Subject: [PATCH] Add viewer for pdf files (#1843) Adds an viewer for pdf files to the source code browser. --- gradle/changelog/pdfviewer.yaml | 2 + .../ui-components/src/PdfViewer.stories.tsx | 34 ++++++++++ scm-ui/ui-components/src/PdfViewer.tsx | 60 ++++++++++++++++++ .../ui-components/src/__resources__/doc.pdf | Bin 0 -> 13926 bytes scm-ui/ui-components/src/index.ts | 1 + .../ui-webapp/public/locales/de/commons.json | 3 + .../ui-webapp/public/locales/en/commons.json | 3 + .../repos/sources/containers/SourcesView.tsx | 4 +- 8 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 gradle/changelog/pdfviewer.yaml create mode 100644 scm-ui/ui-components/src/PdfViewer.stories.tsx create mode 100644 scm-ui/ui-components/src/PdfViewer.tsx create mode 100644 scm-ui/ui-components/src/__resources__/doc.pdf diff --git a/gradle/changelog/pdfviewer.yaml b/gradle/changelog/pdfviewer.yaml new file mode 100644 index 0000000000..98e0cdbf2b --- /dev/null +++ b/gradle/changelog/pdfviewer.yaml @@ -0,0 +1,2 @@ +- type: added + description: Viewer for pdf files ([#1843](https://github.com/scm-manager/scm-manager/pull/1843)) diff --git a/scm-ui/ui-components/src/PdfViewer.stories.tsx b/scm-ui/ui-components/src/PdfViewer.stories.tsx new file mode 100644 index 0000000000..300752c3f1 --- /dev/null +++ b/scm-ui/ui-components/src/PdfViewer.stories.tsx @@ -0,0 +1,34 @@ +/* + * MIT License + * + * Copyright (c) 2020-present Cloudogu GmbH and Contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +import React from "react"; +import PdfViewer from "./PdfViewer"; +// @ts-ignore no need to declare module for a single import +import pdf from "./__resources__/doc.pdf"; +import { storiesOf } from "@storybook/react"; + +storiesOf("PdfViewer", module) + .add("Simple", () => ) + .add("Error", () => ) + .add("Error with download URL", () => ); diff --git a/scm-ui/ui-components/src/PdfViewer.tsx b/scm-ui/ui-components/src/PdfViewer.tsx new file mode 100644 index 0000000000..8333398839 --- /dev/null +++ b/scm-ui/ui-components/src/PdfViewer.tsx @@ -0,0 +1,60 @@ +/* + * MIT License + * + * Copyright (c) 2020-present Cloudogu GmbH and Contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +import React, { FC } from "react"; +import { File, Link } from "@scm-manager/ui-types"; +import { Notification } from "@scm-manager/ui-components"; +import { Trans, useTranslation } from "react-i18next"; + +type Props = { + src: string | File; + download?: string | File; + height?: string; +}; + +const createHref = (src: string | File): string => { + if (typeof src === "string") { + return src; + } + return (src._links.self as Link).href; +}; + +const PdfViewer: FC = ({ src, download, height = "50rem" }) => { + const [t] = useTranslation("commons"); + const href = createHref(src); + const downloadHref = download ? createHref(download) : href; + return ( +
+ + + + Failed to display the document. Please download it from here. + + + +
+ ); +}; + +export default PdfViewer; diff --git a/scm-ui/ui-components/src/__resources__/doc.pdf b/scm-ui/ui-components/src/__resources__/doc.pdf new file mode 100644 index 0000000000000000000000000000000000000000..36d1549eaf7593cbe258588695bd6b067c6d7a4f GIT binary patch literal 13926 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 NURDGuDoJIj{|}tTRAT@D literal 0 HcmV?d00001 diff --git a/scm-ui/ui-components/src/index.ts b/scm-ui/ui-components/src/index.ts index 591503ed02..1fb5ef7e28 100644 --- a/scm-ui/ui-components/src/index.ts +++ b/scm-ui/ui-components/src/index.ts @@ -71,6 +71,7 @@ export { default as UserAutocomplete } from "./UserAutocomplete"; export { default as BranchSelector } from "./BranchSelector"; export { default as Breadcrumb } from "./Breadcrumb"; export { default as MarkdownView } from "./markdown/MarkdownView"; +export { default as PdfViewer } from "./PdfViewer"; export { default as SyntaxHighlighter } from "./SyntaxHighlighter"; export { default as ErrorBoundary } from "./ErrorBoundary"; export { default as OverviewPageActions } from "./OverviewPageActions"; diff --git a/scm-ui/ui-webapp/public/locales/de/commons.json b/scm-ui/ui-webapp/public/locales/de/commons.json index 4c5d0d9226..34bd11fa49 100644 --- a/scm-ui/ui-webapp/public/locales/de/commons.json +++ b/scm-ui/ui-webapp/public/locales/de/commons.json @@ -215,5 +215,8 @@ "copyTimestampTooltip": "Zeitstempel in Zwischenablage kopieren" } } + }, + "pdfViewer": { + "error": "Das Dokument konnte nicht angezeigt werden. Es kann <1>hier heruntergeladen werden." } } diff --git a/scm-ui/ui-webapp/public/locales/en/commons.json b/scm-ui/ui-webapp/public/locales/en/commons.json index 9c7a9de3b5..b6bbaf7615 100644 --- a/scm-ui/ui-webapp/public/locales/en/commons.json +++ b/scm-ui/ui-webapp/public/locales/en/commons.json @@ -216,5 +216,8 @@ "copyTimestampTooltip": "Copy Timestamp to Clipboard" } } + }, + "pdfViewer": { + "error": "Failed to display the document. Please download it from <1>here." } } diff --git a/scm-ui/ui-webapp/src/repos/sources/containers/SourcesView.tsx b/scm-ui/ui-webapp/src/repos/sources/containers/SourcesView.tsx index fb2e41ad78..d526248d40 100644 --- a/scm-ui/ui-webapp/src/repos/sources/containers/SourcesView.tsx +++ b/scm-ui/ui-webapp/src/repos/sources/containers/SourcesView.tsx @@ -28,7 +28,7 @@ import ImageViewer from "../components/content/ImageViewer"; import DownloadViewer from "../components/content/DownloadViewer"; import { ExtensionPoint } from "@scm-manager/ui-extensions"; import { File, Link, Repository } from "@scm-manager/ui-types"; -import { ErrorNotification, Loading } from "@scm-manager/ui-components"; +import { ErrorNotification, Loading, PdfViewer } from "@scm-manager/ui-components"; import SwitchableMarkdownViewer from "../components/content/SwitchableMarkdownViewer"; import styled from "styled-components"; import { useContentType } from "@scm-manager/ui-api"; @@ -69,6 +69,8 @@ const SourcesView: FC = ({ file, repository, revision }) => { sources = ; } else if (contentType.startsWith("text/")) { sources = ; + } else if (contentType.startsWith("application/pdf")) { + sources = ; } else { sources = (