From 79b381b3021cce9a8d4f58f6d0a68a4b55672960 Mon Sep 17 00:00:00 2001 From: Elijah Dunemask Date: Sat, 31 Jul 2021 17:56:04 +0000 Subject: [PATCH] Update Khufu's file retrieval system --- package.json | 5 +- src/App.js | 4 +- src/Stash.jsx | 77 +++++++++++++-------- src/setupProxy.js | 12 ---- src/stash/StashContextMenu.jsx | 54 +++++++-------- src/stash/scss/_global.scss | 2 +- src/stash/scss/global/_zindex.scss | 4 ++ src/stash/scss/stash/StashContextMenu.scss | 2 +- src/stash/scss/stash/StashUploadDialog.scss | 2 +- src/stash/scss/stash/Stashbar.scss | 2 +- 10 files changed, 86 insertions(+), 78 deletions(-) delete mode 100644 src/setupProxy.js create mode 100644 src/stash/scss/global/_zindex.scss diff --git a/package.json b/package.json index 08b48a4..b551e11 100644 --- a/package.json +++ b/package.json @@ -8,10 +8,7 @@ "@fortawesome/free-regular-svg-icons": "^5.15.3", "@fortawesome/free-solid-svg-icons": "^5.15.3", "@fortawesome/react-fontawesome": "^0.1.14", - "@testing-library/jest-dom": "^5.14.1", - "@testing-library/react": "^12.0.0", - "@testing-library/user-event": "^13.2.0", - "http-proxy-middleware": "^2.0.1", + "js-file-download": "^0.4.12", "react": "^17.0.2", "react-axios": "^2.0.5", "react-dom": "^17.0.2", diff --git a/src/App.js b/src/App.js index 764a057..98fddf0 100644 --- a/src/App.js +++ b/src/App.js @@ -5,7 +5,8 @@ import "react-toastify/dist/ReactToastify.css"; //Local Imports import Stash from "./Stash"; //Constants -const token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1dWlkIjoiYmVjYWNjNjdhNmRjLTBlN2QtMDBlNi1jYmVhLWVhZGNlYmUxIiwiaWF0IjoxNjI3MTcxMDU1LCJleHAiOjE2Mjk3NjMwNTV9.zqiHrYnJlB7ozwjMnpgVUsBAt9vfLHLICFgWB0MguLA" +const token = + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1dWlkIjoiYmVjYWNjNjdhNmRjLTBlN2QtMDBlNi1jYmVhLWVhZGNlYmUxIiwiaWF0IjoxNjI3MTcxMDU1LCJleHAiOjE2Mjk3NjMwNTV9.zqiHrYnJlB7ozwjMnpgVUsBAt9vfLHLICFgWB0MguLA"; localStorage.setItem("authToken", token); class App extends React.Component { render() { @@ -18,6 +19,7 @@ class App extends React.Component { newestOnTop={false} closeOnClick={true} rtl={false} + limit={3} pauseOnFocusLoss draggable pauseOnHover={false} diff --git a/src/Stash.jsx b/src/Stash.jsx index cde6c40..094c65b 100644 --- a/src/Stash.jsx +++ b/src/Stash.jsx @@ -11,26 +11,32 @@ import "./stash/scss/Stash.scss"; //Constants const filesUrl = `${serverAddress}/${serverUrls.GET.filesUrl}`; //Class -function getConfig() { - var authToken = localStorage.getItem("authToken"); - console.log({ headers: { authorization: `Bearer ${authToken}` } }); - return { - headers: { authorization: `Bearer ${authToken}`, withCredentials: true }, - }; -} -function buildFilebox(file, index) { - return { - file, - selected: false, - filtered: true, - position: index, - }; -} +const getConfig = () => ({ + headers: { + authorization: `Bearer ${localStorage.getItem("authToken")}`, + withCredentials: true, + }, +}); + +const buildFilebox = (file, index) => ({ + file, + selected: false, + filtered: true, + position: index, +}); +const buildDownload = (name, total) => ({ + name, + total, + completed: 0.01, + progress: 0.01, +}); + class Stash extends React.Component { constructor(props) { super(props); this.state = { fileBoxes: {}, + downloads: {}, contextMenu: null, }; } @@ -39,17 +45,13 @@ class Stash extends React.Component { axios .get(filesUrl, getConfig()) .then((res) => { - if (res.status === 401) { - console.log("Would redirect to login"); - return; - } - if (res.data === undefined || res.data.length === undefined) { - toast.error("Error Loading Files"); - return; - } + if (res.status === 401) return console.log("Would redirect to login"); + if (res.data === undefined || res.data.length === undefined) + return toast.error("Error Loading Files"); + var fileBoxes = {}; res.data.forEach((file, index) => { - fileBoxes[file.fileUuid] = buildFilebox(file, index); + fileBoxes[file._id] = buildFilebox(file, index); }); this.setState({ fileBoxes }); }) @@ -76,13 +78,29 @@ class Stash extends React.Component { addFilebox(file) { var fileBoxes = this.state.fileBoxes; - fileBoxes[file.fileUuid] = buildFilebox( - file, - Object.keys(fileBoxes).length - ); + fileBoxes[file._id] = buildFilebox(file, Object.keys(fileBoxes).length); this.setState({ fileBoxes }); } + startDownload(name, total) { + const downloads = this.state.downloads; + const key = `${Date.now()}-${name}`; + const download = buildDownload(name, total); + download.toast = toast.dark(name, { + progress: download.progress, + position: "bottom-right", + }); + downloads[key] = download; + this.setState({ downloads }); + return key; + } + + updateDownload(downloadId, completed, total) { + const downloads = this.state.downloads; + const progress = completed / total; + toast.update(downloads[downloadId].toast, { progress }); + } + removeDriveContextMenu() { if (this.state.contextMenu !== null) this.setState({ contextMenu: null }); } @@ -118,9 +136,10 @@ class Stash extends React.Component { fileBoxes={this.state.fileBoxes} fileBoxesChanged={this.fileBoxesChanged.bind(this)} getSelectedBoxes={this.getSelectedBoxes.bind(this)} + startDownload={this.startDownload.bind(this)} + updateDownload={this.updateDownload.bind(this)} /> )} -
{ - app.use( - "/api", - createProxyMiddleware({ - target: serverAddress, - changeOrigin: true, - logLevel: "silent", - }) - ); -}; diff --git a/src/stash/StashContextMenu.jsx b/src/stash/StashContextMenu.jsx index 9f6e017..d932117 100644 --- a/src/stash/StashContextMenu.jsx +++ b/src/stash/StashContextMenu.jsx @@ -2,6 +2,7 @@ import React from "react"; import axios from "axios"; import { toast } from "react-toastify"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import FileDownload from "js-file-download"; import { faInfoCircle, faFileDownload, @@ -16,7 +17,6 @@ import { serverUrls, serverAddress } from "./api.json"; const downloadUrl = `${serverAddress}/${serverUrls.POST.downloadUrl}`; const deleteUrl = `${serverAddress}/${serverUrls.POST.deleteUrl}`; const publicUrl = `${serverAddress}/${serverUrls.POST.publicUrl}`; -const rawUrl = `${serverAddress}/${serverUrls.GET.rawUrl}`; function getConfig() { var authToken = localStorage.getItem("authToken"); @@ -26,27 +26,19 @@ function getConfig() { export default class StashContextMenu extends React.Component { infoView() { var selectedCount = this.props.getSelectedBoxes().length; - if (selectedCount === 1) return "View"; - if (selectedCount > 1) return `${selectedCount} files selected`; + if (selectedCount > 0) return `${selectedCount} files selected`; return "No Files Selected"; } - infoClick(e) { - const selectedBoxes = this.props.getSelectedBoxes(); - if (selectedBoxes.length !== 1) return; - const file = selectedBoxes[0]; - let win = window.open(`${rawUrl}?target=${file}`); - if (!win || win.closed || typeof win.closed == "undefined") { - window.location = `${rawUrl}?target=${file}`; - } - } downloadClick() { const selectedBoxes = this.props.getSelectedBoxes(); //ZIPS ARE NOT SUPPORTED YET if (selectedBoxes.length > 1) return toast.error("Downloading multiple files is not yet supported!"); - else - return this.handleDownload(`${downloadUrl}?target=${selectedBoxes[0]}`); + return this.handleDownload( + `${downloadUrl}?target=${selectedBoxes[0]}`, + this.props.fileBoxes[selectedBoxes[0]].file + ); } deleteClick() { const selectedBoxes = this.props.getSelectedBoxes(); @@ -69,19 +61,28 @@ export default class StashContextMenu extends React.Component { toast.error("There was an issue making some files public!"); let fileBoxes = this.props.fileBoxes; selectedBoxes.forEach((selectedBoxId) => { - if (!failedFiles.includes(selectedBoxId)) { + if (failedFiles.includes(selectedBoxId)) + fileBoxes[selectedBoxId].selected = true; + else fileBoxes[selectedBoxId].file.public = !fileBoxes[selectedBoxId].file .public; - } else { - fileBoxes[selectedBoxId].selected = true; - } }); this.props.fileBoxesChanged(fileBoxes); } - handleDownload(url) { - let win = window.open(url); - if (!win || win.closed || typeof win.closed == "undefined") - window.location = url; + handleDownload(url, file) { + const downloadName = `${file.date}-${file.name}`; + const config = getConfig(); + config.method = "GET"; + config["Content-Type"] = "application/octet-stream"; + config.responseType = "blob"; + const downloadId = this.props.startDownload(file.name); + config.onDownloadProgress = (e) => + this.props.updateDownload(downloadId, e.loaded, e.total); + axios.request(url, config).then((response) => { + if (response.status !== 200) + return toast.error("There was an error downloading that!"); + FileDownload(response.data, downloadName); + }); } /** * Handles the response from the deleteClick() @@ -95,11 +96,8 @@ export default class StashContextMenu extends React.Component { if (res.status !== 200) toast.error("Error Deleting Some Files"); let fileBoxes = this.props.fileBoxes; selectedBoxes.forEach((selectedBoxId) => { - if (!failedFiles.includes(selectedBoxId)) { - delete fileBoxes[selectedBoxId]; - } else { - fileBoxes[selectedBoxId].selected = true; - } + if (!failedFiles.includes(selectedBoxId)) delete fileBoxes[selectedBoxId]; + else fileBoxes[selectedBoxId].selected = true; }); this.props.fileBoxesChanged(fileBoxes); } @@ -123,7 +121,7 @@ export default class StashContextMenu extends React.Component { return (
    -
  • +
  • {this.infoView()}
  • diff --git a/src/stash/scss/_global.scss b/src/stash/scss/_global.scss index 3c3bc04..1e17595 100644 --- a/src/stash/scss/_global.scss +++ b/src/stash/scss/_global.scss @@ -1,5 +1,5 @@ @import "global/colors", "global/fonts", "global/measurements", - "global/animations"; + "global/animations", "global/zindex"; html, body { margin-left: auto; diff --git a/src/stash/scss/global/_zindex.scss b/src/stash/scss/global/_zindex.scss new file mode 100644 index 0000000..ff98ce5 --- /dev/null +++ b/src/stash/scss/global/_zindex.scss @@ -0,0 +1,4 @@ +$stashbarIndex: 200; +$contextMenuIndex: 300; +$fudIndex: 100; +$downloadsIndex: 100; diff --git a/src/stash/scss/stash/StashContextMenu.scss b/src/stash/scss/stash/StashContextMenu.scss index a03b66d..f6d72e3 100644 --- a/src/stash/scss/stash/StashContextMenu.scss +++ b/src/stash/scss/stash/StashContextMenu.scss @@ -6,7 +6,7 @@ background: lighten($sectionMenuOptions, 10%); box-shadow: 1px 3px 2px lighten ($sectionMenuOptions, 5%); color: $foreground; - z-index: 300; + z-index: $contextMenuIndex; width: 100%; max-width: inherit; font-size: 1rem; diff --git a/src/stash/scss/stash/StashUploadDialog.scss b/src/stash/scss/stash/StashUploadDialog.scss index ba49789..b7cb990 100644 --- a/src/stash/scss/stash/StashUploadDialog.scss +++ b/src/stash/scss/stash/StashUploadDialog.scss @@ -16,7 +16,7 @@ $actionButtonSize: 25px; max-height: 250px; overflow: hidden; -webkit-transform: translate3d(0, 0, 0); - z-index: 100; + z-index: $fudIndex; display: block; visibility: hidden; } diff --git a/src/stash/scss/stash/Stashbar.scss b/src/stash/scss/stash/Stashbar.scss index afd6c2a..540e63a 100644 --- a/src/stash/scss/stash/Stashbar.scss +++ b/src/stash/scss/stash/Stashbar.scss @@ -2,7 +2,7 @@ .stashbar { width: 100%; - z-index: 200; + z-index: $stashbarIndex; } .stashbar-menu { width: 100%;