Updated minor multi tenant issues
This commit is contained in:
@@ -24,11 +24,14 @@ import {
|
|||||||
Checkbox,
|
Checkbox,
|
||||||
MenuItem,
|
MenuItem,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
|
FormControl,
|
||||||
|
Select,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Link as LinkIcon,
|
Link as LinkIcon,
|
||||||
AutoFixHigh as AutoFixHighIcon,
|
AutoFixHigh as AutoFixHighIcon,
|
||||||
|
AutoFixNormal as AutoFixNormalIcon,
|
||||||
Edit as EditIcon,
|
Edit as EditIcon,
|
||||||
FileCopy as FileCopyIcon,
|
FileCopy as FileCopyIcon,
|
||||||
SelectAll as SelectAllIcon,
|
SelectAll as SelectAllIcon,
|
||||||
@@ -50,8 +53,8 @@ import {
|
|||||||
Business as BusinessIcon,
|
Business as BusinessIcon,
|
||||||
Visibility as VisibilityIcon,
|
Visibility as VisibilityIcon,
|
||||||
VisibilityOff as VisibilityOffIcon,
|
VisibilityOff as VisibilityOffIcon,
|
||||||
CheckBox,
|
Clear as ClearIcon,
|
||||||
Key,
|
Add as AddIcon,
|
||||||
} from "@mui/icons-material";
|
} from "@mui/icons-material";
|
||||||
import { validateJson, } from "../views/Workflows.jsx";
|
import { validateJson, } from "../views/Workflows.jsx";
|
||||||
import { Context } from "../context/ContextApi.jsx";
|
import { Context } from "../context/ContextApi.jsx";
|
||||||
@@ -91,15 +94,40 @@ const CacheView = memo((props) => {
|
|||||||
const [showDistributionPopup, setShowDistributionPopup] = useState(false);
|
const [showDistributionPopup, setShowDistributionPopup] = useState(false);
|
||||||
const [selectedSubOrg, setSelectedSubOrg] = useState([]);
|
const [selectedSubOrg, setSelectedSubOrg] = useState([]);
|
||||||
const [selectedCacheKey, setSelectedCacheKey] = useState("");
|
const [selectedCacheKey, setSelectedCacheKey] = useState("");
|
||||||
|
|
||||||
|
// Direct category migration from ../components/Files.jsx
|
||||||
|
const [selectAllChecked, setSelectAllChecked] = React.useState(false)
|
||||||
|
const [renderTextBox, setRenderTextBox] = React.useState(false);
|
||||||
|
const [fileCategories, setFileCategories] = React.useState(["default"]);
|
||||||
|
const [selectedCategory, setSelectedCategory] = React.useState("default");
|
||||||
|
const [selectedFileId, setSelectedFileId] = React.useState("");
|
||||||
|
const [updateToThisCategory, setUpdateToThisCategory] = useState("")
|
||||||
|
const [showFileCategoryPopup, setShowFileCategoryPopup] = React.useState(false);
|
||||||
|
const [selectedFiles, setSelectedFiles] = useState([]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if(orgId?.length >0){
|
if (orgId?.length > 0) {
|
||||||
listOrgCache(orgId);
|
listOrgCache(orgId, selectedCategory)
|
||||||
}
|
}
|
||||||
}, [orgId]);
|
}, [orgId])
|
||||||
|
|
||||||
|
const handleKeyDown = (event) => {
|
||||||
|
if (event.key === 'Enter') {
|
||||||
|
fileCategories.push(event.target.value);
|
||||||
|
setSelectedCategory(event.target.value);
|
||||||
|
setRenderTextBox(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.key === 'Escape'){ // not working for some reasons
|
||||||
|
console.log('escape pressed')
|
||||||
|
setRenderTextBox(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const listOrgCache = (orgId) => {
|
const listOrgCache = (orgId, category) => {
|
||||||
fetch(globalUrl + `/api/v1/orgs/${orgId}/list_cache`, {
|
const url = `${globalUrl}/api/v1/orgs/${orgId}/list_cache${category !== undefined ? `?category=${category.replaceAll(" ", "_")}` : ""}`
|
||||||
|
fetch(url, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
@@ -119,6 +147,19 @@ const CacheView = memo((props) => {
|
|||||||
if (responseJson.success === true) {
|
if (responseJson.success === true) {
|
||||||
setListCache(responseJson.keys);
|
setListCache(responseJson.keys);
|
||||||
setCachedLoaded(true);
|
setCachedLoaded(true);
|
||||||
|
|
||||||
|
if (fileCategories.length === 1 && fileCategories[0] === "default") {
|
||||||
|
var newcategories = ["default"]
|
||||||
|
for (var key in responseJson.keys) {
|
||||||
|
if (responseJson.keys[key].category !== undefined && responseJson.keys[key].category !== null && responseJson.keys[key].category !== "" && !fileCategories.includes(responseJson.keys[key].category)) {
|
||||||
|
newcategories.push(responseJson.keys[key].category);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("CATEGORIES: ", newcategories)
|
||||||
|
|
||||||
|
setFileCategories(newcategories)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (responseJson.cursor !== undefined && responseJson.cursor !== null && responseJson.cursor !== "") {
|
if (responseJson.cursor !== undefined && responseJson.cursor !== null && responseJson.cursor !== "") {
|
||||||
@@ -132,15 +173,12 @@ const CacheView = memo((props) => {
|
|||||||
|
|
||||||
|
|
||||||
const deleteCache = (orgId, key) => {
|
const deleteCache = (orgId, key) => {
|
||||||
//toast("Attempting to delete Cache");
|
|
||||||
|
|
||||||
// method: "DELETE",
|
|
||||||
const method = "POST"
|
const method = "POST"
|
||||||
//const url = `${globalUrl}/api/v1/orgs/${orgId}/cache/${key}`
|
|
||||||
const url = `${globalUrl}/api/v1/orgs/${orgId}/delete_cache`
|
const url = `${globalUrl}/api/v1/orgs/${orgId}/delete_cache`
|
||||||
const parsed = {
|
const parsed = {
|
||||||
"org_id": orgId,
|
"org_id": orgId,
|
||||||
"key": key,
|
"key": key,
|
||||||
|
"category": selectedCategory === "" || selectedCategory === "default" ? "" : selectedCategory,
|
||||||
}
|
}
|
||||||
|
|
||||||
fetch(url, {
|
fetch(url, {
|
||||||
@@ -155,7 +193,7 @@ const CacheView = memo((props) => {
|
|||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
toast("Successfully deleted Cache");
|
toast("Successfully deleted Cache");
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
listOrgCache(orgId);
|
listOrgCache(orgId, selectedCategory)
|
||||||
}, 1000);
|
}, 1000);
|
||||||
} else {
|
} else {
|
||||||
toast("Failed deleting Cache. Does it still exist?");
|
toast("Failed deleting Cache. Does it still exist?");
|
||||||
@@ -167,7 +205,12 @@ const CacheView = memo((props) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const editOrgCache = (orgId) => {
|
const editOrgCache = (orgId) => {
|
||||||
const cache = { key: dataValue.key , value: value };
|
const cache = {
|
||||||
|
key: dataValue.key,
|
||||||
|
value: value,
|
||||||
|
category: selectedCategory,
|
||||||
|
}
|
||||||
|
|
||||||
setCacheInput([cache]);
|
setCacheInput([cache]);
|
||||||
|
|
||||||
fetch(globalUrl + `/api/v1/orgs/${orgId}/set_cache`, {
|
fetch(globalUrl + `/api/v1/orgs/${orgId}/set_cache`, {
|
||||||
@@ -191,7 +234,7 @@ const CacheView = memo((props) => {
|
|||||||
.then((responseJson) => {
|
.then((responseJson) => {
|
||||||
setAddCache(responseJson);
|
setAddCache(responseJson);
|
||||||
toast("Cache Edited Successfully!");
|
toast("Cache Edited Successfully!");
|
||||||
listOrgCache(orgId);
|
listOrgCache(orgId, selectedCategory);
|
||||||
setModalOpen(false);
|
setModalOpen(false);
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
@@ -200,9 +243,13 @@ const CacheView = memo((props) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const addOrgCache = (orgId) => {
|
const addOrgCache = (orgId) => {
|
||||||
const cache = { key: key, value: value };
|
const cache = {
|
||||||
|
key: key,
|
||||||
|
value: value,
|
||||||
|
category: selectedCategory,
|
||||||
|
}
|
||||||
|
|
||||||
setCacheInput([cache]);
|
setCacheInput([cache]);
|
||||||
console.log("cache input:", cacheInput)
|
|
||||||
|
|
||||||
fetch(globalUrl + `/api/v1/orgs/${orgId}/set_cache`, {
|
fetch(globalUrl + `/api/v1/orgs/${orgId}/set_cache`, {
|
||||||
|
|
||||||
@@ -224,8 +271,8 @@ const CacheView = memo((props) => {
|
|||||||
})
|
})
|
||||||
.then((responseJson) => {
|
.then((responseJson) => {
|
||||||
setAddCache(responseJson);
|
setAddCache(responseJson);
|
||||||
toast("New key Added Successfully!");
|
toast("New key added Successfully!");
|
||||||
listOrgCache(orgId);
|
listOrgCache(orgId, selectedCategory);
|
||||||
setModalOpen(false);
|
setModalOpen(false);
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
@@ -243,7 +290,9 @@ const CacheView = memo((props) => {
|
|||||||
setValue(JSON.stringify(parsedjson, null, 2))
|
setValue(JSON.stringify(parsedjson, null, 2))
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log("Error parsing JSON: ", e)
|
console.log("Error parsing JSON: ", e)
|
||||||
//return JSON.stringify(inputvalue);
|
toast.info("Invalid JSON.", {
|
||||||
|
autoClose: 1500,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -306,13 +355,14 @@ const CacheView = memo((props) => {
|
|||||||
>
|
>
|
||||||
<DialogTitle>
|
<DialogTitle>
|
||||||
<span style={{ color: "white" }}>
|
<span style={{ color: "white" }}>
|
||||||
{ editCache ? "Edit Key" : "Add Key" }
|
{ editCache ? "Edit Key" : "Add Key"}{selectedCategory === "" || selectedCategory === "default" ? "" : ` in category '${selectedCategory}'`}
|
||||||
</span>
|
</span>
|
||||||
</DialogTitle>
|
</DialogTitle>
|
||||||
<div style={{ paddingLeft: "30px", paddingRight: '30px', backgroundColor: "#212121", }}>
|
<div style={{ paddingLeft: "30px", paddingRight: '30px', backgroundColor: "#212121", }}>
|
||||||
Key
|
Key
|
||||||
<TextField
|
<TextField
|
||||||
color="primary"
|
color="primary"
|
||||||
|
disabled={editCache}
|
||||||
style={{ backgroundColor: theme.palette.textFieldStyle.backgroundColor }}
|
style={{ backgroundColor: theme.palette.textFieldStyle.backgroundColor }}
|
||||||
autoFocus
|
autoFocus
|
||||||
InputProps={{
|
InputProps={{
|
||||||
@@ -345,7 +395,7 @@ const CacheView = memo((props) => {
|
|||||||
autoFixJson(value)
|
autoFixJson(value)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<AutoFixHighIcon />
|
<AutoFixNormalIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</div>
|
</div>
|
||||||
@@ -436,46 +486,49 @@ const CacheView = memo((props) => {
|
|||||||
|
|
||||||
const changeDistribution = (id, selectedSubOrg) => {
|
const changeDistribution = (id, selectedSubOrg) => {
|
||||||
|
|
||||||
editFileConfig(id, [...new Set(selectedSubOrg)])
|
editFileConfig(id, [...new Set(selectedSubOrg)], selectedCategory)
|
||||||
}
|
}
|
||||||
|
|
||||||
const editFileConfig = (id, selectedSubOrg, cacheKey) => {
|
|
||||||
const data = {
|
const editFileConfig = (id, selectedSubOrg, category) => {
|
||||||
Key: id,
|
const data = {
|
||||||
action: "suborg_distribute",
|
Key: id,
|
||||||
selected_suborgs: selectedSubOrg,
|
action: "suborg_distribute",
|
||||||
}
|
selected_suborgs: selectedSubOrg,
|
||||||
console.log("data: ", data);
|
category: category === undefined || category === "" || category === "default" ? "" : category,
|
||||||
|
}
|
||||||
const url = `${globalUrl}/api/v1/orgs/${orgId}/cache/config`;
|
|
||||||
|
console.log("data: ", data);
|
||||||
fetch(url, {
|
|
||||||
mode: "cors",
|
const url = `${globalUrl}/api/v1/orgs/${orgId}/cache/config`;
|
||||||
method: "POST",
|
|
||||||
body: JSON.stringify(data),
|
fetch(url, {
|
||||||
credentials: "include",
|
mode: "cors",
|
||||||
crossDomain: true,
|
method: "POST",
|
||||||
withCredentials: true,
|
body: JSON.stringify(data),
|
||||||
headers: {
|
credentials: "include",
|
||||||
"Content-Type": "application/json; charset=utf-8",
|
crossDomain: true,
|
||||||
},
|
withCredentials: true,
|
||||||
})
|
headers: {
|
||||||
.then((response) =>
|
"Content-Type": "application/json; charset=utf-8",
|
||||||
response.json().then((responseJson) => {
|
},
|
||||||
if (responseJson["success"] === false) {
|
})
|
||||||
toast("Failed overwriting datastore");
|
.then((response) =>
|
||||||
} else {
|
response.json().then((responseJson) => {
|
||||||
toast("Successfully updated datastore!");
|
if (responseJson["success"] === false) {
|
||||||
setTimeout(() => {
|
toast("Failed overwriting datastore");
|
||||||
listOrgCache(orgId);
|
} else {
|
||||||
setShowDistributionPopup(false);
|
toast("Successfully updated datastore!");
|
||||||
}, 1000);
|
setTimeout(() => {
|
||||||
}
|
listOrgCache(orgId, selectedCategory);
|
||||||
})
|
setShowDistributionPopup(false);
|
||||||
)
|
}, 1000);
|
||||||
.catch((error) => {
|
}
|
||||||
toast("Err: " + error.toString());
|
})
|
||||||
});
|
)
|
||||||
|
.catch((error) => {
|
||||||
|
toast("Err: " + error.toString());
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -579,7 +632,7 @@ const CacheView = memo((props) => {
|
|||||||
<div style={{height: "100%", maxHeight: 1700, overflowY: "auto", scrollbarColor: '#494949 transparent', scrollbarWidth: 'thin'}}>
|
<div style={{height: "100%", maxHeight: 1700, overflowY: "auto", scrollbarColor: '#494949 transparent', scrollbarWidth: 'thin'}}>
|
||||||
<div style={{ height: "100%", width: "calc(100% - 20px)", scrollbarColor: '#494949 transparent', scrollbarWidth: 'thin' }}>
|
<div style={{ height: "100%", width: "calc(100% - 20px)", scrollbarColor: '#494949 transparent', scrollbarWidth: 'thin' }}>
|
||||||
<div style={{ marginTop: isSelectedDataStore?null:20, marginBottom: 20 }}>
|
<div style={{ marginTop: isSelectedDataStore?null:20, marginBottom: 20 }}>
|
||||||
<h2 style={{ display: isSelectedDataStore?null: "inline" }}>Shuffle Datastore</h2>
|
<h2 style={{ display: isSelectedDataStore?null: "inline" }}>Shuffle Datastore {selectedCategory === "" || selectedCategory === "default" ? "" : `- Category '${selectedCategory}'`}</h2>
|
||||||
<span style={{ marginLeft: isSelectedDataStore?null:25, color:isSelectedDataStore?"#9E9E9E":null}}>
|
<span style={{ marginLeft: isSelectedDataStore?null:25, color:isSelectedDataStore?"#9E9E9E":null}}>
|
||||||
Datastore is a permanent key-value database for storing data that can be used cross-workflow. <br/>You can store anything from lists of IPs to complex configurations.
|
Datastore is a permanent key-value database for storing data that can be used cross-workflow. <br/>You can store anything from lists of IPs to complex configurations.
|
||||||
<a
|
<a
|
||||||
@@ -609,10 +662,175 @@ const CacheView = memo((props) => {
|
|||||||
style={{ marginLeft: 16, marginRight: 15, backgroundColor: isSelectedDataStore?"#2F2F2F":null, boxShadow: isSelectedDataStore ? "none":null,textTransform: isSelectedDataStore ? 'capitalize':null,borderRadius:isSelectedDataStore?4:null, width:isSelectedDataStore?81:null, height:isSelectedDataStore?40:null, }}
|
style={{ marginLeft: 16, marginRight: 15, backgroundColor: isSelectedDataStore?"#2F2F2F":null, boxShadow: isSelectedDataStore ? "none":null,textTransform: isSelectedDataStore ? 'capitalize':null,borderRadius:isSelectedDataStore?4:null, width:isSelectedDataStore?81:null, height:isSelectedDataStore?40:null, }}
|
||||||
variant="contained"
|
variant="contained"
|
||||||
color="primary"
|
color="primary"
|
||||||
onClick={() => listOrgCache(orgId)}
|
onClick={() => listOrgCache(orgId,selectedCategory)}
|
||||||
>
|
>
|
||||||
<CachedIcon />
|
<CachedIcon />
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
|
{fileCategories !== undefined &&
|
||||||
|
fileCategories !== null &&
|
||||||
|
fileCategories.length > 1 ? (
|
||||||
|
<FormControl style={{ minWidth: 150, maxWidth: 150 }}>
|
||||||
|
<Select
|
||||||
|
labelId="input-namespace-select-label"
|
||||||
|
id="input-namespace-select-id"
|
||||||
|
style={{
|
||||||
|
color: "white",
|
||||||
|
minWidth: 122,
|
||||||
|
maxWidth: 122,
|
||||||
|
height: 35,
|
||||||
|
float: "right",
|
||||||
|
position: 'relative',
|
||||||
|
top: 8
|
||||||
|
}}
|
||||||
|
value={selectedCategory}
|
||||||
|
onChange={(event) => {
|
||||||
|
//if (selectAllChecked || listCache.length > 0) {
|
||||||
|
if (selectAllChecked || selectedFiles.length > 0) {
|
||||||
|
setUpdateToThisCategory(event.target.value)
|
||||||
|
setShowFileCategoryPopup(true)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
setSelectedCategory(event.target.value)
|
||||||
|
if (event.target.value === "all" || event.target.value === "default") {
|
||||||
|
listOrgCache(orgId)
|
||||||
|
} else {
|
||||||
|
listOrgCache(orgId, event.target.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Add it to the url as a query
|
||||||
|
if (window.location.search.includes("category=")) {
|
||||||
|
const newurl = window.location.href.replace(/category=[^&]+/, `category=${event.target.value}`)
|
||||||
|
window.history.pushState({ path: newurl }, "", newurl)
|
||||||
|
} else {
|
||||||
|
window.history.pushState({ path: window.location.href }, "", `${window.location.href}&category=${event.target.value}`)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{fileCategories.map((data, index) => {
|
||||||
|
return (
|
||||||
|
<MenuItem
|
||||||
|
key={index}
|
||||||
|
value={data}
|
||||||
|
style={{ color: "white" }}
|
||||||
|
>
|
||||||
|
{data.replaceAll("_", " ")}
|
||||||
|
</MenuItem>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Select>
|
||||||
|
<Dialog
|
||||||
|
PaperProps={{
|
||||||
|
sx: {
|
||||||
|
borderRadius: theme?.palette?.DialogStyle?.borderRadius,
|
||||||
|
border: theme?.palette?.DialogStyle?.border,
|
||||||
|
fontFamily: theme?.typography?.fontFamily,
|
||||||
|
backgroundColor: theme?.palette?.DialogStyle?.backgroundColor,
|
||||||
|
zIndex: 1000,
|
||||||
|
'& .MuiDialogContent-root': {
|
||||||
|
backgroundColor: theme?.palette?.DialogStyle?.backgroundColor,
|
||||||
|
},
|
||||||
|
'& .MuiDialogTitle-root': {
|
||||||
|
backgroundColor: theme?.palette?.DialogStyle?.backgroundColor,
|
||||||
|
},
|
||||||
|
'& .MuiDialogActions-root': {
|
||||||
|
backgroundColor: theme?.palette?.DialogStyle?.backgroundColor,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
open={showFileCategoryPopup}
|
||||||
|
onClose={() => {
|
||||||
|
setShowFileCategoryPopup(false)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<DialogTitle>File Categories</DialogTitle>
|
||||||
|
<DialogContent>
|
||||||
|
Please note that your selected files ({selectedFileId?.length}) will be moved to the <kbd>{updateToThisCategory}</kbd> category.
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
setShowFileCategoryPopup(false)
|
||||||
|
}}
|
||||||
|
style={{fontSize: 16, textTransform: 'none'}}
|
||||||
|
>
|
||||||
|
Close
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
//handleUpdateFileCategory(updateToThisCategory)
|
||||||
|
toast.error("Not implemented.")
|
||||||
|
}}
|
||||||
|
style={{fontSize: 16, textTransform: 'none', color: "#1a1a1a", backgroundColor: "#ff8544"}}
|
||||||
|
>
|
||||||
|
Update
|
||||||
|
</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
|
</FormControl>
|
||||||
|
) : null}
|
||||||
|
|
||||||
|
<div style={{display: "inline-flex", position:"relative", top: 8}}>
|
||||||
|
{renderTextBox ?
|
||||||
|
<Tooltip title={"Close"} style={{}} aria-label={""}>
|
||||||
|
<Button
|
||||||
|
style={{ marginLeft: 5, marginRight: 15, height: 35, borderRadius: 4, backgroundColor: "#494949", textTransform: 'none', fontSize: 16, color: "#f1f1f1" }}
|
||||||
|
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, width: 169, height: 35, borderRadius: 4, backgroundColor: "#494949", textTransform: 'none', fontSize: 16, color: "#f1f1f1" }}
|
||||||
|
color="primary"
|
||||||
|
onClick={() => {
|
||||||
|
setRenderTextBox(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<AddIcon/>
|
||||||
|
Category (beta)
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
|
}
|
||||||
|
|
||||||
|
{renderTextBox && <TextField
|
||||||
|
onKeyPress={(event)=>{
|
||||||
|
handleKeyDown(event);
|
||||||
|
if(event.key === 'Enter' && selectedFileId.length > 0){
|
||||||
|
//setShowFileCategoryPopup(true)
|
||||||
|
setUpdateToThisCategory(event.target.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
height: 35,
|
||||||
|
width: 200,
|
||||||
|
marginTop: 0,
|
||||||
|
}}
|
||||||
|
InputProps={{
|
||||||
|
style: {
|
||||||
|
color: "white",
|
||||||
|
height: 35,
|
||||||
|
fontSize: 16,
|
||||||
|
borderRadius: 4,
|
||||||
|
paddingTop: 0,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
color="primary"
|
||||||
|
placeholder="Category name"
|
||||||
|
required
|
||||||
|
margin="dense"
|
||||||
|
defaultValue={""}
|
||||||
|
autoFocus
|
||||||
|
/>}</div>
|
||||||
{isSelectedDataStore? null :<Divider
|
{isSelectedDataStore? null :<Divider
|
||||||
style={{
|
style={{
|
||||||
marginTop: 20,
|
marginTop: 20,
|
||||||
@@ -704,6 +922,16 @@ const CacheView = memo((props) => {
|
|||||||
</ListItem>
|
</ListItem>
|
||||||
|
|
||||||
): listCache?.map((data, index) => {
|
): listCache?.map((data, index) => {
|
||||||
|
var category = selectedCategory
|
||||||
|
if (selectedCategory === "default") {
|
||||||
|
category = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data?.category === undefined && category === "") {
|
||||||
|
} else if (data?.category !== category) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
var bgColor = isSelectedDataStore? "#212121":"#27292d";
|
var bgColor = isSelectedDataStore? "#212121":"#27292d";
|
||||||
if (index % 2 === 0) {
|
if (index % 2 === 0) {
|
||||||
bgColor = isSelectedDataStore? "#1A1A1A":"#1f2023";
|
bgColor = isSelectedDataStore? "#1A1A1A":"#1f2023";
|
||||||
|
|||||||
@@ -1144,14 +1144,26 @@ const EditWorkflow = (props) => {
|
|||||||
</FormControl>
|
</FormControl>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<Divider style={{marginTop: 75, marginBottom: 75, }}/>
|
||||||
|
|
||||||
<Typography variant="h4" style={{ marginTop: 100, }}>
|
|
||||||
|
<Typography variant="h4" style={{ }}>
|
||||||
Publishing
|
Publishing
|
||||||
|
|
||||||
|
<Chip
|
||||||
|
style={{ marginLeft: 20, marginTop: 10, }}
|
||||||
|
color={workflow?.public === true ? "primary" : "secondary"}
|
||||||
|
variant={workflow?.public === true ? "default" : "outlined"}
|
||||||
|
label={workflow?.public === true ? "Public" : "NOT Public"}
|
||||||
|
/>
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="body2" color="textSecondary" style={{ marginTop: 10, }}>
|
<Typography variant="body2" color="textSecondary" style={{ marginTop: 10, }}>
|
||||||
Publishing is related to making the workflow itself public. When publishing a workflow, all the details (except sensitive info) become available to everyone. The details below will help a user understand this better. When a workflow is published, you keep the original, and a copy enters the workflow search, and is associated with your <a href="/creators" style={{ textDecoration: "none", color: "#f86a3e" }} target="_blank">creator account</a>, if you have one. You can always unpublish the workflow after. When ready to publish, click the three dots next to a workflow on the main workflow screen. After publishing, you can find it in the Shuffle search engine.
|
Publishing is related to making this workflow itself public. When publishing a workflow, all the details (except sensitive info) become available to anyone. The fields below will help a user and Shuffle's system understand your workflow better. When a workflow is published, you keep the original, and a copy enters the Shuffle workflow search, and is associated with your <a href="/creators" style={{ textDecoration: "none", color: "#f86a3e" }} target="_blank">creator</a> or partner account, if you have one. You can always unpublish the workflow after. When ready to publish, click the three dots next to a workflow on the main workflow page.
|
||||||
|
|
||||||
|
You can always unpublish a workflow after.
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
|
|
||||||
<LocalizationProvider style={{marginLeft: 0, }} dateAdapter={AdapterDayjs}>
|
<LocalizationProvider style={{marginLeft: 0, }} dateAdapter={AdapterDayjs}>
|
||||||
<DatePicker
|
<DatePicker
|
||||||
sx={{
|
sx={{
|
||||||
|
|||||||
@@ -89,7 +89,6 @@ const Files = memo((props) => {
|
|||||||
console.log('escape pressed')
|
console.log('escape pressed')
|
||||||
setRenderTextBox(false);
|
setRenderTextBox(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const changeDistribution = (id, selectedSubOrg) => {
|
const changeDistribution = (id, selectedSubOrg) => {
|
||||||
@@ -1051,6 +1050,7 @@ const Files = memo((props) => {
|
|||||||
</Dialog>
|
</Dialog>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
<div style={{display: "inline-flex", position:"relative", top: 8}}>
|
<div style={{display: "inline-flex", position:"relative", top: 8}}>
|
||||||
{renderTextBox ?
|
{renderTextBox ?
|
||||||
<Tooltip title={"Close"} style={{}} aria-label={""}>
|
<Tooltip title={"Close"} style={{}} aria-label={""}>
|
||||||
|
|||||||
@@ -28,7 +28,16 @@ import { validateJson, GetIconInfo } from "../views/Workflows.jsx";
|
|||||||
import theme from "../theme.jsx";
|
import theme from "../theme.jsx";
|
||||||
const itemHeight = 24
|
const itemHeight = 24
|
||||||
|
|
||||||
export const getParentNodes = (workflow, action) => {
|
export const getParentNodes = (workflow, action, count) => {
|
||||||
|
if (count === undefined) {
|
||||||
|
count = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// 50 levels of parent nodes
|
||||||
|
if (count > 50) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
if (action === undefined || action === null) {
|
if (action === undefined || action === null) {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
@@ -81,8 +90,7 @@ export const getParentNodes = (workflow, action) => {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: This part is only handling first level,
|
// FIXME: recursion
|
||||||
// but needs to recurse
|
|
||||||
var incomingEdges = []
|
var incomingEdges = []
|
||||||
for (var branchkey in workflow.branches) {
|
for (var branchkey in workflow.branches) {
|
||||||
const branch = workflow.branches[branchkey]
|
const branch = workflow.branches[branchkey]
|
||||||
@@ -90,13 +98,19 @@ export const getParentNodes = (workflow, action) => {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Go up in the levels
|
// FIXME: Go up in the levels
|
||||||
|
// This somehow creates infinite recursion for now, so
|
||||||
|
// we are skipping it.
|
||||||
|
// This function is also not used for cytoscape recursion,
|
||||||
|
// so it doesn't matter much (yet)
|
||||||
|
/*
|
||||||
const parents = getParentNodes(workflow, {
|
const parents = getParentNodes(workflow, {
|
||||||
id: branch.source_id,
|
id: branch.source_id,
|
||||||
})
|
}, count+1)
|
||||||
if (parents.length > 0) {
|
if (parents.length > 0) {
|
||||||
incomingEdges = incomingEdges.concat(parents)
|
incomingEdges = incomingEdges.concat(parents)
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
incomingEdges.push(branch)
|
incomingEdges.push(branch)
|
||||||
}
|
}
|
||||||
@@ -215,8 +229,6 @@ const WorkflowValidationTimeline = (props) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//const parents = getParentNodes(workflow, action)
|
|
||||||
//console.log("PARENTS", key, parents)
|
|
||||||
if (parents !== undefined && parents !== null && parents.length > 0) {
|
if (parents !== undefined && parents !== null && parents.length > 0) {
|
||||||
const parentfound = parents.find((element) => element.id === startnodeId)
|
const parentfound = parents.find((element) => element.id === startnodeId)
|
||||||
if (parentfound !== undefined) {
|
if (parentfound !== undefined) {
|
||||||
|
|||||||
@@ -574,7 +574,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
}, [editWorkflowModalOpen])
|
}, [editWorkflowModalOpen])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (selectedTrigger !== undefined && selectedTrigger.parameters !== undefined && selectedTrigger.parameters !== undefined && selectedTrigger.parameters.length > 1) {
|
if (selectedTrigger !== undefined && selectedTrigger?.parameters !== undefined && selectedTrigger?.parameters !== null && selectedTrigger?.parameters?.length > 1) {
|
||||||
// Right now just setting for the subflow
|
// Right now just setting for the subflow
|
||||||
setSelectedTriggerValue(selectedTrigger?.parameters[1]?.value)
|
setSelectedTriggerValue(selectedTrigger?.parameters[1]?.value)
|
||||||
}
|
}
|
||||||
@@ -4916,7 +4916,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
if (!branchFound) {
|
if (!branchFound) {
|
||||||
var relevantNodes = []
|
var relevantNodes = []
|
||||||
|
|
||||||
const minDistance = 225
|
const minDistance = 185
|
||||||
const draggedNode = event.target
|
const draggedNode = event.target
|
||||||
const allnodes = cy.nodes().jsons()
|
const allnodes = cy.nodes().jsons()
|
||||||
for (var nodekey in allnodes) {
|
for (var nodekey in allnodes) {
|
||||||
@@ -5481,6 +5481,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
// https://stackoverflow.com/questions/16677856/cy-onselect-callback-only-once
|
// https://stackoverflow.com/questions/16677856/cy-onselect-callback-only-once
|
||||||
// onNodeClick
|
// onNodeClick
|
||||||
const onNodeSelect = (event, newAppAuth) => {
|
const onNodeSelect = (event, newAppAuth) => {
|
||||||
|
|
||||||
// Forces all states to update at the same time,
|
// Forces all states to update at the same time,
|
||||||
// Otherwise everything is SUPER slow
|
// Otherwise everything is SUPER slow
|
||||||
|
|
||||||
@@ -5654,7 +5655,14 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReactDOM.unstable_batchedUpdates(() => {
|
ReactDOM.unstable_batchedUpdates(() => {
|
||||||
|
const selectedNodes = cy.$(':selected')
|
||||||
if (data.isButton) {
|
if (data.isButton) {
|
||||||
|
if (selectedNodes?.length > 1) {
|
||||||
|
event.target.unselect()
|
||||||
|
//console.log(": ", selectedNodes.length)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if (data.buttonType === "suggestion") {
|
if (data.buttonType === "suggestion") {
|
||||||
if (cy === undefined) {
|
if (cy === undefined) {
|
||||||
console.log("Cy not defined yet")
|
console.log("Cy not defined yet")
|
||||||
@@ -5894,6 +5902,14 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (data.type === "ACTION") {
|
if (data.type === "ACTION") {
|
||||||
|
if (selectedNodes?.length > 1) {
|
||||||
|
console.log("Unselecting ACTION due to multiple nodes selected")
|
||||||
|
setSelectedAction({})
|
||||||
|
setSelectedApp({})
|
||||||
|
setSelectedComment({})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
setSelectedComment({})
|
setSelectedComment({})
|
||||||
|
|
||||||
// FIXME: is this what is mapping it an actual action in the workflow? wtf?
|
// FIXME: is this what is mapping it an actual action in the workflow? wtf?
|
||||||
@@ -6241,6 +6257,14 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
setSelectedActionEnvironment(env);
|
setSelectedActionEnvironment(env);
|
||||||
}
|
}
|
||||||
} else if (data.type === "TRIGGER") {
|
} else if (data.type === "TRIGGER") {
|
||||||
|
if (selectedNodes?.length > 1) {
|
||||||
|
console.log("Unselecting ACTION due to multiple nodes selected")
|
||||||
|
setSelectedAction({})
|
||||||
|
setSelectedApp({})
|
||||||
|
setSelectedComment({})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
setSelectedComment({})
|
setSelectedComment({})
|
||||||
if (workflow.triggers === null) {
|
if (workflow.triggers === null) {
|
||||||
workflow.triggers = []
|
workflow.triggers = []
|
||||||
@@ -6442,6 +6466,14 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
//setSelectedActionEnvironment(data.env)
|
//setSelectedActionEnvironment(data.env)
|
||||||
}, 25)
|
}, 25)
|
||||||
} else if (data.type === "COMMENT") {
|
} else if (data.type === "COMMENT") {
|
||||||
|
if (selectedNodes?.length > 1) {
|
||||||
|
console.log("Unselecting ACTION due to multiple nodes selected")
|
||||||
|
setSelectedAction({})
|
||||||
|
setSelectedApp({})
|
||||||
|
setSelectedComment({})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
setSelectedComment(data);
|
setSelectedComment(data);
|
||||||
} else {
|
} else {
|
||||||
toast("Can't handle node type " + data.type);
|
toast("Can't handle node type " + data.type);
|
||||||
@@ -7450,26 +7482,21 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handlePaste = (event) => {
|
const handlePaste = (event) => {
|
||||||
//console.log("EV: ", event)
|
|
||||||
if (
|
if (
|
||||||
event.path !== undefined &&
|
event.path !== undefined &&
|
||||||
event.path !== null &&
|
event.path !== null &&
|
||||||
event.path.length > 0
|
event.path.length > 0
|
||||||
) {
|
) {
|
||||||
//console.log("PATH: ", event.path[0])
|
|
||||||
if (event.path[0].localName !== "body") {
|
if (event.path[0].localName !== "body") {
|
||||||
//console.log("Skipping because body is not targeted")
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//console.log("PATH2: ", event.target)
|
|
||||||
if (
|
if (
|
||||||
event.target !== undefined &&
|
event.target !== undefined &&
|
||||||
event.target !== null
|
event.target !== null
|
||||||
) {
|
) {
|
||||||
if (event.target.localName !== "body") {
|
if (event.target.localName !== "body") {
|
||||||
//console.log("Skipping because body is not targeted")
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7479,12 +7506,10 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
const clipboard = (event.originalEvent || event).clipboardData.getData(
|
const clipboard = (event.originalEvent || event).clipboardData.getData(
|
||||||
"text/plain"
|
"text/plain"
|
||||||
);
|
);
|
||||||
//console.log("Text: ", clipboard)
|
|
||||||
//window.document.execCommand('insertText', false, text);
|
|
||||||
//
|
|
||||||
try {
|
try {
|
||||||
|
const allnodes = cy.nodes().jsons()
|
||||||
var parsedjson = JSON.parse(clipboard);
|
var parsedjson = JSON.parse(clipboard);
|
||||||
// Check if array
|
|
||||||
if (!Array.isArray(parsedjson)) {
|
if (!Array.isArray(parsedjson)) {
|
||||||
console.log("Not array! Adding to array.")
|
console.log("Not array! Adding to array.")
|
||||||
parsedjson = [parsedjson]
|
parsedjson = [parsedjson]
|
||||||
@@ -7492,7 +7517,6 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
|
|
||||||
for (let jsonkey in parsedjson) {
|
for (let jsonkey in parsedjson) {
|
||||||
var item = parsedjson[jsonkey];
|
var item = parsedjson[jsonkey];
|
||||||
console.log("Adding: ", item);
|
|
||||||
|
|
||||||
if (item.data === undefined || item.data === null) {
|
if (item.data === undefined || item.data === null) {
|
||||||
console.log("Appending from here")
|
console.log("Appending from here")
|
||||||
@@ -7512,13 +7536,31 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
item.data.isStartNode = false
|
item.data.isStartNode = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Find a cy.data() label with the same name
|
||||||
|
const foundnodes = allnodes.filter((data) => {
|
||||||
|
//console.log("COMP: ", data.data.label, item.data.label)
|
||||||
|
if (data.data.label === undefined || data.data.label === null) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return data.data.label === item.data.label
|
||||||
|
})
|
||||||
|
|
||||||
|
if (foundnodes !== undefined && foundnodes !== null && foundnodes.length > 0) {
|
||||||
|
// Weird naming copy lol
|
||||||
|
item.data.label = item.data.label + "_copy_" + allnodes.length
|
||||||
|
}
|
||||||
|
|
||||||
item.data.id = uuidv4()
|
item.data.id = uuidv4()
|
||||||
|
|
||||||
cy.add({
|
cy.add({
|
||||||
group: item.group,
|
group: item.group,
|
||||||
data: item.data,
|
data: item.data,
|
||||||
position: item.position,
|
position: {
|
||||||
});
|
x: item.position.x+20,
|
||||||
|
y: item.position.y+20,
|
||||||
|
},
|
||||||
|
})
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log("Error pasting: ", e);
|
console.log("Error pasting: ", e);
|
||||||
@@ -9591,7 +9633,12 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
console.log("Error fitting cytoscape (4): ", error)
|
console.log("Error fitting cytoscape (4): ", error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
cy.on("boxselect", "node", (e) => {
|
cy.on("boxselect", "node", (e) => {
|
||||||
|
e.preventDefault()
|
||||||
|
e.stopPropagation()
|
||||||
|
|
||||||
|
console.log("BOXSELECT: ", e.boxSelectElements)
|
||||||
if (e.target.data("isButton") || e.target.data("isDescriptor") || e.target.data("isSuggestion")) {
|
if (e.target.data("isButton") || e.target.data("isDescriptor") || e.target.data("isSuggestion")) {
|
||||||
e.target.unselect();
|
e.target.unselect();
|
||||||
}
|
}
|
||||||
@@ -9601,10 +9648,15 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
|
|
||||||
cy.on("boxstart", (e) => {
|
cy.on("boxstart", (e) => {
|
||||||
console.log("START");
|
console.log("START");
|
||||||
|
e.preventDefault()
|
||||||
|
e.stopPropagation()
|
||||||
});
|
});
|
||||||
|
|
||||||
cy.on("boxend", (e) => {
|
cy.on("boxend", (e) => {
|
||||||
console.log("END: ", cy)
|
e.preventDefault()
|
||||||
|
e.stopPropagation()
|
||||||
|
|
||||||
|
console.log("END: ", e.target, cy)
|
||||||
var cydata = cy.$(":selected").jsons();
|
var cydata = cy.$(":selected").jsons();
|
||||||
if (cydata !== undefined && cydata !== null && cydata.length > 0) {
|
if (cydata !== undefined && cydata !== null && cydata.length > 0) {
|
||||||
// Unselect all nodes
|
// Unselect all nodes
|
||||||
@@ -17404,11 +17456,11 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
selectedTrigger.status === "running"
|
selectedTrigger.status === "running"
|
||||||
}
|
}
|
||||||
defaultValue={
|
defaultValue={
|
||||||
selectedTrigger?.parameters === undefined || selectedTrigger?.parameters === null || selectedTrigger?.parameters?.length === 0 ? isCloud || selectedTrigger?.environment === "cloud" ? "*/25 * * * *" : "60" : selectedTrigger.parameters[0]?.value
|
selectedTrigger?.parameters === undefined || selectedTrigger?.parameters === null || selectedTrigger?.parameters?.length === 0 ? isCloud || selectedTrigger?.environment === "cloud" ? "*/25 * * * *" : "60" : selectedTrigger?.parameters[0]?.value
|
||||||
}
|
}
|
||||||
color="primary"
|
color="primary"
|
||||||
placeholder={
|
placeholder={
|
||||||
selectedTrigger.parameters === undefined ? isCloud || selectedTrigger?.environment === "cloud" ? "*/25 * * * *" : "60" : selectedTrigger.parameters[0]?.value
|
selectedTrigger.parameters === undefined || selectedTrigger?.parameters === null || selectedTrigger?.parameters?.length === 0 ? isCloud || selectedTrigger?.environment === "cloud" ? "*/25 * * * *" : "60" : selectedTrigger?.parameters[0]?.value
|
||||||
}
|
}
|
||||||
onBlur={(e) => {
|
onBlur={(e) => {
|
||||||
setTriggerCronWrapper(e.target.value);
|
setTriggerCronWrapper(e.target.value);
|
||||||
@@ -21602,10 +21654,8 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
const checked = validateJson(data.value.trim())
|
const checked = validateJson(data.value.trim())
|
||||||
|
|
||||||
if (data.name === "shuffle_action_logs" && data.value !== undefined && data.value !== null && data.value.length > 0 && data.value.includes("add env SHUFFLE_LOGS_DISABLED")) {
|
if (data.name === "shuffle_action_logs" && data.value !== undefined && data.value !== null && data.value.length > 0 && data.value.includes("add env SHUFFLE_LOGS_DISABLED")) {
|
||||||
data.value = `Logs for this action are not available without <a style={{ color: "#FF8544", }} href="/admin?tab=locations" target="_blank" rel="noopener noreferrer">an onprem environment</a> with the <a style={{ color: "#FF8544", }} href="/docs/configuration#scaling-shuffle" target="_blank" rel="noopener noreferrer">SHUFFLE_LOGS_DISABLED</a> environment variable set to false: SHUFFLE_LOGS_DISABLED=false. Logs are enabled by default, except in scale mode.`
|
|
||||||
/*
|
|
||||||
return (
|
return (
|
||||||
<div style={{ maxWidth: 600, marginTop: 15, overflowX: "hidden", }}>
|
<div style={{ maxWidth: 600, marginTop: 75, overflowX: "hidden", }}>
|
||||||
<Typography
|
<Typography
|
||||||
variant="body1"
|
variant="body1"
|
||||||
style={{}}
|
style={{}}
|
||||||
@@ -21613,10 +21663,10 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
<b>Action Logs</b>
|
<b>Action Logs</b>
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="body2" style={{ whiteSpace: 'pre-line', }}>
|
<Typography variant="body2" style={{ whiteSpace: 'pre-line', }}>
|
||||||
|
More log details for this action are not available without <a style={{ color: "#FF8544", }} href="/admin?tab=locations" target="_blank" rel="noopener noreferrer">an onprem environment</a> with the <a style={{ color: "#FF8544", }} href="/docs/configuration#scaling-shuffle" target="_blank" rel="noopener noreferrer">SHUFFLE_LOGS_DISABLED</a> environment variable set to false: SHUFFLE_LOGS_DISABLED=false. Logs are enabled by default, except in scale mode.
|
||||||
</Typography>
|
</Typography>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var showlink = false
|
var showlink = false
|
||||||
|
|||||||
Reference in New Issue
Block a user