diff --git a/src/components/MainPage/MainRight/FileMosaicImageVideoPreviews.tsx b/src/components/MainPage/MainRight/FileMosaicImageVideoPreviews.tsx index 7834c69b7ee8829618c73372fdbb7443caa23445..a3c990ad865d6d2f79092ca12c0ea97bcf0db15a 100644 --- a/src/components/MainPage/MainRight/FileMosaicImageVideoPreviews.tsx +++ b/src/components/MainPage/MainRight/FileMosaicImageVideoPreviews.tsx @@ -40,6 +40,7 @@ const FileMosaicImageVideoPreviews: React.FC< fileId: FileMosaicProps["id"], downloadUrl?: string ) => { + console.log("Download fileId", fileId); console.log("Download fileName", files.filter((x) => x.id === fileId)[0]); console.log("Download downloadUrl", downloadUrl); diff --git a/src/components/demo-components/demo-download/CodeDemoDownload.tsx b/src/components/demo-components/demo-download/CodeDemoDownload.tsx new file mode 100644 index 0000000000000000000000000000000000000000..cb31934ba5d2a2d25e42dbfa15f8bfcf4389e92a --- /dev/null +++ b/src/components/demo-components/demo-download/CodeDemoDownload.tsx @@ -0,0 +1,67 @@ +import * as React from "react"; +import ShowDemoCode from "../../show-demo-code/ShowDemoCode"; + +const CodeDemoDownload1 = (props: { card?: boolean }) => { + const { card } = props; + return ( + <ShowDemoCode + codeCompleteJS={completeCodeJS} + codeCompleteTS={completeCodeTS} + codeSandboxJS="https://codesandbox.io/s/dropzone-ui-basic-3j01v" + codeSandboxTS="https://codesandbox.io/s/dropzone-ui-basic-3j01v" + codeSplittedJS={splittedCodeJS} + codeSplittedTS={splittedCodeTS} + /> + ); +}; +export default CodeDemoDownload1; + +const splittedCodeJS = ``; +const splittedCodeTS = ``; + +const completeCodeJS = `import * as React from "react"; +import { FileCard, FileMosaic } from "@files-ui/react"; + +const outsideDownloadUrl = "https://steamuserimages-a.akamaihd.net/ugc/964219647714510750/C4D97B0E1ECCE3E8A505AFBC8EAD8945E2223C41/?imw=5000&imh=5000&ima=fit&impolicy=Letterbox&imcolor=%23000000&letterbox=false"; + +const sampleFile = { + size: 28 * 1024 * 1024, + type: "image/jpeg", + name: "Thor.jpeg", + imageUrl: outsideDownloadUrl, + downloadUrl: outsideDownloadUrl, +}; + +const DemoDownloadDifferentOriginDownloadUrl = () => { + return ( + <> + <FileMosaic id={4} {...sampleFile} /> + <FileCard id={4} {...sampleFile} /> + </> + ); +}; +export default DemoDownloadDifferentOriginDownloadUrl;`; + + +const completeCodeTS = `import * as React from "react"; +import { FileCard, FileMosaic, ExtFile } from "../../../files-ui"; + +const outsideDownloadUrl = "https://steamuserimages-a.akamaihd.net/ugc/964219647714510750/C4D97B0E1ECCE3E8A505AFBC8EAD8945E2223C41/?imw=5000&imh=5000&ima=fit&impolicy=Letterbox&imcolor=%23000000&letterbox=false"; + +const sampleFile: ExtFile = { + size: 28 * 1024 * 1024, + type: "image/jpeg", + name: "Thor.jpeg", + imageUrl: outsideDownloadUrl, + downloadUrl: outsideDownloadUrl, +}; + +const DemoDownloadDifferentOriginDownloadUrl = () => { + return ( + <> + <FileMosaic id={4} {...sampleFile} /> + <FileCard id={4} {...sampleFile} /> + </> + ); +}; +export default DemoDownloadDifferentOriginDownloadUrl;`; diff --git a/src/components/demo-components/demo-download/CodeDemoDownload1.tsx b/src/components/demo-components/demo-download/CodeDemoDownload1.tsx new file mode 100644 index 0000000000000000000000000000000000000000..e0065bcbd6e4fa1158f6fd3ab9e165e46f6a2fef --- /dev/null +++ b/src/components/demo-components/demo-download/CodeDemoDownload1.tsx @@ -0,0 +1,63 @@ +import * as React from "react"; +import ShowDemoCode from "../../show-demo-code/ShowDemoCode"; + +const CodeDemoDownload1 = (props: { card?: boolean }) => { + const { card } = props; + return ( + <ShowDemoCode + codeCompleteJS={completeCodeJS} + codeCompleteTS={completeCodeTS} + codeSandboxJS="https://codesandbox.io/s/dropzone-ui-basic-3j01v" + codeSandboxTS="https://codesandbox.io/s/dropzone-ui-basic-3j01v" + codeSplittedJS={splittedCodeJS} + codeSplittedTS={splittedCodeTS} + /> + ); +}; +export default CodeDemoDownload1; + +const splittedCodeJS = ``; +const splittedCodeTS = ``; + +const completeCodeJS = `import * as React from "react"; +import { FileCard, FileMosaic } from "@files-ui/react"; + +const sampleFile = { + size: 28 * 1024 * 1024, + type: "video/mp4", + name: "NarutoAndSasukevsMomoshiiki.mp4", +}; + +const VIDEO_URL = "/videodemo/NarutoEN.mp4"; + +const DemoDownloadSameOrigin = () => { + return ( + <> + <FileMosaic id={4} {...sampleFile} downloadUrl={VIDEO_URL} /> + <FileCard id={4} {...sampleFile} downloadUrl={VIDEO_URL} /> + </> + ); +}; +export default DemoDownloadSameOrigin;`; + + +const completeCodeTS = `import * as React from "react"; +import { FileCard, FileMosaic, ExtFile } from "../../../files-ui"; + +const sampleFile: ExtFile = { + size: 28 * 1024 * 1024, + type: "video/mp4", + name: "NarutoAndSasukevsMomoshiiki.mp4", +}; + +const VIDEO_URL = "/videodemo/NarutoEN.mp4"; + +const DemoDownloadSameOrigin = () => { + return ( + <> + <FileMosaic id={4} {...sampleFile} downloadUrl={VIDEO_URL} /> + <FileCard id={4} {...sampleFile} downloadUrl={VIDEO_URL} /> + </> + ); +}; +export default DemoDownloadSameOrigin;`; diff --git a/src/components/demo-components/demo-download/CodeDemoDownload3.tsx b/src/components/demo-components/demo-download/CodeDemoDownload3.tsx new file mode 100644 index 0000000000000000000000000000000000000000..9c5f6fd1d41c1fabd88905625ec672e9e8cf125e --- /dev/null +++ b/src/components/demo-components/demo-download/CodeDemoDownload3.tsx @@ -0,0 +1,116 @@ +import * as React from "react"; +import ShowDemoCode from "../../show-demo-code/ShowDemoCode"; + +const CodeDemoDownload1 = (props: { card?: boolean }) => { + const { card } = props; + return ( + <ShowDemoCode + codeCompleteJS={completeCodeJS} + codeCompleteTS={completeCodeTS} + codeSandboxJS="https://codesandbox.io/s/dropzone-ui-basic-3j01v" + codeSandboxTS="https://codesandbox.io/s/dropzone-ui-basic-3j01v" + codeSplittedJS={splittedCodeJS} + codeSplittedTS={splittedCodeTS} + /> + ); +}; +export default CodeDemoDownload1; + +const splittedCodeJS = ``; +const splittedCodeTS = ``; + +const completeCodeJS = `import * as React from "react"; +import { FileCard, FileMosaic } from "@files-ui/react"; + +const outsideDownloadUrl = + "https://steamuserimages-a.akamaihd.net/ugc/964219647714510750/C4D97B0E1ECCE3E8A505AFBC8EAD8945E2223C41/?imw=5000&imh=5000&ima=fit&impolicy=Letterbox&imcolor=%23000000&letterbox=false"; + +const sampleFile = { + size: 28 * 1024 * 1024, + type: "image/jpeg", + name: "Thor.jpeg", + imageUrl: outsideDownloadUrl, + downloadUrl: outsideDownloadUrl, +}; + +const DemoDownloadDifferentOriginOnDownload = () => { + const handleDownload = async (fileId, downloadUrl) => { + console.log("Download fileId", fileId); + console.log("Download downloadUrl", downloadUrl); + if (!downloadUrl) return; + try { + const image = await fetch(downloadUrl); + const imageBlob = await image.blob(); + const imageURL = URL.createObjectURL(imageBlob); + + const anchor = document.createElement("a"); + anchor.href = imageURL; + anchor.download = sampleFile.name || "newFile.jpeg"; + + document.body.appendChild(anchor); + anchor.click(); + document.body.removeChild(anchor); + URL.revokeObjectURL(imageURL); + } catch (error) { + console.log("Download error", error); + console.error(error); + } + }; + return ( + <> + <FileMosaic id={4} {...sampleFile} onDownload={handleDownload} /> + <FileCard id={4} {...sampleFile} onDownload={handleDownload} /> + </> + ); +}; +export default DemoDownloadDifferentOriginOnDownload;`; + + +const completeCodeTS = `import * as React from "react"; +import { FileCard, FileMosaic, ExtFile } from "../../../files-ui"; + +const outsideDownloadUrl = + "https://steamuserimages-a.akamaihd.net/ugc/964219647714510750/C4D97B0E1ECCE3E8A505AFBC8EAD8945E2223C41/?imw=5000&imh=5000&ima=fit&impolicy=Letterbox&imcolor=%23000000&letterbox=false"; + +const sampleFile: ExtFile = { + size: 28 * 1024 * 1024, + type: "image/jpeg", + name: "Thor.jpeg", + imageUrl: outsideDownloadUrl, + downloadUrl: outsideDownloadUrl, +}; + +const DemoDownloadDifferentOriginOnDownload = () => { + const handleDownload = async ( + fileId: string | number | undefined, + downloadUrl?: string | undefined + ) => { + console.log("Download fileId", fileId); + console.log("Download downloadUrl", downloadUrl); + if (!downloadUrl) return; + try { + const image = await fetch(downloadUrl); + const imageBlob = await image.blob(); + const imageURL = URL.createObjectURL(imageBlob); + + const anchor = document.createElement("a"); + anchor.href = imageURL; + anchor.download = sampleFile.name || "newFile.jpeg"; + + document.body.appendChild(anchor); + anchor.click(); + document.body.removeChild(anchor); + URL.revokeObjectURL(imageURL); + } catch (error) { + console.log("Download error", error); + console.error(error); + } + }; + return ( + <> + <FileMosaic id={4} {...sampleFile} onDownload={handleDownload} /> + <FileCard id={4} {...sampleFile} onDownload={handleDownload} /> + </> + ); +}; +export default DemoDownloadDifferentOriginOnDownload;`; diff --git a/src/components/demo-components/demo-download/DemoDownload1.tsx b/src/components/demo-components/demo-download/DemoDownload1.tsx new file mode 100644 index 0000000000000000000000000000000000000000..ce45e9e2639c5653636e55b49c01b13b870d2017 --- /dev/null +++ b/src/components/demo-components/demo-download/DemoDownload1.tsx @@ -0,0 +1,20 @@ +import * as React from "react"; +import { FileCard, FileMosaic, ExtFile } from "../../../files-ui"; + +const sampleFile: ExtFile = { + size: 28 * 1024 * 1024, + type: "video/mp4", + name: "NarutoAndSasukevsMomoshiiki.mp4", +}; + +const VIDEO_URL = "/videodemo/NarutoEN.mp4"; + +const DemoDownloadSameOrigin = () => { + return ( + <> + <FileMosaic id={4} {...sampleFile} downloadUrl={VIDEO_URL} /> + <FileCard id={4} {...sampleFile} downloadUrl={VIDEO_URL} /> + </> + ); +}; +export default DemoDownloadSameOrigin; diff --git a/src/components/demo-components/demo-download/DemoDownload2.tsx b/src/components/demo-components/demo-download/DemoDownload2.tsx new file mode 100644 index 0000000000000000000000000000000000000000..91abeed6d408366d9cd9ec18ab33f6279d985bfb --- /dev/null +++ b/src/components/demo-components/demo-download/DemoDownload2.tsx @@ -0,0 +1,22 @@ +import * as React from "react"; +import { FileCard, FileMosaic, ExtFile } from "../../../files-ui"; + +const outsideDownloadUrl = "https://steamuserimages-a.akamaihd.net/ugc/964219647714510750/C4D97B0E1ECCE3E8A505AFBC8EAD8945E2223C41/?imw=5000&imh=5000&ima=fit&impolicy=Letterbox&imcolor=%23000000&letterbox=false"; + +const sampleFile: ExtFile = { + size: 28 * 1024 * 1024, + type: "image/jpeg", + name: "Thor.jpeg", + imageUrl: outsideDownloadUrl, + downloadUrl: outsideDownloadUrl, +}; + +const DemoDownloadDifferentOriginDownloadUrl = () => { + return ( + <> + <FileMosaic id={4} {...sampleFile} /> + <FileCard id={4} {...sampleFile} /> + </> + ); +}; +export default DemoDownloadDifferentOriginDownloadUrl; diff --git a/src/components/demo-components/demo-download/DemoDownload3.tsx b/src/components/demo-components/demo-download/DemoDownload3.tsx new file mode 100644 index 0000000000000000000000000000000000000000..847d23b3783483cbac8885f44a4d251264cf9e9c --- /dev/null +++ b/src/components/demo-components/demo-download/DemoDownload3.tsx @@ -0,0 +1,48 @@ +import * as React from "react"; +import { FileCard, FileMosaic, ExtFile } from "../../../files-ui"; + +const outsideDownloadUrl = + "https://steamuserimages-a.akamaihd.net/ugc/964219647714510750/C4D97B0E1ECCE3E8A505AFBC8EAD8945E2223C41/?imw=5000&imh=5000&ima=fit&impolicy=Letterbox&imcolor=%23000000&letterbox=false"; + +const sampleFile: ExtFile = { + size: 28 * 1024 * 1024, + type: "image/jpeg", + name: "Thor.jpeg", + imageUrl: outsideDownloadUrl, + downloadUrl: outsideDownloadUrl, +}; + +const DemoDownloadDifferentOriginOnDownload = () => { + const handleDownload = async ( + fileId: string | number | undefined, + downloadUrl?: string | undefined + ) => { + console.log("Download fileId", fileId); + console.log("Download downloadUrl", downloadUrl); + if (!downloadUrl) return; + try { + const image = await fetch(downloadUrl); + const imageBlob = await image.blob(); + const imageURL = URL.createObjectURL(imageBlob); + + const anchor = document.createElement("a"); + anchor.href = imageURL; + anchor.download = sampleFile.name || "newFile.jpeg"; + + document.body.appendChild(anchor); + anchor.click(); + document.body.removeChild(anchor); + URL.revokeObjectURL(imageURL); + } catch (error) { + console.log("Download error", error); + console.error(error); + } + }; + return ( + <> + <FileMosaic id={4} {...sampleFile} onDownload={handleDownload} /> + <FileCard id={4} {...sampleFile} onDownload={handleDownload} /> + </> + ); +}; +export default DemoDownloadDifferentOriginOnDownload; diff --git a/src/pages/download-page/FileDownloadPage.jsx b/src/pages/download-page/FileDownloadPage.jsx deleted file mode 100644 index 526488aaf1c7c5c93d004bd6fa2af970819c58b2..0000000000000000000000000000000000000000 --- a/src/pages/download-page/FileDownloadPage.jsx +++ /dev/null @@ -1,44 +0,0 @@ -import * as React from "react"; -import MainContentContainer from "../../components/layout-pages/MainContentContainer"; -import MainLayoutPage from "../../components/layout-pages/MainLayoutPage"; -import RightMenuContainer from "../../components/layout-pages/RightMenuContainer"; -import MainTitle from "../../components/main-title/MainTitle"; -import MainParagraph from "../../components/paragraph-main/MainParagraph"; -import RightMenu from "../../components/RightMenu/RightMenu"; - -const FileDownloadPage = (props) => { - return ( - <React.Fragment> - <MainLayoutPage selectedIndex={9}> - <MainContentContainer> - <MainTitle>File Download</MainTitle> - <MainParagraph> - API reference docs for all the important types related to files UI - components. - </MainParagraph> - </MainContentContainer> - </MainLayoutPage> -<section> - -</section> - <RightMenuContainer> - <RightMenu width="240px" items={rightMenuItems} /> - </RightMenuContainer> - </React.Fragment> - ); -}; -export default FileDownloadPage; - -const rightMenuItems = [ - { - id: 0, - label: "Same host", - referTo: "/file-download#samehost", - }, - { - id: 1, - label: "Another host", - referTo: "/file-download#anotherhost", - }, - -]; diff --git a/src/pages/download-page/FileDownloadPage.tsx b/src/pages/download-page/FileDownloadPage.tsx new file mode 100644 index 0000000000000000000000000000000000000000..25cf729c525ad8398d6721146dc762c58aa7fc97 --- /dev/null +++ b/src/pages/download-page/FileDownloadPage.tsx @@ -0,0 +1,193 @@ +import { Paper } from "@mui/material"; +import * as React from "react"; +import CodeHighlight from "../../components/codeHighlight/CodeHighlight"; +import CodeDemoDownload2 from "../../components/demo-components/demo-download/CodeDemoDownload"; +import CodeDemoDownload1 from "../../components/demo-components/demo-download/CodeDemoDownload1"; +import CodeDemoDownload3 from "../../components/demo-components/demo-download/CodeDemoDownload3"; +import DemoDownload1 from "../../components/demo-components/demo-download/DemoDownload1"; +import DemoDownload2 from "../../components/demo-components/demo-download/DemoDownload2"; +import DemoDownload3 from "../../components/demo-components/demo-download/DemoDownload3"; +import DescParagraph from "../../components/demo-components/desc-paragraph/DescParagraph"; +import SubTitle from "../../components/demo-components/sub-title/SubTitle"; +import MainContentContainer from "../../components/layout-pages/MainContentContainer"; +import MainLayoutPage from "../../components/layout-pages/MainLayoutPage"; +import RightMenuContainer from "../../components/layout-pages/RightMenuContainer"; +import MainTitle from "../../components/main-title/MainTitle"; +import MainParagraph from "../../components/paragraph-main/MainParagraph"; +import RightMenu from "../../components/RightMenu/RightMenu"; +import AnchorToTab from "../../components/util-components/AnchorToTab"; + +const FileDownloadPage = () => { + return ( + <React.Fragment> + <MainLayoutPage selectedIndex={9}> + <MainContentContainer> + <MainTitle>File Download</MainTitle> + <MainParagraph> + In this page you will find some demos for downloading files with{" "} + <CodeHighlight>{"<FileMosaic/>"}</CodeHighlight>{" "} + and {" "} + <CodeHighlight>{"<FileCard/>"}</CodeHighlight>{" "} + components. + </MainParagraph> + <section id="samehost"> + <SubTitle content="Same origin URL" /> + <DescParagraph> + When only <CodeHighlight>downloadUrl</CodeHighlight> is specified, + FileMosaic will perform the download only for{" "} + <AnchorToTab href="https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy"> + same-origin URLs + </AnchorToTab>{" "} + since it uses the{" "} + <AnchorToTab href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#attributes"> + anchor + </AnchorToTab>{" "} + tag under the hood. + </DescParagraph> + <Paper + variant="outlined" + style={{ + padding: "25px", + display: "flex", + alignItems: "center", + justifyContent: "space-evenly", + width: "100%", + }} + > + <DemoDownload1 /> + </Paper> + <CodeDemoDownload1 /> + </section> + <section id="differenthost1"> + <SubTitle content="Different origin URL and 'downloadUrl' prop specified" /> + <DescParagraph> + When only <CodeHighlight>downloadUrl</CodeHighlight> is specified + and if the resource is located in any other host (on Stean for + instance), the component will open a new tab and display the + content. + </DescParagraph> + <Paper + variant="outlined" + style={{ + padding: "25px", + display: "flex", + alignItems: "center", + justifyContent: "space-evenly", + width: "100%", + }} + > + <DemoDownload2 /> + </Paper> + <CodeDemoDownload2 /> + </section> + <section id="differenthost2"> + <SubTitle content="Different origin URL and 'onDownload' prop specified" /> + <DescParagraph> + For avoiding the behaviour described above, you can do you own + download implementation by overriding the download function by + setting the <CodeHighlight>onDownload</CodeHighlight> prop. There + is an example of how to do it with pure javascript. + <br /> + The approach we use here can be summerized in 5 steps: + <ol> + <li> + Make a GET request with{" "} + <AnchorToTab href="https://developer.mozilla.org/en-US/docs/Web/API/fetch"> + fetch + </AnchorToTab>{" "} + (you can use{" "} + <AnchorToTab href="https://axios-http.com/"> + axios + </AnchorToTab>{" "} + or any other way to fetch + </li> + <li> + Create an{" "} + <AnchorToTab href="https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL"> + Object URL + </AnchorToTab>{" "} + from the{" "} + <AnchorToTab href="https://developer.mozilla.org/en-US/docs/Web/API/Blob"> + Blob + </AnchorToTab>{" "} + file. + </li> + <li> + Create an{" "} + <AnchorToTab href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#attributes"> + anchor tag + </AnchorToTab>{" "} + set the attributes, append it to the document, and click it + programatically. + </li> + <li> + Finally, revoke the Object URL and remove the anchor from + document. + </li> + </ol> + resources) + </DescParagraph> + <Paper + variant="outlined" + style={{ + padding: "25px", + display: "flex", + alignItems: "center", + justifyContent: "space-evenly", + width: "100%", + }} + > + <DemoDownload3 /> + </Paper> + <CodeDemoDownload3 /> + </section>{" "} + <section id="api"> + <SubTitle content="API" /> + <DescParagraph> + See the documentation below for a complete reference to all of the + props available to the components mentioned here. + </DescParagraph> + <ul> + <li> + <AnchorToTab href="/api/filemosaic"> + {"<FileMosaic/>"} + </AnchorToTab> + </li> + <li> + <AnchorToTab href="/api/filecard">{"<FileCard/>"}</AnchorToTab> + </li> + </ul> + </section> + </MainContentContainer> + </MainLayoutPage> + + <RightMenuContainer> + <RightMenu width="240px" items={rightMenuItems} /> + </RightMenuContainer> + </React.Fragment> + ); +}; +export default FileDownloadPage; + +const rightMenuItems = [ + { + id: 0, + label: "Same host", + referTo: "/file-download#samehost", + }, + { + id: 1, + label: "Different host 1", + referTo: "/file-download#differenthost1", + }, + { + id: 2, + label: "Different host 2", + referTo: "/file-download#differenthost2", + }, + { + id: 3, + label: "Components API", + referTo: "/file-download#api", + }, +];