Fixed Tenzir force start from frontend

This commit is contained in:
Frikky
2025-01-09 22:31:53 +01:00
parent 2fd7f65831
commit aab73b5ecc
14 changed files with 2164 additions and 1564 deletions
+62 -28
View File
@@ -11,6 +11,8 @@ import {
Button, Button,
Stack, Stack,
Avatar, Avatar,
Skeleton,
Tooltip,
} from '@mui/material'; } from '@mui/material';
import CloseIcon from '@mui/icons-material/Close'; import CloseIcon from '@mui/icons-material/Close';
@@ -38,6 +40,7 @@ const AppModal = ({ open, onClose, app, globalUrl }) => {
const [inputUsecase, setInputUsecase] = useState({}) const [inputUsecase, setInputUsecase] = useState({})
const [latestUsecase, setLatestUsecase] = useState([]) const [latestUsecase, setLatestUsecase] = useState([])
const [foundAppUsecase, setFoundAppUsecase] = useState({}) const [foundAppUsecase, setFoundAppUsecase] = useState({})
const [usecaseLoading, setUsecaseLoading] = useState(false)
const navigate = useNavigate(); const navigate = useNavigate();
const parseUsecase = (subcase) => { const parseUsecase = (subcase) => {
const srcdata = findSpecificApp(frameworkData, subcase.type) const srcdata = findSpecificApp(frameworkData, subcase.type)
@@ -142,6 +145,19 @@ const AppModal = ({ open, onClose, app, globalUrl }) => {
}) })
setLatestUsecase(newUsecases) setLatestUsecase(newUsecases)
if (newUsecases?.length > 0) {
const foundCategory = newUsecases?.find((category) =>
category?.list?.some((subcase) => subcase?.srcapp === app?.name || subcase?.dstapp === app?.name)
);
const foundSubcase = foundCategory?.list?.find(
(subcase) => subcase?.srcapp === app?.name || subcase?.dstapp === app?.name
);
setFoundAppUsecase(foundSubcase);
}
setUsecaseLoading(false)
// Matching workflows with usecases // Matching workflows with usecases
if (responseJson.success !== false) { if (responseJson.success !== false) {
if (workflows !== undefined && workflows !== null && workflows.length > 0) { if (workflows !== undefined && workflows !== null && workflows.length > 0) {
@@ -275,23 +291,12 @@ const AppModal = ({ open, onClose, app, globalUrl }) => {
useEffect(() => { useEffect(() => {
setUsecaseLoading(true)
getAvailableWorkflows() getAvailableWorkflows()
getFramework() getFramework()
}, [app]) }, [app])
useEffect(() => {
const foundCategory = latestUsecase?.find((category) =>
category?.list?.some((subcase) => subcase?.srcapp === app?.name || subcase?.dstapp === app?.name)
);
const foundSubcase = foundCategory?.list?.find(
(subcase) => subcase?.srcapp === app?.name || subcase?.dstapp === app?.name
);
setFoundAppUsecase(foundSubcase);
}, [latestUsecase])
const downloadApp = (inputdata) => { const downloadApp = (inputdata) => {
const id = inputdata.id; const id = inputdata.id;
@@ -389,9 +394,8 @@ const AppModal = ({ open, onClose, app, globalUrl }) => {
newAppname = newAppname?.replaceAll("_", " "); newAppname = newAppname?.replaceAll("_", " ");
} }
var canEditApp = userdata.admin === "true" || userdata?.id === app?.owner || app?.owner === "" || (userdata.admin === "true" && userdata.active_org.id === app?.reference_org) || !app?.generated
var canEditApp = userdata !== undefined && (userdata?.admin === "true" || userdata?.id === app?.owner || app?.owner === "" || (userdata?.admin === "true" && userdata?.active_org?.id === app?.reference_org)) || !app?.generated
return ( return (
<Dialog <Dialog
@@ -501,6 +505,13 @@ const AppModal = ({ open, onClose, app, globalUrl }) => {
app?.private_id !== undefined && app?.private_id !== undefined &&
app?.private_id?.length > 0 && app?.private_id?.length > 0 &&
app?.generated ? ( app?.generated ? (
<Tooltip title="Download OpenAPI"
placement="top"
arrow
sx={{
fontFamily: theme?.typography?.fontFamily
}}
>
<Button <Button
variant="contained" variant="contained"
sx={{ sx={{
@@ -522,7 +533,9 @@ const AppModal = ({ open, onClose, app, globalUrl }) => {
}} }}
> >
<CloudDownloadOutlined /> <CloudDownloadOutlined />
</Button>) : null} </Button>
</Tooltip>
) : null}
<Button <Button
variant="contained" variant="contained"
sx={{ sx={{
@@ -655,6 +668,16 @@ const AppModal = ({ open, onClose, app, globalUrl }) => {
justifyContent: "start", justifyContent: "start",
width: "100%" width: "100%"
}}> }}>
{usecaseLoading ? (
<Skeleton
variant="text"
width="55%"
sx={{
fontSize: "16px",
mb: "16px",
}}
/>
) : (
<div style={{ <div style={{
fontFamily: theme?.typography?.fontFamily, fontFamily: theme?.typography?.fontFamily,
fontSize: "16px", fontSize: "16px",
@@ -666,10 +689,11 @@ const AppModal = ({ open, onClose, app, globalUrl }) => {
(foundAppUsecase?.srcapp !== undefined && foundAppUsecase?.dstapp !== undefined) ? ( (foundAppUsecase?.srcapp !== undefined && foundAppUsecase?.dstapp !== undefined) ? (
"Connect " + foundAppUsecase?.srcapp?.replaceAll("_", " ") + " to " + foundAppUsecase?.dstapp?.replaceAll("_", " ") "Connect " + foundAppUsecase?.srcapp?.replaceAll("_", " ") + " to " + foundAppUsecase?.dstapp?.replaceAll("_", " ")
) : ( ) : (
"Connect " + app?.name + " to any tool" "Connect " + app?.name.replaceAll("_", " ") + " to any tool"
) )
} }
</div> </div>
)}
<Box sx={{ <Box sx={{
bgcolor: '#2F2F2F', bgcolor: '#2F2F2F',
@@ -679,11 +703,19 @@ const AppModal = ({ open, onClose, app, globalUrl }) => {
alignItems: 'center', alignItems: 'center',
mb: 3 mb: 3
}}> }}>
{usecaseLoading ? (
<Stack direction="row" spacing={2} alignItems="center" sx={{ width: '100%' }}>
<Stack direction="row" spacing={-1}> <Stack direction="row" spacing={-1}>
{ <Skeleton variant="circular" width={32} height={32} />
foundAppUsecase === undefined ? ( <Skeleton variant="circular" width={32} height={32} />
<Avatar sx={{ width: 32, height: 32, bgcolor: 'background.paper', border: 1, borderColor: 'divider' }}> </Stack>
<Search sx={{ color: 'text.primary', zIndex: 10, fontSize: 18 }} /> <Skeleton variant="text" sx={{ flexGrow: 1 }} width={200} />
</Stack>
) : (
<>
<Stack direction="row" spacing={-1}>
{foundAppUsecase?.srcapp === undefined ? (
<Avatar sx={{ width: 32, height: 32, bgcolor: 'background.paper', border: 1, borderColor: 'divider' }} src={app?.image_url || app?.large_image}>
</Avatar> </Avatar>
) : ( ) : (
<Avatar <Avatar
@@ -697,10 +729,8 @@ const AppModal = ({ open, onClose, app, globalUrl }) => {
zIndex: 10 zIndex: 10
}} }}
/> />
) )}
} {foundAppUsecase?.dstapp === undefined ? (
{
foundAppUsecase === undefined ? (
<Avatar sx={{ width: 32, height: 32, bgcolor: 'background.paper', border: 1, borderColor: 'divider' }}> <Avatar sx={{ width: 32, height: 32, bgcolor: 'background.paper', border: 1, borderColor: 'divider' }}>
<AddIcon sx={{ color: 'text.primary', zIndex: 10, fontSize: 18 }} /> <AddIcon sx={{ color: 'text.primary', zIndex: 10, fontSize: 18 }} />
</Avatar> </Avatar>
@@ -716,12 +746,13 @@ const AppModal = ({ open, onClose, app, globalUrl }) => {
zIndex: 10 zIndex: 10
}} }}
/> />
) )}
}
</Stack> </Stack>
<Typography sx={{ ml: 2, fontSize: "16px", letterSpacing: "0.5px" }}> <Typography sx={{ ml: 2, fontSize: "16px", letterSpacing: "0.5px" }}>
{foundAppUsecase?.name || "Search for a Usecase"} {foundAppUsecase?.name || "Search for a Usecase"}
</Typography> </Typography>
</>
)}
</Box> </Box>
</div> </div>
@@ -742,10 +773,13 @@ const AppModal = ({ open, onClose, app, globalUrl }) => {
minWidth: '200px' minWidth: '200px'
}} }}
onClick={() => { onClick={() => {
navigate("/usecases2") navigate("/usecases")
}} }}
disabled={usecaseLoading}
> >
Find a Usecase {
(foundAppUsecase !== undefined && foundAppUsecase !== null && usecaseLoading === false) ? "See usecase" : "Find a Usecase"
}
</Button> </Button>
</div> </div>
</DialogContent> </DialogContent>
+7 -7
View File
@@ -536,15 +536,16 @@ const AppSelection = props => {
})} })}
</Grid> </Grid>
</div> </div>
{
!isAppPage && (
<>
{!moreButton ? ( {!moreButton ? (
<div style={{ width: "100%", marginLeft: isMobile ? 80 : 200, marginBottom: 20, textAlign: isMobile ? "center" : null }}> <div style={{ width: "100%", marginLeft: isMobile ? 80 : 200, marginBottom: 20, textAlign: isMobile ? "center" : null }}>
<Link style={{ color: "#FF8444" }} onClick={() => { <Link style={{ color: "#FF8444" }} onClick={() => {
setMoreButton(true) setMoreButton(true)
setTimeout(() => { setTimeout(() => {
if (isAppPage) {
navigate("/apps?tab=all_apps")
} else {
navigate("/welcome?tab=2") navigate("/welcome?tab=2")
}
}, 250) }, 250)
}} }}
>See More Apps</Link> >See More Apps</Link>
@@ -552,15 +553,14 @@ const AppSelection = props => {
<div style={{ flexDirection: "row", width: isMobile ? 340 : null, textAlign: isMobile ? "center" : null }}> <div style={{ flexDirection: "row", width: isMobile ? 340 : null, textAlign: isMobile ? "center" : null }}>
<Button variant="contained" type="submit" fullWidth style={bottomButtonStyle} onClick={() => { <Button variant="contained" type="submit" fullWidth style={bottomButtonStyle} onClick={() => {
navigate("/usecases2") navigate("/usecases")
if(!isAppPage) {
setActiveStep(2) setActiveStep(2)
}
}}> }}>
See usecases See usecases
</Button> </Button>
</div> </div>
</>
)
}
</div> </div>
</Fade> </Fade>
) )
+1
View File
@@ -537,6 +537,7 @@ const CacheView = memo((props) => {
padding: "15px 5px", padding: "15px 5px",
maxHeight: 300, maxHeight: 300,
verticalAlign: "middle", verticalAlign: "middle",
maxWidth: 300,
}} }}
primary={validate.valid ? primary={validate.valid ?
<ReactJson <ReactJson
+409 -17
View File
@@ -22,6 +22,9 @@ import {
DialogActions, DialogActions,
Typography, Typography,
Skeleton, Skeleton,
Checkbox,
Chip,
Menu,
} from "@mui/material"; } from "@mui/material";
import { import {
@@ -35,6 +38,7 @@ import {
Publish as PublishIcon, Publish as PublishIcon,
Clear as ClearIcon, Clear as ClearIcon,
Add as AddIcon, Add as AddIcon,
SelectAll,
} from "@mui/icons-material"; } from "@mui/icons-material";
import Dropzone from "../components/Dropzone.jsx"; import Dropzone from "../components/Dropzone.jsx";
@@ -61,6 +65,14 @@ const Files = memo((props) => {
const [downloadBranch, setDownloadBranch] = React.useState("main"); const [downloadBranch, setDownloadBranch] = React.useState("main");
const [downloadFolder, setDownloadFolder] = React.useState("translation_standards"); const [downloadFolder, setDownloadFolder] = React.useState("translation_standards");
const [contentLoading, setContentLoading] = React.useState(false) const [contentLoading, setContentLoading] = React.useState(false)
const [selectAllChecked, setSelectAllChecked] = React.useState(false)
const [selectedFiles, setSelectedFiles] = useState([]);
const [selectedFileId, setSelectedFileId] = useState([])
const [showFileCategoryPopup, setShowFileCategoryPopup] = useState(false)
const [updateToThisCategory, setUpdateToThisCategory] = useState("")
const [showDistributionPopup, setShowDistributionPopup] = useState(false)
const [selectedSubOrg, setSelectedSubOrg] = useState([])
const [fileIdSelectedForDistribution, setFileIdSelectedForDistribution] = useState("")
//const alert = useAlert(); //const alert = useAlert();
const allowedFileTypes = ["txt", "py", "yaml", "yml","json", "html", "js", "csv", "log", "eml", "msg", "md", "xml", "sh", "bat", "ps1", "psm1", "psd1", "ps1xml", "pssc", "psc1", "response"] const allowedFileTypes = ["txt", "py", "yaml", "yml","json", "html", "js", "csv", "log", "eml", "msg", "md", "xml", "sh", "bat", "ps1", "psm1", "psd1", "ps1xml", "pssc", "psc1", "response"]
var upload = ""; var upload = "";
@@ -80,6 +92,56 @@ const Files = memo((props) => {
} }
const changeDistribution = (id, selectedSubOrg) => {
editFileConfig(id, "suborg_distribute", [...new Set(selectedSubOrg)])
}
const editFileConfig = (id, parentAction, selectedSubOrg) => {
const data = {
id: id,
action: parentAction !== undefined && parentAction !== null ? parentAction : "change_category",
selected_suborgs: selectedSubOrg,
}
const url = globalUrl + "/api/v1/files/" + id + "/config";
fetch(url, {
mode: "cors",
method: "POST",
body: JSON.stringify(data),
credentials: "include",
crossDomain: true,
withCredentials: true,
headers: {
"Content-Type": "application/json; charset=utf-8",
},
})
.then((response) =>
response.json().then((responseJson) => {
if (responseJson["success"] === false) {
toast("Failed overwriting files");
} else {
toast("Successfully updated file!");
setTimeout(() => {
getFiles();
}, 1000);
}
})
)
.catch((error) => {
toast("Err: " + error.toString());
});
};
const handleFileCheckboxChange = (index) => {
setSelectedFiles((prevSelected) => {
const updatedSelected = [...prevSelected];
updatedSelected[index] = !updatedSelected[index];
return updatedSelected;
});
};
const runUpdateText = (text) =>{ const runUpdateText = (text) =>{
fetch(`${globalUrl}/api/v1/files/${openFileId}/edit`, { fetch(`${globalUrl}/api/v1/files/${openFileId}/edit`, {
method: "PUT", method: "PUT",
@@ -137,6 +199,7 @@ const Files = memo((props) => {
if (responseJson.files !== undefined && responseJson.files !== null) { if (responseJson.files !== undefined && responseJson.files !== null) {
setFiles(responseJson.files); setFiles(responseJson.files);
setShowLoader(false) setShowLoader(false)
setShowDistributionPopup(false)
} else if (responseJson.list !== undefined && responseJson.list !== null) { } else if (responseJson.list !== undefined && responseJson.list !== null) {
// Set the "namespace" field in all items // Set the "namespace" field in all items
if (namespace !== undefined && namespace !== null) { if (namespace !== undefined && namespace !== null) {
@@ -152,6 +215,7 @@ const Files = memo((props) => {
} else { } else {
setFiles([]); setFiles([]);
setShowLoader(false) setShowLoader(false)
setShowDistributionPopup(false)
} }
if (namespace === undefined || namespace === null || namespace === "default") { if (namespace === undefined || namespace === null || namespace === "default") {
@@ -256,7 +320,7 @@ const Files = memo((props) => {
zIndex: 1000, zIndex: 1000,
minWidth: "800px", minWidth: "800px",
minHeight: "320px", minHeight: "320px",
overflow: "hidden", overflow: "auto",
'& .MuiDialogContent-root': { '& .MuiDialogContent-root': {
backgroundColor: theme?.palette?.DialogStyle?.backgroundColor, backgroundColor: theme?.palette?.DialogStyle?.backgroundColor,
}, },
@@ -400,6 +464,127 @@ const Files = memo((props) => {
</Dialog> </Dialog>
: null : null
const handleSelectSubOrg = (id, action) => {
if (action === "all") {
const childOrgs = userdata.orgs.filter(
(data) => data.creator_org === userdata.active_org.id
);
setSelectedSubOrg((prev) => {
if (prev.length === childOrgs.length) {
// If all child orgs are already selected, clear the selection
return [];
} else {
// Otherwise, select all child org IDs
return childOrgs.map((data) => data.id);
}
});
} else if (action === "none") {
setSelectedSubOrg([]);
} else {
setSelectedSubOrg((prev) => {
if (prev.includes(id)) {
return prev.filter((data) => data !== id);
} else {
return [...prev, id];
}
});
}
};
const fileDistributionModal = showDistributionPopup ? (
<Dialog
open={showDistributionPopup}
onClose={() => setShowDistributionPopup(false)}
PaperProps={{
sx: {
borderRadius: theme?.palette?.DialogStyle?.borderRadius,
border: theme?.palette?.DialogStyle?.border,
fontFamily: theme?.typography?.fontFamily,
backgroundColor: theme?.palette?.DialogStyle?.backgroundColor,
zIndex: 1000,
minWidth: "600px",
minHeight: "320px",
overflow: "auto",
'& .MuiDialogContent-root': {
backgroundColor: theme?.palette?.DialogStyle?.backgroundColor,
},
'& .MuiDialogTitle-root': {
backgroundColor: theme?.palette?.DialogStyle?.backgroundColor,
},
'& .MuiDialogActions-root': {
backgroundColor: theme?.palette?.DialogStyle?.backgroundColor,
},
},
}}
>
<DialogTitle>
<div style={{ color: "rgba(255,255,255,0.9)" }}>
Select sub-org to distribute files
</div>
</DialogTitle>
<DialogContent style={{ color: "rgba(255,255,255,0.65)" }}>
<MenuItem value="none" onClick={()=> {handleSelectSubOrg(null, "none")}}>None</MenuItem>
<MenuItem value="all" onClick={()=> {handleSelectSubOrg(null, "all")}}>All</MenuItem>
{userdata.orgs.map((data, index) => {
if (data.creator_org !== userdata.active_org.id) {
return null;
}
const imagesize = 22;
const imageStyle = {
width: imagesize,
height: imagesize,
pointerEvents: "none",
marginRight: 10,
marginLeft: data.id === userdata.active_org.id ? 0 : 20,
};
const image = data.image === "" ? (
<img alt={data.name} src={theme.palette.defaultImage} style={imageStyle} />
) : (
<img alt={data.name} src={data.image} style={imageStyle} />
);
return (
<MenuItem
key={index}
value={data.id}
onClick={() => handleSelectSubOrg(data.id)}
style={{ display: "flex", alignItems: "center" }}
>
<Checkbox
checked={selectedSubOrg.includes(data.id)}
/>
{image}
<span style={{ marginLeft: 8 }}>{data.name}</span>
</MenuItem>
);
})}
<div style={{ display: "flex", marginTop: 20 }}>
<Button
style={{ borderRadius: "2px", textTransform: 'none', fontSize:16, color: "#ff8544" }}
onClick={() => setShowDistributionPopup(false)}
color="primary"
>
Cancel
</Button>
<Button
variant="contained"
style={{ borderRadius: "2px", textTransform: 'none', fontSize:16, color: "#1a1a1a", backgroundColor: "#ff8544", marginLeft: 10 }}
onClick={() => {
changeDistribution(fileIdSelectedForDistribution, selectedSubOrg);
}}
color="primary"
>
Submit
</Button>
</div>
</DialogContent>
</Dialog>
): null
const deleteFile = (file) => { const deleteFile = (file) => {
fetch(globalUrl + "/api/v1/files/" + file.id, { fetch(globalUrl + "/api/v1/files/" + file.id, {
method: "DELETE", method: "DELETE",
@@ -636,7 +821,7 @@ const Files = memo((props) => {
setTimeout(() => { setTimeout(() => {
getFiles() getFiles()
}, 2500); }, 3000);
}; };
const uploadFile = (e) => { const uploadFile = (e) => {
@@ -649,6 +834,68 @@ const Files = memo((props) => {
uploadFiles(files); uploadFiles(files);
}; };
const handleUpdateFileCategory = (namespace) => {
if (selectedFiles.length === 0 && !selectAllChecked) {
toast("Please select files to update category")
return
}
if (namespace === undefined || namespace === null || namespace === "") {
toast("Please select a category to update files to")
return
}
const url = globalUrl + `/api/v1/files/namespaces/${namespace}/share`
const data = {
SelectedFiles: selectedFileId,
}
setShowLoader(true)
fetch(url, {
mode: "cors",
method: "POST",
body: JSON.stringify(data),
credentials: "include",
crossDomain: true,
withCredentials: true,
headers: {
"Content-Type": "application/json; charset=utf-8",
},
})
.then((response) =>
response.json().then((responseJson) => {
if (responseJson["success"] === false) {
toast("Failed overwriting files");
} else {
setSelectAllChecked(false)
setSelectedFiles([])
setSelectedFileId([])
setShowFileCategoryPopup(false)
setSelectedCategory(namespace)
setTimeout(() => {
getFiles();
toast("Successfully updated file!");
if (window.location.search.includes("category=")) {
const newurl = window.location.href.replace(/category=[^&]+/, `category=${namespace}`)
window.history.pushState({ path: newurl }, "", newurl)
} else {
window.history.pushState({ path: window.location.href }, "", `${window.location.href}&category=${namespace}`)
}
}, 1000);
}
}
))
.catch((error) => {
toast("Err: " + error.toString());
});
}
return ( return (
<Dropzone <Dropzone
style={{ style={{
@@ -659,6 +906,7 @@ const Files = memo((props) => {
}} }}
onDrop={uploadFile} onDrop={uploadFile}
> >
{fileDistributionModal}
<div style={{width: "100%", minHeight: 1100, boxSizing: 'border-box', padding: "27px 10px 19px 27px", height:"100%", backgroundColor: '#212121',borderTopRightRadius: '8px', borderBottomRightRadius: 8, borderLeft: "1px solid #494949", }}> <div style={{width: "100%", minHeight: 1100, boxSizing: 'border-box', padding: "27px 10px 19px 27px", height:"100%", backgroundColor: '#212121',borderTopRightRadius: '8px', borderBottomRightRadius: 8, borderLeft: "1px solid #494949", }}>
<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'}}>
@@ -739,14 +987,19 @@ const Files = memo((props) => {
}} }}
value={selectedCategory} value={selectedCategory}
onChange={(event) => { onChange={(event) => {
if (selectAllChecked || selectedFiles.length > 0) {
setUpdateToThisCategory(event.target.value)
setShowFileCategoryPopup(true)
return
}
setSelectedCategory(event.target.value) setSelectedCategory(event.target.value)
if (event.target.value === "all" || event.target.value === "default") { if (event.target.value === "all" || event.target.value === "default") {
getFiles() getFiles()
} else { } else {
getFiles(event.target.value) getFiles(event.target.value)
} }
// Add it to the url as a query // Add it to the url as a query
if (window.location.search.includes("category=")) { if (window.location.search.includes("category=")) {
const newurl = window.location.href.replace(/category=[^&]+/, `category=${event.target.value}`) const newurl = window.location.href.replace(/category=[^&]+/, `category=${event.target.value}`)
@@ -768,14 +1021,41 @@ const Files = memo((props) => {
); );
})} })}
</Select> </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)} style={{fontSize: 16, textTransform: 'none', color: "#1a1a1a", backgroundColor: "#ff8544"}}>Update</Button>
</DialogActions>
</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={""}>
<Button <Button
style={{ marginLeft: 5, marginRight: 15 }} style={{ marginLeft: 5, marginRight: 15, height: 35, borderRadius: 4, backgroundColor: "#494949", textTransform: 'none', fontSize: 16, color: "#f1f1f1" }}
color="primary" color="primary"
onClick={() => { onClick={() => {
setRenderTextBox(false); setRenderTextBox(false);
@@ -803,10 +1083,24 @@ const Files = memo((props) => {
{renderTextBox && <TextField {renderTextBox && <TextField
onKeyPress={(event)=>{ onKeyPress={(event)=>{
handleKeyDown(event); handleKeyDown(event);
if(event.key === 'Enter' && selectedFileId.length > 0){
setShowFileCategoryPopup(true)
setUpdateToThisCategory(event.target.value)
}
}}
style={{
height: 35,
width: 200,
marginTop: 0,
}} }}
InputProps={{ InputProps={{
style: { style: {
color: "white", color: "white",
height: 35,
fontSize: 16,
borderRadius: 4,
paddingTop: 0,
}, },
}} }}
color="primary" color="primary"
@@ -816,7 +1110,6 @@ const Files = memo((props) => {
defaultValue={""} defaultValue={""}
autoFocus autoFocus
/>}</div> />}</div>
<ShuffleCodeEditor <ShuffleCodeEditor
isCloud={isCloud} isCloud={isCloud}
expansionModalOpen={openEditor} expansionModalOpen={openEditor}
@@ -852,17 +1145,57 @@ const Files = memo((props) => {
tableLayout: "auto", tableLayout: "auto",
display: "table", display: "table",
minWidth: 800, minWidth: 800,
overflowX: "auto" overflowX: "auto",
paddingBottom: 0,
}} }}
> >
<ListItem style={{width:isSelectedFiles?"100%":null, borderBottom:isSelectedFiles?"1px solid #494949":null, display: 'table-row'}}> <ListItem
{["Name", "Workflow", "Md5", "Status", "Filesize", "Actions"].map((header, index) => ( style={{
borderBottom: "1px solid #494949" ,
display: "table-row"
}}
>
{[
<Tooltip title={"Select all files"} style={{}} aria-label={""}>
<Checkbox
sx={{padding: 0}}
onChange={() => {
setSelectAllChecked((prev) => !prev);
setSelectedFiles((prev) => {
if (prev.length === files.length) {
return []
} else {
return files.map((_, index) => !prev.includes(index))
}
})
if (selectAllChecked) {
setSelectedFileId([])
} else {
setSelectedFileId(
files
.filter((file) => file.namespace === selectedCategory)
.map((file) => file.id)
);
}
}}
/>
</Tooltip>,
"Name",
"Workflow",
"Md5",
"Status",
"Filesize",
"Actions",
"Distribution"
]
.filter(Boolean)
.map((header, index) => (
<ListItemText <ListItemText
key={index} key={index}
primary={header} primary={header}
style={{ style={{
display: "table-cell", display: "table-cell",
padding: index === 0 ? "0px 8px 8px 15px": "0px 8px 8px 8px", padding: index === 0 ? "0px 8px 8px 15px" : "0px 8px 8px 8px",
whiteSpace: "nowrap", whiteSpace: "nowrap",
textOverflow: "ellipsis", textOverflow: "ellipsis",
borderBottom: "1px solid #494949", borderBottom: "1px solid #494949",
@@ -870,7 +1203,7 @@ const Files = memo((props) => {
}} }}
primaryTypographyProps={{ primaryTypographyProps={{
style: { style: {
paddingLeft: 10, paddingLeft: 10
} }
}} }}
/> />
@@ -885,7 +1218,7 @@ const Files = memo((props) => {
backgroundColor: "#212121", backgroundColor: "#212121",
}} }}
> >
{Array(6) {Array(8)
.fill() .fill()
.map((_, colIndex) => ( .map((_, colIndex) => (
<ListItemText <ListItemText
@@ -928,7 +1261,7 @@ const Files = memo((props) => {
if (index % 2 === 0) { if (index % 2 === 0) {
bgColor = isSelectedFiles ? "#1A1A1A":"#1f2023"; bgColor = isSelectedFiles ? "#1A1A1A":"#1f2023";
} }
const isDistributed = file?.suborg_distribution?.length > 0 ? true : false;
const filenamesplit = file.filename.split(".") const filenamesplit = file.filename.split(".")
const iseditable = file.filesize < 2000000 && file.status === "active" && allowedFileTypes.includes(filenamesplit[filenamesplit.length-1]) const iseditable = file.filesize < 2000000 && file.status === "active" && allowedFileTypes.includes(filenamesplit[filenamesplit.length-1])
return ( return (
@@ -953,6 +1286,26 @@ const Files = memo((props) => {
primary={new Date(file.updated_at * 1000).toISOString()} primary={new Date(file.updated_at * 1000).toISOString()}
/> />
*/} */}
<ListItemText
style={{
display: 'table-cell',
overflow: "hidden",
textAlign: "center",
}}
>
<Checkbox
style={{ padding: 0 }}
disabled={file.org_id !== selectedOrganization.id}
checked={!!selectedFiles[index] || selectAllChecked}
onChange={() => {handleFileCheckboxChange(index); setSelectedFileId(prev => {
if (prev.includes(file.id)) {
return prev.filter((item) => item !== file.id)
} else {
return [...prev, file.id]
}
})}}
/>
</ListItemText>
<ListItemText <ListItemText
primaryTypographyProps={{ primaryTypographyProps={{
style: { style: {
@@ -1064,7 +1417,7 @@ const Files = memo((props) => {
> >
<span> <span>
<IconButton <IconButton
disabled={!iseditable} disabled={!iseditable || file.org_id !== selectedOrganization.id}
style = {{padding: "6px", }} style = {{padding: "6px", }}
onClick={() => { onClick={() => {
setOpenEditor(true) setOpenEditor(true)
@@ -1137,7 +1490,6 @@ const Files = memo((props) => {
<IconButton <IconButton
style = {{padding: "6px"}} style = {{padding: "6px"}}
onClick={() => { onClick={() => {
console.log("file is : ", file)
navigator.clipboard.writeText(file.id); navigator.clipboard.writeText(file.id);
document.execCommand("copy"); document.execCommand("copy");
@@ -1154,7 +1506,7 @@ const Files = memo((props) => {
> >
<span> <span>
<IconButton <IconButton
disabled={file.status !== "active"} disabled={file.status !== "active" || file.org_id !== selectedOrganization.id}
style={{ padding: "6px" }} style={{ padding: "6px" }}
onClick={() => { onClick={() => {
deleteFile(file); deleteFile(file);
@@ -1166,7 +1518,7 @@ const Files = memo((props) => {
viewBox="0 0 24 24" viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
style={{ style={{
stroke: file.status === "active" ? "#fd4c62" : "#c8c8c8", stroke: file.status === "active" && file.org_id === selectedOrganization.id ? "#fd4c62" : "#c8c8c8",
}} }}
> >
<path <path
@@ -1192,6 +1544,46 @@ const Files = memo((props) => {
// overflow: "hidden", // overflow: "hidden",
}} }}
/> />
<ListItemText primaryTypographyProps={{
style: {
padding: 8
}
}} style={{ display: "table-cell", textAlign: 'center', verticalAlign: 'middle'}} >
{selectedOrganization.id !== undefined && file?.org_id !== selectedOrganization.id ?
<Tooltip
title="Parent organization controlled file. You can use, but not modify this file. Contact an admin of your parent organization if you need changes to this."
placement="top"
>
<Chip
label={"Parent"}
variant="contained"
color="secondary"
style={{display: "table-cell",}}
/>
</Tooltip>
:
<Tooltip
title="Distributed to sub-organizations. This means the sub organizations can use this file, but can not modify it."
placement="top"
>
<Checkbox
disabled={selectedOrganization.creator_org !== undefined && selectedOrganization.creator_org !== null && selectedOrganization.creator_org !== "" ? true : false}
checked={isDistributed}
style={{ }}
color="secondary"
onClick={() => {
setShowDistributionPopup(true)
if(file?.suborg_distribution?.length > 0){
setSelectedSubOrg(file.suborg_distribution)
}else{
setSelectedSubOrg([])
}
setFileIdSelectedForDistribution(file.id)
}}
/>
</Tooltip>
}
</ListItemText>
</ListItem> </ListItem>
); );
}) })
+41 -14
View File
@@ -58,6 +58,7 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
const navigate = useNavigate(); const navigate = useNavigate();
const {setLeftSideBarOpenByClick, leftSideBarOpenByClick, setSearchBarModalOpen, searchBarModalOpen} = useContext(Context); const {setLeftSideBarOpenByClick, leftSideBarOpenByClick, setSearchBarModalOpen, searchBarModalOpen} = useContext(Context);
const [expandLeftNav, setExpandLeftNav] = useState(false); const [expandLeftNav, setExpandLeftNav] = useState(false);
const [activeOrgName, setActiveOrgName] = useState( const [activeOrgName, setActiveOrgName] = useState(
userdata?.active_org?.name || "Select Organziation" userdata?.active_org?.name || "Select Organziation"
@@ -261,17 +262,20 @@ useEffect(() => {
},[currentPath]); },[currentPath]);
useEffect(() => { useEffect(() => {
UpdateTabStatus(); UpdateTabStatus()
const expandLeftNav1 = localStorage.getItem("expandLeftNav");
const expandLeftNav1 = localStorage.getItem("expandLeftNav")
if (expandLeftNav1 === "false") { if (expandLeftNav1 === "false") {
setLeftSideBarOpenByClick(false); setLeftSideBarOpenByClick(false)
setLeftSideBarOpenByClick(false);
} else { } else {
setLeftSideBarOpenByClick(true); const currentLocation = window?.location?.pathname
setLeftSideBarOpenByClick(true); if (currentLocation?.includes('/workflows/')) {
setExpandLeftNav(true); } else {
setLeftSideBarOpenByClick(true)
setExpandLeftNav(true)
} }
}, []); }
}, [])
const getAvailableWorkflows = useCallback((amount) => { const getAvailableWorkflows = useCallback((amount) => {
@@ -533,7 +537,7 @@ useEffect(() => {
<Divider style={{ marginBottom: 10, }} /> <Divider style={{ marginBottom: 10, }} />
<Typography color="textSecondary" align="center" style={{ marginTop: 5, marginBottom: 5, fontSize: 18 }}> <Typography color="textSecondary" align="center" style={{ marginTop: 5, marginBottom: 5, fontSize: 18 }}>
Version: 2.0.0-rc Version: 2.0.0-rc2
</Typography> </Typography>
</Menu> </Menu>
</span> </span>
@@ -591,6 +595,10 @@ useEffect(() => {
org_id: orgId, org_id: orgId,
}; };
if (userdata?.active_org?.id === orgId) {
return
}
localStorage.setItem("globalUrl", ""); localStorage.setItem("globalUrl", "");
localStorage.setItem("getting_started_sidebar", "open"); localStorage.setItem("getting_started_sidebar", "open");
@@ -765,11 +773,18 @@ useEffect(() => {
"UK": "gb" "UK": "gb"
}; };
region = regionMapping[region_url] || "gb"; region = regionMapping[region_url] || "eu";
return `https://flagcdn.com/48x36/${region}.png`; return `https://flagcdn.com/48x36/${region}.png`;
}; };
useEffect(() => {
if (window?.location?.pathname?.includes("/workflows/")) {
setExpandLeftNav(false);
}
}, [window?.location?.pathname]);
return ( return (
<div <div
style={{ style={{
@@ -786,6 +801,18 @@ useEffect(() => {
zoom: 0.8, zoom: 0.8,
height: "calc((100vh - 32px)*1.2)", height: "calc((100vh - 32px)*1.2)",
}} }}
onMouseLeave={() => {
if (window?.location?.pathname?.includes("/workflows/")) {
setExpandLeftNav(false);
}
}}
onMouseOver={() => {
if (window?.location?.pathname?.includes("/workflows/")) {
setExpandLeftNav(true);
}
}
}
> >
{modalView} {modalView}
<Box <Box
@@ -1169,10 +1196,6 @@ useEffect(() => {
}} }}
style={{ style={{
...ButtonStyle, ...ButtonStyle,
backgroundColor:
currentOpenTab === "security"
? "#2f2f2f"
: "transparent",
}} }}
onMouseOver={(event)=>{ onMouseOver={(event)=>{
event.currentTarget.style.backgroundColor = "#2f2f2f"; event.currentTarget.style.backgroundColor = "#2f2f2f";
@@ -1443,6 +1466,8 @@ useEffect(() => {
</Button> </Button>
</Link> </Link>
</Box> </Box>
{recentworkflows?.length > 0 ?
<Box <Box
style={{ style={{
display: "flex", display: "flex",
@@ -1487,6 +1512,8 @@ useEffect(() => {
}) } }) }
</Box> </Box>
</Box> </Box>
: null }
</Box> </Box>
<Box <Box
style={{ style={{
+96 -96
View File
@@ -66,27 +66,27 @@ import "ace-builds/src-noconflict/ext-language_tools";
import "ace-builds/src-noconflict/ext-searchbox"; import "ace-builds/src-noconflict/ext-searchbox";
const liquidFilters = [ const liquidFilters = [
{"name": "Default", "value": `default: []`, "example": `{{ "" | default: "no input" }}`}, { "name": "Default", "value": `default: []`, "example": `{{ "" | default: "no input" }}` },
{"name": "Split", "value": `split: ","`, "example": `{{ "this,can,become,a,list" | split: "," }}`}, { "name": "Split", "value": `split: ","`, "example": `{{ "this,can,become,a,list" | split: "," }}` },
{"name": "Join", "value": `join: ","`, "example": `{{ ["this","can","become","a","string"] | join: "," }}`}, { "name": "Join", "value": `join: ","`, "example": `{{ ["this","can","become","a","string"] | join: "," }}` },
{"name": "Size", "value": "size", "example": ""}, { "name": "Size", "value": "size", "example": "" },
{"name": "Date", "value": `date: "%Y%m%d"`, "example": `{{ "now" | date: "%s" }}`}, { "name": "Date", "value": `date: "%Y%m%d"`, "example": `{{ "now" | date: "%s" }}` },
{"name": "Escape String", "value": `{{ \"\"\"'string with weird'" quotes\"\"\" | escape_string }}`, "example": ``}, { "name": "Escape String", "value": `{{ \"\"\"'string with weird'" quotes\"\"\" | escape_string }}`, "example": `` },
{"name": "Flatten", "value": `flatten`, "example": `{{ [1, [1, 2], [2, 3, 4]] | flatten }}`}, { "name": "Flatten", "value": `flatten`, "example": `{{ [1, [1, 2], [2, 3, 4]] | flatten }}` },
{"name": "URL encode", "value": `url_encode`, "example": `{{ "https://www.google.com/search?q=hello world" | url_encode }}`}, { "name": "URL encode", "value": `url_encode`, "example": `{{ "https://www.google.com/search?q=hello world" | url_encode }}` },
{"name": "URL decode ", "value": `url_decode`, "example": `{{ "https://www.google.com/search?q=hello%20world" | url_decode }}`}, { "name": "URL decode ", "value": `url_decode`, "example": `{{ "https://www.google.com/search?q=hello%20world" | url_decode }}` },
{"name": "base64_encode", "value": `base64_encode`, "example": `{{ "https://www.google.com/search?q=hello%20world" | base64_encode }}`}, { "name": "base64_encode", "value": `base64_encode`, "example": `{{ "https://www.google.com/search?q=hello%20world" | base64_encode }}` },
{"name": "base64_decode", "value": `base64_decode`, "example": `{{ "aGVsbG8K" | base64_encode }}`}, { "name": "base64_decode", "value": `base64_decode`, "example": `{{ "aGVsbG8K" | base64_encode }}` },
] ]
const mathFilters = [ const mathFilters = [
{"name": "Plus", "value": "plus: 1", "example": `{{ "1" | plus: 1 }}`}, { "name": "Plus", "value": "plus: 1", "example": `{{ "1" | plus: 1 }}` },
{"name": "Minus", "value": "minus: 1", "example": `{{ "1" | minus: 1 }}`}, { "name": "Minus", "value": "minus: 1", "example": `{{ "1" | minus: 1 }}` },
] ]
const pythonFilters = [ const pythonFilters = [
{"name": "Hello World", "value": `{% python %}\nprint("hello world")\n{% endpython %}`, "example": ``}, { "name": "Hello World", "value": `{% python %}\nprint("hello world")\n{% endpython %}`, "example": `` },
{"name": "Handle JSON", "value": `{% python %}\nimport json\njsondata = json.loads(r"""$nodename""")\n{% endpython %}`, "example": ``}, { "name": "Handle JSON", "value": `{% python %}\nimport json\njsondata = json.loads(r"""$nodename""")\n{% endpython %}`, "example": `` },
] ]
const extensions = [] const extensions = []
@@ -104,7 +104,7 @@ const CodeEditor = (props) => {
runUpdateText, runUpdateText,
toolsAppId, toolsAppId,
parameterName, parameterName,
selectedAction , selectedAction,
workflowExecutions, workflowExecutions,
getParents, getParents,
activeDialog, activeDialog,
@@ -184,9 +184,9 @@ const CodeEditor = (props) => {
return return
} }
for(var i=0; i < actionlist.length; i++){ for (var i = 0; i < actionlist.length; i++) {
allVariables.push('$'+actionlist[i].autocomplete.toLowerCase()) allVariables.push('$' + actionlist[i].autocomplete.toLowerCase())
tmpVariables.push('$'+actionlist[i].autocomplete.toLowerCase()) tmpVariables.push('$' + actionlist[i].autocomplete.toLowerCase())
var parsedPaths = [] var parsedPaths = []
if (typeof actionlist[i].example === "object") { if (typeof actionlist[i].example === "object") {
@@ -194,7 +194,7 @@ const CodeEditor = (props) => {
} }
for (var key in parsedPaths) { for (var key in parsedPaths) {
const fullpath = "$"+actionlist[i].autocomplete.toLowerCase()+parsedPaths[key].autocomplete const fullpath = "$" + actionlist[i].autocomplete.toLowerCase() + parsedPaths[key].autocomplete
if (!allVariables.includes(fullpath)) { if (!allVariables.includes(fullpath)) {
allVariables.push(fullpath) allVariables.push(fullpath)
allVariables.push(fullpath.toLowerCase()) allVariables.push(fullpath.toLowerCase())
@@ -295,7 +295,7 @@ const CodeEditor = (props) => {
console.log("Parents: ", parents) console.log("Parents: ", parents)
var actionlist = [] var actionlist = []
if (parents.length > 1) { if (parents.length > 1) {
for (let [key,keyval] in Object.entries(parents)) { for (let [key, keyval] in Object.entries(parents)) {
const item = parents[key]; const item = parents[key];
if (item.label === "Execution Argument") { if (item.label === "Execution Argument") {
continue; continue;
@@ -307,7 +307,7 @@ const CodeEditor = (props) => {
if (workflowExecutions.length > 0) { if (workflowExecutions.length > 0) {
// Look for the ID // Look for the ID
const found = false; const found = false;
for (let [key,keyval] in Object.entries(workflowExecutions)) { for (let [key, keyval] in Object.entries(workflowExecutions)) {
if (workflowExecutions[key].results === undefined || workflowExecutions[key].results === null) { if (workflowExecutions[key].results === undefined || workflowExecutions[key].results === null) {
continue; continue;
} }
@@ -499,21 +499,21 @@ const CodeEditor = (props) => {
var variable_ranges = [] var variable_ranges = []
var popup = false var popup = false
for(var ch=0; ch < code_line.length; ch++){ for (var ch = 0; ch < code_line.length; ch++) {
if(code_line[ch] === '$'){ if (code_line[ch] === '$') {
dollar_occurences.push(ch) dollar_occurences.push(ch)
} }
} }
var variable_occurences = code_line.match(/[$]{1}([a-zA-Z0-9_-]+\.?){1}([a-zA-Z0-9#_-]+\.?){0,}/g) var variable_occurences = code_line.match(/[$]{1}([a-zA-Z0-9_-]+\.?){1}([a-zA-Z0-9#_-]+\.?){0,}/g)
try{ try {
for(var occ = 0; occ < variable_occurences.length; occ++){ for (var occ = 0; occ < variable_occurences.length; occ++) {
dollar_occurences_len.push(variable_occurences[occ].length) dollar_occurences_len.push(variable_occurences[occ].length)
} }
} catch (e) {} } catch (e) { }
for(var occ = 0; occ < dollar_occurences.length; occ++){ for (var occ = 0; occ < dollar_occurences.length; occ++) {
// var temp_arr = [] // var temp_arr = []
// for(var occ_len = 0; occ_len<dollar_occurences_len[occ]; occ_len++){ // for(var occ_len = 0; occ_len<dollar_occurences_len[occ]; occ_len++){
// temp_arr.push(dollar_occurences[occ]+occ_len) // temp_arr.push(dollar_occurences[occ]+occ_len)
@@ -522,24 +522,24 @@ const CodeEditor = (props) => {
// temp_arr.push(temp_arr[temp_arr.length-1]+1) // temp_arr.push(temp_arr[temp_arr.length-1]+1)
// variable_ranges.push(temp_arr) // variable_ranges.push(temp_arr)
var temp_arr = [dollar_occurences[occ]] var temp_arr = [dollar_occurences[occ]]
for(var occ_len = 0; occ_len < dollar_occurences_len[occ]; occ_len++){ for (var occ_len = 0; occ_len < dollar_occurences_len[occ]; occ_len++) {
temp_arr.push(dollar_occurences[occ]+occ_len+1) temp_arr.push(dollar_occurences[occ] + occ_len + 1)
} }
if(temp_arr.length==1) { if (temp_arr.length == 1) {
temp_arr.push(temp_arr[temp_arr.length-1]+1) temp_arr.push(temp_arr[temp_arr.length - 1] + 1)
} }
variable_ranges.push(temp_arr) variable_ranges.push(temp_arr)
} }
for(var occ = 0; occ<variable_ranges.length; occ++){ for (var occ = 0; occ < variable_ranges.length; occ++) {
for(var occ1 = 0; occ1<variable_ranges[occ].length; occ1++){ for (var occ1 = 0; occ1 < variable_ranges[occ].length; occ1++) {
// console.log(variable_ranges[occ][occ1]) // console.log(variable_ranges[occ][occ1])
if(loc === variable_ranges[occ][occ1]){ if (loc === variable_ranges[occ][occ1]) {
popup = true popup = true
setCurrentLocation([line, dollar_occurences[occ]]) setCurrentLocation([line, dollar_occurences[occ]])
try{ try {
setCurrentVariable(variable_occurences[occ]) setCurrentVariable(variable_occurences[occ])
} catch (e) { } catch (e) {
@@ -572,7 +572,7 @@ const CodeEditor = (props) => {
// Makes sure #0 and # are same, as we only visualize first one anyway // Makes sure #0 and # are same, as we only visualize first one anyway
if (tmpitem.startsWith("#")) { if (tmpitem.startsWith("#")) {
removedIndexes += tmpitem.length-1 removedIndexes += tmpitem.length - 1
tmpitem = "#" tmpitem = "#"
} }
@@ -614,8 +614,8 @@ const CodeEditor = (props) => {
} }
var dollar_occurence_len = [] var dollar_occurence_len = []
try{ try {
for(let occ = 0; occ < variable_occurence.length; occ++){ for (let occ = 0; occ < variable_occurence.length; occ++) {
dollar_occurence_len.push(variable_occurence[occ].length) dollar_occurence_len.push(variable_occurence[occ].length)
} }
} catch (e) { } catch (e) {
@@ -630,7 +630,7 @@ const CodeEditor = (props) => {
for (let occ = 0; occ < variable_occurence.length; occ++) { for (let occ = 0; occ < variable_occurence.length; occ++) {
const fixedVariable = fixVariable(variable_occurence[occ]) const fixedVariable = fixVariable(variable_occurence[occ])
var correctVariable = availableVariables.includes(fixedVariable.toLowerCase()) var correctVariable = availableVariables.includes(fixedVariable)
var startCh = dollar_occurence[occ] var startCh = dollar_occurence[occ]
var endCh = dollar_occurence[occ] + dollar_occurence_len[occ] var endCh = dollar_occurence[occ] + dollar_occurence_len[occ]
@@ -679,10 +679,10 @@ const CodeEditor = (props) => {
var parsedVariable = currentVariable var parsedVariable = currentVariable
if (currentVariable === undefined || currentVariable === null) { if (currentVariable === undefined || currentVariable === null) {
console.log("Location: ", currentLocation) console.log("Location: ", currentLocation)
parsedVariable= "$" parsedVariable = "$"
} }
code_lines[currentLine] = code_lines[currentLine].slice(0,currentLocation[1]) + "$" + swapVariable + code_lines[currentLine].slice(currentLocation[1]+parsedVariable.length,) code_lines[currentLine] = code_lines[currentLine].slice(0, currentLocation[1]) + "$" + swapVariable + code_lines[currentLine].slice(currentLocation[1] + parsedVariable.length,)
// console.log(code_lines) // console.log(code_lines)
var updatedCode = code_lines.join('\n') var updatedCode = code_lines.join('\n')
// console.log(updatedCode) // console.log(updatedCode)
@@ -721,7 +721,7 @@ const CodeEditor = (props) => {
var valuefound = false var valuefound = false
for (var j = 0; j < actionlist.length; j++) { for (var j = 0; j < actionlist.length; j++) {
if(fixedVariable.slice(1,).toLowerCase() !== actionlist[j].autocomplete.toLowerCase()) { if (fixedVariable.slice(1,).toLowerCase() !== actionlist[j].autocomplete.toLowerCase()) {
continue continue
} }
@@ -746,16 +746,16 @@ const CodeEditor = (props) => {
if (!valuefound) { if (!valuefound) {
} }
if (!valuefound && availableVariables.includes(fixedVariable.toLowerCase())) { if (!valuefound && availableVariables.includes(fixedVariable)) {
var shouldbreak = false var shouldbreak = false
for (var k=0; k < actionlist.length; k++){ for (var k = 0; k < actionlist.length; k++) {
var parsedPaths = [] var parsedPaths = []
if (typeof actionlist[k].example === "object") { if (typeof actionlist[k].example === "object") {
parsedPaths = GetParsedPaths(actionlist[k].example, ""); parsedPaths = GetParsedPaths(actionlist[k].example, "");
} }
for (var key in parsedPaths) { for (var key in parsedPaths) {
const fullpath = "$"+actionlist[k].autocomplete.toLowerCase()+parsedPaths[key].autocomplete.toLowerCase() const fullpath = "$" + actionlist[k].autocomplete.toLowerCase() + parsedPaths[key].autocomplete.toLowerCase()
if (fullpath !== fixedVariable.toLowerCase()) { if (fullpath !== fixedVariable.toLowerCase()) {
continue continue
} }
@@ -877,9 +877,9 @@ const CodeEditor = (props) => {
if (edited === false) { if (edited === false) {
if (!item.value.includes("{%") && !item.value.includes("{{")) { if (!item.value.includes("{%") && !item.value.includes("{{")) {
setlocalcodedata(localcodedata+" | "+item.value+" }}") setlocalcodedata(localcodedata + " | " + item.value + " }}")
} else { } else {
setlocalcodedata(localcodedata+item.value) setlocalcodedata(localcodedata + item.value)
} }
} }
@@ -897,9 +897,9 @@ const CodeEditor = (props) => {
const appid = toolsAppId !== undefined && toolsAppId !== null && toolsAppId.length > 0 ? toolsAppId : "3e2bdf9d5069fe3f4746c29d68785a6a" const appid = toolsAppId !== undefined && toolsAppId !== null && toolsAppId.length > 0 ? toolsAppId : "3e2bdf9d5069fe3f4746c29d68785a6a"
const actionname = selectedAction.name === "execute_python" && !inputdata.replaceAll(" ", "").includes("{%python%}") ? "execute_python" : selectedAction.name === "execute_bash" ? "execute_bash" : "repeat_back_to_me" const actionname = selectedAction.name === "execute_python" && !inputdata.replaceAll(" ", "").includes("{%python%}") ? "execute_python" : selectedAction.name === "execute_bash" ? "execute_bash" : "repeat_back_to_me"
const params = actionname === "execute_python" ? [{"name": "code", "value":inputdata}] : actionname === "execute_bash" ? [{"name": "code", "value":inputdata}, {"name": "shuffle_input", "value": "", }] : [{"name":"call", "value": inputdata}] const params = actionname === "execute_python" ? [{ "name": "code", "value": inputdata }] : actionname === "execute_bash" ? [{ "name": "code", "value": inputdata }, { "name": "shuffle_input", "value": "", }] : [{ "name": "call", "value": inputdata }]
const actiondata = {"description":"Repeats the call parameter","id":"","name":actionname,"label":"","node_type":"","environment":"","sharing":false,"private_id":"","public_id":"","app_id": appid,"tags":null,"authentication":[],"tested":false,"parameters": params, "execution_variable":{"description":"","id":"","name":"","value":""},"returns":{"description":"","example":"","id":"","schema":{"type":"string"}},"authentication_id":"","example":"","auth_not_required":false,"source_workflow":"","run_magic_output":false,"run_magic_input":false,"execution_delay":0,"app_name":"Shuffle Tools","app_version":"1.2.0","selectedAuthentication":{}} const actiondata = { "description": "Repeats the call parameter", "id": "", "name": actionname, "label": "", "node_type": "", "environment": "", "sharing": false, "private_id": "", "public_id": "", "app_id": appid, "tags": null, "authentication": [], "tested": false, "parameters": params, "execution_variable": { "description": "", "id": "", "name": "", "value": "" }, "returns": { "description": "", "example": "", "id": "", "schema": { "type": "string" } }, "authentication_id": "", "example": "", "auth_not_required": false, "source_workflow": "", "run_magic_output": false, "run_magic_input": false, "execution_delay": 0, "app_name": "Shuffle Tools", "app_version": "1.2.0", "selectedAuthentication": {} }
setExecutionResult({ setExecutionResult({
"valid": false, "valid": false,
@@ -929,18 +929,18 @@ const CodeEditor = (props) => {
//console.log("RESPONSE: ", responseJson) //console.log("RESPONSE: ", responseJson)
var newResult = {} var newResult = {}
if (responseJson.success === true && responseJson.result !== null && responseJson.result !== undefined && responseJson.result.length > 0) { if (responseJson.success === true && responseJson.result !== null && responseJson.result !== undefined && responseJson.result.length > 0) {
const result = responseJson.result.slice(0, 50)+"..." const result = responseJson.result.slice(0, 50) + "..."
//toast("SUCCESS: "+result) //toast("SUCCESS: "+result)
const validate = validateJson(responseJson.result) const validate = validateJson(responseJson.result)
newResult = validate newResult = validate
} else if (responseJson.success === false && responseJson.reason !== undefined && responseJson.reason !== null) { } else if (responseJson.success === false && responseJson.reason !== undefined && responseJson.reason !== null) {
toast(responseJson.reason) toast(responseJson.reason)
newResult = {"valid": false, "result": responseJson.reason} newResult = { "valid": false, "result": responseJson.reason }
} else if (responseJson.success === true) { } else if (responseJson.success === true) {
newResult = {"valid": false, "result": "Couldn't finish execution. Please fill all the required fields, and retry the execution."} newResult = { "valid": false, "result": "Couldn't finish execution. Please fill all the required fields, and retry the execution." }
} else { } else {
newResult = {"valid": false, "result": "Couldn't finish execution (2). Please fill all the required fields, and validate the execution."} newResult = { "valid": false, "result": "Couldn't finish execution (2). Please fill all the required fields, and validate the execution." }
} }
if (responseJson.errors !== undefined && responseJson.errors !== null && responseJson.errors.length > 0) { if (responseJson.errors !== undefined && responseJson.errors !== null && responseJson.errors.length > 0) {
@@ -1054,14 +1054,14 @@ const CodeEditor = (props) => {
aria-labelledby="draggable-dialog-title" aria-labelledby="draggable-dialog-title"
// disableBackdropClick={true} // disableBackdropClick={true}
disableEnforceFocus={true} disableEnforceFocus={true}
style={{ pointerEvents: "none", zIndex: activeDialog === "codeeditor" ? 1200 : 1100}} style={{ pointerEvents: "none", zIndex: activeDialog === "codeeditor" ? 1200 : 1100 }}
hideBackdrop={true} hideBackdrop={true}
open={expansionModalOpen} open={expansionModalOpen}
onClose={() => { onClose={() => {
console.log("In closer") console.log("In closer")
if (changeActionParameterCodeMirror !== undefined) { if (changeActionParameterCodeMirror !== undefined) {
changeActionParameterCodeMirror({target: {value: ""}}, fieldCount, localcodedata) changeActionParameterCodeMirror({ target: { value: "" } }, fieldCount, localcodedata)
} else { } else {
console.log("No action called changeActionParameterCodeMirror in code editor") console.log("No action called changeActionParameterCodeMirror in code editor")
} }
@@ -1084,7 +1084,7 @@ const CodeEditor = (props) => {
maxHeight: isMobile ? "100%" : 700, maxHeight: isMobile ? "100%" : 700,
border: theme.palette.defaultBorder, border: theme.palette.defaultBorder,
padding: isMobile ? "25px 10px 25px 10px" : 25, padding: isMobile ? "25px 10px 25px 10px" : 25,
zoom: 0.8, // zoom: 0.8,
backgroundColor: "black", backgroundColor: "black",
}, },
}} }}
@@ -1096,7 +1096,7 @@ const CodeEditor = (props) => {
title={`The File content is loading. Please wait a moment.`} title={`The File content is loading. Please wait a moment.`}
placement="top" placement="top"
> >
<CircularProgress style={{position: "absolute", right: 106, top: 6, }}/> <CircularProgress style={{ position: "absolute", right: 106, top: 6, }} />
</Tooltip> </Tooltip>
: null} : null}
@@ -1142,18 +1142,18 @@ const CodeEditor = (props) => {
<CloseIcon /> <CloseIcon />
</IconButton> </IconButton>
</Tooltip> </Tooltip>
<div style={{display: "flex"}}> <div style={{ display: "flex" }}>
<div style={{flex: 1, }}> <div style={{ flex: 1, }}>
{ isFileEditor ? {isFileEditor ?
<div <div
style={{ style={{
display: 'flex', display: 'flex',
}} }}
> >
<div style={{display: "flex"}}> <div style={{ display: "flex" }}>
<DialogTitle <DialogTitle
style={{ style={{
paddingBottom:20, paddingBottom: 20,
paddingLeft: 10, paddingLeft: 10,
}} }}
> >
@@ -1167,7 +1167,7 @@ const CodeEditor = (props) => {
display: 'flex', display: 'flex',
}} }}
> >
<div style={{display: "flex"}}> <div style={{ display: "flex" }}>
{/* {/*
<DialogTitle <DialogTitle
id="draggable-dialog-title" id="draggable-dialog-title"
@@ -1180,19 +1180,19 @@ const CodeEditor = (props) => {
Code Editor Code Editor
</DialogTitle> </DialogTitle>
*/} */}
{ isFileEditor ? null : {isFileEditor ? null :
<div style={{display: "flex", maxHeight: 40, }}> <div style={{ display: "flex", maxHeight: 40, }}>
{selectedAction?.name === "execute_python" ? {selectedAction?.name === "execute_python" ?
<Typography variant="body1" style={{marginTop: 5, }}> <Typography variant="body1" style={{ marginTop: 5, }}>
Run Python Code Run Python Code
</Typography> </Typography>
: :
selectedAction.name === "execute_bash" ? selectedAction.name === "execute_bash" ?
<Typography variant="body1" style={{marginTop: 5, }}> <Typography variant="body1" style={{ marginTop: 5, }}>
Run Bash Code Run Bash Code
</Typography> </Typography>
: :
<div style={{display: "flex", }}> <div style={{ display: "flex", }}>
<Button <Button
id="basic-button" id="basic-button"
aria-haspopup="true" aria-haspopup="true"
@@ -1442,7 +1442,7 @@ const CodeEditor = (props) => {
handleItemClick([innerdata]); handleItemClick([innerdata]);
}} }}
> >
<Paper style={{minHeight: 550, maxHeight: 550, minWidth: 275, maxWidth: 275, position: "fixed", left: menuPosition1.left-270, padding: "10px 0px 10px 10px", overflow: "hidden", overflowY: "auto", border: "1px solid rgba(255,255,255,0.3)",}}> <Paper style={{ minHeight: 550, maxHeight: 550, minWidth: 275, maxWidth: 275, position: "fixed", left: menuPosition1.left - 270, padding: "10px 0px 10px 10px", overflow: "hidden", overflowY: "auto", border: "1px solid rgba(255,255,255,0.3)", }}>
<MenuItem <MenuItem
key={innerdata.name} key={innerdata.name}
style={{ style={{
@@ -1461,7 +1461,7 @@ const CodeEditor = (props) => {
handleItemClick([innerdata]); handleItemClick([innerdata]);
}} }}
> >
<Typography variant="h6" style={{paddingBottom: 5}}> <Typography variant="h6" style={{ paddingBottom: 5 }}>
{innerdata.name} {innerdata.name}
</Typography> </Typography>
</MenuItem> </MenuItem>
@@ -1470,19 +1470,19 @@ const CodeEditor = (props) => {
//<VpnKeyIcon style={iconStyle} /> //<VpnKeyIcon style={iconStyle} />
const icon = const icon =
pathdata.type === "value" ? ( pathdata.type === "value" ? (
<span style={{marginLeft: 9, }} /> <span style={{ marginLeft: 9, }} />
) : pathdata.type === "list" ? ( ) : pathdata.type === "list" ? (
<FormatListNumberedIcon style={{marginLeft: 9, marginRight: 10, }} /> <FormatListNumberedIcon style={{ marginLeft: 9, marginRight: 10, }} />
) : ( ) : (
<CircleIcon style={{marginLeft: 9, marginRight: 10, color: coverColor}}/> <CircleIcon style={{ marginLeft: 9, marginRight: 10, color: coverColor }} />
); );
//<ExpandMoreIcon style={iconStyle} /> //<ExpandMoreIcon style={iconStyle} />
const indentation_count = (pathdata.name.match(/\./g) || []).length+1 const indentation_count = (pathdata.name.match(/\./g) || []).length + 1
//const boxPadding = pathdata.type === "object" ? "10px 0px 0px 0px" : 0 //const boxPadding = pathdata.type === "object" ? "10px 0px 0px 0px" : 0
const boxPadding = 0 const boxPadding = 0
const namesplit = pathdata.name.split(".") const namesplit = pathdata.name.split(".")
const newname = namesplit[namesplit.length-1] const newname = namesplit[namesplit.length - 1]
return ( return (
<MenuItem <MenuItem
key={pathdata.name} key={pathdata.name}
@@ -1508,11 +1508,11 @@ const CodeEditor = (props) => {
<div style={{ display: "flex", height: 30, }}> <div style={{ display: "flex", height: 30, }}>
{Array(indentation_count).fill().map((subdata, subindex) => { {Array(indentation_count).fill().map((subdata, subindex) => {
return ( return (
<div key={subindex} style={{marginLeft: 20, height: 30, width: 1, backgroundColor: coverColor,}} /> <div key={subindex} style={{ marginLeft: 20, height: 30, width: 1, backgroundColor: coverColor, }} />
) )
})} })}
{icon} {newname} {icon} {newname}
{pathdata.type === "list" ? <SquareFootIcon style={{marginleft: 10, }} onClick={(e) => { {pathdata.type === "list" ? <SquareFootIcon style={{ marginleft: 10, }} onClick={(e) => {
e.preventDefault() e.preventDefault()
e.stopPropagation() e.stopPropagation()
@@ -1521,7 +1521,7 @@ const CodeEditor = (props) => {
// Removing .list from autocomplete // Removing .list from autocomplete
var newname = pathdata.name var newname = pathdata.name
if (newname.length > 5) { if (newname.length > 5) {
newname = newname.slice(0, newname.length-5) newname = newname.slice(0, newname.length - 5)
} }
//selectedActionParameters[count].value += `{{ $${innerdata.name}.${newname} | size }}` //selectedActionParameters[count].value += `{{ $${innerdata.name}.${newname} | size }}`
@@ -1617,9 +1617,9 @@ const CodeEditor = (props) => {
placement="top" placement="top"
> >
{isAiLoading ? {isAiLoading ?
<CircularProgress style={{height: 20, width: 20, color: "rgba(255,255,255,0.7)"}}/> <CircularProgress style={{ height: 20, width: 20, color: "rgba(255,255,255,0.7)" }} />
: :
<AutoFixHighIcon style={{color: "rgba(255,255,255,0.7)"}}/> <AutoFixHighIcon style={{ color: "rgba(255,255,255,0.7)" }} />
} }
</Tooltip> </Tooltip>
</IconButton> </IconButton>
@@ -1690,7 +1690,7 @@ const CodeEditor = (props) => {
}} }}
// options={options} // options={options}
/> />
): null} ) : null}
</div> </div>
<div <div
@@ -1701,7 +1701,7 @@ const CodeEditor = (props) => {
</div> </div>
{isFileEditor ? null : {isFileEditor ? null :
<div style={{flex: 1, marginLeft: 5, borderLeft: "1px solid rgba(255,255,255,0.3)", paddingLeft: 5, overflow: "hidden", }}> <div style={{ flex: 1, marginLeft: 5, borderLeft: "1px solid rgba(255,255,255,0.3)", paddingLeft: 5, overflow: "hidden", }}>
<div> <div>
{isMobile ? null : {isMobile ? null :
<DialogTitle <DialogTitle
@@ -1713,7 +1713,7 @@ const CodeEditor = (props) => {
}} }}
> >
<div> <div>
<span style={{color: "white"}}> <span style={{ color: "white" }}>
{selectedAction === undefined ? "" : selectedAction.name === "execute_python" || selectedAction.name === "execute_bash" ? "Code to run" : `Expected Output for '${selectedAction.name}'`} {selectedAction === undefined ? "" : selectedAction.name === "execute_python" || selectedAction.name === "execute_bash" ? "Code to run" : `Expected Output for '${selectedAction.name}'`}
</span> </span>
@@ -1722,7 +1722,7 @@ const CodeEditor = (props) => {
</DialogTitle> </DialogTitle>
} }
<div style={{ }}> <div style={{}}>
<Tooltip title="Try it! This runs the Shuffle Tools 'repeat back to me' or 'execute python' action with what you see in the expected output window. Commonly used to test your Python scripts or Liquid filters, not requiring the full workflow to run again." placement="top"> <Tooltip title="Try it! This runs the Shuffle Tools 'repeat back to me' or 'execute python' action with what you see in the expected output window. Commonly used to test your Python scripts or Liquid filters, not requiring the full workflow to run again." placement="top">
<Button <Button
variant="outlined" variant="outlined"
@@ -1741,9 +1741,9 @@ const CodeEditor = (props) => {
}} }}
> >
{executing ? {executing ?
<CircularProgress style={{height: 18, width: 18, }} /> <CircularProgress style={{ height: 18, width: 18, }} />
: :
<span>{selectedAction === undefined ? "" : selectedAction.name === "execute_python" ? "Run Python Code" : selectedAction.name === "execute_bash" ? "Run Bash" : "Try it"}<PlayArrowIcon style={{height: 18, width: 18, marginBottom: -4, marginLeft: 5, }} /> </span> <span>{selectedAction === undefined ? "" : selectedAction.name === "execute_python" ? "Run Python Code" : selectedAction.name === "execute_bash" ? "Run Bash" : "Try it"}<PlayArrowIcon style={{ height: 18, width: 18, marginBottom: -4, marginLeft: 5, }} /> </span>
} }
</Button> </Button>
</Tooltip> </Tooltip>
@@ -1826,13 +1826,13 @@ const CodeEditor = (props) => {
name={"Test result"} name={"Test result"}
/> />
: :
<span style={{maxHeight: 190, minHeight: 190, }}> <span style={{ maxHeight: 190, minHeight: 190, }}>
{executionResult.result.length > 0 ? {executionResult.result.length > 0 ?
<span style={{maxHeight: 150, overflow: "auto", marginTop: 20, }}> <span style={{ maxHeight: 150, overflow: "auto", marginTop: 20, }}>
<Typography variant="body2"> <Typography variant="body2">
<b>Test output</b> <b>Test output</b>
</Typography> </Typography>
<Typography variant="body2" style={{whiteSpace: 'pre-line', }}> <Typography variant="body2" style={{ whiteSpace: 'pre-line', }}>
{executionResult.result} {executionResult.result}
</Typography> </Typography>
</span> </span>
@@ -1840,19 +1840,19 @@ const CodeEditor = (props) => {
<div> <div>
<Typography <Typography
variant = 'body2' variant='body2'
color = 'textSecondary' color='textSecondary'
> >
Output is based on the last VALID run of the node(s) you are referencing. Only updates when you refresh the Workflow Window. Output is based on the last VALID run of the node(s) you are referencing. Only updates when you refresh the Workflow Window.
</Typography> </Typography>
<Typography variant="body2" style={{maxHeight: 150, overflow: "auto", marginTop: 20,}}> <Typography variant="body2" style={{ maxHeight: 150, overflow: "auto", marginTop: 20, }}>
No test output yet. No test output yet.
</Typography> </Typography>
</div> </div>
} }
{executionResult.errors !== undefined && executionResult.errors !== null && executionResult.errors.length > 0 ? {executionResult.errors !== undefined && executionResult.errors !== null && executionResult.errors.length > 0 ?
<Typography variant="body2" style={{maxHeight: 100, overflow: "auto", color: "#f85a3e",}}> <Typography variant="body2" style={{ maxHeight: 100, overflow: "auto", color: "#f85a3e", }}>
Errors ({executionResult.errors.length}): {executionResult.errors.join("\n")} Errors ({executionResult.errors.length}): {executionResult.errors.join("\n")}
</Typography> </Typography>
: null} : null}
@@ -1865,7 +1865,7 @@ const CodeEditor = (props) => {
</div> </div>
<div style={{display: 'flex'}}> <div style={{ display: 'flex' }}>
<Button <Button
style={{ style={{
height: 35, height: 35,
@@ -1902,7 +1902,7 @@ const CodeEditor = (props) => {
// console.log(codedata) // console.log(codedata)
// console.log(fieldCount) // console.log(fieldCount)
if (isFileEditor === true){ if (isFileEditor === true) {
runUpdateText(fixedcodedata); runUpdateText(fixedcodedata);
setcodedata(fixedcodedata); setcodedata(fixedcodedata);
setExpansionModalOpen(false) setExpansionModalOpen(false)
+8 -1
View File
@@ -3,11 +3,18 @@ export const Context = createContext();
export const AppContext =(props) => { export const AppContext =(props) => {
const currentLocation = window?.location?.pathname;
// Left side bar global states // Left side bar global states
const [searchBarModalOpen, setSearchBarModalOpen] = useState(false); const [searchBarModalOpen, setSearchBarModalOpen] = useState(false);
const [leftSideBarOpenByClick, setLeftSideBarOpenByClick] = useState(false); const [leftSideBarOpenByClick, setLeftSideBarOpenByClick] = useState(currentLocation?.includes('/workflows/') ? false : true)
const [windowWidth, setWindowWidth] = useState(window.innerWidth); const [windowWidth, setWindowWidth] = useState(window.innerWidth);
useEffect(() => {
if (currentLocation?.includes('/workflows/') && leftSideBarOpenByClick === true) {
setLeftSideBarOpenByClick(false)
}
}, [leftSideBarOpenByClick])
//Calculate window width //Calculate window width
useEffect(() => { useEffect(() => {
+15 -16
View File
@@ -12,18 +12,18 @@ const Admin2 = (props) => {
const [orgRequest, setOrgRequest] = React.useState(true); const [orgRequest, setOrgRequest] = React.useState(true);
const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io"; const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io";
const handleGetOrg = (orgId) => { const handleGetOrg = (orgId) => {
if ( // if (
serverside !== true && // serverside !== true &&
window.location.search !== undefined && // window.location.search !== undefined &&
window.location.search !== null // window.location.search !== null
) { // ) {
const urlSearchParams = new URLSearchParams(window.location.search); // const urlSearchParams = new URLSearchParams(window.location.search);
const params = Object.fromEntries(urlSearchParams.entries()); // const params = Object.fromEntries(urlSearchParams.entries());
const foundorgid = params["org_id"]; // const foundorgid = params["org_id"];
if (foundorgid !== undefined && foundorgid !== null) { // if (foundorgid !== undefined && foundorgid !== null) {
orgId = foundorgid; // orgId = foundorgid;
} // }
} // }
console.log("getting organization details for: ", orgId); console.log("getting organization details for: ", orgId);
// if (orgId === undefined) { // if (orgId === undefined) {
@@ -154,16 +154,15 @@ const Admin2 = (props) => {
}); });
}; };
useEffect(() => {
const urlSearchParams = new URLSearchParams(window.location.search); const urlSearchParams = new URLSearchParams(window.location.search);
const params = Object.fromEntries(urlSearchParams.entries()); const params = Object.fromEntries(urlSearchParams.entries());
const foundOrgID = params["org_id"] const foundOrgID = params["org_id"]
useEffect(() => {
if(foundOrgID !== null && foundOrgID !== undefined && userdata?.support && foundOrgID?.length > 0) { if(foundOrgID !== null && foundOrgID !== undefined && userdata?.support && foundOrgID?.length > 0) {
handleClickChangeOrg(foundOrgID) handleClickChangeOrg(foundOrgID)
} }
}, [foundOrgID]); }, [userdata]);
const handleClickChangeOrg = (orgId) => { const handleClickChangeOrg = (orgId) => {
// Don't really care about the logout // Don't really care about the logout
+17 -11
View File
@@ -399,7 +399,7 @@ const AngularWorkflow = (defaultprops) => {
props.match = {} props.match = {}
props.match.params = params props.match.params = params
const { leftSideBarOpenByClick, windowWidth } = useContext(Context) const { setLeftSideBarOpenByClick, leftSideBarOpenByClick, windowWidth } = useContext(Context)
const [workflowAsCode, setWorkflowAsCode] = useState(false); const [workflowAsCode, setWorkflowAsCode] = useState(false);
var to_be_copied = ""; var to_be_copied = "";
@@ -8662,6 +8662,9 @@ const releaseToConnectLabel = "Release to Connect"
getApps() getApps()
fetchUsecases() fetchUsecases()
setLeftSideBarOpenByClick(false)
localStorage.setItem("expandLeftNav", false)
const cursearch = typeof window === "undefined" || window.location === undefined ? "" : window.location.search; const cursearch = typeof window === "undefined" || window.location === undefined ? "" : window.location.search;
// FIXME: Don't check specific one here // FIXME: Don't check specific one here
@@ -10568,6 +10571,9 @@ const releaseToConnectLabel = "Release to Connect"
const CustomAppHits = connectHits(AppHits) const CustomAppHits = connectHits(AppHits)
var shuffleToolsApp = apps.find((app) => app.name === "Shuffle Tools") var shuffleToolsApp = apps.find((app) => app.name === "Shuffle Tools")
if (shuffleToolsApp !== undefined && shuffleToolsApp !== null) {
shuffleToolsApp = JSON.parse(JSON.stringify(shuffleToolsApp))
}
var viewedApps = [] var viewedApps = []
return ( return (
@@ -10620,24 +10626,24 @@ const releaseToConnectLabel = "Release to Connect"
<div style={{ <div style={{
display: "flex", display: "flex",
}}> }}>
<ParsedAppPaper small={true} action={"repeat_back_to_me"} app={JSON.parse(JSON.stringify(shuffleToolsApp))} /> <ParsedAppPaper small={true} action={"repeat_back_to_me"} app={shuffleToolsApp} />
<div style={{marginLeft: 5, }}/> <div style={{marginLeft: 5, }}/>
<ParsedAppPaper small={true} action={"filter_list"} app={JSON.parse(JSON.stringify(shuffleToolsApp))} /> <ParsedAppPaper small={true} action={"filter_list"} app={shuffleToolsApp} />
<div style={{marginLeft: 5, }}/> <div style={{marginLeft: 5, }}/>
<ParsedAppPaper small={true} action={"execute_python"} app={JSON.parse(JSON.stringify(shuffleToolsApp))} /> <ParsedAppPaper small={true} action={"execute_python"} app={shuffleToolsApp} />
<div style={{marginLeft: 5, }}/> <div style={{marginLeft: 5, }}/>
<ParsedAppPaper small={true} action={"parse_ioc"} app={JSON.parse(JSON.stringify(shuffleToolsApp))} /> <ParsedAppPaper small={true} action={"parse_ioc"} app={shuffleToolsApp} />
</div> </div>
<div style={{ <div style={{
display: "flex", display: "flex",
}}> }}>
<ParsedAppPaper small={true} action={"set_cache_value"} app={JSON.parse(JSON.stringify(shuffleToolsApp))} /> <ParsedAppPaper small={true} action={"set_cache_value"} app={shuffleToolsApp} />
<div style={{marginLeft: 5, }}/> <div style={{marginLeft: 5, }}/>
<ParsedAppPaper small={true} action={"get_file_meta"} app={JSON.parse(JSON.stringify(shuffleToolsApp))} /> <ParsedAppPaper small={true} action={"get_file_meta"} app={shuffleToolsApp} />
<div style={{marginLeft: 5, }}/> <div style={{marginLeft: 5, }}/>
<ParsedAppPaper small={true} action={"merge_lists"} app={JSON.parse(JSON.stringify(shuffleToolsApp))} /> <ParsedAppPaper small={true} action={"merge_lists"} app={shuffleToolsApp} />
<div style={{marginLeft: 5, }}/> <div style={{marginLeft: 5, }}/>
<ParsedAppPaper small={true} action={"send_sms_shuffle"} app={JSON.parse(JSON.stringify(shuffleToolsApp))} /> <ParsedAppPaper small={true} action={"send_sms_shuffle"} app={shuffleToolsApp} />
</div> </div>
</div> </div>
: null} : null}
@@ -16242,7 +16248,7 @@ const releaseToConnectLabel = "Release to Connect"
{!distributedFromParent ? {!distributedFromParent ?
isCorrectOrg ? null : isCorrectOrg ? null :
<Typography variant="body2"> <Typography variant="body2" style={{marginLeft: 10, }}>
<b>Warning</b>: Change <span <b>Warning</b>: Change <span
style={{color: "#FF8544", cursor: "pointer", pointerEvents: "auto", }} style={{color: "#FF8544", cursor: "pointer", pointerEvents: "auto", }}
onClick={() => { onClick={() => {
@@ -16313,7 +16319,7 @@ const releaseToConnectLabel = "Release to Connect"
>Active Organization</span> to edit this Workflow. >Active Organization</span> to edit this Workflow.
</Typography> </Typography>
: :
<Typography variant="body2" color="textSecondary"> <Typography variant="body2" color="textSecondary" style={{marginLeft: 10, }}>
Warning: This workflow is controlled by your parent org and may not be editable. Warning: This workflow is controlled by your parent org and may not be editable.
</Typography> </Typography>
} }
+9 -2
View File
@@ -69,6 +69,7 @@ const ApiExplorerWrapper = (props) => {
const [authenticationType, setAuthenticationType] = React.useState(""); const [authenticationType, setAuthenticationType] = React.useState("");
const [appAuthentication, setAppAuthentication] = useState([]); const [appAuthentication, setAppAuthentication] = useState([]);
const [selectedMeta, setSelectedMeta] = useState(undefined); const [selectedMeta, setSelectedMeta] = useState(undefined);
const [appLoaded, setAppLoaded] = useState(false);
const [selectedAction, setSelectedAction] = useState( const [selectedAction, setSelectedAction] = useState(
{ {
"app_name": selectedAppData.name, "app_name": selectedAppData.name,
@@ -258,6 +259,7 @@ const ApiExplorerWrapper = (props) => {
parsedapp.body === undefined ? parsedapp : JSON.parse(parsedapp.body); parsedapp.body === undefined ? parsedapp : JSON.parse(parsedapp.body);
setOpenapi(data); setOpenapi(data);
setAppLoaded(true);
}; };
const handleAppAuthenticationType = (selectedAppData) => { const handleAppAuthenticationType = (selectedAppData) => {
@@ -773,7 +775,7 @@ const ApiExplorerWrapper = (props) => {
); );
}; };
const skeletonLoader = ( const SkeletonLoader = () => (
<Box <Box
sx={{ sx={{
display: "flex", display: "flex",
@@ -892,6 +894,7 @@ const ApiExplorerWrapper = (props) => {
</Box> </Box>
); );
const AuthenticationData = (props) => { const AuthenticationData = (props) => {
const selectedApp = props.app; const selectedApp = props.app;
@@ -1756,7 +1759,10 @@ const ApiExplorerWrapper = (props) => {
return ( return (
<Wrapper isLoggedIn={isLoggedIn} isLoaded={isLoaded}> <Wrapper isLoggedIn={isLoggedIn} isLoaded={isLoaded}>
<Suspense fallback={skeletonLoader}> {appLoaded === false ? (
<SkeletonLoader />
) : (
<Suspense fallback={SkeletonLoader}>
{authenticationModal} {authenticationModal}
<ApiExplorer <ApiExplorer
openapi={openapi} openapi={openapi}
@@ -1770,6 +1776,7 @@ const ApiExplorerWrapper = (props) => {
isLoaded={isLoaded} isLoaded={isLoaded}
/> />
</Suspense> </Suspense>
)}
</Wrapper> </Wrapper>
); );
}; };
+5 -3
View File
@@ -5811,9 +5811,11 @@ const AppCreator = (defaultprops) => {
variant="outlined" variant="outlined"
color="secondary" color="secondary"
onClick={() => { onClick={() => {
var urlParams = new URLSearchParams(window.location.search); var urlParams = new URLSearchParams(window.location.search)
if (!urlParams.has("id")) { if (urlParams.has("id")) {
window.open(`/apis/${app.id}`, "_blank") window.open(`/apis/${urlParams.get("id")}`, "_blank")
} else if (props.match.params.appid !== undefined && props.match.params.appid !== null && props.match.params.appid.length > 0) {
window.open(`/apis/${props.match.params.appid}`, "_blank")
} else { } else {
toast.error("Build the app first.") toast.error("Build the app first.")
} }
+122 -6
View File
@@ -1,7 +1,6 @@
import React, { useState, useEffect, useContext, useCallback, memo, useMemo, useRef } from "react"; import React, { useState, useEffect, useContext, useCallback, memo, useMemo, useRef } from "react";
import theme from "../theme.jsx"; import theme from "../theme.jsx";
import { isMobile } from "react-device-detect"; import { isMobile } from "react-device-detect";
import AppGrid from "../components/AppGrid.jsx";
import { useLocation, useNavigate } from "react-router-dom"; import { useLocation, useNavigate } from "react-router-dom";
import { import {
TextField, Button, Typography, MenuItem, Select, Tabs, Tab, Zoom, TextField, Button, Typography, MenuItem, Select, Tabs, Tab, Zoom,
@@ -75,6 +74,22 @@ const AppCard = ({ data, index, mouseHoverIndex, setMouseHoverIndex, globalUrl,
style={paperStyle} style={paperStyle}
onMouseOver={() => setMouseHoverIndex(index)} onMouseOver={() => setMouseHoverIndex(index)}
onMouseOut={() => setMouseHoverIndex(-1)} onMouseOut={() => setMouseHoverIndex(-1)}
>
<Tooltip
title="View app details"
placement="top"
componentsProps={{
tooltip: {
sx: {
backgroundColor: "rgba(33, 33, 33, 1)",
color: "rgba(241, 241, 241, 1)",
fontSize: 14,
border: "1px solid rgba(73, 73, 73, 1)",
fontFamily: theme?.typography?.fontFamily,
}
},
}}
arrow
> >
<ButtonBase <ButtonBase
style={{ style={{
@@ -111,7 +126,7 @@ const AppCard = ({ data, index, mouseHoverIndex, setMouseHoverIndex, globalUrl,
fontWeight: '400', fontWeight: '400',
overflow: "hidden", overflow: "hidden",
margin: "12px 0", margin: "12px 0",
fontFamily: theme?.typography?.fontFamily fontFamily: theme?.typography?.fontFamily,
}}> }}>
<div style={{ <div style={{
display: 'flex', display: 'flex',
@@ -207,6 +222,8 @@ const AppCard = ({ data, index, mouseHoverIndex, setMouseHoverIndex, globalUrl,
bgcolor: "rgba(93, 93, 93, 1)", bgcolor: "rgba(93, 93, 93, 1)",
}, },
}} }}
onMouseDown={(e) => e.stopPropagation()}
onMouseUp={(e) => e.stopPropagation()}
onClick={(event) => { onClick={(event) => {
event.preventDefault(); event.preventDefault();
event.stopPropagation(); event.stopPropagation();
@@ -241,6 +258,7 @@ const AppCard = ({ data, index, mouseHoverIndex, setMouseHoverIndex, globalUrl,
</div> </div>
</div> </div>
</ButtonBase> </ButtonBase>
</Tooltip>
</Paper> </Paper>
</Grid> </Grid>
); );
@@ -263,10 +281,11 @@ const Hits = ({
const [allActivatedAppIds, setAllActivatedAppIds] = useState([]); const [allActivatedAppIds, setAllActivatedAppIds] = useState([]);
const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io"; const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io";
const [deactivatedIndexes, setDeactivatedIndexes] = React.useState([]); const [deactivatedIndexes, setDeactivatedIndexes] = React.useState([]);
const [isLoading, setIsLoading] = useState(true) const [isLoading, setIsLoading] = useState(false)
useEffect(() => { useEffect(() => {
var baseurl = globalUrl; var baseurl = globalUrl;
setIsLoading(true)
fetch(baseurl + "/api/v1/me", { fetch(baseurl + "/api/v1/me", {
credentials: "include", credentials: "include",
headers: { headers: {
@@ -361,7 +380,34 @@ const Hits = ({
( (
<div> <div>
{hits?.length === 0 && searchQuery.length >= 0 ? ( {hits?.length === 0 && searchQuery.length >= 0 ? (
<Typography>No apps found</Typography> <div style={{
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
minHeight: 400,
gap: 16,
color: "#F1F1F1",
fontFamily: theme?.typography?.fontFamily
}}>
<SearchIcon style={{ fontSize: 48, color: 'rgba(255, 255, 255, 0.7)' }} />
<Typography variant="h6" style={{
fontFamily: theme?.typography?.fontFamily,
textAlign: "center"
}}>
No apps found matching your search criteria
</Typography>
<Typography
variant="body1"
style={{
color: 'rgba(255, 255, 255, 0.7)',
textAlign: "center",
maxWidth: 400
}}
>
Try adjusting your search terms or filters to find what you're looking for
</Typography>
</div>
) : ( ) : (
<div <div
style={{ style={{
@@ -412,6 +458,22 @@ const Hits = ({
onMouseLeave={() => { onMouseLeave={() => {
setHoverEffect(-1); setHoverEffect(-1);
}} }}
>
<Tooltip
title="View app details"
placement="top"
componentsProps={{
tooltip: {
sx: {
backgroundColor: "rgba(33, 33, 33, 1)",
color: "rgba(241, 241, 241, 1)",
fontSize: 14,
border: "1px solid rgba(73, 73, 73, 1)",
fontFamily: theme?.typography?.fontFamily,
}
},
}}
arrow
> >
<ButtonBase style={{ <ButtonBase style={{
borderRadius: 6, borderRadius: 6,
@@ -448,8 +510,9 @@ const Hits = ({
gap: 6, gap: 6,
fontWeight: '400', fontWeight: '400',
overflow: "hidden", overflow: "hidden",
margin: "12px 0", fontFamily: theme?.typography?.fontFamily,
fontFamily: theme?.typography?.fontFamily marginTop: 8,
marginLeft: 16,
}} }}
> >
<div <div
@@ -571,6 +634,8 @@ const Hits = ({
fontFamily: theme?.typography?.fontFamily, fontFamily: theme?.typography?.fontFamily,
fontSize: 16, fontSize: 16,
}} }}
onMouseDown={(e) => e.stopPropagation()}
onMouseUp={(e) => e.stopPropagation()}
onClick={(event) => { onClick={(event) => {
handleActivateButton(event, data, "deactivate"); handleActivateButton(event, data, "deactivate");
}}> }}>
@@ -588,6 +653,8 @@ const Hits = ({
fontFamily: theme?.typography?.fontFamily, fontFamily: theme?.typography?.fontFamily,
fontSize: 16 fontSize: 16
}} }}
onMouseDown={(e) => e.stopPropagation()}
onMouseUp={(e) => e.stopPropagation()}
onClick={(event) => { onClick={(event) => {
handleActivateButton(event, data, "activate"); handleActivateButton(event, data, "activate");
}} }}
@@ -601,6 +668,7 @@ const Hits = ({
</div> </div>
</div> </div>
</ButtonBase> </ButtonBase>
</Tooltip>
</Paper> </Paper>
</Zoom> </Zoom>
); );
@@ -872,6 +940,42 @@ const filterApps = (apps, searchQuery, selectedCategory, selectedLabel) => {
}); });
}; };
const LoginPrompt = () => {
const navigate = useNavigate();
return (
<div style={{
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
minHeight: 400,
gap: 20,
color: "#F1F1F1",
fontFamily: theme?.typography?.fontFamily
}}>
<Typography variant="h6" style={{ fontFamily: theme?.typography?.fontFamily }}>
Log in to see your organization's apps
</Typography>
<Button
variant="contained"
onClick={() => navigate("/login")}
style={{
backgroundColor: "#FF8544",
color: "#1A1A1A",
textTransform: "none",
fontFamily: theme?.typography?.fontFamily,
fontSize: 16,
padding: "10px 20px",
borderRadius: 4,
fontWeight: 600
}}
>
Log In
</Button>
</div>
)
};
// Add this new component for the app skeleton // Add this new component for the app skeleton
const AppSkeleton = () => { const AppSkeleton = () => {
return ( return (
@@ -1895,6 +1999,7 @@ const Apps2 = (props) => {
fullWidth fullWidth
variant="outlined" variant="outlined"
placeholder="Search for apps" placeholder="Search for apps"
disabled={!isLoggedIn}
value={searchQuery} value={searchQuery}
id="shuffle_search_field" id="shuffle_search_field"
onChange={handleSearchChange} onChange={handleSearchChange}
@@ -1945,6 +2050,7 @@ const Apps2 = (props) => {
variant="outlined" variant="outlined"
value={selectedCategory} value={selectedCategory}
onChange={handleCategoryChange} onChange={handleCategoryChange}
disabled={!isLoggedIn}
displayEmpty displayEmpty
multiple multiple
style={{ style={{
@@ -2009,6 +2115,7 @@ const Apps2 = (props) => {
variant="outlined" variant="outlined"
value={selectedLabel} value={selectedLabel}
onChange={handleLabelChange} onChange={handleLabelChange}
disabled={!isLoggedIn}
displayEmpty displayEmpty
multiple multiple
style={{ style={{
@@ -2067,6 +2174,7 @@ const Apps2 = (props) => {
variant="contained" variant="contained"
color="primary" color="primary"
onClick={handleCreateApp} onClick={handleCreateApp}
disabled={!isLoggedIn}
style={{ style={{
height: "100%", height: "100%",
width: '100%', width: '100%',
@@ -2092,6 +2200,7 @@ const Apps2 = (props) => {
{isLoading ? ( {isLoading ? (
<LoadingGrid /> <LoadingGrid />
) : ( ) : (
isLoggedIn && !isLoading ? (
<> <>
{appsToShow?.length > 0 && appsToShow !== undefined && !isLoading ? ( {appsToShow?.length > 0 && appsToShow !== undefined && !isLoading ? (
<div style={{ <div style={{
@@ -2137,6 +2246,9 @@ const Apps2 = (props) => {
</div> </div>
)} )}
</> </>
) : (
<LoginPrompt />
)
)} )}
</div> </div>
) )
@@ -2147,6 +2259,7 @@ const Apps2 = (props) => {
{isLoading ? ( {isLoading ? (
<LoadingGrid /> <LoadingGrid />
) : ( ) : (
isLoggedIn && !isLoading ? (
<> <>
{appsToShow?.length > 0 && appsToShow !== undefined ? ( {appsToShow?.length > 0 && appsToShow !== undefined ? (
<div style={{ <div style={{
@@ -2182,6 +2295,9 @@ const Apps2 = (props) => {
</div> </div>
)} )}
</> </>
) : (
<LoginPrompt />
)
)} )}
</div> </div>
) )
+16 -12
View File
@@ -716,6 +716,8 @@ const Workflows2 = (props) => {
const [videoViewOpen, setVideoViewOpen] = React.useState(false) const [videoViewOpen, setVideoViewOpen] = React.useState(false)
const [gettingStartedItems, setGettingStartedItems] = React.useState([]) const [gettingStartedItems, setGettingStartedItems] = React.useState([])
const [selectedWorkflowIndexes, setSelectedWorkflowIndexes] = React.useState([]) const [selectedWorkflowIndexes, setSelectedWorkflowIndexes] = React.useState([])
const [page, setPage] = React.useState(0);
const [pageSize, setPageSize] = React.useState(100);
const [highlightIds, setHighlightIds] = React.useState([]) const [highlightIds, setHighlightIds] = React.useState([])
const [apps, setApps] = React.useState([]); const [apps, setApps] = React.useState([]);
@@ -751,15 +753,6 @@ const Workflows2 = (props) => {
navigate(`${location.pathname}?${queryParams.toString()}`); navigate(`${location.pathname}?${queryParams.toString()}`);
}; };
useEffect(() => {
if (currTab === 2) {
setIsLoadingPublicWorkflow(true);
// Simulate loading time for the Algolia search results
setTimeout(() => {
setIsLoadingPublicWorkflow(false);
}, 2500);
}
}, [currTab])
@@ -1322,6 +1315,8 @@ const Workflows2 = (props) => {
if (responseJson !== undefined && responseJson !== null) { if (responseJson !== undefined && responseJson !== null) {
if (responseJson.success === false) { if (responseJson.success === false) {
} else if (responseJson.length === 0) { } else if (responseJson.length === 0) {
// When there are no workflows, we can set the loading to false
setIsLoadingWorkflow(false)
if (currTab !== 2) { if (currTab !== 2) {
toast("No workflows found. Showing workflow discovery") toast("No workflows found. Showing workflow discovery")
setCurrTab(2) setCurrTab(2)
@@ -2483,6 +2478,7 @@ const Workflows2 = (props) => {
} }
} }
return ( return (
<div style={{ width: "100%", minWidth: 320, position: "relative", border: highlightIds.includes(data.id) ? "2px solid #f85a3e" : isDistributed || hasSuborgs ? "2px solid #40E0D0" : "inherit", borderRadius: theme.palette?.borderRadius, backgroundColor: "#212121", fontFamily: theme?.typography?.fontFamily }}> <div style={{ width: "100%", minWidth: 320, position: "relative", border: highlightIds.includes(data.id) ? "2px solid #f85a3e" : isDistributed || hasSuborgs ? "2px solid #40E0D0" : "inherit", borderRadius: theme.palette?.borderRadius, backgroundColor: "#212121", fontFamily: theme?.typography?.fontFamily }}>
<Paper square style={paperAppStyle}> <Paper square style={paperAppStyle}>
@@ -2537,7 +2533,7 @@ const Workflows2 = (props) => {
maxWidth: 310, maxWidth: 310,
padding: "12px 0", padding: "12px 0",
}}> }}>
{(data?.image !== undefined || data?.image_url !== undefined) ? ( {(data?.image !== undefined || (data?.image_url !== undefined && data?.image_url.length > 0)) ? (
<div style={{ <div style={{
marginBottom: 15, marginBottom: 15,
borderRadius: theme.palette?.borderRadius, borderRadius: theme.palette?.borderRadius,
@@ -3371,7 +3367,15 @@ const Workflows2 = (props) => {
className={classes.datagrid} className={classes.datagrid}
rows={rows} rows={rows}
columns={columns} columns={columns}
pageSize={100} page={page}
onPageChange={(newPage) => {
setPage(newPage)
}}
pageSize={pageSize}
onPageSizeChange={(newPageSize) => {
setPageSize(newPageSize);
}}
rowsPerPageOptions={[25, 50, 100, 150]}
checkboxSelection checkboxSelection
autoHeight autoHeight
density="standard" density="standard"
@@ -3962,7 +3966,7 @@ const Workflows2 = (props) => {
setIsLoadingWorkflow(false); setIsLoadingWorkflow(false);
} }
}, [currTab, workflows, userdata, filteredWorkflows]) }, [currTab, workflows, userdata, filteredWorkflows, filters])
+5
View File
@@ -2298,6 +2298,10 @@ func main() {
} else if incRequest.Type == "START_TENZIR" { } else if incRequest.Type == "START_TENZIR" {
log.Printf("[INFO] Got job to start tenzir") log.Printf("[INFO] Got job to start tenzir")
// Manual command = overrides to allow starting of Tenzir from the frontend anyway.
os.Setenv("SHUFFLE_SKIP_PIPELINES", "false")
tenzirDisabled = false
err := deployTenzirNode() err := deployTenzirNode()
if err != nil { if err != nil {
if strings.Contains(fmt.Sprintf("%s", err), "node available") { if strings.Contains(fmt.Sprintf("%s", err), "node available") {
@@ -3456,6 +3460,7 @@ func sendPipelineHealthStatus() (shuffle.LakeConfig, error) {
if (!strings.Contains(err.Error(), "SHUFFLE_SKIP_PIPELINES") && !strings.Contains(err.Error(), "Kubernetes not implemented for Tenzir node")) && !strings.Contains(err.Error(), "Tenzir Node is already running") && !strings.Contains(err.Error(), "docker daemon") { if (!strings.Contains(err.Error(), "SHUFFLE_SKIP_PIPELINES") && !strings.Contains(err.Error(), "Kubernetes not implemented for Tenzir node")) && !strings.Contains(err.Error(), "Tenzir Node is already running") && !strings.Contains(err.Error(), "docker daemon") {
log.Printf("[ERROR] Tenzir node connection problem: %s", err) log.Printf("[ERROR] Tenzir node connection problem: %s", err)
} else { } else {
tenzirDisabled = true tenzirDisabled = true
log.Printf("[ERROR] Disabling pipelines: %s. You will need to restart the Orborus to fix this.", err) log.Printf("[ERROR] Disabling pipelines: %s. You will need to restart the Orborus to fix this.", err)