From aab73b5ecc4a9d8afce2bf4c195dcd12a68d2e3f Mon Sep 17 00:00:00 2001 From: Frikky Date: Thu, 9 Jan 2025 22:31:53 +0100 Subject: [PATCH] Fixed Tenzir force start from frontend --- frontend/src/components/AppModal.jsx | 218 +- frontend/src/components/AppSelection.jsx | 18 +- frontend/src/components/CacheView.jsx | 1 + frontend/src/components/Files.jsx | 456 +++- frontend/src/components/LeftSideBar.jsx | 55 +- .../src/components/ShuffleCodeEditor1.jsx | 1898 ++++++++--------- frontend/src/context/ContextApi.jsx | 9 +- frontend/src/views/Admin2.jsx | 33 +- frontend/src/views/AngularWorkflow.jsx | 28 +- frontend/src/views/ApiExplorerWrapper.jsx | 21 +- frontend/src/views/AppCreator.jsx | 8 +- frontend/src/views/Apps2.jsx | 950 +++++---- frontend/src/views/Workflows2.jsx | 28 +- functions/onprem/orborus/orborus.go | 5 + 14 files changed, 2164 insertions(+), 1564 deletions(-) diff --git a/frontend/src/components/AppModal.jsx b/frontend/src/components/AppModal.jsx index fce90fae..41ca61a8 100644 --- a/frontend/src/components/AppModal.jsx +++ b/frontend/src/components/AppModal.jsx @@ -11,6 +11,8 @@ import { Button, Stack, Avatar, + Skeleton, + Tooltip, } from '@mui/material'; import CloseIcon from '@mui/icons-material/Close'; @@ -38,6 +40,7 @@ const AppModal = ({ open, onClose, app, globalUrl }) => { const [inputUsecase, setInputUsecase] = useState({}) const [latestUsecase, setLatestUsecase] = useState([]) const [foundAppUsecase, setFoundAppUsecase] = useState({}) + const [usecaseLoading, setUsecaseLoading] = useState(false) const navigate = useNavigate(); const parseUsecase = (subcase) => { const srcdata = findSpecificApp(frameworkData, subcase.type) @@ -142,6 +145,19 @@ const AppModal = ({ open, onClose, app, globalUrl }) => { }) 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 if (responseJson.success !== false) { if (workflows !== undefined && workflows !== null && workflows.length > 0) { @@ -275,23 +291,12 @@ const AppModal = ({ open, onClose, app, globalUrl }) => { useEffect(() => { + setUsecaseLoading(true) getAvailableWorkflows() getFramework() }, [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 id = inputdata.id; @@ -389,9 +394,8 @@ const AppModal = ({ open, onClose, app, globalUrl }) => { 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 ( { app?.private_id !== undefined && app?.private_id?.length > 0 && app?.generated ? ( - ) : null} + + + ) : null} diff --git a/frontend/src/components/AppSelection.jsx b/frontend/src/components/AppSelection.jsx index 73528ec2..6d83f2b0 100644 --- a/frontend/src/components/AppSelection.jsx +++ b/frontend/src/components/AppSelection.jsx @@ -536,15 +536,16 @@ const AppSelection = props => { })} - { - !isAppPage && ( - <> {!moreButton ? (
{ setMoreButton(true) setTimeout(() => { - navigate("/welcome?tab=2") + if (isAppPage) { + navigate("/apps?tab=all_apps") + } else { + navigate("/welcome?tab=2") + } }, 250) }} >See More Apps @@ -552,15 +553,14 @@ const AppSelection = props => {
- - ) - }
) diff --git a/frontend/src/components/CacheView.jsx b/frontend/src/components/CacheView.jsx index 7929a7ab..e7835220 100644 --- a/frontend/src/components/CacheView.jsx +++ b/frontend/src/components/CacheView.jsx @@ -537,6 +537,7 @@ const CacheView = memo((props) => { padding: "15px 5px", maxHeight: 300, verticalAlign: "middle", + maxWidth: 300, }} primary={validate.valid ? { const [downloadBranch, setDownloadBranch] = React.useState("main"); const [downloadFolder, setDownloadFolder] = React.useState("translation_standards"); 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 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 = ""; @@ -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) =>{ fetch(`${globalUrl}/api/v1/files/${openFileId}/edit`, { method: "PUT", @@ -137,6 +199,7 @@ const Files = memo((props) => { if (responseJson.files !== undefined && responseJson.files !== null) { setFiles(responseJson.files); setShowLoader(false) + setShowDistributionPopup(false) } else if (responseJson.list !== undefined && responseJson.list !== null) { // Set the "namespace" field in all items if (namespace !== undefined && namespace !== null) { @@ -152,6 +215,7 @@ const Files = memo((props) => { } else { setFiles([]); setShowLoader(false) + setShowDistributionPopup(false) } if (namespace === undefined || namespace === null || namespace === "default") { @@ -256,7 +320,7 @@ const Files = memo((props) => { zIndex: 1000, minWidth: "800px", minHeight: "320px", - overflow: "hidden", + overflow: "auto", '& .MuiDialogContent-root': { backgroundColor: theme?.palette?.DialogStyle?.backgroundColor, }, @@ -400,6 +464,127 @@ const Files = memo((props) => {
: 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 ? ( + 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, + }, + }, + }} + > + +
+ Select sub-org to distribute files +
+
+ + {handleSelectSubOrg(null, "none")}}>None + {handleSelectSubOrg(null, "all")}}>All + {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 === "" ? ( + {data.name} + ) : ( + {data.name} + ); + + return ( + handleSelectSubOrg(data.id)} + style={{ display: "flex", alignItems: "center" }} + > + + {image} + {data.name} + + ); + })} + +
+ + +
+
+
+ + ): null + const deleteFile = (file) => { fetch(globalUrl + "/api/v1/files/" + file.id, { method: "DELETE", @@ -636,7 +821,7 @@ const Files = memo((props) => { setTimeout(() => { getFiles() - }, 2500); + }, 3000); }; const uploadFile = (e) => { @@ -649,6 +834,68 @@ const Files = memo((props) => { 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 ( { }} onDrop={uploadFile} > + {fileDistributionModal}
@@ -739,13 +987,18 @@ const Files = memo((props) => { }} value={selectedCategory} onChange={(event) => { + 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") { getFiles() } else { getFiles(event.target.value) } + // Add it to the url as a query if (window.location.search.includes("category=")) { @@ -768,14 +1021,41 @@ const Files = memo((props) => { ); })} + setShowFileCategoryPopup(false)}> + File Categories + + Please note that your selected files ({selectedFileId?.length}) will be moved to the {updateToThisCategory} category. + + + + + + ) : null}
{renderTextBox ? -
- { tableLayout: "auto", display: "table", minWidth: 800, - overflowX: "auto" + overflowX: "auto", + paddingBottom: 0, }} > - - {["Name", "Workflow", "Md5", "Status", "Filesize", "Actions"].map((header, index) => ( - + {[ + + { + 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) + ); + } + }} + /> + , + "Name", + "Workflow", + "Md5", + "Status", + "Filesize", + "Actions", + "Distribution" + ] + .filter(Boolean) + .map((header, index) => ( + - ))} - + }} + /> + ))} + {showLoader ? [...Array(6)].map((_, rowIndex) => ( { backgroundColor: "#212121", }} > - {Array(6) + {Array(8) .fill() .map((_, colIndex) => ( { if (index % 2 === 0) { bgColor = isSelectedFiles ? "#1A1A1A":"#1f2023"; } - + const isDistributed = file?.suborg_distribution?.length > 0 ? true : false; const filenamesplit = file.filename.split(".") const iseditable = file.filesize < 2000000 && file.status === "active" && allowedFileTypes.includes(filenamesplit[filenamesplit.length-1]) return ( @@ -953,6 +1286,26 @@ const Files = memo((props) => { primary={new Date(file.updated_at * 1000).toISOString()} /> */} + + {handleFileCheckboxChange(index); setSelectedFileId(prev => { + if (prev.includes(file.id)) { + return prev.filter((item) => item !== file.id) + } else { + return [...prev, file.id] + } + })}} + /> + { > { setOpenEditor(true) @@ -1137,7 +1490,6 @@ const Files = memo((props) => { { - console.log("file is : ", file) navigator.clipboard.writeText(file.id); document.execCommand("copy"); @@ -1154,7 +1506,7 @@ const Files = memo((props) => { > { deleteFile(file); @@ -1166,7 +1518,7 @@ const Files = memo((props) => { viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" style={{ - stroke: file.status === "active" ? "#fd4c62" : "#c8c8c8", + stroke: file.status === "active" && file.org_id === selectedOrganization.id ? "#fd4c62" : "#c8c8c8", }} > { // overflow: "hidden", }} /> + + {selectedOrganization.id !== undefined && file?.org_id !== selectedOrganization.id ? + + + + : + + { + setShowDistributionPopup(true) + if(file?.suborg_distribution?.length > 0){ + setSelectedSubOrg(file.suborg_distribution) + }else{ + setSelectedSubOrg([]) + } + setFileIdSelectedForDistribution(file.id) + }} + /> + + } + ); }) diff --git a/frontend/src/components/LeftSideBar.jsx b/frontend/src/components/LeftSideBar.jsx index 3ceea0e8..c6944955 100644 --- a/frontend/src/components/LeftSideBar.jsx +++ b/frontend/src/components/LeftSideBar.jsx @@ -58,6 +58,7 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => { const navigate = useNavigate(); const {setLeftSideBarOpenByClick, leftSideBarOpenByClick, setSearchBarModalOpen, searchBarModalOpen} = useContext(Context); + const [expandLeftNav, setExpandLeftNav] = useState(false); const [activeOrgName, setActiveOrgName] = useState( userdata?.active_org?.name || "Select Organziation" @@ -261,17 +262,20 @@ useEffect(() => { },[currentPath]); useEffect(() => { - UpdateTabStatus(); - const expandLeftNav1 = localStorage.getItem("expandLeftNav"); + UpdateTabStatus() + + const expandLeftNav1 = localStorage.getItem("expandLeftNav") if (expandLeftNav1 === "false") { - setLeftSideBarOpenByClick(false); - setLeftSideBarOpenByClick(false); + setLeftSideBarOpenByClick(false) } else { - setLeftSideBarOpenByClick(true); - setLeftSideBarOpenByClick(true); - setExpandLeftNav(true); + const currentLocation = window?.location?.pathname + if (currentLocation?.includes('/workflows/')) { + } else { + setLeftSideBarOpenByClick(true) + setExpandLeftNav(true) + } } - }, []); + }, []) const getAvailableWorkflows = useCallback((amount) => { @@ -533,7 +537,7 @@ useEffect(() => { - Version: 2.0.0-rc + Version: 2.0.0-rc2 @@ -591,6 +595,10 @@ useEffect(() => { org_id: orgId, }; + if (userdata?.active_org?.id === orgId) { + return + } + localStorage.setItem("globalUrl", ""); localStorage.setItem("getting_started_sidebar", "open"); @@ -765,11 +773,18 @@ useEffect(() => { "UK": "gb" }; - region = regionMapping[region_url] || "gb"; + region = regionMapping[region_url] || "eu"; return `https://flagcdn.com/48x36/${region}.png`; }; + useEffect(() => { + if (window?.location?.pathname?.includes("/workflows/")) { + setExpandLeftNav(false); + } + + }, [window?.location?.pathname]); + return (
{ zoom: 0.8, 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} { }} style={{ ...ButtonStyle, - backgroundColor: - currentOpenTab === "security" - ? "#2f2f2f" - : "transparent", }} onMouseOver={(event)=>{ event.currentTarget.style.backgroundColor = "#2f2f2f"; @@ -1443,6 +1466,8 @@ useEffect(() => { + + {recentworkflows?.length > 0 ? { }) } + : null } + { - const { - globalUrl, - fieldCount, - actionlist, - changeActionParameterCodeMirror, - expansionModalOpen, - setExpansionModalOpen, - codedata, - setcodedata, - isFileEditor, - runUpdateText, - toolsAppId, - parameterName, - selectedAction , + const { + globalUrl, + fieldCount, + actionlist, + changeActionParameterCodeMirror, + expansionModalOpen, + setExpansionModalOpen, + codedata, + setcodedata, + isFileEditor, + runUpdateText, + toolsAppId, + parameterName, + selectedAction, workflowExecutions, getParents, activeDialog, setActiveDialog, fieldname, contentLoading, - editorData, - + editorData, + setAiQueryModalOpen, fullScreenMode } = props @@ -120,12 +120,12 @@ const CodeEditor = (props) => { const [localcodedata, setlocalcodedata] = React.useState(codedata === undefined || codedata === null || codedata.length === 0 ? "" : codedata); //const { setContainer } = useCodeMirror({ - // container: editorRef.current, - // extensions, - // value: localcodedata, + // container: editorRef.current, + // extensions, + // value: localcodedata, //}) - // const {codelang, setcodelang} = props - + // const {codelang, setcodelang} = props + const [validation, setValidation] = React.useState(false); const [expOutput, setExpOutput] = React.useState(" "); const [linewrap, setlinewrap] = React.useState(true); @@ -146,15 +146,15 @@ const CodeEditor = (props) => { const [codeTheme, setcodeTheme] = React.useState("gruvbox-dark"); - const [menuPosition, setMenuPosition] = useState(null); - const [showAutocomplete, setShowAutocomplete] = React.useState(false); - const [markers, setMarkers] = useState([]); + const [menuPosition, setMenuPosition] = useState(null); + const [showAutocomplete, setShowAutocomplete] = React.useState(false); + const [markers, setMarkers] = useState([]); const [isAiLoading, setIsAiLoading] = React.useState(false); - // let markers = []; + // let markers = []; const baseResult = "" const [executionResult, setExecutionResult] = useState({ - "valid": false, + "valid": false, "result": baseResult, }) const [executing, setExecuting] = useState(false) @@ -184,9 +184,9 @@ const CodeEditor = (props) => { return } - for(var i=0; i < actionlist.length; i++){ - allVariables.push('$'+actionlist[i].autocomplete.toLowerCase()) - tmpVariables.push('$'+actionlist[i].autocomplete.toLowerCase()) + for (var i = 0; i < actionlist.length; i++) { + allVariables.push('$' + actionlist[i].autocomplete.toLowerCase()) + tmpVariables.push('$' + actionlist[i].autocomplete.toLowerCase()) var parsedPaths = [] if (typeof actionlist[i].example === "object") { @@ -194,7 +194,7 @@ const CodeEditor = (props) => { } 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)) { allVariables.push(fullpath) allVariables.push(fullpath.toLowerCase()) @@ -211,73 +211,73 @@ const CodeEditor = (props) => { expectedOutput(localcodedata) }, [availableVariables]) - var to_be_copied = ""; + var to_be_copied = ""; const HandleJsonCopy = (base, copy, base_node_name) => { - if (typeof copy.name === "string") { - copy.name = copy.name.replaceAll(" ", "_"); - } + if (typeof copy.name === "string") { + copy.name = copy.name.replaceAll(" ", "_"); + } - //lol - if (typeof base === 'object' || typeof base === 'dict') { - base = JSON.stringify(base) - } + //lol + if (typeof base === 'object' || typeof base === 'dict') { + base = JSON.stringify(base) + } - if (base_node_name === "execution_argument" || base_node_name === "Execution Argument") { - base_node_name = "exec" - } + if (base_node_name === "execution_argument" || base_node_name === "Execution Argument") { + base_node_name = "exec" + } - console.log("COPY: ", base_node_name, copy); + console.log("COPY: ", base_node_name, copy); - //var newitem = JSON.parse(base); - var newitem = validateJson(base).result - to_be_copied = "$" + base_node_name.toLowerCase().replaceAll(" ", "_"); - for (let copykey in copy.namespace) { - if (copy.namespace[copykey].includes("Results for")) { - continue; - } + //var newitem = JSON.parse(base); + var newitem = validateJson(base).result + to_be_copied = "$" + base_node_name.toLowerCase().replaceAll(" ", "_"); + for (let copykey in copy.namespace) { + if (copy.namespace[copykey].includes("Results for")) { + continue; + } - if (newitem !== undefined && newitem !== null) { - newitem = newitem[copy.namespace[copykey]]; - if (!isNaN(copy.namespace[copykey])) { - to_be_copied += ".#"; - } else { - to_be_copied += "." + copy.namespace[copykey]; - } - } - } + if (newitem !== undefined && newitem !== null) { + newitem = newitem[copy.namespace[copykey]]; + if (!isNaN(copy.namespace[copykey])) { + to_be_copied += ".#"; + } else { + to_be_copied += "." + copy.namespace[copykey]; + } + } + } - if (newitem !== undefined && newitem !== null) { - newitem = newitem[copy.name]; - if (!isNaN(copy.name)) { - to_be_copied += ".#"; - } else { - to_be_copied += "." + copy.name; - } - } + if (newitem !== undefined && newitem !== null) { + newitem = newitem[copy.name]; + if (!isNaN(copy.name)) { + to_be_copied += ".#"; + } else { + to_be_copied += "." + copy.name; + } + } - to_be_copied.replaceAll(" ", "_"); - const elementName = "copy_element_shuffle"; - var copyText = document.getElementById(elementName); - if (copyText !== null && copyText !== undefined) { - console.log("NAVIGATOR: ", navigator); - const clipboard = navigator.clipboard; - if (clipboard === undefined) { - toast("Can only copy over HTTPS (port 3443)"); - return; - } + to_be_copied.replaceAll(" ", "_"); + const elementName = "copy_element_shuffle"; + var copyText = document.getElementById(elementName); + if (copyText !== null && copyText !== undefined) { + console.log("NAVIGATOR: ", navigator); + const clipboard = navigator.clipboard; + if (clipboard === undefined) { + toast("Can only copy over HTTPS (port 3443)"); + return; + } - navigator.clipboard.writeText(to_be_copied); - copyText.select(); - copyText.setSelectionRange(0, 99999); /* For mobile devices */ + navigator.clipboard.writeText(to_be_copied); + copyText.select(); + copyText.setSelectionRange(0, 99999); /* For mobile devices */ - /* Copy the text inside the text field */ - document.execCommand("copy"); - console.log("COPYING!"); - toast("Copied JSON path to clipboard.") - } else { - console.log("Couldn't find element ", elementName); - } - } + /* Copy the text inside the text field */ + document.execCommand("copy"); + console.log("COPYING!"); + toast("Copied JSON path to clipboard.") + } else { + console.log("Couldn't find element ", elementName); + } + } const aiSubmit = (value, inputAction) => { if (value === undefined || value === "") { @@ -295,7 +295,7 @@ const CodeEditor = (props) => { console.log("Parents: ", parents) var actionlist = [] if (parents.length > 1) { - for (let [key,keyval] in Object.entries(parents)) { + for (let [key, keyval] in Object.entries(parents)) { const item = parents[key]; if (item.label === "Execution Argument") { continue; @@ -307,7 +307,7 @@ const CodeEditor = (props) => { if (workflowExecutions.length > 0) { // Look for the ID 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) { continue; } @@ -357,8 +357,8 @@ const CodeEditor = (props) => { var fixedResults = [] for (var i = 0; i < actionlist.length; i++) { const item = actionlist[i]; - const responseFix = SetJsonDotnotation(item.example, "") - + const responseFix = SetJsonDotnotation(item.example, "") + // Check if json const validated = validateJson(responseFix) var exampledata = responseFix; @@ -400,50 +400,50 @@ const CodeEditor = (props) => { body: JSON.stringify(conversationData), credentials: "include", }) - .then((response) => { - if (response.status !== 200) { - console.log("Status not 200 for stream results :O!"); - } - - return response.json(); - }) - .then((responseJson) => { - console.log("Conversation response: ", responseJson) - setIsAiLoading(false) - if (responseJson.success === false) { - if (responseJson.reason !== undefined) { + .then((response) => { + if (response.status !== 200) { + console.log("Status not 200 for stream results :O!"); } - return - } + return response.json(); + }) + .then((responseJson) => { + console.log("Conversation response: ", responseJson) + setIsAiLoading(false) + if (responseJson.success === false) { + if (responseJson.reason !== undefined) { + } - if (inputAction !== undefined) { - console.log("In input action! Should check params if they match, and add suggestions") - - if (responseJson.parameters === undefined || responseJson.parameters.length === 0) { return } - for (let respParam of responseJson.parameters) { - if (respParam.name !== parameterName) { - continue + if (inputAction !== undefined) { + console.log("In input action! Should check params if they match, and add suggestions") + + if (responseJson.parameters === undefined || responseJson.parameters.length === 0) { + return } - if (respParam.value === "") { + for (let respParam of responseJson.parameters) { + if (respParam.name !== parameterName) { + continue + } + + if (respParam.value === "") { + break + } + + setlocalcodedata(respParam.value) break } - setlocalcodedata(respParam.value) - break + return } - - return - } - }) - .catch((error) => { - setIsAiLoading(false) - console.log("Conv response error: ", error); - }); + }) + .catch((error) => { + setIsAiLoading(false) + console.log("Conv response error: ", error); + }); } const autoFormat = (input) => { @@ -491,7 +491,7 @@ const CodeEditor = (props) => { const findIndex = (line, loc) => { var code_line = localcodedata.split('\n')[line] if (code_line === undefined) { - return + return } var dollar_occurences = [] @@ -499,21 +499,21 @@ const CodeEditor = (props) => { var variable_ranges = [] var popup = false - for(var ch=0; ch < code_line.length; ch++){ - if(code_line[ch] === '$'){ + for (var ch = 0; ch < code_line.length; ch++) { + if (code_line[ch] === '$') { dollar_occurences.push(ch) } } var variable_occurences = code_line.match(/[$]{1}([a-zA-Z0-9_-]+\.?){1}([a-zA-Z0-9#_-]+\.?){0,}/g) - try{ - for(var occ = 0; occ < variable_occurences.length; occ++){ + try { + for (var occ = 0; occ < variable_occurences.length; occ++) { 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 = [] // for(var occ_len = 0; occ_len { // temp_arr.push(temp_arr[temp_arr.length-1]+1) // variable_ranges.push(temp_arr) var temp_arr = [dollar_occurences[occ]] - for(var occ_len = 0; occ_len < dollar_occurences_len[occ]; occ_len++){ - temp_arr.push(dollar_occurences[occ]+occ_len+1) + for (var occ_len = 0; occ_len < dollar_occurences_len[occ]; occ_len++) { + temp_arr.push(dollar_occurences[occ] + occ_len + 1) } - if(temp_arr.length==1) { - temp_arr.push(temp_arr[temp_arr.length-1]+1) + if (temp_arr.length == 1) { + temp_arr.push(temp_arr[temp_arr.length - 1] + 1) } variable_ranges.push(temp_arr) } - for(var occ = 0; occ { // Makes sure #0 and # are same, as we only visualize first one anyway if (tmpitem.startsWith("#")) { - removedIndexes += tmpitem.length-1 + removedIndexes += tmpitem.length - 1 tmpitem = "#" } @@ -585,26 +585,26 @@ const CodeEditor = (props) => { const highlight_variables = (value) => { if (value === undefined || value === null || value.length === 0) { - setMarkers([]) + setMarkers([]) return } // var session = localcodedata.getSession(); //var code_lines = localcodedata.split('\n') - var newMarkers = [] + var newMarkers = [] var code_lines = value.split('\n') for (var i = 0; i < code_lines.length; i++) { var current_code_line = code_lines[i] var variable_occurence = current_code_line.match(/[\\]{0,1}[$]{1}([a-zA-Z0-9_@-]+\.?){1}([a-zA-Z0-9#_@-]+\.?){0,}/g); - + if (!variable_occurence) { continue; } - + var new_occurences = variable_occurence.filter((occurrence) => occurrence[0]); variable_occurence = new_occurences - + var dollar_occurence = []; for (let ch = 0; ch < current_code_line.length; ch++) { //if (current_code_line[ch] === '$' && (ch === 0)) { @@ -614,8 +614,8 @@ const CodeEditor = (props) => { } var dollar_occurence_len = [] - try{ - for(let occ = 0; occ < variable_occurence.length; occ++){ + try { + for (let occ = 0; occ < variable_occurence.length; occ++) { dollar_occurence_len.push(variable_occurence[occ].length) } } catch (e) { @@ -628,12 +628,12 @@ const CodeEditor = (props) => { //value.markText({line:i, ch:0}, {line:i, ch:code_lines[i].length-1}, {"css": "background-color: #; border-radius: 0px; color: inherit"}) } - for (let occ = 0; occ < variable_occurence.length; occ++) { - const fixedVariable = fixVariable(variable_occurence[occ]) - var correctVariable = availableVariables.includes(fixedVariable.toLowerCase()) + for (let occ = 0; occ < variable_occurence.length; occ++) { + const fixedVariable = fixVariable(variable_occurence[occ]) + var correctVariable = availableVariables.includes(fixedVariable) - var startCh = dollar_occurence[occ] - var endCh = dollar_occurence[occ] + dollar_occurence_len[occ] + var startCh = dollar_occurence[occ] + var endCh = dollar_occurence[occ] + dollar_occurence_len[occ] try { newMarkers.push({ startRow: i, @@ -654,16 +654,16 @@ const CodeEditor = (props) => { type: "text", }) } - + setMarkers(newMarkers) - } + } } catch (e) { console.log("Error in color highlighting: ", e); } } - + setMarkers(newMarkers) } @@ -679,10 +679,10 @@ const CodeEditor = (props) => { var parsedVariable = currentVariable if (currentVariable === undefined || currentVariable === null) { 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) var updatedCode = code_lines.join('\n') // console.log(updatedCode) @@ -713,7 +713,7 @@ const CodeEditor = (props) => { // Whelp this is inefficient af. Single loop pls // When the found array is empty. if (found !== null && found !== undefined) { - try { + try { for (var i = 0; i < found.length; i++) { try { // Finding if the value is in the list at all, and does initial replacement @@ -721,11 +721,11 @@ const CodeEditor = (props) => { var valuefound = false 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 } - valuefound = true + valuefound = true try { if (typeof actionlist[j].example === "object") { @@ -737,25 +737,25 @@ const CodeEditor = (props) => { const newExample = fixStringInput(actionlist[j].example) input = input.replace(found[i], newExample, -1) } - } catch (e) { + } catch (e) { input = input.replace(found[i], actionlist[j].example, -1) } } - + if (!valuefound) { } - if (!valuefound && availableVariables.includes(fixedVariable.toLowerCase())) { + if (!valuefound && availableVariables.includes(fixedVariable)) { var shouldbreak = false - for (var k=0; k < actionlist.length; k++){ + for (var k = 0; k < actionlist.length; k++) { var parsedPaths = [] if (typeof actionlist[k].example === "object") { parsedPaths = GetParsedPaths(actionlist[k].example, ""); } 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()) { continue } @@ -776,7 +776,7 @@ const CodeEditor = (props) => { } else { if (typeof new_input === "string") { // Check if it contains any newlines, and replace them with raw newlines - new_input = fixStringInput(new_input) + new_input = fixStringInput(new_input) // Replace quotes with nothing } else { @@ -792,7 +792,7 @@ const CodeEditor = (props) => { input = input.replace(fixedVariable, new_input, -1) input = input.replace(found[i], new_input, -1) - shouldbreak = true + shouldbreak = true break } @@ -821,7 +821,7 @@ const CodeEditor = (props) => { } } - const handleItemClick = (values) => { + const handleItemClick = (values) => { if (values === undefined || values === null || values.length === 0) { return; } @@ -871,15 +871,15 @@ const CodeEditor = (props) => { setlocalcodedata(codedatasplit.join('\n')) - edited = true + edited = true } } if (edited === false) { if (!item.value.includes("{%") && !item.value.includes("{{")) { - setlocalcodedata(localcodedata+" | "+item.value+" }}") + setlocalcodedata(localcodedata + " | " + item.value + " }}") } else { - setlocalcodedata(localcodedata+item.value) + setlocalcodedata(localcodedata + item.value) } } @@ -897,12 +897,12 @@ const CodeEditor = (props) => { 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 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({ - "valid": false, + "valid": false, "result": baseResult, "errors": [], }) @@ -918,134 +918,134 @@ const CodeEditor = (props) => { body: JSON.stringify(actiondata), credentials: "include", }) - .then((response) => { - if (response.status !== 200) { - console.log("Status not 200 for stream results :O!") - } + .then((response) => { + if (response.status !== 200) { + console.log("Status not 200 for stream results :O!") + } - return response.json() - }) - .then((responseJson) => { - //console.log("RESPONSE: ", responseJson) - var newResult = {} - if (responseJson.success === true && responseJson.result !== null && responseJson.result !== undefined && responseJson.result.length > 0) { - const result = responseJson.result.slice(0, 50)+"..." - //toast("SUCCESS: "+result) + return response.json() + }) + .then((responseJson) => { + //console.log("RESPONSE: ", responseJson) + var newResult = {} + if (responseJson.success === true && responseJson.result !== null && responseJson.result !== undefined && responseJson.result.length > 0) { + const result = responseJson.result.slice(0, 50) + "..." + //toast("SUCCESS: "+result) - const validate = validateJson(responseJson.result) - newResult = validate - } else if (responseJson.success === false && responseJson.reason !== undefined && responseJson.reason !== null) { - toast(responseJson.reason) - newResult = {"valid": false, "result": responseJson.reason} - } else if (responseJson.success === true) { - newResult = {"valid": false, "result": "Couldn't finish execution. Please fill all the required fields, and retry the execution."} - } else { - newResult = {"valid": false, "result": "Couldn't finish execution (2). Please fill all the required fields, and validate the execution."} - } + const validate = validateJson(responseJson.result) + newResult = validate + } else if (responseJson.success === false && responseJson.reason !== undefined && responseJson.reason !== null) { + toast(responseJson.reason) + newResult = { "valid": false, "result": responseJson.reason } + } else if (responseJson.success === true) { + newResult = { "valid": false, "result": "Couldn't finish execution. Please fill all the required fields, and retry the execution." } + } else { + 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) { - newResult.errors = responseJson.errors - } + if (responseJson.errors !== undefined && responseJson.errors !== null && responseJson.errors.length > 0) { + newResult.errors = responseJson.errors + } - setExecutionResult(newResult) - setExecuting(false) - }) - .catch(error => { - //toast("Execution error: "+error.toString()) - console.log("error: ", error) - setExecuting(false) - }) + setExecutionResult(newResult) + setExecuting(false) + }) + .catch(error => { + //toast("Execution error: "+error.toString()) + console.log("error: ", error) + setExecuting(false) + }) } - const adjustPosition = (menuPosition) => { - const { top, left, width, height } = menuPosition; - const windowWidth = window.innerWidth; - const windowHeight = window.innerHeight; + const adjustPosition = (menuPosition) => { + const { top, left, width, height } = menuPosition; + const windowWidth = window.innerWidth; + const windowHeight = window.innerHeight; - let adjustedTop = top; - let adjustedLeft = left; + let adjustedTop = top; + let adjustedLeft = left; - // Adjust top position if menu overflows the bottom of the window - if (top + height > windowHeight) { - adjustedTop = windowHeight - height; - } + // Adjust top position if menu overflows the bottom of the window + if (top + height > windowHeight) { + adjustedTop = windowHeight - height; + } - // Adjust left position if menu overflows the right side of the window - if (left + width > windowWidth) { - adjustedLeft = windowWidth - width; - } + // Adjust left position if menu overflows the right side of the window + if (left + width > windowWidth) { + adjustedLeft = windowWidth - width; + } - return { - "top": adjustedTop, - "left": adjustedLeft - } - }; + return { + "top": adjustedTop, + "left": adjustedLeft + } + }; - // Define a custom completer for the Ace Editor - const customCompleter = { - getCompletions: function(editor, session, pos, prefix, callback) { - console.log("CUSTOM COMPLETER: ", prefix) + // Define a custom completer for the Ace Editor + const customCompleter = { + getCompletions: function(editor, session, pos, prefix, callback) { + console.log("CUSTOM COMPLETER: ", prefix) - callback(null, availableVariables.map((variable) => { - console.log("CUSTOM VAR: ", variable) + callback(null, availableVariables.map((variable) => { + console.log("CUSTOM VAR: ", variable) - return ({ - caption: variable, - value: variable, - meta: 'custom', - }) - })) - } - } + return ({ + caption: variable, + value: variable, + meta: 'custom', + }) + })) + } + } if (fullScreenMode) { return ( { - // setlocalcodedata(value) - // expectedOutput(value) - // highlight_variables(value,editor) - setlocalcodedata(value) - setcodedata(value) - }} - name="python-editor" - fontSize={14} - width="100%" - height="100%" - showPrintMargin={false} - showGutter={true} - markers={markers} - highlightActiveLine={false} - - enableBasicAutocompletion={true} - completers={[customCompleter]} + mode="python" + theme="gruvbox" + value={localcodedata} + onChange={(value, editor) => { + // setlocalcodedata(value) + // expectedOutput(value) + // highlight_variables(value,editor) + setlocalcodedata(value) + setcodedata(value) + }} + name="python-editor" + fontSize={14} + width="100%" + height="100%" + showPrintMargin={false} + showGutter={true} + markers={markers} + highlightActiveLine={false} - style={{ - wordBreak: "break-word", - marginTop: 0, - paddingBottom: 10, - overflowY: "auto", - whiteSpace: "pre-wrap", - wordWrap: "break-word", - backgroundColor: "rgba(40,40,40,1)", - zIndex: activeDialog === "codeeditor" ? 1200 : 1100, - }} + enableBasicAutocompletion={true} + completers={[customCompleter]} - setOptions={{ - enableBasicAutocompletion: true, - enableLiveAutocompletion: true, - enableSnippets: true, - showLineNumbers: true, - tabSize: 4, - fontFamily: "'JetBrains Mono', Consolas, monospace", - useSoftTabs: true - }} - /> + style={{ + wordBreak: "break-word", + marginTop: 0, + paddingBottom: 10, + overflowY: "auto", + whiteSpace: "pre-wrap", + wordWrap: "break-word", + backgroundColor: "rgba(40,40,40,1)", + zIndex: activeDialog === "codeeditor" ? 1200 : 1100, + }} + + setOptions={{ + enableBasicAutocompletion: true, + enableLiveAutocompletion: true, + enableSnippets: true, + showLineNumbers: true, + tabSize: 4, + fontFamily: "'JetBrains Mono', Consolas, monospace", + useSoftTabs: true + }} + /> ) } @@ -1054,14 +1054,14 @@ const CodeEditor = (props) => { aria-labelledby="draggable-dialog-title" // disableBackdropClick={true} disableEnforceFocus={true} - style={{ pointerEvents: "none", zIndex: activeDialog === "codeeditor" ? 1200 : 1100}} + style={{ pointerEvents: "none", zIndex: activeDialog === "codeeditor" ? 1200 : 1100 }} hideBackdrop={true} open={expansionModalOpen} onClose={() => { console.log("In closer") if (changeActionParameterCodeMirror !== undefined) { - changeActionParameterCodeMirror({target: {value: ""}}, fieldCount, localcodedata) + changeActionParameterCodeMirror({ target: { value: "" } }, fieldCount, localcodedata) } else { console.log("No action called changeActionParameterCodeMirror in code editor") } @@ -1084,91 +1084,91 @@ const CodeEditor = (props) => { maxHeight: isMobile ? "100%" : 700, border: theme.palette.defaultBorder, padding: isMobile ? "25px 10px 25px 10px" : 25, - zoom: 0.8, - backgroundColor: "black", + // zoom: 0.8, + backgroundColor: "black", }, }} > - {contentLoading === true ? - + + + : null} + + - - - : null} + title={`Move window`} + placement="left" + > + - { - }} - > - - + cursor: "move", + }} + onClick={() => { + }} + > + + - - { - setExpansionModalOpen(false) - }} - > - - + + { + setExpansionModalOpen(false) + }} + > + + -
-
- { isFileEditor ? +
+
+ {isFileEditor ?
-
- - File Editor ({localcodedata.length}) - + style={{ + display: 'flex', + }} + > +
+ + File Editor ({localcodedata.length}) + +
-
- : -
-
- {/* + : +
+
+ {/* { Code Editor */} - { isFileEditor ? null : -
- {selectedAction?.name === "execute_python" ? - - Run Python Code - - : - selectedAction.name === "execute_bash" ? - - Run Bash Code - - : -
- - { - setAnchorEl(null); - }} - MenuListProps={{ - 'aria-labelledby': 'basic-button', - }} - > - {liquidFilters.map((item, index) => { - return ( - { - handleClick(item) - }}>{item.name} - ) - })} - - - { - setAnchorEl2(null); - }} - MenuListProps={{ - 'aria-labelledby': 'basic-button', - }} - > - {mathFilters.map((item, index) => { - return ( - { - handleClick(item) - }}>{item.name} - ) - })} - - - { - setAnchorEl3(null); - }} - MenuListProps={{ - 'aria-labelledby': 'basic-button', - }} - > - {pythonFilters.map((item, index) => { - return ( - { - handleClick(item) - }}>{item.name} - ) - })} - -
- } - - - { - handleMenuClose(); - }} - open={!!menuPosition} - style={{ - color: "white", - marginTop: 2, - maxHeight: 650, - }} - > - {actionlist?.map((innerdata) => { - const icon = - innerdata.type === "action" ? ( - - ) : innerdata.type === "workflow_variable" || - innerdata.type === "execution_variable" ? ( - - ) : ( - - ); - - const handleExecArgumentHover = (inside) => { - var exec_text_field = document.getElementById( - "execution_argument_input_field" - ); - if (exec_text_field !== null) { - if (inside) { - exec_text_field.style.border = "2px solid #f85a3e"; - } else { - exec_text_field.style.border = ""; - } - } - }; - - const handleActionHover = (inside, actionId) => { - }; - - const handleMouseover = () => { - if (innerdata.type === "Execution Argument") { - handleExecArgumentHover(true); - } else if (innerdata.type === "action") { - handleActionHover(true, innerdata.id); - } - }; - - const handleMouseOut = () => { - if (innerdata.type === "Execution Argument") { - handleExecArgumentHover(false); - } else if (innerdata.type === "action") { - handleActionHover(false, innerdata.id); - } - }; - - var parsedPaths = []; - if (typeof innerdata.example === "object") { - parsedPaths = GetParsedPaths(innerdata.example, ""); - } - - const coverColor = "#82ccc3" - //menuPosition.left -= 50 - //menuPosition.top -= 250 - //console.log("POS: ", menuPosition1) - var menuPosition1 = menuPosition - if (menuPosition1 === null) { - menuPosition1 = { - "left": 0, - "top": 0, - } - } else if (menuPosition1.top === null || menuPosition1.top === undefined) { - menuPosition1.top = 0 - } else if (menuPosition1.left === null || menuPosition1.left === undefined) { - menuPosition1.left = 0 - } - - //console.log("POS1: ", menuPosition1) - - return parsedPaths.length > 0 ? ( - - {icon} {innerdata.name} -
- } - parentMenuOpen={!!menuPosition} - style={{ - color: "white", - minWidth: 250, - maxWidth: 250, - maxHeight: 50, - overflow: "hidden", - }} - onClick={() => { - console.log("CLICKED: ", innerdata); - console.log(innerdata.example) - - //const handleClick = (item) => { - handleItemClick([innerdata]); - }} - > - - { - //console.log("HOVER: ", pathdata); - }} - onClick={() => { - handleItemClick([innerdata]); - }} - > - - {innerdata.name} + {isFileEditor ? null : +
+ {selectedAction?.name === "execute_python" ? + + Run Python Code + + : + selectedAction.name === "execute_bash" ? + + Run Bash Code - - {parsedPaths.map((pathdata, index) => { - // FIXME: Should be recursive in here - // - const icon = - pathdata.type === "value" ? ( - - ) : pathdata.type === "list" ? ( - - ) : ( - - ); - // + : +
+ + { + setAnchorEl(null); + }} + MenuListProps={{ + 'aria-labelledby': 'basic-button', + }} + > + {liquidFilters.map((item, index) => { + return ( + { + handleClick(item) + }}>{item.name} + ) + })} + + + { + setAnchorEl2(null); + }} + MenuListProps={{ + 'aria-labelledby': 'basic-button', + }} + > + {mathFilters.map((item, index) => { + return ( + { + handleClick(item) + }}>{item.name} + ) + })} + + + { + setAnchorEl3(null); + }} + MenuListProps={{ + 'aria-labelledby': 'basic-button', + }} + > + {pythonFilters.map((item, index) => { + return ( + { + handleClick(item) + }}>{item.name} + ) + })} + +
+ } - const indentation_count = (pathdata.name.match(/\./g) || []).length+1 - //const boxPadding = pathdata.type === "object" ? "10px 0px 0px 0px" : 0 - const boxPadding = 0 - const namesplit = pathdata.name.split(".") - const newname = namesplit[namesplit.length-1] - return ( - { + setMenuPosition({ + top: event.pageY, + left: event.pageX, + }) + }} + > + Autocomplete + + { + handleMenuClose(); + }} + open={!!menuPosition} + style={{ + color: "white", + marginTop: 2, + maxHeight: 650, + }} + > + {actionlist?.map((innerdata) => { + const icon = + innerdata.type === "action" ? ( + + ) : innerdata.type === "workflow_variable" || + innerdata.type === "execution_variable" ? ( + + ) : ( + + ); + + const handleExecArgumentHover = (inside) => { + var exec_text_field = document.getElementById( + "execution_argument_input_field" + ); + if (exec_text_field !== null) { + if (inside) { + exec_text_field.style.border = "2px solid #f85a3e"; + } else { + exec_text_field.style.border = ""; + } + } + }; + + const handleActionHover = (inside, actionId) => { + }; + + const handleMouseover = () => { + if (innerdata.type === "Execution Argument") { + handleExecArgumentHover(true); + } else if (innerdata.type === "action") { + handleActionHover(true, innerdata.id); + } + }; + + const handleMouseOut = () => { + if (innerdata.type === "Execution Argument") { + handleExecArgumentHover(false); + } else if (innerdata.type === "action") { + handleActionHover(false, innerdata.id); + } + }; + + var parsedPaths = []; + if (typeof innerdata.example === "object") { + parsedPaths = GetParsedPaths(innerdata.example, ""); + } + + const coverColor = "#82ccc3" + //menuPosition.left -= 50 + //menuPosition.top -= 250 + //console.log("POS: ", menuPosition1) + var menuPosition1 = menuPosition + if (menuPosition1 === null) { + menuPosition1 = { + "left": 0, + "top": 0, + } + } else if (menuPosition1.top === null || menuPosition1.top === undefined) { + menuPosition1.top = 0 + } else if (menuPosition1.left === null || menuPosition1.left === undefined) { + menuPosition1.left = 0 + } + + //console.log("POS1: ", menuPosition1) + + return parsedPaths.length > 0 ? ( + + {icon} {innerdata.name} +
+ } + parentMenuOpen={!!menuPosition} style={{ color: "white", minWidth: 250, maxWidth: 250, - padding: boxPadding, - }} - value={pathdata} - onMouseOver={() => { - //console.log("HOVER: ", pathdata); + maxHeight: 50, + overflow: "hidden", }} onClick={() => { - handleItemClick([innerdata, pathdata]); + console.log("CLICKED: ", innerdata); + console.log(innerdata.example) + + //const handleClick = (item) => { + handleItemClick([innerdata]); + }} + > + + { + //console.log("HOVER: ", pathdata); + }} + onClick={() => { + handleItemClick([innerdata]); + }} + > + + {innerdata.name} + + + {parsedPaths.map((pathdata, index) => { + // FIXME: Should be recursive in here + // + const icon = + pathdata.type === "value" ? ( + + ) : pathdata.type === "list" ? ( + + ) : ( + + ); + // + + const indentation_count = (pathdata.name.match(/\./g) || []).length + 1 + //const boxPadding = pathdata.type === "object" ? "10px 0px 0px 0px" : 0 + const boxPadding = 0 + const namesplit = pathdata.name.split(".") + const newname = namesplit[namesplit.length - 1] + return ( + { + //console.log("HOVER: ", pathdata); + }} + onClick={() => { + handleItemClick([innerdata, pathdata]); + }} + > + +
+ {Array(indentation_count).fill().map((subdata, subindex) => { + return ( +
+ ) + })} + {icon} {newname} + {pathdata.type === "list" ? { + e.preventDefault() + e.stopPropagation() + + console.log("INNER: ", innerdata, pathdata) + + // Removing .list from autocomplete + var newname = pathdata.name + if (newname.length > 5) { + newname = newname.slice(0, newname.length - 5) + } + + //selectedActionParameters[count].value += `{{ $${innerdata.name}.${newname} | size }}` + //selectedAction.parameters[count].value = selectedActionParameters[count].value; + //setSelectedAction(selectedAction); + //setShowDropdown(false); + setMenuPosition(null); + + // innerdata.name + // pathdata.name + //handleItemClick([innerdata, newpathdata]) + //console.log("CLICK LENGTH!") + }} /> : null} +
+ + + ); + })} + + + ) : ( + handleMouseover()} + onMouseOut={() => { + handleMouseOut(); + }} + onClick={() => { + handleItemClick([innerdata]); }} > -
- {Array(indentation_count).fill().map((subdata, subindex) => { - return ( -
- ) - })} - {icon} {newname} - {pathdata.type === "list" ? { - e.preventDefault() - e.stopPropagation() - - console.log("INNER: ", innerdata, pathdata) - - // Removing .list from autocomplete - var newname = pathdata.name - if (newname.length > 5) { - newname = newname.slice(0, newname.length-5) - } - - //selectedActionParameters[count].value += `{{ $${innerdata.name}.${newname} | size }}` - //selectedAction.parameters[count].value = selectedActionParameters[count].value; - //setSelectedAction(selectedAction); - //setShowDropdown(false); - setMenuPosition(null); - - // innerdata.name - // pathdata.name - //handleItemClick([innerdata, newpathdata]) - //console.log("CLICK LENGTH!") - }} /> : null} +
+ {icon} {innerdata.name}
); })} - - - ) : ( - handleMouseover()} - onMouseOut={() => { - handleMouseOut(); - }} - onClick={() => { - handleItemClick([innerdata]); - }} + +
+ } + + { + setlocalcodedata(editorData.example) + }} + color="secondary" + > + - -
- {icon} {innerdata.name} -
-
- - ); - })} - -
+ +
+ + { + if (setAiQueryModalOpen !== undefined) { + setAiQueryModalOpen(true) + } else { + autoFormat(localcodedata) + } + }} + > + + {isAiLoading ? + + : + + } + + +
+
} - + {(availableVariables !== undefined && availableVariables !== null && availableVariables.length > 0) || isFileEditor ? ( + { + highlight_variables(localcodedata) + }} + onCursorChange={(cursorPosition, editor, value) => { + setCurrentCharacter(cursorPosition.cursor.column) + setCurrentLine(cursorPosition.cursor.row) + findIndex(cursorPosition.row, cursorPosition.column) + + }} + onChange={(value, editor) => { + // setlocalcodedata(value) + // expectedOutput(value) + // highlight_variables(value,editor) + setlocalcodedata(value) + expectedOutput(value) + highlight_variables(value) + }} + setOptions={{ + enableBasicAutocompletion: true, + enableLiveAutocompletion: true, + enableSnippets: true, + showLineNumbers: true, + tabSize: 2, + wrap: true, + + useWorker: false, + enableBasicAutocompletion: [customCompleter], + }} + // options={options} + /> + ) : null} +
+ +
{ - setlocalcodedata(editorData.example) - }} - color="secondary" - > - - - - - { - if (setAiQueryModalOpen !== undefined) { - setAiQueryModalOpen(true) - } else { - autoFormat(localcodedata) - } }} > - - {isAiLoading ? - - : - - } - - +
-
- } - -
- {(availableVariables !== undefined && availableVariables !== null && availableVariables.length > 0) || isFileEditor ? ( - { - highlight_variables(localcodedata) - }} - onCursorChange={(cursorPosition, editor, value) => { - setCurrentCharacter(cursorPosition.cursor.column) - setCurrentLine(cursorPosition.cursor.row) - findIndex(cursorPosition.row, cursorPosition.column) - - }} - onChange={(value, editor) => { - // setlocalcodedata(value) - // expectedOutput(value) - // highlight_variables(value,editor) - setlocalcodedata(value) - expectedOutput(value) - highlight_variables(value) - }} - setOptions={{ - enableBasicAutocompletion: true, - enableLiveAutocompletion: true, - enableSnippets: true, - showLineNumbers: true, - tabSize: 2, - wrap: true, - - useWorker: false, - enableBasicAutocompletion: [customCompleter], - }} - // options={options} - /> - ): null} -
- -
-
-
- - {isFileEditor ? null : -
+ {isFileEditor ? null : +
- {isMobile ? null : + {isMobile ? null :
- + {selectedAction === undefined ? "" : selectedAction.name === "execute_python" || selectedAction.name === "execute_bash" ? "Code to run" : `Expected Output for '${selectedAction.name}'`} @@ -1722,46 +1722,46 @@ const CodeEditor = (props) => { } -
+
- - {isMobile ? null : - validation === true ? + {isMobile ? null : + validation === true ? { }} name={"JSON autocompletion"} /> - : + :

{ border: `2px solid ${theme.palette.inputColor}`, borderRadius: theme.palette?.borderRadius, maxHeight: 450, - minHeight: 450, - overflow: "auto", - wordWrap: "anywhere", + minHeight: 450, + overflow: "auto", + wordWrap: "anywhere", zIndex: activeDialog === "codeeditor" ? 1200 : 1100, }} > @@ -1803,16 +1803,16 @@ const CodeEditor = (props) => { }

- {executionResult.valid === true ? + {executionResult.valid === true ? { }} name={"Test result"} /> - : - - {executionResult.result.length > 0 ? - - - Test output - - - {executionResult.result} - - - : + : + + {executionResult.result.length > 0 ? + + + Test output + + + {executionResult.result} + + + : -
- - Output is based on the last VALID run of the node(s) you are referencing. Only updates when you refresh the Workflow Window. - - - No test output yet. - -
- } +
+ + Output is based on the last VALID run of the node(s) you are referencing. Only updates when you refresh the Workflow Window. + + + No test output yet. + +
+ } - {executionResult.errors !== undefined && executionResult.errors !== null && executionResult.errors.length > 0 ? - - Errors ({executionResult.errors.length}): {executionResult.errors.join("\n")} - - : null} -
+ {executionResult.errors !== undefined && executionResult.errors !== null && executionResult.errors.length > 0 ? + + Errors ({executionResult.errors.length}): {executionResult.errors.join("\n")} + + : null} +
}
- -
+ +
}
-
+
) diff --git a/frontend/src/context/ContextApi.jsx b/frontend/src/context/ContextApi.jsx index c9b02e34..3932dfd0 100644 --- a/frontend/src/context/ContextApi.jsx +++ b/frontend/src/context/ContextApi.jsx @@ -3,11 +3,18 @@ export const Context = createContext(); export const AppContext =(props) => { + const currentLocation = window?.location?.pathname; + // Left side bar global states 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); + useEffect(() => { + if (currentLocation?.includes('/workflows/') && leftSideBarOpenByClick === true) { + setLeftSideBarOpenByClick(false) + } + }, [leftSideBarOpenByClick]) //Calculate window width useEffect(() => { diff --git a/frontend/src/views/Admin2.jsx b/frontend/src/views/Admin2.jsx index f22da85b..2e68cef6 100644 --- a/frontend/src/views/Admin2.jsx +++ b/frontend/src/views/Admin2.jsx @@ -12,18 +12,18 @@ const Admin2 = (props) => { const [orgRequest, setOrgRequest] = React.useState(true); const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io"; const handleGetOrg = (orgId) => { - if ( - serverside !== true && - window.location.search !== undefined && - window.location.search !== null - ) { - const urlSearchParams = new URLSearchParams(window.location.search); - const params = Object.fromEntries(urlSearchParams.entries()); - const foundorgid = params["org_id"]; - if (foundorgid !== undefined && foundorgid !== null) { - orgId = foundorgid; - } - } + // if ( + // serverside !== true && + // window.location.search !== undefined && + // window.location.search !== null + // ) { + // const urlSearchParams = new URLSearchParams(window.location.search); + // const params = Object.fromEntries(urlSearchParams.entries()); + // const foundorgid = params["org_id"]; + // if (foundorgid !== undefined && foundorgid !== null) { + // orgId = foundorgid; + // } + // } console.log("getting organization details for: ", orgId); // if (orgId === undefined) { @@ -154,16 +154,15 @@ const Admin2 = (props) => { }); }; - const urlSearchParams = new URLSearchParams(window.location.search); - const params = Object.fromEntries(urlSearchParams.entries()); - const foundOrgID = params["org_id"] useEffect(() => { - + const urlSearchParams = new URLSearchParams(window.location.search); + const params = Object.fromEntries(urlSearchParams.entries()); + const foundOrgID = params["org_id"] if(foundOrgID !== null && foundOrgID !== undefined && userdata?.support && foundOrgID?.length > 0) { handleClickChangeOrg(foundOrgID) } - }, [foundOrgID]); + }, [userdata]); const handleClickChangeOrg = (orgId) => { // Don't really care about the logout diff --git a/frontend/src/views/AngularWorkflow.jsx b/frontend/src/views/AngularWorkflow.jsx index 7550369c..ae87ef6a 100755 --- a/frontend/src/views/AngularWorkflow.jsx +++ b/frontend/src/views/AngularWorkflow.jsx @@ -399,7 +399,7 @@ const AngularWorkflow = (defaultprops) => { props.match = {} props.match.params = params - const { leftSideBarOpenByClick, windowWidth } = useContext(Context) + const { setLeftSideBarOpenByClick, leftSideBarOpenByClick, windowWidth } = useContext(Context) const [workflowAsCode, setWorkflowAsCode] = useState(false); var to_be_copied = ""; @@ -8662,6 +8662,9 @@ const releaseToConnectLabel = "Release to Connect" getApps() fetchUsecases() + setLeftSideBarOpenByClick(false) + localStorage.setItem("expandLeftNav", false) + const cursearch = typeof window === "undefined" || window.location === undefined ? "" : window.location.search; // FIXME: Don't check specific one here @@ -10568,6 +10571,9 @@ const releaseToConnectLabel = "Release to Connect" const CustomAppHits = connectHits(AppHits) var shuffleToolsApp = apps.find((app) => app.name === "Shuffle Tools") + if (shuffleToolsApp !== undefined && shuffleToolsApp !== null) { + shuffleToolsApp = JSON.parse(JSON.stringify(shuffleToolsApp)) + } var viewedApps = [] return ( @@ -10620,24 +10626,24 @@ const releaseToConnectLabel = "Release to Connect"
- +
- +
- +
- +
- +
- +
- +
- +
: null} @@ -16242,7 +16248,7 @@ const releaseToConnectLabel = "Release to Connect" {!distributedFromParent ? isCorrectOrg ? null : - + Warning: Change { @@ -16313,7 +16319,7 @@ const releaseToConnectLabel = "Release to Connect" >Active Organization to edit this Workflow. : - + Warning: This workflow is controlled by your parent org and may not be editable. } diff --git a/frontend/src/views/ApiExplorerWrapper.jsx b/frontend/src/views/ApiExplorerWrapper.jsx index ca06d5a1..8de63fb9 100644 --- a/frontend/src/views/ApiExplorerWrapper.jsx +++ b/frontend/src/views/ApiExplorerWrapper.jsx @@ -69,6 +69,7 @@ const ApiExplorerWrapper = (props) => { const [authenticationType, setAuthenticationType] = React.useState(""); const [appAuthentication, setAppAuthentication] = useState([]); const [selectedMeta, setSelectedMeta] = useState(undefined); + const [appLoaded, setAppLoaded] = useState(false); const [selectedAction, setSelectedAction] = useState( { "app_name": selectedAppData.name, @@ -258,6 +259,7 @@ const ApiExplorerWrapper = (props) => { parsedapp.body === undefined ? parsedapp : JSON.parse(parsedapp.body); setOpenapi(data); + setAppLoaded(true); }; const handleAppAuthenticationType = (selectedAppData) => { @@ -773,7 +775,7 @@ const ApiExplorerWrapper = (props) => { ); }; - const skeletonLoader = ( + const SkeletonLoader = () => ( { - + { }} > - + - + - + { - + { ); + const AuthenticationData = (props) => { const selectedApp = props.app; @@ -1756,7 +1759,10 @@ const ApiExplorerWrapper = (props) => { return ( - + {appLoaded === false ? ( + + ) : ( + {authenticationModal} { isLoaded={isLoaded} /> + )} ); }; diff --git a/frontend/src/views/AppCreator.jsx b/frontend/src/views/AppCreator.jsx index 143e070f..8e474eed 100755 --- a/frontend/src/views/AppCreator.jsx +++ b/frontend/src/views/AppCreator.jsx @@ -5811,9 +5811,11 @@ const AppCreator = (defaultprops) => { variant="outlined" color="secondary" onClick={() => { - var urlParams = new URLSearchParams(window.location.search); - if (!urlParams.has("id")) { - window.open(`/apis/${app.id}`, "_blank") + var urlParams = new URLSearchParams(window.location.search) + if (urlParams.has("id")) { + 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 { toast.error("Build the app first.") } diff --git a/frontend/src/views/Apps2.jsx b/frontend/src/views/Apps2.jsx index 22c900b3..10b9cd78 100644 --- a/frontend/src/views/Apps2.jsx +++ b/frontend/src/views/Apps2.jsx @@ -1,7 +1,6 @@ import React, { useState, useEffect, useContext, useCallback, memo, useMemo, useRef } from "react"; import theme from "../theme.jsx"; import { isMobile } from "react-device-detect"; -import AppGrid from "../components/AppGrid.jsx"; import { useLocation, useNavigate } from "react-router-dom"; import { TextField, Button, Typography, MenuItem, Select, Tabs, Tab, Zoom, @@ -76,171 +75,190 @@ const AppCard = ({ data, index, mouseHoverIndex, setMouseHoverIndex, globalUrl, onMouseOver={() => setMouseHoverIndex(index)} onMouseOut={() => setMouseHoverIndex(-1)} > - { - handleAppClick(data); + - {data.name} -
-
-
- {data.name.replace(/_/g, ' ').replace(/\b\w/g, char => char.toUpperCase())} -
-
-
- {data.categories ? data.categories.join(", ") : "NA"} -
-
{ + handleAppClick(data); + }} + > + {data.name} +
+
+
+ {data.name.replace(/_/g, ' ').replace(/\b\w/g, char => char.toUpperCase())} +
+
- {data.generated !== true && data.tags && data.tags.slice(0, 2).map((tag, tagIndex) => ( - - {tag} - {tagIndex < data.tags.length - 1 ? ", " : ""} - - ))} + {data.categories ? data.categories.join(", ") : "NA"}
- {/* Deactivate button */} - {currTab === 0 && !deactivatedIndexes.includes(index) && mouseHoverIndex === index && data.generated === true && ( +
- { - canEditApp && ( - - ) - } - + {data.generated !== true && data.tags && data.tags.slice(0, 2).map((tag, tagIndex) => ( + + {tag} + {tagIndex < data.tags.length - 1 ? ", " : ""} + + ))}
- )} + {/* Deactivate button */} + {currTab === 0 && !deactivatedIndexes.includes(index) && mouseHoverIndex === index && data.generated === true && ( +
+ { + canEditApp && ( + + ) + } + +
+ )} +
-
- + + ); @@ -263,10 +281,11 @@ const Hits = ({ const [allActivatedAppIds, setAllActivatedAppIds] = useState([]); const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io"; const [deactivatedIndexes, setDeactivatedIndexes] = React.useState([]); - const [isLoading, setIsLoading] = useState(true) + const [isLoading, setIsLoading] = useState(false) useEffect(() => { var baseurl = globalUrl; + setIsLoading(true) fetch(baseurl + "/api/v1/me", { credentials: "include", headers: { @@ -361,7 +380,34 @@ const Hits = ({ (
{hits?.length === 0 && searchQuery.length >= 0 ? ( - No apps found +
+ + + No apps found matching your search criteria + + + Try adjusting your search terms or filters to find what you're looking for + +
) : (
- { - console.log("App modal", data) - handleAppClick(data); + - {data.name} -
{ + console.log("App modal", data) + handleAppClick(data); }} > -
- {(allActivatedAppIds && allActivatedAppIds.includes(data.objectID)) && } -
- {normalizedString(data.name)} -
-
- -
- {data.categories !== null - ? normalizedString(data.categories).join(", ") - : "NA"} -
+ />
-
- {hoverEffect === index && isCloud ? ( -
- {data.tags && ( - - - {data.tags.slice(0, 1).map((tag, tagIndex) => ( - - {normalizedString(tag)} - {tagIndex < 1 ? ", " : ""} - - ))} - - - )} -
- ) : ( -
- {data.tags && - data.tags.map((tag, tagIndex) => ( - - {normalizedString(tag)} - {tagIndex < data.tags.length - 1 ? ", " : ""} - - ))} -
- )} +
+ {(allActivatedAppIds && allActivatedAppIds.includes(data.objectID)) && } +
+ {normalizedString(data.name)} +
-
- {hoverEffect === index && ( -
- {allActivatedAppIds && allActivatedAppIds.includes(data.objectID) ? ( - - ) : ( - - )} -
- )} + +
+ {data.categories !== null + ? normalizedString(data.categories).join(", ") + : "NA"} +
+
+
+ {hoverEffect === index && isCloud ? ( +
+ {data.tags && ( + + + {data.tags.slice(0, 1).map((tag, tagIndex) => ( + + {normalizedString(tag)} + {tagIndex < 1 ? ", " : ""} + + ))} + + + )} +
+ ) : ( +
+ {data.tags && + data.tags.map((tag, tagIndex) => ( + + {normalizedString(tag)} + {tagIndex < data.tags.length - 1 ? ", " : ""} + + ))} +
+ )} +
+
+ {hoverEffect === index && ( +
+ {allActivatedAppIds && allActivatedAppIds.includes(data.objectID) ? ( + + ) : ( + + )} +
+ )} +
-
- + + ); @@ -872,6 +940,42 @@ const filterApps = (apps, searchQuery, selectedCategory, selectedLabel) => { }); }; +const LoginPrompt = () => { + const navigate = useNavigate(); + return ( +
+ + Log in to see your organization's apps + + +
+ ) +}; + // Add this new component for the app skeleton const AppSkeleton = () => { return ( @@ -1853,34 +1957,34 @@ const Apps2 = (props) => { handleTabChange(event, newTab)} - style={{ - fontFamily: theme?.typography?.fontFamily, + style={{ + fontFamily: theme?.typography?.fontFamily, fontSize: 16, marginBottom: "-2px" }} - TabIndicatorProps={{ style: { display: 'none' } }} + TabIndicatorProps={{ style: { display: 'none' } }} > - - -
@@ -1895,6 +1999,7 @@ const Apps2 = (props) => { fullWidth variant="outlined" placeholder="Search for apps" + disabled={!isLoggedIn} value={searchQuery} id="shuffle_search_field" onChange={handleSearchChange} @@ -1945,6 +2050,7 @@ const Apps2 = (props) => { variant="outlined" value={selectedCategory} onChange={handleCategoryChange} + disabled={!isLoggedIn} displayEmpty multiple style={{ @@ -2009,6 +2115,7 @@ const Apps2 = (props) => { variant="outlined" value={selectedLabel} onChange={handleLabelChange} + disabled={!isLoggedIn} displayEmpty multiple style={{ @@ -2067,6 +2174,7 @@ const Apps2 = (props) => { variant="contained" color="primary" onClick={handleCreateApp} + disabled={!isLoggedIn} style={{ height: "100%", width: '100%', @@ -2092,51 +2200,55 @@ const Apps2 = (props) => { {isLoading ? ( ) : ( - <> - {appsToShow?.length > 0 && appsToShow !== undefined && !isLoading ? ( -
- {appsToShow.map((data, index) => ( - + {appsToShow?.length > 0 && appsToShow !== undefined && !isLoading ? ( +
+ {appsToShow.map((data, index) => ( + + ))} +
+ ) : ( +
+ - ))} -
- ) : ( -
- -
- )} - +
+ )} + + ) : ( + + ) )}
) @@ -2147,41 +2259,45 @@ const Apps2 = (props) => { {isLoading ? ( ) : ( - <> - {appsToShow?.length > 0 && appsToShow !== undefined ? ( -
- {appsToShow.map((data, index) => ( - + {appsToShow?.length > 0 && appsToShow !== undefined ? ( +
+ {appsToShow.map((data, index) => ( + + ))} +
+ ) : ( +
+ - ))} -
- ) : ( -
- -
- )} - +
+ )} + + ) : ( + + ) )}
) diff --git a/frontend/src/views/Workflows2.jsx b/frontend/src/views/Workflows2.jsx index 7c124bf0..1ead2cd2 100644 --- a/frontend/src/views/Workflows2.jsx +++ b/frontend/src/views/Workflows2.jsx @@ -716,6 +716,8 @@ const Workflows2 = (props) => { const [videoViewOpen, setVideoViewOpen] = React.useState(false) const [gettingStartedItems, setGettingStartedItems] = 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 [apps, setApps] = React.useState([]); @@ -751,15 +753,6 @@ const Workflows2 = (props) => { 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.success === false) { } else if (responseJson.length === 0) { + // When there are no workflows, we can set the loading to false + setIsLoadingWorkflow(false) if (currTab !== 2) { toast("No workflows found. Showing workflow discovery") setCurrTab(2) @@ -2483,6 +2478,7 @@ const Workflows2 = (props) => { } } + return (
@@ -2537,7 +2533,7 @@ const Workflows2 = (props) => { maxWidth: 310, padding: "12px 0", }}> - {(data?.image !== undefined || data?.image_url !== undefined) ? ( + {(data?.image !== undefined || (data?.image_url !== undefined && data?.image_url.length > 0)) ? (
{ className={classes.datagrid} rows={rows} columns={columns} - pageSize={100} + page={page} + onPageChange={(newPage) => { + setPage(newPage) + }} + pageSize={pageSize} + onPageSizeChange={(newPageSize) => { + setPageSize(newPageSize); + }} + rowsPerPageOptions={[25, 50, 100, 150]} checkboxSelection autoHeight density="standard" @@ -3962,7 +3966,7 @@ const Workflows2 = (props) => { setIsLoadingWorkflow(false); } - }, [currTab, workflows, userdata, filteredWorkflows]) + }, [currTab, workflows, userdata, filteredWorkflows, filters]) diff --git a/functions/onprem/orborus/orborus.go b/functions/onprem/orborus/orborus.go index 9c9c9709..ecebe91f 100755 --- a/functions/onprem/orborus/orborus.go +++ b/functions/onprem/orborus/orborus.go @@ -2298,6 +2298,10 @@ func main() { } else if incRequest.Type == "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() if err != nil { 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") { log.Printf("[ERROR] Tenzir node connection problem: %s", err) + } else { tenzirDisabled = true log.Printf("[ERROR] Disabling pipelines: %s. You will need to restart the Orborus to fix this.", err)