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 0000000000..36d1549eaf Binary files /dev/null and b/scm-ui/ui-components/src/__resources__/doc.pdf differ 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 = (