Update Khufu's file retrieval system

This commit is contained in:
Elijah Dunemask 2021-07-31 17:56:04 +00:00
parent fe36970476
commit 79b381b302
10 changed files with 86 additions and 78 deletions

View file

@ -8,10 +8,7 @@
"@fortawesome/free-regular-svg-icons": "^5.15.3", "@fortawesome/free-regular-svg-icons": "^5.15.3",
"@fortawesome/free-solid-svg-icons": "^5.15.3", "@fortawesome/free-solid-svg-icons": "^5.15.3",
"@fortawesome/react-fontawesome": "^0.1.14", "@fortawesome/react-fontawesome": "^0.1.14",
"@testing-library/jest-dom": "^5.14.1", "js-file-download": "^0.4.12",
"@testing-library/react": "^12.0.0",
"@testing-library/user-event": "^13.2.0",
"http-proxy-middleware": "^2.0.1",
"react": "^17.0.2", "react": "^17.0.2",
"react-axios": "^2.0.5", "react-axios": "^2.0.5",
"react-dom": "^17.0.2", "react-dom": "^17.0.2",

View file

@ -5,7 +5,8 @@ import "react-toastify/dist/ReactToastify.css";
//Local Imports //Local Imports
import Stash from "./Stash"; import Stash from "./Stash";
//Constants //Constants
const token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1dWlkIjoiYmVjYWNjNjdhNmRjLTBlN2QtMDBlNi1jYmVhLWVhZGNlYmUxIiwiaWF0IjoxNjI3MTcxMDU1LCJleHAiOjE2Mjk3NjMwNTV9.zqiHrYnJlB7ozwjMnpgVUsBAt9vfLHLICFgWB0MguLA" const token =
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1dWlkIjoiYmVjYWNjNjdhNmRjLTBlN2QtMDBlNi1jYmVhLWVhZGNlYmUxIiwiaWF0IjoxNjI3MTcxMDU1LCJleHAiOjE2Mjk3NjMwNTV9.zqiHrYnJlB7ozwjMnpgVUsBAt9vfLHLICFgWB0MguLA";
localStorage.setItem("authToken", token); localStorage.setItem("authToken", token);
class App extends React.Component { class App extends React.Component {
render() { render() {
@ -18,6 +19,7 @@ class App extends React.Component {
newestOnTop={false} newestOnTop={false}
closeOnClick={true} closeOnClick={true}
rtl={false} rtl={false}
limit={3}
pauseOnFocusLoss pauseOnFocusLoss
draggable draggable
pauseOnHover={false} pauseOnHover={false}

View file

@ -11,26 +11,32 @@ import "./stash/scss/Stash.scss";
//Constants //Constants
const filesUrl = `${serverAddress}/${serverUrls.GET.filesUrl}`; const filesUrl = `${serverAddress}/${serverUrls.GET.filesUrl}`;
//Class //Class
function getConfig() { const getConfig = () => ({
var authToken = localStorage.getItem("authToken"); headers: {
console.log({ headers: { authorization: `Bearer ${authToken}` } }); authorization: `Bearer ${localStorage.getItem("authToken")}`,
return { withCredentials: true,
headers: { authorization: `Bearer ${authToken}`, withCredentials: true }, },
}; });
}
function buildFilebox(file, index) { const buildFilebox = (file, index) => ({
return { file,
file, selected: false,
selected: false, filtered: true,
filtered: true, position: index,
position: index, });
}; const buildDownload = (name, total) => ({
} name,
total,
completed: 0.01,
progress: 0.01,
});
class Stash extends React.Component { class Stash extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
fileBoxes: {}, fileBoxes: {},
downloads: {},
contextMenu: null, contextMenu: null,
}; };
} }
@ -39,17 +45,13 @@ class Stash extends React.Component {
axios axios
.get(filesUrl, getConfig()) .get(filesUrl, getConfig())
.then((res) => { .then((res) => {
if (res.status === 401) { if (res.status === 401) return console.log("Would redirect to login");
console.log("Would redirect to login"); if (res.data === undefined || res.data.length === undefined)
return; return toast.error("Error Loading Files");
}
if (res.data === undefined || res.data.length === undefined) {
toast.error("Error Loading Files");
return;
}
var fileBoxes = {}; var fileBoxes = {};
res.data.forEach((file, index) => { res.data.forEach((file, index) => {
fileBoxes[file.fileUuid] = buildFilebox(file, index); fileBoxes[file._id] = buildFilebox(file, index);
}); });
this.setState({ fileBoxes }); this.setState({ fileBoxes });
}) })
@ -76,13 +78,29 @@ class Stash extends React.Component {
addFilebox(file) { addFilebox(file) {
var fileBoxes = this.state.fileBoxes; var fileBoxes = this.state.fileBoxes;
fileBoxes[file.fileUuid] = buildFilebox( fileBoxes[file._id] = buildFilebox(file, Object.keys(fileBoxes).length);
file,
Object.keys(fileBoxes).length
);
this.setState({ fileBoxes }); 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() { removeDriveContextMenu() {
if (this.state.contextMenu !== null) this.setState({ contextMenu: null }); if (this.state.contextMenu !== null) this.setState({ contextMenu: null });
} }
@ -118,9 +136,10 @@ class Stash extends React.Component {
fileBoxes={this.state.fileBoxes} fileBoxes={this.state.fileBoxes}
fileBoxesChanged={this.fileBoxesChanged.bind(this)} fileBoxesChanged={this.fileBoxesChanged.bind(this)}
getSelectedBoxes={this.getSelectedBoxes.bind(this)} getSelectedBoxes={this.getSelectedBoxes.bind(this)}
startDownload={this.startDownload.bind(this)}
updateDownload={this.updateDownload.bind(this)}
/> />
)} )}
<div className="stash"> <div className="stash">
<StashUpload <StashUpload
addFilebox={this.addFilebox.bind(this)} addFilebox={this.addFilebox.bind(this)}

View file

@ -1,12 +0,0 @@
const { createProxyMiddleware } = require("http-proxy-middleware");
const { serverAddress } = require("./stash/api.json");
module.exports = (app) => {
app.use(
"/api",
createProxyMiddleware({
target: serverAddress,
changeOrigin: true,
logLevel: "silent",
})
);
};

View file

@ -2,6 +2,7 @@ import React from "react";
import axios from "axios"; import axios from "axios";
import { toast } from "react-toastify"; import { toast } from "react-toastify";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import FileDownload from "js-file-download";
import { import {
faInfoCircle, faInfoCircle,
faFileDownload, faFileDownload,
@ -16,7 +17,6 @@ import { serverUrls, serverAddress } from "./api.json";
const downloadUrl = `${serverAddress}/${serverUrls.POST.downloadUrl}`; const downloadUrl = `${serverAddress}/${serverUrls.POST.downloadUrl}`;
const deleteUrl = `${serverAddress}/${serverUrls.POST.deleteUrl}`; const deleteUrl = `${serverAddress}/${serverUrls.POST.deleteUrl}`;
const publicUrl = `${serverAddress}/${serverUrls.POST.publicUrl}`; const publicUrl = `${serverAddress}/${serverUrls.POST.publicUrl}`;
const rawUrl = `${serverAddress}/${serverUrls.GET.rawUrl}`;
function getConfig() { function getConfig() {
var authToken = localStorage.getItem("authToken"); var authToken = localStorage.getItem("authToken");
@ -26,27 +26,19 @@ function getConfig() {
export default class StashContextMenu extends React.Component { export default class StashContextMenu extends React.Component {
infoView() { infoView() {
var selectedCount = this.props.getSelectedBoxes().length; var selectedCount = this.props.getSelectedBoxes().length;
if (selectedCount === 1) return "View"; if (selectedCount > 0) return `${selectedCount} files selected`;
if (selectedCount > 1) return `${selectedCount} files selected`;
return "No 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() { downloadClick() {
const selectedBoxes = this.props.getSelectedBoxes(); const selectedBoxes = this.props.getSelectedBoxes();
//ZIPS ARE NOT SUPPORTED YET //ZIPS ARE NOT SUPPORTED YET
if (selectedBoxes.length > 1) if (selectedBoxes.length > 1)
return toast.error("Downloading multiple files is not yet supported!"); return toast.error("Downloading multiple files is not yet supported!");
else return this.handleDownload(
return this.handleDownload(`${downloadUrl}?target=${selectedBoxes[0]}`); `${downloadUrl}?target=${selectedBoxes[0]}`,
this.props.fileBoxes[selectedBoxes[0]].file
);
} }
deleteClick() { deleteClick() {
const selectedBoxes = this.props.getSelectedBoxes(); 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!"); toast.error("There was an issue making some files public!");
let fileBoxes = this.props.fileBoxes; let fileBoxes = this.props.fileBoxes;
selectedBoxes.forEach((selectedBoxId) => { selectedBoxes.forEach((selectedBoxId) => {
if (!failedFiles.includes(selectedBoxId)) { if (failedFiles.includes(selectedBoxId))
fileBoxes[selectedBoxId].selected = true;
else
fileBoxes[selectedBoxId].file.public = !fileBoxes[selectedBoxId].file fileBoxes[selectedBoxId].file.public = !fileBoxes[selectedBoxId].file
.public; .public;
} else {
fileBoxes[selectedBoxId].selected = true;
}
}); });
this.props.fileBoxesChanged(fileBoxes); this.props.fileBoxesChanged(fileBoxes);
} }
handleDownload(url) { handleDownload(url, file) {
let win = window.open(url); const downloadName = `${file.date}-${file.name}`;
if (!win || win.closed || typeof win.closed == "undefined") const config = getConfig();
window.location = url; 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() * 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"); if (res.status !== 200) toast.error("Error Deleting Some Files");
let fileBoxes = this.props.fileBoxes; let fileBoxes = this.props.fileBoxes;
selectedBoxes.forEach((selectedBoxId) => { selectedBoxes.forEach((selectedBoxId) => {
if (!failedFiles.includes(selectedBoxId)) { if (!failedFiles.includes(selectedBoxId)) delete fileBoxes[selectedBoxId];
delete fileBoxes[selectedBoxId]; else fileBoxes[selectedBoxId].selected = true;
} else {
fileBoxes[selectedBoxId].selected = true;
}
}); });
this.props.fileBoxesChanged(fileBoxes); this.props.fileBoxesChanged(fileBoxes);
} }
@ -123,7 +121,7 @@ export default class StashContextMenu extends React.Component {
return ( return (
<div className="drive-context-menu" style={this.styleCalc()}> <div className="drive-context-menu" style={this.styleCalc()}>
<ul> <ul>
<li onClick={this.infoClick.bind(this)}> <li>
<FontAwesomeIcon icon={faInfoCircle} /> <FontAwesomeIcon icon={faInfoCircle} />
{this.infoView()} {this.infoView()}
</li> </li>

View file

@ -1,5 +1,5 @@
@import "global/colors", "global/fonts", "global/measurements", @import "global/colors", "global/fonts", "global/measurements",
"global/animations"; "global/animations", "global/zindex";
html, html,
body { body {
margin-left: auto; margin-left: auto;

View file

@ -0,0 +1,4 @@
$stashbarIndex: 200;
$contextMenuIndex: 300;
$fudIndex: 100;
$downloadsIndex: 100;

View file

@ -6,7 +6,7 @@
background: lighten($sectionMenuOptions, 10%); background: lighten($sectionMenuOptions, 10%);
box-shadow: 1px 3px 2px lighten ($sectionMenuOptions, 5%); box-shadow: 1px 3px 2px lighten ($sectionMenuOptions, 5%);
color: $foreground; color: $foreground;
z-index: 300; z-index: $contextMenuIndex;
width: 100%; width: 100%;
max-width: inherit; max-width: inherit;
font-size: 1rem; font-size: 1rem;

View file

@ -16,7 +16,7 @@ $actionButtonSize: 25px;
max-height: 250px; max-height: 250px;
overflow: hidden; overflow: hidden;
-webkit-transform: translate3d(0, 0, 0); -webkit-transform: translate3d(0, 0, 0);
z-index: 100; z-index: $fudIndex;
display: block; display: block;
visibility: hidden; visibility: hidden;
} }

View file

@ -2,7 +2,7 @@
.stashbar { .stashbar {
width: 100%; width: 100%;
z-index: 200; z-index: $stashbarIndex;
} }
.stashbar-menu { .stashbar-menu {
width: 100%; width: 100%;