Update Khufu's file retrieval system
This commit is contained in:
parent
fe36970476
commit
79b381b302
10 changed files with 86 additions and 78 deletions
|
@ -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",
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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)}
|
||||
/>
|
||||
)}
|
||||
|
||||
<div className="stash">
|
||||
<StashUpload
|
||||
addFilebox={this.addFilebox.bind(this)}
|
||||
|
|
|
@ -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",
|
||||
})
|
||||
);
|
||||
};
|
|
@ -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 (
|
||||
<div className="drive-context-menu" style={this.styleCalc()}>
|
||||
<ul>
|
||||
<li onClick={this.infoClick.bind(this)}>
|
||||
<li>
|
||||
<FontAwesomeIcon icon={faInfoCircle} />
|
||||
{this.infoView()}
|
||||
</li>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
@import "global/colors", "global/fonts", "global/measurements",
|
||||
"global/animations";
|
||||
"global/animations", "global/zindex";
|
||||
html,
|
||||
body {
|
||||
margin-left: auto;
|
||||
|
|
4
src/stash/scss/global/_zindex.scss
Normal file
4
src/stash/scss/global/_zindex.scss
Normal file
|
@ -0,0 +1,4 @@
|
|||
$stashbarIndex: 200;
|
||||
$contextMenuIndex: 300;
|
||||
$fudIndex: 100;
|
||||
$downloadsIndex: 100;
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
.stashbar {
|
||||
width: 100%;
|
||||
z-index: 200;
|
||||
z-index: $stashbarIndex;
|
||||
}
|
||||
.stashbar-menu {
|
||||
width: 100%;
|
||||
|
|
Reference in a new issue