From 339742b04b42433bac8fd57b0f0adede663f89da Mon Sep 17 00:00:00 2001 From: frikky Date: Fri, 17 Mar 2023 00:48:33 +0100 Subject: [PATCH] Fixed better File management --- frontend/src/views/Admin.jsx | 782 +---------------------------------- 1 file changed, 12 insertions(+), 770 deletions(-) diff --git a/frontend/src/views/Admin.jsx b/frontend/src/views/Admin.jsx index fd9af9ba..6283185c 100644 --- a/frontend/src/views/Admin.jsx +++ b/frontend/src/views/Admin.jsx @@ -1,13 +1,12 @@ import React, { useState, useEffect } from "react"; import { makeStyles } from "@material-ui/styles"; -import { useTheme } from "@material-ui/core/styles"; import { useNavigate, Link } from "react-router-dom"; import countries from "../components/Countries.jsx"; import CodeEditor from "../components/ShuffleCodeEditor.jsx"; import getLocalCodeData from "../components/ShuffleCodeEditor.jsx"; - +import theme from "../theme"; import AddIcon from "@mui/icons-material/Add"; import ClearIcon from '@mui/icons-material/Clear'; //import ToggleButton from '@mui/material/ToggleButton'; @@ -51,7 +50,6 @@ import { Autocomplete } from "@mui/material"; import { Edit as EditIcon, FileCopy as FileCopyIcon, - Publish as PublishIcon, SelectAll as SelectAllIcon, OpenInNew as OpenInNewIcon, CloudDownload as CloudDownloadIcon, @@ -77,6 +75,7 @@ import HandlePaymentNew from "../views/HandlePaymentNew.jsx"; import OrgHeader from "../components/OrgHeader.jsx"; import OrgHeaderexpanded from "../components/OrgHeaderexpanded.jsx"; import Billing from "../components/Billing.jsx"; +import Files from "../components/Files.jsx"; import { display, style } from "@mui/system"; const useStyles = makeStyles({ @@ -126,9 +125,7 @@ const FileCategoryInput = (props) => { const Admin = (props) => { const { globalUrl, userdata, serverside } = props; - var upload = ""; var to_be_copied = ""; - const theme = useTheme(); const classes = useStyles(); let navigate = useNavigate(); @@ -158,9 +155,6 @@ const Admin = (props) => { const [environments, setEnvironments] = React.useState([]); const [authentication, setAuthentication] = React.useState([]); const [schedules, setSchedules] = React.useState([]); - const [files, setFiles] = React.useState([]); - const [selectedNamespace, setSelectedNamespace] = React.useState("default"); - const [fileNamespaces, setFileNamespaces] = React.useState([]); const [selectedUser, setSelectedUser] = React.useState({}); const [newUsername, setNewUsername] = React.useState(""); const [newPassword, setNewPassword] = React.useState(""); @@ -192,7 +186,6 @@ const Admin = (props) => { const [dealList, setDealList] = React.useState([]); const [adminTab, setAdminTab] = React.useState(1); - const [fileContent, setFileContent] = React.useState(""); const [billingInfo, setBillingInfo] = React.useState({}); useEffect(() => { @@ -202,49 +195,7 @@ const Admin = (props) => { } }, [isDropzone]); - const isCloud = - window.location.host === "localhost:3002" || - window.location.host === "shuffler.io"; - - const [openEditor, setOpenEditor] = React.useState(false); - const [renderTextBox, setRenderTextBox] = React.useState(false); - const [openFileId, setOpenFileId] = React.useState(false); - const allowedFileTypes = ["txt", "py", "yaml", "yml","json", "html", "js", "csv",] - - const runUpdateText = (text) =>{ - fetch(`${globalUrl}/api/v1/files/${openFileId}/edit`, { - method: "PUT", - headers: { - "Content-Type": "application/json", - Accept: "application/json", - }, - body:text, - credentials: "include", - }).then((response) => { - if (response.status !== 200) { - console.log("Can't update file"); - } - return response.json(); - }) - //console.log(text); - } - - const handleKeyDown = (event) => { - if (event.key === 'Enter') { - - console.log('do validate') - console.log("new namespace name->",event.target.value); - fileNamespaces.push(event.target.value); - setSelectedNamespace(event.target.value); - setRenderTextBox(false); - } - if (event.key === 'Escape'){ // not working for some reasons - console.log('escape pressed') - setRenderTextBox(false); - } - - } - + const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io"; const get2faCode = (userId) => { fetch(`${globalUrl}/api/v1/users/${userId}/get2fa`, { @@ -1185,252 +1136,13 @@ const Admin = (props) => { }); }; - const handleFileUpload = (file_id, file) => { - //console.log("FILE: ", file_id, file) - fetch(`${globalUrl}/api/v1/files/${file_id}/upload`, { - method: "POST", - credentials: "include", - body: file, - }) - .then((response) => { - if (response.status !== 200 && response.status !== 201) { - console.log("Status not 200 for apps :O!"); - alert.error("File was created, but failed to upload."); - return; - } - - return response.json(); - }) - .then((responseJson) => { - //console.log("RESPONSE: ", responseJson) - //setFiles(responseJson) - }) - .catch((error) => { - alert.error(error.toString()); - }); - }; - - const handleCreateFile = (filename, file) => { - var data = { - filename: filename, - org_id: selectedOrganization.id, - workflow_id: "global", - }; - - if ( - selectedNamespace !== undefined && - selectedNamespace !== null && - selectedNamespace.length > 0 && - selectedNamespace !== "default" - ) { - data.namespace = selectedNamespace; - } - - fetch(globalUrl + "/api/v1/files/create", { - method: "POST", - headers: { - "Content-Type": "application/json", - Accept: "application/json", - }, - credentials: "include", - body: JSON.stringify(data), - }) - .then((response) => { - if (response.status !== 200) { - console.log("Status not 200 for apps :O!"); - return; - } - - return response.json(); - }) - .then((responseJson) => { - //console.log("RESP: ", responseJson) - if (responseJson.success === true) { - handleFileUpload(responseJson.id, file); - } else { - alert.error("Failed to upload file ", filename); - } - }) - .catch((error) => { - alert.error("Failed to upload file ", filename); - console.log(error.toString()); - }); - }; - - const getFiles = () => { - fetch(globalUrl + "/api/v1/files", { - method: "GET", - headers: { - "Content-Type": "application/json", - Accept: "application/json", - }, - credentials: "include", - }) - .then((response) => { - if (response.status !== 200) { - console.log("Status not 200 for apps :O!"); - return; - } - - return response.json(); - }) - .then((responseJson) => { - if (responseJson.files !== undefined && responseJson.files !== null) { - setFiles(responseJson.files); - } else { - setFiles([]); - } - - console.log("NAMESPACES: ", responseJson.namespaces); - if ( - responseJson.namespaces !== undefined && - responseJson.namespaces !== null - ) { - setFileNamespaces(responseJson.namespaces); - } - }) - .catch((error) => { - alert.error(error.toString()); - }); - }; - - const deleteFile = (file) => { - fetch(globalUrl + "/api/v1/files/" + file.id, { - method: "DELETE", - headers: { - "Content-Type": "application/json", - Accept: "application/json", - }, - credentials: "include", - }) - .then((response) => { - if (response.status !== 200) { - console.log("Status not 200 for file delete :O!"); - } - - return response.json(); - }) - .then((responseJson) => { - if (responseJson.success) { - alert.info("Successfully deleted file " + file.name); - } else if ( - responseJson.reason !== undefined && - responseJson.reason !== null - ) { - alert.error("Failed to delete file: " + responseJson.reason); - } - setTimeout(() => { - getFiles(); - }, 1500); - - console.log(responseJson); - }) - .catch((error) => { - alert.error(error.toString()); - }); - }; - - const readFileData = (file) => { - fetch(globalUrl + "/api/v1/files/" + file.id + "/content", { - method: "GET", - headers: { - "Content-Type": "application/json", - Accept: "application/json", - }, - credentials: "include", - }) - .then((response) => { - if (response.status !== 200) { - console.log("Status not 200 for file :O!"); - return ""; - } - return response.text(); - }) - .then((respdata) => { - // console.log("respdata ->", respdata); - // console.log("respdata type ->", typeof(respdata)); - - if (respdata.length === 0) { - alert.error("Failed getting file. Is it deleted?"); - return; - } - return respdata - }) - .then((responseData) => { - - setFileContent(responseData); - //console.log("filecontent state ",fileContent); - }) - .catch((error) => { - alert.error(error.toString()); - }); - }; - var localData = ""; // useEffect(() => { // console.log('confirm', fileContent); // }, [fileContent]) - const downloadFile = (file) => { - fetch(globalUrl + "/api/v1/files/" + file.id + "/content", { - method: "GET", - credentials: "include", - }) - .then((response) => { - if (response.status !== 200) { - console.log("Status not 200 for apps :O!"); - return ""; - } - - console.log("Resp: ", response) - - return response.blob() - }) - .then((respdata) => { - if (respdata.length === 0) { - alert.error("Failed getting file. Is it deleted?"); - return; - } - - var blob = new Blob([respdata], { - type: "application/octet-stream", - }); - - var url = URL.createObjectURL(blob); - var link = document.createElement("a"); - link.setAttribute("href", url); - link.setAttribute("download", `${file.filename}`); - var event = document.createEvent("MouseEvents"); - event.initMouseEvent( - "click", - true, - true, - window, - 1, - 0, - 0, - 0, - 0, - false, - false, - false, - false, - 0, - null - ); - link.dispatchEvent(event); - - //return response.json() - }) - .then((responseJson) => { - //console.log(responseJson) - //setSchedules(responseJson) - }) - .catch((error) => { - alert.error(error.toString()); - }); - }; + const getSchedules = () => { fetch(globalUrl + "/api/v1/workflows/schedules", { @@ -1620,7 +1332,6 @@ const Admin = (props) => { getAppAuthentication(); } else if (newValue === 3) { document.title = "Shuffle - admin - files"; - getFiles(); } else if (newValue === 4) { document.title = "Shuffle - admin - schedules"; getSchedules(); @@ -3774,484 +3485,15 @@ const Admin = (props) => { //setShow2faSetup(true); }; - const uploadFiles = (files) => { - for (var key in files) { - try { - const filename = files[key].name; - var filedata = new FormData(); - filedata.append("shuffle_file", files[key]); - - if (typeof files[key] === "object") { - handleCreateFile(filename, filedata); - } - - /* - reader.addEventListener('load', (e) => { - var data = e.target.result; - setIsDropzone(false) - console.log(filename) - console.log(data) - console.log(files[key]) - }) - reader.readAsText(files[key]) - */ - } catch (e) { - console.log("Error in dropzone: ", e); - } - } - - setTimeout(() => { - getFiles(); - }, 2500); - }; - - const uploadFile = (e) => { - const isDropzone = - e.dataTransfer === undefined ? false : e.dataTransfer.files.length > 0; - const files = isDropzone ? e.dataTransfer.files : e.target.files; - - //const reader = new FileReader(); - //alert.info("Starting fileupload") - uploadFiles(files); - }; - const filesView = - curTab === 3 ? ( - 1366 ? 1366 : 1200, - margin: "auto", - padding: 20, - }} - onDrop={uploadFile} - > -
-
-

