Fixed better File management
This commit is contained in:
+12
-770
@@ -1,13 +1,12 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
|
|
||||||
import { makeStyles } from "@material-ui/styles";
|
import { makeStyles } from "@material-ui/styles";
|
||||||
import { useTheme } from "@material-ui/core/styles";
|
|
||||||
import { useNavigate, Link } from "react-router-dom";
|
import { useNavigate, Link } from "react-router-dom";
|
||||||
import countries from "../components/Countries.jsx";
|
import countries from "../components/Countries.jsx";
|
||||||
import CodeEditor from "../components/ShuffleCodeEditor.jsx";
|
import CodeEditor from "../components/ShuffleCodeEditor.jsx";
|
||||||
import getLocalCodeData from "../components/ShuffleCodeEditor.jsx";
|
import getLocalCodeData from "../components/ShuffleCodeEditor.jsx";
|
||||||
|
|
||||||
|
import theme from "../theme";
|
||||||
import AddIcon from "@mui/icons-material/Add";
|
import AddIcon from "@mui/icons-material/Add";
|
||||||
import ClearIcon from '@mui/icons-material/Clear';
|
import ClearIcon from '@mui/icons-material/Clear';
|
||||||
//import ToggleButton from '@mui/material/ToggleButton';
|
//import ToggleButton from '@mui/material/ToggleButton';
|
||||||
@@ -51,7 +50,6 @@ import { Autocomplete } from "@mui/material";
|
|||||||
import {
|
import {
|
||||||
Edit as EditIcon,
|
Edit as EditIcon,
|
||||||
FileCopy as FileCopyIcon,
|
FileCopy as FileCopyIcon,
|
||||||
Publish as PublishIcon,
|
|
||||||
SelectAll as SelectAllIcon,
|
SelectAll as SelectAllIcon,
|
||||||
OpenInNew as OpenInNewIcon,
|
OpenInNew as OpenInNewIcon,
|
||||||
CloudDownload as CloudDownloadIcon,
|
CloudDownload as CloudDownloadIcon,
|
||||||
@@ -77,6 +75,7 @@ import HandlePaymentNew from "../views/HandlePaymentNew.jsx";
|
|||||||
import OrgHeader from "../components/OrgHeader.jsx";
|
import OrgHeader from "../components/OrgHeader.jsx";
|
||||||
import OrgHeaderexpanded from "../components/OrgHeaderexpanded.jsx";
|
import OrgHeaderexpanded from "../components/OrgHeaderexpanded.jsx";
|
||||||
import Billing from "../components/Billing.jsx";
|
import Billing from "../components/Billing.jsx";
|
||||||
|
import Files from "../components/Files.jsx";
|
||||||
import { display, style } from "@mui/system";
|
import { display, style } from "@mui/system";
|
||||||
|
|
||||||
const useStyles = makeStyles({
|
const useStyles = makeStyles({
|
||||||
@@ -126,9 +125,7 @@ const FileCategoryInput = (props) => {
|
|||||||
const Admin = (props) => {
|
const Admin = (props) => {
|
||||||
const { globalUrl, userdata, serverside } = props;
|
const { globalUrl, userdata, serverside } = props;
|
||||||
|
|
||||||
var upload = "";
|
|
||||||
var to_be_copied = "";
|
var to_be_copied = "";
|
||||||
const theme = useTheme();
|
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
let navigate = useNavigate();
|
let navigate = useNavigate();
|
||||||
|
|
||||||
@@ -158,9 +155,6 @@ const Admin = (props) => {
|
|||||||
const [environments, setEnvironments] = React.useState([]);
|
const [environments, setEnvironments] = React.useState([]);
|
||||||
const [authentication, setAuthentication] = React.useState([]);
|
const [authentication, setAuthentication] = React.useState([]);
|
||||||
const [schedules, setSchedules] = 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 [selectedUser, setSelectedUser] = React.useState({});
|
||||||
const [newUsername, setNewUsername] = React.useState("");
|
const [newUsername, setNewUsername] = React.useState("");
|
||||||
const [newPassword, setNewPassword] = React.useState("");
|
const [newPassword, setNewPassword] = React.useState("");
|
||||||
@@ -192,7 +186,6 @@ const Admin = (props) => {
|
|||||||
const [dealList, setDealList] = React.useState([]);
|
const [dealList, setDealList] = React.useState([]);
|
||||||
const [adminTab, setAdminTab] = React.useState(1);
|
const [adminTab, setAdminTab] = React.useState(1);
|
||||||
|
|
||||||
const [fileContent, setFileContent] = React.useState("");
|
|
||||||
const [billingInfo, setBillingInfo] = React.useState({});
|
const [billingInfo, setBillingInfo] = React.useState({});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -202,49 +195,7 @@ const Admin = (props) => {
|
|||||||
}
|
}
|
||||||
}, [isDropzone]);
|
}, [isDropzone]);
|
||||||
|
|
||||||
const isCloud =
|
const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io";
|
||||||
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 get2faCode = (userId) => {
|
const get2faCode = (userId) => {
|
||||||
fetch(`${globalUrl}/api/v1/users/${userId}/get2fa`, {
|
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 = "";
|
var localData = "";
|
||||||
|
|
||||||
// useEffect(() => {
|
// useEffect(() => {
|
||||||
// console.log('confirm', fileContent);
|
// console.log('confirm', fileContent);
|
||||||
// }, [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 = () => {
|
const getSchedules = () => {
|
||||||
fetch(globalUrl + "/api/v1/workflows/schedules", {
|
fetch(globalUrl + "/api/v1/workflows/schedules", {
|
||||||
@@ -1620,7 +1332,6 @@ const Admin = (props) => {
|
|||||||
getAppAuthentication();
|
getAppAuthentication();
|
||||||
} else if (newValue === 3) {
|
} else if (newValue === 3) {
|
||||||
document.title = "Shuffle - admin - files";
|
document.title = "Shuffle - admin - files";
|
||||||
getFiles();
|
|
||||||
} else if (newValue === 4) {
|
} else if (newValue === 4) {
|
||||||
document.title = "Shuffle - admin - schedules";
|
document.title = "Shuffle - admin - schedules";
|
||||||
getSchedules();
|
getSchedules();
|
||||||
@@ -3774,484 +3485,15 @@ const Admin = (props) => {
|
|||||||
//setShow2faSetup(true);
|
//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 =
|
const filesView = curTab !== 3 ? null :
|
||||||
curTab === 3 ? (
|
<Files
|
||||||
<Dropzone
|
globalUrl={globalUrl}
|
||||||
style={{
|
userdata={userdata}
|
||||||
maxWidth: window.innerWidth > 1366 ? 1366 : 1200,
|
serverside={serverside}
|
||||||
margin: "auto",
|
selectedOrganization={selectedOrganization}
|
||||||
padding: 20,
|
/>
|
||||||
}}
|
|
||||||
onDrop={uploadFile}
|
|
||||||
>
|
|
||||||
<div>
|
|
||||||
<div style={{ marginTop: 20, marginBottom: 20 }}>
|
|
||||||
<h2 style={{ display: "inline" }}>Files</h2>
|
|
||||||
<span style={{ marginLeft: 25 }}>
|
|
||||||
Files from Workflows.{" "}
|
|
||||||
<a
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
href="https://shuffler.io/docs/organizations#files"
|
|
||||||
style={{ textDecoration: "none", color: "#f85a3e" }}
|
|
||||||
>
|
|
||||||
Learn more
|
|
||||||
</a>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<Button
|
|
||||||
color="primary"
|
|
||||||
variant="contained"
|
|
||||||
onClick={() => {
|
|
||||||
upload.click();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<PublishIcon /> Upload files
|
|
||||||
</Button>
|
|
||||||
{/* <FileCategoryInput
|
|
||||||
isSet={renderTextBox} /> */}
|
|
||||||
<input
|
|
||||||
hidden
|
|
||||||
type="file"
|
|
||||||
multiple
|
|
||||||
ref={(ref) => (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);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Button
|
|
||||||
style={{ marginLeft: 5, marginRight: 15 }}
|
|
||||||
variant="contained"
|
|
||||||
color="primary"
|
|
||||||
onClick={() => getFiles()}
|
|
||||||
>
|
|
||||||
<CachedIcon />
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
{fileNamespaces !== undefined &&
|
|
||||||
fileNamespaces !== null &&
|
|
||||||
fileNamespaces.length > 1 ? (
|
|
||||||
<FormControl style={{ minWidth: 150, maxWidth: 150 }}>
|
|
||||||
<InputLabel id="input-namespace-label">File Category</InputLabel>
|
|
||||||
<Select
|
|
||||||
labelId="input-namespace-select-label"
|
|
||||||
id="input-namespace-select-id"
|
|
||||||
style={{
|
|
||||||
color: "white",
|
|
||||||
minWidth: 150,
|
|
||||||
maxWidth: 150,
|
|
||||||
float: "right",
|
|
||||||
}}
|
|
||||||
value={selectedNamespace}
|
|
||||||
onChange={(event) => {
|
|
||||||
console.log("CHANGE NAMESPACE: ", event.target);
|
|
||||||
setSelectedNamespace(event.target.value);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{fileNamespaces.map((data, index) => {
|
|
||||||
return (
|
|
||||||
<MenuItem
|
|
||||||
key={index}
|
|
||||||
value={data}
|
|
||||||
style={{ color: "white" }}
|
|
||||||
>
|
|
||||||
{data}
|
|
||||||
</MenuItem>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</Select>
|
|
||||||
</FormControl>
|
|
||||||
) : null}
|
|
||||||
<div style={{display: "inline-flex", position:"relative"}}>
|
|
||||||
{renderTextBox ?
|
|
||||||
|
|
||||||
<Tooltip title={"Close"} style={{}} aria-label={""}>
|
|
||||||
<Button
|
|
||||||
style={{ marginLeft: 5, marginRight: 15 }}
|
|
||||||
color="primary"
|
|
||||||
onClick={() => {
|
|
||||||
setRenderTextBox(false);
|
|
||||||
console.log(" close clicked")
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ClearIcon/>
|
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
:
|
|
||||||
<Tooltip title={"Add new file category"} style={{}} aria-label={""}>
|
|
||||||
<Button
|
|
||||||
style={{ marginLeft: 5, marginRight: 15 }}
|
|
||||||
color="primary"
|
|
||||||
onClick={() => {
|
|
||||||
setRenderTextBox(true);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<AddIcon/>
|
|
||||||
</Button>
|
|
||||||
</Tooltip> }
|
|
||||||
{renderTextBox && <TextField
|
|
||||||
onKeyPress={(event)=>{
|
|
||||||
handleKeyDown(event);
|
|
||||||
}}
|
|
||||||
InputProps={{
|
|
||||||
style: {
|
|
||||||
color: "white",
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
color="primary"
|
|
||||||
placeholder="File category name"
|
|
||||||
required
|
|
||||||
margin="dense"
|
|
||||||
defaultValue={""}
|
|
||||||
autoFocus
|
|
||||||
/>}</div>
|
|
||||||
|
|
||||||
<CodeEditor
|
|
||||||
expansionModalOpen={openEditor}
|
|
||||||
setExpansionModalOpen={setOpenEditor}
|
|
||||||
setcodedata = {setFileContent}
|
|
||||||
codedata={fileContent}
|
|
||||||
isFileEditor = {true}
|
|
||||||
key = {fileContent} //https://reactjs.org/docs/reconciliation.html#recursing-on-children
|
|
||||||
runUpdateText = {runUpdateText}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Divider
|
|
||||||
style={{
|
|
||||||
marginTop: 20,
|
|
||||||
marginBottom: 20,
|
|
||||||
backgroundColor: theme.palette.inputColor,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<List>
|
|
||||||
<ListItem>
|
|
||||||
<ListItemText
|
|
||||||
primary="Updated"
|
|
||||||
style={{ maxWidth: 225, minWidth: 225 }}
|
|
||||||
/>
|
|
||||||
<ListItemText
|
|
||||||
primary="Name"
|
|
||||||
style={{
|
|
||||||
maxWidth: 150,
|
|
||||||
minWidth: 150,
|
|
||||||
overflow: "hidden",
|
|
||||||
marginLeft: 10,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<ListItemText
|
|
||||||
primary="Workflow"
|
|
||||||
style={{ maxWidth: 100, minWidth: 100, overflow: "hidden" }}
|
|
||||||
/>
|
|
||||||
<ListItemText
|
|
||||||
primary="Md5"
|
|
||||||
style={{ minWidth: 300, maxWidth: 300, overflow: "hidden" }}
|
|
||||||
/>
|
|
||||||
<ListItemText
|
|
||||||
primary="Status"
|
|
||||||
style={{ minWidth: 75, maxWidth: 75, marginLeft: 10 }}
|
|
||||||
/>
|
|
||||||
<ListItemText
|
|
||||||
primary="Filesize"
|
|
||||||
style={{ minWidth: 125, maxWidth: 125 }}
|
|
||||||
/>
|
|
||||||
<ListItemText primary="Actions" />
|
|
||||||
</ListItem>
|
|
||||||
{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 (
|
|
||||||
<ListItem
|
|
||||||
key={index}
|
|
||||||
style={{
|
|
||||||
backgroundColor: bgColor,
|
|
||||||
maxHeight: 100,
|
|
||||||
overflow: "hidden",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ListItemText
|
|
||||||
style={{
|
|
||||||
maxWidth: 225,
|
|
||||||
minWidth: 225,
|
|
||||||
overflow: "hidden",
|
|
||||||
}}
|
|
||||||
primary={new Date(file.updated_at * 1000).toISOString()}
|
|
||||||
/>
|
|
||||||
<ListItemText
|
|
||||||
style={{
|
|
||||||
maxWidth: 150,
|
|
||||||
minWidth: 150,
|
|
||||||
overflow: "hidden",
|
|
||||||
marginLeft: 10,
|
|
||||||
}}
|
|
||||||
primary={file.filename}
|
|
||||||
/>
|
|
||||||
<ListItemText
|
|
||||||
primary={
|
|
||||||
file.workflow_id === "global" ? (
|
|
||||||
<IconButton
|
|
||||||
disabled={file.workflow_id === "global"}
|
|
||||||
>
|
|
||||||
<OpenInNewIcon
|
|
||||||
style={{
|
|
||||||
color:
|
|
||||||
file.workflow_id !== "global"
|
|
||||||
? "white"
|
|
||||||
: "grey",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</IconButton>
|
|
||||||
) : (
|
|
||||||
<Tooltip
|
|
||||||
title={"Go to workflow"}
|
|
||||||
style={{}}
|
|
||||||
aria-label={"Download"}
|
|
||||||
>
|
|
||||||
<span>
|
|
||||||
<a
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
style={{
|
|
||||||
textDecoration: "none",
|
|
||||||
color: "#f85a3e",
|
|
||||||
}}
|
|
||||||
href={`/workflows/${file.workflow_id}`}
|
|
||||||
target="_blank"
|
|
||||||
>
|
|
||||||
<IconButton
|
|
||||||
disabled={file.workflow_id === "global"}
|
|
||||||
>
|
|
||||||
<OpenInNewIcon
|
|
||||||
style={{
|
|
||||||
color:
|
|
||||||
file.workflow_id !== "global"
|
|
||||||
? "white"
|
|
||||||
: "grey",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</IconButton>
|
|
||||||
</a>
|
|
||||||
</span>
|
|
||||||
</Tooltip>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
style={{
|
|
||||||
minWidth: 100,
|
|
||||||
maxWidth: 100,
|
|
||||||
overflow: "hidden",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<ListItemText
|
|
||||||
primary={file.md5_sum}
|
|
||||||
style={{
|
|
||||||
minWidth: 300,
|
|
||||||
maxWidth: 300,
|
|
||||||
overflow: "hidden",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<ListItemText
|
|
||||||
primary={file.status}
|
|
||||||
style={{
|
|
||||||
minWidth: 75,
|
|
||||||
maxWidth: 75,
|
|
||||||
overflow: "hidden",
|
|
||||||
marginLeft: 10,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<ListItemText
|
|
||||||
primary={file.filesize}
|
|
||||||
style={{
|
|
||||||
minWidth: 125,
|
|
||||||
maxWidth: 125,
|
|
||||||
overflow: "hidden",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<ListItemText
|
|
||||||
primary=<span style={{ display:"inline"}}>
|
|
||||||
<Tooltip
|
|
||||||
title={`Edit File (${allowedFileTypes.join(", ")})`}
|
|
||||||
style={{}}
|
|
||||||
aria-label={"Edit"}
|
|
||||||
>
|
|
||||||
<span>
|
|
||||||
<IconButton
|
|
||||||
disabled={!iseditable}
|
|
||||||
style = {{padding: "6px"}}
|
|
||||||
onClick={() => {
|
|
||||||
setOpenEditor(true)
|
|
||||||
setOpenFileId(file.id)
|
|
||||||
readFileData(file)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<EditIcon
|
|
||||||
style={{color: iseditable ? "white" : "grey",}}
|
|
||||||
/>
|
|
||||||
</IconButton>
|
|
||||||
</span>
|
|
||||||
</Tooltip>
|
|
||||||
<Tooltip
|
|
||||||
title={"Download file"}
|
|
||||||
style={{}}
|
|
||||||
aria-label={"Download"}
|
|
||||||
>
|
|
||||||
<span>
|
|
||||||
<IconButton
|
|
||||||
style = {{padding: "6px"}}
|
|
||||||
disabled={file.status !== "active"}
|
|
||||||
onClick={() => {
|
|
||||||
downloadFile(file);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<CloudDownloadIcon
|
|
||||||
style={{
|
|
||||||
color:
|
|
||||||
file.status === "active"
|
|
||||||
? "white"
|
|
||||||
: "grey",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</IconButton>
|
|
||||||
</span>
|
|
||||||
</Tooltip>
|
|
||||||
<Tooltip
|
|
||||||
title={"Delete file"}
|
|
||||||
style={{}}
|
|
||||||
aria-label={"Delete"}
|
|
||||||
>
|
|
||||||
<span>
|
|
||||||
<IconButton
|
|
||||||
disabled={file.status !== "active"}
|
|
||||||
style = {{padding: "6px"}}
|
|
||||||
onClick={() => {
|
|
||||||
deleteFile(file);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<DeleteIcon
|
|
||||||
style={{
|
|
||||||
color:
|
|
||||||
file.status === "active"
|
|
||||||
? "white"
|
|
||||||
: "grey",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</IconButton>
|
|
||||||
</span>
|
|
||||||
</Tooltip>
|
|
||||||
<Tooltip
|
|
||||||
title={"Copy file ID"}
|
|
||||||
style={{}}
|
|
||||||
aria-label={"copy"}
|
|
||||||
>
|
|
||||||
<IconButton
|
|
||||||
style = {{padding: "6px"}}
|
|
||||||
onClick={() => {
|
|
||||||
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");
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<FileCopyIcon style={{ color: "white" }} />
|
|
||||||
</IconButton>
|
|
||||||
</Tooltip>
|
|
||||||
</span>
|
|
||||||
style={{
|
|
||||||
minWidth: 250,
|
|
||||||
maxWidth: 250,
|
|
||||||
// overflow: "hidden",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</ListItem>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</List>
|
|
||||||
</div>
|
|
||||||
</Dropzone>
|
|
||||||
) : null;
|
|
||||||
|
|
||||||
const schedulesView =
|
const schedulesView =
|
||||||
curTab === 4 ? (
|
curTab === 4 ? (
|
||||||
@@ -4830,7 +4072,7 @@ const Admin = (props) => {
|
|||||||
|
|
||||||
const elementName = "copy_element_shuffle";
|
const elementName = "copy_element_shuffle";
|
||||||
const auth = environment.auth === "" ? 'cb5st3d3Z!3X3zaJ*Pc' : environment.auth
|
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);
|
var copyText = document.getElementById(elementName);
|
||||||
if (copyText !== null && copyText !== undefined) {
|
if (copyText !== null && copyText !== undefined) {
|
||||||
const clipboard = navigator.clipboard;
|
const clipboard = navigator.clipboard;
|
||||||
|
|||||||
Reference in New Issue
Block a user