Files

- - Files from Workflows.{" "} - - Learn more - - -
- - {/* */} - (upload = ref)} - onChange={(event) => { - //const file = event.target.value - //const fileObject = URL.createObjectURL(actualFile) - //setFile(fileObject) - //const files = event.target.files[0] - uploadFiles(event.target.files); - }} - /> - - - {fileNamespaces !== undefined && - fileNamespaces !== null && - fileNamespaces.length > 1 ? ( - - File Category - - - ) : null} -
- {renderTextBox ? - - - - - : - - - } - {renderTextBox && { - handleKeyDown(event); - }} - InputProps={{ - style: { - color: "white", - }, - }} - color="primary" - placeholder="File category name" - required - margin="dense" - defaultValue={""} - autoFocus - />}
- - - - - - - - - - - - - - - - {files === undefined || files === null || files.length === 0 - ? null - : files.map((file, index) => { - if (file.namespace === "") { - file.namespace = "default"; - } - - if (file.namespace !== selectedNamespace) { - return null; - } - - var bgColor = "#27292d"; - if (index % 2 === 0) { - bgColor = "#1f2023"; - } - - const filenamesplit = file.filename.split(".") - const iseditable = file.filesize < 100000 && file.status === "active" && allowedFileTypes.includes(filenamesplit[filenamesplit.length-1]) - - return ( - - - - - - - ) : ( - - - - - - - - - - ) - } - style={{ - minWidth: 100, - maxWidth: 100, - overflow: "hidden", - }} - /> - - - - - - - { - setOpenEditor(true) - setOpenFileId(file.id) - readFileData(file) - }} - > - - - - - - - { - downloadFile(file); - }} - > - - - - - - - { - deleteFile(file); - }} - > - - - - - - { - const elementName = "copy_element_shuffle"; - var copyText = - document.getElementById(elementName); - if ( - copyText !== null && - copyText !== undefined - ) { - const clipboard = navigator.clipboard; - if (clipboard === undefined) { - alert.error( - "Can only copy over HTTPS (port 3443)" - ); - return; - } - - navigator.clipboard.writeText(file.id); - copyText.select(); - copyText.setSelectionRange( - 0, - 99999 - ); /* For mobile devices */ - - /* Copy the text inside the text field */ - document.execCommand("copy"); - - alert.info(file.id + " copied to clipboard"); - } - }} - > - - - - - style={{ - minWidth: 250, - maxWidth: 250, - // overflow: "hidden", - }} - /> - - ); - })} - -
-
- ) : null; + const filesView = curTab !== 3 ? null : + const schedulesView = curTab === 4 ? ( @@ -4830,7 +4072,7 @@ const Admin = (props) => { const elementName = "copy_element_shuffle"; const auth = environment.auth === "" ? 'cb5st3d3Z!3X3zaJ*Pc' : environment.auth - const commandData = `docker run --volume "/var/run/docker.sock:/var/run/docker.sock" -e ENVIRONMENT_NAME="${environment.Name}" -e 'AUTH=${auth}' -e ORG="${props.userdata.active_org.id}" -e DOCKER_API_VERSION=1.40 -e BASE_URL="${globalUrl}" -d ghcr.io/shuffle/shuffle-orborus:latest` + const commandData = `docker run --volume "/var/run/docker.sock:/var/run/docker.sock" -e ENVIRONMENT_NAME="${environment.Name}" -e 'AUTH=${auth}' -e ORG="${props.userdata.active_org.id}" -e DOCKER_API_VERSION=1.40 -e BASE_URL="${globalUrl}" --name="shuffle-orborus" -d ghcr.io/shuffle/shuffle-orborus:latest` var copyText = document.getElementById(elementName); if (copyText !== null && copyText !== undefined) { const clipboard = navigator.clipboard;